]> Pileus Git - ~andy/linux/blobdiff - fs/9p/vfs_inode.c
Merge branches 'device-groups', 'logitech' and 'multitouch' into for-linus
[~andy/linux] / fs / 9p / vfs_inode.c
index 879ed88517373792797f5b29cf110b50c8b7a4b2..014c8dd62962c02a8acfb17f6a771bc76de1a73a 100644 (file)
@@ -23,6 +23,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -59,15 +61,13 @@ static const struct inode_operations v9fs_symlink_inode_operations;
  *
  */
 
-static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
+static u32 unixmode2p9mode(struct v9fs_session_info *v9ses, umode_t mode)
 {
        int res;
        res = mode & 0777;
        if (S_ISDIR(mode))
                res |= P9_DMDIR;
        if (v9fs_proto_dotu(v9ses)) {
-               if (S_ISLNK(mode))
-                       res |= P9_DMSYMLINK;
                if (v9ses->nodev == 0) {
                        if (S_ISSOCK(mode))
                                res |= P9_DMSOCKET;
@@ -85,10 +85,33 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
                        res |= P9_DMSETGID;
                if ((mode & S_ISVTX) == S_ISVTX)
                        res |= P9_DMSETVTX;
-               if ((mode & P9_DMLINK))
-                       res |= P9_DMLINK;
        }
+       return res;
+}
 
+/**
+ * p9mode2perm- convert plan9 mode bits to unix permission bits
+ * @v9ses: v9fs session information
+ * @stat: p9_wstat from which mode need to be derived
+ *
+ */
+static int p9mode2perm(struct v9fs_session_info *v9ses,
+                      struct p9_wstat *stat)
+{
+       int res;
+       int mode = stat->mode;
+
+       res = mode & S_IALLUGO;
+       if (v9fs_proto_dotu(v9ses)) {
+               if ((mode & P9_DMSETUID) == P9_DMSETUID)
+                       res |= S_ISUID;
+
+               if ((mode & P9_DMSETGID) == P9_DMSETGID)
+                       res |= S_ISGID;
+
+               if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
+                       res |= S_ISVTX;
+       }
        return res;
 }
 
@@ -99,14 +122,14 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
  * @rdev: major number, minor number in case of device files.
  *
  */
-static int p9mode2unixmode(struct v9fs_session_info *v9ses,
-                          struct p9_wstat *stat, dev_t *rdev)
+static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses,
+                              struct p9_wstat *stat, dev_t *rdev)
 {
        int res;
-       int mode = stat->mode;
+       u32 mode = stat->mode;
 
-       res = mode & S_IALLUGO;
        *rdev = 0;
+       res = p9mode2perm(v9ses, stat);
 
        if ((mode & P9_DMDIR) == P9_DMDIR)
                res |= S_IFDIR;
@@ -133,24 +156,13 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses,
                        res |= S_IFBLK;
                        break;
                default:
-                       P9_DPRINTK(P9_DEBUG_ERROR,
-                               "Unknown special type %c %s\n", type,
-                               stat->extension);
+                       p9_debug(P9_DEBUG_ERROR, "Unknown special type %c %s\n",
+                                type, stat->extension);
                };
                *rdev = MKDEV(major, minor);
        } else
                res |= S_IFREG;
 
-       if (v9fs_proto_dotu(v9ses)) {
-               if ((mode & P9_DMSETUID) == P9_DMSETUID)
-                       res |= S_ISUID;
-
-               if ((mode & P9_DMSETGID) == P9_DMSETGID)
-                       res |= S_ISGID;
-
-               if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
-                       res |= S_ISVTX;
-       }
        return res;
 }
 
@@ -251,7 +263,6 @@ struct inode *v9fs_alloc_inode(struct super_block *sb)
 static void v9fs_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
 }
 
@@ -261,7 +272,7 @@ void v9fs_destroy_inode(struct inode *inode)
 }
 
 int v9fs_init_inode(struct v9fs_session_info *v9ses,
-                   struct inode *inode, int mode, dev_t rdev)
+                   struct inode *inode, umode_t mode, dev_t rdev)
 {
        int err = 0;
 
@@ -281,8 +292,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
                } else if (v9fs_proto_dotu(v9ses)) {
                        inode->i_op = &v9fs_file_inode_operations;
                } else {
-                       P9_DPRINTK(P9_DEBUG_ERROR,
-                                  "special files without extended mode\n");
+                       p9_debug(P9_DEBUG_ERROR,
+                                "special files without extended mode\n");
                        err = -EINVAL;
                        goto error;
                }
@@ -307,8 +318,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
                break;
        case S_IFLNK:
                if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) {
-                       P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with "
-                                               "legacy protocol.\n");
+                       p9_debug(P9_DEBUG_ERROR,
+                                "extended modes used with legacy protocol\n");
                        err = -EINVAL;
                        goto error;
                }
@@ -335,8 +346,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
 
                break;
        default:
-               P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
-                          mode, mode & S_IFMT);
+               p9_debug(P9_DEBUG_ERROR, "BAD mode 0x%hx S_IFMT 0x%x\n",
+                        mode, mode & S_IFMT);
                err = -EINVAL;
                goto error;
        }
