Skip to contentSkip to conversation

reiser4: make methods supplied to vfs invariant

PATCH In review Edward Shishkin 1 participant 1 message Nov 28, 2007

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 reiser4: make methods supplied to vfs invariant

Andrew,
please, apply.

Thanks,
Edward.

Problem:
hangs when writing to reiser4 partition exported via nfs (found by Roc Vall���s Dom���nech <[email protected]>).

Bug:
vfs (which is not aware of reiser4 plugin conversion) uses obsolete copy of @file->f_op, whereas old methods are not aware about new structures. It leads to memory corruption.

Fixup:
Prevent collisions with vfs:
Make inode_ops, file_ops and a_ops supplied to vfs invariant with respect to plugin conversion.

---
 linux-2.6.23-mm1/fs/reiser4/as_ops.c                      |   40 +
 linux-2.6.23-mm1/fs/reiser4/inode.c                       |   20 
 linux-2.6.23-mm1/fs/reiser4/plugin/file/cryptcompress.c   |  107 ++---
 linux-2.6.23-mm1/fs/reiser4/plugin/file/file.c            |   44 --
 linux-2.6.23-mm1/fs/reiser4/plugin/file/file.h            |  166 +++++--
 linux-2.6.23-mm1/fs/reiser4/plugin/file/file_conversion.c |  204 ++++++---
 linux-2.6.23-mm1/fs/reiser4/plugin/file_ops.c             |   37 +
 linux-2.6.23-mm1/fs/reiser4/plugin/object.c               |  299 +++++++-------
 linux-2.6.23-mm1/fs/reiser4/plugin/plugin.h               |   73 ++-
 9 files changed, 590 insertions(+), 400 deletions(-)
fs/reiser4/plugin/file/file.c renamed from fs/reiser4/plugin/file/file.c.orig +4 -40
@@ -1372,42 +1372,6 @@
 	return result;
 }
 
-/*
- * ->sync() method for unix file.
- *
- * We are trying to be smart here. Instead of committing all atoms (original
- * solution), we scan dirty pages of this file and commit all atoms they are
- * part of.
- *
- * Situation is complicated by anonymous pages: i.e., extent-less pages
- * dirtied through mmap. Fortunately sys_fsync() first calls
- * filemap_fdatawrite() that will ultimately call reiser4_writepages(), insert
- * all missing extents and capture anonymous pages.
- */
-int sync_unix_file(struct file *file, struct dentry *dentry, int datasync)
-{
-	reiser4_context *ctx;
-	txn_atom *atom;
-	reiser4_block_nr reserve;
-
-	ctx = reiser4_init_context(dentry->d_inode->i_sb);
-	if (IS_ERR(ctx))
-		return PTR_ERR(ctx);
-
-	reserve = estimate_update_common(dentry->d_inode);
-	if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) {
-		reiser4_exit_context(ctx);
-		return RETERR(-ENOSPC);
-	}
-	write_sd_by_inode_common(dentry->d_inode);
-
-	atom = get_current_atom_locked();
-	spin_lock_txnh(ctx->trans);
-	force_commit_atom(ctx->trans);
-	reiser4_exit_context(ctx);
-	return 0;
-}
-
 /**
  * readpage_unix_file_nolock - readpage of struct address_space_operations
  * @file:
@@ -2126,7 +2090,7 @@
  * unix file plugin.
  */
 ssize_t write_unix_file(struct file *file, const char __user *buf,
-			size_t count, loff_t *pos)
+			size_t count, loff_t *pos, int *conv)
 {
 	int result;
 	reiser4_context *ctx;
@@ -2317,8 +2281,8 @@
 	if (result == 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
 		reiser4_txn_restart_current();
 		grab_space_enable();
-		result = sync_unix_file(file, file->f_dentry,
-					0 /* data and stat data */ );
+		result = reiser4_sync_file_common(file, file->f_dentry,
+						  0 /* data and stat data */);
 		if (result)
 			warning("reiser4-7", "failed to sync file %llu",
 				(unsigned long long)get_inode_oid(inode));
@@ -2703,7 +2667,7 @@
 }
 
 /**
- * delete_object_unix_file - delete_object of file_plugin
+ * delete_unix_file - delete_object of file_plugin
  * @inode: inode to be deleted
  *
  * Truncates file to length 0, removes stat data and safe link.
fs/reiser4/plugin/file/file.h renamed from fs/reiser4/plugin/file/file.h.orig +108 -58

202 lines not on this page · raw message

fs/reiser4/plugin/file/file_conversion.c renamed from fs/reiser4/plugin/file/file_conversion.c.orig +132 -72

287 lines not on this page · raw message

fs/reiser4/plugin/object.c renamed from fs/reiser4/plugin/object.c.orig +157 -142

354 lines not on this page · raw message

fs/reiser4/plugin/plugin.h renamed from fs/reiser4/plugin/plugin.h.orig +55 -18

100 lines not on this page · raw message

fs/reiser4/as_ops.c renamed from fs/reiser4/as_ops.c.orig +40 -0
@@ -326,6 +326,46 @@
 	}
 }
 
+int reiser4_readpage(struct file *file, struct page *page)
+{
+	assert("edward-1533", PageLocked(page));
+	assert("edward-1534", !PageUptodate(page));
+	assert("edward-1535", page->mapping && page->mapping->host);
+
+	return inode_file_plugin(page->mapping->host)->readpage(file, page);
+}
+
+int reiser4_readpages(struct file *file, struct address_space *mapping,
+		      struct list_head *pages, unsigned nr_pages)
+{
+	return inode_file_plugin(mapping->host)->readpages(file, mapping,
+							   pages, nr_pages);
+}
+
+int reiser4_writepages(struct address_space *mapping,
+		       struct writeback_control *wbc)
+{
+	return inode_file_plugin(mapping->host)->writepages(mapping, wbc);
+}
+
+int reiser4_prepare_write(struct file *file, struct page *page,
+			  unsigned from, unsigned to)
+{
+	return inode_file_plugin(file->f_dentry->d_inode)->prepare_write(file,
+									 page,
+									 from,
+									 to);
+}
+
+int reiser4_commit_write(struct file *file, struct page *page,
+			 unsigned from, unsigned to)
+{
+	return inode_file_plugin(file->f_dentry->d_inode)->commit_write(file,
+									page,
+									from,
+									to);
+}
+
 /* Make Linus happy.
    Local variables:
    c-indentation-style: "K&R"
fs/reiser4/plugin/file/cryptcompress.c renamed from fs/reiser4/plugin/file/cryptcompress.c.orig +47 -60

228 lines not on this page · raw message

fs/reiser4/plugin/file_ops.c renamed from fs/reiser4/plugin/file_ops.c.orig +37 -0
@@ -58,6 +58,43 @@
 	return result;
 }
 
+/*
+ * common sync method for regular files.
+ *
+ * We are trying to be smart here. Instead of committing all atoms (original
+ * solution), we scan dirty pages of this file and commit all atoms they are
+ * part of.
+ *
+ * Situation is complicated by anonymous pages: i.e., extent-less pages
+ * dirtied through mmap. Fortunately sys_fsync() first calls
+ * filemap_fdatawrite() that will ultimately call reiser4_writepages(), insert
+ * all missing extents and capture anonymous pages.
+ */
+int reiser4_sync_file_common(struct file *file,
+			     struct dentry *dentry, int datasync)
+{
+	reiser4_context *ctx;
+	txn_atom *atom;
+	reiser4_block_nr reserve;
+
+	ctx = reiser4_init_context(dentry->d_inode->i_sb);
+	if (IS_ERR(ctx))
+		return PTR_ERR(ctx);
+
+	reserve = estimate_update_common(dentry->d_inode);
+	if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) {
+		reiser4_exit_context(ctx);
+		return RETERR(-ENOSPC);
+	}
+	write_sd_by_inode_common(dentry->d_inode);
+
+	atom = get_current_atom_locked();
+	spin_lock_txnh(ctx->trans);
+	force_commit_atom(ctx->trans);
+	reiser4_exit_context(ctx);
+	return 0;
+}
+
 /* this is common implementation of vfs's sendfile method of struct
    file_operations
 
fs/reiser4/inode.c renamed from fs/reiser4/inode.c.orig +10 -10
@@ -151,38 +151,38 @@
 				rdev = data->rdev;
 			inode->i_blocks = 0;
 			assert("vs-42", fplug->h.id == SPECIAL_FILE_PLUGIN_ID);
-			inode->i_op = &file_plugins[fplug->h.id].inode_ops;
+			inode->i_op = file_plugins[fplug->h.id].inode_ops;
 			/* initialize inode->i_fop and inode->i_rdev for block and char
 			   devices */
 			init_special_inode(inode, inode->i_mode, rdev);
 			/* all address space operations are null */
 			inode->i_mapping->a_ops =
