[Ocfs2-tools-devel] [PATCH 06/10] Dir operation modification for inline data.

Tao Ma tao.ma at oracle.com
Thu Jul 10 23:20:59 PDT 2008


As we have inline data support now and directory is often very small, so
it is nice to have an inlined directory.

The modification for directory includes:
1. Create a new function named ocfs2_init_dir to handle the initialization
   of dir. So the user will call it instead of ocfs2_expand_dir after it
   successfully allocate one inode from the bitmap.
2. Move expand_dir to ocfs2_link itself. So now the caller of ocfs2_link
   doesn't need to expand the dir by itself.
3. Delete libocfs2/newdir.c. The old file only contains one function named
   ocfs2_new_dir_block, so delete it and the work of that function is moved
   into expanddir.c.
4. Abstract the iteration of dir entry from ocfs2_process_dir_block to function
   ocfs2_process_dir_entry. And add a new function ocfs2_inline_dir_iterate
   to do inline iteration.

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 fsck.ocfs2/pass3.c     |   15 +---
 fsck.ocfs2/pass4.c     |   10 +--
 include/ocfs2/ocfs2.h  |    7 +-
 libocfs2/Makefile      |    1 -
 libocfs2/alloc.c       |    6 +-
 libocfs2/dir_iterate.c |  121 +++++++++++++++++++-------
 libocfs2/expanddir.c   |  226 ++++++++++++++++++++++++++++++++++++++++++++----
 libocfs2/inode.c       |   15 +++
 libocfs2/link.c        |   16 +++-
 libocfs2/newdir.c      |   82 -----------------
 mkfs.ocfs2/mkfs.c      |    2 +-
 tunefs.ocfs2/tunefs.c  |   17 +---
 12 files changed, 347 insertions(+), 171 deletions(-)
 delete mode 100644 libocfs2/newdir.c

diff --git a/fsck.ocfs2/pass3.c b/fsck.ocfs2/pass3.c
index f546a72..356cd1a 100644
--- a/fsck.ocfs2/pass3.c
+++ b/fsck.ocfs2/pass3.c
@@ -74,7 +74,7 @@ static void check_root(o2fsck_state *ost)
 		return;
 	}
 
-	ret = ocfs2_expand_dir(ost->ost_fs, blkno, blkno);
+	ret = ocfs2_init_dir(ost->ost_fs, blkno, blkno);
 	if (ret) {
 		com_err(whoami, ret, "while trying to expand a new root "
 			"directory");
@@ -141,15 +141,13 @@ static void check_lostfound(o2fsck_state *ost)
 		return;
 	}
 
-	ret = ocfs2_expand_dir(ost->ost_fs, blkno, ost->ost_fs->fs_root_blkno);
+	ret = ocfs2_init_dir(ost->ost_fs, blkno, ost->ost_fs->fs_root_blkno);
 	if (ret) {
 		com_err(whoami, ret, "while trying to expand a new "
 			"/lost+found directory");
 		goto out;
 	}
 
