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

[Cluster-devel] cluster/gnbd-kernel/src gnbd.c



CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL4
Changes by:	bmarzins sourceware org	2006-11-09 21:22:40

Modified files:
	gnbd-kernel/src: gnbd.c 

Log message:
	It was previously possible to confuse gnbd by sending a process a signal while
	gnbd was writing to the socket (bz 210453). This usually hangs the socket, but
	can possibly cause data corruption. To fix this gnbd now only handles signals
	for gnbd_recvd.  GNBD blocks all signals for all other processes while it
	is going socket IO, so that a partial IO will never be send to the server,
	except when the connection is lost.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gnbd-kernel/src/gnbd.c.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.6.2.2&r2=1.6.2.3

--- cluster/gnbd-kernel/src/gnbd.c	2005/05/09 23:05:17	1.6.2.2
+++ cluster/gnbd-kernel/src/gnbd.c	2006/11/09 21:22:40	1.6.2.3
@@ -289,7 +289,7 @@
  *  Send or receive packet.
  */
 static int sock_xmit(struct socket *sock, int send, void *buf, int size,
-		int msg_flags)
+		int msg_flags, int can_signal)
 {
 	mm_segment_t oldfs;
 	int result;
@@ -300,13 +300,12 @@
 
 	oldfs = get_fs();
 	set_fs(get_ds());
-	/* Allow interception of SIGKILL only
-	 * Don't allow other signals to interrupt the transmission */
 	spin_lock_irqsave(&current->sighand->siglock, flags);
 	oldset = current->blocked;
 	sigfillset(&current->blocked);
-	sigdelsetmask(&current->blocked, sigmask(SIGKILL) | sigmask(SIGTERM) |
-	              sigmask(SIGHUP));
+	if (can_signal)
+		sigdelsetmask(&current->blocked, sigmask(SIGKILL) |
+			      sigmask(SIGTERM) | sigmask(SIGHUP));
 	recalc_sigpending();
 	spin_unlock_irqrestore(&current->sighand->siglock, flags);
 
@@ -328,7 +327,7 @@
 		else
 			result = sock_recvmsg(sock, &msg, size, 0);
 
-		if (signal_pending(current)) {
+		if (can_signal && signal_pending(current)) {
 			siginfo_t info;
 			spin_lock_irqsave(&current->sighand->siglock, flags);
 			printk(KERN_WARNING "gnbd (pid %d: %s) got signal %d\n",
@@ -358,21 +357,22 @@
 }
 
 static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,
-		int flags)
+		int flags, int can_signal)
 {
 	int result;
 	void *kaddr = kmap(bvec->bv_page);
 	result = sock_xmit(sock, 1, kaddr + bvec->bv_offset, bvec->bv_len,
-			flags);
+			flags, can_signal);
 	kunmap(bvec->bv_page);
 	return result;
 }
 
 
-#define gnbd_send_req(dev, req) __gnbd_send_req((dev), (dev)->sock, (req))
+#define gnbd_send_req(dev, req, can_sig) \
+__gnbd_send_req((dev), (dev)->sock, (req), (can_sig))
 	
 int __gnbd_send_req(struct gnbd_device *dev, struct socket *sock,
-		struct request *req)
+		struct request *req, int can_signal)
 {
 	int result, i, flags;
 	struct gnbd_request request;
@@ -399,7 +399,8 @@
 			(unsigned long long)req->sector << 9,
 			req->nr_sectors << 9);
 	result = sock_xmit(sock, 1, &request, sizeof(request),
-			(gnbd_cmd(req) == GNBD_CMD_WRITE)? MSG_MORE: 0);
+			(gnbd_cmd(req) == GNBD_CMD_WRITE)? MSG_MORE: 0,
+			can_signal);
 	if (result < 0) {
 		printk(KERN_ERR "%s: Send control failed (result %d)\n",
 				dev->disk->disk_name, result);
@@ -421,7 +422,8 @@
 				dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
 						dev->disk->disk_name, req,
 						bvec->bv_len);
-				result = sock_send_bvec(sock, bvec, flags);
+				result = sock_send_bvec(sock, bvec, flags,
+							can_signal);
 				if (result < 0) {
 					printk(KERN_ERR "%s: Send data failed (result %d)\n",
 							dev->disk->disk_name,
@@ -459,7 +461,7 @@
 	int result;
 	void *kaddr = kmap(bvec->bv_page);
 	result = sock_xmit(sock, 0, kaddr + bvec->bv_offset, bvec->bv_len,
-			MSG_WAITALL);
+			MSG_WAITALL, 1);
 	kunmap(bvec->bv_page);
 	return result;
 }
@@ -495,7 +497,7 @@
 
 	BUG_ON(dev->magic != GNBD_MAGIC);
 
-	while((result = sock_xmit(sock, 0, &reply,sizeof(reply), MSG_WAITALL)) > 0){
+	while((result = sock_xmit(sock, 0, &reply,sizeof(reply), MSG_WAITALL, 1)) > 0){
 		if (ntohl(reply.magic) == GNBD_KEEP_ALIVE_MAGIC)
 			/* FIXME -- I should reset the wait time here */
 			continue;
@@ -610,7 +612,7 @@
 		list_add(&req->queuelist, &dev->queue_head);
 		spin_unlock(&dev->queue_lock);
 
-		err = gnbd_send_req(dev, req);
+		err = gnbd_send_req(dev, req, 0);
 
 		spin_lock_irq(q->queue_lock);
 		if (err)
@@ -642,7 +644,7 @@
 	printk("resending requests\n");
 	list_for_each(tmp, &dev->queue_head) {
 		req = list_entry(tmp, struct request, queuelist);
-		err = __gnbd_send_req(dev, sock, req);
+		err = __gnbd_send_req(dev, sock, req, 1);
 
 		if (err){
 			printk("failed trying to resend request (%d)\n", err);
@@ -706,7 +708,7 @@
 		/* There is no one using the device, you can disconnect it */
 		if (dev->sock == NULL)
 			return -ENOTCONN;
-		gnbd_send_req(dev, &shutdown_req);
+		gnbd_send_req(dev, &shutdown_req, 1);
                 return 0;
 	case GNBD_CLEAR_QUE:
 		if (down_interruptible(&dev->do_it_lock))
@@ -783,7 +785,7 @@
 			list_add(&ping_req.queuelist, &dev->queue_head);
 		}
 		spin_unlock(&dev->queue_lock);
-		gnbd_send_req(dev, &ping_req); /* ignore the errors */
+		gnbd_send_req(dev, &ping_req, 1); /* ignore the errors */
 		return 0;
 	case GNBD_PRINT_DEBUG:
 		printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",


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