Whamcloud - gitweb
Branch: b_new_cmd
authorwangdi <wangdi>
Tue, 25 Apr 2006 08:41:20 +0000 (08:41 +0000)
committerwangdi <wangdi>
Tue, 25 Apr 2006 08:41:20 +0000 (08:41 +0000)
update fld and iam prototype

ldiskfs/ldiskfs/autoMakefile.am
lustre/fld/Makefile.in
lustre/fld/fld_iam.c [new file with mode: 0644]
lustre/fld/fld_internal.h
lustre/fld/fld_seq.c
lustre/include/linux/lustre_fid.h
lustre/kernel_patches/patches/ext3-iam-ops.patch
lustre/ldiskfs/autoMakefile.am

index 7e378c2..19b553c 100644 (file)
@@ -62,6 +62,7 @@ endif
                        linux-stage/include/linux/ext3$$i \
                        > linux/ldiskfs$$i ; \
        done
+       cp linux-stage/include/linux/lustre_iam.h linux/
        @echo
        touch sources
 
index 15fd645..11ca873 100644 (file)
@@ -1,4 +1,5 @@
 MODULES := fld 
-fld-objs := fld_seq.o
+fld-objs := fld_seq.o fld_iam.o
 
+EXTRA_PRE_CFLAGS := -I@LUSTRE@/ldiskfs/
 @INCLUDE_RULES@
diff --git a/lustre/fld/fld_iam.c b/lustre/fld/fld_iam.c
new file mode 100644 (file)
index 0000000..e676c81
--- /dev/null
@@ -0,0 +1,139 @@
+/* -*- MODE: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  fld/fld.c
+ *
+ *  Copyright (C) 2006 Cluster File Systems, Inc.
+ *   Author: WangDi <wangdi@clusterfs.com>
+ *
+ *   This file is part of the Lustre file system, http://www.lustre.org
+ *   Lustre is a trademark of Cluster File Systems, Inc.
+ *
+ *   You may have signed or agreed to another license before downloading
+ *   this software.  If so, you are bound by the terms and conditions
+ *   of that agreement, and the following does not apply to you.  See the
+ *   LICENSE file included with this distribution for more information.
+ *
+ *   If you did not agree to a different license, then this copy of Lustre
+ *   is open source software; you can redistribute it and/or modify it
+ *   under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ *
+ *   In either case, Lustre 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
+ *   license text for more details.
+ */
+#ifndef EXPORT_SYMTAB
+# define EXPORT_SYMTAB
+#endif
+#define DEBUG_SUBSYSTEM S_LLITE
+
+#include <linux/module.h>
+
+#include <linux/obd.h>
+#include <linux/obd_class.h>
+#include <linux/lustre_ver.h>
+#include <linux/obd_support.h>
+#include <linux/lprocfs_status.h>
+#include <linux/jbd.h>
+
+#include <linux/dt_object.h>
+#include <linux/md_object.h>
+#include <linux/lustre_mdc.h>
+#include <linux/lustre_fid.h>
+#include <linux/lustre_iam.h>
+#include "fld_internal.h"
+
+struct iam_key;
+struct iam_rec;
+
+struct fld_info fld_info;
+
+int fld_handle_insert(struct fld_info *fld_info, fidseq_t seq_num, mdsno_t mdsno)
+{
+        handle_t *handle = NULL;
+        return iam_insert(handle, &fld_info->fi_container,
+                          (struct iam_key *)&seq_num, (struct iam_rec *)&mdsno);
+}
+
+int fld_handle_delete(struct fld_info *fld_info, fidseq_t seq_num, mdsno_t mds_num)
+{
+        handle_t *handle = NULL;
+        return iam_delete(handle, &fld_info->fi_container, 
+                          (struct iam_key *)&seq_num);
+}
+
+int fld_handle_lookup(struct fld_info *fld_info, fidseq_t seq_num, mdsno_t *mds_num)
+{
+        mdsno_t mdsno;
+        int result;
+
+        result = iam_lookup(&fld_info->fi_container, (struct iam_key *)&seq_num,
+                            (struct iam_rec *)&mdsno);
+        if (result == 0)
+                return -ENOENT;
+        else if (result > 0)
+                return mdsno;
+        else
+                return result;
+}
+
+static u32 fld_root_ptr(struct iam_container *c)
+{
+        return 0;
+}
+static int fld_node_check(struct iam_path *path, struct iam_frame *frame)
+{
+        return 0;
+}
+static int fld_node_init(struct iam_container *c, struct buffer_head *bh, 
+                           int root)
+{
+        return 0;
+}
+static int fld_keycmp(struct iam_container *c,
+                        struct iam_key *k1, struct iam_key *k2)
+{
+        return key_cmp(le64_to_cpu(*(__u64 *)k1), le64_to_cpu(*(__u64 *)k2));
+}
+static int fld_node_read(struct iam_container *c, iam_ptr_t ptr,
+                           handle_t *h, struct buffer_head **bh)
+{
+        return 0;
+}
+
+
+static struct iam_descr fld_param = {
+        .id_key_size = sizeof ((struct lu_fid *)0)->f_seq,
+        .id_ptr_size = 4, /* 32 bit block numbers for now */
+        .id_rec_size = sizeof(mdsno_t),
+        .id_node_gap = 0, /* no gaps in index nodes */
+        .id_root_gap = 0,
+
+        .id_root_ptr   = fld_root_ptr, /* returns 0: root is always at the
+                                        * beginning of the file (as it
+                                        * htree) */
+        .id_node_read  = fld_node_read,
+        .id_node_check = fld_node_check,
+        .id_node_init  = fld_node_init,
+        .id_keycmp     = fld_keycmp
+};
+
+int fld_info_init(struct fld_info *fld_info)
+{
+        struct file *fld_file;
+
+        fld_file = filp_open("/fld", O_RDWR, S_IRWXU);
+        /* sanity and security checks... */
+        return iam_container_init(&fld_info->fi_container, &fld_param,
+                                  fld_file->f_dentry->d_inode);
+}
+
+void fld_info_fini(struct fld_info *fld_info)
+{
+        iam_container_fini(&fld_info->fi_container);
+        OBD_FREE_PTR(fld_info);
+}
+
+
index fa31006..4759b60 100644 (file)
 #ifndef _FLD_INTERNAL_H
 #define _FLD_INTERNAL_H
 
