}
 
        open_flags = nd->intent.open.flags;
+       attr.ia_valid = 0;
 
        ctx = create_nfs_open_context(dentry, open_flags);
        res = ERR_CAST(ctx);
 
        if (nd->flags & LOOKUP_CREATE) {
                attr.ia_mode = nd->intent.open.create_mode;
-               attr.ia_valid = ATTR_MODE;
+               attr.ia_valid |= ATTR_MODE;
                attr.ia_mode &= ~current_umask();
-       } else {
+       } else
                open_flags &= ~(O_EXCL | O_CREAT);
-               attr.ia_valid = 0;
+
+       if (open_flags & O_TRUNC) {
+               attr.ia_valid |= ATTR_SIZE;
+               attr.ia_size = 0;
        }
 
        /* Open the file on the server */
        struct inode *inode;
        struct inode *dir;
        struct nfs_open_context *ctx;
+       struct iattr attr;
        int openflags, ret = 0;
 
        if (nd->flags & LOOKUP_RCU)
        /* We cannot do exclusive creation on a positive dentry */
        if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
                goto no_open_dput;
-       /* We can't create new files, or truncate existing ones here */
-       openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
+       /* We can't create new files here */
+       openflags &= ~(O_CREAT|O_EXCL);
 
        ctx = create_nfs_open_context(dentry, openflags);
        ret = PTR_ERR(ctx);
        if (IS_ERR(ctx))
                goto out;
+
+       attr.ia_valid = 0;
+       if (openflags & O_TRUNC) {
+               attr.ia_valid |= ATTR_SIZE;
+               attr.ia_size = 0;
+               nfs_wb_all(inode);
+       }
+
        /*
         * Note: we're not holding inode->i_mutex and so may be racing with
         * operations that change the directory. We therefore save the
         * change attribute *before* we do the RPC call.
         */
-       inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL);
+       inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
        if (IS_ERR(inode)) {
                ret = PTR_ERR(inode);
                switch (ret) {
 
        goto out;
 }
 
-#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
+#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE|ATTR_OPEN)
 
 int
 nfs_setattr(struct dentry *dentry, struct iattr *attr)
 
        /* Optimization: if the end result is no change, don't RPC */
        attr->ia_valid &= NFS_VALID_ATTRS;
-       if ((attr->ia_valid & ~ATTR_FILE) == 0)
+       if ((attr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0)
                return 0;
 
        /* Write all dirty data */
 
        p->o_arg.bitmask = server->attr_bitmask;
        p->o_arg.dir_bitmask = server->cache_consistency_bitmask;
        p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
-       if (flags & O_CREAT) {
+       if (attrs != NULL && attrs->ia_valid != 0) {
                u32 *s;
 
                p->o_arg.u.attrs = &p->attrs;
 {
        int ret = 0;
 
-       if (open_mode & O_EXCL)
+       if (open_mode & (O_EXCL|O_TRUNC))
                goto out;
        switch (mode & (FMODE_READ|FMODE_WRITE)) {
                case FMODE_READ:
        struct nfs4_state *state = opendata->state;
        struct nfs_inode *nfsi = NFS_I(state->inode);
        struct nfs_delegation *delegation;
-       int open_mode = opendata->o_arg.open_flags & O_EXCL;
+       int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC);
        fmode_t fmode = opendata->o_arg.fmode;
        nfs4_stateid stateid;
        int ret = -EAGAIN;
                }
        }
 
+       /* Deal with open(O_TRUNC) */
+       if (sattr->ia_valid & ATTR_OPEN)
+               sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
+
        status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
        if (status == 0)
                nfs_setattr_update_inode(inode, sattr);