aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/client.c1
-rw-r--r--fs/nfs/dir.c47
-rw-r--r--fs/nfs/filelayout/filelayout.c13
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c4
-rw-r--r--fs/nfs/mount_clnt.c2
-rw-r--r--fs/nfs/nfs3proc.c11
-rw-r--r--fs/nfs/pnfs_nfs.c24
-rw-r--r--include/linux/nfs_fs.h2
-rw-r--r--net/sunrpc/xprtsock.c2
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}
824EXPORT_SYMBOL_GPL(nfs_server_copy_userdata); 825EXPORT_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}
2373EXPORT_SYMBOL_GPL(nfs_access_add_cache); 2373EXPORT_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)
2384static int
2385nfs_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
2375void nfs_access_set_mask(struct nfs_access_entry *entry, u32 access_result) 2406void 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}
2386EXPORT_SYMBOL_GPL(nfs_access_set_mask); 2410EXPORT_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);
2420out_cached: 2446out_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;
2423out: 2450out:
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;
573out: 582out:
574 return status; 583 return status;
575out_put: 584out_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
515static unsigned int mnt3_counts[ARRAY_SIZE(mnt_procedures)]; 515static unsigned int mnt3_counts[ARRAY_SIZE(mnt3_procedures)];
516static const struct rpc_version mnt_version3 = { 516static 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);
233out: 226out:
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);
165restart: 166restart:
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}
179EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs); 183EXPORT_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 }
332out: 335out:
333 cinfo->ds->ncommitting = 0;
334 return PNFS_ATTEMPTED; 336 return PNFS_ATTEMPTED;
335} 337}
336EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist); 338EXPORT_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: