diff options
author | Fred Isaman <iisaman@netapp.com> | 2011-01-06 06:36:28 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-01-06 14:46:32 -0500 |
commit | cc6e5340b0981feac5a00a992bab6154cb4b1fa1 (patch) | |
tree | 514db8586801aa60ee97d3880071b12c0cdf2421 /fs/nfs/pnfs.c | |
parent | fc1794c5b04f5322bad05385cd91b52ec85aab72 (diff) |
pnfs: change lo refcounting to atomic_t
This will be required to allow us to grab reference outside of i_lock.
While we are at it, make put_layout_hdr take the same argument as all the
related functions.
Signed-off-by: Fred Isaman <iisaman@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index cd9906415a14..32b66468e5db 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -177,34 +177,38 @@ EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver); | |||
177 | * pNFS client layout cache | 177 | * pNFS client layout cache |
178 | */ | 178 | */ |
179 | 179 | ||
180 | /* Need to hold i_lock if caller does not already hold reference */ | ||
180 | static void | 181 | static void |
181 | get_layout_hdr_locked(struct pnfs_layout_hdr *lo) | 182 | get_layout_hdr(struct pnfs_layout_hdr *lo) |
182 | { | 183 | { |
183 | assert_spin_locked(&lo->plh_inode->i_lock); | 184 | atomic_inc(&lo->plh_refcount); |
184 | lo->plh_refcount++; | ||
185 | } | 185 | } |
186 | 186 | ||
187 | static void | 187 | static void |
188 | put_layout_hdr_locked(struct pnfs_layout_hdr *lo) | 188 | destroy_layout_hdr(struct pnfs_layout_hdr *lo) |
189 | { | 189 | { |
190 | assert_spin_locked(&lo->plh_inode->i_lock); | 190 | dprintk("%s: freeing layout cache %p\n", __func__, lo); |
191 | BUG_ON(lo->plh_refcount == 0); | 191 | BUG_ON(!list_empty(&lo->plh_layouts)); |
192 | NFS_I(lo->plh_inode)->layout = NULL; | ||
193 | kfree(lo); | ||
194 | } | ||
192 | 195 | ||
193 | lo->plh_refcount--; | 196 | static void |
194 | if (!lo->plh_refcount) { | 197 | put_layout_hdr_locked(struct pnfs_layout_hdr *lo) |
195 | dprintk("%s: freeing layout cache %p\n", __func__, lo); | 198 | { |
196 | BUG_ON(!list_empty(&lo->plh_layouts)); | 199 | if (atomic_dec_and_test(&lo->plh_refcount)) |
197 | NFS_I(lo->plh_inode)->layout = NULL; | 200 | destroy_layout_hdr(lo); |
198 | kfree(lo); | ||
199 | } | ||
200 | } | 201 | } |
201 | 202 | ||
202 | void | 203 | void |
203 | put_layout_hdr(struct inode *inode) | 204 | put_layout_hdr(struct pnfs_layout_hdr *lo) |
204 | { | 205 | { |
205 | spin_lock(&inode->i_lock); | 206 | struct inode *inode = lo->plh_inode; |
206 | put_layout_hdr_locked(NFS_I(inode)->layout); | 207 | |
207 | spin_unlock(&inode->i_lock); | 208 | if (atomic_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) { |
209 | destroy_layout_hdr(lo); | ||
210 | spin_unlock(&inode->i_lock); | ||
211 | } | ||
208 | } | 212 | } |
209 | 213 | ||
210 | static void | 214 | static void |
@@ -223,7 +227,7 @@ static void free_lseg(struct pnfs_layout_segment *lseg) | |||
223 | 227 | ||
224 | NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg); | 228 | NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg); |
225 | /* Matched by get_layout_hdr in pnfs_insert_layout */ | 229 | /* Matched by get_layout_hdr in pnfs_insert_layout */ |
226 | put_layout_hdr(ino); | 230 | put_layout_hdr(NFS_I(ino)->layout); |
227 | } | 231 | } |
228 | 232 | ||
229 | /* The use of tmp_list is necessary because pnfs_curr_ld->free_lseg | 233 | /* The use of tmp_list is necessary because pnfs_curr_ld->free_lseg |
@@ -490,7 +494,7 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo, | |||
490 | __func__, lseg, lseg->pls_range.iomode, | 494 | __func__, lseg, lseg->pls_range.iomode, |
491 | lseg->pls_range.offset, lseg->pls_range.length); | 495 | lseg->pls_range.offset, lseg->pls_range.length); |
492 | } | 496 | } |
493 | get_layout_hdr_locked(lo); | 497 | get_layout_hdr(lo); |
494 | 498 | ||
495 | dprintk("%s:Return\n", __func__); | 499 | dprintk("%s:Return\n", __func__); |
496 | } | 500 | } |
@@ -503,7 +507,7 @@ alloc_init_layout_hdr(struct inode *ino) | |||
503 | lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL); | 507 | lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL); |
504 | if (!lo) | 508 | if (!lo) |
505 | return NULL; | 509 | return NULL; |
506 | lo->plh_refcount = 1; | 510 | atomic_set(&lo->plh_refcount, 1); |
507 | INIT_LIST_HEAD(&lo->plh_layouts); | 511 | INIT_LIST_HEAD(&lo->plh_layouts); |
508 | INIT_LIST_HEAD(&lo->plh_segs); | 512 | INIT_LIST_HEAD(&lo->plh_segs); |
509 | lo->plh_inode = ino; | 513 | lo->plh_inode = ino; |
@@ -618,7 +622,7 @@ pnfs_update_layout(struct inode *ino, | |||
618 | goto out_unlock; | 622 | goto out_unlock; |
619 | atomic_inc(&lo->plh_outstanding); | 623 | atomic_inc(&lo->plh_outstanding); |
620 | 624 | ||
621 | get_layout_hdr_locked(lo); | 625 | get_layout_hdr(lo); |
622 | if (list_empty(&lo->plh_segs)) { | 626 | if (list_empty(&lo->plh_segs)) { |
623 | /* The lo must be on the clp list if there is any | 627 | /* The lo must be on the clp list if there is any |
624 | * chance of a CB_LAYOUTRECALL(FILE) coming in. | 628 | * chance of a CB_LAYOUTRECALL(FILE) coming in. |
@@ -641,7 +645,7 @@ pnfs_update_layout(struct inode *ino, | |||
641 | spin_unlock(&ino->i_lock); | 645 | spin_unlock(&ino->i_lock); |
642 | } | 646 | } |
643 | atomic_dec(&lo->plh_outstanding); | 647 | atomic_dec(&lo->plh_outstanding); |
644 | put_layout_hdr(ino); | 648 | put_layout_hdr(lo); |
645 | out: | 649 | out: |
646 | dprintk("%s end, state 0x%lx lseg %p\n", __func__, | 650 | dprintk("%s end, state 0x%lx lseg %p\n", __func__, |
647 | nfsi->layout->plh_flags, lseg); | 651 | nfsi->layout->plh_flags, lseg); |