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-3.18-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:
"Highlights include:

- stable patches to fix NFSv4.x delegation reclaim error paths
- fix a bug whereby we were advertising NFSv4.1 but using NFSv4.2
features
- fix a use-after-free problem with pNFS block layouts
- fix a memory leak in the pNFS files O_DIRECT code
- replace an intrusive and Oops-prone performance fix in the NFSv4
atomic open code with a safer one-line version and revert the two
original patches"

* tag 'nfs-for-3.18-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
sunrpc: fix sleeping under rcu_read_lock in gss_stringify_acceptor
NFS: Don't try to reclaim delegation open state if recovery failed
NFSv4: Ensure that we call FREE_STATEID when NFSv4.x stateids are revoked
NFSv4: Fix races between nfs_remove_bad_delegation() and delegation return
NFSv4.1: nfs41_clear_delegation_stateid shouldn't trust NFS_DELEGATED_STATE
NFSv4: Ensure that we remove NFSv4.0 delegations when state has expired
NFS: SEEK is an NFS v4.2 feature
nfs: Fix use of uninitialized variable in nfs_getattr()
nfs: Remove bogus assignment
nfs: remove spurious WARN_ON_ONCE in write path
pnfs/blocklayout: serialize GETDEVICEINFO calls
nfs: fix pnfs direct write memory leak
Revert "NFS: nfs4_do_open should add negative results to the dcache."
Revert "NFS: remove BUG possibility in nfs4_open_and_get_state"
NFSv4: Ensure nfs_atomic_open set the dentry verifier on ENOENT

