patch-2.4.10 linux/fs/reiserfs/inode.c

Next file: linux/fs/reiserfs/ioctl.c
Previous file: linux/fs/reiserfs/ibalance.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.9/linux/fs/reiserfs/inode.c linux/fs/reiserfs/inode.c
@@ -1,7 +1,6 @@
 /*
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  */
-#ifdef __KERNEL__
 
 #include <linux/config.h>
 #include <linux/sched.h>
@@ -10,12 +9,6 @@
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 
-#else
-
-#include "nokernel.h"
-
-#endif
-
 /* args for the create parameter of reiserfs_get_block */
 #define GET_BLOCK_NO_CREATE 0 /* don't create new blocks or convert tails */
 #define GET_BLOCK_CREATE 1    /* add anything you need to find block */
@@ -55,6 +48,7 @@
 	;
     }
     clear_inode (inode); /* note this must go after the journal_end to prevent deadlock */
+    inode->i_blocks = 0;
     unlock_kernel() ;
 }
 
@@ -525,16 +519,26 @@
     int fs_gen;
     int windex ;
     struct reiserfs_transaction_handle th ;
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 ;
+    /* space reserved in transaction batch: 
+        . 3 balancings in direct->indirect conversion
+        . 1 block involved into reiserfs_update_sd()
+       XXX in practically impossible worst case direct2indirect()
+       can incur (much) more that 3 balancings. */
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1;
     int version;
     int transaction_started = 0 ;
-    loff_t new_offset = (block << inode->i_sb->s_blocksize_bits) + 1 ;
+    loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;
 
 				/* bad.... */
     lock_kernel() ;
     th.t_trans_id = 0 ;
     version = inode_items_version (inode);
 
+    if (block < 0) {
+	unlock_kernel();
+	return -EIO;
+    }
+
     if (!file_capable (inode, block)) {
 	unlock_kernel() ;
 	return -EFBIG;
@@ -552,20 +556,14 @@
 	return ret;
     }
 
-    if (block < 0) {
-	unlock_kernel();
-	return -EIO;
-    }
-
     inode->u.reiserfs_i.i_pack_on_close = 1 ;
 
     windex = push_journal_writer("reiserfs_get_block") ;
   
     /* set the key of the first byte in the 'block'-th block of file */
