Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs...
[pandora-kernel.git] / fs / nfs / dir.c
index ededdbd..57f578e 100644 (file)
@@ -56,7 +56,7 @@ static int nfs_link(struct dentry *, struct inode *, struct dentry *);
 static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
 static int nfs_rename(struct inode *, struct dentry *,
                      struct inode *, struct dentry *);
-static int nfs_fsync_dir(struct file *, int);
+static int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
 static void nfs_readdir_clear_array(struct page*);
 
@@ -945,15 +945,19 @@ out:
  * All directory operations under NFS are synchronous, so fsync()
  * is a dummy operation.
  */
-static int nfs_fsync_dir(struct file *filp, int datasync)
+static int nfs_fsync_dir(struct file *filp, loff_t start, loff_t end,
+                        int datasync)
 {
        struct dentry *dentry = filp->f_path.dentry;
+       struct inode *inode = dentry->d_inode;
 
        dfprintk(FILE, "NFS: fsync dir(%s/%s) datasync %d\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
                        datasync);
 
+       mutex_lock(&inode->i_mutex);
        nfs_inc_stats(dentry->d_inode, NFSIOS_VFSFSYNC);
+       mutex_unlock(&inode->i_mutex);
        return 0;
 }
 
@@ -997,14 +1001,12 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
  * Return the intent data that applies to this particular path component
  *
  * Note that the current set of intents only apply to the very last
- * component of the path.
- * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
+ * component of the path and none of them is set before that last
+ * component.
  */
 static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
                                                unsigned int mask)
 {
-       if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
-               return 0;
        return nd->flags & mask;
 }
 
@@ -1338,25 +1340,31 @@ static int is_atomic_open(struct nameidata *nd)
                return 0;
        /* Are we trying to write to a read only partition? */
        if (__mnt_is_readonly(nd->path.mnt) &&
-           (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
+           (nd->intent.open.flags & (O_CREAT|O_TRUNC|O_ACCMODE)))
                return 0;
        return 1;
 }
 
-static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd)
+static fmode_t flags_to_mode(int flags)
+{
+       fmode_t res = (__force fmode_t)flags & FMODE_EXEC;
+       if ((flags & O_ACCMODE) != O_WRONLY)
+               res |= FMODE_READ;
+       if ((flags & O_ACCMODE) != O_RDONLY)
+               res |= FMODE_WRITE;
+       return res;
+}
+
+static struct nfs_open_context *create_nfs_open_context(struct dentry *dentry, int open_flags)
 {
-       struct path path = {
-               .mnt = nd->path.mnt,
-               .dentry = dentry,
-       };
        struct nfs_open_context *ctx;
        struct rpc_cred *cred;
-       fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
+       fmode_t fmode = flags_to_mode(open_flags);
 
        cred = rpc_lookup_cred();
        if (IS_ERR(cred))
                return ERR_CAST(cred);
-       ctx = alloc_nfs_open_context(&path, cred, fmode);
+       ctx = alloc_nfs_open_context(dentry, cred, fmode);
        put_rpccred(cred);
        if (ctx == NULL)
                return ERR_PTR(-ENOMEM);
@@ -1376,13 +1384,13 @@ static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ct
 
        /* If the open_intent is for execute, we have an extra check to make */
        if (ctx->mode & FMODE_EXEC) {
-               ret = nfs_may_open(ctx->path.dentry->d_inode,
+               ret = nfs_may_open(ctx->dentry->d_inode,
                                ctx->cred,
                                nd->intent.open.flags);
                if (ret < 0)
                        goto out;
        }
-       filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open);
+       filp = lookup_instantiate_filp(nd, ctx->dentry, do_open);
        if (IS_ERR(filp))
                ret = PTR_ERR(filp);
        else
@@ -1420,12 +1428,13 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
                goto out;
        }
 
-       ctx = nameidata_to_nfs_open_context(dentry, nd);
+       open_flags = nd->intent.open.flags;
+
+       ctx = create_nfs_open_context(dentry, open_flags);
        res = ERR_CAST(ctx);
        if (IS_ERR(ctx))
                goto out;
 
