fs/reiser4/plugin/file/cryptcompress.c | 7 ++ fs/reiser4/plugin/file/file.c | 79 ++++++++++++++++++++------------- fs/reiser4/plugin/file/file.h | 3 - fs/reiser4/plugin/file_plugin_common.c | 12 +---- fs/reiser4/plugin/object.c | 4 + fs/reiser4/plugin/plugin.h | 11 ++-- fs/reiser4/super.c | 1 fs/reiser4/super_ops.c | 31 ++++++++++++ 8 files changed, 102 insertions(+), 46 deletions(-) diff -puN fs/reiser4/plugin/file/cryptcompress.c~reiser4-add-put_inode fs/reiser4/plugin/file/cryptcompress.c --- linux-2.6.13/fs/reiser4/plugin/file/cryptcompress.c~reiser4-add-put_inode 2005-10-03 16:00:01.000000000 +0400 +++ linux-2.6.13-vs/fs/reiser4/plugin/file/cryptcompress.c 2005-10-03 16:02:00.000000000 +0400 @@ -3441,6 +3441,13 @@ int delete_cryptcompress(struct inode *i return delete_object_common(inode); } +/* plugin->u.file.pre_delete method + see plugin.h for description */ +int pre_delete_cryptcompress(struct inode *inode) +{ + return cryptcompress_truncate(inode, 0, 0); +} + /* plugin->u.file.setattr method see plugin.h for description */ int setattr_cryptcompress(struct dentry *dentry, /* Object to change attributes */ diff -puN fs/reiser4/plugin/file/file.c~reiser4-add-put_inode fs/reiser4/plugin/file/file.c --- linux-2.6.13/fs/reiser4/plugin/file/file.c~reiser4-add-put_inode 2005-10-03 16:00:08.000000000 +0400 +++ linux-2.6.13-vs/fs/reiser4/plugin/file/file.c 2005-10-03 17:10:02.000000000 +0400 @@ -721,31 +721,25 @@ append_hole(hint_t * hint, struct inode return result; } -/** - * truncate_file_body - change length of file - * @inode: inode of file - * @new_size: new file length - * - * Adjusts items file @inode is built of to match @new_size. It may either cut - * items or add them to represent a hole at the end of file. The caller has to - * obtain exclusive access to the file. - */ +/* this either cuts or add items of/to the file so that items match + new_size. It is used in unix_file_setattr when it is used to truncate + VS-FIXME-HANS: explain that and in unix_file_delete */ static int truncate_file_body(struct inode *inode, loff_t new_size) { int result; + hint_t *hint; - if (inode->i_size < new_size) { - hint_t *hint; - - hint = kmalloc(sizeof(*hint), GFP_KERNEL); - if (hint == NULL) - return RETERR(-ENOMEM); - hint_init_zero(hint); - result = append_hole(hint, inode, new_size, - 1 /* exclusive access is obtained */ ); - kfree(hint); - } else + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) + return RETERR(-ENOMEM); + hint_init_zero(hint); + if (inode->i_size < new_size) + result = + append_hole(hint, inode, new_size, + 1 /* exclusive access is obtained */ ); + else result = shorten_file(inode, new_size); + kfree(hint); return result; } @@ -2965,10 +2959,43 @@ init_inode_data_unix_file(struct inode * } /** + * pre_delete_unix_file - pre_delete of file_plugin + * @inode: inode to delete body of + * + * We need this because generic_delete_inode calls truncate_inode_pages before + * filesystem's delete_inode method. As result of this, reiser4 tree may have + * unallocated extents which do not have pages pointed by them (those pages are + * removed by truncate_inode_pages), which may confuse flush code. The solution + * for this problem is to call pre_delete method from reiser4_put_inode to + * remove file items together with corresponding pages. Generic_delete_inode + * will call truncate_inode_pages which will do nothing and + * reiser4_delete_inode which completes file deletion by removing stat data + * from the tree. + * + * This method is to be called from reiser4_put_inode when file is already + * unlinked and iput is about to drop last reference to inode. If nfsd manages + * to iget the file after pre_delete started, it will either be able to access + * a file content (if it will get access to file earlier than pre_delete) or it + * will get file truncated to 0 size if pre_delete goes first + */ +int pre_delete_unix_file(struct inode *inode) +{ + unix_file_info_t *uf_info; + int result; + + txn_restart_current(); + + uf_info = unix_file_inode_data(inode); + get_exclusive_access(uf_info); + result = truncate_file_body(inode, 0/* size */); + drop_exclusive_access(uf_info); + return result;} + +/** * delete_object_unix_file - delete_object of file_plugin * @inode: inode to be deleted * - * Truncates file to length 0, removes stat data and safe link. + * removes stat data and safe link. */ int delete_object_unix_file(struct inode *inode) { @@ -2981,16 +3008,6 @@ int delete_object_unix_file(struct inode if (inode_get_flag(inode, REISER4_NO_SD)) return 0; - /* truncate file bogy first */ - uf_info = unix_file_inode_data(inode); - get_exclusive_access(uf_info); - result = truncate_file_body(inode, 0 /* size */ ); - drop_exclusive_access(uf_info); - - if (result) - warning("", "failed to truncate file (%llu) on removal: %d", - get_inode_oid(inode), result); - /* remove stat data and safe link */ return delete_object_common(inode); } diff -puN fs/reiser4/plugin/file/file.h~reiser4-add-put_inode fs/reiser4/plugin/file/file.h --- linux-2.6.13/fs/reiser4/plugin/file/file.h~reiser4-add-put_inode 2005-10-03 16:00:10.000000000 +0400 +++ linux-2.6.13-vs/fs/reiser4/plugin/file/file.h 2005-10-03 16:02:00.000000000 +0400 @@ -40,7 +40,7 @@ int flow_by_inode_unix_file(struct inode int owns_item_unix_file(const struct inode *, const coord_t *); void init_inode_data_unix_file(struct inode *, reiser4_object_create_data *, int create); -int delete_object_unix_file(struct inode *); +int pre_delete_unix_file(struct inode *); /* all the write into unix file is performed by item write method. Write method of unix file plugin only decides which item plugin (extent or tail) and in @@ -193,6 +193,7 @@ int cut_tree_worker_cryptcompress(tap_t reiser4_key * smallest_removed, struct inode *object, int truncate, int *progress); +int pre_delete_cryptcompress(struct inode *); void destroy_inode_cryptcompress(struct inode *); extern reiser4_plugin_ops cryptcompress_plugin_ops; diff -puN fs/reiser4/plugin/file_plugin_common.c~reiser4-add-put_inode fs/reiser4/plugin/file_plugin_common.c --- linux-2.6.13/fs/reiser4/plugin/file_plugin_common.c~reiser4-add-put_inode 2005-10-03 16:00:34.000000000 +0400 +++ linux-2.6.13-vs/fs/reiser4/plugin/file_plugin_common.c 2005-10-03 16:02:00.000000000 +0400 @@ -164,14 +164,9 @@ create_object_common(struct inode *objec static int common_object_delete_no_reserve(struct inode *inode); -/** - * delete_object_common - delete_object of file_plugin - * @inode: inode to be deleted - * - * This is common implementation of delete_object method of file_plugin. It - * applies to object its deletion consists of removing two items - stat data - * and safe-link. - */ +/* this is common implementation of delete method of file plugin + all it does is object stat data removal +*/ int delete_object_common(struct inode *inode) { int result; @@ -182,7 +177,6 @@ int delete_object_common(struct inode *i assert("nikita-3420", inode->i_size == 0 || S_ISLNK(inode->i_mode)); assert("nikita-3421", inode->i_nlink == 0); - if (!inode_get_flag(inode, REISER4_NO_SD)) { reiser4_block_nr reserve; diff -puN fs/reiser4/plugin/object.c~reiser4-add-put_inode fs/reiser4/plugin/object.c --- linux-2.6.13/fs/reiser4/plugin/object.c~reiser4-add-put_inode 2005-10-03 16:00:38.000000000 +0400 +++ linux-2.6.13-vs/fs/reiser4/plugin/object.c 2005-10-03 16:02:00.000000000 +0400 @@ -126,7 +126,7 @@ file_plugin file_plugins[LAST_FILE_PLUGI .set_plug_in_inode = set_plug_in_inode_common, .adjust_to_parent = adjust_to_parent_common, .create_object = create_object_common, /* this is not inode_operations's create */ - .delete_object = delete_object_unix_file, + .delete_object = delete_object_common, .add_link = add_link_common, .rem_link = rem_link_common, .owns_item = owns_item_unix_file, @@ -141,6 +141,7 @@ file_plugin file_plugins[LAST_FILE_PLUGI }, .init_inode_data = init_inode_data_unix_file, .cut_tree_worker = cut_tree_worker_common, + .pre_delete = pre_delete_unix_file, .wire = { .write = wire_write_common, .read = wire_read_common, @@ -338,6 +339,7 @@ file_plugin file_plugins[LAST_FILE_PLUGI }, .init_inode_data = init_inode_data_cryptcompress, .cut_tree_worker = cut_tree_worker_cryptcompress, + .pre_delete = pre_delete_cryptcompress, .destroy_inode = destroy_inode_cryptcompress, .wire = { .write = wire_write_common, diff -puN fs/reiser4/plugin/plugin.h~reiser4-add-put_inode fs/reiser4/plugin/plugin.h --- linux-2.6.13/fs/reiser4/plugin/plugin.h~reiser4-add-put_inode 2005-10-03 16:00:43.000000000 +0400 +++ linux-2.6.13-vs/fs/reiser4/plugin/plugin.h 2005-10-03 16:02:00.000000000 +0400 @@ -249,10 +249,10 @@ typedef struct file_plugin { reiser4_object_create_data *); /* - * this method should check REISER4_NO_SD and set REISER4_NO_SD on - * success. Deletion of an object usually includes removal of items - * building file body (for directories this is removal of "." and "..") - * and removal of stat-data item. + * delete empty object. This method should check REISER4_NO_SD and set + * REISER4_NO_SD on success. Deletion of empty object at least includes + * removal of stat-data if any. For directories this also includes + * removal of dot and dot-dot. */ int (*delete_object) (struct inode *); @@ -324,6 +324,9 @@ typedef struct file_plugin { reiser4_key * smallest_removed, struct inode *, int, int *); + /* truncate file to zero size. called by reiser4_drop_inode before truncate_inode_pages */ + int (*pre_delete) (struct inode *); + /* called from ->destroy_inode() */ void (*destroy_inode) (struct inode *); diff -puN fs/reiser4/super.c~reiser4-add-put_inode fs/reiser4/super.c --- linux-2.6.13/fs/reiser4/super.c~reiser4-add-put_inode 2005-10-03 16:00:52.000000000 +0400 +++ linux-2.6.13-vs/fs/reiser4/super.c 2005-10-03 16:02:00.000000000 +0400 @@ -17,6 +17,7 @@ #include /* for __u?? */ #include /* for struct super_block */ + /*const __u32 REISER4_SUPER_MAGIC = 0x52345362;*//* (*(__u32 *)"R4Sb"); */ static __u64 reserved_for_gid(const struct super_block *super, gid_t gid); static __u64 reserved_for_uid(const struct super_block *super, uid_t uid); diff -puN fs/reiser4/vfs_ops.c~reiser4-add-put_inode fs/reiser4/vfs_ops.c diff -puN fs/reiser4/super_ops.c~reiser4-add-put_inode fs/reiser4/super_ops.c --- linux-2.6.13/fs/reiser4/super_ops.c~reiser4-add-put_inode 2005-10-03 16:39:16.000000000 +0400 +++ linux-2.6.13-vs/fs/reiser4/super_ops.c 2005-10-03 17:13:57.000000000 +0400 @@ -156,6 +156,36 @@ static void reiser4_destroy_inode(struct } /** + * reiser4_put_inode - put_inode of super_operations + * @inode: inode being removed from cache + * + * we use put_inode to call pre_delete method of file plugin if it is defined + * and if inode is unlinked and if it is about to drop inode reference count to + * 0. + */ +static void reiser4_put_inode(struct inode *inode) +{ + reiser4_context *ctx; + file_plugin *fplug; + + fplug = inode_file_plugin(inode); + if (fplug == NULL || + inode->i_nlink != 0 || + atomic_read(&inode->i_count) > 1 || fplug->pre_delete == NULL) + return; + + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) { + warning("vs-14", "failed to init context"); + return; + } + /* kill cursors which might be attached to inode if it were a directory one */ + kill_cursors(inode); + fplug->pre_delete(inode); + reiser4_exit_context(ctx); +} + +/** * reiser4_dirty_inode - dirty_inode of super operations * @inode: inode being dirtied * @@ -443,6 +473,7 @@ static int reiser4_show_options(struct s struct super_operations reiser4_super_operations = { .alloc_inode = reiser4_alloc_inode, .destroy_inode = reiser4_destroy_inode, + .put_inode = reiser4_put_inode, .dirty_inode = reiser4_dirty_inode, .delete_inode = reiser4_delete_inode, .put_super = reiser4_put_super, _ .