VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / fs / ext3 / inode.c
index c1508b2..da40fc7 100644 (file)
@@ -208,8 +208,6 @@ void ext3_delete_inode (struct inode * inode)
                 * need to make sure that the in-core orphan linked list
                 * is properly cleaned up. */
                ext3_orphan_del(NULL, inode);
-
-               ext3_std_error(inode->i_sb, PTR_ERR(handle));
                goto no_delete;
        }
 
@@ -292,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
@@ -301,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;
 }
@@ -814,6 +812,7 @@ out:
        if (err == -EAGAIN)
                goto changed;
 
+       goal = 0;
        down(&ei->truncate_sem);
        if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0) {
                up(&ei->truncate_sem);
@@ -863,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) {
@@ -885,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
  */
@@ -1084,14 +1099,16 @@ 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 retries = 0;
 
+retry:
        handle = ext3_journal_start(inode, needed_blocks);
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
                goto out;
        }
        ret = block_prepare_write(page, from, to, ext3_get_block);
-       if (ret != 0)
+       if (ret)
                goto prepare_write_failed;
 
        if (ext3_should_journal_data(inode)) {
@@ -1101,6 +1118,8 @@ static int ext3_prepare_write(struct file *file, struct page *page,
 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;
 }
@@ -2495,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);
@@ -2607,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,
@@ -2831,7 +2850,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
                return error;
 
        if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
-               (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+               (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid) ||
+               (ia_valid & ATTR_XID && attr->ia_xid != inode->i_xid)) {
                handle_t *handle;
 
                /* (user+group)*(old+new) structure, inode write (sb,
@@ -2852,6 +2872,10 @@ 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)
+                       && 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);
        }