[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