Skip to contentSkip to conversation

Nandwrite's behavior in case of write failure

DISCUSSION Nahor 3 participants 7 messages Jun 5, 2009 – Jun 9, 2009 Memory technology devices (MTD)

lore
Share & tools
lore

Nahor

author
#0 lore raw

Hi,

If the call to pwrite fails, nanwrite tries first to erase the block then to mark it as bad. If erase fails, nandwrite aborts. If setting the bad block flag fails, nandwrite just ignores it and go to the next block.

My questions are:
- Why erase the block?
- Probably linked to the first question, why abort if erase fails? Why not just ignore it and rely on the bad block flag?
- Why ignore the bad block flag error? If nandwrite can't set it and just goes on, the caller (app ou user) will think that everything is good. But when reading the partition later, the user will garbage when reaching that page.

Thanks,
Nahor

#1 lore raw
Quoted 5 lines · Nahor

Hi,

If the call to pwrite fails, nanwrite tries first to erase the block then to mark it as bad. If erase fails, nandwrite aborts. If setting the bad block flag fails, nandwrite just ignores it and go to the next block.

I think this is a bug. It should not aborts in erase fails, but mark the block as bad instead. But it should check the error code as well, and mark it as bad only if the error was EIO. I.e., it should not mark the block as bad on ENOMEM.

And yes, if mark_bad() fails, nandwrite should not ignore this.

This is what we do in ubiformat, I think. Also, ubiformat asks the user if he wants to mark the block as bad, unless the -y option was used. nandwrite could do something similar.

Quoted 2 lines

My questions are:
- Why erase the block?

Just in case. We should be very careful with marking blocks as bad, because if you do this by mistake, you may loose your device. Indeed, imagine you marked 100 blocks as bad my mistake, and you do not remember the block numbers. How will you know which blocks you should then unmark?

So the idea of erase is to check whether the block is really bad or this is just a driver bug or something.

Quoted 2 lines

- Probably linked to the first question, why abort if erase fails? Why not just ignore it and rely on the bad block flag?

I guess this is a bug in nandwrite

Quoted 4 lines

- Why ignore the bad block flag error? If nandwrite can't set it and just goes on, the caller (app ou user) will think that everything is good. But when reading the partition later, the user will garbage when reaching that page.

And this must be a bug, IMO.

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)
author
#2 lore raw
Quoted 12 lines · Artem Bityutskiy
Quoted 5 lines · Nahor

Hi,

If the call to pwrite fails, nanwrite tries first to erase the block then to mark it as bad. If erase fails, nandwrite aborts. If setting the bad block flag fails, nandwrite just ignores it and go to the next block.

I think this is a bug. It should not aborts in erase fails, but mark the block as bad instead. But it should check the error code as well, and mark it as bad only if the error was EIO. I.e., it should not mark the block as bad on ENOMEM.

Quoted 5 lines

And yes, if mark_bad() fails, nandwrite should not ignore this.

This is what we do in ubiformat, I think. Also, ubiformat asks the user if he wants to mark the block as bad, unless the -y option was used. nandwrite could do something similar.

nandwrite has the -m/--markbad option instead of -y.
However, if the option is not set, the blocks are skipped without being marked. I guess nandwrite should either ask the user or fail immediately. Continuing seems useless.

Quoted 7 lines
Quoted 2 lines

My questions are:
- Why erase the block?

Just in case. We should be very careful with marking blocks as bad, because if you do this by mistake, you may loose your device. Indeed, imagine you marked 100 blocks as bad my mistake, and you do not remember the block numbers. How will you know which blocks you should then unmark?

Well, one could unmark all of them and run nandtest, then flog oneself and swear to pay more attention next time :)

More seriously, in my case, I want to use nandwrite for automatic updates so I prefer that it marks too many blocks bad than have the update abort because nandwrite wants to be conservative and exits instead of flagging the offending block and continuing.

Quoted 2 lines

So the idea of erase is to check whether the block is really bad or this is just a driver bug or something.

Do you mean that if the erase succeeds, nandwrite shouldn't mark the block bad and just exit?

I'm not too familiar with the NAND technology but it is not possible that a block can be erasable but not written to? At least nandtest thinks so, it mark blocks as bad on either erase or write failures.

And so does ubiformat. flash_image() either exits or marks the block bad if mtd_write fails. It doesn't try to erase it first.

Nahor

#3 lore raw
Quoted 6 lines · Nahor
Quoted 3 lines · Artem Bityutskiy

This is what we do in ubiformat, I think. Also, ubiformat asks the user if he wants to mark the block as bad, unless the -y option was used. nandwrite could do something similar.

nandwrite has the -m/--markbad option instead of -y.

OK.

Quoted 3 lines

However, if the option is not set, the blocks are skipped without being marked. I guess nandwrite should either ask the user or fail immediately. Continuing seems useless.

Yes. It might as well suggest using -m/

Quoted 10 lines
Quoted 7 lines
Quoted 2 lines

My questions are:
- Why erase the block?

Just in case. We should be very careful with marking blocks as bad, because if you do this by mistake, you may loose your device. Indeed, imagine you marked 100 blocks as bad my mistake, and you do not remember the block numbers. How will you know which blocks you should then unmark?

