ARM: tegra: pm375 : Enable utmi1
[linux-3.10.git] / fs / 9p / vfs_inode.c
index b5a1076..d86edc8 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;
 }
 
@@ -180,9 +192,6 @@ int v9fs_uflags2omode(int uflags, int extended)
                break;
        }
 
-       if (uflags & O_TRUNC)
-               ret |= P9_OTRUNC;
-
        if (extended) {
                if (uflags & O_EXCL)
                        ret |= P9_OEXCL;
@@ -216,9 +225,9 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
        wstat->uid = NULL;
        wstat->gid = NULL;
        wstat->muid = NULL;
-       wstat->n_uid = ~0;
-       wstat->n_gid = ~0;
-       wstat->n_muid = ~0;
+       wstat->n_uid = INVALID_UID;
+       wstat->n_gid = INVALID_GID;
+       wstat->n_muid = INVALID_UID;
        wstat->extension = NULL;
 }
 
@@ -251,7 +260,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 +269,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 +289,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 +315,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 +343,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 +360,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);
@@ -436,7 +445,7 @@ void v9fs_evict_inode(struct inode *inode)
        struct v9fs_inode *v9inode = V9FS_I(inode);
 
        truncate_inode_pages(inode->i_mapping, 0);
-       end_writeback(inode);
+       clear_inode(inode);
        filemap_fdatawrite(inode->i_mapping);
 
 #ifdef CONFIG_9P_FSCACHE
@@ -492,7 +501,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 +588,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 +645,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 +654,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 +662,39 @@ 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;
+               }
+               v9fs_fid_add(dentry, fid);
+               d_instantiate(dentry, inode);
        }
-       err = v9fs_fid_add(dentry, fid);
-       if (err < 0)
-               goto error;
-       d_instantiate(dentry, inode);
        return ofid;
 error:
        if (ofid)
@@ -694,88 +707,34 @@ error:
 }
 
 /**
- * v9fs_vfs_create - VFS hook to create files
+ * v9fs_vfs_create - VFS hook to create a regular file
+ *
+ * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open().  This is only called
+ * for mknod(2).
+ *
  * @dir: directory inode that is being created
  * @dentry:  dentry that is being deleted
  * @mode: create permissions
- * @nd: path information
  *
  */
 
 static int
-v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
-               struct nameidata *nd)
+v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+               bool excl)
 {
-       int err;
-       u32 perm;
-       int flags;
-       struct file *filp;
-       struct v9fs_inode *v9inode;
-       struct v9fs_session_info *v9ses;
-       struct p9_fid *fid, *inode_fid;
-
-       err = 0;
-       fid = NULL;
-       v9ses = v9fs_inode2v9ses(dir);
-       perm = unixmode2p9mode(v9ses, mode);
-       if (nd)
-               flags = nd->intent.open.flags;
-       else
-               flags = O_RDWR;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+       u32 perm = unixmode2p9mode(v9ses, mode);
+       struct p9_fid *fid;
 
-       fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
-                               v9fs_uflags2omode(flags,
-                                               v9fs_proto_dotu(v9ses)));
-       if (IS_ERR(fid)) {
-               err = PTR_ERR(fid);
-               fid = NULL;
-               goto error;
-       }
+       /* P9_OEXCL? */
+       fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR);
+       if (IS_ERR(fid))
+               return PTR_ERR(fid);
 
        v9fs_invalidate_inode_attr(dir);