+#define mdsno_t  __u64
+#define fidseq_t __u64
+
+#define key_cmp(e1, e2) ({                              \
+        typeof(e1) __e1 = (e1);                         \
+        typeof(e2) __e2 = (e2);                         \
+        __e1 > __e2 ? +1 : (__e1 < __e2 ? -1 : 0);      \
+})
+
 struct fld_cache {
         struct hlist_node fld_list;
         __u64             fld_mds;
@@ -55,4 +64,15 @@ enum fld_op {
 
 #define FLD_SERVICE_WATCHDOG_TIMEOUT (obd_timeout * 1000)
 
+
+struct fld_info {
+        struct iam_container fi_container;
+};
+
+int fld_handle_insert(struct fld_info *fld, fidseq_t seq_num, mdsno_t mdsno);
+int fld_handle_delete(struct fld_info *fld, fidseq_t seq_num, mdsno_t mdsno);
+int fld_handle_lookup(struct fld_info *fld, fidseq_t seq_num, mdsno_t *mds);
+int fld_info_init(struct fld_info *fld_info);
+void fld_info_fini(struct fld_info *fld_info);
 #endif
index 23cb75d..6460d97 100644 (file)
 #include <linux/lustre_ver.h>
 #include <linux/obd_support.h>
 #include <linux/lprocfs_status.h>
+#include <linux/jbd.h>
 
 #include <linux/dt_object.h>
 #include <linux/md_object.h>
 #include <linux/lustre_mdc.h>
 #include <linux/lustre_fid.h>
+#include <linux/lustre_iam.h>
 #include "fld_internal.h"
 
 static int fld_handle(struct lu_context *ctx,
@@ -354,11 +356,18 @@ int fld_server_init(struct fld *fld, struct dt_device *dt)
                 .psc_watchdog_timeout = FLD_SERVICE_WATCHDOG_TIMEOUT,
                 .psc_num_threads      = FLD_NUM_THREADS
         };
+        struct fld_info *fld_info;
 
         fld->fld_dt = dt;
         lu_device_get(&dt->dd_lu_dev);
         INIT_LIST_HEAD(&fld_list_head.fld_list);
         spin_lock_init(&fld_list_head.fld_lock);
+        
+        OBD_ALLOC_PTR(fld_info);
+        if(!fld_info)
+                return -ENOMEM;
+        fld_info_init(fld_info); 
+        fld->fld_info = fld_info;
 
         fld->fld_service =
                 ptlrpc_init_svc_conf(&fld_conf, fld_req_handle,
@@ -369,8 +378,10 @@ int fld_server_init(struct fld *fld, struct dt_device *dt)
                                               LUSTRE_FLD0_NAME);
         else
                 result = -ENOMEM;
-        if (result != 0)
+        if (result != 0) {
                 fld_server_fini(fld);
+                fld_info_fini(fld_info);
+        }
         return result;
 }
 EXPORT_SYMBOL(fld_server_init);
@@ -393,76 +404,27 @@ void fld_server_fini(struct fld *fld)
         }
         spin_unlock(&fld_list_head.fld_lock);
         lu_device_put(&fld->fld_dt->dd_lu_dev);