-	/* XXX expand_dir itself will leak added dir blocks in some error
-	 * paths so we don't bother trying to clean them up either */
 	ret = ocfs2_link(ost->ost_fs, ost->ost_fs->fs_root_blkno, name, blkno,
 			 OCFS2_FT_DIR);
 	if (ret) {
@@ -286,15 +284,6 @@ void o2fsck_reconnect_file(o2fsck_state *ost, uint64_t inode)
 	ret = ocfs2_link(ost->ost_fs, ost->ost_lostfound_ino, iname, inode,
 			 type);
 	if (ret) {
-		if (ret == OCFS2_ET_DIR_NO_SPACE) {
-			ret = ocfs2_expand_dir(ost->ost_fs,
-					       ost->ost_lostfound_ino,
-					       ost->ost_fs->fs_root_blkno);
-			if (ret == 0)
-				ret = ocfs2_link(ost->ost_fs,
-						 ost->ost_lostfound_ino,
-						 iname, inode, type);
-		}
 		com_err(whoami, ret, "while trying to link inode %"PRIu64" "
 			"into /lost+found", inode);
 		goto out;
diff --git a/fsck.ocfs2/pass4.c b/fsck.ocfs2/pass4.c
index 501f9f0..4c5d112 100644
--- a/fsck.ocfs2/pass4.c
+++ b/fsck.ocfs2/pass4.c
@@ -167,21 +167,13 @@ static errcode_t create_orphan_dir(o2fsck_state *ost, char *fname)
 	if (ret)
 		goto bail;
 
-	ret = ocfs2_expand_dir(fs, blkno, fs->fs_sysdir_blkno);
+	ret = ocfs2_init_dir(fs, blkno, fs->fs_sysdir_blkno);
 	if (ret)
 		goto bail;
 
 	/* Add the inode to the system dir */
 	ret = ocfs2_link(fs, fs->fs_sysdir_blkno, fname, blkno,
 			 OCFS2_FT_DIR);
-	if (ret == OCFS2_ET_DIR_NO_SPACE) {
-		ret = ocfs2_expand_dir(fs, fs->fs_sysdir_blkno,
-				       fs->fs_sysdir_blkno);
-		if (!ret)
-			ret = ocfs2_link(fs, fs->fs_sysdir_blkno,
-					 fname, blkno, OCFS2_FT_DIR);
-	}
-
 	if (ret)
 		goto bail;
 
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 2221397..24bc5a1 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -457,9 +457,12 @@ errcode_t ocfs2_chain_force_val(ocfs2_filesys *fs,
 errcode_t ocfs2_chain_add_group(ocfs2_filesys *fs,
 				ocfs2_cached_inode *cinode);
 
+errcode_t ocfs2_init_dir(ocfs2_filesys *fs,
+			 uint64_t dir,
+			 uint64_t parent_dir);
+
 errcode_t ocfs2_expand_dir(ocfs2_filesys *fs,
-			   uint64_t dir,
-			   uint64_t parent_dir);
+			   uint64_t dir);
 
 errcode_t ocfs2_test_inode_allocated(ocfs2_filesys *fs, uint64_t blkno,
 				     int *is_allocated);
diff --git a/libocfs2/Makefile b/libocfs2/Makefile
index 5e12e7c..446c8b4 100644
--- a/libocfs2/Makefile
+++ b/libocfs2/Makefile
@@ -63,7 +63,6 @@ CFILES = 		\
 	memory.c	\
 	mkjournal.c	\
 	namei.c		\
-	newdir.c	\
 	openfs.c	\
 	slot_map.c	\
 	sysfile.c	\
diff --git a/libocfs2/alloc.c b/libocfs2/alloc.c
index 1dfcab1..80bc294 100644
--- a/libocfs2/alloc.c
+++ b/libocfs2/alloc.c
@@ -194,7 +194,11 @@ static void ocfs2_init_inode(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 	if (flags & OCFS2_SUPER_BLOCK_FL)
 		return ;
 
-	ocfs2_dinode_new_extent_list(fs, di);
+	if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super)) &&
+	    S_ISDIR(di->i_mode))
+		ocfs2_set_inode_data_inline(fs, di);
+	else
+		ocfs2_dinode_new_extent_list(fs, di);
 }
 
 static void ocfs2_init_eb(ocfs2_filesys *fs,
diff --git a/libocfs2/dir_iterate.c b/libocfs2/dir_iterate.c
index eda85fa..29281ea 100644
--- a/libocfs2/dir_iterate.c
+++ b/libocfs2/dir_iterate.c
@@ -35,6 +35,9 @@
 #include "dir_iterate.h"
 #include "dir_util.h"
 
+static int ocfs2_inline_dir_iterate(ocfs2_filesys *fs,
+				    struct ocfs2_dinode *di,
+				    struct dir_context *ctx);
 /*
  * This function checks to see whether or not a potential deleted
  * directory entry looks valid.  What we do is check the deleted entry
@@ -71,6 +74,7 @@ errcode_t ocfs2_dir_iterate2(ocfs2_filesys *fs,
 					 void	*priv_data),
 			     void *priv_data)
 {
+	struct ocfs2_dinode *di;
 	struct		dir_context	ctx;
 	errcode_t	retval;
 	
@@ -90,8 +94,22 @@ errcode_t ocfs2_dir_iterate2(ocfs2_filesys *fs,
 	ctx.func = func;
 	ctx.priv_data = priv_data;
 	ctx.errcode = 0;
-	retval = ocfs2_block_iterate(fs, dir, 0,
-				     ocfs2_process_dir_block, &ctx);
+
+	retval = ocfs2_read_inode(fs, dir, ctx.buf);
+	if (retval)
+		goto out;
+
+	di = (struct ocfs2_dinode *)ctx.buf;
+
+	if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super)) &&
+	    di->i_dyn_features & OCFS2_INLINE_DATA_FL)
+		retval = ocfs2_inline_dir_iterate(fs, di, &ctx);
+	else
+		retval = ocfs2_block_iterate(fs, dir, 0,
+					     ocfs2_process_dir_block,
+					     &ctx);
+
+out:
 	if (!block_buf)
 		ocfs2_free(&ctx.buf);
 	if (retval)
@@ -138,34 +156,17 @@ extern errcode_t ocfs2_dir_iterate(ocfs2_filesys *fs,
 				  xlate_func, &xl);
 }
 
-/*
- * Helper function which is private to this module.  Used by
- * ocfs2_dir_iterate() and ocfs2_dblist_dir_iterate()
- */
-int ocfs2_process_dir_block(ocfs2_filesys *fs,
-			    uint64_t	blocknr,
-			    uint64_t	blockcnt,
-			    uint16_t	ext_flags,
-			    void	*priv_data)
+static int ocfs2_process_dir_entry(ocfs2_filesys *fs,
+				   unsigned int offset,
+				   int entry,
+				   int *changed,
+				   int *do_abort,
+				   struct dir_context *ctx)
 {
-	struct dir_context *ctx = (struct dir_context *) priv_data;
-	unsigned int	offset = 0;
-	unsigned int	next_real_entry = 0;
-	int		ret = 0;
-	int		changed = 0;
-	int		do_abort = 0;
-	int		entry, size;
+	errcode_t ret;
 	struct ocfs2_dir_entry *dirent;
-
-	if (blockcnt < 0)
-		return 0;
-
-	entry = blockcnt ? OCFS2_DIRENT_OTHER_FILE :
-		OCFS2_DIRENT_DOT_FILE;
-	
-	ctx->errcode = ocfs2_read_dir_block(fs, blocknr, ctx->buf);
-	if (ctx->errcode)
-		return OCFS2_BLOCK_ABORT;
+	unsigned int next_real_entry = 0;
+	int size;
 
 	while (offset < fs->fs_blocksize) {
 		dirent = (struct ocfs2_dir_entry *) (ctx->buf + offset);
@@ -193,9 +194,9 @@ int ocfs2_process_dir_block(ocfs2_filesys *fs,
 			entry++;
 			
 		if (ret & OCFS2_DIRENT_CHANGED)
-			changed++;
+			*changed += 1;
 		if (ret & OCFS2_DIRENT_ABORT) {
-			do_abort++;
+			*do_abort += 1;
 			break;
 		}
 next:		
@@ -221,6 +222,66 @@ next:
 		offset += dirent->rec_len;
 	}
 
+	return 0;
+}
+
+static int ocfs2_inline_dir_iterate(ocfs2_filesys *fs,
+				    struct ocfs2_dinode *di,
+				    struct dir_context *ctx)
+{
+	unsigned int offset = offsetof(struct ocfs2_dinode, id2.i_data.id_data);
+	unsigned int next_real_entry = 0;
+	int ret = 0, changed = 0, do_abort = 0, entry;
+
+	entry = OCFS2_DIRENT_DOT_FILE;
+
+	ret = ocfs2_process_dir_entry(fs, offset, entry, &changed,
+				      &do_abort, ctx);
+	if (ret)
+		return ret;
+
+	if (changed) {
+		ctx->errcode = ocfs2_write_inode(fs, di->i_blkno, ctx->buf);
+		if (ctx->errcode)
+			return OCFS2_BLOCK_ABORT;
+	}
+
+	return 0;
+}
+
+/*
+ * Helper function which is private to this module.  Used by
+ * ocfs2_dir_iterate() and ocfs2_dblist_dir_iterate()
+ */
+int ocfs2_process_dir_block(ocfs2_filesys *fs,
+			    uint64_t	blocknr,
+			    uint64_t	blockcnt,
+			    uint16_t	ext_flags,
+			    void	*priv_data)
+{
+	struct dir_context *ctx = (struct dir_context *) priv_data;
+	unsigned int	offset = 0;
+	unsigned int	next_real_entry = 0;
+	int		ret = 0;
+	int		changed = 0;
+	int		do_abort = 0;
+	int		entry;
+
+	if (blockcnt < 0)
+		return 0;
+
+	entry = blockcnt ? OCFS2_DIRENT_OTHER_FILE :
+		OCFS2_DIRENT_DOT_FILE;
+
+	ctx->errcode = ocfs2_read_dir_block(fs, blocknr, ctx->buf);
+	if (ctx->errcode)
+		return OCFS2_BLOCK_ABORT;
+
+	ret = ocfs2_process_dir_entry(fs, offset, entry, &changed,
+				      &do_abort, ctx);
+	if (ret)
+		return ret;
+
 	if (changed) {
 		ctx->errcode = ocfs2_write_dir_block(fs, blocknr,
 						     ctx->buf);
diff --git a/libocfs2/expanddir.c b/libocfs2/expanddir.c
index f6a5385..2d0a074 100644
--- a/libocfs2/expanddir.c
+++ b/libocfs2/expanddir.c
@@ -37,13 +37,96 @@
 
 #include "ocfs2/ocfs2.h"
 
+static void ocfs2_expand_last_dirent(char *start, uint16_t old_size,
+				     uint16_t new_size)
+{
+	struct ocfs2_dir_entry *de;
+	struct ocfs2_dir_entry *prev_de;
+	char *de_buf, *limit;
+	uint16_t bytes = new_size - old_size;
+
+	limit = start + old_size;
+	de_buf = start;
+	de = (struct ocfs2_dir_entry *)de_buf;
+	do {
+		prev_de = de;
+		de_buf += de->rec_len;
+		de = (struct ocfs2_dir_entry *)de_buf;
+	} while (de_buf < limit);
+
+	prev_de->rec_len += bytes;
+}
+
+static errcode_t ocfs2_expand_inline_dir(ocfs2_filesys *fs,
+					 uint64_t dir)
+{
+	errcode_t ret = 0;
+	uint32_t n_clusters;
+	uint64_t blkno;
+	char *buf = NULL, *di_buf = NULL;
+	struct ocfs2_dinode *di;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &di_buf);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_read_inode(fs, dir, di_buf);
+	if (ret)
+		goto bail;
+	di = (struct ocfs2_dinode *)di_buf;
+
+	ret = ocfs2_new_clusters(fs, 1, 1, &blkno, &n_clusters);
+	if (ret)
+		goto bail;
+
+	memcpy(buf, di->id2.i_data.id_data, di->i_size);
+	memset(buf + di->i_size, 0, fs->fs_blocksize - di->i_size);
+	ocfs2_expand_last_dirent(buf, di->i_size, fs->fs_blocksize);
+
+	ret = ocfs2_write_dir_block(fs, blkno, buf);
+	if (ret)
+		goto bail;
+
+	di->i_dyn_features &= ~OCFS2_INLINE_DATA_FL;
+
+	ocfs2_dinode_new_extent_list(fs, di);
+
+	di->i_size = 0;
+	di->i_ctime = di->i_mtime = time(NULL);
+
+	ret = ocfs2_write_inode(fs, dir, di_buf);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_insert_extent(fs, di->i_blkno, 0, blkno, n_clusters, 0);
+	if (ret)
+		goto bail;
+
+	/* re-read the buffer since ocfs2_insert_extent has modified it. */
+	ret = ocfs2_read_inode(fs, dir, di_buf);
+	if (ret)
+		goto bail;
+	di->i_size = fs->fs_blocksize;
+	/* update the size of the inode */
+	ret = ocfs2_write_inode(fs, dir, di_buf);
+
+bail:
+	if (buf)
+		ocfs2_free(&buf);
+
+	return ret;
+}
+
 /*
  * ocfs2_expand_dir()
  *
  */
 errcode_t ocfs2_expand_dir(ocfs2_filesys *fs,
-			   uint64_t dir,
-			   uint64_t parent_dir)
+			   uint64_t dir)
 {
 	errcode_t ret = 0;
 	ocfs2_cached_inode *cinode = NULL;
@@ -52,6 +135,7 @@ errcode_t ocfs2_expand_dir(ocfs2_filesys *fs,
 	uint64_t new_blk;
 	uint64_t contig;
 	char *buf = NULL;
+	struct ocfs2_dir_entry *de;
 
 	if (!(fs->fs_flags & OCFS2_FLAG_RW))
 		return OCFS2_ET_RO_FILESYS;
@@ -66,6 +150,12 @@ errcode_t ocfs2_expand_dir(ocfs2_filesys *fs,
 	if (ret)
 		goto bail;
 
+	if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super)) &&
+	    cinode->ci_inode->i_dyn_features & OCFS2_INLINE_DATA_FL) {
+		ret = ocfs2_expand_inline_dir(fs, dir);
+		goto bail;
+	}
+
 	/* This relies on the fact that i_size of a directory is a
 	 * multiple of blocksize */
 	used_blks = cinode->ci_inode->i_size >>
@@ -92,37 +182,139 @@ errcode_t ocfs2_expand_dir(ocfs2_filesys *fs,
 	if (ret) 
 		goto bail;
 
-	/* init new dir block, with dotty entries if it's first */
-	if (used_blks == 0)
-		ret = ocfs2_new_dir_block(fs, dir, parent_dir, &buf);
-	else
-		ret = ocfs2_new_dir_block(fs, 0, 0, &buf);
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
 	if (ret)
 		goto bail;
 
+	memset(buf, 0, fs->fs_blocksize);
+	de = (struct ocfs2_dir_entry *)buf;
+	de->rec_len = fs->fs_blocksize;
+
 	/* write new dir block */
 	ret = ocfs2_write_dir_block(fs, new_blk, buf);
 	if (ret)
 		goto bail;
 
-	/* did we just add a '..' reference to a parent?  if so, update
-	 * them */
-	if (used_blks == 0) {
-		struct ocfs2_dinode *parent =
-			(struct ocfs2_dinode *)buf;
-		ret = ocfs2_read_inode(fs, parent_dir, buf);
+	/* increase the size */
+	cinode->ci_inode->i_size += fs->fs_blocksize;
+
+	/* update the size of the inode */
+	ret = ocfs2_write_cached_inode(fs, cinode);
+	if (ret)
+		goto bail;
+
+bail:
+	if (buf)
+		ocfs2_free(&buf);
+
+	if (cinode)
+		ocfs2_free_cached_inode(fs, cinode);
+
+	return ret;
+}
+
+static void ocfs2_fill_initial_dirents(uint64_t dir, uint64_t parent,
+				       char *start, uint16_t size)
+{
+	struct ocfs2_dir_entry *de = (struct ocfs2_dir_entry *)start;
+
+	de->inode = dir;
+	de->name_len = 1;
+	de->rec_len = OCFS2_DIR_REC_LEN(de->name_len);
+	de->name[0] = '.';
+	de->file_type = OCFS2_FT_DIR;
+
+	de = (struct ocfs2_dir_entry *) ((char *)de + de->rec_len);
+	de->inode = parent;
+	de->rec_len = size - OCFS2_DIR_REC_LEN(1);
+	de->name_len = 2;
+	strcpy(de->name, "..");
+	de->file_type = OCFS2_FT_DIR;
+}
+
+errcode_t ocfs2_init_dir(ocfs2_filesys *fs,
+			 uint64_t dir,
+			 uint64_t parent_dir)
+{
+	errcode_t ret = 0;
+	ocfs2_cached_inode *cinode = NULL;
+	struct ocfs2_dinode *parent;
+	uint16_t size;
+	uint64_t blkno, contig;
+	char *buf = NULL, *data = NULL;
+	struct ocfs2_inline_data *inline_data;
+
+	if (!(fs->fs_flags & OCFS2_FLAG_RW))
+		return OCFS2_ET_RO_FILESYS;
+
+	/* ensure it is a dir */
+	ret = ocfs2_check_directory(fs, dir);
+	if (ret)
+		goto bail;
+
+	/* read inode */
+	ret = ocfs2_read_cached_inode(fs, dir, &cinode);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	if (ret)
+		goto bail;
+
+	if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) {
+		if (!(cinode->ci_inode->i_dyn_features & OCFS2_INLINE_DATA_FL))
+			return OCFS2_ET_DIR_CORRUPTED;
+
+		inline_data = &cinode->ci_inode->id2.i_data;
+		data = inline_data->id_data;
+		size = inline_data->id_count;
+	} else {
+		if (cinode->ci_inode->i_dyn_features & OCFS2_INLINE_DATA_FL)
+			return OCFS2_ET_DIR_CORRUPTED;
+
+		ret = ocfs2_expand_dir(fs, dir);
+		if (ret)
+			goto bail;
+
+		ocfs2_free_cached_inode(fs, cinode);
+		cinode = NULL;
+
+		ret = ocfs2_read_cached_inode(fs, dir, &cinode);
 		if (ret)
 			goto bail;
-		parent->i_links_count++;
-		ret = ocfs2_write_inode(fs, parent_dir, buf);
+
+		ret = ocfs2_extent_map_get_blocks(cinode, 0, 1,
+						  &blkno, &contig, NULL);
+		if (ret)
+			goto bail;
+
+		data = buf;
+		size = fs->fs_blocksize;
+	}
+
+	/* set '..' and '.' in dir. */
+	ocfs2_fill_initial_dirents(dir, parent_dir, data, size);
+
+	if (!(cinode->ci_inode->i_dyn_features & OCFS2_INLINE_DATA_FL)) {
+		ret = ocfs2_write_dir_block(fs, blkno, buf);
 		if (ret)
 			goto bail;
 	}
 
+	/* set link count of the parent */
+	ret = ocfs2_read_inode(fs, parent_dir, buf);
+	if (ret)
+		goto bail;
+	parent = (struct ocfs2_dinode *)buf;
+	parent->i_links_count++;
+	ret = ocfs2_write_inode(fs, parent_dir, buf);
+	if (ret)
+		goto bail;
+
 	/* increase the size */
-	cinode->ci_inode->i_size += fs->fs_blocksize;
+	cinode->ci_inode->i_size = size;
 
-	/* update the size of the inode */
+	/* update the inode */
 	ret = ocfs2_write_cached_inode(fs, cinode);
 	if (ret)
 		goto bail;
diff --git a/libocfs2/inode.c b/libocfs2/inode.c
index 33d9c9d..31dc2b3 100644
--- a/libocfs2/inode.c
+++ b/libocfs2/inode.c
@@ -89,6 +89,21 @@ static void ocfs2_swap_inode_third(struct ocfs2_dinode *di)
 			rec->t_start    = bswap_32(rec->t_start);
 			rec->t_clusters = bswap_32(rec->t_clusters);
 		}
+	} else if (di->i_dyn_features & OCFS2_INLINE_DATA_FL &&
+		   S_ISDIR(di->i_mode)) {
+		struct ocfs2_dir_entry *de;
+		uint16_t rec_len;
+		char *de_buf = (char *)di->id2.i_data.id_data;
+		char *limit = de_buf + di->i_size;
+
+		while (de_buf < limit) {
+			de = (struct ocfs2_dir_entry *)de_buf;
+			de->inode = bswap_64(de->inode);
+			rec_len = de->rec_len;
+			de->rec_len = bswap_16(de->rec_len);
+
+			de_buf += rec_len;
+		}
 	}
 }
 