-    make_cpu_key (&key, inode,
-		  (loff_t)block * inode->i_sb->s_blocksize + 1, // k_offset
+    make_cpu_key (&key, inode, new_offset,
 		  TYPE_ANY, 3/*key length*/);
-    if ((new_offset + inode->i_sb->s_blocksize) >= inode->i_size) {
+    if ((new_offset + inode->i_sb->s_blocksize - 1) > inode->i_size) {
 	journal_begin(&th, inode->i_sb, jbegin_count) ;
 	transaction_started = 1 ;
     }
@@ -618,10 +616,13 @@
     }
 
     if (indirect_item_found (retval, ih)) {
+	b_blocknr_t unfm_ptr;
+
 	/* 'block'-th block is in the file already (there is
 	   corresponding cell in some indirect item). But it may be
 	   zero unformatted node pointer (hole) */
-	if (!item[pos_in_item]) {
+	unfm_ptr = le32_to_cpu (item[pos_in_item]);
+	if (unfm_ptr == 0) {
 	    /* use allocated block to plug the hole */
 	    reiserfs_prepare_for_journal(inode->i_sb, bh, 1) ;
 	    if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {
@@ -630,15 +631,14 @@
 	    }
 	    bh_result->b_state |= (1UL << BH_New);
 	    item[pos_in_item] = cpu_to_le32 (allocated_block_nr);
+	    unfm_ptr = allocated_block_nr;
 	    journal_mark_dirty (&th, inode->i_sb, bh);
 	    inode->i_blocks += (inode->i_sb->s_blocksize / 512) ;
 	    reiserfs_update_sd(&th, inode) ;
 	}
-	set_block_dev_mapped(bh_result, le32_to_cpu (item[pos_in_item]), inode);
+	set_block_dev_mapped(bh_result, unfm_ptr, inode);
 	pathrelse (&path);
-#ifdef REISERFS_CHECK
 	pop_journal_writer(windex) ;
-#endif /* REISERFS_CHECK */
 	if (transaction_started)
 	    journal_end(&th, inode->i_sb, jbegin_count) ;
 
@@ -815,8 +815,8 @@
 	    goto failure;
 	}
 	if (retval == POSITION_FOUND) {
-	    reiserfs_warning ("vs-: reiserfs_get_block: "
-			      "%k should not be found", &key);
+	    reiserfs_warning ("vs-825: reiserfs_get_block: "
+			      "%k should not be found\n", &key);
 	    retval = -EEXIST;
 	    if (allocated_block_nr)
 	        reiserfs_free_block (&th, allocated_block_nr);
@@ -1139,7 +1139,7 @@
     args.objectid = key->on_disk_key.k_dir_id ;
     inode = iget4 (s, key->on_disk_key.k_objectid, 0, (void *)(&args));
     if (!inode) 
-      return inode ;
+	return ERR_PTR(-ENOMEM) ;
 
     if (comp_short_keys (INODE_PKEY (inode), key) || is_bad_inode (inode)) {
 	/* either due to i/o error or a stale NFS handle */
@@ -1156,6 +1156,24 @@
     struct list_head *lp;
     struct dentry *result;
 
+    /* fhtype happens to reflect the number of u32s encoded.
+     * due to a bug in earlier code, fhtype might indicate there
+     * are more u32s then actually fitted.
+     * so if fhtype seems to be more than len, reduce fhtype.
+     * Valid types are:
+     *   2 - objectid + dir_id - legacy support
+     *   3 - objectid + dir_id + generation
+     *   4 - objectid + dir_id + objectid and dirid of parent - legacy
+     *   5 - objectid + dir_id + generation + objectid and dirid of parent
+     *   6 - as above plus generation of directory
+     * 6 does not fit in NFSv2 handles
+     */
+    if (fhtype > len) {
+	    if (fhtype != 6 || len != 5)
+		    printk(KERN_WARNING "nfsd/reiserfs, fhtype=%d, len=%d - odd\n",
+			   fhtype, len);
+	    fhtype = 5;
+    }
     if (fhtype < 2 || (parent && fhtype < 4)) 
 	goto out ;
 
@@ -1166,22 +1184,24 @@
 	    key.on_disk_key.k_objectid = data[0] ;
 	    key.on_disk_key.k_dir_id = data[1] ;
 	    inode = reiserfs_iget(sb, &key) ;
-	    if (inode && (fhtype == 3 || fhtype == 6) &&
+	    if (inode && !IS_ERR(inode) && (fhtype == 3 || fhtype >= 5) &&
 		data[2] != inode->i_generation) {
 		    iput(inode) ;
 		    inode = NULL ;
 	    }
     } else {
-	    key.on_disk_key.k_objectid = data[fhtype==6?3:2] ;
-	    key.on_disk_key.k_dir_id = data[fhtype==6?4:3] ;
+	    key.on_disk_key.k_objectid = data[fhtype>=5?3:2] ;
+	    key.on_disk_key.k_dir_id = data[fhtype>=5?4:3] ;
 	    inode = reiserfs_iget(sb, &key) ;
-	    if (inode && fhtype == 6 &&
+	    if (inode && !IS_ERR(inode) && fhtype == 6 &&
 		data[5] != inode->i_generation) {
 		    iput(inode) ;
 		    inode = NULL ;
 	    }
     }
 out:
+    if (IS_ERR(inode))
+	return ERR_PTR(PTR_ERR(inode));
     if (!inode)
         return ERR_PTR(-ESTALE) ;
 
@@ -1220,17 +1240,20 @@
     data[0] = inode->i_ino ;
     data[1] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ;
     data[2] = inode->i_generation ;
-    *lenp = 3;
+    *lenp = 3 ;
     /* no room for directory info? return what we've stored so far */
-    if (maxlen < 6 || ! need_parent)
-        return 3;
+    if (maxlen < 5 || ! need_parent)
+        return 3 ;
 
     inode = dentry->d_parent->d_inode ;
     data[3] = inode->i_ino ;
     data[4] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ;
+    *lenp = 5 ;
+    if (maxlen < 6)
+	    return 5 ;
     data[5] = inode->i_generation ;
-    *lenp = 6;
-    return 6; 
+    *lenp = 6 ;
+    return 6 ;
 }
 
 
@@ -1790,7 +1813,6 @@
     for(i = 0 ; i < nr ; i++) {
         bh = bhp[i] ;
 	lock_buffer(bh) ;
-	get_bh(bh) ;		   /* async end_io handler puts this */
 	set_buffer_async_io(bh) ;
 	/* submit_bh doesn't care if the buffer is dirty, but nobody
 	** later on in the call chain will be cleaning it.  So, we

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)