+        fld_info_fini(fld->fld_info);
         fld->fld_dt = NULL;
 }
 EXPORT_SYMBOL(fld_server_fini);
 
-static int fld_handle_create(struct fld *pfld, __u64 seq_num, __u64 mds_num)
-{
-        struct fld_item *fld;
-
-        OBD_ALLOC_PTR(fld);
-        fld->fld_seq = seq_num;
-        fld->fld_mds = mds_num;
-        INIT_LIST_HEAD(&fld->fld_list);
-        spin_lock(&fld_list_head.fld_lock);
-        list_add_tail(&fld_list_head.fld_list, &fld->fld_list);
-        spin_unlock(&fld_list_head.fld_lock);
-        return 0;
-}
-
-static int fld_handle_delete(struct fld *pfld, __u64 seq_num, __u64 mds_num)
-{
-        struct list_head *pos, *n;
-        spin_lock(&fld_list_head.fld_lock);
-        list_for_each_safe(pos, n, &fld_list_head.fld_list) {
-                struct fld_item *fld = list_entry(pos, struct fld_item,
-                                                  fld_list);
-                if (fld->fld_seq == seq_num) {
-                        LASSERT(fld->fld_mds == mds_num);
-                        list_del_init(&fld->fld_list);
-                        OBD_FREE_PTR(fld);
-                        spin_unlock(&fld_list_head.fld_lock);
-                        RETURN(0);
-                }
-        }
-        spin_unlock(&fld_list_head.fld_lock);
-        RETURN(0);
-}
-
-static int fld_handle_get(struct fld *pfld, __u64 seq_num, __u64 *mds_num)
-{
-        struct list_head *pos, *n;
-
-        spin_lock(&fld_list_head.fld_lock);
-        list_for_each_safe(pos, n, &fld_list_head.fld_list) {
-                struct fld_item *fld = list_entry(pos, struct fld_item,
-                                                  fld_list);
-                if (fld->fld_seq == seq_num) {
-                        *mds_num = fld->fld_mds;
-                        spin_unlock(&fld_list_head.fld_lock);
-                        RETURN(0);
-                }
-        }
-        spin_unlock(&fld_list_head.fld_lock);
-        return -ENOENT;
-}
-
 static int fld_handle(struct lu_context *ctx,
                       struct fld *fld, __u32 opts, struct md_fld *mf)
 {
+        struct fld_info *fld_info = fld->fld_info;
         int rc;
         ENTRY;
 
         switch (opts) {
         case FLD_CREATE:
-                rc = fld_handle_create(fld, mf->mf_seq, mf->mf_mds);
+                rc = fld_handle_insert(fld_info, mf->mf_seq, mf->mf_mds);
                 break;
         case FLD_DELETE:
-                rc = fld_handle_delete(fld, mf->mf_seq, mf->mf_mds);
+                rc = fld_handle_delete(fld_info, mf->mf_seq, mf->mf_mds);
                 break;
         case FLD_GET:
-                rc = fld_handle_get(fld, mf->mf_seq, &mf->mf_mds);
+                rc = fld_handle_lookup(fld_info, mf->mf_seq, &mf->mf_mds);
                 break;
         default:
                 rc = -EINVAL;
index ed92c64..c30652a 100644 (file)
@@ -76,6 +76,7 @@ struct fld {
         struct proc_dir_entry   *fld_proc_entry;
         struct ptlrpc_service   *fld_service;
         struct dt_device        *fld_dt;
+        void                    *fld_info;
 };
 
 int  fld_server_init(struct fld *fld, struct dt_device *dt);
index f0181d9..db328ac 100644 (file)
@@ -1,7 +1,7 @@
 Index: linux-2.6.9/fs/ext3/namei.c
 ===================================================================
---- linux-2.6.9.orig/fs/ext3/namei.c   2006-04-23 22:05:38.000000000 +0800
-+++ linux-2.6.9/fs/ext3/namei.c        2006-04-23 22:22:58.000000000 +0800
+--- linux-2.6.9.orig/fs/ext3/namei.c   2006-04-25 15:43:37.000000000 +0800
++++ linux-2.6.9/fs/ext3/namei.c        2006-04-25 15:44:27.000000000 +0800
 @@ -82,13 +82,16 @@
   *
   * Entries in index node are sorted by their key value.
@@ -25,15 +25,292 @@ Index: linux-2.6.9/fs/ext3/namei.c
   *
   *
   *
-@@ -241,6 +244,7 @@
+@@ -96,6 +99,7 @@
+  *
+  */
++#include <linux/module.h>
+ #include <linux/fs.h>
+ #include <linux/pagemap.h>
+ #include <linux/jbd.h>
+@@ -111,7 +115,7 @@
+ #include "xattr.h"
+ #include "iopen.h"
+ #include "acl.h"
+-
++#include <linux/lustre_iam.h>
+ /*
+  * define how far ahead to read directories while searching them.
+  */
+@@ -120,13 +124,6 @@
+ #define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
+ #define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
+-/*
+- * Maximal number of non-leaf levels in htree. In the stock ext3 this is 2.
+- */
+-enum {
+-      DX_MAX_TREE_HEIGHT = 5,
+-      DX_SCRATCH_KEYS    = 2
+-};
+ static struct buffer_head *ext3_append(handle_t *handle,
+                                       struct inode *inode,
+@@ -205,194 +202,6 @@
+       u32 offs;
  };
  
- /* leaf node reached by tree lookup */
-+#define iam_leaf_entry iam_rec
- struct iam_leaf {
-       struct buffer_head *bh;
-       struct iam_leaf_entry *entries;
-@@ -508,6 +512,11 @@
+-/*
+- * Entry within index tree node. Consists of a key immediately followed
+- * (without padding) by a pointer to the child node.
+- *
+- * Both key and pointer are of variable size, hence incomplete type.
+- */
+-struct iam_entry;
+-
+-struct iam_entry_compat {
+-      __le32 hash;
+-      __le32 block;
+-};
+-
+-/*
+- * Incomplete type used to refer to keys in iam container.
+- *
+- * As key size can be different from container to container, iam has to use
+- * incomplete type. Clients cast pointer to iam_key to real key type and back.
+- */
+-struct iam_key;
+-
+-/* Incomplete type use to refer to the records stored in iam containers. */
+-struct iam_rec;
+-
+-typedef __u64 iam_ptr_t;
+-
+-/*
+- * Index node traversed during tree lookup.
+- */
+-struct iam_frame {
+-      struct buffer_head *bh;    /* buffer holding node data */
+-      struct iam_entry *entries; /* array of entries */
+-      struct iam_entry *at;      /* target entry, found by binary search */
+-};
+-
+-/* leaf node reached by tree lookup */
+-struct iam_leaf {
+-      struct buffer_head *bh;
+-      struct iam_leaf_entry *entries;
+-      struct iam_leaf_entry *at;
+-};
+-
+-struct iam_path;
+-struct iam_container;
+-
+-/*
+- * Parameters, describing a flavor of iam container.
+- */
+-struct iam_descr {
+-      /*
+-       * Size of a key in this container, in bytes.
+-       */
+-      size_t       id_key_size;
+-      /*
+-       * Size of a pointer to the next level (stored in index nodes), in
+-       * bytes.
+-       */
+-      size_t       id_ptr_size;
+-      /*
+-       * Size of a record (stored in leaf nodes), in bytes.
+-       */
+-      size_t       id_rec_size;
+-      /*
+-       * Size of unused (by iam) space at the beginning of every non-root
+-       * node, in bytes. Used for compatibility with ext3.
+-       */
+-      size_t       id_node_gap;
+-      /*
+-       * Size of unused (by iam) space at the beginning of root node, in
+-       * bytes. Used for compatibility with ext3.
+-       */
+-      size_t       id_root_gap;
+-
+-      /*
+-       * Returns pointer (in the same sense as pointer in index entry) to
+-       * the root node.
+-       */
+-      __u32 (*id_root_ptr)(struct iam_container *c);
+-
+-      /*
+-       * Check validity and consistency of index node. This is called when
+-       * iam just loaded new node into frame.
+-       */
+-      int (*id_node_check)(struct iam_path *path, struct iam_frame *frame);
+-      /*
+-       * Initialize new node (stored in @bh) that is going to be added into
+-       * tree.
+-       */
+-      int (*id_node_init)(struct iam_container *c,
+-                          struct buffer_head *bh, int root);
+-      int (*id_node_read)(struct iam_container *c, iam_ptr_t ptr,
+-                          handle_t *h, struct buffer_head **bh);
+-      /*
+-       * Key comparison function. Returns -1, 0, +1.
+-       */
+-      int (*id_keycmp)(struct iam_container *c,
+-                       struct iam_key *k1, struct iam_key *k2);
+-      /*
+-       * Create new container.
+-       *
+-       * Newly created container has a root node and a single leaf. Leaf
+-       * contains single record with the smallest possible key.
+-       */
+-      int (*id_create)(struct iam_container *c);
+-      struct {
+-              /*
+-               * leaf operations.
+-               */
+-              /*
+-               * returns true iff leaf is positioned at the last entry.
+-               */
+-              int (*at_end)(struct iam_container *c, struct iam_leaf *l);
+-              /* position leaf at the first entry */
+-              void (*start)(struct iam_container *c, struct iam_leaf *l);
+-              /* more leaf to the next entry. */
+-              void (*next)(struct iam_container *c, struct iam_leaf *l);
+-              /* return key of current leaf record in @k */
+-              void (*key)(struct iam_container *c, struct iam_leaf *l,
+-                          struct iam_key *k);
+-              /* return pointer to entry body */
+-              struct iam_rec *(*rec)(struct iam_container *c,
+-                                     struct iam_leaf *l);
+-      } id_leaf;
+-};
+-
+-struct iam_container {
+-      /*
+-       * Underlying flat file. IO against this object is issued to
+-       * read/write nodes.
+-       */
+-      struct inode     *ic_object;
+-      /*
+-       * container flavor.
+-       */
+-      struct iam_descr *ic_descr;
+-      /*
+-       * pointer to flavor-specific per-container data.
+-       */
+-      void             *ic_descr_data;
+-};
+-
+-/*
+- * Structure to keep track of a path drilled through htree.
+- */
+-struct iam_path {
+-      /*
+-       * Parent container.
+-       */
+-      struct iam_container  *ip_container;
+-      /*
+-       * Number of index levels minus one.
+-       */
+-      int                    ip_indirect;
+-      /*
+-       * Nodes that top-to-bottom traversal passed through.
+-       */
+-      struct iam_frame       ip_frames[DX_MAX_TREE_HEIGHT];
+-      /*
+-       * Last filled frame in ->ip_frames. Refers to the 'twig' node (one
+-       * immediately above leaf).
+-       */
+-      struct iam_frame      *ip_frame;
+-      /*
+-       * Leaf node: a child of ->ip_frame.
+-       */
+-      struct iam_leaf       *ip_leaf;
+-      /*
+-       * Key searched for.
+-       */
+-      struct iam_key        *ip_key_target;
+-      /*
+-       * Scratch-pad area for temporary keys.
+-       */
+-      struct iam_key        *ip_key_scratch[DX_SCRATCH_KEYS];
+-      /*
+-       * pointer to flavor-specific per-container data.
+-       */
+-      void                  *ip_descr_data;
+-};
+-
+-/*
+- * Helper structure for legacy htrees.
+- */
+-struct iam_path_compat {
+-      struct iam_path      ipc_path;
+-      struct iam_container ipc_container;
+-      __u32                ipc_scrach[DX_SCRATCH_KEYS];
+-};
+ static u32 htree_root_ptr(struct iam_container *c);
+ static int htree_node_check(struct iam_path *path, struct iam_frame *frame);
+@@ -427,58 +236,7 @@
+ struct iam_container;
+ struct iam_path;
+-/*
+- * Initialize container @c, acquires additional reference on @inode.
+- */
+-int iam_container_init(struct iam_container *c,
+-                     struct iam_descr *descr, struct inode *inode);
+-/*
+- * Finalize container @c, release all resources.
+- */
+-void iam_container_fini(struct iam_container *c);
+-/*
+- * Search container @c for record with key @k. If record is found, its data
+- * are moved into @r.
+- *
+- *
+- *
+- * Return values: +ve: found, 0: not-found, -ve: error
+- */
+-int iam_lookup(struct iam_container *c, struct iam_key *k, struct iam_rec *r);
+-/*
+- * Insert new record @r with key @k into container @c (within context of
+- * transaction @h.
+- *
+- * Return values: 0: success, -ve: error, including -EEXIST when record with
+- * given key is already present.
+- *
+- * postcondition: ergo(result == 0 || result == -EEXIST,
+- *                                  iam_lookup(c, k, r2) > 0 &&
+- *                                  !memcmp(r, r2, c->ic_descr->id_rec_size));
+- */
+-int iam_insert(handle_t *h, struct iam_container *c,
+-             struct iam_key *k, struct iam_rec *r);
+-/*
+- * Replace existing record with key @k, or insert new one. New record data are
+- * in @r.
+- *
+- * Return values: 0: success, -ve: error.
+- *
+- * postcondition: ergo(result == 0, iam_lookup(c, k, r2) > 0 &&
+- *                                  !memcmp(r, r2, c->ic_descr->id_rec_size));
+- */
+-int iam_update(handle_t *h, struct iam_container *c,
+-             struct iam_key *k, struct iam_rec *r);
+-/*
+- * Delete existing record with key @k.
+- *
+- * Return values: 0: success, -ENOENT: not-found, -ve: other error.
+- *
+- * postcondition: ergo(result == 0 || result == -ENOENT,
+- *                                 !iam_lookup(c, k, *));
+- */
+-int iam_delete(handle_t *h, struct iam_container *c, struct iam_key *k);
+ /*
+  * iam cursor (iterator) api.
+@@ -508,6 +266,11 @@
        IAM_IT_ATTACHED
  };
  
@@ -45,7 +322,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
  /*
   * Iterator.
   *
-@@ -704,7 +713,7 @@
+@@ -704,7 +467,7 @@
                             struct inode *inode);
  
  static inline void iam_path_init(struct iam_path *path,
@@ -54,7 +331,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
  static inline void iam_path_fini(struct iam_path *path);
  
  
-@@ -865,11 +874,6 @@
+@@ -865,11 +628,6 @@
        return 0;
  }
  
@@ -66,7 +343,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
  static int htree_node_check(struct iam_path *path, struct iam_frame *frame)
  {
        void *data;
-@@ -1171,11 +1175,13 @@
+@@ -1171,11 +929,13 @@
        }
  }
  
@@ -81,7 +358,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
  }
  
  static inline void iam_path_fini(struct iam_path *path)
-@@ -1201,7 +1207,7 @@
+@@ -1201,7 +961,7 @@
         * iam_path_fini().
         */
        iput(inode);
@@ -90,7 +367,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
        for (i = 0; i < ARRAY_SIZE(path->ipc_path.ip_key_scratch); ++i)
                path->ipc_path.ip_key_scratch[i] =
                        (struct iam_key *)&path->ipc_scrach[i];
-@@ -1213,6 +1219,382 @@
+@@ -1213,6 +973,425 @@
        iam_container_fini(&path->ipc_container);
  }
  
@@ -116,6 +393,15 @@ Index: linux-2.6.9/fs/ext3/namei.c
 +              brelse(leaf->bh);
 +}
 +
++/*
++ * Search container @c for record with key @k. If record is found, its data
++ * are moved into @r.
++ *
++ *
++ *
++ * Return values: +ve: found, 0: not-found, -ve: error
++ */
++
 +int iam_lookup(struct iam_container *c, struct iam_key *k, struct iam_rec *r)
 +{
 +      struct dx_hash_info     hinfo;
@@ -163,6 +449,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
 +      iam_path_fini(path);
 +      return(err);
 +}
++EXPORT_SYMBOL(iam_lookup);
 +
 +static inline size_t iam_leaf_entry_size(struct iam_path *p)
 +{
@@ -326,6 +613,17 @@ Index: linux-2.6.9/fs/ext3/namei.c
 +}
 +
 +static int split_index_node(handle_t *handle, struct iam_path *path);
++/*
++ * Insert new record @r with key @k into container @c (within context of
++ * transaction @h.
++ *
++ * Return values: 0: success, -ve: error, including -EEXIST when record with
++ * given key is already present.
++ *
++ * postcondition: ergo(result == 0 || result == -EEXIST,
++ *                                  iam_lookup(c, k, r2) > 0 &&
++ *                                  !memcmp(r, r2, c->ic_descr->id_rec_size));
++ */
 +int iam_insert(handle_t *handle, struct iam_container *c, struct iam_key *k, 
 +             struct iam_rec *r)
 +{
@@ -364,6 +662,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
 +      return(err);
 +}
 +
++EXPORT_SYMBOL(iam_insert);
 +static int iam_leaf_delete(handle_t *handle, struct iam_path *path, 
 +                         struct iam_key *k)
 +{
@@ -397,6 +696,14 @@ Index: linux-2.6.9/fs/ext3/namei.c
 +      return err;
 +}
 +
++/*
++ * Delete existing record with key @k.
++ *
++ * Return values: 0: success, -ENOENT: not-found, -ve: other error.
++ *
++ * postcondition: ergo(result == 0 || result == -ENOENT,
++ *                                 !iam_lookup(c, k, *));
++ */
 +int iam_delete(handle_t *h, struct iam_container *c, struct iam_key *k)
 +{
 +      struct dx_hash_info     hinfo;
@@ -421,6 +728,8 @@ Index: linux-2.6.9/fs/ext3/namei.c
 +      return err;
 +}
 +
++EXPORT_SYMBOL(iam_delete);
++
 +static int iam_leaf_update(handle_t *handle, struct iam_path *path, 
 +                         struct iam_key *k, struct iam_rec *r)
 +{
@@ -445,7 +754,15 @@ Index: linux-2.6.9/fs/ext3/namei.c
 +      iam_leaf_fini(&leaf);
 +      return err;
 +}
-+
++/*
++ * Replace existing record with key @k, or insert new one. New record data are
++ * in @r.
++ *
++ * Return values: 0: success, -ve: error.
++ *
++ * postcondition: ergo(result == 0, iam_lookup(c, k, r2) > 0 &&
++ *                                  !memcmp(r, r2, c->ic_descr->id_rec_size));
++ */
 +int iam_update(handle_t *h, struct iam_container *c,
 +             struct iam_key *k, struct iam_rec *r)
 +{
@@ -470,10 +787,13 @@ Index: linux-2.6.9/fs/ext3/namei.c
 +      iam_path_fini(path);
 +      return err;
 +}
++
++EXPORT_SYMBOL(iam_update);
++
  /*
   * This function increments the frame pointer to search the next leaf
   * block, and reads in the necessary intervening nodes if the search
-@@ -2213,59 +2595,21 @@
+@@ -2213,59 +2392,21 @@
  }
  
  #ifdef CONFIG_EXT3_INDEX
@@ -505,11 +825,11 @@ Index: linux-2.6.9/fs/ext3/namei.c
        int nr_splet;
 -      int i;
 -      size_t isize;
-+      int i, err;
+-
 -      iam_path_compat_init(&cpath, dir);
 -      param = path_descr(path);
--
++      int i, err;
 -      err = dx_probe(dentry, NULL, &hinfo, path);
 -      if (err != 0)
 -              return err;
@@ -539,7 +859,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
        /*
         * Tall-tree handling: we might have to split multiple index blocks
         * all the way up to tree root. Tricky point here is error handling:
-@@ -2288,7 +2632,7 @@
+@@ -2288,7 +2429,7 @@
             dx_get_count(frame->entries) == dx_get_limit(frame->entries);
             --frame, ++nr_splet) {
                if (nr_splet == DX_MAX_TREE_HEIGHT) {
@@ -548,7 +868,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
                                     "Directory index full!\n");
                        err = -ENOSPC;
                        goto cleanup;
-@@ -2301,7 +2645,7 @@
+@@ -2301,7 +2442,7 @@
        for (frame = safe + 1, i = 0; i < nr_splet; ++i, ++frame) {
                bh_new[i] = ext3_append (handle, dir, &newblock[i], &err);
                if (!bh_new[i] ||
@@ -557,7 +877,7 @@ Index: linux-2.6.9/fs/ext3/namei.c
                        goto cleanup;
                BUFFER_TRACE(frame->bh, "get_write_access");
                err = ext3_journal_get_write_access(handle, frame->bh);
-@@ -2407,23 +2751,81 @@
+@@ -2407,23 +2548,81 @@
                                goto journal_error;
                }
        }
@@ -644,3 +964,220 @@ Index: linux-2.6.9/fs/ext3/namei.c
        if (err)
                inode->i_size = isize;
        iam_path_fini(path);
+Index: linux-2.6.9/include/linux/lustre_iam.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/lustre_iam.h        2006-04-25 19:24:03.246335296 +0800
++++ linux-2.6.9/include/linux/lustre_iam.h     2006-04-25 15:44:44.000000000 +0800
+@@ -0,0 +1,212 @@
++/*
++ * Maximal number of non-leaf levels in htree. In the stock ext3 this is 2.
++ */
++enum {
++      DX_MAX_TREE_HEIGHT = 5,
++      DX_SCRATCH_KEYS    = 2
++};
++
++/*
++ * Entry within index tree node. Consists of a key immediately followed
++ * (without padding) by a pointer to the child node.
++ *
++ * Both key and pointer are of variable size, hence incomplete type.
++ */
++struct iam_entry;
++
++struct iam_entry_compat {
++      __le32 hash;
++      __le32 block;
++};
++
++/*
++ * Incomplete type used to refer to keys in iam container.
++ *
++ * As key size can be different from container to container, iam has to use
++ * incomplete type. Clients cast pointer to iam_key to real key type and back.
++ */
++struct iam_key;
++
++/* Incomplete type use to refer to the records stored in iam containers. */
++struct iam_rec;
++
++typedef __u64 iam_ptr_t;
++
++/*
++ * Index node traversed during tree lookup.
++ */
++struct iam_frame {
++      struct buffer_head *bh;    /* buffer holding node data */
++      struct iam_entry *entries; /* array of entries */
++      struct iam_entry *at;      /* target entry, found by binary search */
++};
++
++/* leaf node reached by tree lookup */
++#define iam_leaf_entry iam_rec
++struct iam_leaf {
++      struct buffer_head *bh;
++      struct iam_leaf_entry *entries;
++      struct iam_leaf_entry *at;
++};
++
++struct iam_path;
++struct iam_container;
++
++/*
++ * Parameters, describing a flavor of iam container.
++ */
++struct iam_descr {
++      /*
++       * Size of a key in this container, in bytes.
++       */
++      size_t       id_key_size;
++      /*
++       * Size of a pointer to the next level (stored in index nodes), in
++       * bytes.
++       */
++      size_t       id_ptr_size;
++      /*
++       * Size of a record (stored in leaf nodes), in bytes.
++       */
++      size_t       id_rec_size;
++      /*
++       * Size of unused (by iam) space at the beginning of every non-root
++       * node, in bytes. Used for compatibility with ext3.
++       */
++      size_t       id_node_gap;
++      /*
++       * Size of unused (by iam) space at the beginning of root node, in
++       * bytes. Used for compatibility with ext3.
++       */
++      size_t       id_root_gap;
++
++      /*
++       * Returns pointer (in the same sense as pointer in index entry) to
++       * the root node.
++       */
++      __u32 (*id_root_ptr)(struct iam_container *c);
++
++      /*
++       * Check validity and consistency of index node. This is called when
++       * iam just loaded new node into frame.
++       */
++      int (*id_node_check)(struct iam_path *path, struct iam_frame *frame);
++      /*
++       * Initialize new node (stored in @bh) that is going to be added into
++       * tree.
++       */
++      int (*id_node_init)(struct iam_container *c,
++                          struct buffer_head *bh, int root);
++      int (*id_node_read)(struct iam_container *c, iam_ptr_t ptr,
++                          handle_t *h, struct buffer_head **bh);
++      /*
++       * Key comparison function. Returns -1, 0, +1.
++       */
++      int (*id_keycmp)(struct iam_container *c,
++                       struct iam_key *k1, struct iam_key *k2);
++      /*
++       * Create new container.
++       *
++       * Newly created container has a root node and a single leaf. Leaf
++       * contains single record with the smallest possible key.
++       */
++      int (*id_create)(struct iam_container *c);
++      struct {
++              /*
++               * leaf operations.
++               */
++              /*
++               * returns true iff leaf is positioned at the last entry.
++               */
++              int (*at_end)(struct iam_container *c, struct iam_leaf *l);
++              /* position leaf at the first entry */
++              void (*start)(struct iam_container *c, struct iam_leaf *l);
++              /* more leaf to the next entry. */
++              void (*next)(struct iam_container *c, struct iam_leaf *l);
++              /* return key of current leaf record in @k */
++              void (*key)(struct iam_container *c, struct iam_leaf *l,
++                          struct iam_key *k);
++              /* return pointer to entry body */
++              struct iam_rec *(*rec)(struct iam_container *c,
++                                     struct iam_leaf *l);
++      } id_leaf;
++};
++
++struct iam_container {
++      /*
++       * Underlying flat file. IO against this object is issued to
++       * read/write nodes.
++       */
++      struct inode     *ic_object;
++      /*
++       * container flavor.
++       */
++      struct iam_descr *ic_descr;
++      /*
++       * pointer to flavor-specific per-container data.
++       */
++      void             *ic_descr_data;
++};
++
++/*
++ * Structure to keep track of a path drilled through htree.
++ */
++struct iam_path {
++      /*
++       * Parent container.
++       */
++      struct iam_container  *ip_container;
++      /*
++       * Number of index levels minus one.
++       */
++      int                    ip_indirect;
++      /*
++       * Nodes that top-to-bottom traversal passed through.
++       */
++      struct iam_frame       ip_frames[DX_MAX_TREE_HEIGHT];
++      /*
++       * Last filled frame in ->ip_frames. Refers to the 'twig' node (one
++       * immediately above leaf).
++       */
++      struct iam_frame      *ip_frame;
++      /*
++       * Leaf node: a child of ->ip_frame.
++       */
++      struct iam_leaf       *ip_leaf;
++      /*
++       * Key searched for.
++       */
++      struct iam_key        *ip_key_target;
++      /*
++       * Scratch-pad area for temporary keys.
++       */
++      struct iam_key        *ip_key_scratch[DX_SCRATCH_KEYS];
++      /*
++       * pointer to flavor-specific per-container data.
++       */
++      void                  *ip_descr_data;
++};
++
++/*
++ * Helper structure for legacy htrees.
++ */
++struct iam_path_compat {
++      struct iam_path      ipc_path;
++      struct iam_container ipc_container;
++      __u32                ipc_scrach[DX_SCRATCH_KEYS];
++};
++
++int iam_lookup(struct iam_container *c, struct iam_key *k, struct iam_rec *r);
++int iam_delete(handle_t *h, struct iam_container *c, struct iam_key *k);
++int iam_update(handle_t *h, struct iam_container *c, struct iam_key *k, struct iam_rec *r);
++int iam_insert(handle_t *handle, struct iam_container *c, struct iam_key *k, struct iam_rec *r);
++/*
++ * Initialize container @c, acquires additional reference on @inode.
++ */
++int iam_container_init(struct iam_container *c,
++                     struct iam_descr *descr, struct inode *inode);
++/*
++ * Finalize container @c, release all resources.
++ */
++void iam_container_fini(struct iam_container *c);
++
index 7e378c2..19b553c 100644 (file)
@@ -62,6 +62,7 @@ endif
                        linux-stage/include/linux/ext3$$i \
                        > linux/ldiskfs$$i ; \
        done
+       cp linux-stage/include/linux/lustre_iam.h linux/
        @echo
        touch sources