===== fs/reiserfs/inode.c 1.42 vs edited =====
--- 1.42/fs/reiserfs/inode.c Thu Feb 13 15:42:42 2003
+++ edited/fs/reiserfs/inode.c Thu Feb 20 17:23:24 2003
@@ -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 rae 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);
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;
}