]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge branch 'vfs_timespec64' of https://github.com/deepa-hub/vfs into vfs-timespec64
authorArnd Bergmann <arnd@arndb.de>
Thu, 14 Jun 2018 12:51:13 +0000 (14:51 +0200)
committerArnd Bergmann <arnd@arndb.de>
Thu, 14 Jun 2018 12:54:00 +0000 (14:54 +0200)
Pull the timespec64 conversion from Deepa Dinamani:
 "The series aims to switch vfs timestamps to use
  struct timespec64. Currently vfs uses struct timespec,
  which is not y2038 safe.

  The flag patch applies cleanly. I've not seen the timestamps
  update logic change often. The series applies cleanly on 4.17-rc6
  and linux-next tip (top commit: next-20180517).

  I'm not sure how to merge this kind of a series with a flag patch.
  We are targeting 4.18 for this.
  Let me know if you have other suggestions.

  The series involves the following:
  1. Add vfs helper functions for supporting struct timepec64 timestamps.
  2. Cast prints of vfs timestamps to avoid warnings after the switch.
  3. Simplify code using vfs timestamps so that the actual
     replacement becomes easy.
  4. Convert vfs timestamps to use struct timespec64 using a script.
     This is a flag day patch.

  I've tried to keep the conversions with the script simple, to
  aid in the reviews. I've kept all the internal filesystem data
  structures and function signatures the same.

  Next steps:
  1. Convert APIs that can handle timespec64, instead of converting
     timestamps at the boundaries.
  2. Update internal data structures to avoid timestamp conversions."

I've pulled it into a branch based on top of the NFS changes that
are now in mainline, so I could resolve the non-obvious conflict
between the two while merging.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
1  2 
fs/btrfs/inode.c
fs/cramfs/inode.c
fs/ext4/namei.c
fs/f2fs/namei.c
fs/jffs2/dir.c
fs/nfs/callback_proc.c
fs/nfs/inode.c
fs/nfs/nfs4xdr.c
fs/reiserfs/namei.c

diff --combined fs/btrfs/inode.c
index 0b86cf10cf2ac79732ea548bbe970819ea758d4e,233a2bf70351a753940a77d6fbdfc297523330cb..035a529084b996ba972f23d51d011546501cd7dd
@@@ -5777,7 -5777,7 +5777,7 @@@ static struct inode *new_simple_dir(str
        inode->i_mtime = current_time(inode);
        inode->i_atime = inode->i_mtime;
        inode->i_ctime = inode->i_mtime;
-       BTRFS_I(inode)->i_otime = inode->i_mtime;
+       BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime);
  
        return inode;
  }