-       /* if we are opening a file, assign the open fid to the file */
-       if (nd) {
-               v9inode = V9FS_I(dentry->d_inode);
-               mutex_lock(&v9inode->v_mutex);
-               if (v9ses->cache && !v9inode->writeback_fid &&
-                   ((flags & O_ACCMODE) != O_RDONLY)) {
-                       /*
-                        * clone a fid and add it to writeback_fid
-                        * we do it during open time instead of
-                        * page dirty time via write_begin/page_mkwrite
-                        * because we want write after unlink usecase
-                        * to work.
-                        */
-                       inode_fid = v9fs_writeback_fid(dentry);
-                       if (IS_ERR(inode_fid)) {
-                               err = PTR_ERR(inode_fid);
-                               mutex_unlock(&v9inode->v_mutex);
-                               goto error;
-                       }
-                       v9inode->writeback_fid = (void *) inode_fid;
-               }
-               mutex_unlock(&v9inode->v_mutex);
-               filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
-               if (IS_ERR(filp)) {
-                       err = PTR_ERR(filp);
-                       goto error;
-               }
-
-               filp->private_data = fid;
-#ifdef CONFIG_9P_FSCACHE
-               if (v9ses->cache)
-                       v9fs_cache_inode_set_cookie(dentry->d_inode, filp);
-#endif
-       } else
-               p9_client_clunk(fid);
+       p9_client_clunk(fid);
 
        return 0;
-
-error:
-       if (fid)
-               p9_client_clunk(fid);
-
-       return err;
 }
 
 /**
@@ -786,14 +745,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);
@@ -821,7 +780,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  */
 
 struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
-                                     struct nameidata *nameidata)
+                                     unsigned int flags)
 {
        struct dentry *res;
        struct super_block *sb;
@@ -829,10 +788,9 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        struct p9_fid *dfid, *fid;
        struct inode *inode;
        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 flags: %x\n",
+                dir, dentry->d_name.name, dentry, flags);
 
        if (dentry->d_name.len > NAME_MAX)
                return ERR_PTR(-ENAMETOOLONG);
