linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / 9p / vfs_inode.c
index 7a7ec2d..651a9e1 100644 (file)
@@ -7,8 +7,9 @@
  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
  *
  *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  as published by the Free Software Foundation.
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -204,6 +205,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
+               inode->i_blksize = sb->s_blocksize;
                inode->i_blocks = 0;
                inode->i_rdev = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -253,8 +255,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 }
 
 static int
-v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
-       u8 mode, char *extension, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
+v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name,
+       u32 perm, u8 mode, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
 {
        u32 fid;
        int err;
@@ -269,17 +271,14 @@ v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
        err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
        if (err < 0) {
                PRINT_FCALL_ERROR("clone error", fcall);
-               if (fcall && fcall->id == RWALK)
-                       goto clunk_fid;
-               else
-                       goto put_fid;
+               goto error;
        }
        kfree(fcall);
 
-       err = v9fs_t_create(v9ses, fid, name, perm, mode, extension, &fcall);
+       err = v9fs_t_create(v9ses, fid, name, perm, mode, &fcall);
        if (err < 0) {
                PRINT_FCALL_ERROR("create fails", fcall);
-               goto clunk_fid;
+               goto error;
        }
 
        if (iounit)
@@ -294,12 +293,8 @@ v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
        kfree(fcall);
        return 0;
 
-clunk_fid:
-       v9fs_t_clunk(v9ses, fid);
-       fid = V9FS_NOFID;
-
-put_fid:
-       if (fid != V9FS_NOFID)
+error:
+       if (fid >= 0)
                v9fs_put_idpool(fid, &v9ses->fidpool);
 
        kfree(fcall);
@@ -324,9 +319,6 @@ v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
                &fcall);
 
        if (err < 0) {
-               if (fcall && fcall->id == RWALK)
-                       goto clunk_fid;
-
                PRINT_FCALL_ERROR("walk error", fcall);
                v9fs_put_idpool(nfid, &v9ses->fidpool);
                goto error;
@@ -356,7 +348,7 @@ error:
        return ERR_PTR(err);
 }
 
-static struct inode *
+struct inode *
 v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid,
        struct super_block *sb)
 {
@@ -433,11 +425,11 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
        result = v9fs_t_remove(v9ses, fid, &fcall);
        if (result < 0) {
                PRINT_FCALL_ERROR("remove fails", fcall);
+       } else {
+               v9fs_put_idpool(fid, &v9ses->fidpool);
+               v9fs_fid_destroy(v9fid);
        }
 
-       v9fs_put_idpool(fid, &v9ses->fidpool);
-       v9fs_fid_destroy(v9fid);
-
        kfree(fcall);
        return result;
 }
@@ -482,7 +474,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
                flags = O_RDWR;
 
        err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
-               perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit);
+               perm, v9fs_uflags2omode(flags), &fid, &qid, &iounit);
 
        if (err)
                goto error;
@@ -529,6 +521,9 @@ error:
        if (vfid)
                v9fs_fid_destroy(vfid);
 
+       if (inode)
+               iput(inode);
+
        return err;
 }
 
@@ -555,7 +550,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
 
        err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
-               perm, V9FS_OREAD, NULL, &fid, NULL, NULL);
+               perm, V9FS_OREAD, &fid, NULL, NULL);
 
        if (err) {
                dprintk(DEBUG_ERROR, "create error %d\n", err);
@@ -642,26 +637,19 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        }
 
        result = v9fs_t_walk(v9ses, dirfidnum, newfid,
-               (char *)dentry->d_name.name, &fcall);
-
+               (char *)dentry->d_name.name, NULL);
        if (result < 0) {
-               if (fcall && fcall->id == RWALK)
-                       v9fs_t_clunk(v9ses, newfid);
-               else
-                       v9fs_put_idpool(newfid, &v9ses->fidpool);
-
+               v9fs_put_idpool(newfid, &v9ses->fidpool);
                if (result == -ENOENT) {
                        d_add(dentry, NULL);
                        dprintk(DEBUG_VFS,
                                "Return negative dentry %p count %d\n",
                                dentry, atomic_read(&dentry->d_count));
-                       kfree(fcall);
                        return NULL;
                }
                dprintk(DEBUG_ERROR, "walk error:%d\n", result);
                goto FreeFcall;
        }