@@@ -6131,7 -6131,7 +6131,7 @@@ static int btrfs_dirty_inode(struct ino
   * This is a copy of file_update_time.  We need this so we can return error on
   * ENOSPC for updating the inode in the case of file write and mmap writes.
   */
- static int btrfs_update_time(struct inode *inode, struct timespec *now,
+ static int btrfs_update_time(struct inode *inode, struct timespec64 *now,
                             int flags)
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
@@@ -6386,7 -6386,7 +6386,7 @@@ static struct inode *btrfs_new_inode(st
        inode->i_mtime = current_time(inode);
        inode->i_atime = inode->i_mtime;
        inode->i_ctime = inode->i_mtime;
-       BTRFS_I(inode)->i_otime = inode->i_mtime;
+       BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime);
  
        inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
                                  struct btrfs_inode_item);
@@@ -6586,7 -6586,8 +6586,7 @@@ static int btrfs_mknod(struct inode *di
                goto out_unlock_inode;
        } else {
                btrfs_update_inode(trans, root, inode);
 -              unlock_new_inode(inode);
 -              d_instantiate(dentry, inode);
 +              d_instantiate_new(dentry, inode);
        }
  
  out_unlock:
@@@ -6662,7 -6663,8 +6662,7 @@@ static int btrfs_create(struct inode *d
                goto out_unlock_inode;
  
        BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
  
  out_unlock:
        btrfs_end_transaction(trans);
@@@ -6807,7 -6809,12 +6807,7 @@@ static int btrfs_mkdir(struct inode *di
        if (err)
                goto out_fail_inode;
  
 -      d_instantiate(dentry, inode);
 -      /*
 -       * mkdir is special.  We're unlocking after we call d_instantiate
 -       * to avoid a race with nfsd calling d_instantiate.
 -       */
 -      unlock_new_inode(inode);
 +      d_instantiate_new(dentry, inode);
        drop_on_err = 0;
  
  out_fail:
@@@ -9117,8 -9124,7 +9117,8 @@@ static int btrfs_truncate(struct inode 
                                                 BTRFS_EXTENT_DATA_KEY);
                trans->block_rsv = &fs_info->trans_block_rsv;
                if (ret != -ENOSPC && ret != -EAGAIN) {
 -                      err = ret;
 +                      if (ret < 0)
 +                              err = ret;
                        break;
                }
  
@@@ -9465,7 -9471,7 +9465,7 @@@ static int btrfs_rename_exchange(struc
        struct btrfs_root *dest = BTRFS_I(new_dir)->root;
        struct inode *new_inode = new_dentry->d_inode;
        struct inode *old_inode = old_dentry->d_inode;
-       struct timespec ctime = current_time(old_inode);
+       struct timespec64 ctime = current_time(old_inode);
        struct dentry *parent;
        u64 old_ino = btrfs_ino(BTRFS_I(old_inode));
        u64 new_ino = btrfs_ino(BTRFS_I(new_inode));
@@@ -10251,7 -10257,8 +10251,7 @@@ static int btrfs_symlink(struct inode *
                goto out_unlock_inode;
        }
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
  
  out_unlock:
        btrfs_end_transaction(trans);
diff --combined fs/cramfs/inode.c
index 124b093d14e5671e549c77fb9c2c5398f9e93fc1,d7a600e00f289ab16ba9a9709007a6acdb832ddf..b926de280de023b309a461e325d1fafbaa2929ac
@@@ -90,7 -90,7 +90,7 @@@ static struct inode *get_cramfs_inode(s
        const struct cramfs_inode *cramfs_inode, unsigned int offset)
  {
        struct inode *inode;
-       static struct timespec zerotime;
+       static struct timespec64 zerotime;
  
        inode = iget_locked(sb, cramino(cramfs_inode, offset));
        if (!inode)
@@@ -492,7 -492,7 +492,7 @@@ static void cramfs_kill_sb(struct super
  {
        struct cramfs_sb_info *sbi = CRAMFS_SB(sb);
  
 -      if (IS_ENABLED(CCONFIG_CRAMFS_MTD) && sb->s_mtd) {
 +      if (IS_ENABLED(CONFIG_CRAMFS_MTD) && sb->s_mtd) {
                if (sbi && sbi->mtd_point_size)
                        mtd_unpoint(sb->s_mtd, 0, sbi->mtd_point_size);
                kill_mtd_super(sb);
diff --combined fs/ext4/namei.c
index 4a09063ce1d215492c313a2ce54a10418cf63d8b,2feb546dfcafc8f6e6409fe9ae86a5ec64dbf97e..2a4c25c4681da5fac6f61edc848ce45ee2e42218
@@@ -2411,7 -2411,8 +2411,7 @@@ static int ext4_add_nondir(handle_t *ha
        int err = ext4_add_entry(handle, dentry, inode);
        if (!err) {
                ext4_mark_inode_dirty(handle, inode);
 -              unlock_new_inode(inode);
 -              d_instantiate(dentry, inode);
 +              d_instantiate_new(dentry, inode);
                return 0;
        }
        drop_nlink(inode);
@@@ -2650,7 -2651,8 +2650,7 @@@ out_clear_inode
        err = ext4_mark_inode_dirty(handle, dir);
        if (err)
                goto out_clear_inode;
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
        if (IS_DIRSYNC(dir))
                ext4_handle_sync(handle);
  
@@@ -3673,7 -3675,7 +3673,7 @@@ static int ext4_cross_rename(struct ino
        };
        u8 new_file_type;
        int retval;
-       struct timespec ctime;
+       struct timespec64 ctime;
  
        if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT) &&
             !projid_eq(EXT4_I(new_dir)->i_projid,
diff --combined fs/f2fs/namei.c
index 75e37fd720b2ba999c05dbb0219f7f4850d6f25e,ae10fe34f63d37bfc4399777d98a7759482398c4..4455d6c82808530977837303c16df3e05f4ee0d3
@@@ -50,8 -50,8 +50,8 @@@ static struct inode *f2fs_new_inode(str
  
        inode->i_ino = ino;
        inode->i_blocks = 0;
-       inode->i_mtime = inode->i_atime = inode->i_ctime =
-                       F2FS_I(inode)->i_crtime = current_time(inode);
+       inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+       F2FS_I(inode)->i_crtime = timespec64_to_timespec(inode->i_mtime);
        inode->i_generation = sbi->s_next_generation++;
  
        err = insert_inode_locked(inode);
@@@ -294,7 -294,8 +294,7 @@@ static int f2fs_create(struct inode *di
  
        alloc_nid_done(sbi, ino);
  
 -      d_instantiate(dentry, inode);
 -      unlock_new_inode(inode);
 +      d_instantiate_new(dentry, inode);
  
        if (IS_DIRSYNC(dir))
                f2fs_sync_fs(sbi->sb, 1);
@@@ -596,7 -597,8 +596,7 @@@ static int f2fs_symlink(struct inode *d
        err = page_symlink(inode, disk_link.name, disk_link.len);
  
  err_out:
 -      d_instantiate(dentry, inode);
 -      unlock_new_inode(inode);
 +      d_instantiate_new(dentry, inode);
  
        /*
         * Let's flush symlink data in order to avoid broken symlink as much as
@@@ -659,7 -661,8 +659,7 @@@ static int f2fs_mkdir(struct inode *dir
  
        alloc_nid_done(sbi, inode->i_ino);
  
 -      d_instantiate(dentry, inode);
 -      unlock_new_inode(inode);
 +      d_instantiate_new(dentry, inode);
  
        if (IS_DIRSYNC(dir))
                f2fs_sync_fs(sbi->sb, 1);
@@@ -710,7 -713,8 +710,7 @@@ static int f2fs_mknod(struct inode *dir
  
        alloc_nid_done(sbi, inode->i_ino);
  
 -      d_instantiate(dentry, inode);
 -      unlock_new_inode(inode);
 +      d_instantiate_new(dentry, inode);
  
        if (IS_DIRSYNC(dir))
                f2fs_sync_fs(sbi->sb, 1);
diff --combined fs/jffs2/dir.c
index e5a6deb38e1e1be47803250b3de5d115ce5c7e88,4ef97805eb27ed269add4ebfe9ecd1c4b93bb651..b2944f9218f79df0e1b43b3342cf17657784c4d5
@@@ -201,7 -201,7 +201,7 @@@ static int jffs2_create(struct inode *d
        if (ret)
                goto fail;
  
-       dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
+       dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->ctime)));
  
        jffs2_free_raw_inode(ri);
  
                  __func__, inode->i_ino, inode->i_mode, inode->i_nlink,
                  f->inocache->pino_nlink, inode->i_mapping->nrpages);
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
        return 0;
  
   fail:
@@@ -234,7 -235,7 +234,7 @@@ static int jffs2_unlink(struct inode *d
        if (dead_f->inocache)
                set_nlink(d_inode(dentry), dead_f->inocache->pino_nlink);
        if (!ret)
-               dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+               dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
        return ret;
  }
  /***********************************************************************/
@@@ -268,7 -269,7 +268,7 @@@ static int jffs2_link (struct dentry *o
                set_nlink(d_inode(old_dentry), ++f->inocache->pino_nlink);
                mutex_unlock(&f->sem);
                d_instantiate(dentry, d_inode(old_dentry));
-               dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+               dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
                ihold(d_inode(old_dentry));
        }
        return ret;
@@@ -418,7 -419,7 +418,7 @@@ static int jffs2_symlink (struct inode 
                goto fail;
        }
  
-       dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
+       dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(rd->mctime)));
  
        jffs2_free_raw_dirent(rd);
  
        mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
        return 0;
  
   fail:
@@@ -561,7 -563,7 +561,7 @@@ static int jffs2_mkdir (struct inode *d
                goto fail;
        }
  
-       dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
+       dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(rd->mctime)));
        inc_nlink(dir_i);
  
        jffs2_free_raw_dirent(rd);
        mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
        return 0;
  
   fail:
@@@ -598,7 -601,7 +598,7 @@@ static int jffs2_rmdir (struct inode *d
        ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
                              dentry->d_name.len, f, now);
        if (!ret) {
-               dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+               dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
                clear_nlink(d_inode(dentry));
                drop_nlink(dir_i);
        }
@@@ -733,7 -736,7 +733,7 @@@ static int jffs2_mknod (struct inode *d
                goto fail;
        }
  
-       dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
+       dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(rd->mctime)));
  
        jffs2_free_raw_dirent(rd);
  
        mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
        return 0;
  
   fail:
@@@ -853,14 -857,14 +853,14 @@@ static int jffs2_rename (struct inode *
                 * caller won't do it on its own since we are returning an error.
                 */
                d_invalidate(new_dentry);
-               new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
+               new_dir_i->i_mtime = new_dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
                return ret;
        }
  
        if (d_is_dir(old_dentry))
                drop_nlink(old_dir_i);
  
-       new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);
+       new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
  
        return 0;
  }
diff --combined fs/nfs/callback_proc.c
index ee81031cab29e3dd097e55a87a3d5c7b8824f66c,9d24aabcd8bbd820442cca8936ab3cb94a7cebc4..64c214fb9da67d5ba0ce6fb732a6c3df963823cf
@@@ -40,9 -40,7 +40,9 @@@ __be32 nfs4_callback_getattr(void *argp
                rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
  
        inode = nfs_delegation_find_inode(cps->clp, &args->fh);
 -      if (inode == NULL) {
 +      if (IS_ERR(inode)) {
 +              if (inode == ERR_PTR(-EAGAIN))
 +                      res->status = htonl(NFS4ERR_DELAY);
                trace_nfs4_cb_getattr(cps->clp, &args->fh, NULL,
                                -ntohl(res->status));
                goto out;
@@@ -56,8 -54,8 +56,8 @@@
        res->change_attr = delegation->change_attr;
        if (nfs_have_writebacks(inode))
                res->change_attr++;
-       res->ctime = inode->i_ctime;
-       res->mtime = inode->i_mtime;
+       res->ctime = timespec64_to_timespec(inode->i_ctime);
+       res->mtime = timespec64_to_timespec(inode->i_mtime);
        res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) &
                args->bitmap[0];
        res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) &
@@@ -88,9 -86,7 +88,9 @@@ __be32 nfs4_callback_recall(void *argp
  
        res = htonl(NFS4ERR_BADHANDLE);
        inode = nfs_delegation_find_inode(cps->clp, &args->fh);
 -      if (inode == NULL) {
 +      if (IS_ERR(inode)) {
 +              if (inode == ERR_PTR(-EAGAIN))
 +                      res = htonl(NFS4ERR_DELAY);
                trace_nfs4_cb_recall(cps->clp, &args->fh, NULL,
                                &args->stateid, -ntohl(res));
                goto out;
@@@ -128,6 -124,7 +128,6 @@@ static struct inode *nfs_layout_find_in
        struct inode *inode;
        struct pnfs_layout_hdr *lo;
  
 -restart:
        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
                list_for_each_entry(lo, &server->layouts, plh_layouts) {
                        if (stateid != NULL &&
                                continue;
                        inode = igrab(lo->plh_inode);
                        if (!inode)
 -                              continue;
 +                              return ERR_PTR(-EAGAIN);
                        if (!nfs_sb_active(inode->i_sb)) {
                                rcu_read_unlock();
                                spin_unlock(&clp->cl_lock);
                                iput(inode);
                                spin_lock(&clp->cl_lock);
                                rcu_read_lock();
 -                              goto restart;
 +                              return ERR_PTR(-EAGAIN);
                        }
                        return inode;
                }
        }
  
 -      return NULL;
 +      return ERR_PTR(-ENOENT);
  }
  
  /*
@@@ -165,6 -162,7 +165,6 @@@ static struct inode *nfs_layout_find_in
        struct inode *inode;
        struct pnfs_layout_hdr *lo;
  
 -restart:
        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
                list_for_each_entry(lo, &server->layouts, plh_layouts) {
                        nfsi = NFS_I(lo->plh_inode);
                                continue;
                        inode = igrab(lo->plh_inode);
                        if (!inode)
 -                              continue;
 +                              return ERR_PTR(-EAGAIN);
                        if (!nfs_sb_active(inode->i_sb)) {
                                rcu_read_unlock();
                                spin_unlock(&clp->cl_lock);
                                iput(inode);
                                spin_lock(&clp->cl_lock);
                                rcu_read_lock();
 -                              goto restart;
 +                              return ERR_PTR(-EAGAIN);
                        }
                        return inode;
                }
        }
  
 -      return NULL;
 +      return ERR_PTR(-ENOENT);
  }
  
  static struct inode *nfs_layout_find_inode(struct nfs_client *clp,
        spin_lock(&clp->cl_lock);
        rcu_read_lock();
        inode = nfs_layout_find_inode_by_stateid(clp, stateid);
 -      if (!inode)
 +      if (inode == ERR_PTR(-ENOENT))
                inode = nfs_layout_find_inode_by_fh(clp, fh);
        rcu_read_unlock();
        spin_unlock(&clp->cl_lock);
@@@ -254,11 -252,8 +254,11 @@@ static u32 initiate_file_draining(struc
        LIST_HEAD(free_me_list);
  
        ino = nfs_layout_find_inode(clp, &args->cbl_fh, &args->cbl_stateid);
 -      if (!ino)
 -              goto out;
 +      if (IS_ERR(ino)) {
 +              if (ino == ERR_PTR(-EAGAIN))
 +                      rv = NFS4ERR_DELAY;
 +              goto out_noput;
 +      }
  
        pnfs_layoutcommit_inode(ino, false);
  
@@@ -304,10 -299,9 +304,10 @@@ unlock
        nfs_commit_inode(ino, 0);
        pnfs_put_layout_hdr(lo);
  out:
 +      nfs_iput_and_deactive(ino);
 +out_noput:
        trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino,
                        &args->cbl_stateid, -rv);
 -      nfs_iput_and_deactive(ino);
        return rv;
  }
  
@@@ -328,8 -322,6 +328,8 @@@ static u32 initiate_bulk_draining(struc
  static u32 do_callback_layoutrecall(struct nfs_client *clp,
                                    struct cb_layoutrecallargs *args)
  {
 +      write_seqcount_begin(&clp->cl_callback_count);
 +      write_seqcount_end(&clp->cl_callback_count);
        if (args->cbl_recall_type == RETURN_FILE)
                return initiate_file_draining(clp, args);
        return initiate_bulk_draining(clp, args);
@@@ -428,8 -420,11 +428,8 @@@ validate_seqid(const struct nfs4_slot_t
                return htonl(NFS4ERR_SEQ_FALSE_RETRY);
        }
  
 -      /* Wraparound */
 -      if (unlikely(slot->seq_nr == 0xFFFFFFFFU)) {
 -              if (args->csa_sequenceid == 1)
 -                      return htonl(NFS4_OK);
 -      } else if (likely(args->csa_sequenceid == slot->seq_nr + 1))
 +      /* Note: wraparound relies on seq_nr being of type u32 */
 +      if (likely(args->csa_sequenceid == slot->seq_nr + 1))
                return htonl(NFS4_OK);
  
        /* Misordered request */
diff --combined fs/nfs/inode.c
index 73473d9bdfa499945540eda1296719646acc8cae,138941a97327d4ae96a70a4e973dcfeb764efa16..b65aee481d131d00734c057cd16f4532f2898211
@@@ -195,16 -195,10 +195,16 @@@ bool nfs_check_cache_invalid(struct ino
  static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
  {
        struct nfs_inode *nfsi = NFS_I(inode);
 -      bool have_delegation = nfs_have_delegated_attributes(inode);
 +      bool have_delegation = NFS_PROTO(inode)->have_delegation(inode, FMODE_READ);
 +
 +      if (have_delegation) {
 +              if (!(flags & NFS_INO_REVAL_FORCED))
 +                      flags &= ~NFS_INO_INVALID_OTHER;
 +              flags &= ~(NFS_INO_INVALID_CHANGE
 +                              | NFS_INO_INVALID_SIZE
 +                              | NFS_INO_REVAL_PAGECACHE);
 +      }
  
 -      if (have_delegation)
 -              flags &= ~(NFS_INO_INVALID_CHANGE|NFS_INO_REVAL_PAGECACHE);
        if (inode->i_mapping->nrpages == 0)
                flags &= ~NFS_INO_INVALID_DATA;
        nfsi->cache_validity |= flags;
@@@ -454,7 -448,6 +454,7 @@@ nfs_fhget(struct super_block *sb, struc
                /* We can't support update_atime(), since the server will reset it */
                inode->i_flags |= S_NOATIME|S_NOCMTIME;
                inode->i_mode = fattr->mode;
 +              nfsi->cache_validity = 0;
                if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0
                                && nfs_server_capable(inode, NFS_CAP_MODE))
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
                nfsi->read_cache_jiffies = fattr->time_start;
                nfsi->attr_gencount = fattr->gencount;
                if (fattr->valid & NFS_ATTR_FATTR_ATIME)
-                       inode->i_atime = fattr->atime;
+                       inode->i_atime = timespec_to_timespec64(fattr->atime);
                else if (nfs_server_capable(inode, NFS_CAP_ATIME))
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME);
                if (fattr->valid & NFS_ATTR_FATTR_MTIME)
-                       inode->i_mtime = fattr->mtime;
+                       inode->i_mtime = timespec_to_timespec64(fattr->mtime);
                else if (nfs_server_capable(inode, NFS_CAP_MTIME))
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
                if (fattr->valid & NFS_ATTR_FATTR_CTIME)
-                       inode->i_ctime = fattr->ctime;
+                       inode->i_ctime = timespec_to_timespec64(fattr->ctime);
                else if (nfs_server_capable(inode, NFS_CAP_CTIME))
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_CTIME);
                if (fattr->valid & NFS_ATTR_FATTR_CHANGE)
                        inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
                }
  
 +              if (nfsi->cache_validity != 0)
 +                      nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
 +
                nfs_setsecurity(inode, fattr, label);
  
                nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
@@@ -677,13 -667,9 +677,13 @@@ void nfs_setattr_update_inode(struct in
  
        spin_lock(&inode->i_lock);
        NFS_I(inode)->attr_gencount = fattr->gencount;
 -      nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
 -                      | NFS_INO_INVALID_CTIME);
 +      if ((attr->ia_valid & ATTR_SIZE) != 0) {
 +              nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
 +              nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
 +              nfs_vmtruncate(inode, attr->ia_size);
 +      }
        if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
 +              NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_CTIME;
                if ((attr->ia_valid & ATTR_MODE) != 0) {
                        int mode = attr->ia_mode & S_IALLUGO;
                        mode |= inode->i_mode & ~S_IALLUGO;
                        inode->i_uid = attr->ia_uid;
                if ((attr->ia_valid & ATTR_GID) != 0)
                        inode->i_gid = attr->ia_gid;
-                       inode->i_ctime = fattr->ctime;
 +              if (fattr->valid & NFS_ATTR_FATTR_CTIME)
++                      inode->i_ctime = timespec_to_timespec64(fattr->ctime);
 +              else
 +                      nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
 +                                      | NFS_INO_INVALID_CTIME);
                nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS
                                | NFS_INO_INVALID_ACL);
        }
 -      if ((attr->ia_valid & ATTR_SIZE) != 0) {
 -              nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
 -              nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
 -              nfs_vmtruncate(inode, attr->ia_size);
 +      if (attr->ia_valid & (ATTR_ATIME_SET|ATTR_ATIME)) {
 +              NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_ATIME
 +                              | NFS_INO_INVALID_CTIME);
 +              if (fattr->valid & NFS_ATTR_FATTR_ATIME)
-                       inode->i_atime = fattr->atime;
++                      inode->i_atime = timespec_to_timespec64(fattr->atime);
 +              else if (attr->ia_valid & ATTR_ATIME_SET)
 +                      inode->i_atime = attr->ia_atime;
 +              else
 +                      nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME);
 +
 +              if (fattr->valid & NFS_ATTR_FATTR_CTIME)
-                       inode->i_ctime = fattr->ctime;
++                      inode->i_ctime = timespec_to_timespec64(fattr->ctime);
 +              else
 +                      nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
 +                                      | NFS_INO_INVALID_CTIME);
 +      }
 +      if (attr->ia_valid & (ATTR_MTIME_SET|ATTR_MTIME)) {
 +              NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_MTIME
 +                              | NFS_INO_INVALID_CTIME);
 +              if (fattr->valid & NFS_ATTR_FATTR_MTIME)
-                       inode->i_mtime = fattr->mtime;
++                      inode->i_mtime = timespec_to_timespec64(fattr->mtime);
 +              else if (attr->ia_valid & ATTR_MTIME_SET)
 +                      inode->i_mtime = attr->ia_mtime;
 +              else
 +                      nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
 +
 +              if (fattr->valid & NFS_ATTR_FATTR_CTIME)
-                       inode->i_ctime = fattr->ctime;
++                      inode->i_ctime = timespec_to_timespec64(fattr->ctime);
 +              else
 +                      nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
 +                                      | NFS_INO_INVALID_CTIME);
        }
        if (fattr->valid)
                nfs_update_inode(inode, fattr);
@@@ -1143,8 -1097,7 +1143,8 @@@ __nfs_revalidate_inode(struct nfs_serve
                goto out;
        }
  
 -      status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label);
 +      status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr,
 +                      label, inode);
        if (status != 0) {
                dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) getattr failed, error=%d\n",
                         inode->i_sb->s_id,
