[Ocfs2-commits] mfasheh commits r1609 - branches/dlm-glue/src

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Mon Nov 1 15:50:18 CST 2004


Author: mfasheh
Date: 2004-11-01 15:50:16 -0600 (Mon, 01 Nov 2004)
New Revision: 1609

Modified:
   branches/dlm-glue/src/alloc.c
   branches/dlm-glue/src/aops.c
   branches/dlm-glue/src/file.c
Log:
* fix up file_write to take an ex lock when needed and hold it across
  the extend. As a result, we get posix behavior for O_APPEND across the
  cluster.

* Take advantage of the new extend_file and take a lock only once
  during setattr. Fix truncate for the same thing.

* use ocfs_mark_inode_dirty for inode attribute changes.



Modified: branches/dlm-glue/src/alloc.c
===================================================================
--- branches/dlm-glue/src/alloc.c	2004-11-01 20:10:14 UTC (rev 1608)
+++ branches/dlm-glue/src/alloc.c	2004-11-01 21:50:16 UTC (rev 1609)
@@ -1595,6 +1595,14 @@
 			LOG_ERROR_STATUS(status);
 			goto bail;
 		}
+		/* Since we got our cluster lock from caller and we
+		 * don't add it to the handle: */
+		ocfs_set_inode_lock_trans(osb->journal, inode);
+
+		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+		status = ocfs_mark_inode_dirty(handle, inode, fe_bh);
+		if (status < 0)
+			LOG_ERROR_STATUS(status);
 	} else {
 		status = ocfs_extend_trans(handle, credits);
 		if (status < 0) {

Modified: branches/dlm-glue/src/aops.c
===================================================================
--- branches/dlm-glue/src/aops.c	2004-11-01 20:10:14 UTC (rev 1608)
+++ branches/dlm-glue/src/aops.c	2004-11-01 21:50:16 UTC (rev 1609)
@@ -125,7 +125,7 @@
 }
 
 static int ocfs_get_block(struct inode *inode, sector_t iblock,
-		struct buffer_head *bh_result, int create)
+			  struct buffer_head *bh_result, int create)
 {
 	int err = -EIO;
 	u64 vbo = 0;
@@ -492,7 +492,9 @@
  * called like this: dio->get_blocks(dio->inode, fs_startblk,
  * 					fs_count, map_bh, dio->rw == WRITE);
  */
-static int ocfs_direct_IO_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks, struct buffer_head *bh_result, int create)
+static int ocfs_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
+				     unsigned long max_blocks,
+				     struct buffer_head *bh_result, int create)
 {
 	int ret = -1;
 	int status;
@@ -500,11 +502,10 @@
 	u64 vbo_max; /* file offset, max_blocks from iblock */
 	u64 p_blkno;
 	int contig_blocks;
-	int set_new = 0; /* flag */
 	unsigned char blocksize_bits;
 
 	if (!inode || !bh_result) {
-		LOG_ERROR_STR("ocfs_direct_IO_get_blocks: inode or bh_result is null");
+		LOG_ERROR_STR("inode or bh_result is null");
 		return -EIO;
 	}
 
@@ -514,22 +515,17 @@
 	 * nicely aligned and of the right size, so there's no need
 	 * for us to check any of that. */
 
-	vbo_max = (u64)(iblock + max_blocks) << blocksize_bits;
+	vbo_max = ((u64)iblock + max_blocks) << blocksize_bits;
 
-	/* NOTE: create flag is set when we ?may? have to allocate some
-	   blocks for the file. */
-	if (create &&
-	    (vbo_max > ocfs2_clusters_to_bytes(osb->sb,
-					       OCFS_I(inode)->ip_clusters))) {
-		/* WARNING: How much do we really want to extend the file? */
-		status = ocfs_extend_file(osb, inode, vbo_max);
-		if (status < 0) {
-			status = -ENOSPC;
-			LOG_ERROR_STR("ocfs_direct_IO_get_blocks: failed to extend the file!");
-			goto bail;
-		}
-		set_new = 1;
+	spin_lock(&OCFS_I(inode)->ip_lock);
+	if ((iblock + max_blocks) >
+	    ocfs2_clusters_to_blocks(inode->i_sb,
+				     OCFS_I(inode)->ip_clusters)) {
+		spin_unlock(&OCFS_I(inode)->ip_lock);
+		err = -EIO;
+		goto bail;
 	}
+	spin_unlock(&OCFS_I(inode)->ip_lock);
 
 	/* This figure out the size of the next contiguous block, and
 	 * our logical offset */	
@@ -542,16 +538,7 @@
 		goto bail;
 	}
 
-	/* Do whatever we need to the buffer_head */
-	if (set_new) {
-		set_buffer_new(bh_result);
-		/* Do we really want to set bh_result->b_blocknr here too? */
-		bh_result->b_blocknr = p_blkno;
-	} else {
-		clear_buffer_new(bh_result);
-		/* is the last argument here correct? */
-		map_bh(bh_result, inode->i_sb, p_blkno);
-	}
+	map_bh(bh_result, inode->i_sb, p_blkno);
 
 	/* make sure we don't map more than max_blocks blocks here as
 	   that's all the kernel will handle at this point. */

Modified: branches/dlm-glue/src/file.c
===================================================================
--- branches/dlm-glue/src/file.c	2004-11-01 20:10:14 UTC (rev 1608)
+++ branches/dlm-glue/src/file.c	2004-11-01 21:50:16 UTC (rev 1609)
@@ -63,24 +63,6 @@
 					     ocfs2_dinode *fe,
 					     u64 new_size);
 
