Skip to content

Commit

Permalink
NFSv4.1/pnfs: Allow pNFS device drivers to customise layout segment i…
Browse files Browse the repository at this point in the history
…nsertion

This is needed in order to allow merging of contiguous layout segments,
and also to correct the ordering of layouts for those device drivers that
don't necessarily want to place the read-write layouts first.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
  • Loading branch information
Trond Myklebust committed Aug 25, 2015
1 parent 540d986 commit 03772d2
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 9 deletions.
59 changes: 50 additions & 9 deletions fs/nfs/pnfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1188,16 +1188,41 @@ pnfs_lseg_range_cmp(const struct pnfs_layout_range *l1,
return (int)(l1->iomode == IOMODE_READ) - (int)(l2->iomode == IOMODE_READ);
}

static void
pnfs_layout_insert_lseg(struct pnfs_layout_hdr *lo,
struct pnfs_layout_segment *lseg)
static bool
pnfs_lseg_range_is_after(const struct pnfs_layout_range *l1,
const struct pnfs_layout_range *l2)
{
return pnfs_lseg_range_cmp(l1, l2) > 0;
}

static bool
pnfs_lseg_no_merge(struct pnfs_layout_segment *lseg,
struct pnfs_layout_segment *old)
{
return false;
}

void
pnfs_generic_layout_insert_lseg(struct pnfs_layout_hdr *lo,
struct pnfs_layout_segment *lseg,
bool (*is_after)(const struct pnfs_layout_range *,
const struct pnfs_layout_range *),
bool (*do_merge)(struct pnfs_layout_segment *,
struct pnfs_layout_segment *),
struct list_head *free_me)
{
struct pnfs_layout_segment *lp;
struct pnfs_layout_segment *lp, *tmp;

dprintk("%s:Begin\n", __func__);

list_for_each_entry(lp, &lo->plh_segs, pls_list) {
if (pnfs_lseg_range_cmp(&lseg->pls_range, &lp->pls_range) > 0)
list_for_each_entry_safe(lp, tmp, &lo->plh_segs, pls_list) {
if (test_bit(NFS_LSEG_VALID, &lp->pls_flags) == 0)
continue;
if (do_merge(lseg, lp)) {
mark_lseg_invalid(lp, free_me);
continue;
}
if (is_after(&lseg->pls_range, &lp->pls_range))
continue;
list_add_tail(&lseg->pls_list, &lp->pls_list);
dprintk("%s: inserted lseg %p "
Expand All @@ -1219,6 +1244,24 @@ pnfs_layout_insert_lseg(struct pnfs_layout_hdr *lo,

dprintk("%s:Return\n", __func__);
}
EXPORT_SYMBOL_GPL(pnfs_generic_layout_insert_lseg);

static void
pnfs_layout_insert_lseg(struct pnfs_layout_hdr *lo,
struct pnfs_layout_segment *lseg,
struct list_head *free_me)
{
struct inode *inode = lo->plh_inode;
struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;

if (ld->add_lseg != NULL)
ld->add_lseg(lo, lseg, free_me);
else
pnfs_generic_layout_insert_lseg(lo, lseg,
pnfs_lseg_range_is_after,
pnfs_lseg_no_merge,
free_me);
}

static struct pnfs_layout_hdr *
alloc_init_layout_hdr(struct inode *ino,
Expand Down Expand Up @@ -1311,8 +1354,6 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo,
ret = pnfs_get_lseg(lseg);
break;
}
if (lseg->pls_range.offset > range->offset)
break;
}

dprintk("%s:Return lseg %p ref %d\n",
Expand Down Expand Up @@ -1637,7 +1678,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
clear_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);

pnfs_get_lseg(lseg);
pnfs_layout_insert_lseg(lo, lseg);
pnfs_layout_insert_lseg(lo, lseg, &free_me);

if (res->return_on_close)
set_bit(NFS_LSEG_ROC, &lseg->pls_flags);
Expand Down
11 changes: 11 additions & 0 deletions fs/nfs/pnfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ struct pnfs_layoutdriver_type {

struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
void (*free_lseg) (struct pnfs_layout_segment *lseg);
void (*add_lseg) (struct pnfs_layout_hdr *layoutid,
struct pnfs_layout_segment *lseg,
struct list_head *free_me);

void (*return_range) (struct pnfs_layout_hdr *lo,
struct pnfs_layout_range *range);
Expand Down Expand Up @@ -285,6 +288,14 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
gfp_t gfp_flags);
void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo);

void pnfs_generic_layout_insert_lseg(struct pnfs_layout_hdr *lo,
struct pnfs_layout_segment *lseg,
bool (*is_after)(const struct pnfs_layout_range *lseg_range,
const struct pnfs_layout_range *old),
bool (*do_merge)(struct pnfs_layout_segment *lseg,
struct pnfs_layout_segment *old),
struct list_head *free_me);

void nfs4_deviceid_mark_client_invalid(struct nfs_client *clp);
int pnfs_read_done_resend_to_mds(struct nfs_pgio_header *);
int pnfs_write_done_resend_to_mds(struct nfs_pgio_header *);
Expand Down

0 comments on commit 03772d2

Please sign in to comment.