@@@ -1351,6 -1304,8 +1351,8 @@@ static bool nfs_file_has_buffered_write
  
  static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
  {
+       struct timespec ts;
        if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE)
                        && (fattr->valid & NFS_ATTR_FATTR_CHANGE)
                        && inode_eq_iversion_raw(inode, fattr->pre_change_attr)) {
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
        }
        /* If we have atomic WCC data, we may update some attributes */
+       ts = timespec64_to_timespec(inode->i_ctime);
        if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME)
                        && (fattr->valid & NFS_ATTR_FATTR_CTIME)
-                       && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
-               memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+                       && timespec_equal(&ts, &fattr->pre_ctime)) {
+               inode->i_ctime = timespec_to_timespec64(fattr->ctime);
        }
  
+       ts = timespec64_to_timespec(inode->i_mtime);
        if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME)
                        && (fattr->valid & NFS_ATTR_FATTR_MTIME)
-                       && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) {
-               memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+                       && timespec_equal(&ts, &fattr->pre_mtime)) {
+               inode->i_mtime = timespec_to_timespec64(fattr->mtime);
                if (S_ISDIR(inode->i_mode))
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
        }
@@@ -1394,11 -1351,10 +1398,11 @@@ static int nfs_check_inode_attributes(s
        struct nfs_inode *nfsi = NFS_I(inode);
        loff_t cur_size, new_isize;
        unsigned long invalid = 0;
+       struct timespec ts;
  
 -      if (nfs_have_delegated_attributes(inode))
 +      if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
                return 0;
 +
        /* Has the inode gone and changed behind our back? */
        if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid)
                return -ESTALE;
                        invalid |= NFS_INO_INVALID_CHANGE
                                | NFS_INO_REVAL_PAGECACHE;
  
