diff options
author | Olof Johansson <olof@lixom.net> | 2015-04-20 10:59:04 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2015-04-20 10:59:04 -0400 |
commit | cdaa8cf34863028dab238e1498555bf12d693244 (patch) | |
tree | 0034305d152c3c4887b81c8983d0f298e6e3f6cb /fs/nfs | |
parent | 30a5c1894a4c932f5a417f0a6ec369c7da81204b (diff) | |
parent | 98b80987c940956da48f0c703f60340128bb8521 (diff) |
Merge branch 'fixes' into next/fixes-non-critical
Merge a set of fixes that we missed sending in before v4.0 release. These
will also be sent to -stable.
* fixes: (659 commits)
ARM: at91/dt: sama5d3 xplained: add phy address for macb1
kbuild: Create directory for target DTB
ARM: mvebu: Disable CPU Idle on Armada 38x
arm64: juno: Fix misleading name of UART reference clock
ARM: dts: sunxi: Remove overclocked/overvoltaged OPP
ARM: dts: sun4i: a10-lime: Override and remove 1008MHz OPP setting
ARM: socfpga: dts: fix spi1 interrupt
ARM: dts: Fix gpio interrupts for dm816x
ARM: dts: dra7: remove ti,hwmod property from pcie phy
ARM: EXYNOS: Fix build breakage cpuidle on !SMP
ARM: OMAP: dmtimer: disable pm runtime on remove
ARM: OMAP: dmtimer: check for pm_runtime_get_sync() failure
ARM: dts: fix lid and power pin-functions for exynos5250-spring
ARM: dts: fix mmc node updates for exynos5250-spring
ARM: OMAP2+: Fix socbus family info for AM33xx devices
ARM: dts: omap3: Add missing dmas for crypto
+ Linux 4.0-rc4
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/client.c | 2 | ||||
-rw-r--r-- | fs/nfs/delegation.c | 45 | ||||
-rw-r--r-- | fs/nfs/dir.c | 22 | ||||
-rw-r--r-- | fs/nfs/file.c | 11 | ||||
-rw-r--r-- | fs/nfs/inode.c | 111 | ||||
-rw-r--r-- | fs/nfs/internal.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs3xdr.c | 5 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 9 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 31 | ||||
-rw-r--r-- | fs/nfs/nfs4session.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 18 | ||||
-rw-r--r-- | fs/nfs/proc.c | 6 | ||||
-rw-r--r-- | fs/nfs/write.c | 30 |
14 files changed, 237 insertions, 59 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index f9f4845db989..19874151e95c 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -433,7 +433,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat | |||
433 | 433 | ||
434 | static bool nfs_client_init_is_complete(const struct nfs_client *clp) | 434 | static bool nfs_client_init_is_complete(const struct nfs_client *clp) |
435 | { | 435 | { |
436 | return clp->cl_cons_state != NFS_CS_INITING; | 436 | return clp->cl_cons_state <= NFS_CS_READY; |
437 | } | 437 | } |
438 | 438 | ||
439 | int nfs_wait_client_init_complete(const struct nfs_client *clp) | 439 | int nfs_wait_client_init_complete(const struct nfs_client *clp) |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index a1f0685b42ff..a6ad68865880 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -181,8 +181,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, | |||
181 | clear_bit(NFS_DELEGATION_NEED_RECLAIM, | 181 | clear_bit(NFS_DELEGATION_NEED_RECLAIM, |
182 | &delegation->flags); | 182 | &delegation->flags); |
183 | spin_unlock(&delegation->lock); | 183 | spin_unlock(&delegation->lock); |
184 | put_rpccred(oldcred); | ||
185 | rcu_read_unlock(); | 184 | rcu_read_unlock(); |
185 | put_rpccred(oldcred); | ||
186 | trace_nfs4_reclaim_delegation(inode, res->delegation_type); | 186 | trace_nfs4_reclaim_delegation(inode, res->delegation_type); |
187 | } else { | 187 | } else { |
188 | /* We appear to have raced with a delegation return. */ | 188 | /* We appear to have raced with a delegation return. */ |
@@ -370,7 +370,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
370 | delegation = NULL; | 370 | delegation = NULL; |
371 | goto out; | 371 | goto out; |
372 | } | 372 | } |
373 | freeme = nfs_detach_delegation_locked(nfsi, | 373 | if (test_and_set_bit(NFS_DELEGATION_RETURNING, |
374 | &old_delegation->flags)) | ||
375 | goto out; | ||
376 | freeme = nfs_detach_delegation_locked(nfsi, | ||
374 | old_delegation, clp); | 377 | old_delegation, clp); |
375 | if (freeme == NULL) | 378 | if (freeme == NULL) |
376 | goto out; | 379 | goto out; |
@@ -433,6 +436,8 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) | |||
433 | { | 436 | { |
434 | bool ret = false; | 437 | bool ret = false; |
435 | 438 | ||
439 | if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) | ||
440 | goto out; | ||
436 | if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) | 441 | if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) |
437 | ret = true; | 442 | ret = true; |
438 | if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) { | 443 | if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) { |
@@ -444,6 +449,7 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) | |||
444 | ret = true; | 449 | ret = true; |
445 | spin_unlock(&delegation->lock); | 450 | spin_unlock(&delegation->lock); |
446 | } | 451 | } |
452 | out: | ||
447 | return ret; | 453 | return ret; |
448 | } | 454 | } |
449 | 455 | ||
@@ -471,14 +477,20 @@ restart: | |||
471 | super_list) { | 477 | super_list) { |
472 | if (!nfs_delegation_need_return(delegation)) | 478 | if (!nfs_delegation_need_return(delegation)) |
473 | continue; | 479 | continue; |
474 | inode = nfs_delegation_grab_inode(delegation); | 480 | if (!nfs_sb_active(server->super)) |
475 | if (inode == NULL) | ||
476 | continue; | 481 | continue; |
482 | inode = nfs_delegation_grab_inode(delegation); | ||
483 | if (inode == NULL) { | ||
484 | rcu_read_unlock(); | ||
485 | nfs_sb_deactive(server->super); | ||
486 | goto restart; | ||
487 | } | ||
477 | delegation = nfs_start_delegation_return_locked(NFS_I(inode)); | 488 | delegation = nfs_start_delegation_return_locked(NFS_I(inode)); |
478 | rcu_read_unlock(); | 489 | rcu_read_unlock(); |
479 | 490 | ||
480 | err = nfs_end_delegation_return(inode, delegation, 0); | 491 | err = nfs_end_delegation_return(inode, delegation, 0); |
481 | iput(inode); | 492 | iput(inode); |
493 | nfs_sb_deactive(server->super); | ||
482 | if (!err) | 494 | if (!err) |
483 | goto restart; | 495 | goto restart; |
484 | set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); | 496 | set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); |
@@ -809,19 +821,30 @@ restart: | |||
809 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { | 821 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
810 | list_for_each_entry_rcu(delegation, &server->delegations, | 822 | list_for_each_entry_rcu(delegation, &server->delegations, |
811 | super_list) { | 823 | super_list) { |
824 | if (test_bit(NFS_DELEGATION_RETURNING, | ||
825 | &delegation->flags)) | ||
826 | continue; | ||
812 | if (test_bit(NFS_DELEGATION_NEED_RECLAIM, | 827 | if (test_bit(NFS_DELEGATION_NEED_RECLAIM, |
813 | &delegation->flags) == 0) | 828 | &delegation->flags) == 0) |
814 | continue; | 829 | continue; |
815 | inode = nfs_delegation_grab_inode(delegation); | 830 | if (!nfs_sb_active(server->super)) |
816 | if (inode == NULL) | ||
817 | continue; | 831 | continue; |
818 | delegation = nfs_detach_delegation(NFS_I(inode), | 832 | inode = nfs_delegation_grab_inode(delegation); |
819 | delegation, server); | 833 | if (inode == NULL) { |
834 | rcu_read_unlock(); | ||
835 | nfs_sb_deactive(server->super); | ||
836 | goto restart; | ||
837 | } | ||
838 | delegation = nfs_start_delegation_return_locked(NFS_I(inode)); | ||
820 | rcu_read_unlock(); | 839 | rcu_read_unlock(); |
821 | 840 | if (delegation != NULL) { | |
822 | if (delegation != NULL) | 841 | delegation = nfs_detach_delegation(NFS_I(inode), |
823 | nfs_free_delegation(delegation); | 842 | delegation, server); |
843 | if (delegation != NULL) | ||
844 | nfs_free_delegation(delegation); | ||
845 | } | ||
824 | iput(inode); | 846 | iput(inode); |
847 | nfs_sb_deactive(server->super); | ||
825 | goto restart; | 848 | goto restart; |
826 | } | 849 | } |
827 | } | 850 | } |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 9b0c55cb2a2e..c19e16f0b2d0 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -408,14 +408,22 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc, | |||
408 | return 0; | 408 | return 0; |
409 | } | 409 | } |
410 | 410 | ||
411 | /* Match file and dirent using either filehandle or fileid | ||
412 | * Note: caller is responsible for checking the fsid | ||
413 | */ | ||
411 | static | 414 | static |
412 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) | 415 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) |
413 | { | 416 | { |
417 | struct nfs_inode *nfsi; | ||
418 | |||
414 | if (dentry->d_inode == NULL) | 419 | if (dentry->d_inode == NULL) |
415 | goto different; | 420 | goto different; |
416 | if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0) | 421 | |
417 | goto different; | 422 | nfsi = NFS_I(dentry->d_inode); |
418 | return 1; | 423 | if (entry->fattr->fileid == nfsi->fileid) |
424 | return 1; | ||
425 | if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0) | ||
426 | return 1; | ||
419 | different: | 427 | different: |
420 | return 0; | 428 | return 0; |
421 | } | 429 | } |
@@ -469,6 +477,10 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
469 | struct inode *inode; | 477 | struct inode *inode; |
470 | int status; | 478 | int status; |
471 | 479 | ||
480 | if (!(entry->fattr->valid & NFS_ATTR_FATTR_FILEID)) | ||
481 | return; | ||
482 | if (!(entry->fattr->valid & NFS_ATTR_FATTR_FSID)) | ||
483 | return; | ||
472 | if (filename.name[0] == '.') { | 484 | if (filename.name[0] == '.') { |
473 | if (filename.len == 1) | 485 | if (filename.len == 1) |
474 | return; | 486 | return; |
@@ -479,6 +491,10 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
479 | 491 | ||
480 | dentry = d_lookup(parent, &filename); | 492 | dentry = d_lookup(parent, &filename); |
481 | if (dentry != NULL) { | 493 | if (dentry != NULL) { |
494 | /* Is there a mountpoint here? If so, just exit */ | ||
495 | if (!nfs_fsid_equal(&NFS_SB(dentry->d_sb)->fsid, | ||
496 | &entry->fattr->fsid)) | ||
497 | goto out; | ||
482 | if (nfs_same_file(dentry, entry)) { | 498 | if (nfs_same_file(dentry, entry)) { |
483 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 499 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
484 | status = nfs_refresh_inode(dentry->d_inode, entry->fattr); | 500 | status = nfs_refresh_inode(dentry->d_inode, entry->fattr); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 94712fc781fa..e679d24c39d3 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -178,7 +178,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to) | |||
178 | iocb->ki_filp, | 178 | iocb->ki_filp, |
179 | iov_iter_count(to), (unsigned long) iocb->ki_pos); | 179 | iov_iter_count(to), (unsigned long) iocb->ki_pos); |
180 | 180 | ||
181 | result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); | 181 | result = nfs_revalidate_mapping_protected(inode, iocb->ki_filp->f_mapping); |
182 | if (!result) { | 182 | if (!result) { |
183 | result = generic_file_read_iter(iocb, to); | 183 | result = generic_file_read_iter(iocb, to); |
184 | if (result > 0) | 184 | if (result > 0) |
@@ -199,7 +199,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, | |||
199 | dprintk("NFS: splice_read(%pD2, %lu@%Lu)\n", | 199 | dprintk("NFS: splice_read(%pD2, %lu@%Lu)\n", |
200 | filp, (unsigned long) count, (unsigned long long) *ppos); | 200 | filp, (unsigned long) count, (unsigned long long) *ppos); |
201 | 201 | ||
202 | res = nfs_revalidate_mapping(inode, filp->f_mapping); | 202 | res = nfs_revalidate_mapping_protected(inode, filp->f_mapping); |
203 | if (!res) { | 203 | if (!res) { |
204 | res = generic_file_splice_read(filp, ppos, pipe, count, flags); | 204 | res = generic_file_splice_read(filp, ppos, pipe, count, flags); |
205 | if (res > 0) | 205 | if (res > 0) |
@@ -372,6 +372,10 @@ start: | |||
372 | nfs_wait_bit_killable, TASK_KILLABLE); | 372 | nfs_wait_bit_killable, TASK_KILLABLE); |
373 | if (ret) | 373 | if (ret) |
374 | return ret; | 374 | return ret; |
375 | /* | ||
376 | * Wait for O_DIRECT to complete | ||
377 | */ | ||
378 | nfs_inode_dio_wait(mapping->host); | ||
375 | 379 | ||
376 | page = grab_cache_page_write_begin(mapping, index, flags); | 380 | page = grab_cache_page_write_begin(mapping, index, flags); |
377 | if (!page) | 381 | if (!page) |
@@ -619,6 +623,9 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
619 | /* make sure the cache has finished storing the page */ | 623 | /* make sure the cache has finished storing the page */ |
620 | nfs_fscache_wait_on_page_write(NFS_I(inode), page); | 624 | nfs_fscache_wait_on_page_write(NFS_I(inode), page); |
621 | 625 | ||
626 | wait_on_bit_action(&NFS_I(inode)->flags, NFS_INO_INVALIDATING, | ||
627 | nfs_wait_bit_killable, TASK_KILLABLE); | ||
628 | |||
622 | lock_page(page); | 629 | lock_page(page); |
623 | mapping = page_file_mapping(page); | 630 | mapping = page_file_mapping(page); |
624 | if (mapping != inode->i_mapping) | 631 | if (mapping != inode->i_mapping) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 83107be3dd01..d42dff6d5e98 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -556,6 +556,7 @@ EXPORT_SYMBOL_GPL(nfs_setattr); | |||
556 | * This is a copy of the common vmtruncate, but with the locking | 556 | * This is a copy of the common vmtruncate, but with the locking |
557 | * corrected to take into account the fact that NFS requires | 557 | * corrected to take into account the fact that NFS requires |
558 | * inode->i_size to be updated under the inode->i_lock. | 558 | * inode->i_size to be updated under the inode->i_lock. |
559 | * Note: must be called with inode->i_lock held! | ||
559 | */ | 560 | */ |
560 | static int nfs_vmtruncate(struct inode * inode, loff_t offset) | 561 | static int nfs_vmtruncate(struct inode * inode, loff_t offset) |
561 | { | 562 | { |
@@ -565,14 +566,14 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset) | |||
565 | if (err) | 566 | if (err) |
566 | goto out; | 567 | goto out; |
567 | 568 | ||
568 | spin_lock(&inode->i_lock); | ||
569 | i_size_write(inode, offset); | 569 | i_size_write(inode, offset); |
570 | /* Optimisation */ | 570 | /* Optimisation */ |
571 | if (offset == 0) | 571 | if (offset == 0) |
572 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA; | 572 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA; |
573 | spin_unlock(&inode->i_lock); | ||
574 | 573 | ||
574 | spin_unlock(&inode->i_lock); | ||
575 | truncate_pagecache(inode, offset); | 575 | truncate_pagecache(inode, offset); |
576 | spin_lock(&inode->i_lock); | ||
576 | out: | 577 | out: |
577 | return err; | 578 | return err; |
578 | } | 579 | } |
@@ -585,10 +586,15 @@ out: | |||
585 | * Note: we do this in the *proc.c in order to ensure that | 586 | * Note: we do this in the *proc.c in order to ensure that |
586 | * it works for things like exclusive creates too. | 587 | * it works for things like exclusive creates too. |
587 | */ | 588 | */ |
588 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | 589 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, |
590 | struct nfs_fattr *fattr) | ||
589 | { | 591 | { |
592 | /* Barrier: bump the attribute generation count. */ | ||
593 | nfs_fattr_set_barrier(fattr); | ||
594 | |||
595 | spin_lock(&inode->i_lock); | ||
596 | NFS_I(inode)->attr_gencount = fattr->gencount; | ||
590 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { | 597 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { |
591 | spin_lock(&inode->i_lock); | ||
592 | if ((attr->ia_valid & ATTR_MODE) != 0) { | 598 | if ((attr->ia_valid & ATTR_MODE) != 0) { |
593 | int mode = attr->ia_mode & S_IALLUGO; | 599 | int mode = attr->ia_mode & S_IALLUGO; |
594 | mode |= inode->i_mode & ~S_IALLUGO; | 600 | mode |= inode->i_mode & ~S_IALLUGO; |
@@ -600,12 +606,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
600 | inode->i_gid = attr->ia_gid; | 606 | inode->i_gid = attr->ia_gid; |
601 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS | 607 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS |
602 | | NFS_INO_INVALID_ACL); | 608 | | NFS_INO_INVALID_ACL); |
603 | spin_unlock(&inode->i_lock); | ||
604 | } | 609 | } |
605 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 610 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
606 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); | 611 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); |
607 | nfs_vmtruncate(inode, attr->ia_size); | 612 | nfs_vmtruncate(inode, attr->ia_size); |
608 | } | 613 | } |
614 | nfs_update_inode(inode, fattr); | ||
615 | spin_unlock(&inode->i_lock); | ||
609 | } | 616 | } |
610 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); | 617 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); |
611 | 618 | ||
@@ -1028,6 +1035,7 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map | |||
1028 | 1035 | ||
1029 | if (mapping->nrpages != 0) { | 1036 | if (mapping->nrpages != 0) { |
1030 | if (S_ISREG(inode->i_mode)) { | 1037 | if (S_ISREG(inode->i_mode)) { |
1038 | unmap_mapping_range(mapping, 0, 0, 0); | ||
1031 | ret = nfs_sync_mapping(mapping); | 1039 | ret = nfs_sync_mapping(mapping); |
1032 | if (ret < 0) | 1040 | if (ret < 0) |
1033 | return ret; | 1041 | return ret; |
@@ -1060,11 +1068,14 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode) | |||
1060 | } | 1068 | } |
1061 | 1069 | ||
1062 | /** | 1070 | /** |
1063 | * nfs_revalidate_mapping - Revalidate the pagecache | 1071 | * __nfs_revalidate_mapping - Revalidate the pagecache |
1064 | * @inode - pointer to host inode | 1072 | * @inode - pointer to host inode |
1065 | * @mapping - pointer to mapping | 1073 | * @mapping - pointer to mapping |
1074 | * @may_lock - take inode->i_mutex? | ||
1066 | */ | 1075 | */ |
1067 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | 1076 | static int __nfs_revalidate_mapping(struct inode *inode, |
1077 | struct address_space *mapping, | ||
1078 | bool may_lock) | ||
1068 | { | 1079 | { |
1069 | struct nfs_inode *nfsi = NFS_I(inode); | 1080 | struct nfs_inode *nfsi = NFS_I(inode); |
1070 | unsigned long *bitlock = &nfsi->flags; | 1081 | unsigned long *bitlock = &nfsi->flags; |
@@ -1113,7 +1124,12 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
1113 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | 1124 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; |
1114 | spin_unlock(&inode->i_lock); | 1125 | spin_unlock(&inode->i_lock); |
1115 | trace_nfs_invalidate_mapping_enter(inode); | 1126 | trace_nfs_invalidate_mapping_enter(inode); |
1116 | ret = nfs_invalidate_mapping(inode, mapping); | 1127 | if (may_lock) { |
1128 | mutex_lock(&inode->i_mutex); | ||
1129 | ret = nfs_invalidate_mapping(inode, mapping); | ||
1130 | mutex_unlock(&inode->i_mutex); | ||
1131 | } else | ||
1132 | ret = nfs_invalidate_mapping(inode, mapping); | ||
1117 | trace_nfs_invalidate_mapping_exit(inode, ret); | 1133 | trace_nfs_invalidate_mapping_exit(inode, ret); |
1118 | 1134 | ||
1119 | clear_bit_unlock(NFS_INO_INVALIDATING, bitlock); | 1135 | clear_bit_unlock(NFS_INO_INVALIDATING, bitlock); |
@@ -1123,6 +1139,29 @@ out: | |||
1123 | return ret; | 1139 | return ret; |
1124 | } | 1140 | } |
1125 | 1141 | ||
1142 | /** | ||
1143 | * nfs_revalidate_mapping - Revalidate the pagecache | ||
1144 | * @inode - pointer to host inode | ||
1145 | * @mapping - pointer to mapping | ||
1146 | */ | ||
1147 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | ||
1148 | { | ||
1149 | return __nfs_revalidate_mapping(inode, mapping, false); | ||
1150 | } | ||
1151 | |||
1152 | /** | ||
1153 | * nfs_revalidate_mapping_protected - Revalidate the pagecache | ||
1154 | * @inode - pointer to host inode | ||
1155 | * @mapping - pointer to mapping | ||
1156 | * | ||
1157 | * Differs from nfs_revalidate_mapping() in that it grabs the inode->i_mutex | ||
1158 | * while invalidating the mapping. | ||
1159 | */ | ||
1160 | int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping) | ||
1161 | { | ||
1162 | return __nfs_revalidate_mapping(inode, mapping, true); | ||
1163 | } | ||
1164 | |||
1126 | static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 1165 | static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
1127 | { | 1166 | { |
1128 | struct nfs_inode *nfsi = NFS_I(inode); | 1167 | struct nfs_inode *nfsi = NFS_I(inode); |
@@ -1231,13 +1270,6 @@ static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fat | |||
1231 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; | 1270 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; |
1232 | } | 1271 | } |
1233 | 1272 | ||
1234 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | ||
1235 | { | ||
1236 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
1237 | return 0; | ||
1238 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | ||
1239 | } | ||
1240 | |||
1241 | static atomic_long_t nfs_attr_generation_counter; | 1273 | static atomic_long_t nfs_attr_generation_counter; |
1242 | 1274 | ||
1243 | static unsigned long nfs_read_attr_generation_counter(void) | 1275 | static unsigned long nfs_read_attr_generation_counter(void) |
@@ -1249,6 +1281,7 @@ unsigned long nfs_inc_attr_generation_counter(void) | |||
1249 | { | 1281 | { |
1250 | return atomic_long_inc_return(&nfs_attr_generation_counter); | 1282 | return atomic_long_inc_return(&nfs_attr_generation_counter); |
1251 | } | 1283 | } |
1284 | EXPORT_SYMBOL_GPL(nfs_inc_attr_generation_counter); | ||
1252 | 1285 | ||
1253 | void nfs_fattr_init(struct nfs_fattr *fattr) | 1286 | void nfs_fattr_init(struct nfs_fattr *fattr) |
1254 | { | 1287 | { |
@@ -1260,6 +1293,22 @@ void nfs_fattr_init(struct nfs_fattr *fattr) | |||
1260 | } | 1293 | } |
1261 | EXPORT_SYMBOL_GPL(nfs_fattr_init); | 1294 | EXPORT_SYMBOL_GPL(nfs_fattr_init); |
1262 | 1295 | ||
1296 | /** | ||
1297 | * nfs_fattr_set_barrier | ||
1298 | * @fattr: attributes | ||
1299 | * | ||
1300 | * Used to set a barrier after an attribute was updated. This | ||
1301 | * barrier ensures that older attributes from RPC calls that may | ||
1302 | * have raced with our update cannot clobber these new values. | ||
1303 | * Note that you are still responsible for ensuring that other | ||
1304 | * operations which change the attribute on the server do not | ||
1305 | * collide. | ||
1306 | */ | ||
1307 | void nfs_fattr_set_barrier(struct nfs_fattr *fattr) | ||
1308 | { | ||
1309 | fattr->gencount = nfs_inc_attr_generation_counter(); | ||
1310 | } | ||
1311 | |||
1263 | struct nfs_fattr *nfs_alloc_fattr(void) | 1312 | struct nfs_fattr *nfs_alloc_fattr(void) |
1264 | { | 1313 | { |
1265 | struct nfs_fattr *fattr; | 1314 | struct nfs_fattr *fattr; |
@@ -1370,7 +1419,6 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n | |||
1370 | 1419 | ||
1371 | return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || | 1420 | return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || |
1372 | nfs_ctime_need_update(inode, fattr) || | 1421 | nfs_ctime_need_update(inode, fattr) || |
1373 | nfs_size_need_update(inode, fattr) || | ||
1374 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); | 1422 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); |
1375 | } | 1423 | } |
1376 | 1424 | ||
@@ -1460,6 +1508,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1460 | int status; | 1508 | int status; |
1461 | 1509 | ||
1462 | spin_lock(&inode->i_lock); | 1510 | spin_lock(&inode->i_lock); |
1511 | nfs_fattr_set_barrier(fattr); | ||
1463 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1512 | status = nfs_post_op_update_inode_locked(inode, fattr); |
1464 | spin_unlock(&inode->i_lock); | 1513 | spin_unlock(&inode->i_lock); |
1465 | 1514 | ||
@@ -1468,7 +1517,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1468 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | 1517 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); |
1469 | 1518 | ||
1470 | /** | 1519 | /** |
1471 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | 1520 | * nfs_post_op_update_inode_force_wcc_locked - update the inode attribute cache |
1472 | * @inode - pointer to inode | 1521 | * @inode - pointer to inode |
1473 | * @fattr - updated attributes | 1522 | * @fattr - updated attributes |
1474 | * | 1523 | * |
@@ -1478,11 +1527,10 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | |||
1478 | * | 1527 | * |
1479 | * This function is mainly designed to be used by the ->write_done() functions. | 1528 | * This function is mainly designed to be used by the ->write_done() functions. |
1480 | */ | 1529 | */ |
1481 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | 1530 | int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr) |
1482 | { | 1531 | { |
1483 | int status; | 1532 | int status; |
1484 | 1533 | ||
1485 | spin_lock(&inode->i_lock); | ||
1486 | /* Don't do a WCC update if these attributes are already stale */ | 1534 | /* Don't do a WCC update if these attributes are already stale */ |
1487 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | 1535 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || |
1488 | !nfs_inode_attrs_need_update(inode, fattr)) { | 1536 | !nfs_inode_attrs_need_update(inode, fattr)) { |
@@ -1514,6 +1562,27 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
1514 | } | 1562 | } |
1515 | out_noforce: | 1563 | out_noforce: |
1516 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1564 | status = nfs_post_op_update_inode_locked(inode, fattr); |
1565 | return status; | ||
1566 | } | ||
1567 | |||
1568 | /** | ||
1569 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | ||
1570 | * @inode - pointer to inode | ||
1571 | * @fattr - updated attributes | ||
1572 | * | ||
1573 | * After an operation that has changed the inode metadata, mark the | ||
1574 | * attribute cache as being invalid, then try to update it. Fake up | ||
1575 | * weak cache consistency data, if none exist. | ||
1576 | * | ||
1577 | * This function is mainly designed to be used by the ->write_done() functions. | ||
1578 | */ | ||
1579 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | ||
1580 | { | ||
1581 | int status; | ||
1582 | |||
1583 | spin_lock(&inode->i_lock); | ||
1584 | nfs_fattr_set_barrier(fattr); | ||
1585 | status = nfs_post_op_update_inode_force_wcc_locked(inode, fattr); | ||
1517 | spin_unlock(&inode->i_lock); | 1586 | spin_unlock(&inode->i_lock); |
1518 | return status; | 1587 | return status; |
1519 | } | 1588 | } |
@@ -1715,6 +1784,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1715 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1784 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1716 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1785 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1717 | nfsi->attrtimeo_timestamp = now; | 1786 | nfsi->attrtimeo_timestamp = now; |
1787 | /* Set barrier to be more recent than all outstanding updates */ | ||
1718 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); | 1788 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); |
1719 | } else { | 1789 | } else { |
1720 | if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { | 1790 | if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { |
@@ -1722,6 +1792,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1722 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1792 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); |
1723 | nfsi->attrtimeo_timestamp = now; | 1793 | nfsi->attrtimeo_timestamp = now; |
1724 | } | 1794 | } |
1795 | /* Set the barrier to be more recent than this fattr */ | ||
1796 | if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0) | ||
1797 | nfsi->attr_gencount = fattr->gencount; | ||
1725 | } | 1798 | } |
1726 | invalid &= ~NFS_INO_INVALID_ATTR; | 1799 | invalid &= ~NFS_INO_INVALID_ATTR; |
1727 | /* Don't invalidate the data if we were to blame */ | 1800 | /* Don't invalidate the data if we were to blame */ |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index b802fb3a2d99..9e6475bc5ba2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -459,6 +459,7 @@ void nfs_mark_request_commit(struct nfs_page *req, | |||
459 | struct nfs_commit_info *cinfo, | 459 | struct nfs_commit_info *cinfo, |
460 | u32 ds_commit_idx); | 460 | u32 ds_commit_idx); |
461 | int nfs_write_need_commit(struct nfs_pgio_header *); | 461 | int nfs_write_need_commit(struct nfs_pgio_header *); |
462 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr); | ||
462 | int nfs_generic_commit_list(struct inode *inode, struct list_head *head, | 463 | int nfs_generic_commit_list(struct inode *inode, struct list_head *head, |
463 | int how, struct nfs_commit_info *cinfo); | 464 | int how, struct nfs_commit_info *cinfo); |
464 | void nfs_retry_commit(struct list_head *page_list, | 465 | void nfs_retry_commit(struct list_head *page_list, |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 78e557c3ab87..1f11d2533ee4 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -138,7 +138,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
138 | nfs_fattr_init(fattr); | 138 | nfs_fattr_init(fattr); |
139 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 139 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
140 | if (status == 0) | 140 | if (status == 0) |
141 | nfs_setattr_update_inode(inode, sattr); | 141 | nfs_setattr_update_inode(inode, sattr, fattr); |
142 | dprintk("NFS reply setattr: %d\n", status); | 142 | dprintk("NFS reply setattr: %d\n", status); |
143 | return status; | 143 | return status; |
144 | } | 144 | } |
@@ -834,7 +834,7 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) | |||
834 | if (nfs3_async_handle_jukebox(task, inode)) | 834 | if (nfs3_async_handle_jukebox(task, inode)) |
835 | return -EAGAIN; | 835 | return -EAGAIN; |
836 | if (task->tk_status >= 0) | 836 | if (task->tk_status >= 0) |
837 | nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr); | 837 | nfs_writeback_update_inode(hdr); |
838 | return 0; | 838 | return 0; |
839 | } | 839 | } |
840 | 840 | ||
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 2a932fdc57cb..53852a4bd88b 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -1987,6 +1987,11 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
1987 | if (entry->fattr->valid & NFS_ATTR_FATTR_V3) | 1987 | if (entry->fattr->valid & NFS_ATTR_FATTR_V3) |
1988 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); | 1988 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); |
1989 | 1989 | ||
1990 | if (entry->fattr->fileid != entry->ino) { | ||
1991 | entry->fattr->mounted_on_fileid = entry->ino; | ||
1992 | entry->fattr->valid |= NFS_ATTR_FATTR_MOUNTED_ON_FILEID; | ||
1993 | } | ||
1994 | |||
1990 | /* In fact, a post_op_fh3: */ | 1995 | /* In fact, a post_op_fh3: */ |
1991 | p = xdr_inline_decode(xdr, 4); | 1996 | p = xdr_inline_decode(xdr, 4); |
1992 | if (unlikely(p == NULL)) | 1997 | if (unlikely(p == NULL)) |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 8646af9b11d2..86d6214ea022 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -621,6 +621,9 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
621 | spin_lock(&nn->nfs_client_lock); | 621 | spin_lock(&nn->nfs_client_lock); |
622 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { | 622 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { |
623 | 623 | ||
624 | if (pos == new) | ||
625 | goto found; | ||
626 | |||
624 | if (pos->rpc_ops != new->rpc_ops) | 627 | if (pos->rpc_ops != new->rpc_ops) |
625 | continue; | 628 | continue; |
626 | 629 | ||
@@ -639,10 +642,6 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
639 | prev = pos; | 642 | prev = pos; |
640 | 643 | ||
641 | status = nfs_wait_client_init_complete(pos); | 644 | status = nfs_wait_client_init_complete(pos); |
642 | if (pos->cl_cons_state == NFS_CS_SESSION_INITING) { | ||
643 | nfs4_schedule_lease_recovery(pos); | ||
644 | status = nfs4_wait_clnt_recover(pos); | ||
645 | } | ||
646 | spin_lock(&nn->nfs_client_lock); | 645 | spin_lock(&nn->nfs_client_lock); |
647 | if (status < 0) | 646 | if (status < 0) |
648 | break; | 647 | break; |
@@ -668,7 +667,7 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
668 | */ | 667 | */ |
669 | if (!nfs4_match_client_owner_id(pos, new)) | 668 | if (!nfs4_match_client_owner_id(pos, new)) |
670 | continue; | 669 | continue; |
671 | 670 | found: | |
672 | atomic_inc(&pos->cl_count); | 671 | atomic_inc(&pos->cl_count); |
673 | *result = pos; | 672 | *result = pos; |
674 | status = 0; | 673 | status = 0; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 88180ac5ea0e..627f37c44456 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -901,6 +901,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | |||
901 | if (!cinfo->atomic || cinfo->before != dir->i_version) | 901 | if (!cinfo->atomic || cinfo->before != dir->i_version) |
902 | nfs_force_lookup_revalidate(dir); | 902 | nfs_force_lookup_revalidate(dir); |
903 | dir->i_version = cinfo->after; | 903 | dir->i_version = cinfo->after; |
904 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); | ||
904 | nfs_fscache_invalidate(dir); | 905 | nfs_fscache_invalidate(dir); |
905 | spin_unlock(&dir->i_lock); | 906 | spin_unlock(&dir->i_lock); |
906 | } | 907 | } |
@@ -1552,6 +1553,9 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod | |||
1552 | 1553 | ||
1553 | opendata->o_arg.open_flags = 0; | 1554 | opendata->o_arg.open_flags = 0; |
1554 | opendata->o_arg.fmode = fmode; | 1555 | opendata->o_arg.fmode = fmode; |
1556 | opendata->o_arg.share_access = nfs4_map_atomic_open_share( | ||
1557 | NFS_SB(opendata->dentry->d_sb), | ||
1558 | fmode, 0); | ||
1555 | memset(&opendata->o_res, 0, sizeof(opendata->o_res)); | 1559 | memset(&opendata->o_res, 0, sizeof(opendata->o_res)); |
1556 | memset(&opendata->c_res, 0, sizeof(opendata->c_res)); | 1560 | memset(&opendata->c_res, 0, sizeof(opendata->c_res)); |
1557 | nfs4_init_opendata_res(opendata); | 1561 | nfs4_init_opendata_res(opendata); |
@@ -2413,8 +2417,8 @@ static int _nfs4_do_open(struct inode *dir, | |||
2413 | opendata->o_res.f_attr, sattr, | 2417 | opendata->o_res.f_attr, sattr, |
2414 | state, label, olabel); | 2418 | state, label, olabel); |
2415 | if (status == 0) { | 2419 | if (status == 0) { |
2416 | nfs_setattr_update_inode(state->inode, sattr); | 2420 | nfs_setattr_update_inode(state->inode, sattr, |
2417 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); | 2421 | opendata->o_res.f_attr); |
2418 | nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); | 2422 | nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); |
2419 | } | 2423 | } |
2420 | } | 2424 | } |
@@ -2651,7 +2655,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
2651 | case -NFS4ERR_BAD_STATEID: | 2655 | case -NFS4ERR_BAD_STATEID: |
2652 | case -NFS4ERR_EXPIRED: | 2656 | case -NFS4ERR_EXPIRED: |
2653 | if (!nfs4_stateid_match(&calldata->arg.stateid, | 2657 | if (!nfs4_stateid_match(&calldata->arg.stateid, |
2654 | &state->stateid)) { | 2658 | &state->open_stateid)) { |
2655 | rpc_restart_call_prepare(task); | 2659 | rpc_restart_call_prepare(task); |
2656 | goto out_release; | 2660 | goto out_release; |
2657 | } | 2661 | } |
@@ -2687,7 +2691,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2687 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); | 2691 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); |
2688 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); | 2692 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); |
2689 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); | 2693 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); |
2690 | nfs4_stateid_copy(&calldata->arg.stateid, &state->stateid); | 2694 | nfs4_stateid_copy(&calldata->arg.stateid, &state->open_stateid); |
2691 | /* Calculate the change in open mode */ | 2695 | /* Calculate the change in open mode */ |
2692 | calldata->arg.fmode = 0; | 2696 | calldata->arg.fmode = 0; |
2693 | if (state->n_rdwr == 0) { | 2697 | if (state->n_rdwr == 0) { |
@@ -3288,7 +3292,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
3288 | 3292 | ||
3289 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label); | 3293 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label); |
3290 | if (status == 0) { | 3294 | if (status == 0) { |
3291 | nfs_setattr_update_inode(inode, sattr); | 3295 | nfs_setattr_update_inode(inode, sattr, fattr); |
3292 | nfs_setsecurity(inode, fattr, label); | 3296 | nfs_setsecurity(inode, fattr, label); |
3293 | } | 3297 | } |
3294 | nfs4_label_free(label); | 3298 | nfs4_label_free(label); |
@@ -4234,7 +4238,7 @@ static int nfs4_write_done_cb(struct rpc_task *task, | |||
4234 | } | 4238 | } |
4235 | if (task->tk_status >= 0) { | 4239 | if (task->tk_status >= 0) { |
4236 | renew_lease(NFS_SERVER(inode), hdr->timestamp); | 4240 | renew_lease(NFS_SERVER(inode), hdr->timestamp); |
4237 | nfs_post_op_update_inode_force_wcc(inode, &hdr->fattr); | 4241 | nfs_writeback_update_inode(hdr); |
4238 | } | 4242 | } |
4239 | return 0; | 4243 | return 0; |
4240 | } | 4244 | } |
@@ -6893,9 +6897,13 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, | |||
6893 | 6897 | ||
6894 | if (status == 0) { | 6898 | if (status == 0) { |
6895 | clp->cl_clientid = res.clientid; | 6899 | clp->cl_clientid = res.clientid; |
6896 | clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R); | 6900 | clp->cl_exchange_flags = res.flags; |
6897 | if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) | 6901 | /* Client ID is not confirmed */ |
6902 | if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) { | ||
6903 | clear_bit(NFS4_SESSION_ESTABLISHED, | ||
6904 | &clp->cl_session->session_state); | ||
6898 | clp->cl_seqid = res.seqid; | 6905 | clp->cl_seqid = res.seqid; |
6906 | } | ||
6899 | 6907 | ||
6900 | kfree(clp->cl_serverowner); | 6908 | kfree(clp->cl_serverowner); |
6901 | clp->cl_serverowner = res.server_owner; | 6909 | clp->cl_serverowner = res.server_owner; |
@@ -7227,6 +7235,9 @@ static void nfs4_update_session(struct nfs4_session *session, | |||
7227 | struct nfs41_create_session_res *res) | 7235 | struct nfs41_create_session_res *res) |
7228 | { | 7236 | { |
7229 | nfs4_copy_sessionid(&session->sess_id, &res->sessionid); | 7237 | nfs4_copy_sessionid(&session->sess_id, &res->sessionid); |
7238 | /* Mark client id and session as being confirmed */ | ||
7239 | session->clp->cl_exchange_flags |= EXCHGID4_FLAG_CONFIRMED_R; | ||
7240 | set_bit(NFS4_SESSION_ESTABLISHED, &session->session_state); | ||
7230 | session->flags = res->flags; | 7241 | session->flags = res->flags; |
7231 | memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs)); | 7242 | memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs)); |
7232 | if (res->flags & SESSION4_BACK_CHAN) | 7243 | if (res->flags & SESSION4_BACK_CHAN) |
@@ -7322,8 +7333,8 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, | |||
7322 | dprintk("--> nfs4_proc_destroy_session\n"); | 7333 | dprintk("--> nfs4_proc_destroy_session\n"); |
7323 | 7334 | ||
7324 | /* session is still being setup */ | 7335 | /* session is still being setup */ |
7325 | if (session->clp->cl_cons_state != NFS_CS_READY) | 7336 | if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state)) |
7326 | return status; | 7337 | return 0; |
7327 | 7338 | ||
7328 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 7339 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
7329 | trace_nfs4_destroy_session(session->clp, status); | 7340 | trace_nfs4_destroy_session(session->clp, status); |
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index fc46c7455898..e3ea2c5324d6 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
@@ -70,6 +70,7 @@ struct nfs4_session { | |||
70 | 70 | ||
71 | enum nfs4_session_state { | 71 | enum nfs4_session_state { |
72 | NFS4_SESSION_INITING, | 72 | NFS4_SESSION_INITING, |
73 | NFS4_SESSION_ESTABLISHED, | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, | 76 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 5ad908e9ce9c..f95e3b58bbc3 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -346,9 +346,23 @@ int nfs41_discover_server_trunking(struct nfs_client *clp, | |||
346 | status = nfs4_proc_exchange_id(clp, cred); | 346 | status = nfs4_proc_exchange_id(clp, cred); |
347 | if (status != NFS4_OK) | 347 | if (status != NFS4_OK) |
348 | return status; | 348 | return status; |
349 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
350 | 349 | ||
351 | return nfs41_walk_client_list(clp, result, cred); | 350 | status = nfs41_walk_client_list(clp, result, cred); |
351 | if (status < 0) | ||
352 | return status; | ||
353 | if (clp != *result) | ||
354 | return 0; | ||
355 | |||
356 | /* Purge state if the client id was established in a prior instance */ | ||
357 | if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R) | ||
358 | set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | ||
359 | else | ||
360 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
361 | nfs4_schedule_state_manager(clp); | ||
362 | status = nfs_wait_client_init_complete(clp); | ||
363 | if (status < 0) | ||
364 | nfs_put_client(clp); | ||
365 | return status; | ||
352 | } | 366 | } |
353 | 367 | ||
354 | #endif /* CONFIG_NFS_V4_1 */ | 368 | #endif /* CONFIG_NFS_V4_1 */ |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index b09cc23d6f43..c63189acd052 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -139,7 +139,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
139 | nfs_fattr_init(fattr); | 139 | nfs_fattr_init(fattr); |
140 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 140 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
141 | if (status == 0) | 141 | if (status == 0) |
142 | nfs_setattr_update_inode(inode, sattr); | 142 | nfs_setattr_update_inode(inode, sattr, fattr); |
143 | dprintk("NFS reply setattr: %d\n", status); | 143 | dprintk("NFS reply setattr: %d\n", status); |
144 | return status; | 144 | return status; |
145 | } | 145 | } |
@@ -609,10 +609,8 @@ static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task, | |||
609 | 609 | ||
610 | static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) | 610 | static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) |
611 | { | 611 | { |
612 | struct inode *inode = hdr->inode; | ||
613 | |||
614 | if (task->tk_status >= 0) | 612 | if (task->tk_status >= 0) |
615 | nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr); | 613 | nfs_writeback_update_inode(hdr); |
616 | return 0; | 614 | return 0; |
617 | } | 615 | } |
618 | 616 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 595d81e354d1..849ed784d6ac 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1377,6 +1377,36 @@ static int nfs_should_remove_suid(const struct inode *inode) | |||
1377 | return 0; | 1377 | return 0; |
1378 | } | 1378 | } |
1379 | 1379 | ||
1380 | static void nfs_writeback_check_extend(struct nfs_pgio_header *hdr, | ||
1381 | struct nfs_fattr *fattr) | ||
1382 | { | ||
1383 | struct nfs_pgio_args *argp = &hdr->args; | ||
1384 | struct nfs_pgio_res *resp = &hdr->res; | ||
1385 | |||
1386 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
1387 | return; | ||
1388 | if (argp->offset + resp->count != fattr->size) | ||
1389 | return; | ||
1390 | if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode)) | ||
1391 | return; | ||
1392 | /* Set attribute barrier */ | ||
1393 | nfs_fattr_set_barrier(fattr); | ||
1394 | } | ||
1395 | |||
1396 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr) | ||
1397 | { | ||
1398 | struct nfs_fattr *fattr = hdr->res.fattr; | ||
1399 | struct inode *inode = hdr->inode; | ||
1400 | |||
1401 | if (fattr == NULL) | ||
1402 | return; | ||
1403 | spin_lock(&inode->i_lock); | ||
1404 | nfs_writeback_check_extend(hdr, fattr); | ||
1405 | nfs_post_op_update_inode_force_wcc_locked(inode, fattr); | ||
1406 | spin_unlock(&inode->i_lock); | ||
1407 | } | ||
1408 | EXPORT_SYMBOL_GPL(nfs_writeback_update_inode); | ||
1409 | |||
1380 | /* | 1410 | /* |
1381 | * This function is called when the WRITE call is complete. | 1411 | * This function is called when the WRITE call is complete. |
1382 | */ | 1412 | */ |