^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2014-2016 Christoph Hellwig.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/sunrpc/svc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/nfs4.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/nfs_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/nfs_xdr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/pr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "blocklayout.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define NFSDBG_FACILITY NFSDBG_PNFS_LD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) bl_free_device(struct pnfs_block_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) if (dev->nr_children) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) for (i = 0; i < dev->nr_children; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) bl_free_device(&dev->children[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) kfree(dev->children);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (dev->pr_registered) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) const struct pr_ops *ops =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) dev->bdev->bd_disk->fops->pr_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) error = ops->pr_register(dev->bdev, dev->pr_key, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) pr_err("failed to unregister PR key.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (dev->bdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) blkdev_put(dev->bdev, FMODE_READ | FMODE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) bl_free_deviceid_node(struct nfs4_deviceid_node *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct pnfs_block_dev *dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) container_of(d, struct pnfs_block_dev, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) bl_free_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) kfree_rcu(dev, node.rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) __be32 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) p = xdr_inline_decode(xdr, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) b->type = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) switch (b->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case PNFS_BLOCK_VOLUME_SIMPLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) p = xdr_inline_decode(xdr, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) b->simple.nr_sigs = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!b->simple.nr_sigs || b->simple.nr_sigs > PNFS_BLOCK_MAX_UUIDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) dprintk("Bad signature count: %d\n", b->simple.nr_sigs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) b->simple.len = 4 + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) for (i = 0; i < b->simple.nr_sigs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) p = xdr_inline_decode(xdr, 8 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) p = xdr_decode_hyper(p, &b->simple.sigs[i].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) b->simple.sigs[i].sig_len = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (b->simple.sigs[i].sig_len > PNFS_BLOCK_UUID_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pr_info("signature too long: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) b->simple.sigs[i].sig_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) p = xdr_inline_decode(xdr, b->simple.sigs[i].sig_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) memcpy(&b->simple.sigs[i].sig, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) b->simple.sigs[i].sig_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) b->simple.len += 8 + 4 + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) (XDR_QUADLEN(b->simple.sigs[i].sig_len) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case PNFS_BLOCK_VOLUME_SLICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) p = xdr_inline_decode(xdr, 8 + 8 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) p = xdr_decode_hyper(p, &b->slice.start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) p = xdr_decode_hyper(p, &b->slice.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) b->slice.volume = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) case PNFS_BLOCK_VOLUME_CONCAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) p = xdr_inline_decode(xdr, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) b->concat.volumes_count = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (b->concat.volumes_count > PNFS_BLOCK_MAX_DEVICES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dprintk("Too many volumes: %d\n", b->concat.volumes_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) p = xdr_inline_decode(xdr, b->concat.volumes_count * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) for (i = 0; i < b->concat.volumes_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) b->concat.volumes[i] = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case PNFS_BLOCK_VOLUME_STRIPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) p = xdr_inline_decode(xdr, 8 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) p = xdr_decode_hyper(p, &b->stripe.chunk_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) b->stripe.volumes_count = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (b->stripe.volumes_count > PNFS_BLOCK_MAX_DEVICES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) dprintk("Too many volumes: %d\n", b->stripe.volumes_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) p = xdr_inline_decode(xdr, b->stripe.volumes_count * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) for (i = 0; i < b->stripe.volumes_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) b->stripe.volumes[i] = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case PNFS_BLOCK_VOLUME_SCSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) p = xdr_inline_decode(xdr, 4 + 4 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) b->scsi.code_set = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) b->scsi.designator_type = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) b->scsi.designator_len = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) p = xdr_inline_decode(xdr, b->scsi.designator_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (b->scsi.designator_len > 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) memcpy(&b->scsi.designator, p, b->scsi.designator_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) p = xdr_inline_decode(xdr, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) p = xdr_decode_hyper(p, &b->scsi.pr_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) dprintk("unknown volume type!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static bool bl_map_simple(struct pnfs_block_dev *dev, u64 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct pnfs_block_dev_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) map->start = dev->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) map->len = dev->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) map->disk_offset = dev->disk_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) map->bdev = dev->bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static bool bl_map_concat(struct pnfs_block_dev *dev, u64 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct pnfs_block_dev_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) for (i = 0; i < dev->nr_children; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct pnfs_block_dev *child = &dev->children[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (child->start > offset ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) child->start + child->len <= offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) child->map(child, offset - child->start, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) dprintk("%s: ran off loop!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static bool bl_map_stripe(struct pnfs_block_dev *dev, u64 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct pnfs_block_dev_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct pnfs_block_dev *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u64 chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u32 chunk_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u64 disk_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) chunk = div_u64(offset, dev->chunk_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) div_u64_rem(chunk, dev->nr_children, &chunk_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (chunk_idx >= dev->nr_children) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) dprintk("%s: invalid chunk idx %d (%lld/%lld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) __func__, chunk_idx, offset, dev->chunk_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* error, should not happen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* truncate offset to the beginning of the stripe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) offset = chunk * dev->chunk_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* disk offset of the stripe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) disk_offset = div_u64(offset, dev->nr_children);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) child = &dev->children[chunk_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) child->map(child, disk_offset, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) map->start += offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) map->disk_offset += disk_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) map->len = dev->chunk_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) bl_parse_deviceid(struct nfs_server *server, struct pnfs_block_dev *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) bl_parse_simple(struct nfs_server *server, struct pnfs_block_dev *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct pnfs_block_volume *v = &volumes[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct block_device *bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dev_t dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dev = bl_resolve_deviceid(server, v, gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_WRITE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (IS_ERR(bdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) printk(KERN_WARNING "pNFS: failed to open device %d:%d (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) MAJOR(dev), MINOR(dev), PTR_ERR(bdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return PTR_ERR(bdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) d->bdev = bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) d->len = i_size_read(d->bdev->bd_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) d->map = bl_map_simple;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) printk(KERN_INFO "pNFS: using block device %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) d->bdev->bd_disk->disk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) bl_validate_designator(struct pnfs_block_volume *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) switch (v->scsi.designator_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case PS_DESIGNATOR_EUI64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (v->scsi.code_set != PS_CODE_SET_BINARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (v->scsi.designator_len != 8 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) v->scsi.designator_len != 10 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) v->scsi.designator_len != 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case PS_DESIGNATOR_NAA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (v->scsi.code_set != PS_CODE_SET_BINARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (v->scsi.designator_len != 8 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) v->scsi.designator_len != 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) case PS_DESIGNATOR_T10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) case PS_DESIGNATOR_NAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) pr_err("pNFS: unsupported designator "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) "(code set %d, type %d, len %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) v->scsi.code_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) v->scsi.designator_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) v->scsi.designator_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) pr_err("pNFS: invalid designator "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) "(code set %d, type %d, len %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) v->scsi.code_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) v->scsi.designator_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) v->scsi.designator_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * Try to open the udev path for the WWN. At least on Debian the udev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * by-id path will always point to the dm-multipath device if one exists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static struct block_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) bl_open_udev_path(struct pnfs_block_volume *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct block_device *bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) const char *devname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/wwn-0x%*phN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) v->scsi.designator_len, v->scsi.designator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (!devname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) bdev = blkdev_get_by_path(devname, FMODE_READ | FMODE_WRITE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (IS_ERR(bdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) pr_warn("pNFS: failed to open device %s (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) devname, PTR_ERR(bdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) kfree(devname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * Try to open the RH/Fedora specific dm-mpath udev path for this WWN, as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * wwn- links will only point to the first discovered SCSI device there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static struct block_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) bl_open_dm_mpath_udev_path(struct pnfs_block_volume *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct block_device *bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) const char *devname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) devname = kasprintf(GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) "/dev/disk/by-id/dm-uuid-mpath-%d%*phN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) v->scsi.designator_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) v->scsi.designator_len, v->scsi.designator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (!devname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) bdev = blkdev_get_by_path(devname, FMODE_READ | FMODE_WRITE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) kfree(devname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) bl_parse_scsi(struct nfs_server *server, struct pnfs_block_dev *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct pnfs_block_volume *v = &volumes[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct block_device *bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) const struct pr_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (!bl_validate_designator(v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) bdev = bl_open_dm_mpath_udev_path(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (IS_ERR(bdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) bdev = bl_open_udev_path(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (IS_ERR(bdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return PTR_ERR(bdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) d->bdev = bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) d->len = i_size_read(d->bdev->bd_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) d->map = bl_map_simple;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) d->pr_key = v->scsi.pr_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) pr_info("pNFS: using block device %s (reservation key 0x%llx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) d->bdev->bd_disk->disk_name, d->pr_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) ops = d->bdev->bd_disk->fops->pr_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (!ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) pr_err("pNFS: block device %s does not support reservations.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) d->bdev->bd_disk->disk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) goto out_blkdev_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) error = ops->pr_register(d->bdev, 0, d->pr_key, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) pr_err("pNFS: failed to register key for block device %s.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) d->bdev->bd_disk->disk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) goto out_blkdev_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) d->pr_registered = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) out_blkdev_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) blkdev_put(d->bdev, FMODE_READ | FMODE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) bl_parse_slice(struct nfs_server *server, struct pnfs_block_dev *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct pnfs_block_volume *v = &volumes[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ret = bl_parse_deviceid(server, d, volumes, v->slice.volume, gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) d->disk_offset = v->slice.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) d->len = v->slice.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) bl_parse_concat(struct nfs_server *server, struct pnfs_block_dev *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct pnfs_block_volume *v = &volumes[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) u64 len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) d->children = kcalloc(v->concat.volumes_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) sizeof(struct pnfs_block_dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!d->children)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) for (i = 0; i < v->concat.volumes_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) ret = bl_parse_deviceid(server, &d->children[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) volumes, v->concat.volumes[i], gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) d->nr_children++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) d->children[i].start += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) len += d->children[i].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) d->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) d->map = bl_map_concat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) bl_parse_stripe(struct nfs_server *server, struct pnfs_block_dev *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct pnfs_block_volume *v = &volumes[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) u64 len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) d->children = kcalloc(v->stripe.volumes_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) sizeof(struct pnfs_block_dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (!d->children)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) for (i = 0; i < v->stripe.volumes_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) ret = bl_parse_deviceid(server, &d->children[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) volumes, v->stripe.volumes[i], gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) d->nr_children++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) len += d->children[i].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) d->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) d->chunk_size = v->stripe.chunk_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) d->map = bl_map_stripe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) bl_parse_deviceid(struct nfs_server *server, struct pnfs_block_dev *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) switch (volumes[idx].type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) case PNFS_BLOCK_VOLUME_SIMPLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return bl_parse_simple(server, d, volumes, idx, gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) case PNFS_BLOCK_VOLUME_SLICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return bl_parse_slice(server, d, volumes, idx, gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) case PNFS_BLOCK_VOLUME_CONCAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return bl_parse_concat(server, d, volumes, idx, gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case PNFS_BLOCK_VOLUME_STRIPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return bl_parse_stripe(server, d, volumes, idx, gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case PNFS_BLOCK_VOLUME_SCSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return bl_parse_scsi(server, d, volumes, idx, gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) dprintk("unsupported volume type: %d\n", volumes[idx].type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct nfs4_deviceid_node *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) bl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) gfp_t gfp_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct nfs4_deviceid_node *node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct pnfs_block_volume *volumes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct pnfs_block_dev *top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct xdr_stream xdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct xdr_buf buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct page *scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) int nr_volumes, ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) __be32 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) scratch = alloc_page(gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (!scratch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) xdr_init_decode_pages(&xdr, &buf, pdev->pages, pdev->pglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) xdr_set_scratch_buffer(&xdr, page_address(scratch), PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) p = xdr_inline_decode(&xdr, sizeof(__be32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) goto out_free_scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) nr_volumes = be32_to_cpup(p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) volumes = kcalloc(nr_volumes, sizeof(struct pnfs_block_volume),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (!volumes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) goto out_free_scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) for (i = 0; i < nr_volumes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ret = nfs4_block_decode_volume(&xdr, &volumes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) goto out_free_volumes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) top = kzalloc(sizeof(*top), gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (!top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) goto out_free_volumes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ret = bl_parse_deviceid(server, top, volumes, nr_volumes - 1, gfp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) node = &top->node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) nfs4_init_deviceid_node(node, server, &pdev->dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) nfs4_mark_deviceid_unavailable(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) out_free_volumes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) kfree(volumes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) out_free_scratch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) __free_page(scratch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }