patch-2.4.15 linux/fs/partitions/ldm.c
Next file: linux/fs/partitions/ldm.h
Previous file: linux/fs/openpromfs/inode.c
Back to the patch index
Back to the overall index
- Lines: 187
- Date:
Mon Nov 12 09:43:11 2001
- Orig file:
v2.4.14/linux/fs/partitions/ldm.c
- Orig date:
Tue Oct 9 17:06:53 2001
diff -u --recursive --new-file v2.4.14/linux/fs/partitions/ldm.c linux/fs/partitions/ldm.c
@@ -1,10 +1,8 @@
/*
- * $Id: ldm.c,v 1.25 2001/07/25 23:32:02 flatcap Exp $
- *
* ldm - Part of the Linux-NTFS project.
*
- * Copyright (C) 2001 Richard Russon <ntfs@flatcap.org>
- * Copyright (C) 2001 Anton Altaparmakov <antona@users.sf.net>
+ * Copyright (C) 2001 Richard Russon <ldm@flatcap.org>
+ * Copyright (C) 2001 Anton Altaparmakov <antona@users.sf.net> (AIA)
*
* Documentation is available at http://linux-ntfs.sf.net/ldm
*
@@ -22,6 +20,8 @@
* along with this program (in the main directory of the Linux-NTFS source
* in the file COPYING); if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * 28/10/2001 - Added sorting of ldm partitions. (AIA)
*/
#include <linux/types.h>
#include <asm/unaligned.h>
@@ -158,6 +158,60 @@
}
/**
+ * add_partition_to_list - insert partition into a partition list
+ * @pl: sorted list of partitions
+ * @hd: gendisk structure to which the data partition belongs
+ * @disk_minor: minor number of the disk device
+ * @start: first sector within the disk device
+ * @size: number of sectors on the partition device
+ *
+ * This sanity checks the partition specified by @start and @size against the
+ * device specified by @hd and inserts the partition into the sorted partition
+ * list @pl if the checks pass.
+ *
+ * On success return 1, otherwise return -1.
+ *
+ * TODO: Add sanity check for overlapping partitions. (AIA)
+ */
+static int add_partition_to_list(struct list_head *pl, const struct gendisk *hd,
+ const int disk_minor, const unsigned long start,
+ const unsigned long size)
+{
+ struct ldm_part *lp, *lptmp;
+ struct list_head *tmp;
+
+ if (!hd->part)
+ return -1;
+ if ((start < 1) || ((start + size) > hd->part[disk_minor].nr_sects)) {
+ printk(LDM_CRIT "LDM partition exceeds physical disk. "
+ "Skipping.\n");
+ return -1;
+ }
+ lp = (struct ldm_part*)kmalloc(sizeof(struct ldm_part), GFP_KERNEL);
+ if (!lp) {
+ printk(LDM_CRIT "Not enough memory! Aborting LDM partition "
+ "parsing.\n");
+ return -2;
+ }
+ INIT_LIST_HEAD(&lp->part_list);
+ lp->start = start;
+ lp->size = size;
+ list_for_each(tmp, pl) {
+ lptmp = list_entry(tmp, struct ldm_part, part_list);
+ if (start > lptmp->start)
+ continue;
+ if (start < lptmp->start)
+ break;
+ printk(LDM_CRIT "Duplicate LDM partition entry! Skipping.\n");
+ kfree(lp);
+ return -1;
+ }
+ list_add_tail(&lp->part_list, tmp);
+ ldm_debug("Added LDM partition successfully.\n");
+ return 1;
+}
+
+/**
* create_data_partitions - create the data partition devices
* @hd: gendisk structure in which to create the data partitions
* @first_sector: first sector within the disk device
@@ -172,7 +226,10 @@
* the partitions in the database that belong to this disk.
*
* For each found partition, we create a corresponding partition device starting
- * with minor number @first_part_minor.
+ * with minor number @first_part_minor. But we do this in such a way that we
+ * actually sort the partitions in order of on-disk position. Any invalid
+ * partitions are completely ignored/skipped (an error is output but that's
+ * all).
*
* Return 1 on success and -1 on error.
*/
@@ -182,13 +239,16 @@
const struct privhead *ph, const struct ldmdisk *dk,
unsigned long base)
{
- Sector sect;
+ Sector sect;
unsigned char *data;
struct vblk *vb;
+ LIST_HEAD(pl); /* Sorted list of partitions. */
+ struct ldm_part *lp;
+ struct list_head *tmp;
int vblk;
int vsize; /* VBLK size. */
int perbuf; /* VBLKs per buffer. */
- int buffer, lastbuf, lastofs, err;
+ int buffer, lastbuf, lastofs, err, disk_minor;
vb = (struct vblk*)kmalloc(sizeof(struct vblk), GFP_KERNEL);
if (!vb)
@@ -207,7 +267,11 @@
if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize >
ph->config_size * 512)
goto err_out;
- printk(" <");
+ /*
+ * Get the minor number of the parent device so we can check we don't
+ * go beyond the end of the device.
+ */
+ disk_minor = (first_part_minor >> hd->minor_shift) << hd->minor_shift;
for (buffer = 0; buffer < lastbuf; buffer++) {
data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, §);
if (!data)
@@ -226,17 +290,34 @@
continue;
if (dk->obj_id != vb->disk_id)
continue;
- if (create_partition(hd, first_part_minor,
+ /* Ignore invalid partition errors. */
+ if (add_partition_to_list(&pl, hd, disk_minor,
first_sector + vb->start_sector +
ph->logical_disk_start,
- vb->num_sectors) == 1)
- first_part_minor++;
+ vb->num_sectors) < -1)
+ goto brelse_out;
}
put_dev_sector(sect);
}
- printk(" >\n");
err = 1;
out:
+ /* Finally create the nicely sorted data partitions. */
+ printk(" <");
+ list_for_each(tmp, &pl) {
+ lp = list_entry(tmp, struct ldm_part, part_list);
+ add_gd_partition(hd, first_part_minor++, lp->start, lp->size);
+ }
+ printk(" >\n");
+ if (!list_empty(&pl)) {
+ struct list_head *tmp2;
+
+ /* Cleanup the partition list which is now superfluous. */
+ list_for_each_safe(tmp, tmp2, &pl) {
+ lp = list_entry(tmp, struct ldm_part, part_list);
+ list_del(tmp);
+ kfree(lp);
+ }
+ }
kfree(vb);
return err;
brelse_out:
@@ -372,7 +453,10 @@
delta = vblk * vsize + 0x18;
if (delta >= 512)
goto brelse_out;
- if (block[0x13] != VBLK_DISK)
+ if (block[0x0D] != 0) /* Extended VBLK, ignore */
+ continue;
+ if ((block[0x13] != VBLK_DSK1) &&
+ (block[0x13] != VBLK_DSK2))
continue;
/* Calculate relative offsets. */
rel_objid = 1 + block[0x18];
@@ -895,7 +979,7 @@
put_dev_sector(sect);
return 1;
not_dynamic_disk:
- ldm_debug("Found basic MS-DOS partition, not a dynamic disk.\n");
+// ldm_debug("Found basic MS-DOS partition, not a dynamic disk.\n");
no_msdos_partition:
put_dev_sector(sect);
return 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)