2 * device-process.c: detailed processing of device information sent
5 * Copyright (c) 2006 The Regents of the University of Michigan.
8 * Andy Adamson <andros@citi.umich.edu>
9 * Fred Isaman <iisaman@umich.edu>
11 * Copyright (c) 2010 EMC Corporation, Haiying Tang <Tang_Haiying@emc.com>
13 * Used codes in linux/fs/nfs/blocklayout/blocklayoutdev.c.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/types.h>
39 #include <arpa/inet.h>
40 #include <linux/kdev_t.h>
50 #include "device-discovery.h"
52 static char *pretty_sig(char *sig, uint32_t siglen)
58 if (siglen <= sizeof(sigval)) {
60 for (i = 0; i < siglen; i++)
61 sigval |= ((unsigned char *)sig)[i] << (i * 8);
62 sprintf(rs, "0x%0llx", (unsigned long long) sigval);
64 if (siglen > sizeof rs - 4) {
65 siglen = sizeof rs - 4;
66 sprintf(&rs[siglen], "...");
69 memcpy(rs, sig, siglen);
74 uint32_t *blk_overflow(uint32_t * p, uint32_t * end, size_t nbytes)
76 uint32_t *q = p + ((nbytes + 3) >> 2);
83 static int decode_blk_signature(uint32_t **pp, uint32_t * end,
87 uint32_t siglen, *p = *pp;
89 BLK_READBUF(p, end, 4);
90 READ32(sig->si_num_comps);
91 if (sig->si_num_comps == 0) {
92 BL_LOG_ERR("0 components in sig\n");
95 if (sig->si_num_comps >= BLOCK_MAX_SIG_COMP) {
96 BL_LOG_ERR("number of sig comps %i >= BLOCK_MAX_SIG_COMP\n",
100 for (i = 0; i < sig->si_num_comps; i++) {
101 struct bl_sig_comp *comp = &sig->si_comps[i];
103 BLK_READBUF(p, end, 12);
104 READ64(comp->bs_offset);
106 comp->bs_length = siglen;
107 BLK_READBUF(p, end, siglen);
108 /* Note we rely here on fact that sig is used immediately
109 * for mapping, then thrown away.
111 comp->bs_string = (char *)p;
112 BL_LOG_INFO("%s: si_comps[%d]: bs_length %d, bs_string %s\n",
114 pretty_sig(comp->bs_string, siglen));
115 p += ((siglen + 3) >> 2);
124 * Read signature from device and compare to sig_comp
125 * return: 0=match, 1=no match, -1=error
128 read_cmp_blk_sig(struct bl_disk *disk, int fd, struct bl_sig_comp *comp)
130 const char *dev_name = disk->valid_path->full_path;
132 ssize_t siglen = comp->bs_length;
133 int64_t bs_offset = comp->bs_offset;
136 sig = (char *)malloc(siglen);
138 BL_LOG_ERR("%s: Out of memory\n", __func__);
143 bs_offset += (((int64_t) disk->size) << 9);
144 if (lseek64(fd, bs_offset, SEEK_SET) == -1) {
145 BL_LOG_ERR("File %s lseek error\n", dev_name);
149 if (read(fd, sig, siglen) != siglen) {
150 BL_LOG_ERR("File %s read error\n", dev_name);
154 ret = memcmp(sig, comp->bs_string, siglen);
156 BL_LOG_INFO("%s: %s sig %s at %lld\n", __func__, dev_name,
157 pretty_sig(sig, siglen),
158 (long long)comp->bs_offset);
167 * All signatures in sig must be found on disk for verification.
168 * Returns True if sig matches, False otherwise.
170 static int verify_sig(struct bl_disk *disk, struct bl_sig *sig)
172 const char *dev_name = disk->valid_path->full_path;
175 fd = open(dev_name, O_RDONLY | O_LARGEFILE);
177 BL_LOG_ERR("%s: %s could not be opened for read\n", __func__,
184 for (i = 0; i < sig->si_num_comps; i++) {
185 if (read_cmp_blk_sig(disk, fd, &sig->si_comps[i])) {
197 * map_sig_to_device()
198 * Given a signature, walk the list of visible disks searching for
199 * a match. Returns True if mapping was done, False otherwise.
201 * While we're at it, fill in the vol->bv_size.
203 static int map_sig_to_device(struct bl_sig *sig, struct bl_volume *vol)
206 struct bl_disk *disk;
208 /* scan disk list to find out match device */
209 for (disk = visible_disk_list; disk; disk = disk->next) {
210 /* FIXME: should we use better algorithm for disk scan? */
211 mapped = verify_sig(disk, sig);
213 vol->param.bv_dev = disk->dev;
214 vol->bv_size = disk->size;
221 /* We are given an array of XDR encoded array indices, each of which should
222 * refer to a previously decoded device. Translate into a list of pointers
223 * to the appropriate pnfs_blk_volume's.
225 static int set_vol_array(uint32_t **pp, uint32_t *end,
226 struct bl_volume *vols, int working)
230 struct bl_volume **array = vols[working].bv_vols;
232 for (i = 0; i < vols[working].bv_vol_n; i++) {
233 BLK_READBUF(p, end, 4);
235 if ((index < 0) || (index >= working)) {
236 BL_LOG_ERR("set_vol_array: Id %i out of range\n",
240 array[i] = &vols[index];
248 static uint64_t sum_subvolume_sizes(struct bl_volume *vol)
253 for (i = 0; i < vol->bv_vol_n; i++)
254 sum += vol->bv_vols[i]->bv_size;
259 decode_blk_volume(uint32_t **pp, uint32_t *end, struct bl_volume *vols, int voln,
265 struct bl_volume *vol = &vols[voln];
268 BLK_READBUF(p, end, 4);
269 READ32(vol->bv_type);
271 switch (vol->bv_type) {
272 case BLOCK_VOLUME_SIMPLE:
274 status = decode_blk_signature(&p, end, &sig);
277 status = map_sig_to_device(&sig, vol);
279 BL_LOG_ERR("Could not find disk for device\n");
282 BL_LOG_INFO("%s: simple %d\n", __func__, voln);
285 case BLOCK_VOLUME_SLICE:
286 BLK_READBUF(p, end, 16);
287 READ_SECTOR(vol->param.bv_offset);
288 READ_SECTOR(vol->bv_size);
289 *array_cnt = vol->bv_vol_n = 1;
290 BL_LOG_INFO("%s: slice %d\n", __func__, voln);
291 status = set_vol_array(&p, end, vols, voln);
293 case BLOCK_VOLUME_STRIPE:
294 BLK_READBUF(p, end, 8);
295 READ_SECTOR(vol->param.bv_stripe_unit);
296 off_t stripe_unit = vol->param.bv_stripe_unit;
297 /* Check limitations imposed by device-mapper */
298 if ((stripe_unit & (stripe_unit - 1)) != 0
299 || stripe_unit < (off_t) (sysconf(_SC_PAGE_SIZE) >> 9))
301 BLK_READBUF(p, end, 4);
302 READ32(vol->bv_vol_n);
305 *array_cnt = vol->bv_vol_n;
306 BL_LOG_INFO("%s: stripe %d nvols=%d unit=%ld\n", __func__, voln,
307 vol->bv_vol_n, (long)stripe_unit);
308 status = set_vol_array(&p, end, vols, voln);
311 for (j = 1; j < vol->bv_vol_n; j++) {
312 if (vol->bv_vols[j]->bv_size !=
313 vol->bv_vols[0]->bv_size) {
314 BL_LOG_ERR("varying subvol size\n");
318 vol->bv_size = vol->bv_vols[0]->bv_size * vol->bv_vol_n;
320 case BLOCK_VOLUME_CONCAT:
321 BLK_READBUF(p, end, 4);
322 READ32(vol->bv_vol_n);
325 *array_cnt = vol->bv_vol_n;
326 BL_LOG_INFO("%s: concat %d %d\n", __func__, voln,
328 status = set_vol_array(&p, end, vols, voln);
331 vol->bv_size = sum_subvolume_sizes(vol);
334 BL_LOG_ERR("Unknown volume type %i\n", vol->bv_type);
342 uint64_t process_deviceinfo(const char *dev_addr_buf,
343 unsigned int dev_addr_len,
344 uint32_t *major, uint32_t *minor)
346 int num_vols, i, status, count;
348 struct bl_volume *vols = NULL, **arrays = NULL, **arrays_ptr = NULL;
351 p = (uint32_t *) dev_addr_buf;
352 end = (uint32_t *) ((char *)p + dev_addr_len);
354 /* Decode block volume */
355 BLK_READBUF(p, end, 4);
357 BL_LOG_INFO("%s: %d vols\n", __func__, num_vols);
361 vols = (struct bl_volume *)malloc(num_vols * sizeof(struct bl_volume));
363 BL_LOG_ERR("%s: Out of memory\n", __func__);
367 /* Each volume in vols array needs its own array. Save time by
368 * allocating them all in one large hunk. Because each volume
369 * array can only reference previous volumes, and because once
370 * a concat or stripe references a volume, it may never be
371 * referenced again, the volume arrays are guaranteed to fit
372 * in the suprisingly small space allocated.
374 arrays_ptr = arrays =
375 (struct bl_volume **)malloc(num_vols * 2 *
376 sizeof(struct bl_volume *));
378 BL_LOG_ERR("%s: Out of memory\n", __func__);
382 for (i = 0; i < num_vols; i++) {
383 vols[i].bv_vols = arrays_ptr;
384 status = decode_blk_volume(&p, end, vols, i, &count);
391 BL_LOG_ERR("p is not equal to end!\n");
395 dev = dm_device_create(vols, num_vols);