-static void ocfs_fe_set_attributes(ocfs2_dinode *fe, struct iattr *attr)
-{
-	if (attr->ia_valid & ATTR_SIZE)
-		fe->i_size = attr->ia_size;
-	if (attr->ia_valid & ATTR_UID)
-		fe->i_uid = attr->ia_uid;
-	if (attr->ia_valid & ATTR_GID)
-		fe->i_gid = attr->ia_gid;
-	if (attr->ia_valid & ATTR_MODE)
-		fe->i_mode = attr->ia_mode;
-	if (attr->ia_valid & ATTR_CTIME)
-		fe->i_ctime = ocfs_get_seconds(attr->ia_ctime);
-	if (attr->ia_valid & ATTR_ATIME)
-		fe->i_atime = ocfs_get_seconds(attr->ia_atime);
-	if (attr->ia_valid & ATTR_MTIME)
-		fe->i_mtime = ocfs_get_seconds(attr->ia_mtime);
-}
-
 int ocfs_sync_inode(struct inode *inode)
 {
 	filemap_fdatawrite(inode->i_mapping);
@@ -168,7 +150,7 @@
  *
  */
 static int ocfs_sync_file(struct file *file, struct dentry *dentry,
-		int datasync)
+			  int datasync)
 {
 	int err = 0;
 	journal_t *journal;
@@ -200,85 +182,8 @@
 	return (err < 0) ? -EIO : 0;
 }				/* ocfs_sync_file */
 
-/* ocfs_change_file_attrib()
- *
- */
-static int ocfs_change_file_attrib(ocfs_super *osb, struct iattr *attr,
-				   struct inode *inode)
-{
-	int status = 0;
-	ocfs2_dinode *fe = NULL;
-	struct buffer_head *bh = NULL;
-	ocfs_journal_handle *handle = NULL;
 
-	LOG_ENTRY ();
-
 #ifdef PURE_EVIL
-	if (evil_filename_check(EVIL_INODE, inode)) {
-		LOG_ERROR_STR("EVIL ATTRIB");
-	}
-#endif
-
-	handle = ocfs_alloc_handle(osb);
-	if (handle == NULL) {
-		LOG_ERROR_STATUS(status);
-		goto leave;
-	}
-
-	status = ocfs2_meta_lock(inode, handle, &bh, 1);
-	if (status < 0) {
-		if (status != -EINTR)
-			LOG_ERROR_STATUS (status);
-		goto leave;
-	}
-
-	/* Start a transaction - need a minimal amount of block credits (1) */
-	handle = ocfs_start_trans(osb, handle, OCFS_INODE_UPDATE_CREDITS);
-	if (handle == NULL) {
-		LOG_ERROR_STATUS(status);
-		goto leave;
-	}
-
-	fe = (ocfs2_dinode *) bh->b_data;
-
-	OCFS_ASSERT_RO(IS_VALID_FILE_ENTRY(fe));
-
-	status = ocfs_journal_access(handle, inode, bh, 
-				     OCFS_JOURNAL_ACCESS_WRITE);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto leave;
-	}
-
-	fe = (ocfs2_dinode *) bh->b_data;
-
-	fe->i_mtime = OCFS_CURRENT_TIME;
-
-	ocfs_fe_set_attributes(fe, attr);
-
-	status = ocfs_journal_dirty(handle, bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto leave;
-	}
-
-leave:
-	if (handle)
-		ocfs_commit_trans(handle);
-
-	if (bh != NULL)
-		brelse(bh);
-
-	if (status < 0)
-		if (status != -ENOSPC && status != -EINTR)
-			LOG_ERROR_STATUS (status);
-
-	LOG_EXIT_STATUS (status);
-	return status;
-}				/* ocfs_change_file_attrib */
-
-
-#ifdef PURE_EVIL
 int evil_filename_check(int type, void *ptr)
 {
 	struct file *filp = ptr;
@@ -318,7 +223,7 @@
 		size_t count, loff_t *ppos)
 {
 	int ret = 0;
-	int writingAtEOF = 0;
+	int extended = 0;
 	ocfs_super *osb = NULL;
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *inode = dentry->d_inode;
@@ -328,24 +233,15 @@
 	int do_direct_io = 0;
 	int sector_size;
 	int have_i_sem = 0;
+	int level = filp->f_flags & O_APPEND;
+	loff_t saved_ppos;
 
 	LOG_SET_CONTEXT(WRITE);
 
 	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u, '%*s')\n", filp, buf,
 			(unsigned int)count,
