[Ocfs2-commits] mfasheh commits r1491 - branches/dlm-changes/src

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Fri Sep 24 18:42:25 CDT 2004


Author: mfasheh
Date: 2004-09-24 18:42:23 -0500 (Fri, 24 Sep 2004)
New Revision: 1491

Modified:
   branches/dlm-changes/src/namei.c
   branches/dlm-changes/src/namei.h
Log:
* move ocfs_match into namei.h as dir.c wants it now.

* take directory locks outside of transactions. We do this with a prepare / 
  insert api. Prepare is responsible for finding a spot (and extending to 
  create a new one if need be) and insert actually makes the changes.



Modified: branches/dlm-changes/src/namei.c
===================================================================
--- branches/dlm-changes/src/namei.c	2004-09-24 23:39:22 UTC (rev 1490)
+++ branches/dlm-changes/src/namei.c	2004-09-24 23:42:23 UTC (rev 1491)
@@ -58,6 +58,7 @@
 #include "inode.h"
 #include "lockres.h"
 #include "namei.h"
+#include "suballoc.h"
 #include "util.h"
 #include "vote.h"
 
@@ -71,26 +72,35 @@
 				  const char *name, int namelen, 
 				  unsigned long offset, 
 				  struct ocfs2_dir_entry **res_dir);
+
 static int ocfs_delete_entry(ocfs_journal_handle *handle,
 			     struct inode *dir, 
 			     struct ocfs2_dir_entry *de_del, 
 			     struct buffer_head *bh);
-static int __ocfs_add_entry(ocfs_journal_handle *handle,
-			    struct inode *dir,
-			    const char *name, int namelen, 
-			    struct inode *inode, u64 blkno, 
-			    struct buffer_head *parent_fe_bh);
-static inline int ocfs_match(int len, const char *const name,
-			     struct ocfs2_dir_entry *de);
 
+static int __ocfs_add_entry (ocfs_journal_handle *handle, struct inode *dir,
+			     const char *name, int namelen, 
+			     struct inode *inode, u64 blkno, 
+			     struct buffer_head *parent_fe_bh, 
+			     struct buffer_head *insert_bh);
+
 static int ocfs_mknod_locked(ocfs_super *osb, struct inode *dir, 
 			     struct dentry *dentry, int mode, 
 			     dev_t dev,
 			     struct buffer_head **new_fe_bh, 
 			     struct buffer_head *parent_fe_bh,
 			     ocfs_journal_handle *handle,
-			     struct inode *inode);
+			     struct inode *inode,
+			     ocfs2_alloc_context *inode_ac,
+			     struct buffer_head *de_bh);
 
+static int ocfs_fill_new_dir(ocfs_super *osb, 
+			     ocfs_journal_handle *handle,
+			     struct inode *parent, 
+			     struct inode *inode,
+			     struct buffer_head *fe_bh,
+			     ocfs2_alloc_context *data_ac);
+
 static int ocfs_double_lock(ocfs_super *osb,
 			    ocfs_journal_handle *handle,
 			    __u32 type1, __u32 flags1, 
@@ -100,8 +110,15 @@
 			    struct buffer_head **bh2,
 		     	    struct inode *inode2);
 
+static int ocfs_prepare_orphan_dir(ocfs_super *osb, 
+				   ocfs_journal_handle *handle,
+				   struct inode *inode,
+				   char **ret_name,
+				   struct buffer_head **de_bh);
+
 static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle,
-			   struct inode *inode, ocfs2_dinode *fe);
+			   struct inode *inode, ocfs2_dinode *fe, 
+			   char *name, struct buffer_head *de_bh);
 
 static int ocfs_create_symlink_data(ocfs_super *osb, 
 				    ocfs_journal_handle *handle, 
@@ -111,11 +128,12 @@
 static inline int ocfs_add_entry(ocfs_journal_handle *handle, 
 				 struct dentry *dentry, 
 				 struct inode *inode, u64 blkno, 
-				 struct buffer_head *parent_fe_bh) 
+				 struct buffer_head *parent_fe_bh,
+				 struct buffer_head *insert_bh) 
 {
 	return(__ocfs_add_entry(handle, dentry->d_parent->d_inode, 
 				dentry->d_name.name, dentry->d_name.len, 
-				inode, blkno, parent_fe_bh));
+				inode, blkno, parent_fe_bh, insert_bh));
 }
 
 /*
@@ -169,13 +187,82 @@
 bail:
 	if (dirent_bh)
 		brelse(dirent_bh);
-	
+
 	LOG_EXIT_PTR (ret);
 
 	LOG_CLEAR_CONTEXT();
 	return ret;
 }				/* ocfs_lookup */
 
