vserver 1.9.5.x5
[linux-2.6.git] / fs / reiserfs / inode.c
index ce9c3d8..d44d122 100644 (file)
@@ -4,7 +4,10 @@
 
 #include <linux/config.h>
 #include <linux/time.h>
+#include <linux/fs.h>
 #include <linux/reiserfs_fs.h>
+#include <linux/reiserfs_acl.h>
+#include <linux/reiserfs_xattr.h>
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
 #include <linux/buffer_head.h>
 #include <linux/mpage.h>
 #include <linux/writeback.h>
+#include <linux/quotaops.h>
 #include <linux/vserver/xid.h>
 
 extern int reiserfs_default_io_size; /* default io size devuned in super.c */
 
-/* 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 */
-#define GET_BLOCK_NO_HOLE 2   /* return -ENOENT for file holes */
-#define GET_BLOCK_READ_DIRECT 4  /* read the tail if indirect item not found */
-#define GET_BLOCK_NO_ISEM     8 /* i_sem is not held, don't preallocate */
-#define GET_BLOCK_NO_DANGLE   16 /* don't leave any transactions running */
-
-static int reiserfs_get_block (struct inode * inode, sector_t block,
-                              struct buffer_head * bh_result, int create);
 static int reiserfs_commit_write(struct file *f, struct page *page,
                                  unsigned from, unsigned to);
+static int reiserfs_prepare_write(struct file *f, struct page *page,
+                                 unsigned from, unsigned to);
 
 void reiserfs_delete_inode (struct inode * inode)
 {
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2; 
+    /* We need blocks for transaction + (user+group) quota update (possibly delete) */
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS;
     struct reiserfs_transaction_handle th ;
   
     reiserfs_write_lock(inode->i_sb);
@@ -41,21 +38,39 @@ void reiserfs_delete_inode (struct inode * inode)
     if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
        down (&inode->i_sem); 
 
-       journal_begin(&th, inode->i_sb, jbegin_count) ;
+       reiserfs_delete_xattrs (inode);
+
+       if (journal_begin(&th, inode->i_sb, jbegin_count)) {
+           up (&inode->i_sem);
+           goto out;
+       }
        reiserfs_update_inode_transaction(inode) ;
 
-       reiserfs_delete_object (&th, inode);
+       if (reiserfs_delete_object (&th, inode)) {
+           up (&inode->i_sem);
+           goto out;
+       }
 
-       journal_end(&th, inode->i_sb, jbegin_count) ;
+       /* Do quota update inside a transaction for journaled quotas. We must do that
+        * after delete_object so that quota updates go into the same transaction as
+        * stat data deletion */
+       DQUOT_FREE_INODE(inode);
+
+       if (journal_end(&th, inode->i_sb, jbegin_count)) {
+           up (&inode->i_sem);
+           goto out;
+       }
 
         up (&inode->i_sem);
 
         /* all items of file are deleted, so we can remove "save" link */
-       remove_save_link (inode, 0/* not truncate */);
+       remove_save_link (inode, 0/* not truncate */); /* we can't do anything
+                                                        * about an error here */
     } else {
        /* no object items are in the tree */
        ;
     }
+out:
     clear_inode (inode); /* note this must go after the journal_end to prevent deadlock */
     inode->i_blocks = 0;
     reiserfs_write_unlock(inode->i_sb);
@@ -195,20 +210,28 @@ static int file_capable (struct inode * inode, long block)
     return 0;
 }
 
