Blame view
fs/nfsd/blocklayoutxdr.c
5.15 KB
8650b8a05 nfsd: pNFS block ... |
1 |
/* |
f99d4fbda nfsd: add SCSI la... |
2 |
* Copyright (c) 2014-2016 Christoph Hellwig. |
8650b8a05 nfsd: pNFS block ... |
3 4 5 |
*/ #include <linux/sunrpc/svc.h> #include <linux/exportfs.h> |
199a31c6d fs: move struct i... |
6 |
#include <linux/iomap.h> |
8650b8a05 nfsd: pNFS block ... |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#include <linux/nfs4.h> #include "nfsd.h" #include "blocklayoutxdr.h" #define NFSDDBG_FACILITY NFSDDBG_PNFS __be32 nfsd4_block_encode_layoutget(struct xdr_stream *xdr, struct nfsd4_layoutget *lgp) { struct pnfs_block_extent *b = lgp->lg_content; int len = sizeof(__be32) + 5 * sizeof(__be64) + sizeof(__be32); __be32 *p; p = xdr_reserve_space(xdr, sizeof(__be32) + len); if (!p) return nfserr_toosmall; *p++ = cpu_to_be32(len); *p++ = cpu_to_be32(1); /* we always return a single extent */ p = xdr_encode_opaque_fixed(p, &b->vol_id, sizeof(struct nfsd4_deviceid)); p = xdr_encode_hyper(p, b->foff); p = xdr_encode_hyper(p, b->len); p = xdr_encode_hyper(p, b->soff); *p++ = cpu_to_be32(b->es); return 0; } static int nfsd4_block_encode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b) { __be32 *p; int len; switch (b->type) { case PNFS_BLOCK_VOLUME_SIMPLE: |
dd51db188 nfsd/blocklayout:... |
47 |
len = 4 + 4 + 8 + 4 + (XDR_QUADLEN(b->simple.sig_len) << 2); |
8650b8a05 nfsd: pNFS block ... |
48 49 50 51 52 53 54 55 56 |
p = xdr_reserve_space(xdr, len); if (!p) return -ETOOSMALL; *p++ = cpu_to_be32(b->type); *p++ = cpu_to_be32(1); /* single signature */ p = xdr_encode_hyper(p, b->simple.offset); p = xdr_encode_opaque(p, b->simple.sig, b->simple.sig_len); break; |
f99d4fbda nfsd: add SCSI la... |
57 |
case PNFS_BLOCK_VOLUME_SCSI: |
dd51db188 nfsd/blocklayout:... |
58 |
len = 4 + 4 + 4 + 4 + (XDR_QUADLEN(b->scsi.designator_len) << 2) + 8; |
f99d4fbda nfsd: add SCSI la... |
59 60 61 62 63 64 65 66 67 68 |
p = xdr_reserve_space(xdr, len); if (!p) return -ETOOSMALL; *p++ = cpu_to_be32(b->type); *p++ = cpu_to_be32(b->scsi.code_set); *p++ = cpu_to_be32(b->scsi.designator_type); p = xdr_encode_opaque(p, b->scsi.designator, b->scsi.designator_len); p = xdr_encode_hyper(p, b->scsi.pr_key); break; |
8650b8a05 nfsd: pNFS block ... |
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
default: return -ENOTSUPP; } return len; } __be32 nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr, struct nfsd4_getdeviceinfo *gdp) { struct pnfs_block_deviceaddr *dev = gdp->gd_device; int len = sizeof(__be32), ret, i; __be32 *p; p = xdr_reserve_space(xdr, len + sizeof(__be32)); if (!p) return nfserr_resource; for (i = 0; i < dev->nr_volumes; i++) { ret = nfsd4_block_encode_volume(xdr, &dev->volumes[i]); if (ret < 0) return nfserrno(ret); len += ret; } /* * Fill in the overall length and number of volumes at the beginning * of the layout. */ *p++ = cpu_to_be32(len); *p++ = cpu_to_be32(dev->nr_volumes); return 0; } int nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, u32 block_size) { struct iomap *iomaps; |
4b15da44e nfsd: better layo... |
109 |
u32 nr_iomaps, i; |
8650b8a05 nfsd: pNFS block ... |
110 111 112 113 114 115 |
if (len < sizeof(u32)) { dprintk("%s: extent array too small: %u ", __func__, len); return -EINVAL; } |
4b15da44e nfsd: better layo... |
116 117 118 119 120 121 |
len -= sizeof(u32); if (len % PNFS_BLOCK_EXTENT_SIZE) { dprintk("%s: extent array invalid: %u ", __func__, len); return -EINVAL; } |
8650b8a05 nfsd: pNFS block ... |
122 123 |
nr_iomaps = be32_to_cpup(p++); |
4b15da44e nfsd: better layo... |
124 |
if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE) { |
8650b8a05 nfsd: pNFS block ... |
125 126 |
dprintk("%s: extent array size mismatch: %u/%u ", |
4b15da44e nfsd: better layo... |
127 |
__func__, len, nr_iomaps); |
8650b8a05 nfsd: pNFS block ... |
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
return -EINVAL; } iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL); if (!iomaps) { dprintk("%s: failed to allocate extent array ", __func__); return -ENOMEM; } for (i = 0; i < nr_iomaps; i++) { struct pnfs_block_extent bex; memcpy(&bex.vol_id, p, sizeof(struct nfsd4_deviceid)); p += XDR_QUADLEN(sizeof(struct nfsd4_deviceid)); p = xdr_decode_hyper(p, &bex.foff); if (bex.foff & (block_size - 1)) { |
853695230 NFSD: Printk bloc... |
146 147 |
dprintk("%s: unaligned offset 0x%llx ", |
8650b8a05 nfsd: pNFS block ... |
148 149 150 151 152 |
__func__, bex.foff); goto fail; } p = xdr_decode_hyper(p, &bex.len); if (bex.len & (block_size - 1)) { |
853695230 NFSD: Printk bloc... |
153 154 |
dprintk("%s: unaligned length 0x%llx ", |
8650b8a05 nfsd: pNFS block ... |
155 156 157 158 159 |
__func__, bex.foff); goto fail; } p = xdr_decode_hyper(p, &bex.soff); if (bex.soff & (block_size - 1)) { |
853695230 NFSD: Printk bloc... |
160 161 |
dprintk("%s: unaligned disk offset 0x%llx ", |
8650b8a05 nfsd: pNFS block ... |
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
__func__, bex.soff); goto fail; } bex.es = be32_to_cpup(p++); if (bex.es != PNFS_BLOCK_READWRITE_DATA) { dprintk("%s: incorrect extent state %d ", __func__, bex.es); goto fail; } iomaps[i].offset = bex.foff; iomaps[i].length = bex.len; } *iomapp = iomaps; return nr_iomaps; fail: kfree(iomaps); return -EINVAL; } |
f99d4fbda nfsd: add SCSI la... |
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
int nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, u32 block_size) { struct iomap *iomaps; u32 nr_iomaps, expected, i; if (len < sizeof(u32)) { dprintk("%s: extent array too small: %u ", __func__, len); return -EINVAL; } nr_iomaps = be32_to_cpup(p++); expected = sizeof(__be32) + nr_iomaps * PNFS_SCSI_RANGE_SIZE; if (len != expected) { dprintk("%s: extent array size mismatch: %u/%u ", __func__, len, expected); return -EINVAL; } iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL); if (!iomaps) { dprintk("%s: failed to allocate extent array ", __func__); return -ENOMEM; } for (i = 0; i < nr_iomaps; i++) { u64 val; p = xdr_decode_hyper(p, &val); if (val & (block_size - 1)) { dprintk("%s: unaligned offset 0x%llx ", __func__, val); goto fail; } iomaps[i].offset = val; p = xdr_decode_hyper(p, &val); if (val & (block_size - 1)) { dprintk("%s: unaligned length 0x%llx ", __func__, val); goto fail; } iomaps[i].length = val; } *iomapp = iomaps; return nr_iomaps; fail: kfree(iomaps); return -EINVAL; } |