Changes by: flatcap
Update of /cvsroot/linux-ntfs/dynamic-disk/linux/fs/partitions
In directory usw-pr-cvs1:/tmp/cvs-serv5773/linux/fs/partitions
Modified Files:
ldm.c ldm.h
Log Message:
new fragment handling code.
more elegant than mine, simpler than Jakob's and smaller than both.
Index: ldm.c
===================================================================
RCS file: /cvsroot/linux-ntfs/dynamic-disk/linux/fs/partitions/ldm.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -U2 -r1.70 -r1.71
--- ldm.c 15 Apr 2002 00:14:20 -0000 1.70
+++ ldm.c 15 Apr 2002 21:57:33 -0000 1.71
@@ -728,5 +728,5 @@
int minor;
- DEBUG_ON (!hd || !ldb || !disk);
+ DEBUG_ON (!hd || !ldb);
disk = ldm_get_disk_objid (ldb);
@@ -1162,5 +1162,5 @@
part->parent_id = ldm_get_vnum (buffer + 0x34 + r_size);
part->disk_id = ldm_get_vnum (buffer + 0x34 + r_parent);
- if (vb->flags & VBLK_FLAG_SUCCESSIVE)
+ if (vb->flags & VBLK_FLAG_PART_INDEX)
part->partnum = buffer[0x35 + r_diskid];
else
@@ -1257,7 +1257,4 @@
DEBUG_ON (!buf || !vb);
- buf -= VBLK_SIZE_HEAD; /* Skip the header FIXME WHAT? */
- len += VBLK_SIZE_HEAD;
-
if (ldm_out_of_range (buf, len, 0x18)) {
// FIXME logging
@@ -1301,11 +1298,22 @@
* FIXME prereq:vb is already sanity-checked.
*
- * Return: none
+ * Return: none FIXME
*/
-static void ldm_ldmdb_add(struct vblk *vb, struct ldmdb *ldb)
+static BOOL ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb)
{
+ struct vblk *vb;
list_t *item;
- DEBUG_ON (!vb || !ldb);
+ DEBUG_ON (!data || !ldb);
+
+ vb = kmalloc (sizeof(*vb), GFP_KERNEL);
+ if (!vb) {
+ ldm_crit ("out of mem"); // FIXME
+ return FALSE;
+ }
+
+ if (!ldm_parse_vblk (data, len, vb)) {
+ return FALSE; /* Already logged */
+ }
/* Put vblk into the correct list. */
@@ -1314,15 +1322,15 @@
case VBLK_DGR4:
list_add(&vb->list, &ldb->v_dgrp);
- return;
+ break;
case VBLK_DSK3:
case VBLK_DSK4:
list_add(&vb->list, &ldb->v_disk);
- return;
+ break;
case VBLK_VOL5:
list_add(&vb->list, &ldb->v_volu);
- return;
+ break;
case VBLK_CMP3:
list_add(&vb->list, &ldb->v_comp);
- return;
+ break;
case VBLK_PRT3:
/* Sort by the partition's start sector. */
@@ -1332,35 +1340,70 @@
(v->vblk.part.start > vb->vblk.part.start)) {
list_add_tail(&vb->list, &v->list);
- return;
+ return TRUE;
}
}
list_add_tail(&vb->list, &ldb->v_part);
- return;
+ break;
}
+ return TRUE;
}
/**
- * ldm_frag_find - Obvious fraglist helper functions.
- * @list: List of fragments.
- * FIXME: better descriptions.
+ * ldm_frag_add
*/
-static struct frags *ldm_frag_find(list_t *list, u32 group)
+static BOOL ldm_frag_add (const u8 *data, int size, list_t *frags)
{
+ struct frag *f;
list_t *item;
+ int rec, num, group;
- DEBUG_ON (!list);
+ DEBUG_ON (!data || !frags);
- list_for_each(item, list) {
- struct frags *f = list_entry(item, struct frags, list);
+ group = BE32 (data + 0x08);
+ rec = BE16 (data + 0x0C);
+ num = BE16 (data + 0x0E);
+ if ((num < 1) || (num > 4)) {
+ ldm_error ("corrupt vblk %d parts.", num);
+ return FALSE;
+ }
+
+ list_for_each(item, frags) {
+ f = list_entry(item, struct frag, list);
if (f->group == group)
- return f;
+ goto found;
+ }
+
+ f = kmalloc (sizeof (*f) + size*num, GFP_KERNEL);
+ if (!f) {
+ ldm_crit ("Out of memory.");
+ return FALSE;
}
- return 0;
+
+ f->group = group;
+ f->num = num;
+ f->rec = rec;
+ f->map = 0xFF << num;
+
+ list_add_tail(&f->list, frags);
+found:
+ if (f->map & (1 << rec)) {
+ ldm_error ("Duplicate VBLK, part %d.", rec);
+ }
+
+ f->map |= 1 << rec;
+
+ if (num > 0) {
+ data += VBLK_SIZE_HEAD;
+ size -= VBLK_SIZE_HEAD;
+ }
+ memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size);
+
+ return TRUE;
}
/**
- * ldm_frag_listfree -
+ * ldm_frag_free -
*/
-static void ldm_frag_listfree(list_t *list)
+static void ldm_frag_free (list_t *list)
{
list_t *item, *tmp;
@@ -1369,76 +1412,5 @@
list_for_each_safe(item, tmp, list)
- kfree (list_entry(item, struct frags, list));
-
- INIT_LIST_HEAD(list);
-}
-
-/**
- * ldm_frag_add - Adds a VBLK fragment to fragment list.
- * @list: Fragment list.
- * @vbh: VBLK header.
- * @data: pointer to raw data.
- * @size: size of datablock.
- *
- * Process fragment data and copy to fragment list.
- * FIXME: desc.
- *
- * Returns: TRUE fragment added.
- * FALSE vblk record is corrupt.
- * -1 error.
- */
-static int ldm_frag_add(list_t *list, const struct vblk_head *vbh,
- const u8 *data, int size)
-{
- BOOL bad = FALSE;
- struct frags *f;
-
- DEBUG_ON (!list || !vbh || !data);
-
- /* Sanity check vblk header. */
- if (vbh->nrec > FRAG_MAX || vbh->rec >= vbh->nrec) {
- ldm_error ("Invalid VBLK header.");
- bad = TRUE; // FIXME shouldn't we return?
- }
-
- /* Try to find previous entry. */
- if ((f = ldm_frag_find(list, vbh->group))) {
- /* More sanity checking. */
- if (FRAG_GETBAD(f)) {
- bad = TRUE;
- // FIXME has this been logged already?
- } else if (vbh->nrec != f->nrec || FRAG_GETMAP(f, vbh->rec)) {
- ldm_error ("Inconsistent VBLK fragments!");
- bad = TRUE;
- }
- } else { /* Not found, create a new entry in list. */
- const int nrec = (bad) ? 0 : vbh->nrec;
-
- /* Allocate memory */
- f = kmalloc(sizeof (*f) + nrec * size, GFP_KERNEL);
- if (!f) {
- ldm_crit ("Out of memory.");
- return -1;
- }
-
- /* Initialize entry. */
- f->group = vbh->group;
- f->nrec = nrec;
- f->map = 0x00;
-
- /* Add to end of list. */
- list_add_tail(&f->list, list);
- }
-
- /* Mark as bad if necessary. */
- if (bad)
- FRAG_SETBAD(f);
- /* Copy data */
- else {
- memcpy(f->data + vbh->rec*size, data, size);
- FRAG_SETMAP(f, vbh->rec);
- }
-
- return !bad;
+ kfree (list_entry(item, struct frag, list));
}
@@ -1446,5 +1418,4 @@
* ldm_frag_commit - Parse complete multipart VBLK records and add to ldmdb.
* @list: Fragment list.
- * @size: fragmentsize.
* @ldb: ldmdb.
*
@@ -1454,144 +1425,79 @@
* FALSE
*/
-static BOOL ldm_frag_commit(list_t *list, int size, struct ldmdb *ldb)
+static BOOL ldm_frag_commit (list_t *frags, struct ldmdb *ldb)
{
- list_t *item, *tmp;
- struct vblk *vb = NULL;
- BOOL result;
+ struct frag *f;
+ list_t *item;
+ BOOL result = FALSE;
- DEBUG_ON (!list || !ldb);
+ DEBUG_ON (!frags || !ldb);
- list_for_each_safe(item, tmp, list) {
- struct frags *f = list_entry(item, struct frags, list);
- int i;
-
- if (FRAG_GETBAD(f))
- goto entry_done;
-
- /* Make sure we've got all parts. */
- for (i = 0; i < f->nrec; i++)
- if (!FRAG_GETMAP(f, i)) {
- ldm_error ("VBLK group %lu is incomplete.",
- (unsigned long)f->group);
- goto entry_done;
- }
+ list_for_each(item, frags) {
+ f = list_entry(item, struct frag, list);
- /* Allocate memory for VBLK if necessary. */
- if (!vb)
- vb = kmalloc (sizeof(*vb), GFP_KERNEL);
- if (!vb) {
- ldm_crit ("Out of memory.");
- result = FALSE;
+ if (f->map != 0xFF) {
+ ldm_error ("VBLK group %d is incomplete.", f->group);
goto out;
}
- /* Parse vblk entry and add to list. */
- if (ldm_parse_vblk (f->data, size * f->nrec, vb)) {
- ldm_ldmdb_add(vb, ldb);
- vb = NULL;
- }
- /* else - Already logged */
- entry_done:
- list_del(&f->list);
- kfree (f);
+ if (!ldm_ldmdb_add (f->data, f->num*ldb->vm.vblk_size, ldb))
+ goto out;
}
+
result = TRUE;
out:
- kfree (vb);
-
return result;
}
/**
- * ldm_get_vblks - Read and cache the VMDB in the ldmdb
- * @bdev: The device to read from
- * @base: The offset into the device
- * @ldb: ldmdb struct
- *
- * This reads all VBLK entries and then stores relevant information
- * in the appropriate list inside the ldmdb
- *
- * Returns: TRUE Database read without any errors
- * FALSE Error
- */
-static BOOL ldm_get_vblks(struct block_device *bdev, unsigned long base,
- struct ldmdb *ldb)
-{
- // FIXME: This function is ugly, it should be rewritten.
- const int perbuf = 512 / ldb->vm.vblk_size;
- const int skip = ldb->vm.vblk_offset / 512;
- const int finish = (ldb->vm.vblk_size * ldb->vm.last_vblk_seq) / 512;
- const int body_size = ldb->vm.vblk_size - VBLK_SIZE_HEAD;
- LIST_HEAD(fraglist);
- struct vblk *vb = NULL;
+ * ldm_get_vblks - new
+ */
+static BOOL ldm_get_vblks(struct block_device *bdev, unsigned long base, struct ldmdb *ldb)
+{
+ int size, perbuf, skip, finish, s, v, recs;
u8 *data = NULL;
Sector sect;
- int s;
BOOL result = FALSE;
+ LIST_HEAD(frags);
+
+ DEBUG_ON (!bdev || !ldb);
- DEBUG_ON (!bdev || !ldb); // FIXME useless after deref'ing ldb (above)
+ size = ldb->vm.vblk_size;
+ perbuf = 512 / size;
+ skip = ldb->vm.vblk_offset / 512;
+ finish = (size * ldb->vm.last_vblk_seq) / 512;
- /* Loop through sectors */
- for (s = skip; s < finish; s++) {
- int i;
- if (data)
- put_dev_sector(sect);
+ for (s = skip; s < finish; s++) { /* For each sector */
data = read_dev_sector (bdev, base + OFF_VMDB + s, §);
if (!data) {
- ldm_crit ("Disk read failed in get buffers."); //FIXME
+ ldm_crit ("Disk read failed.");
goto out;
}
- /* Loop through all entries in sector */
- for (i = 0; i < perbuf; i++) {
- const u8 *block = data + i*ldb->vm.vblk_size;
- const u8 *body_data = block + VBLK_SIZE_HEAD;
- struct vblk_head vbh;
-
- if (MAGIC_VBLK != BE32 (block)) {
- ldm_error ("not a VBLK"); //FIXME
+ for (v = 0; v < perbuf; v++, data+=size) { /* For each vblk */
+ if (MAGIC_VBLK != BE32 (data)) {
+ ldm_error ("Expected to find a VBLK.");
goto out;
}
- /* Common to all VBLKs */
- vbh.group = BE32 (block + 0x08);
- vbh.rec = BE16 (block + 0x0C);
- vbh.nrec = BE16 (block + 0x0E);
- if (vbh.nrec == 0) /* Record is not in use */
- continue;
-
- /* Record is multipart */
- if (vbh.nrec > 1) {
- if (ldm_frag_add(&fraglist, &vbh, body_data, body_size) < 0)
- goto out; /* already logged */
- continue;
+ recs = BE16 (data + 0x0E); /* Number of records */
+ if (recs == 1) {
+ if (!ldm_ldmdb_add (data, size, ldb))
+ goto out; /* Already logged */
+ } else if (recs > 1) {
+ if (!ldm_frag_add (data, size, &frags))
+ goto out; /* Already logged */
}
-
- /* Allocate memory for vblk */
- if (!vb)
- vb = kmalloc (sizeof(*vb), GFP_KERNEL);
- if (!vb) {
- ldm_crit ("Out of memory.");
- goto out;
- }
-
- /* Parse record and add to list. */
- if (ldm_parse_vblk (body_data, body_size, vb)) {
- ldm_ldmdb_add(vb, ldb);
- vb = NULL;
- }
- /* else - Already logged */
+ /* else Record is not in use, ignore it. */
}
+ put_dev_sector(sect);
+ data = NULL;
}
- /* Combine fragments. */
- result = ldm_frag_commit(&fraglist, body_size, ldb);
+ result = ldm_frag_commit (&frags, ldb);
out:
- kfree(vb);
if (data)
put_dev_sector(sect);
-
- /* Free fraglist */
- ldm_frag_listfree(&fraglist);
+ ldm_frag_free (&frags);
return result;
@@ -1701,2 +1607,3 @@
return err;
}
+
Index: ldm.h
===================================================================
RCS file: /cvsroot/linux-ntfs/dynamic-disk/linux/fs/partitions/ldm.h,v
retrieving revision 1.43
retrieving revision 1.44
diff -U2 -r1.43 -r1.44
--- ldm.h 15 Apr 2002 00:14:20 -0000 1.43
+++ ldm.h 15 Apr 2002 21:57:33 -0000 1.44
@@ -56,8 +56,4 @@
#define VBLK_DGR4 0x45 /* Disk Group, version 4 */
-/* vblk flags. */
-#define VBLK_FLAG_COMPOUND 0x10 /* 00010000 Compound comp. */
-#define VBLK_FLAG_SUCCESSIVE 0x08 /* 00001000 n-th in set, n>1 */
-
/* vblk flags indicating extra information will be present */
#define VBLK_FLAG_COMP_STRIPE 0x10
@@ -117,16 +113,10 @@
/* VBLK Fragment handling */
-#define FRAG_MAPBITS 8
-#define FRAG_MAX (FRAG_MAPBITS-1)
-#define FRAG_GETMAP(f,n) (f->map & (1 << n))
-#define FRAG_SETMAP(f,n) (f->map |= (1 << n))
-#define FRAG_GETBAD(f) (f->map & (1 << (FRAG_MAPBITS-1)))
-#define FRAG_SETBAD(f) (f->map |= (1 << (FRAG_MAPBITS-1)))
-
-struct frags {
+struct frag {
list_t list;
u32 group;
- u8 nrec;
- u8 map;
+ u8 num; /* Total number of records */
+ u8 rec; /* This is record number n */
+ u8 map; /* Which portions are in use */
u8 data[0];
};
|