reiser4: make methods supplied to vfs invariant
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.
Signed-off-by Edward Shishkin <[email protected]>
--- 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",