Re: tree corrupted on disk quota full

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Thu, 11 Jan 2007, Linus Torvalds wrote:
> 
> That said, clearly something didn't check the error return of a write() 
> call. Some of that got fixed up recently, so it might even be fixed in 
> current git already.

I'm not convinced.

The "write_in_full()" logic is supposed to help people avoid problems, but 
it *still* returns a success for a partial write.

Example of extreme breakage:

	static int write_buffer(int fd, const void *buf, size_t len)
	{
	        ssize_t size;
	
	        size = write_in_full(fd, buf, len);
	        if (!size)
	                return error("file write: disk full");
	        if (size < 0)
	                return error("file write error (%s)", strerror(errno));
	        return 0;
	}

which is TOTAL GARBAGE, because the disk-full event might have happened in 
the middle of the write, so "write_in_full()" might have returned 4096, 
for example, even though the buffer length was much bigger.

I personally think write_in_full() is totally mis-designed. If you are 
ready to handle partial writes, you should use "xwrite()". If you're not 
ready to handle partial writes, you should either use "write_or_die()", 
_or_ you should expect a partial write to at least return an error code 
(which is how "write_buffer()" works).

But that's not how write_in_full() actually works. Write-in-full does not 
return an error for a partial write, it returns the partial size.

Which is idiotic. It makes the function pointless. Just use xwrite() for 
that.

I would suggest perhaps a patch like this..  And then you _really_ can 
just do

	if (write_in_full(fd, buf, len) < 0)
		die("Not going to work: %s", strerror(errno));

and be happy.

		Linus

---
diff --git a/write_or_die.c b/write_or_die.c
index a119e1d..f95299a 100644
--- a/write_or_die.c
+++ b/write_or_die.c
@@ -37,15 +37,14 @@ int write_in_full(int fd, const void *buf, size_t count)
 {
 	const char *p = buf;
 	ssize_t total = 0;
-	ssize_t written = 0;
 
 	while (count > 0) {
-		written = xwrite(fd, p, count);
-		if (written <= 0) {
-			if (total)
-				return total;
-			else
-				return written;
+		size_t written = xwrite(fd, p, count);
+		if (written < 0)
+			return -1;
+		if (!written) {
+			errno = ENOSPC;
+			return -1
 		}
 		count -= written;
 		p += written;
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]