cluster: RHEL4 - GFS: genesis w/flocks on NFS over GFS causes corruption

Bob Peterson rpeterso at fedoraproject.org
Wed Jul 21 20:48:40 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=c11570abe26008d5c5328932f2adf312978c2130
Commit:        c11570abe26008d5c5328932f2adf312978c2130
Parent:        74f94cce6528c9f985f9ebb5c2134b63b054dea8
Author:        Bob Peterson <rpeterso at redhat.com>
AuthorDate:    Wed Jul 21 14:37:56 2010 -0500
Committer:     Bob Peterson <rpeterso at redhat.com>
CommitterDate: Wed Jul 21 14:43:00 2010 -0500

GFS: genesis w/flocks on NFS over GFS causes corruption

This patch does a few things to avoid the NFS over GFS corruption on
small (stuffed) files:

1. kmap_atomic is used in place of kmap in stuffed_readpage and
   gfs_commit_write.
2. Function stuffed_readpage now flushes the dcache page after
   the page is updated in both of those functions as well.
3. In gfs_get_name there was a typo in an if clause.
4. In do_write_buf the new size is written into the incore inode
   if the file size has increased.

rhbz#212203
---
 gfs-kernel/src/gfs/ops_address.c |   21 ++++++++++-----------
 gfs-kernel/src/gfs/ops_export.c  |    5 +----
 gfs-kernel/src/gfs/ops_file.c    |    5 +++++
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/gfs-kernel/src/gfs/ops_address.c b/gfs-kernel/src/gfs/ops_address.c
index 6661421..ae7359c 100644
--- a/gfs-kernel/src/gfs/ops_address.c
+++ b/gfs-kernel/src/gfs/ops_address.c
@@ -211,20 +211,20 @@ static int
 stuffed_readpage(struct gfs_inode *ip, struct page *page)
 {
 	struct buffer_head *dibh;
-	void *kaddr;
+	char *kaddr;
 	int error;
 
 	error = gfs_get_inode_buffer(ip, &dibh);
 	if (!error) {
-		kaddr = kmap(page);
-		memcpy((char *)kaddr,
+		kaddr = (char *)kmap_atomic(page, KM_USER0);
+		memcpy(kaddr,
 		       dibh->b_data + sizeof(struct gfs_dinode),
 		       ip->i_di.di_size);
-		memset((char *)kaddr + ip->i_di.di_size,
+		memset(kaddr + ip->i_di.di_size,
 		       0,
 		       PAGE_CACHE_SIZE - ip->i_di.di_size);
-		kunmap(page);
-
+		kunmap_atomic(kaddr, KM_USER0);
+		flush_dcache_page(page);
 		brelse(dibh);
 
 		SetPageUptodate(page);
@@ -386,20 +386,19 @@ gfs_commit_write(struct file *file, struct page *page,
 
 		gfs_trans_add_bh(ip->i_gl, dibh);
 
-		kaddr = kmap(page);
+		kaddr = kmap_atomic(page, KM_USER0);
 		memcpy(dibh->b_data + sizeof(struct gfs_dinode) + from,
 		       (char *)kaddr + from,
 		       to - from);
-		kunmap(page);
-
-		brelse(dibh);
+		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
 
 		SetPageUptodate(page);
-
 		if (inode->i_size < file_size) {
 			i_size_write(inode, file_size);
 			mark_inode_dirty(inode);
 		}
+		brelse(dibh);
 	} else {
 		error = generic_commit_write(file, page, from, to);
 		if (error)
diff --git a/gfs-kernel/src/gfs/ops_export.c b/gfs-kernel/src/gfs/ops_export.c
index 4cbc8e0..c9cfb54 100644
--- a/gfs-kernel/src/gfs/ops_export.c
+++ b/gfs-kernel/src/gfs/ops_export.c
@@ -62,9 +62,6 @@ gfs_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
 
 	atomic_inc(&vfs2sdp(sb)->sd_ops_export);
 
-	if (fh_type != fh_len)
-		return NULL;
-
 	memset(&parent, 0, sizeof(struct inode_cookie));
 
 	switch (fh_type) {
@@ -216,7 +213,7 @@ int gfs_get_name(struct dentry *parent, char *name,
 
 	gfs_glock_dq_uninit(&gh);
 
-	if (!error & !*name)
+	if (!error && !*name)
 		error = -ENOENT;
 
 	return error;
diff --git a/gfs-kernel/src/gfs/ops_file.c b/gfs-kernel/src/gfs/ops_file.c
index 005b0b9..628ab99 100644
--- a/gfs-kernel/src/gfs/ops_file.c
+++ b/gfs-kernel/src/gfs/ops_file.c
@@ -984,6 +984,7 @@ do_write_buf(struct file *file,
 	size_t s;
 	ssize_t count = 0;
 	int error;
+	struct inode *inode = file->f_mapping->host;
 
 	gfs_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ghs[num_gh]);
 
@@ -1030,6 +1031,10 @@ do_write_buf(struct file *file,
 	}
 
 	error = 0;
+	if (inode->i_size < ip->i_di.di_size) {
+		i_size_write(inode, ip->i_di.di_size);
+		mark_inode_dirty(inode);
+	}
 
  out_gunlock:
 	gfs_glock_dq_m(num_gh + 1, ghs);


More information about the cluster-commits mailing list