-/*static*/ void restart_transaction(struct reiserfs_transaction_handle *th,
+/*static*/ int restart_transaction(struct reiserfs_transaction_handle *th,
                                struct inode *inode, struct path *path) {
   struct super_block *s = th->t_super ;
   int len = th->t_blocks_allocated ;
+  int err;
+
+  BUG_ON (!th->t_trans_id);
+  BUG_ON (!th->t_refcount);
 
   /* we cannot restart while nested */
   if (th->t_refcount > 1) {
-      return  ;
+      return  ;
   }
   pathrelse(path) ;
   reiserfs_update_sd(th, inode) ;
-  journal_end(th, s, len) ;
-  journal_begin(th, s, JOURNAL_PER_BALANCE_CNT * 6) ;
-  reiserfs_update_inode_transaction(inode) ;
+  err = journal_end(th, s, len) ;
+  if (!err) {
+      err = journal_begin(th, s, JOURNAL_PER_BALANCE_CNT * 6) ;
+      if (!err)
+        reiserfs_update_inode_transaction(inode) ;
+  }
+  return err;
 }
 
 // it is called by get_block when create == 0. Returns block number
@@ -383,8 +406,8 @@ finished:
 
 // this is called to create file map. So, _get_block_create_0 will not
 // read direct item
-int reiserfs_bmap (struct inode * inode, sector_t block,
-                  struct buffer_head * bh_result, int create)
+static int reiserfs_bmap (struct inode * inode, sector_t block,
+                         struct buffer_head * bh_result, int create)
 {
     if (!file_capable (inode, block))
        return -EFBIG;
@@ -437,9 +460,11 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode,
 
     ret = reiserfs_get_block(inode, iblock, bh_result,
                              create | GET_BLOCK_NO_DANGLE) ;
+    if (ret)
+        goto out;
 
     /* don't allow direct io onto tail pages */
-    if (ret == 0 && buffer_mapped(bh_result) && bh_result->b_blocknr == 0) {
+    if (buffer_mapped(bh_result) && bh_result->b_blocknr == 0) {
         /* make sure future calls to the direct io funcs for this offset
         ** in the file fail by unmapping the buffer
         */
@@ -449,11 +474,15 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode,
     /* Possible unpacked tail. Flush the data before pages have
        disappeared */
     if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) {
+        int err;
         lock_kernel();
-        reiserfs_commit_for_inode(inode);
+        err = reiserfs_commit_for_inode(inode);
         REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
         unlock_kernel();
+        if (err < 0)
+            ret = err;
     }
+out:
     return ret ;
 }
 
@@ -533,6 +562,7 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th,
                           b_blocknr_t *allocated_block_nr, 
                           struct path * path,
                           int flags) {
+    BUG_ON (!th->t_trans_id);
   
 #ifdef REISERFS_PREALLOCATE
     if (!(flags & GET_BLOCK_NO_ISEM)) {
@@ -545,12 +575,12 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th,
 int reiserfs_get_block (struct inode * inode, sector_t block,
                        struct buffer_head * bh_result, int create)
 {
-    int repeat, retval;
+    int repeat, retval = 0;
     b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is (unsigned) 32 bit int
     INITIALIZE_PATH(path);
     int pos_in_item;
     struct cpu_key key;
-    struct buffer_head * bh, * unbh = 0;
+    struct buffer_head * bh, * unbh = NULL;
     struct item_head * ih, tmp_ih;
     __u32 * item;
     int done;
@@ -560,8 +590,9 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
         . 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;
+       can incur (much) more than 3 balancings.
+       quota update for user, group */
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS;
     int version;
     int dangle = 1;
     loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;
@@ -643,19 +674,24 @@ start_trans:
 
        repeat = _allocate_block(th, block, inode, &allocated_block_nr, &path, create);
 
-       if (repeat == NO_DISK_SPACE) {
+       if (repeat == NO_DISK_SPACE || repeat == QUOTA_EXCEEDED) {
            /* restart the transaction to give the journal a chance to free
            ** some blocks.  releases the path, so we have to go back to
            ** research if we succeed on the second try
            */
            SB_JOURNAL(inode->i_sb)->j_next_async_flush = 1;
-           restart_transaction(th, inode, &path) ;
+           retval = restart_transaction(th, inode, &path) ;
+            if (retval)
+                goto failure;
            repeat = _allocate_block(th, block, inode, &allocated_block_nr, NULL, create);
 
-           if (repeat != NO_DISK_SPACE) {
+           if (repeat != NO_DISK_SPACE && repeat != QUOTA_EXCEEDED) {
                goto research ;
            }
-           retval = -ENOSPC;
+           if (repeat == QUOTA_EXCEEDED)
+               retval = -EDQUOT;
+           else
+               retval = -ENOSPC;
            goto failure;
        }
 
@@ -683,13 +719,13 @@ start_trans:
            put_block_num(item, pos_in_item, 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, unfm_ptr, inode);
        pathrelse (&path);
+        retval = 0;
        if (!dangle && th)
-           reiserfs_end_persistent_transaction(th);
+           retval = reiserfs_end_persistent_transaction(th);
 
        reiserfs_write_unlock(inode->i_sb);
         
@@ -697,7 +733,7 @@ start_trans:
        ** there is no need to make sure the inode is updated with this 
        ** transaction
        */
-       return 0;
+       return retval;
     }
 
     if (!th) {
@@ -730,13 +766,11 @@ start_trans:
            set_cpu_key_k_offset (&tmp_key, 1);
            PATH_LAST_POSITION(&path) ++;
 
-           retval = reiserfs_insert_item (th, &path, &tmp_key, &tmp_ih, (char *)&unp);
+           retval = reiserfs_insert_item (th, &path, &tmp_key, &tmp_ih, inode, (char *)&unp);
            if (retval) {
-               reiserfs_free_block (th, allocated_block_nr);
-               goto failure; // retval == -ENOSPC or -EIO or -EEXIST
+               reiserfs_free_block (th, inode, allocated_block_nr, 1);
+               goto failure; // retval == -ENOSPC, -EDQUOT or -EIO or -EEXIST
            }
-           if (unp)
-               inode->i_blocks += inode->i_sb->s_blocksize / 512;
            //mark_tail_converted (inode);
        } else if (is_direct_le_ih (ih)) {
            /* direct item has to be converted */
@@ -760,21 +794,24 @@ start_trans:
                 * ugly, but we can only end the transaction if
                 * we aren't nested
                 */
+               BUG_ON (!th->t_refcount);
                if (th->t_refcount == 1) {
-                   reiserfs_end_persistent_transaction(th);
+                   retval = reiserfs_end_persistent_transaction(th);
                    th = NULL;
+                   if (retval)
+                       goto failure;
                }
 
                retval = convert_tail_for_hole(inode, bh_result, tail_offset) ;
                if (retval) {
                    if ( retval != -ENOSPC )
-                       printk("clm-6004: convert tail failed inode %lu, error %d\n", inode->i_ino, retval) ;
+                       reiserfs_warning (inode->i_sb, "clm-6004: convert tail failed inode %lu, error %d", inode->i_ino, retval) ;
                    if (allocated_block_nr) {
                        /* the bitmap, the super, and the stat data == 3 */
                        if (!th)
                            th = reiserfs_persistent_transaction(inode->i_sb,3);
                        if (th)
-                           reiserfs_free_block (th, allocated_block_nr);
+                           reiserfs_free_block (th,inode,allocated_block_nr,1);
                    }
                    goto failure ;
                }
@@ -783,7 +820,7 @@ start_trans:
            retval = direct2indirect (th, inode, &path, unbh, tail_offset);
            if (retval) {
                reiserfs_unmap_buffer(unbh);
-               reiserfs_free_block (th, allocated_block_nr);
+               reiserfs_free_block (th, inode, allocated_block_nr, 1);
                goto failure;
            }
            /* it is important the set_buffer_uptodate is done after
@@ -816,9 +853,6 @@ start_trans:
                 */
                mark_buffer_dirty(unbh) ;
            }
-
-           //inode->i_blocks += inode->i_sb->s_blocksize / 512;
-           //mark_tail_converted (inode);
        } else {
            /* append indirect item with holes if needed, when appending
               pointer to 'block'-th block use block, which is already
@@ -866,24 +900,21 @@ start_trans:
                   only have space for one block */
                blocks_needed=max_to_insert?max_to_insert:1;
            }
-           retval = reiserfs_paste_into_item (th, &path, &tmp_key, (char *)un, UNFM_P_SIZE * blocks_needed);
+           retval = reiserfs_paste_into_item (th, &path, &tmp_key, inode, (char *)un, UNFM_P_SIZE * blocks_needed);
 
            if (blocks_needed != 1)
                kfree(un);
 
            if (retval) {
-               reiserfs_free_block (th, allocated_block_nr);
+               reiserfs_free_block (th, inode, allocated_block_nr, 1);
                goto failure;
            }
-           if (done) {
-               inode->i_blocks += inode->i_sb->s_blocksize / 512;
-           } else {
+           if (!done) {
                /* We need to mark new file size in case this function will be
                   interrupted/aborted later on. And we may do this only for
                   holes. */
                inode->i_size += inode->i_sb->s_blocksize * blocks_needed;
            }
-           //mark_tail_converted (inode);
        }
 
        if (done == 1)
@@ -898,7 +929,9 @@ start_trans:
        ** ending their transaction will be able to continue.
        */
        if (journal_transaction_should_end(th, th->t_blocks_allocated)) {
-         restart_transaction(th, inode, &path) ;
+         retval = restart_transaction(th, inode, &path) ;
+         if (retval)
+           goto failure;
        }
        /* inserting indirect pointers for a hole can take a 
        ** long time.  reschedule if needed
@@ -911,11 +944,11 @@ start_trans:
            goto failure;
        }
        if (retval == POSITION_FOUND) {
-           reiserfs_warning ("vs-825: reiserfs_get_block: "
-                             "%K should not be found\n", &key);
+           reiserfs_warning (inode->i_sb, "vs-825: reiserfs_get_block: "
+                             "%K should not be found", &key);
            retval = -EEXIST;
            if (allocated_block_nr)
-               reiserfs_free_block (th, allocated_block_nr);
+               reiserfs_free_block (th, inode, allocated_block_nr, 1);
            pathrelse(&path) ;
            goto failure;
        }
@@ -929,10 +962,15 @@ start_trans:
     retval = 0;
 
  failure:
-    if (th && !dangle) {
-      reiserfs_update_sd(th, inode) ;
-      reiserfs_end_persistent_transaction(th);
+    if (th && (!dangle || (retval && !th->t_trans_id))) {
+        int err;
+        if (th->t_trans_id)
+            reiserfs_update_sd(th, inode);
+        err = reiserfs_end_persistent_transaction(th);
+        if (err)
+            retval = err;
     }
+
     reiserfs_write_unlock(inode->i_sb);
     reiserfs_check_path(&path) ;
     return retval;
@@ -945,6 +983,58 @@ reiserfs_readpages(struct file *file, struct address_space *mapping,
     return mpage_readpages(mapping, pages, nr_pages, reiserfs_get_block);
 }
 
+/* Compute real number of used bytes by file
+ * Following three functions can go away when we'll have enough space in stat item
+ */
+static int real_space_diff(struct inode *inode, int sd_size)
+{
+    int bytes;
+    loff_t blocksize = inode->i_sb->s_blocksize ;
+
+    if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode))
+        return sd_size ;
+
+    /* End of file is also in full block with indirect reference, so round
+    ** up to the next block.
+    **
+    ** there is just no way to know if the tail is actually packed
+    ** on the file, so we have to assume it isn't.  When we pack the
+    ** tail, we add 4 bytes to pretend there really is an unformatted
+    ** node pointer
+    */
+    bytes = ((inode->i_size + (blocksize-1)) >> inode->i_sb->s_blocksize_bits) * UNFM_P_SIZE + sd_size;
+    return bytes ;
+}
+
+static inline loff_t to_real_used_space(struct inode *inode, ulong blocks,
+                                        int sd_size)
+{
+    if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) {
+        return inode->i_size + (loff_t)(real_space_diff(inode, sd_size)) ;
+    }
+    return ((loff_t)real_space_diff(inode, sd_size)) + (((loff_t)blocks) << 9);
+}
+
+/* Compute number of blocks used by file in ReiserFS counting */
+static inline ulong to_fake_used_blocks(struct inode *inode, int sd_size)
+{
+    loff_t bytes = inode_get_bytes(inode) ;
+    loff_t real_space = real_space_diff(inode, sd_size) ;
+
+    /* keeps fsck and non-quota versions of reiserfs happy */
+    if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) {
+        bytes += (loff_t)511 ;
+    }
+
+    /* files from before the quota patch might i_blocks such that
+    ** bytes < real_space.  Deal with that here to prevent it from
+    ** going negative.
+    */
+    if (bytes < real_space)
+        return 0 ;
+    return (bytes - real_space) >> 9;
+}
+
 //
 // BAD: new directories have stat data of new type and all other items
 // of old type. Version stored in the inode says about body items, so