diff --git a/libocfs2/link.c b/libocfs2/link.c
index fcfe56f..b001a7b 100644
--- a/libocfs2/link.c
+++ b/libocfs2/link.c
@@ -110,6 +110,7 @@ errcode_t ocfs2_link(ocfs2_filesys *fs, uint64_t dir, const char *name,
 {
 	errcode_t		retval;
 	struct link_struct	ls;
+	int allocation = 0;
 #if 0 /* Maybe later */
         char *buf;
 	struct ocfs2_dinode	inode;
@@ -128,15 +129,24 @@ errcode_t ocfs2_link(ocfs2_filesys *fs, uint64_t dir, const char *name,
 	ls.flags = flags;
 	ls.done = 0;
 	ls.sb = fs->fs_super;
-
+again:
 	retval = ocfs2_dir_iterate(fs, dir,
                                    OCFS2_DIRENT_FLAG_INCLUDE_EMPTY,
                                    NULL, link_proc, &ls);
 	if (retval)
 		return retval;
 
-	if (!ls.done)
-		return OCFS2_ET_DIR_NO_SPACE;
+	if (!ls.done) {
+		if (allocation)
+			return OCFS2_ET_INTERNAL_FAILURE;
+
+		retval = ocfs2_expand_dir(fs, dir);
+		if (retval)
+			return retval;
+
+		allocation = 1;
+		goto again;
+	}
 
 #if 0 /* Maybe later */
         retval = ocfs2_malloc_block(fs->fs_io, &buf);
diff --git a/libocfs2/newdir.c b/libocfs2/newdir.c
deleted file mode 100644
index 480ac80..0000000
--- a/libocfs2/newdir.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * newdir.c
- *
- * Create a new directory block
- *
- * Copyright (C) 2004 Oracle.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License, version 2,  as published by the Free Software Foundation.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- *  This code is a port of e2fsprogs/lib/ext2fs/newdir.c
- *  Copyright (C) 1994, 1995 Theodore Ts'o.
- */
-
-#define _XOPEN_SOURCE 600 /* Triggers magic in features.h */
-#define _LARGEFILE64_SOURCE
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ocfs2/ocfs2.h"
-
-/*
- * Create new directory block
- */
-errcode_t ocfs2_new_dir_block(ocfs2_filesys *fs, uint64_t dir_ino,
-			      uint64_t parent_ino, char **block)
-{
-	struct ocfs2_dir_entry 	*dir;
-	errcode_t		ret;
-	char			*buf;
-
-	ret = ocfs2_malloc_block(fs->fs_io, &buf);
-	if (ret)
-		return ret;
-
-	memset(buf, 0, fs->fs_blocksize);
-
-	dir = (struct ocfs2_dir_entry *) buf;
-	dir->rec_len = fs->fs_blocksize;
-
-	if (dir_ino) {
-		/*
-		 * Set up entry for '.'
-		 */
-		dir->inode = dir_ino;
-		dir->rec_len = OCFS2_DIR_REC_LEN(1);
-		dir->name_len = 1;
-		dir->file_type = OCFS2_FT_DIR;
-		dir->name[0] = '.';
-
-		/*
-		 * Set up entry for '..'
-		 */
-		dir = (struct ocfs2_dir_entry *) (buf + dir->rec_len);
-		dir->inode = parent_ino;
-		dir->rec_len = fs->fs_blocksize - OCFS2_DIR_REC_LEN(1);
-		dir->name_len = 2;
-		dir->file_type = OCFS2_FT_DIR;
-		dir->name[0] = '.';
-		dir->name[1] = '.';
-	}
-
-	*block = buf;
-	return 0;
-}
diff --git a/mkfs.ocfs2/mkfs.c b/mkfs.ocfs2/mkfs.c
index 77018af..ff1d497 100644
--- a/mkfs.ocfs2/mkfs.c
+++ b/mkfs.ocfs2/mkfs.c
@@ -2296,7 +2296,7 @@ static void create_lost_found_dir(State *s)
 		goto bail;
 	}
 
-	ret = ocfs2_expand_dir(fs, lost_found_blkno, fs->fs_root_blkno);
+	ret = ocfs2_init_dir(fs, lost_found_blkno, fs->fs_root_blkno);
 	if (ret) {
 		com_err(s->progname, ret, "while adding lost+found dir data");
 		goto bail;
diff --git a/tunefs.ocfs2/tunefs.c b/tunefs.ocfs2/tunefs.c
index be10eb2..6d52062 100644
--- a/tunefs.ocfs2/tunefs.c
+++ b/tunefs.ocfs2/tunefs.c
@@ -489,11 +489,12 @@ static errcode_t add_slots(ocfs2_filesys *fs)
 
 			/* if dir, alloc space to it */
 			if (ftype == OCFS2_FT_DIR) {
-				ret = ocfs2_expand_dir(fs, blkno, fs->fs_sysdir_blkno);
+				ret = ocfs2_init_dir(fs, blkno,
+						     fs->fs_sysdir_blkno);
 				if (ret) {
 					printf("\n");
-					com_err(opts.progname, ret,
-						"while expanding system directory");
+					com_err(opts.progname, ret, "while "
+						"initializing system directory");
 					goto bail;
 				}
 			}
@@ -501,15 +502,7 @@ static errcode_t add_slots(ocfs2_filesys *fs)
 			/* Add the inode to the system dir */
 			ret = ocfs2_link(fs, fs->fs_sysdir_blkno, fname, blkno,
 					 ftype);
-			if (!ret)
-				goto next_file;
-			if (ret == OCFS2_ET_DIR_NO_SPACE) {
-				ret = ocfs2_expand_dir(fs, fs->fs_sysdir_blkno,
-						       fs->fs_sysdir_blkno);
-				if (!ret)
-					ret = ocfs2_link(fs, fs->fs_sysdir_blkno,
-							 fname, blkno, ftype);
-			} else {
+			if (ret) {
 				com_err(opts.progname, 0, "while linking inode "
 					"%"PRIu64" to the system directory", blkno);
 				goto bail;
-- 
1.5.4.GIT




More information about the Ocfs2-tools-devel mailing list