]>
git.ipfire.org Git - thirdparty/linux.git/blob - fs/nfs/blocklayout/dev.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014-2016 Christoph Hellwig.
5 #include <linux/sunrpc/svc.h>
6 #include <linux/blkdev.h>
7 #include <linux/nfs4.h>
8 #include <linux/nfs_fs.h>
9 #include <linux/nfs_xdr.h>
12 #include "blocklayout.h"
14 #define NFSDBG_FACILITY NFSDBG_PNFS_LD
17 bl_free_device(struct pnfs_block_dev
*dev
)
19 if (dev
->nr_children
) {
22 for (i
= 0; i
< dev
->nr_children
; i
++)
23 bl_free_device(&dev
->children
[i
]);
26 if (dev
->pr_registered
) {
27 const struct pr_ops
*ops
=
28 file_bdev(dev
->bdev_file
)->bd_disk
->fops
->pr_ops
;
31 error
= ops
->pr_register(file_bdev(dev
->bdev_file
),
32 dev
->pr_key
, 0, false);
34 pr_err("failed to unregister PR key.\n");
43 bl_free_deviceid_node(struct nfs4_deviceid_node
*d
)
45 struct pnfs_block_dev
*dev
=
46 container_of(d
, struct pnfs_block_dev
, node
);
49 kfree_rcu(dev
, node
.rcu
);
53 nfs4_block_decode_volume(struct xdr_stream
*xdr
, struct pnfs_block_volume
*b
)
58 p
= xdr_inline_decode(xdr
, 4);
61 b
->type
= be32_to_cpup(p
++);
64 case PNFS_BLOCK_VOLUME_SIMPLE
:
65 p
= xdr_inline_decode(xdr
, 4);
68 b
->simple
.nr_sigs
= be32_to_cpup(p
++);
69 if (!b
->simple
.nr_sigs
|| b
->simple
.nr_sigs
> PNFS_BLOCK_MAX_UUIDS
) {
70 dprintk("Bad signature count: %d\n", b
->simple
.nr_sigs
);
74 b
->simple
.len
= 4 + 4;
75 for (i
= 0; i
< b
->simple
.nr_sigs
; i
++) {
76 p
= xdr_inline_decode(xdr
, 8 + 4);
79 p
= xdr_decode_hyper(p
, &b
->simple
.sigs
[i
].offset
);
80 b
->simple
.sigs
[i
].sig_len
= be32_to_cpup(p
++);
81 if (b
->simple
.sigs
[i
].sig_len
> PNFS_BLOCK_UUID_LEN
) {
82 pr_info("signature too long: %d\n",
83 b
->simple
.sigs
[i
].sig_len
);
87 p
= xdr_inline_decode(xdr
, b
->simple
.sigs
[i
].sig_len
);
90 memcpy(&b
->simple
.sigs
[i
].sig
, p
,
91 b
->simple
.sigs
[i
].sig_len
);
93 b
->simple
.len
+= 8 + 4 + \
94 (XDR_QUADLEN(b
->simple
.sigs
[i
].sig_len
) << 2);
97 case PNFS_BLOCK_VOLUME_SLICE
:
98 p
= xdr_inline_decode(xdr
, 8 + 8 + 4);
101 p
= xdr_decode_hyper(p
, &b
->slice
.start
);
102 p
= xdr_decode_hyper(p
, &b
->slice
.len
);
103 b
->slice
.volume
= be32_to_cpup(p
++);
105 case PNFS_BLOCK_VOLUME_CONCAT
:
106 p
= xdr_inline_decode(xdr
, 4);
110 b
->concat
.volumes_count
= be32_to_cpup(p
++);
111 if (b
->concat
.volumes_count
> PNFS_BLOCK_MAX_DEVICES
) {
112 dprintk("Too many volumes: %d\n", b
->concat
.volumes_count
);
116 p
= xdr_inline_decode(xdr
, b
->concat
.volumes_count
* 4);
119 for (i
= 0; i
< b
->concat
.volumes_count
; i
++)
120 b
->concat
.volumes
[i
] = be32_to_cpup(p
++);
122 case PNFS_BLOCK_VOLUME_STRIPE
:
123 p
= xdr_inline_decode(xdr
, 8 + 4);
127 p
= xdr_decode_hyper(p
, &b
->stripe
.chunk_size
);
128 b
->stripe
.volumes_count
= be32_to_cpup(p
++);
129 if (b
->stripe
.volumes_count
> PNFS_BLOCK_MAX_DEVICES
) {
130 dprintk("Too many volumes: %d\n", b
->stripe
.volumes_count
);
134 p
= xdr_inline_decode(xdr
, b
->stripe
.volumes_count
* 4);
137 for (i
= 0; i
< b
->stripe
.volumes_count
; i
++)
138 b
->stripe
.volumes
[i
] = be32_to_cpup(p
++);
140 case PNFS_BLOCK_VOLUME_SCSI
:
141 p
= xdr_inline_decode(xdr
, 4 + 4 + 4);
144 b
->scsi
.code_set
= be32_to_cpup(p
++);
145 b
->scsi
.designator_type
= be32_to_cpup(p
++);
146 b
->scsi
.designator_len
= be32_to_cpup(p
++);
147 p
= xdr_inline_decode(xdr
, b
->scsi
.designator_len
);
150 if (b
->scsi
.designator_len
> 256)
152 memcpy(&b
->scsi
.designator
, p
, b
->scsi
.designator_len
);
153 p
= xdr_inline_decode(xdr
, 8);
156 p
= xdr_decode_hyper(p
, &b
->scsi
.pr_key
);
159 dprintk("unknown volume type!\n");
166 static bool bl_map_simple(struct pnfs_block_dev
*dev
, u64 offset
,
167 struct pnfs_block_dev_map
*map
)
169 map
->start
= dev
->start
;
171 map
->disk_offset
= dev
->disk_offset
;
172 map
->bdev
= file_bdev(dev
->bdev_file
);
176 static bool bl_map_concat(struct pnfs_block_dev
*dev
, u64 offset
,
177 struct pnfs_block_dev_map
*map
)
181 for (i
= 0; i
< dev
->nr_children
; i
++) {
182 struct pnfs_block_dev
*child
= &dev
->children
[i
];
184 if (child
->start
> offset
||
185 child
->start
+ child
->len
<= offset
)
188 child
->map(child
, offset
- child
->start
, map
);
192 dprintk("%s: ran off loop!\n", __func__
);
196 static bool bl_map_stripe(struct pnfs_block_dev
*dev
, u64 offset
,
197 struct pnfs_block_dev_map
*map
)
199 struct pnfs_block_dev
*child
;
204 chunk
= div_u64(offset
, dev
->chunk_size
);
205 div_u64_rem(chunk
, dev
->nr_children
, &chunk_idx
);
207 if (chunk_idx
>= dev
->nr_children
) {
208 dprintk("%s: invalid chunk idx %d (%lld/%lld)\n",
209 __func__
, chunk_idx
, offset
, dev
->chunk_size
);
210 /* error, should not happen */
214 /* truncate offset to the beginning of the stripe */
215 offset
= chunk
* dev
->chunk_size
;
217 /* disk offset of the stripe */
218 disk_offset
= div_u64(offset
, dev
->nr_children
);
220 child
= &dev
->children
[chunk_idx
];
221 child
->map(child
, disk_offset
, map
);
223 map
->start
+= offset
;
224 map
->disk_offset
+= disk_offset
;
225 map
->len
= dev
->chunk_size
;
230 bl_parse_deviceid(struct nfs_server
*server
, struct pnfs_block_dev
*d
,
231 struct pnfs_block_volume
*volumes
, int idx
, gfp_t gfp_mask
);
235 bl_parse_simple(struct nfs_server
*server
, struct pnfs_block_dev
*d
,
236 struct pnfs_block_volume
*volumes
, int idx
, gfp_t gfp_mask
)
238 struct pnfs_block_volume
*v
= &volumes
[idx
];
239 struct file
*bdev_file
;
242 dev
= bl_resolve_deviceid(server
, v
, gfp_mask
);
246 bdev_file
= bdev_file_open_by_dev(dev
, BLK_OPEN_READ
| BLK_OPEN_WRITE
,
248 if (IS_ERR(bdev_file
)) {
249 printk(KERN_WARNING
"pNFS: failed to open device %d:%d (%ld)\n",
250 MAJOR(dev
), MINOR(dev
), PTR_ERR(bdev_file
));
251 return PTR_ERR(bdev_file
);
253 d
->bdev_file
= bdev_file
;
254 d
->len
= bdev_nr_bytes(file_bdev(bdev_file
));
255 d
->map
= bl_map_simple
;
257 printk(KERN_INFO
"pNFS: using block device %s\n",
258 file_bdev(bdev_file
)->bd_disk
->disk_name
);
263 bl_validate_designator(struct pnfs_block_volume
*v
)
265 switch (v
->scsi
.designator_type
) {
266 case PS_DESIGNATOR_EUI64
:
267 if (v
->scsi
.code_set
!= PS_CODE_SET_BINARY
)
270 if (v
->scsi
.designator_len
!= 8 &&
271 v
->scsi
.designator_len
!= 10 &&
272 v
->scsi
.designator_len
!= 16)
276 case PS_DESIGNATOR_NAA
:
277 if (v
->scsi
.code_set
!= PS_CODE_SET_BINARY
)
280 if (v
->scsi
.designator_len
!= 8 &&
281 v
->scsi
.designator_len
!= 16)
285 case PS_DESIGNATOR_T10
:
286 case PS_DESIGNATOR_NAME
:
287 pr_err("pNFS: unsupported designator "
288 "(code set %d, type %d, len %d.\n",
290 v
->scsi
.designator_type
,
291 v
->scsi
.designator_len
);
294 pr_err("pNFS: invalid designator "
295 "(code set %d, type %d, len %d.\n",
297 v
->scsi
.designator_type
,
298 v
->scsi
.designator_len
);
304 bl_open_path(struct pnfs_block_volume
*v
, const char *prefix
)
306 struct file
*bdev_file
;
309 devname
= kasprintf(GFP_KERNEL
, "/dev/disk/by-id/%s%*phN",
310 prefix
, v
->scsi
.designator_len
, v
->scsi
.designator
);
312 return ERR_PTR(-ENOMEM
);
314 bdev_file
= bdev_file_open_by_path(devname
, BLK_OPEN_READ
| BLK_OPEN_WRITE
,
316 if (IS_ERR(bdev_file
)) {
317 pr_warn("pNFS: failed to open device %s (%ld)\n",
318 devname
, PTR_ERR(bdev_file
));
326 bl_parse_scsi(struct nfs_server
*server
, struct pnfs_block_dev
*d
,
327 struct pnfs_block_volume
*volumes
, int idx
, gfp_t gfp_mask
)
329 struct pnfs_block_volume
*v
= &volumes
[idx
];
330 struct file
*bdev_file
;
331 const struct pr_ops
*ops
;
334 if (!bl_validate_designator(v
))
338 * Try to open the RH/Fedora specific dm-mpath udev path first, as the
339 * wwn- links will only point to the first discovered SCSI device there.
340 * On other distributions like Debian, the default SCSI by-id path will
341 * point to the dm-multipath device if one exists.
343 bdev_file
= bl_open_path(v
, "dm-uuid-mpath-0x");
344 if (IS_ERR(bdev_file
))
345 bdev_file
= bl_open_path(v
, "wwn-0x");
346 if (IS_ERR(bdev_file
))
347 return PTR_ERR(bdev_file
);
348 d
->bdev_file
= bdev_file
;
350 d
->len
= bdev_nr_bytes(file_bdev(d
->bdev_file
));
351 d
->map
= bl_map_simple
;
352 d
->pr_key
= v
->scsi
.pr_key
;
357 pr_info("pNFS: using block device %s (reservation key 0x%llx)\n",
358 file_bdev(d
->bdev_file
)->bd_disk
->disk_name
, d
->pr_key
);
360 ops
= file_bdev(d
->bdev_file
)->bd_disk
->fops
->pr_ops
;
362 pr_err("pNFS: block device %s does not support reservations.",
363 file_bdev(d
->bdev_file
)->bd_disk
->disk_name
);
368 error
= ops
->pr_register(file_bdev(d
->bdev_file
), 0, d
->pr_key
, true);
370 pr_err("pNFS: failed to register key for block device %s.",
371 file_bdev(d
->bdev_file
)->bd_disk
->disk_name
);
375 d
->pr_registered
= true;
384 bl_parse_slice(struct nfs_server
*server
, struct pnfs_block_dev
*d
,
385 struct pnfs_block_volume
*volumes
, int idx
, gfp_t gfp_mask
)
387 struct pnfs_block_volume
*v
= &volumes
[idx
];
390 ret
= bl_parse_deviceid(server
, d
, volumes
, v
->slice
.volume
, gfp_mask
);
394 d
->disk_offset
= v
->slice
.start
;
395 d
->len
= v
->slice
.len
;
400 bl_parse_concat(struct nfs_server
*server
, struct pnfs_block_dev
*d
,
401 struct pnfs_block_volume
*volumes
, int idx
, gfp_t gfp_mask
)
403 struct pnfs_block_volume
*v
= &volumes
[idx
];
407 d
->children
= kcalloc(v
->concat
.volumes_count
,
408 sizeof(struct pnfs_block_dev
), gfp_mask
);
412 for (i
= 0; i
< v
->concat
.volumes_count
; i
++) {
413 ret
= bl_parse_deviceid(server
, &d
->children
[i
],
414 volumes
, v
->concat
.volumes
[i
], gfp_mask
);
419 d
->children
[i
].start
+= len
;
420 len
+= d
->children
[i
].len
;
424 d
->map
= bl_map_concat
;
429 bl_parse_stripe(struct nfs_server
*server
, struct pnfs_block_dev
*d
,
430 struct pnfs_block_volume
*volumes
, int idx
, gfp_t gfp_mask
)
432 struct pnfs_block_volume
*v
= &volumes
[idx
];
436 d
->children
= kcalloc(v
->stripe
.volumes_count
,
437 sizeof(struct pnfs_block_dev
), gfp_mask
);
441 for (i
= 0; i
< v
->stripe
.volumes_count
; i
++) {
442 ret
= bl_parse_deviceid(server
, &d
->children
[i
],
443 volumes
, v
->stripe
.volumes
[i
], gfp_mask
);
448 len
+= d
->children
[i
].len
;
452 d
->chunk_size
= v
->stripe
.chunk_size
;
453 d
->map
= bl_map_stripe
;
458 bl_parse_deviceid(struct nfs_server
*server
, struct pnfs_block_dev
*d
,
459 struct pnfs_block_volume
*volumes
, int idx
, gfp_t gfp_mask
)
461 switch (volumes
[idx
].type
) {
462 case PNFS_BLOCK_VOLUME_SIMPLE
:
463 return bl_parse_simple(server
, d
, volumes
, idx
, gfp_mask
);
464 case PNFS_BLOCK_VOLUME_SLICE
:
465 return bl_parse_slice(server
, d
, volumes
, idx
, gfp_mask
);
466 case PNFS_BLOCK_VOLUME_CONCAT
:
467 return bl_parse_concat(server
, d
, volumes
, idx
, gfp_mask
);
468 case PNFS_BLOCK_VOLUME_STRIPE
:
469 return bl_parse_stripe(server
, d
, volumes
, idx
, gfp_mask
);
470 case PNFS_BLOCK_VOLUME_SCSI
:
471 return bl_parse_scsi(server
, d
, volumes
, idx
, gfp_mask
);
473 dprintk("unsupported volume type: %d\n", volumes
[idx
].type
);
478 struct nfs4_deviceid_node
*
479 bl_alloc_deviceid_node(struct nfs_server
*server
, struct pnfs_device
*pdev
,
482 struct nfs4_deviceid_node
*node
= NULL
;
483 struct pnfs_block_volume
*volumes
;
484 struct pnfs_block_dev
*top
;
485 struct xdr_stream xdr
;
487 struct page
*scratch
;
488 int nr_volumes
, ret
, i
;
491 scratch
= alloc_page(gfp_mask
);
495 xdr_init_decode_pages(&xdr
, &buf
, pdev
->pages
, pdev
->pglen
);
496 xdr_set_scratch_page(&xdr
, scratch
);
498 p
= xdr_inline_decode(&xdr
, sizeof(__be32
));
500 goto out_free_scratch
;
501 nr_volumes
= be32_to_cpup(p
++);
503 volumes
= kcalloc(nr_volumes
, sizeof(struct pnfs_block_volume
),
506 goto out_free_scratch
;
508 for (i
= 0; i
< nr_volumes
; i
++) {
509 ret
= nfs4_block_decode_volume(&xdr
, &volumes
[i
]);
511 goto out_free_volumes
;
514 top
= kzalloc(sizeof(*top
), gfp_mask
);
516 goto out_free_volumes
;
518 ret
= bl_parse_deviceid(server
, top
, volumes
, nr_volumes
- 1, gfp_mask
);
521 nfs4_init_deviceid_node(node
, server
, &pdev
->dev_id
);
523 nfs4_mark_deviceid_unavailable(node
);
528 __free_page(scratch
);