+static int ocfs_fill_new_dir(ocfs_super *osb, 
+			     ocfs_journal_handle *handle,
+			     struct inode *parent, 
+			     struct inode *inode,
+			     struct buffer_head *fe_bh,
+			     ocfs2_alloc_context *data_ac)
+{
+	int status;
+	struct buffer_head *new_bh = NULL;
+	struct ocfs2_dir_entry *de = NULL;
+
+	LOG_ENTRY();
+
+	status = ocfs_do_extend_dir(osb->sb, handle, inode, fe_bh,
+				    data_ac, NULL, &new_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	set_buffer_uptodate(new_bh);
+	SET_BH_SEQNUM(inode, new_bh);
+	status = ocfs_journal_access(handle, new_bh, 
+				     OCFS_JOURNAL_ACCESS_CREATE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+	memset(new_bh->b_data, 0, osb->sb->s_blocksize);
+
+	de = (struct ocfs2_dir_entry *) new_bh->b_data;
+	de->inode = cpu_to_le64(OCFS_I(inode)->ip_blkno);
+	de->name_len = 1;
+	de->rec_len =
+		cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
+	strcpy (de->name, ".");
+	ocfs_set_de_type(de, S_IFDIR);
+	de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+	de->inode = cpu_to_le64(OCFS_I(parent)->ip_blkno);
+	de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize -
+				  OCFS2_DIR_REC_LEN(1));
+	de->name_len = 2;
+	strcpy (de->name, "..");
+	ocfs_set_de_type(de, S_IFDIR);
+
+	status = ocfs_journal_dirty(handle, new_bh);	
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	inode->i_size = inode->i_sb->s_blocksize;
+	inode->i_nlink = 2;
+	inode->i_blocks = 1;
+	status = ocfs_mark_inode_dirty(handle, inode, fe_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	status = 0;
+bail:
+	if (new_bh)
+		brelse(new_bh);
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+}
+
 static int ocfs_mknod(struct inode *dir, struct dentry *dentry,
 		int mode, dev_t dev)
 {
@@ -187,7 +274,10 @@
 	ocfs2_dinode *fe = NULL;
 	ocfs2_dinode *dirfe;
 	struct buffer_head *new_fe_bh = NULL;
+	struct buffer_head *de_bh = NULL;
 	struct inode *inode = NULL;
+	ocfs2_alloc_context *inode_ac = NULL;
+	ocfs2_alloc_context *data_ac = NULL;
 
 	LOG_SET_CONTEXT(MKNOD);
 
@@ -251,6 +341,32 @@
 		goto leave;
 	}
 
+	/* get a spot inside the dir. */
+	status = ocfs_prepare_dir_for_insert(osb, dir, parent_fe_bh, 
+					     dentry->d_name.name, 
+					     dentry->d_name.len, &de_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	/* reserve an inode spot */
+	status = ocfs_reserve_new_inode(osb, handle, &inode_ac);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
+	/* are we making a directory? If so, reserve a cluster for his
+	 * 1st extent. */
+	if (S_ISDIR(mode)) {
+		status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto leave;
+		}
+	}
+
 	handle = ocfs_start_trans(osb, handle, OCFS_MKNOD_CREDITS);
 	if (handle == NULL) {
 		LOG_ERROR_STATUS (status = -ENOMEM);
@@ -259,7 +375,8 @@
 
 	/* do the real work now. */
 	status = ocfs_mknod_locked(osb, dir, dentry, mode, dev,
-				   &new_fe_bh, parent_fe_bh, handle, inode);
+				   &new_fe_bh, parent_fe_bh, handle, 
+				   inode, inode_ac, de_bh);
 	if (status < 0) {
 		if (status != -EINTR)
 			LOG_ERROR_STATUS(status);
@@ -283,50 +400,19 @@
 
 	status = ocfs_update_lockres(osb, new_fe_bh, inode, 0);
 	if (S_ISDIR (mode)) {
-		struct buffer_head *newdirbh = NULL;
-		int retval = 0;
-		struct ocfs2_dir_entry *de = NULL;
-
-		newdirbh = ocfs_bread (handle, inode, 0, 1, &retval, 0);
-		if (!newdirbh) {
-			LOG_ERROR_STATUS(status = retval);
-			goto leave;
-		}
-		status = ocfs_journal_access(handle, newdirbh, OCFS_JOURNAL_ACCESS_WRITE);
+		status = ocfs_fill_new_dir(osb, handle, dir, inode, 
+					   new_fe_bh, data_ac);
 		if (status < 0) {
-			brelse(newdirbh);
 			LOG_ERROR_STATUS(status);
 			goto leave;
 		}
-		de = (struct ocfs2_dir_entry *) newdirbh->b_data;
-		de->inode = cpu_to_le64(fe->i_blkno);
-		fe = NULL;
-		de->name_len = 1;
-		de->rec_len =
-			cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
-		strcpy (de->name, ".");
-		ocfs_set_de_type(de, S_IFDIR);
-		de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
-		de->inode = cpu_to_le64(OCFS_I(dir)->ip_blkno);
-		de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize -
-					  OCFS2_DIR_REC_LEN(1));
-		de->name_len = 2;
-		strcpy (de->name, "..");
-		ocfs_set_de_type(de, S_IFDIR);
-		inode->i_nlink = 2;
-		status = ocfs_journal_dirty(handle, newdirbh);
-		brelse (newdirbh);
+
+		status = ocfs_journal_access(handle, parent_fe_bh, 
+					     OCFS_JOURNAL_ACCESS_WRITE);
 		if (status < 0) {
 			LOG_ERROR_STATUS(status);
 			goto leave;
 		}
-		inode->i_size = inode->i_sb->s_blocksize;
-	
-		status = ocfs_journal_access(handle, parent_fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
-		if (status < 0) {
-			LOG_ERROR_STATUS(status);
-			goto leave;
-		}
 		fe = (ocfs2_dinode *) parent_fe_bh->b_data;
 		fe->i_links_count++;
 		fe = NULL;
@@ -355,12 +441,21 @@
 	if (new_fe_bh) 
 		brelse(new_fe_bh);
 
+	if (de_bh) 
+		brelse(de_bh);
+
 	if (parent_fe_bh != NULL) 
 		brelse(parent_fe_bh);
 
 	if ((status < 0) && inode)
 		iput(inode);
 
+	if (inode_ac)
+		ocfs_free_alloc_context(inode_ac);
+
+	if (data_ac)
+		ocfs_free_alloc_context(data_ac);
+
 	LOG_EXIT_STATUS(status);
 
 	LOG_CLEAR_CONTEXT();
@@ -377,30 +472,28 @@
 			     struct buffer_head **new_fe_bh, 
 			     struct buffer_head *parent_fe_bh,
 			     ocfs_journal_handle *handle,
-			     struct inode *inode)
+			     struct inode *inode,
+			     ocfs2_alloc_context *inode_ac,
+			     struct buffer_head *de_bh)
 {
 	int status = 0;
 	ocfs2_dinode *fe = NULL;
 	ocfs2_extent_list *fel;
-	__u64 disk_off = 0;
 	u64 fe_blkno = 0;
-	__u64 fileOffset = 0;
+	u16 suballoc_bit;
 
 	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %d, %lu, '%*s')\n", dir, dentry, mode,
 			(unsigned long)dev, dentry->d_name.len, dentry->d_name.name);
 
 	OCFS_ASSERT(new_fe_bh);
 	*new_fe_bh = NULL;
-	
-	status = ocfs_alloc_node_block(osb, osb->sb->s_blocksize,
-			      	       &disk_off, &fileOffset, 
-			       	       osb->node_num, DISK_ALLOC_INODE, 
-		       		       handle);
+
+	status = ocfs_claim_new_inode(osb, handle, inode_ac, &suballoc_bit,
+				      &fe_blkno);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
 		goto leave;
 	}
-	fe_blkno = disk_off >> osb->sb->s_blocksize_bits;
 
 	*new_fe_bh = sb_getblk(osb->sb, fe_blkno);
 	if (!*new_fe_bh) {
@@ -433,7 +526,7 @@
 	spin_unlock(&osb->s_next_gen_lock);
 	fe->i_generation = cpu_to_le32(inode->i_generation);
 	fe->i_blkno = fe_blkno;
-	fe->i_suballoc_blkno = fileOffset >> osb->sb->s_blocksize_bits;
+	fe->i_suballoc_bit = suballoc_bit;
 	fe->i_suballoc_node = osb->node_num;
 	fe->i_uid = current->fsuid;
 	if (dir->i_mode & S_ISGID) {
@@ -480,7 +573,7 @@
 	inode->i_mode = mode;
 
 	status = ocfs_add_entry(handle, dentry, inode, fe_blkno,
-				parent_fe_bh);
+				parent_fe_bh, de_bh);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
 		goto leave;
@@ -547,6 +640,7 @@
 	int err;
 	struct buffer_head *fe_bh = NULL;
 	struct buffer_head *parent_fe_bh = NULL;
+	struct buffer_head *de_bh = NULL;
 	ocfs2_dinode *fe = NULL;
 	ocfs_super *osb = OCFS_SB(dir->i_sb);
 
@@ -584,6 +678,14 @@
 	ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE, 0, dir);
 	ocfs_handle_add_inode(handle, dir);
 
