Skip to content

Commit a1dce71

Browse files
sbashirochucklever
authored andcommitted
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>
1 parent 3524b02 commit a1dce71

1 file changed

Lines changed: 66 additions & 49 deletions

File tree

fs/nfsd/blocklayout.c

Lines changed: 66 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,68 +17,44 @@
1717
#define NFSDDBG_FACILITY NFSDDBG_PNFS
1818

1919

20+
/*
21+
* Get an extent from the file system that starts at offset or below
22+
* and may be shorter than the requested length.
23+
*/
2024
static __be32
21-
nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode,
22-
const struct svc_fh *fhp, struct nfsd4_layoutget *args)
25+
nfsd4_block_map_extent(struct inode *inode, const struct svc_fh *fhp,
26+
u64 offset, u64 length, u32 iomode, u64 minlength,
27+
struct pnfs_block_extent *bex)
2328
{
24-
struct nfsd4_layout_seg *seg = &args->lg_seg;
2529
struct super_block *sb = inode->i_sb;
26-
u64 length;
27-
u32 block_size = i_blocksize(inode);
28-
struct pnfs_block_extent *bex;
2930
struct iomap iomap;
3031
u32 device_generation = 0;
3132
int error;
3233

33-
if (locks_in_grace(SVC_NET(rqstp)))
34-
return nfserr_grace;
35-
36-
if (seg->offset & (block_size - 1)) {
37-
dprintk("pnfsd: I/O misaligned\n");
38-
goto out_layoutunavailable;
39-
}
40-
41-
/*
42-
* Some clients barf on non-zero block numbers for NONE or INVALID
43-
* layouts, so make sure to zero the whole structure.
44-
*/
45-
error = -ENOMEM;
46-
bex = kzalloc(sizeof(*bex), GFP_KERNEL);
47-
if (!bex)
48-
goto out_error;
49-
args->lg_content = bex;
50-
51-
error = sb->s_export_op->map_blocks(inode, seg->offset, seg->length,
52-
&iomap, seg->iomode != IOMODE_READ,
53-
&device_generation);
34+
error = sb->s_export_op->map_blocks(inode, offset, length, &iomap,
35+
iomode != IOMODE_READ, &device_generation);
5436
if (error) {
5537
if (error == -ENXIO)
56-
goto out_layoutunavailable;
57-
goto out_error;
58-
}
59-
60-
length = iomap.offset + iomap.length - seg->offset;
61-
if (length < args->lg_minlength) {
62-
dprintk("pnfsd: extent smaller than minlength\n");
63-
goto out_layoutunavailable;
38+
return nfserr_layoutunavailable;
39+
return nfserrno(error);
6440
}
6541

6642
switch (iomap.type) {
6743
case IOMAP_MAPPED:
68-
if (seg->iomode == IOMODE_READ)
44+
if (iomode == IOMODE_READ)
6945
bex->es = PNFS_BLOCK_READ_DATA;
7046
else
7147
bex->es = PNFS_BLOCK_READWRITE_DATA;
7248
bex->soff = iomap.addr;
7349
break;
7450
case IOMAP_UNWRITTEN:
75-
if (seg->iomode & IOMODE_RW) {
51+
if (iomode & IOMODE_RW) {
7652
/*
7753
* Crack monkey special case from section 2.3.1.
7854
*/
79-
if (args->lg_minlength == 0) {
55+
if (minlength == 0) {
8056
dprintk("pnfsd: no soup for you!\n");
81-
goto out_layoutunavailable;
57+
return nfserr_layoutunavailable;
8258
}
8359

8460
bex->es = PNFS_BLOCK_INVALID_DATA;
@@ -87,35 +63,76 @@ nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode,
8763
}
8864
fallthrough;
8965
case IOMAP_HOLE:
90-
if (seg->iomode == IOMODE_READ) {
66+
if (iomode == IOMODE_READ) {
9167
bex->es = PNFS_BLOCK_NONE_DATA;
9268
break;
9369
}
9470
fallthrough;
9571
case IOMAP_DELALLOC:
9672
default:
9773
WARN(1, "pnfsd: filesystem returned %d extent\n", iomap.type);
98-
goto out_layoutunavailable;
74+
return nfserr_layoutunavailable;
9975
}
10076

10177
error = nfsd4_set_deviceid(&bex->vol_id, fhp, device_generation);
10278
if (error)
103-
goto out_error;
79+
return nfserrno(error);
80+
10481
bex->foff = iomap.offset;
10582
bex->len = iomap.length;
83+
return nfs_ok;
84+
}
85+
86+
static __be32
87+
nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode,
88+
const struct svc_fh *fhp, struct nfsd4_layoutget *args)
89+
{
90+
struct nfsd4_layout_seg *seg = &args->lg_seg;
91+
struct pnfs_block_extent *bex;
92+
u64 length;
93+
u32 block_size = i_blocksize(inode);
94+
__be32 nfserr;
95+
96+
if (locks_in_grace(SVC_NET(rqstp)))
97+
return nfserr_grace;
10698

107-
seg->offset = iomap.offset;
108-
seg->length = iomap.length;
99+
nfserr = nfserr_layoutunavailable;
100+
if (seg->offset & (block_size - 1)) {
101+
dprintk("pnfsd: I/O misaligned\n");
102+
goto out_error;
103+
}
104+
105+
/*
106+
* Some clients barf on non-zero block numbers for NONE or INVALID
107+
* layouts, so make sure to zero the whole structure.
108+
*/
109+
nfserr = nfserrno(-ENOMEM);
110+
bex = kzalloc(sizeof(*bex), GFP_KERNEL);
111+
if (!bex)
112+
goto out_error;
113+
args->lg_content = bex;
114+
115+
nfserr = nfsd4_block_map_extent(inode, fhp, seg->offset, seg->length,
116+
seg->iomode, args->lg_minlength, bex);
117+
if (nfserr != nfs_ok)
118+
goto out_error;
119+
120+
nfserr = nfserr_layoutunavailable;
121+
length = bex->foff + bex->len - seg->offset;
122+
if (length < args->lg_minlength) {
123+
dprintk("pnfsd: extent smaller than minlength\n");
124+
goto out_error;
125+
}
126+
127+
seg->offset = bex->foff;
128+
seg->length = bex->len;
109129

110130
dprintk("GET: 0x%llx:0x%llx %d\n", bex->foff, bex->len, bex->es);
111-
return 0;
131+
return nfs_ok;
112132

113133
out_error:
114134
seg->length = 0;
115-
return nfserrno(error);
116-
out_layoutunavailable:
117-
seg->length = 0;
118-
return nfserr_layoutunavailable;
135+
return nfserr;
119136
}
120137

121138
static __be32

0 commit comments

Comments
 (0)