[Ocfs2-commits] mfasheh commits r1922 - trunk/fs/ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Mon Feb 28 18:20:51 CST 2005


Author: mfasheh
Signed-off-by: zab
Date: 2005-02-28 18:20:50 -0600 (Mon, 28 Feb 2005)
New Revision: 1922

Modified:
   trunk/fs/ocfs2/file.c
   trunk/fs/ocfs2/file.h
Log:
* deal with out of space errors more gracefully.

Signed-off-by: zab



Modified: trunk/fs/ocfs2/file.c
===================================================================
--- trunk/fs/ocfs2/file.c	2005-03-01 00:06:48 UTC (rev 1921)
+++ trunk/fs/ocfs2/file.c	2005-03-01 00:20:50 UTC (rev 1922)
@@ -66,6 +66,11 @@
 					     ocfs2_dinode *fe,
 					     u64 new_size);
 
+static int ocfs_extend_file(ocfs_super *osb, 
+			    struct inode *inode,
+			    u64 new_i_size,
+			    u64 *bytes_extended);
+
 int ocfs_sync_inode(struct inode *inode)
 {
 	filemap_fdatawrite(inode->i_mapping);
@@ -174,6 +179,16 @@
 	return (err < 0) ? -EIO : 0;
 }				/* ocfs_sync_file */
 
+static void ocfs2_update_inode_size(struct inode *inode,
+				    u64 new_size)
+{
+	struct super_block *sb = inode->i_sb;
+
+	i_size_write(inode, new_size);
+	inode->i_blocks = (new_size + sb->s_blocksize - 1) >> 
+		sb->s_blocksize_bits;
+}
+
 /*
  * ocfs_file_write()
  * Linux 2.6 TODO: Remove all O_DIRECT conditionals here, they are no longer
@@ -188,8 +203,7 @@
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *inode = dentry->d_inode;
 	int status;
-	u64 newsize;
-	struct super_block *sb = inode->i_sb;
+	u64 newsize, bytes_added = 0;
 	int do_direct_io = 0;
 	int sector_size;
 	int have_i_sem = 0;
@@ -305,20 +319,34 @@
 			       "i_size=%llu, need=%llu\n",
 			       i_size_read(inode), newsize);
 
-		status = ocfs_extend_file(osb, inode, newsize);
-		if (status < 0) {
+		/* If we extend AT ALL here then we update our state
+		 * and continue the write call, regardless of error --
+		 * this is basically a short write. */
+		status = ocfs_extend_file(osb, inode, newsize, &bytes_added);
+		if (status < 0 && (!bytes_added)) {
 			if (status != -EINTR && status != -ENOSPC) {
 				LOG_ERROR_STATUS (status);
-				LOG_ERROR_ARGS ("Failed to extend file from "
-						"%llu to %llu",
-			     		*ppos, newsize);
-				ret = -ENOSPC;
-			} else
-				ret = status;
-
-			ocfs2_meta_unlock(inode, level);
+				LOG_ERROR_ARGS("Failed to extend inode %llu "
+					       "from %llu to %llu",
+						OCFS_I(inode)->ip_blkno,
+					       *ppos, newsize);
+			}
+			ret = status;
 			goto bail_unlock;
 		}
+
+		/* We need to recalulate newsize and count according
+		 * to what extend could give us. If we got the whole
+		 * extend then this doesn't wind up changing the
+		 * values. */
+		newsize = i_size_read(inode) + bytes_added;
+		count = newsize - saved_ppos;
+
+		if (status < 0 && status != -ENOSPC && status != -EINTR)
+			LOG_ERROR_ARGS("status return of %d extending inode "
+				       "%llu\n", status,
+				       OCFS_I(inode)->ip_blkno);
+		status = 0;
 	}
 
 	/* we've got whatever cluster lock is appropriate now, so we
@@ -332,6 +360,14 @@
 				LOG_ERROR_STATUS(status);
 			ret = status;
 
+			/* The write context stuff needs to be updated
+			 * to understand that we haven't locked for
+			 * data so that we can just jump down to the
+			 * generic zeroing code here instead. */
+			if (extended) {
+				ocfs2_update_inode_size(inode, newsize);
+				OCFS_I(inode)->ip_mmu_private = newsize;
+			}
 			ocfs2_meta_unlock(inode, level);
 			goto bail_unlock;
 		}
@@ -347,7 +383,7 @@
 	if (ret < 0) {
 		if (ret != -EINTR)
 			LOG_ERROR_STATUS(ret);
-		goto bail_unlock;
+		goto bail_zero;
 	}
 
 	down_read(&OCFS_I(inode)->ip_alloc_sem);
@@ -378,11 +414,12 @@
 #endif
 	up_read(&OCFS_I(inode)->ip_alloc_sem);
 
