Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sergey Bashirov and committed by
Chuck Lever
a1dce715 3524b021

+66 -49
+66 -49
fs/nfsd/blocklayout.c
··· 17 17 #define NFSDDBG_FACILITY NFSDDBG_PNFS 18 18 19 19 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 + */ 20 24 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) 23 28 { 24 - struct nfsd4_layout_seg *seg = &args->lg_seg; 25 29 struct super_block *sb = inode->i_sb; 26 - u64 length; 27 - u32 block_size = i_blocksize(inode); 28 - struct pnfs_block_extent *bex; 29 30 struct iomap iomap; 30 31 u32 device_generation = 0; 31 32 int error; 32 33 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); 54 36 if (error) { 55 37 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); 64 40 } 65 41 66 42 switch (iomap.type) { 67 43 case IOMAP_MAPPED: 68 - if (seg->iomode == IOMODE_READ) 44 + if (iomode == IOMODE_READ) 69 45 bex->es = PNFS_BLOCK_READ_DATA; 70 46 else 71 47 bex->es = PNFS_BLOCK_READWRITE_DATA; 72 48 bex->soff = iomap.addr; 73 49 break; 74 50 case IOMAP_UNWRITTEN: 75 - if (seg->iomode & IOMODE_RW) { 51 + if (iomode & IOMODE_RW) { 76 52 /* 77 53 * Crack monkey special case from section 2.3.1. 78 54 */ 79 - if (args->lg_minlength == 0) { 55 + if (minlength == 0) { 80 56 dprintk("pnfsd: no soup for you!\n"); 81 - goto out_layoutunavailable; 57 + return nfserr_layoutunavailable; 82 58 } 83 59 84 60 bex->es = PNFS_BLOCK_INVALID_DATA; ··· 63 87 } 64 88 fallthrough; 65 89 case IOMAP_HOLE: 66 - if (seg->iomode == IOMODE_READ) { 90 + if (iomode == IOMODE_READ) { 67 91 bex->es = PNFS_BLOCK_NONE_DATA; 68 92 break; 69 93 } ··· 71 95 case IOMAP_DELALLOC: 72 96 default: 73 97 WARN(1, "pnfsd: filesystem returned %d extent\n", iomap.type); 74 - goto out_layoutunavailable; 98 + return nfserr_layoutunavailable; 75 99 } 76 100 77 101 error = nfsd4_set_deviceid(&bex->vol_id, fhp, device_generation); 78 102 if (error) 79 - goto out_error; 103 + return nfserrno(error); 104 + 80 105 bex->foff = iomap.offset; 81 106 bex->len = iomap.length; 107 + return nfs_ok; 108 + } 82 109 83 - seg->offset = iomap.offset; 84 - seg->length = iomap.length; 110 + static __be32 111 + nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode, 112 + const struct svc_fh *fhp, struct nfsd4_layoutget *args) 113 + { 114 + struct nfsd4_layout_seg *seg = &args->lg_seg; 115 + struct pnfs_block_extent *bex; 116 + u64 length; 117 + u32 block_size = i_blocksize(inode); 118 + __be32 nfserr; 119 + 120 + if (locks_in_grace(SVC_NET(rqstp))) 121 + return nfserr_grace; 122 + 123 + nfserr = nfserr_layoutunavailable; 124 + if (seg->offset & (block_size - 1)) { 125 + dprintk("pnfsd: I/O misaligned\n"); 126 + goto out_error; 127 + } 128 + 129 + /* 130 + * Some clients barf on non-zero block numbers for NONE or INVALID 131 + * layouts, so make sure to zero the whole structure. 132 + */ 133 + nfserr = nfserrno(-ENOMEM); 134 + bex = kzalloc(sizeof(*bex), GFP_KERNEL); 135 + if (!bex) 136 + goto out_error; 137 + args->lg_content = bex; 138 + 139 + nfserr = nfsd4_block_map_extent(inode, fhp, seg->offset, seg->length, 140 + seg->iomode, args->lg_minlength, bex); 141 + if (nfserr != nfs_ok) 142 + goto out_error; 143 + 144 + nfserr = nfserr_layoutunavailable; 145 + length = bex->foff + bex->len - seg->offset; 146 + if (length < args->lg_minlength) { 147 + dprintk("pnfsd: extent smaller than minlength\n"); 148 + goto out_error; 149 + } 150 + 151 + seg->offset = bex->foff; 152 + seg->length = bex->len; 85 153 86 154 dprintk("GET: 0x%llx:0x%llx %d\n", bex->foff, bex->len, bex->es); 87 - return 0; 155 + return nfs_ok; 88 156 89 157 out_error: 90 158 seg->length = 0; 91 - return nfserrno(error); 92 - out_layoutunavailable: 93 - seg->length = 0; 94 - return nfserr_layoutunavailable; 159 + return nfserr; 95 160 } 96 161 97 162 static __be32