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.13-2' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client bugfixes from Anna Schumaker:
"Stable bugfix:
- Fix error reporting regression

Bugfixes:
- Fix setting filelayout ds address race
- Fix subtle access bug when using ACLs
- Fix setting mnt3_counts array size
- Fix a couple of pNFS commit races"

* tag 'nfs-for-4.13-2' of git://git.linux-nfs.org/projects/anna/linux-nfs:
NFS/filelayout: Fix racy setting of fl->dsaddr in filelayout_check_deviceid()
NFS: Be more careful about mapping file permissions
NFS: Store the raw NFS access mask in the inode's access cache
NFSv3: Convert nfs3_proc_access() to use nfs_access_set_mask()
NFS: Refactor NFS access to kernel access mask calculation
net/sunrpc/xprt_sock: fix regression in connection error reporting.
nfs: count correct array for mnt3_counts array size
Revert commit 722f0b891198 ("pNFS: Don't send COMMITs to the DSes if...")
pNFS/flexfiles: Handle expired layout segments in ff_layout_initiate_commit()
NFS: Fix another COMMIT race in pNFS
NFS: Fix a COMMIT race in pNFS
mount: copy the port field into the cloned nfs_server structure.
NFS: Don't run wake_up_bit() when nobody is waiting...
nfs: add export operations