@@ -847,13 +805,11 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        name = (char *) dentry->d_name.name;
        fid = p9_client_walk(dfid, 1, &name, 1);
        if (IS_ERR(fid)) {
-               result = PTR_ERR(fid);
-               if (result == -ENOENT) {
-                       inode = NULL;
-                       goto inst_out;
+               if (fid == ERR_PTR(-ENOENT)) {
+                       d_add(dentry, NULL);
+                       return NULL;
                }
-
-               return ERR_PTR(result);
+               return ERR_CAST(fid);
        }
        /*
         * Make sure we don't use a wrong inode due to parallel
@@ -865,14 +821,9 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        else
                inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
        if (IS_ERR(inode)) {
-               result = PTR_ERR(inode);
-               inode = NULL;
-               goto error;
+               p9_client_clunk(fid);
+               return ERR_CAST(inode);
        }
-       result = v9fs_fid_add(dentry, fid);
-       if (result < 0)
-               goto error_iput;
-inst_out:
        /*
         * If we had a rename on the server and a parallel lookup
         * for the new name, then make sure we instantiate with
@@ -881,15 +832,93 @@ inst_out:
         * k/b.
         */
        res = d_materialise_unique(dentry, inode);
-       if (!IS_ERR(res))
-               return res;
-       result = PTR_ERR(res);
-error_iput:
-       iput(inode);
-error:
-       p9_client_clunk(fid);
+       if (!res)
+               v9fs_fid_add(dentry, fid);
+       else if (!IS_ERR(res))
+               v9fs_fid_add(res, fid);
+       else
+               p9_client_clunk(fid);
+       return res;
+}
+
+static int
+v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
+                    struct file *file, unsigned flags, umode_t mode,
+                    int *opened)
+{
+       int err;
+       u32 perm;
+       struct v9fs_inode *v9inode;
+       struct v9fs_session_info *v9ses;
+       struct p9_fid *fid, *inode_fid;
+       struct dentry *res = NULL;
+
+       if (d_unhashed(dentry)) {
+               res = v9fs_vfs_lookup(dir, dentry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
 
-       return ERR_PTR(result);
+               if (res)
+                       dentry = res;
+       }
+
+       /* Only creates */
+       if (!(flags & O_CREAT) || dentry->d_inode)
+               return finish_no_open(file, res);
+
+       err = 0;
+       fid = NULL;
+       v9ses = v9fs_inode2v9ses(dir);
+       perm = unixmode2p9mode(v9ses, mode);
+       fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
+                               v9fs_uflags2omode(flags,
+                                               v9fs_proto_dotu(v9ses)));
+       if (IS_ERR(fid)) {
+               err = PTR_ERR(fid);
+               fid = NULL;
+               goto error;
+       }
+
+       v9fs_invalidate_inode_attr(dir);
+       v9inode = V9FS_I(dentry->d_inode);
+       mutex_lock(&v9inode->v_mutex);
+       if (v9ses->cache && !v9inode->writeback_fid &&
+           ((flags & O_ACCMODE) != O_RDONLY)) {
+               /*
+                * clone a fid and add it to writeback_fid
+                * we do it during open time instead of
+                * page dirty time via write_begin/page_mkwrite
+                * because we want write after unlink usecase
+                * to work.
+                */
+               inode_fid = v9fs_writeback_fid(dentry);
+               if (IS_ERR(inode_fid)) {
+                       err = PTR_ERR(inode_fid);
+                       mutex_unlock(&v9inode->v_mutex);
+                       goto error;
+               }
+               v9inode->writeback_fid = (void *) inode_fid;
+       }
+       mutex_unlock(&v9inode->v_mutex);
+       err = finish_open(file, dentry, generic_file_open, opened);
+       if (err)
+               goto error;
+
+       file->private_data = fid;
+#ifdef CONFIG_9P_FSCACHE
+       if (v9ses->cache)
+               v9fs_cache_inode_set_cookie(dentry->d_inode, file);
+#endif
+
+       *opened |= FILE_CREATED;
+out:
+       dput(res);
+       return err;
+
+error:
+       if (fid)
+               p9_client_clunk(fid);
+       goto out;
 }
 
 /**
@@ -938,7 +967,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 +1003,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 +1059,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 +1096,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,14 +1159,14 @@ 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;
        struct v9fs_session_info *v9ses = sb->s_fs_info;
        struct v9fs_inode *v9inode = V9FS_I(inode);
 
-       inode->i_nlink = 1;
+       set_nlink(inode, 1);
 
        inode->i_atime.tv_sec = stat->atime;
        inode->i_mtime.tv_sec = stat->mtime;
@@ -1164,10 +1192,10 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
                        /* HARDLINKCOUNT %u */
                        sscanf(ext, "%13s %u", tag_name, &i_nlink);
                        if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
-                               inode->i_nlink = i_nlink;
+                               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 +1241,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);
@@ -1233,12 +1261,12 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
        }
 
        /* copy extension buffer into buffer */
-       strncpy(buffer, st->extension, buflen);
+       retval = min(strlen(st->extension)+1, (size_t)buflen);
+       memcpy(buffer, st->extension, retval);
 
-       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, buflen, buffer);
 
-       retval = strnlen(buffer, buflen);
 done:
        p9stat_free(st);
        kfree(st);
@@ -1257,7 +1285,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 +1316,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 +1332,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 +1366,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 +1388,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 +1423,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 +1454,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;
@@ -1471,6 +1499,7 @@ out:
 static const struct inode_operations v9fs_dir_inode_operations_dotu = {
        .create = v9fs_vfs_create,
        .lookup = v9fs_vfs_lookup,
+       .atomic_open = v9fs_vfs_atomic_open,
        .symlink = v9fs_vfs_symlink,
        .link = v9fs_vfs_link,
        .unlink = v9fs_vfs_unlink,
@@ -1485,6 +1514,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = {
 static const struct inode_operations v9fs_dir_inode_operations = {
        .create = v9fs_vfs_create,
        .lookup = v9fs_vfs_lookup,
+       .atomic_open = v9fs_vfs_atomic_open,
        .unlink = v9fs_vfs_unlink,
        .mkdir = v9fs_vfs_mkdir,
        .rmdir = v9fs_vfs_rmdir,