+bail_zero:
 	if (extended) {
 		LOG_TRACE_STR
 		    ("Generic_file_write ok, asking for OIN update now");
-		i_size_write(inode, newsize);
-		inode->i_blocks = (newsize + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+		ocfs2_update_inode_size(inode, newsize);
+
 		if (do_direct_io) {
 			/*
 			 * This leaves dirty data in holes.
@@ -867,10 +904,15 @@
  *
  * Ok, this function is heavy on the goto's - we need to clean it up a
  * bit.
+ *
+ * *bytes_extended is a measure of how much was added to
+ * dinode->i_size, NOT how much allocated was actually added to the
+ * file. It will always be correct, even when we return an error.
  */
-int ocfs_extend_file(ocfs_super *osb, 
-		     struct inode *inode,
-		     u64 new_i_size)
+static int ocfs_extend_file(ocfs_super *osb, 
+			    struct inode *inode,
+			    u64 new_i_size,
+			    u64 *bytes_extended)
 {
 	int status = 0;
 	int restart_func = 0;
@@ -879,6 +921,7 @@
 	int credits, num_free_extents;
 	unsigned int overalloc_bits = 0;
 	u32 clusters_to_add;
+	u64 new_fe_size;
 	struct buffer_head *bh = NULL;
 	ocfs2_dinode *fe;
 	ocfs_journal_handle *handle = NULL;
@@ -888,6 +931,8 @@
 
 	LOG_ENTRY_ARGS("(new_i_size=%llu)\n", new_i_size);
 
+	*bytes_extended = 0;
+
 	/* setattr sometimes calls us like this. */
 	if (new_i_size == 0)
 		goto leave;
@@ -908,7 +953,7 @@
 
 	fe = (ocfs2_dinode *) bh->b_data;
 	OCFS_ASSERT(IS_VALID_FILE_ENTRY(fe));
-	OCFS_ASSERT(i_size_read(inode) == fe->i_size);
+	OCFS_ASSERT(i_size_read(inode) == (fe->i_size - *bytes_extended));
 	OCFS_ASSERT(new_i_size >= i_size_read(inode));
 
 	if (i_size_read(inode) == new_i_size)
@@ -1019,11 +1064,13 @@
 		} else {
 			OCFS_ASSERT(why == RESTART_TRANS);
 
+			new_fe_size = ocfs2_clusters_to_bytes(osb->sb,
+							      fe->i_clusters);
+			*bytes_extended += new_fe_size - fe->i_size;
 			/* update i_size in case we crash after the
 			 * extend_trans */
-			fe->i_size =
-				ocfs2_clusters_to_bytes(osb->sb,
-							fe->i_clusters);
+			fe->i_size = new_fe_size;
+
 			fe->i_mtime = OCFS_CURRENT_TIME;
 
 			status = ocfs_journal_dirty(handle, bh);
@@ -1056,11 +1103,13 @@
 no_alloc:
 	/* this may not be the end of our allocation so only update
 	 * i_size to what's appropriate. */
-	if (new_i_size > ocfs2_clusters_to_bytes(osb->sb, fe->i_clusters))
-		fe->i_size = ocfs2_clusters_to_bytes(osb->sb, fe->i_clusters);
-	else
-		fe->i_size = new_i_size;
+	new_fe_size = ocfs2_clusters_to_bytes(osb->sb, fe->i_clusters);
+	if (new_i_size < new_fe_size)
+		new_fe_size = new_i_size;
 
+	*bytes_extended += new_fe_size - fe->i_size;
+	fe->i_size = new_fe_size;
+
 	LOG_TRACE_ARGS("fe: i_clusters = %u, i_size=%llu\n", 
 		       fe->i_clusters, fe->i_size);
 
@@ -1100,6 +1149,7 @@
 		restart_func = 0;
 		goto restart_all;
 	}
+
 	LOG_EXIT_STATUS (status);
 	return status;
 }				/* ocfs_extend_file */
@@ -1112,7 +1162,7 @@
 {
 	int status = 0;
 	int unlock = 0;
-	u64 newsize;
+	u64 newsize, bytes_added;
 	struct inode *inode = dentry->d_inode;
 	struct super_block *sb = inode->i_sb;
 	ocfs_super *osb = OCFS2_SB(sb);
@@ -1156,19 +1206,32 @@
 
 	if (attr->ia_valid & ATTR_SIZE &&
 	    newsize != i_size_read(inode)) {
+		bytes_added = 0;
+
 		if (i_size_read(inode) > newsize)
 			status = ocfs_truncate_file(osb, newsize, inode);
 		else
-			status = ocfs_extend_file(osb, inode, newsize);
-		if (status < 0) {
+			status = ocfs_extend_file(osb, inode, newsize,
+						  &bytes_added);
+		if (status < 0 && (!bytes_added)) {
 			if (status != -EINTR && status != -ENOSPC)
 				LOG_ERROR_STATUS(status);
 			status = -ENOSPC;
 			goto bail;
 		}
+
+		/* partial extend, we continue with what we've got. */
+		if (status < 0 && status != -ENOSPC && status != -EINTR)
+			LOG_ERROR_ARGS("status return of %d extending inode "
+				       "%llu\n", status,
+				       OCFS_I(inode)->ip_blkno);
+		status = 0;
+
+		newsize = bytes_added + i_size_read(inode);
+		if (bytes_added)
+			ocfs2_update_inode_size(inode, newsize);
+
 		spin_lock(&OCFS_I(inode)->ip_lock);
-		i_size_write(inode, newsize);
-		inode->i_blocks = (newsize + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 		if (OCFS_I(inode)->ip_flags & OCFS_INODE_OPEN_DIRECT) {
 			/* This is a total broken hack for O_DIRECT crack */
 			OCFS_I(inode)->ip_mmu_private = i_size_read(inode);

Modified: trunk/fs/ocfs2/file.h
===================================================================
--- trunk/fs/ocfs2/file.h	2005-03-01 00:06:48 UTC (rev 1921)
+++ trunk/fs/ocfs2/file.h	2005-03-01 00:20:50 UTC (rev 1922)
@@ -43,9 +43,6 @@
 			   struct _ocfs2_alloc_context *data_ac,
 			   struct _ocfs2_alloc_context *meta_ac,
 			   enum ocfs2_alloc_restarted *reason);
-int ocfs_extend_file(ocfs_super *osb, 
-		     struct inode *inode,
-		     u64 new_i_size);
 int ocfs_setattr(struct dentry *dentry, struct iattr *attr);
 int ocfs_sync_inode(struct inode *inode);
 



More information about the Ocfs2-commits mailing list