VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / fs / ext3 / inode.c
index ebfa3b0..da40fc7 100644 (file)
@@ -290,7 +290,7 @@ static int ext3_alloc_block (handle_t *handle,
                                 &ei->i_prealloc_count,
                                 &ei->i_prealloc_block, err);
                else
-                       result = ext3_new_block (inode, goal, 0, 0, err);
+                       result = ext3_new_block(inode, goal, NULL, NULL, err);
                /*
                 * AKPM: this is somewhat sticky.  I'm not surprised it was
                 * disabled in 2.2's ext3.  Need to integrate b_committed_data
@@ -299,7 +299,7 @@ static int ext3_alloc_block (handle_t *handle,
                 */
        }
 #else
-       result = ext3_new_block (handle, inode, goal, 0, 0, err);
+       result = ext3_new_block(handle, inode, goal, NULL, NULL, err);
 #endif
        return result;
 }
@@ -862,7 +862,7 @@ changed:
 static int ext3_get_block(struct inode *inode, sector_t iblock,
                        struct buffer_head *bh_result, int create)
 {
-       handle_t *handle = 0;
+       handle_t *handle = NULL;
        int ret;
 
        if (create) {
@@ -884,26 +884,42 @@ ext3_direct_io_get_blocks(struct inode *inode, sector_t iblock,
        handle_t *handle = journal_current_handle();
        int ret = 0;
 
-       if (handle && handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) {
+       if (!handle)
+               goto get_block;         /* A read */
+
+       if (handle->h_transaction->t_state == T_LOCKED) {
+               /*
+                * Huge direct-io writes can hold off commits for long
+                * periods of time.  Let this commit run.
+                */
+               ext3_journal_stop(handle);
+               handle = ext3_journal_start(inode, DIO_CREDITS);
+               if (IS_ERR(handle))
+                       ret = PTR_ERR(handle);
+               goto get_block;
+       }
+
+       if (handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) {
                /*
                 * Getting low on buffer credits...
                 */
-               if (!ext3_journal_extend(handle, DIO_CREDITS)) {
+               ret = ext3_journal_extend(handle, DIO_CREDITS);
+               if (ret > 0) {
                        /*
-                        * Couldn't extend the transaction.  Start a new one
+                        * Couldn't extend the transaction.  Start a new one.
                         */
                        ret = ext3_journal_restart(handle, DIO_CREDITS);
                }
        }
+
+get_block:
        if (ret == 0)
                ret = ext3_get_block_handle(handle, inode, iblock,
                                        bh_result, create, 0);
-       if (ret == 0)
-               bh_result->b_size = (1 << inode->i_blkbits);
+       bh_result->b_size = (1 << inode->i_blkbits);
        return ret;
 }
 
-
 /*
  * `handle' can be NULL if create is zero
  */
@@ -1083,7 +1099,7 @@ static int ext3_prepare_write(struct file *file, struct page *page,
        struct inode *inode = page->mapping->host;
        int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
        handle_t *handle;
-       int tried_commit = 0;
+       int retries = 0;
 
 retry:
        handle = ext3_journal_start(inode, needed_blocks);
@@ -1092,19 +1108,8 @@ retry:
                goto out;
        }
        ret = block_prepare_write(page, from, to, ext3_get_block);
-       if (ret) {
-               if (ret != -ENOSPC || tried_commit)
-                       goto prepare_write_failed;
-               /*
-                * It could be that there _is_ free space, but it's all tied up
-                * in uncommitted bitmaps.  So force a commit here, which makes
-                * those blocks allocatable and try again.
-                */
-               tried_commit = 1;
-               handle->h_sync = 1;
-               ext3_journal_stop(handle);
-               goto retry;
-       }
+       if (ret)
+               goto prepare_write_failed;
 
        if (ext3_should_journal_data(inode)) {
                ret = walk_page_buffers(handle, page_buffers(page),
@@ -1113,6 +1118,8 @@ retry:
 prepare_write_failed:
        if (ret)
                ext3_journal_stop(handle);
+       if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
+               goto retry;
 out:
        return ret;
 }
@@ -2507,10 +2514,10 @@ void ext3_read_inode(struct inode * inode)
                uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
                gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
        }
-       inode->i_uid = INOXID_UID(uid, gid);
-       inode->i_gid = INOXID_GID(uid, gid);
-       if (inode->i_sb->s_flags & MS_TAGXID)
-               inode->i_xid = INOXID_XID(uid, gid, le16_to_cpu(raw_inode->i_raw_xid));
+       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,
+               le16_to_cpu(raw_inode->i_raw_xid));
 
        inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
        inode->i_size = le32_to_cpu(raw_inode->i_size);
@@ -2619,8 +2626,8 @@ static int ext3_do_update_inode(handle_t *handle,
        struct ext3_inode *raw_inode = ext3_raw_inode(iloc);
        struct ext3_inode_info *ei = EXT3_I(inode);
        struct buffer_head *bh = iloc->bh;
-       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);
        int err = 0, rc, block;
 
        /* For fields not not tracking in the in-memory inode,
@@ -2865,7 +2872,9 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
                        inode->i_uid = attr->ia_uid;
                if (attr->ia_valid & ATTR_GID)
                        inode->i_gid = attr->ia_gid;
-               if (attr->ia_valid & ATTR_XID)
+               if ((attr->ia_valid & ATTR_XID)
+                       && inode->i_sb
+                       && (inode->i_sb->s_flags & MS_TAGXID))
                        inode->i_xid = attr->ia_xid;
                error = ext3_mark_inode_dirty(handle, inode);
                ext3_journal_stop(handle);