[Cluster-devel] cluster/gfs-kernel/src/gfs ops_address.c ops_i ...

wcheng at sourceware.org wcheng at sourceware.org
Sun Oct 15 06:32:07 UTC 2006


CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	wcheng at sourceware.org	2006-10-15 06:32:06

Modified files:
	gfs-kernel/src/gfs: ops_address.c ops_inode.c 

Log message:
	Bugzilla 203170 - direct IO deadlock: We'll have the same deadlock as
	described in bugzilla 173912 without RHEL4 kernel DIO_CLUSTER_LOCKING
	flag. To work around this issue, the i_alloc_sem is dropped from GFS.
	We expect glock will be able to handle the local synchronization.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ops_address.c.diff?cvsroot=cluster&r1=1.13&r2=1.14
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ops_inode.c.diff?cvsroot=cluster&r1=1.12&r2=1.13

--- cluster/gfs-kernel/src/gfs/ops_address.c	2006/08/02 17:21:19	1.13
+++ cluster/gfs-kernel/src/gfs/ops_address.c	2006/10/15 06:32:06	1.14
@@ -466,9 +466,15 @@
 	if (rw == WRITE && !get_transaction)
 		gb = get_blocks_noalloc;
 
-	return blockdev_direct_IO(rw, iocb, inode,
+	if (rw == WRITE)
+		return blockdev_direct_IO(rw, iocb, inode,
 				  inode->i_sb->s_bdev, iov,
 				  offset, nr_segs, gb, NULL);
+	else
+		return blockdev_direct_IO_no_locking(rw, iocb, inode,
+				  inode->i_sb->s_bdev, iov,
+				  offset, nr_segs, gb, NULL);
+
 }
 
 struct address_space_operations gfs_file_aops = {
--- cluster/gfs-kernel/src/gfs/ops_inode.c	2006/10/03 17:27:34	1.12
+++ cluster/gfs-kernel/src/gfs/ops_inode.c	2006/10/15 06:32:06	1.13
@@ -1340,7 +1340,36 @@
 
 	atomic_inc(&sdp->sd_ops_inode);
 
+	/* Bugzilla 203170: we'll have the same deadlock as described 
+	 * in bugzilla 173912 if
+	 * 1. without RHEL4's DIO_CLUSTER_LOCKING, and
+	 * 2. we come down to this line of code from do_truncate()
+	 *    where i_sem(i_mutex) and i_alloc_sem have been taken, and
+	 * 3. grab the exclusive glock here.
+	 * To avoid this to happen, i_alloc_sem must be dropped and trust
+	 * be put into glock that it can carry the same protection. 
+	 *
+	 * One issue with dropping i_alloc_sem is gfs_setattr() can be 
+	 * called from other code path without this sempaphore. Since linux
+	 * semaphore implementation doesn't include owner id, we have no way 
+	 * to reliably decide whether the following "up" is a correct reset. 
+	 * This implies if i_alloc_sem is ever used by non-direct_IO code 
+	 * path in the future, this hack will fall apart. In short, with this 
+	 * change, i_alloc_sem has become a meaningless lock within GFS and 
+	 * don't expect its counter representing any correct state. 
+	 *
+	 * wcheng at redhat.com 10/14/06  
+	 */ 
+	if (attr->ia_valid & ATTR_SIZE) {
+		up_write(&dentry->d_inode->i_alloc_sem); 
+	}
+	
 	error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
+
+	if (attr->ia_valid & ATTR_SIZE) {
+		down_write(&dentry->d_inode->i_alloc_sem); 
+	}
+	
 	if (error)
 		return error;
 




More information about the Cluster-devel mailing list