@@ -352,17 +363,18 @@ error:
  *
  */
 
-struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t rdev)
+struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t rdev)
 {
        int err;
        struct inode *inode;
        struct v9fs_session_info *v9ses = sb->s_fs_info;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
+       p9_debug(P9_DEBUG_VFS, "super block: %p mode: %ho\n", sb, mode);
 
        inode = new_inode(sb);
        if (!inode) {
-               P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
+               pr_warn("%s (%d): Problem allocating inode\n",
+                       __func__, task_pid_nr(current));
                return ERR_PTR(-ENOMEM);
        }
        err = v9fs_init_inode(v9ses, inode, mode, rdev);
@@ -492,7 +504,8 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
                                   int new)
 {
        dev_t rdev;
-       int retval, umode;
+       int retval;
+       umode_t umode;
        unsigned long i_ino;
        struct inode *inode;
        struct v9fs_session_info *v9ses = sb->s_fs_info;
@@ -578,15 +591,15 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
        struct p9_fid *v9fid, *dfid;
        struct v9fs_session_info *v9ses;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
-                  dir, dentry, flags);
+       p9_debug(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
+                dir, dentry, flags);
 
        v9ses = v9fs_inode2v9ses(dir);
        inode = dentry->d_inode;
        dfid = v9fs_fid_lookup(dentry->d_parent);
        if (IS_ERR(dfid)) {
                retval = PTR_ERR(dfid);
-               P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
+               p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
                return retval;
        }
        if (v9fs_proto_dotl(v9ses))
@@ -635,7 +648,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
        struct p9_fid *dfid, *ofid, *fid;
        struct inode *inode;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
+       p9_debug(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
 
        err = 0;
        ofid = NULL;
@@ -644,7 +657,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
        dfid = v9fs_fid_lookup(dentry->d_parent);
        if (IS_ERR(dfid)) {
                err = PTR_ERR(dfid);
-               P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
+               p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
                return ERR_PTR(err);
        }
 
@@ -652,36 +665,41 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
        ofid = p9_client_walk(dfid, 0, NULL, 1);
        if (IS_ERR(ofid)) {
                err = PTR_ERR(ofid);
-               P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
+               p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
                return ERR_PTR(err);
        }
 
        err = p9_client_fcreate(ofid, name, perm, mode, extension);
        if (err < 0) {
-               P9_DPRINTK(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
+               p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
                goto error;
        }
 
-       /* now walk from the parent so we can get unopened fid */
-       fid = p9_client_walk(dfid, 1, &name, 1);
-       if (IS_ERR(fid)) {
-               err = PTR_ERR(fid);
-               P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-               fid = NULL;
-               goto error;
-       }
-
-       /* instantiate inode and assign the unopened fid to the dentry */
-       inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
-       if (IS_ERR(inode)) {
-               err = PTR_ERR(inode);
-               P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
-               goto error;
+       if (!(perm & P9_DMLINK)) {
+               /* now walk from the parent so we can get unopened fid */
+               fid = p9_client_walk(dfid, 1, &name, 1);
+               if (IS_ERR(fid)) {
+                       err = PTR_ERR(fid);
+                       p9_debug(P9_DEBUG_VFS,
+                                  "p9_client_walk failed %d\n", err);
+                       fid = NULL;
+                       goto error;
+               }
+               /*
+                * instantiate inode and assign the unopened fid to the dentry
+                */
+               inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
+               if (IS_ERR(inode)) {
+                       err = PTR_ERR(inode);
+                       p9_debug(P9_DEBUG_VFS,
+                                  "inode creation failed %d\n", err);
+                       goto error;
+               }
+               err = v9fs_fid_add(dentry, fid);
+               if (err < 0)
+                       goto error;
+               d_instantiate(dentry, inode);
        }
-       err = v9fs_fid_add(dentry, fid);
-       if (err < 0)
-               goto error;
-       d_instantiate(dentry, inode);
        return ofid;
 error:
        if (ofid)
@@ -703,7 +721,7 @@ error:
  */
 
 static int
-v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
+v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                struct nameidata *nd)
 {
        int err;
@@ -786,14 +804,14 @@ error:
  *
  */
 
-static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        int err;
        u32 perm;
        struct p9_fid *fid;
        struct v9fs_session_info *v9ses;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
+       p9_debug(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
        err = 0;
        v9ses = v9fs_inode2v9ses(dir);
        perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
@@ -831,8 +849,8 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        char *name;
        int result = 0;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
-               dir, dentry->d_name.name, dentry, nameidata);
+       p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
+                dir, dentry->d_name.name, dentry, nameidata);
 
        if (dentry->d_name.len > NAME_MAX)
                return ERR_PTR(-ENAMETOOLONG);
@@ -938,7 +956,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct p9_fid *newdirfid;
        struct p9_wstat wstat;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "\n");
+       p9_debug(P9_DEBUG_VFS, "\n");
        retval = 0;
        old_inode = old_dentry->d_inode;
        new_inode = new_dentry->d_inode;
@@ -974,8 +992,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                 * 9P .u can only handle file rename in the same directory
                 */
 
-               P9_DPRINTK(P9_DEBUG_ERROR,
-                               "old dir and new dir are different\n");
+               p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n");
                retval = -EXDEV;
                goto clunk_newdir;
        }
