[Ocfs2-devel] Commenting patch for hash.c

John L. Villalovos john.l.villalovos at intel.com
Fri Apr 23 16:50:35 CDT 2004


Started going through trying to figure stuff out.

I commented stuff that I didn't quite understand in the beginning.

Index: hash.c
===================================================================
--- hash.c	(revision 865)
+++ hash.c	(working copy)
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noet sw=8 ts=8 ai tw=80 sts=0:
+ *
   * hash.c
   *
   * lockid hash, bh sem hash, inode hash
@@ -687,19 +689,36 @@
  #define ocfs_bh_sem_hash_fn(_b)   \
  	(_hashfn((unsigned int)BH_GET_DEVICE((_b)), (_b)->b_blocknr) & ocfs_bh_hash_shift)

+/*
+ * ocfs_bh_sem_hash_init()
+ *
+ * Setup our buffer head semaphore hash table.
+ *
+ * The purpose of the buffer head semaphore hash table is to store semaphores
+ * for our buffer heads.  In order to help speed up the performance of finding
+ * the correct semaphore for our buffer heads we use a hash.  The way this is
+ * done is we create a table that has "buckets" of semaphores.  Each bucket
+ * contains a list of semaphores for our buffer heads which all have the same
+ * hash value.  When we need to find the correct semaphore for a buffer head we
+ * call the ocfs_bh_sem_lookup() function.
+ */
  int ocfs_bh_sem_hash_init()
  {
  	int i, ret;

  	spin_lock_init (&OcfsGlobalCtxt.bh_sem_hash_lock);
+	/* Get 4 ( = pow(2, 2) ) pages of memory. */
  	OcfsGlobalCtxt.bh_sem_hash = (struct list_head *)__get_free_pages(GFP_KERNEL, 2);
  	if (!OcfsGlobalCtxt.bh_sem_hash) {
  		LOG_ERROR_STR("ENOMEM allocating ocfs_bh_sem_hash");
  		ret = -ENOMEM;
  		goto bail;
  	}
+	/* Keep track of how many buckets we have spots for in our hash table
+	 * */
  	OcfsGlobalCtxt.bh_sem_hash_sz = (PAGE_SIZE * 4) / sizeof(struct list_head);
-
+	/* Setup all our buckets, so that they have properly initialized lists
+	 * */
  	for (i=OcfsGlobalCtxt.bh_sem_hash_sz-1; i>=0; i--)
  		INIT_LIST_HEAD(&OcfsGlobalCtxt.bh_sem_hash[i]);

@@ -728,15 +747,25 @@
  	return 0;
  }

-
+/*
+ * ocfs_bh_sem_lookup()
+ *
+ * Lookup the semaphore for our buffer head.  If one does NOT exist then we
+ * will create it and add it to the buffer head semaphore hash table.
+ */
  ocfs_bh_sem * ocfs_bh_sem_lookup(struct buffer_head *bh)
  {
  	int depth, bucket;
  	struct list_head *head, *iter = NULL;
  	ocfs_bh_sem *sem = NULL, *newsem = NULL;

+	/* Figure out which bucket our buffer head is in and then get the list
+	 * of semaphores for that bucket */
  	bucket = ocfs_bh_sem_hash_fn(bh);
  	head = &OcfsGlobalCtxt.bh_sem_hash[bucket];
+
+/* We will jump to this point after we add a new semaphore for an entry that
+ * was not prexisting in the hash table */
  again:
  	depth = 0;
  	spin_lock (&OcfsGlobalCtxt.bh_sem_hash_lock);
@@ -747,8 +776,15 @@
  			atomic_set(&OcfsGlobalCtxt.bh_sem_hash_target_bucket, bucket);
  		}
  		sem = list_entry (iter, ocfs_bh_sem, s_list);
