HAMMER VFS - version 2 work - move directory entries to inode localization
authorMatthew Dillon <dillon@apollo.backplane.com>
Sun, 28 Jun 2009 17:23:23 +0000 (10:23 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sun, 28 Jun 2009 17:23:23 +0000 (10:23 -0700)
* Set version 2 features.  Directories created in a version 2 HAMMER
  filesystem place their directory entries in the B-Tree's inode localization
  space instead of the general space.  Pre-existing directories continue
  to use the old scheme.

* Amost doubles directory lookup / find / ls performance in effected
  directories.  However, at the moment the B-Tree must be reblocked before
  the gains are seen.

sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_disk.h
sys/vfs/hammer/hammer_inode.c
sys/vfs/hammer/hammer_ioctl.c
sys/vfs/hammer/hammer_object.c
sys/vfs/hammer/hammer_vnops.c

index d1c72ad..0092fbc 100644 (file)
@@ -1330,3 +1330,20 @@ hammer_modify_node_done(hammer_node_t node)
        hammer_modify_node(trans, node, &(node)->ondisk->field, \
                             sizeof((node)->ondisk->field))
 
+/*
+ * The HAMMER_INODE_CAP_DIR_LOCAL_INO capability is set on newly
+ * created directories for HAMMER version 2 or greater and causes
+ * directory entries to be placed the inode localization zone in
+ * the B-Tree instead of the misc zone.
+ *
+ * This greatly improves localization between directory entries and
+ * inodes
+ */
+static __inline u_int32_t
+hammer_dir_localization(hammer_inode_t dip)
+{
+       if (dip->ino_data.cap_flags & HAMMER_INODE_CAP_DIR_LOCAL_INO)
+               return(HAMMER_LOCALIZE_INODE);
+       else
+               return(HAMMER_LOCALIZE_MISC);
+}
index 8da1e1d..97243f1 100644 (file)
@@ -539,11 +539,11 @@ typedef struct hammer_volume_ondisk *hammer_volume_ondisk_t;
 
 #define HAMMER_VOL_VERSION_MIN         1       /* minimum supported version */
 #define HAMMER_VOL_VERSION_DEFAULT     1       /* newfs default version */
-#define HAMMER_VOL_VERSION_WIP         2       /* version >= this is WIP */
+#define HAMMER_VOL_VERSION_WIP         3       /* version >= this is WIP */
 #define HAMMER_VOL_VERSION_MAX         2       /* maximum supported version */
 
 #define HAMMER_VOL_VERSION_ONE         1
-#define HAMMER_VOL_VERSION_TWO         2
+#define HAMMER_VOL_VERSION_TWO         2       /* new dirent layout (2.3+) */
 /*
  * Record types are fairly straightforward.  The B-Tree includes the record
  * type in its index sort.
@@ -642,12 +642,15 @@ struct hammer_inode_data {
 
 /*
  * Capability & implementation flags.
+ *
+ * DIR_LOCAL_INO - Use inode B-Tree localization for directory entries.
  */
 #define HAMMER_INODE_CAP_DIRHASH_MASK  0x03    /* directory: hash algorithm */
 #define HAMMER_INODE_CAP_DIRHASH_ALG0  0x00
 #define HAMMER_INODE_CAP_DIRHASH_ALG1  0x01
 #define HAMMER_INODE_CAP_DIRHASH_ALG2  0x02
 #define HAMMER_INODE_CAP_DIRHASH_ALG3  0x03
+#define HAMMER_INODE_CAP_DIR_LOCAL_INO 0x04    /* use inode localization */
 
 /*
  * A HAMMER directory entry associates a HAMMER filesystem object with a
index bdd30b1..4a4c306 100644 (file)
@@ -751,12 +751,13 @@ hammer_create_inode(hammer_transaction_t trans, struct vattr *vap,
        ip->ino_data.ctime = trans->time;
 
        /*
-        * If we are running version 2 or greater we use dirhash algorithm #1
-        * which is semi-sorted.  Algorithm #0 was just a pure crc.
+        * If we are running version 2 or greater directory entries are
+        * inode-localized instead of data-localized.
         */
        if (trans->hmp->version >= HAMMER_VOL_VERSION_TWO) {
                if (ip->ino_leaf.base.obj_type == HAMMER_OBJTYPE_DIRECTORY) {
-                       ip->ino_data.cap_flags |= HAMMER_INODE_CAP_DIRHASH_ALG1;
+                       ip->ino_data.cap_flags |=
+                               HAMMER_INODE_CAP_DIR_LOCAL_INO;
                }
        }
 
index 5c3f920..bf4f540 100644 (file)
@@ -233,6 +233,10 @@ hammer_ioc_gethistory(hammer_transaction_t trans, hammer_inode_t ip,
                        break;
                case HAMMER_OBJTYPE_DIRECTORY:
                        cursor.key_beg.rec_type = HAMMER_RECTYPE_DIRENTRY;
+                       cursor.key_beg.localization =
+                                               hammer_dir_localization(ip);
+                       cursor.key_end.localization =
+                                               hammer_dir_localization(ip);
                        break;
                case HAMMER_OBJTYPE_DBFILE:
                        cursor.key_beg.rec_type = HAMMER_RECTYPE_DB;
@@ -441,7 +445,7 @@ hammer_ioc_get_version(hammer_transaction_t trans, hammer_inode_t ip,
                break;
        case 2:
                ksnprintf(ver->description, sizeof(ver->description),
-                        "2.2 - New directory hash");
+                        "2.3 - New directory entry layout");
                break;
        default:
                ksnprintf(ver->description, sizeof(ver->description),
index 74fe30b..4f3f5c4 100644 (file)
@@ -648,7 +648,7 @@ hammer_ip_add_directory(struct hammer_transaction *trans,
 
        record->type = HAMMER_MEM_RECORD_ADD;
        record->leaf.base.localization = dip->obj_localization +
-                                        HAMMER_LOCALIZE_MISC;
+                                        hammer_dir_localization(dip);
        record->leaf.base.obj_id = dip->obj_id;
        record->leaf.base.key = hammer_directory_namekey(dip, name, bytes,
                                                         &max_iterations);
@@ -2385,7 +2385,7 @@ hammer_ip_check_directory_empty(hammer_transaction_t trans, hammer_inode_t ip)
        hammer_init_cursor(trans, &cursor, &ip->cache[1], ip);
 
        cursor.key_beg.localization = ip->obj_localization +
-                                     HAMMER_LOCALIZE_MISC;
+                                     hammer_dir_localization(ip);
        cursor.key_beg.obj_id = ip->obj_id;
        cursor.key_beg.create_tid = 0;
        cursor.key_beg.delete_tid = 0;
index 65f59f2..f6612ee 100644 (file)
@@ -896,7 +896,7 @@ hammer_vop_nresolve(struct vop_nresolve_args *ap)
 
        error = hammer_init_cursor(&trans, &cursor, &dip->cache[1], dip);
        cursor.key_beg.localization = dip->obj_localization +
-                                     HAMMER_LOCALIZE_MISC;
+                                     hammer_dir_localization(dip);
         cursor.key_beg.obj_id = dip->obj_id;
        cursor.key_beg.key = namekey;
         cursor.key_beg.create_tid = 0;
@@ -1358,7 +1358,7 @@ hammer_vop_readdir(struct vop_readdir_args *ap)
         */
        hammer_init_cursor(&trans, &cursor, &ip->cache[1], ip);
        cursor.key_beg.localization = ip->obj_localization +
-                                     HAMMER_LOCALIZE_MISC;
+                                     hammer_dir_localization(ip);
        cursor.key_beg.obj_id = ip->obj_id;
        cursor.key_beg.create_tid = 0;
        cursor.key_beg.delete_tid = 0;
@@ -1650,7 +1650,7 @@ hammer_vop_nrename(struct vop_nrename_args *ap)
 retry:
        hammer_init_cursor(&trans, &cursor, &fdip->cache[1], fdip);
        cursor.key_beg.localization = fdip->obj_localization +
-                                     HAMMER_LOCALIZE_MISC;
+                                     hammer_dir_localization(fdip);
         cursor.key_beg.obj_id = fdip->obj_id;
        cursor.key_beg.key = namekey;
         cursor.key_beg.create_tid = 0;
@@ -2814,7 +2814,7 @@ hammer_dounlink(hammer_transaction_t trans, struct nchandle *nch,
 retry:
        hammer_init_cursor(trans, &cursor, &dip->cache[1], dip);
        cursor.key_beg.localization = dip->obj_localization +
-                                     HAMMER_LOCALIZE_MISC;
+                                     hammer_dir_localization(dip);
         cursor.key_beg.obj_id = dip->obj_id;
        cursor.key_beg.key = namekey;
         cursor.key_beg.create_tid = 0;