-			filp->f_dentry->d_name.len, filp->f_dentry->d_name.name);
-
-#ifdef PURE_EVIL
-	if (evil_filename_check(EVIL_DENTRY, dentry)) {
-		int z;
-		LOG_ERROR_ARGS("EVIL FILE_WRITE: count=%u, ppos=%llu, flags=%d\n", (unsigned int)count, *ppos, filp->f_flags);
-		for (z=0; z<(count<16?count:16); z++) {
-			printk("data[%d]=%02x ", z, ((char)buf[z]) & 0xff);
-		}
-		printk("\n");
-	}
-#endif
-
+			filp->f_dentry->d_name.len, 
+			filp->f_dentry->d_name.name);
 	/* happy write of zero bytes */
 	if (count == 0) {
 		ret = 0;
@@ -366,14 +262,26 @@
 		ret = -EIO;
 		goto bail;
 	}
-	
+
 	down(&inode->i_sem);
 	have_i_sem = 1;
 
+lock:
+	status = ocfs2_meta_lock(inode, NULL, NULL, level);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		ret = status;
+		goto bail;
+	}
+
+	/* work on a copy of ppos until we're sure that we won't have
+	 * to recalculate it due to relocking. */
+	saved_ppos = *ppos;
+
 	if (filp->f_flags & O_APPEND) {
 		LOG_TRACE_ARGS("O_APPEND: inode->i_size=%llu, ppos was %llu\n",
-			       inode->i_size, *ppos);
-		*ppos = inode->i_size;
+			       inode->i_size, saved_ppos);
+		saved_ppos = inode->i_size;
 
 		/* ugh, work around some applications which open
 		 * everything O_DIRECT + O_APPEND and really don't
@@ -385,38 +293,37 @@
 	if (filp->f_flags & O_DIRECT) {
 		/* anything special for o_direct? */
 		LOG_TRACE_STR ("O_DIRECT");
-		if (((*ppos) & (sector_size - 1)) || (count & (sector_size - 1)) || 
-		    ((unsigned long)buf & (sector_size - 1)) ) {
+		if ((saved_ppos & (sector_size - 1)) || 
+		    (count & (sector_size - 1)) || 
+		    ((unsigned long)buf & (sector_size - 1))) {
 			do_direct_io = 0;
 			filp->f_flags |= O_SYNC;
 		} else
 			do_direct_io = 1;
 	}
 
-	status = ocfs2_meta_lock(inode, NULL, NULL, 0);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		ret = status;
-		goto bail;
-	}
-
-	newsize = count + *ppos;
+	newsize = count + saved_ppos;
 	if (filp->f_flags & O_APPEND)
 		newsize = count + inode->i_size;
 
 	LOG_TRACE_ARGS ("ppos=%llu newsize=%llu cursize=%llu\n",
-			*ppos, newsize, inode->i_size);
+			saved_ppos, newsize, inode->i_size);
 
 	if (newsize > inode->i_size) {
-		writingAtEOF = 1;
+		if (!level) {
+			/* we want an extend, but need a higher
+			 * level cluster lock. */
+			LOG_TRACE_ARGS("inode %llu, had a PR, looping back "
+				       "for EX\n", OCFS_I(inode)->ip_blkno);
+			ocfs2_meta_unlock(inode, level);
+			level = 1;
+			goto lock;
+		}
+		extended = 1;
 
-		LOG_TRACE_ARGS
-		    ("Writing at EOF, will need more allocation: have=%llu, "
-		     "need=%llu\n",
-		     ocfs2_clusters_to_bytes(inode->i_sb,
-					     OCFS_I(inode)->ip_clusters),
-		     newsize);
-		ocfs2_meta_unlock(inode, 0);
+		LOG_TRACE_ARGS("Writing at EOF, will need more allocation: "
+			       "i_size=%llu, need=%llu\n",
+			       inode->i_size, newsize);
 
 		status = ocfs_extend_file(osb, inode, newsize);
 		if (status < 0) {
@@ -428,23 +335,24 @@
 				ret = -ENOSPC;
 			} else
 				ret = status;
+
+			ocfs2_meta_unlock(inode, level);
 			goto bail;
 		}
