[2.4] ReiserFS iput deadlock fix
Please apply.
Signature · 1 line
Hans
Hello!
This changeset fixes possible iput deadlock in reiserfs, when iput is called and transaction is open. This is sometimes happen when there is no free space on the partition.
Please apply.
You can pull it from bk://thebsh.namesys.com/bk/reiser3-linux-2.4-iput-ddlk-fix
Diffstat:
fs/reiserfs/inode.c | 120 +++++++++++++++++++---------------- fs/reiserfs/namei.c | 147 +++++++++++++++++++++++++++----------------- include/linux/reiserfs_fs.h | 11 +-- 3 files changed, 162 insertions(+), 116 deletions(-)
Plain text patch:
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas:
# ChangeSet 1.903 -> 1.904 # fs/reiserfs/inode.c 1.40 -> 1.41 # fs/reiserfs/namei.c 1.24 -> 1.25
# include/linux/reiserfs_fs.h 1.25 -> 1.26
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/01/20 [email protected] 1.904
# reiserfs: iput deadlock fix - do not call iput() from inside of transaction # --------------------------------------------
#
fs/reiserfs/inode.c +64 -56
@@ -1463,13 +1463,22 @@/* inserts the stat data into the tree, and then calls reiserfs_new_directory (to insert ".", ".." item if new object is directory) or reiserfs_new_symlink (to insert symlink body if new -object is symlink) or nothing (if new object is regular file) */ -struct inode *reiserfs_new_inode (struct reiserfs_transaction_handle *th, -struct inode * dir,int mode, -const char * symname, -int i_size,/* 0 for regular, EMTRY_DIR_SIZE for dirs, -strlen (symname) for symlinks)*/ -struct dentry *dentry,struct inode *inode,int * err) +object is symlink) or nothing (if new object is regular file) + +NOTE! uid and gid must already be set in the inode. If we return +non-zero due to an error, we have to drop the quota previously allocated +for the fresh inode. This can only be done outside a transaction, so +if we return non-zero, we also end the transaction. + +*/ +int reiserfs_new_inode (struct reiserfs_transaction_handle *th, +struct inode * dir,int mode, +const char * symname, +/* 0 for regular, EMTRY_DIR_SIZE for dirs, +strlen (symname) for symlinks) */ +int i_size, +struct dentry *dentry, +struct inode *inode) {struct super_block * sb;INITIALIZE_PATH (path_to_key);
@@ -1477,11 +1486,11 @@struct item_head ih;struct stat_data sd;int retval; +int err ;if (!dir || !dir->i_nlink) { - *err = -EPERM ; -iput (inode) ; -return NULL ; + err = -EPERM ; + goto out_bad_inode ; } sb = dir->i_sb;
@@ -1489,13 +1498,16 @@ dir -> u.reiserfs_i.i_attrs &REISERFS_INHERIT_MASK ;sd_attrs_to_i_attrs ( inode -> u.reiserfs_i.i_attrs, inode ); +/* symlink cannot be immutable or append only, right? */ +if (S_ISLNK ( inode -> i_mode ) ) + inode -> i_flags &= ~ (S_IMMUTABLE |S_APPEND ); +/* item head of new item */ ih.ih_key.k_dir_id =INODE_PKEY (dir)->k_objectid; ih.ih_key.k_objectid =cpu_to_le32 (reiserfs_get_unused_objectid (th));if (!ih.ih_key.k_objectid) { -iput (inode) ; - *err = -ENOMEM ; -return NULL ; + err = -ENOMEM ; + goto out_bad_inode ; }if (old_format_only (sb))/* not a perfect generation count, as object ids can be reused, but this
@@ -1511,12 +1523,24 @@#else inode->i_generation = ++event;#endif +/* fill stat data */ + inode->i_nlink = (S_ISDIR (mode) ?2 :1 ); + +/* uid and gid must already be set by the caller for quota init */ + + inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME ; + inode->i_size = i_size; + inode->i_blocks = (inode->i_size +511 ) >>9 ; + inode->u.reiserfs_i.i_first_direct_byte =S_ISLNK (mode) ?1 : +U32_MAX /*NO_BYTES_IN_DIRECT_ITEM*/ ; + +INIT_LIST_HEAD (&inode->u.reiserfs_i.i_prealloc_list) ; +if (old_format_only (sb))make_le_item_head (&ih,0 ,KEY_FORMAT_3_5 ,SD_OFFSET ,TYPE_STAT_DATA ,SD_V1_SIZE ,MAX_US_INT );else make_le_item_head (&ih,0 ,KEY_FORMAT_3_6 ,SD_OFFSET ,TYPE_STAT_DATA ,SD_SIZE ,MAX_US_INT ); -/* key to search for correct place for new stat data */ _make_cpu_key (&key,KEY_FORMAT_3_6 ,le32_to_cpu (ih.ih_key.k_dir_id),le32_to_cpu (ih.ih_key.k_objectid),SD_OFFSET ,TYPE_STAT_DATA ,3 /*key length*/ );
@@ -1524,47 +1548,21 @@/* find proper place for inserting of stat data */ retval =search_item (sb, &key, &path_to_key);if (retval ==IO_ERROR ) { -iput (inode); - *err = -EIO ; -return NULL ; + err = -EIO ; + goto out_bad_inode; }if (retval ==ITEM_FOUND ) {pathrelse (&path_to_key); -iput (inode); - *err = -EEXIST ; -return NULL ; + err = -EEXIST ; + goto out_bad_inode; } -/* fill stat data */ - inode->i_mode = mode; - inode->i_nlink = (S_ISDIR (mode) ?2 :1 ); - inode->i_uid = current->fsuid; -if (dir->i_mode &S_ISGID ) { - inode->i_gid = dir->i_gid; -if (S_ISDIR (mode)) - inode->i_mode |=S_ISGID ; - }else - inode->i_gid = current->fsgid; - -/* symlink cannot be immutable or append only, right? */ -if (S_ISLNK ( inode -> i_mode ) ) - inode -> i_flags &= ~ (S_IMMUTABLE |S_APPEND ); - - inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME ; - inode->i_size = i_size; - inode->i_blocks = (inode->i_size +511 ) >>9 ; - inode->u.reiserfs_i.i_first_direct_byte =S_ISLNK (mode) ?1 : -U32_MAX /*NO_BYTES_IN_DIRECT_ITEM*/ ; - -INIT_LIST_HEAD (&inode->u.reiserfs_i.i_prealloc_list) ; -if (old_format_only (sb)) {if (inode->i_uid & ~0xffff || inode->i_gid & ~0xffff ) {pathrelse (&path_to_key);/* i_uid or i_gid is too big to be stored in stat data v3.5 */ -iput (inode); - *err = -EINVAL ; -return NULL ; + err = -EINVAL ; + goto out_bad_inode; }inode2sd_v1 (&sd, inode); }else
@@ -1595,10 +1593,9 @@#endif retval =reiserfs_insert_item (th, &path_to_key, &key, &ih, (char *)(&sd));if (retval) { -iput (inode); - *err = retval;reiserfs_check_path (&path_to_key) ; -return NULL ; + err = retval; + goto out_bad_inode; }#ifdef DISPLACE_NEW_PACKING_LOCALITIES
@@ -1617,19 +1614,30 @@ retval =reiserfs_new_symlink (th, &ih, &path_to_key, symname, i_size); }if (retval) { - inode->i_nlink =0 ; -iput (inode); - *err = retval; + err = retval;reiserfs_check_path (&path_to_key) ; -return NULL ; +journal_end (th, th->t_super, th->t_blocks_allocated) ; + goto out_inserted_sd; }insert_inode_hash (inode); -// we do not mark inode dirty: on disk content matches to the -// in-core one +reiserfs_update_sd (th, inode) ;reiserfs_check_path (&path_to_key) ; -return inode; +return 0 ; +out_bad_inode: +/* Invalidate the object, nothing was inserted yet */ +INODE_PKEY (inode)->k_objectid =0 ; + +/* dquot_drop must be done outside a transaction */ +journal_end (th, th->t_super, th->t_blocks_allocated) ; +make_bad_inode (inode); + +out_inserted_sd: + inode->i_nlink =0 ; + th->t_trans_id =0 ;/* so the caller can't use this handle later */ +iput (inode) ; +return err; }/*
fs/reiserfs/namei.c +92 -55
279 lines not on this page · raw message
include/linux/reiserfs_fs.h +6 -5
@@ -1748,11 +1748,12 @@struct inode *reiserfs_iget (struct super_block * s,const struct cpu_key * key); - -struct inode *reiserfs_new_inode (struct reiserfs_transaction_handle *th, -struct inode * dir,int mode, -const char * symname,int item_len, -struct dentry *dentry,struct inode *inode,int * err); +int reiserfs_new_inode (struct reiserfs_transaction_handle *th, +struct inode * dir,int mode, +const char * symname, +int i_size, +struct dentry *dentry, +struct inode *inode);int reiserfs_sync_inode (struct reiserfs_transaction_handle *th,struct inode * inode);void reiserfs_update_sd (struct reiserfs_transaction_handle *th,struct inode * inode);
Bye,
Oleg
PATCH 1/1 [2.4] Speedup 'make dep'
Hi Marcelo,
During 'make dep', make spends most of its time (sometimes more than 75%) uselessly analysing .hdepend. Delaying its production makes 'make dep' much faster.
The following patch also builds .depend last, in order to make the dependency information generation more resistant against ^C and other failures.
Regards,
-- Benoit
Makefile +3 -2
@@ -488,12 +488,13 @@ find . -type f -print | sort | xargs sum > .SUMS dep-files: scripts/mkdep archdep include/linux/version.h - scripts/mkdep -- init/*.c > .depend - scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend + rm -f .depend .hdepend $(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" ifdef CONFIG_MODVERSIONS $(MAKE) update-modverfile endif + scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend + scripts/mkdep -- init/*.c > .depend ifdef CONFIG_MODVERSIONS MODVERFILE := $(TOPDIR)/include/linux/modversions.h
Re: [PATCH][2.4] Speedup 'make dep'
On Tuesday 21 January 2003 02:03, Benoit Poulot-Cazajous wrote:
Hi Marcelo,
apply this too, please!
Quoted 10 lines
During 'make dep', make spends most of its time (sometimes more than 75%) uselessly analysing .hdepend. Delaying its production makes 'make dep' much faster.
The following patch also builds .depend last, in order to make the dependency information generation more resistant against ^C and other failures.Regards,
-- Benoit
Makefile +3 -2
@@ -488,12 +488,13 @@ find . -type f -print | sort | xargs sum > .SUMS dep-files: scripts/mkdep archdep include/linux/version.h - scripts/mkdep -- init/*.c > .depend - scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend + rm -f .depend .hdepend $(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" ifdef CONFIG_MODVERSIONS $(MAKE) update-modverfile endif + scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend + scripts/mkdep -- init/*.c > .depend ifdef CONFIG_MODVERSIONS MODVERFILE := $(TOPDIR)/include/linux/modversions.h