@@ -975,6 +1065,9 @@ static void init_inode (struct inode * inode, struct path * path)
     REISERFS_I(inode)->i_prealloc_count = 0;
     REISERFS_I(inode)->i_trans_id = 0;
     REISERFS_I(inode)->i_jl = NULL;
+    REISERFS_I(inode)->i_acl_access = NULL;
+    REISERFS_I(inode)->i_acl_default = NULL;
+    init_rwsem (&REISERFS_I(inode)->xattr_sem);
 
     if (stat_data_v1 (ih)) {
        struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
@@ -1010,6 +1103,14 @@ static void init_inode (struct inode * inode, struct path * path)
 
         rdev = sd_v1_rdev(sd);
        REISERFS_I(inode)->i_first_direct_byte = sd_v1_first_direct_byte(sd);
+       /* an early bug in the quota code can give us an odd number for the
+       ** block count.  This is incorrect, fix it here.
+       */
+       if (inode->i_blocks & 1) {
+           inode->i_blocks++ ;
+       }
+       inode_set_bytes(inode, to_real_used_space(inode, inode->i_blocks,
+                                                 SD_V1_SIZE));
        /* nopack is initially zero for v1 objects. For v2 objects,
           nopack is initialised from sd_attrs */
        REISERFS_I(inode)->i_flags &= ~i_nopack_mask;
@@ -1043,14 +1144,16 @@ static void init_inode (struct inode * inode, struct path * path)
            set_inode_item_key_version (inode, KEY_FORMAT_3_6);
        REISERFS_I(inode)->i_first_direct_byte = 0;
        set_inode_sd_version (inode, STAT_DATA_V2);
+       inode_set_bytes(inode, to_real_used_space(inode, inode->i_blocks,
+                                                 SD_V2_SIZE));
        /* read persistent inode attributes from sd and initalise
           generic inode flags from them */
        REISERFS_I(inode)->i_attrs = sd_v2_attrs( sd );
        sd_attrs_to_i_attrs( sd_v2_attrs( sd ), inode );
     }
-    inode->i_uid = INOXID_UID(uid, gid);
-    inode->i_gid = INOXID_GID(uid, gid);
-    inode->i_xid = INOXID_XID(uid, gid, 0);
+    inode->i_uid = INOXID_UID(XID_TAG(inode), uid, gid);
+    inode->i_gid = INOXID_GID(XID_TAG(inode), uid, gid);
+    inode->i_xid = INOXID_XID(XID_TAG(inode), uid, gid, 0);
 
     pathrelse (path);
     if (S_ISREG (inode->i_mode)) {
@@ -1061,32 +1164,33 @@ static void init_inode (struct inode * inode, struct path * path)
        inode->i_op = &reiserfs_dir_inode_operations;
        inode->i_fop = &reiserfs_dir_operations;
     } else if (S_ISLNK (inode->i_mode)) {
-       inode->i_op = &page_symlink_inode_operations;
+       inode->i_op = &reiserfs_symlink_inode_operations;
        inode->i_mapping->a_ops = &reiserfs_address_space_operations;
     } else {
        inode->i_blocks = 0;
+       inode->i_op = &reiserfs_special_inode_operations;
        init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
     }
 }
 
 
 // update new stat data with inode fields
-static void inode2sd (void * sd, struct inode * inode)
+static void inode2sd (void * sd, struct inode * inode, loff_t size)
 {
     struct stat_data * sd_v2 = (struct stat_data *)sd;
-    uid_t uid = XIDINO_UID(inode->i_uid, inode->i_xid);
-    gid_t gid = XIDINO_GID(inode->i_gid, inode->i_xid);
+    uid_t uid = XIDINO_UID(XID_TAG(inode), inode->i_uid, inode->i_xid);
+    gid_t gid = XIDINO_GID(XID_TAG(inode), inode->i_gid, inode->i_xid);
     __u16 flags;
 
     set_sd_v2_uid(sd_v2, uid );
     set_sd_v2_gid(sd_v2, gid );
     set_sd_v2_mode(sd_v2, inode->i_mode );
     set_sd_v2_nlink(sd_v2, inode->i_nlink );
-    set_sd_v2_size(sd_v2, inode->i_size );
+    set_sd_v2_size(sd_v2, size );
     set_sd_v2_mtime(sd_v2, inode->i_mtime.tv_sec );
     set_sd_v2_atime(sd_v2, inode->i_atime.tv_sec );
     set_sd_v2_ctime(sd_v2, inode->i_ctime.tv_sec );
-    set_sd_v2_blocks(sd_v2, inode->i_blocks );
+    set_sd_v2_blocks(sd_v2, to_fake_used_blocks(inode, SD_V2_SIZE));
     if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
        set_sd_v2_rdev(sd_v2, new_encode_dev(inode->i_rdev));
     else
@@ -1098,7 +1202,7 @@ static void inode2sd (void * sd, struct inode * inode)
 
 
 // used to copy inode's fields to old stat data
-static void inode2sd_v1 (void * sd, struct inode * inode)
+static void inode2sd_v1 (void * sd, struct inode * inode, loff_t size)
 {
     struct stat_data_v1 * sd_v1 = (struct stat_data_v1 *)sd;
 
@@ -1106,7 +1210,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode)
     set_sd_v1_uid(sd_v1, inode->i_uid );
     set_sd_v1_gid(sd_v1, inode->i_gid );
     set_sd_v1_nlink(sd_v1, inode->i_nlink );
-    set_sd_v1_size(sd_v1, inode->i_size );
+    set_sd_v1_size(sd_v1, size );
     set_sd_v1_atime(sd_v1, inode->i_atime.tv_sec );
     set_sd_v1_ctime(sd_v1, inode->i_ctime.tv_sec );
     set_sd_v1_mtime(sd_v1, inode->i_mtime.tv_sec );
@@ -1114,7 +1218,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode)
     if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
         set_sd_v1_rdev(sd_v1, new_encode_dev(inode->i_rdev));
     else
