[Ocfs2-commits] zab commits r2613 -
branches/locking-changes/fs/ocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Thu Sep 22 18:10:41 CDT 2005
Author: zab
Date: 2005-09-22 18:10:39 -0500 (Thu, 22 Sep 2005)
New Revision: 2613
Modified:
branches/locking-changes/fs/ocfs2/aops.c
branches/locking-changes/fs/ocfs2/aops.h
branches/locking-changes/fs/ocfs2/file.c
Log:
don't set i_size as we zero extend, only in commit_write
o get_blocks now has to expect to get blocks anywhere beyond i_size
o rework walk_page_buffers helpers a little so caller can use generic or
block commit write
o setattr needs to not rely on zero_extend to set i_size
o zero extend needs to zero from i_size, not from its target size :)
Modified: branches/locking-changes/fs/ocfs2/aops.c
===================================================================
--- branches/locking-changes/fs/ocfs2/aops.c 2005-09-22 23:00:17 UTC (rev 2612)
+++ branches/locking-changes/fs/ocfs2/aops.c 2005-09-22 23:10:39 UTC (rev 2613)
@@ -131,17 +131,15 @@
static int ocfs2_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
- int err = -EIO;
- u64 p_blkno;
- u64 eof_blkno;
+ int err = 0;
+ u64 p_blkno, past_eof;
mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode,
(unsigned long long)iblock, bh_result, create);
- if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) {
+ if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE)
mlog(ML_NOTICE, "get_block on system inode 0x%p (%lu)\n",
inode, inode->i_ino);
- }
if (S_ISLNK(inode->i_mode)) {
/* this always does I/O for some reason. */
@@ -151,18 +149,15 @@
/* this can happen if another node truncs after our extend! */
spin_lock(&OCFS2_I(inode)->ip_lock);
- if (iblock >=
- ocfs2_clusters_to_blocks(inode->i_sb,
- OCFS2_I(inode)->ip_clusters)) {
- spin_unlock(&OCFS2_I(inode)->ip_lock);
+ if (iblock >= ocfs2_clusters_to_blocks(inode->i_sb,
+ OCFS2_I(inode)->ip_clusters))
err = -EIO;
- goto bail;
- }
spin_unlock(&OCFS2_I(inode)->ip_lock);
+ if (err)
+ goto bail;
err = ocfs2_extent_map_get_blocks(inode, iblock, 1, &p_blkno,
NULL);
-
if (err) {
mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, "
"%"MLFu64", NULL)\n", err, inode,
@@ -172,8 +167,6 @@
map_bh(bh_result, inode->i_sb, p_blkno);
- err = 0;
-
if (bh_result->b_blocknr == 0) {
err = -EIO;
mlog(ML_ERROR, "iblock = %llu p_blkno = %"MLFu64" "
@@ -181,20 +174,11 @@
p_blkno, OCFS2_I(inode)->ip_blkno);
}
- eof_blkno = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)) - 1;
- mlog(0, "Inode %lu, eof_blkno = %"MLFu64"\n", inode->i_ino, eof_blkno);
- /* We don't support holes, so I/O inside of i_size can't be
- * marked 'new' */
- if (iblock <= eof_blkno)
- goto bail;
- if (!create)
- goto bail;
- mlog_bug_on_msg(iblock != (eof_blkno + 1),
- "Inode %"MLFu64": I/O past tail of file! (i_size = "
- "%lld, iblock = %llu)\n", OCFS2_I(inode)->ip_blkno,
- i_size_read(inode), (unsigned long long) iblock);
+ past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
+ mlog(0, "Inode %lu, past_eof = %"MLFu64"\n", inode->i_ino, past_eof);
- set_buffer_new(bh_result);
+ if (create && (iblock >= past_eof))
+ set_buffer_new(bh_result);
bail:
if (err < 0)
@@ -284,83 +268,37 @@
return ret;
}
-/* Does the actual work of a commit_write. No cluster locks are
- * taken. If extending is nonzero then it's assumed that di_bh is non
- * null and that the caller has the proper cluster locks. */
-int ocfs2_commit_write_nolocks(struct file *file, struct page *page,
- unsigned from, unsigned to,
- struct buffer_head *di_bh,
- unsigned extending)
+ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
+ struct page *page,
+ unsigned from,
+ unsigned to)
{
- int ret;
- u64 size;
- ocfs2_dinode *di = NULL;
- ocfs2_journal_handle *handle = NULL;
- struct inode *inode = page->mapping->host;
ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ ocfs2_journal_handle *handle = NULL;
+ int ret = 0;
- if (extending) {
- handle = ocfs2_start_trans(osb, NULL,
- OCFS2_INODE_UPDATE_CREDITS);
- if (!handle) {
- ret = -ENOMEM;
- mlog_errno(ret);
- goto out;
- }
-
- /* Only do this on extending writes - we don't
- * hold the right cluster locks otherwise. */
- if (ocfs2_should_order_data(inode)) {
- ret = walk_page_buffers(handle->k_handle,
- page_buffers(page),
- from, to, NULL,
- ocfs2_journal_dirty_data);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
- }
-
- di = (ocfs2_dinode *) di_bh->b_data;
- /* Mark our buffer early. We'd rather catch this error
- * up here as opposed to after a successful
- * commit_write which would require us to set back
- * inode->i_size. */
- ret = ocfs2_journal_access(handle, inode, di_bh,
- OCFS2_JOURNAL_ACCESS_WRITE);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
- }
-
- ret = generic_commit_write(file, page, from, to);
- if (ret < 0) {
+ handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
+ if (!handle) {
+ ret = -ENOMEM;
mlog_errno(ret);
goto out;
}
- if (extending) {
- size = (u64) i_size_read(inode);
- /* ocfs2_mark_inode_dirty is too heavy to use here. */
- inode->i_blocks = ocfs2_align_bytes_to_sectors(size);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-
- di->i_size = cpu_to_le64(size);
- di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
- di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
-
- ret = ocfs2_journal_dirty(handle, di_bh);
- if (ret < 0) {
+ if (ocfs2_should_order_data(inode)) {
+ ret = walk_page_buffers(handle->k_handle,
+ page_buffers(page),
+ from, to, NULL,
+ ocfs2_journal_dirty_data);
+ if (ret < 0)
mlog_errno(ret);
- goto out;
- }
}
-
out:
- if (handle)
- ocfs2_commit_trans(handle);
- return ret;
+ if (ret) {
+ if (handle)
+ ocfs2_commit_trans(handle);
+ handle = ERR_PTR(ret);
+ }
+ return handle;
}
static int ocfs2_commit_write(struct file *file, struct page *page,
@@ -370,6 +308,7 @@
loff_t new_i_size;
struct buffer_head *di_bh = NULL;
struct inode *inode = page->mapping->host;
+ ocfs2_journal_handle *handle = NULL;
mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to);
@@ -401,15 +340,58 @@
goto out_unlock_meta;
}
- ret = ocfs2_commit_write_nolocks(file, page, from, to, di_bh,
- extending);
+ if (extending) {
+ handle = ocfs2_start_walk_page_trans(inode, page, from, to);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ handle = NULL;
+ goto out_unlock_data;
+ }
+
+ /* Mark our buffer early. We'd rather catch this error up here
+ * as opposed to after a successful commit_write which would
+ * require us to set back inode->i_size. */
+ ret = ocfs2_journal_access(handle, inode, di_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_commit;
+ }
+ }
+
+ /* might update i_size */
+ ret = generic_commit_write(file, page, from, to);
if (ret < 0) {
mlog_errno(ret);
- goto out_unlock_data;
+ goto out_commit;
}
+ if (extending) {
+ loff_t size = (u64) i_size_read(inode);
+ ocfs2_dinode *di = (ocfs2_dinode *)di_bh->b_data;
+
+ /* ocfs2_mark_inode_dirty is too heavy to use here. */
+ inode->i_blocks = ocfs2_align_bytes_to_sectors(size);
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+ di->i_size = cpu_to_le64(size);
+ di->i_ctime = di->i_mtime =
+ cpu_to_le64(inode->i_mtime.tv_sec);
+ di->i_ctime_nsec = di->i_mtime_nsec =
+ cpu_to_le32(inode->i_mtime.tv_nsec);
+
+ ret = ocfs2_journal_dirty(handle, di_bh);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_commit;
+ }
+ }
+
BUG_ON(extending && (i_size_read(inode) != new_i_size));
+out_commit:
+ if (handle)
+ ocfs2_commit_trans(handle);
out_unlock_data:
ocfs2_data_unlock(inode, 1);
out_unlock_meta:
Modified: branches/locking-changes/fs/ocfs2/aops.h
===================================================================
--- branches/locking-changes/fs/ocfs2/aops.h 2005-09-22 23:00:17 UTC (rev 2612)
+++ branches/locking-changes/fs/ocfs2/aops.h 2005-09-22 23:10:39 UTC (rev 2613)
@@ -25,9 +25,9 @@
int ocfs2_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to);
-int ocfs2_commit_write_nolocks(struct file *file, struct page *page,
- unsigned from, unsigned to,
- struct buffer_head *di_bh,
- unsigned extending);
+ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
+ struct page *page,
+ unsigned from,
+ unsigned to);
#endif /* OCFS2_FILE_H */
Modified: branches/locking-changes/fs/ocfs2/file.c
===================================================================
--- branches/locking-changes/fs/ocfs2/file.c 2005-09-22 23:00:17 UTC (rev 2612)
+++ branches/locking-changes/fs/ocfs2/file.c 2005-09-22 23:10:39 UTC (rev 2613)
@@ -623,7 +623,9 @@
{
struct address_space *mapping = inode->i_mapping;
struct page *page;
- unsigned long index, offset;
+ unsigned long index;
+ unsigned int offset;
+ ocfs2_journal_handle *handle = NULL;
int ret;
offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */
@@ -649,13 +651,25 @@
goto out_unlock;
}
- ret = ocfs2_commit_write_nolocks(NULL, page, offset, offset, di_bh, 1);
- if (ret < 0) {
- mlog_errno(ret);
- goto out_unlock;
+ if (ocfs2_should_order_data(inode)) {
+ handle = ocfs2_start_walk_page_trans(inode, page, offset,
+ offset);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ handle = NULL;
+ goto out_unlock;
+ }
}
- ret = 0;
+ /* must not update i_size! */
+ ret = block_commit_write(page, offset, offset);
+ if (ret < 0)
+ mlog_errno(ret);
+ else
+ ret = 0;
+
+ if (handle)
+ ocfs2_commit_trans(handle);
out_unlock:
unlock_page(page);
page_cache_release(page);
@@ -678,7 +692,7 @@
goto out;
}
- start_off = ocfs2_align_bytes_to_blocks(sb, zero_to_size);
+ start_off = ocfs2_align_bytes_to_blocks(sb, i_size_read(inode));
while (start_off < zero_to_size) {
ret = ocfs2_write_zero_page(inode, di_bh, start_off);
if (ret < 0) {
@@ -718,20 +732,19 @@
goto out;
}
- /* This will update i_size for us. */
ret = ocfs2_zero_extend(inode, new_i_size);
if (ret < 0) {
mlog_errno(ret);
goto out;
}
- } else {
- /* No allocation required, we just use this helper to
- * do a trivial update of i_size. */
- ret = ocfs2_simple_size_update(inode, di_bh, new_i_size);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
+ }
+
+ /* No allocation required, we just use this helper to
+ * do a trivial update of i_size. */
+ ret = ocfs2_simple_size_update(inode, di_bh, new_i_size);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
}
out:
More information about the Ocfs2-commits
mailing list