-               if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime))
+               ts = timespec64_to_timespec(inode->i_mtime);
+               if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&ts, &fattr->mtime))
                        invalid |= NFS_INO_INVALID_MTIME;
  
-               if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&inode->i_ctime, &fattr->ctime))
+               ts = timespec64_to_timespec(inode->i_ctime);
+               if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&ts, &fattr->ctime))
                        invalid |= NFS_INO_INVALID_CTIME;
  
                if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
        if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink)
                invalid |= NFS_INO_INVALID_OTHER;
  
-       if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime))
+       ts = timespec64_to_timespec(inode->i_atime);
+       if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&ts, &fattr->atime))
                invalid |= NFS_INO_INVALID_ATIME;
  
        if (invalid != 0)
 -              nfs_set_cache_invalid(inode, invalid | NFS_INO_REVAL_FORCED);
 +              nfs_set_cache_invalid(inode, invalid);
  
        nfsi->read_cache_jiffies = fattr->time_start;
        return 0;
@@@ -1677,8 -1636,7 +1684,8 @@@ int nfs_post_op_update_inode(struct ino
        nfs_fattr_set_barrier(fattr);
        status = nfs_post_op_update_inode_locked(inode, fattr,
                        NFS_INO_INVALID_CHANGE
 -                      | NFS_INO_INVALID_CTIME);
 +                      | NFS_INO_INVALID_CTIME
 +                      | NFS_INO_REVAL_FORCED);
        spin_unlock(&inode->i_lock);
  
        return status;
