mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
NFSD/blocklayout: Extract extent mapping from proc_layoutget
No changes in functionality. Split the proc_layoutget function to create a helper function that maps single extent to the requested range. This helper function is then used to implement support for multiple extents per LAYOUTGET. Signed-off-by: Sergey Bashirov <sergeybashirov@gmail.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
committed by
Chuck Lever
parent
3524b021b0
commit
a1dce715c6
@@ -17,68 +17,44 @@
|
|||||||
#define NFSDDBG_FACILITY NFSDDBG_PNFS
|
#define NFSDDBG_FACILITY NFSDDBG_PNFS
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get an extent from the file system that starts at offset or below
|
||||||
|
* and may be shorter than the requested length.
|
||||||
|
*/
|
||||||
static __be32
|
static __be32
|
||||||
nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode,
|
nfsd4_block_map_extent(struct inode *inode, const struct svc_fh *fhp,
|
||||||
const struct svc_fh *fhp, struct nfsd4_layoutget *args)
|
u64 offset, u64 length, u32 iomode, u64 minlength,
|
||||||
|
struct pnfs_block_extent *bex)
|
||||||
{
|
{
|
||||||
struct nfsd4_layout_seg *seg = &args->lg_seg;
|
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
u64 length;
|
|
||||||
u32 block_size = i_blocksize(inode);
|
|
||||||
struct pnfs_block_extent *bex;
|
|
||||||
struct iomap iomap;
|
struct iomap iomap;
|
||||||
u32 device_generation = 0;
|
u32 device_generation = 0;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (locks_in_grace(SVC_NET(rqstp)))
|
error = sb->s_export_op->map_blocks(inode, offset, length, &iomap,
|
||||||
return nfserr_grace;
|
iomode != IOMODE_READ, &device_generation);
|
||||||
|
|
||||||
if (seg->offset & (block_size - 1)) {
|
|
||||||
dprintk("pnfsd: I/O misaligned\n");
|
|
||||||
goto out_layoutunavailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some clients barf on non-zero block numbers for NONE or INVALID
|
|
||||||
* layouts, so make sure to zero the whole structure.
|
|
||||||
*/
|
|
||||||
error = -ENOMEM;
|
|
||||||
bex = kzalloc(sizeof(*bex), GFP_KERNEL);
|
|
||||||
if (!bex)
|
|
||||||
goto out_error;
|
|
||||||
args->lg_content = bex;
|
|
||||||
|
|
||||||
error = sb->s_export_op->map_blocks(inode, seg->offset, seg->length,
|
|
||||||
&iomap, seg->iomode != IOMODE_READ,
|
|
||||||
&device_generation);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error == -ENXIO)
|
if (error == -ENXIO)
|
||||||
goto out_layoutunavailable;
|
return nfserr_layoutunavailable;
|
||||||
goto out_error;
|
return nfserrno(error);
|
||||||
}
|
|
||||||
|
|
||||||
length = iomap.offset + iomap.length - seg->offset;
|
|
||||||
if (length < args->lg_minlength) {
|
|
||||||
dprintk("pnfsd: extent smaller than minlength\n");
|
|
||||||
goto out_layoutunavailable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (iomap.type) {
|
switch (iomap.type) {
|
||||||
case IOMAP_MAPPED:
|
case IOMAP_MAPPED:
|
||||||
if (seg->iomode == IOMODE_READ)
|
if (iomode == IOMODE_READ)
|
||||||
bex->es = PNFS_BLOCK_READ_DATA;
|
bex->es = PNFS_BLOCK_READ_DATA;
|
||||||
else
|
else
|
||||||
bex->es = PNFS_BLOCK_READWRITE_DATA;
|
bex->es = PNFS_BLOCK_READWRITE_DATA;
|
||||||
bex->soff = iomap.addr;
|
bex->soff = iomap.addr;
|
||||||
break;
|
break;
|
||||||
case IOMAP_UNWRITTEN:
|
case IOMAP_UNWRITTEN:
|
||||||
if (seg->iomode & IOMODE_RW) {
|
if (iomode & IOMODE_RW) {
|
||||||
/*
|
/*
|
||||||
* Crack monkey special case from section 2.3.1.
|
* Crack monkey special case from section 2.3.1.
|
||||||
*/
|
*/
|
||||||
if (args->lg_minlength == 0) {
|
if (minlength == 0) {
|
||||||
dprintk("pnfsd: no soup for you!\n");
|
dprintk("pnfsd: no soup for you!\n");
|
||||||
goto out_layoutunavailable;
|
return nfserr_layoutunavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
bex->es = PNFS_BLOCK_INVALID_DATA;
|
bex->es = PNFS_BLOCK_INVALID_DATA;
|
||||||
@@ -87,7 +63,7 @@ nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode,
|
|||||||
}
|
}
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case IOMAP_HOLE:
|
case IOMAP_HOLE:
|
||||||
if (seg->iomode == IOMODE_READ) {
|
if (iomode == IOMODE_READ) {
|
||||||
bex->es = PNFS_BLOCK_NONE_DATA;
|
bex->es = PNFS_BLOCK_NONE_DATA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -95,27 +71,68 @@ nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode,
|
|||||||
case IOMAP_DELALLOC:
|
case IOMAP_DELALLOC:
|
||||||
default:
|
default:
|
||||||
WARN(1, "pnfsd: filesystem returned %d extent\n", iomap.type);
|
WARN(1, "pnfsd: filesystem returned %d extent\n", iomap.type);
|
||||||
goto out_layoutunavailable;
|
return nfserr_layoutunavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = nfsd4_set_deviceid(&bex->vol_id, fhp, device_generation);
|
error = nfsd4_set_deviceid(&bex->vol_id, fhp, device_generation);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_error;
|
return nfserrno(error);
|
||||||
|
|
||||||
bex->foff = iomap.offset;
|
bex->foff = iomap.offset;
|
||||||
bex->len = iomap.length;
|
bex->len = iomap.length;
|
||||||
|
return nfs_ok;
|
||||||
|
}
|
||||||
|
|
||||||
seg->offset = iomap.offset;
|
static __be32
|
||||||
seg->length = iomap.length;
|
nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode,
|
||||||
|
const struct svc_fh *fhp, struct nfsd4_layoutget *args)
|
||||||
|
{
|
||||||
|
struct nfsd4_layout_seg *seg = &args->lg_seg;
|
||||||
|
struct pnfs_block_extent *bex;
|
||||||
|
u64 length;
|
||||||
|
u32 block_size = i_blocksize(inode);
|
||||||
|
__be32 nfserr;
|
||||||
|
|
||||||
|
if (locks_in_grace(SVC_NET(rqstp)))
|
||||||
|
return nfserr_grace;
|
||||||
|
|
||||||
|
nfserr = nfserr_layoutunavailable;
|
||||||
|
if (seg->offset & (block_size - 1)) {
|
||||||
|
dprintk("pnfsd: I/O misaligned\n");
|
||||||
|
goto out_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some clients barf on non-zero block numbers for NONE or INVALID
|
||||||
|
* layouts, so make sure to zero the whole structure.
|
||||||
|
*/
|
||||||
|
nfserr = nfserrno(-ENOMEM);
|
||||||
|
bex = kzalloc(sizeof(*bex), GFP_KERNEL);
|
||||||
|
if (!bex)
|
||||||
|
goto out_error;
|
||||||
|
args->lg_content = bex;
|
||||||
|
|
||||||
|
nfserr = nfsd4_block_map_extent(inode, fhp, seg->offset, seg->length,
|
||||||
|
seg->iomode, args->lg_minlength, bex);
|
||||||
|
if (nfserr != nfs_ok)
|
||||||
|
goto out_error;
|
||||||
|
|
||||||
|
nfserr = nfserr_layoutunavailable;
|
||||||
|
length = bex->foff + bex->len - seg->offset;
|
||||||
|
if (length < args->lg_minlength) {
|
||||||
|
dprintk("pnfsd: extent smaller than minlength\n");
|
||||||
|
goto out_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
seg->offset = bex->foff;
|
||||||
|
seg->length = bex->len;
|
||||||
|
|
||||||
dprintk("GET: 0x%llx:0x%llx %d\n", bex->foff, bex->len, bex->es);
|
dprintk("GET: 0x%llx:0x%llx %d\n", bex->foff, bex->len, bex->es);
|
||||||
return 0;
|
return nfs_ok;
|
||||||
|
|
||||||
out_error:
|
out_error:
|
||||||
seg->length = 0;
|
seg->length = 0;
|
||||||
return nfserrno(error);
|
return nfserr;
|
||||||
out_layoutunavailable:
|
|
||||||
seg->length = 0;
|
|
||||||
return nfserr_layoutunavailable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __be32
|
static __be32
|
||||||
|
|||||||
Reference in New Issue
Block a user