2 * Copyright (c) 2014-2016 Christoph Hellwig.
4 #include <linux/sunrpc/svc.h>
5 #include <linux/exportfs.h>
6 #include <linux/nfs4.h>
9 #include "blocklayoutxdr.h"
11 #define NFSDDBG_FACILITY NFSDDBG_PNFS
15 nfsd4_block_encode_layoutget(struct xdr_stream
*xdr
,
16 struct nfsd4_layoutget
*lgp
)
18 struct pnfs_block_extent
*b
= lgp
->lg_content
;
19 int len
= sizeof(__be32
) + 5 * sizeof(__be64
) + sizeof(__be32
);
22 p
= xdr_reserve_space(xdr
, sizeof(__be32
) + len
);
24 return nfserr_toosmall
;
26 *p
++ = cpu_to_be32(len
);
27 *p
++ = cpu_to_be32(1); /* we always return a single extent */
29 p
= xdr_encode_opaque_fixed(p
, &b
->vol_id
,
30 sizeof(struct nfsd4_deviceid
));
31 p
= xdr_encode_hyper(p
, b
->foff
);
32 p
= xdr_encode_hyper(p
, b
->len
);
33 p
= xdr_encode_hyper(p
, b
->soff
);
34 *p
++ = cpu_to_be32(b
->es
);
39 nfsd4_block_encode_volume(struct xdr_stream
*xdr
, struct pnfs_block_volume
*b
)
45 case PNFS_BLOCK_VOLUME_SIMPLE
:
46 len
= 4 + 4 + 8 + 4 + b
->simple
.sig_len
;
47 p
= xdr_reserve_space(xdr
, len
);
51 *p
++ = cpu_to_be32(b
->type
);
52 *p
++ = cpu_to_be32(1); /* single signature */
53 p
= xdr_encode_hyper(p
, b
->simple
.offset
);
54 p
= xdr_encode_opaque(p
, b
->simple
.sig
, b
->simple
.sig_len
);
56 case PNFS_BLOCK_VOLUME_SCSI
:
57 len
= 4 + 4 + 4 + 4 + b
->scsi
.designator_len
+ 8;
58 p
= xdr_reserve_space(xdr
, len
);
62 *p
++ = cpu_to_be32(b
->type
);
63 *p
++ = cpu_to_be32(b
->scsi
.code_set
);
64 *p
++ = cpu_to_be32(b
->scsi
.designator_type
);
65 p
= xdr_encode_opaque(p
, b
->scsi
.designator
, b
->scsi
.designator_len
);
66 p
= xdr_encode_hyper(p
, b
->scsi
.pr_key
);
76 nfsd4_block_encode_getdeviceinfo(struct xdr_stream
*xdr
,
77 struct nfsd4_getdeviceinfo
*gdp
)
79 struct pnfs_block_deviceaddr
*dev
= gdp
->gd_device
;
80 int len
= sizeof(__be32
), ret
, i
;
83 p
= xdr_reserve_space(xdr
, len
+ sizeof(__be32
));
85 return nfserr_resource
;
87 for (i
= 0; i
< dev
->nr_volumes
; i
++) {
88 ret
= nfsd4_block_encode_volume(xdr
, &dev
->volumes
[i
]);
95 * Fill in the overall length and number of volumes at the beginning
98 *p
++ = cpu_to_be32(len
);
99 *p
++ = cpu_to_be32(dev
->nr_volumes
);
104 nfsd4_block_decode_layoutupdate(__be32
*p
, u32 len
, struct iomap
**iomapp
,
107 struct iomap
*iomaps
;
108 u32 nr_iomaps
, expected
, i
;
110 if (len
< sizeof(u32
)) {
111 dprintk("%s: extent array too small: %u\n", __func__
, len
);
115 nr_iomaps
= be32_to_cpup(p
++);
116 expected
= sizeof(__be32
) + nr_iomaps
* PNFS_BLOCK_EXTENT_SIZE
;
117 if (len
!= expected
) {
118 dprintk("%s: extent array size mismatch: %u/%u\n",
119 __func__
, len
, expected
);
123 iomaps
= kcalloc(nr_iomaps
, sizeof(*iomaps
), GFP_KERNEL
);
125 dprintk("%s: failed to allocate extent array\n", __func__
);
129 for (i
= 0; i
< nr_iomaps
; i
++) {
130 struct pnfs_block_extent bex
;
132 memcpy(&bex
.vol_id
, p
, sizeof(struct nfsd4_deviceid
));
133 p
+= XDR_QUADLEN(sizeof(struct nfsd4_deviceid
));
135 p
= xdr_decode_hyper(p
, &bex
.foff
);
136 if (bex
.foff
& (block_size
- 1)) {
137 dprintk("%s: unaligned offset 0x%llx\n",
141 p
= xdr_decode_hyper(p
, &bex
.len
);
142 if (bex
.len
& (block_size
- 1)) {
143 dprintk("%s: unaligned length 0x%llx\n",
147 p
= xdr_decode_hyper(p
, &bex
.soff
);
148 if (bex
.soff
& (block_size
- 1)) {
149 dprintk("%s: unaligned disk offset 0x%llx\n",
153 bex
.es
= be32_to_cpup(p
++);
154 if (bex
.es
!= PNFS_BLOCK_READWRITE_DATA
) {
155 dprintk("%s: incorrect extent state %d\n",
160 iomaps
[i
].offset
= bex
.foff
;
161 iomaps
[i
].length
= bex
.len
;
172 nfsd4_scsi_decode_layoutupdate(__be32
*p
, u32 len
, struct iomap
**iomapp
,
175 struct iomap
*iomaps
;
176 u32 nr_iomaps
, expected
, i
;
178 if (len
< sizeof(u32
)) {
179 dprintk("%s: extent array too small: %u\n", __func__
, len
);
183 nr_iomaps
= be32_to_cpup(p
++);
184 expected
= sizeof(__be32
) + nr_iomaps
* PNFS_SCSI_RANGE_SIZE
;
185 if (len
!= expected
) {
186 dprintk("%s: extent array size mismatch: %u/%u\n",
187 __func__
, len
, expected
);
191 iomaps
= kcalloc(nr_iomaps
, sizeof(*iomaps
), GFP_KERNEL
);
193 dprintk("%s: failed to allocate extent array\n", __func__
);
197 for (i
= 0; i
< nr_iomaps
; i
++) {
200 p
= xdr_decode_hyper(p
, &val
);
201 if (val
& (block_size
- 1)) {
202 dprintk("%s: unaligned offset 0x%llx\n", __func__
, val
);
205 iomaps
[i
].offset
= val
;
207 p
= xdr_decode_hyper(p
, &val
);
208 if (val
& (block_size
- 1)) {
209 dprintk("%s: unaligned length 0x%llx\n", __func__
, val
);
212 iomaps
[i
].length
= val
;