diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index cb99fd90a9ac..f03d9d5f5ba4 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1305,7 +1305,7 @@ static const struct rpc_call_ops nfs4_close_ops = { | |||
1305 | * | 1305 | * |
1306 | * NOTE: Caller must be holding the sp->so_owner semaphore! | 1306 | * NOTE: Caller must be holding the sp->so_owner semaphore! |
1307 | */ | 1307 | */ |
1308 | int nfs4_do_close(struct path *path, struct nfs4_state *state) | 1308 | int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) |
1309 | { | 1309 | { |
1310 | struct nfs_server *server = NFS_SERVER(state->inode); | 1310 | struct nfs_server *server = NFS_SERVER(state->inode); |
1311 | struct nfs4_closedata *calldata; | 1311 | struct nfs4_closedata *calldata; |
@@ -1333,8 +1333,11 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state) | |||
1333 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); | 1333 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); |
1334 | if (IS_ERR(task)) | 1334 | if (IS_ERR(task)) |
1335 | return PTR_ERR(task); | 1335 | return PTR_ERR(task); |
1336 | status = 0; | ||
1337 | if (wait) | ||
1338 | status = rpc_wait_for_completion_task(task); | ||
1336 | rpc_put_task(task); | 1339 | rpc_put_task(task); |
1337 | return 0; | 1340 | return status; |
1338 | out_free_calldata: | 1341 | out_free_calldata: |
1339 | kfree(calldata); | 1342 | kfree(calldata); |
1340 | out: | 1343 | out: |
@@ -1365,13 +1368,14 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct | |||
1365 | } | 1368 | } |
1366 | ret = PTR_ERR(filp); | 1369 | ret = PTR_ERR(filp); |
1367 | out_close: | 1370 | out_close: |
1368 | nfs4_close_state(path, state, nd->intent.open.flags); | 1371 | nfs4_close_sync(path, state, nd->intent.open.flags); |
1369 | return ret; | 1372 | return ret; |
1370 | } | 1373 | } |
1371 | 1374 | ||
1372 | struct dentry * | 1375 | struct dentry * |
1373 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1376 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
1374 | { | 1377 | { |
1378 | struct dentry *parent; | ||
1375 | struct path path = { | 1379 | struct path path = { |
1376 | .mnt = nd->mnt, | 1380 | .mnt = nd->mnt, |
1377 | .dentry = dentry, | 1381 | .dentry = dentry, |
@@ -1394,6 +1398,9 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
1394 | cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); | 1398 | cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); |
1395 | if (IS_ERR(cred)) | 1399 | if (IS_ERR(cred)) |
1396 | return (struct dentry *)cred; | 1400 | return (struct dentry *)cred; |
1401 | parent = dentry->d_parent; | ||
1402 | /* Protect against concurrent sillydeletes */ | ||
1403 | nfs_block_sillyrename(parent); | ||
1397 | state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred); | 1404 | state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred); |
1398 | put_rpccred(cred); | 1405 | put_rpccred(cred); |
1399 | if (IS_ERR(state)) { | 1406 | if (IS_ERR(state)) { |
@@ -1401,12 +1408,14 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
1401 | d_add(dentry, NULL); | 1408 | d_add(dentry, NULL); |
1402 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1409 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1403 | } | 1410 | } |
1411 | nfs_unblock_sillyrename(parent); | ||
1404 | return (struct dentry *)state; | 1412 | return (struct dentry *)state; |
1405 | } | 1413 | } |
1406 | res = d_add_unique(dentry, igrab(state->inode)); | 1414 | res = d_add_unique(dentry, igrab(state->inode)); |
1407 | if (res != NULL) | 1415 | if (res != NULL) |
1408 | path.dentry = res; | 1416 | path.dentry = res; |
1409 | nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); | 1417 | nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); |
1418 | nfs_unblock_sillyrename(parent); | ||
1410 | nfs4_intent_set_file(nd, &path, state); | 1419 | nfs4_intent_set_file(nd, &path, state); |
1411 | return res; | 1420 | return res; |
1412 | } | 1421 | } |
@@ -1444,7 +1453,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st | |||
1444 | nfs4_intent_set_file(nd, &path, state); | 1453 | nfs4_intent_set_file(nd, &path, state); |
1445 | return 1; | 1454 | return 1; |
1446 | } | 1455 | } |
1447 | nfs4_close_state(&path, state, openflags); | 1456 | nfs4_close_sync(&path, state, openflags); |
1448 | out_drop: | 1457 | out_drop: |
1449 | d_drop(dentry); | 1458 | d_drop(dentry); |
1450 | return 0; | 1459 | return 0; |
@@ -1898,7 +1907,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
1898 | if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) | 1907 | if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) |
1899 | status = nfs4_intent_set_file(nd, &path, state); | 1908 | status = nfs4_intent_set_file(nd, &path, state); |
1900 | else | 1909 | else |
1901 | nfs4_close_state(&path, state, flags); | 1910 | nfs4_close_sync(&path, state, flags); |
1902 | out: | 1911 | out: |
1903 | return status; | 1912 | return status; |
1904 | } | 1913 | } |