uuid.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. #include <linux/blkdev.h>
  2. #include <linux/ctype.h>
  3. #include <linux/fs_uuid.h>
  4. #include <linux/slab.h>
  5. #include <linux/export.h>
  6. static int debug_enabled;
  7. #define PRINTK(fmt, args...) do { \
  8. if (debug_enabled) \
  9. pr_debug(fmt, ## args); \
  10. } while (0)
  11. #define PRINT_HEX_DUMP(v1, v2, v3, v4, v5, v6, v7, v8) \
  12. do { \
  13. if (debug_enabled) \
  14. print_hex_dump(v1, v2, v3, v4, v5, v6, v7, v8); \
  15. } while (0)
  16. /*
  17. * Simple UUID translation
  18. */
  19. struct uuid_info {
  20. const char *key;
  21. const char *name;
  22. long bkoff;
  23. unsigned sboff;
  24. unsigned sig_len;
  25. const char *magic;
  26. int uuid_offset;
  27. int last_mount_offset;
  28. int last_mount_size;
  29. };
  30. /*
  31. * Based on libuuid's blkid_magic array. Note that I don't
  32. * have uuid offsets for all of these yet - mssing ones are 0x0.
  33. * Further information welcome.
  34. *
  35. * Rearranged by page of fs signature for optimisation.
  36. */
  37. static struct uuid_info uuid_list[] = {
  38. {NULL, "oracleasm", 0, 32, 8, "ORCLDISK", 0x0, 0, 0},
  39. {"ntfs", "ntfs", 0, 3, 8, "NTFS ", 0x0, 0, 0},
  40. {"vfat", "vfat", 0, 0x52, 5, "MSWIN", 0x0, 0, 0},
  41. {"vfat", "vfat", 0, 0x52, 8, "FAT32 ", 0x0, 0, 0},
  42. {"vfat", "vfat", 0, 0x36, 5, "MSDOS", 0x0, 0, 0},
  43. {"vfat", "vfat", 0, 0x36, 8, "FAT16 ", 0x0, 0, 0},
  44. {"vfat", "vfat", 0, 0x36, 8, "FAT12 ", 0x0, 0, 0},
  45. {"vfat", "vfat", 0, 0, 1, "\353", 0x0, 0, 0},
  46. {"vfat", "vfat", 0, 0, 1, "\351", 0x0, 0, 0},
  47. {"vfat", "vfat", 0, 0x1fe, 2, "\125\252", 0x0, 0, 0},
  48. {"xfs", "xfs", 0, 0, 4, "XFSB", 0x20, 0, 0},
  49. {"romfs", "romfs", 0, 0, 8, "-rom1fs-", 0x0, 0, 0},
  50. {"bfs", "bfs", 0, 0, 4, "\316\372\173\033", 0, 0, 0},
  51. {"cramfs", "cramfs", 0, 0, 4, "E=\315\050", 0x0, 0, 0},
  52. {"qnx4", "qnx4", 0, 4, 6, "QNX4FS", 0, 0, 0},
  53. {NULL, "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", 0x0, 0, 0},
  54. {"squashfs", "squashfs", 0, 0, 4, "sqsh", 0, 0, 0},
  55. {"squashfs", "squashfs", 0, 0, 4, "hsqs", 0, 0, 0},
  56. {"ocfs", "ocfs", 0, 8, 9, "OracleCFS", 0x0, 0, 0},
  57. {"lvm2pv", "lvm2pv", 0, 0x018, 8, "LVM2 001", 0x0, 0, 0},
  58. {"sysv", "sysv", 0, 0x3f8, 4, "\020~\030\375", 0, 0, 0},
  59. {"ext", "ext", 1, 0x38, 2, "\123\357", 0x468, 0x42c, 4},
  60. {"minix", "minix", 1, 0x10, 2, "\177\023", 0, 0, 0},
  61. {"minix", "minix", 1, 0x10, 2, "\217\023", 0, 0, 0},
  62. {"minix", "minix", 1, 0x10, 2, "\150\044", 0, 0, 0},
  63. {"minix", "minix", 1, 0x10, 2, "\170\044", 0, 0, 0},
  64. {"lvm2pv", "lvm2pv", 1, 0x018, 8, "LVM2 001", 0x0, 0, 0},
  65. {"vxfs", "vxfs", 1, 0, 4, "\365\374\001\245", 0, 0, 0},
  66. {"hfsplus", "hfsplus", 1, 0, 2, "BD", 0x0, 0, 0},
  67. {"hfsplus", "hfsplus", 1, 0, 2, "H+", 0x0, 0, 0},
  68. {"hfsplus", "hfsplus", 1, 0, 2, "HX", 0x0, 0, 0},
  69. {"hfs", "hfs", 1, 0, 2, "BD", 0x0, 0, 0},
  70. {"ocfs2", "ocfs2", 1, 0, 6, "OCFSV2", 0x0, 0, 0},
  71. {"lvm2pv", "lvm2pv", 0, 0x218, 8, "LVM2 001", 0x0, 0, 0},
  72. {"lvm2pv", "lvm2pv", 1, 0x218, 8, "LVM2 001", 0x0, 0, 0},
  73. {"ocfs2", "ocfs2", 2, 0, 6, "OCFSV2", 0x0, 0, 0},
  74. {"swap", "swap", 0, 0xff6, 10, "SWAP-SPACE", 0x40c, 0, 0},
  75. {"swap", "swap", 0, 0xff6, 10, "SWAPSPACE2", 0x40c, 0, 0},
  76. {"swap", "swsuspend", 0, 0xff6, 9, "S1SUSPEND", 0x40c, 0, 0},
  77. {"swap", "swsuspend", 0, 0xff6, 9, "S2SUSPEND", 0x40c, 0, 0},
  78. {"swap", "swsuspend", 0, 0xff6, 9, "ULSUSPEND", 0x40c, 0, 0},
  79. {"ocfs2", "ocfs2", 4, 0, 6, "OCFSV2", 0x0, 0, 0},
  80. {"ocfs2", "ocfs2", 8, 0, 6, "OCFSV2", 0x0, 0, 0},
  81. {"hpfs", "hpfs", 8, 0, 4, "I\350\225\371", 0, 0, 0},
  82. {"reiserfs", "reiserfs", 8, 0x34, 8, "ReIsErFs", 0x10054, 0, 0},
  83. {"reiserfs", "reiserfs", 8, 20, 8, "ReIsErFs", 0x10054, 0, 0},
  84. {"zfs", "zfs", 8, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", 0x0, 0, 0},
  85. {"zfs", "zfs", 8, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", 0x0, 0, 0},
  86. {"ufs", "ufs", 8, 0x55c, 4, "T\031\001\000", 0, 0, 0},
  87. {"swap", "swap", 0, 0x1ff6, 10, "SWAP-SPACE", 0x40c, 0, 0},
  88. {"swap", "swap", 0, 0x1ff6, 10, "SWAPSPACE2", 0x40c, 0, 0},
  89. {"swap", "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", 0x40c, 0, 0},
  90. {"swap", "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", 0x40c, 0, 0},
  91. {"swap", "swsuspend", 0, 0x1ff6, 9, "ULSUSPEND", 0x40c, 0, 0},
  92. {"reiserfs", "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", 0x10054, 0, 0},
  93. {"reiserfs", "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", 0x10054, 0, 0},
  94. {"reiserfs", "reiserfs", 64, 0x34, 8, "ReIsErFs", 0x10054, 0, 0},
  95. {"reiser4", "reiser4", 64, 0, 7, "ReIsEr4", 0x100544, 0, 0},
  96. {"gfs2", "gfs2", 64, 0, 4, "\x01\x16\x19\x70", 0x0, 0, 0},
  97. {"gfs", "gfs", 64, 0, 4, "\x01\x16\x19\x70", 0x0, 0, 0},
  98. {"btrfs", "btrfs", 64, 0x40, 8, "_BHRfS_M", 0x0, 0, 0},
  99. {"swap", "swap", 0, 0x3ff6, 10, "SWAP-SPACE", 0x40c, 0, 0},
  100. {"swap", "swap", 0, 0x3ff6, 10, "SWAPSPACE2", 0x40c, 0, 0},
  101. {"swap", "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", 0x40c, 0, 0},
  102. {"swap", "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", 0x40c, 0, 0},
  103. {"swap", "swsuspend", 0, 0x3ff6, 9, "ULSUSPEND", 0x40c, 0, 0},
  104. {"udf", "udf", 32, 1, 5, "BEA01", 0x0, 0, 0},
  105. {"udf", "udf", 32, 1, 5, "BOOT2", 0x0, 0, 0},
  106. {"udf", "udf", 32, 1, 5, "CD001", 0x0, 0, 0},
  107. {"udf", "udf", 32, 1, 5, "CDW02", 0x0, 0, 0},
  108. {"udf", "udf", 32, 1, 5, "NSR02", 0x0, 0, 0},
  109. {"udf", "udf", 32, 1, 5, "NSR03", 0x0, 0, 0},
  110. {"udf", "udf", 32, 1, 5, "TEA01", 0x0, 0, 0},
  111. {"iso9660", "iso9660", 32, 1, 5, "CD001", 0x0, 0, 0},
  112. {"iso9660", "iso9660", 32, 9, 5, "CDROM", 0x0, 0, 0},
  113. {"jfs", "jfs", 32, 0, 4, "JFS1", 0x88, 0, 0},
  114. {"swap", "swap", 0, 0x7ff6, 10, "SWAP-SPACE", 0x40c, 0, 0},
  115. {"swap", "swap", 0, 0x7ff6, 10, "SWAPSPACE2", 0x40c, 0, 0},
  116. {"swap", "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", 0x40c, 0, 0},
  117. {"swap", "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", 0x40c, 0, 0},
  118. {"swap", "swsuspend", 0, 0x7ff6, 9, "ULSUSPEND", 0x40c, 0, 0},
  119. {"swap", "swap", 0, 0xfff6, 10, "SWAP-SPACE", 0x40c, 0, 0},
  120. {"swap", "swap", 0, 0xfff6, 10, "SWAPSPACE2", 0x40c, 0, 0},
  121. {"swap", "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", 0x40c, 0, 0},
  122. {"swap", "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", 0x40c, 0, 0},
  123. {"swap", "swsuspend", 0, 0xfff6, 9, "ULSUSPEND", 0x40c, 0, 0},
  124. {"zfs", "zfs", 264, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", 0x0, 0, 0},
  125. {"zfs", "zfs", 264, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", 0x0, 0, 0},
  126. {NULL, NULL, 0, 0, 0, NULL, 0x0, 0, 0}
  127. };
  128. static int null_uuid(const char *uuid)
  129. {
  130. int i;
  131. for (i = 0; i < 16 && !uuid[i]; i++)
  132. ;
  133. return (i == 16);
  134. }
  135. static void uuid_end_bio(struct bio *bio, int err)
  136. {
  137. struct page *page = bio->bi_io_vec[0].bv_page;
  138. if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
  139. SetPageError(page);
  140. unlock_page(page);
  141. bio_put(bio);
  142. }
  143. /**
  144. * submit - submit BIO request
  145. * @dev: The block device we're using.
  146. * @page_num: The page we're reading.
  147. *
  148. * Based on Patrick Mochell's pmdisk code from long ago: "Straight from the
  149. * textbook - allocate and initialize the bio. If we're writing, make sure
  150. * the page is marked as dirty. Then submit it and carry on."
  151. **/
  152. static struct page *read_bdev_page(struct block_device *dev, int page_num)
  153. {
  154. struct bio *bio = NULL;
  155. struct page *page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
  156. if (!page) {
  157. pr_err("Failed to allocate a page for reading data " "in UUID checks.");
  158. return NULL;
  159. }
  160. bio = bio_alloc(GFP_NOFS, 1);
  161. bio->bi_bdev = dev;
  162. bio->bi_iter.bi_sector = page_num << 3;
  163. bio->bi_end_io = uuid_end_bio;
  164. bio->bi_flags |= (1 << BIO_TOI);
  165. PRINTK("Submitting bio on device %lx, page %d using bio %p and page %p.\n",
  166. (unsigned long)dev->bd_dev, page_num, bio, page);
  167. if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
  168. pr_debug("ERROR: adding page to bio at %d\n", page_num);
  169. bio_put(bio);
  170. __free_page(page);
  171. pr_debug("read_bdev_page freed page %p (in error " "path).\n", page);
  172. return NULL;
  173. }
  174. lock_page(page);
  175. submit_bio(READ | REQ_SYNC, bio);
  176. wait_on_page_locked(page);
  177. if (PageError(page)) {
  178. __free_page(page);
  179. page = NULL;
  180. }
  181. return page;
  182. }
  183. int bdev_matches_key(struct block_device *bdev, const char *key)
  184. {
  185. unsigned char *data = NULL;
  186. struct page *data_page = NULL;
  187. int dev_offset, pg_num, pg_off, i;
  188. int last_pg_num = -1;
  189. int result = 0;
  190. char buf[50];
  191. if (null_uuid(key)) {
  192. PRINTK("Refusing to find a NULL key.\n");
  193. return 0;
  194. }
  195. if (!bdev->bd_disk) {
  196. bdevname(bdev, buf);
  197. PRINTK("bdev %s has no bd_disk.\n", buf);
  198. return 0;
  199. }
  200. if (!bdev->bd_disk->queue) {
  201. bdevname(bdev, buf);
  202. PRINTK("bdev %s has no queue.\n", buf);
  203. return 0;
  204. }
  205. for (i = 0; uuid_list[i].name; i++) {
  206. struct uuid_info *dat = &uuid_list[i];
  207. if (!dat->key || strcmp(dat->key, key))
  208. continue;
  209. dev_offset = (dat->bkoff << 10) + dat->sboff;
  210. pg_num = dev_offset >> 12;
  211. pg_off = dev_offset & 0xfff;
  212. if ((((pg_num + 1) << 3) - 1) > bdev->bd_part->nr_sects >> 1)
  213. continue;
  214. if (pg_num != last_pg_num) {
  215. if (data_page) {
  216. kunmap(data_page);
  217. __free_page(data_page);
  218. }
  219. data_page = read_bdev_page(bdev, pg_num);
  220. if (!data_page)
  221. continue;
  222. data = kmap(data_page);
  223. }
  224. last_pg_num = pg_num;
  225. if (strncmp(&data[pg_off], dat->magic, dat->sig_len))
  226. continue;
  227. result = 1;
  228. break;
  229. }
  230. if (data_page) {
  231. kunmap(data_page);
  232. __free_page(data_page);
  233. }
  234. return result;
  235. }
  236. /*
  237. * part_matches_fs_info - Does the given partition match the details given?
  238. *
  239. * Returns a score saying how good the match is.
  240. * 0 = no UUID match.
  241. * 1 = UUID but last mount time differs.
  242. * 2 = UUID, last mount time but not dev_t
  243. * 3 = perfect match
  244. *
  245. * This lets us cope elegantly with probing resulting in dev_ts changing
  246. * from boot to boot, and with the case where a user copies a partition
  247. * (UUID is non unique), and we need to check the last mount time of the
  248. * correct partition.
  249. */
  250. int part_matches_fs_info(struct hd_struct *part, struct fs_info *seek)
  251. {
  252. struct block_device *bdev;
  253. struct fs_info *got;
  254. int result = 0;
  255. char buf[50];
  256. if (null_uuid((char *)&seek->uuid)) {
  257. PRINTK("Refusing to find a NULL uuid.\n");
  258. return 0;
  259. }
  260. bdev = bdget(part_devt(part));
  261. PRINTK("part_matches fs info considering %x.\n", part_devt(part));
  262. if (blkdev_get(bdev, FMODE_READ, 0)) {
  263. PRINTK("blkdev_get failed.\n");
  264. return 0;
  265. }
  266. if (!bdev->bd_disk) {
  267. bdevname(bdev, buf);
  268. PRINTK("bdev %s has no bd_disk.\n", buf);
  269. goto out;
  270. }
  271. if (!bdev->bd_disk->queue) {
  272. bdevname(bdev, buf);
  273. PRINTK("bdev %s has no queue.\n", buf);
  274. goto out;
  275. }
  276. got = fs_info_from_block_dev(bdev);
  277. if (got && !memcmp(got->uuid, seek->uuid, 16)) {
  278. PRINTK(" Have matching UUID.\n");
  279. PRINTK(" Got: LMS %d, LM %p.\n", got->last_mount_size, got->last_mount);
  280. PRINTK(" Seek: LMS %d, LM %p.\n", seek->last_mount_size, seek->last_mount);
  281. result = 1;
  282. if (got->last_mount_size == seek->last_mount_size &&
  283. got->last_mount && seek->last_mount &&
  284. !memcmp(got->last_mount, seek->last_mount, got->last_mount_size)) {
  285. result = 2;
  286. PRINTK(" Matching last mount time.\n");
  287. if (part_devt(part) == seek->dev_t) {
  288. result = 3;
  289. PRINTK(" Matching dev_t.\n");
  290. } else
  291. PRINTK("Dev_ts differ (%x vs %x).\n", part_devt(part), seek->dev_t);
  292. }
  293. }
  294. PRINTK(" Score for %x is %d.\n", part_devt(part), result);
  295. free_fs_info(got);
  296. out:
  297. blkdev_put(bdev, FMODE_READ);
  298. return result;
  299. }
  300. void free_fs_info(struct fs_info *fs_info)
  301. {
  302. if (!fs_info || IS_ERR(fs_info))
  303. return;
  304. kfree(fs_info->last_mount);
  305. kfree(fs_info);
  306. }
  307. EXPORT_SYMBOL_GPL(free_fs_info);
  308. struct fs_info *fs_info_from_block_dev(struct block_device *bdev)
  309. {
  310. unsigned char *data = NULL;
  311. struct page *data_page = NULL;
  312. int dev_offset, pg_num, pg_off;
  313. int uuid_pg_num, uuid_pg_off, i;
  314. unsigned char *uuid_data = NULL;
  315. struct page *uuid_data_page = NULL;
  316. int last_pg_num = -1, last_uuid_pg_num = 0;
  317. char buf[50];
  318. struct fs_info *fs_info = NULL;
  319. bdevname(bdev, buf);
  320. PRINTK("uuid_from_block_dev looking for partition type of %s.\n", buf);
  321. for (i = 0; uuid_list[i].name; i++) {
  322. struct uuid_info *dat = &uuid_list[i];
  323. dev_offset = (dat->bkoff << 10) + dat->sboff;
  324. pg_num = dev_offset >> 12;
  325. pg_off = dev_offset & 0xfff;
  326. uuid_pg_num = dat->uuid_offset >> 12;
  327. uuid_pg_off = dat->uuid_offset & 0xfff;
  328. if ((((pg_num + 1) << 3) - 1) > bdev->bd_part->nr_sects >> 1)
  329. continue;
  330. /* Ignore partition types with no UUID offset */
  331. if (!dat->uuid_offset)
  332. continue;
  333. if (pg_num != last_pg_num) {
  334. if (data_page) {
  335. kunmap(data_page);
  336. __free_page(data_page);
  337. }
  338. data_page = read_bdev_page(bdev, pg_num);
  339. if (!data_page)
  340. continue;
  341. data = kmap(data_page);
  342. }
  343. last_pg_num = pg_num;
  344. if (strncmp(&data[pg_off], dat->magic, dat->sig_len))
  345. continue;
  346. PRINTK("This partition looks like %s.\n", dat->name);
  347. fs_info = kzalloc(sizeof(struct fs_info), GFP_KERNEL);
  348. if (!fs_info) {
  349. PRINTK("Failed to allocate fs_info struct.");
  350. fs_info = ERR_PTR(-ENOMEM);
  351. break;
  352. }
  353. /* UUID can't be off the end of the disk */
  354. if ((uuid_pg_num > bdev->bd_part->nr_sects >> 3) || !dat->uuid_offset)
  355. goto no_uuid;
  356. if (!uuid_data || uuid_pg_num != last_uuid_pg_num) {
  357. /* No need to reread the page from above */
  358. if (uuid_pg_num == pg_num && uuid_data)
  359. memcpy(uuid_data, data, PAGE_SIZE);
  360. else {
  361. if (uuid_data_page) {
  362. kunmap(uuid_data_page);
  363. __free_page(uuid_data_page);
  364. }
  365. uuid_data_page = read_bdev_page(bdev, uuid_pg_num);
  366. if (!uuid_data_page)
  367. continue;
  368. uuid_data = kmap(uuid_data_page);
  369. }
  370. }
  371. last_uuid_pg_num = uuid_pg_num;
  372. memcpy(&fs_info->uuid, &uuid_data[uuid_pg_off], 16);
  373. fs_info->dev_t = bdev->bd_dev;
  374. no_uuid:
  375. PRINT_HEX_DUMP(KERN_EMERG, "fs_info_from_block_dev returning uuid ", DUMP_PREFIX_NONE, 16, 1,
  376. fs_info->uuid, 16, 0);
  377. if (dat->last_mount_size) {
  378. int pg = dat->last_mount_offset >> 12, sz;
  379. int off = dat->last_mount_offset & 0xfff;
  380. struct page *last_mount = read_bdev_page(bdev, pg);
  381. unsigned char *last_mount_data;
  382. char *ptr;
  383. if (!last_mount) {
  384. kfree(fs_info);
  385. fs_info = ERR_PTR(-ENOMEM);
  386. break;
  387. }
  388. last_mount_data = kmap(last_mount);
  389. sz = dat->last_mount_size;
  390. ptr = kmalloc(sz, GFP_KERNEL);
  391. if (ptr) {
  392. fs_info->last_mount = ptr;
  393. fs_info->last_mount_size = sz;
  394. memcpy(ptr, &last_mount_data[off], sz);
  395. } else {
  396. free_fs_info(fs_info);
  397. fs_info = ERR_PTR(-ENOMEM);
  398. }
  399. kunmap(last_mount);
  400. __free_page(last_mount);
  401. }
  402. break;
  403. }
  404. if (data_page) {
  405. kunmap(data_page);
  406. __free_page(data_page);
  407. }
  408. if (uuid_data_page) {
  409. kunmap(uuid_data_page);
  410. __free_page(uuid_data_page);
  411. }
  412. return fs_info;
  413. }
  414. EXPORT_SYMBOL_GPL(fs_info_from_block_dev);
  415. static int __init uuid_debug_setup(char *str)
  416. {
  417. int value;
  418. if (sscanf(str, "=%d", &value) == 1)
  419. debug_enabled = value;
  420. return 1;
  421. }
  422. __setup("uuid_debug", uuid_debug_setup);