NFS4: on a O_EXCL OPEN make sure SETATTR sets the fields holding the verifier
[linux-2.6-block.git] / fs / nfs / nfs4proc.c
index 3cc75445a68de627c3def7ed4cc2b1e16db34eda..fee2d14b158bf10bc1fb845df68cc6982819d152 100644 (file)
@@ -942,6 +942,22 @@ static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, st
        return res;
 }
 
+/*
+ * on an EXCLUSIVE create, the server should send back a bitmask with FATTR4-*
+ * fields corresponding to attributes that were used to store the verifier.
+ * Make sure we clobber those fields in the later setattr call
+ */
+static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct iattr *sattr)
+{
+       if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
+           !(sattr->ia_valid & ATTR_ATIME_SET))
+               sattr->ia_valid |= ATTR_ATIME;
+
+       if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
+           !(sattr->ia_valid & ATTR_MTIME_SET))
+               sattr->ia_valid |= ATTR_MTIME;
+}
+
 /*
  * Returns a referenced nfs4_state
  */
@@ -973,6 +989,9 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct
        if (status != 0)
                goto err_opendata_free;
 
+       if (opendata->o_arg.open_flags & O_EXCL)
+               nfs4_exclusive_attrset(opendata, sattr);
+
        status = -ENOMEM;
        state = nfs4_opendata_to_nfs4_state(opendata);
        if (state == NULL)
@@ -1784,6 +1803,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
                if (status == 0)
                        nfs_setattr_update_inode(state->inode, sattr);
+               nfs_post_op_update_inode(state->inode, &fattr);
        }
        if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
                status = nfs4_intent_set_file(nd, &path, state);