|
@@ -560,6 +560,50 @@ filelayout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
|
|
|
return PNFS_ATTEMPTED;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
|
|
|
+ struct nfs4_filelayout_segment *fl,
|
|
|
+ gfp_t gfp_flags)
|
|
|
+{
|
|
|
+ struct nfs4_deviceid_node *d;
|
|
|
+ struct nfs4_file_layout_dsaddr *dsaddr;
|
|
|
+ int status = -EINVAL;
|
|
|
+
|
|
|
+ /* find and reference the deviceid */
|
|
|
+ d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid,
|
|
|
+ lo->plh_lc_cred, gfp_flags);
|
|
|
+ if (d == NULL)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
|
|
|
+ /* Found deviceid is unavailable */
|
|
|
+ if (filelayout_test_devid_unavailable(&dsaddr->id_node))
|
|
|
+ goto out_put;
|
|
|
+
|
|
|
+ fl->dsaddr = dsaddr;
|
|
|
+
|
|
|
+ if (fl->first_stripe_index >= dsaddr->stripe_count) {
|
|
|
+ dprintk("%s Bad first_stripe_index %u\n",
|
|
|
+ __func__, fl->first_stripe_index);
|
|
|
+ goto out_put;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((fl->stripe_type == STRIPE_SPARSE &&
|
|
|
+ fl->num_fh > 1 && fl->num_fh != dsaddr->ds_num) ||
|
|
|
+ (fl->stripe_type == STRIPE_DENSE &&
|
|
|
+ fl->num_fh != dsaddr->stripe_count)) {
|
|
|
+ dprintk("%s num_fh %u not valid for given packing\n",
|
|
|
+ __func__, fl->num_fh);
|
|
|
+ goto out_put;
|
|
|
+ }
|
|
|
+ status = 0;
|
|
|
+out:
|
|
|
+ return status;
|
|
|
+out_put:
|
|
|
+ nfs4_fl_put_deviceid(dsaddr);
|
|
|
+ goto out;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* filelayout_check_layout()
|
|
|
*
|
|
@@ -574,8 +618,6 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
|
|
|
struct nfs4_layoutget_res *lgr,
|
|
|
gfp_t gfp_flags)
|
|
|
{
|
|
|
- struct nfs4_deviceid_node *d;
|
|
|
- struct nfs4_file_layout_dsaddr *dsaddr;
|
|
|
int status = -EINVAL;
|
|
|
|
|
|
dprintk("--> %s\n", __func__);
|
|
@@ -600,41 +642,10 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /* find and reference the deviceid */
|
|
|
- d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid,
|
|
|
- lo->plh_lc_cred, gfp_flags);
|
|
|
- if (d == NULL)
|
|
|
- goto out;
|
|
|
-
|
|
|
- dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
|
|
|
- /* Found deviceid is unavailable */
|
|
|
- if (filelayout_test_devid_unavailable(&dsaddr->id_node))
|
|
|
- goto out_put;
|
|
|
-
|
|
|
- fl->dsaddr = dsaddr;
|
|
|
-
|
|
|
- if (fl->first_stripe_index >= dsaddr->stripe_count) {
|
|
|
- dprintk("%s Bad first_stripe_index %u\n",
|
|
|
- __func__, fl->first_stripe_index);
|
|
|
- goto out_put;
|
|
|
- }
|
|
|
-
|
|
|
- if ((fl->stripe_type == STRIPE_SPARSE &&
|
|
|
- fl->num_fh > 1 && fl->num_fh != dsaddr->ds_num) ||
|
|
|
- (fl->stripe_type == STRIPE_DENSE &&
|
|
|
- fl->num_fh != dsaddr->stripe_count)) {
|
|
|
- dprintk("%s num_fh %u not valid for given packing\n",
|
|
|
- __func__, fl->num_fh);
|
|
|
- goto out_put;
|
|
|
- }
|
|
|
-
|
|
|
status = 0;
|
|
|
out:
|
|
|
dprintk("--> %s returns %d\n", __func__, status);
|
|
|
return status;
|
|
|
-out_put:
|
|
|
- nfs4_fl_put_deviceid(dsaddr);
|
|
|
- goto out;
|
|
|
}
|
|
|
|
|
|
static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl)
|
|
@@ -885,18 +896,51 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
|
|
|
return min(stripe_unit - (unsigned int)stripe_offset, size);
|
|
|
}
|
|
|
|
|
|
+static struct pnfs_layout_segment *
|
|
|
+fl_pnfs_update_layout(struct inode *ino,
|
|
|
+ struct nfs_open_context *ctx,
|
|
|
+ loff_t pos,
|
|
|
+ u64 count,
|
|
|
+ enum pnfs_iomode iomode,
|
|
|
+ bool strict_iomode,
|
|
|
+ gfp_t gfp_flags)
|
|
|
+{
|
|
|
+ struct pnfs_layout_segment *lseg = NULL;
|
|
|
+ struct pnfs_layout_hdr *lo;
|
|
|
+ struct nfs4_filelayout_segment *fl;
|
|
|
+ int status;
|
|
|
+
|
|
|
+ lseg = pnfs_update_layout(ino, ctx, pos, count, iomode, strict_iomode,
|
|
|
+ gfp_flags);
|
|
|
+ if (!lseg)
|
|
|
+ lseg = ERR_PTR(-ENOMEM);
|
|
|
+ if (IS_ERR(lseg))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ lo = NFS_I(ino)->layout;
|
|
|
+ fl = FILELAYOUT_LSEG(lseg);
|
|
|
+
|
|
|
+ status = filelayout_check_deviceid(lo, fl, gfp_flags);
|
|
|
+ if (status)
|
|
|
+ lseg = ERR_PTR(status);
|
|
|
+out:
|
|
|
+ if (IS_ERR(lseg))
|
|
|
+ pnfs_put_lseg(lseg);
|
|
|
+ return lseg;
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
|
|
|
struct nfs_page *req)
|
|
|
{
|
|
|
if (!pgio->pg_lseg) {
|
|
|
- pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
|
|
|
- req->wb_context,
|
|
|
- 0,
|
|
|
- NFS4_MAX_UINT64,
|
|
|
- IOMODE_READ,
|
|
|
- false,
|
|
|
- GFP_KERNEL);
|
|
|
+ pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
|
|
|
+ req->wb_context,
|
|
|
+ 0,
|
|
|
+ NFS4_MAX_UINT64,
|
|
|
+ IOMODE_READ,
|
|
|
+ false,
|
|
|
+ GFP_KERNEL);
|
|
|
if (IS_ERR(pgio->pg_lseg)) {
|
|
|
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
|
|
|
pgio->pg_lseg = NULL;
|
|
@@ -916,13 +960,13 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
|
|
|
int status;
|
|
|
|
|
|
if (!pgio->pg_lseg) {
|
|
|
- pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
|
|
|
- req->wb_context,
|
|
|
- 0,
|
|
|
- NFS4_MAX_UINT64,
|
|
|
- IOMODE_RW,
|
|
|
- false,
|
|
|
- GFP_NOFS);
|
|
|
+ pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
|
|
|
+ req->wb_context,
|
|
|
+ 0,
|
|
|
+ NFS4_MAX_UINT64,
|
|
|
+ IOMODE_RW,
|
|
|
+ false,
|
|
|
+ GFP_NOFS);
|
|
|
if (IS_ERR(pgio->pg_lseg)) {
|
|
|
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
|
|
|
pgio->pg_lseg = NULL;
|