-        set_sd_v1_blocks(sd_v1, inode->i_blocks );
+        set_sd_v1_blocks(sd_v1, to_fake_used_blocks(inode, SD_V1_SIZE));
 
     // Sigh. i_first_direct_byte is back
     set_sd_v1_first_direct_byte(sd_v1, REISERFS_I(inode)->i_first_direct_byte);
@@ -1124,7 +1228,8 @@ static void inode2sd_v1 (void * sd, struct inode * inode)
 /* NOTE, you must prepare the buffer head before sending it here,
 ** and then log it after the call
 */
-static void update_stat_data (struct path * path, struct inode * inode)
+static void update_stat_data (struct path * path, struct inode * inode,
+                              loff_t size)
 {
     struct buffer_head * bh;
     struct item_head * ih;
@@ -1138,17 +1243,17 @@ static void update_stat_data (struct path * path, struct inode * inode)
   
     if (stat_data_v1 (ih)) {
        // path points to old stat data
-       inode2sd_v1 (B_I_PITEM (bh, ih), inode);
+       inode2sd_v1 (B_I_PITEM (bh, ih), inode, size);
     } else {
-       inode2sd (B_I_PITEM (bh, ih), inode);
+       inode2sd (B_I_PITEM (bh, ih), inode, size);
     }
 
     return;
 }
 
 
