diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-06 19:46:30 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-08 12:53:21 -0400 |
commit | dc327ed4cd320be689596365372a3683208c3ba0 (patch) | |
tree | 9393e6e22f5a3ece9ac0e739d93303f0cf1b9dc3 /fs/nfs/delegation.c | |
parent | c57d1bc5e043dbb5ba82ded07003d71a8033d899 (diff) |
NFSv4: nfs_client_return_marked_delegations can't flush data
Since even filemap_flush() needs to lock pages that are dirty, we
cannot risk calling it from the state manager context. Therefore,
we need to move the call to filemap_flush() to
nfs_async_inode_return_delegation().
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r-- | fs/nfs/delegation.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index a19cb5ad6b13..bd3a9601d32d 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -316,6 +316,10 @@ out: | |||
316 | * nfs_client_return_marked_delegations - return previously marked delegations | 316 | * nfs_client_return_marked_delegations - return previously marked delegations |
317 | * @clp: nfs_client to process | 317 | * @clp: nfs_client to process |
318 | * | 318 | * |
319 | * Note that this function is designed to be called by the state | ||
320 | * manager thread. For this reason, it cannot flush the dirty data, | ||
321 | * since that could deadlock in case of a state recovery error. | ||
322 | * | ||
319 | * Returns zero on success, or a negative errno value. | 323 | * Returns zero on success, or a negative errno value. |
320 | */ | 324 | */ |
321 | int nfs_client_return_marked_delegations(struct nfs_client *clp) | 325 | int nfs_client_return_marked_delegations(struct nfs_client *clp) |
@@ -340,11 +344,9 @@ restart: | |||
340 | server); | 344 | server); |
341 | rcu_read_unlock(); | 345 | rcu_read_unlock(); |
342 | 346 | ||
343 | if (delegation != NULL) { | 347 | if (delegation != NULL) |
344 | filemap_flush(inode->i_mapping); | ||
345 | err = __nfs_inode_return_delegation(inode, | 348 | err = __nfs_inode_return_delegation(inode, |
346 | delegation, 0); | 349 | delegation, 0); |
347 | } | ||
348 | iput(inode); | 350 | iput(inode); |
349 | if (!err) | 351 | if (!err) |
350 | goto restart; | 352 | goto restart; |
@@ -542,6 +544,8 @@ int nfs_async_inode_return_delegation(struct inode *inode, | |||
542 | struct nfs_client *clp = server->nfs_client; | 544 | struct nfs_client *clp = server->nfs_client; |
543 | struct nfs_delegation *delegation; | 545 | struct nfs_delegation *delegation; |
544 | 546 | ||
547 | filemap_flush(inode->i_mapping); | ||
548 | |||
545 | rcu_read_lock(); | 549 | rcu_read_lock(); |
546 | delegation = rcu_dereference(NFS_I(inode)->delegation); | 550 | delegation = rcu_dereference(NFS_I(inode)->delegation); |
547 | 551 | ||