-       kfree(fcall);
 
        result = v9fs_t_stat(v9ses, newfid, &fcall);
        if (result < 0) {
@@ -949,8 +937,9 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
 
        inode->i_size = stat->length;
 
+       inode->i_blksize = sb->s_blocksize;
        inode->i_blocks =
-           (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+           (inode->i_size + inode->i_blksize - 1) >> sb->s_blocksize_bits;
 }
 
 /**
@@ -1019,13 +1008,11 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
 
        /* copy extension buffer into buffer */
        if (fcall->params.rstat.stat.extension.len < buflen)
-               buflen = fcall->params.rstat.stat.extension.len + 1;
+               buflen = fcall->params.rstat.stat.extension.len;
 
-       memmove(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
+       memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
        buffer[buflen-1] = 0;
 
-       dprintk(DEBUG_ERROR, "%s -> %.*s (%s)\n", dentry->d_name.name, fcall->params.rstat.stat.extension.len,
-               fcall->params.rstat.stat.extension.str, buffer);
        retval = buflen;
 
       FreeFcall:
@@ -1049,9 +1036,6 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,
        int ret;
        char *link = __getname();
 
-       if (unlikely(!link))
-               return -ENOMEM;
-
        if (buflen > PATH_MAX)
                buflen = PATH_MAX;
 
@@ -1088,7 +1072,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
        if (!link)
                link = ERR_PTR(-ENOMEM);
        else {
-               len = v9fs_readlink(dentry, link, PATH_MAX);
+               len = v9fs_readlink(dentry, link, strlen(link));
 
                if (len < 0) {
                        __putname(link);
@@ -1125,7 +1109,10 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
        struct v9fs_session_info *v9ses;
        struct v9fs_fid *dfid, *vfid;
        struct inode *inode;
+       struct v9fs_fcall *fcall;
+       struct v9fs_wstat wstat;
 
+       fcall = NULL;
        inode = NULL;
        vfid = NULL;
        v9ses = v9fs_inode2v9ses(dir);
@@ -1138,7 +1125,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
        }
 
        err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
-               perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL);
+               perm, V9FS_OREAD, &fid, NULL, NULL);
 
        if (err)
                goto error;
@@ -1161,14 +1148,29 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
                goto error;
        }
 
+       /* issue a Twstat */
+       v9fs_blank_wstat(&wstat);
+       wstat.muid = v9ses->name;
+       wstat.extension = (char *) extension;
+       err = v9fs_t_wstat(v9ses, vfid->fid, &wstat, &fcall);
+       if (err < 0) {
+               PRINT_FCALL_ERROR("wstat error", fcall);
+               goto error;
+       }
+
+       kfree(fcall);
        dentry->d_op = &v9fs_dentry_operations;
        d_instantiate(dentry, inode);
        return 0;
 
 error:
+       kfree(fcall);
        if (vfid)
                v9fs_fid_destroy(vfid);
 
+       if (inode)
+               iput(inode);
+
        return err;
 
 }
@@ -1222,10 +1224,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
        }
 
        name = __getname();
-       if (unlikely(!name))
-               return -ENOMEM;
-
-       sprintf(name, "%d\n", oldfid->fid);
+       sprintf(name, "hardlink(%d)\n", oldfid->fid);
        retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
        __putname(name);
 
@@ -1254,8 +1253,6 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
                return -EINVAL;
 
        name = __getname();
-       if (!name)
-               return -ENOMEM;
        /* build extension */
        if (S_ISBLK(mode))
                sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));