]> 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 e0f20de6aa2bc53f2a6b47b7f9926696f301e389..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>
@@ -87,6 +89,32 @@ static u32 unixmode2p9mode(struct v9fs_session_info *v9ses, umode_t mode)
        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;
+}
+
 /**
  * p9mode2unixmode- convert plan9 mode bits to unix mode bits
  * @v9ses: v9fs session information
@@ -100,8 +128,8 @@ static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses,
        int res;
        u32 mode = stat->mode;
 
-       res = mode & S_IALLUGO;
        *rdev = 0;
+       res = p9mode2perm(v9ses, stat);
 
        if ((mode & P9_DMDIR) == P9_DMDIR)
                res |= S_IFDIR;
@@ -128,24 +156,13 @@ static umode_t 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;
 }
 
@@ -275,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;
                }
@@ -301,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;
                }
@@ -329,8 +346,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
 
                break;
        default:
-               P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%hx 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,11 +369,12 @@ struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t rdev)
        struct inode *inode;
        struct v9fs_session_info *v9ses = sb->s_fs_info;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %ho\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);
@@ -573,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))
@@ -630,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;
@@ -639,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);
        }
 
@@ -647,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);
-               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;
+               p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
                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)
@@ -788,7 +811,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
        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);
@@ -826,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);
@@ -933,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;
@@ -969,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;
        }
@@ -1026,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) {
@@ -1063,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;
@@ -1162,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);
@@ -1208,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);
@@ -1230,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:
@@ -1252,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);
@@ -1283,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);
 }
@@ -1306,7 +1328,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
 
        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;
        }
 
@@ -1333,8 +1355,8 @@ 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, P9_DMSYMLINK, symname);
 }
@@ -1355,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,9 +1419,9 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rde
        char *name;
        u32 perm;
 
-       P9_DPRINTK(P9_DEBUG_VFS,
-               " %lu,%s mode: %hx 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;