[2.4] reiserfs: iget4() race fix]
Signature · 2 lines
-- Hans
Hello!
This changeset implements a fix for iget4() race possible on reiserfs filesystems. This is minimalistic fix that is intended to be replaced with iget5_locked() implementation later on. The iget5_locked patch is too much of a change for 2.4.21-rc2, I afraid. The race itself may lead to pretty much disasters, we've already seen it may lead to direntries pointing to nowhere, incorrect nlink counts, NFS problems.
Please pull from bk://namesys.com/bk/reiser3-linux-2.4-race-fix
Diffstat:
inode.c | 26 ++++++++++++++++++++++++-- 1 files changed, 24 insertions(+), 2 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.988 -> 1.989
# fs/reiserfs/inode.c 1.42 -> 1.43
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/05/03 [email protected] 1.989
# reiserfs: iget4() race fix
# --------------------------------------------
#
fs/reiserfs/inode.c +24 -2
@@ -20,6 +20,10 @@static int reiserfs_get_block (struct inode * inode,long block,struct buffer_head * bh_result,int create); +/* This spinlock guards inode pkey in private part of inode +against race between find_actor() vs reiserfs_read_inode2 */ +static spinlock_t keycopy_lock =SPIN_LOCK_UNLOCKED ; +void reiserfs_delete_inode (struct inode * inode) {int jbegin_count =JOURNAL_PER_BALANCE_CNT *2 ;
@@ -898,8 +902,9 @@ bh =PATH_PLAST_BUFFER (path); ih =PATH_PITEM_HEAD (path); - +spin_lock (&keycopy_lock);copy_key (INODE_PKEY (inode), &(ih->ih_key)); +spin_unlock (&keycopy_lock); inode->i_blksize =PAGE_SIZE ;INIT_LIST_HEAD (&inode->u.reiserfs_i.i_prealloc_list) ;
@@ -1220,10 +1225,27 @@ unsigned long inode_no, void *opaque ) { struct reiserfs_iget4_args *args; +int retval; args = opaque; +/* We protect against possible parallel init_inode() on another CPU here. */ +spin_lock (&keycopy_lock);/* args is already in CPU order */ -return le32_to_cpu (INODE_PKEY (inode)->k_dir_id) == args -> objectid; +if (le32_to_cpu (INODE_PKEY (inode)->k_dir_id) == args -> objectid) + retval =1 ; +else +/* If The key does not match, lets see if we are racing +with another iget4, that already progressed so far +to reiserfs_read_inode2() and was preempted in +call to search_by_key(). The signs of that are: +Inode is locked +dirid and object id are zero (not yet initialized)*/ + retval = (inode->i_state &I_LOCK ) && + !INODE_PKEY (inode)->k_dir_id && + !INODE_PKEY (inode)->k_objectid; + +spin_unlock (&keycopy_lock); +return retval; }struct inode *reiserfs_iget (struct super_block * s,const struct cpu_key * key)