switch reiserfs to inode->i_acl
[safe/jmp/linux-2.6] / fs / reiserfs / inode.c
index 5f82352..a14d6cd 100644 (file)
@@ -2,12 +2,12 @@
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  */
 
-#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/exportfs.h>
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
 #include <linux/mpage.h>
 #include <linux/writeback.h>
 #include <linux/quotaops.h>
+#include <linux/swap.h>
 
-extern int reiserfs_default_io_size;   /* default io size devuned in super.c */
-
-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);
+int reiserfs_commit_write(struct file *f, struct page *page,
+                         unsigned from, unsigned to);
+int reiserfs_prepare_write(struct file *f, struct page *page,
+                          unsigned from, unsigned to);
 
 void reiserfs_delete_inode(struct inode *inode)
 {
@@ -32,6 +31,7 @@ void reiserfs_delete_inode(struct inode *inode)
            JOURNAL_PER_BALANCE_CNT * 2 +
            2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
        struct reiserfs_transaction_handle th;
+       int err;
 
        truncate_inode_pages(&inode->i_data, 0);
 
@@ -39,32 +39,30 @@ void reiserfs_delete_inode(struct inode *inode)
 
        /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
        if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) {  /* also handles bad_inode case */
-               down(&inode->i_sem);
-
                reiserfs_delete_xattrs(inode);
 
-               if (journal_begin(&th, inode->i_sb, jbegin_count)) {
-                       up(&inode->i_sem);
+               if (journal_begin(&th, inode->i_sb, jbegin_count))
                        goto out;
-               }
                reiserfs_update_inode_transaction(inode);
 
-               if (reiserfs_delete_object(&th, inode)) {
-                       up(&inode->i_sem);
-                       goto out;
-               }
+               reiserfs_discard_prealloc(&th, inode);
+
+               err = reiserfs_delete_object(&th, inode);
 
                /* 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 (!err) 
+                       vfs_dq_free_inode(inode);
 
-               if (journal_end(&th, inode->i_sb, jbegin_count)) {
-                       up(&inode->i_sem);
+               if (journal_end(&th, inode->i_sb, jbegin_count))
                        goto out;
-               }
 
-               up(&inode->i_sem);
+               /* check return value from reiserfs_delete_object after
+                * ending the transaction
+                */
+               if (err)
+                   goto out;
 
                /* all items of file are deleted, so we can remove "save" link */
                remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything
@@ -203,7 +201,7 @@ static inline void set_block_dev_mapped(struct buffer_head *bh,
 // files which were created in the earlier version can not be longer,
 // than 2 gb
 //
-static int file_capable(struct inode *inode, long block)
+static int file_capable(struct inode *inode, sector_t block)
 {
        if (get_inode_item_key_version(inode) != KEY_FORMAT_3_5 ||      // it is new file.
            block < (1 << (31 - inode->i_sb->s_blocksize_bits)))        // old file, but 'block' is inside of 2gb
@@ -212,8 +210,8 @@ static int file_capable(struct inode *inode, long block)
        return 0;
 }
 
-/*static*/ int restart_transaction(struct reiserfs_transaction_handle *th,
-                                  struct inode *inode, struct path *path)
+static int restart_transaction(struct reiserfs_transaction_handle *th,
+                              struct inode *inode, struct treepath *path)
 {
        struct super_block *s = th->t_super;
        int len = th->t_blocks_allocated;
@@ -222,11 +220,12 @@ static int file_capable(struct inode *inode, long block)
        BUG_ON(!th->t_trans_id);
        BUG_ON(!th->t_refcount);
 
+       pathrelse(path);
+
        /* we cannot restart while nested */
        if (th->t_refcount > 1) {
                return 0;
        }
-       pathrelse(path);
        reiserfs_update_sd(th, inode);
        err = journal_end(th, s, len);
        if (!err) {
@@ -245,7 +244,7 @@ static int file_capable(struct inode *inode, long block)
 // Please improve the english/clarity in the comment above, as it is
 // hard to understand.
 
-static int _get_block_create_0(struct inode *inode, long block,
+static int _get_block_create_0(struct inode *inode, sector_t block,
                               struct buffer_head *bh_result, int args)
 {
        INITIALIZE_PATH(path);
@@ -253,7 +252,7 @@ static int _get_block_create_0(struct inode *inode, long block,
        struct buffer_head *bh;
        struct item_head *ih, tmp_ih;
        int fs_gen;
-       int blocknr;
+       b_blocknr_t blocknr;
        char *p = NULL;
        int chars;
        int ret;
@@ -364,7 +363,7 @@ static int _get_block_create_0(struct inode *inode, long block,
                }
                /* make sure we don't read more bytes than actually exist in
                 ** the file.  This can happen in odd cases where i_size isn't
-                ** correct, and when direct item padding results in a few 
+                ** correct, and when direct item padding results in a few
                 ** extra bytes at the end of the direct item
                 */
                if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size)
@@ -439,15 +438,15 @@ static int reiserfs_bmap(struct inode *inode, sector_t block,
 ** -ENOENT instead of a valid buffer.  block_prepare_write expects to
 ** be able to do i/o on the buffers returned, unless an error value
 ** is also returned.
-** 
+**
 ** So, this allows block_prepare_write to be used for reading a single block
 ** in a page.  Where it does not produce a valid page for holes, or past the
 ** end of the file.  This turns out to be exactly what we need for reading
 ** tails for conversion.
 **
 ** The point of the wrapper is forcing a certain value for create, even
-** though the VFS layer is calling this function with create==1.  If you 
-** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block, 
+** though the VFS layer is calling this function with create==1.  If you
+** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block,
 ** don't use this function.
 */
 static int reiserfs_get_block_create_0(struct inode *inode, sector_t block,
@@ -461,7 +460,6 @@ static int reiserfs_get_block_create_0(struct inode *inode, sector_t block,
    direct_IO request. */
 static int reiserfs_get_blocks_direct_io(struct inode *inode,
                                         sector_t iblock,
-                                        unsigned long max_blocks,
                                         struct buffer_head *bh_result,
                                         int create)
 {
@@ -546,7 +544,7 @@ static int convert_tail_for_hole(struct inode *inode,
 
        /* we don't have to make sure the conversion did not happen while
         ** we were locking the page because anyone that could convert
-        ** must first take i_sem.
+        ** must first take i_mutex.
         **
         ** We must fix the tail page for writing because it might have buffers
         ** that are mapped, but have a block number of 0.  This indicates tail
@@ -573,15 +571,15 @@ static int convert_tail_for_hole(struct inode *inode,
 }
 
 static inline int _allocate_block(struct reiserfs_transaction_handle *th,
-                                 long block,
+                                 sector_t block,
                                  struct inode *inode,
                                  b_blocknr_t * allocated_block_nr,
-                                 struct path *path, int flags)
+                                 struct treepath *path, int flags)
 {
        BUG_ON(!th->t_trans_id);
 
 #ifdef REISERFS_PREALLOCATE
-       if (!(flags & GET_BLOCK_NO_ISEM)) {
+       if (!(flags & GET_BLOCK_NO_IMUX)) {
                return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr,
                                                  path, block);
        }
@@ -604,7 +602,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
        int done;
        int fs_gen;
        struct reiserfs_transaction_handle *th = NULL;
-       /* space reserved in transaction batch: 
+       /* 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()
@@ -622,11 +620,6 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
        reiserfs_write_lock(inode->i_sb);
        version = get_inode_item_key_version(inode);
 
-       if (block < 0) {
-               reiserfs_write_unlock(inode->i_sb);
-               return -EIO;
-       }
-
        if (!file_capable(inode, block)) {
                reiserfs_write_unlock(inode->i_sb);
                return -EFBIG;
@@ -761,7 +754,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                reiserfs_write_unlock(inode->i_sb);
 
                /* the item was found, so new blocks were not added to the file
-                ** there is no need to make sure the inode is updated with this 
+                ** there is no need to make sure the inode is updated with this
                 ** transaction
                 */
                return retval;
@@ -848,10 +841,12 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                                                          tail_offset);
                                if (retval) {
                                        if (retval != -ENOSPC)
-                                               reiserfs_warning(inode->i_sb,
-                                                                "clm-6004: convert tail failed inode %lu, error %d",
-                                                                inode->i_ino,
-                                                                retval);
+                                               reiserfs_error(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)
@@ -929,25 +924,23 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                                     //pos_in_item * inode->i_sb->s_blocksize,
                                     TYPE_INDIRECT, 3); // key type is unimportant
 
+                       RFALSE(cpu_key_k_offset(&tmp_key) > cpu_key_k_offset(&key),
+                              "green-805: invalid offset");
                        blocks_needed =
                            1 +
                            ((cpu_key_k_offset(&key) -
                              cpu_key_k_offset(&tmp_key)) >> inode->i_sb->
                             s_blocksize_bits);
-                       RFALSE(blocks_needed < 0, "green-805: invalid offset");
 
                        if (blocks_needed == 1) {
                                un = &unf_single;
                        } else {
-                               un = kmalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_ATOMIC);      // We need to avoid scheduling.
+                               un = kzalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_ATOMIC);      // We need to avoid scheduling.
                                if (!un) {
                                        un = &unf_single;
                                        blocks_needed = 1;
                                        max_to_insert = 0;
-                               } else
-                                       memset(un, 0,
-                                              UNFM_P_SIZE * min(blocks_needed,
-                                                                max_to_insert));
+                               }
                        }
                        if (blocks_needed <= max_to_insert) {
                                /* we are going to add target block to the file. Use allocated
@@ -993,7 +986,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
 
                /* this loop could log more blocks than we had originally asked
                 ** for.  So, we have to allow the transaction to end if it is
-                ** too big or too full.  Update the inode so things are 
+                ** too big or too full.  Update the inode so things are
                 ** consistent if we crash before the function returns
                 **
                 ** release the path so that anybody waiting on the path before
@@ -1004,7 +997,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                        if (retval)
                                goto failure;
                }
-               /* inserting indirect pointers for a hole can take a 
+               /* inserting indirect pointers for a hole can take a
                 ** long time.  reschedule if needed
                 */
                cond_resched();
@@ -1015,8 +1008,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                        goto failure;
                }
                if (retval == POSITION_FOUND) {
-                       reiserfs_warning(inode->i_sb,
-                                        "vs-825: reiserfs_get_block: "
+                       reiserfs_warning(inode->i_sb, "vs-825",
                                         "%K should not be found", &key);
                        retval = -EEXIST;
                        if (allocated_block_nr)
@@ -1120,7 +1112,7 @@ static inline ulong to_fake_used_blocks(struct inode *inode, int sd_size)
 //
 
 // called by read_locked_inode
-static void init_inode(struct inode *inode, struct path *path)
+static void init_inode(struct inode *inode, struct treepath *path)
 {
        struct buffer_head *bh;
        struct item_head *ih;
@@ -1131,7 +1123,6 @@ static void init_inode(struct inode *inode, struct path *path)
        ih = PATH_PITEM_HEAD(path);
 
        copy_key(INODE_PKEY(inode), &(ih->ih_key));
-       inode->i_blksize = reiserfs_default_io_size;
 
        INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list));
        REISERFS_I(inode)->i_flags = 0;
@@ -1139,9 +1130,8 @@ 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);
+       mutex_init(&(REISERFS_I(inode)->i_mmap));
+       reiserfs_init_xattr_rwsem(inode);
 
        if (stat_data_v1(ih)) {
                struct stat_data_v1 *sd =
@@ -1298,7 +1288,7 @@ static void inode2sd_v1(void *sd, struct inode *inode, loff_t size)
 /* 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 treepath *path, struct inode *inode,
                             loff_t size)
 {
        struct buffer_head *bh;
@@ -1308,8 +1298,7 @@ static void update_stat_data(struct path *path, struct inode *inode,
        ih = PATH_PITEM_HEAD(path);
 
        if (!is_statdata_le_ih(ih))
-               reiserfs_panic(inode->i_sb,
-                              "vs-13065: update_stat_data: key %k, found item %h",
+               reiserfs_panic(inode->i_sb, "vs-13065", "key %k, found item %h",
                               INODE_PKEY(inode), ih);
 
        if (stat_data_v1(ih)) {
@@ -1341,10 +1330,9 @@ void reiserfs_update_sd_size(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(inode->i_sb,
-                                        "vs-13050: reiserfs_update_sd: "
-                                        "i/o failure occurred trying to update %K stat data",
-                                        &key);
+                       reiserfs_error(inode->i_sb, "vs-13050",
+                                      "i/o failure occurred trying to "
+                                      "update %K stat data", &key);
                        return;
                }
                if (retval == ITEM_NOT_FOUND) {
@@ -1354,9 +1342,9 @@ void reiserfs_update_sd_size(struct reiserfs_transaction_handle *th,
                                /*reiserfs_warning (inode->i_sb, "vs-13050: reiserfs_update_sd: i_nlink == 0, stat data not found"); */
                                return;
                        }
-                       reiserfs_warning(inode->i_sb,
-                                        "vs-13060: reiserfs_update_sd: "
-                                        "stat data of object %k (nlink == %d) not found (pos %d)",
+                       reiserfs_warning(inode->i_sb, "vs-13060",
+                                        "stat data of object %k (nlink == %d) "
+                                        "not found (pos %d)",
                                         INODE_PKEY(inode), inode->i_nlink,
                                         pos);
                        reiserfs_check_path(&path);
@@ -1433,10 +1421,9 @@ void reiserfs_read_locked_inode(struct inode *inode,
        /* look for the object's stat data */
        retval = search_item(inode->i_sb, &key, &path_to_sd);
        if (retval == IO_ERROR) {
-               reiserfs_warning(inode->i_sb,
-                                "vs-13070: reiserfs_read_locked_inode: "
-                                "i/o failure occurred trying to find stat data of %K",
-                                &key);
+               reiserfs_error(inode->i_sb, "vs-13070",
+                              "i/o failure occurred trying to find "
+                              "stat data of %K", &key);
                reiserfs_make_bad_inode(inode);
                return;
        }
@@ -1455,7 +1442,7 @@ void reiserfs_read_locked_inode(struct inode *inode,
           update sd on unlink all that is required is to check for nlink
           here. This bug was first found by Sizif when debugging
           SquidNG/Butterfly, forgotten, and found again after Philippe
-          Gramoulle <philippe.gramoulle@mmania.com> reproduced it. 
+          Gramoulle <philippe.gramoulle@mmania.com> reproduced it.
 
           More logical fix would require changes in fs/inode.c:iput() to
           remove inode from hash-table _after_ fs cleaned disk stuff up and
@@ -1466,8 +1453,7 @@ void reiserfs_read_locked_inode(struct inode *inode,
           during mount (fs/reiserfs/super.c:finish_unfinished()). */
        if ((inode->i_nlink == 0) &&
            !REISERFS_SB(inode->i_sb)->s_is_unlinked_ok) {
-               reiserfs_warning(inode->i_sb,
-                                "vs-13075: reiserfs_read_locked_inode: "
+               reiserfs_warning(inode->i_sb, "vs-13075",
                                 "dead inode read from disk %K. "
                                 "This is likely to be race with knfsd. Ignore",
                                 &key);
@@ -1526,43 +1512,30 @@ struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key)
        return inode;
 }
 
-struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp)
+static struct dentry *reiserfs_get_dentry(struct super_block *sb,
+       u32 objectid, u32 dir_id, u32 generation)
+
 {
-       __u32 *data = vobjp;
        struct cpu_key key;
-       struct dentry *result;
        struct inode *inode;
 
-       key.on_disk_key.k_objectid = data[0];
-       key.on_disk_key.k_dir_id = data[1];
+       key.on_disk_key.k_objectid = objectid;
+       key.on_disk_key.k_dir_id = dir_id;
        reiserfs_write_lock(sb);
        inode = reiserfs_iget(sb, &key);
-       if (inode && !IS_ERR(inode) && data[2] != 0 &&
-           data[2] != inode->i_generation) {
+       if (inode && !IS_ERR(inode) && generation != 0 &&
+           generation != inode->i_generation) {
                iput(inode);
                inode = NULL;
        }
        reiserfs_write_unlock(sb);
-       if (!inode)
-               inode = ERR_PTR(-ESTALE);
-       if (IS_ERR(inode))
-               return ERR_PTR(PTR_ERR(inode));
-       result = d_alloc_anon(inode);
-       if (!result) {
-               iput(inode);
-               return ERR_PTR(-ENOMEM);
-       }
-       return result;
+
+       return d_obtain_alias(inode);
 }
 
-struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data,
-                                 int len, int fhtype,
-                                 int (*acceptable) (void *contect,
-                                                    struct dentry * de),
-                                 void *context)
+struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+               int fh_len, int fh_type)
 {
-       __u32 obj[3], parent[3];
-
        /* 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.
@@ -1575,32 +1548,28 @@ struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data,
         *   6 - as above plus generation of directory
         * 6 does not fit in NFSv2 handles
         */
-       if (fhtype > len) {
-               if (fhtype != 6 || len != 5)
-                       reiserfs_warning(sb,
-                                        "nfsd/reiserfs, fhtype=%d, len=%d - odd",
-                                        fhtype, len);
-               fhtype = 5;
-       }
-
-       obj[0] = data[0];
-       obj[1] = data[1];
-       if (fhtype == 3 || fhtype >= 5)
-               obj[2] = data[2];
-       else
-               obj[2] = 0;     /* generation number */
-
-       if (fhtype >= 4) {
-               parent[0] = data[fhtype >= 5 ? 3 : 2];
-               parent[1] = data[fhtype >= 5 ? 4 : 3];
-               if (fhtype == 6)
-                       parent[2] = data[5];
-               else
-                       parent[2] = 0;
+       if (fh_type > fh_len) {
+               if (fh_type != 6 || fh_len != 5)
+                       reiserfs_warning(sb, "reiserfs-13077",
+                               "nfsd/reiserfs, fhtype=%d, len=%d - odd",
+                               fh_type, fh_len);
+               fh_type = 5;
        }
-       return sb->s_export_op->find_exported_dentry(sb, obj,
-                                                    fhtype < 4 ? NULL : parent,
-                                                    acceptable, context);
+
+       return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1],
+               (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0);
+}
+
+struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid,
+               int fh_len, int fh_type)
+{
+       if (fh_type < 4)
+               return NULL;
+
+       return reiserfs_get_dentry(sb,
+               (fh_type >= 5) ? fid->raw[3] : fid->raw[2],
+               (fh_type >= 5) ? fid->raw[4] : fid->raw[3],
+               (fh_type == 6) ? fid->raw[5] : 0);
 }
 
 int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
@@ -1648,7 +1617,7 @@ int reiserfs_write_inode(struct inode *inode, int do_sync)
        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 
+        ** these cases are just when the system needs ram, not when the
         ** inode needs to reach disk for safety, and they can safely be
         ** ignored because the altered inode has already been logged.
         */
@@ -1667,7 +1636,7 @@ int reiserfs_write_inode(struct inode *inode, int do_sync)
    containing "." and ".." entries */
 static int reiserfs_new_directory(struct reiserfs_transaction_handle *th,
                                  struct inode *inode,
-                                 struct item_head *ih, struct path *path,
+                                 struct item_head *ih, struct treepath *path,
                                  struct inode *dir)
 {
        struct super_block *sb = th->t_super;
@@ -1706,13 +1675,13 @@ 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(sb, "vs-13080: reiserfs_new_directory: "
-                                "i/o failure occurred creating new directory");
+               reiserfs_error(sb, "vs-13080",
+                              "i/o failure occurred creating new directory");
                return -EIO;
        }
        if (retval == ITEM_FOUND) {
                pathrelse(path);
-               reiserfs_warning(sb, "vs-13070: reiserfs_new_directory: "
+               reiserfs_warning(sb, "vs-13070",
                                 "object with this key exists (%k)",
                                 &(ih->ih_key));
                return -EEXIST;
@@ -1726,7 +1695,7 @@ static int reiserfs_new_directory(struct reiserfs_transaction_handle *th,
    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,
+                               struct treepath *path, const char *symname,
                                int item_len)
 {
        struct super_block *sb = th->t_super;
@@ -1746,13 +1715,13 @@ static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct i
        /* look for place in the tree for new item */
        retval = search_item(sb, &key, path);
        if (retval == IO_ERROR) {
-               reiserfs_warning(sb, "vs-13080: reiserfs_new_symlinik: "
-                                "i/o failure occurred creating new symlink");
+               reiserfs_error(sb, "vs-13080",
+                              "i/o failure occurred creating new symlink");
                return -EIO;
        }
        if (retval == ITEM_FOUND) {
                pathrelse(path);
-               reiserfs_warning(sb, "vs-13080: reiserfs_new_symlink: "
+               reiserfs_warning(sb, "vs-13080",
                                 "object with this key exists (%k)",
                                 &(ih->ih_key));
                return -EEXIST;
@@ -1765,7 +1734,7 @@ static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct i
 /* 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) 
+   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
@@ -1773,12 +1742,14 @@ static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct i
    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, 
+                      /* 0 for regular, EMTRY_DIR_SIZE for dirs,
                          strlen (symname) for symlinks) */
                       loff_t i_size, struct dentry *dentry,
-                      struct inode *inode)
+                      struct inode *inode,
+                      struct reiserfs_security_handle *security)
 {
        struct super_block *sb;
+       struct reiserfs_iget_args args;
        INITIALIZE_PATH(path_to_key);
        struct cpu_key key;
        struct item_head ih;
@@ -1788,11 +1759,11 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
        BUG_ON(!th->t_trans_id);
 
-       if (DQUOT_ALLOC_INODE(inode)) {
+       if (vfs_dq_alloc_inode(inode)) {
                err = -EDQUOT;
                goto out_end_trans;
        }
-       if (!dir || !dir->i_nlink) {
+       if (!dir->i_nlink) {
                err = -EPERM;
                goto out_bad_inode;
        }
@@ -1806,8 +1777,22 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
                err = -ENOMEM;
                goto out_bad_inode;
        }
+       args.objectid = inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid);
        if (old_format_only(sb))
-               /* not a perfect generation count, as object ids can be reused, but 
+               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, NULL, KEY_FORMAT_3_6, SD_OFFSET,
+                                 TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);
+       memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);
+       args.dirid = le32_to_cpu(ih.ih_key.k_dir_id);
+       if (insert_inode_locked4(inode, args.objectid,
+                            reiserfs_find_actor, &args) < 0) {
+               err = -EINVAL;
+               goto out_bad_inode;
+       }
+       if (old_format_only(sb))
+               /* not a perfect generation count, as object ids can be reused, but
                 ** this is as good as reiserfs can do right now.
                 ** note that the private part of inode isn't filled in yet, we have
                 ** to use the directory.
@@ -1846,16 +1831,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        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, NULL, KEY_FORMAT_3_5, SD_OFFSET,
-                                 TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT);
-       else
-               make_le_item_head(&ih, NULL, KEY_FORMAT_3_6, SD_OFFSET,
-                                 TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);
+       mutex_init(&(REISERFS_I(inode)->i_mmap));
+       reiserfs_init_xattr_rwsem(inode);
 
        /* 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),
@@ -1884,14 +1861,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        } else {
                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);
-       inode->i_blksize = reiserfs_default_io_size;
-
        // store in in-core inode the key of stat data and version all
        // object items will have (directory items will have old offset
        // format, other new objects will consist of new items)
-       memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);
        if (old_format_only(sb) || S_ISDIR(mode) || S_ISLNK(mode))
                set_inode_item_key_version(inode, KEY_FORMAT_3_5);
        else
@@ -1939,9 +1911,8 @@ 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);
+               retval = reiserfs_inherit_default_acl(th, dir, dentry, inode);
                if (retval) {
                        err = retval;
                        reiserfs_check_path(&path_to_key);
@@ -1949,13 +1920,25 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
                        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, "
+               reiserfs_warning(inode->i_sb, "jdm-13090",
+                                "ACLs aren't enabled in the fs, "
                                 "but vfs thinks they are!");
-       } else if (is_reiserfs_priv_object(dir)) {
-               reiserfs_mark_inode_private(inode);
+       } else if (IS_PRIVATE(dir))
+               inode->i_flags |= S_PRIVATE;
+
+       if (security->name) {
+               retval = reiserfs_security_write(th, inode, security);
+               if (retval) {
+                       err = retval;
+                       reiserfs_check_path(&path_to_key);
+                       retval = journal_end(th, th->t_super,
+                                            th->t_blocks_allocated);
+                       if (retval)
+                               err = retval;
+                       goto out_inserted_sd;
+               }
        }
 
-       insert_inode_hash(inode);
        reiserfs_update_sd(th, inode);
        reiserfs_check_path(&path_to_key);
 
@@ -1970,29 +1953,20 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        INODE_PKEY(inode)->k_objectid = 0;
 
        /* Quota change must be inside a transaction for journaling */
-       DQUOT_FREE_INODE(inode);
+       vfs_dq_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);
+       vfs_dq_drop(inode);
        inode->i_flags |= S_NOQUOTA;
        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 */
-
-       /* If we were inheriting an ACL, we need to release the lock so that
-        * iput doesn't deadlock in reiserfs_delete_xattrs. The locking
-        * code really needs to be reworked, but this will take care of it
-        * for now. -jeffm */
-       if (REISERFS_I(dir)->i_acl_default && !IS_ERR(REISERFS_I(dir)->i_acl_default)) {
-               reiserfs_write_unlock_xattrs(dir->i_sb);
-               iput(inode);
-               reiserfs_write_lock_xattrs(dir->i_sb);
-       } else
-               iput(inode);
+       unlock_new_inode(inode); /* OK to do even if we hadn't locked it */
+       iput(inode);
        return err;
 }
 
@@ -2009,7 +1983,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 **
 ** on failure, nonzero is returned, page_result and bh_result are untouched.
 */
-static int grab_tail_page(struct inode *p_s_inode,
+static int grab_tail_page(struct inode *inode,
                          struct page **page_result,
                          struct buffer_head **bh_result)
 {
@@ -2017,11 +1991,11 @@ static int grab_tail_page(struct inode *p_s_inode,
        /* we want the page with the last byte in the file,
         ** not the page that will hold the next byte for appending
         */
-       unsigned long index = (p_s_inode->i_size - 1) >> PAGE_CACHE_SHIFT;
+       unsigned long index = (inode->i_size - 1) >> PAGE_CACHE_SHIFT;
        unsigned long pos = 0;
        unsigned long start = 0;
-       unsigned long blocksize = p_s_inode->i_sb->s_blocksize;
-       unsigned long offset = (p_s_inode->i_size) & (PAGE_CACHE_SIZE - 1);
+       unsigned long blocksize = inode->i_sb->s_blocksize;
+       unsigned long offset = (inode->i_size) & (PAGE_CACHE_SIZE - 1);
        struct buffer_head *bh;
        struct buffer_head *head;
        struct page *page;
@@ -2035,7 +2009,7 @@ static int grab_tail_page(struct inode *p_s_inode,
        if ((offset & (blocksize - 1)) == 0) {
                return -ENOENT;
        }
-       page = grab_cache_page(p_s_inode->i_mapping, index);
+       page = grab_cache_page(inode->i_mapping, index);
        error = -ENOMEM;
        if (!page) {
                goto out;
@@ -2064,10 +2038,8 @@ 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(p_s_inode->i_sb,
-                                "clm-6000: error reading block %lu on dev %s",
-                                bh->b_blocknr,
-                                reiserfs_bdevname(p_s_inode->i_sb));
+               reiserfs_error(inode->i_sb, "clm-6000",
+                              "error reading block %lu", bh->b_blocknr);
                error = -EIO;
                goto unlock;
        }
@@ -2089,63 +2061,69 @@ static int grab_tail_page(struct inode *p_s_inode,
 **
 ** some code taken from block_truncate_page
 */
-int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
+int reiserfs_truncate_file(struct inode *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);
-       unsigned blocksize = p_s_inode->i_sb->s_blocksize;
+       unsigned long offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
+       unsigned blocksize = inode->i_sb->s_blocksize;
        unsigned length;
        struct page *page = NULL;
        int error;
        struct buffer_head *bh = NULL;
+       int err2;
 
-       reiserfs_write_lock(p_s_inode->i_sb);
+       reiserfs_write_lock(inode->i_sb);
 
-       if (p_s_inode->i_size > 0) {
-               if ((error = grab_tail_page(p_s_inode, &page, &bh))) {
-                       // -ENOENT means we truncated past the end of the file, 
+       if (inode->i_size > 0) {
+               error = grab_tail_page(inode, &page, &bh);
+               if (error) {
+                       // -ENOENT means we truncated past the end of the file,
                        // and get_block_create_0 could not find a block to read in,
                        // which is ok.
                        if (error != -ENOENT)
-                               reiserfs_warning(p_s_inode->i_sb,
-                                                "clm-6001: grab_tail_page failed %d",
-                                                error);
+                               reiserfs_error(inode->i_sb, "clm-6001",
+                                              "grab_tail_page failed %d",
+                                              error);
                        page = NULL;
                        bh = NULL;
                }
        }
 
-       /* so, if page != NULL, we have a buffer head for the offset at 
-        ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0, 
-        ** then we have an unformatted node.  Otherwise, we have a direct item, 
-        ** and no zeroing is required on disk.  We zero after the truncate, 
-        ** because the truncate might pack the item anyway 
+       /* so, if page != NULL, we have a buffer head for the offset at
+        ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0,
+        ** then we have an unformatted node.  Otherwise, we have a direct item,
+        ** and no zeroing is required on disk.  We zero after the truncate,
+        ** because the truncate might pack the item anyway
         ** (it will unmap bh if it packs).
         */
        /* 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 */
-       error = journal_begin(&th, p_s_inode->i_sb,
+       error = journal_begin(&th, inode->i_sb,
                              JOURNAL_PER_BALANCE_CNT * 2 + 1);
        if (error)
                goto out;
-       reiserfs_update_inode_transaction(p_s_inode);
+       reiserfs_update_inode_transaction(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);
-       error = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
-       if (error)
-               goto out;
+               add_save_link(&th, inode, 1);
+       err2 = reiserfs_do_truncate(&th, inode, page, update_timestamps);
        error =
-           journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
+           journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
        if (error)
                goto out;
 
+       /* check reiserfs_do_truncate after ending the transaction */
+       if (err2) {
+               error = err2;
+               goto out;
+       }
+       
        if (update_timestamps) {
-               error = remove_save_link(p_s_inode, 1 /* truncate */ );
+               error = remove_save_link(inode, 1 /* truncate */);
                if (error)
                        goto out;
        }
@@ -2154,13 +2132,8 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
                length = offset & (blocksize - 1);
                /* if we are not on a block boundary */
                if (length) {
-                       char *kaddr;
-
                        length = blocksize - length;
-                       kaddr = kmap_atomic(page, KM_USER0);
-                       memset(kaddr + offset, 0, length);
-                       flush_dcache_page(page);
-                       kunmap_atomic(kaddr, KM_USER0);
+                       zero_user(page, offset, length);
                        if (buffer_mapped(bh) && bh->b_blocknr != 0) {
                                mark_buffer_dirty(bh);
                        }
@@ -2169,14 +2142,14 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
                page_cache_release(page);
        }
 
-       reiserfs_write_unlock(p_s_inode->i_sb);
+       reiserfs_write_unlock(inode->i_sb);
        return 0;
       out:
        if (page) {
                unlock_page(page);
                page_cache_release(page);
        }
-       reiserfs_write_unlock(p_s_inode->i_sb);
+       reiserfs_write_unlock(inode->i_sb);
        return error;
 }
 
@@ -2194,7 +2167,7 @@ static int map_block_for_writepage(struct inode *inode,
        INITIALIZE_PATH(path);
        int pos_in_item;
        int jbegin_count = JOURNAL_PER_BALANCE_CNT;
-       loff_t byte_offset = (block << inode->i_sb->s_blocksize_bits) + 1;
+       loff_t byte_offset = ((loff_t)block << inode->i_sb->s_blocksize_bits)+1;
        int retval;
        int use_get_block = 0;
        int bytes_copied = 0;
@@ -2228,9 +2201,8 @@ static int map_block_for_writepage(struct inode *inode,
        /* we've found an unformatted node */
        if (indirect_item_found(retval, ih)) {
                if (bytes_copied > 0) {
-                       reiserfs_warning(inode->i_sb,
-                                        "clm-6002: bytes_copied %d",
-                                        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 */
@@ -2287,9 +2259,8 @@ static int map_block_for_writepage(struct inode *inode,
                        goto research;
                }
        } else {
-               reiserfs_warning(inode->i_sb,
-                                "clm-6003: bad item inode %lu, device %s",
-                                inode->i_ino, reiserfs_bdevname(inode->i_sb));
+               reiserfs_warning(inode->i_sb, "clm-6003",
+                                "bad item inode %lu", inode->i_ino);
                retval = -EIO;
                goto out;
        }
@@ -2308,7 +2279,7 @@ static int map_block_for_writepage(struct inode *inode,
        /* this is where we fill in holes in the file. */
        if (use_get_block) {
                retval = reiserfs_get_block(inode, block, bh_result,
-                                           GET_BLOCK_CREATE | GET_BLOCK_NO_ISEM
+                                           GET_BLOCK_CREATE | GET_BLOCK_NO_IMUX
                                            | GET_BLOCK_NO_DANGLE);
                if (!retval) {
                        if (!buffer_mapped(bh_result)
@@ -2332,8 +2303,8 @@ static int map_block_for_writepage(struct inode *inode,
        return retval;
 }
 
-/* 
- * mason@suse.com: updated in 2.5.54 to follow the same general io 
+/*
+ * mason@suse.com: updated in 2.5.54 to follow the same general io
  * start/recovery path as __block_write_full_page, along with special
  * code to handle reiserfs tails.
  */
@@ -2344,6 +2315,7 @@ static int reiserfs_write_full_page(struct page *page,
        unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
        int error = 0;
        unsigned long block;
+       sector_t last_block;
        struct buffer_head *head, *bh;
        int partial = 0;
        int nr = 0;
@@ -2353,6 +2325,13 @@ static int reiserfs_write_full_page(struct page *page,
        int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize;
        th.t_trans_id = 0;
 
+       /* no logging allowed when nonblocking or from PF_MEMALLOC */
+       if (checked && (current->flags & PF_MEMALLOC)) {
+               redirty_page_for_writepage(wbc, page);
+               unlock_page(page);
+               return 0;
+       }
+
        /* The page dirty bit is cleared before writepage is called, which
         * means we have to tell create_empty_buffers to make dirty buffers
         * The page really should be up to date at this point, so tossing
@@ -2368,7 +2347,6 @@ static int reiserfs_write_full_page(struct page *page,
         ** last byte in the file
         */
        if (page->index >= end_index) {
-               char *kaddr;
                unsigned last_offset;
 
                last_offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
@@ -2377,17 +2355,23 @@ static int reiserfs_write_full_page(struct page *page,
                        unlock_page(page);
                        return 0;
                }
-               kaddr = kmap_atomic(page, KM_USER0);
-               memset(kaddr + last_offset, 0, PAGE_CACHE_SIZE - last_offset);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
+               zero_user_segment(page, last_offset, PAGE_CACHE_SIZE);
        }
        bh = head;
        block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits);
+       last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
        /* first map all the buffers, logging any direct items we find */
        do {
-               if ((checked || buffer_dirty(bh)) && (!buffer_mapped(bh) ||
-                                                     (buffer_mapped(bh)
+               if (block > last_block) {
+                       /*
+                        * This can happen when the block size is less than
+                        * the page size.  The corresponding bytes in the page
+                        * were zero filled above
+                        */
+                       clear_buffer_dirty(bh);
+                       set_buffer_uptodate(bh);
+               } else 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
@@ -2437,7 +2421,7 @@ static int reiserfs_write_full_page(struct page *page,
                if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {
                        lock_buffer(bh);
                } else {
-                       if (test_set_buffer_locked(bh)) {
+                       if (!trylock_buffer(bh)) {
                                redirty_page_for_writepage(wbc, page);
                                continue;
                        }
@@ -2460,7 +2444,7 @@ static int reiserfs_write_full_page(struct page *page,
        unlock_page(page);
 
        /*
-        * since any buffer might be the only dirty buffer on the page, 
+        * since any buffer might be the only dirty buffer on the page,
         * the first submit_bh can bring the page out of writeback.
         * be careful with the buffers.
         */
@@ -2479,8 +2463,8 @@ static int reiserfs_write_full_page(struct page *page,
        if (nr == 0) {
                /*
                 * if this page only had a direct item, it is very possible for
-                * no io to be required without there being an error.  Or, 
-                * someone else could have locked them and sent them down the 
+                * no io to be required without there being an error.  Or,
+                * someone else could have locked them and sent them down the
                 * pipe without locking the page
                 */
                bh = head;
@@ -2499,7 +2483,7 @@ static int reiserfs_write_full_page(struct page *page,
 
       fail:
        /* catches various errors, we need to make sure any valid dirty blocks
-        * get to the media.  The page is currently locked and not marked for 
+        * get to the media.  The page is currently locked and not marked for
         * writeback
         */
        ClearPageUptodate(page);
@@ -2547,8 +2531,78 @@ static int reiserfs_writepage(struct page *page, struct writeback_control *wbc)
        return reiserfs_write_full_page(page, wbc);
 }
 
-static int reiserfs_prepare_write(struct file *f, struct page *page,
-                                 unsigned from, unsigned to)
+static int reiserfs_write_begin(struct file *file,
+                               struct address_space *mapping,
+                               loff_t pos, unsigned len, unsigned flags,
+                               struct page **pagep, void **fsdata)
+{
+       struct inode *inode;
+       struct page *page;
+       pgoff_t index;
+       int ret;
+       int old_ref = 0;
+
+       inode = mapping->host;
+       *fsdata = 0;
+       if (flags & AOP_FLAG_CONT_EXPAND &&
+           (pos & (inode->i_sb->s_blocksize - 1)) == 0) {
+               pos ++;
+               *fsdata = (void *)(unsigned long)flags;
+       }
+
+       index = pos >> PAGE_CACHE_SHIFT;
+       page = grab_cache_page_write_begin(mapping, index, flags);
+       if (!page)
+               return -ENOMEM;
+       *pagep = page;
+
+       reiserfs_wait_on_write_block(inode->i_sb);
+       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;
+               BUG_ON(!th->t_refcount);
+               BUG_ON(!th->t_trans_id);
+               old_ref = th->t_refcount;
+               th->t_refcount++;
+       }
+       ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+                               reiserfs_get_block);
+       if (ret && reiserfs_transaction_running(inode->i_sb)) {
+               struct reiserfs_transaction_handle *th = current->journal_info;
+               /* this gets a little ugly.  If reiserfs_get_block returned an
+                * error and left a transacstion running, we've got to close it,
+                * and we've got to free handle if it was a persistent transaction.
+                *
+                * But, if we had nested into an existing transaction, we need
+                * to just drop the ref count on the handle.
+                *
+                * If old_ref == 0, the transaction is from reiserfs_get_block,
+                * and it was a persistent trans.  Otherwise, it was nested above.
+                */
+               if (th->t_refcount > old_ref) {
+                       if (old_ref)
+                               th->t_refcount--;
+                       else {
+                               int err;
+                               reiserfs_write_lock(inode->i_sb);
+                               err = reiserfs_end_persistent_transaction(th);
+                               reiserfs_write_unlock(inode->i_sb);
+                               if (err)
+                                       ret = err;
+                       }
+               }
+       }
+       if (ret) {
+               unlock_page(page);
+               page_cache_release(page);
+       }
+       return ret;
+}
+
+int reiserfs_prepare_write(struct file *f, struct page *page,
+                          unsigned from, unsigned to)
 {
        struct inode *inode = page->mapping->host;
        int ret;
@@ -2601,8 +2655,102 @@ static sector_t reiserfs_aop_bmap(struct address_space *as, sector_t block)
        return generic_block_bmap(as, block, reiserfs_bmap);
 }
 
-static int reiserfs_commit_write(struct file *f, struct page *page,
-                                unsigned from, unsigned to)
+static int reiserfs_write_end(struct file *file, struct address_space *mapping,
+                             loff_t pos, unsigned len, unsigned copied,
+                             struct page *page, void *fsdata)
+{
+       struct inode *inode = page->mapping->host;
+       int ret = 0;
+       int update_sd = 0;
+       struct reiserfs_transaction_handle *th;
+       unsigned start;
+
+       if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND)
+               pos ++;
+
+       reiserfs_wait_on_write_block(inode->i_sb);
+       if (reiserfs_transaction_running(inode->i_sb))
+               th = current->journal_info;
+       else
+               th = NULL;
+
+       start = pos & (PAGE_CACHE_SIZE - 1);
+       if (unlikely(copied < len)) {
+               if (!PageUptodate(page))
+                       copied = 0;
+
+               page_zero_new_buffers(page, start + copied, start + len);
+       }
+       flush_dcache_page(page);
+
+       reiserfs_commit_page(inode, page, start, start + copied);
+
+       /* generic_commit_write does this for us, but does not update the
+        ** transaction tracking stuff when the size changes.  So, we have
+        ** to do the i_size updates here.
+        */
+       pos += copied;
+       if (pos > inode->i_size) {
+               struct reiserfs_transaction_handle myth;
+               reiserfs_write_lock(inode->i_sb);
+               /* If the file have grown beyond the border where it
+                  can have a tail, unmark it as needing a tail
+                  packing */
+               if ((have_large_tails(inode->i_sb)
+                    && inode->i_size > i_block_size(inode) * 4)
+                   || (have_small_tails(inode->i_sb)
+                       && inode->i_size > i_block_size(inode)))
+                       REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
+
+               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;
+               /*
+                * this will just nest into our transaction.  It's important
+                * to use mark_inode_dirty so the inode gets pushed around on the
+                * dirty lists, and so that O_SYNC works as expected
+                */
+               mark_inode_dirty(inode);
+               reiserfs_update_sd(&myth, inode);
+               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);
+               if (!update_sd)
+                       mark_inode_dirty(inode);
+               ret = reiserfs_end_persistent_transaction(th);
+               reiserfs_write_unlock(inode->i_sb);
+               if (ret)
+                       goto out;
+       }
+
+      out:
+       unlock_page(page);
+       page_cache_release(page);
+       return ret == 0 ? copied : 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);
+       }
+
+       goto out;
+}
+
+int reiserfs_commit_write(struct file *f, struct page *page,
+                         unsigned from, unsigned to)
 {
        struct inode *inode = page->mapping->host;
        loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + to;
@@ -2733,6 +2881,7 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh)
        int ret = 1;
        struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb);
 
+       lock_buffer(bh);
        spin_lock(&j->j_dirty_buffers_lock);
        if (!buffer_mapped(bh)) {
                goto free_jh;
@@ -2748,7 +2897,7 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh)
                if (buffer_journaled(bh) || buffer_journal_dirty(bh)) {
                        ret = 0;
                }
-       } else if (buffer_dirty(bh) || buffer_locked(bh)) {
+       } else  if (buffer_dirty(bh)) {
                struct reiserfs_journal_list *jl;
                struct reiserfs_jh *jh = bh->b_private;
 
@@ -2774,11 +2923,12 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh)
                reiserfs_free_jh(bh);
        }
        spin_unlock(&j->j_dirty_buffers_lock);
+       unlock_buffer(bh);
        return ret;
 }
 
 /* clm -- taken from fs/buffer.c:block_invalidate_page */
-static int reiserfs_invalidatepage(struct page *page, unsigned long offset)
+static void reiserfs_invalidatepage(struct page *page, unsigned long offset)
 {
        struct buffer_head *head, *bh, *next;
        struct inode *inode = page->mapping->host;
@@ -2817,10 +2967,12 @@ static int reiserfs_invalidatepage(struct page *page, unsigned long offset)
         * The get_block cached value has been unconditionally invalidated,
         * so real IO is not possible anymore.
         */
-       if (!offset && ret)
+       if (!offset && ret) {
                ret = try_to_release_page(page, 0);
+               /* maybe should BUG_ON(!ret); - neilb */
+       }
       out:
-       return ret;
+       return;
 }
 
 static int reiserfs_set_page_dirty(struct page *page)
@@ -2889,7 +3041,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
        int error;
-       unsigned int ia_valid = attr->ia_valid;
+       unsigned int ia_valid;
+
+       /* must be turned off for recursive notify_change calls */
+       ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
+
        reiserfs_write_lock(inode->i_sb);
        if (attr->ia_valid & ATTR_SIZE) {
                /* version 2 items will be caught by the s_maxbytes check
@@ -2902,7 +3058,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                }
                /* fill in hole pointers in the expanding truncate case. */
                if (attr->ia_size > inode->i_size) {
-                       error = generic_cont_expand(inode, attr->ia_size);
+                       error = generic_cont_expand_simple(inode, attr->ia_size);
                        if (REISERFS_I(inode)->i_prealloc_count > 0) {
                                int err;
                                struct reiserfs_transaction_handle th;
@@ -2917,6 +3073,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                        }
                        if (error)
                                goto out;
+                       /*
+                        * file size is changed, ctime and mtime are
+                        * to be updated
+                        */
+                       attr->ia_valid |= (ATTR_MTIME | ATTR_CTIME);
                }
        }
 
@@ -2949,7 +3110,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                                if (error)
                                        goto out;
                                error =
-                                   DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
+                                   vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
                                if (error) {
                                        journal_end(&th, inode->i_sb,
                                                    jbegin_count);
@@ -2980,15 +3141,15 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        return error;
 }
 
-struct address_space_operations reiserfs_address_space_operations = {
+const struct address_space_operations reiserfs_address_space_operations = {
        .writepage = reiserfs_writepage,
        .readpage = reiserfs_readpage,
        .readpages = reiserfs_readpages,
        .releasepage = reiserfs_releasepage,
        .invalidatepage = reiserfs_invalidatepage,
        .sync_page = block_sync_page,
-       .prepare_write = reiserfs_prepare_write,
-       .commit_write = reiserfs_commit_write,
+       .write_begin = reiserfs_write_begin,
+       .write_end = reiserfs_write_end,
        .bmap = reiserfs_aop_bmap,
        .direct_IO = reiserfs_direct_IO,
        .set_page_dirty = reiserfs_set_page_dirty,