*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/fs_struct.h>
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/namei.h>
 static __be32
 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
                   struct iattr *iattr, struct nfs4_acl **acl,
-                  struct xdr_netobj *label)
+                  struct xdr_netobj *label, int *umask)
 {
        int expected_len, len = 0;
        u32 dummy32;
                        return nfserr_jukebox;
        }
 #endif
+       if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
+               if (!umask)
+                       goto xdr_error;
+               READ_BUF(8);
+               len += 8;
+               dummy32 = be32_to_cpup(p++);
+               iattr->ia_mode = dummy32 & (S_IFMT | S_IALLUGO);
+               dummy32 = be32_to_cpup(p++);
+               *umask = dummy32 & S_IRWXUGO;
+               iattr->ia_valid |= ATTR_MODE;
+       }
        if (len != expected_len)
                goto xdr_error;
 
                return status;
 
        status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
-                                   &create->cr_acl, &create->cr_label);
+                                   &create->cr_acl, &create->cr_label,
+                                   ¤t->fs->umask);
        if (status)
                goto out;
 
        case NFS4_OPEN_NOCREATE:
                break;
        case NFS4_OPEN_CREATE:
+               current->fs->umask = 0;
                READ_BUF(4);
                open->op_createmode = be32_to_cpup(p++);
                switch (open->op_createmode) {
                case NFS4_CREATE_UNCHECKED:
                case NFS4_CREATE_GUARDED:
                        status = nfsd4_decode_fattr(argp, open->op_bmval,
-                               &open->op_iattr, &open->op_acl, &open->op_label);
+                               &open->op_iattr, &open->op_acl, &open->op_label,
+                               ¤t->fs->umask);
                        if (status)
                                goto out;
                        break;
                        READ_BUF(NFS4_VERIFIER_SIZE);
                        COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
                        status = nfsd4_decode_fattr(argp, open->op_bmval,
-                               &open->op_iattr, &open->op_acl, &open->op_label);
+                               &open->op_iattr, &open->op_acl, &open->op_label,
+                               ¤t->fs->umask);
                        if (status)
                                goto out;
                        break;
        if (status)
                return status;
        return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
-                                 &setattr->sa_acl, &setattr->sa_label);
+                                 &setattr->sa_acl, &setattr->sa_label, NULL);
 }
 
 static __be32
 
 
 #define NFSD4_2_SUPPORTED_ATTRS_WORD2 \
        (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \
+       FATTR4_WORD2_MODE_UMASK | \
        NFSD4_2_SECURITY_ATTRS)
 
 extern u32 nfsd_suppattrs[3][3];
        (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \
        | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
-#define NFSD_WRITEABLE_ATTRS_WORD2 FATTR4_WORD2_SECURITY_LABEL
+#define MAYBE_FATTR4_WORD2_SECURITY_LABEL \
+       FATTR4_WORD2_SECURITY_LABEL
 #else
-#define NFSD_WRITEABLE_ATTRS_WORD2 0
+#define MAYBE_FATTR4_WORD2_SECURITY_LABEL 0
 #endif
+#define NFSD_WRITEABLE_ATTRS_WORD2 \
+       (FATTR4_WORD2_MODE_UMASK \
+       | MAYBE_FATTR4_WORD2_SECURITY_LABEL)
 
 #define NFSD_SUPPATTR_EXCLCREAT_WORD0 \
        NFSD_WRITEABLE_ATTRS_WORD0