diff options
| -rw-r--r-- | fs/nfs/client.c | 1 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 47 | ||||
| -rw-r--r-- | fs/nfs/filelayout/filelayout.c | 13 | ||||
| -rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 4 | ||||
| -rw-r--r-- | fs/nfs/mount_clnt.c | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs3proc.c | 11 | ||||
| -rw-r--r-- | fs/nfs/pnfs_nfs.c | 24 | ||||
| -rw-r--r-- | include/linux/nfs_fs.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 2 |
9 files changed, 72 insertions, 34 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index ee5ddbd36088..efebe6cf4378 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -820,6 +820,7 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour | |||
| 820 | target->caps = source->caps; | 820 | target->caps = source->caps; |
| 821 | target->options = source->options; | 821 | target->options = source->options; |
| 822 | target->auth_info = source->auth_info; | 822 | target->auth_info = source->auth_info; |
| 823 | target->port = source->port; | ||
| 823 | } | 824 | } |
| 824 | EXPORT_SYMBOL_GPL(nfs_server_copy_userdata); | 825 | EXPORT_SYMBOL_GPL(nfs_server_copy_userdata); |
| 825 | 826 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 5ac484fe0dee..3522b1249019 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -2372,16 +2372,40 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) | |||
| 2372 | } | 2372 | } |
| 2373 | EXPORT_SYMBOL_GPL(nfs_access_add_cache); | 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 | void nfs_access_set_mask(struct nfs_access_entry *entry, u32 access_result) | 2406 | void nfs_access_set_mask(struct nfs_access_entry *entry, u32 access_result) |
| 2376 | { | 2407 | { |
| 2377 | entry->mask = 0; | 2408 | entry->mask = access_result; |
| 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; | ||
| 2385 | } | 2409 | } |
| 2386 | EXPORT_SYMBOL_GPL(nfs_access_set_mask); | 2410 | EXPORT_SYMBOL_GPL(nfs_access_set_mask); |
| 2387 | 2411 | ||
| @@ -2389,6 +2413,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) | |||
| 2389 | { | 2413 | { |
| 2390 | struct nfs_access_entry cache; | 2414 | struct nfs_access_entry cache; |
| 2391 | bool may_block = (mask & MAY_NOT_BLOCK) == 0; | 2415 | bool may_block = (mask & MAY_NOT_BLOCK) == 0; |
| 2416 | int cache_mask; | ||
| 2392 | int status; | 2417 | int status; |
| 2393 | 2418 | ||
| 2394 | trace_nfs_access_enter(inode); | 2419 | trace_nfs_access_enter(inode); |
| @@ -2404,7 +2429,8 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) | |||
| 2404 | goto out; | 2429 | goto out; |
| 2405 | 2430 | ||
| 2406 | /* Be clever: ask server to check for all possible rights */ | 2431 | /* Be clever: ask server to check for all possible rights */ |
| 2407 | cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ; | 2432 | cache.mask = NFS_MAY_LOOKUP | NFS_MAY_EXECUTE |
| 2433 | | NFS_MAY_WRITE | NFS_MAY_READ; | ||
| 2408 | cache.cred = cred; | 2434 | cache.cred = cred; |
| 2409 | cache.jiffies = jiffies; | 2435 | cache.jiffies = jiffies; |
| 2410 | status = NFS_PROTO(inode)->access(inode, &cache); | 2436 | status = NFS_PROTO(inode)->access(inode, &cache); |
| @@ -2418,7 +2444,8 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) | |||
| 2418 | } | 2444 | } |
| 2419 | nfs_access_add_cache(inode, &cache); | 2445 | nfs_access_add_cache(inode, &cache); |
| 2420 | out_cached: | 2446 | out_cached: |
| 2421 | if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) | 2447 | cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode); |
| 2448 | if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) | ||
| 2422 | status = -EACCES; | 2449 | status = -EACCES; |
| 2423 | out: | 2450 | out: |
| 2424 | trace_nfs_access_exit(inode, status); | 2451 | trace_nfs_access_exit(inode, status); |
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 080fc6b278bd..44c638b7876c 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
| @@ -542,6 +542,10 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo, | |||
| 542 | struct nfs4_file_layout_dsaddr *dsaddr; | 542 | struct nfs4_file_layout_dsaddr *dsaddr; |
| 543 | int status = -EINVAL; | 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 | /* find and reference the deviceid */ | 549 | /* find and reference the deviceid */ |
| 546 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid, | 550 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid, |
| 547 | lo->plh_lc_cred, gfp_flags); | 551 | lo->plh_lc_cred, gfp_flags); |
| @@ -553,8 +557,6 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo, | |||
| 553 | if (filelayout_test_devid_unavailable(&dsaddr->id_node)) | 557 | if (filelayout_test_devid_unavailable(&dsaddr->id_node)) |
| 554 | goto out_put; | 558 | goto out_put; |
| 555 | 559 | ||
| 556 | fl->dsaddr = dsaddr; | ||
| 557 | |||
| 558 | if (fl->first_stripe_index >= dsaddr->stripe_count) { | 560 | if (fl->first_stripe_index >= dsaddr->stripe_count) { |
| 559 | dprintk("%s Bad first_stripe_index %u\n", | 561 | dprintk("%s Bad first_stripe_index %u\n", |
| 560 | __func__, fl->first_stripe_index); | 562 | __func__, fl->first_stripe_index); |
| @@ -570,6 +572,13 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo, | |||
| 570 | goto out_put; | 572 | goto out_put; |
| 571 | } | 573 | } |
| 572 | status = 0; | 574 | status = 0; |
| 575 | |||
| 576 | /* | ||
| 577 | * Atomic compare and xchange to ensure we don't scribble | ||
| 578 | * over a non-NULL pointer. | ||
| 579 | */ | ||
| 580 | if (cmpxchg(&fl->dsaddr, NULL, dsaddr) != NULL) | ||
| 581 | goto out_put; | ||
| 573 | out: | 582 | out: |
| 574 | return status; | 583 | return status; |
| 575 | out_put: | 584 | out_put: |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 1f2ac3dd0fe5..b0fa83a60754 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
| @@ -1842,6 +1842,10 @@ static int ff_layout_initiate_commit(struct nfs_commit_data *data, int how) | |||
| 1842 | int vers, ret; | 1842 | int vers, ret; |
| 1843 | struct nfs_fh *fh; | 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 | idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); | 1849 | idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); |
| 1846 | ds = nfs4_ff_layout_prepare_ds(lseg, idx, true); | 1850 | ds = nfs4_ff_layout_prepare_ds(lseg, idx, true); |
| 1847 | if (!ds) | 1851 | if (!ds) |
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 3efe946672be..60bad882c123 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
| @@ -512,7 +512,7 @@ static const struct rpc_version mnt_version1 = { | |||
| 512 | .counts = mnt_counts, | 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 | static const struct rpc_version mnt_version3 = { | 516 | static const struct rpc_version mnt_version3 = { |
| 517 | .number = 3, | 517 | .number = 3, |
| 518 | .nrprocs = ARRAY_SIZE(mnt3_procedures), | 518 | .nrprocs = ARRAY_SIZE(mnt3_procedures), |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index df4a7d3ab915..d1e87ec0df84 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
| @@ -220,15 +220,8 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
| 220 | 220 | ||
| 221 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 221 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
| 222 | nfs_refresh_inode(inode, res.fattr); | 222 | nfs_refresh_inode(inode, res.fattr); |
| 223 | if (status == 0) { | 223 | if (status == 0) |
| 224 | entry->mask = 0; | 224 | nfs_access_set_mask(entry, res.access); |
| 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 | } | ||
| 232 | nfs_free_fattr(res.fattr); | 225 | nfs_free_fattr(res.fattr); |
| 233 | out: | 226 | out: |
| 234 | dprintk("NFS reply access: %d\n", status); | 227 | dprintk("NFS reply access: %d\n", status); |
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index d40755a0984b..25f28fa64c57 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c | |||
| @@ -159,13 +159,18 @@ void pnfs_generic_recover_commit_reqs(struct list_head *dst, | |||
| 159 | { | 159 | { |
| 160 | struct pnfs_commit_bucket *b; | 160 | struct pnfs_commit_bucket *b; |
| 161 | struct pnfs_layout_segment *freeme; | 161 | struct pnfs_layout_segment *freeme; |
| 162 | int nwritten; | ||
| 162 | int i; | 163 | int i; |
| 163 | 164 | ||
| 164 | lockdep_assert_held(&cinfo->inode->i_lock); | 165 | lockdep_assert_held(&cinfo->inode->i_lock); |
| 165 | restart: | 166 | restart: |
| 166 | for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { | 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 | nwritten = pnfs_generic_transfer_commit_list(&b->written, |
| 168 | cinfo, 0)) { | 169 | dst, cinfo, 0); |
| 170 | if (!nwritten) | ||
| 171 | continue; | ||
| 172 | cinfo->ds->nwritten -= nwritten; | ||
| 173 | if (list_empty(&b->written)) { | ||
| 169 | freeme = b->wlseg; | 174 | freeme = b->wlseg; |
| 170 | b->wlseg = NULL; | 175 | b->wlseg = NULL; |
| 171 | spin_unlock(&cinfo->inode->i_lock); | 176 | spin_unlock(&cinfo->inode->i_lock); |
| @@ -174,7 +179,6 @@ restart: | |||
| 174 | goto restart; | 179 | goto restart; |
| 175 | } | 180 | } |
| 176 | } | 181 | } |
| 177 | cinfo->ds->nwritten = 0; | ||
| 178 | } | 182 | } |
| 179 | EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs); | 183 | EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs); |
| 180 | 184 | ||
| @@ -183,6 +187,7 @@ static void pnfs_generic_retry_commit(struct nfs_commit_info *cinfo, int idx) | |||
| 183 | struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; | 187 | struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; |
| 184 | struct pnfs_commit_bucket *bucket; | 188 | struct pnfs_commit_bucket *bucket; |
| 185 | struct pnfs_layout_segment *freeme; | 189 | struct pnfs_layout_segment *freeme; |
| 190 | struct list_head *pos; | ||
| 186 | LIST_HEAD(pages); | 191 | LIST_HEAD(pages); |
| 187 | int i; | 192 | int i; |
| 188 | 193 | ||
| @@ -193,6 +198,8 @@ static void pnfs_generic_retry_commit(struct nfs_commit_info *cinfo, int idx) | |||
| 193 | continue; | 198 | continue; |
| 194 | freeme = bucket->clseg; | 199 | freeme = bucket->clseg; |
| 195 | bucket->clseg = NULL; | 200 | bucket->clseg = NULL; |
| 201 | list_for_each(pos, &bucket->committing) | ||
| 202 | cinfo->ds->ncommitting--; | ||
| 196 | list_splice_init(&bucket->committing, &pages); | 203 | list_splice_init(&bucket->committing, &pages); |
| 197 | spin_unlock(&cinfo->inode->i_lock); | 204 | spin_unlock(&cinfo->inode->i_lock); |
| 198 | nfs_retry_commit(&pages, freeme, cinfo, i); | 205 | nfs_retry_commit(&pages, freeme, cinfo, i); |
| @@ -217,13 +224,6 @@ pnfs_generic_alloc_ds_commits(struct nfs_commit_info *cinfo, | |||
| 217 | for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) { | 224 | for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) { |
| 218 | if (list_empty(&bucket->committing)) | 225 | if (list_empty(&bucket->committing)) |
| 219 | continue; | 226 | continue; |
| 220 | /* | ||
| 221 | * If the layout segment is invalid, then let | ||
| 222 | * pnfs_generic_retry_commit() clean up the bucket. | ||
| 223 | */ | ||
| 224 | if (bucket->clseg && !pnfs_is_valid_lseg(bucket->clseg) && | ||
| 225 | !test_bit(NFS_LSEG_LAYOUTRETURN, &bucket->clseg->pls_flags)) | ||
| 226 | break; | ||
| 227 | data = nfs_commitdata_alloc(false); | 227 | data = nfs_commitdata_alloc(false); |
| 228 | if (!data) | 228 | if (!data) |
| 229 | break; | 229 | break; |
| @@ -243,9 +243,12 @@ void pnfs_fetch_commit_bucket_list(struct list_head *pages, | |||
| 243 | struct nfs_commit_info *cinfo) | 243 | struct nfs_commit_info *cinfo) |
| 244 | { | 244 | { |
| 245 | struct pnfs_commit_bucket *bucket; | 245 | struct pnfs_commit_bucket *bucket; |
| 246 | struct list_head *pos; | ||
| 246 | 247 | ||
| 247 | bucket = &cinfo->ds->buckets[data->ds_commit_index]; | 248 | bucket = &cinfo->ds->buckets[data->ds_commit_index]; |
| 248 | spin_lock(&cinfo->inode->i_lock); | 249 | spin_lock(&cinfo->inode->i_lock); |
| 250 | list_for_each(pos, &bucket->committing) | ||
| 251 | cinfo->ds->ncommitting--; | ||
| 249 | list_splice_init(&bucket->committing, pages); | 252 | list_splice_init(&bucket->committing, pages); |
| 250 | data->lseg = bucket->clseg; | 253 | data->lseg = bucket->clseg; |
| 251 | bucket->clseg = NULL; | 254 | bucket->clseg = NULL; |
| @@ -330,7 +333,6 @@ pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages, | |||
| 330 | } | 333 | } |
| 331 | } | 334 | } |
| 332 | out: | 335 | out: |
| 333 | cinfo->ds->ncommitting = 0; | ||
| 334 | return PNFS_ATTEMPTED; | 336 | return PNFS_ATTEMPTED; |
| 335 | } | 337 | } |
| 336 | EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist); | 338 | EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist); |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index e52cc55ac300..5cc91d6381a3 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
| @@ -51,7 +51,7 @@ struct nfs_access_entry { | |||
| 51 | struct list_head lru; | 51 | struct list_head lru; |
| 52 | unsigned long jiffies; | 52 | unsigned long jiffies; |
| 53 | struct rpc_cred * cred; | 53 | struct rpc_cred * cred; |
| 54 | int mask; | 54 | __u32 mask; |
| 55 | struct rcu_head rcu_head; | 55 | struct rcu_head rcu_head; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d5b54c020dec..4f154d388748 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -1624,6 +1624,8 @@ static void xs_tcp_state_change(struct sock *sk) | |||
| 1624 | if (test_and_clear_bit(XPRT_SOCK_CONNECTING, | 1624 | if (test_and_clear_bit(XPRT_SOCK_CONNECTING, |
| 1625 | &transport->sock_state)) | 1625 | &transport->sock_state)) |
| 1626 | xprt_clear_connecting(xprt); | 1626 | xprt_clear_connecting(xprt); |
| 1627 | if (sk->sk_err) | ||
| 1628 | xprt_wake_pending_tasks(xprt, -sk->sk_err); | ||
| 1627 | xs_sock_mark_closed(xprt); | 1629 | xs_sock_mark_closed(xprt); |
| 1628 | } | 1630 | } |
| 1629 | out: | 1631 | out: |
