This is in order to prepare for the forgetful client. There is no need to explicitly count the number of outstanding layout operations, as the protocol has provision for it (seqid of stateid -- e.g. section 12.5.5.2.1.2). As long as no requests for intersecting layouts are issued, LAYOUTGETs/LAYOUTRETURNs can be sent in parallel Signed-off-by: Alexandros Batsakis <batsakis@xxxxxxxxxx> --- fs/nfs/nfs4proc.c | 5 ++--- fs/nfs/pnfs.c | 46 ++++++++++++---------------------------------- fs/nfs/pnfs.h | 3 +-- include/linux/nfs_fs.h | 2 -- 4 files changed, 15 insertions(+), 41 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index df908be..a8a6ad2 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5501,7 +5501,7 @@ static void nfs4_pnfs_layoutget_release(void *calldata) struct nfs4_pnfs_layoutget *lgp = calldata; dprintk("--> %s\n", __func__); - pnfs_layout_release(lgp->lo, &lgp->lo->lgetcount, NULL); + pnfs_layout_release(lgp->lo, NULL); if (lgp->res.layout.buf != NULL) free_page((unsigned long) lgp->res.layout.buf); kfree(calldata); @@ -5722,8 +5722,7 @@ static void nfs4_pnfs_layoutreturn_release(void *calldata) if (lrp->lo && (lrp->args.return_type == RETURN_FILE)) { if (!lrp->res.lrs_present) pnfs_set_layout_stateid(lrp->lo, &zero_stateid); - pnfs_layout_release(lrp->lo, &lrp->lo->lretcount, - &lrp->args.lseg); + pnfs_layout_release(lrp->lo, &lrp->args.lseg); } kfree(calldata); dprintk("<-- %s\n", __func__); diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 74cb998..b2d203f 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -375,7 +375,7 @@ out: } void -pnfs_layout_release(struct pnfs_layout_type *lo, atomic_t *count, +pnfs_layout_release(struct pnfs_layout_type *lo, struct nfs4_pnfs_layout_segment *range) { struct nfs_inode *nfsi = PNFS_NFS_INODE(lo); @@ -383,7 +383,6 @@ pnfs_layout_release(struct pnfs_layout_type *lo, atomic_t *count, lock_current_layout(nfsi); if (range) pnfs_free_layout(lo, range); - atomic_dec(count); put_unlock_current_layout(lo); wake_up_all(&nfsi->lo_waitq); } @@ -568,7 +567,7 @@ get_layout(struct inode *ino, lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); if (lgp == NULL) { - pnfs_layout_release(lo, &lo->lgetcount, NULL); + pnfs_layout_release(lo, NULL); return -ENOMEM; } lgp->lo = lo; @@ -642,6 +641,13 @@ has_layout_to_return(struct pnfs_layout_type *lo, return out; } +static inline bool +_pnfs_can_return_lseg(struct pnfs_layout_segment *lseg) +{ + return atomic_read(&lseg->kref.refcount) == 1; +} + + static void pnfs_free_layout(struct pnfs_layout_type *lo, struct nfs4_pnfs_layout_segment *range) @@ -652,7 +658,8 @@ pnfs_free_layout(struct pnfs_layout_type *lo, BUG_ON_UNLOCKED_LO(lo); list_for_each_entry_safe (lseg, next, &lo->segs, fi_list) { - if (!should_free_lseg(lseg, range)) + if (!should_free_lseg(lseg, range) || + !_pnfs_can_return_lseg(lseg)) continue; dprintk("%s: freeing lseg %p iomode %d " "offset %llu length %llu\n", __func__, @@ -665,12 +672,6 @@ pnfs_free_layout(struct pnfs_layout_type *lo, dprintk("%s:Return\n", __func__); } -static inline bool -_pnfs_can_return_lseg(struct pnfs_layout_segment *lseg) -{ - return atomic_read(&lseg->kref.refcount) == 1; -} - static bool pnfs_return_layout_barrier(struct nfs_inode *nfsi, struct nfs4_pnfs_layout_segment *range) @@ -690,8 +691,6 @@ pnfs_return_layout_barrier(struct nfs_inode *nfsi, ret = true; } } - if (atomic_read(&nfsi->layout.lgetcount)) - ret = true; unlock_current_layout(nfsi); dprintk("%s:Return %d\n", __func__, ret); @@ -712,7 +711,7 @@ return_layout(struct inode *ino, struct nfs4_pnfs_layout_segment *range, lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); if (lrp == NULL) { if (lo && (type == RETURN_FILE)) - pnfs_layout_release(lo, &lo->lretcount, NULL); + pnfs_layout_release(lo, NULL); goto out; } lrp->args.reclaim = 0; @@ -776,9 +775,6 @@ _pnfs_return_layout(struct inode *ino, struct nfs4_pnfs_layout_segment *range, goto out; } - /* Matching dec is done in .rpc_release (on non-error paths) */ - atomic_inc(&lo->lretcount); - /* unlock w/o put rebalanced by eventual call to * pnfs_layout_release */ @@ -893,8 +889,6 @@ alloc_init_layout(struct inode *ino) seqlock_init(&lo->seqlock); memset(&lo->stateid, 0, NFS4_STATEID_SIZE); lo->refcount = 1; - atomic_set(&lo->lgetcount, 0); - atomic_set(&lo->lretcount, 0); INIT_LIST_HEAD(&lo->segs); lo->roc_iomode = 0; return lo; @@ -1058,19 +1052,6 @@ pnfs_find_get_lseg(struct inode *inode, return lseg; } -/* Called with spin lock held */ -void drain_layoutreturns(struct pnfs_layout_type *lo) -{ - while (atomic_read(&lo->lretcount)) { - struct nfs_inode *nfsi = PNFS_NFS_INODE(lo); - - unlock_current_layout(nfsi); - dprintk("%s: waiting\n", __func__); - wait_event(nfsi->lo_waitq, (atomic_read(&lo->lretcount) == 0)); - lock_current_layout(nfsi); - } -} - /* Update the file's layout for the given range and iomode. * Layout is retreived from the server if needed. * If lsegpp is given, the appropriate layout segment is referenced and @@ -1158,9 +1139,6 @@ pnfs_update_layout(struct inode *ino, } } - drain_layoutreturns(lo); - /* Matching dec is done in .rpc_release (on non-error paths) */ - atomic_inc(&lo->lgetcount); /* Lose lock, but not reference, match this with pnfs_layout_release */ unlock_current_layout(nfsi); diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 8318112..9e43973 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -71,8 +71,7 @@ void pnfs_free_fsdata(struct pnfs_fsdata *fsdata); ssize_t pnfs_file_write(struct file *, const char __user *, size_t, loff_t *); void pnfs_get_layout_done(struct nfs4_pnfs_layoutget *, int rpc_status); int pnfs_layout_process(struct nfs4_pnfs_layoutget *lgp); -void pnfs_layout_release(struct pnfs_layout_type *, atomic_t *, - struct nfs4_pnfs_layout_segment *range); +void pnfs_layout_release(struct pnfs_layout_type *, struct nfs4_pnfs_layout_segment *range); void pnfs_set_layout_stateid(struct pnfs_layout_type *lo, const nfs4_stateid *stateid); void pnfs_destroy_layout(struct nfs_inode *); diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 5048b97..2434bba 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -99,8 +99,6 @@ struct posix_acl; struct pnfs_layout_type { int refcount; - atomic_t lretcount; /* Layoutreturns outstanding */ - atomic_t lgetcount; /* Layoutgets outstanding */ struct list_head segs; /* layout segments list */ int roc_iomode; /* iomode to return on close, 0=none */ seqlock_t seqlock; /* Protects the stateid */ -- 1.6.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html