* JFFS1 scan procedure
@ 2001-11-30 17:26 Aleksander Sanochkin
2001-12-01 10:19 ` David Woodhouse
0 siblings, 1 reply; 2+ messages in thread
From: Aleksander Sanochkin @ 2001-11-30 17:26 UTC (permalink / raw)
To: linux-mtd, jffs-dev
[-- Attachment #1: Type: TEXT/PLAIN, Size: 455 bytes --]
Hi!
I've been using JFFS1 for some time and faced a problem
that the JFFS1 scan procedure is not robust enough. Namely,
it expects that the flash region it scans is either erased
or is in a state left by JFFS1 itself. That is, it doesn't
expect that the flash is containing a "garbage", which can
be the case sometimes.
I've improved the scan procedure to work smoothly in all
cases for me. Attached is a diff against the current CVS.
Best regards.
[-- Attachment #2: Type: TEXT/PLAIN, Size: 7881 bytes --]
diff -ur cvs/fs/jffs/intrep.c scan_flash/fs/jffs/intrep.c
--- cvs/fs/jffs/intrep.c Mon Sep 24 03:28:36 2001
+++ scan_flash/fs/jffs/intrep.c Wed Nov 21 19:55:02 2001
@@ -772,6 +772,9 @@
__u32 free_chunk_size1;
__u32 free_chunk_size2;
+ __u32 largest_hole = 0;
+ __u32 hole_end_offset = 0;
+ __u32 head_offset;
#define NUMFREEALLOWED 2 /* 2 chunks of at least erase size space allowed */
int num_free_space = 0; /* Flag err if more than TWO
@@ -884,6 +887,22 @@
(unsigned int) start,
(unsigned int)(test_start - start)));
+ D1(printk("Reducing start to 0x%x from 0x%x\n",
+ test_start, start));
+ if (largest_hole < test_start - start)
+ {
+ D3(printk("was hole = %x end_offset = %x\n",
+ largest_hole, hole_end_offset));
+ if (fmc->head)
+ {
+ largest_hole = test_start - start;
+ hole_end_offset = test_start;
+ }
+ }
+
+ D3(printk("now = %x end_offset = %x\n",
+ largest_hole, hole_end_offset));
+
/* below, space from "start" to "pos" will be marked dirty. */
start = test_start;
@@ -956,6 +975,20 @@
num_free_space++;
D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
(unsigned int) start, (unsigned int) (pos - start)));
+
+ if (largest_hole < pos - start)
+ {
+ D3(printk("was hole = %x end_offset = %x\n",
+ largest_hole, hole_end_offset));
+ if (fmc->head)
+ {
+ largest_hole = pos - start;
+ hole_end_offset = pos;
+ }
+
+ D3(printk("now = %x end_offset = %x\n",
+ largest_hole, hole_end_offset));
+ }
}else{
num_free_spc_not_accp++;
D1(printk("Free space (#%i) found but *Not* accepted: Starting "
@@ -1002,9 +1035,11 @@
to scan for the magic pattern. */
D1(printk("*************** Dirty flash memory or "
"bad inode: "
- "hexdump(pos = 0x%lx, len = 128):\n",
- (long)pos));
- D1(jffs_hexdump(fmc->mtd, pos, 128));
+ "hexdump(pos = 0x%lx, len = %d):\n",
+ (long)pos,
+ end - pos > 128 ? 128 : end - pos));
+ D1(jffs_hexdump(fmc->mtd, pos,
+ end - pos > 128 ? 128 : end - pos));
for (pos += 4; pos < end; pos += 4) {
switch (flash_read_u32(fmc->mtd, pos)) {
@@ -1197,12 +1232,6 @@
return -ENOMEM;
}
- if ((err = jffs_insert_node(c, 0, &raw_inode,
- name, node)) < 0) {
- printk("JFFS: Failed to handle raw inode. "
- "(err = %d)\n", err);
- break;
- }
if (raw_inode.rename) {
struct jffs_delete_list *dl
= (struct jffs_delete_list *)
@@ -1226,6 +1255,12 @@
c->delete_list = dl;
node->data_size = 0;
}
+ if ((err = jffs_insert_node(c, 0, &raw_inode,
+ name, node)) < 0) {
+ printk("JFFS: Failed to handle raw inode. "
+ "(err = %d)\n", err);
+ break;
+ }
D3(jffs_print_node(node));
node = 0; /* Don't free the node! */
}
@@ -1242,7 +1277,22 @@
jffs_free_node(node);
DJM(no_jffs_node--);
}
- jffs_build_end(fmc);
+ if (fmc->head && fmc->tail_extra &&
+ fmc->head->offset + fmc->flash_size -
+ fmc->tail_extra->offset - fmc->tail_extra->size > largest_hole)
+ {
+ head_offset = fmc->head->offset;
+ }
+ else
+ {
+ head_offset = hole_end_offset;
+ }
+
+ if (jffs_build_end(fmc, head_offset) < 0)
+ {
+ D(printk("jffs_build_end() failed\n"));
+ return -ENOMEM;
+ }
/* Free read buffer */
kfree (read_buf);
diff -ur cvs/fs/jffs/jffs_fm.c scan_flash/fs/jffs/jffs_fm.c
--- cvs/fs/jffs/jffs_fm.c Thu Sep 20 16:29:47 2001
+++ scan_flash/fs/jffs/jffs_fm.c Wed Nov 21 19:02:25 2001
@@ -89,8 +89,8 @@
/* When the flash memory scan has completed, this function should be called
before use of the control structure. */
-void
-jffs_build_end(struct jffs_fmcontrol *fmc)
+int
+jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset)
{
D3(printk("jffs_build_end()\n"));
@@ -99,13 +99,112 @@
fmc->tail = fmc->tail_extra;
}
else if (fmc->head_extra) {
- fmc->tail_extra->next = fmc->head;
- fmc->head->prev = fmc->tail_extra;
- fmc->head = fmc->head_extra;
+ struct jffs_fm *fm, *cur;
+
+ if (head_offset == fmc->head->offset)
+ {
+ fmc->tail->next = fmc->head_extra;
+ fmc->head_extra->prev = fmc->tail;
+ fmc->tail = fmc->tail_extra;
+ }
+ else
+ {
+ fmc->tail_extra->next = fmc->head;
+ fmc->head->prev = fmc->tail_extra;
+ fmc->head = fmc->head_extra;
+ while (fmc->head->offset != head_offset)
+ {
+ fmc->tail->next = fmc->head;
+ fmc->head = fmc->head->next;
+ fmc->head->prev = 0;
+ fmc->tail->next->prev = fmc->tail;
+ fmc->tail = fmc->tail->next;
+ fmc->tail->next = 0;
+ }
+ }
+ /* Make sure the only free space we have is between tail and head.
+ */
+ for (cur = fmc->head; cur && cur != fmc->tail;)
+ {
+ if (cur->offset + cur->size < cur->next->offset)
+ {
+ if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL)))
+ {
+ D(printk("jffs_buid_end(): kmalloc failed!\n"));
+ return -ENOMEM;
+ }
+ DJM(no_jffs_fm++);
+ fm->size = cur->next->offset - cur->offset - cur->size;
+ fm->offset = cur->offset + cur->size;
+ fm->nodes = 0;
+ fm->next = cur->next;
+ fm->prev = cur;
+ cur->next->prev = fm;
+ cur->next = fm;
+ cur = fm->next;
+ fmc->free_size -= fm->size;
+ fmc->dirty_size += fm->size;
+ }
+ else if (cur->offset > cur->next->offset)
+ {
+ if (cur->offset + cur->size < fmc->flash_size)
+ {
+ if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL)))
+ {
+ D(printk("jffs_buid_end(): kmalloc failed!\n"));
+ return -ENOMEM;
+ }
+ DJM(no_jffs_fm++);
+ fm->size = fmc->flash_size -
+ cur->offset - cur->size;
+ fm->nodes = 0;
+ fm->offset = cur->offset + cur->size;
+ fm->next = cur->next;
+ fm->prev = cur;
+ cur->next->prev = fm;
+ cur->next = fm;
+ cur = fm->next;
+ fmc->free_size -= fm->size;
+ fmc->dirty_size += fm->size;
+ }
+ else
+ {
+ cur = cur->next;
+ }
+ if (cur->offset > 0)
+ {
+ if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL)))
+ {
+ D(printk("jffs_buid_end(): kmalloc failed!\n"));
+ return -ENOMEM;
+ }
+ DJM(no_jffs_fm++);
+ fm->size = cur->offset;
+ fm->nodes = 0;
+ fm->offset = 0;
+ fm->next = cur;
+ fm->prev = cur->prev;
+ cur->prev->next = fm;
+ cur->prev = fm;
+ fmc->free_size -= fm->size;
+ fmc->dirty_size += fm->size;
+ }
+ }
+ else if (cur->offset + cur->size != cur->next->offset)
+ {
+ printk("jffs_build_end(): Internal error.\n");
+ return -EINVAL;
+ }
+ else
+ {
+ cur = cur->next;
+ }
+ }
}
fmc->head_extra = 0; /* These two instructions should be omitted. */
fmc->tail_extra = 0;
D3(jffs_print_fmcontrol(fmc));
+ return 0;
}
diff -ur cvs/fs/jffs/jffs_fm.h scan_flash/fs/jffs/jffs_fm.h
--- cvs/fs/jffs/jffs_fm.h Thu Jan 11 15:03:25 2001
+++ scan_flash/fs/jffs/jffs_fm.h Wed Nov 21 19:03:30 2001
@@ -123,7 +123,7 @@
struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, kdev_t dev);
-void jffs_build_end(struct jffs_fmcontrol *fmc);
+int jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset);
void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc);
int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size,
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: JFFS1 scan procedure
2001-11-30 17:26 JFFS1 scan procedure Aleksander Sanochkin
@ 2001-12-01 10:19 ` David Woodhouse
0 siblings, 0 replies; 2+ messages in thread
From: David Woodhouse @ 2001-12-01 10:19 UTC (permalink / raw)
To: Aleksander Sanochkin; +Cc: linux-mtd, jffs-dev
asanochkin@Lnxw.COM said:
> I've been using JFFS1 for some time and faced a problem that the JFFS1
> scan procedure is not robust enough. Namely, it expects that the flash
> region it scans is either erased or is in a state left by JFFS1
> itself. That is, it doesn't expect that the flash is containing a
> "garbage", which can be the case sometimes.
This looks sane to me, although I'll admit that JFFS1 is a vague and
distant memory - I have enough trouble remembering the details of JFFS2 :)
Unless someone else objects to it shortly, feel free to go ahead and commit
it. Please could I ask you to make the layout of the new code match what was
there already though? Curly braces on the same line as the if() statement,
etc. I'll refrain from being pedantic about printks without priorities as
that _does_ actually match the existing code :)
--
dwmw2
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2001-12-01 10:09 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-11-30 17:26 JFFS1 scan procedure Aleksander Sanochkin
2001-12-01 10:19 ` David Woodhouse
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox