aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2011-02-28 20:34:13 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-11 15:38:42 -0500
commitd684d2ae10a4f95d3035abf698d7d611ff2cd279 (patch)
tree9bae2d1808b8e2a0d153d8d1d13f0d9a01408de0
parent94de8b27d0dcb2608d56a7e5c2941b87e6da7ce3 (diff)
NFSv4.1: lseg refcounting
Prepare put_lseg and get_lseg to be called from the pNFS I/O code. Pull common code from pnfs_lseg_locked to call from pnfs_lseg. Inline pnfs_lseg_locked into it's only caller. Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/pnfs.c62
-rw-r--r--fs/nfs/pnfs.h20
2 files changed, 59 insertions, 23 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 7d031cd7d92..3afa82e4543 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -230,32 +230,41 @@ static void free_lseg(struct pnfs_layout_segment *lseg)
230 put_layout_hdr(NFS_I(ino)->layout); 230 put_layout_hdr(NFS_I(ino)->layout);
231} 231}
232 232
233/* The use of tmp_list is necessary because pnfs_curr_ld->free_lseg 233static void
234 * could sleep, so must be called outside of the lock. 234put_lseg_common(struct pnfs_layout_segment *lseg)
235 * Returns 1 if object was removed, otherwise return 0. 235{
236 */ 236 struct inode *inode = lseg->pls_layout->plh_inode;
237static int 237
238put_lseg_locked(struct pnfs_layout_segment *lseg, 238 BUG_ON(test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
239 struct list_head *tmp_list) 239 list_del_init(&lseg->pls_list);
240 if (list_empty(&lseg->pls_layout->plh_segs)) {
241 set_bit(NFS_LAYOUT_DESTROYED, &lseg->pls_layout->plh_flags);
242 /* Matched by initial refcount set in alloc_init_layout_hdr */
243 put_layout_hdr_locked(lseg->pls_layout);
244 }
245 rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq);
246}
247
248static void
249put_lseg(struct pnfs_layout_segment *lseg)
240{ 250{
251 struct inode *inode;
252
253 if (!lseg)
254 return;
255
241 dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg, 256 dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg,
242 atomic_read(&lseg->pls_refcount), 257 atomic_read(&lseg->pls_refcount),
243 test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); 258 test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
244 if (atomic_dec_and_test(&lseg->pls_refcount)) { 259 inode = lseg->pls_layout->plh_inode;
245 struct inode *ino = lseg->pls_layout->plh_inode; 260 if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
261 LIST_HEAD(free_me);
246 262
247 BUG_ON(test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); 263 put_lseg_common(lseg);
248 list_del(&lseg->pls_list); 264 list_add(&lseg->pls_list, &free_me);
249 if (list_empty(&lseg->pls_layout->plh_segs)) { 265 spin_unlock(&inode->i_lock);
250 set_bit(NFS_LAYOUT_DESTROYED, &lseg->pls_layout->plh_flags); 266 pnfs_free_lseg_list(&free_me);
251 /* Matched by initial refcount set in alloc_init_layout_hdr */
252 put_layout_hdr_locked(lseg->pls_layout);
253 }
254 rpc_wake_up(&NFS_SERVER(ino)->roc_rpcwaitq);
255 list_add(&lseg->pls_list, tmp_list);
256 return 1;
257 } 267 }
258 return 0;
259} 268}
260 269
261static bool 270static bool
@@ -276,7 +285,13 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
276 * list. It will now be removed when all 285 * list. It will now be removed when all
277 * outstanding io is finished. 286 * outstanding io is finished.
278 */ 287 */
279 rv = put_lseg_locked(lseg, tmp_list); 288 dprintk("%s: lseg %p ref %d\n", __func__, lseg,
289 atomic_read(&lseg->pls_refcount));
290 if (atomic_dec_and_test(&lseg->pls_refcount)) {
291 put_lseg_common(lseg);
292 list_add(&lseg->pls_list, tmp_list);
293 rv = 1;
294 }
280 } 295 }
281 return rv; 296 return rv;
282} 297}
@@ -689,7 +704,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode)
689 list_for_each_entry(lseg, &lo->plh_segs, pls_list) { 704 list_for_each_entry(lseg, &lo->plh_segs, pls_list) {
690 if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && 705 if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) &&
691 is_matching_lseg(lseg, iomode)) { 706 is_matching_lseg(lseg, iomode)) {
692 ret = lseg; 707 ret = get_lseg(lseg);
693 break; 708 break;
694 } 709 }
695 if (cmp_layout(iomode, lseg->pls_range.iomode) > 0) 710 if (cmp_layout(iomode, lseg->pls_range.iomode) > 0)
@@ -769,6 +784,7 @@ pnfs_update_layout(struct inode *ino,
769out: 784out:
770 dprintk("%s end, state 0x%lx lseg %p\n", __func__, 785 dprintk("%s end, state 0x%lx lseg %p\n", __func__,
771 nfsi->layout ? nfsi->layout->plh_flags : -1, lseg); 786 nfsi->layout ? nfsi->layout->plh_flags : -1, lseg);
787 put_lseg(lseg); /* STUB - callers currently ignore return value */
772 return lseg; 788 return lseg;
773out_unlock: 789out_unlock:
774 spin_unlock(&ino->i_lock); 790 spin_unlock(&ino->i_lock);
@@ -821,7 +837,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
821 } 837 }
822 init_lseg(lo, lseg); 838 init_lseg(lo, lseg);
823 lseg->pls_range = res->range; 839 lseg->pls_range = res->range;
824 *lgp->lsegpp = lseg; 840 *lgp->lsegpp = get_lseg(lseg);
825 pnfs_insert_layout(lo, lseg); 841 pnfs_insert_layout(lo, lseg);
826 842
827 if (res->return_on_close) { 843 if (res->return_on_close) {
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index e2612ea0cbe..9a994bc9899 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -177,6 +177,16 @@ static inline int lo_fail_bit(u32 iomode)
177 NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED; 177 NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED;
178} 178}
179 179
180static inline struct pnfs_layout_segment *
181get_lseg(struct pnfs_layout_segment *lseg)
182{
183 if (lseg) {
184 atomic_inc(&lseg->pls_refcount);
185 smp_mb__after_atomic_inc();
186 }
187 return lseg;
188}
189
180/* Return true if a layout driver is being used for this mountpoint */ 190/* Return true if a layout driver is being used for this mountpoint */
181static inline int pnfs_enabled_sb(struct nfs_server *nfss) 191static inline int pnfs_enabled_sb(struct nfs_server *nfss)
182{ 192{
@@ -194,6 +204,16 @@ static inline void pnfs_destroy_layout(struct nfs_inode *nfsi)
194} 204}
195 205
196static inline struct pnfs_layout_segment * 206static inline struct pnfs_layout_segment *
207get_lseg(struct pnfs_layout_segment *lseg)
208{
209 return NULL;
210}
211
212static inline void put_lseg(struct pnfs_layout_segment *lseg)
213{
214}
215
216static inline struct pnfs_layout_segment *
197pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, 217pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
198 enum pnfs_iomode access_type) 218 enum pnfs_iomode access_type)
199{ 219{