Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 397

kernel-2.6.18-238.el5.src.rpm

From: Josef Bacik <josef@redhat.com>
Date: Thu, 7 Jan 2010 14:49:20 -0500
Subject: [block] loop: fix aops check for GFS
Message-id: <20100107144919.GC2199@localhost.localdomain>
Patchwork-id: 22334
O-Subject: [RHEL5.5][PATCH] loop: fix aops check for GFS
Bugzilla: 549397
RH-Acked-by: Steven Whitehouse <swhiteho@redhat.com>
RH-Acked-by: Robert S Peterson <rpeterso@redhat.com>

This is in reference to bz 549397.

GFS can't deal with loop devices via the normal AOPs because of how locking
works with GFS, so it does this trick where it doesn't set the .commit_write
AOP's for it's inodes until we come into GFS's .prepare_write.  The loop code
used to have something like this

if (aops->prepare_write && aops->commit_write)
	use aops
else
	dont

but with the new AOPs patches this changed to

if (aops->prepare_write || aops->write_begin)
	use aops
else
	dont

which has messed up this little hack in GFS.  So the solution is to just go in
and change it to do this

if ((aops->prepare_write && aops->commit_write) ||
	(aops->write_being && aops->write_end))
	use aops
else
	dont

so that loop files on GFS can go back to working.  This won't be an issue with
RHEL6 since GFS isn't there and GFS2 does its locking on the page level as
opposed to the inode level.  This has been tested by the customer who it broke
for and they confirmed it's now working fine.  Thanks,

Josef

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0b481f1..24cd1a9 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -764,13 +764,18 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
 	error = -EINVAL;
 	if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) {
 		const struct address_space_operations *aops = mapping->a_ops;
+		struct address_space_operations_ext *axops =
+			(struct address_space_operations_ext *)mapping->a_ops;
+
 		/*
 		 * If we can't read - sorry. If we only can't write - well,
 		 * it's going to be read-only.
 		 */
 		if (!file->f_op->sendfile)
 			goto out_putf;
-		if (aops->prepare_write || IS_NEWAOPS(inode))
+		if ((aops->prepare_write && aops->commit_write) ||
+		    (IS_NEWAOPS(inode) && axops->write_begin &&
+		     axops->write_end))
 			lo_flags |= LO_FLAGS_USE_AOPS;
 		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
 			lo_flags |= LO_FLAGS_READ_ONLY;