+	err = ocfs_prepare_dir_for_insert(osb, dir, parent_fe_bh, 
+					     dentry->d_name.name, 
+					     dentry->d_name.len, &de_bh);
+	if (err < 0) {
+		LOG_ERROR_STATUS (err);
+		goto bail;
+	}
+
 	err = ocfs_acquire_lock (osb, OCFS_LKM_EXMODE, 0, &fe_bh, inode);
 	if (err < 0) {
 		if (err != -EINTR)
@@ -627,8 +729,8 @@
 		goto bail;
 	}
 
-	err = ocfs_add_entry(handle, dentry, inode,
-			     OCFS_I(inode)->ip_blkno, parent_fe_bh);
+	err = ocfs_add_entry(handle, dentry, inode, OCFS_I(inode)->ip_blkno, 
+			     parent_fe_bh, de_bh);
 	if (err) {
 		fe->i_links_count--;
 		inode->i_nlink--;
@@ -641,7 +743,8 @@
 bail:
 	if (handle)
 		ocfs_commit_trans(handle);
-
+	if (de_bh) 
+		brelse(de_bh);
 	if (fe_bh)
 		brelse(fe_bh);
 	if (parent_fe_bh)
@@ -670,6 +773,8 @@
 	ocfs_journal_handle *handle = NULL;
 	struct ocfs2_dir_entry *dirent = NULL;
 	struct buffer_head *dirent_bh = NULL;
+	char *orphan_name;
+	struct buffer_head *orphan_entry_bh = NULL;
 
 	LOG_SET_CONTEXT(UNLINK);
 
@@ -738,6 +843,16 @@
 		}
 	}
 
