Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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()

+45 -23
+7 -4
fs/nfs/dir.c
··· 424 424 static 425 425 int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) 426 426 { 427 + struct inode *inode; 427 428 struct nfs_inode *nfsi; 428 429 429 430 if (d_really_is_negative(dentry)) 430 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 438 if (entry->fattr->fileid == nfsi->fileid) 434 439 return 1; 435 440 if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0) ··· 1368 1363 struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) 1369 1364 { 1370 1365 struct dentry *res; 1371 - struct dentry *parent; 1372 1366 struct inode *inode = NULL; 1373 1367 struct nfs_fh *fhandle = NULL; 1374 1368 struct nfs_fattr *fattr = NULL; ··· 1397 1393 if (IS_ERR(label)) 1398 1394 goto out; 1399 1395 1400 - parent = dentry->d_parent; 1401 1396 /* Protect against concurrent sillydeletes */ 1402 1397 trace_nfs_lookup_enter(dir, dentry, flags); 1403 1398 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); ··· 1539 1536 err = PTR_ERR(inode); 1540 1537 trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); 1541 1538 put_nfs_open_context(ctx); 1539 + d_drop(dentry); 1542 1540 switch (err) { 1543 1541 case -ENOENT: 1544 - d_drop(dentry); 1545 1542 d_add(dentry, NULL); 1546 1543 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1547 1544 break;
+7 -3
fs/nfs/direct.c
··· 353 353 354 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 360 if (!result) 357 361 result = dreq->error; 358 - if (!result) 359 - result = dreq->count; 360 362 361 363 out: 362 364 return (ssize_t) result; ··· 388 386 389 387 if (dreq->iocb) { 390 388 long res = (long) dreq->error; 391 - if (!res) 389 + if (dreq->count != 0) { 392 390 res = (long) dreq->count; 391 + WARN_ON_ONCE(dreq->count < 0); 392 + } 393 393 dreq->iocb->ki_complete(dreq->iocb, res, 0); 394 394 } 395 395
+1
fs/nfs/inode.c
··· 282 282 struct nfs_fattr *fattr = desc->fattr; 283 283 284 284 set_nfs_fileid(inode, fattr->fileid); 285 + inode->i_mode = fattr->mode; 285 286 nfs_copy_fh(NFS_FH(inode), desc->fh); 286 287 return 0; 287 288 }
+10 -8
fs/nfs/nfs4proc.c
··· 2882 2882 call_close |= is_wronly; 2883 2883 else if (is_wronly) 2884 2884 calldata->arg.fmode |= FMODE_WRITE; 2885 + if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE)) 2886 + call_close |= is_rdwr; 2885 2887 } else if (is_rdwr) 2886 2888 calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; 2887 - 2888 - if (calldata->arg.fmode == 0) 2889 - call_close |= is_rdwr; 2890 2889 2891 2890 if (!nfs4_valid_open_stateid(state)) 2892 2891 call_close = 0; ··· 7923 7924 break; 7924 7925 } 7925 7926 lo = NFS_I(inode)->layout; 7926 - if (lo && nfs4_stateid_match(&lgp->args.stateid, 7927 - &lo->plh_stateid)) { 7927 + if (lo && !test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) && 7928 + nfs4_stateid_match_other(&lgp->args.stateid, &lo->plh_stateid)) { 7928 7929 LIST_HEAD(head); 7929 7930 7930 7931 /* ··· 7935 7936 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0); 7936 7937 spin_unlock(&inode->i_lock); 7937 7938 pnfs_free_lseg_list(&head); 7939 + status = -EAGAIN; 7940 + goto out; 7938 7941 } else 7939 7942 spin_unlock(&inode->i_lock); 7940 - status = -EAGAIN; 7941 - goto out; 7942 7943 } 7943 7944 7944 7945 status = nfs4_handle_exception(server, status, exception); ··· 8035 8036 .flags = RPC_TASK_ASYNC, 8036 8037 }; 8037 8038 struct pnfs_layout_segment *lseg = NULL; 8038 - struct nfs4_exception exception = { .timeout = *timeout }; 8039 + struct nfs4_exception exception = { 8040 + .inode = inode, 8041 + .timeout = *timeout, 8042 + }; 8039 8043 int status = 0; 8040 8044 8041 8045 dprintk("--> %s\n", __func__);
+1 -1
fs/nfs/nfs4state.c
··· 1488 1488 } 1489 1489 spin_unlock(&state->state_lock); 1490 1490 } 1491 - nfs4_put_open_state(state); 1492 1491 clear_bit(NFS_STATE_RECLAIM_NOGRACE, 1493 1492 &state->flags); 1493 + nfs4_put_open_state(state); 1494 1494 spin_lock(&sp->so_lock); 1495 1495 goto restart; 1496 1496 }
+7 -3
fs/nfs/pnfs.c
··· 361 361 list_del_init(&lseg->pls_list); 362 362 /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */ 363 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 366 clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); 367 + } 366 368 rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); 367 369 } 368 370 ··· 1292 1290 INIT_LIST_HEAD(&lo->plh_bulk_destroy); 1293 1291 lo->plh_inode = ino; 1294 1292 lo->plh_lc_cred = get_rpccred(ctx->cred); 1293 + lo->plh_flags |= 1 << NFS_LAYOUT_INVALID_STID; 1295 1294 return lo; 1296 1295 } 1297 1296 ··· 1300 1297 pnfs_find_alloc_layout(struct inode *ino, 1301 1298 struct nfs_open_context *ctx, 1302 1299 gfp_t gfp_flags) 1300 + __releases(&ino->i_lock) 1301 + __acquires(&ino->i_lock) 1303 1302 { 1304 1303 struct nfs_inode *nfsi = NFS_I(ino); 1305 1304 struct pnfs_layout_hdr *new = NULL; ··· 1570 1565 * stateid, or it has been invalidated, then we must use the open 1571 1566 * stateid. 1572 1567 */ 1573 - if (lo->plh_stateid.seqid == 0 || 1574 - test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) { 1568 + if (test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) { 1575 1569 1576 1570 /* 1577 1571 * The first layoutget for the file. Need to serialize per
+10 -2
fs/nfs/pnfs_nfs.c
··· 247 247 } 248 248 249 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 255 static bool 252 256 pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, 253 257 struct nfs_commit_data *data, ··· 260 256 if (list_empty(pages)) { 261 257 if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) 262 258 wake_up_atomic_t(&cinfo->mds->rpcs_out); 263 - nfs_commitdata_release(data); 259 + /* don't call nfs_commitdata_release - it tries to put 260 + * the open_context which is not acquired until nfs_init_commit 261 + * which has not been called on @data */ 262 + WARN_ON_ONCE(data->context); 263 + nfs_commit_free(data); 264 264 return true; 265 265 } 266 266
+2 -2
fs/nfs/read.c
··· 367 367 nfs_list_remove_request(new); 368 368 nfs_readpage_release(new); 369 369 error = desc->pgio->pg_error; 370 - goto out_unlock; 370 + goto out; 371 371 } 372 372 return 0; 373 373 out_error: 374 374 error = PTR_ERR(new); 375 - out_unlock: 376 375 unlock_page(page); 376 + out: 377 377 return error; 378 378 } 379 379