-			    &file_plugins[fplug->h.id].as_ops;
+			    file_plugins[fplug->h.id].as_ops;
 			break;
 		}
 	case S_IFLNK:
 		assert("vs-46", fplug != NULL);
 		assert("vs-42", fplug->h.id == SYMLINK_FILE_PLUGIN_ID);
-		inode->i_op = &file_plugins[fplug->h.id].inode_ops;
+		inode->i_op = file_plugins[fplug->h.id].inode_ops;
 		inode->i_fop = NULL;
 		/* all address space operations are null */
-		inode->i_mapping->a_ops = &file_plugins[fplug->h.id].as_ops;
+		inode->i_mapping->a_ops = file_plugins[fplug->h.id].as_ops;
 		break;
 	case S_IFDIR:
 		assert("vs-46", dplug != NULL);
 		assert("vs-43", (dplug->h.id == HASHED_DIR_PLUGIN_ID ||
 				 dplug->h.id == SEEKABLE_HASHED_DIR_PLUGIN_ID));
-		inode->i_op = &dir_plugins[dplug->h.id].inode_ops;
-		inode->i_fop = &dir_plugins[dplug->h.id].file_ops;
-		inode->i_mapping->a_ops = &dir_plugins[dplug->h.id].as_ops;
+		inode->i_op = dir_plugins[dplug->h.id].inode_ops;
+		inode->i_fop = dir_plugins[dplug->h.id].file_ops;
+		inode->i_mapping->a_ops = dir_plugins[dplug->h.id].as_ops;
 		break;
 	case S_IFREG:
 		assert("vs-46", fplug != NULL);
 		assert("vs-43", (fplug->h.id == UNIX_FILE_PLUGIN_ID ||
 				 fplug->h.id == CRYPTCOMPRESS_FILE_PLUGIN_ID));
-		inode->i_op = &file_plugins[fplug->h.id].inode_ops;
-		inode->i_fop = &file_plugins[fplug->h.id].file_ops;
-		inode->i_mapping->a_ops = &file_plugins[fplug->h.id].as_ops;
+		inode->i_op = file_plugins[fplug->h.id].inode_ops;
+		inode->i_fop = file_plugins[fplug->h.id].file_ops;
+		inode->i_mapping->a_ops = file_plugins[fplug->h.id].as_ops;
 		break;
 	default:
 		warning("nikita-291", "wrong file mode: %o for %llu",