aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-02-23 19:39:21 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-23 19:39:21 -0500
commit420eb6d7efc4591ef1968106cdaa980ea06fe00e (patch)
tree28a3215400d9cfe7d5b93313402d023caee5ecbe /fs
parentde9e478b9d49f3a0214310d921450cf5bb4a21e6 (diff)
parent9fd4b9fc7695a4da1363a0b439853f88fb6a034f (diff)
Merge tag 'nfs-for-4.5-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Stable bugfixes: - Fix nfs_size_to_loff_t - NFSv4: Fix a dentry leak on alias use Other bugfixes: - Don't schedule a layoutreturn if the layout segment can be freed immediately. - Always set NFS_LAYOUT_RETURN_REQUESTED with lo->plh_return_iomode - rpcrdma_bc_receive_call() should init rq_private_buf.len - fix stateid handling for the NFS v4.2 operations - pnfs/blocklayout: fix a memeory leak when using,vmalloc_to_page - fix panic in gss_pipe_downcall() in fips mode - Fix a race between layoutget and pnfs_destroy_layout - Fix a race between layoutget and bulk recalls" * tag 'nfs-for-4.5-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4.x/pnfs: Fix a race between layoutget and bulk recalls NFSv4.x/pnfs: Fix a race between layoutget and pnfs_destroy_layout auth_gss: fix panic in gss_pipe_downcall() in fips mode pnfs/blocklayout: fix a memeory leak when using,vmalloc_to_page nfs4: fix stateid handling for the NFS v4.2 operations NFSv4: Fix a dentry leak on alias use xprtrdma: rpcrdma_bc_receive_call() should init rq_private_buf.len pNFS: Always set NFS_LAYOUT_RETURN_REQUESTED with lo->plh_return_iomode pNFS: Fix pnfs_mark_matching_lsegs_return() nfs: fix nfs_size_to_loff_t
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/blocklayout/extent_tree.c10
-rw-r--r--fs/nfs/nfs42proc.c119
-rw-r--r--fs/nfs/nfs4proc.c4
-rw-r--r--fs/nfs/pnfs.c55
4 files changed, 126 insertions, 62 deletions
diff --git a/fs/nfs/blocklayout/extent_tree.c b/fs/nfs/blocklayout/extent_tree.c
index c59a59c37f3d..35ab51c04814 100644
--- a/fs/nfs/blocklayout/extent_tree.c
+++ b/fs/nfs/blocklayout/extent_tree.c
@@ -476,6 +476,7 @@ static void ext_tree_free_commitdata(struct nfs4_layoutcommit_args *arg,
476 476
477 for (i = 0; i < nr_pages; i++) 477 for (i = 0; i < nr_pages; i++)
478 put_page(arg->layoutupdate_pages[i]); 478 put_page(arg->layoutupdate_pages[i]);
479 vfree(arg->start_p);
479 kfree(arg->layoutupdate_pages); 480 kfree(arg->layoutupdate_pages);
480 } else { 481 } else {
481 put_page(arg->layoutupdate_page); 482 put_page(arg->layoutupdate_page);
@@ -559,10 +560,15 @@ retry:
559 560
560 if (unlikely(arg->layoutupdate_pages != &arg->layoutupdate_page)) { 561 if (unlikely(arg->layoutupdate_pages != &arg->layoutupdate_page)) {
561 void *p = start_p, *end = p + arg->layoutupdate_len; 562 void *p = start_p, *end = p + arg->layoutupdate_len;
563 struct page *page = NULL;
562 int i = 0; 564 int i = 0;
563 565
564 for ( ; p < end; p += PAGE_SIZE) 566 arg->start_p = start_p;
565 arg->layoutupdate_pages[i++] = vmalloc_to_page(p); 567 for ( ; p < end; p += PAGE_SIZE) {
568 page = vmalloc_to_page(p);
569 arg->layoutupdate_pages[i++] = page;
570 get_page(page);
571 }
566 } 572 }
567 573
568 dprintk("%s found %zu ranges\n", __func__, count); 574 dprintk("%s found %zu ranges\n", __func__, count);
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
index bd25dc7077f7..dff83460e5a6 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -16,29 +16,8 @@
16 16
17#define NFSDBG_FACILITY NFSDBG_PROC 17#define NFSDBG_FACILITY NFSDBG_PROC
18 18
19static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file,
20 fmode_t fmode)
21{
22 struct nfs_open_context *open;
23 struct nfs_lock_context *lock;
24 int ret;
25
26 open = get_nfs_open_context(nfs_file_open_context(file));
27 lock = nfs_get_lock_context(open);
28 if (IS_ERR(lock)) {
29 put_nfs_open_context(open);
30 return PTR_ERR(lock);
31 }
32
33 ret = nfs4_set_rw_stateid(dst, open, lock, fmode);
34
35 nfs_put_lock_context(lock);
36 put_nfs_open_context(open);
37 return ret;
38}
39
40static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, 19static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
41 loff_t offset, loff_t len) 20 struct nfs_lock_context *lock, loff_t offset, loff_t len)
42{ 21{
43 struct inode *inode = file_inode(filep); 22 struct inode *inode = file_inode(filep);
44 struct nfs_server *server = NFS_SERVER(inode); 23 struct nfs_server *server = NFS_SERVER(inode);
@@ -56,7 +35,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
56 msg->rpc_argp = &args; 35 msg->rpc_argp = &args;
57 msg->rpc_resp = &res; 36 msg->rpc_resp = &res;
58 37
59 status = nfs42_set_rw_stateid(&args.falloc_stateid, filep, FMODE_WRITE); 38 status = nfs4_set_rw_stateid(&args.falloc_stateid, lock->open_context,
39 lock, FMODE_WRITE);
60 if (status) 40 if (status)
61 return status; 41 return status;
62 42
@@ -78,15 +58,26 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
78{ 58{
79 struct nfs_server *server = NFS_SERVER(file_inode(filep)); 59 struct nfs_server *server = NFS_SERVER(file_inode(filep));
80 struct nfs4_exception exception = { }; 60 struct nfs4_exception exception = { };
61 struct nfs_lock_context *lock;
81 int err; 62 int err;
82 63
64 lock = nfs_get_lock_context(nfs_file_open_context(filep));
65 if (IS_ERR(lock))
66 return PTR_ERR(lock);
67
68 exception.inode = file_inode(filep);
69 exception.state = lock->open_context->state;
70
83 do { 71 do {
84 err = _nfs42_proc_fallocate(msg, filep, offset, len); 72 err = _nfs42_proc_fallocate(msg, filep, lock, offset, len);
85 if (err == -ENOTSUPP) 73 if (err == -ENOTSUPP) {
86 return -EOPNOTSUPP; 74 err = -EOPNOTSUPP;
75 break;
76 }
87 err = nfs4_handle_exception(server, err, &exception); 77 err = nfs4_handle_exception(server, err, &exception);
88 } while (exception.retry); 78 } while (exception.retry);
89 79
80 nfs_put_lock_context(lock);
90 return err; 81 return err;
91} 82}
92 83
@@ -135,7 +126,8 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
135 return err; 126 return err;
136} 127}
137 128
138static loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) 129static loff_t _nfs42_proc_llseek(struct file *filep,
130 struct nfs_lock_context *lock, loff_t offset, int whence)
139{ 131{
140 struct inode *inode = file_inode(filep); 132 struct inode *inode = file_inode(filep);
141 struct nfs42_seek_args args = { 133 struct nfs42_seek_args args = {
@@ -156,7 +148,8 @@ static loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
156 if (!nfs_server_capable(inode, NFS_CAP_SEEK)) 148 if (!nfs_server_capable(inode, NFS_CAP_SEEK))
157 return -ENOTSUPP; 149 return -ENOTSUPP;
158 150
159 status = nfs42_set_rw_stateid(&args.sa_stateid, filep, FMODE_READ); 151 status = nfs4_set_rw_stateid(&args.sa_stateid, lock->open_context,
152 lock, FMODE_READ);
160 if (status) 153 if (status)
161 return status; 154 return status;
162 155
@@ -175,17 +168,28 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
175{ 168{
176 struct nfs_server *server = NFS_SERVER(file_inode(filep)); 169 struct nfs_server *server = NFS_SERVER(file_inode(filep));
177 struct nfs4_exception exception = { }; 170 struct nfs4_exception exception = { };
171 struct nfs_lock_context *lock;
178 loff_t err; 172 loff_t err;
179 173
174 lock = nfs_get_lock_context(nfs_file_open_context(filep));
175 if (IS_ERR(lock))
176 return PTR_ERR(lock);
177
178 exception.inode = file_inode(filep);
179 exception.state = lock->open_context->state;
180
180 do { 181 do {
181 err = _nfs42_proc_llseek(filep, offset, whence); 182 err = _nfs42_proc_llseek(filep, lock, offset, whence);
182 if (err >= 0) 183 if (err >= 0)
183 break; 184 break;
184 if (err == -ENOTSUPP) 185 if (err == -ENOTSUPP) {
185 return -EOPNOTSUPP; 186 err = -EOPNOTSUPP;
187 break;
188 }
186 err = nfs4_handle_exception(server, err, &exception); 189 err = nfs4_handle_exception(server, err, &exception);
187 } while (exception.retry); 190 } while (exception.retry);
188 191
192 nfs_put_lock_context(lock);
189 return err; 193 return err;
190} 194}
191 195
@@ -298,8 +302,9 @@ int nfs42_proc_layoutstats_generic(struct nfs_server *server,
298} 302}
299 303
300static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f, 304static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
301 struct file *dst_f, loff_t src_offset, 305 struct file *dst_f, struct nfs_lock_context *src_lock,
302 loff_t dst_offset, loff_t count) 306 struct nfs_lock_context *dst_lock, loff_t src_offset,
307 loff_t dst_offset, loff_t count)
303{ 308{
304 struct inode *src_inode = file_inode(src_f); 309 struct inode *src_inode = file_inode(src_f);
305 struct inode *dst_inode = file_inode(dst_f); 310 struct inode *dst_inode = file_inode(dst_f);
@@ -320,11 +325,13 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
320 msg->rpc_argp = &args; 325 msg->rpc_argp = &args;
321 msg->rpc_resp = &res; 326 msg->rpc_resp = &res;
322 327
323 status = nfs42_set_rw_stateid(&args.src_stateid, src_f, FMODE_READ); 328 status = nfs4_set_rw_stateid(&args.src_stateid, src_lock->open_context,
329 src_lock, FMODE_READ);
324 if (status) 330 if (status)
325 return status; 331 return status;
326 332
327 status = nfs42_set_rw_stateid(&args.dst_stateid, dst_f, FMODE_WRITE); 333 status = nfs4_set_rw_stateid(&args.dst_stateid, dst_lock->open_context,
334 dst_lock, FMODE_WRITE);
328 if (status) 335 if (status)
329 return status; 336 return status;
330 337
@@ -349,22 +356,48 @@ int nfs42_proc_clone(struct file *src_f, struct file *dst_f,
349 }; 356 };
350 struct inode *inode = file_inode(src_f); 357 struct inode *inode = file_inode(src_f);
351 struct nfs_server *server = NFS_SERVER(file_inode(src_f)); 358 struct nfs_server *server = NFS_SERVER(file_inode(src_f));
352 struct nfs4_exception exception = { }; 359 struct nfs_lock_context *src_lock;
353 int err; 360 struct nfs_lock_context *dst_lock;
361 struct nfs4_exception src_exception = { };
362 struct nfs4_exception dst_exception = { };
363 int err, err2;
354 364
355 if (!nfs_server_capable(inode, NFS_CAP_CLONE)) 365 if (!nfs_server_capable(inode, NFS_CAP_CLONE))
356 return -EOPNOTSUPP; 366 return -EOPNOTSUPP;
357 367
368 src_lock = nfs_get_lock_context(nfs_file_open_context(src_f));
369 if (IS_ERR(src_lock))
370 return PTR_ERR(src_lock);
371
372 src_exception.inode = file_inode(src_f);
373 src_exception.state = src_lock->open_context->state;
374
375 dst_lock = nfs_get_lock_context(nfs_file_open_context(dst_f));
376 if (IS_ERR(dst_lock)) {
377 err = PTR_ERR(dst_lock);
378 goto out_put_src_lock;
379 }
380
381 dst_exception.inode = file_inode(dst_f);
382 dst_exception.state = dst_lock->open_context->state;
383
358 do { 384 do {
359 err = _nfs42_proc_clone(&msg, src_f, dst_f, src_offset, 385 err = _nfs42_proc_clone(&msg, src_f, dst_f, src_lock, dst_lock,
360 dst_offset, count); 386 src_offset, dst_offset, count);
361 if (err == -ENOTSUPP || err == -EOPNOTSUPP) { 387 if (err == -ENOTSUPP || err == -EOPNOTSUPP) {
362 NFS_SERVER(inode)->caps &= ~NFS_CAP_CLONE; 388 NFS_SERVER(inode)->caps &= ~NFS_CAP_CLONE;
363 return -EOPNOTSUPP; 389 err = -EOPNOTSUPP;
390 break;
364 } 391 }
365 err = nfs4_handle_exception(server, err, &exception);
366 } while (exception.retry);
367 392
368 return err; 393 err2 = nfs4_handle_exception(server, err, &src_exception);
394 err = nfs4_handle_exception(server, err, &dst_exception);
395 if (!err)
396 err = err2;
397 } while (src_exception.retry || dst_exception.retry);
369 398
399 nfs_put_lock_context(dst_lock);
400out_put_src_lock:
401 nfs_put_lock_context(src_lock);
402 return err;
370} 403}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4bfc33ad0563..14881594dd07 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2466,9 +2466,9 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
2466 dentry = d_add_unique(dentry, igrab(state->inode)); 2466 dentry = d_add_unique(dentry, igrab(state->inode));
2467 if (dentry == NULL) { 2467 if (dentry == NULL) {
2468 dentry = opendata->dentry; 2468 dentry = opendata->dentry;
2469 } else if (dentry != ctx->dentry) { 2469 } else {
2470 dput(ctx->dentry); 2470 dput(ctx->dentry);
2471 ctx->dentry = dget(dentry); 2471 ctx->dentry = dentry;
2472 } 2472 }
2473 nfs_set_verifier(dentry, 2473 nfs_set_verifier(dentry,
2474 nfs_save_change_attribute(d_inode(opendata->dir))); 2474 nfs_save_change_attribute(d_inode(opendata->dir)));
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 482b6e94bb37..2fa483e6dbe2 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -252,6 +252,27 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
252 } 252 }
253} 253}
254 254
255/*
256 * Mark a pnfs_layout_hdr and all associated layout segments as invalid
257 *
258 * In order to continue using the pnfs_layout_hdr, a full recovery
259 * is required.
260 * Note that caller must hold inode->i_lock.
261 */
262static int
263pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,
264 struct list_head *lseg_list)
265{
266 struct pnfs_layout_range range = {
267 .iomode = IOMODE_ANY,
268 .offset = 0,
269 .length = NFS4_MAX_UINT64,
270 };
271
272 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
273 return pnfs_mark_matching_lsegs_invalid(lo, lseg_list, &range);
274}
275
255static int 276static int
256pnfs_iomode_to_fail_bit(u32 iomode) 277pnfs_iomode_to_fail_bit(u32 iomode)
257{ 278{
@@ -554,9 +575,8 @@ pnfs_destroy_layout(struct nfs_inode *nfsi)
554 spin_lock(&nfsi->vfs_inode.i_lock); 575 spin_lock(&nfsi->vfs_inode.i_lock);
555 lo = nfsi->layout; 576 lo = nfsi->layout;
556 if (lo) { 577 if (lo) {
557 lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */
558 pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
559 pnfs_get_layout_hdr(lo); 578 pnfs_get_layout_hdr(lo);
579 pnfs_mark_layout_stateid_invalid(lo, &tmp_list);
560 pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED); 580 pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED);
561 pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED); 581 pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED);
562 spin_unlock(&nfsi->vfs_inode.i_lock); 582 spin_unlock(&nfsi->vfs_inode.i_lock);
@@ -617,11 +637,6 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list,
617{ 637{
618 struct pnfs_layout_hdr *lo; 638 struct pnfs_layout_hdr *lo;
619 struct inode *inode; 639 struct inode *inode;
620 struct pnfs_layout_range range = {
621 .iomode = IOMODE_ANY,
622 .offset = 0,
623 .length = NFS4_MAX_UINT64,
624 };
625 LIST_HEAD(lseg_list); 640 LIST_HEAD(lseg_list);
626 int ret = 0; 641 int ret = 0;
627 642
@@ -636,11 +651,11 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list,
636 651
637 spin_lock(&inode->i_lock); 652 spin_lock(&inode->i_lock);
638 list_del_init(&lo->plh_bulk_destroy); 653 list_del_init(&lo->plh_bulk_destroy);
639 lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */ 654 if (pnfs_mark_layout_stateid_invalid(lo, &lseg_list)) {
640 if (is_bulk_recall) 655 if (is_bulk_recall)
641 set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); 656 set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
642 if (pnfs_mark_matching_lsegs_invalid(lo, &lseg_list, &range))
643 ret = -EAGAIN; 657 ret = -EAGAIN;
658 }
644 spin_unlock(&inode->i_lock); 659 spin_unlock(&inode->i_lock);
645 pnfs_free_lseg_list(&lseg_list); 660 pnfs_free_lseg_list(&lseg_list);
646 /* Free all lsegs that are attached to commit buckets */ 661 /* Free all lsegs that are attached to commit buckets */
@@ -1738,8 +1753,19 @@ pnfs_set_plh_return_iomode(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode)
1738 if (lo->plh_return_iomode != 0) 1753 if (lo->plh_return_iomode != 0)
1739 iomode = IOMODE_ANY; 1754 iomode = IOMODE_ANY;
1740 lo->plh_return_iomode = iomode; 1755 lo->plh_return_iomode = iomode;
1756 set_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags);
1741} 1757}
1742 1758
1759/**
1760 * pnfs_mark_matching_lsegs_return - Free or return matching layout segments
1761 * @lo: pointer to layout header
1762 * @tmp_list: list header to be used with pnfs_free_lseg_list()
1763 * @return_range: describe layout segment ranges to be returned
1764 *
1765 * This function is mainly intended for use by layoutrecall. It attempts
1766 * to free the layout segment immediately, or else to mark it for return
1767 * as soon as its reference count drops to zero.
1768 */
1743int 1769int
1744pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, 1770pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
1745 struct list_head *tmp_list, 1771 struct list_head *tmp_list,
@@ -1762,12 +1788,11 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
1762 lseg, lseg->pls_range.iomode, 1788 lseg, lseg->pls_range.iomode,
1763 lseg->pls_range.offset, 1789 lseg->pls_range.offset,
1764 lseg->pls_range.length); 1790 lseg->pls_range.length);
1791 if (mark_lseg_invalid(lseg, tmp_list))
1792 continue;
1793 remaining++;
1765 set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags); 1794 set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags);
1766 pnfs_set_plh_return_iomode(lo, return_range->iomode); 1795 pnfs_set_plh_return_iomode(lo, return_range->iomode);
1767 if (!mark_lseg_invalid(lseg, tmp_list))
1768 remaining++;
1769 set_bit(NFS_LAYOUT_RETURN_REQUESTED,
1770 &lo->plh_flags);
1771 } 1796 }
1772 return remaining; 1797 return remaining;
1773} 1798}