@@@ -1716,12 -1674,12 +1723,12 @@@ int nfs_post_op_update_inode_force_wcc_
        }
        if ((fattr->valid & NFS_ATTR_FATTR_CTIME) != 0 &&
                        (fattr->valid & NFS_ATTR_FATTR_PRECTIME) == 0) {
-               memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime));
+               fattr->pre_ctime = timespec64_to_timespec(inode->i_ctime);
                fattr->valid |= NFS_ATTR_FATTR_PRECTIME;
        }
        if ((fattr->valid & NFS_ATTR_FATTR_MTIME) != 0 &&
                        (fattr->valid & NFS_ATTR_FATTR_PREMTIME) == 0) {
-               memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime));
+               fattr->pre_mtime = timespec64_to_timespec(inode->i_mtime);
                fattr->valid |= NFS_ATTR_FATTR_PREMTIME;
        }
        if ((fattr->valid & NFS_ATTR_FATTR_SIZE) != 0 &&
@@@ -1795,8 -1753,6 +1802,8 @@@ static int nfs_update_inode(struct inod
        unsigned long save_cache_validity;
        bool have_writers = nfs_file_has_buffered_writers(nfsi);
        bool cache_revalidated = true;
 +      bool attr_changed = false;
 +      bool have_delegation;
  
        dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%x)\n",
                        __func__, inode->i_sb->s_id, inode->i_ino,
                        !IS_AUTOMOUNT(inode))
                server->fsid = fattr->fsid;
  
 +      /* Save the delegation state before clearing cache_validity */
 +      have_delegation = nfs_have_delegated_attributes(inode);
 +
        /*
         * Update the read time so we don't revalidate too often.
         */
        /* More cache consistency checks */
        if (fattr->valid & NFS_ATTR_FATTR_CHANGE) {
                if (!inode_eq_iversion_raw(inode, fattr->change_attr)) {
 -                      dprintk("NFS: change_attr change on server for file %s/%ld\n",
 -                                      inode->i_sb->s_id, inode->i_ino);
                        /* Could it be a race with writeback? */
 -                      if (!have_writers) {
 -                              invalid |= NFS_INO_INVALID_CHANGE
 -                                      | NFS_INO_INVALID_DATA
 +                      if (!(have_writers || have_delegation)) {
 +                              invalid |= NFS_INO_INVALID_DATA
                                        | NFS_INO_INVALID_ACCESS
                                        | NFS_INO_INVALID_ACL;
                                /* Force revalidate of all attributes */
                                        | NFS_INO_INVALID_OTHER;
                                if (S_ISDIR(inode->i_mode))
                                        nfs_force_lookup_revalidate(inode);
 +                              dprintk("NFS: change_attr change on server for file %s/%ld\n",
 +                                              inode->i_sb->s_id,
 +                                              inode->i_ino);
                        }
                        inode_set_iversion_raw(inode, fattr->change_attr);
 +                      attr_changed = true;
                }
        } else {
                nfsi->cache_validity |= save_cache_validity &
        }
  
        if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
-               memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+               inode->i_mtime = timespec_to_timespec64(fattr->mtime);
        } else if (server->caps & NFS_CAP_MTIME) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_MTIME
        }
  
        if (fattr->valid & NFS_ATTR_FATTR_CTIME) {
-               memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+               inode->i_ctime = timespec_to_timespec64(fattr->ctime);
        } else if (server->caps & NFS_CAP_CTIME) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_CTIME
        if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
                new_isize = nfs_size_to_loff_t(fattr->size);
                cur_isize = i_size_read(inode);
 -              if (new_isize != cur_isize) {
 +              if (new_isize != cur_isize && !have_delegation) {
                        /* Do we perhaps have any outstanding writes, or has
                         * the file grown beyond our last write? */
                        if (!nfs_have_writebacks(inode) || new_isize > cur_isize) {
                                i_size_write(inode, new_isize);
                                if (!have_writers)
                                        invalid |= NFS_INO_INVALID_DATA;
 +                              attr_changed = true;
                        }
                        dprintk("NFS: isize change on server for file %s/%ld "
                                        "(%Ld to %Ld)\n",
  
  
        if (fattr->valid & NFS_ATTR_FATTR_ATIME)
-               memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
+               inode->i_atime = timespec_to_timespec64(fattr->atime);
        else if (server->caps & NFS_CAP_ATIME) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_ATIME
                        newmode |= fattr->mode & S_IALLUGO;
                        inode->i_mode = newmode;
                        invalid |= NFS_INO_INVALID_ACCESS
 -                              | NFS_INO_INVALID_ACL
 -                              | NFS_INO_INVALID_OTHER;
 +                              | NFS_INO_INVALID_ACL;
 +                      attr_changed = true;
                }
        } else if (server->caps & NFS_CAP_MODE) {
                nfsi->cache_validity |= save_cache_validity &
 -                              (NFS_INO_INVALID_ACCESS
 -                              | NFS_INO_INVALID_ACL
 -                              | NFS_INO_INVALID_OTHER
 +                              (NFS_INO_INVALID_OTHER
                                | NFS_INO_REVAL_FORCED);
                cache_revalidated = false;
        }
        if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
                if (!uid_eq(inode->i_uid, fattr->uid)) {
                        invalid |= NFS_INO_INVALID_ACCESS
 -                              | NFS_INO_INVALID_ACL
 -                              | NFS_INO_INVALID_OTHER;
 +                              | NFS_INO_INVALID_ACL;
                        inode->i_uid = fattr->uid;
 +                      attr_changed = true;
                }
        } else if (server->caps & NFS_CAP_OWNER) {
                nfsi->cache_validity |= save_cache_validity &
 -                              (NFS_INO_INVALID_ACCESS
 -                              | NFS_INO_INVALID_ACL
 -                              | NFS_INO_INVALID_OTHER
 +                              (NFS_INO_INVALID_OTHER
                                | NFS_INO_REVAL_FORCED);
                cache_revalidated = false;
        }
        if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
                if (!gid_eq(inode->i_gid, fattr->gid)) {
                        invalid |= NFS_INO_INVALID_ACCESS
 -                              | NFS_INO_INVALID_ACL
 -                              | NFS_INO_INVALID_OTHER;
 +                              | NFS_INO_INVALID_ACL;
                        inode->i_gid = fattr->gid;
 +                      attr_changed = true;
                }
        } else if (server->caps & NFS_CAP_OWNER_GROUP) {
                nfsi->cache_validity |= save_cache_validity &
 -                              (NFS_INO_INVALID_ACCESS
 -                              | NFS_INO_INVALID_ACL
 -                              | NFS_INO_INVALID_OTHER
 +                              (NFS_INO_INVALID_OTHER
                                | NFS_INO_REVAL_FORCED);
                cache_revalidated = false;
        }
  
        if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
                if (inode->i_nlink != fattr->nlink) {
 -                      invalid |= NFS_INO_INVALID_OTHER;
                        if (S_ISDIR(inode->i_mode))
                                invalid |= NFS_INO_INVALID_DATA;
                        set_nlink(inode, fattr->nlink);
 +                      attr_changed = true;
                }
        } else if (server->caps & NFS_CAP_NLINK) {
                nfsi->cache_validity |= save_cache_validity &
                cache_revalidated = false;
  
        /* Update attrtimeo value if we're out of the unstable period */
 -      if (invalid & NFS_INO_INVALID_ATTR) {
 +      if (attr_changed) {
                invalid &= ~NFS_INO_INVALID_ATTR;
                nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
                nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
                                || S_ISLNK(inode->i_mode)))
                invalid &= ~NFS_INO_INVALID_DATA;
 -      if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) ||
 -                      (save_cache_validity & NFS_INO_REVAL_FORCED))
 -              nfs_set_cache_invalid(inode, invalid);
 +      nfs_set_cache_invalid(inode, invalid);
  
        return 0;
   out_err:
diff --combined fs/nfs/nfs4xdr.c
index 738a7be019d2f696737ba6ccd46d04e996644c22,481426e9e6f05de893ace0eab80d94fa57ea04ca..cd41d2577a049b489496b24a05ec2e28b959ee9d
  /* Mapping from NFS error code to "errno" error code. */
  #define errno_NFSERR_IO               EIO
  
 +struct compound_hdr;
  static int nfs4_stat_to_errno(int);
 +static void encode_layoutget(struct xdr_stream *xdr,
 +                           const struct nfs4_layoutget_args *args,
 +                           struct compound_hdr *hdr);
 +static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
 +                           struct nfs4_layoutget_res *res);
  
  /* NFSv4 COMPOUND tags are only wanted for debugging purposes */
  #ifdef DEBUG
  #define decode_sequence_maxsz 0
  #define encode_layoutreturn_maxsz 0
  #define decode_layoutreturn_maxsz 0
 +#define encode_layoutget_maxsz        0
 +#define decode_layoutget_maxsz        0
  #endif /* CONFIG_NFS_V4_1 */
  
  #define NFS4_enc_compound_sz  (1024)  /* XXX: large enough? */
                                encode_open_maxsz + \
                                encode_access_maxsz + \
                                encode_getfh_maxsz + \
 -                              encode_getattr_maxsz)
 +                              encode_getattr_maxsz + \
 +                              encode_layoutget_maxsz)
  #define NFS4_dec_open_sz        (compound_decode_hdr_maxsz + \
                                decode_sequence_maxsz + \
                                decode_putfh_maxsz + \
                                decode_open_maxsz + \
                                decode_access_maxsz + \
                                decode_getfh_maxsz + \
 -                              decode_getattr_maxsz)
 +                              decode_getattr_maxsz + \
 +                              decode_layoutget_maxsz)
  #define NFS4_enc_open_confirm_sz \
                                (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
                                        encode_putfh_maxsz + \
                                        encode_open_maxsz + \
                                        encode_access_maxsz + \
 -                                      encode_getattr_maxsz)
 +                                      encode_getattr_maxsz + \
 +                                      encode_layoutget_maxsz)
  #define NFS4_dec_open_noattr_sz       (compound_decode_hdr_maxsz + \
                                        decode_sequence_maxsz + \
                                        decode_putfh_maxsz + \
                                        decode_open_maxsz + \
                                        decode_access_maxsz + \
 -                                      decode_getattr_maxsz)
 +                                      decode_getattr_maxsz + \
 +                                      decode_layoutget_maxsz)
  #define NFS4_enc_open_downgrade_sz \
                                (compound_encode_hdr_maxsz + \
                                 encode_sequence_maxsz + \
@@@ -1069,6 -1057,7 +1069,7 @@@ static void encode_attrs(struct xdr_str
                                const struct nfs_server *server,
                                const uint32_t attrmask[])
  {
+       struct timespec ts;
        char owner_name[IDMAP_NAMESZ];
        char owner_group[IDMAP_NAMESZ];
        int owner_namelen = 0;
        if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
                if (iap->ia_valid & ATTR_ATIME_SET) {
                        *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
-                       p = xdr_encode_nfstime4(p, &iap->ia_atime);
+                       ts = timespec64_to_timespec(iap->ia_atime);
+                       p = xdr_encode_nfstime4(p, &ts);
                } else
                        *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
        }
        if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
                if (iap->ia_valid & ATTR_MTIME_SET) {
                        *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
-                       p = xdr_encode_nfstime4(p, &iap->ia_mtime);
+                       ts = timespec64_to_timespec(iap->ia_mtime);
+                       p = xdr_encode_nfstime4(p, &ts);
                } else
                        *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
        }