-		status = ocfs2_meta_lock(inode, NULL, NULL, 0);
-		if (status < 0) {
-			LOG_ERROR_STATUS(status);
-			ret = status;
-			goto bail;
-		}
 	}
 
+	/* we've got whatever cluster lock is appropriate now, so we
+	 * can stuff *ppos back. */
+	*ppos = saved_ppos;
+
 	if (!do_direct_io) {
 		status = ocfs2_data_lock(inode, 1);
 		if (status < 0) {
-			LOG_ERROR_STATUS(status);
+			if (status != -EINTR)
+				LOG_ERROR_STATUS(status);
 			ret = status;
 
-			ocfs2_meta_unlock(inode, 0);
+			ocfs2_meta_unlock(inode, level);
 			goto bail;
 		}
 	}
@@ -479,7 +387,7 @@
 	if (!do_direct_io)
 		ocfs2_data_unlock(inode, 1);
 
-	if (writingAtEOF) {
+	if (extended) {
 		LOG_TRACE_STR
 		    ("Generic_file_write ok, asking for OIN update now");
 		inode->i_size = newsize;
@@ -500,7 +408,7 @@
 				LOG_ERROR_ARGS("Unable to pre-zero extension of inode (%d)", status);
 		}
 	}
-	ocfs2_meta_unlock(inode, 0);
+	ocfs2_meta_unlock(inode, level);
 
 bail:
 	if (have_i_sem)
@@ -572,7 +480,8 @@
 	if (!do_direct_io) {
 		status = ocfs2_data_lock(inode, 0);
 		if (status < 0) {
-			LOG_ERROR_STATUS(status);
+			if (status != -EINTR)
+				LOG_ERROR_STATUS(status);
 			/* is this ret code correct? */
 			ret = status;
 			goto bail;
@@ -655,9 +564,10 @@
 
 	grow = new_i_size > inode->i_size;
 	inode->i_size = new_i_size;
-	OCFS_SET_INODE_TIME(inode, i_mtime, OCFS_CURRENT_TIME);
 	inode->i_blocks = (new_i_size + sb->s_blocksize - 1) 
 		>> sb->s_blocksize_bits;
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
 	status = ocfs_mark_inode_dirty(handle, inode, fe_bh);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
@@ -723,16 +633,12 @@
 	LOG_ENTRY_ARGS("(inode = %llu, new_i_size = %llu\n", 
 		       OCFS_I(inode)->ip_blkno, new_i_size);
 
-	handle = ocfs_alloc_handle(osb);
-	if (handle == NULL) {
-		LOG_ERROR_STATUS (status = -ENOMEM);
-		goto bail;
-	}
+	ocfs_truncate_inode_pages(inode, new_i_size);
 
-	status = ocfs2_meta_lock(inode, handle, &fe_bh, 1);
+	status = ocfs_read_block(osb, OCFS_I(inode)->ip_blkno, &fe_bh,
+				 OCFS_BH_CACHED, inode);
 	if (status < 0) {
-		if (status != -EINTR)
-			LOG_ERROR_STATUS (status);
+		LOG_ERROR_STATUS(status);
 		goto bail;
 	}
 
@@ -763,13 +669,17 @@
 			       "truncate\n", fe->i_clusters);
 		/* No allocation change is required, so lets fast path
 		 * this truncate. */	
-		handle = ocfs_start_trans(osb, handle, 
+		handle = ocfs_start_trans(osb, NULL, 
 					  OCFS_INODE_UPDATE_CREDITS);
 		if (handle == NULL) {
 			LOG_ERROR_STATUS (status = -ENOMEM);
 			goto bail;
 		}
 
+		/* Since we got our cluster lock from caller and we
+		 * don't add it to the handle: */
+		ocfs_set_inode_lock_trans(osb->journal, inode);
+
 		status = ocfs_set_inode_size(handle, inode, fe_bh, new_i_size);
 		if (status < 0)
 			LOG_ERROR_STATUS (status);
@@ -779,7 +689,8 @@
 	/* This forces other nodes to sync and drop their pages */
 	status = ocfs2_data_lock(inode, 1);
 	if (status < 0) {
-		LOG_ERROR_STATUS(status);
+		if (status != -EINTR)
+			LOG_ERROR_STATUS(status);
 		goto bail;
 	}
 	ocfs2_data_unlock(inode, 1);
@@ -975,7 +886,7 @@
 	/* TODO: We will keep a small history of allocs on the filp
 	 * and calculate a reasonable overalloc based on that data
 	 * here. */
-	return(0);
+	return 0;
 }
 
 /* ocfs_extend_file()
@@ -1014,21 +925,20 @@
 		goto leave;
 	}
 
-	status = ocfs2_meta_lock(inode, handle, &bh, 1);
+	status = ocfs_read_block(osb, OCFS_I(inode)->ip_blkno, &bh,
+				 OCFS_BH_CACHED, inode);
 	if (status < 0) {
-		if (status != -EINTR)
-			LOG_ERROR_STATUS (status);
+		LOG_ERROR_STATUS(status);
 		goto leave;
 	}
 
 	fe = (ocfs2_dinode *) bh->b_data;
 	OCFS_ASSERT(IS_VALID_FILE_ENTRY(fe));
-	OCFS_ASSERT(new_i_size >= fe->i_size);
+	OCFS_ASSERT(inode->i_size == fe->i_size);
+	OCFS_ASSERT(new_i_size >= inode->i_size);
 
-	if (fe->i_size == new_i_size) {
-		OCFS_ASSERT(inode->i_size == new_i_size);
-		goto leave;
-	}
+	if (inode->i_size == new_i_size)
+  		goto leave;
 
 	clusters_to_add = ocfs2_clusters_for_bytes(osb->sb, new_i_size) 
 		- fe->i_clusters;
@@ -1038,14 +948,14 @@
 		       OCFS_I(inode)->ip_blkno, new_i_size, inode->i_size, 
 		       fe->i_clusters, clusters_to_add);
 
-	if (!clusters_to_add) 
+	if (!clusters_to_add)
 		goto do_start_trans;
 
 	overalloc_bits = 0;
 	if (!skip_overalloc) {
-		overalloc_bits = ocfs_calc_overalloc_bits(osb, 
-							  NULL, 
-							  fe, 
+		overalloc_bits = ocfs_calc_overalloc_bits(osb,
+							  NULL,
+							  fe,
 							  new_i_size);
 		clusters_to_add += overalloc_bits;
 		skip_overalloc = 1;
@@ -1095,6 +1005,9 @@
 		goto leave;
 	}
 
+	/* Since we got our cluster lock from caller and we don't add
+	 * it to the handle: */
+	ocfs_set_inode_lock_trans(osb->journal, inode);
 restarted_transaction:
 	/* reserve a write to the file entry early on - that we if we
 	 * run out of credits in the allocation path, we can still
@@ -1173,14 +1086,14 @@
 		fe->i_size = ocfs2_clusters_to_bytes(osb->sb, fe->i_clusters);
 	else
 		fe->i_size = new_i_size;
-#warning "is there a reason why we don't update i_blocks here?"
+
 	LOG_TRACE_ARGS("fe: i_clusters = %u, i_size=%llu\n", 
 		       fe->i_clusters, fe->i_size);
 
 	LOG_TRACE_ARGS("inode: ip_clusters=%u, i_size=%llu\n",
 		       OCFS_I(inode)->ip_clusters, inode->i_size);
 
-	fe->i_mtime = OCFS_CURRENT_TIME;
+	fe->i_ctime = fe->i_mtime = OCFS_CURRENT_TIME;
 
 	status = ocfs_journal_dirty(handle, bh);
 	if (status < 0) {
@@ -1223,33 +1136,18 @@
  */
 int ocfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
+	int status = 0;
+	int unlock = 0;
+	u64 newsize;
 	struct inode *inode = dentry->d_inode;
-	int error = 0;
-	__u64 newsize;
-	int status;
-	ocfs_super *osb = NULL;
 	struct super_block *sb = inode->i_sb;
+	ocfs_super *osb = OCFS2_SB(sb);
+	struct buffer_head *bh = NULL;
+	ocfs_journal_handle *handle = NULL;
 
-	LOG_SET_CONTEXT(SETATTR);
-
 	LOG_ENTRY_ARGS ("(0x%p, '%*s')\n", dentry,
 			dentry->d_name.len, dentry->d_name.name);
 
-	osb = OCFS_SB(inode->i_sb);
-
-#ifdef PURE_EVIL
-	if (evil_filename_check(EVIL_DENTRY, dentry)) {
-		LOG_ERROR_ARGS("EVIL SETATTR\n");
-	}
-#endif
-
-	if (!dentry->d_parent || !dentry->d_parent->d_inode) {
-		LOG_ERROR_STR ("bad inode or root inode");
-		goto bail;
-	}
-
-	newsize = attr->ia_size;
-
 	if (attr->ia_valid & ATTR_MODE)
 		LOG_TRACE_ARGS ("mode change: %d\n", attr->ia_mode);
 	if (attr->ia_valid & ATTR_UID)
@@ -1261,33 +1159,39 @@
 	if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME))
 		LOG_TRACE_STR ("time change...");
 
-	if (!(attr->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME |
-				ATTR_SIZE | ATTR_GID | ATTR_UID | ATTR_MODE))) {
-		LOG_TRACE_STR
-		    ("can only change mode, uid, gid, size and time.  exiting!");
-		goto bail;
+#define OCFS2_VALID_ATTRS (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME | ATTR_SIZE \
+			   | ATTR_GID | ATTR_UID | ATTR_MODE)
+	if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) {
+		LOG_TRACE_ARGS("can't handle attrs: 0x%x\n", attr->ia_valid);
+		return 0;
 	}
 
-	error = inode_change_ok (inode, attr);
-	if (error)
+	status = inode_change_ok (inode, attr);
+	if (status)
+		return status;
+
+	newsize = attr->ia_size;
+
+	status = ocfs2_meta_lock(inode, NULL, &bh, 1);
+	if (status < 0) {
+		if (status != -EINTR)
+			LOG_ERROR_STATUS(status);
 		goto bail;
+	}
+	unlock = 1;
 
-	/* get the file and parent offsets, and the file oin if present */
-	if (attr->ia_valid & ATTR_SIZE) {
-		if (inode->i_size > newsize) {
-			ocfs_truncate_inode_pages(inode, newsize);
-			status = ocfs_truncate_file(osb, newsize, 
-						    inode);
-		} else {
+	if (attr->ia_valid & ATTR_SIZE &&
+	    newsize != inode->i_size) {
+		if (inode->i_size > newsize)
+			status = ocfs_truncate_file(osb, newsize, inode);
+		else
 			status = ocfs_extend_file(osb, inode, newsize);
-		}
 		if (status < 0) {
 			if (status != -EINTR)
-				LOG_ERROR_STATUS (status);
-			error = -ENOSPC;
+				LOG_ERROR_STATUS(status);
+			status = -ENOSPC;
 			goto bail;
 		}
-
 		spin_lock(&OCFS_I(inode)->ip_lock);
 		inode->i_size = newsize;
 		inode->i_blocks = (newsize + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
@@ -1303,20 +1207,42 @@
 		}
 	}
 
-	status = ocfs_change_file_attrib(osb, attr, inode);
+	handle = ocfs_start_trans(osb, NULL, OCFS_INODE_UPDATE_CREDITS);
+	if (handle == NULL) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	/* Ok, this is the last transaction we'll do for a setattr so
+	 * just add our lock to the handle and let commit_trans deal
+	 * with it. */
+	status = ocfs_handle_add_lock(handle, inode);
+	if (status < 0)
+		LOG_ERROR_STATUS(status);
+	unlock = 0;
+
+	status = inode_setattr (inode, attr);
 	if (status < 0) {
-		if (status != -EINTR)
-			LOG_ERROR_STATUS (status);
-		error = -EIO;
+		LOG_ERROR_STATUS(status);
 		goto bail;
 	}
-	error = inode_setattr (inode, attr);
 
+	status = ocfs_mark_inode_dirty(handle, inode, bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
 bail:
-	LOG_EXIT_INT (error);
+	if (handle)
+		ocfs_commit_trans(handle);
+	if (unlock)
+		ocfs2_meta_unlock(inode, 1);
+	if (bh)
+		brelse(bh);
 
-	LOG_CLEAR_CONTEXT();
-	return error;
+	LOG_EXIT_STATUS(status);
+	return status;
 }				/* ocfs_setattr */
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)



More information about the Ocfs2-commits mailing list