diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/dir.c | 11 | ||||
-rw-r--r-- | fs/nfs/direct.c | 10 | ||||
-rw-r--r-- | fs/nfs/inode.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 18 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 2 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 10 | ||||
-rw-r--r-- | fs/nfs/pnfs_nfs.c | 12 | ||||
-rw-r--r-- | fs/nfs/read.c | 4 |
8 files changed, 45 insertions, 23 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index aaf7bd0cbae2..d8015a03db4c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -424,12 +424,17 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc, | |||
424 | static | 424 | static |
425 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) | 425 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) |
426 | { | 426 | { |
427 | struct inode *inode; | ||
427 | struct nfs_inode *nfsi; | 428 | struct nfs_inode *nfsi; |
428 | 429 | ||
429 | if (d_really_is_negative(dentry)) | 430 | if (d_really_is_negative(dentry)) |
430 | return 0; | 431 | return 0; |
431 | 432 | ||
432 | nfsi = NFS_I(d_inode(dentry)); | 433 | inode = d_inode(dentry); |
434 | if (is_bad_inode(inode) || NFS_STALE(inode)) | ||
435 | return 0; | ||
436 | |||
437 | nfsi = NFS_I(inode); | ||
433 | if (entry->fattr->fileid == nfsi->fileid) | 438 | if (entry->fattr->fileid == nfsi->fileid) |
434 | return 1; | 439 | return 1; |
435 | if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0) | 440 | if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0) |
@@ -1363,7 +1368,6 @@ EXPORT_SYMBOL_GPL(nfs_dentry_operations); | |||
1363 | struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) | 1368 | struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) |
1364 | { | 1369 | { |
1365 | struct dentry *res; | 1370 | struct dentry *res; |
1366 | struct dentry *parent; | ||
1367 | struct inode *inode = NULL; | 1371 | struct inode *inode = NULL; |
1368 | struct nfs_fh *fhandle = NULL; | 1372 | struct nfs_fh *fhandle = NULL; |
1369 | struct nfs_fattr *fattr = NULL; | 1373 | struct nfs_fattr *fattr = NULL; |
@@ -1393,7 +1397,6 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1393 | if (IS_ERR(label)) | 1397 | if (IS_ERR(label)) |
1394 | goto out; | 1398 | goto out; |
1395 | 1399 | ||
1396 | parent = dentry->d_parent; | ||
1397 | /* Protect against concurrent sillydeletes */ | 1400 | /* Protect against concurrent sillydeletes */ |
1398 | trace_nfs_lookup_enter(dir, dentry, flags); | 1401 | trace_nfs_lookup_enter(dir, dentry, flags); |
1399 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | 1402 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
@@ -1536,9 +1539,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1536 | err = PTR_ERR(inode); | 1539 | err = PTR_ERR(inode); |
1537 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); | 1540 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); |
1538 | put_nfs_open_context(ctx); | 1541 | put_nfs_open_context(ctx); |
1542 | d_drop(dentry); | ||
1539 | switch (err) { | 1543 | switch (err) { |
1540 | case -ENOENT: | 1544 | case -ENOENT: |
1541 | d_drop(dentry); | ||
1542 | d_add(dentry, NULL); | 1545 | d_add(dentry, NULL); |
1543 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1546 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1544 | break; | 1547 | break; |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 979b3c4dee6a..c7326c2af2c3 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -353,10 +353,12 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) | |||
353 | 353 | ||
354 | result = wait_for_completion_killable(&dreq->completion); | 354 | result = wait_for_completion_killable(&dreq->completion); |
355 | 355 | ||
356 | if (!result) { | ||
357 | result = dreq->count; | ||
358 | WARN_ON_ONCE(dreq->count < 0); | ||
359 | } | ||
356 | if (!result) | 360 | if (!result) |
357 | result = dreq->error; | 361 | result = dreq->error; |
358 | if (!result) | ||
359 | result = dreq->count; | ||
360 | 362 | ||
361 | out: | 363 | out: |
362 | return (ssize_t) result; | 364 | return (ssize_t) result; |
@@ -386,8 +388,10 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write) | |||
386 | 388 | ||
387 | if (dreq->iocb) { | 389 | if (dreq->iocb) { |
388 | long res = (long) dreq->error; | 390 | long res = (long) dreq->error; |
389 | if (!res) | 391 | if (dreq->count != 0) { |
390 | res = (long) dreq->count; | 392 | res = (long) dreq->count; |
393 | WARN_ON_ONCE(dreq->count < 0); | ||
394 | } | ||
391 | dreq->iocb->ki_complete(dreq->iocb, res, 0); | 395 | dreq->iocb->ki_complete(dreq->iocb, res, 0); |
392 | } | 396 | } |
393 | 397 | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 52e7d6869e3b..dda689d7a8a7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -282,6 +282,7 @@ nfs_init_locked(struct inode *inode, void *opaque) | |||
282 | struct nfs_fattr *fattr = desc->fattr; | 282 | struct nfs_fattr *fattr = desc->fattr; |
283 | 283 | ||
284 | set_nfs_fileid(inode, fattr->fileid); | 284 | set_nfs_fileid(inode, fattr->fileid); |
285 | inode->i_mode = fattr->mode; | ||
285 | nfs_copy_fh(NFS_FH(inode), desc->fh); | 286 | nfs_copy_fh(NFS_FH(inode), desc->fh); |
286 | return 0; | 287 | return 0; |
287 | } | 288 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index de97567795a5..ff416d0e24bc 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2882,12 +2882,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2882 | call_close |= is_wronly; | 2882 | call_close |= is_wronly; |
2883 | else if (is_wronly) | 2883 | else if (is_wronly) |
2884 | calldata->arg.fmode |= FMODE_WRITE; | 2884 | calldata->arg.fmode |= FMODE_WRITE; |
2885 | if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE)) | ||
2886 | call_close |= is_rdwr; | ||
2885 | } else if (is_rdwr) | 2887 | } else if (is_rdwr) |
2886 | calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; | 2888 | calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; |
2887 | 2889 | ||
2888 | if (calldata->arg.fmode == 0) | ||
2889 | call_close |= is_rdwr; | ||
2890 | |||
2891 | if (!nfs4_valid_open_stateid(state)) | 2890 | if (!nfs4_valid_open_stateid(state)) |
2892 | call_close = 0; | 2891 | call_close = 0; |
2893 | spin_unlock(&state->owner->so_lock); | 2892 | spin_unlock(&state->owner->so_lock); |
@@ -7924,8 +7923,8 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, | |||
7924 | break; | 7923 | break; |
7925 | } | 7924 | } |
7926 | lo = NFS_I(inode)->layout; | 7925 | lo = NFS_I(inode)->layout; |
7927 | if (lo && nfs4_stateid_match(&lgp->args.stateid, | 7926 | if (lo && !test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) && |
7928 | &lo->plh_stateid)) { | 7927 | nfs4_stateid_match_other(&lgp->args.stateid, &lo->plh_stateid)) { |
7929 | LIST_HEAD(head); | 7928 | LIST_HEAD(head); |
7930 | 7929 | ||
7931 | /* | 7930 | /* |
@@ -7936,10 +7935,10 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, | |||
7936 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0); | 7935 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0); |
7937 | spin_unlock(&inode->i_lock); | 7936 | spin_unlock(&inode->i_lock); |
7938 | pnfs_free_lseg_list(&head); | 7937 | pnfs_free_lseg_list(&head); |
7938 | status = -EAGAIN; | ||
7939 | goto out; | ||
7939 | } else | 7940 | } else |
7940 | spin_unlock(&inode->i_lock); | 7941 | spin_unlock(&inode->i_lock); |
7941 | status = -EAGAIN; | ||
7942 | goto out; | ||
7943 | } | 7942 | } |
7944 | 7943 | ||
7945 | status = nfs4_handle_exception(server, status, exception); | 7944 | status = nfs4_handle_exception(server, status, exception); |
@@ -8036,7 +8035,10 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags) | |||
8036 | .flags = RPC_TASK_ASYNC, | 8035 | .flags = RPC_TASK_ASYNC, |
8037 | }; | 8036 | }; |
8038 | struct pnfs_layout_segment *lseg = NULL; | 8037 | struct pnfs_layout_segment *lseg = NULL; |
8039 | struct nfs4_exception exception = { .timeout = *timeout }; | 8038 | struct nfs4_exception exception = { |
8039 | .inode = inode, | ||
8040 | .timeout = *timeout, | ||
8041 | }; | ||
8040 | int status = 0; | 8042 | int status = 0; |
8041 | 8043 | ||
8042 | dprintk("--> %s\n", __func__); | 8044 | dprintk("--> %s\n", __func__); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 9679f4749364..834b875900d6 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1488,9 +1488,9 @@ restart: | |||
1488 | } | 1488 | } |
1489 | spin_unlock(&state->state_lock); | 1489 | spin_unlock(&state->state_lock); |
1490 | } | 1490 | } |
1491 | nfs4_put_open_state(state); | ||
1492 | clear_bit(NFS_STATE_RECLAIM_NOGRACE, | 1491 | clear_bit(NFS_STATE_RECLAIM_NOGRACE, |
1493 | &state->flags); | 1492 | &state->flags); |
1493 | nfs4_put_open_state(state); | ||
1494 | spin_lock(&sp->so_lock); | 1494 | spin_lock(&sp->so_lock); |
1495 | goto restart; | 1495 | goto restart; |
1496 | } | 1496 | } |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 0c7e0d45a4de..0fbe734cc38c 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -361,8 +361,10 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo, | |||
361 | list_del_init(&lseg->pls_list); | 361 | list_del_init(&lseg->pls_list); |
362 | /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */ | 362 | /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */ |
363 | atomic_dec(&lo->plh_refcount); | 363 | atomic_dec(&lo->plh_refcount); |
364 | if (list_empty(&lo->plh_segs)) | 364 | if (list_empty(&lo->plh_segs)) { |
365 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | ||
365 | clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); | 366 | clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); |
367 | } | ||
366 | rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); | 368 | rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); |
367 | } | 369 | } |
368 | 370 | ||
@@ -1290,6 +1292,7 @@ alloc_init_layout_hdr(struct inode *ino, | |||
1290 | INIT_LIST_HEAD(&lo->plh_bulk_destroy); | 1292 | INIT_LIST_HEAD(&lo->plh_bulk_destroy); |
1291 | lo->plh_inode = ino; | 1293 | lo->plh_inode = ino; |
1292 | lo->plh_lc_cred = get_rpccred(ctx->cred); | 1294 | lo->plh_lc_cred = get_rpccred(ctx->cred); |
1295 | lo->plh_flags |= 1 << NFS_LAYOUT_INVALID_STID; | ||
1293 | return lo; | 1296 | return lo; |
1294 | } | 1297 | } |
1295 | 1298 | ||
@@ -1297,6 +1300,8 @@ static struct pnfs_layout_hdr * | |||
1297 | pnfs_find_alloc_layout(struct inode *ino, | 1300 | pnfs_find_alloc_layout(struct inode *ino, |
1298 | struct nfs_open_context *ctx, | 1301 | struct nfs_open_context *ctx, |
1299 | gfp_t gfp_flags) | 1302 | gfp_t gfp_flags) |
1303 | __releases(&ino->i_lock) | ||
1304 | __acquires(&ino->i_lock) | ||
1300 | { | 1305 | { |
1301 | struct nfs_inode *nfsi = NFS_I(ino); | 1306 | struct nfs_inode *nfsi = NFS_I(ino); |
1302 | struct pnfs_layout_hdr *new = NULL; | 1307 | struct pnfs_layout_hdr *new = NULL; |
@@ -1565,8 +1570,7 @@ lookup_again: | |||
1565 | * stateid, or it has been invalidated, then we must use the open | 1570 | * stateid, or it has been invalidated, then we must use the open |
1566 | * stateid. | 1571 | * stateid. |
1567 | */ | 1572 | */ |
1568 | if (lo->plh_stateid.seqid == 0 || | 1573 | if (test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) { |
1569 | test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) { | ||
1570 | 1574 | ||
1571 | /* | 1575 | /* |
1572 | * The first layoutget for the file. Need to serialize per | 1576 | * The first layoutget for the file. Need to serialize per |
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index 0dfc476da3e1..b38e3c0dc790 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c | |||
@@ -247,7 +247,11 @@ void pnfs_fetch_commit_bucket_list(struct list_head *pages, | |||
247 | } | 247 | } |
248 | 248 | ||
249 | /* Helper function for pnfs_generic_commit_pagelist to catch an empty | 249 | /* Helper function for pnfs_generic_commit_pagelist to catch an empty |
250 | * page list. This can happen when two commits race. */ | 250 | * page list. This can happen when two commits race. |
251 | * | ||
252 | * This must be called instead of nfs_init_commit - call one or the other, but | ||
253 | * not both! | ||
254 | */ | ||
251 | static bool | 255 | static bool |
252 | pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, | 256 | pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, |
253 | struct nfs_commit_data *data, | 257 | struct nfs_commit_data *data, |
@@ -256,7 +260,11 @@ pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, | |||
256 | if (list_empty(pages)) { | 260 | if (list_empty(pages)) { |
257 | if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) | 261 | if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) |
258 | wake_up_atomic_t(&cinfo->mds->rpcs_out); | 262 | wake_up_atomic_t(&cinfo->mds->rpcs_out); |
259 | nfs_commitdata_release(data); | 263 | /* don't call nfs_commitdata_release - it tries to put |
264 | * the open_context which is not acquired until nfs_init_commit | ||
265 | * which has not been called on @data */ | ||
266 | WARN_ON_ONCE(data->context); | ||
267 | nfs_commit_free(data); | ||
260 | return true; | 268 | return true; |
261 | } | 269 | } |
262 | 270 | ||
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 6776d7a7839e..572e5b3b06f1 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -367,13 +367,13 @@ readpage_async_filler(void *data, struct page *page) | |||
367 | nfs_list_remove_request(new); | 367 | nfs_list_remove_request(new); |
368 | nfs_readpage_release(new); | 368 | nfs_readpage_release(new); |
369 | error = desc->pgio->pg_error; | 369 | error = desc->pgio->pg_error; |
370 | goto out_unlock; | 370 | goto out; |
371 | } | 371 | } |
372 | return 0; | 372 | return 0; |
373 | out_error: | 373 | out_error: |
374 | error = PTR_ERR(new); | 374 | error = PTR_ERR(new); |
375 | out_unlock: | ||
376 | unlock_page(page); | 375 | unlock_page(page); |
376 | out: | ||
377 | return error; | 377 | return error; |
378 | } | 378 | } |
379 | 379 | ||