aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2014-10-08 16:39:12 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-10-08 16:45:43 -0400
commit6543f803670530f6aa93790d9fa116d8395a537d (patch)
tree0c39c9b0eaab0e5932eb43226c933e353abde369 /fs
parentea18cb3f113d7f8d622622c176c51363cc656521 (diff)
NFSv4.1/pnfs: replace broken pnfs_put_lseg_async
You cannot call pnfs_put_lseg_async() more than once per lseg, so it is really an inappropriate way to deal with a refcount issue. Instead, replace it with a function that decrements the refcount, and puts the final 'free' operation (which is incompatible with locks) on the workqueue. Cc: Weston Andros Adamson <dros@primarydata.com> Fixes: e6cf82d1830f: pnfs: add pnfs_put_lseg_async Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/filelayout/filelayout.c2
-rw-r--r--fs/nfs/pnfs.c33
-rw-r--r--fs/nfs/pnfs.h6
3 files changed, 29 insertions, 12 deletions
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c
index abc5056999d6..46fab1cb455a 100644
--- a/fs/nfs/filelayout/filelayout.c
+++ b/fs/nfs/filelayout/filelayout.c
@@ -1031,7 +1031,7 @@ filelayout_clear_request_commit(struct nfs_page *req,
1031 } 1031 }
1032out: 1032out:
1033 nfs_request_remove_commit_list(req, cinfo); 1033 nfs_request_remove_commit_list(req, cinfo);
1034 pnfs_put_lseg_async(freeme); 1034 pnfs_put_lseg_locked(freeme);
1035} 1035}
1036 1036
1037static void 1037static void
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 76de7f568119..0a5dda4d85c2 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -361,22 +361,43 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)
361} 361}
362EXPORT_SYMBOL_GPL(pnfs_put_lseg); 362EXPORT_SYMBOL_GPL(pnfs_put_lseg);
363 363
364static void pnfs_put_lseg_async_work(struct work_struct *work) 364static void pnfs_free_lseg_async_work(struct work_struct *work)
365{ 365{
366 struct pnfs_layout_segment *lseg; 366 struct pnfs_layout_segment *lseg;
367 struct pnfs_layout_hdr *lo;
367 368
368 lseg = container_of(work, struct pnfs_layout_segment, pls_work); 369 lseg = container_of(work, struct pnfs_layout_segment, pls_work);
370 lo = lseg->pls_layout;
369 371
370 pnfs_put_lseg(lseg); 372 pnfs_free_lseg(lseg);
373 pnfs_put_layout_hdr(lo);
371} 374}
372 375
373void 376static void pnfs_free_lseg_async(struct pnfs_layout_segment *lseg)
374pnfs_put_lseg_async(struct pnfs_layout_segment *lseg)
375{ 377{
376 INIT_WORK(&lseg->pls_work, pnfs_put_lseg_async_work); 378 INIT_WORK(&lseg->pls_work, pnfs_free_lseg_async_work);
377 schedule_work(&lseg->pls_work); 379 schedule_work(&lseg->pls_work);
378} 380}
379EXPORT_SYMBOL_GPL(pnfs_put_lseg_async); 381
382void
383pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg)
384{
385 if (!lseg)
386 return;
387
388 assert_spin_locked(&lseg->pls_layout->plh_inode->i_lock);
389
390 dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg,
391 atomic_read(&lseg->pls_refcount),
392 test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
393 if (atomic_dec_and_test(&lseg->pls_refcount)) {
394 struct pnfs_layout_hdr *lo = lseg->pls_layout;
395 pnfs_get_layout_hdr(lo);
396 pnfs_layout_remove_lseg(lo, lseg);
397 pnfs_free_lseg_async(lseg);
398 }
399}
400EXPORT_SYMBOL_GPL(pnfs_put_lseg_locked);
380 401
381static u64 402static u64
382end_offset(u64 start, u64 len) 403end_offset(u64 start, u64 len)
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 509a710148ba..9ae5b765b073 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -190,7 +190,7 @@ extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp);
190/* pnfs.c */ 190/* pnfs.c */
191void pnfs_get_layout_hdr(struct pnfs_layout_hdr *lo); 191void pnfs_get_layout_hdr(struct pnfs_layout_hdr *lo);
192void pnfs_put_lseg(struct pnfs_layout_segment *lseg); 192void pnfs_put_lseg(struct pnfs_layout_segment *lseg);
193void pnfs_put_lseg_async(struct pnfs_layout_segment *lseg); 193void pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg);
194 194
195void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32); 195void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32);
196void unset_pnfs_layoutdriver(struct nfs_server *); 196void unset_pnfs_layoutdriver(struct nfs_server *);
@@ -445,10 +445,6 @@ static inline void pnfs_put_lseg(struct pnfs_layout_segment *lseg)
445{ 445{
446} 446}
447 447
448static inline void pnfs_put_lseg_async(struct pnfs_layout_segment *lseg)
449{
450}
451
452static inline int pnfs_return_layout(struct inode *ino) 448static inline int pnfs_return_layout(struct inode *ino)
453{ 449{
454 return 0; 450 return 0;