+		/* Is this the correct semaphore for our buffer head? */
  		if (sem->s_blocknr == bh->b_blocknr &&
  		    sem->s_dev == BH_GET_DEVICE(bh)) {
+			/* We have found our semaphore. */
+
+			/* We want to make sure that if nobody is currently
+			 * using the semaphore that there should be no buffer
+			 * head associated with it.  If it isn't being used
+			 * then we can use it for our buffer head */
  			if (atomic_read(&sem->s_refcnt)==0) {
  				if (sem->s_bh) {
  					LOG_ERROR_STR("refcount was zero but s_bh not NULL!");
@@ -757,6 +793,9 @@
  				get_bh(bh);
  				sem->s_bh = bh;
  			}
+			/* Make sure that the buffer head associated with the
+			 * semaphore is our buffer head.  If it isn't then
+			 * something went wrong somewhere :( */
  			if (sem->s_bh != bh) {
  				LOG_ERROR_ARGS("bad bh_sem->bh: sem(%p,%lu,%lu), new(%p,%lu)\n",
  					       sem->s_bh, sem->s_bh ? sem->s_bh->b_blocknr : 0,
@@ -768,8 +807,13 @@
  		sem = NULL;
  	}

+/* TODO: Should "again:" be moved here? Or should the logic of this be moved
+ * down below? */
  	if (newsem && !sem) {
-		/* second pass, we are first to insert */
+		/* We have gone through the list a second time and did not find
+		 * our list item.  Though it seem obvious that we wouldn't find
+		 * it in the second pass since we didn't add it to the list.
+		 * So not sure why we go through the list a second time?? */
  		sem = newsem;
  		list_add(&sem->s_list, head);
  		get_bh(bh);
@@ -777,10 +821,14 @@
  	}

  	if (sem) {
-		/* found something on first or second pass */
+		/* We have found a match, either on the first time through or
+		 * we created a semaphore and added it to the list on the
+		 * second time through.  */
+
  		ocfs_bh_sem_get(sem);
  		if (newsem != sem) {
-			/* if not just added, mru to front */
+			/* if it wasn't just added, the Most Recently Used goes
+			 * to the front of the list */
  			list_del(&sem->s_list);
  			list_add(&sem->s_list, head);
  		}
@@ -788,17 +836,25 @@
  		//	      sem->s_bh->b_blocknr,
  		//	      buffer_modified(sem->s_bh) ? "true" : "false",
  		//	      sem->s_pid);
-			
+
  		if (buffer_modified(sem->s_bh) && sem->s_pid == 0) {
  			LOG_ERROR_ARGS("found a%s sem with a modified bh but no pid!!! (block=%d)\n",
  				       newsem != sem ? "n old" : " new",
  				       sem->s_bh->b_blocknr);
  		}
  	} else {
-		/* first pass. not found. do alloc */
+		/* We went through the list and did NOT find a match for our
+		 * buffer head.  So now we need to create a new semaphore and
+		 * then go back and go through the list again. */
  		spin_unlock (&OcfsGlobalCtxt.bh_sem_hash_lock);
+		/* Create our new semaphore */
  		newsem = ocfs_bh_sem_alloc();
  		if (newsem) {
+			/* Setup the new semaphore.  When a new semaphore is
+			 * created we don't yet assign our buffer head to it.
+			 * We just set the refcnt to 0 and set the block # and
+			 * device.  The buffer head will get put into place
+			 * above. */
  			newsem->s_bh = NULL;
  			atomic_set(&newsem->s_refcnt, 0);
  			newsem->s_blocknr = bh->b_blocknr;
@@ -809,8 +865,12 @@
  #ifdef BH_SEM_DEBUG
  			memset(&newsem->s_modifier[0], 0, 40);
  #endif
+			/* Go back and look up the semaphore again.  It is
+			 * there now since we have just created it */
  			goto again;
  		}
+		/* ERROR.  Shouldn't get here.  If we did then we failed to
+		 * allocate a semaphore. */
  		sem = NULL;
  		goto bail;
  	}
@@ -822,7 +882,7 @@
  		ocfs_bh_sem_free(newsem);
  	}

-bail:	
+bail:
  	return sem;
  }

-------------- next part --------------
Index: super.c
===================================================================
--- super.c	(revision 865)
+++ super.c	(working copy)
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noet sw=8 ts=8 ai tw=80 sts=0:
+ *
  * super.c
  *
  * load/unload driver, mount/dismount volumes
@@ -375,13 +377,14 @@
 	LOG_ENTRY ();
 
 	ocfs_version_print();
-	
+
 	ocfs_hostname = kmalloc(strlen(system_utsname.nodename) + 1, GFP_KERNEL);
 	if (ocfs_hostname==NULL)
 		return -EINVAL;
 	strcpy(ocfs_hostname, system_utsname.nodename);
 	printk("ocfs2: hostname is %s\n", ocfs_hostname);
-	
+
+	/* Take care of setting up our /proc (and sysctl entries) */
 	ocfs_table_header = register_sysctl_table(ocfs_root_table, 0);
 	if (!ocfs_table_header) {
 		LOG_ERROR_STATUS(status = -ENOMEM);
@@ -395,7 +398,6 @@
         INIT_LIST_HEAD (&(OcfsGlobalCtxt.item_list));
 #endif
 	INIT_LIST_HEAD (&(OcfsGlobalCtxt.osb_next));
-	INIT_LIST_HEAD (&(OcfsGlobalCtxt.osb_next));
 
 	/* Read remaining insmod params */
 	if ((status = ocfs_read_params ()) < 0)
@@ -415,7 +417,7 @@
 		LOG_ERROR_STATUS (status);
 		goto leave;
 	}
-	
+
 	status = ocfs_bh_sem_hash_init();
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
@@ -962,6 +964,8 @@
 	
 	osb->publ_map |= (1 << osb->node_num);
 	osb->vol_state = VOLUME_INIT;
+	/* Check if first time this partition has been mounted.  If so create
+	   the root Oracle INode. */
 	status = ocfs_create_root_oin (osb, NULL);
 	if (status >= 0)
 		osb->vol_state = VOLUME_ENABLED;
Index: hash.c
===================================================================
--- hash.c	(revision 865)
+++ hash.c	(working copy)
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noet sw=8 ts=8 ai tw=80 sts=0:
+ *
  * hash.c
  *
  * lockid hash, bh sem hash, inode hash
@@ -687,19 +689,36 @@
 #define ocfs_bh_sem_hash_fn(_b)   \
 	(_hashfn((unsigned int)BH_GET_DEVICE((_b)), (_b)->b_blocknr) & ocfs_bh_hash_shift)
 
+/*
+ * ocfs_bh_sem_hash_init()
+ *
+ * Setup our buffer head semaphore hash table.
+ *
+ * The purpose of the buffer head semaphore hash table is to store semaphores
+ * for our buffer heads.  In order to help speed up the performance of finding
+ * the correct semaphore for our buffer heads we use a hash.  The way this is
+ * done is we create a table that has "buckets" of semaphores.  Each bucket
+ * contains a list of semaphores for our buffer heads which all have the same
+ * hash value.  When we need to find the correct semaphore for a buffer head we
+ * call the ocfs_bh_sem_lookup() function.
+ */
 int ocfs_bh_sem_hash_init()
 {
 	int i, ret;
 
 	spin_lock_init (&OcfsGlobalCtxt.bh_sem_hash_lock);
+	/* Get 4 ( = pow(2, 2) ) pages of memory. */
 	OcfsGlobalCtxt.bh_sem_hash = (struct list_head *)__get_free_pages(GFP_KERNEL, 2);
 	if (!OcfsGlobalCtxt.bh_sem_hash) {
 		LOG_ERROR_STR("ENOMEM allocating ocfs_bh_sem_hash");
 		ret = -ENOMEM;
 		goto bail;
 	}
+	/* Keep track of how many buckets we have spots for in our hash table
+	 * */
 	OcfsGlobalCtxt.bh_sem_hash_sz = (PAGE_SIZE * 4) / sizeof(struct list_head);
-
+	/* Setup all our buckets, so that they have properly initialized lists
+	 * */
 	for (i=OcfsGlobalCtxt.bh_sem_hash_sz-1; i>=0; i--)
 		INIT_LIST_HEAD(&OcfsGlobalCtxt.bh_sem_hash[i]);
 
@@ -728,15 +747,25 @@
 	return 0;
 }
 
-
+/*
+ * ocfs_bh_sem_lookup()
+ *
+ * Lookup the semaphore for our buffer head.  If one does NOT exist then we
+ * will create it and add it to the buffer head semaphore hash table.
+ */
 ocfs_bh_sem * ocfs_bh_sem_lookup(struct buffer_head *bh)
 {
 	int depth, bucket;
 	struct list_head *head, *iter = NULL;
 	ocfs_bh_sem *sem = NULL, *newsem = NULL;
 
+	/* Figure out which bucket our buffer head is in and then get the list
+	 * of semaphores for that bucket */
 	bucket = ocfs_bh_sem_hash_fn(bh);
 	head = &OcfsGlobalCtxt.bh_sem_hash[bucket];
+
+/* We will jump to this point after we add a new semaphore for an entry that
+ * was not prexisting in the hash table */
 again:
 	depth = 0;
 	spin_lock (&OcfsGlobalCtxt.bh_sem_hash_lock);
@@ -747,8 +776,15 @@
 			atomic_set(&OcfsGlobalCtxt.bh_sem_hash_target_bucket, bucket);
 		}
 		sem = list_entry (iter, ocfs_bh_sem, s_list);
+		/* Is this the correct semaphore for our buffer head? */
 		if (sem->s_blocknr == bh->b_blocknr &&
 		    sem->s_dev == BH_GET_DEVICE(bh)) {
+			/* We have found our semaphore. */
+
+			/* We want to make sure that if nobody is currently
+			 * using the semaphore that there should be no buffer
+			 * head associated with it.  If it isn't being used
+			 * then we can use it for our buffer head */
 			if (atomic_read(&sem->s_refcnt)==0) {
 				if (sem->s_bh) {
 					LOG_ERROR_STR("refcount was zero but s_bh not NULL!");
@@ -757,6 +793,9 @@
 				get_bh(bh);
 				sem->s_bh = bh;
 			}
+			/* Make sure that the buffer head associated with the
+			 * semaphore is our buffer head.  If it isn't then
+			 * something went wrong somewhere :( */
 			if (sem->s_bh != bh) {
 				LOG_ERROR_ARGS("bad bh_sem->bh: sem(%p,%lu,%lu), new(%p,%lu)\n",
 					       sem->s_bh, sem->s_bh ? sem->s_bh->b_blocknr : 0, 
@@ -768,8 +807,13 @@
 		sem = NULL;
 	}
 
+/* TODO: Should "again:" be moved here? Or should the logic of this be moved
+ * down below? */
 	if (newsem && !sem) {
-		/* second pass, we are first to insert */
+		/* We have gone through the list a second time and did not find
+		 * our list item.  Though it seem obvious that we wouldn't find
+		 * it in the second pass since we didn't add it to the list.
+		 * So not sure why we go through the list a second time?? */
 		sem = newsem;
 		list_add(&sem->s_list, head);
 		get_bh(bh);
@@ -777,10 +821,14 @@
 	}
 
 	if (sem) {
-		/* found something on first or second pass */
+		/* We have found a match, either on the first time through or
+		 * we created a semaphore and added it to the list on the
+		 * second time through.  */
+
 		ocfs_bh_sem_get(sem);
 		if (newsem != sem) {
-			/* if not just added, mru to front */
+			/* if it wasn't just added, the Most Recently Used goes
+			 * to the front of the list */
 			list_del(&sem->s_list);
 			list_add(&sem->s_list, head);
 		}
@@ -788,17 +836,25 @@
 		//	      sem->s_bh->b_blocknr,
 		//	      buffer_modified(sem->s_bh) ? "true" : "false",
 		//	      sem->s_pid);
-			      
+
 		if (buffer_modified(sem->s_bh) && sem->s_pid == 0) {
 			LOG_ERROR_ARGS("found a%s sem with a modified bh but no pid!!! (block=%d)\n", 
 				       newsem != sem ? "n old" : " new",
 				       sem->s_bh->b_blocknr);
 		}
 	} else {
-		/* first pass. not found. do alloc */
+		/* We went through the list and did NOT find a match for our
+		 * buffer head.  So now we need to create a new semaphore and
+		 * then go back and go through the list again. */
 		spin_unlock (&OcfsGlobalCtxt.bh_sem_hash_lock);
+		/* Create our new semaphore */
 		newsem = ocfs_bh_sem_alloc();
 		if (newsem) {
+			/* Setup the new semaphore.  When a new semaphore is
+			 * created we don't yet assign our buffer head to it.
+			 * We just set the refcnt to 0 and set the block # and
+			 * device.  The buffer head will get put into place
+			 * above. */
 			newsem->s_bh = NULL;
 			atomic_set(&newsem->s_refcnt, 0);
 			newsem->s_blocknr = bh->b_blocknr;
@@ -809,8 +865,12 @@
 #ifdef BH_SEM_DEBUG
 			memset(&newsem->s_modifier[0], 0, 40);
 #endif
+			/* Go back and look up the semaphore again.  It is
+			 * there now since we have just created it */
 			goto again;
 		}
+		/* ERROR.  Shouldn't get here.  If we did then we failed to
+		 * allocate a semaphore. */
 		sem = NULL;
 		goto bail;
 	}
@@ -822,7 +882,7 @@
 		ocfs_bh_sem_free(newsem);
 	}
 
-bail:	
+bail:
 	return sem;
 }
 
Index: osb.c
===================================================================
--- osb.c	(revision 865)
+++ osb.c	(working copy)
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noet sw=8 ts=8 ai tw=80 sts=0:
+ *
  * osb.c
  *
  * Initialize, verify osb
Index: oin.c
===================================================================
--- oin.c	(revision 865)
+++ oin.c	(working copy)
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noet sw=8 ts=8 ai tw=80 sts=0:
+ *
  * oin.c
  *
  * Create, verify, release oin
@@ -451,6 +453,11 @@
 
 /* ocfs_create_root_oin()
  *
+ * This function will create the root Oracle INode (OIN) on the file system if
+ * this is the first time that this partition has ever been mounted.
+ *
+ * If this is NOT the first time this partition has been mounted (meaning it
+ * has been mounted before) then this function does nothing.
  */
 int ocfs_create_root_oin (ocfs_super * osb, struct inode *root)
 {
@@ -464,7 +471,15 @@
 
 	LOG_ENTRY ();
 
+	/* Is this the first time this partition has been mounted? */
 	if (osb->vol_layout.root_start_off == 0) {
+		/* This is our first time being mounted.  We need to take care
+		 * of setting up the root Oracle inode.  In order to do this we
+		 * are going to call ocfs_create_root_dir_node.  So we need to
+		 * get the disk offset to the root directory (root_dirnode).
+		 * In order to get that we need to read in the volume header
+		 * from the first sector of the disk.  */
+
 		status = ocfs_wait_for_disk_lock_release (osb, OCFS_VOLUME_LOCK_OFFSET,
 						 10000, OCFS_DLM_NO_LOCK);
 		if (status < 0) {
@@ -476,12 +491,14 @@
 				     OCFS_DLM_EXCLUSIVE_LOCK, FLAG_FILE_CREATE,
 				     &lockres, &bh, NULL);
 		if (status >= 0) {
+			/* Read the volume header from the first sector of the
+			 * partition and put it into our buffer head */
 			status = ocfs_read_bh(osb, 0, &hdr_bh, 0, NULL);
 			if (status < 0)
 				LOG_ERROR_STATUS (status);
 
 			tmpstat = ocfs_release_lock (osb, OCFS_VOLUME_LOCK_OFFSET, OCFS_DLM_EXCLUSIVE_LOCK, 0, lockres, bh, NULL);
-	
+
 			if (bh)
 				brelse(bh);
 
@@ -497,7 +514,13 @@
 				LOG_ERROR_STATUS (status);
 			goto finally;
 		}
-		
+
+		/* Get the volume header data from our buffer head.  We need to
+		 * know the following in order to call
+		 * ocfs_create_root_dir_node():
+		 *      * root_off: disk offset to the ocfs root dirnode
+		 *        (root_directory)
+		 *      * internal_off: disk offset to the data segment */
 		volDiskHdr = (ocfs_vol_disk_hdr *) OCFS_BH_GET_DATA_READ(hdr_bh); /* read */
 		root_off = volDiskHdr->root_off;
 		int_off = volDiskHdr->internal_off;
@@ -507,10 +530,13 @@
 			ocfs_wait_for_disk_lock_release (osb,
 							OCFS_VOLUME_LOCK_OFFSET,
 							30000, OCFS_DLM_NO_LOCK);
+			/* Setup the root_start_off with the correct value so
+			 * that it will not run this function the next time the
+			 * filesystem is mounted.  */
 			osb->vol_layout.root_start_off = root_off;
 			osb->vol_layout.root_int_off = int_off;
 		}
-
+		/* Do all the work in creating our root directory */
 		status = ocfs_create_root_dir_node (osb);
 		if (status < 0) {
 			LOG_ERROR_STATUS (status);


More information about the Ocfs2-devel mailing list