@@@ -2082,13 -2073,6 +2085,13 @@@ encode_layoutreturn(struct xdr_stream *
                    struct compound_hdr *hdr)
  {
  }
 +
 +static void
 +encode_layoutget(struct xdr_stream *xdr,
 +                    const struct nfs4_layoutget_args *args,
 +                    struct compound_hdr *hdr)
 +{
 +}
  #endif /* CONFIG_NFS_V4_1 */
  
  /*
@@@ -2335,12 -2319,6 +2338,12 @@@ static void nfs4_xdr_enc_open(struct rp
        if (args->access)
                encode_access(xdr, args->access, &hdr);
        encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
 +      if (args->lg_args) {
 +              encode_layoutget(xdr, args->lg_args, &hdr);
 +              xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
 +                               args->lg_args->layout.pages,
 +                               0, args->lg_args->layout.pglen);
 +      }
        encode_nops(&hdr);
  }
  
@@@ -2381,12 -2359,6 +2384,12 @@@ static void nfs4_xdr_enc_open_noattr(st
        if (args->access)
                encode_access(xdr, args->access, &hdr);
        encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
 +      if (args->lg_args) {
 +              encode_layoutget(xdr, args->lg_args, &hdr);
 +              xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
 +                               args->lg_args->layout.pages,
 +                               0, args->lg_args->layout.pglen);
 +      }
        encode_nops(&hdr);
  }
  
@@@ -6055,7 -6027,7 +6058,7 @@@ static int decode_layoutget(struct xdr_
  
        status = decode_op_hdr(xdr, OP_LAYOUTGET);
        if (status)
 -              return status;
 +              goto out;
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
                goto out_overflow;
        if (!layout_count) {
                dprintk("%s: server responded with empty layout array\n",
                        __func__);
 -              return -EINVAL;
 +              status = -EINVAL;
 +              goto out;
        }
  
        p = xdr_inline_decode(xdr, 28);
                dprintk("NFS: server cheating in layoutget reply: "
                                "layout len %u > recvd %u\n",
                                res->layoutp->len, recvd);
 -              return -EINVAL;
 +              status = -EINVAL;
 +              goto out;
        }
  
        if (layout_count > 1) {
                        __func__, layout_count);
        }
  
 -      return 0;
 +out:
 +      res->status = status;
 +      return status;
  out_overflow:
        print_overflow_msg(__func__, xdr);
 -      return -EIO;
 +      status = -EIO;
 +      goto out;
  }
  
  static int decode_layoutreturn(struct xdr_stream *xdr,
@@@ -6213,13 -6180,6 +6216,13 @@@ int decode_layoutreturn(struct xdr_stre
  {
        return 0;
  }
 +
 +static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
 +                          struct nfs4_layoutget_res *res)
 +{
 +      return 0;
 +}
 +
  #endif /* CONFIG_NFS_V4_1 */
  
  /*
@@@ -6666,8 -6626,6 +6669,8 @@@ static int nfs4_xdr_dec_open(struct rpc
        if (res->access_request)
                decode_access(xdr, &res->access_supported, &res->access_result);
        decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server);
 +      if (res->lg_res)
 +              decode_layoutget(xdr, rqstp, res->lg_res);
  out:
        return status;
  }
@@@ -6720,8 -6678,6 +6723,8 @@@ static int nfs4_xdr_dec_open_noattr(str
        if (res->access_request)
                decode_access(xdr, &res->access_supported, &res->access_result);
        decode_getfattr(xdr, res->f_attr, res->server);
 +      if (res->lg_res)
 +              decode_layoutget(xdr, rqstp, res->lg_res);
  out:
        return status;
  }
diff --combined fs/reiserfs/namei.c
index 5089dac0266020d705e54dcb8f06ca1a998ccec2,d2869ced6d394463ac4910ae96245e7c35201c56..97f3fc4fdd79e8b1b1fa2ad3be41a394742780ee
@@@ -687,7 -687,8 +687,7 @@@ static int reiserfs_create(struct inod
        reiserfs_update_inode_transaction(inode);
        reiserfs_update_inode_transaction(dir);
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
        retval = journal_end(&th);
  
  out_failed:
@@@ -770,7 -771,8 +770,7 @@@ static int reiserfs_mknod(struct inode 
                goto out_failed;
        }
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
        retval = journal_end(&th);
  
  out_failed:
@@@ -869,7 -871,8 +869,7 @@@ static int reiserfs_mkdir(struct inode 
        /* the above add_entry did not update dir's stat data */
        reiserfs_update_sd(&th, dir);
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
        retval = journal_end(&th);
  out_failed:
        reiserfs_write_unlock(dir->i_sb);
@@@ -1184,7 -1187,8 +1184,7 @@@ static int reiserfs_symlink(struct inod
                goto out_failed;
        }
  
 -      unlock_new_inode(inode);
 -      d_instantiate(dentry, inode);
 +      d_instantiate_new(dentry, inode);
        retval = journal_end(&th);
  out_failed:
        reiserfs_write_unlock(parent_dir->i_sb);
@@@ -1316,7 -1320,7 +1316,7 @@@ static int reiserfs_rename(struct inod
        int jbegin_count;
        umode_t old_inode_mode;
        unsigned long savelink = 1;
-       struct timespec ctime;
+       struct timespec64 ctime;
  
        if (flags & ~RENAME_NOREPLACE)
                return -EINVAL;