+72 -34
+1
fs/nfs/client.c
··· 820 820 target->caps = source->caps; 821 821 target->options = source->options; 822 822 target->auth_info = source->auth_info; 823 + target->port = source->port; 823 824 } 824 825 EXPORT_SYMBOL_GPL(nfs_server_copy_userdata); 825 826
+37 -10
fs/nfs/dir.c
··· 2372 2372 } 2373 2373 EXPORT_SYMBOL_GPL(nfs_access_add_cache); 2374 2374 2375 + #define NFS_MAY_READ (NFS4_ACCESS_READ) 2376 + #define NFS_MAY_WRITE (NFS4_ACCESS_MODIFY | \ 2377 + NFS4_ACCESS_EXTEND | \ 2378 + NFS4_ACCESS_DELETE) 2379 + #define NFS_FILE_MAY_WRITE (NFS4_ACCESS_MODIFY | \ 2380 + NFS4_ACCESS_EXTEND) 2381 + #define NFS_DIR_MAY_WRITE NFS_MAY_WRITE 2382 + #define NFS_MAY_LOOKUP (NFS4_ACCESS_LOOKUP) 2383 + #define NFS_MAY_EXECUTE (NFS4_ACCESS_EXECUTE) 2384 + static int 2385 + nfs_access_calc_mask(u32 access_result, umode_t umode) 2386 + { 2387 + int mask = 0; 2388 + 2389 + if (access_result & NFS_MAY_READ) 2390 + mask |= MAY_READ; 2391 + if (S_ISDIR(umode)) { 2392 + if ((access_result & NFS_DIR_MAY_WRITE) == NFS_DIR_MAY_WRITE) 2393 + mask |= MAY_WRITE; 2394 + if ((access_result & NFS_MAY_LOOKUP) == NFS_MAY_LOOKUP) 2395 + mask |= MAY_EXEC; 2396 + } else if (S_ISREG(umode)) { 2397 + if ((access_result & NFS_FILE_MAY_WRITE) == NFS_FILE_MAY_WRITE) 2398 + mask |= MAY_WRITE; 2399 + if ((access_result & NFS_MAY_EXECUTE) == NFS_MAY_EXECUTE) 2400 + mask |= MAY_EXEC; 2401 + } else if (access_result & NFS_MAY_WRITE) 2402 + mask |= MAY_WRITE; 2403 + return mask; 2404 + } 2405 + 2375 2406 void nfs_access_set_mask(struct nfs_access_entry *entry, u32 access_result) 2376 2407 { 2377 - entry->mask = 0; 2378 - if (access_result & NFS4_ACCESS_READ) 2379 - entry->mask |= MAY_READ; 2380 - if (access_result & 2381 - (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE)) 2382 - entry->mask |= MAY_WRITE; 2383 - if (access_result & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE)) 2384 - entry->mask |= MAY_EXEC; 2408 + entry->mask = access_result; 2385 2409 } 2386 2410 EXPORT_SYMBOL_GPL(nfs_access_set_mask); 2387 2411 ··· 2413 2389 { 2414 2390 struct nfs_access_entry cache; 2415 2391 bool may_block = (mask & MAY_NOT_BLOCK) == 0; 2392 + int cache_mask; 2416 2393 int status; 2417 2394 2418 2395 trace_nfs_access_enter(inode); ··· 2429 2404 goto out; 2430 2405 2431 2406 /* Be clever: ask server to check for all possible rights */ 2432 - cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ; 2407 + cache.mask = NFS_MAY_LOOKUP | NFS_MAY_EXECUTE 2408 + | NFS_MAY_WRITE | NFS_MAY_READ; 2433 2409 cache.cred = cred; 2434 2410 cache.jiffies = jiffies; 2435 2411 status = NFS_PROTO(inode)->access(inode, &cache); ··· 2444 2418 } 2445 2419 nfs_access_add_cache(inode, &cache); 2446 2420 out_cached: 2447 - if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) 2421 + cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode); 2422 + if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) 2448 2423 status = -EACCES; 2449 2424 out: 2450 2425 trace_nfs_access_exit(inode, status);
+11 -2
fs/nfs/filelayout/filelayout.c
··· 542 542 struct nfs4_file_layout_dsaddr *dsaddr; 543 543 int status = -EINVAL; 544 544 545 + /* Is the deviceid already set? If so, we're good. */ 546 + if (fl->dsaddr != NULL) 547 + return 0; 548 + 545 549 /* find and reference the deviceid */ 546 550 d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid, 547 551 lo->plh_lc_cred, gfp_flags); ··· 556 552 /* Found deviceid is unavailable */ 557 553 if (filelayout_test_devid_unavailable(&dsaddr->id_node)) 558 554 goto out_put; 559 - 560 - fl->dsaddr = dsaddr; 561 555 562 556 if (fl->first_stripe_index >= dsaddr->stripe_count) { 563 557 dprintk("%s Bad first_stripe_index %u\n", ··· 572 570 goto out_put; 573 571 } 574 572 status = 0; 573 + 574 + /* 575 + * Atomic compare and xchange to ensure we don't scribble 576 + * over a non-NULL pointer. 577 + */ 578 + if (cmpxchg(&fl->dsaddr, NULL, dsaddr) != NULL) 579 + goto out_put; 575 580 out: 576 581 return status; 577 582 out_put:
+4
fs/nfs/flexfilelayout/flexfilelayout.c
··· 1842 1842 int vers, ret; 1843 1843 struct nfs_fh *fh; 1844 1844 1845 + if (!lseg || !(pnfs_is_valid_lseg(lseg) || 1846 + test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))) 1847 + goto out_err; 1848 + 1845 1849 idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); 1846 1850 ds = nfs4_ff_layout_prepare_ds(lseg, idx, true); 1847 1851 if (!ds)
+1 -1
fs/nfs/mount_clnt.c
··· 512 512 .counts = mnt_counts, 513 513 }; 514 514 515 - static unsigned int mnt3_counts[ARRAY_SIZE(mnt_procedures)]; 515 + static unsigned int mnt3_counts[ARRAY_SIZE(mnt3_procedures)]; 516 516 static const struct rpc_version mnt_version3 = { 517 517 .number = 3, 518 518 .nrprocs = ARRAY_SIZE(mnt3_procedures),
+2 -9
fs/nfs/nfs3proc.c
··· 220 220 221 221 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 222 222 nfs_refresh_inode(inode, res.fattr); 223 - if (status == 0) { 224 - entry->mask = 0; 225 - if (res.access & NFS3_ACCESS_READ) 226 - entry->mask |= MAY_READ; 227 - if (res.access & (NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE)) 228 - entry->mask |= MAY_WRITE; 229 - if (res.access & (NFS3_ACCESS_LOOKUP|NFS3_ACCESS_EXECUTE)) 230 - entry->mask |= MAY_EXEC; 231 - } 223 + if (status == 0) 224 + nfs_access_set_mask(entry, res.access); 232 225 nfs_free_fattr(res.fattr); 233 226 out: 234 227 dprintk("NFS reply access: %d\n", status);
+13 -11
fs/nfs/pnfs_nfs.c
··· 159 159 { 160 160 struct pnfs_commit_bucket *b; 161 161 struct pnfs_layout_segment *freeme; 162 + int nwritten; 162 163 int i; 163 164 164 165 lockdep_assert_held(&cinfo->inode->i_lock); 165 166 restart: 166 167 for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { 167 - if (pnfs_generic_transfer_commit_list(&b->written, dst, 168 - cinfo, 0)) { 168 + nwritten = pnfs_generic_transfer_commit_list(&b->written, 169 + dst, cinfo, 0); 170 + if (!nwritten) 171 + continue; 172 + cinfo->ds->nwritten -= nwritten; 173 + if (list_empty(&b->written)) { 169 174 freeme = b->wlseg; 170 175 b->wlseg = NULL; 171 176 spin_unlock(&cinfo->inode->i_lock); ··· 179 174 goto restart; 180 175 } 181 176 } 182 - cinfo->ds->nwritten = 0; 183 177 } 184 178 EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs); 185 179 ··· 187 183 struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; 188 184 struct pnfs_commit_bucket *bucket; 189 185 struct pnfs_layout_segment *freeme; 186 + struct list_head *pos; 190 187 LIST_HEAD(pages); 191 188 int i; 192 189 ··· 198 193 continue; 199 194 freeme = bucket->clseg; 200 195 bucket->clseg = NULL; 196 + list_for_each(pos, &bucket->committing) 197 + cinfo->ds->ncommitting--; 201 198 list_splice_init(&bucket->committing, &pages); 202 199 spin_unlock(&cinfo->inode->i_lock); 203 200 nfs_retry_commit(&pages, freeme, cinfo, i); ··· 224 217 for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) { 225 218 if (list_empty(&bucket->committing)) 226 219 continue; 227 - /* 228 - * If the layout segment is invalid, then let 229 - * pnfs_generic_retry_commit() clean up the bucket. 230 - */ 231 - if (bucket->clseg && !pnfs_is_valid_lseg(bucket->clseg) && 232 - !test_bit(NFS_LSEG_LAYOUTRETURN, &bucket->clseg->pls_flags)) 233 - break; 234 220 data = nfs_commitdata_alloc(false); 235 221 if (!data) 236 222 break; ··· 243 243 struct nfs_commit_info *cinfo) 244 244 { 245 245 struct pnfs_commit_bucket *bucket; 246 + struct list_head *pos; 246 247 247 248 bucket = &cinfo->ds->buckets[data->ds_commit_index]; 248 249 spin_lock(&cinfo->inode->i_lock); 250 + list_for_each(pos, &bucket->committing) 251 + cinfo->ds->ncommitting--; 249 252 list_splice_init(&bucket->committing, pages); 250 253 data->lseg = bucket->clseg; 251 254 bucket->clseg = NULL; ··· 333 330 } 334 331 } 335 332 out: 336 - cinfo->ds->ncommitting = 0; 337 333 return PNFS_ATTEMPTED; 338 334 } 339 335 EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist);
+1 -1
include/linux/nfs_fs.h
··· 51 51 struct list_head lru; 52 52 unsigned long jiffies; 53 53 struct rpc_cred * cred; 54 - int mask; 54 + __u32 mask; 55 55 struct rcu_head rcu_head; 56 56 }; 57 57
+2
net/sunrpc/xprtsock.c
··· 1624 1624 if (test_and_clear_bit(XPRT_SOCK_CONNECTING, 1625 1625 &transport->sock_state)) 1626 1626 xprt_clear_connecting(xprt); 1627 + if (sk->sk_err) 1628 + xprt_wake_pending_tasks(xprt, -sk->sk_err); 1627 1629 xs_sock_mark_closed(xprt); 1628 1630 } 1629 1631 out: