X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fext3%2Finode.c;h=da40fc7c6264da9fd8dc658658cda30b4fee94ed;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=ebfa3b05e96411a53f71fc23ff5314139a18845d;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index ebfa3b05e..da40fc7c6 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -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);