[Ocfs2-devel] [PATCH]2.6 mechanism for holding private inode data

Rusty Lynch rusty at linux.co.intel.com
Sun Mar 14 14:34:40 CST 2004


On Fri, Mar 12, 2004 at 04:09:13PM -0800, Mark Fasheh wrote:
> On Fri, Mar 12, 2004 at 01:07:01PM -0800, Rusty Lynch wrote:
> > This is what I wanted to do, but I was attempting to leave no trail on the
> > 2.4 code.  I am also running my changes on a 2.4 kernel, but not doing much 
> > testing other then mounting a volume, unpackaging a bunch stuff, moving it
> > around, ... and what ever else strikes me as significant.
> That should work for a basic test, I'll put it through the rest of it's
> paces :)
>  
> > I'll make another pass that makes the 2.4 and 2.6 code store the inode private
> > data in the way suggested in 2.6.
> Is it even possible to handle this in the way suggested in 2.6? It's a
> slightly different mechanism for 2.4, right? For 2.4, what I was thinking
> was along the lines of:
> 
> <near the top of ocfs_populate_inode, prolly after the fe sanity check>
> 
> if (!inode->u.generic_ip)
> 	inode->u.generic_ip = kmem_cache_alloc(OcfsGlobalCtxt.inode_cache, 
> 					       GFP_NOFS);
> 
> Of course, with proper error checking and whatnot.
> Then in ocfs_clear_inode, we could just do:
> 
> ocfs_destroy_inode(inode);
> inode->u.generic_ip = NULL;
> 
> Again, cleaned up and bugchecked and whatnot.
> What do you think?
> 
> > As to the use of upper case for MACROS... I agree.  I was just trying to sneak
> > in some macro genocide without having to touch all the code that calls the
> > macros.
> Well, it's a good cause :)
> 
> > So just curious, when do you feel a macro is better then an inline function?
> Umm, I have no strong opinions really. I think mostly my rule is if it's
> only a line or two that doesn't necessarily require any typechecking, then a
> macro is fine. Otherwise, an inline's the better choice.
>  
> > Either way I'll generate a patch that just does the minimal about to move the
> > inode private data, and seperate the macro question to another patch (or series
> > of patches.)

Here is a patch that stores the inode private data as you talked about above.
There is a little more complexity because you have to handle the cases where:
* new inodes are created via ocfs_mknod and ocfs_symlink, and we need to
  start setting private data before ocfs_populate_inode
* reading the root inode in ocfs_read_inode2 (2.4 kernel) or
  ocfs_read_locked_inode (2.6 kernel) where we just directly populate the
  inode and do not call ocfs_populate_inode()

There is really no difference between a 2.4 and 2.6 build (other then where
to put the code for reading the root inode.)

    --rusty


Index: src/inode.c
===================================================================
--- src/inode.c	(revision 776)
+++ src/inode.c	(working copy)
@@ -251,6 +251,15 @@
 		BUG();
 	}
 
+	if (!inode->u.generic_ip)
+		inode->u.generic_ip = kmem_cache_alloc(OcfsGlobalCtxt.inode_cache,
+						       GFP_NOFS);
+	if (!inode->u.generic_ip) {
+		/* How can we recover gracefully? */
+		LOG_ERROR_STR("unable to allocate private data for inode");
+		goto bail;
+	}
+	
 	OCFS_SET_INODE_DEV(sb, inode);
 	inode->i_mode = mode;
 	inode->i_uid = fe->uid;
@@ -306,6 +315,7 @@
 		    break;
 	}
 
+ bail:
 	LOG_EXIT ();
 	return;
 }				/* ocfs_populate_inode */
@@ -337,6 +347,13 @@
 	LOG_TRACE_ARGS("osb = %x\n", osb);
 	if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
 		LOG_TRACE_ARGS("Populating root inode (i_ino = %lu)\n", inode->i_ino);
+		inode->u.generic_ip = kmem_cache_alloc(OcfsGlobalCtxt.inode_cache, GFP_NOFS);
+		if (!inode->u.generic_ip) {
+			/* How can we recover gracefully? */
+			LOG_ERROR_STR("unable to allocate private data for inode");
+			goto bail;
+		}
+
 		inode->i_mode = S_IFDIR | osb->vol_layout.prot_bits;
 		inode->i_blksize = 512;	/* TODO: fix */
 		inode->i_blkbits = 9;
@@ -434,6 +451,13 @@
 	sb = inode->i_sb;
 	osb = (ocfs_super *) OCFS_GENERIC_SB_P(sb);
 	if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
+		inode->u.generic_ip = kmem_cache_alloc(OcfsGlobalCtxt.inode_cache, GFP_NOFS);
+		if (!inode->u.generic_ip) {
+			/* How can we recover gracefully? */
+			LOG_ERROR_STR("unable to allocate private data for inode");
+			goto bail;
+		}
+
 		inode->i_mode = S_IFDIR | osb->vol_layout.prot_bits;
 		inode->i_blksize = (__u32) osb->vol_layout.cluster_size;
 		inode->i_size = OCFS_DEFAULT_DIR_NODE_SIZE;
@@ -745,24 +769,14 @@
 		LOG_TRACE_STR ("inode with oin : clear inode");
 
 		oin = GET_INODE_OIN(inode);
-		if (oin == osb->oin_root_dir) {
-			LOG_TRACE_STR("this is the root inode, doing "
-				      "cleanup now!");
-			ocfs_sync_blockdev(inode->i_sb);
-			LOG_TRACE_STR ("syncing past root inode");
-			LOG_TRACE_STR ("calling dismount");
-			ocfs_dismount_volume (inode->i_sb);
-			goto bail;
-		} else 
+		if (oin != osb->oin_root_dir)
 			BUG();
