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

Re: jffs garbage collection and signal handling




p2@xxxxxxx.be said:
>  While debugging an application which heavily uses signals, I noticed
> that write calls sometimes returned -EINTR even though the signal
> handlers were registered with the SA_RESTART flag. 

Hmmm. That's sane but still leaves you with the possibility of a short write
when a write is interrupted. Which is permitted by POSIX and all code should
deal with that, but there's a lot of broken code out there which doesn't --
so much so that we should really try to avoid breaking it, unfortunately.

I suspect I need to find a barf-bag and try to bring myself to commit 
something like the following:

Index: fs/jffs2/write.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/write.c,v
retrieving revision 1.60
diff -u -p -r1.60 write.c
--- fs/jffs2/write.c	9 Sep 2002 16:29:08 -0000	1.60
+++ fs/jffs2/write.c	14 Oct 2002 09:30:01 -0000
@@ -270,7 +270,9 @@ int jffs2_write_inode_range(struct jffs2
 {
 	int ret = 0;
 	uint32_t writtenlen = 0;
-
+#ifndef USER_SPACE_PROGRAMMERS_DONT_SUCK_ARSE_ANY_MORE
+	int need_recalc_current_sigpending = 0;
+#endif
        	D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n",
 		  f->inocache->ino, offset, writelen));
 		
@@ -286,6 +288,23 @@ int jffs2_write_inode_range(struct jffs2
 		ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL);
 		if (ret) {
 			D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
+			if (ret == -EINTR) {
+				if (!writtenlen) {
+					/* Nobody expects the Spanish Inquisition. */
+					ret = -ERESTARTNOINTR;
+#ifndef USER_SPACE_PROGRAMMERS_DONT_SUCK_ARSE_ANY_MORE
+				} else {
+					/* Lots of broken software out there which can't deal
+					   with partial writes. So we copy this vomit-inducing
+					   crap from fs/lockd/svc.c to attempt to work around it. */
+					D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ignoring signals, write already started\n"));
+					current->sigpending = 0;
+					need_recalc_current_sigpending = 1;
+					continue;
+#endif
+
+				}
+			}
 			break;
 		}
 		down(&f->sem);
@@ -363,6 +382,13 @@ int jffs2_write_inode_range(struct jffs2
 		writelen -= datalen;
 		buf += datalen;
 	}
+#ifndef USER_SPACE_PROGRAMMERS_DONT_SUCK_ARSE_ANY_MORE
+	if (need_recalc_current_sigpending) {
+		spin_lock_irq(&current->sigmask_lock);
+		recalc_sigpending(current);
+		spin_unlock_irq(&current->sigmask_lock);
+	}
+#endif
 	*retlen = writtenlen;
 	return ret;
 }


--
dwmw2



To unsubscribe from this list: send the line "unsubscribe jffs-dev" in
the body of a message to majordomo@xxxxxxx.com