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()
Unified · Split
| @@ -424,12 +424,17 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc, · 423 unmodified lines | |||
| 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); · 927 unmodified lines | |||
| 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 · 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; |
| @@ -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 | ||
| 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) · 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 | ||
| @@ -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 | } |
| @@ -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 | } 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) · 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__); |
| @@ -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 | } |
| @@ -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 | |||
| 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: · 262 unmodified lines | |||
| 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 |
| @@ -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 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, · 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 | ||
| @@ -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; |
| 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 | ||