+	if (S_ISDIR(inode->i_mode) || (inode->i_nlink == 1)) {
+		status = ocfs_prepare_orphan_dir(osb, handle, inode, 
+						 &orphan_name, 
+						 &orphan_entry_bh);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto leave;
+		}
+	}
+
 	handle = ocfs_start_trans(osb, handle, OCFS_FILE_DELETE_CREDITS);
 	if (handle == NULL) {
 		LOG_ERROR_STATUS (status = -ENOMEM);
@@ -763,7 +878,8 @@
 	else
 		fe->i_links_count--;
 	if (!fe->i_links_count) {
-		status = ocfs_orphan_add(osb, handle, inode, fe);
+		status = ocfs_orphan_add(osb, handle, inode, fe, orphan_name,
+					 orphan_entry_bh);
 		if (status < 0) {
 			LOG_ERROR_STATUS(status);
 			goto leave;
@@ -832,6 +948,12 @@
 	if (parent_node_bh)
 		brelse(parent_node_bh);
 
+	if (orphan_entry_bh)
+		brelse(orphan_entry_bh);
+
+	if (orphan_name)
+		kfree(orphan_name);
+
 	LOG_EXIT_INT (retval);
 
 	LOG_CLEAR_CONTEXT();
@@ -924,17 +1046,22 @@
 #define PARENT_INO(buffer) \
 	((struct ocfs2_dir_entry *) ((char *) buffer + \
 	le16_to_cpu(((struct ocfs2_dir_entry *) buffer)->rec_len)))->inode
+
 /*
  * ocfs_rename()
  *
  */
 static int ocfs_rename (struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
 {
+#warning "this needs to be split up into seperate functions."
 	int status = 0;
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
 	ocfs2_dinode *newfe = NULL;
+	char *orphan_name;
+	struct buffer_head *orphan_entry_bh = NULL;
 	struct buffer_head *newfe_bh = NULL;
+	struct buffer_head *insert_entry_bh = NULL;
 	ocfs_super *osb = NULL;
 	u64 newfe_blkno;
 	ocfs_journal_handle *handle = NULL;
@@ -1023,7 +1150,7 @@
 		ocfs_handle_add_inode(handle, old_inode);
 
 		status = -EIO;
-		old_inode_de_bh = ocfs_bread (handle, old_inode, 0, 0, &status, 0);
+		old_inode_de_bh = ocfs_bread (old_inode, 0, &status, 0);
 		if (!old_inode_de_bh)
 			goto finally;
 
@@ -1044,7 +1171,7 @@
 			goto finally;
 		}
 	}
-	
+
 	status = -ENOENT;
 	old_de_bh = ocfs_find_entry(old_dentry->d_name.name, 
 				    old_dentry->d_name.len,
@@ -1111,6 +1238,27 @@
 			       "new_blkno=%llu newfebh=%p bhblocknr=%llu\n",
 			       new_de, newfe_blkno, newfe_bh, newfe_bh ?
 			       (unsigned long long)newfe_bh->b_blocknr : 0ULL);
+
+		if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) {
+			status = ocfs_prepare_orphan_dir(osb, handle, 
+							 new_inode, 
+							 &orphan_name,
+							 &orphan_entry_bh);
+			if (status < 0) {
+				LOG_ERROR_STATUS (status);
+				goto finally;
+			}
+		}
+	} else {
+		OCFS_ASSERT(new_dentry->d_parent->d_inode == new_dir);
+		status = ocfs_prepare_dir_for_insert(osb, new_dir, new_dir_bh,
+						     new_dentry->d_name.name, 
+						     new_dentry->d_name.len,
+						     &insert_entry_bh);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
+		}
 	}
 
 	handle = ocfs_start_trans(osb, handle, OCFS_FILE_RENAME_CREDITS);
@@ -1141,7 +1289,8 @@
 
 		if (!newfe->i_links_count) {
 			status = ocfs_orphan_add(osb, handle, new_inode,
-						 newfe);
+						 newfe, orphan_name, 
+						 orphan_entry_bh);
 			if (status < 0) {
 				LOG_ERROR_STATUS(status);
 				goto finally;
@@ -1174,7 +1323,7 @@
 		/* if the name was not found in new_dir, add it now */
 		status = ocfs_add_entry (handle, new_dentry, old_inode, 
 					 OCFS_I(old_inode)->ip_blkno, 
-					 new_dir_bh);
+					 new_dir_bh, insert_entry_bh);
 	}
 
 finally:
@@ -1279,7 +1428,14 @@
 		brelse(old_de_bh);
 	if (old_inode_de_bh)
 		brelse(old_inode_de_bh);
+	if (orphan_entry_bh)
+		brelse(orphan_entry_bh);
+	if (insert_entry_bh)
+		brelse(insert_entry_bh);
+	if (orphan_name)
+		kfree(orphan_name);
 
+
 	LOG_EXIT_STATUS(status);
 
 	LOG_CLEAR_CONTEXT();
@@ -1411,11 +1567,14 @@
 	struct super_block *sb;
 	int l;
 	struct buffer_head *new_fe_bh = NULL;
+	struct buffer_head *de_bh = NULL;
 	struct buffer_head *parent_fe_bh = NULL;
 	ocfs2_dinode *fe = NULL;
 	ocfs2_dinode *dirfe;
 	ocfs_journal_handle *handle = NULL;
 	int credits;
+	ocfs2_alloc_context *inode_ac = NULL;
+	ocfs2_alloc_context *data_ac = NULL;
 
 	LOG_SET_CONTEXT(SYMLINK);
 
@@ -1444,7 +1603,7 @@
 	l = strlen (symname) + 1;
 	newsize = l - 1;
 
-	credits = ocfs_calc_symlink_credits(sb, newsize);
+	credits = ocfs_calc_symlink_credits(sb);
 
 	handle = ocfs_alloc_handle(osb);
 	if (handle == NULL) {
@@ -1470,6 +1629,26 @@
 		goto abort_trans;
 	}
 
