From: wangdi Date: Tue, 25 Apr 2006 08:41:20 +0000 (+0000) Subject: Branch: b_new_cmd X-Git-Tag: v1_8_0_110~486^2~1934 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=e145ff31805bd822aa84ab0fce40ad4bc0d276a0;p=fs%2Flustre-release.git Branch: b_new_cmd update fld and iam prototype --- diff --git a/ldiskfs/ldiskfs/autoMakefile.am b/ldiskfs/ldiskfs/autoMakefile.am index 7e378c2..19b553c 100644 --- a/ldiskfs/ldiskfs/autoMakefile.am +++ b/ldiskfs/ldiskfs/autoMakefile.am @@ -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 diff --git a/lustre/fld/Makefile.in b/lustre/fld/Makefile.in index 15fd645..11ca873 100644 --- a/lustre/fld/Makefile.in +++ b/lustre/fld/Makefile.in @@ -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 index 0000000..e676c81 --- /dev/null +++ b/lustre/fld/fld_iam.c @@ -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 + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#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); +} + + diff --git a/lustre/fld/fld_internal.h b/lustre/fld/fld_internal.h index fa31006..4759b60 100644 --- a/lustre/fld/fld_internal.h +++ b/lustre/fld/fld_internal.h @@ -26,6 +26,15 @@ #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 diff --git a/lustre/fld/fld_seq.c b/lustre/fld/fld_seq.c index 23cb75d..6460d97 100644 --- a/lustre/fld/fld_seq.c +++ b/lustre/fld/fld_seq.c @@ -36,11 +36,13 @@ #include #include #include +#include #include #include #include #include +#include #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; diff --git a/lustre/include/linux/lustre_fid.h b/lustre/include/linux/lustre_fid.h index ed92c64..c30652a 100644 --- a/lustre/include/linux/lustre_fid.h +++ b/lustre/include/linux/lustre_fid.h @@ -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); diff --git a/lustre/kernel_patches/patches/ext3-iam-ops.patch b/lustre/kernel_patches/patches/ext3-iam-ops.patch index f0181d9..db328ac 100644 --- a/lustre/kernel_patches/patches/ext3-iam-ops.patch +++ b/lustre/kernel_patches/patches/ext3-iam-ops.patch @@ -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 + #include + #include + #include +@@ -111,7 +115,7 @@ + #include "xattr.h" + #include "iopen.h" + #include "acl.h" +- ++#include + /* + * 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); ++ diff --git a/lustre/ldiskfs/autoMakefile.am b/lustre/ldiskfs/autoMakefile.am index 7e378c2..19b553c 100644 --- a/lustre/ldiskfs/autoMakefile.am +++ b/lustre/ldiskfs/autoMakefile.am @@ -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