Well, one could unmark all of them and run nandtest, then flog oneself and swear to pay more attention next time :)

The problem is that factory-marked bad blocks do not have to manifest themselves easily. They may appear to work fine, and file later, e.g. when the temperature is higher.

Quoted 4 lines

More seriously, in my case, I want to use nandwrite for automatic updates so I prefer that it marks too many blocks bad than have the update abort because nandwrite wants to be conservative and exits instead of flagging the offending block and continuing.

Then you probably need to fix the tool. I wonder, it it would make sense to use libmtd.c from UBI utils and re-write nandwrite? Of course libmtd.c would need to be improved as well. But the benefit would be shared code between ubiformat and nandwrite.

Quoted 5 lines
Quoted 2 lines

So the idea of erase is to check whether the block is really bad or this is just a driver bug or something.

Do you mean that if the erase succeeds, nandwrite shouldn't mark the block bad and just exit?

I think it should do something like UBI is doing - erase the eraseblock, then torture it by writing several patterns and reading them back. If the eraseblock survived torturing, nandwrite may re-try writing, otherwise it marks the eraseblock as bad.

Quoted 3 lines

I'm not too familiar with the NAND technology but it is not possible that a block can be erasable but not written to? At least nandtest thinks so, it mark blocks as bad on either erase or write failures.

Yes, write and erase failure mean that the erasblock is bad. But I think marking a block as bad straight away is just dangerous. Who knows may be this is a small glitch in a bus, or a software bug, or some-one corrupted driver's memory, or whatever. This is why UBI is doing eraseblock torturing before marking it as bad. And it is very careful about error codes - only EIO code is considered as a reason to mark an eraseblock as bad.

Quoted 2 lines

And so does ubiformat. flash_image() either exits or marks the block bad if mtd_write fails. It doesn't try to erase it first.

Yes, this is not very good, I've added TODO there. It should torture the eraseblock - I'll implement this later in libmtd.c.

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)
author
#4 lore raw
Quoted 4 lines · Artem Bityutskiy

I wonder, it it would make sense
to use libmtd.c from UBI utils and re-write nandwrite? Of course libmtd.c would need to be improved as well. But the benefit would be shared code between ubiformat and nandwrite.

I've been thinking that too. Unfortunately, I've too much work on my hands already and I don't have the time for things that are not strictly necessary. :(

#5 lore raw
In reply to Artem Bityutskiy
Quoted 7 lines · Artem Bityutskiy

Yes, write and erase failure mean that the erasblock is bad. But I think marking a block as bad straight away is just dangerous. Who knows may be this is a small glitch in a bus, or a software bug, or some-one corrupted driver's memory, or whatever. This is why UBI is doing eraseblock torturing before marking it as bad. And it is very careful about error codes - only EIO code is considered as a reason to mark an eraseblock as bad.

Fixed broken behavior in case of write failure. More specifically:
- Only try to mark a block bad if the errors are EIO. Other errors will abort the tool.
- Also abort the tool if the marking fails instead of ignoring it.

nandwrite.c +8 -2
@@ -586,6 +586,10 @@ int main(int argc, char * const argv[])
 			erase_info_t erase;
 
 			perror ("pwrite");
+			if (errno != EIO) {
+				goto closeall;
+			}
+
 			/* Must rewind to blockstart if we can */
 			rewind_blocks = (mtdoffset - blockstart) / meminfo.writesize; /* Not including the one we just attempted */
 			rewind_bytes = (rewind_blocks * meminfo.writesize) + readlen;
@@ -602,7 +606,9 @@ int main(int argc, char * const argv[])
 				(long)erase.start, (long)erase.start+erase.length-1);
 			if (ioctl(fd, MEMERASE, &erase) != 0) {
 				perror("MEMERASE");
-				goto closeall;
+				if (errno != EIO) {
+					goto closeall;
+				}
 			}
 
 			if (markbad) {
@@ -610,7 +616,7 @@ int main(int argc, char * const argv[])
 				fprintf(stderr, "Marking block at %08lx bad\n", (long)bad_addr);
 				if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) {
 					perror("MEMSETBADBLOCK");
-					/* But continue anyway */
+					goto closeall;
 				}
 			}
 			mtdoffset = blockstart + meminfo.erasesize;
#6 lore raw
Quoted 10 lines · Jehan Bing
Quoted 7 lines · Artem Bityutskiy

Yes, write and erase failure mean that the erasblock is bad. But I think marking a block as bad straight away is just dangerous. Who knows may be this is a small glitch in a bus, or a software bug, or some-one corrupted driver's memory, or whatever. This is why UBI is doing eraseblock torturing before marking it as bad. And it is very careful about error codes - only EIO code is considered as a reason to mark an eraseblock as bad.

Quoted 6 lines

Fixed broken behavior in case of write failure. More specifically:
- Only try to mark a block bad if the errors are EIO. Other errors will abort the tool.
- Also abort the tool if the marking fails instead of ignoring it.

Looks good to me, pushed, thanks.

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)