-       open_flags = nd->intent.open.flags;
        if (nd->flags & LOOKUP_CREATE) {
                attr.ia_mode = nd->intent.open.create_mode;
                attr.ia_valid = ATTR_MODE;
@@ -1463,8 +1472,8 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
        res = d_add_unique(dentry, inode);
        nfs_unblock_sillyrename(dentry->d_parent);
        if (res != NULL) {
-               dput(ctx->path.dentry);
-               ctx->path.dentry = dget(res);
+               dput(ctx->dentry);
+               ctx->dentry = dget(res);
                dentry = res;
        }
        err = nfs_intent_set_file(nd, ctx);
@@ -1517,7 +1526,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
        /* We can't create new files, or truncate existing ones here */
        openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
 
-       ctx = nameidata_to_nfs_open_context(dentry, nd);
+       ctx = create_nfs_open_context(dentry, openflags);
        ret = PTR_ERR(ctx);
        if (IS_ERR(ctx))
                goto out;
@@ -1570,7 +1579,7 @@ static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
        struct nfs_open_context *ctx = NULL;
        struct iattr attr;
        int error;
-       int open_flags = 0;
+       int open_flags = O_CREAT|O_EXCL;
 
        dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1578,27 +1587,27 @@ static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
        attr.ia_mode = mode;
        attr.ia_valid = ATTR_MODE;
 
-       if ((nd->flags & LOOKUP_CREATE) != 0) {
+       if (nd)
                open_flags = nd->intent.open.flags;
 
-               ctx = nameidata_to_nfs_open_context(dentry, nd);
-               error = PTR_ERR(ctx);
-               if (IS_ERR(ctx))
-                       goto out_err_drop;
-       }
+       ctx = create_nfs_open_context(dentry, open_flags);
+       error = PTR_ERR(ctx);
+       if (IS_ERR(ctx))
+               goto out_err_drop;
 
        error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
        if (error != 0)
                goto out_put_ctx;
-       if (ctx != NULL) {
+       if (nd) {
                error = nfs_intent_set_file(nd, ctx);
                if (error < 0)
                        goto out_err;
+       } else {
+               put_nfs_open_context(ctx);
        }
        return 0;
 out_put_ctx:
-       if (ctx != NULL)
-               put_nfs_open_context(ctx);
+       put_nfs_open_context(ctx);
 out_err_drop:
        d_drop(dentry);
 out_err:
@@ -1660,7 +1669,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 {
        struct iattr attr;
        int error;
-       int open_flags = 0;
+       int open_flags = O_CREAT|O_EXCL;
 
        dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1668,7 +1677,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
        attr.ia_mode = mode;
        attr.ia_valid = ATTR_MODE;
 
-       if ((nd->flags & LOOKUP_CREATE) != 0)
+       if (nd)
                open_flags = nd->intent.open.flags;
 
        error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL);
@@ -2259,11 +2268,11 @@ static int nfs_open_permission_mask(int openflags)
 {
        int mask = 0;
 
-       if (openflags & FMODE_READ)
+       if ((openflags & O_ACCMODE) != O_WRONLY)
                mask |= MAY_READ;
-       if (openflags & FMODE_WRITE)
+       if ((openflags & O_ACCMODE) != O_RDONLY)
                mask |= MAY_WRITE;
-       if (openflags & FMODE_EXEC)
+       if (openflags & __FMODE_EXEC)
                mask |= MAY_EXEC;
        return mask;
 }
@@ -2273,12 +2282,12 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
        return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
 }
 
-int nfs_permission(struct inode *inode, int mask, unsigned int flags)
+int nfs_permission(struct inode *inode, int mask)
 {
        struct rpc_cred *cred;
        int res = 0;
 
-       if (flags & IPERM_FLAG_RCU)
+       if (mask & MAY_NOT_BLOCK)
                return -ECHILD;
 
        nfs_inc_stats(inode, NFSIOS_VFSACCESS);
@@ -2328,7 +2337,7 @@ out:
 out_notsup:
        res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
        if (res == 0)
-               res = generic_permission(inode, mask, flags, NULL);
+               res = generic_permission(inode, mask);
        goto out;
 }