ldm.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:43k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /**
  2.  * ldm - Support for Windows Logical Disk Manager (Dynamic Disks)
  3.  *
  4.  * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
  5.  * Copyright (C) 2001      Anton Altaparmakov <aia21@cantab.net>
  6.  * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
  7.  *
  8.  * Documentation is available at http://linux-ntfs.sf.net/ldm
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify it under
  11.  * the terms of the GNU General Public License as published by the Free Software
  12.  * Foundation; either version 2 of the License, or (at your option) any later
  13.  * version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful, but WITHOUT
  16.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  17.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  18.  * details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License along with
  21.  * this program (in the main directory of the source in the file COPYING); if
  22.  * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  23.  * Boston, MA  02111-1307  USA
  24.  */
  25. #include <linux/slab.h>
  26. #include <linux/stringify.h>
  27. #include <linux/pagemap.h>
  28. #include "ldm.h"
  29. #include "check.h"
  30. #include "msdos.h"
  31. typedef enum {
  32. FALSE = 0,
  33. TRUE  = 1
  34. } BOOL;
  35. /**
  36.  * ldm_debug/info/error/crit - Output an error message
  37.  * @f:    A printf format string containing the message
  38.  * @...:  Variables to substitute into @f
  39.  *
  40.  * ldm_debug() writes a DEBUG level message to the syslog but only if the
  41.  * driver was compiled with debug enabled. Otherwise, the call turns into a NOP.
  42.  */
  43. #ifndef CONFIG_LDM_DEBUG
  44. #define ldm_debug(...) do {} while (0)
  45. #else
  46. #define ldm_debug(f, a...) _ldm_printk (KERN_DEBUG, __FUNCTION__, f, ##a)
  47. #endif
  48. #define ldm_crit(f, a...)  _ldm_printk (KERN_CRIT,  __FUNCTION__, f, ##a)
  49. #define ldm_error(f, a...) _ldm_printk (KERN_ERR,   __FUNCTION__, f, ##a)
  50. #define ldm_info(f, a...)  _ldm_printk (KERN_INFO,  __FUNCTION__, f, ##a)
  51. __attribute__ ((format (printf, 3, 4)))
  52. static void _ldm_printk (const char *level, const char *function,
  53.  const char *fmt, ...)
  54. {
  55. static char buf[128];
  56. va_list args;
  57. va_start (args, fmt);
  58. vsnprintf (buf, sizeof (buf), fmt, args);
  59. va_end (args);
  60. printk ("%s%s(): %sn", level, function, buf);
  61. }
  62. /**
  63.  * ldm_parse_hexbyte - Convert a ASCII hex number to a byte
  64.  * @src:  Pointer to at least 2 characters to convert.
  65.  *
  66.  * Convert a two character ASCII hex string to a number.
  67.  *
  68.  * Return:  0-255  Success, the byte was parsed correctly
  69.  *          -1     Error, an invalid character was supplied
  70.  */
  71. static int ldm_parse_hexbyte (const u8 *src)
  72. {
  73. unsigned int x; /* For correct wrapping */
  74. int h;
  75. /* high part */
  76. if      ((x = src[0] - '0') <= '9'-'0') h = x;
  77. else if ((x = src[0] - 'a') <= 'f'-'a') h = x+10;
  78. else if ((x = src[0] - 'A') <= 'F'-'A') h = x+10;
  79. else return -1;
  80. h <<= 4;
  81. /* low part */
  82. if ((x = src[1] - '0') <= '9'-'0') return h | x;
  83. if ((x = src[1] - 'a') <= 'f'-'a') return h | (x+10);
  84. if ((x = src[1] - 'A') <= 'F'-'A') return h | (x+10);
  85. return -1;
  86. }
  87. /**
  88.  * ldm_parse_guid - Convert GUID from ASCII to binary
  89.  * @src:   36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
  90.  * @dest:  Memory block to hold binary GUID (16 bytes)
  91.  *
  92.  * N.B. The GUID need not be NULL terminated.
  93.  *
  94.  * Return:  TRUE   @dest contains binary GUID
  95.  *          FALSE  @dest contents are undefined
  96.  */
  97. static BOOL ldm_parse_guid (const u8 *src, u8 *dest)
  98. {
  99. static const int size[] = { 4, 2, 2, 2, 6 };
  100. int i, j, v;
  101. if (src[8]  != '-' || src[13] != '-' ||
  102.     src[18] != '-' || src[23] != '-')
  103. return FALSE;
  104. for (j = 0; j < 5; j++, src++)
  105. for (i = 0; i < size[j]; i++, src+=2, *dest++ = v)
  106. if ((v = ldm_parse_hexbyte (src)) < 0)
  107. return FALSE;
  108. return TRUE;
  109. }
  110. /**
  111.  * ldm_parse_privhead - Read the LDM Database PRIVHEAD structure
  112.  * @data:  Raw database PRIVHEAD structure loaded from the device
  113.  * @ph:    In-memory privhead structure in which to return parsed information
  114.  *
  115.  * This parses the LDM database PRIVHEAD structure supplied in @data and
  116.  * sets up the in-memory privhead structure @ph with the obtained information.
  117.  *
  118.  * Return:  TRUE   @ph contains the PRIVHEAD data
  119.  *          FALSE  @ph contents are undefined
  120.  */
  121. static BOOL ldm_parse_privhead (const u8 *data, struct privhead *ph)
  122. {
  123. BUG_ON (!data);
  124. BUG_ON (!ph);
  125. if (MAGIC_PRIVHEAD != BE64 (data)) {
  126. ldm_error ("Cannot find PRIVHEAD structure. LDM database is"
  127. " corrupt. Aborting.");
  128. return FALSE;
  129. }
  130. ph->ver_major          = BE16 (data + 0x000C);
  131. ph->ver_minor          = BE16 (data + 0x000E);
  132. ph->logical_disk_start = BE64 (data + 0x011B);
  133. ph->logical_disk_size  = BE64 (data + 0x0123);
  134. ph->config_start       = BE64 (data + 0x012B);
  135. ph->config_size        = BE64 (data + 0x0133);
  136. if ((ph->ver_major != 2) || (ph->ver_minor != 11)) {
  137. ldm_error ("Expected PRIVHEAD version %d.%d, got %d.%d."
  138. " Aborting.", 2, 11, ph->ver_major, ph->ver_minor);
  139. return FALSE;
  140. }
  141. if (ph->config_size != LDM_DB_SIZE) { /* 1 MiB in sectors. */
  142. /* Warn the user and continue, carefully */
  143. ldm_info ("Database is normally %u bytes, it claims to "
  144. "be %llu bytes.", LDM_DB_SIZE,
  145. (unsigned long long)ph->config_size );
  146. }
  147. if ((ph->logical_disk_size == 0) ||
  148.     (ph->logical_disk_start + ph->logical_disk_size > ph->config_start)) {
  149. ldm_error ("PRIVHEAD disk size doesn't match real disk size");
  150. return FALSE;
  151. }
  152. if (!ldm_parse_guid (data + 0x0030, ph->disk_id)) {
  153. ldm_error ("PRIVHEAD contains an invalid GUID.");
  154. return FALSE;
  155. }
  156. ldm_debug ("Parsed PRIVHEAD successfully.");
  157. return TRUE;
  158. }
  159. /**
  160.  * ldm_parse_tocblock - Read the LDM Database TOCBLOCK structure
  161.  * @data:  Raw database TOCBLOCK structure loaded from the device
  162.  * @toc:   In-memory toc structure in which to return parsed information
  163.  *
  164.  * This parses the LDM Database TOCBLOCK (table of contents) structure supplied
  165.  * in @data and sets up the in-memory tocblock structure @toc with the obtained
  166.  * information.
  167.  *
  168.  * N.B.  The *_start and *_size values returned in @toc are not range-checked.
  169.  *
  170.  * Return:  TRUE   @toc contains the TOCBLOCK data
  171.  *          FALSE  @toc contents are undefined
  172.  */
  173. static BOOL ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
  174. {
  175. BUG_ON (!data);
  176. BUG_ON (!toc);
  177. if (MAGIC_TOCBLOCK != BE64 (data)) {
  178. ldm_crit ("Cannot find TOCBLOCK, database may be corrupt.");
  179. return FALSE;
  180. }
  181. strncpy (toc->bitmap1_name, data + 0x24, sizeof (toc->bitmap1_name));
  182. toc->bitmap1_name[sizeof (toc->bitmap1_name) - 1] = 0;
  183. toc->bitmap1_start = BE64 (data + 0x2E);
  184. toc->bitmap1_size  = BE64 (data + 0x36);
  185. if (strncmp (toc->bitmap1_name, TOC_BITMAP1,
  186. sizeof (toc->bitmap1_name)) != 0) {
  187. ldm_crit ("TOCBLOCK's first bitmap is '%s', should be '%s'.",
  188. TOC_BITMAP1, toc->bitmap1_name);
  189. return FALSE;
  190. }
  191. strncpy (toc->bitmap2_name, data + 0x46, sizeof (toc->bitmap2_name));
  192. toc->bitmap2_name[sizeof (toc->bitmap2_name) - 1] = 0;
  193. toc->bitmap2_start = BE64 (data + 0x50);
  194. toc->bitmap2_size  = BE64 (data + 0x58);
  195. if (strncmp (toc->bitmap2_name, TOC_BITMAP2,
  196. sizeof (toc->bitmap2_name)) != 0) {
  197. ldm_crit ("TOCBLOCK's second bitmap is '%s', should be '%s'.",
  198. TOC_BITMAP2, toc->bitmap2_name);
  199. return FALSE;
  200. }
  201. ldm_debug ("Parsed TOCBLOCK successfully.");
  202. return TRUE;
  203. }
  204. /**
  205.  * ldm_parse_vmdb - Read the LDM Database VMDB structure
  206.  * @data:  Raw database VMDB structure loaded from the device
  207.  * @vm:    In-memory vmdb structure in which to return parsed information
  208.  *
  209.  * This parses the LDM Database VMDB structure supplied in @data and sets up
  210.  * the in-memory vmdb structure @vm with the obtained information.
  211.  *
  212.  * N.B.  The *_start, *_size and *_seq values will be range-checked later.
  213.  *
  214.  * Return:  TRUE   @vm contains VMDB info
  215.  *          FALSE  @vm contents are undefined
  216.  */
  217. static BOOL ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
  218. {
  219. BUG_ON (!data);
  220. BUG_ON (!vm);
  221. if (MAGIC_VMDB != BE32 (data)) {
  222. ldm_crit ("Cannot find the VMDB, database may be corrupt.");
  223. return FALSE;
  224. }
  225. vm->ver_major = BE16 (data + 0x12);
  226. vm->ver_minor = BE16 (data + 0x14);
  227. if ((vm->ver_major != 4) || (vm->ver_minor != 10)) {
  228. ldm_error ("Expected VMDB version %d.%d, got %d.%d. "
  229. "Aborting.", 4, 10, vm->ver_major, vm->ver_minor);
  230. return FALSE;
  231. }
  232. vm->vblk_size     = BE32 (data + 0x08);
  233. vm->vblk_offset   = BE32 (data + 0x0C);
  234. vm->last_vblk_seq = BE32 (data + 0x04);
  235. ldm_debug ("Parsed VMDB successfully.");
  236. return TRUE;
  237. }
  238. /**
  239.  * ldm_compare_privheads - Compare two privhead objects
  240.  * @ph1:  First privhead
  241.  * @ph2:  Second privhead
  242.  *
  243.  * This compares the two privhead structures @ph1 and @ph2.
  244.  *
  245.  * Return:  TRUE   Identical
  246.  *          FALSE  Different
  247.  */
  248. static BOOL ldm_compare_privheads (const struct privhead *ph1,
  249.    const struct privhead *ph2)
  250. {
  251. BUG_ON (!ph1);
  252. BUG_ON (!ph2);
  253. return ((ph1->ver_major          == ph2->ver_major) &&
  254. (ph1->ver_minor          == ph2->ver_minor) &&
  255. (ph1->logical_disk_start == ph2->logical_disk_start) &&
  256. (ph1->logical_disk_size  == ph2->logical_disk_size) &&
  257. (ph1->config_start       == ph2->config_start) &&
  258. (ph1->config_size        == ph2->config_size) &&
  259. !memcmp (ph1->disk_id, ph2->disk_id, GUID_SIZE));
  260. }
  261. /**
  262.  * ldm_compare_tocblocks - Compare two tocblock objects
  263.  * @toc1:  First toc
  264.  * @toc2:  Second toc
  265.  *
  266.  * This compares the two tocblock structures @toc1 and @toc2.
  267.  *
  268.  * Return:  TRUE   Identical
  269.  *          FALSE  Different
  270.  */
  271. static BOOL ldm_compare_tocblocks (const struct tocblock *toc1,
  272.    const struct tocblock *toc2)
  273. {
  274. BUG_ON (!toc1);
  275. BUG_ON (!toc2);
  276. return ((toc1->bitmap1_start == toc2->bitmap1_start) &&
  277. (toc1->bitmap1_size  == toc2->bitmap1_size) &&
  278. (toc1->bitmap2_start == toc2->bitmap2_start) &&
  279. (toc1->bitmap2_size  == toc2->bitmap2_size) &&
  280. !strncmp (toc1->bitmap1_name, toc2->bitmap1_name,
  281. sizeof (toc1->bitmap1_name)) &&
  282. !strncmp (toc1->bitmap2_name, toc2->bitmap2_name,
  283. sizeof (toc1->bitmap2_name)));
  284. }
  285. /**
  286.  * ldm_validate_privheads - Compare the primary privhead with its backups
  287.  * @bdev:  Device holding the LDM Database
  288.  * @ph1:   Memory struct to fill with ph contents
  289.  *
  290.  * Read and compare all three privheads from disk.
  291.  *
  292.  * The privheads on disk show the size and location of the main disk area and
  293.  * the configuration area (the database).
  294.  *
  295.  * Return:  TRUE   Success
  296.  *          FALSE  Error
  297.  */
  298. static BOOL ldm_validate_privheads (struct block_device *bdev,
  299. unsigned long first_sector, struct privhead *ph1, struct gendisk *hd,
  300. unsigned long first_minor)
  301. {
  302. static const int off[3] = { OFF_PRIV1, OFF_PRIV2, OFF_PRIV3 };
  303. struct privhead *ph[3] = { ph1 };
  304. Sector sect;
  305. u8 *data;
  306. BOOL result = FALSE;
  307. long num_sects;
  308. int i;
  309. BUG_ON (!bdev);
  310. BUG_ON (!ph1);
  311. ph[1] = kmalloc (sizeof (*ph[1]), GFP_KERNEL);
  312. ph[2] = kmalloc (sizeof (*ph[2]), GFP_KERNEL);
  313. if (!ph[1] || !ph[2]) {
  314. ldm_crit ("Out of memory.");
  315. goto out;
  316. }
  317. /* off[1 & 2] are relative to ph[0]->config_start */
  318. ph[0]->config_start = 0;
  319. /* Read and parse privheads */
  320. for (i = 0; i < 3; i++) {
  321. data = read_dev_sector (bdev,
  322. first_sector + ph[0]->config_start + off[i], &sect);
  323. if (!data) {
  324. ldm_crit ("Disk read failed.");
  325. goto out;
  326. }
  327. result = ldm_parse_privhead (data, ph[i]);
  328. put_dev_sector (sect);
  329. if (!result) {
  330. ldm_error ("Cannot find PRIVHEAD %d.", i+1); /* Log again */
  331. if (i < 2)
  332. goto out; /* Already logged */
  333. else
  334. break; /* FIXME ignore for now, 3rd PH can fail on odd-sized disks */
  335. }
  336. }
  337. num_sects = hd->part[(first_minor >> hd->minor_shift)
  338. << hd->minor_shift].nr_sects;
  339. if ((ph[0]->config_start > num_sects) ||
  340.    ((ph[0]->config_start + ph[0]->config_size) > num_sects)) {
  341. ldm_crit ("Database extends beyond the end of the disk.");
  342. goto out;
  343. }
  344. if ((ph[0]->logical_disk_start > ph[0]->config_start) ||
  345.    ((ph[0]->logical_disk_start + ph[0]->logical_disk_size)
  346.     > ph[0]->config_start)) {
  347. ldm_crit ("Disk and database overlap.");
  348. goto out;
  349. }
  350. if (!ldm_compare_privheads (ph[0], ph[1])) {
  351. ldm_crit ("Primary and backup PRIVHEADs don't match.");
  352. goto out;
  353. }
  354. /* FIXME ignore this for now
  355. if (!ldm_compare_privheads (ph[0], ph[2])) {
  356. ldm_crit ("Primary and backup PRIVHEADs don't match.");
  357. goto out;
  358. }*/
  359. ldm_debug ("Validated PRIVHEADs successfully.");
  360. result = TRUE;
  361. out:
  362. kfree (ph[1]);
  363. kfree (ph[2]);
  364. return result;
  365. }
  366. /**
  367.  * ldm_validate_tocblocks - Validate the table of contents and its backups
  368.  * @bdev:  Device holding the LDM Database
  369.  * @base:  Offset, into @bdev, of the database
  370.  * @ldb:   Cache of the database structures
  371.  *
  372.  * Find and compare the four tables of contents of the LDM Database stored on
  373.  * @bdev and return the parsed information into @toc1.
  374.  *
  375.  * The offsets and sizes of the configs are range-checked against a privhead.
  376.  *
  377.  * Return:  TRUE   @toc1 contains validated TOCBLOCK info
  378.  *          FALSE  @toc1 contents are undefined
  379.  */
  380. static BOOL ldm_validate_tocblocks (struct block_device *bdev,
  381. unsigned long base, struct ldmdb *ldb)
  382. {
  383. static const int off[4] = { OFF_TOCB1, OFF_TOCB2, OFF_TOCB3, OFF_TOCB4};
  384. struct tocblock *tb[4];
  385. struct privhead *ph;
  386. Sector sect;
  387. u8 *data;
  388. BOOL result = FALSE;
  389. int i;
  390. BUG_ON (!bdev);
  391. BUG_ON (!ldb);
  392. ph    = &ldb->ph;
  393. tb[0] = &ldb->toc;
  394. tb[1] = kmalloc (sizeof (*tb[1]), GFP_KERNEL);
  395. tb[2] = kmalloc (sizeof (*tb[2]), GFP_KERNEL);
  396. tb[3] = kmalloc (sizeof (*tb[3]), GFP_KERNEL);
  397. if (!tb[1] || !tb[2] || !tb[3]) {
  398. ldm_crit ("Out of memory.");
  399. goto out;
  400. }
  401. for (i = 0; i < 4; i++) /* Read and parse all four toc's. */
  402. {
  403. data = read_dev_sector (bdev, base + off[i], &sect);
  404. if (!data) {
  405. ldm_crit ("Disk read failed.");
  406. goto out;
  407. }
  408. result = ldm_parse_tocblock (data, tb[i]);
  409. put_dev_sector (sect);
  410. if (!result)
  411. goto out; /* Already logged */
  412. }
  413. /* Range check the toc against a privhead. */
  414. if (((tb[0]->bitmap1_start + tb[0]->bitmap1_size) > ph->config_size) ||
  415.     ((tb[0]->bitmap2_start + tb[0]->bitmap2_size) > ph->config_size)) {
  416. ldm_crit ("The bitmaps are out of range.  Giving up.");
  417. goto out;
  418. }
  419. if (!ldm_compare_tocblocks (tb[0], tb[1]) || /* Compare all tocs. */
  420.     !ldm_compare_tocblocks (tb[0], tb[2]) ||
  421.     !ldm_compare_tocblocks (tb[0], tb[3])) {
  422. ldm_crit ("The TOCBLOCKs don't match.");
  423. goto out;
  424. }
  425. ldm_debug ("Validated TOCBLOCKs successfully.");
  426. result = TRUE;
  427. out:
  428. kfree (tb[1]);
  429. kfree (tb[2]);
  430. kfree (tb[3]);
  431. return result;
  432. }
  433. /**
  434.  * ldm_validate_vmdb - Read the VMDB and validate it
  435.  * @bdev:  Device holding the LDM Database
  436.  * @base:  Offset, into @bdev, of the database
  437.  * @ldb:   Cache of the database structures
  438.  *
  439.  * Find the vmdb of the LDM Database stored on @bdev and return the parsed
  440.  * information in @ldb.
  441.  *
  442.  * Return:  TRUE   @ldb contains validated VBDB info
  443.  *          FALSE  @ldb contents are undefined
  444.  */
  445. static BOOL ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
  446.        struct ldmdb *ldb)
  447. {
  448. Sector sect;
  449. u8 *data;
  450. BOOL result = FALSE;
  451. struct vmdb *vm;
  452. struct tocblock *toc;
  453. BUG_ON (!bdev);
  454. BUG_ON (!ldb);
  455. vm  = &ldb->vm;
  456. toc = &ldb->toc;
  457. data = read_dev_sector (bdev, base + OFF_VMDB, &sect);
  458. if (!data) {
  459. ldm_crit ("Disk read failed.");
  460. return FALSE;
  461. }
  462. if (!ldm_parse_vmdb (data, vm))
  463. goto out; /* Already logged */
  464. /* Are there uncommitted transactions? */
  465. if (BE16(data + 0x10) != 0x01) {
  466. ldm_crit ("Database is not in a consistant state.  Aborting.");
  467. goto out;
  468. }
  469. if (vm->vblk_offset != 512)
  470. ldm_info ("VBLKs start at offset 0x%04x.", vm->vblk_offset);
  471. /* FIXME: How should we handle this situation? */
  472. if ((vm->vblk_size * vm->last_vblk_seq) != (toc->bitmap1_size << 9))
  473. ldm_info ("VMDB and TOCBLOCK don't agree on the database size.");
  474. result = TRUE;
  475. out:
  476. put_dev_sector (sect);
  477. return result;
  478. }
  479. /**
  480.  * ldm_validate_partition_table - Determine whether bdev might be a dynamic disk
  481.  * @bdev:  Device holding the LDM Database
  482.  *
  483.  * This function provides a weak test to decide whether the device is a dynamic
  484.  * disk or not.  It looks for an MS-DOS-style partition table containing at
  485.  * least one partition of type 0x42 (formerly SFS, now used by Windows for
  486.  * dynamic disks).
  487.  *
  488.  * N.B.  The only possible error can come from the read_dev_sector and that is
  489.  *       only likely to happen if the underlying device is strange.  If that IS
  490.  *       the case we should return zero to let someone else try.
  491.  *
  492.  * Return:  TRUE   @bdev is a dynamic disk
  493.  *          FALSE  @bdev is not a dynamic disk, or an error occurred
  494.  */
  495. static BOOL ldm_validate_partition_table (struct block_device *bdev)
  496. {
  497. Sector sect;
  498. u8 *data;
  499. struct partition *p;
  500. int i;
  501. BOOL result = FALSE;
  502. BUG_ON (!bdev);
  503. data = read_dev_sector (bdev, 0, &sect);
  504. if (!data) {
  505. ldm_crit ("Disk read failed.");
  506. return FALSE;
  507. }
  508. if (*(u16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC)) {
  509. ldm_debug ("No MS-DOS partition table found.");
  510. goto out;
  511. }
  512. p = (struct partition*)(data + 0x01BE);
  513. for (i = 0; i < 4; i++, p++)
  514. if (SYS_IND (p) == WIN2K_DYNAMIC_PARTITION) {
  515. result = TRUE;
  516. break;
  517. }
  518. if (result)
  519. ldm_debug ("Parsed partition table successfully.");
  520. else
  521. ldm_debug ("Found an MS-DOS partition table, not a dynamic disk.");
  522. out:
  523. put_dev_sector (sect);
  524. return result;
  525. }
  526. /**
  527.  * ldm_get_disk_objid - Search a linked list of vblk's for a given Disk Id
  528.  * @ldb:  Cache of the database structures
  529.  *
  530.  * The LDM Database contains a list of all partitions on all dynamic disks.  The
  531.  * primary PRIVHEAD, at the beginning of the physical disk, tells us the GUID of
  532.  * this disk.  This function searches for the GUID in a linked list of vblk's.
  533.  *
  534.  * Return:  Pointer, A matching vblk was found
  535.  *          NULL,    No match, or an error
  536.  */
  537. static struct vblk * ldm_get_disk_objid (const struct ldmdb *ldb)
  538. {
  539. struct list_head *item;
  540. BUG_ON (!ldb);
  541. list_for_each (item, &ldb->v_disk) {
  542. struct vblk *v = list_entry (item, struct vblk, list);
  543. if (!memcmp (v->vblk.disk.disk_id, ldb->ph.disk_id, GUID_SIZE))
  544. return v;
  545. }
  546. return NULL;
  547. }
  548. /**
  549.  * ldm_create_partition - Create a kernel partition device
  550.  * @hd:     gendisk structure in which to create partition
  551.  * @minor:  Create a this minor number on the device
  552.  * @start:  Offset (in sectors) into the device of the partition
  553.  * @size:   Size (in sectors) of the partition
  554.  *
  555.  * This validates the range, then puts an entry into the kernel's partition
  556.  * table.
  557.  *
  558.  * Return:  TRUE   Created the partition
  559.  *          FALSE  Error
  560.  */
  561. static BOOL ldm_create_partition (struct gendisk *hd, int minor, int start,
  562.   int size)
  563. {
  564. int disk_minor;
  565. BUG_ON (!hd);;
  566. BUG_ON (!hd->part);
  567. /* Get the minor number of the parent device
  568.  * so we can check we don't go beyond the end of the device.  */
  569. disk_minor = (minor >> hd->minor_shift) << hd->minor_shift;
  570. if ((start < 1) || ((start + size) > hd->part[disk_minor].nr_sects)) {
  571. ldm_crit ("Partition exceeds physical disk. Aborting.");
  572. return FALSE;
  573. }
  574. add_gd_partition (hd, minor, start, size);
  575. ldm_debug ("Created partition successfully.");
  576. return TRUE;
  577. }
  578. /**
  579.  * ldm_create_data_partitions - Create data partitions for this device
  580.  * @pp:   List of the partitions parsed so far
  581.  * @ldb:  Cache of the database structures
  582.  *
  583.  * The database contains ALL the partitions for ALL disk groups, so we need to
  584.  * filter out this specific disk. Using the disk's object id, we can find all
  585.  * the partitions in the database that belong to this disk.
  586.  *
  587.  * Add each partition in our database, to the parsed_partitions structure.
  588.  *
  589.  * N.B.  This function creates the partitions in the order it finds partition
  590.  *       objects in the linked list.
  591.  *
  592.  * Return:  TRUE   Partition created
  593.  *          FALSE  Error, probably a range checking problem
  594.  */
  595. static BOOL ldm_create_data_partitions (struct gendisk *hd,
  596. unsigned long first_sector, int first_minor, const struct ldmdb *ldb)
  597. {
  598. struct list_head *item;
  599. struct vblk_part *part;
  600. struct vblk *disk;
  601. int disk_minor;
  602. int minor;
  603. BUG_ON (!hd);
  604. BUG_ON (!ldb);
  605. disk = ldm_get_disk_objid (ldb);
  606. if (!disk) {
  607. ldm_crit ("Can't find the ID of this disk in the database.");
  608. return FALSE;
  609. }
  610. /* We use the range-check the partitions against the parent device. */
  611. disk_minor = (first_minor >> hd->minor_shift) << hd->minor_shift;
  612. minor = first_minor;
  613. printk (" [LDM]");
  614. /* Create the data partitions */
  615. list_for_each (item, &ldb->v_part) {
  616. struct vblk *vb;
  617. vb = list_entry (item, struct vblk, list);
  618. part = &vb->vblk.part;
  619. if (part->disk_id != disk->obj_id)
  620. continue;
  621. if (!ldm_create_partition (hd, minor,
  622.     part->start + ldb->ph.logical_disk_start, part->size))
  623. continue; /* Already logged */
  624. minor++;
  625. }
  626. printk ("n");
  627. return TRUE;
  628. }
  629. /**
  630.  * ldm_relative - Calculate the next relative offset
  631.  * @buffer:  Block of data being worked on
  632.  * @buflen:  Size of the block of data
  633.  * @base:    Size of the previous fixed width fields
  634.  * @offset:  Cumulative size of the previous variable-width fields
  635.  *
  636.  * Because many of the VBLK fields are variable-width, it's necessary
  637.  * to calculate each offset based on the previous one and the length
  638.  * of the field it pointed to.
  639.  *
  640.  * Return:  -1 Error, the calculated offset exceeded the size of the buffer
  641.  *           n OK, a range-checked offset into buffer
  642.  */
  643. static int ldm_relative (const u8 *buffer, int buflen, int base, int offset)
  644. {
  645. base += offset;
  646. if ((!buffer) || (offset < 0) || (base > buflen))
  647. return -1;
  648. if ((base + buffer[base]) >= buflen)
  649. return -1;
  650. return buffer[base] + offset + 1;
  651. }
  652. /**
  653.  * ldm_get_vnum - Convert a variable-width, big endian number, into cpu order
  654.  * @block:  Pointer to the variable-width number to convert
  655.  *
  656.  * Large numbers in the LDM Database are often stored in a packed format.  Each
  657.  * number is prefixed by a one byte width marker.  All numbers in the database
  658.  * are stored in big-endian byte order.  This function reads one of these
  659.  * numbers and returns the result
  660.  *
  661.  * N.B.  This function DOES NOT perform any range checking, though the most
  662.  *       it will read is eight bytes.
  663.  *
  664.  * Return:  n A number
  665.  *          0 Zero, or an error occurred
  666.  */
  667. static u64 ldm_get_vnum (const u8 *block)
  668. {
  669. u64 tmp = 0;
  670. u8 length;
  671. BUG_ON (!block);
  672. length = *block++;
  673. if (length && length <= 8)
  674. while (length--)
  675. tmp = (tmp << 8) | *block++;
  676. else
  677. ldm_error ("Illegal length %d.", length);
  678. return tmp;
  679. }
  680. /**
  681.  * ldm_get_vstr - Read a length-prefixed string into a buffer
  682.  * @block:   Pointer to the length marker
  683.  * @buffer:  Location to copy string to
  684.  * @buflen:  Size of the output buffer
  685.  *
  686.  * Many of the strings in the LDM Database are not NULL terminated.  Instead
  687.  * they are prefixed by a one byte length marker.  This function copies one of
  688.  * these strings into a buffer.
  689.  *
  690.  * N.B.  This function DOES NOT perform any range checking on the input.
  691.  *       If the buffer is too small, the output will be truncated.
  692.  *
  693.  * Return:  0, Error and @buffer contents are undefined
  694.  *          n, String length in characters (excluding NULL)
  695.  *          buflen-1, String was truncated.
  696.  */
  697. static int ldm_get_vstr (const u8 *block, u8 *buffer, int buflen)
  698. {
  699. int length;
  700. BUG_ON (!block);
  701. BUG_ON (!buffer);
  702. length = block[0];
  703. if (length >= buflen) {
  704. ldm_error ("Truncating string %d -> %d.", length, buflen);
  705. length = buflen - 1;
  706. }
  707. memcpy (buffer, block + 1, length);
  708. buffer[length] = 0;
  709. return length;
  710. }
  711. /**
  712.  * ldm_parse_cmp3 - Read a raw VBLK Component object into a vblk structure
  713.  * @buffer:  Block of data being worked on
  714.  * @buflen:  Size of the block of data
  715.  * @vb:      In-memory vblk in which to return information
  716.  *
  717.  * Read a raw VBLK Component object (version 3) into a vblk structure.
  718.  *
  719.  * Return:  TRUE   @vb contains a Component VBLK
  720.  *          FALSE  @vb contents are not defined
  721.  */
  722. static BOOL ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
  723. {
  724. int r_objid, r_name, r_vstate, r_child, r_parent, r_stripe, r_cols, len;
  725. struct vblk_comp *comp;
  726. BUG_ON (!buffer);
  727. BUG_ON (!vb);
  728. r_objid  = ldm_relative (buffer, buflen, 0x18, 0);
  729. r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);
  730. r_vstate = ldm_relative (buffer, buflen, 0x18, r_name);
  731. r_child  = ldm_relative (buffer, buflen, 0x1D, r_vstate);
  732. r_parent = ldm_relative (buffer, buflen, 0x2D, r_child);
  733. if (buffer[0x12] & VBLK_FLAG_COMP_STRIPE) {
  734. r_stripe = ldm_relative (buffer, buflen, 0x2E, r_parent);
  735. r_cols   = ldm_relative (buffer, buflen, 0x2E, r_stripe);
  736. len = r_cols;
  737. } else {
  738. r_stripe = 0;
  739. r_cols   = 0;
  740. len = r_parent;
  741. }
  742. if (len < 0)
  743. return FALSE;
  744. len += VBLK_SIZE_CMP3;
  745. if (len != BE32 (buffer + 0x14))
  746. return FALSE;
  747. comp = &vb->vblk.comp;
  748. ldm_get_vstr (buffer + 0x18 + r_name, comp->state,
  749. sizeof (comp->state));
  750. comp->type      = buffer[0x18 + r_vstate];
  751. comp->children  = ldm_get_vnum (buffer + 0x1D + r_vstate);
  752. comp->parent_id = ldm_get_vnum (buffer + 0x2D + r_child);
  753. comp->chunksize = r_stripe ? ldm_get_vnum (buffer+r_parent+0x2E) : 0;
  754. return TRUE;
  755. }
  756. /**
  757.  * ldm_parse_dgr3 - Read a raw VBLK Disk Group object into a vblk structure
  758.  * @buffer:  Block of data being worked on
  759.  * @buflen:  Size of the block of data
  760.  * @vb:      In-memory vblk in which to return information
  761.  *
  762.  * Read a raw VBLK Disk Group object (version 3) into a vblk structure.
  763.  *
  764.  * Return:  TRUE   @vb contains a Disk Group VBLK
  765.  *          FALSE  @vb contents are not defined
  766.  */
  767. static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb)
  768. {
  769. int r_objid, r_name, r_diskid, r_id1, r_id2, len;
  770. struct vblk_dgrp *dgrp;
  771. BUG_ON (!buffer);
  772. BUG_ON (!vb);
  773. r_objid  = ldm_relative (buffer, buflen, 0x18, 0);
  774. r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);
  775. r_diskid = ldm_relative (buffer, buflen, 0x18, r_name);
  776. if (buffer[0x12] & VBLK_FLAG_DGR3_IDS) {
  777. r_id1 = ldm_relative (buffer, buflen, 0x24, r_diskid);
  778. r_id2 = ldm_relative (buffer, buflen, 0x24, r_id1);
  779. len = r_id2;
  780. } else {
  781. r_id1 = 0;
  782. r_id2 = 0;
  783. len = r_diskid;
  784. }
  785. if (len < 0)
  786. return FALSE;
  787. len += VBLK_SIZE_DGR3;
  788. if (len != BE32 (buffer + 0x14))
  789. return FALSE;
  790. dgrp = &vb->vblk.dgrp;
  791. ldm_get_vstr (buffer + 0x18 + r_name, dgrp->disk_id,
  792. sizeof (dgrp->disk_id));
  793. return TRUE;
  794. }
  795. /**
  796.  * ldm_parse_dgr4 - Read a raw VBLK Disk Group object into a vblk structure
  797.  * @buffer:  Block of data being worked on
  798.  * @buflen:  Size of the block of data
  799.  * @vb:      In-memory vblk in which to return information
  800.  *
  801.  * Read a raw VBLK Disk Group object (version 4) into a vblk structure.
  802.  *
  803.  * Return:  TRUE   @vb contains a Disk Group VBLK
  804.  *          FALSE  @vb contents are not defined
  805.  */
  806. static BOOL ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb)
  807. {
  808. char buf[64];
  809. int r_objid, r_name, r_id1, r_id2, len;
  810. struct vblk_dgrp *dgrp;
  811. BUG_ON (!buffer);
  812. BUG_ON (!vb);
  813. r_objid  = ldm_relative (buffer, buflen, 0x18, 0);
  814. r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);
  815. if (buffer[0x12] & VBLK_FLAG_DGR4_IDS) {
  816. r_id1 = ldm_relative (buffer, buflen, 0x44, r_name);
  817. r_id2 = ldm_relative (buffer, buflen, 0x44, r_id1);
  818. len = r_id2;
  819. } else {
  820. r_id1 = 0;
  821. r_id2 = 0;
  822. len = r_name;
  823. }
  824. if (len < 0)
  825. return FALSE;
  826. len += VBLK_SIZE_DGR4;
  827. if (len != BE32 (buffer + 0x14))
  828. return FALSE;
  829. dgrp = &vb->vblk.dgrp;
  830. ldm_get_vstr (buffer + 0x18 + r_objid, buf, sizeof (buf));
  831. return TRUE;
  832. }
  833. /**
  834.  * ldm_parse_dsk3 - Read a raw VBLK Disk object into a vblk structure
  835.  * @buffer:  Block of data being worked on
  836.  * @buflen:  Size of the block of data
  837.  * @vb:      In-memory vblk in which to return information
  838.  *
  839.  * Read a raw VBLK Disk object (version 3) into a vblk structure.
  840.  *
  841.  * Return:  TRUE   @vb contains a Disk VBLK
  842.  *          FALSE  @vb contents are not defined
  843.  */
  844. static BOOL ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb)
  845. {
  846. int r_objid, r_name, r_diskid, r_altname, len;
  847. struct vblk_disk *disk;
  848. BUG_ON (!buffer);
  849. BUG_ON (!vb);
  850. r_objid   = ldm_relative (buffer, buflen, 0x18, 0);
  851. r_name    = ldm_relative (buffer, buflen, 0x18, r_objid);
  852. r_diskid  = ldm_relative (buffer, buflen, 0x18, r_name);
  853. r_altname = ldm_relative (buffer, buflen, 0x18, r_diskid);
  854. len = r_altname;
  855. if (len < 0)
  856. return FALSE;
  857. len += VBLK_SIZE_DSK3;
  858. if (len != BE32 (buffer + 0x14))
  859. return FALSE;
  860. disk = &vb->vblk.disk;
  861. ldm_get_vstr (buffer + 0x18 + r_diskid, disk->alt_name,
  862. sizeof (disk->alt_name));
  863. if (!ldm_parse_guid (buffer + 0x19 + r_name, disk->disk_id))
  864. return FALSE;
  865. return TRUE;
  866. }
  867. /**
  868.  * ldm_parse_dsk4 - Read a raw VBLK Disk object into a vblk structure
  869.  * @buffer:  Block of data being worked on
  870.  * @buflen:  Size of the block of data
  871.  * @vb:      In-memory vblk in which to return information
  872.  *
  873.  * Read a raw VBLK Disk object (version 4) into a vblk structure.
  874.  *
  875.  * Return:  TRUE   @vb contains a Disk VBLK
  876.  *          FALSE  @vb contents are not defined
  877.  */
  878. static BOOL ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
  879. {
  880. int r_objid, r_name, len;
  881. struct vblk_disk *disk;
  882. BUG_ON (!buffer);
  883. BUG_ON (!vb);
  884. r_objid = ldm_relative (buffer, buflen, 0x18, 0);
  885. r_name  = ldm_relative (buffer, buflen, 0x18, r_objid);
  886. len     = r_name;
  887. if (len < 0)
  888. return FALSE;
  889. len += VBLK_SIZE_DSK4;
  890. if (len != BE32 (buffer + 0x14))
  891. return FALSE;
  892. disk = &vb->vblk.disk;
  893. memcpy (disk->disk_id, buffer + 0x18 + r_name, GUID_SIZE);
  894. return TRUE;
  895. }
  896. /**
  897.  * ldm_parse_prt3 - Read a raw VBLK Partition object into a vblk structure
  898.  * @buffer:  Block of data being worked on
  899.  * @buflen:  Size of the block of data
  900.  * @vb:      In-memory vblk in which to return information
  901.  *
  902.  * Read a raw VBLK Partition object (version 3) into a vblk structure.
  903.  *
  904.  * Return:  TRUE   @vb contains a Partition VBLK
  905.  *          FALSE  @vb contents are not defined
  906.  */
  907. static BOOL ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb)
  908. {
  909. int r_objid, r_name, r_size, r_parent, r_diskid, r_index, len;
  910. struct vblk_part *part;
  911. BUG_ON (!buffer);
  912. BUG_ON (!vb);
  913. r_objid  = ldm_relative (buffer, buflen, 0x18, 0);
  914. r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);
  915. r_size   = ldm_relative (buffer, buflen, 0x34, r_name);
  916. r_parent = ldm_relative (buffer, buflen, 0x34, r_size);
  917. r_diskid = ldm_relative (buffer, buflen, 0x34, r_parent);
  918. if (buffer[0x12] & VBLK_FLAG_PART_INDEX) {
  919. r_index = ldm_relative (buffer, buflen, 0x34, r_diskid);
  920. len = r_index;
  921. } else {
  922. r_index = 0;
  923. len = r_diskid;
  924. }
  925. if (len < 0)
  926. return FALSE;
  927. len += VBLK_SIZE_PRT3;
  928. if (len != BE32 (buffer + 0x14))
  929. return FALSE;
  930. part = &vb->vblk.part;
  931. part->start         = BE64         (buffer + 0x24 + r_name);
  932. part->volume_offset = BE64         (buffer + 0x2C + r_name);
  933. part->size          = ldm_get_vnum (buffer + 0x34 + r_name);
  934. part->parent_id     = ldm_get_vnum (buffer + 0x34 + r_size);
  935. part->disk_id       = ldm_get_vnum (buffer + 0x34 + r_parent);
  936. if (vb->flags & VBLK_FLAG_PART_INDEX)
  937. part->partnum = buffer[0x35 + r_diskid];
  938. else
  939. part->partnum = 0;
  940. return TRUE;
  941. }
  942. /**
  943.  * ldm_parse_vol5 - Read a raw VBLK Volume object into a vblk structure
  944.  * @buffer:  Block of data being worked on
  945.  * @buflen:  Size of the block of data
  946.  * @vb:      In-memory vblk in which to return information
  947.  *
  948.  * Read a raw VBLK Volume object (version 5) into a vblk structure.
  949.  *
  950.  * Return:  TRUE   @vb contains a Volume VBLK
  951.  *          FALSE  @vb contents are not defined
  952.  */
  953. static BOOL ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
  954. {
  955. int r_objid, r_name, r_vtype, r_child, r_size, r_id1, r_id2, r_size2;
  956. int r_drive, len;
  957. struct vblk_volu *volu;
  958. BUG_ON (!buffer);
  959. BUG_ON (!vb);
  960. r_objid  = ldm_relative (buffer, buflen, 0x18, 0);
  961. r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);
  962. r_vtype  = ldm_relative (buffer, buflen, 0x18, r_name);
  963. r_child  = ldm_relative (buffer, buflen, 0x2E, r_vtype);
  964. r_size   = ldm_relative (buffer, buflen, 0x3E, r_child);
  965. if (buffer[0x12] & VBLK_FLAG_VOLU_ID1)
  966. r_id1 = ldm_relative (buffer, buflen, 0x53, r_size);
  967. else
  968. r_id1 = r_size;
  969. if (buffer[0x12] & VBLK_FLAG_VOLU_ID2)
  970. r_id2 = ldm_relative (buffer, buflen, 0x53, r_id1);
  971. else
  972. r_id2 = r_id1;
  973. if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE)
  974. r_size2 = ldm_relative (buffer, buflen, 0x53, r_id2);
  975. else
  976. r_size2 = r_id2;
  977. if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE)
  978. r_drive = ldm_relative (buffer, buflen, 0x53, r_size2);
  979. else
  980. r_drive = r_size2;
  981. len = r_drive;
  982. if (len < 0)
  983. return FALSE;
  984. len += VBLK_SIZE_VOL5;
  985. if (len != BE32 (buffer + 0x14))
  986. return FALSE;
  987. volu = &vb->vblk.volu;
  988. ldm_get_vstr (buffer + 0x18 + r_name,  volu->volume_type,
  989. sizeof (volu->volume_type));
  990. memcpy (volu->volume_state, buffer + 0x19 + r_vtype,
  991. sizeof (volu->volume_state));
  992. volu->size = ldm_get_vnum (buffer + 0x3E + r_child);
  993. volu->partition_type = buffer[0x42 + r_size];
  994. memcpy (volu->guid, buffer + 0x43 + r_size,  sizeof (volu->guid));
  995. if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) {
  996. ldm_get_vstr (buffer + 0x53 + r_size,  volu->drive_hint,
  997. sizeof (volu->drive_hint));
  998. }
  999. return TRUE;
  1000. }
  1001. /**
  1002.  * ldm_parse_vblk - Read a raw VBLK object into a vblk structure
  1003.  * @buf:  Block of data being worked on
  1004.  * @len:  Size of the block of data
  1005.  * @vb:   In-memory vblk in which to return information
  1006.  *
  1007.  * Read a raw VBLK object into a vblk structure.  This function just reads the
  1008.  * information common to all VBLK types, then delegates the rest of the work to
  1009.  * helper functions: ldm_parse_*.
  1010.  *
  1011.  * Return:  TRUE   @vb contains a VBLK
  1012.  *          FALSE  @vb contents are not defined
  1013.  */
  1014. static BOOL ldm_parse_vblk (const u8 *buf, int len, struct vblk *vb)
  1015. {
  1016. BOOL result = FALSE;
  1017. int r_objid;
  1018. BUG_ON (!buf);
  1019. BUG_ON (!vb);
  1020. r_objid = ldm_relative (buf, len, 0x18, 0);
  1021. if (r_objid < 0) {
  1022. ldm_error ("VBLK header is corrupt.");
  1023. return FALSE;
  1024. }
  1025. vb->flags  = buf[0x12];
  1026. vb->type   = buf[0x13];
  1027. vb->obj_id = ldm_get_vnum (buf + 0x18);
  1028. ldm_get_vstr (buf+0x18+r_objid, vb->name, sizeof (vb->name));
  1029. switch (vb->type) {
  1030. case VBLK_CMP3:  result = ldm_parse_cmp3 (buf, len, vb); break;
  1031. case VBLK_DSK3:  result = ldm_parse_dsk3 (buf, len, vb); break;
  1032. case VBLK_DSK4:  result = ldm_parse_dsk4 (buf, len, vb); break;
  1033. case VBLK_DGR3:  result = ldm_parse_dgr3 (buf, len, vb); break;
  1034. case VBLK_DGR4:  result = ldm_parse_dgr4 (buf, len, vb); break;
  1035. case VBLK_PRT3:  result = ldm_parse_prt3 (buf, len, vb); break;
  1036. case VBLK_VOL5:  result = ldm_parse_vol5 (buf, len, vb); break;
  1037. }
  1038. if (result)
  1039. ldm_debug ("Parsed VBLK 0x%llx (type: 0x%02x) ok.",
  1040.  (unsigned long long) vb->obj_id, vb->type);
  1041. else
  1042. ldm_error ("Failed to parse VBLK 0x%llx (type: 0x%02x).",
  1043. (unsigned long long) vb->obj_id, vb->type);
  1044. return result;
  1045. }
  1046. /**
  1047.  * ldm_ldmdb_add - Adds a raw VBLK entry to the ldmdb database
  1048.  * @data:  Raw VBLK to add to the database
  1049.  * @len:   Size of the raw VBLK
  1050.  * @ldb:   Cache of the database structures
  1051.  *
  1052.  * The VBLKs are sorted into categories.  Partitions are also sorted by offset.
  1053.  *
  1054.  * N.B.  This function does not check the validity of the VBLKs.
  1055.  *
  1056.  * Return:  TRUE   The VBLK was added
  1057.  *          FALSE  An error occurred
  1058.  */
  1059. static BOOL ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb)
  1060. {
  1061. struct vblk *vb;
  1062. struct list_head *item;
  1063. BUG_ON (!data);
  1064. BUG_ON (!ldb);
  1065. vb = kmalloc (sizeof (*vb), GFP_KERNEL);
  1066. if (!vb) {
  1067. ldm_crit ("Out of memory.");
  1068. return FALSE;
  1069. }
  1070. if (!ldm_parse_vblk (data, len, vb))
  1071. return FALSE; /* Already logged */
  1072. /* Put vblk into the correct list. */
  1073. switch (vb->type) {
  1074. case VBLK_DGR3:
  1075. case VBLK_DGR4:
  1076. list_add (&vb->list, &ldb->v_dgrp);
  1077. break;
  1078. case VBLK_DSK3:
  1079. case VBLK_DSK4:
  1080. list_add (&vb->list, &ldb->v_disk);
  1081. break;
  1082. case VBLK_VOL5:
  1083. list_add (&vb->list, &ldb->v_volu);
  1084. break;
  1085. case VBLK_CMP3:
  1086. list_add (&vb->list, &ldb->v_comp);
  1087. break;
  1088. case VBLK_PRT3:
  1089. /* Sort by the partition's start sector. */
  1090. list_for_each (item, &ldb->v_part) {
  1091. struct vblk *v = list_entry (item, struct vblk, list);
  1092. if ((v->vblk.part.disk_id == vb->vblk.part.disk_id) &&
  1093.     (v->vblk.part.start > vb->vblk.part.start)) {
  1094. list_add_tail (&vb->list, &v->list);
  1095. return TRUE;
  1096. }
  1097. }
  1098. list_add_tail (&vb->list, &ldb->v_part);
  1099. break;
  1100. }
  1101. return TRUE;
  1102. }
  1103. /**
  1104.  * ldm_frag_add - Add a VBLK fragment to a list
  1105.  * @data:   Raw fragment to be added to the list
  1106.  * @size:   Size of the raw fragment
  1107.  * @frags:  Linked list of VBLK fragments
  1108.  *
  1109.  * Fragmented VBLKs may not be consecutive in the database, so they are placed
  1110.  * in a list so they can be pieced together later.
  1111.  *
  1112.  * Return:  TRUE   Success, the VBLK was added to the list
  1113.  *          FALSE  Error, a problem occurred
  1114.  */
  1115. static BOOL ldm_frag_add (const u8 *data, int size, struct list_head *frags)
  1116. {
  1117. struct frag *f;
  1118. struct list_head *item;
  1119. int rec, num, group;
  1120. BUG_ON (!data);
  1121. BUG_ON (!frags);
  1122. group = BE32 (data + 0x08);
  1123. rec   = BE16 (data + 0x0C);
  1124. num   = BE16 (data + 0x0E);
  1125. if ((num < 1) || (num > 4)) {
  1126. ldm_error ("A VBLK claims to have %d parts.", num);
  1127. return FALSE;
  1128. }
  1129. list_for_each (item, frags) {
  1130. f = list_entry (item, struct frag, list);
  1131. if (f->group == group)
  1132. goto found;
  1133. }
  1134. f = kmalloc (sizeof (*f) + size*num, GFP_KERNEL);
  1135. if (!f) {
  1136. ldm_crit ("Out of memory.");
  1137. return FALSE;
  1138. }
  1139. f->group = group;
  1140. f->num   = num;
  1141. f->rec   = rec;
  1142. f->map   = 0xFF << num;
  1143. list_add_tail (&f->list, frags);
  1144. found:
  1145. if (f->map & (1 << rec)) {
  1146. ldm_error ("Duplicate VBLK, part %d.", rec);
  1147. f->map &= 0x7F; /* Mark the group as broken */
  1148. return FALSE;
  1149. }
  1150. f->map |= (1 << rec);
  1151. if (num > 0) {
  1152. data += VBLK_SIZE_HEAD;
  1153. size -= VBLK_SIZE_HEAD;
  1154. }
  1155. memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size);
  1156. return TRUE;
  1157. }
  1158. /**
  1159.  * ldm_frag_free - Free a linked list of VBLK fragments
  1160.  * @list:  Linked list of fragments
  1161.  *
  1162.  * Free a linked list of VBLK fragments
  1163.  *
  1164.  * Return:  none
  1165.  */
  1166. static void ldm_frag_free (struct list_head *list)
  1167. {
  1168. struct list_head *item, *tmp;
  1169. BUG_ON (!list);
  1170. list_for_each_safe (item, tmp, list)
  1171. kfree (list_entry (item, struct frag, list));
  1172. }
  1173. /**
  1174.  * ldm_frag_commit - Validate fragmented VBLKs and add them to the database
  1175.  * @frags:  Linked list of VBLK fragments
  1176.  * @ldb:    Cache of the database structures
  1177.  *
  1178.  * Now that all the fragmented VBLKs have been collected, they must be added to
  1179.  * the database for later use.
  1180.  *
  1181.  * Return:  TRUE   All the fragments we added successfully
  1182.  *          FALSE  One or more of the fragments we invalid
  1183.  */
  1184. static BOOL ldm_frag_commit (struct list_head *frags, struct ldmdb *ldb)
  1185. {
  1186. struct frag *f;
  1187. struct list_head *item;
  1188. BUG_ON (!frags);
  1189. BUG_ON (!ldb);
  1190. list_for_each (item, frags) {
  1191. f = list_entry (item, struct frag, list);
  1192. if (f->map != 0xFF) {
  1193. ldm_error ("VBLK group %d is incomplete (0x%02x).",
  1194. f->group, f->map);
  1195. return FALSE;
  1196. }
  1197. if (!ldm_ldmdb_add (f->data, f->num*ldb->vm.vblk_size, ldb))
  1198. return FALSE; /* Already logged */
  1199. }
  1200. return TRUE;
  1201. }
  1202. /**
  1203.  * ldm_get_vblks - Read the on-disk database of VBLKs into memory
  1204.  * @bdev:  Device holding the LDM Database
  1205.  * @base:  Offset, into @bdev, of the database
  1206.  * @ldb:   Cache of the database structures
  1207.  *
  1208.  * To use the information from the VBLKs, they need to be read from the disk,
  1209.  * unpacked and validated.  We cache them in @ldb according to their type.
  1210.  *
  1211.  * Return:  TRUE   All the VBLKs were read successfully
  1212.  *          FALSE  An error occurred
  1213.  */
  1214. static BOOL ldm_get_vblks (struct block_device *bdev, unsigned long base,
  1215.    struct ldmdb *ldb)
  1216. {
  1217. int size, perbuf, skip, finish, s, v, recs;
  1218. u8 *data = NULL;
  1219. Sector sect;
  1220. BOOL result = FALSE;
  1221. LIST_HEAD (frags);
  1222. BUG_ON (!bdev);
  1223. BUG_ON (!ldb);
  1224. size   = ldb->vm.vblk_size;
  1225. perbuf = 512 / size;
  1226. skip   = ldb->vm.vblk_offset >> 9; /* Bytes to sectors */
  1227. finish = (size * ldb->vm.last_vblk_seq) >> 9;
  1228. for (s = skip; s < finish; s++) { /* For each sector */
  1229. data = read_dev_sector (bdev, base + OFF_VMDB + s, &sect);
  1230. if (!data) {
  1231. ldm_crit ("Disk read failed.");
  1232. goto out;
  1233. }
  1234. for (v = 0; v < perbuf; v++, data+=size) {  /* For each vblk */
  1235. if (MAGIC_VBLK != BE32 (data)) {
  1236. ldm_error ("Expected to find a VBLK.");
  1237. goto out;
  1238. }
  1239. recs = BE16 (data + 0x0E); /* Number of records */
  1240. if (recs == 1) {
  1241. if (!ldm_ldmdb_add (data, size, ldb))
  1242. goto out; /* Already logged */
  1243. } else if (recs > 1) {
  1244. if (!ldm_frag_add (data, size, &frags))
  1245. goto out; /* Already logged */
  1246. }
  1247. /* else Record is not in use, ignore it. */
  1248. }
  1249. put_dev_sector (sect);
  1250. data = NULL;
  1251. }
  1252. result = ldm_frag_commit (&frags, ldb); /* Failures, already logged */
  1253. out:
  1254. if (data)
  1255. put_dev_sector (sect);
  1256. ldm_frag_free (&frags);
  1257. return result;
  1258. }
  1259. /**
  1260.  * ldm_free_vblks - Free a linked list of vblk's
  1261.  * @lh:  Head of a linked list of struct vblk
  1262.  *
  1263.  * Free a list of vblk's and free the memory used to maintain the list.
  1264.  *
  1265.  * Return:  none
  1266.  */
  1267. static void ldm_free_vblks (struct list_head *lh)
  1268. {
  1269. struct list_head *item, *tmp;
  1270. BUG_ON (!lh);
  1271. list_for_each_safe (item, tmp, lh)
  1272. kfree (list_entry (item, struct vblk, list));
  1273. }
  1274. /**
  1275.  * ldm_partition - Find out whether a device is a dynamic disk and handle it
  1276.  * @hd:            gendisk structure in which to return the handled disk
  1277.  * @bdev:          Device we need to look at
  1278.  * @first_sector:  First sector within the device
  1279.  * @first_minor:   First minor number of partitions for the device
  1280.  *
  1281.  * This determines whether the device @bdev is a dynamic disk and if so creates
  1282.  * the partitions necessary in the gendisk structure pointed to by @hd.
  1283.  *
  1284.  * We create a dummy device 1, which contains the LDM database, and then create
  1285.  * each partition described by the LDM database in sequence as devices 2+. For
  1286.  * example, if the device is hda, we would have: hda1: LDM database, hda2, hda3,
  1287.  * and so on: the actual data containing partitions.
  1288.  *
  1289.  * Return:  1 Success, @bdev is a dynamic disk and we handled it
  1290.  *          0 Success, @bdev is not a dynamic disk
  1291.  *         -1 An error occurred before enough information had been read
  1292.  *            Or @bdev is a dynamic disk, but it may be corrupted
  1293.  */
  1294. int ldm_partition (struct gendisk *hd, struct block_device *bdev,
  1295. unsigned long first_sector, int first_minor)
  1296. {
  1297. struct ldmdb  *ldb;
  1298. unsigned long base;
  1299. int result = -1;
  1300. BUG_ON (!hd);
  1301. BUG_ON (!bdev);
  1302. /* Look for signs of a Dynamic Disk */
  1303. if (!ldm_validate_partition_table (bdev))
  1304. return 0;
  1305. ldb = kmalloc (sizeof (*ldb), GFP_KERNEL);
  1306. if (!ldb) {
  1307. ldm_crit ("Out of memory.");
  1308. goto out;
  1309. }
  1310. /* Parse and check privheads. */
  1311. if (!ldm_validate_privheads (bdev, first_sector, &ldb->ph, hd, first_minor))
  1312. goto out; /* Already logged */
  1313. /* All further references are relative to base (database start). */
  1314. base = first_sector + ldb->ph.config_start;
  1315. /* Parse and check tocs and vmdb. */
  1316. if (!ldm_validate_tocblocks (bdev, base, ldb) ||
  1317.     !ldm_validate_vmdb      (bdev, base, ldb))
  1318.      goto out; /* Already logged */
  1319. /* Initialize vblk lists in ldmdb struct */
  1320. INIT_LIST_HEAD (&ldb->v_dgrp);
  1321. INIT_LIST_HEAD (&ldb->v_disk);
  1322. INIT_LIST_HEAD (&ldb->v_volu);
  1323. INIT_LIST_HEAD (&ldb->v_comp);
  1324. INIT_LIST_HEAD (&ldb->v_part);
  1325. if (!ldm_get_vblks (bdev, base, ldb)) {
  1326. ldm_crit ("Failed to read the VBLKs from the database.");
  1327. goto cleanup;
  1328. }
  1329. /* Finally, create the data partition devices. */
  1330. if (ldm_create_data_partitions (hd, first_sector, first_minor, ldb)) {
  1331. ldm_debug ("Parsed LDM database successfully.");
  1332. result = 1;
  1333. }
  1334. /* else Already logged */
  1335. cleanup:
  1336. ldm_free_vblks (&ldb->v_dgrp);
  1337. ldm_free_vblks (&ldb->v_disk);
  1338. ldm_free_vblks (&ldb->v_volu);
  1339. ldm_free_vblks (&ldb->v_comp);
  1340. ldm_free_vblks (&ldb->v_part);
  1341. out:
  1342. kfree (ldb);
  1343. return result;
  1344. }