-void reiserfs_update_sd (struct reiserfs_transaction_handle *th, 
-                        struct inode * inode)
+void reiserfs_update_sd_size (struct reiserfs_transaction_handle *th,
+                             struct inode * inode, loff_t size)
 {
     struct cpu_key key;
     INITIALIZE_PATH(path);
@@ -1157,6 +1262,8 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th,
     struct item_head *ih, tmp_ih ;
     int retval;
 
+    BUG_ON (!th->t_trans_id);
+
     make_cpu_key (&key, inode, SD_OFFSET, TYPE_STAT_DATA, 3);//key type is unimportant
     
     for(;;) {
@@ -1164,7 +1271,7 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th,
        /* look for the object's stat data */
        retval = search_item (inode->i_sb, &key, &path);
        if (retval == IO_ERROR) {
-           reiserfs_warning ("vs-13050: reiserfs_update_sd: "
+           reiserfs_warning (inode->i_sb, "vs-13050: reiserfs_update_sd: "
                              "i/o failure occurred trying to update %K stat data",
                              &key);
            return;
@@ -1173,11 +1280,11 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th,
            pos = PATH_LAST_POSITION (&path);
            pathrelse(&path) ;
            if (inode->i_nlink == 0) {
-               /*printk ("vs-13050: reiserfs_update_sd: i_nlink == 0, stat data not found\n");*/
+               /*reiserfs_warning (inode->i_sb, "vs-13050: reiserfs_update_sd: i_nlink == 0, stat data not found");*/
                return;
            }
-           reiserfs_warning ("vs-13060: reiserfs_update_sd: "
-                             "stat data of object %k (nlink == %d) not found (pos %d)\n", 
+           reiserfs_warning (inode->i_sb, "vs-13060: reiserfs_update_sd: "
+                             "stat data of object %k (nlink == %d) not found (pos %d)",
                              INODE_PKEY (inode), inode->i_nlink, pos);
            reiserfs_check_path(&path) ;
            return;
@@ -1198,7 +1305,7 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th,
        }
        break;
     }
-    update_stat_data (&path, inode);
+    update_stat_data (&path, inode, size);
     journal_mark_dirty(th, th->t_super, bh) ; 
     pathrelse (&path);
     return;
@@ -1250,9 +1357,9 @@ void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args
     /* look for the object's stat data */
     retval = search_item (inode->i_sb, &key, &path_to_sd);
     if (retval == IO_ERROR) {
-       reiserfs_warning ("vs-13070: reiserfs_read_locked_inode: "
-                    "i/o failure occurred trying to find stat data of %K\n",
-                    &key);
+       reiserfs_warning (inode->i_sb, "vs-13070: reiserfs_read_locked_inode: "
+                         "i/o failure occurred trying to find stat data of %K",
+                         &key);
        reiserfs_make_bad_inode(inode) ;
        return;
     }
@@ -1282,9 +1389,10 @@ void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args
        during mount (fs/reiserfs/super.c:finish_unfinished()). */
     if( ( inode -> i_nlink == 0 ) && 
        ! REISERFS_SB(inode -> i_sb) -> s_is_unlinked_ok ) {
-           reiserfs_warning( "vs-13075: reiserfs_read_locked_inode: "
+           reiserfs_warning (inode->i_sb,
+                             "vs-13075: reiserfs_read_locked_inode: "
                              "dead inode read from disk %K. "
-                             "This is likely to be race with knfsd. Ignore\n", 
+                             "This is likely to be race with knfsd. Ignore",
                              &key );
            reiserfs_make_bad_inode( inode );
     }
@@ -1335,7 +1443,7 @@ struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key
     if (comp_short_keys (INODE_PKEY (inode), key) || is_bad_inode (inode)) {
        /* either due to i/o error or a stale NFS handle */
        iput (inode);
-       inode = 0;
+       inode = NULL;
     }
     return inode;
 }
@@ -1349,12 +1457,14 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp)
     
     key.on_disk_key.k_objectid = data[0] ;
     key.on_disk_key.k_dir_id = data[1] ;
+    reiserfs_write_lock(sb);
     inode = reiserfs_iget(sb, &key) ;
     if (inode && !IS_ERR(inode) && data[2] != 0 &&
        data[2] != inode->i_generation) {
            iput(inode) ;
            inode = NULL ;
     }
+    reiserfs_write_unlock(sb);
     if (!inode)
            inode = ERR_PTR(-ESTALE);
     if (IS_ERR(inode))
@@ -1387,7 +1497,7 @@ struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 *data,
      */
     if (fhtype > len) {
            if (fhtype != 6 || len != 5)
-                   printk(KERN_WARNING "nfsd/reiserfs, fhtype=%d, len=%d - odd\n",
+                   reiserfs_warning (sb, "nfsd/reiserfs, fhtype=%d, len=%d - odd",
                           fhtype, len);
            fhtype = 5;
     }
@@ -1445,15 +1555,12 @@ int reiserfs_encode_fh(struct dentry *dentry, __u32 *data, int *lenp, int need_p
 ** to properly mark inodes for datasync and such, but only actually
 ** does something when called for a synchronous update.
 */
-void reiserfs_write_inode (struct inode * inode, int do_sync) {
+int reiserfs_write_inode (struct inode * inode, int do_sync) {
     struct reiserfs_transaction_handle th ;
     int jbegin_count = 1 ;
 
-    if (inode->i_sb->s_flags & MS_RDONLY) {
-        reiserfs_warning("clm-6005: writing inode %lu on readonly FS\n", 
-                         inode->i_ino) ;
-        return ;
-    }
+    if (inode->i_sb->s_flags & MS_RDONLY)
+        return -EROFS;
     /* memory pressure can sometimes initiate write_inode calls with sync == 1,
     ** these cases are just when the system needs ram, not when the 
     ** inode needs to reach disk for safety, and they can safely be
@@ -1461,26 +1568,19 @@ void reiserfs_write_inode (struct inode * inode, int do_sync) {
     */
     if (do_sync && !(current->flags & PF_MEMALLOC)) {
        reiserfs_write_lock(inode->i_sb);
-       journal_begin(&th, inode->i_sb, jbegin_count) ;
-       reiserfs_update_sd (&th, inode);
-       journal_end_sync(&th, inode->i_sb, jbegin_count) ;
+       if (!journal_begin(&th, inode->i_sb, jbegin_count)) {
+            reiserfs_update_sd (&th, inode);
+            journal_end_sync(&th, inode->i_sb, jbegin_count) ;
+        }
        reiserfs_write_unlock(inode->i_sb);
     }
+    return 0;
 }
 
-/* FIXME: no need any more. right? */
-int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode * inode)
-{
-  int err = 0;
-
-  reiserfs_update_sd (th, inode);
-  return err;
-}
-
-
 /* stat data of new object is inserted already, this inserts the item
    containing "." and ".." entries */
 static int reiserfs_new_directory (struct reiserfs_transaction_handle *th, 
+                                  struct inode *inode,
                                   struct item_head * ih, struct path * path,
                                   struct inode * dir)
 {
@@ -1489,6 +1589,8 @@ static int reiserfs_new_directory (struct reiserfs_transaction_handle *th,
     char * body = empty_dir;
     struct cpu_key key;
     int retval;
+
+    BUG_ON (!th->t_trans_id);
     
     _make_cpu_key (&key, KEY_FORMAT_3_5, le32_to_cpu (ih->ih_key.k_dir_id),
                   le32_to_cpu (ih->ih_key.k_objectid), DOT_OFFSET, TYPE_DIRENTRY, 3/*key length*/);
@@ -1497,13 +1599,13 @@ static int reiserfs_new_directory (struct reiserfs_transaction_handle *th,
        old type (ITEM_VERSION_1). Do not set key (second arg is 0), it
        is done by reiserfs_new_inode */
     if (old_format_only (sb)) {
-       make_le_item_head (ih, 0, KEY_FORMAT_3_5, DOT_OFFSET, TYPE_DIRENTRY, EMPTY_DIR_SIZE_V1, 2);
+       make_le_item_head (ih, NULL, KEY_FORMAT_3_5, DOT_OFFSET, TYPE_DIRENTRY, EMPTY_DIR_SIZE_V1, 2);
        
        make_empty_dir_item_v1 (body, ih->ih_key.k_dir_id, ih->ih_key.k_objectid,
                                INODE_PKEY (dir)->k_dir_id, 
                                INODE_PKEY (dir)->k_objectid );
     } else {
-       make_le_item_head (ih, 0, KEY_FORMAT_3_5, DOT_OFFSET, TYPE_DIRENTRY, EMPTY_DIR_SIZE, 2);
+       make_le_item_head (ih, NULL, KEY_FORMAT_3_5, DOT_OFFSET, TYPE_DIRENTRY, EMPTY_DIR_SIZE, 2);
        
        make_empty_dir_item (body, ih->ih_key.k_dir_id, ih->ih_key.k_objectid,
                                INODE_PKEY (dir)->k_dir_id, 
@@ -1513,25 +1615,26 @@ static int reiserfs_new_directory (struct reiserfs_transaction_handle *th,
     /* look for place in the tree for new item */
     retval = search_item (sb, &key, path);
     if (retval == IO_ERROR) {
-       reiserfs_warning ("vs-13080: reiserfs_new_directory: "
-                         "i/o failure occurred creating new directory\n");
+       reiserfs_warning (sb, "vs-13080: reiserfs_new_directory: "
+                         "i/o failure occurred creating new directory");
        return -EIO;
     }
     if (retval == ITEM_FOUND) {
        pathrelse (path);
-       reiserfs_warning ("vs-13070: reiserfs_new_directory: "
+       reiserfs_warning (sb, "vs-13070: reiserfs_new_directory: "
                          "object with this key exists (%k)", &(ih->ih_key));
        return -EEXIST;
     }
 
     /* insert item, that is empty directory item */
-    return reiserfs_insert_item (th, path, &key, ih, body);
+    return reiserfs_insert_item (th, path, &key, ih, inode, body);
 }
 
 
 /* stat data of object has been inserted, this inserts the item
    containing the body of symlink */
 static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th, 
+                                struct inode *inode,   /* Inode of symlink */
                                 struct item_head * ih,
                                 struct path * path, const char * symname, int item_len)
 {
@@ -1539,29 +1642,31 @@ static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th,
     struct cpu_key key;
     int retval;
 
+    BUG_ON (!th->t_trans_id);
+
     _make_cpu_key (&key, KEY_FORMAT_3_5, 
                   le32_to_cpu (ih->ih_key.k_dir_id), 
                   le32_to_cpu (ih->ih_key.k_objectid),
                   1, TYPE_DIRECT, 3/*key length*/);
 
-    make_le_item_head (ih, 0, KEY_FORMAT_3_5, 1, TYPE_DIRECT, item_len, 0/*free_space*/);
+    make_le_item_head (ih, NULL, KEY_FORMAT_3_5, 1, TYPE_DIRECT, item_len, 0/*free_space*/);
 
     /* look for place in the tree for new item */
     retval = search_item (sb, &key, path);
     if (retval == IO_ERROR) {
-       reiserfs_warning ("vs-13080: reiserfs_new_symlinik: "
-                         "i/o failure occurred creating new symlink\n");
+       reiserfs_warning (sb, "vs-13080: reiserfs_new_symlinik: "
+                         "i/o failure occurred creating new symlink");
        return -EIO;
     }
     if (retval == ITEM_FOUND) {
        pathrelse (path);
-       reiserfs_warning ("vs-13080: reiserfs_new_symlink: "
+       reiserfs_warning (sb, "vs-13080: reiserfs_new_symlink: "
                          "object with this key exists (%k)", &(ih->ih_key));
        return -EEXIST;
     }
 
     /* insert item, that is body of symlink */
-    return reiserfs_insert_item (th, path, &key, ih, symname);
+    return reiserfs_insert_item (th, path, &key, ih, inode, symname);
 }
 
 
@@ -1589,7 +1694,13 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
     struct stat_data sd;
     int retval;
     int err;
+
+    BUG_ON (!th->t_trans_id);
   
+    if (DQUOT_ALLOC_INODE(inode)) {
+       err = -EDQUOT;
+       goto out_end_trans;
+    }
     if (!dir || !dir->i_nlink) {
        err = -EPERM;
        goto out_bad_inode;
@@ -1598,7 +1709,7 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
     sb = dir->i_sb;
 
     /* item head of new item */
-    ih.ih_key.k_dir_id = INODE_PKEY (dir)->k_objectid;
+    ih.ih_key.k_dir_id = reiserfs_choose_packing(dir);
     ih.ih_key.k_objectid = cpu_to_le32 (reiserfs_get_unused_objectid (th));
     if (!ih.ih_key.k_objectid) {
        err = -ENOMEM;
@@ -1627,9 +1738,11 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
     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_mtime = inode->i_atime = inode->i_ctime =
+           CURRENT_TIME_SEC;
     inode->i_size = i_size;
-    inode->i_blocks = (inode->i_size + 511) >> 9;
+    inode->i_blocks = 0;
+    inode->i_bytes = 0;
     REISERFS_I(inode)->i_first_direct_byte = S_ISLNK(mode) ? 1 : 
       U32_MAX/*NO_BYTES_IN_DIRECT_ITEM*/;
 
@@ -1638,15 +1751,18 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
     REISERFS_I(inode)->i_prealloc_block = 0;
     REISERFS_I(inode)->i_prealloc_count = 0;
     REISERFS_I(inode)->i_trans_id = 0;
-    REISERFS_I(inode)->i_jl = 0;
+    REISERFS_I(inode)->i_jl = NULL;
     REISERFS_I(inode)->i_attrs =
        REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
     sd_attrs_to_i_attrs( REISERFS_I(inode) -> i_attrs, inode );
+    REISERFS_I(inode)->i_acl_access = NULL;
+    REISERFS_I(inode)->i_acl_default = NULL;
+    init_rwsem (&REISERFS_I(inode)->xattr_sem);
 
     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);
+       make_le_item_head (&ih, NULL, 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);
+       make_le_item_head (&ih, NULL, 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),
@@ -1663,7 +1779,6 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
        err = -EEXIST;
        goto out_bad_inode;
     }
-
     if (old_format_only (sb)) {
        if (inode->i_uid & ~0xffff || inode->i_gid & ~0xffff) {
            pathrelse (&path_to_key);
@@ -1671,9 +1786,9 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
            err = -EINVAL;
            goto out_bad_inode;
        }
-       inode2sd_v1 (&sd, inode);
+       inode2sd_v1 (&sd, inode, inode->i_size);
     } else {
-       inode2sd (&sd, inode);
+       inode2sd (&sd, inode, inode->i_size);
     }
     // these do not go to on-disk stat data
     inode->i_ino = le32_to_cpu (ih.ih_key.k_objectid);
@@ -1697,7 +1812,7 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
     if (REISERFS_I(dir)->new_packing_locality)
        th->displace_new_blocks = 1;
 #endif
-    retval = reiserfs_insert_item (th, &path_to_key, &key, &ih, (char *)(&sd));
+    retval = reiserfs_insert_item (th, &path_to_key, &key, &ih, inode, (char *)(&sd));
     if (retval) {
        err = retval;
        reiserfs_check_path(&path_to_key) ;
@@ -1710,14 +1825,14 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
 #endif
     if (S_ISDIR(mode)) {
        /* insert item with "." and ".." */
-       retval = reiserfs_new_directory (th, &ih, &path_to_key, dir);
+       retval = reiserfs_new_directory (th, inode, &ih, &path_to_key, dir);
     }
 
     if (S_ISLNK(mode)) {
        /* insert body of symlink */
        if (!old_format_only (sb))
            i_size = ROUND_UP(i_size);
-       retval = reiserfs_new_symlink (th, &ih, &path_to_key, symname, i_size);
+       retval = reiserfs_new_symlink (th, inode, &ih, &path_to_key, symname, i_size);
     }
     if (retval) {
        err = retval;
@@ -1726,6 +1841,20 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
        goto out_inserted_sd;
     }
 
+    /* XXX CHECK THIS */
+    if (reiserfs_posixacl (inode->i_sb)) {
+        retval = reiserfs_inherit_default_acl (dir, dentry, inode);
+        if (retval) {
+            err = retval;
+            reiserfs_check_path(&path_to_key) ;
+            journal_end(th, th->t_super, th->t_blocks_allocated);
+            goto out_inserted_sd;
+        }
+    } else if (inode->i_sb->s_flags & MS_POSIXACL) {
+       reiserfs_warning (inode->i_sb, "ACLs aren't enabled in the fs, "
+                         "but vfs thinks they are!");
+    }
+
     insert_inode_hash (inode);
     reiserfs_update_sd(th, inode);
     reiserfs_check_path(&path_to_key) ;
@@ -1740,8 +1869,14 @@ out_bad_inode:
     /* Invalidate the object, nothing was inserted yet */
     INODE_PKEY(inode)->k_objectid = 0;
 
-    /* dquot_drop must be done outside a transaction */
+    /* Quota change must be inside a transaction for journaling */
+    DQUOT_FREE_INODE(inode);
+
+out_end_trans:
     journal_end(th, th->t_super, th->t_blocks_allocated) ;
+    /* Drop can be outside and it needs more credits so it's better to have it outside */
+    DQUOT_DROP(inode);
+    inode->i_flags |= S_NOQUOTA;
     make_bad_inode(inode);
 
 out_inserted_sd:
@@ -1818,9 +1953,10 @@ static int grab_tail_page(struct inode *p_s_inode,
        ** I've screwed up the code to find the buffer, or the code to
        ** call prepare_write
        */
-       reiserfs_warning("clm-6000: error reading block %lu on dev %s\n",
-                        bh->b_blocknr,
-                        reiserfs_bdevname (p_s_inode->i_sb)) ;
+       reiserfs_warning (p_s_inode->i_sb,
+                         "clm-6000: error reading block %lu on dev %s",
+                         bh->b_blocknr,
+                         reiserfs_bdevname (p_s_inode->i_sb)) ;
        error = -EIO ;
        goto unlock ;
     }
@@ -1842,7 +1978,7 @@ unlock:
 **
 ** some code taken from block_truncate_page
 */
-void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
+int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
     struct reiserfs_transaction_handle th ;
     /* we want the offset for the first byte after the end of the file */
     unsigned long offset = p_s_inode->i_size & (PAGE_CACHE_SIZE - 1) ;
@@ -1860,7 +1996,9 @@ void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
            // and get_block_create_0 could not find a block to read in,
            // which is ok.
            if (error != -ENOENT)
-               reiserfs_warning("clm-6001: grab_tail_page failed %d\n", error);
+               reiserfs_warning (p_s_inode->i_sb,
+                                 "clm-6001: grab_tail_page failed %d",
+                                 error);
            page = NULL ;
            bh = NULL ;
        }
@@ -1876,18 +2014,28 @@ void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
     /* it is enough to reserve space in transaction for 2 balancings:
        one for "save" link adding and another for the first
        cut_from_item. 1 is for update_sd */
-    journal_begin(&th, p_s_inode->i_sb,  JOURNAL_PER_BALANCE_CNT * 2 + 1 ) ;
+    error = journal_begin (&th, p_s_inode->i_sb,
+                           JOURNAL_PER_BALANCE_CNT * 2 + 1);
+    if (error)
+        goto out;
     reiserfs_update_inode_transaction(p_s_inode) ;
     if (update_timestamps)
            /* we are doing real truncate: if the system crashes before the last
               transaction of truncating gets committed - on reboot the file
               either appears truncated properly or not truncated at all */
        add_save_link (&th, p_s_inode, 1);
-    reiserfs_do_truncate (&th, p_s_inode, page, update_timestamps) ;
-    journal_end(&th, p_s_inode->i_sb,  JOURNAL_PER_BALANCE_CNT * 2 + 1 ) ;
+    error = reiserfs_do_truncate (&th, p_s_inode, page, update_timestamps) ;
+    if (error)
+        goto out;
+    error = journal_end (&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
+    if (error)
+        goto out;
 
-    if (update_timestamps)
-       remove_save_link (p_s_inode, 1/* truncate */);
+    if (update_timestamps) {
+       error = remove_save_link (p_s_inode, 1/* truncate */);
+        if (error)
+            goto out;
+    }
 
     if (page) {
         length = offset & (blocksize - 1) ;
@@ -1909,6 +2057,14 @@ void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
     }
 
     reiserfs_write_unlock(p_s_inode->i_sb);
+    return 0;
+out:
+    if (page) {
+        unlock_page (page);
+        page_cache_release (page);
+    }
+    reiserfs_write_unlock(p_s_inode->i_sb);
+    return error;
 }
 
 static int map_block_for_writepage(struct inode *inode, 
@@ -1958,7 +2114,8 @@ research:
     /* we've found an unformatted node */
     if (indirect_item_found(retval, ih)) {
        if (bytes_copied > 0) {
-           reiserfs_warning("clm-6002: bytes_copied %d\n", bytes_copied) ;
+           reiserfs_warning (inode->i_sb, "clm-6002: bytes_copied %d",
+                             bytes_copied) ;
        }
         if (!get_block_num(item, pos_in_item)) {
            /* crap, we are writing to a hole */
@@ -1977,7 +2134,9 @@ research:
 
        if (!trans_running) {
            /* vs-3050 is gone, no need to drop the path */
-           journal_begin(&th, inode->i_sb, jbegin_count) ;
+           retval = journal_begin(&th, inode->i_sb, jbegin_count) ;
+            if (retval)
+                goto out;
            reiserfs_update_inode_transaction(inode) ;
            trans_running = 1;
            if (fs_changed(fs_gen, inode->i_sb) && item_moved(&tmp_ih, &path)) {
@@ -2006,7 +2165,9 @@ research:
            goto research ;
        }
     } else {
-        reiserfs_warning("clm-6003: bad item inode %lu, device %s\n", inode->i_ino, reiserfs_bdevname (inode->i_sb)) ;
+        reiserfs_warning (inode->i_sb,
+                         "clm-6003: bad item inode %lu, device %s",
+                         inode->i_ino, reiserfs_bdevname (inode->i_sb)) ;
         retval = -EIO ;
        goto out ;
     }
@@ -2015,7 +2176,9 @@ research:
 out:
     pathrelse(&path) ;
     if (trans_running) {
-       journal_end(&th, inode->i_sb, jbegin_count) ;
+        int err = journal_end(&th, inode->i_sb, jbegin_count) ;
+        if (err)
+            retval = err;
        trans_running = 0;
     }
     reiserfs_write_unlock(inode->i_sb);
@@ -2059,6 +2222,11 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control
     struct buffer_head *head, *bh;
     int partial = 0 ;
     int nr = 0;
+    int checked = PageChecked(page);
+    struct reiserfs_transaction_handle th;
+    struct super_block *s = inode->i_sb;
+    int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize;
+    th.t_trans_id = 0;
 
     /* The page dirty bit is cleared before writepage is called, which
      * means we have to tell create_empty_buffers to make dirty buffers
@@ -2066,7 +2234,7 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control
      * in the BH_Uptodate is just a sanity check.
      */
     if (!page_has_buffers(page)) {
-       create_empty_buffers(page, inode->i_sb->s_blocksize, 
+       create_empty_buffers(page, s->s_blocksize,
                            (1 << BH_Dirty) | (1 << BH_Uptodate));
     }
     head = page_buffers(page) ;
@@ -2090,10 +2258,10 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control
        kunmap_atomic(kaddr, KM_USER0) ;
     }
     bh = head ;
-    block = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits) ;
+    block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits) ;
     /* first map all the buffers, logging any direct items we find */
     do {
-       if (buffer_dirty(bh) && (!buffer_mapped(bh) ||
+       if ((checked || buffer_dirty(bh)) && (!buffer_mapped(bh) ||
           (buffer_mapped(bh) && bh->b_blocknr == 0))) {
            /* not mapped yet, or it points to a direct item, search
             * the btree for the mapping info, and log any direct
@@ -2107,6 +2275,22 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control
        block++;
     } while(bh != head) ;
 
+    /*
+     * we start the transaction after map_block_for_writepage,
+     * because it can create holes in the file (an unbounded operation).
+     * starting it here, we can make a reliable estimate for how many
+     * blocks we're going to log
+     */
+    if (checked) {
+       ClearPageChecked(page);
+       reiserfs_write_lock(s);
+       error = journal_begin(&th, s, bh_per_page + 1);
+       if (error) {
+           reiserfs_write_unlock(s);
+           goto fail;
+       }
+       reiserfs_update_inode_transaction(inode);
+    }
     /* now go through and lock any dirty buffers on the page */
     do {
        get_bh(bh);
@@ -2115,6 +2299,11 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control
        if (buffer_mapped(bh) && bh->b_blocknr == 0)
            continue;
 
+       if (checked) {
+           reiserfs_prepare_for_journal(s, bh, 1);
+           journal_mark_dirty(&th, s, bh);
+           continue;
+       }
        /* from this point on, we know the buffer is mapped to a
         * real block and not a direct item
         */
@@ -2133,6 +2322,12 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control
        }
     } while((bh = bh->b_this_page) != head);
 
+    if (checked) {
+       error = journal_end(&th, s, bh_per_page + 1);
+       reiserfs_write_unlock(s);
+       if (error)
+           goto fail;
+    }
     BUG_ON(PageWriteback(page));
     set_page_writeback(page);
     unlock_page(page);
@@ -2227,7 +2422,7 @@ static int reiserfs_writepage (struct page * page, struct writeback_control *wbc
     return reiserfs_write_full_page(page, wbc) ;
 }
 
-int reiserfs_prepare_write(struct file *f, struct page *page, 
+static int reiserfs_prepare_write(struct file *f, struct page *page,
                           unsigned from, unsigned to) {
     struct inode *inode = page->mapping->host ;
     int ret;
@@ -2237,7 +2432,9 @@ int reiserfs_prepare_write(struct file *f, struct page *page,
     fix_tail_page_for_writing(page) ;
     if (reiserfs_transaction_running(inode->i_sb)) {
        struct reiserfs_transaction_handle *th;
-        th = (struct reiserfs_transaction_handle *)current->journal_info;
+       th = (struct reiserfs_transaction_handle *)current->journal_info;
+        BUG_ON (!th->t_refcount);
+        BUG_ON (!th->t_trans_id);
        old_ref = th->t_refcount;
        th->t_refcount++;
     }
@@ -2259,9 +2456,12 @@ int reiserfs_prepare_write(struct file *f, struct page *page,
            if (old_ref)
                th->t_refcount--;
            else {
+                int err;
                reiserfs_write_lock(inode->i_sb);
-               reiserfs_end_persistent_transaction(th);
+               err = reiserfs_end_persistent_transaction(th);
                reiserfs_write_unlock(inode->i_sb);
+                if (err)
+                    ret = err;
            }
        }
     }
@@ -2279,6 +2479,7 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
     struct inode *inode = page->mapping->host ;
     loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
     int ret = 0;
+    int update_sd = 0;
     struct reiserfs_transaction_handle *th = NULL;
     
     reiserfs_wait_on_write_block(inode->i_sb) ;
@@ -2301,17 +2502,28 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
             (have_small_tails (inode->i_sb) && inode->i_size > i_block_size(inode)) )
            REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask ;
 
-       journal_begin(&myth, inode->i_sb, 1) ;
+       ret = journal_begin(&myth, inode->i_sb, 1) ;
+       if (ret) {
+           reiserfs_write_unlock(inode->i_sb);
+           goto journal_error;
+       }
        reiserfs_update_inode_transaction(inode) ;
        inode->i_size = pos ;
        reiserfs_update_sd(&myth, inode) ;
-       journal_end(&myth, inode->i_sb, 1) ;
+       update_sd = 1;
+       ret = journal_end(&myth, inode->i_sb, 1) ;
        reiserfs_write_unlock(inode->i_sb);
+       if (ret)
+           goto journal_error;
     }
     if (th) {
        reiserfs_write_lock(inode->i_sb);
-        reiserfs_end_persistent_transaction(th);
+       if (!update_sd)
+           reiserfs_update_sd(th, inode) ;
+       ret = reiserfs_end_persistent_transaction(th);
        reiserfs_write_unlock(inode->i_sb);
+       if (ret)
+           goto out;
     }
  
     /* we test for O_SYNC here so we can commit the transaction
@@ -2319,10 +2531,22 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
     */
     if (f && (f->f_flags & O_SYNC)) {
        reiserfs_write_lock(inode->i_sb);
-       reiserfs_commit_for_inode(inode) ;
+       ret = reiserfs_commit_for_inode(inode) ;
        reiserfs_write_unlock(inode->i_sb);
     }
+out:
     return ret ;
+
+journal_error:
+    if (th) {
+       reiserfs_write_lock(inode->i_sb);
+       if (!update_sd)
+           reiserfs_update_sd(th, inode) ;
+        ret = reiserfs_end_persistent_transaction(th);
+       reiserfs_write_unlock(inode->i_sb);
+    }
+
+    return ret;
 }
 
 void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode )
@@ -2404,17 +2628,15 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh)
     /* the page is locked, and the only places that log a data buffer
      * also lock the page.
      */
-#if 0
     if (reiserfs_file_data_log(inode)) {
-       /* very conservative, leave the buffer pinned if anyone might need it.
-       ** this should be changed to drop the buffer if it is only in the
-       ** current transaction
-       */
+       /*
+        * very conservative, leave the buffer pinned if
+        * anyone might need it.
+        */
         if (buffer_journaled(bh) || buffer_journal_dirty(bh)) {
            ret = 0 ;
        }
     } else
-#endif
     if (buffer_dirty(bh) || buffer_locked(bh)) {
        struct reiserfs_journal_list *jl;
        struct reiserfs_jh *jh = bh->b_private;
@@ -2452,6 +2674,10 @@ static int reiserfs_invalidatepage(struct page *page, unsigned long offset)
     int ret = 1;
 
     BUG_ON(!PageLocked(page));
+
+    if (offset == 0)
+       ClearPageChecked(page);
+
     if (!page_has_buffers(page))
        goto out;
 
@@ -2485,6 +2711,15 @@ out:
     return ret;
 }
 
+static int reiserfs_set_page_dirty(struct page *page) {
+    struct inode *inode = page->mapping->host;
+    if (reiserfs_file_data_log(inode)) {
+       SetPageChecked(page);
+       return __set_page_dirty_nobuffers(page);
+    }
+    return __set_page_dirty_buffers(page);
+}
+
 /*
  * Returns 1 if the page's buffers were dropped.  The page is locked.
  *
@@ -2502,6 +2737,7 @@ static int reiserfs_releasepage(struct page *page, int unused_gfp_flags)
     struct buffer_head *bh ;
     int ret = 1 ;
 
+    WARN_ON(PageChecked(page));
     spin_lock(&j->j_dirty_buffers_lock) ;
     head = page_buffers(page) ;
     bh = head ;
@@ -2534,6 +2770,115 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb,
                        offset, nr_segs, reiserfs_get_blocks_direct_io, NULL);
 }
 
+int reiserfs_setattr_flags(struct inode *inode, unsigned int flags)
+{
+       unsigned int oldflags, newflags;
+
+       oldflags = REISERFS_I(inode)->i_flags;
+       newflags = oldflags & ~(REISERFS_IMMUTABLE_FL |
+               REISERFS_IUNLINK_FL | REISERFS_BARRIER_FL);
+       if (flags & ATTR_FLAG_IMMUTABLE)
+               newflags |= REISERFS_IMMUTABLE_FL;
+       if (flags & ATTR_FLAG_IUNLINK)
+               newflags |= REISERFS_IUNLINK_FL;
+       if (flags & ATTR_FLAG_BARRIER)
+               newflags |= REISERFS_BARRIER_FL;
+
+       if (oldflags ^ newflags) {
+               REISERFS_I(inode)->i_flags = newflags;
+               inode->i_ctime = CURRENT_TIME;
+       }
+       return 0;
+}
+
+int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
+    struct inode *inode = dentry->d_inode ;
+    int error ;
+    unsigned int ia_valid = attr->ia_valid;
+    reiserfs_write_lock(inode->i_sb);
+    if (attr->ia_valid & ATTR_SIZE) {
+       /* version 2 items will be caught by the s_maxbytes check
+       ** done for us in vmtruncate
+       */
+       if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
+           attr->ia_size > MAX_NON_LFS) {
+           error = -EFBIG ;
+           goto out;
+       }
+       /* fill in hole pointers in the expanding truncate case. */
+        if (attr->ia_size > inode->i_size) {
+           error = generic_cont_expand(inode, attr->ia_size) ;
+           if (REISERFS_I(inode)->i_prealloc_count > 0) {
+               int err;
+               struct reiserfs_transaction_handle th ;
+               /* we're changing at most 2 bitmaps, inode + super */
+               err = journal_begin(&th, inode->i_sb, 4) ;
+               if (!err) {
+                   reiserfs_discard_prealloc (&th, inode);
+                   err = journal_end(&th, inode->i_sb, 4) ;
+               }
+               if (err)
+                   error = err;
+           }
+           if (error)
+               goto out;
+       }
+    }
+
+    if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) ||
+        ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) &&
+       (get_inode_sd_version (inode) == STAT_DATA_V1)) {
+               /* stat data of format v3.5 has 16 bit uid and gid */
+           error = -EINVAL;
+           goto out;
+       }
+
+    error = inode_change_ok(inode, attr) ;
+
+    if (!error && attr->ia_valid & ATTR_ATTR_FLAG)
+       reiserfs_setattr_flags(inode, attr->ia_attr_flags);
+
+    if (!error) {
+       if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
+           (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+                error = reiserfs_chown_xattrs (inode, attr);
+
+                if (!error) {
+                   struct reiserfs_transaction_handle th;
+
+                   /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
+                   journal_begin(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+                    error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
+                   if (error) {
+                       journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+                       goto out;
+                   }
+                   /* Update corresponding info in inode so that everything is in
+                    * one transaction */
+                   if (attr->ia_valid & ATTR_UID)
+                       inode->i_uid = attr->ia_uid;
+                   if (attr->ia_valid & ATTR_GID)
+                       inode->i_gid = attr->ia_gid;
+                   mark_inode_dirty(inode);
+                   journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+               }
+        }
+        if (!error)
+            error = inode_setattr(inode, attr) ;
+    }
+
+
+    if (!error && reiserfs_posixacl (inode->i_sb)) {
+        if (attr->ia_valid & ATTR_MODE)
+            error = reiserfs_acl_chmod (inode);
+    }
+
+out:
+    reiserfs_write_unlock(inode->i_sb);
+    return error ;
+}
+
+
 
 struct address_space_operations reiserfs_address_space_operations = {
     .writepage = reiserfs_writepage,
@@ -2545,5 +2890,6 @@ struct address_space_operations reiserfs_address_space_operations = {
     .prepare_write = reiserfs_prepare_write,
     .commit_write = reiserfs_commit_write,
     .bmap = reiserfs_aop_bmap,
-    .direct_IO = reiserfs_direct_IO
+    .direct_IO = reiserfs_direct_IO,
+    .set_page_dirty = reiserfs_set_page_dirty,
 } ;