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