-
-		ocfs_extent_map_destroy (&oin->map);
-		ocfs_extent_map_init (&oin->map);
-
-		ocfs_release_cached_oin (osb, oin);
-		ocfs_release_oin (oin, true);
-		oin = NULL;
-		LOG_TRACE_STR ("yeah! done with deallocs!");
+		
+		LOG_TRACE_STR("this is the root inode, doing cleanup now!");
+		ocfs_sync_blockdev(inode->i_sb);
+		LOG_TRACE_STR ("syncing past root inode");
+		LOG_TRACE_STR ("calling dismount");
+		ocfs_dismount_volume (inode->i_sb);
 	} else {
 		if (!ocfs_lookup_sector_node (osb, offset, &lockres)) {
 			if (lockres) {
@@ -780,6 +794,9 @@
 		}
 	}
 
+	if (inode->u.generic_ip)
+		kmem_cache_free(OcfsGlobalCtxt.inode_cache, 
+				inode->u.generic_ip);
 bail:
 	LOG_EXIT ();
 	return;
Index: src/super.c
===================================================================
--- src/super.c	(revision 776)
+++ src/super.c	(working copy)
@@ -782,12 +782,30 @@
 }
 #endif
 
+static void ocfs_inode_init_once(void *p, kmem_cache_t *cachep, 
+				 unsigned long flags)
+{
+        ocfs_inode_private *i = (ocfs_inode_private *) p;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR) {
+		i->generic_ip = NULL;
+		i->voteoff = 0;
+		i->feoff = 0;
+		atomic_set(&i->i_clean_buffer_seq, 0);
+         }	
+}
+
 /*
  * ocfs_initialize_mem_lists()
  *
  */
 static int ocfs_initialize_mem_lists (void)
 {
+	OcfsGlobalCtxt.inode_cache = kmem_cache_create("ocfs2_inode",
+		 sizeof(ocfs_inode_private), 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
+		 ocfs_inode_init_once, NULL);
+
 	OcfsGlobalCtxt.oin_cache = kmem_cache_create ("ocfs2_oin",
 		sizeof (ocfs_inode) + OCFS_POINTER_SIZE, 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
 		NULL, NULL);
@@ -826,6 +844,7 @@
  */
 static void ocfs_free_mem_lists (void)
 {
+	kmem_cache_destroy (OcfsGlobalCtxt.inode_cache);
 	kmem_cache_destroy (OcfsGlobalCtxt.oin_cache);
 	kmem_cache_destroy (OcfsGlobalCtxt.ofile_cache);
 	kmem_cache_destroy (OcfsGlobalCtxt.fe_cache);
Index: src/inc/ocfs.h
===================================================================
--- src/inc/ocfs.h	(revision 776)
+++ src/inc/ocfs.h	(working copy)
@@ -239,11 +239,9 @@
 	__u8             deleted; /* this can be a generic flags field later */
 } ocfs_inode_private;
 
-#define CLEAN_SEQ_OFF    	((unsigned long)(&((ocfs_inode_private *)0)->i_clean_buffer_seq))
-#define INODE_PRIVATE_OFF    	((unsigned long)(&((struct inode *)0)->u.generic_ip))
-#define GET_INODE_CLEAN_SEQ(i)  (atomic_t *)(((unsigned long)i) + INODE_PRIVATE_OFF + CLEAN_SEQ_OFF)
+#define GET_INODE_CLEAN_SEQ(i)  (atomic_t *)(&(OCFS_GENERIC_IP(i)->i_clean_buffer_seq))
 
-#define OCFS_GENERIC_IP(i)        ((ocfs_inode_private *)(&(i->u.generic_ip)))
+#define OCFS_GENERIC_IP(i)        ((ocfs_inode_private *)(i->u.generic_ip))
 
 #define inode_data_is_oin(i)      (OCFS_GENERIC_IP(i)->generic_ip != NULL)
 
@@ -2081,6 +2079,7 @@
 	ocfs_obj_id obj_id;
 	ocfs_sem res;
 	struct list_head osb_next;	/* List of all volumes */
+	kmem_cache_t *inode_cache;
 	kmem_cache_t *oin_cache;
 	kmem_cache_t *ofile_cache;
 	kmem_cache_t *fe_cache;
Index: src/namei.c
===================================================================
--- src/namei.c	(revision 776)
+++ src/namei.c	(working copy)
@@ -195,7 +195,13 @@
 		LOG_ERROR_STR("new_inode failed!");
 		goto leave;
 	}
-	
+
+	inode->u.generic_ip = kmem_cache_alloc(OcfsGlobalCtxt.inode_cache, GFP_NOFS);
+	if (!inode->u.generic_ip) {
+		LOG_ERROR_STATUS(status = -ENOMEM);
+		goto leave;
+	}
+
 	/* need the offset of our parent directory to lock it */
 	if (!ocfs_linux_get_inode_offset (dir, &parent_off, NULL)) {
 		LOG_ERROR_STATUS (status = -ENOENT);
@@ -1342,6 +1348,13 @@
 		LOG_ERROR_STR("new_inode failed!");
 		goto bail;
 	}
+
+	inode->u.generic_ip = kmem_cache_alloc(OcfsGlobalCtxt.inode_cache, GFP_NOFS);
+	if (!inode->u.generic_ip) {
+		LOG_ERROR_STATUS(status = -ENOMEM);
+		goto bail;
+	}
+
 	//atomic_set(GET_INODE_CLEAN_SEQ(inode), atomic_read(&osb->clean_buffer_seq));
 
 	parentInode = dentry->d_parent->d_inode;


More information about the Ocfs2-devel mailing list