+	status = ocfs_prepare_dir_for_insert(osb, dir, parent_fe_bh, 
+					     dentry->d_name.name, 
+					     dentry->d_name.len, &de_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto abort_trans;
+	}
+
+	status = ocfs_reserve_new_inode(osb, handle, &inode_ac);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto abort_trans;
+	}
+
+	status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto abort_trans;
+	}
+
 	handle = ocfs_start_trans(osb, handle, credits);
 	if (handle == NULL) {
 		LOG_ERROR_STATUS (status = -ENOMEM);
@@ -1479,14 +1658,14 @@
 	status = ocfs_mknod_locked(osb, dir, dentry, 
  				   S_IFLNK | S_IRWXUGO, 0,
  				   &new_fe_bh, parent_fe_bh, handle,
-				   inode);
+				   inode, inode_ac, de_bh);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto abort_trans;
 	}
 
 	fe = (ocfs2_dinode *) new_fe_bh->b_data;
-	
+
 	if (ocfs_populate_inode (inode, fe, 1) < 0) {
 		LOG_ERROR_ARGS("populate inode failed! bh->b_blocknr=%llu, "
 			       "i_blkno=%llu, i_ino=%lu\n",
@@ -1501,8 +1680,8 @@
 	if (status < 0)
 		LOG_ERROR_STATUS(status);
 
-	status = ocfs_extend_file(osb, newsize, handle, inode, NULL, 0,
-				  new_fe_bh);
+	status = ocfs_extend_allocation(osb, inode, 1, new_fe_bh, handle, 
+					data_ac, NULL, NULL);
 	if (status < 0) {
 		if (status != -ENOSPC && status != -EINTR) {
 			LOG_ERROR_ARGS ("Failed to extend file to %llu", newsize);
@@ -1515,6 +1694,12 @@
 	inode->i_size = newsize;
 	inode->i_blocks = (newsize + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 
+	status = ocfs_mark_inode_dirty(handle, inode, new_fe_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto abort_trans;
+	}
+
 	status = ocfs_inode_fill_ext_map(osb, new_fe_bh, inode);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
@@ -1540,6 +1725,10 @@
 		brelse(new_fe_bh);
 	if (parent_fe_bh)
 		brelse(parent_fe_bh);
+	if (de_bh)
+		brelse(de_bh);
+	if (inode_ac)
+		ocfs_free_alloc_context(inode_ac);
 
 	LOG_EXIT_STATUS (status);
 
@@ -1572,75 +1761,41 @@
 	return error_msg == NULL ? 1 : 0;
 }
 
-static inline int ocfs_match (int len, const char * const name, struct ocfs2_dir_entry * de)
-{
-	if (len != de->name_len)
-		return 0;
-	if (!de->inode)
-		return 0;
-	return !memcmp(name, de->name, len);
-}
-
 /* we don't always have a dentry for what we want to add, so people
- * like orphan dir can call this instead. */
+ * like orphan dir can call this instead. 
+ *
+ * If you pass me insert_bh, I'll skip the search of the other dir
+ * blocks and put the record in there. 
+*/
 static int __ocfs_add_entry (ocfs_journal_handle *handle, struct inode *dir,
 			     const char *name, int namelen, 
 			     struct inode *inode, u64 blkno, 
-			     struct buffer_head *parent_fe_bh) 
+			     struct buffer_head *parent_fe_bh, 
+			     struct buffer_head *insert_bh) 
 {
 	unsigned long offset;
 	unsigned short rec_len;
-	struct buffer_head * bh;
 	struct ocfs2_dir_entry * de, * de1;
 	struct super_block * sb;
 	int retval, status;
-	ocfs2_dinode *fe = NULL;
 
 	LOG_ENTRY();
+	OCFS_ASSERT(insert_bh);
 
 	sb = dir->i_sb;
 
 	if (!namelen)
 		return -EINVAL;
-	bh = ocfs_bread (handle, dir, 0, 0, &retval, 0);
-	if (!bh)
-		return retval;
+
 	rec_len = OCFS2_DIR_REC_LEN(namelen);
 	offset = 0;
-	de = (struct ocfs2_dir_entry *) bh->b_data;
+	de = (struct ocfs2_dir_entry *) insert_bh->b_data;
 	while (1) {
-		if ((char *)de >= sb->s_blocksize + bh->b_data) {
-			brelse (bh);
-			bh = NULL;
-			bh = ocfs_bread (handle, dir, offset >> sb->s_blocksize_bits, 1, &retval, 0);
-			if (!bh)
-				goto bail;
-			if (dir->i_size <= offset) {
-				if (dir->i_size == 0) {
-					retval = -ENOENT;
-					goto bail;
-				}
-
-				/* create next block */
-				status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
-				de = (struct ocfs2_dir_entry *) bh->b_data;
-				de->inode = 0;
-				de->rec_len = le16_to_cpu(sb->s_blocksize);
-				dir->i_size = offset + sb->s_blocksize;
-				status = ocfs_journal_dirty(handle, bh);
-
-				/* update the parent file entry file size */
-				status = ocfs_journal_access(handle, parent_fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
-				fe = (ocfs2_dinode *) parent_fe_bh->b_data;
-				fe->i_size = dir->i_size;
-				status = ocfs_journal_dirty(handle, parent_fe_bh);
-			} else {
-				/* move to next block */
-				de = (struct ocfs2_dir_entry *) bh->b_data;
-			}
-			
-		}
-		if (!ocfs_check_dir_entry (dir, de, bh, offset)) {
+		OCFS_ASSERT((char *)de < sb->s_blocksize + insert_bh->b_data);
+		/* These checks should've already been passed by the
+		 * prepare function, but I guess we can leave them
+		 * here anyway. */
+		if (!ocfs_check_dir_entry (dir, de, insert_bh, offset)) {
 			retval = -ENOENT;
 			goto bail;
 		}
@@ -1652,7 +1807,8 @@
 		     (le16_to_cpu(de->rec_len) >= rec_len)) ||
 		    (le16_to_cpu(de->rec_len) >=
 		     (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
-			status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+			status = ocfs_journal_access(handle, insert_bh, 
+						    OCFS_JOURNAL_ACCESS_WRITE);
 			/* By now the buffer is marked for journaling */
 			offset += le16_to_cpu(de->rec_len);
 			if (le64_to_cpu(de->inode)) {
@@ -1675,7 +1831,7 @@
 
 			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 			dir->i_version++;
-			status = ocfs_journal_dirty(handle, bh);
+			status = ocfs_journal_dirty(handle, insert_bh);
 			retval = 0;
 			goto bail;
 		}
@@ -1683,9 +1839,10 @@
 		de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
 	}
 
+	/* when you think about it, the assert above should prevent us
+	 * from ever getting here. */
 	retval = -ENOSPC;
 bail:
-	brelse (bh);
 
 	LOG_EXIT_STATUS(retval);
 	return retval;
@@ -1832,7 +1989,7 @@
 				num++;
 		
 #warning questionable readahead stuff here	
-				bh = ocfs_bread(NULL, dir, b++, 0, &err, 1);
+				bh = ocfs_bread(dir, b++, &err, 1);
 				bh_use[ra_max] = bh;
 #if 0		// ???
 				if (bh)
@@ -1884,44 +2041,62 @@
 	return ret;
 }
 
-/*
- * ocfs_orphan_add()
- *
- */
-static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle,
-			   struct inode *inode, ocfs2_dinode *fe)
+static int ocfs_blkno_stringify(u64 blkno, char **retval)
 {
-	struct inode *orphan_dir_inode = NULL;
-	struct buffer_head *orphan_dir_bh = NULL;
-	int status = 0;
 	char *name = NULL;
 	int namelen;
-	ocfs2_dinode *orphan_fe;
 
-	LOG_ENTRY_ARGS("(inode->i_ino = %lu)\n", inode->i_ino);
+	LOG_ENTRY();
 
-	/* create a unique name here. */
+	*retval = NULL;
 	name = kmalloc(OCFS2_MAX_FILENAME_LENGTH+1, GFP_KERNEL);
 	if (!name) {
-		status = -EFAIL;
-		LOG_ERROR_STATUS(status);
-		goto leave;
+		namelen = -ENOMEM;
+		LOG_ERROR_STATUS(namelen);
+		goto bail;
 	}
 
 	namelen = snprintf(name, OCFS2_MAX_FILENAME_LENGTH+1, "%llu", 
-			   OCFS_I(inode)->ip_blkno);
+			   blkno);
 	if (namelen <= 0) {
-		if (namelen)
-			status = namelen;
-		else
-			status = -EFAIL;
+		kfree(name);
+		if (!namelen)
+			namelen = -EFAULT;
+		LOG_ERROR_STATUS(namelen);
+		goto bail;
+	}
+
+	LOG_TRACE_ARGS("built filename '%s' for orphan dir (len=%d)\n", name, 
+		       namelen);
+
+	*retval = name;
+bail:
+	LOG_EXIT_STATUS(namelen);
+	return(namelen);
+}
+
+static int ocfs_prepare_orphan_dir(ocfs_super *osb, 
+				   ocfs_journal_handle *handle,
+				   struct inode *inode,
+				   char **ret_name,
+				   struct buffer_head **de_bh)
+{
+	struct inode *orphan_dir_inode = NULL;
+	struct buffer_head *orphan_dir_bh = NULL;
+	int status = 0;
+	char *name = NULL;
+	int namelen;
+
+	*ret_name = NULL;
+
+	/* create a unique name here. */
+	namelen = ocfs_blkno_stringify(OCFS_I(inode)->ip_blkno, &name);
+	if (namelen < 0) {
+		status = namelen;
 		LOG_ERROR_STATUS(status);
 		goto leave;
 	}
 
-	LOG_TRACE_ARGS("adding filename '%s' to orphan dir (len=%d)\n", name, 
-		       namelen);
-
 	orphan_dir_inode = ocfs_get_system_file_inode(osb, 
 						      ORPHAN_DIR_SYSTEM_INODE, 
 						      -1);
@@ -1942,9 +2117,65 @@
 			     orphan_dir_inode);
 	ocfs_handle_add_inode(handle, orphan_dir_inode);
 
+	status = ocfs_prepare_dir_for_insert(osb, orphan_dir_inode, 
+					     orphan_dir_bh, name, namelen, 
+					     de_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	*ret_name = name;
+leave:
+	if (orphan_dir_inode)
+		iput(orphan_dir_inode);
+
+	if ((status < 0) && name)
+		kfree(name);
+
+	if (orphan_dir_bh)
+		brelse(orphan_dir_bh);
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+}
+
+/*
+ * ocfs_orphan_add()
+ *
+ */
+static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle,
+			   struct inode *inode, ocfs2_dinode *fe, 
+			   char *name, struct buffer_head *de_bh)
+{
+	struct inode *orphan_dir_inode = NULL;
+	struct buffer_head *orphan_dir_bh = NULL;
+	int status = 0;
+	int namelen;
+	ocfs2_dinode *orphan_fe;
+
+	LOG_ENTRY_ARGS("(inode->i_ino = %lu)\n", inode->i_ino);
+
+	namelen = strlen(name);
+
+	orphan_dir_inode = ocfs_get_system_file_inode(osb, 
+						      ORPHAN_DIR_SYSTEM_INODE, 
+						      -1);
+	if (!orphan_dir_inode) {
+		status = -EFAIL;
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	status = ocfs_read_bh(osb, OCFS_I(orphan_dir_inode)->ip_blkno << osb->sb->s_blocksize_bits, &orphan_dir_bh, OCFS_BH_CACHED, orphan_dir_inode);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
 	status = __ocfs_add_entry(handle, orphan_dir_inode, name, namelen, 
 				  inode, OCFS_I(inode)->ip_blkno, 
-				  orphan_dir_bh);
+				  orphan_dir_bh, de_bh);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto leave;
@@ -1970,16 +2201,11 @@
 		goto leave;
 	}
 
-
 	fe->i_flags |= OCFS2_ORPHANED_FL;
-
 leave:
 	if (orphan_dir_inode)
 		iput(orphan_dir_inode);
 
-	if (name)
-		kfree(name);
-
 	if (orphan_dir_bh)
 		brelse(orphan_dir_bh);
 

Modified: branches/dlm-changes/src/namei.h
===================================================================
--- branches/dlm-changes/src/namei.h	2004-09-24 23:39:22 UTC (rev 1490)
+++ branches/dlm-changes/src/namei.h	2004-09-24 23:42:23 UTC (rev 1491)
@@ -40,5 +40,13 @@
 int ocfs_orphan_del(ocfs_super *osb, ocfs_journal_handle *handle,
 		    struct inode *orphan_dir_inode, struct inode *inode,
 		    struct buffer_head *orphan_dir_bh);
+static inline int ocfs_match (int len, const char * const name, struct ocfs2_dir_entry * de)
+{
+	if (len != de->name_len)
+		return 0;
+	if (!de->inode)
+		return 0;
+	return !memcmp(name, de->name, len);
+}
 
 #endif /* OCFS2_NAMEI_H */



More information about the Ocfs2-commits mailing list