+124 -69
+1 -1
fs/nfs/blocklayout/blocklayout.c
··· 378 378 loff_t offset = header->args.offset; 379 379 size_t count = header->args.count; 380 380 struct page **pages = header->args.pages; 381 - int pg_index = pg_index = header->args.pgbase >> PAGE_CACHE_SHIFT; 381 + int pg_index = header->args.pgbase >> PAGE_CACHE_SHIFT; 382 382 unsigned int pg_len; 383 383 struct blk_plug plug; 384 384 int i;
+9 -5
fs/nfs/blocklayout/rpc_pipefs.c
··· 65 65 66 66 dprintk("%s CREATING PIPEFS MESSAGE\n", __func__); 67 67 68 + mutex_lock(&nn->bl_mutex); 68 69 bl_pipe_msg.bl_wq = &nn->bl_wq; 69 70 70 71 b->simple.len += 4; /* single volume */ 71 72 if (b->simple.len > PAGE_SIZE) 72 - return -EIO; 73 + goto out_unlock; 73 74 74 75 memset(msg, 0, sizeof(*msg)); 75 76 msg->len = sizeof(*bl_msg) + b->simple.len; 76 77 msg->data = kzalloc(msg->len, gfp_mask); 77 78 if (!msg->data) 78 - goto out; 79 + goto out_free_data; 79 80 80 81 bl_msg = msg->data; 81 82 bl_msg->type = BL_DEVICE_MOUNT, ··· 88 87 rc = rpc_queue_upcall(nn->bl_device_pipe, msg); 89 88 if (rc < 0) { 90 89 remove_wait_queue(&nn->bl_wq, &wq); 91 - goto out; 90 + goto out_free_data; 92 91 } 93 92 94 93 set_current_state(TASK_UNINTERRUPTIBLE); ··· 98 97 if (reply->status != BL_DEVICE_REQUEST_PROC) { 99 98 printk(KERN_WARNING "%s failed to decode device: %d\n", 100 99 __func__, reply->status); 101 - goto out; 100 + goto out_free_data; 102 101 } 103 102 104 103 dev = MKDEV(reply->major, reply->minor); 105 - out: 104 + out_free_data: 106 105 kfree(msg->data); 106 + out_unlock: 107 + mutex_unlock(&nn->bl_mutex); 107 108 return dev; 108 109 } 109 110 ··· 235 232 struct nfs_net *nn = net_generic(net, nfs_net_id); 236 233 struct dentry *dentry; 237 234 235 + mutex_init(&nn->bl_mutex); 238 236 init_waitqueue_head(&nn->bl_wq); 239 237 nn->bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0); 240 238 if (IS_ERR(nn->bl_device_pipe))
+23 -2
fs/nfs/delegation.c
··· 125 125 continue; 126 126 if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) 127 127 continue; 128 + if (!nfs4_valid_open_stateid(state)) 129 + continue; 128 130 if (!nfs4_stateid_match(&state->stateid, stateid)) 129 131 continue; 130 132 get_nfs_open_context(ctx); ··· 195 193 { 196 194 int res = 0; 197 195 198 - res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); 196 + if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) 197 + res = nfs4_proc_delegreturn(inode, 198 + delegation->cred, 199 + &delegation->stateid, 200 + issync); 199 201 nfs_free_delegation(delegation); 200 202 return res; 201 203 } ··· 386 380 { 387 381 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 388 382 struct nfs_inode *nfsi = NFS_I(inode); 389 - int err; 383 + int err = 0; 390 384 391 385 if (delegation == NULL) 392 386 return 0; 393 387 do { 388 + if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) 389 + break; 394 390 err = nfs_delegation_claim_opens(inode, &delegation->stateid); 395 391 if (!issync || err != -EAGAIN) 396 392 break; ··· 613 605 rcu_read_unlock(); 614 606 } 615 607 608 + static void nfs_revoke_delegation(struct inode *inode) 609 + { 610 + struct nfs_delegation *delegation; 611 + rcu_read_lock(); 612 + delegation = rcu_dereference(NFS_I(inode)->delegation); 613 + if (delegation != NULL) { 614 + set_bit(NFS_DELEGATION_REVOKED, &delegation->flags); 615 + nfs_mark_return_delegation(NFS_SERVER(inode), delegation); 616 + } 617 + rcu_read_unlock(); 618 + } 619 + 616 620 void nfs_remove_bad_delegation(struct inode *inode) 617 621 { 618 622 struct nfs_delegation *delegation; 619 623 624 + nfs_revoke_delegation(inode); 620 625 delegation = nfs_inode_detach_delegation(inode); 621 626 if (delegation) { 622 627 nfs_inode_find_state_and_recover(inode, &delegation->stateid);
+1
fs/nfs/delegation.h
··· 31 31 NFS_DELEGATION_RETURN_IF_CLOSED, 32 32 NFS_DELEGATION_REFERENCED, 33 33 NFS_DELEGATION_RETURNING, 34 + NFS_DELEGATION_REVOKED, 34 35 }; 35 36 36 37 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
+1
fs/nfs/dir.c
··· 1527 1527 case -ENOENT: 1528 1528 d_drop(dentry); 1529 1529 d_add(dentry, NULL); 1530 + nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1530 1531 break; 1531 1532 case -EISDIR: 1532 1533 case -ENOTDIR:
+1
fs/nfs/direct.c
··· 266 266 { 267 267 struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); 268 268 269 + nfs_free_pnfs_ds_cinfo(&dreq->ds_cinfo); 269 270 if (dreq->l_ctx != NULL) 270 271 nfs_put_lock_context(dreq->l_ctx); 271 272 if (dreq->ctx != NULL)
-3
fs/nfs/filelayout/filelayout.c
··· 145 145 case -NFS4ERR_DELEG_REVOKED: 146 146 case -NFS4ERR_ADMIN_REVOKED: 147 147 case -NFS4ERR_BAD_STATEID: 148 - if (state == NULL) 149 - break; 150 - nfs_remove_bad_delegation(state->inode); 151 148 case -NFS4ERR_OPENMODE: 152 149 if (state == NULL) 153 150 break;
+1 -1
fs/nfs/inode.c
··· 626 626 { 627 627 struct inode *inode = dentry->d_inode; 628 628 int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; 629 - int err; 629 + int err = 0; 630 630 631 631 trace_nfs_getattr_enter(inode); 632 632 /* Flush out writes to the server in order to update c/mtime. */
+1
fs/nfs/netns.h
··· 19 19 struct rpc_pipe *bl_device_pipe; 20 20 struct bl_dev_msg bl_mount_reply; 21 21 wait_queue_head_t bl_wq; 22 + struct mutex bl_mutex; 22 23 struct list_head nfs_client_list; 23 24 struct list_head nfs_volume_list; 24 25 #if IS_ENABLED(CONFIG_NFS_V4)
+45 -50
fs/nfs/nfs4proc.c
··· 370 370 case -NFS4ERR_DELEG_REVOKED: 371 371 case -NFS4ERR_ADMIN_REVOKED: 372 372 case -NFS4ERR_BAD_STATEID: 373 - if (inode != NULL && nfs4_have_delegation(inode, FMODE_READ)) { 374 - nfs_remove_bad_delegation(inode); 375 - exception->retry = 1; 376 - break; 377 - } 378 373 if (state == NULL) 379 374 break; 380 375 ret = nfs4_schedule_stateid_recovery(server, state); ··· 1649 1654 nfs_inode_find_state_and_recover(state->inode, 1650 1655 stateid); 1651 1656 nfs4_schedule_stateid_recovery(server, state); 1652 - return 0; 1657 + return -EAGAIN; 1653 1658 case -NFS4ERR_DELAY: 1654 1659 case -NFS4ERR_GRACE: 1655 1660 set_bit(NFS_DELEGATED_STATE, &state->flags); ··· 2104 2109 return ret; 2105 2110 } 2106 2111 2112 + static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state) 2113 + { 2114 + nfs_remove_bad_delegation(state->inode); 2115 + write_seqlock(&state->seqlock); 2116 + nfs4_stateid_copy(&state->stateid, &state->open_stateid); 2117 + write_sequnlock(&state->seqlock); 2118 + clear_bit(NFS_DELEGATED_STATE, &state->flags); 2119 + } 2120 + 2121 + static void nfs40_clear_delegation_stateid(struct nfs4_state *state) 2122 + { 2123 + if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL) 2124 + nfs_finish_clear_delegation_stateid(state); 2125 + } 2126 + 2127 + static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) 2128 + { 2129 + /* NFSv4.0 doesn't allow for delegation recovery on open expire */ 2130 + nfs40_clear_delegation_stateid(state); 2131 + return nfs4_open_expired(sp, state); 2132 + } 2133 + 2107 2134 #if defined(CONFIG_NFS_V4_1) 2108 - static void nfs41_clear_delegation_stateid(struct nfs4_state *state) 2135 + static void nfs41_check_delegation_stateid(struct nfs4_state *state) 2109 2136 { 2110 2137 struct nfs_server *server = NFS_SERVER(state->inode); 2111 - nfs4_stateid *stateid = &state->stateid; 2138 + nfs4_stateid stateid; 2112 2139 struct nfs_delegation *delegation; 2113 - struct rpc_cred *cred = NULL; 2114 - int status = -NFS4ERR_BAD_STATEID; 2115 - 2116 - /* If a state reset has been done, test_stateid is unneeded */ 2117 - if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) 2118 - return; 2140 + struct rpc_cred *cred; 2141 + int status; 2119 2142 2120 2143 /* Get the delegation credential for use by test/free_stateid */ 2121 2144 rcu_read_lock(); 2122 2145 delegation = rcu_dereference(NFS_I(state->inode)->delegation); 2123 - if (delegation != NULL && 2124 - nfs4_stateid_match(&delegation->stateid, stateid)) { 2125 - cred = get_rpccred(delegation->cred); 2146 + if (delegation == NULL) { 2126 2147 rcu_read_unlock(); 2127 - status = nfs41_test_stateid(server, stateid, cred); 2128 - trace_nfs4_test_delegation_stateid(state, NULL, status); 2129 - } else 2130 - rcu_read_unlock(); 2148 + return; 2149 + } 2150 + 2151 + nfs4_stateid_copy(&stateid, &delegation->stateid); 2152 + cred = get_rpccred(delegation->cred); 2153 + rcu_read_unlock(); 2154 + status = nfs41_test_stateid(server, &stateid, cred); 2155 + trace_nfs4_test_delegation_stateid(state, NULL, status); 2131 2156 2132 2157 if (status != NFS_OK) { 2133 2158 /* Free the stateid unless the server explicitly 2134 2159 * informs us the stateid is unrecognized. */ 2135 2160 if (status != -NFS4ERR_BAD_STATEID) 2136 - nfs41_free_stateid(server, stateid, cred); 2137 - nfs_remove_bad_delegation(state->inode); 2138 - 2139 - write_seqlock(&state->seqlock); 2140 - nfs4_stateid_copy(&state->stateid, &state->open_stateid); 2141 - write_sequnlock(&state->seqlock); 2142 - clear_bit(NFS_DELEGATED_STATE, &state->flags); 2161 + nfs41_free_stateid(server, &stateid, cred); 2162 + nfs_finish_clear_delegation_stateid(state); 2143 2163 } 2144 2164 2145 - if (cred != NULL) 2146 - put_rpccred(cred); 2165 + put_rpccred(cred); 2147 2166 } 2148 2167 2149 2168 /** ··· 2201 2192 { 2202 2193 int status; 2203 2194 2204 - nfs41_clear_delegation_stateid(state); 2195 + nfs41_check_delegation_stateid(state); 2205 2196 status = nfs41_check_open_stateid(state); 2206 2197 if (status != NFS_OK) 2207 2198 status = nfs4_open_expired(sp, state); ··· 2240 2231 seq = raw_seqcount_begin(&sp->so_reclaim_seqcount); 2241 2232 2242 2233 ret = _nfs4_proc_open(opendata); 2243 - if (ret != 0) { 2244 - if (ret == -ENOENT) { 2245 - dentry = opendata->dentry; 2246 - if (dentry->d_inode) 2247 - d_delete(dentry); 2248 - else if (d_unhashed(dentry)) 2249 - d_add(dentry, NULL); 2250 - 2251 - nfs_set_verifier(dentry, 2252 - nfs_save_change_attribute(opendata->dir->d_inode)); 2253 - } 2234 + if (ret != 0) 2254 2235 goto out; 2255 - } 2256 2236 2257 2237 state = nfs4_opendata_to_nfs4_state(opendata); 2258 2238 ret = PTR_ERR(state); ··· 4839 4841 case -NFS4ERR_DELEG_REVOKED: 4840 4842 case -NFS4ERR_ADMIN_REVOKED: 4841 4843 case -NFS4ERR_BAD_STATEID: 4842 - if (state == NULL) 4843 - break; 4844 - nfs_remove_bad_delegation(state->inode); 4845 4844 case -NFS4ERR_OPENMODE: 4846 4845 if (state == NULL) 4847 4846 break; ··· 8336 8341 static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { 8337 8342 .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, 8338 8343 .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, 8339 - .recover_open = nfs4_open_expired, 8344 + .recover_open = nfs40_open_expired, 8340 8345 .recover_lock = nfs4_lock_expired, 8341 8346 .establish_clid = nfs4_init_clientid, 8342 8347 }; ··· 8403 8408 | NFS_CAP_CHANGE_ATTR 8404 8409 | NFS_CAP_POSIX_LOCK 8405 8410 | NFS_CAP_STATEID_NFSV41 8406 - | NFS_CAP_ATOMIC_OPEN_V1 8407 - | NFS_CAP_SEEK, 8411 + | NFS_CAP_ATOMIC_OPEN_V1, 8408 8412 .init_client = nfs41_init_client, 8409 8413 .shutdown_client = nfs41_shutdown_client, 8410 8414 .match_stateid = nfs41_match_stateid, ··· 8425 8431 | NFS_CAP_CHANGE_ATTR 8426 8432 | NFS_CAP_POSIX_LOCK 8427 8433 | NFS_CAP_STATEID_NFSV41 8428 - | NFS_CAP_ATOMIC_OPEN_V1, 8434 + | NFS_CAP_ATOMIC_OPEN_V1 8435 + | NFS_CAP_SEEK, 8429 8436 .init_client = nfs41_init_client, 8430 8437 .shutdown_client = nfs41_shutdown_client, 8431 8438 .match_stateid = nfs41_match_stateid,
-2
fs/nfs/write.c
··· 715 715 716 716 if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) 717 717 nfs_release_request(req); 718 - else 719 - WARN_ON_ONCE(1); 720 718 } 721 719 722 720 static void
+11
include/linux/nfs_xdr.h
··· 1224 1224 unsigned int status; 1225 1225 }; 1226 1226 1227 + static inline void 1228 + nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo) 1229 + { 1230 + kfree(cinfo->buckets); 1231 + } 1232 + 1227 1233 #else 1228 1234 1229 1235 struct pnfs_ds_commit_info { 1230 1236 }; 1237 + 1238 + static inline void 1239 + nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo) 1240 + { 1241 + } 1231 1242 1232 1243 #endif /* CONFIG_NFS_V4_1 */ 1233 1244
+30 -5
net/sunrpc/auth_gss/auth_gss.c
··· 1353 1353 char *string = NULL; 1354 1354 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); 1355 1355 struct gss_cl_ctx *ctx; 1356 + unsigned int len; 1356 1357 struct xdr_netobj *acceptor; 1357 1358 1358 1359 rcu_read_lock(); ··· 1361 1360 if (!ctx) 1362 1361 goto out; 1363 1362 1364 - acceptor = &ctx->gc_acceptor; 1363 + len = ctx->gc_acceptor.len; 1364 + rcu_read_unlock(); 1365 1365 1366 1366 /* no point if there's no string */ 1367 - if (!acceptor->len) 1368 - goto out; 1369 - 1370 - string = kmalloc(acceptor->len + 1, GFP_KERNEL); 1367 + if (!len) 1368 + return NULL; 1369 + realloc: 1370 + string = kmalloc(len + 1, GFP_KERNEL); 1371 1371 if (!string) 1372 + return NULL; 1373 + 1374 + rcu_read_lock(); 1375 + ctx = rcu_dereference(gss_cred->gc_ctx); 1376 + 1377 + /* did the ctx disappear or was it replaced by one with no acceptor? */ 1378 + if (!ctx || !ctx->gc_acceptor.len) { 1379 + kfree(string); 1380 + string = NULL; 1372 1381 goto out; 1382 + } 1383 + 1384 + acceptor = &ctx->gc_acceptor; 1385 + 1386 + /* 1387 + * Did we find a new acceptor that's longer than the original? Allocate 1388 + * a longer buffer and try again. 1389 + */ 1390 + if (len < acceptor->len) { 1391 + len = acceptor->len; 1392 + rcu_read_unlock(); 1393 + kfree(string); 1394 + goto realloc; 1395 + } 1373 1396 1374 1397 memcpy(string, acceptor->data, acceptor->len); 1375 1398 string[acceptor->len] = '\0';