History

Merge tag 'nfs-for-4.7-2' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client bugfixes from Anna Schumaker: "Stable bugfixes: - Fix _cancel_empty_pagelist - Fix a double page unlock - Make nfs_atomic_open() call d_drop() on all ->open_context() errors. - Fix another OPEN_DOWNGRADE bug Other bugfixes: - Ensure we handle delegation errors in nfs4_proc_layoutget() - Layout stateids start out as being invalid - Add sparse lock annotations for pnfs_find_alloc_layout - Handle bad delegation stateids in nfs4_layoutget_handle_exception - Fix up O_DIRECT results - Fix potential use after free of state in nfs4_do_reclaim. - Mark the layout stateid invalid when all segments are removed - Don't let readdirplus revalidate an inode that was marked as stale - Fix potential race in nfs_fhget() - Fix an unused variable warning" * tag 'nfs-for-4.7-2' of git://git.linux-nfs.org/projects/anna/linux-nfs: NFS: Fix another OPEN_DOWNGRADE bug make nfs_atomic_open() call d_drop() on all ->open_context() errors. NFS: Fix an unused variable warning NFS: Fix potential race in nfs_fhget() NFS: Don't let readdirplus revalidate an inode that was marked as stale NFSv4.1/pnfs: Mark the layout stateid invalid when all segments are removed NFS: Fix a double page unlock pnfs_nfs: fix _cancel_empty_pagelist nfs4: Fix potential use after free of state in nfs4_do_reclaim. NFS: Fix up O_DIRECT results NFS/pnfs: handle bad delegation stateids in nfs4_layoutget_handle_exception NFSv4.1/pnfs: Add sparse lock annotations for pnfs_find_alloc_layout NFSv4.1/pnfs: Layout stateids start out as being invalid NFSv4.1/pnfs: Ensure we handle delegation errors in nfs4_proc_layoutget()

Linus Torvalds committed 10 years ago

Commit e7bdea72 parents 89a82a9 e547f268 files · +45 −23Browse files

Unified · Split

8 files
  1. fs/nfs/dir.c +7 −4
  2. fs/nfs/direct.c +7 −3
  3. fs/nfs/inode.c +1 −0
  4. fs/nfs/nfs4proc.c +10 −8
  5. fs/nfs/nfs4state.c +1 −1
  6. fs/nfs/pnfs.c +7 −3
  7. fs/nfs/pnfs_nfs.c +10 −2
  8. fs/nfs/read.c +2 −2
fs/nfs/dir.c+7−4
@@ -424,12 +424,17 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc, · 423 unmodified lines
424static424static
425int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)425int 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); · 927 unmodified lines
1363struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)1368struct 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 · 23 unmodified lines
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, · 136 unmodified lines
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;
fs/nfs/direct.c+7−3
@@ -353,10 +353,12 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) · 352 unmodified lines
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
361out:363out:
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) · 23 unmodified lines
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
fs/nfs/inode.c+1−0
@@ -282,6 +282,7 @@ nfs_init_locked(struct inode *inode, void *opaque) · 281 unmodified lines
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}
fs/nfs/nfs4proc.c+10−8
@@ -2882,12 +2882,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) · 2881 unmodified lines
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, · 5030 unmodified lines
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, · 4 unmodified lines
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 } else7940 } 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) · 90 unmodified lines
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__);
fs/nfs/nfs4state.c+1−1
@@ -1488,9 +1488,9 @@ restart: · 1487 unmodified lines
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 }
fs/nfs/pnfs.c+7−3
@@ -361,8 +361,10 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo, · 360 unmodified lines
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, · 921 unmodified lines
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 * · 1 unmodified line
1297pnfs_find_alloc_layout(struct inode *ino,1300pnfs_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: · 262 unmodified lines
1565 * stateid, or it has been invalidated, then we must use the open1570 * 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 per1576 * The first layoutget for the file. Need to serialize per
fs/nfs/pnfs_nfs.c+10−2
@@ -247,7 +247,11 @@ void pnfs_fetch_commit_bucket_list(struct list_head *pages, · 246 unmodified lines
247}247}
248 248
249/* Helper function for pnfs_generic_commit_pagelist to catch an empty249/* 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 */
251static bool255static bool
252pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages,256pnfs_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, · 2 unmodified lines
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
fs/nfs/read.c+2−2
@@ -367,13 +367,13 @@ readpage_async_filler(void *data, struct page *page) · 366 unmodified lines
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;
373out_error:373out_error:
374 error = PTR_ERR(new);374 error = PTR_ERR(new);
375out_unlock:
376 unlock_page(page);375 unlock_page(page);
376out:
377 return error;377 return error;
378}378}
379 379

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t