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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  Code extracted from drivers/block/genhd.c
  3.  *  Copyright (C) 1991-1998  Linus Torvalds
  4.  *  Re-organised Feb 1998 Russell King
  5.  *
  6.  *  We now have independent partition support from the
  7.  *  block drivers, which allows all the partition code to
  8.  *  be grouped in one location, and it to be mostly self
  9.  *  contained.
  10.  *
  11.  *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
  12.  */
  13. #include <linux/config.h>
  14. #include <linux/fs.h>
  15. #include <linux/genhd.h>
  16. #include <linux/kernel.h>
  17. #include <linux/major.h>
  18. #include <linux/blk.h>
  19. #include <linux/init.h>
  20. #include <linux/raid/md.h>
  21. #include "check.h"
  22. #include "acorn.h"
  23. #include "amiga.h"
  24. #include "atari.h"
  25. #include "ldm.h"
  26. #include "mac.h"
  27. #include "msdos.h"
  28. #include "osf.h"
  29. #include "sgi.h"
  30. #include "sun.h"
  31. #include "ibm.h"
  32. #include "ultrix.h"
  33. #include "efi.h"
  34. extern int *blk_size[];
  35. int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
  36. static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
  37. #ifdef CONFIG_ACORN_PARTITION
  38. acorn_partition,
  39. #endif
  40. #ifdef CONFIG_EFI_PARTITION
  41. efi_partition, /* this must come before msdos */
  42. #endif
  43. #ifdef CONFIG_LDM_PARTITION
  44. ldm_partition, /* this must come before msdos */
  45. #endif
  46. #ifdef CONFIG_MSDOS_PARTITION
  47. msdos_partition,
  48. #endif
  49. #ifdef CONFIG_OSF_PARTITION
  50. osf_partition,
  51. #endif
  52. #ifdef CONFIG_SUN_PARTITION
  53. sun_partition,
  54. #endif
  55. #ifdef CONFIG_AMIGA_PARTITION
  56. amiga_partition,
  57. #endif
  58. #ifdef CONFIG_ATARI_PARTITION
  59. atari_partition,
  60. #endif
  61. #ifdef CONFIG_MAC_PARTITION
  62. mac_partition,
  63. #endif
  64. #ifdef CONFIG_SGI_PARTITION
  65. sgi_partition,
  66. #endif
  67. #ifdef CONFIG_ULTRIX_PARTITION
  68. ultrix_partition,
  69. #endif
  70. #ifdef CONFIG_IBM_PARTITION
  71. ibm_partition,
  72. #endif
  73. NULL
  74. };
  75. /*
  76.  * This is ucking fugly but its probably the best thing for 2.4.x
  77.  * Take it as a clear reminder that: 1) we should put the device name
  78.  * generation in the object kdev_t points to in 2.5.
  79.  * and 2) ioctls better work on half-opened devices.
  80.  */
  81.  
  82. #ifdef CONFIG_ARCH_S390
  83. int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
  84. int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
  85.     unsigned int no, unsigned long data);
  86. EXPORT_SYMBOL(genhd_dasd_name);
  87. EXPORT_SYMBOL(genhd_dasd_ioctl);
  88. #endif
  89. /*
  90.  * disk_name() is used by partition check code and the md driver.
  91.  * It formats the devicename of the indicated disk into
  92.  * the supplied buffer (of size at least 32), and returns
  93.  * a pointer to that same buffer (for convenience).
  94.  */
  95. char *disk_name (struct gendisk *hd, int minor, char *buf)
  96. {
  97. const char *maj = hd->major_name;
  98. unsigned int unit = (minor >> hd->minor_shift);
  99. unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
  100. if ((unit < hd->nr_real) && hd->part[minor].de) {
  101. int pos;
  102. pos = devfs_generate_path (hd->part[minor].de, buf, 64);
  103. if (pos >= 0)
  104. return buf + pos;
  105. }
  106. #ifdef CONFIG_ARCH_S390
  107. if (genhd_dasd_name
  108.     && genhd_dasd_name (buf, unit, part, hd) == 0)
  109. return buf;
  110. #endif
  111. /*
  112.  * IDE devices use multiple major numbers, but the drives
  113.  * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
  114.  * This requires special handling here.
  115.  */
  116. switch (hd->major) {
  117. case IDE9_MAJOR:
  118. unit += 2;
  119. case IDE8_MAJOR:
  120. unit += 2;
  121. case IDE7_MAJOR:
  122. unit += 2;
  123. case IDE6_MAJOR:
  124. unit += 2;
  125. case IDE5_MAJOR:
  126. unit += 2;
  127. case IDE4_MAJOR:
  128. unit += 2;
  129. case IDE3_MAJOR:
  130. unit += 2;
  131. case IDE2_MAJOR:
  132. unit += 2;
  133. case IDE1_MAJOR:
  134. unit += 2;
  135. case IDE0_MAJOR:
  136. maj = "hd";
  137. break;
  138. case MD_MAJOR:
  139. sprintf(buf, "%s%d", maj, unit);
  140. return buf;
  141. }
  142. if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
  143. unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
  144. if (unit+'a' > 'z') {
  145. unit -= 26;
  146. sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
  147. if (part)
  148. sprintf(buf + 4, "%d", part);
  149. return buf;
  150. }
  151. }
  152. if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
  153. int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
  154.   if (part == 0)
  155.   sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  156.   else
  157.   sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  158.   return buf;
  159.   }
  160. if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
  161.                 int ctlr = hd->major - COMPAQ_CISS_MAJOR;
  162.                 if (part == 0)
  163.                         sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  164.                 else
  165.                         sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  166.                 return buf;
  167. }
  168. if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
  169. int ctlr = hd->major - DAC960_MAJOR;
  170.   if (part == 0)
  171.   sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  172.   else
  173.   sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  174.   return buf;
  175.   }
  176. if (hd->major == ATARAID_MAJOR) {
  177. int disk = minor >> hd->minor_shift;
  178. int part = minor & (( 1 << hd->minor_shift) - 1);
  179. if (part == 0)
  180. sprintf(buf, "%s/d%d", maj, disk);
  181. else
  182. sprintf(buf, "%s/d%dp%d", maj, disk, part);
  183. return buf;
  184. }
  185. if (part)
  186. sprintf(buf, "%s%c%d", maj, unit+'a', part);
  187. else
  188. sprintf(buf, "%s%c", maj, unit+'a');
  189. return buf;
  190. }
  191. /*
  192.  * Add a partitions details to the devices partition description.
  193.  */
  194. void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
  195. {
  196. #ifndef CONFIG_DEVFS_FS
  197. char buf[40];
  198. #endif
  199. hd->part[minor].start_sect = start;
  200. hd->part[minor].nr_sects   = size;
  201. #ifdef CONFIG_DEVFS_FS
  202. printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
  203. #else
  204. if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
  205.     (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
  206. printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
  207. else
  208. printk(" %s", disk_name(hd, minor, buf));
  209. #endif
  210. }
  211. static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
  212. {
  213. devfs_handle_t de = NULL;
  214. static int first_time = 1;
  215. unsigned long first_sector;
  216. struct block_device *bdev;
  217. char buf[64];
  218. int i;
  219. if (first_time)
  220. printk(KERN_INFO "Partition check:n");
  221. first_time = 0;
  222. first_sector = hd->part[MINOR(dev)].start_sect;
  223. /*
  224.  * This is a kludge to allow the partition check to be
  225.  * skipped for specific drives (e.g. IDE CD-ROM drives)
  226.  */
  227. if ((int)first_sector == -1) {
  228. hd->part[MINOR(dev)].start_sect = 0;
  229. return;
  230. }
  231. if (hd->de_arr)
  232. de = hd->de_arr[MINOR(dev) >> hd->minor_shift];
  233. i = devfs_generate_path (de, buf, sizeof buf);
  234. if (i >= 0)
  235. printk(KERN_INFO " /dev/%s:", buf + i);
  236. else
  237. printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
  238. bdev = bdget(kdev_t_to_nr(dev));
  239. bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
  240. bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
  241. for (i = 0; check_part[i]; i++) {
  242. int res;
  243. res = check_part[i](hd, bdev, first_sector, first_part_minor);
  244. if (res) {
  245. if (res < 0 &&  warn_no_part)
  246. printk(" unable to read partition tablen");
  247. goto setup_devfs;
  248. }
  249. }
  250. printk(" unknown partition tablen");
  251. setup_devfs:
  252. invalidate_bdev(bdev, 1);
  253. truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
  254. bdput(bdev);
  255. i = first_part_minor - 1;
  256. devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
  257. }
  258. #ifdef CONFIG_DEVFS_FS
  259. static void devfs_register_partition (struct gendisk *dev, int minor, int part)
  260. {
  261. int devnum = minor >> dev->minor_shift;
  262. devfs_handle_t dir;
  263. unsigned int devfs_flags = DEVFS_FL_DEFAULT;
  264. char devname[16];
  265. if (dev->part[minor + part].de) return;
  266. dir = devfs_get_parent (dev->part[minor].de);
  267. if (!dir) return;
  268. if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
  269. devfs_flags |= DEVFS_FL_REMOVABLE;
  270. sprintf (devname, "part%d", part);
  271. dev->part[minor + part].de =
  272.     devfs_register (dir, devname, devfs_flags,
  273.     dev->major, minor + part,
  274.     S_IFBLK | S_IRUSR | S_IWUSR,
  275.     dev->fops, NULL);
  276. }
  277. static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
  278. static void devfs_register_disc (struct gendisk *dev, int minor)
  279. {
  280. int pos = 0;
  281. int devnum = minor >> dev->minor_shift;
  282. devfs_handle_t dir, slave;
  283. unsigned int devfs_flags = DEVFS_FL_DEFAULT;
  284. char dirname[64], symlink[16];
  285. static devfs_handle_t devfs_handle;
  286. if (dev->part[minor].de) return;
  287. if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
  288. devfs_flags |= DEVFS_FL_REMOVABLE;
  289. if (dev->de_arr) {
  290. dir = dev->de_arr[devnum];
  291. if (!dir)  /*  Aware driver wants to block disc management  */
  292. return;
  293. pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
  294. if (pos < 0) return;
  295. strncpy (dirname + pos, "../", 3);
  296. }
  297. else {
  298. /*  Unaware driver: construct "real" directory  */
  299. sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
  300. dir = devfs_mk_dir (NULL, dirname + 3, NULL);
  301. }
  302. if (!devfs_handle)
  303. devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
  304. dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
  305. sprintf (symlink, "disc%d", dev->part[minor].number);
  306. devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
  307.   dirname + pos, &slave, NULL);
  308. dev->part[minor].de =
  309.     devfs_register (dir, "disc", devfs_flags, dev->major, minor,
  310.     S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
  311. devfs_auto_unregister (dev->part[minor].de, slave);
  312. if (!dev->de_arr)
  313. devfs_auto_unregister (slave, dir);
  314. }
  315. #endif  /*  CONFIG_DEVFS_FS  */
  316. void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
  317. {
  318. #ifdef CONFIG_DEVFS_FS
  319. int part;
  320. if (!unregister)
  321. devfs_register_disc (dev, minor);
  322. for (part = 1; part < dev->max_p; part++) {
  323. if ( unregister || (dev->part[minor].nr_sects < 1) ||
  324.      (dev->part[part + minor].nr_sects < 1) ) {
  325. devfs_unregister (dev->part[part + minor].de);
  326. dev->part[part + minor].de = NULL;
  327. continue;
  328. }
  329. devfs_register_partition (dev, minor, part);
  330. }
  331. if (unregister) {
  332. devfs_unregister (dev->part[minor].de);
  333. dev->part[minor].de = NULL;
  334. devfs_dealloc_unique_number (&disc_numspace,
  335.      dev->part[minor].number);
  336. }
  337. #endif  /*  CONFIG_DEVFS_FS  */
  338. }
  339. /*
  340.  * This function will re-read the partition tables for a given device,
  341.  * and set things back up again.  There are some important caveats,
  342.  * however.  You must ensure that no one is using the device, and no one
  343.  * can start using the device while this function is being executed.
  344.  *
  345.  * Much of the cleanup from the old partition tables should have already been
  346.  * done
  347.  */
  348. void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
  349. struct block_device_operations *ops, long size)
  350. {
  351. if (!gdev)
  352. return;
  353. grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
  354. }
  355. void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
  356. {
  357. int i;
  358. int first_minor = drive << dev->minor_shift;
  359. int end_minor = first_minor + dev->max_p;
  360. if(!dev->sizes)
  361. blk_size[dev->major] = NULL;
  362. dev->part[first_minor].nr_sects = size;
  363. /* No such device or no minors to use for partitions */
  364. if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
  365. devfs_register_partitions (dev, first_minor, 0);
  366. if (!size || minors == 1)
  367. return;
  368. if (dev->sizes) {
  369. dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
  370. for (i = first_minor + 1; i < end_minor; i++)
  371. dev->sizes[i] = 0;
  372. }
  373. blk_size[dev->major] = dev->sizes;
  374. check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
  375.   /*
  376.    * We need to set the sizes array before we will be able to access
  377.    * any of the partitions on this device.
  378.    */
  379. if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
  380. for (i = first_minor; i < end_minor; i++)
  381. dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
  382. }
  383. }
  384. unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
  385. {
  386. struct address_space *mapping = bdev->bd_inode->i_mapping;
  387. int sect = PAGE_CACHE_SIZE / 512;
  388. struct page *page;
  389. page = read_cache_page(mapping, n/sect,
  390. (filler_t *)mapping->a_ops->readpage, NULL);
  391. if (!IS_ERR(page)) {
  392. wait_on_page(page);
  393. if (!Page_Uptodate(page))
  394. goto fail;
  395. if (PageError(page))
  396. goto fail;
  397. p->v = page;
  398. return (unsigned char *)page_address(page) + 512 * (n % sect);
  399. fail:
  400. page_cache_release(page);
  401. }
  402. p->v = NULL;
  403. return NULL;
  404. }