@@ -1031,7 +1048,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        struct p9_fid *fid;
        struct p9_wstat *st;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
+       p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
        err = -EPERM;
        v9ses = v9fs_dentry2v9ses(dentry);
        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
@@ -1068,7 +1085,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
        struct p9_fid *fid;
        struct p9_wstat wstat;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "\n");
+       p9_debug(P9_DEBUG_VFS, "\n");
        retval = inode_change_ok(dentry->d_inode, iattr);
        if (retval)
                return retval;
@@ -1131,7 +1148,7 @@ void
 v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
        struct super_block *sb)
 {
-       mode_t mode;
+       umode_t mode;
        char ext[32];
        char tag_name[14];
        unsigned int i_nlink;
@@ -1167,7 +1184,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
                                set_nlink(inode, i_nlink);
                }
        }
-       mode = stat->mode & S_IALLUGO;
+       mode = p9mode2perm(v9ses, stat);
        mode |= inode->i_mode & ~S_IALLUGO;
        inode->i_mode = mode;
        i_size_write(inode, stat->length);
@@ -1213,7 +1230,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
        struct p9_fid *fid;
        struct p9_wstat *st;
 
-       P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
+       p9_debug(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
        retval = -EPERM;
        v9ses = v9fs_dentry2v9ses(dentry);
        fid = v9fs_fid_lookup(dentry);
@@ -1235,8 +1252,8 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
        /* copy extension buffer into buffer */
        strncpy(buffer, st->extension, buflen);
 
-       P9_DPRINTK(P9_DEBUG_VFS,
-               "%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer);
+       p9_debug(P9_DEBUG_VFS, "%s -> %s (%s)\n",
+                dentry->d_name.name, st->extension, buffer);
 
        retval = strnlen(buffer, buflen);
 done:
@@ -1257,7 +1274,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
        int len = 0;
        char *link = __getname();
 
-       P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
+       p9_debug(P9_DEBUG_VFS, "%s\n", dentry->d_name.name);
 
        if (!link)
                link = ERR_PTR(-ENOMEM);
@@ -1288,8 +1305,8 @@ v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
 {
        char *s = nd_get_link(nd);
 
-       P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name,
-               IS_ERR(s) ? "<error>" : s);
+       p9_debug(P9_DEBUG_VFS, " %s %s\n",
+                dentry->d_name.name, IS_ERR(s) ? "<error>" : s);
        if (!IS_ERR(s))
                __putname(s);
 }
@@ -1304,19 +1321,17 @@ v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
  */
 
 static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
-       int mode, const char *extension)
+       u32 perm, const char *extension)
 {
-       u32 perm;
        struct p9_fid *fid;
        struct v9fs_session_info *v9ses;
 
        v9ses = v9fs_inode2v9ses(dir);
        if (!v9fs_proto_dotu(v9ses)) {
-               P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
+               p9_debug(P9_DEBUG_ERROR, "not extended\n");
                return -EPERM;
        }
 
-       perm = unixmode2p9mode(v9ses, mode);
        fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
                                                                P9_OREAD);
        if (IS_ERR(fid))
@@ -1340,10 +1355,10 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
 static int
 v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
-       P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino,
-                                       dentry->d_name.name, symname);
+       p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n",
+                dir->i_ino, dentry->d_name.name, symname);
 
-       return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
+       return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname);
 }
 
 /**
@@ -1362,9 +1377,8 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
        char *name;
        struct p9_fid *oldfid;
 
-       P9_DPRINTK(P9_DEBUG_VFS,
-               " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
-               old_dentry->d_name.name);
+       p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n",
+                dir->i_ino, dentry->d_name.name, old_dentry->d_name.name);
 
        oldfid = v9fs_fid_clone(old_dentry);
        if (IS_ERR(oldfid))
@@ -1398,14 +1412,16 @@ clunk_fid:
  */
 
 static int
-v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
 {
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
        int retval;
        char *name;
+       u32 perm;
 
-       P9_DPRINTK(P9_DEBUG_VFS,
-               " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
-               dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
+       p9_debug(P9_DEBUG_VFS, " %lu,%s mode: %hx MAJOR: %u MINOR: %u\n",
+                dir->i_ino, dentry->d_name.name, mode,
+                MAJOR(rdev), MINOR(rdev));
 
        if (!new_valid_dev(rdev))
                return -EINVAL;
@@ -1427,7 +1443,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
                return -EINVAL;
        }
 
-       retval = v9fs_vfs_mkspecial(dir, dentry, mode, name);
+       perm = unixmode2p9mode(v9ses, mode);
+       retval = v9fs_vfs_mkspecial(dir, dentry, perm, name);
        __putname(name);
 
        return retval;