'unlabeled-1.1.2.1.2'.
+++ /dev/null
-.deps
-Makefile
-Makefile.in
+++ /dev/null
-# Copyright (C) 2002 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-
-MODULE = cobd
-modulefs_DATA = cobd.o
-EXTRA_PROGRAMS = cobd
-LINX=
-
-cobd_SOURCES = cache_obd.c lproc_cache.c $(LINX)
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#define DEBUG_SUBSYSTEM S_COBD
-
-#include <linux/obd_support.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_idl.h>
-#include <linux/obd_class.h>
-#include <linux/obd_cache.h>
-
-extern struct lprocfs_vars status_var_nm_1[];
-extern struct lprocfs_vars status_class_var[];
-
-static int
-cobd_attach (struct obd_device *dev, obd_count len, void *data)
-{
- return (lprocfs_reg_obd (dev, status_var_nm_1, dev));
-}
-
-static int
-cobd_detach (struct obd_device *dev)
-{
- return (lprocfs_dereg_obd (dev));
-}
-
-static int
-cobd_setup (struct obd_device *dev, obd_count len, void *buf)
-{
- struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
- struct cache_obd *cobd = &dev->u.cobd;
- struct obd_device *target;
- struct obd_device *cache;
- int rc;
-
- if (data->ioc_inlbuf1 == NULL ||
- data->ioc_inlbuf2 == NULL)
- return (-EINVAL);
-
- target = class_uuid2obd (data->ioc_inlbuf1);
- cache = class_uuid2obd (data->ioc_inlbuf2);
- if (target == NULL ||
- cache == NULL)
- return (-EINVAL);
-
- /* don't bother checking attached/setup;
- * obd_connect() should, and it can change underneath us */
-
- rc = obd_connect (&cobd->cobd_target, target, NULL, NULL, NULL);
- if (rc != 0)
- return (rc);
-
- rc = obd_connect (&cobd->cobd_cache, cache, NULL, NULL, NULL);
- if (rc != 0)
- goto fail_0;
-
- MOD_INC_USE_COUNT;
- return (0);
-
- fail_0:
- obd_disconnect (&cobd->cobd_target);
- return (rc);
-}
-
-static int
-cobd_cleanup (struct obd_device *dev)
-{
- struct cache_obd *cobd = &dev->u.cobd;
- int rc;
-
- if (!list_empty (&dev->obd_exports))
- return (-EBUSY);
-
- rc = obd_disconnect (&cobd->cobd_cache);
- if (rc != 0)
- CERROR ("error %d disconnecting cache\n", rc);
-
- rc = obd_disconnect (&cobd->cobd_target);
- if (rc != 0)
- CERROR ("error %d disconnecting target\n", rc);
-
- MOD_DEC_USE_COUNT;
- return (0);
-}
-
-static int
-cobd_connect (struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- int rc = class_connect (conn, obd, cluuid);
-
- CERROR ("rc %d\n", rc);
- return (rc);
-}
-
-static int
-cobd_disconnect (struct lustre_handle *conn)
-{
- int rc = class_disconnect (conn);
-
- CERROR ("rc %d\n", rc);
- return (rc);
-}
-
-static int
-cobd_get_info(struct lustre_handle *conn, obd_count keylen,
- void *key, obd_count *vallen, void **val)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- cobd = &obd->u.cobd;
-
- /* intercept cache utilisation info? */
-
- return (obd_get_info (&cobd->cobd_target,
- keylen, key, vallen, val));
-}
-
-static int
-cobd_statfs(struct lustre_handle *conn, struct obd_statfs *osfs)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- cobd = &obd->u.cobd;
- return (obd_statfs (&cobd->cobd_target, osfs));
-}
-
-static int
-cobd_getattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- cobd = &obd->u.cobd;
- return (obd_getattr (&cobd->cobd_target, oa, lsm));
-}
-
-static int
-cobd_open(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- cobd = &obd->u.cobd;
- return (obd_open (&cobd->cobd_target, oa, lsm));
-}
-
-static int
-cobd_close(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- cobd = &obd->u.cobd;
- return (obd_close (&cobd->cobd_target, oa, lsm));
-}
-
-static int
-cobd_preprw(int cmd, struct lustre_handle *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_remote *nb,
- struct niobuf_local *res, void **desc_private)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- if ((cmd & OBD_BRW_WRITE) != 0)
- return -EOPNOTSUPP;
-
- cobd = &obd->u.cobd;
- return (obd_preprw (cmd, &cobd->cobd_target,
- objcount, obj,
- niocount, nb,
- res, desc_private));
-}
-
-static int
-cobd_commitrw(int cmd, struct lustre_handle *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_local *local,
- void *desc_private)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- if ((cmd & OBD_BRW_WRITE) != 0)
- return -EOPNOTSUPP;
-
- cobd = &obd->u.cobd;
- return (obd_commitrw (cmd, &cobd->cobd_target,
- objcount, obj,
- niocount, local,
- desc_private));
-}
-
-static inline int
-cobd_brw(int cmd, struct lustre_handle *conn,
- struct lov_stripe_md *lsm, obd_count oa_bufs,
- struct brw_page *pga, struct obd_brw_set *set)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- if ((cmd & OBD_BRW_WRITE) != 0)
- return -EOPNOTSUPP;
-
- cobd = &obd->u.cobd;
- return (obd_brw (cmd, &cobd->cobd_target,
- lsm, oa_bufs, pga, set));
-}
-
-static int
-cobd_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len,
- void *karg, void *uarg)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- /* intercept? */
-
- cobd = &obd->u.cobd;
- return (obd_iocontrol (cmd, &cobd->cobd_target, len, karg, uarg));
-}
-
-static struct obd_ops cobd_ops = {
- o_attach: cobd_attach,
- o_detach: cobd_detach,
-
- o_setup: cobd_setup,
- o_cleanup: cobd_cleanup,
-
- o_connect: cobd_connect,
- o_disconnect: cobd_disconnect,
-
- o_get_info: cobd_get_info,
- o_statfs: cobd_statfs,
-
- o_getattr: cobd_getattr,
- o_open: cobd_open,
- o_close: cobd_close,
- o_preprw: cobd_preprw,
- o_commitrw: cobd_commitrw,
- o_brw: cobd_brw,
- o_iocontrol: cobd_iocontrol,
-};
-
-static int __init
-cobd_init (void)
-{
- int rc;
-
- printk (KERN_INFO "Lustre Caching OBD driver\n");
-
- rc = class_register_type (&cobd_ops, status_class_var,
- OBD_CACHE_DEVICENAME);
- return (rc);
-}
-
-static void __exit
-cobd_exit (void)
-{
- class_unregister_type (OBD_CACHE_DEVICENAME);
-}
-
-MODULE_AUTHOR("Cluster Filesystems Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Caching OBD driver");
-MODULE_LICENSE("GPL");
-
-module_init(cobd_init);
-module_exit(cobd_exit);
-
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-/*
- * Common STATUS namespace
- */
-
-static int
-rd_uuid (char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
-
- return (snprintf(page, count, "%s\n", dev->obd_uuid));
-}
-
-static int
-rd_target (char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct obd_device *dev = (struct obd_device*)data;
- struct cache_obd *cobd = &dev->u.cobd;
- struct lustre_handle *conn = &cobd->cobd_target;
- struct obd_export *exp;
- int rc;
-
- if ((dev->obd_flags & OBD_SET_UP) == 0)
- rc = snprintf (page, count, "not set up\n");
- else {
- exp = class_conn2export (conn);
- LASSERT (exp != NULL);
- rc = snprintf(page, count, "%s\n", exp->exp_obd->obd_uuid);
- }
- return (rc);
-}
-
-static int
-rd_cache (char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct obd_device *dev = (struct obd_device*)data;
- struct cache_obd *cobd = &dev->u.cobd;
- struct lustre_handle *conn = &cobd->cobd_cache;
- struct obd_export *exp;
- int rc;
-
- if ((dev->obd_flags & OBD_SET_UP) == 0)
- rc = snprintf (page, count, "not set up\n");
- else {
- exp = class_conn2export (conn);
- LASSERT (exp != NULL);
- rc = snprintf(page, count, "%s\n", exp->exp_obd->obd_uuid);
- }
- return (rc);
-}
-
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {"status/target_uuid", rd_target, 0, 0},
- {"status/cache_uuid", rd_cache, 0, 0},
-
- {0}
-};
-
-int
-rd_numrefs (char* page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
-
- return (snprintf(page, count, "%d\n", class->typ_refcnt));
-}
-
-struct lprocfs_vars status_class_var[] = {
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
-};
+++ /dev/null
-balloc.c
-bitmap.c
-dir.c
-file.c
-fsync.c
-ialloc.c
-inode.c
-ioctl.c
-namei.c
-super.c
-symlink.c
+++ /dev/null
---- linux-2.4.17/fs/extN/super.c.orig Fri Dec 21 10:41:55 2001
-+++ linux-2.4.17/fs/extN/super.c Fri Mar 22 11:00:41 2002
-@@ -1742,7 +1742,7 @@
- unregister_filesystem(&extN_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(extN_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
+++ /dev/null
---- ./include/linux/extN_fs.h.orig Tue May 7 17:06:03 2002
-+++ ./include/linux/extN_fs.h Tue May 7 17:07:11 2002
-@@ -17,6 +17,8 @@
- #define _LINUX_EXTN_FS_H
-
- #include <linux/types.h>
-+#include <linux/extN_fs_sb.h>
-+#include <linux/extN_fs_i.h>
-
- /*
- * The second extended filesystem constants/structures
-@@ -86,8 +88,8 @@
- #define EXTN_MIN_BLOCK_LOG_SIZE 10
-
- #ifdef __KERNEL__
--#define EXTN_SB(sb) (&((sb)->u.extN_sb))
--#define EXTN_I(inode) (&((inode)->u.extN_i))
-+#define EXTN_SB(sb) ((struct extN_sb_info *)&((sb)->u.generic_sbp))
-+#define EXTN_I(inode) ((struct extN_inode_info *)&((inode)->u.generic_ip))
-
- #define EXTN_BLOCK_SIZE(s) ((s)->s_blocksize)
- #define EXTN_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -445,7 +445,9 @@
- };
-
- #define NEXT_ORPHAN(inode) EXTN_I(inode)->i_dtime
--#define orphan_list_entry(l) list_entry((l), struct inode, u.extN_i.i_orphan)
-+#define orphan_list_entry(l) ((struct inode *)((char *)(l) - \
-+ (unsigned long)(offsetof(struct inode, u.generic_ip) + \
-+ offsetof(struct extN_inode_info, i_orphan))))
-
- /*
- * Codes for operating systems
+++ /dev/null
---- linux-2.4.17/fs/extN/super.c.orig Fri Dec 21 10:41:55 2001
-+++ linux-2.4.17/fs/extN/super.c Fri Mar 22 11:00:41 2002
-@@ -1344,10 +1342,10 @@
- printk(KERN_ERR "EXTN-fs: I/O error on journal device\n");
- goto out_journal;
- }
-- if (ntohl(journal->j_superblock->s_nr_users) != 1) {
-+ if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
- printk(KERN_ERR "EXTN-fs: External journal has more than one "
- "user (unsupported) - %d\n",
-- ntohl(journal->j_superblock->s_nr_users));
-+ be32_to_cpu(journal->j_superblock->s_nr_users));
- goto out_journal;
- }
- EXTN_SB(sb)->journal_bdev = bdev;
+++ /dev/null
---- ./fs/ext3/dir.c 2002/03/05 06:18:59 2.1
-+++ ./fs/ext3/dir.c 2002/03/05 06:26:56
-@@ -26,7 +26,7 @@
- DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
- };
-
--static int ext3_readdir(struct file *, void *, filldir_t);
-+int ext3_readdir(struct file *, void *, filldir_t);
-
- struct file_operations ext3_dir_operations = {
- read: generic_read_dir,
-@@ -65,7 +65,7 @@
- return error_msg == NULL ? 1 : 0;
- }
-
--static int ext3_readdir(struct file * filp,
-+int ext3_readdir(struct file * filp,
- void * dirent, filldir_t filldir)
- {
- int error = 0;
---- ./fs/ext3/super.c 2002/03/05 06:18:59 2.1
-+++ ./fs/ext3/super.c 2002/03/05 06:26:56
-@@ -529,6 +529,12 @@
- "EXT3 Check option not supported\n");
- #endif
- }
-+ else if (!strcmp (this_char, "index"))
-+#ifdef CONFIG_EXT3_INDEX
-+ set_opt (*mount_options, INDEX);
-+#else
-+ printk("EXT3 index option not supported\n");
-+#endif
- else if (!strcmp (this_char, "debug"))
- set_opt (*mount_options, DEBUG);
- else if (!strcmp (this_char, "errors")) {
-@@ -712,6 +718,10 @@
- EXT3_BLOCKS_PER_GROUP(sb),
- EXT3_INODES_PER_GROUP(sb),
- sbi->s_mount_opt);
-+
-+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
-+ set_opt (EXT3_SB(sb)->s_mount_opt, INDEX);
-+
- printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ",
- bdevname(sb->s_dev));
- if (EXT3_SB(sb)->s_journal->j_inode == NULL) {
---- ./fs/ext3/namei.c 2002/03/05 06:18:59 2.1
-+++ ./fs/ext3/namei.c 2002/03/06 00:13:18
-@@ -16,6 +16,10 @@
- * David S. Miller (davem@caip.rutgers.edu), 1995
- * Directory entry file type support and forward compatibility hooks
- * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
-+ * Hash Tree Directory indexing (c)
-+ * Daniel Phillips, 2001
-+ * Hash Tree Directory indexing porting
-+ * Christopher Li, 2002
- */
-
- #include <linux/fs.h>
-@@ -38,6 +42,435 @@
- #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
- #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
-
-+void ext3_add_compat_feature (struct super_block *sb, unsigned feature)
-+{
-+ if (!EXT3_HAS_COMPAT_FEATURE(sb, feature))
-+ {
-+ lock_super(sb);
-+ ext3_update_dynamic_rev(sb);
-+ EXT3_SET_COMPAT_FEATURE(sb, feature);
-+ ext3_write_super(sb);
-+ unlock_super(sb);
-+ }
-+}
-+
-+static struct buffer_head *ext3_append (handle_t *handle,
-+ struct inode *inode,
-+ u32 *block, int *err)
-+{
-+ struct buffer_head *bh;
-+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
-+ if((bh = ext3_bread (handle,inode, *block, 1, err))) {
-+ inode->i_size += inode->i_sb->s_blocksize;
-+ ext3_journal_get_write_access(handle,bh);
-+ }
-+ return bh;
-+}
-+
-+#ifndef assert
-+#define assert(test) do if (!(test)) BUG(); while (0)
-+#endif
-+
-+#ifndef swap
-+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
-+#endif
-+
-+typedef struct { u32 v; } le_u32;
-+typedef struct { u16 v; } le_u16;
-+
-+#define dxtrace_on(command) command
-+#define dxtrace_off(command)
-+#define dxtrace dxtrace_off
-+
-+struct fake_dirent
-+{
-+ /*le*/u32 inode;
-+ /*le*/u16 rec_len;
-+ u8 name_len;
-+ u8 file_type;
-+};
-+
-+struct dx_countlimit
-+{
-+ le_u16 limit;
-+ le_u16 count;
-+};
-+
-+struct dx_entry
-+{
-+ le_u32 hash;
-+ le_u32 block;
-+};
-+
-+/*
-+ * dx_root_info is laid out so that if it should somehow get overlaid by a
-+ * dirent the two low bits of the hash version will be zero. Therefore, the
-+ * hash version mod 4 should never be 0. Sincerely, the paranoia department.
-+ */
-+
-+struct dx_root
-+{
-+ struct fake_dirent fake1;
-+ char dot1[4];
-+ struct fake_dirent fake2;
-+ char dot2[4];
-+ struct dx_root_info
-+ {
-+ le_u32 reserved_zero;
-+ u8 hash_version; /* 0 now, 1 at release */
-+ u8 info_length; /* 8 */
-+ u8 indirect_levels;
-+ u8 unused_flags;
-+ }
-+ info;
-+ struct dx_entry entries[0];
-+};
-+
-+struct dx_node
-+{
-+ struct fake_dirent fake;
-+ struct dx_entry entries[0];
-+};
-+
-+
-+struct dx_frame
-+{
-+ struct buffer_head *bh;
-+ struct dx_entry *entries;
-+ struct dx_entry *at;
-+};
-+
-+struct dx_map_entry
-+{
-+ u32 hash;
-+ u32 offs;
-+};
-+
-+typedef struct ext3_dir_entry_2 ext3_dirent;
-+static inline unsigned dx_get_block (struct dx_entry *entry);
-+static void dx_set_block (struct dx_entry *entry, unsigned value);
-+static inline unsigned dx_get_hash (struct dx_entry *entry);
-+static void dx_set_hash (struct dx_entry *entry, unsigned value);
-+static unsigned dx_get_count (struct dx_entry *entries);
-+static unsigned dx_get_limit (struct dx_entry *entries);
-+static void dx_set_count (struct dx_entry *entries, unsigned value);
-+static void dx_set_limit (struct dx_entry *entries, unsigned value);
-+static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
-+static unsigned dx_node_limit (struct inode *dir);
-+static unsigned dx_hack_hash (const u8 *name, int len);
-+static struct dx_frame *dx_probe (struct inode *dir, u32 hash, struct dx_frame *frame);
-+static void dx_release (struct dx_frame *frames);
-+static int dx_make_map (ext3_dirent *de, int size, struct dx_map_entry map[]);
-+static void dx_sort_map(struct dx_map_entry *map, unsigned count);
-+static ext3_dirent *dx_copy_dirents (char *from, char *to,
-+ struct dx_map_entry *map, int count);
-+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
-+
-+
-+#ifdef CONFIG_EXT3_INDEX
-+/*
-+ * Future: use high four bits of block for coalesce-on-delete flags
-+ * Mask them off for now.
-+ */
-+
-+static inline unsigned dx_get_block (struct dx_entry *entry)
-+{
-+ return le32_to_cpu(entry->block.v) & 0x0fffffff;
-+}
-+
-+static inline void dx_set_block (struct dx_entry *entry, unsigned value)
-+{
-+ entry->block.v = cpu_to_le32(value);
-+}
-+
-+static inline unsigned dx_get_hash (struct dx_entry *entry)
-+{
-+ return le32_to_cpu(entry->hash.v);
-+}
-+
-+static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
-+{
-+ entry->hash.v = cpu_to_le32(value);
-+}
-+
-+static inline unsigned dx_get_count (struct dx_entry *entries)
-+{
-+ return le16_to_cpu(((struct dx_countlimit *) entries)->count.v);
-+}
-+
-+static inline unsigned dx_get_limit (struct dx_entry *entries)
-+{
-+ return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v);
-+}
-+
-+static inline void dx_set_count (struct dx_entry *entries, unsigned value)
-+{
-+ ((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value);
-+}
-+
-+static inline void dx_set_limit (struct dx_entry *entries, unsigned value)
-+{
-+ ((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value);
-+}
-+
-+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
-+{
-+ unsigned entry_space = dir->i_sb->s_blocksize - 24 - infosize;
-+ return 0? 20: entry_space / sizeof(struct dx_entry);
-+}
-+
-+static inline unsigned dx_node_limit (struct inode *dir)
-+{
-+ unsigned entry_space = dir->i_sb->s_blocksize - sizeof(struct fake_dirent);
-+ return 0? 22: entry_space / sizeof(struct dx_entry);
-+}
-+
-+/* Hash function - not bad, but still looking for an ideal default */
-+
-+static unsigned dx_hack_hash (const u8 *name, int len)
-+{
-+ u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
-+ while (len--)
-+ {
-+ u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
-+ if (hash & 0x80000000) hash -= 0x7fffffff;
-+ hash1 = hash0;
-+ hash0 = hash;
-+ }
-+ return 80; /* FIXME: for test only */
-+ return hash0;
-+}
-+
-+#define dx_hash(s,n) (dx_hack_hash(s,n) << 1)
-+
-+/*
-+ * Debug
-+ */
-+static void dx_show_index (char * label, struct dx_entry *entries)
-+{
-+ int i, n = dx_get_count (entries);
-+ printk("%s index ", label);
-+ for (i = 0; i < n; i++)
-+ {
-+ printk("%x->%u ", i? dx_get_hash(entries + i): 0, dx_get_block(entries + i));
-+ }
-+ printk("\n");
-+}
-+
-+struct stats
-+{
-+ unsigned names;
-+ unsigned space;
-+ unsigned bcount;
-+};
-+
-+static struct stats dx_show_leaf (ext3_dirent *de, int size, int show_names)
-+{
-+ unsigned names = 0, space = 0;
-+ char *base = (char *) de;
-+ printk("names: ");
-+ while ((char *) de < base + size)
-+ {
-+ if (de->inode)
-+ {
-+ if (show_names)
-+ {
-+ int len = de->name_len;
-+ char *name = de->name;
-+ while (len--) printk("%c", *name++);
-+ printk(":%x.%u ", dx_hash (de->name, de->name_len), ((char *) de - base));
-+ }
-+ space += EXT3_DIR_REC_LEN(de->name_len);
-+ names++;
-+ }
-+ de = (ext3_dirent *) ((char *) de + le16_to_cpu(de->rec_len));
-+ }
-+ printk("(%i)\n", names);
-+ return (struct stats) { names, space, 1 };
-+}
-+
-+struct stats dx_show_entries (struct inode *dir, struct dx_entry *entries, int levels)
-+{
-+ unsigned blocksize = dir->i_sb->s_blocksize;
-+ unsigned count = dx_get_count (entries), names = 0, space = 0, i;
-+ unsigned bcount = 0;
-+ struct buffer_head *bh;
-+ int err;
-+ printk("%i indexed blocks...\n", count);
-+ for (i = 0; i < count; i++, entries++)
-+ {
-+ u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0;
-+ u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
-+ struct stats stats;
-+ printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range);
-+ if (!(bh = ext3_bread (NULL,dir, block, 0,&err))) continue;
-+ stats = levels?
-+ dx_show_entries (dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
-+ dx_show_leaf ((ext3_dirent *) bh->b_data, blocksize, 0);
-+ names += stats.names;
-+ space += stats.space;
-+ bcount += stats.bcount;
-+ brelse (bh);
-+ }
-+ if (bcount)
-+ printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ",
-+ names, space/bcount,(space/bcount)*100/blocksize);
-+ return (struct stats) { names, space, bcount};
-+}
-+
-+static void dx_show_buckets (struct inode *dir)
-+{
-+ struct buffer_head *bh;
-+ struct dx_root *root;
-+ int err;
-+ if (!(bh = ext3_bread (NULL,dir, 0, 0,&err))) return;
-+ root = (struct dx_root *) bh->b_data;
-+ dx_show_entries (dir, root->entries, root->info.indirect_levels);
-+ brelse (bh);
-+}
-+
-+ssize_t hack_show_dir (struct file * filp, void * dirent, filldir_t filldir)
-+{
-+ if (is_dx (filp->f_dentry->d_inode) && !filp->f_pos)
-+ dx_show_buckets (filp->f_dentry->d_inode);
-+ return ext3_readdir(filp,dirent,filldir);
-+}
-+
-+/*
-+ * Probe for a directory leaf block to search
-+ */
-+
-+static struct dx_frame *dx_probe (struct inode *dir, u32 hash, struct dx_frame *frame)
-+{
-+ unsigned count, indirect;
-+ struct dx_entry *at, *entries, *p, *q, *m;
-+ struct dx_root *root;
-+ struct buffer_head *bh;
-+ int err;
-+ if (!(bh = ext3_bread (NULL,dir, 0, 0,&err)))
-+ goto fail;
-+ root = (struct dx_root *) bh->b_data;
-+ if (root->info.hash_version > 0 || root->info.unused_flags & 1)
-+ goto fail;
-+ if ((indirect = root->info.indirect_levels) > 1)
-+ goto fail;
-+ entries = (struct dx_entry *) (((char *) &root->info) + root->info.info_length);
-+ assert (dx_get_limit(entries) == dx_root_limit(dir, root->info.info_length));
-+ dxtrace (printk("Look up %x", hash));
-+ while (1)
-+ {
-+ count = dx_get_count(entries);
-+ assert (count && count <= dx_get_limit(entries));
-+ p = entries + 1;
-+ q = entries + count - 1;
-+ while (p <= q)
-+ {
-+ m = p + (q - p)/2;
-+ dxtrace(printk("."));
-+ if (dx_get_hash(m) > hash)
-+ q = m - 1;
-+ else
-+ p = m + 1;
-+ }
-+
-+ if (0) // linear search cross check
-+ {
-+ unsigned n = count - 1;
-+ at = entries;
-+ while (n--)
-+ {
-+ dxtrace(printk(","));
-+ if (dx_get_hash(++at) > hash)
-+ {
-+ at--;
-+ break;
-+ }
-+ }
-+ assert (at == p - 1);
-+ }
-+
-+ at = p - 1;
-+ dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
-+ frame->bh = bh;
-+ frame->entries = entries;
-+ frame->at = at;
-+ if (!indirect--) return frame;
-+ if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0,&err)))
-+ goto fail2;
-+ at = entries = ((struct dx_node *) bh->b_data)->entries;
-+ assert (dx_get_limit(entries) == dx_node_limit (dir));
-+ frame++;
-+ }
-+fail2:
-+ brelse(frame->bh);
-+fail:
-+ return NULL;
-+}
-+
-+static void dx_release (struct dx_frame *frames)
-+{
-+ if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
-+ brelse (frames[1].bh);
-+ brelse (frames[0].bh);
-+}
-+
-+/*
-+ * Directory block splitting, compacting
-+ */
-+
-+static int dx_make_map (ext3_dirent *de, int size, struct dx_map_entry map[])
-+{
-+ int count = 0;
-+ char *base = (char *) de;
-+ while ((char *) de < base + size)
-+ {
-+ map[count].hash = dx_hash (de->name, de->name_len);
-+ map[count].offs = (u32) ((char *) de - base);
-+ de = (ext3_dirent *) ((char *) de + le16_to_cpu(de->rec_len));
-+ count++;
-+ }
-+ return count;
-+}
-+
-+static void dx_sort_map (struct dx_map_entry *map, unsigned count)
-+{
-+ struct dx_map_entry *p, *q, *top = map + count - 1;
-+ int more;
-+ /* Combsort until bubble sort doesn't suck */
-+ while (count > 2)
-+ {
-+ count = count*10/13;
-+ if (count - 9 < 2) /* 9, 10 -> 11 */
-+ count = 11;
-+ for (p = top, q = p - count; q >= map; p--, q--)
-+ if (p->hash < q->hash)
-+ swap(*p, *q);
-+ }
-+ /* Garden variety bubble sort */
-+ do {
-+ more = 0;
-+ q = top;
-+ while (q-- > map)
-+ {
-+ if (q[1].hash >= q[0].hash)
-+ continue;
-+ swap(*(q+1), *q);
-+ more = 1;
-+ }
-+ } while(more);
-+}
-+
-+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block)
-+{
-+ struct dx_entry *entries = frame->entries, *at = frame->at;
-+ assert (dx_get_count (entries) < dx_get_limit (entries));
-+ memmove (at + 2, at+1, (char *) (entries + dx_get_count(entries)) - (char *) (at));
-+ dx_set_hash(at + 1, hash);
-+ dx_set_block(at + 1, block);
-+ dx_set_count(entries, dx_get_count(entries) + 1);
-+}
-+#endif
-+
- /*
- * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure.
- *
-@@ -95,6 +529,15 @@
- }
-
- /*
-+ * p is at least 6 bytes before the end of page
-+ */
-+static inline ext3_dirent *ext3_next_entry(ext3_dirent *p)
-+{
-+ return (ext3_dirent *)((char*)p + le16_to_cpu(p->rec_len));
-+}
-+
-+
-+/*
- * ext3_find_entry()
- *
- * finds an entry in the specified directory with the wanted name. It
-@@ -105,6 +548,8 @@
- * The returned buffer_head has ->b_count elevated. The caller is expected
- * to brelse() it when appropriate.
- */
-+
-+
- static struct buffer_head * ext3_find_entry (struct dentry *dentry,
- struct ext3_dir_entry_2 ** res_dir)
- {
-@@ -119,10 +564,76 @@
- int num = 0;
- int nblocks, i, err;
- struct inode *dir = dentry->d_parent->d_inode;
-+ int namelen;
-+ const u8 *name;
-+ unsigned blocksize;
-+ ext3_dirent *de, *top;
-
- *res_dir = NULL;
- sb = dir->i_sb;
-+ blocksize = sb->s_blocksize;
-+ namelen = dentry->d_name.len;
-+ name = dentry->d_name.name;
-+ if (namelen > EXT3_NAME_LEN)
-+ return NULL;
-+ if (ext3_dx && is_dx(dir)) {
-+ u32 hash = dx_hash (name, namelen);
-+ struct dx_frame frames[2], *frame;
-+ if (!(frame = dx_probe (dir, hash, frames)))
-+ return NULL;
-+dxnext:
-+ block = dx_get_block(frame->at);
-+ if (!(bh = ext3_bread (NULL,dir, block, 0, &err)))
-+ goto dxfail;
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ top = (struct ext3_dir_entry_2 *) ((char *) de + blocksize
-+ - EXT3_DIR_REC_LEN(0));
-+ for (; de < top; de = ext3_next_entry(de))
-+ if (ext3_match (namelen, name, de)) {
-+ if (!ext3_check_dir_entry("ext3_find_entry",
-+ dir, de, bh,
-+ (block<<EXT3_BLOCK_SIZE_BITS(sb))
-+ +((char *)de - bh->b_data))) {
-+ brelse (bh);
-+ goto dxfail;
-+ }
-+ *res_dir = de;
-+ goto dxfound;
-+ }
-+ brelse (bh);
-+ /* Same hash continues in next block? Search on. */
-+ if (++(frame->at) == frame->entries + dx_get_count(frame->entries))
-+ {
-+ struct buffer_head *bh2;
-+ if (frame == frames)
-+ goto dxfail;
-+ if (++(frames->at) == frames->entries + dx_get_count(frames->entries))
-+ goto dxfail;
-+ /* should omit read if not continued */
-+ if (!(bh2 = ext3_bread (NULL, dir,
-+ dx_get_block(frames->at),
-+ 0, &err)))
-+ goto dxfail;
-+ brelse (frame->bh);
-+ frame->bh = bh2;
-+ frame->at = frame->entries = ((struct dx_node *) bh2->b_data)->entries;
-+ /* Subtle: the 0th entry has the count, find the hash in frame above */
-+ if ((dx_get_hash(frames->at) & -2) == hash)
-+ goto dxnext;
-+ goto dxfail;
-+ }
-+ if ((dx_get_hash(frame->at) & -2) == hash)
-+ goto dxnext;
-+dxfail:
-+ dxtrace(printk("%s not found\n", name));
-+ dx_release (frames);
-+ return NULL;
-+dxfound:
-+ dx_release (frames);
-+ return bh;
-
-+ }
-+
- nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
- start = dir->u.ext3_i.i_dir_start_lookup;
- if (start >= nblocks)
-@@ -237,6 +748,88 @@
- de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
- }
-
-+static ext3_dirent *
-+dx_copy_dirents (char *from, char *to, struct dx_map_entry *map, int count)
-+{
-+ unsigned rec_len = 0;
-+
-+ while (count--) {
-+ ext3_dirent *de = (ext3_dirent *) (from + map->offs);
-+ rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ memcpy (to, de, rec_len);
-+ ((ext3_dirent *) to)->rec_len = rec_len;
-+ to += rec_len;
-+ map++;
-+ }
-+ return (ext3_dirent *) (to - rec_len);
-+}
-+
-+#ifdef CONFIG_EXT3_INDEX
-+static ext3_dirent *do_split(handle_t *handle, struct inode *dir,
-+ struct buffer_head **bh,struct dx_frame *frame,
-+ u32 hash, int *error)
-+{
-+ unsigned blocksize = dir->i_sb->s_blocksize;
-+ unsigned count, continued;
-+ struct buffer_head *bh2;
-+ u32 newblock;
-+ unsigned MAX_DX_MAP = PAGE_CACHE_SIZE/EXT3_DIR_REC_LEN(1) + 1;
-+ u32 hash2;
-+ struct dx_map_entry map[MAX_DX_MAP];
-+ char *data1 = (*bh)->b_data, *data2, *data3;
-+ unsigned split;
-+ ext3_dirent *de, *de2;
-+
-+ bh2 = ext3_append (handle, dir, &newblock, error);
-+ if (!(bh2))
-+ {
-+ brelse(*bh);
-+ *bh = NULL;
-+ return (ext3_dirent *)bh2;
-+ }
-+
-+ BUFFER_TRACE(*bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, *bh);
-+ BUFFER_TRACE(frame->bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, frame->bh);
-+
-+ data2 = bh2->b_data;
-+
-+ count = dx_make_map ((ext3_dirent *) data1, blocksize, map);
-+ split = count/2; // need to adjust to actual middle
-+ dx_sort_map (map, count);
-+ hash2 = map[split].hash;
-+ continued = hash2 == map[split - 1].hash;
-+ dxtrace(printk("Split block %i at %x, %i/%i\n",
-+ dx_get_block(frame->at), hash2, split, count-split));
-+
-+ /* Fancy dance to stay within two buffers */
-+ de2 = dx_copy_dirents (data1, data2, map + split, count - split);
-+ data3 = (char *) de2 + de2->rec_len;
-+ de = dx_copy_dirents (data1, data3, map, split);
-+ memcpy(data1, data3, (char *) de + de->rec_len - data3);
-+ de = (ext3_dirent *) ((char *) de - data3 + data1); // relocate de
-+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-+ dxtrace(dx_show_leaf ((ext3_dirent *) data1, blocksize, 1));
-+ dxtrace(dx_show_leaf ((ext3_dirent *) data2, blocksize, 1));
-+
-+ /* Which block gets the new entry? */
-+ if (hash >= hash2)
-+ {
-+ swap(*bh, bh2);
-+ de = de2;
-+ }
-+ dx_insert_block (frame, hash2 + continued, newblock);
-+ ext3_journal_dirty_metadata (handle, bh2);
-+ brelse (bh2);
-+ ext3_journal_dirty_metadata (handle, frame->bh);
-+ dxtrace(dx_show_index ("frame", frame->entries));
-+ return de;
-+}
-+#endif
-+
-+
- /*
- * ext3_add_entry()
- *
-@@ -251,6 +844,7 @@
- /*
- * AKPM: the journalling code here looks wrong on the error paths
- */
-+
- static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
- struct inode *inode)
- {
-@@ -258,117 +852,284 @@
- const char *name = dentry->d_name.name;
- int namelen = dentry->d_name.len;
- unsigned long offset;
-- unsigned short rec_len;
- struct buffer_head * bh;
- struct ext3_dir_entry_2 * de, * de1;
-- struct super_block * sb;
-+ struct super_block * sb = dir->i_sb;
- int retval;
-+ unsigned short reclen = EXT3_DIR_REC_LEN(namelen);
-
-- sb = dir->i_sb;
-+ unsigned blocksize = sb->s_blocksize;
-+ unsigned nlen, rlen;
-+ u32 block;
-+ char *top;
-
- if (!namelen)
- return -EINVAL;
-- bh = ext3_bread (handle, dir, 0, 0, &retval);
-- if (!bh)
-- return retval;
-- rec_len = EXT3_DIR_REC_LEN(namelen);
-- offset = 0;
-- de = (struct ext3_dir_entry_2 *) bh->b_data;
-- while (1) {
-- if ((char *)de >= sb->s_blocksize + bh->b_data) {
-- brelse (bh);
-- bh = NULL;
-- bh = ext3_bread (handle, dir,
-- offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval);
-- if (!bh)
-- return retval;
-- if (dir->i_size <= offset) {
-- if (dir->i_size == 0) {
-- brelse(bh);
-- return -ENOENT;
-+ if (ext3_dx && is_dx(dir))
-+ {
-+ struct dx_frame frames[2], *frame;
-+ struct dx_entry *entries, *at;
-+ u32 hash;
-+ char *data1;
-+
-+ hash = dx_hash (name, namelen);
-+ frame = dx_probe (dir, hash, frames); // do something if null
-+ entries = frame->entries;
-+ at = frame->at;
-+
-+ if (!(bh = ext3_bread (handle,dir, dx_get_block(frame->at), 0,&retval)))
-+ goto dxfail1;
-+
-+ BUFFER_TRACE(bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, bh);
-+
-+ data1 = bh->b_data;
-+ de = (ext3_dirent *) data1;
-+ top = data1 + (0? 200: blocksize);
-+ while ((char *) de < top)
-+ {
-+ /* FIXME: check EEXIST and dir */
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ if ((de->inode? rlen - nlen: rlen) >= reclen)
-+ goto dx_add;
-+ de = (ext3_dirent *) ((char *) de + rlen);
-+ }
-+ /* Block full, should compress but for now just split */
-+ dxtrace(printk("using %u of %u node entries\n",
-+ dx_get_count(entries), dx_get_limit(entries)));
-+ /* Need to split index? */
-+ if (dx_get_count(entries) == dx_get_limit(entries))
-+ {
-+ u32 newblock;
-+ unsigned icount = dx_get_count(entries);
-+ char *idata2;
-+ int levels = frame - frames;
-+ struct dx_entry *entries2;
-+ struct buffer_head *bh2;
-+ if (levels && dx_get_count(frames->entries) == dx_get_limit(frames->entries))
-+ goto dxfull;
-+ bh2 = ext3_append (handle, dir, &newblock, &retval);
-+ if (!(bh2))
-+ goto dxfail2;
-+ idata2 = bh2->b_data;
-+ entries2 = ((struct dx_node *) idata2)->entries;
-+ ((struct dx_node *) idata2)->fake.rec_len = cpu_to_le16(blocksize);
-+ /* fake.inode already 0 */
-+ /* Seems that is not true. We still need to set inode = 0 -Chrisl*/
-+ ((struct dx_node *) idata2)->fake.inode = 0;
-+ BUFFER_TRACE(frame->bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, frame->bh);
-+ if (levels)
-+ {
-+ unsigned icount1 = icount/2, icount2 = icount - icount1;
-+ unsigned hash2 = dx_get_hash(entries + icount1);
-+ dxtrace(printk("Split index %i/%i\n", icount1, icount2));
-+
-+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
-+ ext3_journal_get_write_access(handle, frames[0].bh);
-+
-+ memcpy ((char *) entries2, (char *) (entries + icount1),
-+ icount2 * sizeof(struct dx_entry));
-+ dx_set_count (entries, icount1);
-+ dx_set_count (entries2, icount2);
-+ dx_set_limit (entries2, dx_node_limit(dir));
-+
-+ /* Which index block gets the new entry? */
-+ if (at - entries > icount1) {
-+ frame->at = at = at - entries - icount1 + entries2;
-+ frame->entries = entries = entries2;
-+ swap(frame->bh, bh2);
- }
--
-- ext3_debug ("creating next block\n");
--
-- BUFFER_TRACE(bh, "get_write_access");
-- ext3_journal_get_write_access(handle, bh);
-- de = (struct ext3_dir_entry_2 *) bh->b_data;
-- de->inode = 0;
-- de->rec_len = le16_to_cpu(sb->s_blocksize);
-- dir->u.ext3_i.i_disksize =
-- dir->i_size = offset + sb->s_blocksize;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- ext3_mark_inode_dirty(handle, dir);
-+ dx_insert_block (frames + 0, hash2, newblock);
-+ dxtrace(dx_show_index ("node", frames[1].entries));
-+ dxtrace(dx_show_index ("node",
-+ ((struct dx_node *) bh2->b_data)->entries));
-+ ext3_journal_dirty_metadata(handle, bh2);
-+ brelse (bh2);
- } else {
--
-- ext3_debug ("skipping to next block\n");
--
-- de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ dxtrace(printk("Creating second level index...\n"));
-+ memcpy((char *) entries2, (char *) entries,
-+ icount * sizeof(struct dx_entry));
-+ dx_set_limit(entries2, dx_node_limit(dir));
-+
-+ /* Set up root */
-+ dx_set_count(entries, 1);
-+ dx_set_block(entries + 0, newblock);
-+ ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
-+
-+ /* Add new access path frame */
-+ frame = frames + 1;
-+ frame->at = at = at - entries + entries2;
-+ frame->entries = entries = entries2;
-+ frame->bh = bh2;
-+ ext3_journal_get_write_access(handle, frame->bh);
- }
-+ ext3_journal_dirty_metadata(handle, frames[0].bh);
- }
-- if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh,
-- offset)) {
-- brelse (bh);
-- return -ENOENT;
-- }
-- if (ext3_match (namelen, name, de)) {
-+ de = do_split(handle, dir, &bh, frame, hash, &retval);
-+ dx_release (frames);
-+ if (!(de))
-+ goto fail;
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ goto add;
-+
-+dx_add:
-+ dx_release (frames);
-+ goto add;
-+
-+dxfull:
-+ ext3_warning(sb, __FUNCTION__, "Directory index full!\n");
-+ retval = -ENOSPC;
-+dxfail2:
-+ brelse(bh);
-+dxfail1:
-+ dx_release (frames);
-+ goto fail1;
-+ }
-+ block = offset = 0;
-+ while (offset < dir->i_size) {
-+ bh = ext3_bread (handle, dir, block, 0, &retval);
-+ if(!bh)
-+ return retval;
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ top = bh->b_data+blocksize-reclen;
-+ while ((char *) de <= top) {
-+
-+ if (!ext3_check_dir_entry ("ext3_add_entry", dir, de,
-+ bh,offset)) {
-+ brelse (bh);
-+ return -ENOENT;
-+ }
-+ if (ext3_match (namelen, name, de)) {
- brelse (bh);
- return -EEXIST;
-- }
-- if ((le32_to_cpu(de->inode) == 0 &&
-- le16_to_cpu(de->rec_len) >= rec_len) ||
-- (le16_to_cpu(de->rec_len) >=
-- EXT3_DIR_REC_LEN(de->name_len) + rec_len)) {
-- BUFFER_TRACE(bh, "get_write_access");
-- ext3_journal_get_write_access(handle, bh);
-- /* By now the buffer is marked for journaling */
-- offset += le16_to_cpu(de->rec_len);
-- if (le32_to_cpu(de->inode)) {
-- de1 = (struct ext3_dir_entry_2 *) ((char *) de +
-- EXT3_DIR_REC_LEN(de->name_len));
-- de1->rec_len =
-- cpu_to_le16(le16_to_cpu(de->rec_len) -
-- EXT3_DIR_REC_LEN(de->name_len));
-- de->rec_len = cpu_to_le16(
-- EXT3_DIR_REC_LEN(de->name_len));
-- de = de1;
- }
-- de->file_type = EXT3_FT_UNKNOWN;
-- if (inode) {
-- de->inode = cpu_to_le32(inode->i_ino);
-- ext3_set_de_type(dir->i_sb, de, inode->i_mode);
-- } else
-- de->inode = 0;
-- de->name_len = namelen;
-- memcpy (de->name, name, namelen);
-- /*
-- * XXX shouldn't update any times until successful
-- * completion of syscall, but too many callers depend
-- * on this.
-- *
-- * XXX similarly, too many callers depend on
-- * ext3_new_inode() setting the times, but error
-- * recovery deletes the inode, so the worst that can
-- * happen is that the times are slightly out of date
-- * and/or different from the directory change time.
-- */
-- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- ext3_mark_inode_dirty(handle, dir);
-- dir->i_version = ++event;
-- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-- ext3_journal_dirty_metadata(handle, bh);
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ if ((de->inode? rlen - nlen: rlen) >= reclen)
-+ goto add;
-+ de = (struct ext3_dir_entry_2 *) ((char *) de + rlen);
-+ offset += rlen;
-+ }
-+ if (ext3_dx && dir->i_size==blocksize && test_opt(sb, INDEX))
-+ goto dx_make_index;
-+ brelse(bh);
-+ }
-+ bh = ext3_append(handle, dir, &block, &retval);
-+ if (!bh)
-+ return retval;
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ de->inode = 0;
-+ de->rec_len = cpu_to_le16(rlen = blocksize);
-+ nlen = 0;
-+ goto add;
-+
-+add:
-+ BUFFER_TRACE(bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, bh);
-+ /* By now the buffer is marked for journaling */
-+ if (de->inode) {
-+ de1 = (struct ext3_dir_entry_2 *) ((char *) de + nlen);
-+ de1->rec_len = cpu_to_le16(rlen - nlen);
-+ de->rec_len = cpu_to_le16(nlen);
-+ de = de1;
-+ }
-+ de->file_type = EXT3_FT_UNKNOWN;
-+ if (inode) {
-+ de->inode = cpu_to_le32(inode->i_ino);
-+ ext3_set_de_type(dir->i_sb, de, inode->i_mode);
-+ } else
-+ de->inode = 0;
-+ de->name_len = namelen;
-+ memcpy (de->name, name, namelen);
-+ /*
-+ * XXX shouldn't update any times until successful
-+ * completion of syscall, but too many callers depend
-+ * on this.
-+ *
-+ * XXX similarly, too many callers depend on
-+ * ext3_new_inode() setting the times, but error
-+ * recovery deletes the inode, so the worst that can
-+ * happen is that the times are slightly out of date
-+ * and/or different from the directory change time.
-+ */
-+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-+ /* EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL; */
-+ ext3_mark_inode_dirty(handle, dir);
-+ dir->i_version = ++event;
-+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-+ ext3_journal_dirty_metadata(handle, bh);
-+ brelse(bh);
-+ return 0;
-+
-+dx_make_index:
-+ {
-+ struct buffer_head *bh2;
-+ struct dx_root *root;
-+ struct dx_frame frames[2], *frame;
-+ struct dx_entry *entries;
-+ struct ext3_dir_entry_2 *de2;
-+ char *data1;
-+ unsigned len;
-+ u32 hash;
-+
-+ dxtrace(printk("Creating index\n"));
-+ ext3_journal_get_write_access(handle, bh);
-+ root = (struct dx_root *) bh->b_data;
-+
-+ ext3_add_compat_feature (sb, EXT3_FEATURE_COMPAT_DIR_INDEX);
-+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
-+ bh2 = ext3_append (handle, dir, &block, &retval);
-+ if (!(bh2))
-+ {
- brelse(bh);
-- return 0;
-+ return retval;
- }
-- offset += le16_to_cpu(de->rec_len);
-- de = (struct ext3_dir_entry_2 *)
-- ((char *) de + le16_to_cpu(de->rec_len));
-+ data1 = bh2->b_data;
-+
-+ /* The 0th block becomes the root, move the dirents out */
-+ de = (ext3_dirent *) &root->info;
-+ len = ((char *) root) + blocksize - (char *) de;
-+ memcpy (data1, de, len);
-+ de = (ext3_dirent *) data1;
-+ top = data1 + len;
-+ while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top)
-+ de = de2;
-+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+ /* Initialize the root; the dot dirents already exist */
-+ de = (ext3_dirent *) (&root->fake2);
-+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
-+ memset (&root->info, 0, sizeof(root->info));
-+ root->info.info_length = sizeof(root->info);
-+ entries = root->entries;
-+ dx_set_block (entries, 1);
-+ dx_set_count (entries, 1);
-+ dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
-+
-+ /* Initialize as for dx_probe */
-+ hash = dx_hash (name, namelen);
-+ frame = frames;
-+ frame->entries = entries;
-+ frame->at = entries;
-+ frame->bh = bh;
-+ bh = bh2;
-+ de = do_split(handle,dir, &bh, frame, hash, &retval);
-+ dx_release (frames);
-+ if (!(de))
-+ return retval;
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ goto add;
- }
-- brelse (bh);
-- return -ENOSPC;
-+fail1:
-+ return retval;
-+fail:
-+ return -ENOENT;
- }
-
-+
- /*
- * ext3_delete_entry deletes a directory entry by merging it with the
- * previous entry
-@@ -451,7 +1212,8 @@
- struct inode * inode;
- int err;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -478,7 +1240,8 @@
- struct inode *inode;
- int err;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -507,7 +1270,8 @@
- if (dir->i_nlink >= EXT3_LINK_MAX)
- return -EMLINK;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -832,7 +1596,7 @@
- ext3_mark_inode_dirty(handle, inode);
- dir->i_nlink--;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ // EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL;
- ext3_mark_inode_dirty(handle, dir);
-
- end_rmdir:
-@@ -878,7 +1642,7 @@
- if (retval)
- goto end_unlink;
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ // EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL;
- ext3_mark_inode_dirty(handle, dir);
- inode->i_nlink--;
- if (!inode->i_nlink)
-@@ -904,7 +1668,8 @@
- if (l > dir->i_sb->s_blocksize)
- return -ENAMETOOLONG;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -959,7 +1724,8 @@
- if (inode->i_nlink >= EXT3_LINK_MAX)
- return -EMLINK;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -995,7 +1761,8 @@
-
- old_bh = new_bh = dir_bh = NULL;
-
-- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2);
-+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -1077,7 +1844,7 @@
- new_inode->i_ctime = CURRENT_TIME;
- }
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
-- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ // EXT3_I(old_dir)->i_flags &= ~EXT3_INDEX_FL;
- if (dir_bh) {
- BUFFER_TRACE(dir_bh, "get_write_access");
- ext3_journal_get_write_access(handle, dir_bh);
-@@ -1089,7 +1856,7 @@
- new_inode->i_nlink--;
- } else {
- new_dir->i_nlink++;
-- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ // EXT3_I(new_dir)->i_flags &= ~EXT3_INDEX_FL;
- ext3_mark_inode_dirty(handle, new_dir);
- }
- }
---- ./include/linux/ext3_fs.h 2002/03/05 06:18:59 2.1
-+++ ./include/linux/ext3_fs.h 2002/03/05 06:26:56
-@@ -339,6 +339,7 @@
- #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
- #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
-+#define EXT3_MOUNT_INDEX 0x4000 /* Enable directory index */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -575,6 +576,24 @@
- #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1)
- #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \
- ~EXT3_DIR_ROUND)
-+/*
-+ * Hash Tree Directory indexing
-+ * (c) Daniel Phillips, 2001
-+ */
-+
-+#define CONFIG_EXT3_INDEX
-+
-+#ifdef CONFIG_EXT3_INDEX
-+ enum {ext3_dx = 1};
-+ #define is_dx(dir) (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)
-+#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX)
-+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
-+#else
-+ enum {ext3_dx = 0};
-+ #define is_dx(dir) 0
-+#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX)
-+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
-+#endif
-
- #ifdef __KERNEL__
- /*
---- ./include/linux/ext3_jbd.h 2002/03/05 06:18:59 2.1
-+++ ./include/linux/ext3_jbd.h 2002/03/05 06:33:54
-@@ -63,6 +63,8 @@
-
- #define EXT3_RESERVE_TRANS_BLOCKS 12
-
-+#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8
-+
- int
- ext3_mark_iloc_dirty(handle_t *handle,
- struct inode *inode,
+++ /dev/null
-Linux Extended Attributes -- Kernel Patch
-24 April 2002, 11:31:18
-
-
-This patch is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This patch 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
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this patch; if not, write to the Free Software Foundation,
-Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-After extracting the linux-2.4.18.tar.gz package, apply this patch as follows:
-
- cd linux
- patch -p1 < ../linux-2.4.18ea-0.8.26.patch
-
-diff -Nur linux-2.4.18/fs/ext3/file.c linux-2.4.18ea/fs/ext3/file.c
---- linux-2.4.18/fs/ext3/file.c Thu Nov 15 22:37:55 2001
-+++ linux-2.4.18ea/fs/ext3/file.c Sun Feb 24 04:34:43 2002
-@@ -23,6 +23,7 @@
- #include <linux/locks.h>
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/ext3_jbd.h>
- #include <linux/smp_lock.h>
-
-@@ -90,5 +91,9 @@
- struct inode_operations ext3_file_inode_operations = {
- truncate: ext3_truncate, /* BKL held */
- setattr: ext3_setattr, /* BKL held */
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
- };
-
-diff -Nur linux-2.4.18/fs/ext3/ialloc.c linux-2.4.18ea/fs/ext3/ialloc.c
---- linux-2.4.18/fs/ext3/ialloc.c Sun Feb 24 04:42:59 2002
-+++ linux-2.4.18ea/fs/ext3/ialloc.c Sun Feb 24 04:34:43 2002
-@@ -17,6 +17,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/stat.h>
- #include <linux/string.h>
- #include <linux/locks.h>
-@@ -216,6 +217,7 @@
- * as writing the quota to disk may need the lock as well.
- */
- DQUOT_INIT(inode);
-+ ext3_xattr_drop_inode(handle, inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
-
-diff -Nur linux-2.4.18/fs/ext3/inode.c linux-2.4.18ea/fs/ext3/inode.c
---- linux-2.4.18/fs/ext3/inode.c Sun Feb 24 04:42:59 2002
-+++ linux-2.4.18ea/fs/ext3/inode.c Thu Mar 14 21:51:59 2002
-@@ -39,6 +39,18 @@
- */
- #undef SEARCH_FROM_ZERO
-
-+/*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext3_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = EXT3_I(inode)->i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
- /* The ext3 forget function must perform a revoke if we are freeing data
- * which has been journaled. Metadata (eg. indirect blocks) must be
- * revoked in all cases.
-@@ -48,7 +60,7 @@
- * still needs to be revoked.
- */
-
--static int ext3_forget(handle_t *handle, int is_metadata,
-+int ext3_forget(handle_t *handle, int is_metadata,
- struct inode *inode, struct buffer_head *bh,
- int blocknr)
- {
-@@ -164,9 +176,7 @@
- {
- handle_t *handle;
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
-
- lock_kernel();
-@@ -1845,6 +1855,8 @@
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext3_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -1992,8 +2004,6 @@
- struct ext3_group_desc * gdp;
-
- if ((inode->i_ino != EXT3_ROOT_INO &&
-- inode->i_ino != EXT3_ACL_IDX_INO &&
-- inode->i_ino != EXT3_ACL_DATA_INO &&
- inode->i_ino != EXT3_JOURNAL_INO &&
- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(
-@@ -2120,10 +2130,7 @@
-
- brelse (iloc.bh);
-
-- if (inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
- inode->i_mapping->a_ops = &ext3_aops;
-@@ -2131,13 +2138,15 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext3_inode_is_fast_symlink(inode))
- inode->i_op = &ext3_fast_symlink_inode_operations;
- else {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext3_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext3_aops;
- }
-- } else
-+ } else {
-+ inode->i_op = &ext3_special_inode_operations;
- init_special_inode(inode, inode->i_mode,
- le32_to_cpu(iloc.raw_inode->i_block[0]));
-+ }
- /* inode->i_attr_flags = 0; unused */
-diff -Nur linux-2.4.18/fs/ext3/namei.c linux-2.4.18ea/fs/ext3/namei.c
---- linux-2.4.18/fs/ext3/namei.c Fri Nov 9 23:25:04 2001
-+++ linux-2.4.18ea/fs/ext3/namei.c Mon Mar 11 03:27:00 2002
-@@ -23,6 +23,7 @@
- #include <linux/sched.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/fcntl.h>
- #include <linux/stat.h>
- #include <linux/string.h>
-@@ -466,6 +467,8 @@
- inode->i_mapping->a_ops = &ext3_aops;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ if (err)
-+ ext3_xattr_drop_inode(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -491,6 +494,8 @@
- init_special_inode(inode, mode, rdev);
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ if (err)
-+ ext3_xattr_drop_inode(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -514,7 +519,7 @@
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFDIR);
-+ inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
-@@ -522,7 +527,6 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
-- inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize;
-- inode->i_blocks = 0;
-+ inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
- dir_block = ext3_bread (handle, inode, 0, 1, &err);
- if (!dir_block) {
- inode->i_nlink--; /* is this nlink == 0? */
-@@ -549,9 +553,6 @@
- BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, dir_block);
- brelse (dir_block);
-- inode->i_mode = S_IFDIR | mode;
-- if (dir->i_mode & S_ISGID)
-- inode->i_mode |= S_ISGID;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_entry (handle, dentry, inode);
- if (err)
-@@ -565,6 +566,7 @@
- return err;
-
- out_no_entry:
-+ ext3_xattr_drop_inode(handle, inode);
- inode->i_nlink = 0;
- ext3_mark_inode_dirty(handle, inode);
- iput (inode);
-@@ -917,7 +919,7 @@
- goto out_stop;
-
-- if (l > sizeof (inode->u.ext3_i.i_data)) {
-- inode->i_op = &page_symlink_inode_operations;
-+ if (l > sizeof(EXT3_I(inode)->i_data)) {
-+ inode->i_op = &ext3_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext3_aops;
- /*
- * block_symlink() calls back into ext3_prepare/commit_write.
-@@ -1122,4 +1124,16 @@
- rmdir: ext3_rmdir, /* BKL held */
- mknod: ext3_mknod, /* BKL held */
- rename: ext3_rename, /* BKL held */
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
- };
-+
-+struct inode_operations ext3_special_inode_operations = {
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
-+};
-+
-diff -Nur linux-2.4.18/fs/ext3/super.c linux-2.4.18ea/fs/ext3/super.c
---- linux-2.4.18/fs/ext3/super.c Sun Feb 24 04:42:59 2002
-+++ linux-2.4.18ea/fs/ext3/super.c Thu Apr 4 21:41:05 2002
-@@ -24,6 +24,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/locks.h>
-@@ -404,6 +405,7 @@
- kdev_t j_dev = sbi->s_journal->j_dev;
- int i;
-
-+ ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
- EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-@@ -1734,14 +1772,25 @@
-
- static DECLARE_FSTYPE_DEV(ext3_fs_type, "ext3", ext3_read_super);
-
--static int __init init_ext3_fs(void)
-+static void exit_ext3_fs(void)
- {
-- return register_filesystem(&ext3_fs_type);
-+ unregister_filesystem(&ext3_fs_type);
-+ exit_ext3_xattr_user();
-+ exit_ext3_xattr();
- }
-
--static void __exit exit_ext3_fs(void)
-+static int __init init_ext3_fs(void)
- {
-- unregister_filesystem(&ext3_fs_type);
-+ int error = init_ext3_xattr();
-+ if (!error)
-+ error = init_ext3_xattr_user();
-+ if (!error)
-+ error = register_filesystem(&ext3_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext3_fs();
-+ return error;
- }
-
- EXPORT_NO_SYMBOLS;
-diff -Nur linux-2.4.18/fs/ext3/symlink.c linux-2.4.18ea/fs/ext3/symlink.c
---- linux-2.4.18/fs/ext3/symlink.c Fri Nov 9 23:25:04 2001
-+++ linux-2.4.18ea/fs/ext3/symlink.c Mon Mar 11 03:27:00 2002
-@@ -20,6 +20,7 @@
- #include <linux/fs.h>
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
-+#include <linux/ext3_xattr.h>
-
- static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-@@ -33,7 +34,20 @@
- return vfs_follow_link(nd, s);
- }
-
-+struct inode_operations ext3_symlink_inode_operations = {
-+ readlink: page_readlink, /* BKL not held. Don't need */
-+ follow_link: page_follow_link, /* BKL not held. Don't need */
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
-+};
-+
- struct inode_operations ext3_fast_symlink_inode_operations = {
- readlink: ext3_readlink, /* BKL not held. Don't need */
- follow_link: ext3_follow_link, /* BKL not held. Don't need */
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
- };
-diff -Nur linux-2.4.18/fs/ext3/xattr.c linux-2.4.18ea/fs/ext3/xattr.c
---- linux-2.4.18/fs/ext3/xattr.c Thu Jan 1 01:00:00 1970
-+++ linux-2.4.18ea/fs/ext3/xattr.c Wed Apr 3 13:19:05 2002
-@@ -0,0 +1,1241 @@
-+/*
-+ * linux/fs/ext3/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
-+ * Extended attributes for symlinks and special files added per
-+ * suggestion of Luka Renko <luka.renko@hermes.si>.
-+ */
-+
-+/*
-+ * Extended attributes are stored on disk blocks allocated outside of
-+ * any inode. The i_file_acl field is then made to point to this allocated
-+ * block. If all extended attributes of an inode are identical, these
-+ * inodes may share the same extended attribute block. Such situations
-+ * are automatically detected by keeping a cache of recent attribute block
-+ * numbers and hashes over the block's contents in memory.
-+ *
-+ *
-+ * Extended attribute block layout:
-+ *
-+ * +------------------+
-+ * | header |
-+ * ¦ entry 1 | |
-+ * | entry 2 | | growing downwards
-+ * | entry 3 | v
-+ * | four null bytes |
-+ * | . . . |
-+ * | value 1 | ^
-+ * | value 3 | | growing upwards
-+ * | value 2 | |
-+ * +------------------+
-+ *
-+ * The block header is followed by multiple entry descriptors. These entry
-+ * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
-+ * byte boundaries. The entry descriptors are sorted by attribute name,
-+ * so that two extended attribute blocks can be compared efficiently.
-+ *
-+ * Attribute values are aligned to the end of the block, stored in
-+ * no specific order. They are also padded to EXT3_XATTR_PAD byte
-+ * boundaries. No additional gaps are left between them.
-+ *
-+ * Locking strategy
-+ * ----------------
-+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of
-+ * the xattr inode operations are called, so we are guaranteed that only one
-+ * processes accesses extended attributes of an inode at any time.
-+ *
-+ * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
-+ * only a single process is modifying an extended attribute block, even
-+ * if the block is shared among inodes.
-+ *
-+ * Note for porting to 2.5
-+ * -----------------------
-+ * The BKL will no longer be held in the xattr inode operations.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/locks.h>
-+#include <linux/slab.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_xattr.h>
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+#include <linux/mbcache.h>
-+#endif
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include <linux/compatmac.h>
-+
-+#define EXT3_EA_USER "user."
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
-+#endif
-+
-+#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT3_XATTR_DEBUG
-+# define ea_idebug(inode, f...) do { \
-+ printk(KERN_DEBUG "inode %s:%ld: ", \
-+ kdevname(inode->i_dev), inode->i_ino); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+# define ea_bdebug(bh, f...) do { \
-+ printk(KERN_DEBUG "block %s:%ld: ", \
-+ kdevname(bh->b_dev), bh->b_blocknr); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+#else
-+# define ea_idebug(f...)
-+# define ea_bdebug(f...)
-+#endif
-+
-+static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
-+ struct ext3_xattr_header *);
-+
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+
-+static int ext3_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext3_xattr_cache_find(struct inode *,
-+ struct ext3_xattr_header *);
-+static void ext3_xattr_cache_remove(struct buffer_head *);
-+static void ext3_xattr_rehash(struct ext3_xattr_header *,
-+ struct ext3_xattr_entry *);
-+
-+static struct mb_cache *ext3_xattr_cache;
-+
-+#else
-+# define ext3_xattr_cache_insert(bh) 0
-+# define ext3_xattr_cache_find(inode, header) NULL
-+# define ext3_xattr_cache_remove(bh) do {} while(0)
-+# define ext3_xattr_rehash(header, entry) do {} while(0)
-+#endif
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext3_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+DECLARE_MUTEX(ext3_xattr_sem);
-+
-+static inline void
-+ext3_xattr_lock(void)
-+{
-+ down(&ext3_xattr_sem);
-+}
-+
-+static inline void
-+ext3_xattr_unlock(void)
-+{
-+ up(&ext3_xattr_sem);
-+}
-+
-+static inline int
-+ext3_xattr_new_block(handle_t *handle, struct inode *inode,
-+ int * errp, int force)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-+ EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
-+
-+ /* How can we enforce the allocation? */
-+ int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
-+#ifdef OLD_QUOTAS
-+ if (!*errp)
-+ inode->i_blocks += inode->i_sb->s_blocksize >> 9;
-+#endif
-+ return block;
-+}
-+
-+static inline int
-+ext3_xattr_quota_alloc(struct inode *inode, int force)
-+{
-+ /* How can we enforce the allocation? */
-+#ifdef OLD_QUOTAS
-+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
-+ if (!error)
-+ inode->i_blocks += inode->i_sb->s_blocksize >> 9;
-+#else
-+ int error = DQUOT_ALLOC_BLOCK(inode, 1);
-+#endif
-+ return error;
-+}
-+
-+#ifdef OLD_QUOTAS
-+
-+static inline void
-+ext3_xattr_quota_free(struct inode *inode)
-+{
-+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+static inline void
-+ext3_xattr_free_block(handle_t *handle, struct inode * inode,
-+ unsigned long block)
-+{
-+ ext3_free_blocks(handle, inode, block, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+#else
-+# define ext3_xattr_quota_free(inode) \
-+ DQUOT_FREE_BLOCK(inode, 1)
-+# define ext3_xattr_free_block(handle, inode, block) \
-+ ext3_free_blocks(handle, inode, block, 1)
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
-+
-+static inline struct buffer_head *
-+sb_bread(struct super_block *sb, int block)
-+{
-+ return bread(sb->s_dev, block, sb->s_blocksize);
-+}
-+
-+static inline struct buffer_head *
-+sb_getblk(struct super_block *sb, int block)
-+{
-+ return getblk(sb->s_dev, block, sb->s_blocksize);
-+}
-+
-+#endif
-+
-+struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
-+rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ if (!ext3_xattr_handlers[name_index-1]) {
-+ ext3_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext3_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ ext3_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext3_handler_lock);
-+ }
-+}
-+
-+static inline const char *
-+strcmp_prefix(const char *a, const char *a_prefix)
-+{
-+ while (*a_prefix && *a == *a_prefix) {
-+ a++;
-+ a_prefix++;
-+ }
-+ return *a_prefix ? NULL : a;
-+}
-+
-+/*
-+ * Decode the extended attribute name, and translate it into
-+ * the name_index and name suffix.
-+ */
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_resolve_name(const char **name)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext3_handler_lock);
-+ for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
-+ if (ext3_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext3_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext3_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext3_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_handler(int name_index)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ read_lock(&ext3_handler_lock);
-+ handler = ext3_xattr_handlers[name_index-1];
-+ read_unlock(&ext3_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext3_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->get(inode, name, buffer, size);
-+}
-+
-+/*
-+ * Inode operation listxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext3_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext3_setxattr(struct dentry *dentry, const char *name,
-+ void *value, size_t size, int flags)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, value, size, flags);
-+}
-+
-+/*
-+ * Inode operation removexattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext3_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext3_xattr_get()
-+ *
-+ * Copy an extended attribute into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size;
-+ char *end;
-+ int name_len, error;
-+
-+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
-+ name_index, name, buffer, (long)buffer_size);
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return -ENOATTR;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* find named attribute */
-+ name_len = strlen(name);
-+
-+ error = -ERANGE;
-+ if (name_len > 255)
-+ goto cleanup;
-+ entry = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0)
-+ goto found;
-+ entry = next;
-+ }
-+ /* Check the remaining name entries */
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ error = -ENOATTR;
-+ goto cleanup;
-+found:
-+ /* check the buffer size */
-+ if (entry->e_value_block != 0)
-+ goto bad_block;
-+ size = le32_to_cpu(entry->e_value_size);
-+ if (size > inode->i_sb->s_blocksize ||
-+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
-+ goto bad_block;
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (buffer) {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ /* return value of attribute */
-+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
-+ size);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size = 0;
-+ char *buf, *end;
-+ int error;
-+
-+ ea_idebug(inode, "buffer=%p, buffer_size=%ld",
-+ buffer, (long)buffer_size);
-+
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* compute the size required for the list of attribute names */
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len) + 1;
-+ }
-+ }
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (!buffer) {
-+ error = size;
-+ goto cleanup;
-+ } else {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ }
-+
-+ /* list the attribute names */
-+ buf = buffer;
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ *buf++ = '\0';
-+ }
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext3_xattr_update_super_block(handle_t *handle,
-+ struct super_block *sb)
-+{
-+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+ ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+ EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
-+#endif
-+ EXT3_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext3_xattr_set()
-+ *
-+ * Create, replace or remove an extended attribute for this inode. Buffer
-+ * is NULL to remove an existing extended attribute, and non-NULL to
-+ * either replace an existing extended attribute, or create a new extended
-+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
-+ * specify that an extended attribute must exist and must not exist
-+ * previous to the call, respectively.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, void *value, size_t value_len, int flags)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_header *header = NULL;
-+ struct ext3_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int min_offs = sb->s_blocksize, not_found = 1, free, error;
-+ char *end;
-+
-+ /*
-+ * header -- Points either into bh, or to a temporarily
-+ * allocated buffer.
-+ * here -- The named entry found, or the place for inserting, within
-+ * the block pointed to by header.
-+ * last -- Points right after the last named entry within the block
-+ * pointed to by header.
-+ * min_offs -- The offset of the first value (values are aligned
-+ * towards the end of the block).
-+ * end -- Points right after the block pointed to by header.
-+ */
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+ return -EPERM;
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > sb->s_blocksize)
-+ return -ERANGE;
-+ ext3_xattr_lock();
-+
-+ if (EXT3_I(inode)->i_file_acl) {
-+ /* The inode already has an extended attribute block. */
-+ int block = EXT3_I(inode)->i_file_acl;
-+
-+ bh = sb_bread(sb, block);
-+ error = -EIO;
-+ if (!bh)
-+ goto cleanup;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)),
-+ le32_to_cpu(HDR(bh)->h_refcount));
-+ header = HDR(bh);
-+ end = bh->b_data + bh->b_size;
-+ if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(sb, "ext3_xattr_set",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* Find the named attribute. */
-+ here = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(here)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!here->e_value_block && here->e_value_size) {
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ not_found = name_index - here->e_name_index;
-+ if (!not_found)
-+ not_found = name_len - here->e_name_len;
-+ if (!not_found)
-+ not_found = memcmp(name, here->e_name,name_len);
-+ if (not_found <= 0)
-+ break;
-+ here = next;
-+ }
-+ last = here;
-+ /* We still need to compute min_offs and last. */
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!last->e_value_block && last->e_value_size) {
-+ int offs = le16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ last = next;
-+ }
-+
-+ /* Check whether we have enough space left. */
-+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
-+ } else {
-+ /* We will use a new extended attribute block. */
-+ free = sb->s_blocksize -
-+ sizeof(struct ext3_xattr_header) - sizeof(__u32);
-+ here = last = NULL; /* avoid gcc uninitialized warning. */
-+ }
-+
-+ if (not_found) {
-+ /* Request to remove a nonexistent attribute? */
-+ error = -ENOATTR;
-+ if (flags & XATTR_REPLACE)
-+ goto cleanup;
-+ error = 0;
-+ if (value == NULL)
-+ goto cleanup;
-+ else
-+ free -= EXT3_XATTR_LEN(name_len);
-+ } else {
-+ /* Request to create an existing attribute? */
-+ error = -EEXIST;
-+ if (flags & XATTR_CREATE)
-+ goto cleanup;
-+ if (!here->e_value_block && here->e_value_size) {
-+ unsigned int size = le32_to_cpu(here->e_value_size);
-+
-+ if (le16_to_cpu(here->e_value_offs) + size >
-+ sb->s_blocksize || size > sb->s_blocksize)
-+ goto bad_block;
-+ free += EXT3_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT3_XATTR_SIZE(value_len);
-+ error = -ENOSPC;
-+ if (free < 0)
-+ goto cleanup;
-+
-+ /* Here we know that we can set the new attribute. */
-+
-+ if (header) {
-+ if (header->h_refcount == cpu_to_le32(1)) {
-+ ea_bdebug(bh, "modifying in-place");
-+ ext3_xattr_cache_remove(bh);
-+ error = ext3_journal_get_write_access(handle, bh);
-+ if (error)
-+ goto cleanup;
-+ } else {
-+ int offset;
-+
-+ ea_bdebug(bh, "cloning");
-+ header = kmalloc(bh->b_size, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memcpy(header, HDR(bh), bh->b_size);
-+ header->h_refcount = cpu_to_le32(1);
-+ offset = (char *)header - bh->b_data;
-+ here = ENTRY((char *)here + offset);
-+ last = ENTRY((char *)last + offset);
-+ }
-+ } else {
-+ /* Allocate a buffer where we construct the new block. */
-+ header = kmalloc(sb->s_blocksize, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memset(header, 0, sb->s_blocksize);
-+ end = (char *)header + sb->s_blocksize;
-+ header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
-+ header->h_blocks = header->h_refcount = cpu_to_le32(1);
-+ last = here = ENTRY(header+1);
-+ }
-+
-+ if (not_found) {
-+ /* Insert the new name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ int rest = (char *)last - (char *)here;
-+ memmove((char *)here + size, here, rest);
-+ memset(here, 0, size);
-+ here->e_name_index = name_index;
-+ here->e_name_len = name_len;
-+ memcpy(here->e_name, name, name_len);
-+ } else {
-+ /* Remove the old value. */
-+ if (!here->e_value_block && here->e_value_size) {
-+ char *first_val = (char *)header + min_offs;
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ char *val = (char *)header + offs;
-+ size_t size = EXT3_XATTR_SIZE(
-+ le32_to_cpu(here->e_value_size));
-+ memmove(first_val + size, first_val, val - first_val);
-+ memset(first_val, 0, size);
-+ here->e_value_offs = 0;
-+ min_offs += size;
-+
-+ /* Adjust all value offsets. */
-+ last = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(last)) {
-+ int o = le16_to_cpu(last->e_value_offs);
-+ if (!last->e_value_block && o < offs)
-+ last->e_value_offs =
-+ cpu_to_le16(o + size);
-+ last = EXT3_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext3_xattr_set2(handle, inode, bh,NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ last = ENTRY((char *)last - size);
-+ memmove(here, (char*)here + size,
-+ (char*)last - (char*)here);
-+ memset(last, 0, size);
-+ }
-+ }
-+ }
-+
-+ if (value != NULL) {
-+ /* Insert the new value. */
-+ here->e_value_size = cpu_to_le32(value_len);
-+ if (value_len) {
-+ size_t size = EXT3_XATTR_SIZE(value_len);
-+ char *val = (char *)header + min_offs - size;
-+ here->e_value_offs =
-+ cpu_to_le16((char *)val - (char *)header);
-+ memset(val + size - EXT3_XATTR_PAD, 0,
-+ EXT3_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext3_xattr_rehash(header, here);
-+
-+ error = ext3_xattr_set2(handle, inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ ext3_xattr_unlock();
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext3_xattr_set(): Update the file system.
-+ */
-+static int
-+ext3_xattr_set2(handle_t *handle, struct inode *inode,
-+ struct buffer_head *old_bh, struct ext3_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext3_xattr_cache_find(inode, header);
-+ if (new_bh) {
-+ /*
-+ * We found an identical block in the cache.
-+ * The old block will be released after updating
-+ * the inode.
-+ */
-+ ea_bdebug(old_bh, "reusing block %ld",
-+ new_bh->b_blocknr);
-+
-+ error = -EDQUOT;
-+ if (ext3_xattr_quota_alloc(inode, 1))
-+ goto cleanup;
-+
-+ error = ext3_journal_get_write_access(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ HDR(new_bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
-+ ea_bdebug(new_bh, "refcount now=%d",
-+ le32_to_cpu(HDR(new_bh)->h_refcount));
-+ } else if (old_bh && header == HDR(old_bh)) {
-+ /* Keep this block. */
-+ new_bh = old_bh;
-+ ext3_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int force = EXT3_I(inode)->i_file_acl != 0;
-+ int block = ext3_xattr_new_block(handle, inode,
-+ &error, force);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+getblk_failed: ext3_xattr_free_block(handle, inode, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ error = ext3_journal_get_create_access(handle, new_bh);
-+ if (error) {
-+ unlock_buffer(new_bh);
-+ goto getblk_failed;
-+ }
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ mark_buffer_uptodate(new_bh, 1);
-+ unlock_buffer(new_bh);
-+ ext3_xattr_cache_insert(new_bh);
-+ ext3_xattr_update_super_block(handle, sb);
-+ }
-+ error = ext3_journal_dirty_metadata(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ }
-+
-+ /* Update the inode. */
-+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ ext3_mark_inode_dirty(handle, inode);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+
-+ error = 0;
-+ if (old_bh && old_bh != new_bh) {
-+ /*
-+ * If there was an old block, and we are not still using it,
-+ * we now release the old block.
-+ */
-+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-+
-+ error = ext3_journal_get_write_access(handle, old_bh);
-+ if (error)
-+ goto cleanup;
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
-+
-+ /* ext3_forget() calls bforget() for us, but we
-+ let our caller release old_bh, so we need to
-+ duplicate the handle before. */
-+ get_bh(old_bh);
-+ ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ ext3_xattr_quota_free(inode);
-+ ext3_journal_dirty_metadata(handle, old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_drop_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext3_xattr_drop_inode(handle_t *handle, struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT3_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ ext3_xattr_lock();
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_drop_inode",
-+ "inode %ld: block %d read error", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext3_error(inode->i_sb, "ext3_xattr_drop_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ext3_journal_get_write_access(handle, bh);
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext3_xattr_cache_remove(bh);
-+ ext3_xattr_free_block(handle, inode, block);
-+ ext3_forget(handle, 1, inode, bh, block);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ ext3_journal_dirty_metadata(handle, bh);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+ ext3_xattr_quota_free(inode);
-+ }
-+ EXT3_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ ext3_xattr_unlock();
-+}
-+
-+/*
-+ * ext3_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+ mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
-+#endif
-+}
-+
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+
-+/*
-+ * ext3_xattr_cache_insert()
-+ *
-+ * Create a new entry in the extended attribute cache, and insert
-+ * it unless such an entry is already in the cache.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+static int
-+ext3_xattr_cache_insert(struct buffer_head *bh)
-+{
-+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
-+ struct mb_cache_entry *ce;
-+ int error;
-+
-+ ce = mb_cache_entry_alloc(ext3_xattr_cache);
-+ if (!ce)
-+ return -ENOMEM;
-+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
-+ if (error) {
-+ mb_cache_entry_free(ce);
-+ if (error == -EBUSY) {
-+ ea_bdebug(bh, "already in cache (%d cache entries)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_cmp()
-+ *
-+ * Compare two extended attribute blocks for equality.
-+ *
-+ * Returns 0 if the blocks are equal, 1 if they differ, and
-+ * a negative error number on errors.
-+ */
-+static int
-+ext3_xattr_cmp(struct ext3_xattr_header *header1,
-+ struct ext3_xattr_header *header2)
-+{
-+ struct ext3_xattr_entry *entry1, *entry2;
-+
-+ entry1 = ENTRY(header1+1);
-+ entry2 = ENTRY(header2+1);
-+ while (!IS_LAST_ENTRY(entry1)) {
-+ if (IS_LAST_ENTRY(entry2))
-+ return 1;
-+ if (entry1->e_hash != entry2->e_hash ||
-+ entry1->e_name_len != entry2->e_name_len ||
-+ entry1->e_value_size != entry2->e_value_size ||
-+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
-+ return 1;
-+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
-+ return -EIO;
-+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
-+ (char *)header2 + le16_to_cpu(entry2->e_value_offs),
-+ le32_to_cpu(entry1->e_value_size)))
-+ return 1;
-+
-+ entry1 = EXT3_XATTR_NEXT(entry1);
-+ entry2 = EXT3_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext3_xattr_cache_find()
-+ *
-+ * Find an identical extended attribute block.
-+ *
-+ * Returns a pointer to the block found, or NULL if such a block was
-+ * not found or an error occurred.
-+ */
-+static struct buffer_head *
-+ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
-+{
-+ __u32 hash = le32_to_cpu(header->h_hash);
-+ struct mb_cache_entry *ce;
-+
-+ if (!header->h_hash)
-+ return NULL; /* never share */
-+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT3_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT3_XATTR_REFCOUNT_MAX);
-+ } else if (!ext3_xattr_cmp(header, HDR(bh))) {
-+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
-+ mb_cache_entry_release(ce);
-+ return bh;
-+ }
-+ brelse(bh);
-+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * ext3_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext3_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count)-1);
-+ mb_cache_entry_free(ce);
-+ } else
-+ ea_bdebug(bh, "no cache entry");
-+}
-+
-+#define NAME_HASH_SHIFT 5
-+#define VALUE_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ __u32 hash = 0;
-+ char *name = entry->e_name;
-+ int n;
-+
-+ for (n=0; n < entry->e_name_len; n++) {
-+ hash = (hash << NAME_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-+ *name++;
-+ }
-+
-+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-+ __u32 *value = (__u32 *)((char *)header +
-+ le16_to_cpu(entry->e_value_offs));
-+ for (n = (le32_to_cpu(entry->e_value_size) +
-+ EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
-+ hash = (hash << VALUE_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
-+ le32_to_cpu(*value++);
-+ }
-+ }
-+ entry->e_hash = cpu_to_le32(hash);
-+}
-+
-+#undef NAME_HASH_SHIFT
-+#undef VALUE_HASH_SHIFT
-+
-+#define BLOCK_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext3_xattr_rehash(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ struct ext3_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext3_xattr_hash_entry(header, entry);
-+ here = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(here)) {
-+ if (!here->e_hash) {
-+ /* Block is not shared if an entry's hash value == 0 */
-+ hash = 0;
-+ break;
-+ }
-+ hash = (hash << BLOCK_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
-+ le32_to_cpu(here->e_hash);
-+ here = EXT3_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+
-+int __init
-+init_ext3_xattr(void)
-+{
-+ ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 61);
-+ if (!ext3_xattr_cache)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext3_xattr(void)
-+{
-+ if (ext3_xattr_cache)
-+ mb_cache_destroy(ext3_xattr_cache);
-+ ext3_xattr_cache = NULL;
-+}
-+
-+#else /* CONFIG_EXT3_FS_XATTR_SHARING */
-+
-+int __init
-+init_ext3_xattr(void)
-+{
-+ return 0;
-+}
-+
-+void
-+exit_ext3_xattr(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
-diff -Nur linux-2.4.18/include/linux/ext3_fs.h linux-2.4.18ea/include/linux/ext3_fs.h
---- linux-2.4.18/include/linux/ext3_fs.h Sun Feb 24 04:42:59 2002
-+++ linux-2.4.18ea/include/linux/ext3_fs.h Mon Mar 11 03:27:00 2002
-@@ -58,8 +58,6 @@
- */
- #define EXT3_BAD_INO 1 /* Bad blocks inode */
- #define EXT3_ROOT_INO 2 /* Root inode */
--#define EXT3_ACL_IDX_INO 3 /* ACL inode */
--#define EXT3_ACL_DATA_INO 4 /* ACL inode */
- #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
- #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
-@@ -89,7 +87,6 @@
- #else
- # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
- #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -124,28 +121,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext3_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext3_acl_entry /* Access Control List Entry */
--{
-- __u32 acle_size;
-- __u16 acle_perms; /* Access permissions */
-- __u16 acle_type; /* Type of entry */
-- __u16 acle_tag; /* User or group identity */
-- __u16 acle_pad1;
-- __u32 acle_next; /* Pointer on next entry for the */
-- /* same inode or on next free entry */
--};
--
--/*
- * Structure of a blocks group descriptor
- */
- struct ext3_group_desc
-@@ -512,7 +487,7 @@
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-
--#define EXT3_FEATURE_COMPAT_SUPP 0
-+#define EXT3_FEATURE_COMPAT_SUPP EXT3_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
-@@ -603,4 +578,22 @@
- */
-
-+/* Defined for extended attributes */
-+#define CONFIG_EXT3_FS_XATTR y
-+#ifndef ENOATTR
-+#define ENOATTR ENODATA /* No such attribute */
-+#endif
-+#ifndef ENOTSUP
-+#define ENOTSUP EOPNOTSUPP /* Operation not supported */
-+#endif
-+#ifndef XATTR_NAME_MAX
-+#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
-+#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */
-+#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */
-+#endif
-+#ifndef XATTR_CREATE
-+#define XATTR_CREATE 1 /* set value, fail if attr already exists */
-+#define XATTR_REPLACE 2 /* set value, fail if attr does not exist */
-+#endif
-+
- /*
- * Ok, these declarations are also in <linux/kernel.h> but none of the
-@@ -628,6 +603,7 @@
- extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
-
- /* inode.c */
-+extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
- extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
- extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-
-@@ -694,8 +670,10 @@
-
- /* namei.c */
- extern struct inode_operations ext3_dir_inode_operations;
-+extern struct inode_operations ext3_special_inode_operations;
-
- /* symlink.c */
-+extern struct inode_operations ext3_symlink_inode_operations;
- extern struct inode_operations ext3_fast_symlink_inode_operations;
-
-
-diff -Nur linux-2.4.18/include/linux/ext3_jbd.h linux-2.4.18ea/include/linux/ext3_jbd.h
---- linux-2.4.18/include/linux/ext3_jbd.h Fri Dec 21 18:42:03 2001
-+++ linux-2.4.18ea/include/linux/ext3_jbd.h Mon Mar 25 00:11:36 2002
-@@ -30,13 +30,19 @@
-
- #define EXT3_SINGLEDATA_TRANS_BLOCKS 8
-
-+/* Extended attributes may touch two data buffers, two bitmap buffers,
-+ * and two group and summaries. */
-+
-+#define EXT3_XATTR_TRANS_BLOCKS 8
-+
- /* Define the minimum size for a transaction which modifies data. This
- * needs to take into account the fact that we may end up modifying two
- * quota files too (one for the group, one for the user quota). The
- * superblock only gets updated once, of course, so don't bother
- * counting that again for the quota updates. */
-
--#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
-+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
-+ EXT3_XATTR_TRANS_BLOCKS - 2)
-
- extern int ext3_writepage_trans_blocks(struct inode *inode);
-
-diff -Nur linux-2.4.18/include/linux/ext3_xattr.h linux-2.4.18ea/include/linux/ext3_xattr.h
---- linux-2.4.18/include/linux/ext3_xattr.h Thu Jan 1 01:00:00 1970
-+++ linux-2.4.18ea/include/linux/ext3_xattr.h Fri Apr 5 10:08:01 2002
-@@ -0,0 +1,155 @@
-+/*
-+ File: linux/ext3_xattr.h
-+
-+ On-disk format of extended attributes for the ext3 filesystem.
-+
-+ (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/xattr.h>
-+
-+/* Magic value in attribute blocks */
-+#define EXT3_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT3_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT3_XATTR_INDEX_MAX 10
-+#define EXT3_XATTR_INDEX_USER 1
-+
-+struct ext3_xattr_header {
-+ __u32 h_magic; /* magic number for identification */
-+ __u32 h_refcount; /* reference count */
-+ __u32 h_blocks; /* number of disk blocks used */
-+ __u32 h_hash; /* hash value of all attributes */
-+ __u32 h_reserved[4]; /* zero right now */
-+};
-+
-+struct ext3_xattr_entry {
-+ __u8 e_name_len; /* length of name */
-+ __u8 e_name_index; /* attribute name index */
-+ __u16 e_value_offs; /* offset in disk block of value */
-+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */
-+ __u32 e_value_size; /* size of attribute value */
-+ __u32 e_hash; /* hash value of name and value */
-+ char e_name[0]; /* attribute name */
-+};
-+
-+#define EXT3_XATTR_PAD_BITS 2
-+#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
-+#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
-+#define EXT3_XATTR_LEN(name_len) \
-+ (((name_len) + EXT3_XATTR_ROUND + \
-+ sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
-+#define EXT3_XATTR_NEXT(entry) \
-+ ( (struct ext3_xattr_entry *)( \
-+ (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT3_XATTR_SIZE(size) \
-+ (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
-+
-+#ifdef __KERNEL__
-+
-+# ifdef CONFIG_EXT3_FS_XATTR
-+
-+struct ext3_xattr_handler {
-+ char *prefix;
-+ size_t (*list)(char *list, struct inode *inode, const char *name,
-+ int name_len);
-+ int (*get)(struct inode *inode, const char *name, void *buffer,
-+ size_t size);
-+ int (*set)(struct inode *inode, const char *name, void *buffer,
-+ size_t size, int flags);
-+};
-+
-+extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
-+extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
-+
-+extern int ext3_setxattr(struct dentry *, const char *, void *, size_t, int);
-+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
-+extern int ext3_removexattr(struct dentry *, const char *);
-+
-+extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext3_xattr_list(struct inode *, char *, size_t);
-+extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, void *, size_t, int);
-+
-+extern void ext3_xattr_drop_inode(handle_t *, struct inode *);
-+extern void ext3_xattr_put_super(struct super_block *);
-+
-+extern int init_ext3_xattr(void) __init;
-+extern void exit_ext3_xattr(void);
-+
-+# else /* CONFIG_EXT3_FS_XATTR */
-+# define ext3_setxattr NULL
-+# define ext3_getxattr NULL
-+# define ext3_listxattr NULL
-+# define ext3_removexattr NULL
-+
-+static inline int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext3_xattr_list(struct inode *inode, void *buffer, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, void *value, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline void
-+ext3_xattr_drop_inode(handle_t *handle, struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext3_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext3_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT3_FS_XATTR */
-+
-+# ifdef CONFIG_EXT3_FS_XATTR_USER
-+
-+extern int init_ext3_xattr_user(void) __init;
-+extern void exit_ext3_xattr_user(void);
-+
-+# else /* CONFIG_EXT3_FS_XATTR_USER */
-+
-+static inline int
-+init_ext3_xattr_user(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext3_xattr_user(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT3_FS_XATTR_USER */
-+
-+#endif /* __KERNEL__ */
-+
-diff -Nur linux-2.4.18/include/linux/xattr.h linux-2.4.18ea/include/linux/xattr.h
---- linux-2.4.18/include/linux/xattr.h Thu Jan 1 01:00:00 1970
-+++ linux-2.4.18ea/include/linux/xattr.h Sun Mar 24 23:42:21 2002
-@@ -0,0 +1,15 @@
-+/*
-+ File: linux/xattr.h
-+
-+ Extended attributes handling.
-+
-+ Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
-+ Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
-+*/
-+#ifndef _LINUX_XATTR_H
-+#define _LINUX_XATTR_H
-+
-+#define XATTR_CREATE 1 /* set value, fail if attr already exists */
-+#define XATTR_REPLACE 2 /* set value, fail if attr does not exist */
-+
-+#endif /* _LINUX_XATTR_H */
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef _LUSTRE_DEBUG_H
-#define _LUSTRE_DEBUG_H
-
-#include <linux/lustre_net.h>
-
-#define ASSERT_MAX_SIZE_MB 60000ULL
-#define ASSERT_PAGE_INDEX(index, OP) \
-do { if (index > ASSERT_MAX_SIZE_MB << (20 - PAGE_SHIFT)) { \
- CERROR("bad page index %lu > %Lu\n", index, \
- ASSERT_MAX_SIZE_MB << (20 - PAGE_SHIFT)); \
- portal_debug = ~0UL; \
- OP; \
-}} while(0)
-
-#define ASSERT_FILE_OFFSET(offset, OP) \
-do { if (offset > ASSERT_MAX_SIZE_MB << 20) { \
- CERROR("bad file offset %Lu > %Lu\n", offset, \
- ASSERT_MAX_SIZE_MB << 20); \
- portal_debug = ~0UL; \
- OP; \
-}} while(0)
-
-/* lib/debug.c */
-int dump_lniobuf(struct niobuf_local *lnb);
-int dump_rniobuf(struct niobuf_remote *rnb);
-int dump_ioo(struct obd_ioobj *nb);
-int dump_req(struct ptlrpc_request *req);
-int dump_obdo(struct obdo *oa);
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc. <info@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Filesystem interface helper.
- *
- */
-
-#ifndef _LUSTRE_FSFILT_H
-#define _LUSTRE_FSFILT_H
-
-#ifdef __KERNEL__
-
-#include <linux/obd.h>
-#include <linux/fs.h>
-
-typedef void (*fsfilt_cb_t)(struct obd_device *obd, __u64 last_rcvd, int error);
-
-struct fsfilt_objinfo {
- struct dentry *fso_dentry;
- int fso_bufcnt;
-};
-
-struct fsfilt_operations {
- struct list_head fs_list;
- struct module *fs_owner;
- char *fs_type;
- void *(* fs_start)(struct inode *inode, int op);
- void *(* fs_brw_start)(int objcount, struct fsfilt_objinfo *fso,
- int niocount, struct niobuf_remote *nb);
- int (* fs_commit)(struct inode *inode, void *handle);
- int (* fs_setattr)(struct dentry *dentry, void *handle,
- struct iattr *iattr);
- int (* fs_set_md)(struct inode *inode, void *handle, void *md,
- int size);
- int (* fs_get_md)(struct inode *inode, void *md, int size);
- ssize_t (* fs_readpage)(struct file *file, char *buf, size_t count,
- loff_t *offset);
- int (* fs_journal_data)(struct file *file);
- int (* fs_set_last_rcvd)(struct obd_device *obd, __u64 last_rcvd,
- void *handle, fsfilt_cb_t cb_func);
- int (* fs_statfs)(struct super_block *sb, struct obd_statfs *osfs);
-};
-
-extern int fsfilt_register_ops(struct fsfilt_operations *fs_ops);
-extern void fsfilt_unregister_ops(struct fsfilt_operations *fs_ops);
-extern struct fsfilt_operations *fsfilt_get_ops(char *type);
-extern void fsfilt_put_ops(struct fsfilt_operations *fs_ops);
-
-#define FSFILT_OP_UNLINK 1
-#define FSFILT_OP_RMDIR 2
-#define FSFILT_OP_RENAME 3
-#define FSFILT_OP_CREATE 4
-#define FSFILT_OP_MKDIR 5
-#define FSFILT_OP_SYMLINK 6
-#define FSFILT_OP_MKNOD 7
-#define FSFILT_OP_SETATTR 8
-#define FSFILT_OP_LINK 9
-
-static inline void *fsfilt_start(struct obd_device *obd,
- struct inode *inode, int op)
-{
- return obd->obd_fsops->fs_start(inode, op);
-}
-
-static inline void *fsfilt_brw_start(struct obd_device *obd, int objcount,
- struct fsfilt_objinfo *fso, int niocount,
- struct niobuf_remote *nb)
-{
- return obd->obd_fsops->fs_brw_start(objcount, fso, niocount, nb);
-}
-
-static inline int fsfilt_commit(struct obd_device *obd, struct inode *inode,
- void *handle)
-{
- return obd->obd_fsops->fs_commit(inode, handle);
-}
-
-static inline int fsfilt_setattr(struct obd_device *obd, struct dentry *dentry,
- void *handle, struct iattr *iattr)
-{
- int rc;
- /*
- * NOTE: we probably don't need to take i_sem here when changing
- * ATTR_SIZE because the MDS never needs to truncate a file.
- * The ext2/ext3 code never truncates a directory, and files
- * stored on the MDS are entirely sparse (no data blocks).
- * If we do need to get it, we can do it here.
- */
- lock_kernel();
- rc = obd->obd_fsops->fs_setattr(dentry, handle, iattr);
- unlock_kernel();
-
- return rc;
-}
-
-static inline int fsfilt_set_md(struct obd_device *obd, struct inode *inode,
- void *handle, void *md, int size)
-{
- return obd->obd_fsops->fs_set_md(inode, handle, md, size);
-}
-
-static inline int fsfilt_get_md(struct obd_device *obd, struct inode *inode,
- void *md, int size)
-{
- return obd->obd_fsops->fs_get_md(inode, md, size);
-}
-
-static inline ssize_t fsfilt_readpage(struct obd_device *obd,
- struct file *file, char *buf,
- size_t count, loff_t *offset)
-{
- return obd->obd_fsops->fs_readpage(file, buf, count, offset);
-}
-
-static inline int fsfilt_journal_data(struct obd_device *obd, struct file *file)
-{
- return obd->obd_fsops->fs_journal_data(file);
-}
-
-static inline int fsfilt_set_last_rcvd(struct obd_device *obd, __u64 last_rcvd,
- void *handle, fsfilt_cb_t cb_func)
-{
- return obd->obd_fsops->fs_set_last_rcvd(obd, last_rcvd,handle,cb_func);
-}
-
-static inline int fsfilt_statfs(struct obd_device *obd, struct super_block *fs,
- struct obd_statfs *osfs)
-{
- return obd->obd_fsops->fs_statfs(fs, osfs);
-}
-
-#endif /* __KERNEL__ */
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#ifndef _OBD_CACHE_H__
-#define _OBD_CACHE_H__
-
-#ifdef __KERNEL__
-
-#define OBD_CACHE_DEVICENAME "cobd"
-
-#endif
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#ifndef _OBD_LOV_H__
-#define _OBD_LOV_H__
-
-#ifdef __KERNEL__
-
-#define OBD_LOV_DEVICENAME "lov"
-
-struct lov_object_id { /* per-child structure */
- __u64 l_object_id;
- __u32 l_device_id;
-};
-
-struct lov_md {
- __u64 lmd_object_id; /* lov object id */
- __u64 lmd_stripe_count;
- __u32 lmd_stripe_size;
- __u32 lmd_stripe_pattern; /* per-lov object stripe pattern */
- struct lov_object_id lmd_objects[0];
-};
-
-#endif
-#endif
+++ /dev/null
-# This is a BitKeeper generated patch for the following project:
-# Project Name: Linux kernel tree
-# This patch format is intended for GNU patch command version 2.5 or higher.
-# This patch includes the following deltas:
-# ChangeSet 1.809 -> 1.812
-# kernel/ksyms.c 1.149 -> 1.151
-# fs/ext3/Makefile 1.4 -> 1.5
-# include/linux/ext3_jbd.h 1.5 -> 1.6
-# fs/driverfs/inode.c 1.52 -> 1.53
-# include/linux/fs.h 1.175 -> 1.177
-# include/linux/namei.h 1.3 -> 1.4
-# fs/namei.c 1.56 -> 1.58
-# fs/nfsd/vfs.c 1.44 -> 1.45
-# arch/um/kernel/mem.c 1.5 -> 1.6
-# fs/ext3/ialloc.c 1.17 -> 1.18
-# fs/ext3/symlink.c 1.3 -> 1.4
-# fs/Makefile 1.42 -> 1.43
-# fs/ext3/namei.c 1.22 -> 1.23
-# include/linux/ext3_fs.h 1.11 -> 1.12
-# net/unix/af_unix.c 1.29 -> 1.30
-# fs/Config.in 1.39 -> 1.40
-# fs/ext3/inode.c 1.42 -> 1.43
-# fs/Config.help 1.21 -> 1.22
-# mm/slab.c 1.33 -> 1.34
-# fs/sysfs/inode.c 1.55 -> 1.56
-# fs/ext3/super.c 1.33 -> 1.34
-# fs/ext3/file.c 1.9 -> 1.10
-# include/linux/slab.h 1.13 -> 1.14
-# include/linux/dcache.h 1.19 -> 1.20
-# (new) -> 1.1 fs/ext3/xattr.h
-# (new) -> 1.1 include/linux/mbcache.h
-# (new) -> 1.1 include/linux/lustre_version.h
-# (new) -> 1.2 fs/ext3/xattr.c
-# (new) -> 1.1 fs/mbcache.c
-# (new) -> 1.1 fs/ext3/xattr_user.c
-#
-# The following is the BitKeeper ChangeSet Log
-# --------------------------------------------
-# 02/10/20 braam@clusterfs.com 1.810
-# xattrs for UML bk repository
-# --------------------------------------------
-# 02/10/20 braam@clusterfs.com 1.811
-# Changes for Lustre
-# --------------------------------------------
-# 02/12/11 root@kai.(none) 1.812
-# changed for lustre
-# --------------------------------------------
-#
-diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
---- a/arch/um/kernel/mem.c Thu Dec 12 20:58:37 2002
-+++ b/arch/um/kernel/mem.c Thu Dec 12 20:58:37 2002
-@@ -656,6 +656,22 @@
- return(phys_mem_map(pte_val(pte)));
- }
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+ struct page *page;
-+ struct mem_region *mr;
-+ unsigned long phys = __pa(kaddr);
-+ unsigned int n = phys_region_index(phys);
-+
-+ if(regions[n] == NULL)
-+ return NULL;
-+
-+ mr = regions[n];
-+ page = (struct page *) mr->mem_map;
-+ return page + ((phys_addr(phys)) >> PAGE_SHIFT);
-+}
-+
-+
- struct mem_region *page_region(struct page *page, int *index_out)
- {
- int i;
-@@ -743,7 +759,7 @@
- (addr <= region->start + region->len))
- return(mk_phys(addr - region->start, i));
- }
-- panic("region_pa : no region for virtual address");
-+ //panic("region_pa : no region for virtual address");
- return(0);
- }
-
-diff -Nru a/fs/Config.help b/fs/Config.help
---- a/fs/Config.help Thu Dec 12 20:58:37 2002
-+++ b/fs/Config.help Thu Dec 12 20:58:37 2002
-@@ -154,6 +154,13 @@
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this may be dangerous.
-
-+CONFIG_EXT3_FS_XATTR
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
- CONFIG_JBD
- This is a generic journaling layer for block devices. It is
- currently used by the ext3 file system, but it could also be used to
-diff -Nru a/fs/Config.in b/fs/Config.in
---- a/fs/Config.in Thu Dec 12 20:58:37 2002
-+++ b/fs/Config.in Thu Dec 12 20:58:37 2002
-@@ -27,6 +27,7 @@
- dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
-
- tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
-+dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
- # CONFIG_JBD could be its own option (even modular), but until there are
- # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
- # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
-@@ -180,6 +181,17 @@
- define_tristate CONFIG_ZISOFS_FS $CONFIG_ISO9660_FS
- else
- define_tristate CONFIG_ZISOFS_FS n
-+fi
-+
-+# Meta block cache for Extended Attributes (ext2/ext3)
-+if [ "$CONFIG_EXT2_FS_XATTR" = "y" -o "$CONFIG_EXT3_FS_XATTR" = "y" ]; then
-+ if [ "$CONFIG_EXT2_FS" = "y" -o "$CONFIG_EXT3_FS" = "y" ]; then
-+ define_tristate CONFIG_FS_MBCACHE y
-+ else
-+ if [ "$CONFIG_EXT2_FS" = "m" -o "$CONFIG_EXT3_FS" = "m" ]; then
-+ define_tristate CONFIG_FS_MBCACHE m
-+ fi
-+ fi
- fi
-
- mainmenu_option next_comment
-diff -Nru a/fs/Makefile b/fs/Makefile
---- a/fs/Makefile Thu Dec 12 20:58:37 2002
-+++ b/fs/Makefile Thu Dec 12 20:58:37 2002
-@@ -6,7 +6,7 @@
- #
-
- export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o \
-- fcntl.o read_write.o dcookies.o
-+ fcntl.o read_write.o dcookies.o mbcache.o
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
- bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \
-@@ -29,6 +29,8 @@
- obj-y += binfmt_script.o
-
- obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
-+
-+obj-$(CONFIG_FS_MBCACHE) += mbcache.o
-
- obj-$(CONFIG_QUOTA) += dquot.o
- obj-$(CONFIG_QFMT_V1) += quota_v1.o
-diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c
---- a/fs/driverfs/inode.c Thu Dec 12 20:58:37 2002
-+++ b/fs/driverfs/inode.c Thu Dec 12 20:58:37 2002
-@@ -523,7 +523,7 @@
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-- return lookup_hash(&qstr,parent);
-+ return lookup_hash(&qstr,parent, NULL);
- }
-
- /**
-diff -Nru a/fs/ext3/Makefile b/fs/ext3/Makefile
---- a/fs/ext3/Makefile Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/Makefile Thu Dec 12 20:58:37 2002
-@@ -7,4 +7,10 @@
- ext3-objs := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o hash.o
-
-+export-objs += xattr.o
-+
-+ifeq ($(CONFIG_EXT3_FS_XATTR),y)
-+ext3-objs += xattr.o xattr_user.o
-+endif
-+
- include $(TOPDIR)/Rules.make
-diff -Nru a/fs/ext3/file.c b/fs/ext3/file.c
---- a/fs/ext3/file.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/file.c Thu Dec 12 20:58:37 2002
-@@ -23,7 +23,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
--#include <linux/smp_lock.h>
-+#include "xattr.h"
-
- /*
- * Called when an inode is released. Note that this is different
-@@ -98,5 +98,9 @@
- struct inode_operations ext3_file_inode_operations = {
- .truncate = ext3_truncate,
- .setattr = ext3_setattr,
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
- };
-
-diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
---- a/fs/ext3/ialloc.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/ialloc.c Thu Dec 12 20:58:37 2002
-@@ -25,6 +25,8 @@
- #include <asm/bitops.h>
- #include <asm/byteorder.h>
-
-+#include "xattr.h"
-+
- /*
- * ialloc.c contains the inodes allocation and deallocation routines
- */
-@@ -118,6 +120,7 @@
- * as writing the quota to disk may need the lock as well.
- */
- DQUOT_INIT(inode);
-+ ext3_xattr_delete_inode(handle, inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
-
-diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
---- a/fs/ext3/inode.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/inode.c Thu Dec 12 20:58:37 2002
-@@ -42,6 +42,18 @@
- */
- #undef SEARCH_FROM_ZERO
-
-+/*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext3_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = EXT3_I(inode)->i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
- /* The ext3 forget function must perform a revoke if we are freeing data
- * which has been journaled. Metadata (eg. indirect blocks) must be
- * revoked in all cases.
-@@ -51,7 +63,7 @@
- * still needs to be revoked.
- */
-
--static int ext3_forget(handle_t *handle, int is_metadata,
-+int ext3_forget(handle_t *handle, int is_metadata,
- struct inode *inode, struct buffer_head *bh,
- int blocknr)
- {
-@@ -167,9 +179,7 @@
- {
- handle_t *handle;
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
-
- lock_kernel();
-@@ -1979,6 +1989,8 @@
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext3_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -2130,8 +2142,6 @@
- struct ext3_group_desc * gdp;
-
- if ((inode->i_ino != EXT3_ROOT_INO &&
-- inode->i_ino != EXT3_ACL_IDX_INO &&
-- inode->i_ino != EXT3_ACL_DATA_INO &&
- inode->i_ino != EXT3_JOURNAL_INO &&
- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(
-@@ -2263,10 +2273,7 @@
-
- brelse (iloc.bh);
-
-- if (inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
- if (ext3_should_writeback_data(inode))
-@@ -2277,18 +2284,20 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext3_inode_is_fast_symlink(inode))
- inode->i_op = &ext3_fast_symlink_inode_operations;
- else {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext3_symlink_inode_operations;
- if (ext3_should_writeback_data(inode))
- inode->i_mapping->a_ops = &ext3_writeback_aops;
- else
- inode->i_mapping->a_ops = &ext3_aops;
- }
-- } else
-+ } else {
-+ inode->i_op = &ext3_special_inode_operations;
- init_special_inode(inode, inode->i_mode,
- le32_to_cpu(iloc.raw_inode->i_block[0]));
-+ }
- if (ei->i_flags & EXT3_SYNC_FL)
- inode->i_flags |= S_SYNC;
- if (ei->i_flags & EXT3_APPEND_FL)
-diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c
---- a/fs/ext3/namei.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/namei.c Thu Dec 12 20:58:37 2002
-@@ -36,6 +36,7 @@
- #include <linux/quotaops.h>
- #include <linux/buffer_head.h>
- #include <linux/smp_lock.h>
-+#include "xattr.h"
-
-
- /*
-@@ -1654,7 +1655,7 @@
- if (IS_DIRSYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFDIR);
-+ inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
-@@ -1662,7 +1663,6 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-- inode->i_blocks = 0;
- dir_block = ext3_bread (handle, inode, 0, 1, &err);
- if (!dir_block) {
- inode->i_nlink--; /* is this nlink == 0? */
-@@ -1689,9 +1689,6 @@
- BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, dir_block);
- brelse (dir_block);
-- inode->i_mode = S_IFDIR | mode;
-- if (dir->i_mode & S_ISGID)
-- inode->i_mode |= S_ISGID;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_entry (handle, dentry, inode);
- if (err) {
-@@ -2068,7 +2065,7 @@
- goto out_stop;
-
- if (l > sizeof (EXT3_I(inode)->i_data)) {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext3_symlink_inode_operations;
- if (ext3_should_writeback_data(inode))
- inode->i_mapping->a_ops = &ext3_writeback_aops;
- else
-@@ -2284,4 +2281,17 @@
- .rmdir = ext3_rmdir,
- .mknod = ext3_mknod,
- .rename = ext3_rename,
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
- };
-+
-+struct inode_operations ext3_special_inode_operations = {
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
-+};
-+
-+
-diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
---- a/fs/ext3/super.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/super.c Thu Dec 12 20:58:37 2002
-@@ -30,6 +30,7 @@
- #include <linux/smp_lock.h>
- #include <linux/buffer_head.h>
- #include <asm/uaccess.h>
-+#include "xattr.h"
-
- #ifdef CONFIG_JBD_DEBUG
- static int ext3_ro_after; /* Make fs read-only after this many jiffies */
-@@ -405,6 +406,7 @@
- struct ext3_super_block *es = sbi->s_es;
- int i;
-
-+ ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
- EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-@@ -554,6 +556,7 @@
- int is_remount)
- {
- unsigned long *mount_options = &sbi->s_mount_opt;
-+
- uid_t *resuid = &sbi->s_resuid;
- gid_t *resgid = &sbi->s_resgid;
- char * this_char;
-@@ -566,6 +569,13 @@
- continue;
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT3_FS_XATTR
-+ if (!strcmp (this_char, "user_xattr"))
-+ set_opt (*mount_options, XATTR_USER);
-+ else if (!strcmp (this_char, "nouser_xattr"))
-+ clear_opt (*mount_options, XATTR_USER);
-+ else
-+#endif
- if (!strcmp (this_char, "bsddf"))
- clear_opt (*mount_options, MINIX_DF);
- else if (!strcmp (this_char, "nouid32")) {
-@@ -982,6 +992,12 @@
- sbi->s_mount_opt = 0;
- sbi->s_resuid = EXT3_DEF_RESUID;
- sbi->s_resgid = EXT3_DEF_RESGID;
-+
-+ /* Default extended attribute flags */
-+#ifdef CONFIG_EXT3_FS_XATTR
-+ set_opt(sbi->s_mount_opt, XATTR_USER);
-+#endif
-+
- if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0))
- goto out_fail;
-
-@@ -1820,7 +1836,10 @@
-
- static int __init init_ext3_fs(void)
- {
-- int err = init_inodecache();
-+ int err = init_ext3_xattr();
-+ if (err)
-+ return err;
-+ err = init_inodecache();
- if (err)
- goto out1;
- err = register_filesystem(&ext3_fs_type);
-@@ -1830,6 +1849,7 @@
- out:
- destroy_inodecache();
- out1:
-+ exit_ext3_xattr();
- return err;
- }
-
-@@ -1837,6 +1857,7 @@
- {
- unregister_filesystem(&ext3_fs_type);
- destroy_inodecache();
-+ exit_ext3_xattr();
- }
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
-diff -Nru a/fs/ext3/symlink.c b/fs/ext3/symlink.c
---- a/fs/ext3/symlink.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/symlink.c Thu Dec 12 20:58:37 2002
-@@ -20,6 +20,7 @@
- #include <linux/fs.h>
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
-+#include "xattr.h"
-
- static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-@@ -33,7 +34,20 @@
- return vfs_follow_link(nd, (char*)ei->i_data);
- }
-
-+struct inode_operations ext3_symlink_inode_operations = {
-+ .readlink = page_readlink,
-+ .follow_link = page_follow_link,
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
-+};
-+
- struct inode_operations ext3_fast_symlink_inode_operations = {
-- .readlink = ext3_readlink, /* BKL not held. Don't need */
-+ .readlink = ext3_readlink, /* BKL not held. Don't need */
- .follow_link = ext3_follow_link, /* BKL not held. Don't need */
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
- };
-diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/ext3/xattr.c Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,1131 @@
-+/*
-+ * linux/fs/ext3/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
-+ * Extended attributes for symlinks and special files added per
-+ * suggestion of Luka Renko <luka.renko@hermes.si>.
-+ */
-+
-+/*
-+ * Extended attributes are stored on disk blocks allocated outside of
-+ * any inode. The i_file_acl field is then made to point to this allocated
-+ * block. If all extended attributes of an inode are identical, these
-+ * inodes may share the same extended attribute block. Such situations
-+ * are automatically detected by keeping a cache of recent attribute block
-+ * numbers and hashes over the block's contents in memory.
-+ *
-+ *
-+ * Extended attribute block layout:
-+ *
-+ * +------------------+
-+ * | header |
-+ * ¦ entry 1 | |
-+ * | entry 2 | | growing downwards
-+ * | entry 3 | v
-+ * | four null bytes |
-+ * | . . . |
-+ * | value 1 | ^
-+ * | value 3 | | growing upwards
-+ * | value 2 | |
-+ * +------------------+
-+ *
-+ * The block header is followed by multiple entry descriptors. These entry
-+ * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
-+ * byte boundaries. The entry descriptors are sorted by attribute name,
-+ * so that two extended attribute blocks can be compared efficiently.
-+ *
-+ * Attribute values are aligned to the end of the block, stored in
-+ * no specific order. They are also padded to EXT3_XATTR_PAD byte
-+ * boundaries. No additional gaps are left between them.
-+ *
-+ * Locking strategy
-+ * ----------------
-+ * The VFS holdsinode->i_sem semaphore when any of the xattr inode
-+ * operations are called, so we are guaranteed that only one
-+ * processes accesses extended attributes of an inode at any time.
-+ *
-+ * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
-+ * only a single process is modifying an extended attribute block, even
-+ * if the block is shared among inodes.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/mbcache.h>
-+#include <linux/module.h>
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include "xattr.h"
-+
-+#define EXT3_EA_USER "user."
-+
-+#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT3_XATTR_DEBUG
-+# define ea_idebug(inode, f...) do { \
-+ printk(KERN_DEBUG "inode %s:%ld: ", \
-+ kdevname(inode->i_dev), inode->i_ino); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+# define ea_bdebug(bh, f...) do { \
-+ printk(KERN_DEBUG "block %s:%ld: ", \
-+ kdevname(bh->b_dev), bh->b_blocknr); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+#else
-+# define ea_idebug(f...)
-+# define ea_bdebug(f...)
-+#endif
-+
-+static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
-+ struct ext3_xattr_header *);
-+
-+static int ext3_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext3_xattr_cache_find(struct inode *,
-+ struct ext3_xattr_header *);
-+static void ext3_xattr_cache_remove(struct buffer_head *);
-+static void ext3_xattr_rehash(struct ext3_xattr_header *,
-+ struct ext3_xattr_entry *);
-+
-+static struct mb_cache *ext3_xattr_cache;
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext3_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+static DECLARE_MUTEX(ext3_xattr_sem);
-+static struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
-+static rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ if (!ext3_xattr_handlers[name_index-1]) {
-+ ext3_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext3_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ ext3_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext3_handler_lock);
-+ }
-+}
-+
-+static inline const char *
-+strcmp_prefix(const char *a, const char *a_prefix)
-+{
-+ while (*a_prefix && *a == *a_prefix) {
-+ a++;
-+ a_prefix++;
-+ }
-+ return *a_prefix ? NULL : a;
-+}
-+
-+/*
-+ * Decode the extended attribute name, and translate it into
-+ * the name_index and name suffix.
-+ */
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_resolve_name(const char **name)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext3_handler_lock);
-+ for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
-+ if (ext3_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext3_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext3_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext3_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_handler(int name_index)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ read_lock(&ext3_handler_lock);
-+ handler = ext3_xattr_handlers[name_index-1];
-+ read_unlock(&ext3_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+ssize_t
-+ext3_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -EOPNOTSUPP;
-+ return handler->get(inode, name, buffer, size);
-+}
-+
-+/*
-+ * Inode operation listxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+ssize_t
-+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext3_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+int
-+ext3_setxattr(struct dentry *dentry, const char *name,
-+ void *value, size_t size, int flags)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -EOPNOTSUPP;
-+ return handler->set(inode, name, value, size, flags);
-+}
-+
-+/*
-+ * Inode operation removexattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+int
-+ext3_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -EOPNOTSUPP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext3_xattr_get()
-+ *
-+ * Copy an extended attribute into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size;
-+ char *end;
-+ int name_len, error;
-+
-+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
-+ name_index, name, buffer, (long)buffer_size);
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return -ENODATA;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* find named attribute */
-+ name_len = strlen(name);
-+
-+ error = -ERANGE;
-+ if (name_len > 255)
-+ goto cleanup;
-+ entry = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0)
-+ goto found;
-+ entry = next;
-+ }
-+ /* Check the remaining name entries */
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ error = -ENODATA;
-+ goto cleanup;
-+found:
-+ /* check the buffer size */
-+ if (entry->e_value_block != 0)
-+ goto bad_block;
-+ size = le32_to_cpu(entry->e_value_size);
-+ if (size > inode->i_sb->s_blocksize ||
-+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
-+ goto bad_block;
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (buffer) {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ /* return value of attribute */
-+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
-+ size);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size = 0;
-+ char *buf, *end;
-+ int error;
-+
-+ ea_idebug(inode, "buffer=%p, buffer_size=%ld",
-+ buffer, (long)buffer_size);
-+
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* compute the size required for the list of attribute names */
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len) + 1;
-+ }
-+ }
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (!buffer) {
-+ error = size;
-+ goto cleanup;
-+ } else {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ }
-+
-+ /* list the attribute names */
-+ buf = buffer;
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ *buf++ = '\0';
-+ }
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext3_xattr_update_super_block(handle_t *handle,
-+ struct super_block *sb)
-+{
-+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+ ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-+ EXT3_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext3_xattr_set()
-+ *
-+ * Create, replace or remove an extended attribute for this inode. Buffer
-+ * is NULL to remove an existing extended attribute, and non-NULL to
-+ * either replace an existing extended attribute, or create a new extended
-+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
-+ * specify that an extended attribute must exist and must not exist
-+ * previous to the call, respectively.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t value_len, int flags)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_header *header = NULL;
-+ struct ext3_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int min_offs = sb->s_blocksize, not_found = 1, free, error;
-+ char *end;
-+
-+ /*
-+ * header -- Points either into bh, or to a temporarily
-+ * allocated buffer.
-+ * here -- The named entry found, or the place for inserting, within
-+ * the block pointed to by header.
-+ * last -- Points right after the last named entry within the block
-+ * pointed to by header.
-+ * min_offs -- The offset of the first value (values are aligned
-+ * towards the end of the block).
-+ * end -- Points right after the block pointed to by header.
-+ */
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+ return -EPERM;
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > sb->s_blocksize)
-+ return -ERANGE;
-+ down(&ext3_xattr_sem);
-+
-+ if (EXT3_I(inode)->i_file_acl) {
-+ /* The inode already has an extended attribute block. */
-+ int block = EXT3_I(inode)->i_file_acl;
-+
-+ bh = sb_bread(sb, block);
-+ error = -EIO;
-+ if (!bh)
-+ goto cleanup;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)),
-+ le32_to_cpu(HDR(bh)->h_refcount));
-+ header = HDR(bh);
-+ end = bh->b_data + bh->b_size;
-+ if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(sb, "ext3_xattr_set",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* Find the named attribute. */
-+ here = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(here)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!here->e_value_block && here->e_value_size) {
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ not_found = name_index - here->e_name_index;
-+ if (!not_found)
-+ not_found = name_len - here->e_name_len;
-+ if (!not_found)
-+ not_found = memcmp(name, here->e_name,name_len);
-+ if (not_found <= 0)
-+ break;
-+ here = next;
-+ }
-+ last = here;
-+ /* We still need to compute min_offs and last. */
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!last->e_value_block && last->e_value_size) {
-+ int offs = le16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ last = next;
-+ }
-+
-+ /* Check whether we have enough space left. */
-+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
-+ } else {
-+ /* We will use a new extended attribute block. */
-+ free = sb->s_blocksize -
-+ sizeof(struct ext3_xattr_header) - sizeof(__u32);
-+ here = last = NULL; /* avoid gcc uninitialized warning. */
-+ }
-+
-+ if (not_found) {
-+ /* Request to remove a nonexistent attribute? */
-+ error = -ENODATA;
-+ if (flags & XATTR_REPLACE)
-+ goto cleanup;
-+ error = 0;
-+ if (value == NULL)
-+ goto cleanup;
-+ else
-+ free -= EXT3_XATTR_LEN(name_len);
-+ } else {
-+ /* Request to create an existing attribute? */
-+ error = -EEXIST;
-+ if (flags & XATTR_CREATE)
-+ goto cleanup;
-+ if (!here->e_value_block && here->e_value_size) {
-+ unsigned int size = le32_to_cpu(here->e_value_size);
-+
-+ if (le16_to_cpu(here->e_value_offs) + size >
-+ sb->s_blocksize || size > sb->s_blocksize)
-+ goto bad_block;
-+ free += EXT3_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT3_XATTR_SIZE(value_len);
-+ error = -ENOSPC;
-+ if (free < 0)
-+ goto cleanup;
-+
-+ /* Here we know that we can set the new attribute. */
-+
-+ if (header) {
-+ if (header->h_refcount == cpu_to_le32(1)) {
-+ ea_bdebug(bh, "modifying in-place");
-+ ext3_xattr_cache_remove(bh);
-+ error = ext3_journal_get_write_access(handle, bh);
-+ if (error)
-+ goto cleanup;
-+ } else {
-+ int offset;
-+
-+ ea_bdebug(bh, "cloning");
-+ header = kmalloc(bh->b_size, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memcpy(header, HDR(bh), bh->b_size);
-+ header->h_refcount = cpu_to_le32(1);
-+ offset = (char *)header - bh->b_data;
-+ here = ENTRY((char *)here + offset);
-+ last = ENTRY((char *)last + offset);
-+ }
-+ } else {
-+ /* Allocate a buffer where we construct the new block. */
-+ header = kmalloc(sb->s_blocksize, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memset(header, 0, sb->s_blocksize);
-+ end = (char *)header + sb->s_blocksize;
-+ header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
-+ header->h_blocks = header->h_refcount = cpu_to_le32(1);
-+ last = here = ENTRY(header+1);
-+ }
-+
-+ if (not_found) {
-+ /* Insert the new name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ int rest = (char *)last - (char *)here;
-+ memmove((char *)here + size, here, rest);
-+ memset(here, 0, size);
-+ here->e_name_index = name_index;
-+ here->e_name_len = name_len;
-+ memcpy(here->e_name, name, name_len);
-+ } else {
-+ /* Remove the old value. */
-+ if (!here->e_value_block && here->e_value_size) {
-+ char *first_val = (char *)header + min_offs;
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ char *val = (char *)header + offs;
-+ size_t size = EXT3_XATTR_SIZE(
-+ le32_to_cpu(here->e_value_size));
-+ memmove(first_val + size, first_val, val - first_val);
-+ memset(first_val, 0, size);
-+ here->e_value_offs = 0;
-+ min_offs += size;
-+
-+ /* Adjust all value offsets. */
-+ last = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(last)) {
-+ int o = le16_to_cpu(last->e_value_offs);
-+ if (!last->e_value_block && o < offs)
-+ last->e_value_offs =
-+ cpu_to_le16(o + size);
-+ last = EXT3_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext3_xattr_set2(handle, inode, bh,NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ last = ENTRY((char *)last - size);
-+ memmove(here, (char*)here + size,
-+ (char*)last - (char*)here);
-+ memset(last, 0, size);
-+ }
-+ }
-+ }
-+
-+ if (value != NULL) {
-+ /* Insert the new value. */
-+ here->e_value_size = cpu_to_le32(value_len);
-+ if (value_len) {
-+ size_t size = EXT3_XATTR_SIZE(value_len);
-+ char *val = (char *)header + min_offs - size;
-+ here->e_value_offs =
-+ cpu_to_le16((char *)val - (char *)header);
-+ memset(val + size - EXT3_XATTR_PAD, 0,
-+ EXT3_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext3_xattr_rehash(header, here);
-+
-+ error = ext3_xattr_set2(handle, inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ up(&ext3_xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext3_xattr_set(): Update the file system.
-+ */
-+static int
-+ext3_xattr_set2(handle_t *handle, struct inode *inode,
-+ struct buffer_head *old_bh, struct ext3_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext3_xattr_cache_find(inode, header);
-+ if (new_bh) {
-+ /*
-+ * We found an identical block in the cache.
-+ * The old block will be released after updating
-+ * the inode.
-+ */
-+ ea_bdebug(old_bh, "reusing block %ld",
-+ new_bh->b_blocknr);
-+
-+ error = -EDQUOT;
-+ if (DQUOT_ALLOC_BLOCK(inode, 1))
-+ goto cleanup;
-+
-+ error = ext3_journal_get_write_access(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ HDR(new_bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
-+ ea_bdebug(new_bh, "refcount now=%d",
-+ le32_to_cpu(HDR(new_bh)->h_refcount));
-+ } else if (old_bh && header == HDR(old_bh)) {
-+ /* Keep this block. */
-+ new_bh = old_bh;
-+ ext3_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int block;
-+ int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-+ EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
-+
-+ block = ext3_new_block(handle, inode, goal, 0,
-+ 0, &error);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+getblk_failed:
-+ ext3_free_blocks(handle, inode, block, 1);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ error = ext3_journal_get_create_access(handle, new_bh);
-+ if (error) {
-+ unlock_buffer(new_bh);
-+ goto getblk_failed;
-+ }
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ set_buffer_uptodate(new_bh);
-+ unlock_buffer(new_bh);
-+ ext3_xattr_cache_insert(new_bh);
-+
-+ ext3_xattr_update_super_block(handle, sb);
-+ }
-+ error = ext3_journal_dirty_metadata(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ }
-+
-+ /* Update the inode. */
-+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ ext3_mark_inode_dirty(handle, inode);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+
-+ error = 0;
-+ if (old_bh && old_bh != new_bh) {
-+ /*
-+ * If there was an old block, and we are not still using it,
-+ * we now release the old block.
-+ */
-+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-+
-+ error = ext3_journal_get_write_access(handle, old_bh);
-+ if (error)
-+ goto cleanup;
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext3_free_blocks(handle, inode, old_bh->b_blocknr, 1);
-+
-+ /* ext3_forget() calls bforget() for us, but we
-+ let our caller release old_bh, so we need to
-+ duplicate the handle before. */
-+ get_bh(old_bh);
-+ ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ DQUOT_FREE_BLOCK(inode, 1);
-+ ext3_journal_dirty_metadata(handle, old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT3_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ down(&ext3_xattr_sem);
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
-+ "inode %ld: block %d read error", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ext3_journal_get_write_access(handle, bh);
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext3_xattr_cache_remove(bh);
-+ ext3_free_blocks(handle, inode, block, 1);
-+ ext3_forget(handle, 1, inode, bh, block);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ ext3_journal_dirty_metadata(handle, bh);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+ DQUOT_FREE_BLOCK(inode, 1);
-+ }
-+ EXT3_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ up(&ext3_xattr_sem);
-+}
-+
-+/*
-+ * ext3_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+ mb_cache_shrink(ext3_xattr_cache, sb->s_bdev);
-+}
-+
-+/*
-+ * ext3_xattr_cache_insert()
-+ *
-+ * Create a new entry in the extended attribute cache, and insert
-+ * it unless such an entry is already in the cache.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+static int
-+ext3_xattr_cache_insert(struct buffer_head *bh)
-+{
-+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
-+ struct mb_cache_entry *ce;
-+ int error;
-+
-+ ce = mb_cache_entry_alloc(ext3_xattr_cache);
-+ if (!ce)
-+ return -ENOMEM;
-+ error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, &hash);
-+ if (error) {
-+ mb_cache_entry_free(ce);
-+ if (error == -EBUSY) {
-+ ea_bdebug(bh, "already in cache (%d cache entries)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_cmp()
-+ *
-+ * Compare two extended attribute blocks for equality.
-+ *
-+ * Returns 0 if the blocks are equal, 1 if they differ, and
-+ * a negative error number on errors.
-+ */
-+static int
-+ext3_xattr_cmp(struct ext3_xattr_header *header1,
-+ struct ext3_xattr_header *header2)
-+{
-+ struct ext3_xattr_entry *entry1, *entry2;
-+
-+ entry1 = ENTRY(header1+1);
-+ entry2 = ENTRY(header2+1);
-+ while (!IS_LAST_ENTRY(entry1)) {
-+ if (IS_LAST_ENTRY(entry2))
-+ return 1;
-+ if (entry1->e_hash != entry2->e_hash ||
-+ entry1->e_name_len != entry2->e_name_len ||
-+ entry1->e_value_size != entry2->e_value_size ||
-+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
-+ return 1;
-+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
-+ return -EIO;
-+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
-+ (char *)header2 + le16_to_cpu(entry2->e_value_offs),
-+ le32_to_cpu(entry1->e_value_size)))
-+ return 1;
-+
-+ entry1 = EXT3_XATTR_NEXT(entry1);
-+ entry2 = EXT3_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext3_xattr_cache_find()
-+ *
-+ * Find an identical extended attribute block.
-+ *
-+ * Returns a pointer to the block found, or NULL if such a block was
-+ * not found or an error occurred.
-+ */
-+static struct buffer_head *
-+ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
-+{
-+ __u32 hash = le32_to_cpu(header->h_hash);
-+ struct mb_cache_entry *ce;
-+
-+ if (!header->h_hash)
-+ return NULL; /* never share */
-+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_bdev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, (unsigned long) ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT3_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",
-+ (unsigned long) ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT3_XATTR_REFCOUNT_MAX);
-+ } else if (!ext3_xattr_cmp(header, HDR(bh))) {
-+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
-+ mb_cache_entry_release(ce);
-+ return bh;
-+ }
-+ brelse(bh);
-+ ce = mb_cache_entry_find_next(ce, 0, inode->i_bdev, hash);
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * ext3_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext3_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_bdev,
-+ bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count)-1);
-+ mb_cache_entry_free(ce);
-+ } else
-+ ea_bdebug(bh, "no cache entry");
-+}
-+
-+#define NAME_HASH_SHIFT 5
-+#define VALUE_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ __u32 hash = 0;
-+ char *name = entry->e_name;
-+ int n;
-+
-+ for (n=0; n < entry->e_name_len; n++) {
-+ hash = (hash << NAME_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-+ *name++;
-+ }
-+
-+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-+ __u32 *value = (__u32 *)((char *)header +
-+ le16_to_cpu(entry->e_value_offs));
-+ for (n = (le32_to_cpu(entry->e_value_size) +
-+ EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
-+ hash = (hash << VALUE_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
-+ le32_to_cpu(*value++);
-+ }
-+ }
-+ entry->e_hash = cpu_to_le32(hash);
-+}
-+
-+#undef NAME_HASH_SHIFT
-+#undef VALUE_HASH_SHIFT
-+
-+#define BLOCK_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext3_xattr_rehash(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ struct ext3_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext3_xattr_hash_entry(header, entry);
-+ here = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(here)) {
-+ if (!here->e_hash) {
-+ /* Block is not shared if an entry's hash value == 0 */
-+ hash = 0;
-+ break;
-+ }
-+ hash = (hash << BLOCK_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
-+ le32_to_cpu(here->e_hash);
-+ here = EXT3_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+EXPORT_SYMBOL(ext3_xattr_get);
-+EXPORT_SYMBOL(ext3_xattr_set);
-+EXPORT_SYMBOL(ext3_bread);
-+
-+int __init
-+init_ext3_xattr(void)
-+{
-+ int err;
-+
-+ err = ext3_xattr_register(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
-+ if (err)
-+ return err;
-+ ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 6);
-+ if (!ext3_xattr_cache) {
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext3_xattr(void)
-+{
-+ if (ext3_xattr_cache)
-+ mb_cache_destroy(ext3_xattr_cache);
-+ ext3_xattr_cache = NULL;
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
-+}
-+
-diff -Nru a/fs/ext3/xattr.h b/fs/ext3/xattr.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/ext3/xattr.h Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,133 @@
-+/*
-+ File: fs/ext3/xattr.h
-+
-+ On-disk format of extended attributes for the ext3 filesystem.
-+
-+ (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+#include <linux/config.h>
-+#include <linux/xattr.h>
-+
-+/* Magic value in attribute blocks */
-+#define EXT3_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT3_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT3_XATTR_INDEX_MAX 10
-+#define EXT3_XATTR_INDEX_USER 1
-+#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
-+#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+
-+struct ext3_xattr_header {
-+ __u32 h_magic; /* magic number for identification */
-+ __u32 h_refcount; /* reference count */
-+ __u32 h_blocks; /* number of disk blocks used */
-+ __u32 h_hash; /* hash value of all attributes */
-+ __u32 h_reserved[4]; /* zero right now */
-+};
-+
-+struct ext3_xattr_entry {
-+ __u8 e_name_len; /* length of name */
-+ __u8 e_name_index; /* attribute name index */
-+ __u16 e_value_offs; /* offset in disk block of value */
-+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */
-+ __u32 e_value_size; /* size of attribute value */
-+ __u32 e_hash; /* hash value of name and value */
-+ char e_name[0]; /* attribute name */
-+};
-+
-+#define EXT3_XATTR_PAD_BITS 2
-+#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
-+#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
-+#define EXT3_XATTR_LEN(name_len) \
-+ (((name_len) + EXT3_XATTR_ROUND + \
-+ sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
-+#define EXT3_XATTR_NEXT(entry) \
-+ ( (struct ext3_xattr_entry *)( \
-+ (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT3_XATTR_SIZE(size) \
-+ (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
-+
-+# ifdef CONFIG_EXT3_FS_XATTR
-+
-+struct ext3_xattr_handler {
-+ char *prefix;
-+ size_t (*list)(char *list, struct inode *inode, const char *name,
-+ int name_len);
-+ int (*get)(struct inode *inode, const char *name, void *buffer,
-+ size_t size);
-+ int (*set)(struct inode *inode, const char *name, const void *buffer,
-+ size_t size, int flags);
-+};
-+
-+extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
-+extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
-+
-+extern int ext3_setxattr(struct dentry *, const char *, void *, size_t, int);
-+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
-+extern int ext3_removexattr(struct dentry *, const char *);
-+
-+extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext3_xattr_list(struct inode *, char *, size_t);
-+extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
-+
-+extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
-+extern void ext3_xattr_put_super(struct super_block *);
-+
-+extern int init_ext3_xattr(void);
-+extern void exit_ext3_xattr(void);
-+
-+# else /* CONFIG_EXT3_FS_XATTR */
-+# define ext3_setxattr NULL
-+# define ext3_getxattr NULL
-+# define ext3_listxattr NULL
-+# define ext3_removexattr NULL
-+
-+static inline int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+ext3_xattr_list(struct inode *inode, void *buffer, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline void
-+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext3_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext3_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT3_FS_XATTR */
-+
-+extern struct ext3_xattr_handler ext3_xattr_user_handler;
-diff -Nru a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/ext3/xattr_user.c Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,99 @@
-+/*
-+ * linux/fs/ext3/xattr_user.c
-+ * Handler for extended user attributes.
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/smp_lock.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include "xattr.h"
-+
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+# include <linux/ext3_acl.h>
-+#endif
-+
-+#define XATTR_USER_PREFIX "user."
-+
-+static size_t
-+ext3_xattr_user_list(char *list, struct inode *inode,
-+ const char *name, int name_len)
-+{
-+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
-+
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return 0;
-+
-+ if (list) {
-+ memcpy(list, XATTR_USER_PREFIX, prefix_len);
-+ memcpy(list+prefix_len, name, name_len);
-+ }
-+ return prefix_len + name_len;
-+}
-+
-+static int
-+ext3_xattr_user_get(struct inode *inode, const char *name,
-+ void *buffer, size_t size)
-+{
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -EOPNOTSUPP;
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+ error = ext3_permission_locked(inode, MAY_READ);
-+#else
-+ error = permission(inode, MAY_READ);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
-+ buffer, size);
-+}
-+
-+static int
-+ext3_xattr_user_set(struct inode *inode, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ handle_t *handle;
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -EOPNOTSUPP;
-+ if ( !S_ISREG(inode->i_mode) &&
-+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-+ return -EPERM;
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+ error = ext3_permission_locked(inode, MAY_WRITE);
-+#else
-+ error = permission(inode, MAY_WRITE);
-+#endif
-+ if (error)
-+ return error;
-+
-+ lock_kernel();
-+ handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+ error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
-+ value, size, flags);
-+ ext3_journal_stop(handle, inode);
-+ unlock_kernel();
-+
-+ return error;
-+}
-+
-+struct ext3_xattr_handler ext3_xattr_user_handler = {
-+ prefix: XATTR_USER_PREFIX,
-+ list: ext3_xattr_user_list,
-+ get: ext3_xattr_user_get,
-+ set: ext3_xattr_user_set,
-+};
-diff -Nru a/fs/mbcache.c b/fs/mbcache.c
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/mbcache.c Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,702 @@
-+/*
-+ * linux/fs/mbcache.c
-+ * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+/*
-+ * Filesystem Meta Information Block Cache (mbcache)
-+ *
-+ * The mbcache caches blocks of block devices that need to be located
-+ * by their device/block number, as well as by other criteria (such
-+ * as the block's contents).
-+ *
-+ * There can only be one cache entry in a cache per device and block number.
-+ * Additional indexes need not be unique in this sense. The number of
-+ * additional indexes (=other criteria) can be hardwired (at compile time)
-+ * or specified at cache create time.
-+ *
-+ * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
-+ * in the cache. A valid entry is in the main hash tables of the cache,
-+ * and may also be in the lru list. An invalid entry is not in any hashes
-+ * or lists.
-+ *
-+ * A valid cache entry is only in the lru list if no handles refer to it.
-+ * Invalid cache entries will be freed when the last handle to the cache
-+ * entry is released.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/hash.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <linux/mbcache.h>
-+
-+
-+#ifdef MB_CACHE_DEBUG
-+# define mb_debug(f...) do { \
-+ printk(KERN_DEBUG f); \
-+ printk("\n"); \
-+ } while (0)
-+#define mb_assert(c) do { if (!(c)) \
-+ printk(KERN_ERR "assertion " #c " failed\n"); \
-+ } while(0)
-+#else
-+# define mb_debug(f...) do { } while(0)
-+# define mb_assert(c) do { } while(0)
-+#endif
-+#define mb_error(f...) do { \
-+ printk(KERN_ERR f); \
-+ printk("\n"); \
-+ } while(0)
-+
-+MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
-+MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
-+MODULE_LICENSE("GPL");
-+
-+EXPORT_SYMBOL(mb_cache_create);
-+EXPORT_SYMBOL(mb_cache_shrink);
-+EXPORT_SYMBOL(mb_cache_destroy);
-+EXPORT_SYMBOL(mb_cache_entry_alloc);
-+EXPORT_SYMBOL(mb_cache_entry_insert);
-+EXPORT_SYMBOL(mb_cache_entry_release);
-+EXPORT_SYMBOL(mb_cache_entry_takeout);
-+EXPORT_SYMBOL(mb_cache_entry_free);
-+EXPORT_SYMBOL(mb_cache_entry_dup);
-+EXPORT_SYMBOL(mb_cache_entry_get);
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+EXPORT_SYMBOL(mb_cache_entry_find_first);
-+EXPORT_SYMBOL(mb_cache_entry_find_next);
-+#endif
-+
-+
-+/*
-+ * Global data: list of all mbcache's, lru list, and a spinlock for
-+ * accessing cache data structures on SMP machines. (The lru list is
-+ * global across all mbcaches.)
-+ */
-+
-+static LIST_HEAD(mb_cache_list);
-+static LIST_HEAD(mb_cache_lru_list);
-+static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
-+static struct shrinker *mb_shrinker;
-+
-+static inline int
-+mb_cache_indexes(struct mb_cache *cache)
-+{
-+#ifdef MB_CACHE_INDEXES_COUNT
-+ return MB_CACHE_INDEXES_COUNT;
-+#else
-+ return cache->c_indexes_count;
-+#endif
-+}
-+
-+/*
-+ * What the mbcache registers as to get shrunk dynamically.
-+ */
-+
-+static int mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask);
-+
-+static inline void
-+__mb_cache_entry_takeout_lru(struct mb_cache_entry *ce)
-+{
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_into_lru(struct mb_cache_entry *ce)
-+{
-+ list_add(&ce->e_lru_list, &mb_cache_lru_list);
-+}
-+
-+
-+static inline int
-+__mb_cache_entry_in_lru(struct mb_cache_entry *ce)
-+{
-+ return (!list_empty(&ce->e_lru_list));
-+}
-+
-+
-+/*
-+ * Insert the cache entry into all hashes.
-+ */
-+static inline void
-+__mb_cache_entry_link(struct mb_cache_entry *ce)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket;
-+ int n;
-+
-+ bucket = hash_long((unsigned long)ce->e_bdev +
-+ (ce->e_block & 0xffffff), cache->c_bucket_bits);
-+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
-+ for (n=0; n<mb_cache_indexes(cache); n++) {
-+ bucket = hash_long(ce->e_indexes[n].o_key,
-+ cache->c_bucket_bits);
-+ list_add(&ce->e_indexes[n].o_list,
-+ &cache->c_indexes_hash[n][bucket]);
-+ }
-+}
-+
-+
-+/*
-+ * Remove the cache entry from all hashes.
-+ */
-+static inline void
-+__mb_cache_entry_unlink(struct mb_cache_entry *ce)
-+{
-+ int n;
-+
-+ list_del_init(&ce->e_block_list);
-+ for (n = 0; n < mb_cache_indexes(ce->e_cache); n++)
-+ list_del(&ce->e_indexes[n].o_list);
-+}
-+
-+
-+static inline int
-+__mb_cache_entry_is_linked(struct mb_cache_entry *ce)
-+{
-+ return (!list_empty(&ce->e_block_list));
-+}
-+
-+
-+static inline struct mb_cache_entry *
-+__mb_cache_entry_read(struct mb_cache_entry *ce)
-+{
-+ __mb_cache_entry_takeout_lru(ce);
-+ atomic_inc(&ce->e_used);
-+ return ce;
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_forget(struct mb_cache_entry *ce)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+
-+ mb_assert(atomic_read(&ce->e_used) == 0);
-+ atomic_dec(&cache->c_entry_count);
-+ if (cache->c_op.free)
-+ cache->c_op.free(ce);
-+ kmem_cache_free(cache->c_entry_cache, ce);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
-+{
-+ if (atomic_dec_and_test(&ce->e_used)) {
-+ if (!__mb_cache_entry_is_linked(ce))
-+ goto forget;
-+ __mb_cache_entry_into_lru(ce);
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ return;
-+forget:
-+ spin_unlock(&mb_cache_spinlock);
-+ __mb_cache_entry_forget(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_shrink_fn() memory pressure callback
-+ *
-+ * This function is called by the kernel memory management when memory
-+ * gets low.
-+ *
-+ * @nr_to_scan: Number of objects to scan
-+ * @gfp_mask: (ignored)
-+ *
-+ * Returns the number of objects which are present in the cache.
-+ */
-+static int
-+mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l;
-+ int count = 0;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_prev(l, &mb_cache_list) {
-+ struct mb_cache *cache =
-+ list_entry(l, struct mb_cache, c_cache_list);
-+ mb_debug("cache %s (%d)", cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ count += atomic_read(&cache->c_entry_count);
-+ }
-+ mb_debug("trying to free %d entries", nr_to_scan);
-+ if (nr_to_scan == 0) {
-+ spin_unlock(&mb_cache_spinlock);
-+ goto out;
-+ }
-+ while (nr_to_scan && !list_empty(&mb_cache_lru_list)) {
-+ struct mb_cache_entry *ce =
-+ list_entry(mb_cache_lru_list.prev,
-+ struct mb_cache_entry, e_lru_list);
-+ list_move(&ce->e_lru_list, &free_list);
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ nr_to_scan--;
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ l = free_list.prev;
-+ while (l != &free_list) {
-+ struct mb_cache_entry *ce = list_entry(l,
-+ struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ __mb_cache_entry_forget(ce);
-+ count--;
-+ }
-+out:
-+ mb_debug("%d remaining entries ", count);
-+ return count;
-+}
-+
-+
-+/*
-+ * mb_cache_create() create a new cache
-+ *
-+ * All entries in one cache are equal size. Cache entries may be from
-+ * multiple devices. If this is the first mbcache created, registers
-+ * the cache with kernel memory management. Returns NULL if no more
-+ * memory was available.
-+ *
-+ * @name: name of the cache (informal)
-+ * @cache_op: contains the callback called when freeing a cache entry
-+ * @entry_size: The size of a cache entry, including
-+ * struct mb_cache_entry
-+ * @indexes_count: number of additional indexes in the cache. Must equal
-+ * MB_CACHE_INDEXES_COUNT if the number of indexes is
-+ * hardwired.
-+ * @bucket_bits: log2(number of hash buckets)
-+ */
-+struct mb_cache *
-+mb_cache_create(const char *name, struct mb_cache_op *cache_op,
-+ size_t entry_size, int indexes_count, int bucket_bits)
-+{
-+ int m=0, n, bucket_count = 1 << bucket_bits;
-+ struct mb_cache *cache = NULL;
-+
-+ if(entry_size < sizeof(struct mb_cache_entry) +
-+ indexes_count * sizeof(struct mb_cache_entry_index))
-+ return NULL;
-+
-+ cache = kmalloc(sizeof(struct mb_cache) +
-+ indexes_count * sizeof(struct list_head), GFP_KERNEL);
-+ if (!cache)
-+ goto fail;
-+ cache->c_name = name;
-+ if (cache_op)
-+ cache->c_op.free = cache_op->free;
-+ else
-+ cache->c_op.free = NULL;
-+ atomic_set(&cache->c_entry_count, 0);
-+ cache->c_bucket_bits = bucket_bits;
-+#ifdef MB_CACHE_INDEXES_COUNT
-+ mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
-+#else
-+ cache->c_indexes_count = indexes_count;
-+#endif
-+ cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
-+ GFP_KERNEL);
-+ if (!cache->c_block_hash)
-+ goto fail;
-+ for (n=0; n<bucket_count; n++)
-+ INIT_LIST_HEAD(&cache->c_block_hash[n]);
-+ for (m=0; m<indexes_count; m++) {
-+ cache->c_indexes_hash[m] = kmalloc(bucket_count *
-+ sizeof(struct list_head),
-+ GFP_KERNEL);
-+ if (!cache->c_indexes_hash[m])
-+ goto fail;
-+ for (n=0; n<bucket_count; n++)
-+ INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
-+ }
-+ cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
-+ 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
-+ if (!cache->c_entry_cache)
-+ goto fail;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ if (list_empty(&mb_cache_list)) {
-+ if (mb_shrinker) {
-+ printk(KERN_ERR "%s: already have a shrinker!\n",
-+ __FUNCTION__);
-+ remove_shrinker(mb_shrinker);
-+ }
-+ mb_shrinker = set_shrinker(DEFAULT_SEEKS, mb_cache_shrink_fn);
-+ }
-+ list_add(&cache->c_cache_list, &mb_cache_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ return cache;
-+
-+fail:
-+ if (cache) {
-+ while (--m >= 0)
-+ kfree(cache->c_indexes_hash[m]);
-+ if (cache->c_block_hash)
-+ kfree(cache->c_block_hash);
-+ kfree(cache);
-+ }
-+ return NULL;
-+}
-+
-+
-+/*
-+ * mb_cache_shrink()
-+ *
-+ * Removes all cache entires of a device from the cache. All cache entries
-+ * currently in use cannot be freed, and thus remain in the cache. All others
-+ * are freed.
-+ *
-+ * @cache: which cache to shrink
-+ * @bdev: which device's cache entries to shrink
-+ */
-+void
-+mb_cache_shrink(struct mb_cache *cache, struct block_device *bdev)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ l = mb_cache_lru_list.prev;
-+ while (l != &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ if (ce->e_bdev == bdev) {
-+ list_move(&ce->e_lru_list, &free_list);
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ l = free_list.prev;
-+ while (l != &free_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ __mb_cache_entry_forget(ce);
-+ }
-+}
-+
-+
-+/*
-+ * mb_cache_destroy()
-+ *
-+ * Shrinks the cache to its minimum possible size (hopefully 0 entries),
-+ * and then destroys it. If this was the last mbcache, un-registers the
-+ * mbcache from kernel memory management.
-+ */
-+void
-+mb_cache_destroy(struct mb_cache *cache)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l;
-+ int n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ l = mb_cache_lru_list.prev;
-+ while (l != &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ if (ce->e_cache == cache) {
-+ list_move(&ce->e_lru_list, &free_list);
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ }
-+ }
-+ list_del(&cache->c_cache_list);
-+ if (list_empty(&mb_cache_list) && mb_shrinker) {
-+ remove_shrinker(mb_shrinker);
-+ mb_shrinker = 0;
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+
-+ l = free_list.prev;
-+ while (l != &free_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ __mb_cache_entry_forget(ce);
-+ }
-+
-+ if (atomic_read(&cache->c_entry_count) > 0) {
-+ mb_error("cache %s: %d orphaned entries",
-+ cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ }
-+
-+ kmem_cache_destroy(cache->c_entry_cache);
-+
-+ for (n=0; n < mb_cache_indexes(cache); n++)
-+ kfree(cache->c_indexes_hash[n]);
-+ kfree(cache->c_block_hash);
-+
-+ kfree(cache);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_alloc()
-+ *
-+ * Allocates a new cache entry. The new entry will not be valid initially,
-+ * and thus cannot be looked up yet. It should be filled with data, and
-+ * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
-+ * if no more memory was available.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_alloc(struct mb_cache *cache)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ atomic_inc(&cache->c_entry_count);
-+ ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
-+ if (ce) {
-+ INIT_LIST_HEAD(&ce->e_lru_list);
-+ INIT_LIST_HEAD(&ce->e_block_list);
-+ ce->e_cache = cache;
-+ atomic_set(&ce->e_used, 1);
-+ }
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_insert()
-+ *
-+ * Inserts an entry that was allocated using mb_cache_entry_alloc() into
-+ * the cache. After this, the cache entry can be looked up, but is not yet
-+ * in the lru list as the caller still holds a handle to it. Returns 0 on
-+ * success, or -EBUSY if a cache entry for that device + inode exists
-+ * already (this may happen after a failed lookup, but when another process
-+ * has inserted the same cache entry in the meantime).
-+ *
-+ * @bdev: device the cache entry belongs to
-+ * @block: block number
-+ * @keys: array of additional keys. There must be indexes_count entries
-+ * in the array (as specified when creating the cache).
-+ */
-+int
-+mb_cache_entry_insert(struct mb_cache_entry *ce, struct block_device *bdev,
-+ sector_t block, unsigned int keys[])
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket;
-+ struct list_head *l;
-+ int error = -EBUSY, n;
-+
-+ bucket = hash_long((unsigned long)bdev + (block & 0xffffffff),
-+ cache->c_bucket_bits);
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_prev(l, &cache->c_block_hash[bucket]) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_bdev == bdev && ce->e_block == block)
-+ goto out;
-+ }
-+ mb_assert(!__mb_cache_entry_is_linked(ce));
-+ ce->e_bdev = bdev;
-+ ce->e_block = block;
-+ for (n=0; n<mb_cache_indexes(cache); n++)
-+ ce->e_indexes[n].o_key = keys[n];
-+ __mb_cache_entry_link(ce);
-+out:
-+ spin_unlock(&mb_cache_spinlock);
-+ return error;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_release()
-+ *
-+ * Release a handle to a cache entry. When the last handle to a cache entry
-+ * is released it is either freed (if it is invalid) or otherwise inserted
-+ * in to the lru list.
-+ */
-+void
-+mb_cache_entry_release(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ __mb_cache_entry_release_unlock(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_takeout()
-+ *
-+ * Take a cache entry out of the cache, making it invalid. The entry can later
-+ * be re-inserted using mb_cache_entry_insert(), or released using
-+ * mb_cache_entry_release().
-+ */
-+void
-+mb_cache_entry_takeout(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ mb_assert(!__mb_cache_entry_in_lru(ce));
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ spin_unlock(&mb_cache_spinlock);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_free()
-+ *
-+ * This is equivalent to the sequence mb_cache_entry_takeout() --
-+ * mb_cache_entry_release().
-+ */
-+void
-+mb_cache_entry_free(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ mb_assert(!__mb_cache_entry_in_lru(ce));
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ __mb_cache_entry_release_unlock(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_dup()
-+ *
-+ * Duplicate a handle to a cache entry (does not duplicate the cache entry
-+ * itself). After the call, both the old and the new handle must be released.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_dup(struct mb_cache_entry *ce)
-+{
-+ atomic_inc(&ce->e_used);
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_get()
-+ *
-+ * Get a cache entry by device / block number. (There can only be one entry
-+ * in the cache per device and block.) Returns NULL if no such cache entry
-+ * exists.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_get(struct mb_cache *cache, struct block_device *bdev,
-+ sector_t block)
-+{
-+ unsigned int bucket;
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ bucket = hash_long((unsigned long)bdev + (block & 0xffffffff),
-+ cache->c_bucket_bits);
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(l, &cache->c_block_hash[bucket]) {
-+ ce = list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_bdev == bdev && ce->e_block == block) {
-+ ce = __mb_cache_entry_read(ce);
-+ goto cleanup;
-+ }
-+ }
-+ ce = NULL;
-+
-+cleanup:
-+ spin_unlock(&mb_cache_spinlock);
-+ return ce;
-+}
-+
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+
-+static struct mb_cache_entry *
-+__mb_cache_entry_find(struct list_head *l, struct list_head *head,
-+ int index, struct block_device *bdev, unsigned int key)
-+{
-+ while (l != head) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry,
-+ e_indexes[index].o_list);
-+ if (ce->e_bdev == bdev &&
-+ ce->e_indexes[index].o_key == key) {
-+ ce = __mb_cache_entry_read(ce);
-+ if (ce)
-+ return ce;
-+ }
-+ l = l->next;
-+ }
-+ return NULL;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_find_first()
-+ *
-+ * Find the first cache entry on a given device with a certain key in
-+ * an additional index. Additonal matches can be found with
-+ * mb_cache_entry_find_next(). Returns NULL if no match was found.
-+ *
-+ * @cache: the cache to search
-+ * @index: the number of the additonal index to search (0<=index<indexes_count)
-+ * @bdev: the device the cache entry should belong to
-+ * @key: the key in the index
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_find_first(struct mb_cache *cache, int index,
-+ struct block_device *bdev, unsigned int key)
-+{
-+ unsigned int bucket = hash_long(key, cache->c_bucket_bits);
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ mb_assert(index < mb_cache_indexes(cache));
-+ spin_lock(&mb_cache_spinlock);
-+ l = cache->c_indexes_hash[index][bucket].next;
-+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
-+ index, bdev, key);
-+ spin_unlock(&mb_cache_spinlock);
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_find_next()
-+ *
-+ * Find the next cache entry on a given device with a certain key in an
-+ * additional index. Returns NULL if no match could be found. The previous
-+ * entry is atomatically released, so that mb_cache_entry_find_next() can
-+ * be called like this:
-+ *
-+ * entry = mb_cache_entry_find_first();
-+ * while (entry) {
-+ * ...
-+ * entry = mb_cache_entry_find_next(entry, ...);
-+ * }
-+ *
-+ * @prev: The previous match
-+ * @index: the number of the additonal index to search (0<=index<indexes_count)
-+ * @bdev: the device the cache entry should belong to
-+ * @key: the key in the index
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_find_next(struct mb_cache_entry *prev, int index,
-+ struct block_device *bdev, unsigned int key)
-+{
-+ struct mb_cache *cache = prev->e_cache;
-+ unsigned int bucket = hash_long(key, cache->c_bucket_bits);
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ mb_assert(index < mb_cache_indexes(cache));
-+ spin_lock(&mb_cache_spinlock);
-+ l = prev->e_indexes[index].o_list.next;
-+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
-+ index, bdev, key);
-+ __mb_cache_entry_release_unlock(prev);
-+ return ce;
-+}
-+
-+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
-diff -Nru a/fs/namei.c b/fs/namei.c
---- a/fs/namei.c Thu Dec 12 20:58:37 2002
-+++ b/fs/namei.c Thu Dec 12 20:58:37 2002
-@@ -265,6 +265,9 @@
-
- void path_release(struct nameidata *nd)
- {
-+ if (&nd->it && nd->dentry && nd->dentry->d_op &&
-+ nd->dentry->d_op->d_intent_release)
-+ nd->dentry->d_op->d_intent_release(nd->dentry, &nd->it);
- dput(nd->dentry);
- mntput(nd->mnt);
- }
-@@ -273,10 +276,18 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -351,7 +362,7 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -369,7 +380,10 @@
- struct dentry * dentry = d_alloc(parent, name);
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
-- result = dir->i_op->lookup(dir, dentry);
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
-+ result = dir->i_op->lookup(dir, dentry);
- if (result)
- dput(dentry);
- else {
-@@ -391,6 +405,12 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -402,7 +422,8 @@
- * Without that kind of total limit, nasty chains of consecutive
- * symlinks can cause almost arbitrarily long lookups.
- */
--static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
-+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- int err = -ELOOP;
- if (current->link_count >= 5)
-@@ -419,7 +440,10 @@
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-@@ -534,7 +558,7 @@
- unlock_nd(nd);
-
- need_lookup:
-- dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE, &nd->it);
- if (IS_ERR(dentry))
- goto fail;
- mntget(mnt);
-@@ -662,11 +686,11 @@
- if (!inode->i_op)
- break;
-
-- if (inode->i_op->follow_link) {
-+ if (inode->i_op->follow_link || inode->i_op->follow_link2) {
- mntget(next.mnt);
- dget_locked(next.dentry);
- unlock_nd(nd);
-- err = do_follow_link(next.dentry, nd);
-+ err = do_follow_link(next.dentry, nd, &nd->it);
- dput(next.dentry);
- mntput(next.mnt);
- if (err)
-@@ -684,7 +708,7 @@
- nd->dentry = next.dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -717,11 +741,12 @@
- follow_mount(&next.mnt, &next.dentry);
- inode = next.dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
-- && inode && inode->i_op && inode->i_op->follow_link) {
-+ && inode && inode->i_op &&
-+ (inode->i_op->follow_link || inode->i_op->follow_link2)) {
- mntget(next.mnt);
- dget_locked(next.dentry);
- unlock_nd(nd);
-- err = do_follow_link(next.dentry, nd);
-+ err = do_follow_link(next.dentry, nd, &nd->it);
- dput(next.dentry);
- mntput(next.mnt);
- if (err)
-@@ -737,7 +762,8 @@
- break;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op ||
-+ (!inode->i_op->lookup && !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -886,7 +912,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -909,13 +936,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
-- dentry = inode->i_op->lookup(inode, new);
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
-+ dentry = inode->i_op->lookup(inode, new);
- if (!dentry) {
- dentry = new;
- security_ops->inode_post_lookup(inode, dentry);
-@@ -927,7 +957,7 @@
- }
-
- /* SMP-safe */
--struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, int len, struct lookup_intent *it)
- {
- unsigned long hash;
- struct qstr this;
-@@ -947,11 +977,16 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash(&this, base, it);
- access:
- return ERR_PTR(-EACCES);
- }
-
-+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+{
-+ return lookup_one_len_it(name, base, len, NULL);
-+}
-+
- /*
- * namei()
- *
-@@ -1268,7 +1303,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1310,7 +1345,8 @@
- error = -ENOENT;
- if (!dentry->d_inode)
- goto exit_dput;
-- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
-+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
-+ dentry->d_inode->i_op->follow_link2))
- goto do_link;
-
- dput(nd->dentry);
-@@ -1370,7 +1406,7 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
- putname(nd->last.name);
- goto do_last;
- }
-@@ -1384,7 +1420,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1614,7 +1650,7 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd.it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1675,7 +1711,7 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd.it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1949,7 +1985,8 @@
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
-@@ -2020,7 +2057,7 @@
-
- trap = lock_rename(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash(&oldnd.last, old_dir, &oldnd.it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -2040,7 +2077,7 @@
- error = -EINVAL;
- if (old_dentry == trap)
- goto exit4;
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ new_dentry = lookup_hash(&newnd.last, new_dir, &newnd.it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-@@ -2050,7 +2087,7 @@
- goto exit5;
-
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, NULL);
- exit5:
- dput(new_dentry);
- exit4:
-@@ -2102,7 +2139,8 @@
- }
-
- static inline int
--__vfs_follow_link(struct nameidata *nd, const char *link)
-+__vfs_follow_link(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
- {
- int res = 0;
- char *name;
-@@ -2138,7 +2176,13 @@
-
- int vfs_follow_link(struct nameidata *nd, const char *link)
- {
-- return __vfs_follow_link(nd, link);
-+ return __vfs_follow_link(nd, link, NULL);
-+}
-+
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
-+{
-+ return __vfs_follow_link(nd, link, it);
- }
-
- /* get the link contents into pagecache */
-@@ -2180,7 +2224,7 @@
- {
- struct page *page = NULL;
- char *s = page_getlink(dentry, &page);
-- int res = __vfs_follow_link(nd, s);
-+ int res = __vfs_follow_link(nd, s, NULL);
- if (page) {
- kunmap(page);
- page_cache_release(page);
-diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
---- a/fs/nfsd/vfs.c Thu Dec 12 20:58:37 2002
-+++ b/fs/nfsd/vfs.c Thu Dec 12 20:58:37 2002
-@@ -1292,7 +1292,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
-diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
---- a/fs/sysfs/inode.c Thu Dec 12 20:58:37 2002
-+++ b/fs/sysfs/inode.c Thu Dec 12 20:58:37 2002
-@@ -471,7 +471,7 @@
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-- return lookup_hash(&qstr,parent);
-+ return lookup_hash(&qstr,parent,NULL);
- }
-
- /**
-diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
---- a/include/linux/dcache.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/dcache.h Thu Dec 12 20:58:37 2002
-@@ -9,6 +9,24 @@
- #include <linux/spinlock.h>
- #include <asm/page.h> /* for BUG() */
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
-+
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -30,6 +48,8 @@
- unsigned int hash;
- };
-
-+#include <linux/namei.h>
-+
- struct dentry_stat_t {
- int nr_dentry;
- int nr_unused;
-@@ -79,6 +99,7 @@
- struct list_head d_subdirs; /* our children */
- struct list_head d_alias; /* inode alias list */
- int d_mounted;
-+ struct lookup_intent *d_it;
- struct qstr d_name;
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
-@@ -96,6 +117,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
-diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
---- a/include/linux/ext3_fs.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/ext3_fs.h Thu Dec 12 20:58:37 2002
-@@ -64,8 +64,6 @@
- */
- #define EXT3_BAD_INO 1 /* Bad blocks inode */
- #define EXT3_ROOT_INO 2 /* Root inode */
--#define EXT3_ACL_IDX_INO 3 /* ACL inode */
--#define EXT3_ACL_DATA_INO 4 /* ACL inode */
- #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
- #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
-@@ -95,7 +93,6 @@
- #else
- # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
- #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -130,28 +127,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext3_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext3_acl_entry /* Access Control List Entry */
--{
-- __u32 acle_size;
-- __u16 acle_perms; /* Access permissions */
-- __u16 acle_type; /* Type of entry */
-- __u16 acle_tag; /* User or group identity */
-- __u16 acle_pad1;
-- __u32 acle_next; /* Pointer on next entry for the */
-- /* same inode or on next free entry */
--};
--
--/*
- * Structure of a blocks group descriptor
- */
- struct ext3_group_desc
-@@ -347,6 +322,7 @@
- #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
- #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
-+#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -529,7 +505,7 @@
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-
--#define EXT3_FEATURE_COMPAT_SUPP 0
-+#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
-@@ -713,6 +689,7 @@
-
-
- /* inode.c */
-+extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
- extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
- extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-
-@@ -781,8 +758,10 @@
-
- /* namei.c */
- extern struct inode_operations ext3_dir_inode_operations;
-+extern struct inode_operations ext3_special_inode_operations;
-
- /* symlink.c */
-+extern struct inode_operations ext3_symlink_inode_operations;
- extern struct inode_operations ext3_fast_symlink_inode_operations;
-
-
-diff -Nru a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
---- a/include/linux/ext3_jbd.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/ext3_jbd.h Thu Dec 12 20:58:37 2002
-@@ -30,13 +30,19 @@
-
- #define EXT3_SINGLEDATA_TRANS_BLOCKS 8
-
-+/* Extended attributes may touch two data buffers, two bitmap buffers,
-+ * and two group and summaries. */
-+
-+#define EXT3_XATTR_TRANS_BLOCKS 8
-+
- /* Define the minimum size for a transaction which modifies data. This
- * needs to take into account the fact that we may end up modifying two
- * quota files too (one for the group, one for the user quota). The
- * superblock only gets updated once, of course, so don't bother
- * counting that again for the quota updates. */
-
--#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
-+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
-+ EXT3_XATTR_TRANS_BLOCKS - 2)
-
- extern int ext3_writepage_trans_blocks(struct inode *inode);
-
-diff -Nru a/include/linux/fs.h b/include/linux/fs.h
---- a/include/linux/fs.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/fs.h Thu Dec 12 20:58:37 2002
-@@ -700,7 +700,7 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct lookup_intent *it);
-
- /*
- * File types
-@@ -769,6 +769,8 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *,
-+ struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -779,6 +781,7 @@
- struct inode *, struct dentry *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *, struct lookup_intent *it);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*setattr) (struct dentry *, struct iattr *);
-@@ -995,6 +998,7 @@
- extern int unregister_filesystem(struct file_system_type *);
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-
- #define kern_umount mntput
-@@ -1285,6 +1289,8 @@
-
- extern int vfs_readlink(struct dentry *, char *, int, const char *);
- extern int vfs_follow_link(struct nameidata *, const char *);
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it);
- extern int page_readlink(struct dentry *, char *, int);
- extern int page_follow_link(struct dentry *, struct nameidata *);
- extern int page_symlink(struct inode *inode, const char *symname, int len);
-diff -Nru a/include/linux/lustre_version.h b/include/linux/lustre_version.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/include/linux/lustre_version.h Thu Dec 12 20:58:37 2002
-@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 4
-diff -Nru a/include/linux/mbcache.h b/include/linux/mbcache.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/include/linux/mbcache.h Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,72 @@
-+/*
-+ File: linux/mbcache.h
-+
-+ (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+/* Hardwire the number of additional indexes */
-+#define MB_CACHE_INDEXES_COUNT 1
-+
-+struct mb_cache_entry;
-+
-+struct mb_cache_op {
-+ void (*free)(struct mb_cache_entry *);
-+};
-+
-+struct mb_cache {
-+ struct list_head c_cache_list;
-+ const char *c_name;
-+ struct mb_cache_op c_op;
-+ atomic_t c_entry_count;
-+ int c_bucket_bits;
-+#ifndef MB_CACHE_INDEXES_COUNT
-+ int c_indexes_count;
-+#endif
-+ kmem_cache_t *c_entry_cache;
-+ struct list_head *c_block_hash;
-+ struct list_head *c_indexes_hash[0];
-+};
-+
-+struct mb_cache_entry_index {
-+ struct list_head o_list;
-+ unsigned int o_key;
-+};
-+
-+struct mb_cache_entry {
-+ struct list_head e_lru_list;
-+ struct mb_cache *e_cache;
-+ atomic_t e_used;
-+ struct block_device *e_bdev;
-+ sector_t e_block;
-+ struct list_head e_block_list;
-+ struct mb_cache_entry_index e_indexes[0];
-+};
-+
-+/* Functions on caches */
-+
-+struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
-+ int, int);
-+void mb_cache_shrink(struct mb_cache *, struct block_device *);
-+void mb_cache_destroy(struct mb_cache *);
-+
-+/* Functions on cache entries */
-+
-+struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
-+int mb_cache_entry_insert(struct mb_cache_entry *, struct block_device *,
-+ sector_t, unsigned int[]);
-+void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
-+void mb_cache_entry_release(struct mb_cache_entry *);
-+void mb_cache_entry_takeout(struct mb_cache_entry *);
-+void mb_cache_entry_free(struct mb_cache_entry *);
-+struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
-+struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *,
-+ struct block_device *,
-+ sector_t);
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
-+ struct block_device *,
-+ unsigned int);
-+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
-+ struct block_device *,
-+ unsigned int);
-+#endif
-diff -Nru a/include/linux/namei.h b/include/linux/namei.h
---- a/include/linux/namei.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/namei.h Thu Dec 12 20:58:37 2002
-@@ -5,6 +5,17 @@
-
- struct vfsmount;
-
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- struct nameidata {
- struct dentry *dentry;
- struct vfsmount *mnt;
-@@ -13,6 +24,7 @@
- int last_type;
- struct dentry *old_dentry;
- struct vfsmount *old_mnt;
-+ struct lookup_intent it;
- };
-
- /*
-@@ -46,7 +58,7 @@
- extern void path_release(struct nameidata *);
-
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
--extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
-+extern struct dentry * lookup_hash(struct qstr *, struct dentry *, struct lookup_intent *);
-
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
-diff -Nru a/include/linux/slab.h b/include/linux/slab.h
---- a/include/linux/slab.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/slab.h Thu Dec 12 20:58:37 2002
-@@ -56,6 +56,7 @@
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
- extern unsigned int kmem_cache_size(kmem_cache_t *);
-
- extern void *kmalloc(size_t, int);
-diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
---- a/kernel/ksyms.c Thu Dec 12 20:58:37 2002
-+++ b/kernel/ksyms.c Thu Dec 12 20:58:37 2002
-@@ -286,6 +286,7 @@
- EXPORT_SYMBOL(mark_page_accessed);
- EXPORT_SYMBOL(vfs_readlink);
- EXPORT_SYMBOL(vfs_follow_link);
-+EXPORT_SYMBOL(vfs_follow_link_it);
- EXPORT_SYMBOL(page_readlink);
- EXPORT_SYMBOL(page_follow_link);
- EXPORT_SYMBOL(page_symlink_inode_operations);
-@@ -365,6 +366,13 @@
- EXPORT_SYMBOL(tty_get_baud_rate);
- EXPORT_SYMBOL(do_SAK);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+//EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(exit_files);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
- /* filesystem registration */
- EXPORT_SYMBOL(register_filesystem);
- EXPORT_SYMBOL(unregister_filesystem);
-@@ -529,6 +537,7 @@
- EXPORT_SYMBOL(seq_lseek);
- EXPORT_SYMBOL(single_open);
- EXPORT_SYMBOL(single_release);
-+EXPORT_SYMBOL(reparent_to_init);
-
- /* Program loader interfaces */
- EXPORT_SYMBOL(setup_arg_pages);
-diff -Nru a/mm/slab.c b/mm/slab.c
---- a/mm/slab.c Thu Dec 12 20:58:37 2002
-+++ b/mm/slab.c Thu Dec 12 20:58:37 2002
-@@ -1236,6 +1236,59 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!page_mem_map(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
-diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
---- a/net/unix/af_unix.c Thu Dec 12 20:58:37 2002
-+++ b/net/unix/af_unix.c Thu Dec 12 20:58:37 2002
-@@ -715,7 +715,7 @@
- /*
- * Do the final lookup.
- */
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- goto out_mknod_unlock;
+++ /dev/null
-# This is a BitKeeper generated patch for the following project:
-# Project Name: Linux kernel tree
-# This patch format is intended for GNU patch command version 2.5 or higher.
-# This patch includes the following deltas:
-# ChangeSet 1.811 -> 1.812
-# kernel/ksyms.c 1.150 -> 1.151
-# include/linux/fs.h 1.176 -> 1.177
-# fs/namei.c 1.57 -> 1.58
-# fs/ext3/xattr.c 1.1 -> 1.2
-# (new) -> 1.1 include/linux/lustre_version.h
-#
-# The following is the BitKeeper ChangeSet Log
-# --------------------------------------------
-# 02/12/11 root@kai.(none) 1.812
-# changed for lustre
-# --------------------------------------------
-#
-diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
---- a/fs/ext3/xattr.c Thu Dec 12 20:58:52 2002
-+++ b/fs/ext3/xattr.c Thu Dec 12 20:58:52 2002
-@@ -58,6 +58,7 @@
- #include <linux/ext3_jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/mbcache.h>
-+#include <linux/module.h>
- #include <linux/quotaops.h>
- #include <asm/semaphore.h>
- #include "xattr.h"
-@@ -1096,6 +1097,9 @@
- }
-
- #undef BLOCK_HASH_SHIFT
-+EXPORT_SYMBOL(ext3_xattr_get);
-+EXPORT_SYMBOL(ext3_xattr_set);
-+EXPORT_SYMBOL(ext3_bread);
-
- int __init
- init_ext3_xattr(void)
-diff -Nru a/fs/namei.c b/fs/namei.c
---- a/fs/namei.c Thu Dec 12 20:58:52 2002
-+++ b/fs/namei.c Thu Dec 12 20:58:52 2002
-@@ -265,7 +265,7 @@
-
- void path_release(struct nameidata *nd)
- {
-- if (nd->dentry && nd->dentry->d_op &&
-+ if (&nd->it && nd->dentry && nd->dentry->d_op &&
- nd->dentry->d_op->d_intent_release)
- nd->dentry->d_op->d_intent_release(nd->dentry, &nd->it);
- dput(nd->dentry);
-@@ -422,7 +422,8 @@
- * Without that kind of total limit, nasty chains of consecutive
- * symlinks can cause almost arbitrarily long lookups.
- */
--static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
-+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- int err = -ELOOP;
- if (current->link_count >= 5)
-@@ -439,7 +440,10 @@
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-@@ -682,11 +686,11 @@
- if (!inode->i_op)
- break;
-
-- if (inode->i_op->follow_link) {
-+ if (inode->i_op->follow_link || inode->i_op->follow_link2) {
- mntget(next.mnt);
- dget_locked(next.dentry);
- unlock_nd(nd);
-- err = do_follow_link(next.dentry, nd);
-+ err = do_follow_link(next.dentry, nd, &nd->it);
- dput(next.dentry);
- mntput(next.mnt);
- if (err)
-@@ -737,11 +741,12 @@
- follow_mount(&next.mnt, &next.dentry);
- inode = next.dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
-- && inode && inode->i_op && inode->i_op->follow_link) {
-+ && inode && inode->i_op &&
-+ (inode->i_op->follow_link || inode->i_op->follow_link2)) {
- mntget(next.mnt);
- dget_locked(next.dentry);
- unlock_nd(nd);
-- err = do_follow_link(next.dentry, nd);
-+ err = do_follow_link(next.dentry, nd, &nd->it);
- dput(next.dentry);
- mntput(next.mnt);
- if (err)
-@@ -1340,7 +1345,8 @@
- error = -ENOENT;
- if (!dentry->d_inode)
- goto exit_dput;
-- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
-+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
-+ dentry->d_inode->i_op->follow_link2))
- goto do_link;
-
- dput(nd->dentry);
-@@ -2133,7 +2139,8 @@
- }
-
- static inline int
--__vfs_follow_link(struct nameidata *nd, const char *link)
-+__vfs_follow_link(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
- {
- int res = 0;
- char *name;
-@@ -2169,7 +2176,13 @@
-
- int vfs_follow_link(struct nameidata *nd, const char *link)
- {
-- return __vfs_follow_link(nd, link);
-+ return __vfs_follow_link(nd, link, NULL);
-+}
-+
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
-+{
-+ return __vfs_follow_link(nd, link, it);
- }
-
- /* get the link contents into pagecache */
-@@ -2211,7 +2224,7 @@
- {
- struct page *page = NULL;
- char *s = page_getlink(dentry, &page);
-- int res = __vfs_follow_link(nd, s);
-+ int res = __vfs_follow_link(nd, s, NULL);
- if (page) {
- kunmap(page);
- page_cache_release(page);
-diff -Nru a/include/linux/fs.h b/include/linux/fs.h
---- a/include/linux/fs.h Thu Dec 12 20:58:52 2002
-+++ b/include/linux/fs.h Thu Dec 12 20:58:52 2002
-@@ -781,6 +781,7 @@
- struct inode *, struct dentry *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *, struct lookup_intent *it);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*setattr) (struct dentry *, struct iattr *);
-@@ -1288,6 +1289,8 @@
-
- extern int vfs_readlink(struct dentry *, char *, int, const char *);
- extern int vfs_follow_link(struct nameidata *, const char *);
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it);
- extern int page_readlink(struct dentry *, char *, int);
- extern int page_follow_link(struct dentry *, struct nameidata *);
- extern int page_symlink(struct inode *inode, const char *symname, int len);
-diff -Nru a/include/linux/lustre_version.h b/include/linux/lustre_version.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/include/linux/lustre_version.h Thu Dec 12 20:58:52 2002
-@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 4
-diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
---- a/kernel/ksyms.c Thu Dec 12 20:58:52 2002
-+++ b/kernel/ksyms.c Thu Dec 12 20:58:52 2002
-@@ -286,6 +286,7 @@
- EXPORT_SYMBOL(mark_page_accessed);
- EXPORT_SYMBOL(vfs_readlink);
- EXPORT_SYMBOL(vfs_follow_link);
-+EXPORT_SYMBOL(vfs_follow_link_it);
- EXPORT_SYMBOL(page_readlink);
- EXPORT_SYMBOL(page_follow_link);
- EXPORT_SYMBOL(page_symlink_inode_operations);
-@@ -536,6 +537,7 @@
- EXPORT_SYMBOL(seq_lseek);
- EXPORT_SYMBOL(single_open);
- EXPORT_SYMBOL(single_release);
-+EXPORT_SYMBOL(reparent_to_init);
-
- /* Program loader interfaces */
- EXPORT_SYMBOL(setup_arg_pages);
+++ /dev/null
-# This is a BitKeeper generated patch for the following project:
-# Project Name: Linux kernel tree
-# This patch format is intended for GNU patch command version 2.5 or higher.
-# This patch includes the following deltas:
-# ChangeSet 1.809 -> 1.812
-# kernel/ksyms.c 1.149 -> 1.151
-# fs/ext3/Makefile 1.4 -> 1.5
-# include/linux/ext3_jbd.h 1.5 -> 1.6
-# fs/driverfs/inode.c 1.52 -> 1.53
-# include/linux/fs.h 1.175 -> 1.177
-# include/linux/namei.h 1.3 -> 1.4
-# fs/namei.c 1.56 -> 1.58
-# fs/nfsd/vfs.c 1.44 -> 1.45
-# arch/um/kernel/mem.c 1.5 -> 1.6
-# fs/ext3/ialloc.c 1.17 -> 1.18
-# fs/ext3/symlink.c 1.3 -> 1.4
-# fs/Makefile 1.42 -> 1.43
-# fs/ext3/namei.c 1.22 -> 1.23
-# include/linux/ext3_fs.h 1.11 -> 1.12
-# net/unix/af_unix.c 1.29 -> 1.30
-# fs/Config.in 1.39 -> 1.40
-# fs/ext3/inode.c 1.42 -> 1.43
-# fs/Config.help 1.21 -> 1.22
-# mm/slab.c 1.33 -> 1.34
-# fs/sysfs/inode.c 1.55 -> 1.56
-# fs/ext3/super.c 1.33 -> 1.34
-# fs/ext3/file.c 1.9 -> 1.10
-# include/linux/slab.h 1.13 -> 1.14
-# include/linux/dcache.h 1.19 -> 1.20
-# (new) -> 1.1 fs/ext3/xattr.h
-# (new) -> 1.1 include/linux/mbcache.h
-# (new) -> 1.1 include/linux/lustre_version.h
-# (new) -> 1.2 fs/ext3/xattr.c
-# (new) -> 1.1 fs/mbcache.c
-# (new) -> 1.1 fs/ext3/xattr_user.c
-#
-# The following is the BitKeeper ChangeSet Log
-# --------------------------------------------
-# 02/10/20 braam@clusterfs.com 1.810
-# xattrs for UML bk repository
-# --------------------------------------------
-# 02/10/20 braam@clusterfs.com 1.811
-# Changes for Lustre
-# --------------------------------------------
-# 02/12/11 root@kai.(none) 1.812
-# changed for lustre
-# --------------------------------------------
-#
-diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
---- a/arch/um/kernel/mem.c Thu Dec 12 20:58:37 2002
-+++ b/arch/um/kernel/mem.c Thu Dec 12 20:58:37 2002
-@@ -656,6 +656,22 @@
- return(phys_mem_map(pte_val(pte)));
- }
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+ struct page *page;
-+ struct mem_region *mr;
-+ unsigned long phys = __pa(kaddr);
-+ unsigned int n = phys_region_index(phys);
-+
-+ if(regions[n] == NULL)
-+ return NULL;
-+
-+ mr = regions[n];
-+ page = (struct page *) mr->mem_map;
-+ return page + ((phys_addr(phys)) >> PAGE_SHIFT);
-+}
-+
-+
- struct mem_region *page_region(struct page *page, int *index_out)
- {
- int i;
-@@ -743,7 +759,7 @@
- (addr <= region->start + region->len))
- return(mk_phys(addr - region->start, i));
- }
-- panic("region_pa : no region for virtual address");
-+ //panic("region_pa : no region for virtual address");
- return(0);
- }
-
-diff -Nru a/fs/Config.help b/fs/Config.help
---- a/fs/Config.help Thu Dec 12 20:58:37 2002
-+++ b/fs/Config.help Thu Dec 12 20:58:37 2002
-@@ -154,6 +154,13 @@
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this may be dangerous.
-
-+CONFIG_EXT3_FS_XATTR
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
- CONFIG_JBD
- This is a generic journaling layer for block devices. It is
- currently used by the ext3 file system, but it could also be used to
-diff -Nru a/fs/Config.in b/fs/Config.in
---- a/fs/Config.in Thu Dec 12 20:58:37 2002
-+++ b/fs/Config.in Thu Dec 12 20:58:37 2002
-@@ -27,6 +27,7 @@
- dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
-
- tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
-+dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
- # CONFIG_JBD could be its own option (even modular), but until there are
- # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
- # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
-@@ -180,6 +181,17 @@
- define_tristate CONFIG_ZISOFS_FS $CONFIG_ISO9660_FS
- else
- define_tristate CONFIG_ZISOFS_FS n
-+fi
-+
-+# Meta block cache for Extended Attributes (ext2/ext3)
-+if [ "$CONFIG_EXT2_FS_XATTR" = "y" -o "$CONFIG_EXT3_FS_XATTR" = "y" ]; then
-+ if [ "$CONFIG_EXT2_FS" = "y" -o "$CONFIG_EXT3_FS" = "y" ]; then
-+ define_tristate CONFIG_FS_MBCACHE y
-+ else
-+ if [ "$CONFIG_EXT2_FS" = "m" -o "$CONFIG_EXT3_FS" = "m" ]; then
-+ define_tristate CONFIG_FS_MBCACHE m
-+ fi
-+ fi
- fi
-
- mainmenu_option next_comment
-diff -Nru a/fs/Makefile b/fs/Makefile
---- a/fs/Makefile Thu Dec 12 20:58:37 2002
-+++ b/fs/Makefile Thu Dec 12 20:58:37 2002
-@@ -6,7 +6,7 @@
- #
-
- export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o \
-- fcntl.o read_write.o dcookies.o
-+ fcntl.o read_write.o dcookies.o mbcache.o
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
- bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \
-@@ -29,6 +29,8 @@
- obj-y += binfmt_script.o
-
- obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
-+
-+obj-$(CONFIG_FS_MBCACHE) += mbcache.o
-
- obj-$(CONFIG_QUOTA) += dquot.o
- obj-$(CONFIG_QFMT_V1) += quota_v1.o
-diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c
---- a/fs/driverfs/inode.c Thu Dec 12 20:58:37 2002
-+++ b/fs/driverfs/inode.c Thu Dec 12 20:58:37 2002
-@@ -523,7 +523,7 @@
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-- return lookup_hash(&qstr,parent);
-+ return lookup_hash(&qstr,parent, NULL);
- }
-
- /**
-diff -Nru a/fs/ext3/Makefile b/fs/ext3/Makefile
---- a/fs/ext3/Makefile Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/Makefile Thu Dec 12 20:58:37 2002
-@@ -7,4 +7,10 @@
- ext3-objs := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o hash.o
-
-+export-objs += xattr.o
-+
-+ifeq ($(CONFIG_EXT3_FS_XATTR),y)
-+ext3-objs += xattr.o xattr_user.o
-+endif
-+
- include $(TOPDIR)/Rules.make
-diff -Nru a/fs/ext3/file.c b/fs/ext3/file.c
---- a/fs/ext3/file.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/file.c Thu Dec 12 20:58:37 2002
-@@ -23,7 +23,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
--#include <linux/smp_lock.h>
-+#include "xattr.h"
-
- /*
- * Called when an inode is released. Note that this is different
-@@ -98,5 +98,9 @@
- struct inode_operations ext3_file_inode_operations = {
- .truncate = ext3_truncate,
- .setattr = ext3_setattr,
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
- };
-
-diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
---- a/fs/ext3/ialloc.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/ialloc.c Thu Dec 12 20:58:37 2002
-@@ -25,6 +25,8 @@
- #include <asm/bitops.h>
- #include <asm/byteorder.h>
-
-+#include "xattr.h"
-+
- /*
- * ialloc.c contains the inodes allocation and deallocation routines
- */
-@@ -118,6 +120,7 @@
- * as writing the quota to disk may need the lock as well.
- */
- DQUOT_INIT(inode);
-+ ext3_xattr_delete_inode(handle, inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
-
-diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
---- a/fs/ext3/inode.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/inode.c Thu Dec 12 20:58:37 2002
-@@ -42,6 +42,18 @@
- */
- #undef SEARCH_FROM_ZERO
-
-+/*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext3_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = EXT3_I(inode)->i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
- /* The ext3 forget function must perform a revoke if we are freeing data
- * which has been journaled. Metadata (eg. indirect blocks) must be
- * revoked in all cases.
-@@ -51,7 +63,7 @@
- * still needs to be revoked.
- */
-
--static int ext3_forget(handle_t *handle, int is_metadata,
-+int ext3_forget(handle_t *handle, int is_metadata,
- struct inode *inode, struct buffer_head *bh,
- int blocknr)
- {
-@@ -167,9 +179,7 @@
- {
- handle_t *handle;
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
-
- lock_kernel();
-@@ -1979,6 +1989,8 @@
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext3_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -2130,8 +2142,6 @@
- struct ext3_group_desc * gdp;
-
- if ((inode->i_ino != EXT3_ROOT_INO &&
-- inode->i_ino != EXT3_ACL_IDX_INO &&
-- inode->i_ino != EXT3_ACL_DATA_INO &&
- inode->i_ino != EXT3_JOURNAL_INO &&
- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(
-@@ -2263,10 +2273,7 @@
-
- brelse (iloc.bh);
-
-- if (inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
- if (ext3_should_writeback_data(inode))
-@@ -2277,18 +2284,20 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext3_inode_is_fast_symlink(inode))
- inode->i_op = &ext3_fast_symlink_inode_operations;
- else {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext3_symlink_inode_operations;
- if (ext3_should_writeback_data(inode))
- inode->i_mapping->a_ops = &ext3_writeback_aops;
- else
- inode->i_mapping->a_ops = &ext3_aops;
- }
-- } else
-+ } else {
-+ inode->i_op = &ext3_special_inode_operations;
- init_special_inode(inode, inode->i_mode,
- le32_to_cpu(iloc.raw_inode->i_block[0]));
-+ }
- if (ei->i_flags & EXT3_SYNC_FL)
- inode->i_flags |= S_SYNC;
- if (ei->i_flags & EXT3_APPEND_FL)
-diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c
---- a/fs/ext3/namei.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/namei.c Thu Dec 12 20:58:37 2002
-@@ -36,6 +36,7 @@
- #include <linux/quotaops.h>
- #include <linux/buffer_head.h>
- #include <linux/smp_lock.h>
-+#include "xattr.h"
-
-
- /*
-@@ -1654,7 +1655,7 @@
- if (IS_DIRSYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFDIR);
-+ inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
-@@ -1662,7 +1663,6 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-- inode->i_blocks = 0;
- dir_block = ext3_bread (handle, inode, 0, 1, &err);
- if (!dir_block) {
- inode->i_nlink--; /* is this nlink == 0? */
-@@ -1689,9 +1689,6 @@
- BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, dir_block);
- brelse (dir_block);
-- inode->i_mode = S_IFDIR | mode;
-- if (dir->i_mode & S_ISGID)
-- inode->i_mode |= S_ISGID;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_entry (handle, dentry, inode);
- if (err) {
-@@ -2068,7 +2065,7 @@
- goto out_stop;
-
- if (l > sizeof (EXT3_I(inode)->i_data)) {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext3_symlink_inode_operations;
- if (ext3_should_writeback_data(inode))
- inode->i_mapping->a_ops = &ext3_writeback_aops;
- else
-@@ -2284,4 +2281,17 @@
- .rmdir = ext3_rmdir,
- .mknod = ext3_mknod,
- .rename = ext3_rename,
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
- };
-+
-+struct inode_operations ext3_special_inode_operations = {
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
-+};
-+
-+
-diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
---- a/fs/ext3/super.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/super.c Thu Dec 12 20:58:37 2002
-@@ -30,6 +30,7 @@
- #include <linux/smp_lock.h>
- #include <linux/buffer_head.h>
- #include <asm/uaccess.h>
-+#include "xattr.h"
-
- #ifdef CONFIG_JBD_DEBUG
- static int ext3_ro_after; /* Make fs read-only after this many jiffies */
-@@ -405,6 +406,7 @@
- struct ext3_super_block *es = sbi->s_es;
- int i;
-
-+ ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
- EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-@@ -554,6 +556,7 @@
- int is_remount)
- {
- unsigned long *mount_options = &sbi->s_mount_opt;
-+
- uid_t *resuid = &sbi->s_resuid;
- gid_t *resgid = &sbi->s_resgid;
- char * this_char;
-@@ -566,6 +569,13 @@
- continue;
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT3_FS_XATTR
-+ if (!strcmp (this_char, "user_xattr"))
-+ set_opt (*mount_options, XATTR_USER);
-+ else if (!strcmp (this_char, "nouser_xattr"))
-+ clear_opt (*mount_options, XATTR_USER);
-+ else
-+#endif
- if (!strcmp (this_char, "bsddf"))
- clear_opt (*mount_options, MINIX_DF);
- else if (!strcmp (this_char, "nouid32")) {
-@@ -982,6 +992,12 @@
- sbi->s_mount_opt = 0;
- sbi->s_resuid = EXT3_DEF_RESUID;
- sbi->s_resgid = EXT3_DEF_RESGID;
-+
-+ /* Default extended attribute flags */
-+#ifdef CONFIG_EXT3_FS_XATTR
-+ set_opt(sbi->s_mount_opt, XATTR_USER);
-+#endif
-+
- if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0))
- goto out_fail;
-
-@@ -1820,7 +1836,10 @@
-
- static int __init init_ext3_fs(void)
- {
-- int err = init_inodecache();
-+ int err = init_ext3_xattr();
-+ if (err)
-+ return err;
-+ err = init_inodecache();
- if (err)
- goto out1;
- err = register_filesystem(&ext3_fs_type);
-@@ -1830,6 +1849,7 @@
- out:
- destroy_inodecache();
- out1:
-+ exit_ext3_xattr();
- return err;
- }
-
-@@ -1837,6 +1857,7 @@
- {
- unregister_filesystem(&ext3_fs_type);
- destroy_inodecache();
-+ exit_ext3_xattr();
- }
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
-diff -Nru a/fs/ext3/symlink.c b/fs/ext3/symlink.c
---- a/fs/ext3/symlink.c Thu Dec 12 20:58:37 2002
-+++ b/fs/ext3/symlink.c Thu Dec 12 20:58:37 2002
-@@ -20,6 +20,7 @@
- #include <linux/fs.h>
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
-+#include "xattr.h"
-
- static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-@@ -33,7 +34,20 @@
- return vfs_follow_link(nd, (char*)ei->i_data);
- }
-
-+struct inode_operations ext3_symlink_inode_operations = {
-+ .readlink = page_readlink,
-+ .follow_link = page_follow_link,
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
-+};
-+
- struct inode_operations ext3_fast_symlink_inode_operations = {
-- .readlink = ext3_readlink, /* BKL not held. Don't need */
-+ .readlink = ext3_readlink, /* BKL not held. Don't need */
- .follow_link = ext3_follow_link, /* BKL not held. Don't need */
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
- };
-diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/ext3/xattr.c Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,1131 @@
-+/*
-+ * linux/fs/ext3/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
-+ * Extended attributes for symlinks and special files added per
-+ * suggestion of Luka Renko <luka.renko@hermes.si>.
-+ */
-+
-+/*
-+ * Extended attributes are stored on disk blocks allocated outside of
-+ * any inode. The i_file_acl field is then made to point to this allocated
-+ * block. If all extended attributes of an inode are identical, these
-+ * inodes may share the same extended attribute block. Such situations
-+ * are automatically detected by keeping a cache of recent attribute block
-+ * numbers and hashes over the block's contents in memory.
-+ *
-+ *
-+ * Extended attribute block layout:
-+ *
-+ * +------------------+
-+ * | header |
-+ * ¦ entry 1 | |
-+ * | entry 2 | | growing downwards
-+ * | entry 3 | v
-+ * | four null bytes |
-+ * | . . . |
-+ * | value 1 | ^
-+ * | value 3 | | growing upwards
-+ * | value 2 | |
-+ * +------------------+
-+ *
-+ * The block header is followed by multiple entry descriptors. These entry
-+ * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
-+ * byte boundaries. The entry descriptors are sorted by attribute name,
-+ * so that two extended attribute blocks can be compared efficiently.
-+ *
-+ * Attribute values are aligned to the end of the block, stored in
-+ * no specific order. They are also padded to EXT3_XATTR_PAD byte
-+ * boundaries. No additional gaps are left between them.
-+ *
-+ * Locking strategy
-+ * ----------------
-+ * The VFS holdsinode->i_sem semaphore when any of the xattr inode
-+ * operations are called, so we are guaranteed that only one
-+ * processes accesses extended attributes of an inode at any time.
-+ *
-+ * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
-+ * only a single process is modifying an extended attribute block, even
-+ * if the block is shared among inodes.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/mbcache.h>
-+#include <linux/module.h>
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include "xattr.h"
-+
-+#define EXT3_EA_USER "user."
-+
-+#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT3_XATTR_DEBUG
-+# define ea_idebug(inode, f...) do { \
-+ printk(KERN_DEBUG "inode %s:%ld: ", \
-+ kdevname(inode->i_dev), inode->i_ino); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+# define ea_bdebug(bh, f...) do { \
-+ printk(KERN_DEBUG "block %s:%ld: ", \
-+ kdevname(bh->b_dev), bh->b_blocknr); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+#else
-+# define ea_idebug(f...)
-+# define ea_bdebug(f...)
-+#endif
-+
-+static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
-+ struct ext3_xattr_header *);
-+
-+static int ext3_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext3_xattr_cache_find(struct inode *,
-+ struct ext3_xattr_header *);
-+static void ext3_xattr_cache_remove(struct buffer_head *);
-+static void ext3_xattr_rehash(struct ext3_xattr_header *,
-+ struct ext3_xattr_entry *);
-+
-+static struct mb_cache *ext3_xattr_cache;
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext3_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+static DECLARE_MUTEX(ext3_xattr_sem);
-+static struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
-+static rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ if (!ext3_xattr_handlers[name_index-1]) {
-+ ext3_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext3_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ ext3_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext3_handler_lock);
-+ }
-+}
-+
-+static inline const char *
-+strcmp_prefix(const char *a, const char *a_prefix)
-+{
-+ while (*a_prefix && *a == *a_prefix) {
-+ a++;
-+ a_prefix++;
-+ }
-+ return *a_prefix ? NULL : a;
-+}
-+
-+/*
-+ * Decode the extended attribute name, and translate it into
-+ * the name_index and name suffix.
-+ */
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_resolve_name(const char **name)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext3_handler_lock);
-+ for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
-+ if (ext3_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext3_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext3_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext3_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_handler(int name_index)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ read_lock(&ext3_handler_lock);
-+ handler = ext3_xattr_handlers[name_index-1];
-+ read_unlock(&ext3_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+ssize_t
-+ext3_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -EOPNOTSUPP;
-+ return handler->get(inode, name, buffer, size);
-+}
-+
-+/*
-+ * Inode operation listxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+ssize_t
-+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext3_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+int
-+ext3_setxattr(struct dentry *dentry, const char *name,
-+ void *value, size_t size, int flags)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -EOPNOTSUPP;
-+ return handler->set(inode, name, value, size, flags);
-+}
-+
-+/*
-+ * Inode operation removexattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+int
-+ext3_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -EOPNOTSUPP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext3_xattr_get()
-+ *
-+ * Copy an extended attribute into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size;
-+ char *end;
-+ int name_len, error;
-+
-+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
-+ name_index, name, buffer, (long)buffer_size);
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return -ENODATA;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* find named attribute */
-+ name_len = strlen(name);
-+
-+ error = -ERANGE;
-+ if (name_len > 255)
-+ goto cleanup;
-+ entry = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0)
-+ goto found;
-+ entry = next;
-+ }
-+ /* Check the remaining name entries */
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ error = -ENODATA;
-+ goto cleanup;
-+found:
-+ /* check the buffer size */
-+ if (entry->e_value_block != 0)
-+ goto bad_block;
-+ size = le32_to_cpu(entry->e_value_size);
-+ if (size > inode->i_sb->s_blocksize ||
-+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
-+ goto bad_block;
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (buffer) {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ /* return value of attribute */
-+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
-+ size);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size = 0;
-+ char *buf, *end;
-+ int error;
-+
-+ ea_idebug(inode, "buffer=%p, buffer_size=%ld",
-+ buffer, (long)buffer_size);
-+
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* compute the size required for the list of attribute names */
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len) + 1;
-+ }
-+ }
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (!buffer) {
-+ error = size;
-+ goto cleanup;
-+ } else {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ }
-+
-+ /* list the attribute names */
-+ buf = buffer;
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ *buf++ = '\0';
-+ }
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext3_xattr_update_super_block(handle_t *handle,
-+ struct super_block *sb)
-+{
-+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+ ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-+ EXT3_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext3_xattr_set()
-+ *
-+ * Create, replace or remove an extended attribute for this inode. Buffer
-+ * is NULL to remove an existing extended attribute, and non-NULL to
-+ * either replace an existing extended attribute, or create a new extended
-+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
-+ * specify that an extended attribute must exist and must not exist
-+ * previous to the call, respectively.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t value_len, int flags)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_header *header = NULL;
-+ struct ext3_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int min_offs = sb->s_blocksize, not_found = 1, free, error;
-+ char *end;
-+
-+ /*
-+ * header -- Points either into bh, or to a temporarily
-+ * allocated buffer.
-+ * here -- The named entry found, or the place for inserting, within
-+ * the block pointed to by header.
-+ * last -- Points right after the last named entry within the block
-+ * pointed to by header.
-+ * min_offs -- The offset of the first value (values are aligned
-+ * towards the end of the block).
-+ * end -- Points right after the block pointed to by header.
-+ */
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+ return -EPERM;
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > sb->s_blocksize)
-+ return -ERANGE;
-+ down(&ext3_xattr_sem);
-+
-+ if (EXT3_I(inode)->i_file_acl) {
-+ /* The inode already has an extended attribute block. */
-+ int block = EXT3_I(inode)->i_file_acl;
-+
-+ bh = sb_bread(sb, block);
-+ error = -EIO;
-+ if (!bh)
-+ goto cleanup;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)),
-+ le32_to_cpu(HDR(bh)->h_refcount));
-+ header = HDR(bh);
-+ end = bh->b_data + bh->b_size;
-+ if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(sb, "ext3_xattr_set",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* Find the named attribute. */
-+ here = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(here)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!here->e_value_block && here->e_value_size) {
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ not_found = name_index - here->e_name_index;
-+ if (!not_found)
-+ not_found = name_len - here->e_name_len;
-+ if (!not_found)
-+ not_found = memcmp(name, here->e_name,name_len);
-+ if (not_found <= 0)
-+ break;
-+ here = next;
-+ }
-+ last = here;
-+ /* We still need to compute min_offs and last. */
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!last->e_value_block && last->e_value_size) {
-+ int offs = le16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ last = next;
-+ }
-+
-+ /* Check whether we have enough space left. */
-+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
-+ } else {
-+ /* We will use a new extended attribute block. */
-+ free = sb->s_blocksize -
-+ sizeof(struct ext3_xattr_header) - sizeof(__u32);
-+ here = last = NULL; /* avoid gcc uninitialized warning. */
-+ }
-+
-+ if (not_found) {
-+ /* Request to remove a nonexistent attribute? */
-+ error = -ENODATA;
-+ if (flags & XATTR_REPLACE)
-+ goto cleanup;
-+ error = 0;
-+ if (value == NULL)
-+ goto cleanup;
-+ else
-+ free -= EXT3_XATTR_LEN(name_len);
-+ } else {
-+ /* Request to create an existing attribute? */
-+ error = -EEXIST;
-+ if (flags & XATTR_CREATE)
-+ goto cleanup;
-+ if (!here->e_value_block && here->e_value_size) {
-+ unsigned int size = le32_to_cpu(here->e_value_size);
-+
-+ if (le16_to_cpu(here->e_value_offs) + size >
-+ sb->s_blocksize || size > sb->s_blocksize)
-+ goto bad_block;
-+ free += EXT3_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT3_XATTR_SIZE(value_len);
-+ error = -ENOSPC;
-+ if (free < 0)
-+ goto cleanup;
-+
-+ /* Here we know that we can set the new attribute. */
-+
-+ if (header) {
-+ if (header->h_refcount == cpu_to_le32(1)) {
-+ ea_bdebug(bh, "modifying in-place");
-+ ext3_xattr_cache_remove(bh);
-+ error = ext3_journal_get_write_access(handle, bh);
-+ if (error)
-+ goto cleanup;
-+ } else {
-+ int offset;
-+
-+ ea_bdebug(bh, "cloning");
-+ header = kmalloc(bh->b_size, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memcpy(header, HDR(bh), bh->b_size);
-+ header->h_refcount = cpu_to_le32(1);
-+ offset = (char *)header - bh->b_data;
-+ here = ENTRY((char *)here + offset);
-+ last = ENTRY((char *)last + offset);
-+ }
-+ } else {
-+ /* Allocate a buffer where we construct the new block. */
-+ header = kmalloc(sb->s_blocksize, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memset(header, 0, sb->s_blocksize);
-+ end = (char *)header + sb->s_blocksize;
-+ header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
-+ header->h_blocks = header->h_refcount = cpu_to_le32(1);
-+ last = here = ENTRY(header+1);
-+ }
-+
-+ if (not_found) {
-+ /* Insert the new name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ int rest = (char *)last - (char *)here;
-+ memmove((char *)here + size, here, rest);
-+ memset(here, 0, size);
-+ here->e_name_index = name_index;
-+ here->e_name_len = name_len;
-+ memcpy(here->e_name, name, name_len);
-+ } else {
-+ /* Remove the old value. */
-+ if (!here->e_value_block && here->e_value_size) {
-+ char *first_val = (char *)header + min_offs;
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ char *val = (char *)header + offs;
-+ size_t size = EXT3_XATTR_SIZE(
-+ le32_to_cpu(here->e_value_size));
-+ memmove(first_val + size, first_val, val - first_val);
-+ memset(first_val, 0, size);
-+ here->e_value_offs = 0;
-+ min_offs += size;
-+
-+ /* Adjust all value offsets. */
-+ last = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(last)) {
-+ int o = le16_to_cpu(last->e_value_offs);
-+ if (!last->e_value_block && o < offs)
-+ last->e_value_offs =
-+ cpu_to_le16(o + size);
-+ last = EXT3_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext3_xattr_set2(handle, inode, bh,NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ last = ENTRY((char *)last - size);
-+ memmove(here, (char*)here + size,
-+ (char*)last - (char*)here);
-+ memset(last, 0, size);
-+ }
-+ }
-+ }
-+
-+ if (value != NULL) {
-+ /* Insert the new value. */
-+ here->e_value_size = cpu_to_le32(value_len);
-+ if (value_len) {
-+ size_t size = EXT3_XATTR_SIZE(value_len);
-+ char *val = (char *)header + min_offs - size;
-+ here->e_value_offs =
-+ cpu_to_le16((char *)val - (char *)header);
-+ memset(val + size - EXT3_XATTR_PAD, 0,
-+ EXT3_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext3_xattr_rehash(header, here);
-+
-+ error = ext3_xattr_set2(handle, inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ up(&ext3_xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext3_xattr_set(): Update the file system.
-+ */
-+static int
-+ext3_xattr_set2(handle_t *handle, struct inode *inode,
-+ struct buffer_head *old_bh, struct ext3_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext3_xattr_cache_find(inode, header);
-+ if (new_bh) {
-+ /*
-+ * We found an identical block in the cache.
-+ * The old block will be released after updating
-+ * the inode.
-+ */
-+ ea_bdebug(old_bh, "reusing block %ld",
-+ new_bh->b_blocknr);
-+
-+ error = -EDQUOT;
-+ if (DQUOT_ALLOC_BLOCK(inode, 1))
-+ goto cleanup;
-+
-+ error = ext3_journal_get_write_access(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ HDR(new_bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
-+ ea_bdebug(new_bh, "refcount now=%d",
-+ le32_to_cpu(HDR(new_bh)->h_refcount));
-+ } else if (old_bh && header == HDR(old_bh)) {
-+ /* Keep this block. */
-+ new_bh = old_bh;
-+ ext3_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int block;
-+ int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-+ EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
-+
-+ block = ext3_new_block(handle, inode, goal, 0,
-+ 0, &error);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+getblk_failed:
-+ ext3_free_blocks(handle, inode, block, 1);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ error = ext3_journal_get_create_access(handle, new_bh);
-+ if (error) {
-+ unlock_buffer(new_bh);
-+ goto getblk_failed;
-+ }
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ set_buffer_uptodate(new_bh);
-+ unlock_buffer(new_bh);
-+ ext3_xattr_cache_insert(new_bh);
-+
-+ ext3_xattr_update_super_block(handle, sb);
-+ }
-+ error = ext3_journal_dirty_metadata(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ }
-+
-+ /* Update the inode. */
-+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ ext3_mark_inode_dirty(handle, inode);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+
-+ error = 0;
-+ if (old_bh && old_bh != new_bh) {
-+ /*
-+ * If there was an old block, and we are not still using it,
-+ * we now release the old block.
-+ */
-+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-+
-+ error = ext3_journal_get_write_access(handle, old_bh);
-+ if (error)
-+ goto cleanup;
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext3_free_blocks(handle, inode, old_bh->b_blocknr, 1);
-+
-+ /* ext3_forget() calls bforget() for us, but we
-+ let our caller release old_bh, so we need to
-+ duplicate the handle before. */
-+ get_bh(old_bh);
-+ ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ DQUOT_FREE_BLOCK(inode, 1);
-+ ext3_journal_dirty_metadata(handle, old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT3_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ down(&ext3_xattr_sem);
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
-+ "inode %ld: block %d read error", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ext3_journal_get_write_access(handle, bh);
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext3_xattr_cache_remove(bh);
-+ ext3_free_blocks(handle, inode, block, 1);
-+ ext3_forget(handle, 1, inode, bh, block);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ ext3_journal_dirty_metadata(handle, bh);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+ DQUOT_FREE_BLOCK(inode, 1);
-+ }
-+ EXT3_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ up(&ext3_xattr_sem);
-+}
-+
-+/*
-+ * ext3_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+ mb_cache_shrink(ext3_xattr_cache, sb->s_bdev);
-+}
-+
-+/*
-+ * ext3_xattr_cache_insert()
-+ *
-+ * Create a new entry in the extended attribute cache, and insert
-+ * it unless such an entry is already in the cache.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+static int
-+ext3_xattr_cache_insert(struct buffer_head *bh)
-+{
-+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
-+ struct mb_cache_entry *ce;
-+ int error;
-+
-+ ce = mb_cache_entry_alloc(ext3_xattr_cache);
-+ if (!ce)
-+ return -ENOMEM;
-+ error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, &hash);
-+ if (error) {
-+ mb_cache_entry_free(ce);
-+ if (error == -EBUSY) {
-+ ea_bdebug(bh, "already in cache (%d cache entries)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_cmp()
-+ *
-+ * Compare two extended attribute blocks for equality.
-+ *
-+ * Returns 0 if the blocks are equal, 1 if they differ, and
-+ * a negative error number on errors.
-+ */
-+static int
-+ext3_xattr_cmp(struct ext3_xattr_header *header1,
-+ struct ext3_xattr_header *header2)
-+{
-+ struct ext3_xattr_entry *entry1, *entry2;
-+
-+ entry1 = ENTRY(header1+1);
-+ entry2 = ENTRY(header2+1);
-+ while (!IS_LAST_ENTRY(entry1)) {
-+ if (IS_LAST_ENTRY(entry2))
-+ return 1;
-+ if (entry1->e_hash != entry2->e_hash ||
-+ entry1->e_name_len != entry2->e_name_len ||
-+ entry1->e_value_size != entry2->e_value_size ||
-+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
-+ return 1;
-+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
-+ return -EIO;
-+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
-+ (char *)header2 + le16_to_cpu(entry2->e_value_offs),
-+ le32_to_cpu(entry1->e_value_size)))
-+ return 1;
-+
-+ entry1 = EXT3_XATTR_NEXT(entry1);
-+ entry2 = EXT3_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext3_xattr_cache_find()
-+ *
-+ * Find an identical extended attribute block.
-+ *
-+ * Returns a pointer to the block found, or NULL if such a block was
-+ * not found or an error occurred.
-+ */
-+static struct buffer_head *
-+ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
-+{
-+ __u32 hash = le32_to_cpu(header->h_hash);
-+ struct mb_cache_entry *ce;
-+
-+ if (!header->h_hash)
-+ return NULL; /* never share */
-+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_bdev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, (unsigned long) ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT3_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",
-+ (unsigned long) ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT3_XATTR_REFCOUNT_MAX);
-+ } else if (!ext3_xattr_cmp(header, HDR(bh))) {
-+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
-+ mb_cache_entry_release(ce);
-+ return bh;
-+ }
-+ brelse(bh);
-+ ce = mb_cache_entry_find_next(ce, 0, inode->i_bdev, hash);
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * ext3_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext3_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_bdev,
-+ bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count)-1);
-+ mb_cache_entry_free(ce);
-+ } else
-+ ea_bdebug(bh, "no cache entry");
-+}
-+
-+#define NAME_HASH_SHIFT 5
-+#define VALUE_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ __u32 hash = 0;
-+ char *name = entry->e_name;
-+ int n;
-+
-+ for (n=0; n < entry->e_name_len; n++) {
-+ hash = (hash << NAME_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-+ *name++;
-+ }
-+
-+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-+ __u32 *value = (__u32 *)((char *)header +
-+ le16_to_cpu(entry->e_value_offs));
-+ for (n = (le32_to_cpu(entry->e_value_size) +
-+ EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
-+ hash = (hash << VALUE_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
-+ le32_to_cpu(*value++);
-+ }
-+ }
-+ entry->e_hash = cpu_to_le32(hash);
-+}
-+
-+#undef NAME_HASH_SHIFT
-+#undef VALUE_HASH_SHIFT
-+
-+#define BLOCK_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext3_xattr_rehash(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ struct ext3_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext3_xattr_hash_entry(header, entry);
-+ here = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(here)) {
-+ if (!here->e_hash) {
-+ /* Block is not shared if an entry's hash value == 0 */
-+ hash = 0;
-+ break;
-+ }
-+ hash = (hash << BLOCK_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
-+ le32_to_cpu(here->e_hash);
-+ here = EXT3_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+EXPORT_SYMBOL(ext3_xattr_get);
-+EXPORT_SYMBOL(ext3_xattr_set);
-+EXPORT_SYMBOL(ext3_bread);
-+
-+int __init
-+init_ext3_xattr(void)
-+{
-+ int err;
-+
-+ err = ext3_xattr_register(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
-+ if (err)
-+ return err;
-+ ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 6);
-+ if (!ext3_xattr_cache) {
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext3_xattr(void)
-+{
-+ if (ext3_xattr_cache)
-+ mb_cache_destroy(ext3_xattr_cache);
-+ ext3_xattr_cache = NULL;
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
-+}
-+
-diff -Nru a/fs/ext3/xattr.h b/fs/ext3/xattr.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/ext3/xattr.h Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,133 @@
-+/*
-+ File: fs/ext3/xattr.h
-+
-+ On-disk format of extended attributes for the ext3 filesystem.
-+
-+ (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+#include <linux/config.h>
-+#include <linux/xattr.h>
-+
-+/* Magic value in attribute blocks */
-+#define EXT3_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT3_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT3_XATTR_INDEX_MAX 10
-+#define EXT3_XATTR_INDEX_USER 1
-+#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
-+#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+
-+struct ext3_xattr_header {
-+ __u32 h_magic; /* magic number for identification */
-+ __u32 h_refcount; /* reference count */
-+ __u32 h_blocks; /* number of disk blocks used */
-+ __u32 h_hash; /* hash value of all attributes */
-+ __u32 h_reserved[4]; /* zero right now */
-+};
-+
-+struct ext3_xattr_entry {
-+ __u8 e_name_len; /* length of name */
-+ __u8 e_name_index; /* attribute name index */
-+ __u16 e_value_offs; /* offset in disk block of value */
-+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */
-+ __u32 e_value_size; /* size of attribute value */
-+ __u32 e_hash; /* hash value of name and value */
-+ char e_name[0]; /* attribute name */
-+};
-+
-+#define EXT3_XATTR_PAD_BITS 2
-+#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
-+#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
-+#define EXT3_XATTR_LEN(name_len) \
-+ (((name_len) + EXT3_XATTR_ROUND + \
-+ sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
-+#define EXT3_XATTR_NEXT(entry) \
-+ ( (struct ext3_xattr_entry *)( \
-+ (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT3_XATTR_SIZE(size) \
-+ (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
-+
-+# ifdef CONFIG_EXT3_FS_XATTR
-+
-+struct ext3_xattr_handler {
-+ char *prefix;
-+ size_t (*list)(char *list, struct inode *inode, const char *name,
-+ int name_len);
-+ int (*get)(struct inode *inode, const char *name, void *buffer,
-+ size_t size);
-+ int (*set)(struct inode *inode, const char *name, const void *buffer,
-+ size_t size, int flags);
-+};
-+
-+extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
-+extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
-+
-+extern int ext3_setxattr(struct dentry *, const char *, void *, size_t, int);
-+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
-+extern int ext3_removexattr(struct dentry *, const char *);
-+
-+extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext3_xattr_list(struct inode *, char *, size_t);
-+extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
-+
-+extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
-+extern void ext3_xattr_put_super(struct super_block *);
-+
-+extern int init_ext3_xattr(void);
-+extern void exit_ext3_xattr(void);
-+
-+# else /* CONFIG_EXT3_FS_XATTR */
-+# define ext3_setxattr NULL
-+# define ext3_getxattr NULL
-+# define ext3_listxattr NULL
-+# define ext3_removexattr NULL
-+
-+static inline int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+ext3_xattr_list(struct inode *inode, void *buffer, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline void
-+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext3_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext3_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT3_FS_XATTR */
-+
-+extern struct ext3_xattr_handler ext3_xattr_user_handler;
-diff -Nru a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/ext3/xattr_user.c Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,99 @@
-+/*
-+ * linux/fs/ext3/xattr_user.c
-+ * Handler for extended user attributes.
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/smp_lock.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include "xattr.h"
-+
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+# include <linux/ext3_acl.h>
-+#endif
-+
-+#define XATTR_USER_PREFIX "user."
-+
-+static size_t
-+ext3_xattr_user_list(char *list, struct inode *inode,
-+ const char *name, int name_len)
-+{
-+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
-+
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return 0;
-+
-+ if (list) {
-+ memcpy(list, XATTR_USER_PREFIX, prefix_len);
-+ memcpy(list+prefix_len, name, name_len);
-+ }
-+ return prefix_len + name_len;
-+}
-+
-+static int
-+ext3_xattr_user_get(struct inode *inode, const char *name,
-+ void *buffer, size_t size)
-+{
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -EOPNOTSUPP;
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+ error = ext3_permission_locked(inode, MAY_READ);
-+#else
-+ error = permission(inode, MAY_READ);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
-+ buffer, size);
-+}
-+
-+static int
-+ext3_xattr_user_set(struct inode *inode, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ handle_t *handle;
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -EOPNOTSUPP;
-+ if ( !S_ISREG(inode->i_mode) &&
-+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-+ return -EPERM;
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+ error = ext3_permission_locked(inode, MAY_WRITE);
-+#else
-+ error = permission(inode, MAY_WRITE);
-+#endif
-+ if (error)
-+ return error;
-+
-+ lock_kernel();
-+ handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+ error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
-+ value, size, flags);
-+ ext3_journal_stop(handle, inode);
-+ unlock_kernel();
-+
-+ return error;
-+}
-+
-+struct ext3_xattr_handler ext3_xattr_user_handler = {
-+ prefix: XATTR_USER_PREFIX,
-+ list: ext3_xattr_user_list,
-+ get: ext3_xattr_user_get,
-+ set: ext3_xattr_user_set,
-+};
-diff -Nru a/fs/mbcache.c b/fs/mbcache.c
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/mbcache.c Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,702 @@
-+/*
-+ * linux/fs/mbcache.c
-+ * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+/*
-+ * Filesystem Meta Information Block Cache (mbcache)
-+ *
-+ * The mbcache caches blocks of block devices that need to be located
-+ * by their device/block number, as well as by other criteria (such
-+ * as the block's contents).
-+ *
-+ * There can only be one cache entry in a cache per device and block number.
-+ * Additional indexes need not be unique in this sense. The number of
-+ * additional indexes (=other criteria) can be hardwired (at compile time)
-+ * or specified at cache create time.
-+ *
-+ * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
-+ * in the cache. A valid entry is in the main hash tables of the cache,
-+ * and may also be in the lru list. An invalid entry is not in any hashes
-+ * or lists.
-+ *
-+ * A valid cache entry is only in the lru list if no handles refer to it.
-+ * Invalid cache entries will be freed when the last handle to the cache
-+ * entry is released.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/hash.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <linux/mbcache.h>
-+
-+
-+#ifdef MB_CACHE_DEBUG
-+# define mb_debug(f...) do { \
-+ printk(KERN_DEBUG f); \
-+ printk("\n"); \
-+ } while (0)
-+#define mb_assert(c) do { if (!(c)) \
-+ printk(KERN_ERR "assertion " #c " failed\n"); \
-+ } while(0)
-+#else
-+# define mb_debug(f...) do { } while(0)
-+# define mb_assert(c) do { } while(0)
-+#endif
-+#define mb_error(f...) do { \
-+ printk(KERN_ERR f); \
-+ printk("\n"); \
-+ } while(0)
-+
-+MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
-+MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
-+MODULE_LICENSE("GPL");
-+
-+EXPORT_SYMBOL(mb_cache_create);
-+EXPORT_SYMBOL(mb_cache_shrink);
-+EXPORT_SYMBOL(mb_cache_destroy);
-+EXPORT_SYMBOL(mb_cache_entry_alloc);
-+EXPORT_SYMBOL(mb_cache_entry_insert);
-+EXPORT_SYMBOL(mb_cache_entry_release);
-+EXPORT_SYMBOL(mb_cache_entry_takeout);
-+EXPORT_SYMBOL(mb_cache_entry_free);
-+EXPORT_SYMBOL(mb_cache_entry_dup);
-+EXPORT_SYMBOL(mb_cache_entry_get);
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+EXPORT_SYMBOL(mb_cache_entry_find_first);
-+EXPORT_SYMBOL(mb_cache_entry_find_next);
-+#endif
-+
-+
-+/*
-+ * Global data: list of all mbcache's, lru list, and a spinlock for
-+ * accessing cache data structures on SMP machines. (The lru list is
-+ * global across all mbcaches.)
-+ */
-+
-+static LIST_HEAD(mb_cache_list);
-+static LIST_HEAD(mb_cache_lru_list);
-+static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
-+static struct shrinker *mb_shrinker;
-+
-+static inline int
-+mb_cache_indexes(struct mb_cache *cache)
-+{
-+#ifdef MB_CACHE_INDEXES_COUNT
-+ return MB_CACHE_INDEXES_COUNT;
-+#else
-+ return cache->c_indexes_count;
-+#endif
-+}
-+
-+/*
-+ * What the mbcache registers as to get shrunk dynamically.
-+ */
-+
-+static int mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask);
-+
-+static inline void
-+__mb_cache_entry_takeout_lru(struct mb_cache_entry *ce)
-+{
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_into_lru(struct mb_cache_entry *ce)
-+{
-+ list_add(&ce->e_lru_list, &mb_cache_lru_list);
-+}
-+
-+
-+static inline int
-+__mb_cache_entry_in_lru(struct mb_cache_entry *ce)
-+{
-+ return (!list_empty(&ce->e_lru_list));
-+}
-+
-+
-+/*
-+ * Insert the cache entry into all hashes.
-+ */
-+static inline void
-+__mb_cache_entry_link(struct mb_cache_entry *ce)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket;
-+ int n;
-+
-+ bucket = hash_long((unsigned long)ce->e_bdev +
-+ (ce->e_block & 0xffffff), cache->c_bucket_bits);
-+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
-+ for (n=0; n<mb_cache_indexes(cache); n++) {
-+ bucket = hash_long(ce->e_indexes[n].o_key,
-+ cache->c_bucket_bits);
-+ list_add(&ce->e_indexes[n].o_list,
-+ &cache->c_indexes_hash[n][bucket]);
-+ }
-+}
-+
-+
-+/*
-+ * Remove the cache entry from all hashes.
-+ */
-+static inline void
-+__mb_cache_entry_unlink(struct mb_cache_entry *ce)
-+{
-+ int n;
-+
-+ list_del_init(&ce->e_block_list);
-+ for (n = 0; n < mb_cache_indexes(ce->e_cache); n++)
-+ list_del(&ce->e_indexes[n].o_list);
-+}
-+
-+
-+static inline int
-+__mb_cache_entry_is_linked(struct mb_cache_entry *ce)
-+{
-+ return (!list_empty(&ce->e_block_list));
-+}
-+
-+
-+static inline struct mb_cache_entry *
-+__mb_cache_entry_read(struct mb_cache_entry *ce)
-+{
-+ __mb_cache_entry_takeout_lru(ce);
-+ atomic_inc(&ce->e_used);
-+ return ce;
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_forget(struct mb_cache_entry *ce)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+
-+ mb_assert(atomic_read(&ce->e_used) == 0);
-+ atomic_dec(&cache->c_entry_count);
-+ if (cache->c_op.free)
-+ cache->c_op.free(ce);
-+ kmem_cache_free(cache->c_entry_cache, ce);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
-+{
-+ if (atomic_dec_and_test(&ce->e_used)) {
-+ if (!__mb_cache_entry_is_linked(ce))
-+ goto forget;
-+ __mb_cache_entry_into_lru(ce);
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ return;
-+forget:
-+ spin_unlock(&mb_cache_spinlock);
-+ __mb_cache_entry_forget(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_shrink_fn() memory pressure callback
-+ *
-+ * This function is called by the kernel memory management when memory
-+ * gets low.
-+ *
-+ * @nr_to_scan: Number of objects to scan
-+ * @gfp_mask: (ignored)
-+ *
-+ * Returns the number of objects which are present in the cache.
-+ */
-+static int
-+mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l;
-+ int count = 0;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_prev(l, &mb_cache_list) {
-+ struct mb_cache *cache =
-+ list_entry(l, struct mb_cache, c_cache_list);
-+ mb_debug("cache %s (%d)", cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ count += atomic_read(&cache->c_entry_count);
-+ }
-+ mb_debug("trying to free %d entries", nr_to_scan);
-+ if (nr_to_scan == 0) {
-+ spin_unlock(&mb_cache_spinlock);
-+ goto out;
-+ }
-+ while (nr_to_scan && !list_empty(&mb_cache_lru_list)) {
-+ struct mb_cache_entry *ce =
-+ list_entry(mb_cache_lru_list.prev,
-+ struct mb_cache_entry, e_lru_list);
-+ list_move(&ce->e_lru_list, &free_list);
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ nr_to_scan--;
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ l = free_list.prev;
-+ while (l != &free_list) {
-+ struct mb_cache_entry *ce = list_entry(l,
-+ struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ __mb_cache_entry_forget(ce);
-+ count--;
-+ }
-+out:
-+ mb_debug("%d remaining entries ", count);
-+ return count;
-+}
-+
-+
-+/*
-+ * mb_cache_create() create a new cache
-+ *
-+ * All entries in one cache are equal size. Cache entries may be from
-+ * multiple devices. If this is the first mbcache created, registers
-+ * the cache with kernel memory management. Returns NULL if no more
-+ * memory was available.
-+ *
-+ * @name: name of the cache (informal)
-+ * @cache_op: contains the callback called when freeing a cache entry
-+ * @entry_size: The size of a cache entry, including
-+ * struct mb_cache_entry
-+ * @indexes_count: number of additional indexes in the cache. Must equal
-+ * MB_CACHE_INDEXES_COUNT if the number of indexes is
-+ * hardwired.
-+ * @bucket_bits: log2(number of hash buckets)
-+ */
-+struct mb_cache *
-+mb_cache_create(const char *name, struct mb_cache_op *cache_op,
-+ size_t entry_size, int indexes_count, int bucket_bits)
-+{
-+ int m=0, n, bucket_count = 1 << bucket_bits;
-+ struct mb_cache *cache = NULL;
-+
-+ if(entry_size < sizeof(struct mb_cache_entry) +
-+ indexes_count * sizeof(struct mb_cache_entry_index))
-+ return NULL;
-+
-+ cache = kmalloc(sizeof(struct mb_cache) +
-+ indexes_count * sizeof(struct list_head), GFP_KERNEL);
-+ if (!cache)
-+ goto fail;
-+ cache->c_name = name;
-+ if (cache_op)
-+ cache->c_op.free = cache_op->free;
-+ else
-+ cache->c_op.free = NULL;
-+ atomic_set(&cache->c_entry_count, 0);
-+ cache->c_bucket_bits = bucket_bits;
-+#ifdef MB_CACHE_INDEXES_COUNT
-+ mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
-+#else
-+ cache->c_indexes_count = indexes_count;
-+#endif
-+ cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
-+ GFP_KERNEL);
-+ if (!cache->c_block_hash)
-+ goto fail;
-+ for (n=0; n<bucket_count; n++)
-+ INIT_LIST_HEAD(&cache->c_block_hash[n]);
-+ for (m=0; m<indexes_count; m++) {
-+ cache->c_indexes_hash[m] = kmalloc(bucket_count *
-+ sizeof(struct list_head),
-+ GFP_KERNEL);
-+ if (!cache->c_indexes_hash[m])
-+ goto fail;
-+ for (n=0; n<bucket_count; n++)
-+ INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
-+ }
-+ cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
-+ 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
-+ if (!cache->c_entry_cache)
-+ goto fail;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ if (list_empty(&mb_cache_list)) {
-+ if (mb_shrinker) {
-+ printk(KERN_ERR "%s: already have a shrinker!\n",
-+ __FUNCTION__);
-+ remove_shrinker(mb_shrinker);
-+ }
-+ mb_shrinker = set_shrinker(DEFAULT_SEEKS, mb_cache_shrink_fn);
-+ }
-+ list_add(&cache->c_cache_list, &mb_cache_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ return cache;
-+
-+fail:
-+ if (cache) {
-+ while (--m >= 0)
-+ kfree(cache->c_indexes_hash[m]);
-+ if (cache->c_block_hash)
-+ kfree(cache->c_block_hash);
-+ kfree(cache);
-+ }
-+ return NULL;
-+}
-+
-+
-+/*
-+ * mb_cache_shrink()
-+ *
-+ * Removes all cache entires of a device from the cache. All cache entries
-+ * currently in use cannot be freed, and thus remain in the cache. All others
-+ * are freed.
-+ *
-+ * @cache: which cache to shrink
-+ * @bdev: which device's cache entries to shrink
-+ */
-+void
-+mb_cache_shrink(struct mb_cache *cache, struct block_device *bdev)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ l = mb_cache_lru_list.prev;
-+ while (l != &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ if (ce->e_bdev == bdev) {
-+ list_move(&ce->e_lru_list, &free_list);
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ l = free_list.prev;
-+ while (l != &free_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ __mb_cache_entry_forget(ce);
-+ }
-+}
-+
-+
-+/*
-+ * mb_cache_destroy()
-+ *
-+ * Shrinks the cache to its minimum possible size (hopefully 0 entries),
-+ * and then destroys it. If this was the last mbcache, un-registers the
-+ * mbcache from kernel memory management.
-+ */
-+void
-+mb_cache_destroy(struct mb_cache *cache)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l;
-+ int n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ l = mb_cache_lru_list.prev;
-+ while (l != &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ if (ce->e_cache == cache) {
-+ list_move(&ce->e_lru_list, &free_list);
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ }
-+ }
-+ list_del(&cache->c_cache_list);
-+ if (list_empty(&mb_cache_list) && mb_shrinker) {
-+ remove_shrinker(mb_shrinker);
-+ mb_shrinker = 0;
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+
-+ l = free_list.prev;
-+ while (l != &free_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ __mb_cache_entry_forget(ce);
-+ }
-+
-+ if (atomic_read(&cache->c_entry_count) > 0) {
-+ mb_error("cache %s: %d orphaned entries",
-+ cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ }
-+
-+ kmem_cache_destroy(cache->c_entry_cache);
-+
-+ for (n=0; n < mb_cache_indexes(cache); n++)
-+ kfree(cache->c_indexes_hash[n]);
-+ kfree(cache->c_block_hash);
-+
-+ kfree(cache);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_alloc()
-+ *
-+ * Allocates a new cache entry. The new entry will not be valid initially,
-+ * and thus cannot be looked up yet. It should be filled with data, and
-+ * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
-+ * if no more memory was available.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_alloc(struct mb_cache *cache)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ atomic_inc(&cache->c_entry_count);
-+ ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
-+ if (ce) {
-+ INIT_LIST_HEAD(&ce->e_lru_list);
-+ INIT_LIST_HEAD(&ce->e_block_list);
-+ ce->e_cache = cache;
-+ atomic_set(&ce->e_used, 1);
-+ }
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_insert()
-+ *
-+ * Inserts an entry that was allocated using mb_cache_entry_alloc() into
-+ * the cache. After this, the cache entry can be looked up, but is not yet
-+ * in the lru list as the caller still holds a handle to it. Returns 0 on
-+ * success, or -EBUSY if a cache entry for that device + inode exists
-+ * already (this may happen after a failed lookup, but when another process
-+ * has inserted the same cache entry in the meantime).
-+ *
-+ * @bdev: device the cache entry belongs to
-+ * @block: block number
-+ * @keys: array of additional keys. There must be indexes_count entries
-+ * in the array (as specified when creating the cache).
-+ */
-+int
-+mb_cache_entry_insert(struct mb_cache_entry *ce, struct block_device *bdev,
-+ sector_t block, unsigned int keys[])
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket;
-+ struct list_head *l;
-+ int error = -EBUSY, n;
-+
-+ bucket = hash_long((unsigned long)bdev + (block & 0xffffffff),
-+ cache->c_bucket_bits);
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_prev(l, &cache->c_block_hash[bucket]) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_bdev == bdev && ce->e_block == block)
-+ goto out;
-+ }
-+ mb_assert(!__mb_cache_entry_is_linked(ce));
-+ ce->e_bdev = bdev;
-+ ce->e_block = block;
-+ for (n=0; n<mb_cache_indexes(cache); n++)
-+ ce->e_indexes[n].o_key = keys[n];
-+ __mb_cache_entry_link(ce);
-+out:
-+ spin_unlock(&mb_cache_spinlock);
-+ return error;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_release()
-+ *
-+ * Release a handle to a cache entry. When the last handle to a cache entry
-+ * is released it is either freed (if it is invalid) or otherwise inserted
-+ * in to the lru list.
-+ */
-+void
-+mb_cache_entry_release(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ __mb_cache_entry_release_unlock(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_takeout()
-+ *
-+ * Take a cache entry out of the cache, making it invalid. The entry can later
-+ * be re-inserted using mb_cache_entry_insert(), or released using
-+ * mb_cache_entry_release().
-+ */
-+void
-+mb_cache_entry_takeout(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ mb_assert(!__mb_cache_entry_in_lru(ce));
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ spin_unlock(&mb_cache_spinlock);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_free()
-+ *
-+ * This is equivalent to the sequence mb_cache_entry_takeout() --
-+ * mb_cache_entry_release().
-+ */
-+void
-+mb_cache_entry_free(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ mb_assert(!__mb_cache_entry_in_lru(ce));
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ __mb_cache_entry_release_unlock(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_dup()
-+ *
-+ * Duplicate a handle to a cache entry (does not duplicate the cache entry
-+ * itself). After the call, both the old and the new handle must be released.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_dup(struct mb_cache_entry *ce)
-+{
-+ atomic_inc(&ce->e_used);
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_get()
-+ *
-+ * Get a cache entry by device / block number. (There can only be one entry
-+ * in the cache per device and block.) Returns NULL if no such cache entry
-+ * exists.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_get(struct mb_cache *cache, struct block_device *bdev,
-+ sector_t block)
-+{
-+ unsigned int bucket;
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ bucket = hash_long((unsigned long)bdev + (block & 0xffffffff),
-+ cache->c_bucket_bits);
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(l, &cache->c_block_hash[bucket]) {
-+ ce = list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_bdev == bdev && ce->e_block == block) {
-+ ce = __mb_cache_entry_read(ce);
-+ goto cleanup;
-+ }
-+ }
-+ ce = NULL;
-+
-+cleanup:
-+ spin_unlock(&mb_cache_spinlock);
-+ return ce;
-+}
-+
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+
-+static struct mb_cache_entry *
-+__mb_cache_entry_find(struct list_head *l, struct list_head *head,
-+ int index, struct block_device *bdev, unsigned int key)
-+{
-+ while (l != head) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry,
-+ e_indexes[index].o_list);
-+ if (ce->e_bdev == bdev &&
-+ ce->e_indexes[index].o_key == key) {
-+ ce = __mb_cache_entry_read(ce);
-+ if (ce)
-+ return ce;
-+ }
-+ l = l->next;
-+ }
-+ return NULL;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_find_first()
-+ *
-+ * Find the first cache entry on a given device with a certain key in
-+ * an additional index. Additonal matches can be found with
-+ * mb_cache_entry_find_next(). Returns NULL if no match was found.
-+ *
-+ * @cache: the cache to search
-+ * @index: the number of the additonal index to search (0<=index<indexes_count)
-+ * @bdev: the device the cache entry should belong to
-+ * @key: the key in the index
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_find_first(struct mb_cache *cache, int index,
-+ struct block_device *bdev, unsigned int key)
-+{
-+ unsigned int bucket = hash_long(key, cache->c_bucket_bits);
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ mb_assert(index < mb_cache_indexes(cache));
-+ spin_lock(&mb_cache_spinlock);
-+ l = cache->c_indexes_hash[index][bucket].next;
-+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
-+ index, bdev, key);
-+ spin_unlock(&mb_cache_spinlock);
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_find_next()
-+ *
-+ * Find the next cache entry on a given device with a certain key in an
-+ * additional index. Returns NULL if no match could be found. The previous
-+ * entry is atomatically released, so that mb_cache_entry_find_next() can
-+ * be called like this:
-+ *
-+ * entry = mb_cache_entry_find_first();
-+ * while (entry) {
-+ * ...
-+ * entry = mb_cache_entry_find_next(entry, ...);
-+ * }
-+ *
-+ * @prev: The previous match
-+ * @index: the number of the additonal index to search (0<=index<indexes_count)
-+ * @bdev: the device the cache entry should belong to
-+ * @key: the key in the index
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_find_next(struct mb_cache_entry *prev, int index,
-+ struct block_device *bdev, unsigned int key)
-+{
-+ struct mb_cache *cache = prev->e_cache;
-+ unsigned int bucket = hash_long(key, cache->c_bucket_bits);
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ mb_assert(index < mb_cache_indexes(cache));
-+ spin_lock(&mb_cache_spinlock);
-+ l = prev->e_indexes[index].o_list.next;
-+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
-+ index, bdev, key);
-+ __mb_cache_entry_release_unlock(prev);
-+ return ce;
-+}
-+
-+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
-diff -Nru a/fs/namei.c b/fs/namei.c
---- a/fs/namei.c Thu Dec 12 20:58:37 2002
-+++ b/fs/namei.c Thu Dec 12 20:58:37 2002
-@@ -265,6 +265,9 @@
-
- void path_release(struct nameidata *nd)
- {
-+ if (&nd->it && nd->dentry && nd->dentry->d_op &&
-+ nd->dentry->d_op->d_intent_release)
-+ nd->dentry->d_op->d_intent_release(nd->dentry, &nd->it);
- dput(nd->dentry);
- mntput(nd->mnt);
- }
-@@ -273,10 +276,18 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -351,7 +362,7 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -369,7 +380,10 @@
- struct dentry * dentry = d_alloc(parent, name);
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
-- result = dir->i_op->lookup(dir, dentry);
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
-+ result = dir->i_op->lookup(dir, dentry);
- if (result)
- dput(dentry);
- else {
-@@ -391,6 +405,12 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -402,7 +422,8 @@
- * Without that kind of total limit, nasty chains of consecutive
- * symlinks can cause almost arbitrarily long lookups.
- */
--static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
-+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- int err = -ELOOP;
- if (current->link_count >= 5)
-@@ -419,7 +440,10 @@
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-@@ -534,7 +558,7 @@
- unlock_nd(nd);
-
- need_lookup:
-- dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE, &nd->it);
- if (IS_ERR(dentry))
- goto fail;
- mntget(mnt);
-@@ -662,11 +686,11 @@
- if (!inode->i_op)
- break;
-
-- if (inode->i_op->follow_link) {
-+ if (inode->i_op->follow_link || inode->i_op->follow_link2) {
- mntget(next.mnt);
- dget_locked(next.dentry);
- unlock_nd(nd);
-- err = do_follow_link(next.dentry, nd);
-+ err = do_follow_link(next.dentry, nd, &nd->it);
- dput(next.dentry);
- mntput(next.mnt);
- if (err)
-@@ -684,7 +708,7 @@
- nd->dentry = next.dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -717,11 +741,12 @@
- follow_mount(&next.mnt, &next.dentry);
- inode = next.dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
-- && inode && inode->i_op && inode->i_op->follow_link) {
-+ && inode && inode->i_op &&
-+ (inode->i_op->follow_link || inode->i_op->follow_link2)) {
- mntget(next.mnt);
- dget_locked(next.dentry);
- unlock_nd(nd);
-- err = do_follow_link(next.dentry, nd);
-+ err = do_follow_link(next.dentry, nd, &nd->it);
- dput(next.dentry);
- mntput(next.mnt);
- if (err)
-@@ -737,7 +762,8 @@
- break;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op ||
-+ (!inode->i_op->lookup && !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -886,7 +912,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -909,13 +936,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
-- dentry = inode->i_op->lookup(inode, new);
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
-+ dentry = inode->i_op->lookup(inode, new);
- if (!dentry) {
- dentry = new;
- security_ops->inode_post_lookup(inode, dentry);
-@@ -927,7 +957,7 @@
- }
-
- /* SMP-safe */
--struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, int len, struct lookup_intent *it)
- {
- unsigned long hash;
- struct qstr this;
-@@ -947,11 +977,16 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash(&this, base, it);
- access:
- return ERR_PTR(-EACCES);
- }
-
-+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+{
-+ return lookup_one_len_it(name, base, len, NULL);
-+}
-+
- /*
- * namei()
- *
-@@ -1268,7 +1303,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1310,7 +1345,8 @@
- error = -ENOENT;
- if (!dentry->d_inode)
- goto exit_dput;
-- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
-+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
-+ dentry->d_inode->i_op->follow_link2))
- goto do_link;
-
- dput(nd->dentry);
-@@ -1370,7 +1406,7 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
- putname(nd->last.name);
- goto do_last;
- }
-@@ -1384,7 +1420,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1614,7 +1650,7 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd.it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1675,7 +1711,7 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd.it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1949,7 +1985,8 @@
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
-@@ -2020,7 +2057,7 @@
-
- trap = lock_rename(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash(&oldnd.last, old_dir, &oldnd.it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -2040,7 +2077,7 @@
- error = -EINVAL;
- if (old_dentry == trap)
- goto exit4;
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ new_dentry = lookup_hash(&newnd.last, new_dir, &newnd.it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-@@ -2050,7 +2087,7 @@
- goto exit5;
-
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, NULL);
- exit5:
- dput(new_dentry);
- exit4:
-@@ -2102,7 +2139,8 @@
- }
-
- static inline int
--__vfs_follow_link(struct nameidata *nd, const char *link)
-+__vfs_follow_link(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
- {
- int res = 0;
- char *name;
-@@ -2138,7 +2176,13 @@
-
- int vfs_follow_link(struct nameidata *nd, const char *link)
- {
-- return __vfs_follow_link(nd, link);
-+ return __vfs_follow_link(nd, link, NULL);
-+}
-+
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
-+{
-+ return __vfs_follow_link(nd, link, it);
- }
-
- /* get the link contents into pagecache */
-@@ -2180,7 +2224,7 @@
- {
- struct page *page = NULL;
- char *s = page_getlink(dentry, &page);
-- int res = __vfs_follow_link(nd, s);
-+ int res = __vfs_follow_link(nd, s, NULL);
- if (page) {
- kunmap(page);
- page_cache_release(page);
-diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
---- a/fs/nfsd/vfs.c Thu Dec 12 20:58:37 2002
-+++ b/fs/nfsd/vfs.c Thu Dec 12 20:58:37 2002
-@@ -1292,7 +1292,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
-diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
---- a/fs/sysfs/inode.c Thu Dec 12 20:58:37 2002
-+++ b/fs/sysfs/inode.c Thu Dec 12 20:58:37 2002
-@@ -471,7 +471,7 @@
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-- return lookup_hash(&qstr,parent);
-+ return lookup_hash(&qstr,parent,NULL);
- }
-
- /**
-diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
---- a/include/linux/dcache.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/dcache.h Thu Dec 12 20:58:37 2002
-@@ -9,6 +9,24 @@
- #include <linux/spinlock.h>
- #include <asm/page.h> /* for BUG() */
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
-+
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -30,6 +48,8 @@
- unsigned int hash;
- };
-
-+#include <linux/namei.h>
-+
- struct dentry_stat_t {
- int nr_dentry;
- int nr_unused;
-@@ -79,6 +99,7 @@
- struct list_head d_subdirs; /* our children */
- struct list_head d_alias; /* inode alias list */
- int d_mounted;
-+ struct lookup_intent *d_it;
- struct qstr d_name;
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
-@@ -96,6 +117,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
-diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
---- a/include/linux/ext3_fs.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/ext3_fs.h Thu Dec 12 20:58:37 2002
-@@ -64,8 +64,6 @@
- */
- #define EXT3_BAD_INO 1 /* Bad blocks inode */
- #define EXT3_ROOT_INO 2 /* Root inode */
--#define EXT3_ACL_IDX_INO 3 /* ACL inode */
--#define EXT3_ACL_DATA_INO 4 /* ACL inode */
- #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
- #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
-@@ -95,7 +93,6 @@
- #else
- # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
- #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -130,28 +127,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext3_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext3_acl_entry /* Access Control List Entry */
--{
-- __u32 acle_size;
-- __u16 acle_perms; /* Access permissions */
-- __u16 acle_type; /* Type of entry */
-- __u16 acle_tag; /* User or group identity */
-- __u16 acle_pad1;
-- __u32 acle_next; /* Pointer on next entry for the */
-- /* same inode or on next free entry */
--};
--
--/*
- * Structure of a blocks group descriptor
- */
- struct ext3_group_desc
-@@ -347,6 +322,7 @@
- #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
- #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
-+#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -529,7 +505,7 @@
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-
--#define EXT3_FEATURE_COMPAT_SUPP 0
-+#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
-@@ -713,6 +689,7 @@
-
-
- /* inode.c */
-+extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
- extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
- extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-
-@@ -781,8 +758,10 @@
-
- /* namei.c */
- extern struct inode_operations ext3_dir_inode_operations;
-+extern struct inode_operations ext3_special_inode_operations;
-
- /* symlink.c */
-+extern struct inode_operations ext3_symlink_inode_operations;
- extern struct inode_operations ext3_fast_symlink_inode_operations;
-
-
-diff -Nru a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
---- a/include/linux/ext3_jbd.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/ext3_jbd.h Thu Dec 12 20:58:37 2002
-@@ -30,13 +30,19 @@
-
- #define EXT3_SINGLEDATA_TRANS_BLOCKS 8
-
-+/* Extended attributes may touch two data buffers, two bitmap buffers,
-+ * and two group and summaries. */
-+
-+#define EXT3_XATTR_TRANS_BLOCKS 8
-+
- /* Define the minimum size for a transaction which modifies data. This
- * needs to take into account the fact that we may end up modifying two
- * quota files too (one for the group, one for the user quota). The
- * superblock only gets updated once, of course, so don't bother
- * counting that again for the quota updates. */
-
--#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
-+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
-+ EXT3_XATTR_TRANS_BLOCKS - 2)
-
- extern int ext3_writepage_trans_blocks(struct inode *inode);
-
-diff -Nru a/include/linux/fs.h b/include/linux/fs.h
---- a/include/linux/fs.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/fs.h Thu Dec 12 20:58:37 2002
-@@ -700,7 +700,7 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct lookup_intent *it);
-
- /*
- * File types
-@@ -769,6 +769,8 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *,
-+ struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -779,6 +781,7 @@
- struct inode *, struct dentry *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *, struct lookup_intent *it);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*setattr) (struct dentry *, struct iattr *);
-@@ -995,6 +998,7 @@
- extern int unregister_filesystem(struct file_system_type *);
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-
- #define kern_umount mntput
-@@ -1285,6 +1289,8 @@
-
- extern int vfs_readlink(struct dentry *, char *, int, const char *);
- extern int vfs_follow_link(struct nameidata *, const char *);
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it);
- extern int page_readlink(struct dentry *, char *, int);
- extern int page_follow_link(struct dentry *, struct nameidata *);
- extern int page_symlink(struct inode *inode, const char *symname, int len);
-diff -Nru a/include/linux/lustre_version.h b/include/linux/lustre_version.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/include/linux/lustre_version.h Thu Dec 12 20:58:37 2002
-@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 4
-diff -Nru a/include/linux/mbcache.h b/include/linux/mbcache.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/include/linux/mbcache.h Thu Dec 12 20:58:37 2002
-@@ -0,0 +1,72 @@
-+/*
-+ File: linux/mbcache.h
-+
-+ (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+/* Hardwire the number of additional indexes */
-+#define MB_CACHE_INDEXES_COUNT 1
-+
-+struct mb_cache_entry;
-+
-+struct mb_cache_op {
-+ void (*free)(struct mb_cache_entry *);
-+};
-+
-+struct mb_cache {
-+ struct list_head c_cache_list;
-+ const char *c_name;
-+ struct mb_cache_op c_op;
-+ atomic_t c_entry_count;
-+ int c_bucket_bits;
-+#ifndef MB_CACHE_INDEXES_COUNT
-+ int c_indexes_count;
-+#endif
-+ kmem_cache_t *c_entry_cache;
-+ struct list_head *c_block_hash;
-+ struct list_head *c_indexes_hash[0];
-+};
-+
-+struct mb_cache_entry_index {
-+ struct list_head o_list;
-+ unsigned int o_key;
-+};
-+
-+struct mb_cache_entry {
-+ struct list_head e_lru_list;
-+ struct mb_cache *e_cache;
-+ atomic_t e_used;
-+ struct block_device *e_bdev;
-+ sector_t e_block;
-+ struct list_head e_block_list;
-+ struct mb_cache_entry_index e_indexes[0];
-+};
-+
-+/* Functions on caches */
-+
-+struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
-+ int, int);
-+void mb_cache_shrink(struct mb_cache *, struct block_device *);
-+void mb_cache_destroy(struct mb_cache *);
-+
-+/* Functions on cache entries */
-+
-+struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
-+int mb_cache_entry_insert(struct mb_cache_entry *, struct block_device *,
-+ sector_t, unsigned int[]);
-+void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
-+void mb_cache_entry_release(struct mb_cache_entry *);
-+void mb_cache_entry_takeout(struct mb_cache_entry *);
-+void mb_cache_entry_free(struct mb_cache_entry *);
-+struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
-+struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *,
-+ struct block_device *,
-+ sector_t);
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
-+ struct block_device *,
-+ unsigned int);
-+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
-+ struct block_device *,
-+ unsigned int);
-+#endif
-diff -Nru a/include/linux/namei.h b/include/linux/namei.h
---- a/include/linux/namei.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/namei.h Thu Dec 12 20:58:37 2002
-@@ -5,6 +5,17 @@
-
- struct vfsmount;
-
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- struct nameidata {
- struct dentry *dentry;
- struct vfsmount *mnt;
-@@ -13,6 +24,7 @@
- int last_type;
- struct dentry *old_dentry;
- struct vfsmount *old_mnt;
-+ struct lookup_intent it;
- };
-
- /*
-@@ -46,7 +58,7 @@
- extern void path_release(struct nameidata *);
-
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
--extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
-+extern struct dentry * lookup_hash(struct qstr *, struct dentry *, struct lookup_intent *);
-
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
-diff -Nru a/include/linux/slab.h b/include/linux/slab.h
---- a/include/linux/slab.h Thu Dec 12 20:58:37 2002
-+++ b/include/linux/slab.h Thu Dec 12 20:58:37 2002
-@@ -56,6 +56,7 @@
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
- extern unsigned int kmem_cache_size(kmem_cache_t *);
-
- extern void *kmalloc(size_t, int);
-diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
---- a/kernel/ksyms.c Thu Dec 12 20:58:37 2002
-+++ b/kernel/ksyms.c Thu Dec 12 20:58:37 2002
-@@ -286,6 +286,7 @@
- EXPORT_SYMBOL(mark_page_accessed);
- EXPORT_SYMBOL(vfs_readlink);
- EXPORT_SYMBOL(vfs_follow_link);
-+EXPORT_SYMBOL(vfs_follow_link_it);
- EXPORT_SYMBOL(page_readlink);
- EXPORT_SYMBOL(page_follow_link);
- EXPORT_SYMBOL(page_symlink_inode_operations);
-@@ -365,6 +366,13 @@
- EXPORT_SYMBOL(tty_get_baud_rate);
- EXPORT_SYMBOL(do_SAK);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+//EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(exit_files);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
- /* filesystem registration */
- EXPORT_SYMBOL(register_filesystem);
- EXPORT_SYMBOL(unregister_filesystem);
-@@ -529,6 +537,7 @@
- EXPORT_SYMBOL(seq_lseek);
- EXPORT_SYMBOL(single_open);
- EXPORT_SYMBOL(single_release);
-+EXPORT_SYMBOL(reparent_to_init);
-
- /* Program loader interfaces */
- EXPORT_SYMBOL(setup_arg_pages);
-diff -Nru a/mm/slab.c b/mm/slab.c
---- a/mm/slab.c Thu Dec 12 20:58:37 2002
-+++ b/mm/slab.c Thu Dec 12 20:58:37 2002
-@@ -1236,6 +1236,59 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!page_mem_map(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
-diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
---- a/net/unix/af_unix.c Thu Dec 12 20:58:37 2002
-+++ b/net/unix/af_unix.c Thu Dec 12 20:58:37 2002
-@@ -715,7 +715,7 @@
- /*
- * Do the final lookup.
- */
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- goto out_mknod_unlock;
+++ /dev/null
-# This is a BitKeeper generated patch for the following project:
-# Project Name: Linux kernel tree
-# This patch format is intended for GNU patch command version 2.5 or higher.
-# This patch includes the following deltas:
-# ChangeSet 1.810 -> 1.811
-# kernel/ksyms.c 1.149 -> 1.150
-# fs/driverfs/inode.c 1.52 -> 1.53
-# include/linux/fs.h 1.175 -> 1.176
-# include/linux/namei.h 1.3 -> 1.4
-# fs/namei.c 1.56 -> 1.57
-# fs/nfsd/vfs.c 1.44 -> 1.45
-# arch/um/kernel/mem.c 1.5 -> 1.6
-# net/unix/af_unix.c 1.29 -> 1.30
-# mm/slab.c 1.33 -> 1.34
-# fs/sysfs/inode.c 1.55 -> 1.56
-# include/linux/slab.h 1.13 -> 1.14
-# include/linux/dcache.h 1.19 -> 1.20
-#
-# The following is the BitKeeper ChangeSet Log
-# --------------------------------------------
-# 02/10/20 braam@clusterfs.com 1.811
-# Changes for Lustre
-# --------------------------------------------
-#
-diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
---- a/arch/um/kernel/mem.c Sun Dec 8 02:49:38 2002
-+++ b/arch/um/kernel/mem.c Sun Dec 8 02:49:38 2002
-@@ -656,6 +656,22 @@
- return(phys_mem_map(pte_val(pte)));
- }
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+ struct page *page;
-+ struct mem_region *mr;
-+ unsigned long phys = __pa(kaddr);
-+ unsigned int n = phys_region_index(phys);
-+
-+ if(regions[n] == NULL)
-+ return NULL;
-+
-+ mr = regions[n];
-+ page = (struct page *) mr->mem_map;
-+ return page + ((phys_addr(phys)) >> PAGE_SHIFT);
-+}
-+
-+
- struct mem_region *page_region(struct page *page, int *index_out)
- {
- int i;
-@@ -743,7 +759,7 @@
- (addr <= region->start + region->len))
- return(mk_phys(addr - region->start, i));
- }
-- panic("region_pa : no region for virtual address");
-+ //panic("region_pa : no region for virtual address");
- return(0);
- }
-
-diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c
---- a/fs/driverfs/inode.c Sun Dec 8 02:49:38 2002
-+++ b/fs/driverfs/inode.c Sun Dec 8 02:49:38 2002
-@@ -523,7 +523,7 @@
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-- return lookup_hash(&qstr,parent);
-+ return lookup_hash(&qstr,parent, NULL);
- }
-
- /**
-diff -Nru a/fs/namei.c b/fs/namei.c
---- a/fs/namei.c Sun Dec 8 02:49:38 2002
-+++ b/fs/namei.c Sun Dec 8 02:49:38 2002
-@@ -265,6 +265,9 @@
-
- void path_release(struct nameidata *nd)
- {
-+ if (nd->dentry && nd->dentry->d_op &&
-+ nd->dentry->d_op->d_intent_release)
-+ nd->dentry->d_op->d_intent_release(nd->dentry, &nd->it);
- dput(nd->dentry);
- mntput(nd->mnt);
- }
-@@ -273,10 +276,18 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -351,7 +362,7 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -369,7 +380,10 @@
- struct dentry * dentry = d_alloc(parent, name);
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
-- result = dir->i_op->lookup(dir, dentry);
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
-+ result = dir->i_op->lookup(dir, dentry);
- if (result)
- dput(dentry);
- else {
-@@ -391,6 +405,12 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -534,7 +554,7 @@
- unlock_nd(nd);
-
- need_lookup:
-- dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE, &nd->it);
- if (IS_ERR(dentry))
- goto fail;
- mntget(mnt);
-@@ -684,7 +704,7 @@
- nd->dentry = next.dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -737,7 +757,8 @@
- break;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op ||
-+ (!inode->i_op->lookup && !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -886,7 +907,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -909,13 +931,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
-- dentry = inode->i_op->lookup(inode, new);
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
-+ dentry = inode->i_op->lookup(inode, new);
- if (!dentry) {
- dentry = new;
- security_ops->inode_post_lookup(inode, dentry);
-@@ -927,7 +952,7 @@
- }
-
- /* SMP-safe */
--struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, int len, struct lookup_intent *it)
- {
- unsigned long hash;
- struct qstr this;
-@@ -947,11 +972,16 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash(&this, base, it);
- access:
- return ERR_PTR(-EACCES);
- }
-
-+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+{
-+ return lookup_one_len_it(name, base, len, NULL);
-+}
-+
- /*
- * namei()
- *
-@@ -1268,7 +1298,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1370,7 +1400,7 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
- putname(nd->last.name);
- goto do_last;
- }
-@@ -1384,7 +1414,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1614,7 +1644,7 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd.it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1675,7 +1705,7 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd.it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1949,7 +1979,8 @@
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
-@@ -2020,7 +2051,7 @@
-
- trap = lock_rename(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash(&oldnd.last, old_dir, &oldnd.it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -2040,7 +2071,7 @@
- error = -EINVAL;
- if (old_dentry == trap)
- goto exit4;
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ new_dentry = lookup_hash(&newnd.last, new_dir, &newnd.it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-@@ -2050,7 +2081,7 @@
- goto exit5;
-
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, NULL);
- exit5:
- dput(new_dentry);
- exit4:
-diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
---- a/fs/nfsd/vfs.c Sun Dec 8 02:49:38 2002
-+++ b/fs/nfsd/vfs.c Sun Dec 8 02:49:38 2002
-@@ -1292,7 +1292,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
-diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
---- a/fs/sysfs/inode.c Sun Dec 8 02:49:39 2002
-+++ b/fs/sysfs/inode.c Sun Dec 8 02:49:39 2002
-@@ -471,7 +471,7 @@
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-- return lookup_hash(&qstr,parent);
-+ return lookup_hash(&qstr,parent,NULL);
- }
-
- /**
-diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
---- a/include/linux/dcache.h Sun Dec 8 02:49:39 2002
-+++ b/include/linux/dcache.h Sun Dec 8 02:49:39 2002
-@@ -9,6 +9,24 @@
- #include <linux/spinlock.h>
- #include <asm/page.h> /* for BUG() */
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
-+
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -30,6 +48,8 @@
- unsigned int hash;
- };
-
-+#include <linux/namei.h>
-+
- struct dentry_stat_t {
- int nr_dentry;
- int nr_unused;
-@@ -79,6 +99,7 @@
- struct list_head d_subdirs; /* our children */
- struct list_head d_alias; /* inode alias list */
- int d_mounted;
-+ struct lookup_intent *d_it;
- struct qstr d_name;
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
-@@ -96,6 +117,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
-diff -Nru a/include/linux/fs.h b/include/linux/fs.h
---- a/include/linux/fs.h Sun Dec 8 02:49:38 2002
-+++ b/include/linux/fs.h Sun Dec 8 02:49:38 2002
-@@ -700,7 +700,7 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct lookup_intent *it);
-
- /*
- * File types
-@@ -769,6 +769,8 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *,
-+ struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -995,6 +997,7 @@
- extern int unregister_filesystem(struct file_system_type *);
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-
- #define kern_umount mntput
-diff -Nru a/include/linux/namei.h b/include/linux/namei.h
---- a/include/linux/namei.h Sun Dec 8 02:49:38 2002
-+++ b/include/linux/namei.h Sun Dec 8 02:49:38 2002
-@@ -5,6 +5,17 @@
-
- struct vfsmount;
-
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- struct nameidata {
- struct dentry *dentry;
- struct vfsmount *mnt;
-@@ -13,6 +24,7 @@
- int last_type;
- struct dentry *old_dentry;
- struct vfsmount *old_mnt;
-+ struct lookup_intent it;
- };
-
- /*
-@@ -46,7 +58,7 @@
- extern void path_release(struct nameidata *);
-
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
--extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
-+extern struct dentry * lookup_hash(struct qstr *, struct dentry *, struct lookup_intent *);
-
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
-diff -Nru a/include/linux/slab.h b/include/linux/slab.h
---- a/include/linux/slab.h Sun Dec 8 02:49:39 2002
-+++ b/include/linux/slab.h Sun Dec 8 02:49:39 2002
-@@ -56,6 +56,7 @@
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
- extern unsigned int kmem_cache_size(kmem_cache_t *);
-
- extern void *kmalloc(size_t, int);
-diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
---- a/kernel/ksyms.c Sun Dec 8 02:49:38 2002
-+++ b/kernel/ksyms.c Sun Dec 8 02:49:38 2002
-@@ -365,6 +365,13 @@
- EXPORT_SYMBOL(tty_get_baud_rate);
- EXPORT_SYMBOL(do_SAK);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+//EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(exit_files);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
- /* filesystem registration */
- EXPORT_SYMBOL(register_filesystem);
- EXPORT_SYMBOL(unregister_filesystem);
-diff -Nru a/mm/slab.c b/mm/slab.c
---- a/mm/slab.c Sun Dec 8 02:49:39 2002
-+++ b/mm/slab.c Sun Dec 8 02:49:39 2002
-@@ -1236,6 +1236,59 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!page_mem_map(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
-diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
---- a/net/unix/af_unix.c Sun Dec 8 02:49:38 2002
-+++ b/net/unix/af_unix.c Sun Dec 8 02:49:38 2002
-@@ -715,7 +715,7 @@
- /*
- * Do the final lookup.
- */
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- goto out_mknod_unlock;
+++ /dev/null
-
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/arch/um/kernel/mem.c~uml_check_get_page 2002-12-06 14:52:30.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/arch/um/kernel/mem.c 2002-12-06 14:52:30.000000000 -0800
-@@ -529,6 +529,21 @@ struct page *pte_mem_map(pte_t pte)
- return(phys_mem_map(pte_val(pte)));
- }
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+ struct page *page;
-+ struct mem_region *mr;
-+ unsigned long phys = __pa(kaddr);
-+ unsigned int n = phys_region_index(phys);
-+
-+ if (regions[n] == NULL)
-+ return NULL;
-+
-+ mr = regions[n];
-+ page = (struct page *) mr->mem_map;
-+ return page + ((phys_addr(phys)) >> PAGE_SHIFT);
-+}
-+
- struct mem_region *page_region(struct page *page, int *index_out)
- {
- int i;
-
-_
+++ /dev/null
-
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/arch/um/kernel/mem.c~uml_no_panic 2002-12-06 14:52:30.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/arch/um/kernel/mem.c 2002-12-06 14:52:30.000000000 -0800
-@@ -559,7 +559,9 @@ struct mem_region *page_region(struct pa
- return(region);
- }
- }
-- panic("No region found for page");
-+// panic("No region found for page");
-+ printk(KERN_ERR "no region foudn for page %p\n, returning NULL\n",
-+ page);
- return(NULL);
- }
-
-@@ -581,7 +583,9 @@ unsigned long region_pa(void *virt)
- (addr <= region->start + region->len))
- return(mk_phys(addr - region->start, i));
- }
-- panic("region_pa : no region for virtual address");
-+ //panic("region_pa : no region for virtual address");
-+ printk(KERN_ERR "no region for virtual address %lu, return pa 0\n",
-+ addr);
- return(0);
- }
-
-
-_
+++ /dev/null
-arch/um/kernel/mem.c
-fs/Config.help
-fs/Config.in
-fs/driverfs/inode.c
-fs/ext3/file.c
-fs/ext3/ialloc.c
-fs/ext3/inode.c
-fs/ext3/Makefile
-fs/ext3/namei.c
-fs/ext3/super.c
-fs/ext3/symlink.c
-fs/ext3/xattr.c
-fs/ext3/xattr.h
-fs/ext3/xattr_user.c
-fs/Makefile
-fs/mbcache.c
-fs/namei.c
-fs/nfsd/vfs.c
-fs/sysfs/inode.c
-include/linux/dcache.h
-include/linux/ext3_fs.h
-include/linux/ext3_jbd.h
-include/linux/fs.h
-include/linux/lustre_version.h
-include/linux/mbcache.h
-include/linux/namei.h
-include/linux/slab.h
-kernel/ksyms.c
-mm/slab.c
-net/unix/af_unix.c
+++ /dev/null
-./include/linux/lustre_version.h
-./arch/ia64/mm/init.c
-./arch/i386/mm/init.c
-./drivers/block/blkpg.c
-./drivers/block/loop.c
-./drivers/ide/ide-disk.c
-./fs/ext3/Makefile
-./fs/ext3/super.c
-./fs/jbd/commit.c
-./fs/jbd/journal.c
-./fs/jbd/transaction.c
-./include/linux/blkdev.h
-./include/linux/slab.h
-./include/linux/jbd.h
-./kernel/ksyms.c
-./include/linux/dcache.h
-./include/linux/fs.h
-./fs/dcache.c
-./fs/nfsd/vfs.c
-./fs/namei.c
-./fs/open.c
-./fs/stat.c
-./mm/slab.c
+++ /dev/null
-include/linux/lustre_version.h
-arch/ia64/mm/init.c
-arch/i386/mm/init.c
-drivers/block/blkpg.c
-drivers/block/loop.c
-drivers/ide/ide-disk.c
-fs/ext3/Makefile
-fs/ext3/super.c
-fs/jbd/commit.c
-fs/jbd/journal.c
-fs/jbd/transaction.c
-include/linux/blkdev.h
-include/linux/slab.h
-include/linux/jbd.h
-kernel/ksyms.c
-include/linux/dcache.h
-include/linux/fs.h
-fs/dcache.c
-fs/nfsd/vfs.c
-fs/namei.c
-fs/open.c
-fs/stat.c
-mm/slab.c
+++ /dev/null
-include/linux/lustre_version.h
-arch/ia64/mm/init.c
-arch/i386/mm/init.c
-drivers/block/blkpg.c
-drivers/block/loop.c
-drivers/ide/ide-disk.c
-fs/ext3/Makefile
-fs/ext3/super.c
-fs/jbd/commit.c
-fs/jbd/journal.c
-fs/jbd/transaction.c
-include/linux/blkdev.h
-include/linux/slab.h
-include/linux/jbd.h
-kernel/ksyms.c
-include/linux/dcache.h
-include/linux/fs.h
-fs/dcache.c
-fs/nfsd/vfs.c
-fs/namei.c
-fs/open.c
-fs/stat.c
-mm/slab.c
+++ /dev/null
-fs/dcache.c
-fs/namei.c
-fs/nfsd/vfs.c
-fs/open.c
-fs/stat.c
-include/linux/dcache.h
-include/linux/fs.h
-kernel/ksyms.c
+++ /dev/null
-fs/dcache.c
-fs/namei.c
-fs/nfsd/vfs.c
-fs/open.c
-fs/stat.c
-include/linux/dcache.h
-include/linux/fs.h
-kernel/ksyms.c
+++ /dev/null
-#!/bin/bash
-
-die() {
- echo -e $* >&2
- echo aborting.. >&2
- exit 1
-}
-
-canon() {
- cd $1
- CANON=$PWD
- cd -
-}
-
-canon $(dirname $0)
-MYDIR=$CANON
-
-while [ ${#*} -gt 1 ]; do
- case "$1" in
- -t)
- shift;
- TREE=$1
- ;;
- -s)
- shift;
- SERIES=$1
- ;;
- *)
- die "unknown argument $1"
- break;
- ;;
- esac
- shift;
-done
-
-[ -z "$TREE" -o -z "$SERIES" ] && die "I need a tree and series:\n\t$0 -t kernel_dir -s series_name"
-[ ! -d $TREE ] && die "kernel tree '$TREE' isn't a directory"
-SERIES=$(basename $SERIES)
-[ ! -f $MYDIR/series/$SERIES ] && die "no series file '$SERIES'"
-
-canon $TREE
-TREE=$CANON
-
-# patch scripts wants a relative path from the linux tree to
-# its patch pile :(
-
-MY=$(echo $MYDIR | sed -e 's_^/__')
-TR=$(echo $TREE | sed -e 's_^/__')
-
-while true ; do
- M=$(echo $MY | cut -d/ -f 1)
- T=$(echo $TR | cut -d/ -f 1)
-
- if [ $M != $T ]; then
- break;
- fi
-
- MY=$(echo $MY | cut -d/ -f 2-)
- TR=$(echo $TR | cut -d/ -f 2-)
-done
-
-[ $MY == $MYDIR ] && die "bad! $MY == $MYDIR"
-
-REVERSE=$(revpath $TR)${MY}
-ABSINO=$(stat $MYDIR | awk '($3 == "Inode:") {print $4}')
-REVINO=`(cd $TREE ; stat $REVERSE | awk '($3 == "Inode:") {print $4}')`
-
-[ $ABSINO != $REVINO ] && die "inodes differ, my reverse path is bad?"
-
-echo export PATCHSCRIPTS=$REVERSE
-
-cd $TREE
-ln -sf $REVERSE/series/$SERIES series
-
-PATH_ELEMENTS=$(echo $PATH | sed -e 's/:/ /g')
-
-NEW_PATH=$MYDIR/scripts
-
-for p in $PATH_ELEMENTS; do
- if echo $p | grep kernel_patches/scripts > /dev/null 2>&1 ; then
- continue;
- fi
- NEW_PATH="$NEW_PATH:$p"
-done
-
-echo export PATH=$NEW_PATH
-
-echo "'$TREE' successfully setup" >&2
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-
-do_apply()
-{
- FILES=$(cat $P/pc/$PATCH_NAME.pc)
- for file in $FILES
- do
- copy_file_to_bup $file $PATCH_NAME
- done
-
- silent=-s
- if [ $opt_force != 0 ]
- then
- silent=
- fi
-
- if patch -p1 $silent -i "$1" || [ $opt_force != 0 ]
- then
- true
- else
- echo SOMETHING WENT WRONG
- exit 1
- fi
-}
-
-add_to_db()
-{
- basename "$1" >> "$DB"
-}
-
-usage()
-{
- echo "Usage: apatch patchname"
- exit 1
-}
-
-opt_force=0
-PATCH_NAMES=""
-
-for i in $*
-do
- case "$i" in
- -f)
- opt_force=1;;
- *)
- PATCH_NAMES="$PATCH_NAMES $i"
- esac
-done
-
-if [ x"$PATCH_NAMES" == x ]
-then
- usage
-fi
-
-apatch()
-{
- PATCH_NAME=$(stripit $1)
-
- need_file_there $P/pc/$PATCH_NAME.pc
-
- if is_applied "$PATCH_NAME"
- then
- echo "$PATCH_NAME" is already applied
- exit 1
- fi
-
- if [ $opt_force != 0 ]
- then
- echo FORCING PATCH
- fi
-
- if [ $opt_force != 0 ] || can_apply $P/patches/"$PATCH_NAME".patch
- then
- do_apply $P/patches/"$PATCH_NAME".patch
- add_to_db "$PATCH_NAME"
- echo applied $PATCH_NAME
- echo
- else
- echo "$PATCH_NAME" does not apply
- exit 1
- fi
-}
-
-for i in $PATCH_NAMES
-do
- if ! apatch $i
- then
- exit 1
- fi
-done
-
+++ /dev/null
-DB=applied-patches
-
-#
-# Work out where the user's pc/, patch/ and txt/ directories live.
-#
-# If the user specified PATCHSCRIPTS in environment then use that (it's
-# probably a relative path)
-#
-# If there is a directory ./patch-scripts then use that
-#
-# Otherwise use "."
-#
-
-if [ x$PATCHSCRIPTS != x ]
-then
- P=$PATCHSCRIPTS
-elif [ -d ./patch-scripts ]
-then
- P=./patch-scripts
-elif [ -d ./patches ]
-then
- P=.
-else
- echo "could not locate your pc/ and patches/ directories"
- exit 1
-fi
-
-top_patch()
-{
- tail -1 $DB
-}
-
-die()
-{
- echo error: $*
- exit 1
-}
-
-is_numeric()
-{
- if echo $1 | egrep '^[0-9]*$' > /dev/null
- then
- return 0
- fi
- return 1
-}
-
-is_applied_last()
-{
- name="$(stripit $1)"
- top_patch >$DB.1
- if grep "^$name$" "$DB.1" > /dev/null 2>&1
- then
- rm $DB.1
- return 0
- else
- rm $DB.1
- return 1
- fi
-}
-
-is_applied()
-{
- name=$(stripit "$1")
- if grep "^$name$" "$DB" > /dev/null 2>&1
- then
- return 0
- else
- return 1
- fi
-}
-
-can_apply()
-{
- if patch -p1 --dry-run -i "$1" -f
- then
- return 0
- else
- return 1
- fi
-}
-
-can_remove()
-{
- if patch -R -p1 --dry-run -i $P/patches/"$1".patch -f
- then
- return 0
- else
- return 1
- fi
-}
-
-remove_from_db()
-{
- tmpfile=$(mktemp /tmp/p_XXXXXX)
- name="$1"
- sed -e "/^$name$/d" < "$DB" > $tmpfile
- mv $tmpfile "$DB"
-}
-
-stripit()
-{
- ret=$(basename $1)
- ret=$(echo $ret | sed -e 's/\.patch$//')
- ret=$(echo $ret | sed -e 's/\.pc$//')
- ret=$(echo $ret | sed -e 's/\.txt$//')
- echo $ret
-}
-
-top_is_current()
-{
- patch_name=$(top_patch)
- if [ x$patch_name == x ]
- then
- return 1
- else
- patch_file=$P/patches/"$patch_name".patch
- files=$(cat $P/pc/$patch_name.pc)
- for file in $files
- do
- if [ $file -nt $patch_file ]
- then
- echo $file newer than $patch_file
- return 0
- fi
- done
- fi
- return 1
-}
-
-need_top_current()
-{
- if top_is_current
- then
- echo "Error: Top patch is not up-to-date"
- exit 1
- fi
-}
-
-warn_top_current()
-{
- if top_is_current
- then
- echo "Warning: Top patch is not up-to-date"
- fi
-}
-
-file_in_patch()
-{
- file=$1
- patch=$2
-
- if [ -e $P/pc/$patch.pc ]
- then
- if grep "^"$file"$" $P/pc/$patch.pc > /dev/null
- then
- return 0
- fi
- fi
- return 1
-}
-
-# copy_file_to_bup filename patchname
-copy_file_to_bup()
-{
- file=$1
- patch=$2
- bup="$file"~"$patch"
-
- if [ -e $bup ]
- then
- echo "Cannot install file $file in patch $patch: backup $bup exists"
- exit 1
- fi
-
- if [ -e $file ]
- then
- cp $file "$file"~"$patch"
- else
- echo "file $file appears to be newly added"
- fi
-}
-
-install_file_in_patch()
-{
- file=$1
- patch=$2
-
- copy_file_to_bup $file $patch
- echo $file >> $P/pc/$patch.pc
-# touch $P/txt/$patch.txt
-}
-
-need_file_there()
-{
- if [ ! -e $1 ]
- then
- echo "File $1 does not exist"
- exit 1
- fi
-}
-
-desc()
-{
- state=0
- while read x
- do
- if [ x"$x" = xDESC ]
- then
- state=1
- elif [ x"$x" = xEDESC ]
- then
- state=0
- elif [ $state = 1 ]
- then
- echo " $x"
- fi
- done
-}
-
-body()
-{
- file=$1
-
- did_stuff=0
- while read x
- do
- if [ x"$x" = xEDESC ]
- then
- cat
- did_stuff=1
- fi
- done < $file
-
- if [ $did_stuff = 0 ]
- then
- cat $file
- fi
-}
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: poppatch [npatches]"
- exit 1
-}
-
-doit()
-{
- echo $* 1>&2
- $* || {
- echo oops
- exit 1
- }
-}
-
-if [ $# -gt 1 ]
-then
- usage
-fi
-
-NR=1
-STOP_AT=""
-if [ $# -eq 1 ]
-then
- if is_numeric $1
- then
- NR=$1
- else
- NR=1000
- STOP_AT=$(stripit $1)
- fi
-fi
-
-pop_one()
-{
- TOP_PATCH=$(top_patch)
- if [ x$TOP_PATCH == x ]
- then
- echo "no patches applied"
- exit 0
- else
- popped_patch="$(top_patch)"
- if ! rpatch $(top_patch)
- then
- echo still at $(top_patch)
- exit 1
- fi
- echo
- fi
-}
-
-for i in $(seq 1 $NR)
-do
- pop_one
- if [ x$STOP_AT != "x" ]
- then
- if [ $STOP_AT == $(toppatch) ]
- then
- exit 0
- fi
- fi
-done
+++ /dev/null
-#!/bin/sh
-
-#
-# Add next patch in series
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: pushpatch [npatches]"
- exit 1
-}
-
-opt_force=0
-
-for i in $*
-do
- case "$i" in
- -f)
- opt_force=1;;
- *)
- if [ -n "$NR" -o -n "$STOP_AT" ]
- then
- usage
- fi
- if is_numeric $i
- then
- NR=$i
- else
- NR=1000
- STOP_AT=$(stripit $i)
- fi;;
- esac
-done
-
-[ $opt_force = 1 ] && force="-f"
-
-SERIES=series
-
-if [ ! -e $SERIES ]
-then
- echo 'File "series" not found'
- exit 1
-fi
-
-push_one()
-{
- top=$(toppatch)
- if [ x"$top" == x ]
- then
- todo=$(head -1 $SERIES)
- else
- last_in_series=$(stripit $(tail -1 $SERIES))
- if [ $last_in_series == $top ]
- then
- echo "Series fully applied. Ends at $top"
- exit 0
- fi
- todo=$(grep -C1 "^$top\.patch" $SERIES | tail -1)
- if [ x$todo = x ]
- then
- todo=$(head -1 $SERIES)
- fi
- fi
-
- apatch $force $todo
-}
-
-for i in $(seq 1 $NR)
-do
- push_one
- if [ x$STOP_AT != "x" ]
- then
- if [ $STOP_AT == $(toppatch) ]
- then
- exit 0
- fi
- fi
-done
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: refpatch"
- exit 1
-}
-
-doit()
-{
- echo $* 1>&2
- $* || {
- echo oops
- exit 1
- }
-}
-
-if [ $# != 0 ]
-then
- usage
-fi
-
-TOP_PATCH=$(top_patch)
-mpatch $* $(top_patch)
-echo "Refreshed $TOP_PATCH"
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-do_remove()
-{
- if patch -R -p1 -s -i $P/patches/"$1".patch
- then
- true
- else
- echo SOMETHING WENT WRONG
- exit 1
- fi
-}
-
-kill_old_ones()
-{
- FILES=$(cat $P/pc/$1.pc)
- for file in $FILES
- do
- rm -f "$file"~"$1"
- done
-}
-
-usage()
-{
- echo "Usage: rpatch patchname"
- exit 1
-}
-
-if [ $# == 0 ]
-then
- usage
-fi
-
-PATCH_NAME=$(stripit $1)
-
-warn_top_current
-
-if is_applied "$PATCH_NAME"
-then
- if can_remove "$PATCH_NAME"
- then
- do_remove "$PATCH_NAME"
- kill_old_ones "$PATCH_NAME"
- remove_from_db "$PATCH_NAME"
- else
- echo "$PATCH_NAME" does not remove cleanly
- exit 1
- fi
-else
- echo "$PATCH_NAME" is not applied
- exit 1
-fi
-
-top=$(top_patch)
-if [ x"$top" == x ]
-then
- msg="no patches applied"
-else
- msg="now at $top"
-fi
-
-echo Removed $PATCH_NAME, $msg
-
+++ /dev/null
-dev_read_only.patch
-exports.patch
-kmem_cache_validate.patch
-lustre_version.patch
-vfs_intent.patch
+++ /dev/null
-patch-2.4.18-hp1_pnnl18.2.8qsnet
+++ /dev/null
-lin-2.5.44.patch
+++ /dev/null
-dev_read_only.patch
-exports.patch
-kmem_cache_validate.patch
-lustre_version.patch
-uml_check_get_page.patch
-uml_no_panic.patch
-vfs_intent-2.4.18-18.patch
-uml_compile_fixes.patch
+++ /dev/null
-vanilla-2.4.18
+++ /dev/null
-vanilla-2.4.19
+++ /dev/null
-DESC
-patches for making kernel 2.5.44 ready for mounting Lustre.
-EDESC
+++ /dev/null
-DESC
-(undescribed patch)
-EDESC
+++ /dev/null
-series/rh-8.0:
- redhat 2.4.18-14
- redhat 2.4.18-17
-series/rh-2.4.18-18
- redhat 2.4.18-18
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Helper routines for dumping data structs for debugging.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copryright (C) 2002 Cluster File Systems, Inc.
- *
- */
-
-#define DEBUG_SUBSYSTEM D_OTHER
-
-#include <linux/obd_ost.h>
-#include <linux/lustre_debug.h>
-
-int dump_ioo(struct obd_ioobj *ioo)
-{
- CERROR("obd_ioobj: ioo_id=%Ld, ioo_gr=%Ld, ioo_type=%d, ioo_bufct=%d\n",
- ioo->ioo_id, ioo->ioo_gr, ioo->ioo_type, ioo->ioo_bufcnt);
- return -EINVAL;
-}
-
-int dump_lniobuf(struct niobuf_local *nb)
-{
- CERROR("niobuf_local: addr=%p, offset=%Ld, len=%d, xid=%d, page=%p\n",
- nb->addr, nb->offset, nb->len, nb->xid, nb->page);
- CERROR("nb->page: index = %ld\n", nb->page ? nb->page->index : -1);
-
- return -EINVAL;
-}
-
-int dump_rniobuf(struct niobuf_remote *nb)
-{
- CERROR("niobuf_remote: offset=%Ld, len=%d, flags=%x, xid=%d\n",
- nb->offset, nb->len, nb->flags, nb->xid);
-
- return -EINVAL;
-}
-
-int dump_obdo(struct obdo *oa)
-{
- CERROR("obdo: o_valid = %08x\n", oa->o_valid);
- if (oa->o_valid & OBD_MD_FLID)
- CERROR("obdo: o_id = %Ld\n", oa->o_id);
- if (oa->o_valid & OBD_MD_FLATIME)
- CERROR("obdo: o_atime = %Ld\n", oa->o_atime);
- if (oa->o_valid & OBD_MD_FLMTIME)
- CERROR("obdo: o_mtime = %Ld\n", oa->o_mtime);
- if (oa->o_valid & OBD_MD_FLCTIME)
- CERROR("obdo: o_ctime = %Ld\n", oa->o_ctime);
- if (oa->o_valid & OBD_MD_FLSIZE)
- CERROR("obdo: o_size = %Ld\n", oa->o_size);
- if (oa->o_valid & OBD_MD_FLBLOCKS) /* allocation of space */
- CERROR("obdo: o_blocks = %Ld\n", oa->o_blocks);
- if (oa->o_valid & OBD_MD_FLBLKSZ)
- CERROR("obdo: o_blksize = %d\n", oa->o_blksize);
- if (oa->o_valid & OBD_MD_FLMODE)
- CERROR("obdo: o_mode = %o\n", oa->o_mode);
- if (oa->o_valid & OBD_MD_FLUID)
- CERROR("obdo: o_uid = %d\n", oa->o_uid);
- if (oa->o_valid & OBD_MD_FLGID)
- CERROR("obdo: o_gid = %d\n", oa->o_gid);
- if (oa->o_valid & OBD_MD_FLFLAGS)
- CERROR("obdo: o_flags = %x\n", oa->o_flags);
- if (oa->o_valid & OBD_MD_FLNLINK)
- CERROR("obdo: o_nlink = %d\n", oa->o_nlink);
- if (oa->o_valid & OBD_MD_FLGENER)
- CERROR("obdo: o_generation = %d\n", oa->o_generation);
-
- return -EINVAL;
-}
-
-/* XXX assumes only a single page in request */
-int dump_req(struct ptlrpc_request *req)
-{
- struct ost_body *body = lustre_msg_buf(req->rq_reqmsg, 0);
- struct obd_ioobj *ioo = lustre_msg_buf(req->rq_reqmsg, 1);
- //struct niobuf *nb = lustre_msg_buf(req->rq_reqmsg, 2);
-
- CERROR("ost_body: connid = %d, data = %d\n", body->connid, body->data);
- dump_obdo(&body->oa);
- //dump_niobuf(nb);
- dump_ioo(ioo);
-
- return -EINVAL;
-}
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc. <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (Un)packing of OST/MDS requests
- *
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_net.h>
-#include <linux/obd_support.h>
-
-void obd_statfs_pack(struct obd_statfs *osfs, struct statfs *sfs)
-{
- if (osfs == NULL || sfs == NULL)
- LBUG();
-
- osfs->os_type = HTON__u64(sfs->f_type);
- osfs->os_blocks = HTON__u64(sfs->f_blocks);
- osfs->os_bfree = HTON__u64(sfs->f_bfree);
- osfs->os_bavail = HTON__u64(sfs->f_bavail);
- osfs->os_files = HTON__u64(sfs->f_files);
- osfs->os_ffree = HTON__u64(sfs->f_ffree);
- osfs->os_bsize = HTON__u32(sfs->f_bsize);
- osfs->os_namelen = HTON__u32(sfs->f_namelen);
-}
-
-void obd_statfs_unpack(struct obd_statfs *osfs, struct statfs *sfs)
-{
- if (osfs == NULL || sfs == NULL)
- LBUG();
-
- sfs->f_type = NTOH__u64(osfs->os_type);
- sfs->f_blocks = NTOH__u64(osfs->os_blocks);
- sfs->f_bfree = NTOH__u64(osfs->os_bfree);
- sfs->f_bavail = NTOH__u64(osfs->os_bavail);
- sfs->f_files = NTOH__u64(osfs->os_files);
- sfs->f_ffree = NTOH__u64(osfs->os_ffree);
- sfs->f_bsize = NTOH__u32(osfs->os_bsize);
- sfs->f_namelen = NTOH__u32(osfs->os_namelen);
-}
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc. <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (Un)packing of OST/MDS requests
- *
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_net.h>
-#include <linux/obd_support.h>
-
-void lov_packdesc(struct lov_desc *ld)
-{
- ld->ld_tgt_count = HTON__u32(ld->ld_tgt_count);
- ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
- ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
- ld->ld_pattern = HTON__u32(ld->ld_pattern);
-}
-
-void lov_unpackdesc(struct lov_desc *ld)
-{
- ld->ld_tgt_count = NTOH__u32(ld->ld_tgt_count);
- ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
- ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
- ld->ld_pattern = HTON__u32(ld->ld_pattern);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copyright (C) 2001, Cluster File Systems, Inc.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/obd_support.h>
-#include <linux/lustre_lite.h>
-
-extern struct address_space_operations ll_aops;
-
-void ll_intent_release(struct dentry *de)
-{
- struct ldlm_lock *lock;
- struct lustre_handle *handle;
- ENTRY;
-
- if (de->d_it == NULL) {
- EXIT;
- return;
- }
-
- handle = (struct lustre_handle *)de->d_it->it_lock_handle;
- lock = lustre_handle2object(handle);
- CDEBUG(D_INFO, "calling ldlm_lock_decref(%p, %d)\n", lock,
- de->d_it->it_lock_mode);
- ldlm_lock_decref(lock, de->d_it->it_lock_mode);
- EXIT;
-}
-
-int ll_revalidate2(struct dentry *de, int flags, struct lookup_intent *it)
-{
- ENTRY;
-
- RETURN(0);
-}
-
-
-struct dentry_operations ll_d_ops = {
- d_revalidate2: ll_revalidate2,
- d_intent_release: ll_intent_release
-};
+++ /dev/null
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/kmod.h>
-#include <linux/pagemap.h>
-#include <linux/low-latency.h>
-#include <linux/mm_inline.h>
-#include <asm/unistd.h>
-
-#define DEBUG_SUBSYSTEM S_LLITE
-#include <linux/lustre_lite.h>
-
-/* wakeup every 30s */
-#define LIOD_WAKEUP_CYCLE (30)
-
-/* FIXME tempororily copy from mm_inline.h */
-static inline void __add_page_to_inactive_clean_list(struct page * page)
-{
- struct zone_struct * zone = page_zone(page);
- DEBUG_LRU_PAGE(page);
- SetPageInactiveClean(page);
- list_add(&page->lru, &zone->inactive_clean_list);
- zone->inactive_clean_pages++;
-// nr_inactive_clean_pages++;
-}
-
-static inline void __del_page_from_active_list(struct page * page)
-{
- struct zone_struct * zone = page_zone(page);
- list_del(&page->lru);
- ClearPageActive(page);
-// nr_active_pages--;
- zone->active_pages--;
- DEBUG_LRU_PAGE(page);
-}
-
-static inline void __del_page_from_inactive_dirty_list(struct page * page)
-{
- struct zone_struct * zone = page_zone(page);
- list_del(&page->lru);
- ClearPageInactiveDirty(page);
-// nr_inactive_dirty_pages--;
- zone->inactive_dirty_pages--;
- DEBUG_LRU_PAGE(page);
-}
-
-/* move page into inactive_clean list.
- *
- * caller need to make sure that this page is not used
- * by anyothers
- */
-void refile_clean_page(struct page *page)
-{
- LASSERT(PageLocked(page));
- LASSERT(!PageDirty(page));
-
- ClearPageReferenced(page);
- page->age = 0;
-
- spin_lock(&pagemap_lru_lock);
- if (PageActive(page)) {
- __del_page_from_active_list(page);
- __add_page_to_inactive_clean_list(page);
- } else if (PageInactiveClean(page)) {
- __del_page_from_inactive_dirty_list(page);
- __add_page_to_inactive_clean_list(page);
- }
- spin_unlock(&pagemap_lru_lock);
-}
-
-
-/* return value:
- * -1: no need to flush
- * 0: need async flush
- * 1: need sync flush
- *
- * Note: here we are more sensitive than kswapd, hope we could
- * do more flush work by ourselves, not resort to kswapd
- */
-static inline int balance_dirty_state(void)
-{
- if (free_high(ALL_ZONES) > 0) {
- printk("memory low, sync flush\n");
- return 1;
- }
- if (free_plenty(ALL_ZONES) > 0) {
- printk("memory high, async flush\n");
- return 0;
- }
- else
- return -1;
-}
-
-extern spinlock_t inode_lock;
-
-static int flush_some_pages(struct super_block *sb);
-
-/* the main liod loop */
-static int liod_main(void *arg)
-{
- struct super_block *sb = (struct super_block *)arg;
- struct ll_io_daemon *iod = &ll_s2sbi(sb)->ll_iod;
-
- ENTRY;
-
- lock_kernel();
- daemonize();
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- our_recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-#else
- sigfillset(¤t->blocked);
- our_recalc_sigpending(current);
-#endif
-
- sprintf(current->comm, "liod");
- unlock_kernel();
-
- /* declare we are ready */
- set_bit(LIOD_FLAG_ALIVE, &iod->io_flag);
- wake_up(&iod->io_waitq);
-
- CDEBUG(D_CACHE, "liod(%d) started\n", current->pid);
- while (1) {
- int flushed;
- int t;
- int times;
-
- /* check the stop command */
- if (test_bit(LIOD_FLAG_STOP, &iod->io_flag)) {
- /* at umount time, should not be anyone
- * trying to flushing pages */
- LASSERT(!waitqueue_active(&iod->io_sem.wait));
- break;
- }
-
- t = interruptible_sleep_on_timeout(&iod->io_sleepq,
- LIOD_WAKEUP_CYCLE*HZ);
- CDEBUG(D_NET, "liod(%d) active due to %s\n", current->pid,
- (t ? "wakeup" : "timeout"));
-
- printk("liod(%d) active due to %s\n", current->pid,
- (t ? "wakeup" : "timeout"));
-
- times=0;
- down(&iod->io_sem);
- do {
- flushed = flush_some_pages(sb);
- conditional_schedule();
- printk("iod: loop %d times\n", ++times);
- } while (flushed && (balance_dirty_state() >= 0));
- up(&iod->io_sem);
- }
-
- clear_bit(LIOD_FLAG_ALIVE, &iod->io_flag);
- wake_up(&iod->io_waitq);
-
- CDEBUG(D_NET, "liod(%d) exit\n", current->pid);
- RETURN(0);
-}
-
-int liod_start(struct super_block *sb)
-{
- struct ll_io_daemon *iod = &ll_s2sbi(sb)->ll_iod;
- int rc;
-
- /* initialize */
- iod->io_flag = 0;
- init_waitqueue_head(&iod->io_sleepq);
- init_waitqueue_head(&iod->io_waitq);
- init_MUTEX(&iod->io_sem);
-
- rc = kernel_thread(liod_main, (void *) sb,
- CLONE_VM | CLONE_FS | CLONE_FILES);
-
- if (rc < 0) {
- CERROR("fail to start liod, error %d\n", rc);
- return rc;
- }
-
- /* wait liod start */
- wait_event(iod->io_waitq, test_bit(LIOD_FLAG_ALIVE, &iod->io_flag));
-
- return 0;
-}
-
-static inline void liod_wakeup(struct ll_io_daemon *iod)
-{
- wake_up(&iod->io_sleepq);
-}
-
-static inline void select_one_page(struct brw_page *pg,
- struct inode *inode,
- struct page *page)
-{
- obd_off off;
-
- pg->pg = page;
- pg->off = ((obd_off)page->index) << PAGE_SHIFT;
- pg->flag = OBD_BRW_CREATE;
-
- off = ((obd_off)(page->index + 1)) << PAGE_SHIFT;
- if (off > inode->i_size)
- pg->count = inode->i_size & ~PAGE_MASK;
- else
- pg->count = PAGE_SIZE;
-}
-
-/* select candidate dirty pages within an inode
- * return:
- * - npgs contains number of pages selected
- * - 0: all pages in dirty list are searched
- * 1: probably still have dirty pages
- *
- * don't sleep in this functions
- * */
-static int select_inode_pages(struct inode *inode, struct brw_page *pgs, int *npgs)
-{
- int nrmax = *npgs, nr = 0;
- struct address_space *mapping = inode->i_mapping;
- struct page *page;
- struct list_head *list, *end;
-
- LASSERT(nrmax <= LIOD_FLUSH_NR);
-
- *npgs = 0;
-
- spin_lock(&pagecache_lock);
-
- /* if no dirty pages, just return */
- if (list_empty(&mapping->dirty_pages)) {
- spin_unlock(&pagecache_lock);
- return 0;
- }
-
- list = mapping->dirty_pages.prev;
- end = &mapping->dirty_pages;
- while (nr < nrmax) {
- /* no more dirty pages on this inode */
- if (list == end)
- break;
-
- page = list_entry(list, struct page, list);
- list = list->prev;
-
- /* flush pages only if we could gain the lock */
- if (!TryLockPage(page)) {
- /* remove from dirty list */
- list_del(&page->list);
-
- if (PageDirty(page)) {
- page_cache_get(page);
- /* add to locked list */
- list_add(&page->list, &mapping->locked_pages);
-
- select_one_page(&pgs[nr++], inode, page);
-
- if (nr >= nrmax)
- break;
- } else {
- /* it's quite possible. add to clean list */
- list_add(&page->list, &mapping->clean_pages);
- UnlockPage(page);
- }
- } else {
- if (list == &mapping->dirty_pages)
- break;
-
- /* move to tail */
- list_del(&page->list);
- list_add(&page->list, &mapping->dirty_pages);
- if (end == &mapping->dirty_pages)
- end = &page->list;
- }
- }
- spin_unlock(&pagecache_lock);
-
- *npgs = nr;
-
- if (list == end)
- return 0;
- else
- return 1;
-}
-
-static int bulk_flush_pages(
- struct inode *inode,
- int npgs,
- struct brw_page *pgs,
- struct obd_brw_set *set)
-{
- struct page *page;
- int rc;
-
- set->brw_callback = ll_brw_sync_wait;
- rc = obd_brw(OBD_BRW_WRITE, ll_i2obdconn(inode),
- ll_i2info(inode)->lli_smd, npgs, pgs, set);
- if (rc) {
- CERROR("error from obd_brw: rc = %d\n", rc);
- } else {
- rc = ll_brw_sync_wait(set, CB_PHASE_START);
- if (rc)
- CERROR("error from callback: rc = %d\n", rc);
- }
-
- rc = 0;
-
- while (--npgs >= 0) {
- page = pgs[npgs].pg;
-
- LASSERT(PageLocked(page));
-
- if (!rc) {
- ClearPageDirty(page);
-
- /* move pages to clean list */
- spin_lock(&pagecache_lock);
- list_del(&page->list);
- list_add(&page->list, &inode->i_mapping->clean_pages);
- spin_unlock(&pagecache_lock);
-
- refile_clean_page(page);
- rc++;
- } else {
- SetPageDirty(page);
-
- /* add back to dirty list */
- spin_lock(&pagecache_lock);
- list_del(&page->list);
- list_add(&page->list, &inode->i_mapping->dirty_pages);
- spin_unlock(&pagecache_lock);
- }
- UnlockPage(page);
-
- page_cache_release(page);
- }
-
- spin_lock(&pagecache_lock);
- if (list_empty(&inode->i_mapping->dirty_pages))
- inode->i_state &= ~I_DIRTY_PAGES;
- spin_unlock(&pagecache_lock);
-
- return rc;
-}
-
-/* syncronously flush certain amount of dirty pages right away
- * don't simply call fdatasync(), we need a more efficient way
- * to do flush in bunch mode.
- *
- * return the number of pages were flushed
- *
- * caller should gain the sbi->io_sem lock
- *
- * FIXME now we simply flush pages on at most one inode, probably
- * need add multiple inode flush later.
- */
-static int flush_some_pages(struct super_block *sb)
-{
- struct ll_io_daemon *iod;
- struct brw_page *pgs;
- struct obd_brw_set *set;
- struct list_head *list, *end;
- struct inode *inode;
- int npgs;
-
- iod = &ll_s2sbi(sb)->ll_iod;
- set = &iod->io_set;
- pgs = iod->io_pgs;
-
- /* init set */
- init_waitqueue_head(&set->brw_waitq);
- INIT_LIST_HEAD(&set->brw_desc_head);
- atomic_set(&set->brw_refcount, 0);
-
- {
- int n = 0;
- list = sb->s_dirty.prev;
- while (list != &sb->s_dirty) {
- n++;
- list = list->prev;
- }
- printk("dirty inode length %d\n", n);
- }
-
- /* FIXME simutanously gain inode_lock and pagecache_lock could
- * cause busy spin forever? Check this */
- spin_lock(&inode_lock);
-
- /* sync dirty inodes from tail, since we try to sync
- * from the oldest one */
- npgs = 0;
- list = sb->s_dirty.prev;
- end = &sb->s_dirty;
- while (1) {
- int ret;
-
- /* no dirty inodes left */
- if (list == end)
- break;
-
- inode = list_entry(list, struct inode, i_list);
- list = list->next;
-
- /* if inode is locked, it should be have been moved away
- * from dirty list */
- if (inode->i_state & I_LOCK)
- LBUG();
-
- npgs = LIOD_FLUSH_NR;
- ret = select_inode_pages(inode, pgs, &npgs);
-
- /* quit if found some pages */
- if (npgs) {
- /* if all pages are searched on this inode,
- * we could move it to the list end */
- if (!ret) {
- list_del(&inode->i_list);
- list_add(&inode->i_list, &sb->s_dirty);
- }
- break;
- } else {
- /* no page found, move inode to the end of list */
- if (list == &sb->s_dirty)
- break;
-
- list_del(&inode->i_list);
- list_add(&inode->i_list, &sb->s_dirty);
- if (end == &sb->s_dirty)
- end = &inode->i_list;
- }
- }
- spin_unlock(&inode_lock);
-
- if (npgs)
- printk("got %d pages of inode %lu to flush\n",
- npgs, inode->i_ino);
- else
- printk("didn't found dirty pages\n");
-
- if (!npgs)
- return 0;
-
- if (!inode)
- LBUG();
-
- CDEBUG(D_CACHE, "got %d pages of inode %lu to flush\n",
- npgs, inode->i_ino);
-
- return bulk_flush_pages(inode, npgs, pgs, set);
-}
-
-void ll_balance_dirty_pages(struct super_block *sb)
-{
- int flush;
- struct ll_sb_info *sbi = ll_s2sbi(sb);
-
- flush = balance_dirty_state();
- if (flush < 0)
- return;
-
- if (flush > 0) {
- int n = 0, flush;
-
- if (!down_trylock(&sbi->ll_iod.io_sem)) {
- do {
- flush = flush_some_pages(sb);
- printk("ll_balance_dirty: loop %d times\n", ++n);
- } while (flush && (balance_dirty_state() > 0));
-
- up(&sbi->ll_iod.io_sem);
- }
- }
-
- /* FIXME we need a way to wake up liods on *all* llite fs */
- liod_wakeup(&sbi->ll_iod);
-}
-
-void liod_stop(struct super_block *sb)
-{
- struct ll_io_daemon *iod = &ll_s2sbi(sb)->ll_iod;
-
- if (!test_bit(LIOD_FLAG_ALIVE, &iod->io_flag)) {
- CERROR("liod died unexpectedly!\n");
- return;
- }
-
- /* send the kill command */
- set_bit(LIOD_FLAG_STOP, &iod->io_flag);
-
- /* if wakeup daemon */
- wake_up(&iod->io_sleepq);
-
- /* wait liod exit */
- wait_event(iod->io_waitq, !test_bit(LIOD_FLAG_ALIVE, &iod->io_flag));
-
- return;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-
-int rd_path(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- return 0;
-
-}
-int rd_fstype(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct super_block *sb=(struct super_block*)data;
-
- len+=snprintf(page, count, "%s\n", sb->s_type->name);
- return len;
-}
-int rd_blksize(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct super_block *sb=(struct super_block*)data;
- struct statfs mystats;
- (sb->s_op->statfs)(sb, &mystats);
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_bsize));
- return len;
-
-}
-int rd_blktotal(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct super_block *sb=(struct super_block*)data;
- struct statfs mystats;
- (sb->s_op->statfs)(sb, &mystats);
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_blocks));
- return len;
-
-}
-
-int rd_blkfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct super_block *sb=(struct super_block*)data;
- struct statfs mystats;
- (sb->s_op->statfs)(sb, &mystats);
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_bfree));
- return len;
-
-
-}
-
-int rd_kbfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct super_block *sb=(struct super_block*)data;
- struct statfs mystats;
- long blk_size=0;
-
- (sb->s_op->statfs)(sb, &mystats);
- blk_size=mystats.f_bsize;
-
- len+=snprintf(page, count, LPU64"\n",
- (__u64)((mystats.f_bfree)/(blk_size*1024)));
- return len;
-
-}
-
-int rd_filestotal(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- int len=0;
- struct super_block *sb=(struct super_block*)data;
-
- struct statfs mystats;
-
-
- (sb->s_op->statfs)(sb, &mystats);
-
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_files));
- return len;
-}
-
-int rd_filesfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- int len=0;
- struct super_block *sb=(struct super_block*)data;
-
- struct statfs mystats;
-
-
- (sb->s_op->statfs)(sb, &mystats);
-
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_ffree));
- return len;
-}
-
-int rd_filegroups(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-int rd_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct super_block *sb=(struct super_block*)data;
- struct ll_sb_info *sbi=ll_s2sbi(sb);
- len+=snprintf(page, count, "%s\n", sbi->ll_sb_uuid);
- return len;
-
-}
-int rd_dev_name(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct obd_device* dev=(struct obd_device*)data;
- len+=snprintf(page, count, "%s\n", dev->obd_name);
- return len;
-}
-
-int rd_dev_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct obd_device* dev=(struct obd_device*)data;
- len+=snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-}
-
-
-lprocfs_vars_t status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0},
- {"status/mntpt_path", rd_path, 0},
- {"status/fs_type", rd_fstype, 0},
- {"status/blocksize",rd_blksize, 0},
- {"status/blockstotal",rd_blktotal, 0},
- {"status/blocksfree",rd_blkfree, 0},
- {"status/kbytesfree", rd_kbfree, 0},
- {"status/filestotal", rd_filestotal, 0},
- {"status/filesfree", rd_filesfree, 0},
- {"status/filegroups", rd_filegroups, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Light Super operations
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copryright (C) 1996 Peter J. Braam <braam@stelias.com>
- * Copryright (C) 1999 Stelias Computing Inc. <braam@stelias.com>
- * Copryright (C) 1999 Seagate Technology Inc.
- * Copryright (C) 2001 Mountain View Data, Inc.
- * Copryright (C) 2002 Cluster File Systems, Inc.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_lite.h>
-#include <linux/lustre_ha.h>
-
-void ll_recover(struct ptlrpc_client *cli)
-{
- struct ptlrpc_request *req;
- struct list_head *tmp, *pos;
- ENTRY;
-
- spin_lock(&cli->cli_lock);
- /* first shot at this: resend the request */
- list_for_each_safe(tmp, pos, &cli->cli_sent_head) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
- CDEBUG(D_INODE, "replaying request %p\n", req);
- list_del(&req->rq_list);
- ptlrpc_resend_req(req);
- }
-
- recovd_cli_fixed(cli);
- spin_unlock(&cli->cli_lock);
-
- EXIT;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc. <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (Un)packing of OST/MDS requests
- *
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_net.h>
-#include <linux/obd.h>
-#include <linux/obd_lov.h>
-#include <linux/obd_support.h>
-
-/* lov_packdesc() is in mds/mds_lov.c */
-
-void lov_unpackdesc(struct lov_desc *ld)
-{
- ld->ld_tgt_count = NTOH__u32(ld->ld_tgt_count);
- ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
- ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
- ld->ld_pattern = HTON__u32(ld->ld_pattern);
-}
-
-/* Pack LOV object metadata for shipment to the MDS.
- *
- * XXX In the future, this will be enhanced to get the EA size from the
- * underlying OSC device(s) to get their EA sizes so we can stack
- * LOVs properly. For now lov_mds_md_size() just assumes one obd_id
- * per stripe.
- */
-int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp,
- struct lov_stripe_md *lsm)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct lov_obd *lov = &obd->u.lov;
- struct lov_oinfo *loi;
- struct lov_mds_md *lmm;
- int ost_count = lov->desc.ld_tgt_count;
- int stripe_count = ost_count;
- int lmm_size;
- int i;
- ENTRY;
-
- if (lsm)
- stripe_count = lsm->lsm_stripe_count;
-
- /* XXX LOV STACKING call into osc for sizes */
- lmm_size = lov_mds_md_size(ost_count);
-
- if (!lmmp)
- RETURN(lmm_size);
-
- if (*lmmp && !lsm) {
- /* endianness */
- ost_count = ((*lmmp)->lmm_ost_count);
- OBD_FREE(*lmmp, lov_mds_md_size(ost_count));
- *lmmp = NULL;
- RETURN(0);
- }
-
- if (!*lmmp) {
- OBD_ALLOC(*lmmp, lmm_size);
- if (!*lmmp)
- RETURN(-ENOMEM);
- }
-
- lmm = *lmmp;
-
- lmm->lmm_stripe_count = (stripe_count);
- if (!lsm)
- RETURN(lmm_size);
- /* XXX endianness */
- lmm->lmm_magic = (lsm->lsm_magic);
- lmm->lmm_object_id = (lsm->lsm_object_id);
- lmm->lmm_stripe_size = (lsm->lsm_stripe_size);
- lmm->lmm_stripe_pattern = (lsm->lsm_stripe_pattern);
- lmm->lmm_stripe_offset = (lsm->lsm_stripe_offset);
- lmm->lmm_ost_count = (lov->desc.ld_tgt_count);
-
- /* Only fill in the object ids which we are actually using.
- * Assumes lmm_objects is otherwise zero-filled. */
- for (i = 0, loi = lsm->lsm_oinfo; i < stripe_count; i++, loi++)
- /* XXX call down to osc_packmd() to do the packing */
- lmm->lmm_objects[loi->loi_ost_idx].l_object_id = (loi->loi_id);
-
- RETURN(lmm_size);
-}
-
-int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
- struct lov_mds_md *lmm)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct lov_obd *lov = &obd->u.lov;
- struct lov_stripe_md *lsm;
- struct lov_oinfo *loi;
- int ost_count = lov->desc.ld_active_tgt_count;
- int ost_offset = 0;
- int stripe_count = 0;
- int lsm_size;
- int i;
- ENTRY;
-
- if (lmm)
- /* endianness */
- stripe_count = (lmm->lmm_stripe_count);
-
- if (!stripe_count)
- stripe_count = lov->desc.ld_default_stripe_count;
- if (!stripe_count || stripe_count > ost_count)
- stripe_count = ost_count;
-
- /* XXX LOV STACKING call into osc for sizes */
- lsm_size = lov_stripe_md_size(stripe_count);
-
- if (!lsmp)
- RETURN(lsm_size);
-
- if (*lsmp && !lmm) {
- stripe_count = (*lsmp)->lsm_stripe_count;
- OBD_FREE(*lsmp, lov_stripe_md_size(stripe_count));
- *lsmp = NULL;
- RETURN(0);
- }
-
- if (!*lsmp) {
- OBD_ALLOC(*lsmp, lsm_size);
- if (!*lsmp)
- RETURN(-ENOMEM);
- }
-
- lsm = *lsmp;
-
- lsm->lsm_stripe_count = stripe_count;
- if (!lmm)
- RETURN(lsm_size);
-
- /* XXX endianness */
- ost_offset = lsm->lsm_stripe_offset = (lmm->lmm_stripe_offset);
- lsm->lsm_magic = (lmm->lmm_magic);
- lsm->lsm_object_id = (lmm->lmm_object_id);
- lsm->lsm_stripe_size = (lmm->lmm_stripe_size);
- lsm->lsm_stripe_pattern = (lmm->lmm_stripe_pattern);
-
- for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) {
- ost_offset %= ost_count;
-
- if (!lmm->lmm_objects[ost_offset].l_object_id)
- continue;
-
- LASSERT(loi - lsm->lsm_oinfo < stripe_count);
- /* XXX LOV STACKING call down to osc_unpackmd() */
- loi->loi_id = (lmm->lmm_objects[ost_offset].l_object_id);
- loi->loi_ost_idx = ost_offset;
- loi++;
- }
-
- RETURN(lsm_size);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-/*
- * Common STATUS namespace
- */
-
-int rd_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct obd_device* dev=(struct obd_device*)data;
- len+=snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-
-
-}
-int rd_stripesize(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* dev=(struct obd_device*)data;
- int len=0;
- struct lov_obd* lov=&dev->u.lov;
- len+=snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_default_stripe_size));
-
- return len;
-}
-
-int rd_stripeoffset(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* dev=(struct obd_device*)data;
- int len=0;
- struct lov_obd* lov=&dev->u.lov;
- len+=snprintf(page, count, LPU64"\n",
- lov->desc.ld_default_stripe_offset);
- return len;
-
-}
-
-int rd_stripetype(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* dev=(struct obd_device*)data;
- int len=0;
- struct lov_obd* lov=&dev->u.lov;
- len+=snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_pattern));
- return len;
-
-}
-int rd_stripecount(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* dev=(struct obd_device*)data;
- int len=0;
- struct lov_obd* lov=&dev->u.lov;
- len+=snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_default_stripe_count));
- return len;
-
-}
-int rd_numobd(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* dev=(struct obd_device*)data;
- int len=0;
- struct lov_obd* lov=&dev->u.lov;
- len+=snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_tgt_count));
- return len;
-
-}
-
-int rd_activeobd(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* dev=(struct obd_device*)data;
- int len=0;
- struct lov_obd* lov=&dev->u.lov;
- len+=snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_active_tgt_count));
- return len;
-
-}
-
-int rd_blksize(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-
-int rd_blktotal(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_blkfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_kbfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_numobjects(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_objfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_objgroups(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_target(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* dev=(struct obd_device*)data;
- int len=0, i=0;
- struct lov_obd* lov=&dev->u.lov;
- struct lov_tgt_desc* tgts=lov->tgts;
- while(i<lov->desc.ld_tgt_count){
- len+=snprintf(page, count, "%d: %s\n", i, tgts->uuid);
- i++;
- tgts++;
- }
-
- return len;
-}
-int rd_mdc(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* dev=(struct obd_device*)data;
- int len=0;
- struct lov_obd* lov=&dev->u.lov;
- len+=snprintf(page, count, "%s\n", lov->mdcobd->obd_uuid);
- return len;
-}
-
-lprocfs_vars_t status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0},
- {"status/stripesize",rd_stripesize, 0},
- {"status/stripeoffset",rd_stripeoffset, 0},
- {"status/stripecount",rd_stripecount, 0},
- {"status/stripetype", rd_stripetype, 0},
- {"status/numobd",rd_numobd, 0},
- {"status/activeobd", rd_activeobd, 0},
- {"status/objects", rd_numobjects, 0},
- {"status/objectsfree", rd_objfree, 0},
- {"status/objectgroups", rd_objgroups, 0},
- {"status/blocksize", rd_blksize, 0},
- {"status/blockstotal", rd_blktotal, 0},
- {"status/kbytesfree", rd_kbfree, 0},
- {"status/blocksfree", rd_blkfree, 0},
- {"status/target_obd", rd_target, 0},
- {"status/target_mdc", rd_mdc, 0},
-
- {0}
-};
-int rd_numdevices(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_type* class=(struct obd_type*)data;
- int len=0;
- len+=snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-lprocfs_vars_t status_class_var[]={
- {"status/num_devices", rd_numdevices, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- struct obd_device* temp=(struct obd_device*)data;
- int len=0;
- len+=snprintf(page, count, "%s\n",temp->obd_uuid);
- return len;
-
-
-}
-int rd_blksize(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- return 0;
-
-}
-int rd_kbtotal(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_kbfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-
-int rd_files(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_filesfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_filegroups(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-int rd_conn_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct client_obd* cli=&temp->u.cli;
- struct obd_import* imp=&cli->cl_import;
- int len=0;
- len+=snprintf(page, count, "%s\n",imp->imp_connection->c_remote_uuid);
- return len;
-}
-
-int rd_server_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct client_obd* cli=&temp->u.cli;
- int len=0;
- len+=snprintf(page, count, "%s\n",cli->cl_target_uuid);
- return len;
-}
-
-int rd_server_name(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-
-}
-
-lprocfs_vars_t status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0},
- {"status/blocksize",rd_blksize, 0},
- {"status/kbytestotal",rd_kbtotal, 0},
- {"status/kbytesfree", rd_kbfree, 0},
- {"status/files", rd_files, 0},
- {"status/filesfree", rd_filesfree, 0},
- {"status/filegroups", rd_filegroups, 0},
- {"status/server_uuid", rd_server_uuid, 0},
- {"status/conn_uuid", rd_conn_uuid, 0},
- {0}
-};
-int rd_numdevices(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_type* class=(struct obd_type*)data;
- int len=0;
- len+=snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-lprocfs_vars_t status_class_var[]={
- {"status/num_devices", rd_numdevices, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- int len=0;
- len+=snprintf(page, count, "%s\n", temp->obd_uuid);
- return len;
-}
-int rd_blksize(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct mds_obd *mds=&temp->u.mds;
- struct statfs mystats;
- int rc, len=0;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_bsize));
- return len;
-
-}
-int rd_blktotal(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct mds_obd *mds=&temp->u.mds;
- struct statfs mystats;
- int rc, len=0;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_blocks));
- return len;
-
-}
-
-int rd_blkfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct mds_obd *mds=&temp->u.mds;
- struct statfs mystats;
- int rc, len=0;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_bfree));
- return len;
-
-}
-
-int rd_kbfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct mds_obd *mds=&temp->u.mds;
- struct statfs mystats;
- int rc, blk_size, len=0;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
- blk_size=mystats.f_bsize;
- len+=snprintf(page, count, LPU64"\n",
- (__u64)((mystats.f_bfree)/(blk_size*1024)));
- return len;
-
-}
-
-int rd_fstype(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct mds_obd *mds=&temp->u.mds;
- int len=0;
- len+=snprintf(page, count, "%s\n", mds->mds_fstype);
- return len;
-
-}
-
-int rd_ffiles(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct mds_obd *mds=&temp->u.mds;
- struct statfs mystats;
- int rc, len=0;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
-
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_files));
- return len;
-
-
-}
-
-int rd_inodesfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct mds_obd *mds=&temp->u.mds;
- struct statfs mystats;
- int rc, len=0;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
-
- len+=snprintf(page, count, LPU64"\n", (__u64)(mystats.f_ffree));
- return len;
-}
-
-int rd_filesets(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-lprocfs_vars_t status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0},
- {"status/f_blocksize",rd_blksize, 0},
- {"status/f_blockstotal",rd_blktotal, 0},
- {"status/f_blocksfree",rd_blkfree, 0},
- {"status/f_kbytesfree", rd_kbfree, 0},
- {"status/f_fstype", rd_fstype, 0},
- {"status/f_files", rd_ffiles, 0},
- {"status/f_inodesfree", rd_inodesfree, 0},
- {"status/f_filesets", rd_filesets, 0},
- {0}
-};
-int rd_numdevices(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_type* class=(struct obd_type*)data;
- int len=0;
- len+=snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-lprocfs_vars_t status_class_var[]={
- {"status/num_devices", rd_numdevices, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * linux/mds/mds_fs.c
- *
- * Lustre Metadata Server (MDS) filesystem interface code
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Andreas Dilger <adilger@clusterfs.com>
- *
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/lustre_mds.h>
-
-LIST_HEAD(mds_fs_types);
-
-struct mds_fs_type {
- struct list_head mft_list;
- struct mds_fs_operations *mft_ops;
- char *mft_name;
-};
-
-/* This will be a hash table at some point. */
-static int mds_init_client_data(struct mds_obd *mds)
-{
- INIT_LIST_HEAD(&mds->mds_client_info);
- return 0;
-}
-
-#define MDS_MAX_CLIENTS 1024
-#define MDS_MAX_CLIENT_WORDS (MDS_MAX_CLIENTS / sizeof(unsigned long))
-
-static unsigned long last_rcvd_slots[MDS_MAX_CLIENT_WORDS];
-
-/* Add client data to the MDS. The in-memory storage will be a hash at some
- * point. We use a bitmap to locate a free space in the last_rcvd file if
- * cl_off is -1 (i.e. a new client). Otherwise, we have just read the data
- * from the last_rcvd file and we know its offset.
- */
-int mds_client_add(struct mds_obd *mds, struct mds_client_data *mcd, int cl_off)
-{
- struct mds_client_info *mci;
-
- OBD_ALLOC(mci, sizeof(*mci));
- if (!mci) {
- CERROR("no memory for MDS client info\n");
- RETURN(-ENOMEM);
- }
- INIT_LIST_HEAD(&mci->mci_open_head);
-
- CDEBUG(D_INFO, "client at offset %d with UUID '%s' added\n",
- cl_off, mcd->mcd_uuid);
-
- if (cl_off == -1) {
- unsigned long *word;
- int bit;
-
- repeat:
- word = last_rcvd_slots;
- while(*word == ~0UL)
- ++word;
- if (word - last_rcvd_slots >= MDS_MAX_CLIENT_WORDS) {
- CERROR("no room in client MDS bitmap - fix code\n");
- return -ENOMEM;
- }
- bit = ffz(*word);
- if (test_and_set_bit(bit, word)) {
- CERROR("found bit %d set for word %d - fix code\n",
- bit, word - last_rcvd_slots);
- goto repeat;
- }
- cl_off = word - last_rcvd_slots + bit;
- } else {
- if (test_and_set_bit(cl_off, last_rcvd_slots)) {
- CERROR("bit %d already set in bitmap - bad bad\n",
- cl_off);
- LBUG();
- }
- }
-
- mci->mci_mcd = mcd;
- mci->mci_off = cl_off;
-
- /* For now we just put the clients in a list, not a hashed list */
- list_add_tail(&mci->mci_list, &mds->mds_client_info);
-
- mds->mds_client_count++;
-
- return 0;
-}
-
-void mds_client_del(struct mds_obd *mds, struct mds_client_info *mci)
-{
- unsigned long *word;
- int bit;
-
- word = last_rcvd_slots + mci->mci_off / sizeof(unsigned long);
- bit = mci->mci_off % sizeof(unsigned long);
-
- if (!test_and_clear_bit(bit, word)) {
- CERROR("bit %d already clear in word %d - bad bad\n",
- bit, word - last_rcvd_slots);
- LBUG();
- }
-
- --mds->mds_client_count;
- list_del(&mci->mci_list);
- OBD_FREE(mci->mci_mcd, sizeof(*mci->mci_mcd));
- OBD_FREE(mci, sizeof (*mci));
-}
-
-static int mds_client_free_all(struct mds_obd *mds)
-{
- struct list_head *p, *n;
-
- list_for_each_safe(p, n, &mds->mds_client_info) {
- struct mds_client_info *mci;
-
- mci = list_entry(p, struct mds_client_info, mci_list);
- mds_client_del(mds, mci);
- }
-
- return 0;
-}
-
-static int mds_server_free_data(struct mds_obd *mds)
-{
- OBD_FREE(mds->mds_server_data, sizeof(*mds->mds_server_data));
- mds->mds_server_data = NULL;
-
- return 0;
-}
-
-#define LAST_RCVD "last_rcvd"
-
-static int mds_read_last_rcvd(struct mds_obd *mds, struct file *f)
-{
- struct mds_server_data *msd;
- struct mds_client_data *mcd = NULL;
- loff_t fsize = f->f_dentry->d_inode->i_size;
- loff_t off = 0;
- int cl_off;
- __u64 last_rcvd = 0;
- __u64 last_mount;
- int rc = 0;
-
- OBD_ALLOC(msd, sizeof(*msd));
- if (!msd)
- RETURN(-ENOMEM);
- rc = lustre_fread(f, (char *)msd, sizeof(*msd), &off);
-
- mds->mds_server_data = msd;
- if (rc == 0) {
- CERROR("empty MDS %s, new MDS?\n", LAST_RCVD);
- RETURN(0);
- } else if (rc != sizeof(*msd)) {
- CERROR("error reading MDS %s: rc = %d\n", LAST_RCVD, rc);
- if (rc > 0) {
- rc = -EIO;
- }
- GOTO(err_msd, rc);
- }
-
- /*
- * When we do a clean MDS shutdown, we save the last_rcvd into
- * the header. If we find clients with higher last_rcvd values
- * then those clients may need recovery done.
- */
- last_rcvd = le64_to_cpu(msd->msd_last_rcvd);
- mds->mds_last_rcvd = last_rcvd;
- CDEBUG(D_INODE, "got %Lu for server last_rcvd value\n",
- (unsigned long long)last_rcvd);
-
- last_mount = le64_to_cpu(msd->msd_mount_count);
- mds->mds_mount_count = last_mount;
- CDEBUG(D_INODE, "got %Lu for server last_mount value\n",
- (unsigned long long)last_mount);
-
- for (off = MDS_LR_CLIENT, cl_off = 0, rc = sizeof(*mcd);
- off <= fsize - sizeof(*mcd) && rc == sizeof(*mcd);
- off = MDS_LR_CLIENT + ++cl_off * MDS_LR_SIZE) {
- if (!mcd)
- OBD_ALLOC(mcd, sizeof(*mcd));
- if (!mcd)
- GOTO(err_msd, rc = -ENOMEM);
-
- rc = lustre_fread(f, (char *)mcd, sizeof(*mcd), &off);
- if (rc != sizeof(*mcd)) {
- CERROR("error reading MDS %s offset %d: rc = %d\n",
- LAST_RCVD, cl_off, rc);
- if (rc > 0)
- rc = -EIO;
- break;
- }
-
- last_rcvd = le64_to_cpu(mcd->mcd_last_rcvd);
- last_mount = le64_to_cpu(mcd->mcd_mount_count);
-
- if (last_rcvd &&
- last_mount - mcd->mcd_mount_count < MDS_MOUNT_RECOV) {
- rc = mds_client_add(mds, mcd, cl_off);
- if (rc) {
- rc = 0;
- break;
- }
- mcd = NULL;
- } else {
- CDEBUG(D_INFO,
- "client at offset %d with UUID '%s' ignored\n",
- cl_off, mcd->mcd_uuid);
- }
-
- if (last_rcvd > mds->mds_last_rcvd) {
- CDEBUG(D_OTHER,
- "client at offset %d has last_rcvd = %Lu\n",
- cl_off, (unsigned long long)last_rcvd);
- mds->mds_last_rcvd = last_rcvd;
- }
- }
- CDEBUG(D_INODE, "got %Lu for highest last_rcvd value, %d clients\n",
- (unsigned long long)mds->mds_last_rcvd, mds->mds_client_count);
-
- /* After recovery, there can be no local uncommitted transactions */
- mds->mds_last_committed = mds->mds_last_rcvd;
-
- return 0;
-
-err_msd:
- mds_server_free_data(mds);
- return rc;
-}
-
-static int mds_fs_prep(struct mds_obd *mds)
-{
- struct obd_run_ctxt saved;
- struct dentry *dentry;
- struct file *f;
- int rc;
-
- push_ctxt(&saved, &mds->mds_ctxt);
- dentry = simple_mkdir(current->fs->pwd, "ROOT", 0755);
- if (IS_ERR(dentry)) {
- rc = PTR_ERR(dentry);
- CERROR("cannot create ROOT directory: rc = %d\n", rc);
- GOTO(err_pop, rc);
- }
- /* XXX probably want to hold on to this later... */
- dput(dentry);
- f = filp_open("ROOT", O_RDONLY, 0);
- if (IS_ERR(f)) {
- rc = PTR_ERR(f);
- CERROR("cannot open ROOT: rc = %d\n", rc);
- LBUG();
- GOTO(err_pop, rc);
- }
-
- mds->mds_rootfid.id = f->f_dentry->d_inode->i_ino;
- mds->mds_rootfid.generation = f->f_dentry->d_inode->i_generation;
- mds->mds_rootfid.f_type = S_IFDIR;
-
- rc = filp_close(f, 0);
- if (rc) {
- CERROR("cannot close ROOT: rc = %d\n", rc);
- LBUG();
- }
-
- dentry = simple_mkdir(current->fs->pwd, "FH", 0700);
- if (IS_ERR(dentry)) {
- rc = PTR_ERR(dentry);
- CERROR("cannot create FH directory: rc = %d\n", rc);
- GOTO(err_pop, rc);
- }
- /* XXX probably want to hold on to this later... */
- dput(dentry);
-
- rc = mds_init_client_data(mds);
- if (rc)
- GOTO(err_pop, rc);
-
- f = filp_open(LAST_RCVD, O_RDWR | O_CREAT, 0644);
- if (IS_ERR(f)) {
- rc = PTR_ERR(f);
- CERROR("cannot open/create %s file: rc = %d\n", LAST_RCVD, rc);
- GOTO(err_pop, rc = PTR_ERR(f));
- }
- if (!S_ISREG(f->f_dentry->d_inode->i_mode)) {
- CERROR("%s is not a regular file!: mode = %o\n", LAST_RCVD,
- f->f_dentry->d_inode->i_mode);
- GOTO(err_pop, rc = -ENOENT);
- }
-
- rc = mds_fs_journal_data(mds, f);
- if (rc) {
- CERROR("cannot journal data on %s: rc = %d\n", LAST_RCVD, rc);
- GOTO(err_filp, rc);
- }
-
- rc = mds_read_last_rcvd(mds, f);
- if (rc) {
- CERROR("cannot read %s: rc = %d\n", LAST_RCVD, rc);
- GOTO(err_client, rc);
- }
- mds->mds_rcvd_filp = f;
- pop_ctxt(&saved);
-
- RETURN(0);
-
-err_client:
- mds_client_free_all(mds);
-err_filp:
- if (filp_close(f, 0))
- CERROR("can't close %s after error\n", LAST_RCVD);
-err_pop:
- pop_ctxt(&saved);
-
- return rc;
-}
-
-static struct mds_fs_operations *mds_search_fs_type(const char *name)
-{
- struct list_head *p;
- struct mds_fs_type *type;
-
- /* lock mds_fs_types list */
- list_for_each(p, &mds_fs_types) {
- type = list_entry(p, struct mds_fs_type, mft_list);
- if (!strcmp(type->mft_name, name)) {
- /* unlock mds_fs_types list */
- return type->mft_ops;
- }
- }
- /* unlock mds_fs_types list */
- return NULL;
-}
-
-int mds_register_fs_type(struct mds_fs_operations *ops, const char *name)
-{
- struct mds_fs_operations *found;
- struct mds_fs_type *type;
-
- if ((found = mds_search_fs_type(name))) {
- if (found != ops) {
- CERROR("different operations for type %s\n", name);
- RETURN(-EEXIST);
- }
- return 0;
- }
- OBD_ALLOC(type, sizeof(*type));
- if (!type)
- RETURN(-ENOMEM);
-
- INIT_LIST_HEAD(&type->mft_list);
- type->mft_ops = ops;
- type->mft_name = strdup(name);
- if (!type->mft_name) {
- OBD_FREE(type, sizeof(*type));
- RETURN(-ENOMEM);
- }
- MOD_INC_USE_COUNT;
- list_add(&type->mft_list, &mds_fs_types);
-
- return 0;
-}
-
-void mds_unregister_fs_type(const char *name)
-{
- struct list_head *p;
-
- /* lock mds_fs_types list */
- list_for_each(p, &mds_fs_types) {
- struct mds_fs_type *type;
-
- type = list_entry(p, struct mds_fs_type, mft_list);
- if (!strcmp(type->mft_name, name)) {
- list_del(p);
- kfree(type->mft_name);
- OBD_FREE(type, sizeof(*type));
- MOD_DEC_USE_COUNT;
- break;
- }
- }
- /* unlock mds_fs_types list */
-}
-
-int mds_fs_setup(struct mds_obd *mds, struct vfsmount *mnt)
-{
- struct mds_fs_operations *fs_ops;
- int rc;
-
- if (!(fs_ops = mds_search_fs_type(mds->mds_fstype))) {
- char name[32];
-
- snprintf(name, sizeof(name) - 1, "mds_%s", mds->mds_fstype);
- name[sizeof(name) - 1] = '\0';
-
- if ((rc = request_module(name))) {
- fs_ops = mds_search_fs_type(mds->mds_fstype);
- CDEBUG(D_INFO, "Loaded module '%s'\n", name);
- if (!fs_ops)
- rc = -ENOENT;
- }
-
- if (rc) {
- CERROR("Can't find MDS fs interface '%s'\n", name);
- RETURN(rc);
- }
- }
-
- mds->mds_fsops = fs_ops;
- mds->mds_vfsmnt = mnt;
- mds->mds_ctxt.pwdmnt = mnt;
- mds->mds_ctxt.pwd = mnt->mnt_root;
- mds->mds_ctxt.fs = KERNEL_DS;
-
- /*
- * Replace the client filesystem delete_inode method with our own,
- * so that we can clear the object ID before the inode is deleted.
- * The fs_delete_inode method will call cl_delete_inode for us.
- * We need to do this for the MDS superblock only, hence we install
- * a modified copy of the original superblock method table.
- *
- * We still assume that there is only a single MDS client filesystem
- * type, as we don't have access to the mds struct in delete_inode
- * and store the client delete_inode method in a global table. This
- * will only become a problem if/when multiple MDSs are running on a
- * single host with different underlying filesystems.
- */
- OBD_ALLOC(mds->mds_sop, sizeof(*mds->mds_sop));
- if (!mds->mds_sop)
- RETURN(-ENOMEM);
-
- memcpy(mds->mds_sop, mds->mds_sb->s_op, sizeof(*mds->mds_sop));
- mds->mds_fsops->cl_delete_inode = mds->mds_sop->delete_inode;
- mds->mds_sop->delete_inode = mds->mds_fsops->fs_delete_inode;
- mds->mds_sb->s_op = mds->mds_sop;
-
- rc = mds_fs_prep(mds);
-
- if (rc)
- OBD_FREE(mds->mds_sop, sizeof(*mds->mds_sop));
-
- return rc;
-}
-
-void mds_fs_cleanup(struct mds_obd *mds)
-{
- mds_client_free_all(mds);
- mds_server_free_data(mds);
-
- OBD_FREE(mds->mds_sop, sizeof(*mds->mds_sop));
-}
-
-EXPORT_SYMBOL(mds_register_fs_type);
-EXPORT_SYMBOL(mds_unregister_fs_type);
+++ /dev/null
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_FILTER
-
-#include <linux/fs.h>
-#include <linux/jbd.h>
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/slab.h>
-#include <linux/extN_fs.h>
-#include <linux/extN_jbd.h>
-#include <linux/extN_xattr.h>
-#include <linux/kp30.h>
-#include <linux/lustre_fsfilt.h>
-
-LIST_HEAD(fsfilt_types);
-
-static struct fsfilt_operations *fsfilt_search_type(const char *type)
-{
- struct fsfilt_operations *found;
- struct list_head *p;
-
- list_for_each(p, &fsfilt_types) {
- found = list_entry(p, struct fsfilt_operations, fs_list);
- if (!strcmp(found->fs_type, type)) {
- return found;
- }
- }
- return NULL;
-}
-
-int fsfilt_register_ops(struct fsfilt_operations *fs_ops)
-{
- struct fsfilt_operations *found;
-
- /* lock fsfilt_types list */
- if ((found = fsfilt_search_type(fs_ops->fs_type))) {
- if (found != fs_ops) {
- CERROR("different operations for type %s\n",
- fs_ops->fs_type);
- /* unlock fsfilt_types list */
- RETURN(-EEXIST);
- }
- } else {
- MOD_INC_USE_COUNT;
- list_add(&fs_ops->fs_list, &fsfilt_types);
- }
-
- /* unlock fsfilt_types list */
- return 0;
-}
-
-void fsfilt_unregister_ops(struct fsfilt_operations *fs_ops)
-{
- struct list_head *p;
-
- /* lock fsfilt_types list */
- list_for_each(p, &fsfilt_types) {
- struct fsfilt_operations *found;
-
- found = list_entry(p, typeof(*found), fs_list);
- if (found == fs_ops) {
- list_del(p);
- MOD_DEC_USE_COUNT;
- break;
- }
- }
- /* unlock fsfilt_types list */
-}
-
-struct fsfilt_operations *fsfilt_get_ops(char *type)
-{
- struct fsfilt_operations *fs_ops;
-
- /* lock fsfilt_types list */
- if (!(fs_ops = fsfilt_search_type(type))) {
- char name[32];
- int rc;
-
- snprintf(name, sizeof(name) - 1, "fsfilt_%s", type);
- name[sizeof(name) - 1] = '\0';
-
- if ((rc = request_module(name))) {
- fs_ops = fsfilt_search_type(type);
- CDEBUG(D_INFO, "Loaded module '%s'\n", name);
- if (!fs_ops)
- rc = -ENOENT;
- }
-
- if (rc) {
- CERROR("Can't find fsfilt_%s interface\n", name);
- RETURN(ERR_PTR(rc));
- /* unlock fsfilt_types list */
- }
- }
- __MOD_INC_USE_COUNT(fs_ops->fs_owner);
- /* unlock fsfilt_types list */
-
- return fs_ops;
-}
-
-void fsfilt_put_ops(struct fsfilt_operations *fs_ops)
-{
- __MOD_DEC_USE_COUNT(fs_ops->fs_owner);
-}
-
-
-EXPORT_SYMBOL(fsfilt_register_ops);
-EXPORT_SYMBOL(fsfilt_unregister_ops);
-EXPORT_SYMBOL(fsfilt_get_ops);
-EXPORT_SYMBOL(fsfilt_put_ops);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lustre/lib/fsfilt_ext3.c
- * Lustre filesystem abstraction routines
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Andreas Dilger <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_FILTER
-
-#include <linux/fs.h>
-#include <linux/jbd.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/ext3_fs.h>
-#include <linux/ext3_jbd.h>
-#include <linux/ext3_xattr.h>
-#include <linux/kp30.h>
-#include <linux/lustre_fsfilt.h>
-#include <linux/obd.h>
-#include <linux/module.h>
-
-static kmem_cache_t *fcb_cache;
-static int fcb_cache_count;
-
-struct fsfilt_cb_data {
- struct journal_callback cb_jcb; /* data private to jbd */
- fsfilt_cb_t cb_func; /* MDS/OBD completion function */
- struct obd_device *cb_obd; /* MDS/OBD completion device */
- __u64 cb_last_rcvd; /* MDS/OST last committed operation */
-};
-
-#define EXT3_XATTR_INDEX_LUSTRE 5
-#define XATTR_LUSTRE_MDS_OBJID "system.lustre_mds_objid"
-
-/*
- * We don't currently need any additional blocks for rmdir and
- * unlink transactions because we are storing the OST oa_id inside
- * the inode (which we will be changing anyways as part of this
- * transaction).
- */
-static void *fsfilt_ext3_start(struct inode *inode, int op)
-{
- /* For updates to the last recieved file */
- int nblocks = EXT3_DATA_TRANS_BLOCKS;
- void *handle;
-
- switch(op) {
- case FSFILT_OP_RMDIR:
- case FSFILT_OP_UNLINK:
- nblocks += EXT3_DELETE_TRANS_BLOCKS;
- break;
- case FSFILT_OP_RENAME:
- /* We may be modifying two directories */
- nblocks += EXT3_DATA_TRANS_BLOCKS;
- case FSFILT_OP_SYMLINK:
- /* Possible new block + block bitmap + GDT for long symlink */
- nblocks += 3;
- case FSFILT_OP_CREATE:
- case FSFILT_OP_MKDIR:
- case FSFILT_OP_MKNOD:
- /* New inode + block bitmap + GDT for new file */
- nblocks += 3;
- case FSFILT_OP_LINK:
- /* Change parent directory */
- nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS;
- break;
- case FSFILT_OP_SETATTR:
- /* Setattr on inode */
- nblocks += 1;
- break;
- default: CERROR("unknown transaction start op %d\n", op);
- LBUG();
- }
-
- lock_kernel();
- handle = journal_start(EXT3_JOURNAL(inode), nblocks);
- unlock_kernel();
-
- return handle;
-}
-
-static int fsfilt_ext3_commit(struct inode *inode, void *handle)
-{
- int rc;
-
- lock_kernel();
- rc = journal_stop((handle_t *)handle);
- unlock_kernel();
-
- return rc;
-}
-
-static int fsfilt_ext3_setattr(struct dentry *dentry, void *handle,
- struct iattr *iattr)
-{
- struct inode *inode = dentry->d_inode;
- int rc;
-
- lock_kernel();
- if (inode->i_op->setattr)
- rc = inode->i_op->setattr(dentry, iattr);
- else
- rc = inode_setattr(inode, iattr);
-
- unlock_kernel();
-
- return rc;
-}
-
-static int fsfilt_ext3_set_md(struct inode *inode, void *handle,
- void *lmm, int lmm_size)
-{
- int rc;
-
- down(&inode->i_sem);
- lock_kernel();
- rc = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, lmm, lmm_size, 0);
- unlock_kernel();
- up(&inode->i_sem);
-
- if (rc) {
- CERROR("error adding MD data to inode %lu: rc = %d\n",
- inode->i_ino, rc);
- if (rc != -ENOSPC) LBUG();
- }
- return rc;
-}
-
-static int fsfilt_ext3_get_md(struct inode *inode, void *lmm, int size)
-{
- int rc;
-
- down(&inode->i_sem);
- lock_kernel();
- rc = ext3_xattr_get(inode, EXT3_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, lmm, size);
- unlock_kernel();
- up(&inode->i_sem);
-
- /* This gives us the MD size */
- if (lmm == NULL)
- return (rc == -ENODATA) ? 0 : rc;
-
- if (rc < 0) {
- CDEBUG(D_INFO, "error getting EA %s from inode %lu: "
- "rc = %d\n", XATTR_LUSTRE_MDS_OBJID, inode->i_ino, rc);
- memset(lmm, 0, size);
- return (rc == -ENODATA) ? 0 : rc;
- }
-
- return rc;
-}
-
-static ssize_t fsfilt_ext3_readpage(struct file *file, char *buf, size_t count,
- loff_t *offset)
-{
- struct inode *inode = file->f_dentry->d_inode;
- int rc = 0;
-
- if (S_ISREG(inode->i_mode))
- rc = file->f_op->read(file, buf, count, offset);
- else {
- struct buffer_head *bh;
-
- /* FIXME: this assumes the blocksize == count, but the calling
- * function will detect this as an error for now */
- bh = ext3_bread(NULL, inode,
- *offset >> inode->i_sb->s_blocksize_bits,
- 0, &rc);
-
- if (bh) {
- memcpy(buf, bh->b_data, inode->i_blksize);
- brelse(bh);
- rc = inode->i_blksize;
- }
- }
-
- return rc;
-}
-
-static void fsfilt_ext3_cb_func(struct journal_callback *jcb, int error)
-{
- struct fsfilt_cb_data *fcb = (struct fsfilt_cb_data *)jcb;
-
- fcb->cb_func(fcb->cb_obd, fcb->cb_last_rcvd, error);
-
- kmem_cache_free(fcb_cache, fcb);
- --fcb_cache_count;
-}
-
-static int fsfilt_ext3_set_last_rcvd(struct obd_device *obd, __u64 last_rcvd,
- void *handle, fsfilt_cb_t cb_func)
-{
-#ifdef HAVE_JOURNAL_CALLBACK_STATUS
- struct fsfilt_cb_data *fcb;
-
- fcb = kmem_cache_alloc(fcb_cache, GFP_NOFS);
- if (!fcb)
- RETURN(-ENOMEM);
-
- ++fcb_cache_count;
- fcb->cb_func = cb_func;
- fcb->cb_obd = obd;
- fcb->cb_last_rcvd = last_rcvd;
-
- CDEBUG(D_EXT2, "set callback for last_rcvd: "LPD64"\n", last_rcvd);
- lock_kernel();
- /* Note that an "incompatible pointer" warning here is OK for now */
- journal_callback_set(handle, fsfilt_ext3_cb_func,
- (struct journal_callback *)fcb);
- unlock_kernel();
-#else
-#warning "no journal callback kernel patch, faking it..."
- static long next = 0;
-
- if (time_after(jiffies, next)) {
- CERROR("no journal callback kernel patch, faking it...\n");
- next = jiffies + 300 * HZ;
- }
-
- cb_func(obd, last_rcvd, 0);
-#endif
-
- return 0;
-}
-
-static int fsfilt_ext3_journal_data(struct file *filp)
-{
- struct inode *inode = filp->f_dentry->d_inode;
-
- EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL;
-
- return 0;
-}
-
-/*
- * We need to hack the return value for the free inode counts because
- * the current EA code requires one filesystem block per inode with EAs,
- * so it is possible to run out of blocks before we run out of inodes.
- *
- * This can be removed when the ext3 EA code is fixed.
- */
-static int fsfilt_ext3_statfs(struct super_block *sb, struct statfs *sfs)
-{
- int rc = vfs_statfs(sb, sfs);
-
- if (!rc && sfs->f_bfree < sfs->f_ffree)
- sfs->f_ffree = sfs->f_bfree;
-
- return rc;
-}
-
-static struct fsfilt_operations fsfilt_ext3_ops = {
- fs_type: "ext3",
- fs_owner: THIS_MODULE,
- fs_start: fsfilt_ext3_start,
- fs_commit: fsfilt_ext3_commit,
- fs_setattr: fsfilt_ext3_setattr,
- fs_set_md: fsfilt_ext3_set_md,
- fs_get_md: fsfilt_ext3_get_md,
- fs_readpage: fsfilt_ext3_readpage,
- fs_journal_data: fsfilt_ext3_journal_data,
- fs_set_last_rcvd: fsfilt_ext3_set_last_rcvd,
- fs_statfs: fsfilt_ext3_statfs,
-};
-
-static int __init fsfilt_ext3_init(void)
-{
- int rc;
-
- //rc = ext3_xattr_register();
- fcb_cache = kmem_cache_create("fsfilt_ext3_fcb",
- sizeof(struct fsfilt_cb_data), 0,
- 0, NULL, NULL);
- if (!fcb_cache) {
- CERROR("error allocating fsfilt journal callback cache\n");
- GOTO(out, rc = -ENOMEM);
- }
-
- rc = fsfilt_register_ops(&fsfilt_ext3_fs_ops);
-
- if (rc)
- kmem_cache_destroy(fcb_cache);
-out:
- return rc;
-}
-
-static void __exit fsfilt_ext3_exit(void)
-{
- int rc;
-
- fsfilt_unregister_ops(&fsfilt_ext3_fs_ops);
- rc = kmem_cache_destroy(fcb_cache);
-
- if (rc || fcb_cache_count) {
- CERROR("can't free fsfilt callback cache: count %d, rc = %d\n",
- fcb_cache_count, rc);
- }
-
- //rc = ext3_xattr_unregister();
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre ext3 Filesystem Helper v0.1");
-MODULE_LICENSE("GPL");
-
-module_init(fsfilt_ext3_init);
-module_exit(fsfilt_ext3_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lustre/lib/fsfilt_extN.c
- * Lustre filesystem abstraction routines
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Andreas Dilger <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_FILTER
-
-#include <linux/fs.h>
-#include <linux/jbd.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/quotaops.h>
-#include <linux/extN_fs.h>
-#include <linux/extN_jbd.h>
-#include <linux/extN_xattr.h>
-#include <linux/kp30.h>
-#include <linux/lustre_fsfilt.h>
-#include <linux/obd.h>
-#include <linux/module.h>
-
-static kmem_cache_t *fcb_cache;
-static int fcb_cache_count;
-
-struct fsfilt_cb_data {
- struct journal_callback cb_jcb; /* data private to jbd */
- fsfilt_cb_t cb_func; /* MDS/OBD completion function */
- struct obd_device *cb_obd; /* MDS/OBD completion device */
- __u64 cb_last_rcvd; /* MDS/OST last committed operation */
-};
-
-#define EXTN_XATTR_INDEX_LUSTRE 5
-#define XATTR_LUSTRE_MDS_OBJID "system.lustre_mds_objid"
-
-/*
- * We don't currently need any additional blocks for rmdir and
- * unlink transactions because we are storing the OST oa_id inside
- * the inode (which we will be changing anyways as part of this
- * transaction).
- */
-static void *fsfilt_extN_start(struct inode *inode, int op)
-{
- /* For updates to the last recieved file */
- int nblocks = EXTN_DATA_TRANS_BLOCKS;
- void *handle;
-
- switch(op) {
- case FSFILT_OP_RMDIR:
- case FSFILT_OP_UNLINK:
- nblocks += EXTN_DELETE_TRANS_BLOCKS;
- break;
- case FSFILT_OP_RENAME:
- /* modify additional directory */
- nblocks += EXTN_DATA_TRANS_BLOCKS;
- /* no break */
- case FSFILT_OP_SYMLINK:
- /* additional block + block bitmap + GDT for long symlink */
- nblocks += 3;
- /* no break */
- case FSFILT_OP_CREATE:
- case FSFILT_OP_MKDIR:
- case FSFILT_OP_MKNOD:
- /* modify one inode + block bitmap + GDT */
- nblocks += 3;
- /* no break */
- case FSFILT_OP_LINK:
- /* modify parent directory */
- nblocks += EXTN_INDEX_EXTRA_TRANS_BLOCKS+EXTN_DATA_TRANS_BLOCKS;
- break;
- case FSFILT_OP_SETATTR:
- /* Setattr on inode */
- nblocks += 1;
- break;
- default: CERROR("unknown transaction start op %d\n", op);
- LBUG();
- }
-
- LASSERT(!current->journal_info);
- lock_kernel();
- handle = journal_start(EXTN_JOURNAL(inode), nblocks);
- unlock_kernel();
-
- return handle;
-}
-
-/*
- * Calculate the number of buffer credits needed to write multiple pages in
- * a single extN transaction. No, this shouldn't be here, but as yet extN
- * doesn't have a nice API for calculating this sort of thing in advance.
- *
- * See comment above extN_writepage_trans_blocks for details. We assume
- * no data journaling is being done, but it does allow for all of the pages
- * being non-contiguous. If we are guaranteed contiguous pages we could
- * reduce the number of (d)indirect blocks a lot.
- *
- * With N blocks per page and P pages, for each inode we have at most:
- * N*P indirect
- * min(N*P, blocksize/4 + 1) dindirect blocks
- * niocount tindirect
- *
- * For the entire filesystem, we have at most:
- * min(sum(nindir + P), ngroups) bitmap blocks (from the above)
- * min(sum(nindir + P), gdblocks) group descriptor blocks (from the above)
- * objcount inode blocks
- * 1 superblock
- * 2 * EXTN_SINGLEDATA_TRANS_BLOCKS for the quota files
- */
-static int fsfilt_extN_credits_needed(int objcount, struct fsfilt_objinfo *fso)
-{
- struct super_block *sb = fso->fso_dentry->d_inode->i_sb;
- int blockpp = 1 << (PAGE_CACHE_SHIFT - sb->s_blocksize_bits);
- int addrpp = EXTN_ADDR_PER_BLOCK(sb) * blockpp;
- int nbitmaps = 0;
- int ngdblocks = 0;
- int needed = objcount + 1;
- int i;
-
- for (i = 0; i < objcount; i++, fso++) {
- int nblocks = fso->fso_bufcnt * blockpp;
- int ndindirect = min(nblocks, addrpp + 1);
- int nindir = nblocks + ndindirect + 1;
-
- nbitmaps += nindir + nblocks;
- ngdblocks += nindir + nblocks;
-
- needed += nindir;
- }
-
- /* Assumes extN and extN have same sb_info layout at the start. */
- if (nbitmaps > EXTN_SB(sb)->s_groups_count)
- nbitmaps = EXTN_SB(sb)->s_groups_count;
- if (ngdblocks > EXTN_SB(sb)->s_gdb_count)
- ngdblocks = EXTN_SB(sb)->s_gdb_count;
-
- needed += nbitmaps + ngdblocks;
-
-#ifdef CONFIG_QUOTA
- /* We assume that there will be 1 bit set in s_dquot.flags for each
- * quota file that is active. This is at least true for now.
- */
- needed += hweight32(sb_any_quota_enabled(sb)) *
- EXTN_SINGLEDATA_TRANS_BLOCKS;
-#endif
-
- return needed;
-}
-
-/* We have to start a huge journal transaction here to hold all of the
- * metadata for the pages being written here. This is necessitated by
- * the fact that we do lots of prepare_write operations before we do
- * any of the matching commit_write operations, so even if we split
- * up to use "smaller" transactions none of them could complete until
- * all of them were opened. By having a single journal transaction,
- * we eliminate duplicate reservations for common blocks like the
- * superblock and group descriptors or bitmaps.
- *
- * We will start the transaction here, but each prepare_write will
- * add a refcount to the transaction, and each commit_write will
- * remove a refcount. The transaction will be closed when all of
- * the pages have been written.
- */
-static void *fsfilt_extN_brw_start(int objcount, struct fsfilt_objinfo *fso,
- int niocount, struct niobuf_remote *nb)
-{
- journal_t *journal;
- handle_t *handle;
- int needed;
- ENTRY;
-
- LASSERT(!current->journal_info);
- journal = EXTN_SB(fso->fso_dentry->d_inode->i_sb)->s_journal;
- needed = fsfilt_extN_credits_needed(objcount, fso);
-
- /* The number of blocks we could _possibly_ dirty can very large.
- * We reduce our request if it is absurd (and we couldn't get that
- * many credits for a single handle anyways).
- *
- * At some point we have to limit the size of I/Os sent at one time,
- * increase the size of the journal, or we have to calculate the
- * actual journal requirements more carefully by checking all of
- * the blocks instead of being maximally pessimistic. It remains to
- * be seen if this is a real problem or not.
- */
- if (needed > journal->j_max_transaction_buffers) {
- CERROR("want too many journal credits (%d) using %d instead\n",
- needed, journal->j_max_transaction_buffers);
- needed = journal->j_max_transaction_buffers;
- }
-
- lock_kernel();
- handle = journal_start(journal, needed);
- unlock_kernel();
- if (IS_ERR(handle))
- CERROR("can't get handle for %d credits: rc = %ld\n", needed,
- PTR_ERR(handle));
-
- RETURN(handle);
-}
-
-static int fsfilt_extN_commit(struct inode *inode, void *handle)
-{
- int rc;
-
- lock_kernel();
- rc = journal_stop((handle_t *)handle);
- unlock_kernel();
-
- return rc;
-}
-
-static int fsfilt_extN_setattr(struct dentry *dentry, void *handle,
- struct iattr *iattr)
-{
- struct inode *inode = dentry->d_inode;
- int rc;
-
- lock_kernel();
- if (inode->i_op->setattr)
- rc = inode->i_op->setattr(dentry, iattr);
- else
- rc = inode_setattr(inode, iattr);
-
- unlock_kernel();
-
- return rc;
-}
-
-static int fsfilt_extN_set_md(struct inode *inode, void *handle,
- void *lmm, int lmm_size)
-{
- int rc;
-
- down(&inode->i_sem);
- lock_kernel();
- rc = extN_xattr_set(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, lmm, lmm_size, 0);
- unlock_kernel();
- up(&inode->i_sem);
-
- if (rc) {
- CERROR("error adding MD data to inode %lu: rc = %d\n",
- inode->i_ino, rc);
- if (rc != -ENOSPC) LBUG();
- }
- return rc;
-}
-
-static int fsfilt_extN_get_md(struct inode *inode, void *lmm, int size)
-{
- int rc;
-
- down(&inode->i_sem);
- lock_kernel();
- rc = extN_xattr_get(inode, EXTN_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, lmm, size);
- unlock_kernel();
- up(&inode->i_sem);
-
- /* This gives us the MD size */
- if (lmm == NULL)
- return (rc == -ENODATA) ? 0 : rc;
-
- if (rc < 0) {
- CDEBUG(D_INFO, "error getting EA %s from inode %lu: "
- "rc = %d\n", XATTR_LUSTRE_MDS_OBJID, inode->i_ino, rc);
- memset(lmm, 0, size);
- return (rc == -ENODATA) ? 0 : rc;
- }
-
- return rc;
-}
-
-static ssize_t fsfilt_extN_readpage(struct file *file, char *buf, size_t count,
- loff_t *offset)
-{
- struct inode *inode = file->f_dentry->d_inode;
- int rc = 0;
-
- if (S_ISREG(inode->i_mode))
- rc = file->f_op->read(file, buf, count, offset);
- else {
- struct buffer_head *bh;
-
- /* FIXME: this assumes the blocksize == count, but the calling
- * function will detect this as an error for now */
- bh = extN_bread(NULL, inode,
- *offset >> inode->i_sb->s_blocksize_bits,
- 0, &rc);
-
- if (bh) {
- memcpy(buf, bh->b_data, inode->i_blksize);
- brelse(bh);
- rc = inode->i_blksize;
- }
- }
-
- return rc;
-}
-
-static void fsfilt_extN_cb_func(struct journal_callback *jcb, int error)
-{
- struct fsfilt_cb_data *fcb = (struct fsfilt_cb_data *)jcb;
-
- fcb->cb_func(fcb->cb_obd, fcb->cb_last_rcvd, error);
-
- kmem_cache_free(fcb_cache, fcb);
- --fcb_cache_count;
-}
-
-static int fsfilt_extN_set_last_rcvd(struct obd_device *obd, __u64 last_rcvd,
- void *handle, fsfilt_cb_t cb_func)
-{
-#ifdef HAVE_JOURNAL_CALLBACK_STATUS
- struct fsfilt_cb_data *fcb;
-
- fcb = kmem_cache_alloc(fcb_cache, GFP_NOFS);
- if (!fcb)
- RETURN(-ENOMEM);
-
- ++fcb_cache_count;
- fcb->cb_func = cb_func;
- fcb->cb_obd = obd;
- fcb->cb_last_rcvd = last_rcvd;
-
- CDEBUG(D_EXT2, "set callback for last_rcvd: "LPD64"\n", last_rcvd);
- lock_kernel();
- /* Note that an "incompatible pointer" warning here is OK for now */
- journal_callback_set(handle, fsfilt_extN_cb_func,
- (struct journal_callback *)fcb);
- unlock_kernel();
-#else
-#warning "no journal callback kernel patch, faking it..."
- static long next = 0;
-
- if (time_after(jiffies, next)) {
- CERROR("no journal callback kernel patch, faking it...\n");
- next = jiffies + 300 * HZ;
- }
-
- cb_func(obd, last_rcvd, 0);
-#endif
-
- return 0;
-}
-
-static int fsfilt_extN_journal_data(struct file *filp)
-{
- struct inode *inode = filp->f_dentry->d_inode;
-
- EXTN_I(inode)->i_flags |= EXTN_JOURNAL_DATA_FL;
-
- return 0;
-}
-
-/*
- * We need to hack the return value for the free inode counts because
- * the current EA code requires one filesystem block per inode with EAs,
- * so it is possible to run out of blocks before we run out of inodes.
- *
- * This can be removed when the extN EA code is fixed.
- */
-static int fsfilt_extN_statfs(struct super_block *sb, struct obd_statfs *osfs)
-{
- struct statfs sfs;
- int rc = vfs_statfs(sb, &sfs);
-
- if (!rc && sfs.f_bfree < sfs.f_ffree)
- sfs.f_ffree = sfs.f_bfree;
-
- statfs_pack(osfs, &sfs);
- return rc;
-}
-
-static struct fsfilt_operations fsfilt_extN_ops = {
- fs_type: "extN",
- fs_owner: THIS_MODULE,
- fs_start: fsfilt_extN_start,
- fs_brw_start: fsfilt_extN_brw_start,
- fs_commit: fsfilt_extN_commit,
- fs_setattr: fsfilt_extN_setattr,
- fs_set_md: fsfilt_extN_set_md,
- fs_get_md: fsfilt_extN_get_md,
- fs_readpage: fsfilt_extN_readpage,
- fs_journal_data: fsfilt_extN_journal_data,
- fs_set_last_rcvd: fsfilt_extN_set_last_rcvd,
- fs_statfs: fsfilt_extN_statfs,
-};
-
-static int __init fsfilt_extN_init(void)
-{
- int rc;
-
- //rc = extN_xattr_register();
- fcb_cache = kmem_cache_create("fsfilt_extN_fcb",
- sizeof(struct fsfilt_cb_data), 0,
- 0, NULL, NULL);
- if (!fcb_cache) {
- CERROR("error allocating fsfilt journal callback cache\n");
- GOTO(out, rc = -ENOMEM);
- }
-
- rc = fsfilt_register_ops(&fsfilt_extN_ops);
-
- if (rc)
- kmem_cache_destroy(fcb_cache);
-out:
- return rc;
-}
-
-static void __exit fsfilt_extN_exit(void)
-{
- int rc;
-
- fsfilt_unregister_ops(&fsfilt_extN_ops);
- rc = kmem_cache_destroy(fcb_cache);
-
- if (rc || fcb_cache_count) {
- CERROR("can't free fsfilt callback cache: count %d, rc = %d\n",
- fcb_cache_count, rc);
- }
-
- //rc = extN_xattr_unregister();
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre extN Filesystem Helper v0.1");
-MODULE_LICENSE("GPL");
-
-module_init(fsfilt_extN_init);
-module_exit(fsfilt_extN_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define EXPORT_SYMTAB
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-#define DEBUG_SUBSYSTEM S_CLASS
-#define MAX_STRING_SIZE 100
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-#ifdef LPROC_SNMP
-
-#define DEFAULT_MODE 0444
-/*
- * Tokenizer array. Change this array to include special
- * characters for string tokenizing
- */
-char tok[] = {'/', (char)0};
-
-
-
-/*
- * Externs
- */
-extern struct proc_dir_entry proc_root; /* Defined in proc/root.c */
-
-/*
- * Globals
- */
-struct proc_dir_entry *proc_lustre_root = 0;
-struct proc_dir_entry *proc_lustre_dev_root = 0;
-struct proc_dir_entry *proc_lustre_fs_root=0;
-
-struct proc_dir_entry* lprocfs_mkdir(const char* dname,
- struct proc_dir_entry *parent)
-{
- struct proc_dir_entry *child_dir_entry;
-
- child_dir_entry = proc_mkdir(dname, parent);
-
- if (!child_dir_entry)
- CERROR("lustre: failed to create /proc entry %s\n", dname);
-
- return child_dir_entry;
-}
-struct proc_dir_entry* lprocfs_srch(struct proc_dir_entry* head,
- const char* name)
-{
- struct proc_dir_entry* temp;
-
- if (!head)
- return 0;
- temp = head->subdir;
- while (temp != NULL) {
- if (!strcmp(temp->name, name))
- return temp;
- temp = temp->next;
- }
-
- return 0;
-}
-
-
-void lprocfs_remove_all(struct proc_dir_entry* root)
-{
-
- struct proc_dir_entry *temp=root;
- struct proc_dir_entry* rm_entry;
-
- while(1){
-
- while(temp->subdir){
- temp=temp->subdir;
- }
- rm_entry=temp;
- temp=temp->parent;
- remove_proc_entry(rm_entry->name, rm_entry->parent);
- if(temp==root->parent) break;
-
- }
-
-
-}
-
-struct proc_dir_entry* lprocfs_new_dir(struct proc_dir_entry* root,
- const char* string,
- const char* tok)
-{
- struct proc_dir_entry* new_root = 0;
- struct proc_dir_entry* temp_entry = 0;
-
- char temp_string[MAX_STRING_SIZE];
- char* my_str;
- char* mover_str;
-
- /*
- * Remove trailing escaping character
- */
- memset(temp_string, 0, MAX_STRING_SIZE);
- if (strlen(string) >= MAX_STRING_SIZE) {
- CDEBUG(D_OTHER, "Directory namespace too long");
- return 0;
- }
-
- strcpy(temp_string, string);
- temp_string[strlen(string) + 1] = '\0';
-
- new_root=root;
- mover_str=temp_string;
- while ((my_str = strsep(&mover_str, tok))) {
- if(!*my_str)
- continue;
- CDEBUG(D_OTHER, "SEARCH= %s\t, ROOT=%s\n", my_str,
- new_root->name);
- temp_entry = lprocfs_srch(new_root, my_str);
- if (temp_entry == 0) {
- CDEBUG(D_OTHER, "Adding: %s\n", my_str);
- temp_entry = lprocfs_mkdir(my_str, new_root);
- if (temp_entry == 0) {
- CDEBUG(D_OTHER,
- "! Did not create new dir %s !!\n",
- my_str);
- return 0;
- }
- }
- new_root = temp_entry;
- }
-
- return new_root;
-}
-
-int lprocfs_new_vars(struct proc_dir_entry* root,
- lprocfs_vars_t* list,
- const char* tok,
- void* data)
-{
- struct proc_dir_entry* temp_root=0;
- struct proc_dir_entry* new_leaf=0;
- struct proc_dir_entry* new_parent=0;
- char temp_string[MAX_STRING_SIZE];
-
- if(!list)
- return 0;
-
- while(list->name){
- temp_root=lprocfs_new_dir(root, list->name, tok);
-
- if(!temp_root){
- CDEBUG(D_OTHER, "!LProcFS: Mods: No root!");
- return -EINVAL;
- }
- /* Convert the last element into a leaf-node */
- memset(temp_string, 0, MAX_STRING_SIZE);
- strcpy(temp_string, temp_root->name);
- temp_string[strlen(temp_root->name) + 1] = '\0';
- new_parent=temp_root->parent;
- if (new_parent != 0){
- remove_proc_entry(temp_root->name, new_parent);
- } else {
- remove_proc_entry(temp_root->name, NULL);
- }
- new_leaf = create_proc_entry(temp_string, DEFAULT_MODE,
- new_parent);
- new_leaf->read_proc = list->read_fptr;
- new_leaf->write_proc = list->write_fptr;
- new_leaf->data=data;
- list++;
- }
- return 0;
-
-}
-
-/*
- * API implementations
- */
-
-int lprocfs_add_vars(struct proc_dir_entry* root,
- lprocfs_vars_t* var,
- void* data)
-{
-
- return lprocfs_new_vars(root, var,
- (const char*) tok, data);
-
-
-}
-
-int lprocfs_reg_obd(struct obd_device* device,
- lprocfs_vars_t* list,
- void* data)
-{
-
- int retval = 0;
- struct proc_dir_entry* this_dev_root=0;
-
- /* Obtain this device root */
- this_dev_root = lprocfs_mkdir(device->obd_name,
- device->obd_type->typ_procroot);
-
- device->obd_proc_entry=this_dev_root;
- retval=lprocfs_add_vars(this_dev_root, list,
- data);
-
- return retval;
-}
-
-int lprocfs_dereg_obd(struct obd_device* device)
-{
-
- CDEBUG(D_OTHER, "LPROCFS removing device = %s\n", device->obd_name);
-
- if (!device) {
- CDEBUG(D_OTHER, "! LProcfs: Null pointer !\n");
- return 0;
- }
-
- lprocfs_remove_all(device->obd_proc_entry);
-
- if (device->counters)
- OBD_FREE(device->counters, device->cntr_mem_size);
-
- return 0;
-}
-
-struct proc_dir_entry* lprocfs_reg_mnt(char* mnt_name)
-{
- return lprocfs_mkdir(mnt_name, proc_lustre_fs_root);
-
-}
-
-int lprocfs_dereg_mnt(struct proc_dir_entry* root)
-{
- lprocfs_remove_all(root);
- return 0;
-
-}
-
-int lprocfs_reg_class(struct obd_type* type,
- lprocfs_vars_t* list,
- void* data)
-{
- struct proc_dir_entry* root;
- int retval;
-
- root=lprocfs_mkdir(type->typ_name, proc_lustre_dev_root);
-
- type->typ_procroot=root;
-
- retval=lprocfs_add_vars(root, list, data);
-
- return retval;
-}
-
-int lprocfs_dereg_class(struct obd_type* class)
-{
- if(!class){
- CDEBUG(D_OTHER, "Non-existent class",
- class->typ_name);
- return 0;
- }
-
- lprocfs_remove_all(class->typ_procroot);
-
- CDEBUG(D_OTHER, "LPROCFS removed = %s\n", class->typ_name);
-
- return 0;
-
-}
-int lprocfs_reg_main()
-{
- proc_lustre_root = lprocfs_mkdir("lustre", &proc_root);
- if (!proc_lustre_root) {
- CERROR(" !! Cannot create /proc/lustre !! \n");
- return -EINVAL;
- }
-
- proc_lustre_dev_root =lprocfs_mkdir("devices", proc_lustre_root);
-
- if (!proc_lustre_dev_root) {
- CERROR(" !! Cannot create /proc/lustre/devices !! \n");
- return -EINVAL;
- }
- proc_lustre_fs_root=lprocfs_mkdir("mnt_pnt", proc_lustre_root);
-
- if (!proc_lustre_fs_root) {
- CERROR(" !! Cannot create /proc/lustre/mnt_pnt !! \n");
- return -EINVAL;
- }
-
- return 0;
-
-}
-
-int lprocfs_dereg_main()
-{
- lprocfs_remove_all(proc_lustre_root);
- proc_lustre_root=0;
- proc_lustre_dev_root=0;
- proc_lustre_fs_root=0;
- return 0;
-
-}
-
-
-/*
- * Needs to go...
- */
-
-int lprocfs_ll_rd(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- __u64 *temp = (__u64 *)data;
- int len;
-
- len = snprintf(page, count, LPU64"\n", *temp);
-
- return len;
-}
-
-#endif /* LPROC_SNMP */
-
-
-EXPORT_SYMBOL(lprocfs_reg_obd);
-EXPORT_SYMBOL(lprocfs_dereg_obd);
-EXPORT_SYMBOL(lprocfs_reg_main);
-EXPORT_SYMBOL(lprocfs_dereg_main);
-EXPORT_SYMBOL(lprocfs_reg_mnt);
-EXPORT_SYMBOL(lprocfs_dereg_mnt);
-EXPORT_SYMBOL(lprocfs_add_vars);
-EXPORT_SYMBOL(lprocfs_reg_class);
-EXPORT_SYMBOL(lprocfs_dereg_class);
-EXPORT_SYMBOL(lprocfs_ll_rd);
-
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-
-#define DEBUG_SUBSYSTEM S_ECHO
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/obd_echo.h>
-#include <linux/lustre_debug.h>
-#include <linux/lprocfs_status.h>
-
-static int echo_iocontrol(long cmd, struct lustre_handle *obdconn, int len,
- void *karg, void *uarg)
-{
- struct obd_device *obd = class_conn2obd(obdconn);
- struct echo_client_obd *ec = &obd->u.echo_client;
- struct obd_ioctl_data *data = karg;
- int rw = OBD_BRW_READ, rc = 0;
- ENTRY;
-
- if (obd == NULL) {
- CERROR("ioctl: No device\n");
- GOTO(out, rc = -EINVAL);
- }
-
- switch (cmd) {
- case OBD_IOC_CREATE: {
- struct lov_stripe_md *lsm = NULL;
-#warning FIXME: save lsm into file handle for other ops, release on close
- rc = obd_create(&ec->conn, &data->ioc_obdo1, &lsm);
- GOTO(out, rc);
- }
-
- case OBD_IOC_GETATTR:
- rc = obd_getattr(&ec->conn, &data->ioc_obdo1, NULL);
- GOTO(out, rc);
-
- case OBD_IOC_SETATTR:
- rc = obd_setattr(&ec->conn, &data->ioc_obdo1, NULL);
- GOTO(out, rc);
-
- case OBD_IOC_DESTROY: {
- //void *ea;
- rc = obd_destroy(&ec->conn, &data->ioc_obdo1, NULL);
- GOTO(out, rc);
- }
-
- case OBD_IOC_OPEN: {
- struct lov_stripe_md *lsm = NULL; // XXX fill in from create
-
- rc = obd_open(&ec->conn, &data->ioc_obdo1, lsm);
- GOTO(out, rc);
- }
-
- case OBD_IOC_CLOSE: {
- struct lov_stripe_md *lsm = NULL; // XXX fill in from create
-
- rc = obd_close(&ec->conn, &data->ioc_obdo1, lsm);
- GOTO(out, rc);
- }
-
- case OBD_IOC_BRW_WRITE:
- rw = OBD_BRW_WRITE;
- case OBD_IOC_BRW_READ: {
- struct lov_stripe_md tmp_lsm; // XXX fill in from create
- struct lov_stripe_md *lsm = &tmp_lsm; // XXX fill in from create
- struct obd_brw_set *set;
- obd_count pages = 0;
- struct brw_page *pga, *pgp;
- __u64 id = data->ioc_obdo1.o_id;
- int gfp_mask = (id & 1) ? GFP_HIGHUSER : GFP_KERNEL;
- int verify = (id != 0);
- __u64 off;
- int j;
-
- set = obd_brw_set_new();
- if (set == NULL)
- GOTO(out, rc = -ENOMEM);
-
- pages = data->ioc_count / PAGE_SIZE;
- off = data->ioc_offset;
-
- CDEBUG(D_INODE, "BRW %s with %d pages @ "LPX64"\n",
- rw == OBD_BRW_READ ? "read" : "write", pages, off);
- OBD_ALLOC(pga, pages * sizeof(*pga));
- if (!pga) {
- CERROR("no memory for %d BRW per-page data\n", pages);
- GOTO(brw_free, rc = -ENOMEM);
- }
-
- memset(lsm, 0, sizeof(*lsm)); // XXX don't do this later
- lsm->lsm_object_id = id; // ensure id == lsm->lsm_object_id
-
- for (j = 0, pgp = pga; j < pages; j++, off += PAGE_SIZE, pgp++){
- pgp->pg = alloc_pages(gfp_mask, 0);
- if (!pgp->pg) {
- CERROR("no memory for brw pages\n");
- GOTO(brw_cleanup, rc = -ENOMEM);
- }
- pgp->count = PAGE_SIZE;
- pgp->off = off;
- pgp->flag = 0;
-
- if (verify) {
- void *addr = kmap(pgp->pg);
-
- if (rw == OBD_BRW_WRITE)
- page_debug_setup(addr, pgp->count,
- pgp->off, id);
- else
- page_debug_setup(addr, pgp->count,
- 0xdeadbeef00c0ffee,
- 0xdeadbeef00c0ffee);
- kunmap(pgp->pg);
- }
- }
-
- set->brw_callback = ll_brw_sync_wait;
- rc = obd_brw(rw, &ec->conn, lsm, j, pga, set);
- if (rc)
- CERROR("test_brw: error from obd_brw: rc = %d\n", rc);
- else {
- rc = ll_brw_sync_wait(set, CB_PHASE_START);
- if (rc)
- CERROR("test_brw: error from callback: rc = "
- "%d\n", rc);
- }
- EXIT;
- brw_cleanup:
- for (j = 0, pgp = pga; j < pages; j++, pgp++) {
- if (pgp->pg == NULL)
- continue;
-
- if (verify && !rc) {
- void *addr = kmap(pgp->pg);
-
- rc = page_debug_check("test_brw", addr,
- PAGE_SIZE, pgp->off, id);
- kunmap(pgp->pg);
- }
- __free_pages(pgp->pg, 0);
- }
- brw_free:
- obd_brw_set_free(set);
- OBD_FREE(pga, pages * sizeof(*pga));
- GOTO(out, rc);
- }
- default:
- return -ENOTTY;
- }
-
- out:
- RETURN(rc);
-}
-
-static int echo_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- struct obd_ioctl_data* data = buf;
- struct echo_client_obd *ec = &obddev->u.echo_client;
- struct obd_device *tgt;
- int rc;
- ENTRY;
-
- if (data->ioc_inllen1 < 1) {
- CERROR("requires a TARGET OBD UUID\n");
- RETURN(-EINVAL);
- }
- if (data->ioc_inllen1 > 37) {
- CERROR("OBD UUID must be less than 38 characters\n");
- RETURN(-EINVAL);
- }
-
- MOD_INC_USE_COUNT;
- tgt = class_uuid2obd(data->ioc_inlbuf1);
- if (!tgt || !(tgt->obd_flags & OBD_ATTACHED) ||
- !(tgt->obd_flags & OBD_SET_UP)) {
- CERROR("device not attached or not set up (%d)\n",
- data->ioc_dev);
- GOTO(error_dec, rc = -EINVAL);
- }
-
- rc = obd_connect(&ec->conn, tgt, NULL, NULL, NULL);
- if (rc) {
- CERROR("fail to connect to device %d\n", data->ioc_dev);
- GOTO(error_dec, rc = -EINVAL);
- }
- RETURN(rc);
-error_dec:
- MOD_DEC_USE_COUNT;
- RETURN(rc);
-}
-
-static int echo_cleanup(struct obd_device * obddev)
-{
- struct echo_client_obd *ec = &obddev->u.echo_client;
- int rc;
- ENTRY;
-
- if (!list_empty(&obddev->obd_exports)) {
- CERROR("still has clients!\n");
- RETURN(-EBUSY);
- }
-
- rc = obd_disconnect(&ec->conn);
- if (rc) {
- CERROR("fail to disconnect device: %d\n", rc);
- RETURN(-EINVAL);
- }
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-static int echo_connect(struct lustre_handle *conn, struct obd_device *src,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- return class_connect(conn, src, cluuid);
-}
-
-static struct obd_ops echo_obd_ops = {
- o_setup: echo_setup,
- o_cleanup: echo_cleanup,
- o_iocontrol: echo_iocontrol,
- o_connect: echo_connect,
- o_disconnect: class_disconnect
-};
-
-int echo_client_init(void)
-{
- extern struct lprocfs_vars status_class_var[];
-
- return class_register_type(&echo_obd_ops, status_class_var,
- OBD_ECHO_CLIENT_DEVICENAME);
-}
-
-void echo_client_cleanup(void)
-{
- class_unregister_type(OBD_ECHO_CLIENT_DEVICENAME);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_ECHO
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct obd_device* dev=(struct obd_device*)data;
- len+=snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-
-}
-
-int rd_fstype(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct obd_device* dev=(struct obd_device*)data;
- len+=snprintf(page, count, "%s\n", dev->u.echo.eo_fstype);
- return len;
-
-}
-
-
-lprocfs_vars_t status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0},
- {"status/fstype", rd_fstype, 0},
- {0}
-};
-
-int rd_numdevices(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_type* class=(struct obd_type*)data;
- int len=0;
- len+=snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-lprocfs_vars_t status_class_var[]={
- {"status/num_devices", rd_numdevices, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct obd_device* dev=(struct obd_device*)data;
- len+=snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-
-
-
-}
-int rd_blksize(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct statfs mystats;
-
- int len=0;
-
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
-
- len+=snprintf(page, count, "%ld\n", mystats.f_bsize);
- return len;
-
-
-}
-int rd_kbtotal(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct statfs mystats;
- int len=0;
- __u64 result;
-
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
-
- result=((__u64)(mystats.f_blocks*mystats.f_bsize))>>10;
-
- len+=snprintf(page, count, LPU64"\n", result);
-
- return len;
-}
-
-int rd_kbfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct statfs mystats;
-
- int len=0;
- __u64 result;
-
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
- result=((__u64)(mystats.f_bfree*mystats.f_bsize))>>10;
-
- len+=snprintf(page, count, LPU64"\n", result);
- return len;
-}
-
-int rd_fstype(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- struct obd_device* temp=(struct obd_device*)data;
- int len=0;
-
- len+=snprintf(page, count, "%s\n", temp->u.filter.fo_fstype);
- return len;
-
-}
-int rd_files(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- struct obd_device* temp=(struct obd_device*)data;
- struct statfs mystats;
-
- int len=0;
-
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
-
- len+=snprintf(page, count, "%ld\n", mystats.f_files);
- return len;
-}
-
-int rd_filesfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct statfs mystats;
-
- int len=0;
-
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
-
- len+=snprintf(page, count, "%ld\n", mystats.f_ffree);
- return len;
-
-
-}
-
-lprocfs_vars_t status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0},
- {"status/blocksize",rd_blksize, 0},
- {"status/kbytestotal",rd_kbtotal, 0},
- {"status/kbytesfree", rd_kbfree, 0},
- {"status/files", rd_files, 0},
- {"status/filesfree", rd_filesfree, 0},
- {"status/fstype", rd_fstype, 0},
- {0}
-};
-int rd_numdevices(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_type* class=(struct obd_type*)data;
- int len=0;
- len+=snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-lprocfs_vars_t status_class_var[]={
- {"status/num_devices", rd_numdevices, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-int rd_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- struct obd_device* dev=(struct obd_device*)data;
- len+=snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-
-}
-int rd_blksize(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-int rd_blktotal(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_blkfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_kbfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_numobjects(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_objfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-int rd_objgroups(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-int rd_server_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- struct obd_device* temp=(struct obd_device*)data;
- struct client_obd* cli=&temp->u.cli;
- int len=0;
- len+=snprintf(page, count, "%s\n",cli->cl_target_uuid);
- return len;
-
-
-}
-int rd_conn_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct client_obd* cli=&temp->u.cli;
- struct obd_import* imp=&cli->cl_import;
- int len=0;
- len+=snprintf(page, count, "%s\n",\
- imp->imp_connection->c_remote_uuid);
- return len;
-
-}
-
-lprocfs_vars_t status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0},
- {"status/f_blocksize",rd_blksize, 0},
- {"status/f_blockstotal",rd_blktotal, 0},
- {"status/f_blocksfree",rd_blkfree, 0},
- {"status/f_kbytesfree", rd_kbfree, 0},
- {"status/f_objects", rd_numobjects, 0},
- {"status/f_objectsfree", rd_objfree, 0},
- {"status/f_objectgroups", rd_objgroups, 0},
- {"status/ost_server_uuid", rd_server_uuid, 0},
- {"status/ost_conn_uuid", rd_conn_uuid, 0},
- {0}
-};
-int rd_numdevices(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_type* class=(struct obd_type*)data;
- int len=0;
- len+=snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-lprocfs_vars_t status_class_var[]={
- {"status/num_devices", rd_numdevices, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_OST
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- struct obd_device* temp=(struct obd_device*)data;
- int len=0;
- len+=snprintf(page, count, "%s\n", temp->obd_uuid);
- return len;
-
-
-}
-int rd_blksize(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- struct obd_device* temp=(struct obd_device*)data;
- struct ost_obd *ost=&temp->u.ost;
- struct lustre_handle *conn=&ost->ost_conn;
- struct obd_statfs mystats;
- int len=0;
-
- obd_statfs(conn, &mystats);
- len+=snprintf(page, count, "%d\n", mystats.os_bsize);
- return len;
-
-}
-int rd_kbtotal(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct ost_obd *ost=&temp->u.ost;
- struct lustre_handle *conn=&ost->ost_conn;
- struct obd_statfs mystats;
- int len=0;
- __u32 blk_size;
- __u64 result;
-
-
- obd_statfs(conn, &mystats);
-
- blk_size=mystats.os_bsize;
- blk_size>>=10;
-
- result=mystats.os_blocks;
-
- while(blk_size>>=1){
- result<<=1;
- }
-
- len+=snprintf(page, count, LPU64"\n", result);
- return len;
-
-
-}
-
-
-int rd_kbfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- struct obd_device* temp=(struct obd_device*)data;
- struct ost_obd *ost=&temp->u.ost;
- struct lustre_handle *conn=&ost->ost_conn;
- struct obd_statfs mystats;
- int len=0;
- __u32 blk_size;
- __u64 result;
-
- obd_statfs(conn, &mystats);
-
- blk_size=mystats.os_bsize;
- blk_size>>=10;
-
- result=mystats.os_bfree;
-
- while(blk_size>>=1){
- result<<=1;
- }
-
- len+=snprintf(page, count, LPU64"\n", result);
- return len;
-
-}
-
-int rd_files(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- struct obd_device* temp=(struct obd_device*)data;
- struct ost_obd *ost=&temp->u.ost;
- struct lustre_handle *conn=&ost->ost_conn;
- struct obd_statfs mystats;
- int len=0;
-
- obd_statfs(conn, &mystats);
-
- len+=snprintf(page, count, LPU64"\n",mystats.os_files);
- return len;
-
-}
-
-int rd_filesfree(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
-
- struct obd_device* temp=(struct obd_device*)data;
- struct ost_obd *ost=&temp->u.ost;
- struct lustre_handle *conn=&ost->ost_conn;
- struct obd_statfs mystats;
- int len=0;
-
- obd_statfs(conn, &mystats);
- len+=snprintf(page, count, LPU64"\n", mystats.os_ffree);
- return len;
-
-}
-
-int rd_objgroups(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-
-lprocfs_vars_t status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0},
- {"status/blocksize",rd_blksize, 0},
- {"status/kbytesfree", rd_kbfree, 0},
- {"status/kbytestotal", rd_kbtotal, 0},
- {"status/files", rd_files, 0},
- {"status/filesfree", rd_filesfree, 0},
- {"status/objectgroups", rd_objgroups, 0},
- {0}
-};
-
-int rd_numdevices(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_type* class=(struct obd_type*)data;
- int len=0;
- len+=snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-lprocfs_vars_t status_class_var[]={
- {"status/num_devices", rd_numdevices, 0},
- {0}
-};
+++ /dev/null
---- linux-2.4.18-chaos5-pristine/drivers/block/blkpg.c Sat Jun 29 23:07:36 2002
-+++ linux-2.4.18-chaos5/drivers/block/blkpg.c Sat Jun 29 23:09:04 2002
-@@ -295,3 +295,38 @@
- }
-
- EXPORT_SYMBOL(blk_ioctl);
-+
-+#define NUM_DEV_NO_WRITE 16
-+static int dev_no_write[NUM_DEV_NO_WRITE];
-+
-+/*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+void dev_set_rdonly(kdev_t dev, int no_write)
-+{
-+ if (dev) {
-+ printk(KERN_WARNING "Turning device %s read-only\n",
-+ bdevname(dev));
-+ dev_no_write[no_write] = 0xdead0000 + dev;
-+ }
-+}
-+
-+int dev_check_rdonly(kdev_t dev) {
-+ int i;
-+
-+ for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
-+ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
-+ dev == (dev_no_write[i] & 0xffff))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
---- linux-2.4.18-chaos5-pristine/drivers/block/loop.c Sat Jun 29 23:07:36 2002
-+++ linux-2.4.18-chaos5/drivers/block/loop.c Sat Jun 29 23:09:04 2002
-@@ -503,6 +503,11 @@
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
-+#endif
-+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
---- linux-2.4.18-chaos5-pristine/drivers/ide/ide-disk.c Sat Jun 29 23:07:36 2002
-+++ linux-2.4.18-chaos5/drivers/ide/ide-disk.c Sat Jun 29 23:09:04 2002
-@@ -557,6 +557,12 @@
- */
- static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
- {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(1, HWGROUP(drive));
-+ return ide_stopped;
-+ }
-+#endif
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
-
---- linux-2.4.18-chaos5-pristine/fs/ext3/Makefile Sat Jun 29 23:07:56 2002
-+++ linux-2.4.18-chaos5/fs/ext3/Makefile Sat Jun 29 23:09:04 2002
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o
-+
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
---- linux-2.4.18-chaos5-pristine/fs/ext3/super.c Sat Jun 29 23:07:56 2002
-+++ linux-2.4.18-chaos5/fs/ext3/super.c Sat Jun 29 23:09:04 2002
-@@ -1746,7 +1746,7 @@
- unregister_filesystem(&ext3_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- linux-2.4.18-chaos5-pristine/fs/jbd/commit.c Sat Jun 29 23:07:56 2002
-+++ linux-2.4.18-chaos5/fs/jbd/commit.c Sat Jun 29 23:09:04 2002
-@@ -482,7 +482,7 @@
- transaction's t_log_list queue, and metadata buffers are on
- the t_iobuf_list queue.
-
-- Wait for the transactions in reverse order. That way we are
-+ Wait for the buffers in reverse order. That way we are
- less likely to be woken up until all IOs have completed, and
- so we incur less scheduling load.
- */
-@@ -575,8 +575,10 @@
-
- jbd_debug(3, "JBD: commit phase 6\n");
-
-- if (is_journal_aborted(journal))
-+ if (is_journal_aborted(journal)) {
-+ unlock_journal(journal);
- goto skip_commit;
-+ }
-
- /* Done it all: now write the commit record. We should have
- * cleaned up our previous buffers by now, so if we are in abort
-@@ -586,9 +588,10 @@
- descriptor = journal_get_descriptor_buffer(journal);
- if (!descriptor) {
- __journal_abort_hard(journal);
-+ unlock_journal(journal);
- goto skip_commit;
- }
--
-+
- /* AKPM: buglet - add `i' to tmp! */
- for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
- journal_header_t *tmp =
-@@ -609,7 +612,6 @@
- put_bh(bh); /* One for getblk() */
- journal_unlock_journal_head(descriptor);
- }
-- lock_journal(journal);
-
- /* End of a transaction! Finally, we can do checkpoint
- processing: any buffers committed as a result of this
-@@ -618,6 +620,25 @@
-
- skip_commit:
-
-+ /* Call any callbacks that had been registered for handles in this
-+ * transaction. It is up to the callback to free any allocated
-+ * memory.
-+ */
-+ if (!list_empty(&commit_transaction->t_jcb)) {
-+ struct list_head *p, *n;
-+ int error = is_journal_aborted(journal);
-+
-+ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+ struct journal_callback *jcb;
-+
-+ jcb = list_entry(p, struct journal_callback, jcb_list);
-+ list_del(p);
-+ jcb->jcb_func(jcb, error);
-+ }
-+ }
-+
-+ lock_journal(journal);
-+
- jbd_debug(3, "JBD: commit phase 7\n");
-
- J_ASSERT(commit_transaction->t_sync_datalist == NULL);
---- linux-2.4.18-chaos5-pristine/fs/jbd/journal.c Sat Jun 29 23:07:56 2002
-+++ linux-2.4.18-chaos5/fs/jbd/journal.c Sat Jun 29 23:09:04 2002
-@@ -58,6 +58,7 @@
- #endif
- EXPORT_SYMBOL(journal_flush);
- EXPORT_SYMBOL(journal_revoke);
-+EXPORT_SYMBOL(journal_callback_set);
-
- EXPORT_SYMBOL(journal_init_dev);
- EXPORT_SYMBOL(journal_init_inode);
---- linux-2.4.18-chaos5-pristine/fs/jbd/transaction.c Sat Jun 29 23:07:56 2002
-+++ linux-2.4.18-chaos5/fs/jbd/transaction.c Sat Jun 29 23:09:04 2002
-@@ -57,6 +57,7 @@
- transaction->t_state = T_RUNNING;
- transaction->t_tid = journal->j_transaction_sequence++;
- transaction->t_expires = jiffies + journal->j_commit_interval;
-+ INIT_LIST_HEAD(&transaction->t_jcb);
-
- /* Set up the commit timer for the new transaction. */
- J_ASSERT (!journal->j_commit_timer_active);
-@@ -201,6 +202,20 @@
- return 0;
- }
-
-+/* Allocate a new handle. This should probably be in a slab... */
-+static handle_t *get_handle(int nblocks)
-+{
-+ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+ if (!handle)
-+ return NULL;
-+ memset(handle, 0, sizeof (handle_t));
-+ handle->h_buffer_credits = nblocks;
-+ handle->h_ref = 1;
-+ INIT_LIST_HEAD(&handle->h_jcb);
-+
-+ return handle;
-+}
-+
- /*
- * Obtain a new handle.
- *
-@@ -227,14 +242,11 @@
- handle->h_ref++;
- return handle;
- }
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = get_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = start_this_handle(journal, handle);
-@@ -333,14 +345,11 @@
-
- if (is_journal_aborted(journal))
- return ERR_PTR(-EIO);
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = get_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = try_start_this_handle(journal, handle);
-@@ -1319,6 +1328,29 @@
- #endif
-
- /*
-+ * Register a callback function for this handle. The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters. There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations. The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void journal_callback_set(handle_t *handle, void (*func)(void *, int),
-+ void *cb_data)
-+{
-+ struct journal_callback *jcb = cb_data;
-+
-+ list_add(&jcb->jcb_list, &handle->h_jcb);
-+ jcb->jcb_func = func;
-+}
-+
-+/*
- * All done for a particular handle.
- *
- * There is not much action needed here. We just return any remaining
-@@ -1383,7 +1415,10 @@
- wake_up(&journal->j_wait_transaction_locked);
- }
-
-- /*
-+ /* Move callbacks from the handle to the transaction. */
-+ list_splice(&handle->h_jcb, &transaction->t_jcb);
-+
-+ /*
- * If the handle is marked SYNC, we need to set another commit
- * going! We also want to force a commit if the current
- * transaction is occupying too much of the log, or if the
---- linux-2.4.18-chaos5-pristine/include/linux/blkdev.h Sat Jun 29 23:07:57 2002
-+++ linux-2.4.18-chaos5/include/linux/blkdev.h Mon Jul 1 08:51:17 2002
-@@ -276,4 +276,9 @@
- }
- return retval;
- }
-+
-+#define CONFIG_DEV_RDONLY
-+void dev_set_rdonly(kdev_t, int);
-+int dev_check_rdonly(kdev_t);
-+void dev_clear_rdonly(int);
- #endif
---- linux-2.4.18-chaos5-pristine/include/linux/jbd.h Sat Jun 29 23:07:57 2002
-+++ linux-2.4.18-chaos5/include/linux/jbd.h Mon Jul 1 08:51:19 2002
-@@ -257,6 +257,13 @@
- return bh->b_private;
- }
-
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+struct journal_callback {
-+ struct list_head jcb_list;
-+ void (*jcb_func)(void *cb_data, int error);
-+ /* user data goes here */
-+};
-+
- struct jbd_revoke_table_s;
-
- /* The handle_t type represents a single atomic update being performed
-@@ -287,6 +294,12 @@
- operations */
- int h_err;
-
-+ /* List of application registered callbacks for this handle.
-+ * The function(s) will be called after the transaction that
-+ * this handle is part of has been committed to disk.
-+ */
-+ struct list_head h_jcb;
-+
- /* Flags */
- unsigned int h_sync: 1; /* sync-on-close */
- unsigned int h_jdata: 1; /* force data journaling */
-@@ -406,6 +419,10 @@
-
- /* How many handles used this transaction? */
- int t_handle_count;
-+
-+ /* List of registered callback functions for this transaction.
-+ * Called when the transaction is committed. */
-+ struct list_head t_jcb;
- };
-
-
-@@ -654,6 +671,8 @@
- extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
- extern int journal_stop(handle_t *);
- extern int journal_flush (journal_t *);
-+extern void journal_callback_set(handle_t *handle, void (*fn)(void *, int),
-+ void *cb_data);
-
- extern void journal_lock_updates (journal_t *);
- extern void journal_unlock_updates (journal_t *);
---- linux-2.4.18-chaos5-pristine/kernel/ksyms.c Sat Jun 29 23:07:57 2002
-+++ linux-2.4.18-chaos5/kernel/ksyms.c Sat Jun 29 23:09:04 2002
-@@ -306,6 +306,13 @@
- EXPORT_SYMBOL(lock_may_write);
- EXPORT_SYMBOL(dcache_readdir);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+EXPORT_SYMBOL(do_kern_mount);
-+
-+
- /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
- EXPORT_SYMBOL(default_llseek);
- EXPORT_SYMBOL(dentry_open);
---- linux-2.4.18-chaos5-pristine/include/linux/dcache.h Sat Jun 29 23:07:57 2002
-+++ linux-2.4.18-chaos5/include/linux/dcache.h Mon Jul 1 08:51:12 2002
-@@ -6,6 +6,33 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_SYMLINK (1<<4)
-+#define IT_UNLINK (1<<5)
-+#define IT_RMDIR (1<<6)
-+#define IT_RENAME (1<<7)
-+#define IT_RENAME2 (1<<8)
-+#define IT_READDIR (1<<9)
-+#define IT_GETATTR (1<<10)
-+#define IT_SETATTR (1<<11)
-+#define IT_READLINK (1<<12)
-+#define IT_MKNOD (1<<13)
-+#define IT_LOOKUP (1<<14)
-+
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -78,6 +105,7 @@
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
- struct super_block * d_sb; /* The root of the dentry tree */
-+ struct lookup_intent *d_it;
- unsigned long d_vfs_flags;
- void * d_fsdata; /* fs-specific data */
- void * d_extra_attributes; /* TUX-specific data */
-@@ -91,6 +119,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
---- linux-2.4.18-chaos5-pristine/include/linux/fs.h Sat Jun 29 23:07:57 2002
-+++ linux-2.4.18-chaos5/include/linux/fs.h Mon Jul 1 08:51:12 2002
-@@ -572,6 +572,7 @@
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_intent;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -829,7 +830,9 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it);
-
- /*
- * File types
-@@ -890,6 +893,7 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -1036,6 +1040,7 @@
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
- extern void umount_tree(struct vfsmount *);
-
- #define kern_umount mntput
-@@ -1370,6 +1375,7 @@
- extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
-
- extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
-+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
- extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
- extern int FASTCALL(path_walk(const char *, struct nameidata *));
- extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1381,6 +1387,8 @@
- extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
- #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
- #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
-+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
-+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
-
- extern void iput(struct inode *);
- extern void force_delete(struct inode *);
---- linux-2.4.18-chaos5-pristine/fs/dcache.c Mon Feb 25 12:38:08 2002
-+++ linux-2.4.18-chaos5/fs/dcache.c Wed Jul 31 11:44:36 2002
-@@ -617,6 +617,7 @@
- dentry->d_op = NULL;
- dentry->d_fsdata = NULL;
- dentry->d_mounted = 0;
-+ dentry->d_it = NULL;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
---- linux-2.4.18-chaos5-pristine/fs/nfsd/vfs.c Sat Jun 29 23:07:56 2002
-+++ linux-2.4.18-chaos5/fs/nfsd/vfs.c Sat Jun 29 23:09:04 2002
-@@ -1298,7 +1298,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- unlock_kernel();
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
---- linux-2.4.18-chaos5-pristine/fs/namei.c Sat Jun 29 23:07:56 2002
-+++ linux-2.4.18-chaos5/fs/namei.c Tue Jul 2 16:06:05 2002
-@@ -94,6 +94,14 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct dentry *de)
-+{
-+ if (de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de);
-+ de->d_it = NULL;
-+}
-+
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -260,10 +268,19 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -281,7 +297,8 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -300,6 +316,9 @@
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -322,6 +341,13 @@
- result = ERR_PTR(-ENOENT);
- }
- }
-+ else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
-+ }
- return result;
- }
-
-@@ -447,7 +472,8 @@
- *
- * We expect 'base' to be positive and a directory.
- */
--int link_path_walk(const char * name, struct nameidata *nd)
-+int link_path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
- struct inode *inode;
-@@ -524,12 +549,12 @@
- break;
- }
- /* This does the actual lookups.. */
-- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, it);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, it);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -563,7 +588,7 @@
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -590,12 +615,12 @@
- if (err < 0)
- break;
- }
-- dentry = cached_lookup(nd->dentry, &this, 0);
-+ dentry = cached_lookup(nd->dentry, &this, 0, it);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, 0);
-+ dentry = real_lookup(nd->dentry, &this, 0, it);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -619,7 +644,8 @@
- goto no_inode;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op || (!inode->i_op->lookup &&
-+ !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -651,6 +677,7 @@
- }
- }
- return_base:
-+ nd->dentry->d_it = it;
- return 0;
- out_dput:
- dput(dentry);
-@@ -658,15 +685,29 @@
- }
- path_release(nd);
- return_err:
-+ if (!err)
-+ nd->dentry->d_it = it;
- return err;
- }
-
-+int link_path_walk(const char * name, struct nameidata *nd)
-+{
-+ return link_path_walk_it(name, nd, NULL);
-+}
-+
-+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
-+{
-+ current->total_link_count = 0;
-+ return link_path_walk_it(name, nd, it);
-+}
-+
- int path_walk(const char * name, struct nameidata *nd)
- {
- current->total_link_count = 0;
-- return link_path_walk(name, nd);
-+ return link_path_walk_it(name, nd, NULL);
- }
-
-+
- /* SMP-safe */
- /* returns 1 if everything is done */
- static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
-@@ -749,6 +790,17 @@
- }
-
- /* SMP-safe */
-+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ int error = 0;
-+ if (path_init(path, flags, nd))
-+ error = path_walk_it(path, nd, it);
-+ return error;
-+}
-+
-+
-+/* SMP-safe */
- int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
- {
- int error = 0;
-@@ -777,7 +829,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -800,13 +853,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
- lock_kernel();
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -818,6 +874,12 @@
- return dentry;
- }
-
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+{
-+ return lookup_hash_it(name, base, NULL);
-+}
-+
-+
- /* SMP-safe */
- struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
- {
-@@ -839,7 +901,7 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash_it(&this, base, NULL);
- access:
- return ERR_PTR(-EACCES);
- }
-@@ -870,6 +932,23 @@
- return err;
- }
-
-+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ char *tmp;
-+ int err;
-+
-+ tmp = getname(name);
-+ err = PTR_ERR(tmp);
-+ if (!IS_ERR(tmp)) {
-+ err = 0;
-+ if (path_init(tmp, flags, nd))
-+ err = path_walk_it(tmp, nd, it);
-+ putname(tmp);
-+ }
-+ return err;
-+}
-+
- /*
- * It's inline, so penalty for filesystems that don't use sticky bit is
- * minimal.
-@@ -1008,7 +1086,8 @@
- * for symlinks (where the permissions are checked later).
- * SMP-safe
- */
--int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
-+int open_namei_it(const char *pathname, int flag, int mode,
-+ struct nameidata *nd, struct lookup_intent *it)
- {
- int acc_mode, error = 0;
- struct inode *inode;
-@@ -1022,16 +1101,19 @@
- * The simplest case - just a plain lookup.
- */
- if (!(flag & O_CREAT)) {
-- error = path_lookup(pathname, lookup_flags(flag), nd);
-+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it);
- if (error)
- return error;
- dentry = nd->dentry;
-+ dentry->d_it = it;
- goto ok;
- }
-
- /*
- * Create - we need to know the parent.
- */
-+ if (it)
-+ it->it_op |= IT_CREAT;
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1047,7 +1129,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1056,6 +1138,7 @@
- goto exit;
- }
-
-+ dentry->d_it = it;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- error = vfs_create(dir->d_inode, dentry,
-@@ -1172,9 +1255,11 @@
- if (flag & FMODE_WRITE)
- DQUOT_INIT(inode);
-
-+ intent_release(dentry);
- return 0;
-
- exit_dput:
-+ intent_release(dentry);
- dput(dentry);
- exit:
- path_release(nd);
-@@ -1217,13 +1302,20 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, NULL);
- putname(nd->last.name);
- goto do_last;
- }
-
-+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
-+{
-+ return open_namei_it(pathname, flag, mode, nd, NULL);
-+}
-+
-+
- /* SMP-safe */
--static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
-+static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
-
-@@ -1231,7 +1323,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1277,6 +1369,7 @@
- char * tmp;
- struct dentry * dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { IT_MKNOD , mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1287,11 +1380,12 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
-
- mode &= ~current->fs->umask;
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- switch (mode & S_IFMT) {
- case 0: case S_IFREG:
- error = vfs_create(nd.dentry->d_inode,dentry,mode);
-@@ -1305,6 +1399,7 @@
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1345,6 +1440,7 @@
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { IT_MKDIR, mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1355,11 +1451,13 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ dentry = lookup_create(&nd, 1, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
- mode & ~current->fs->umask);
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1439,6 +1537,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { IT_RMDIR, 0 };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1460,10 +1559,12 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1507,6 +1608,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { IT_UNLINK, 0 };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1519,14 +1621,16 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- /* Why not before? Because we want correct error value */
- if (nd.last.name[nd.last.len])
- goto slashes;
- error = vfs_unlink(nd.dentry->d_inode, dentry);
- exit2:
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1573,6 +1677,7 @@
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { IT_SYMLINK, 0 };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1586,11 +1691,13 @@
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
-- dput(dentry);
-+ intent_release(dentry);
-+ dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
- path_release(&nd);
-@@ -1654,6 +1761,7 @@
- {
- int error;
- char * to;
-+ struct lookup_intent it = { IT_LINK, 0 };
-
- to = getname(newname);
- error = PTR_ERR(to);
-@@ -1670,10 +1778,12 @@
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ new_dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
-+ new_dentry->d_it = ⁢
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-+ intent_release(new_dentry);
- dput(new_dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1714,7 +1824,8 @@
- * locking].
- */
- int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- struct inode *target;
-@@ -1768,10 +1879,12 @@
- } else
- double_down(&old_dir->i_zombie,
- &new_dir->i_zombie);
-+ new_dentry->d_it = it;
- if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1793,7 +1906,8 @@
- }
-
- int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -1820,10 +1934,12 @@
- DQUOT_INIT(old_dir);
- DQUOT_INIT(new_dir);
- double_down(&old_dir->i_zombie, &new_dir->i_zombie);
-+ new_dentry->d_it = it;
- if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry);
- double_up(&old_dir->i_zombie, &new_dir->i_zombie);
- if (error)
- return error;
-@@ -1835,13 +1951,14 @@
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- if (S_ISDIR(old_dentry->d_inode->i_mode))
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -1858,6 +1975,7 @@
- int error = 0;
- struct dentry * old_dir, * new_dir;
- struct dentry * old_dentry, *new_dentry;
-+ struct lookup_intent it = {IT_RENAME, 0};
- struct nameidata oldnd, newnd;
-
- error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
-@@ -1883,7 +2001,7 @@
-
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1899,14 +2019,15 @@
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ it.it_op = IT_RENAME2;
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-
- lock_kernel();
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, &it);
- unlock_kernel();
-
- dput(new_dentry);
---- linux-2.4.18-chaos5-pristine/fs/open.c Sat Jun 29 23:07:56 2002
-+++ linux-2.4.18-chaos5/fs/open.c Sat Jun 29 23:09:04 2002
-@@ -19,6 +19,8 @@
- #include <asm/uaccess.h>
-
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
-+extern int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it);
-+extern void intent_release(struct dentry *de);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -118,14 +120,19 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it;
-+
-+ it.it_op = IT_SETATTR;
-+
-
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-
-- error = user_path_walk(path, &nd);
-+ error = user_path_walk_it(path, &nd, &it);
- if (error)
- goto out;
-+ nd.dentry->d_it = ⁢
- inode = nd.dentry->d_inode;
-
- /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
-@@ -168,6 +175,7 @@
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -259,10 +267,14 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it;
-
-- error = user_path_walk(filename, &nd);
-+ it.it_op = IT_SETATTR;
-+
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
-+ nd.dentry->d_it = ⁢
- inode = nd.dentry->d_inode;
-
- error = -EROFS;
-@@ -286,6 +298,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -303,11 +316,15 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it;
-+
-+ it.it_op = IT_SETATTR;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
-
- if (error)
- goto out;
-+ nd.dentry->d_it = ⁢
- inode = nd.dentry->d_inode;
-
- error = -EROFS;
-@@ -330,6 +347,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -346,6 +364,9 @@
- int old_fsuid, old_fsgid;
- kernel_cap_t old_cap;
- int res;
-+ struct lookup_intent it;
-+
-+ it.it_op = IT_GETATTR;
-
- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
- return -EINVAL;
-@@ -363,13 +384,14 @@
- else
- current->cap_effective = current->cap_permitted;
-
-- res = user_path_walk(filename, &nd);
-+ res = user_path_walk_it(filename, &nd, &it);
- if (!res) {
- res = permission(nd.dentry->d_inode, mode);
- /* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
- res = -EROFS;
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
-
-@@ -384,11 +406,13 @@
- {
- int error;
- struct nameidata nd;
--
-- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
-+ struct lookup_intent it = {IT_GETATTR};
-+
-+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it);
- if (error)
- goto out;
-
-+ nd.dentry->d_it = ⁢
- error = permission(nd.dentry->d_inode,MAY_EXEC);
- if (error)
- goto dput_and_out;
-@@ -396,6 +420,7 @@
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -435,12 +460,14 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = {IT_GETATTR};
-
-- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
-+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
- if (error)
- goto out;
-
-+ nd.dentry->d_it = ⁢
- error = permission(nd.dentry->d_inode,MAY_EXEC);
- if (error)
- goto dput_and_out;
-@@ -453,6 +480,7 @@
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -497,12 +525,15 @@
- struct inode * inode;
- int error;
- struct iattr newattrs;
-+ struct lookup_intent it;
-
-- error = user_path_walk(filename, &nd);
-+ it.it_op = IT_SETATTR;
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ nd.dentry->d_it = ⁢
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -518,6 +549,7 @@
- error = notify_change(nd.dentry, &newattrs);
-
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -587,10 +619,15 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it;
-+
-+ it.it_op = IT_SETATTR;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
-+ nd.dentry->d_it = ⁢
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
- return error;
-@@ -600,10 +637,15 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it;
-
-- error = user_path_walk_link(filename, &nd);
-+ it.it_op = IT_SETATTR;
-+
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
-+ nd.dentry->d_it = ⁢
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
- return error;
-@@ -637,10 +679,15 @@
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, int flags, struct lookup_intent *it);
-+
- struct file *filp_open(const char * filename, int flags, int mode)
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = {IT_OPEN, 0};
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -648,14 +695,14 @@
- if (namei_flags & O_TRUNC)
- namei_flags |= 2;
-
-- error = open_namei(filename, namei_flags, mode, &nd);
-+ error = open_namei_it(filename, namei_flags, mode, &nd, &it);
- if (!error)
-- return dentry_open(nd.dentry, nd.mnt, flags);
-+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
-
- return ERR_PTR(error);
- }
-
--struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, int flags, struct lookup_intent *it)
- {
- struct file * f;
- struct inode *inode;
-@@ -712,11 +759,19 @@
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(dentry);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+
-+}
-+
-+
- /*
- * Find an empty file descriptor entry, and mark it busy.
- */
---- linux-2.4.18-chaos5-pristine/fs/stat.c Sat Jun 29 23:07:56 2002
-+++ linux-2.4.18-chaos5/fs/stat.c Mon Jul 1 08:54:45 2002
-@@ -13,6 +13,8 @@
-
- #include <asm/uaccess.h>
-
-+
-+extern void intent_release(struct dentry *de);
- /*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
-@@ -104,10 +106,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { IT_GETATTR};
-
-- error = user_path_walk(name, &nd);
-+ error = user_path_walk_it(name, &nd, &it);
- if (!error) {
- error = do_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
- return error;
-@@ -117,10 +121,13 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { IT_GETATTR};
-+
-
-- error = user_path_walk_link(name, &nd);
-+ error = user_path_walk_link_it(name, &nd, &it);
- if (!error) {
- error = do_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
- return error;
---- linux-2.4.18-chaos5-pristine/mm/slab.c Sat Jun 29 23:07:57 2002
-+++ linux-2.4.18-chaos5/mm/slab.c Sat Jun 29 23:09:04 2002
-@@ -1207,6 +1207,58 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!VALID_PAGE(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
---- linux-2.4.18-chaos5-pristine/arch/i386/mm/init.c Sat Jun 29 23:07:34 2002
-+++ linux-2.4.18-chaos5/arch/i386/mm/init.c Sat Jun 29 23:09:04 2002
-@@ -43,6 +43,14 @@
- static unsigned long totalram_pages;
- static unsigned long totalhigh_pages;
-
-+
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid enough?
-+ return virt_to_page(kaddr);
-+}
-+
-+
- int do_check_pgt_cache(int low, int high)
- {
- int freed = 0;
---- linux-2.4.18-chaos5-pristine/include/linux/slab.h Sat Jun 29 23:07:57 2002
-+++ linux-2.4.18-chaos5/include/linux/slab.h Mon Jul 1 08:51:12 2002
-@@ -57,6 +57,7 @@
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
-
- extern void *kmalloc(size_t, int);
- extern void kfree(const void *);
---- linux-2.4.18-chaos5-pristine/scripts/mkspec Sat Jun 29 23:07:58 2002
-+++ linux-2.4.18-chaos5/scripts/mkspec Sat Jun 29 23:09:04 2002
-@@ -64,6 +64,7 @@
- fi
- # Back on track, again
- echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
-+echo 'cp vmlinux $RPM_BUILD_ROOT'"/boot/vmlinux-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
- echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
- echo ""
- echo "%clean"
+++ /dev/null
---- linux-pristine/./include/linux/lustre_version.h Wed Dec 31 19:00:00 1969
-+++ linux/./include/linux/lustre_version.h Tue Nov 26 07:02:14 2002
-@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 4
---- linux-pristine/./arch/ia64/mm/init.c Thu Dec 5 10:47:25 2002
-+++ linux/./arch/ia64/mm/init.c Fri Nov 29 18:06:20 2002
-@@ -44,6 +44,12 @@
-
- static struct page *vmem_map;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int
- do_check_pgt_cache (int low, int high)
- {
---- linux-pristine/./arch/i386/mm/init.c Thu Dec 5 10:47:24 2002
-+++ linux/./arch/i386/mm/init.c Fri Nov 29 18:06:20 2002
-@@ -43,6 +43,12 @@
- static unsigned long totalram_pages;
- static unsigned long totalhigh_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int do_check_pgt_cache(int low, int high)
- {
- int freed = 0;
---- linux-pristine/./drivers/block/blkpg.c Thu Dec 5 10:47:36 2002
-+++ linux/./drivers/block/blkpg.c Fri Nov 29 18:08:05 2002
-@@ -308,6 +308,41 @@
-
- EXPORT_SYMBOL(blk_ioctl);
-
-+#define NUM_DEV_NO_WRITE 16
-+static int dev_no_write[NUM_DEV_NO_WRITE];
-+
-+/*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+void dev_set_rdonly(kdev_t dev, int no_write)
-+{
-+ if (dev) {
-+ printk(KERN_WARNING "Turning device %s read-only\n",
-+ bdevname(dev));
-+ dev_no_write[no_write] = 0xdead0000 + dev;
-+ }
-+}
-+
-+int dev_check_rdonly(kdev_t dev) {
-+ int i;
-+
-+ for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
-+ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
-+ dev == (dev_no_write[i] & 0xffff))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
-+
- /*********************
- * get_last_sector()
- *
---- linux-pristine/./drivers/block/loop.c Thu Dec 5 10:47:37 2002
-+++ linux/./drivers/block/loop.c Fri Nov 29 18:06:20 2002
-@@ -471,6 +471,11 @@
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
-+#endif
-+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
---- linux-pristine/./drivers/ide/ide-disk.c Thu Dec 5 10:47:59 2002
-+++ linux/./drivers/ide/ide-disk.c Fri Nov 29 18:06:20 2002
-@@ -367,6 +367,12 @@
- */
- static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
- {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(1, HWGROUP(drive));
-+ return ide_stopped;
-+ }
-+#endif
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
- OUT_BYTE(0x00, IDE_FEATURE_REG);
---- linux-pristine/./fs/ext3/Makefile Thu Dec 5 10:49:13 2002
-+++ linux/./fs/ext3/Makefile Fri Nov 29 18:06:20 2002
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o
-+
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
---- linux-pristine/./fs/ext3/super.c Thu Dec 5 10:49:13 2002
-+++ linux/./fs/ext3/super.c Fri Nov 29 18:06:20 2002
-@@ -1744,7 +1744,7 @@
- unregister_filesystem(&ext3_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- linux-pristine/./fs/jbd/commit.c Thu Dec 5 10:49:15 2002
-+++ linux/./fs/jbd/commit.c Fri Nov 29 18:06:20 2002
-@@ -475,7 +475,7 @@
- transaction's t_log_list queue, and metadata buffers are on
- the t_iobuf_list queue.
-
-- Wait for the transactions in reverse order. That way we are
-+ Wait for the buffers in reverse order. That way we are
- less likely to be woken up until all IOs have completed, and
- so we incur less scheduling load.
- */
-@@ -566,8 +566,10 @@
-
- jbd_debug(3, "JBD: commit phase 6\n");
-
-- if (is_journal_aborted(journal))
-+ if (is_journal_aborted(journal)) {
-+ unlock_journal(journal);
- goto skip_commit;
-+ }
-
- /* Done it all: now write the commit record. We should have
- * cleaned up our previous buffers by now, so if we are in abort
-@@ -577,6 +579,7 @@
- descriptor = journal_get_descriptor_buffer(journal);
- if (!descriptor) {
- __journal_abort_hard(journal);
-+ unlock_journal(journal);
- goto skip_commit;
- }
-
-@@ -600,7 +603,6 @@
- put_bh(bh); /* One for getblk() */
- journal_unlock_journal_head(descriptor);
- }
-- lock_journal(journal);
-
- /* End of a transaction! Finally, we can do checkpoint
- processing: any buffers committed as a result of this
-@@ -609,6 +611,25 @@
-
- skip_commit:
-
-+ /* Call any callbacks that had been registered for handles in this
-+ * transaction. It is up to the callback to free any allocated
-+ * memory.
-+ */
-+ if (!list_empty(&commit_transaction->t_jcb)) {
-+ struct list_head *p, *n;
-+ int error = is_journal_aborted(journal);
-+
-+ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+ struct journal_callback *jcb;
-+
-+ jcb = list_entry(p, struct journal_callback, jcb_list);
-+ list_del(p);
-+ jcb->jcb_func(jcb, error);
-+ }
-+ }
-+
-+ lock_journal(journal);
-+
- jbd_debug(3, "JBD: commit phase 7\n");
-
- J_ASSERT(commit_transaction->t_sync_datalist == NULL);
---- linux-pristine/./fs/jbd/journal.c Thu Dec 5 10:49:15 2002
-+++ linux/./fs/jbd/journal.c Fri Nov 29 18:06:20 2002
-@@ -58,6 +58,7 @@
- #endif
- EXPORT_SYMBOL(journal_flush);
- EXPORT_SYMBOL(journal_revoke);
-+EXPORT_SYMBOL(journal_callback_set);
-
- EXPORT_SYMBOL(journal_init_dev);
- EXPORT_SYMBOL(journal_init_inode);
---- linux-pristine/./fs/jbd/transaction.c Thu Dec 5 10:49:15 2002
-+++ linux/./fs/jbd/transaction.c Fri Nov 29 18:06:20 2002
-@@ -57,6 +57,7 @@
- transaction->t_state = T_RUNNING;
- transaction->t_tid = journal->j_transaction_sequence++;
- transaction->t_expires = jiffies + journal->j_commit_interval;
-+ INIT_LIST_HEAD(&transaction->t_jcb);
-
- /* Set up the commit timer for the new transaction. */
- J_ASSERT (!journal->j_commit_timer_active);
-@@ -201,6 +202,20 @@
- return 0;
- }
-
-+/* Allocate a new handle. This should probably be in a slab... */
-+static handle_t *new_handle(int nblocks)
-+{
-+ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+ if (!handle)
-+ return NULL;
-+ memset(handle, 0, sizeof (handle_t));
-+ handle->h_buffer_credits = nblocks;
-+ handle->h_ref = 1;
-+ INIT_LIST_HEAD(&handle->h_jcb);
-+
-+ return handle;
-+}
-+
- /*
- * Obtain a new handle.
- *
-@@ -227,14 +242,11 @@
- handle->h_ref++;
- return handle;
- }
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = start_this_handle(journal, handle);
-@@ -333,14 +345,11 @@
-
- if (is_journal_aborted(journal))
- return ERR_PTR(-EIO);
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = try_start_this_handle(journal, handle);
-@@ -1328,6 +1337,28 @@
- #endif
-
- /*
-+ * Register a callback function for this handle. The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters. There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations. The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void journal_callback_set(handle_t *handle,
-+ void (*func)(struct journal_callback *jcb, int error),
-+ struct journal_callback *jcb)
-+{
-+ list_add(&jcb->jcb_list, &handle->h_jcb);
-+ jcb->jcb_func = func;
-+}
-+
-+/*
- * All done for a particular handle.
- *
- * There is not much action needed here. We just return any remaining
-@@ -1393,7 +1424,10 @@
- wake_up(&journal->j_wait_transaction_locked);
- }
-
-- /*
-+ /* Move callbacks from the handle to the transaction. */
-+ list_splice(&handle->h_jcb, &transaction->t_jcb);
-+
-+ /*
- * If the handle is marked SYNC, we need to set another commit
- * going! We also want to force a commit if the current
- * transaction is occupying too much of the log, or if the
---- linux-pristine/./include/linux/blkdev.h Thu Dec 5 10:49:41 2002
-+++ linux/./include/linux/blkdev.h Fri Nov 29 18:30:34 2002
-@@ -228,4 +228,8 @@
- return retval;
- }
-
-+#define CONFIG_DEV_RDONLY
-+void dev_set_rdonly(kdev_t, int);
-+int dev_check_rdonly(kdev_t);
-+void dev_clear_rdonly(int);
- #endif
---- linux-pristine/./include/linux/slab.h Thu Dec 5 10:49:53 2002
-+++ linux/./include/linux/slab.h Fri Nov 29 18:30:15 2002
-@@ -58,6 +58,7 @@
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void *kmem_cache_zalloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
-
- extern void *kmalloc(size_t, int);
- extern void kfree(const void *);
---- linux-pristine/./include/linux/jbd.h Thu Dec 5 10:49:43 2002
-+++ linux/./include/linux/jbd.h Fri Nov 29 18:50:01 2002
-@@ -249,6 +249,13 @@
- return bh->b_private;
- }
-
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+struct journal_callback {
-+ struct list_head jcb_list;
-+ void (*jcb_func)(struct journal_callback *jcb, int error);
-+ /* user data goes here */
-+};
-+
- struct jbd_revoke_table_s;
-
- /* The handle_t type represents a single atomic update being performed
-@@ -279,6 +286,12 @@
- operations */
- int h_err;
-
-+ /* List of application registered callbacks for this handle.
-+ * The function(s) will be called after the transaction that
-+ * this handle is part of has been committed to disk.
-+ */
-+ struct list_head h_jcb;
-+
- /* Flags */
- unsigned int h_sync: 1; /* sync-on-close */
- unsigned int h_jdata: 1; /* force data journaling */
-@@ -398,6 +411,10 @@
-
- /* How many handles used this transaction? */
- int t_handle_count;
-+
-+ /* List of registered callback functions for this transaction.
-+ * Called when the transaction is committed. */
-+ struct list_head t_jcb;
- };
-
-
-@@ -646,6 +663,9 @@
- extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
- extern int journal_stop(handle_t *);
- extern int journal_flush (journal_t *);
-+extern void journal_callback_set(handle_t *handle,
-+ void (*fn)(struct journal_callback *,int),
-+ struct journal_callback *jcb);
-
- extern void journal_lock_updates (journal_t *);
- extern void journal_unlock_updates (journal_t *);
---- linux-pristine/./kernel/ksyms.c Thu Dec 5 10:50:01 2002
-+++ linux/./kernel/ksyms.c Fri Nov 29 18:37:23 2002
-@@ -271,6 +271,7 @@
- EXPORT_SYMBOL(set_page_dirty);
- EXPORT_SYMBOL(vfs_readlink);
- EXPORT_SYMBOL(vfs_follow_link);
-+EXPORT_SYMBOL(vfs_follow_link_it);
- EXPORT_SYMBOL(page_readlink);
- EXPORT_SYMBOL(page_follow_link);
- EXPORT_SYMBOL(page_symlink_inode_operations);
-@@ -285,6 +286,11 @@
- EXPORT_SYMBOL(nr_free_pages);
- EXPORT_SYMBOL(page_cache_size);
-
-+/* lustre */
-+EXPORT_SYMBOL(pagecache_lock);
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
- /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
- EXPORT_SYMBOL(default_llseek);
- EXPORT_SYMBOL(dentry_open);
---- linux-pristine/./include/linux/dcache.h Thu Dec 5 10:49:42 2002
-+++ linux/./include/linux/dcache.h Fri Nov 29 18:30:11 2002
-@@ -6,6 +6,34 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
-+
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -78,6 +106,7 @@
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
- struct super_block * d_sb; /* The root of the dentry tree */
-+ struct lookup_intent *d_it;
- unsigned long d_vfs_flags;
- void * d_fsdata; /* fs-specific data */
- unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
-@@ -90,6 +119,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
---- linux-pristine/./include/linux/fs.h Thu Dec 5 10:49:42 2002
-+++ linux/./include/linux/fs.h Fri Nov 29 18:30:15 2002
-@@ -588,6 +588,7 @@
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_intent;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -849,7 +850,9 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it);
-
- /*
- * File types
-@@ -911,6 +914,7 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -921,6 +925,8 @@
- struct inode *, struct dentry *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *,
-+ struct lookup_intent *it);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*revalidate) (struct dentry *);
-@@ -1063,7 +1069,7 @@
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
--
-+struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data);
- #define kern_umount mntput
-
- extern int vfs_statfs(struct super_block *, struct statfs *);
-@@ -1387,6 +1393,7 @@
- extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
-
- extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
-+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
- extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
- extern int FASTCALL(path_walk(const char *, struct nameidata *));
- extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
-@@ -1397,6 +1404,8 @@
- extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
- #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
- #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
-+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
-+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
-
- extern void iput(struct inode *);
- extern void force_delete(struct inode *);
-@@ -1508,6 +1517,8 @@
-
- extern int vfs_readlink(struct dentry *, char *, int, const char *);
- extern int vfs_follow_link(struct nameidata *, const char *);
-+extern int vfs_follow_link_it(struct nameidata *, const char *,
-+ struct lookup_intent *it);
- extern int page_readlink(struct dentry *, char *, int);
- extern int page_follow_link(struct dentry *, struct nameidata *);
- extern struct inode_operations page_symlink_inode_operations;
---- linux-pristine/./fs/dcache.c Thu Dec 5 10:49:13 2002
-+++ linux/./fs/dcache.c Fri Nov 29 18:06:20 2002
-@@ -617,6 +617,7 @@
- dentry->d_op = NULL;
- dentry->d_fsdata = NULL;
- dentry->d_mounted = 0;
-+ dentry->d_it = NULL;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
---- linux-pristine/./fs/nfsd/vfs.c Thu Dec 5 10:49:18 2002
-+++ linux/./fs/nfsd/vfs.c Fri Nov 29 18:06:20 2002
-@@ -1285,7 +1285,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
---- linux-pristine/./fs/namei.c Thu Dec 5 10:49:16 2002
-+++ linux/./fs/namei.c Fri Nov 29 18:11:18 2002
-@@ -94,6 +94,12 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct dentry *de, struct lookup_intent *it)
-+{
-+ if (it && de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de, it);
-+}
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -260,10 +266,19 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -281,7 +296,8 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -300,6 +316,9 @@
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +340,12 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -332,7 +357,8 @@
- * Without that kind of total limit, nasty chains of consecutive
- * symlinks can cause almost arbitrarily long lookups.
- */
--static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
-+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- int err;
- if (current->link_count >= 5)
-@@ -346,10 +372,14 @@
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-+ intent_release(dentry, it);
- path_release(nd);
- return -ELOOP;
- }
-@@ -445,7 +475,8 @@
- *
- * We expect 'base' to be positive and a directory.
- */
--int link_path_walk(const char * name, struct nameidata *nd)
-+int link_path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
- struct inode *inode;
-@@ -518,9 +549,9 @@
- break;
- }
- /* This does the actual lookups.. */
-- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- if (!dentry) {
-- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -537,8 +568,8 @@
- if (!inode->i_op)
- goto out_dput;
-
-- if (inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ if (inode->i_op->follow_link || inode->i_op->follow_link2) {
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -554,7 +585,7 @@
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -581,9 +612,9 @@
- if (err < 0)
- break;
- }
-- dentry = cached_lookup(nd->dentry, &this, 0);
-+ dentry = cached_lookup(nd->dentry, &this, 0, it);
- if (!dentry) {
-- dentry = real_lookup(nd->dentry, &this, 0);
-+ dentry = real_lookup(nd->dentry, &this, 0, it);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -591,9 +622,9 @@
- while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
- ;
- inode = dentry->d_inode;
-- if ((lookup_flags & LOOKUP_FOLLOW)
-- && inode && inode->i_op && inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ if ((lookup_flags & LOOKUP_FOLLOW) && inode && inode->i_op &&
-+ (inode->i_op->follow_link || inode->i_op->follow_link2)) {
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -607,7 +638,8 @@
- goto no_inode;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op ||
-+ (!inode->i_op->lookup && !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -636,10 +668,21 @@
- return err;
- }
-
-+int link_path_walk(const char * name, struct nameidata *nd)
-+{
-+ return link_path_walk_it(name, nd, NULL);
-+}
-+
-+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
-+{
-+ current->total_link_count = 0;
-+ return link_path_walk_it(name, nd, it);
-+}
-+
- int path_walk(const char * name, struct nameidata *nd)
- {
- current->total_link_count = 0;
-- return link_path_walk(name, nd);
-+ return link_path_walk_it(name, nd, NULL);
- }
-
- /* SMP-safe */
-@@ -742,7 +785,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -765,13 +809,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
- lock_kernel();
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -783,6 +830,12 @@
- return dentry;
- }
-
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+{
-+ return lookup_hash_it(name, base, NULL);
-+}
-+
-+
- /* SMP-safe */
- struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
- {
-@@ -804,7 +857,7 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash_it(&this, base, NULL);
- access:
- return ERR_PTR(-EACCES);
- }
-@@ -836,6 +889,23 @@
- return err;
- }
-
-+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ char *tmp;
-+ int err;
-+
-+ tmp = getname(name);
-+ err = PTR_ERR(tmp);
-+ if (!IS_ERR(tmp)) {
-+ err = 0;
-+ if (path_init(tmp, flags, nd))
-+ err = path_walk_it(tmp, nd, it);
-+ putname(tmp);
-+ }
-+ return err;
-+}
-+
- /*
- * It's inline, so penalty for filesystems that don't use sticky bit is
- * minimal.
-@@ -970,7 +1040,8 @@
- * for symlinks (where the permissions are checked later).
- * SMP-safe
- */
--int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
-+int open_namei_it(const char *pathname, int flag, int mode,
-+ struct nameidata *nd, struct lookup_intent *it)
- {
- int acc_mode, error = 0;
- struct inode *inode;
-@@ -985,7 +1056,7 @@
- */
- if (!(flag & O_CREAT)) {
- if (path_init(pathname, lookup_flags(flag), nd))
-- error = path_walk(pathname, nd);
-+ error = path_walk_it(pathname, nd, it);
- if (error)
- return error;
- dentry = nd->dentry;
-@@ -995,6 +1066,10 @@
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- if (path_init(pathname, LOOKUP_PARENT, nd))
- error = path_walk(pathname, nd);
- if (error)
-@@ -1011,7 +1086,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1020,6 +1095,7 @@
- goto exit;
- }
-
-+ it->it_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- if (!IS_POSIX_ACL(dir->d_inode))
-@@ -1054,7 +1130,8 @@
- error = -ENOENT;
- if (!dentry->d_inode)
- goto exit_dput;
-- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
-+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
-+ dentry->d_inode->i_op->follow_link2))
- goto do_link;
-
- dput(nd->dentry);
-@@ -1140,8 +1217,10 @@
- return 0;
-
- exit_dput:
-+ intent_release(dentry, it);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry, it);
- path_release(nd);
- return error;
-
-@@ -1160,7 +1239,12 @@
- * are done. Procfs-like symlinks just set LAST_BIND.
- */
- UPDATE_ATIME(dentry->d_inode);
-- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ error = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(dentry, it);
- dput(dentry);
- if (error)
- return error;
-@@ -1182,13 +1266,20 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- putname(nd->last.name);
- goto do_last;
- }
-
-+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
-+{
-+ return open_namei_it(pathname, flag, mode, nd, NULL);
-+}
-+
-+
- /* SMP-safe */
--static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
-+static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
-
-@@ -1196,7 +1287,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1242,6 +1333,7 @@
- char * tmp;
- struct dentry * dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1253,7 +1345,7 @@
- error = path_walk(tmp, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
-
- if (!IS_POSIX_ACL(nd.dentry->d_inode))
-@@ -1272,6 +1364,7 @@
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1312,6 +1405,7 @@
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1323,12 +1417,13 @@
- error = path_walk(tmp, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ dentry = lookup_create(&nd, 1, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- if (!IS_POSIX_ACL(nd.dentry->d_inode))
- mode &= ~current->fs->umask;
- error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1410,6 +1505,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_RMDIR };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1432,10 +1528,11 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1479,6 +1576,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_UNLINK };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1492,7 +1590,7 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1500,6 +1598,7 @@
- goto slashes;
- error = vfs_unlink(nd.dentry->d_inode, dentry);
- exit2:
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1546,6 +1645,7 @@
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_SYMLINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1560,10 +1660,12 @@
- error = path_walk(to, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ it.it_data = from;
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1629,6 +1731,7 @@
- int error;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_LINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1641,7 +1744,7 @@
-
- error = 0;
- if (path_init(from, LOOKUP_POSITIVE, &old_nd))
-- error = path_walk(from, &old_nd);
-+ error = path_walk_it(from, &old_nd, &it);
- if (error)
- goto exit;
- if (path_init(to, LOOKUP_PARENT, &nd))
-@@ -1651,10 +1754,12 @@
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ it.it_op = IT_LINK2;
-+ new_dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1697,7 +1802,8 @@
- * locking].
- */
- int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- struct inode *target;
-@@ -1757,6 +1863,7 @@
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1778,7 +1885,8 @@
- }
-
- int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -1809,6 +1917,7 @@
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- double_up(&old_dir->i_zombie, &new_dir->i_zombie);
- if (error)
- return error;
-@@ -1820,13 +1929,14 @@
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- if (S_ISDIR(old_dentry->d_inode->i_mode))
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -1843,6 +1953,7 @@
- int error = 0;
- struct dentry * old_dir, * new_dir;
- struct dentry * old_dentry, *new_dentry;
-+ struct lookup_intent it = { .it_op = IT_RENAME };
- struct nameidata oldnd, newnd;
-
- if (path_init(oldname, LOOKUP_PARENT, &oldnd))
-@@ -1871,7 +1982,7 @@
-
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1887,18 +1998,21 @@
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ it.it_op = IT_RENAME2;
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-
- lock_kernel();
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, &it);
- unlock_kernel();
-
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- exit4:
-+ intent_release(old_dentry, &it);
- dput(old_dentry);
- exit3:
- double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
-@@ -1947,7 +2061,8 @@
- }
-
- static inline int
--__vfs_follow_link(struct nameidata *nd, const char *link)
-+__vfs_follow_link(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
- {
- int res = 0;
- char *name;
-@@ -1960,7 +2075,7 @@
- /* weird __emul_prefix() stuff did it */
- goto out;
- }
-- res = link_path_walk(link, nd);
-+ res = link_path_walk_it(link, nd, it);
- out:
- if (current->link_count || res || nd->last_type!=LAST_NORM)
- return res;
-@@ -1982,7 +2097,13 @@
-
- int vfs_follow_link(struct nameidata *nd, const char *link)
- {
-- return __vfs_follow_link(nd, link);
-+ return __vfs_follow_link(nd, link, NULL);
-+}
-+
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
-+{
-+ return __vfs_follow_link(nd, link, it);
- }
-
- /* get the link contents into pagecache */
-@@ -2024,7 +2145,7 @@
- {
- struct page *page = NULL;
- char *s = page_getlink(dentry, &page);
-- int res = __vfs_follow_link(nd, s);
-+ int res = __vfs_follow_link(nd, s, NULL);
- if (page) {
- kunmap(page);
- page_cache_release(page);
---- linux-pristine/./fs/open.c Thu Dec 5 10:49:20 2002
-+++ linux/./fs/open.c Fri Nov 29 18:06:21 2002
-@@ -19,6 +19,9 @@
- #include <asm/uaccess.h>
-
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
-+extern int path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it);
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -94,12 +97,13 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-
-- error = user_path_walk(path, &nd);
-+ error = user_path_walk_it(path, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -144,6 +148,7 @@
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -235,8 +240,9 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -262,6 +268,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -279,8 +286,9 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
-
- if (error)
- goto out;
-@@ -307,6 +315,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -323,6 +332,7 @@
- int old_fsuid, old_fsgid;
- kernel_cap_t old_cap;
- int res;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
- return -EINVAL;
-@@ -340,13 +350,14 @@
- else
- current->cap_effective = current->cap_permitted;
-
-- res = user_path_walk(filename, &nd);
-+ res = user_path_walk_it(filename, &nd, &it);
- if (!res) {
- res = permission(nd.dentry->d_inode, mode);
- /* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
- res = -EROFS;
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
-
-@@ -362,6 +373,7 @@
- int error;
- struct nameidata nd;
- char *name;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- name = getname(filename);
- error = PTR_ERR(name);
-@@ -370,7 +382,7 @@
-
- error = 0;
- if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd))
-- error = path_walk(name, &nd);
-+ error = path_walk_it(name, &nd, &it);
- putname(name);
- if (error)
- goto out;
-@@ -382,6 +394,7 @@
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -422,6 +435,7 @@
- int error;
- struct nameidata nd;
- char *name;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- name = getname(filename);
- error = PTR_ERR(name);
-@@ -430,7 +444,7 @@
-
- path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
-- error = path_walk(name, &nd);
-+ error = path_walk_it(name, &nd, &it);
- putname(name);
- if (error)
- goto out;
-@@ -447,6 +461,7 @@
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -491,8 +506,9 @@
- struct inode * inode;
- int error;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -512,6 +528,7 @@
- error = notify_change(nd.dentry, &newattrs);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -581,10 +598,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -594,10 +613,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -631,10 +652,16 @@
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
-+
- struct file *filp_open(const char * filename, int flags, int mode)
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -642,14 +669,15 @@
- if (namei_flags & O_TRUNC)
- namei_flags |= 2;
-
-- error = open_namei(filename, namei_flags, mode, &nd);
-- if (!error)
-- return dentry_open(nd.dentry, nd.mnt, flags);
-+ error = open_namei_it(filename, namei_flags, mode, &nd, &it);
-+ if (error)
-+ return ERR_PTR(error);
-
-- return ERR_PTR(error);
-+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
- }
-
--struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it)
- {
- struct file * f;
- struct inode *inode;
-@@ -692,6 +720,7 @@
- }
- f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-
-+ intent_release(dentry, it);
- return f;
-
- cleanup_all:
-@@ -706,11 +735,17 @@
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(dentry, it);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+}
-+
- /*
- * Find an empty file descriptor entry, and mark it busy.
- */
---- linux-pristine/./fs/stat.c Thu Dec 5 10:49:22 2002
-+++ linux/./fs/stat.c Fri Nov 29 18:06:21 2002
-@@ -13,6 +13,7 @@
-
- #include <asm/uaccess.h>
-
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
- /*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
-@@ -135,13 +136,15 @@
- asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -151,13 +154,15 @@
- asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -172,13 +177,15 @@
- asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -189,13 +196,15 @@
- asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -247,20 +256,21 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_READLINK };
-
- if (bufsiz <= 0)
- return -EINVAL;
-
-- error = user_path_walk_link(path, &nd);
-+ error = user_path_walk_link_it(path, &nd, &it);
- if (!error) {
- struct inode * inode = nd.dentry->d_inode;
--
- error = -EINVAL;
- if (inode->i_op && inode->i_op->readlink &&
- !(error = do_revalidate(nd.dentry))) {
- UPDATE_ATIME(inode);
- error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
- }
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -333,12 +343,14 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -348,12 +360,14 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
---- linux-pristine/./mm/slab.c Thu Dec 5 10:50:02 2002
-+++ linux/./mm/slab.c Fri Nov 29 18:06:21 2002
-@@ -1187,6 +1187,59 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!VALID_PAGE(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
+++ /dev/null
-diff -ru ../kernel-2.4.9/drivers/block/blkpg.c ../kernel-2.4.9-lustre/drivers/block/blkpg.c
---- ../kernel-2.4.9/drivers/block/blkpg.c Wed Oct 31 17:50:05 2001
-+++ ../kernel-2.4.9-lustre/drivers/block/blkpg.c Mon May 13 14:35:35 2002
-@@ -326,7 +326,43 @@
-
- EXPORT_SYMBOL(blk_ioctl);
-
-- /*********************
-+#define NUM_DEV_NO_WRITE 16
-+static int dev_no_write[NUM_DEV_NO_WRITE];
-+
-+/*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+void dev_set_rdonly(kdev_t dev, int no_write)
-+{
-+ if (dev) {
-+ printk(KERN_WARNING "Turning device %s read-only\n",
-+ bdevname(dev));
-+ dev_no_write[no_write] = 0xdead0000 + dev;
-+ }
-+}
-+
-+int dev_check_rdonly(kdev_t dev) {
-+ int i;
-+
-+ for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
-+ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
-+ dev == (dev_no_write[i] & 0xffff))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
-+
-+
-+/*********************
- * get_last_sector()
- *
- * Description: This function will read any inaccessible blocks at the end
-diff -ru ../kernel-2.4.9/drivers/block/loop.c ../kernel-2.4.9-lustre/drivers/block/loop.c
---- ../kernel-2.4.9/drivers/block/loop.c Wed Oct 31 17:50:05 2001
-+++ ../kernel-2.4.9-lustre/drivers/block/loop.c Mon May 13 14:23:05 2002
-@@ -482,6 +482,11 @@
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
-+#endif
-+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
-diff -ru ../kernel-2.4.9/drivers/ide/ide-disk.c ../kernel-2.4.9-lustre/drivers/ide/ide-disk.c
---- ../kernel-2.4.9/drivers/ide/ide-disk.c Wed Oct 31 17:50:21 2001
-+++ ../kernel-2.4.9-lustre/drivers/ide/ide-disk.c Mon May 13 14:23:05 2002
-@@ -374,6 +374,12 @@
- */
- static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
- {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(1, HWGROUP(drive));
-+ return ide_stopped;
-+ }
-+#endif
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
- OUT_BYTE(0x00, IDE_FEATURE_REG);
-diff -ru ../kernel-2.4.9/fs/jbd/commit.c ../kernel-2.4.9-lustre/fs/jbd/commit.c
---- ../kernel-2.4.9/fs/jbd/commit.c Wed Oct 31 17:51:37 2001
-+++ ../kernel-2.4.9-lustre/fs/jbd/commit.c Mon May 13 14:23:05 2002
-@@ -462,7 +462,7 @@
- transaction's t_log_list queue, and metadata buffers are on
- the t_iobuf_list queue.
-
-- Wait for the transactions in reverse order. That way we are
-+ Wait for the buffers in reverse order. That way we are
- less likely to be woken up until all IOs have completed, and
- so we incur less scheduling load.
- */
-@@ -566,8 +566,10 @@
-
- jbd_debug(3, "JBD: commit phase 6\n");
-
-- if (is_journal_aborted(journal))
-+ if (is_journal_aborted(journal)) {
-+ unlock_journal(journal);
- goto skip_commit;
-+ }
-
- /* Done it all: now write the commit record. We should have
- * cleaned up our previous buffers by now, so if we are in abort
-@@ -577,9 +579,10 @@
- descriptor = journal_get_descriptor_buffer(journal);
- if (!descriptor) {
- __journal_abort_hard(journal);
-+ unlock_journal(journal);
- goto skip_commit;
- }
--
-+
- /* AKPM: buglet - add `i' to tmp! */
- for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
- journal_header_t *tmp =
-@@ -600,7 +603,6 @@
- put_bh(bh); /* One for getblk() */
- journal_unlock_journal_head(descriptor);
- }
-- lock_journal(journal);
-
- /* End of a transaction! Finally, we can do checkpoint
- processing: any buffers committed as a result of this
-@@ -609,6 +611,25 @@
-
- skip_commit:
-
-+ /* Call any callbacks that had been registered for handles in this
-+ * transaction. It is up to the callback to free any allocated
-+ * memory.
-+ */
-+ if (!list_empty(&commit_transaction->t_jcb)) {
-+ struct list_head *p, *n;
-+ int error = is_journal_aborted(journal);
-+
-+ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+ struct journal_callback *jcb;
-+
-+ jcb = list_entry(p, struct journal_callback, jcb_list);
-+ list_del(p);
-+ jcb->jcb_func(jcb, error);
-+ }
-+ }
-+
-+ lock_journal(journal);
-+
- jbd_debug(3, "JBD: commit phase 7\n");
-
- J_ASSERT(commit_transaction->t_sync_datalist == NULL);
-diff -ru ../kernel-2.4.9/fs/jbd/journal.c ../kernel-2.4.9-lustre/fs/jbd/journal.c
---- ../kernel-2.4.9/fs/jbd/journal.c Wed Oct 31 17:51:37 2001
-+++ ../kernel-2.4.9-lustre/fs/jbd/journal.c Mon May 13 14:23:05 2002
-@@ -56,6 +56,7 @@
- #endif
- EXPORT_SYMBOL(journal_flush);
- EXPORT_SYMBOL(journal_revoke);
-+EXPORT_SYMBOL(journal_callback_set);
-
- EXPORT_SYMBOL(journal_init_dev);
- EXPORT_SYMBOL(journal_init_inode);
-diff -ru ../kernel-2.4.9/fs/jbd/transaction.c ../kernel-2.4.9-lustre/fs/jbd/transaction.c
---- ../kernel-2.4.9/fs/jbd/transaction.c Sat Jan 26 01:42:21 2002
-+++ ../kernel-2.4.9-lustre/fs/jbd/transaction.c Mon May 13 14:23:05 2002
-@@ -59,6 +59,7 @@
- transaction->t_state = T_RUNNING;
- transaction->t_tid = journal->j_transaction_sequence++;
- transaction->t_expires = jiffies + journal->j_commit_interval;
-+ INIT_LIST_HEAD(&transaction->t_jcb);
-
- /* Set up the commit timer for the new transaction. */
- J_ASSERT (!journal->j_commit_timer_active);
-@@ -202,6 +203,20 @@
- return 0;
- }
-
-+/* Allocate a new handle. This should probably be in a slab... */
-+static handle_t *get_handle(int nblocks)
-+{
-+ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+ if (!handle)
-+ return NULL;
-+ memset(handle, 0, sizeof (handle_t));
-+ handle->h_buffer_credits = nblocks;
-+ handle->h_ref = 1;
-+ INIT_LIST_HEAD(&handle->h_jcb);
-+
-+ return handle;
-+}
-+
- /*
- * Obtain a new handle.
- *
-@@ -228,14 +243,11 @@
- handle->h_ref++;
- return handle;
- }
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = get_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = start_this_handle(journal, handle);
-@@ -334,14 +346,11 @@
-
- if (is_journal_aborted(journal))
- return ERR_PTR(-EIO);
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = get_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = try_start_this_handle(journal, handle);
-@@ -1328,6 +1337,29 @@
- #endif
-
- /*
-+ * Register a callback function for this handle. The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters. There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations. The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void journal_callback_set(handle_t *handle, void (*func)(void *, int),
-+ void *cb_data)
-+{
-+ struct journal_callback *jcb = cb_data;
-+
-+ list_add(&jcb->jcb_list, &handle->h_jcb);
-+ jcb->jcb_func = func;
-+}
-+
-+/*
- * All done for a particular handle.
- *
- * There is not much action needed here. We just return any remaining
-@@ -1409,7 +1439,10 @@
- wake_up(&journal->j_wait_transaction_locked);
- }
-
-- /*
-+ /* Move callbacks from the handle to the transaction. */
-+ list_splice(&handle->h_jcb, &transaction->t_jcb);
-+
-+ /*
- * If the handle is marked SYNC, we need to set another commit
- * going! We also want to force a commit if the current
- * transaction is occupying too much of the log, or if the
-diff -ru ../kernel-2.4.9/include/linux/blkdev.h ../kernel-2.4.9-lustre/include/linux/blkdev.h
---- ../kernel-2.4.9/include/linux/blkdev.h Thu May 9 12:59:13 2002
-+++ ../kernel-2.4.9-lustre/include/linux/blkdev.h Mon May 13 14:23:05 2002
-@@ -257,5 +257,9 @@
- #define blk_started_io(nsects) \
- atomic_add(nsects, &queued_sectors);
-
-+#define CONFIG_DEV_RDONLY
-+void dev_set_rdonly(kdev_t, int);
-+int dev_check_rdonly(kdev_t);
-+void dev_clear_rdonly(int);
- #endif
-
-diff -ru ../kernel-2.4.9/include/linux/jbd.h ../kernel-2.4.9-lustre/include/linux/jbd.h
---- ../kernel-2.4.9/include/linux/jbd.h Thu May 9 12:59:02 2002
-+++ ../kernel-2.4.9-lustre/include/linux/jbd.h Mon May 13 14:23:05 2002
-@@ -251,6 +251,13 @@
- return bh->b_private;
- }
-
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+struct journal_callback {
-+ struct list_head jcb_list;
-+ void (*jcb_func)(void *cb_data, int error);
-+ /* user data goes here */
-+};
-+
- struct jbd_revoke_table_s;
-
- /* The handle_t type represents a single atomic update being performed
-@@ -281,6 +288,12 @@
- operations */
- int h_err;
-
-+ /* List of application registered callbacks for this handle.
-+ * The function(s) will be called after the transaction that
-+ * this handle is part of has been committed to disk.
-+ */
-+ struct list_head h_jcb;
-+
- /* Flags */
- unsigned int h_sync: 1; /* sync-on-close */
- unsigned int h_jdata: 1; /* force data journaling */
-@@ -400,6 +413,10 @@
-
- /* How many handles used this transaction? */
- int t_handle_count;
-+
-+ /* List of registered callback functions for this transaction.
-+ * Called when the transaction is committed. */
-+ struct list_head t_jcb;
- };
-
-
-@@ -647,6 +664,8 @@
- extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
- extern int journal_stop(handle_t *);
- extern int journal_flush (journal_t *);
-+extern void journal_callback_set(handle_t *handle, void (*func)(void *),
-+ void *cb_data);
-
- extern void journal_lock_updates (journal_t *);
- extern void journal_unlock_updates (journal_t *);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * obd/rpc/recovd.c
- *
- * Lustre High Availability Daemon
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Peter Braam <braam@clusterfs.com>
- *
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/kmod.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_ha.h>
-
-static int connmgr_unpack_body(struct ptlrpc_request *req)
-{
- struct connmgr_body *b = lustre_msg_buf(req->rq_repmsg, 0);
- if (b == NULL) {
- LBUG();
- RETURN(-EINVAL);
- }
-
- b->generation = NTOH__u32(b->generation);
-
- return 0;
-}
-
-int connmgr_connect(struct recovd_obd *recovd, struct ptlrpc_connection *conn)
-{
- struct ptlrpc_request *req;
- struct ptlrpc_client *cl;
- struct connmgr_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- if (!recovd) {
- CERROR("no manager\n");
- LBUG();
- }
- cl = recovd->recovd_client;
-
- req = ptlrpc_prep_req(cl, conn, CONNMGR_CONNECT, 1, &size, NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- body->generation = HTON__u32(conn->c_generation);
- body->conn = (__u64)(unsigned long)conn;
- body->conn_token = conn->c_token;
- strncpy(body->conn_uuid, conn->c_local_uuid, sizeof(body->conn_uuid));
-
- req->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
- if (!rc) {
- rc = connmgr_unpack_body(req);
- if (rc)
- GOTO(out_free, rc);
- body = lustre_msg_buf(req->rq_repmsg, 0);
- CDEBUG(D_NET, "remote generation: %o\n", body->generation);
- conn->c_level = LUSTRE_CONN_CON;
- conn->c_remote_conn = body->conn;
- conn->c_remote_token = body->conn_token;
- strncpy(conn->c_remote_uuid, body->conn_uuid,
- sizeof(conn->c_remote_uuid));
- }
-
- EXIT;
- out_free:
- ptlrpc_free_req(req);
- out:
- return rc;
-}
-
-static int connmgr_handle_connect(struct ptlrpc_request *req)
-{
- struct connmgr_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc) {
- CERROR("connmgr: out of memory\n");
- req->rq_status = -ENOMEM;
- RETURN(0);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- connmgr_unpack_body(req);
-
- req->rq_connection->c_remote_conn = body->conn;
- req->rq_connection->c_remote_token = body->conn_token;
- strncpy(req->rq_connection->c_remote_uuid, body->conn_uuid,
- sizeof(req->rq_connection->c_remote_uuid));
-
- CERROR("incoming generation %d\n", body->generation);
- body = lustre_msg_buf(req->rq_repmsg, 0);
- body->generation = 4711;
- body->conn = (__u64)(unsigned long)req->rq_connection;
- body->conn_token = req->rq_connection->c_token;
-
- req->rq_connection->c_level = LUSTRE_CONN_CON;
- RETURN(0);
-}
-
-int connmgr_handle(struct obd_device *dev, struct ptlrpc_service *svc,
- struct ptlrpc_request *req)
-{
- int rc;
- ENTRY;
-
- rc = lustre_unpack_msg(req->rq_reqmsg, req->rq_reqlen);
- if (rc) {
- CERROR("Invalid request\n");
- GOTO(out, rc);
- }
-
- if (req->rq_reqmsg->type != NTOH__u32(PTL_RPC_MSG_REQUEST)) {
- CERROR("wrong packet type sent %d\n",
- req->rq_reqmsg->type);
- GOTO(out, rc = -EINVAL);
- }
-
- switch (req->rq_reqmsg->opc) {
- case CONNMGR_CONNECT:
- CDEBUG(D_INODE, "connmgr connect\n");
- rc = connmgr_handle_connect(req);
- break;
-
- default:
- rc = ptlrpc_error(svc, req);
- RETURN(rc);
- }
-
- EXIT;
-out:
- if (rc) {
- ptlrpc_error(svc, req);
- } else {
- CDEBUG(D_NET, "sending reply\n");
- ptlrpc_reply(svc, req);
- }
-
- return 0;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free 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.
- *
- * 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
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-int rd_uuid(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len=0;
- len+=snprintf(page, count, "%s\n",
- ((struct obd_device*)data)->obd_uuid);
- return len;
-
-}
-
-lprocfs_vars_t status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0},
- {0}
-};
-int rd_numdevices(char* page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct obd_type* class=(struct obd_type*)data;
- int len=0;
- len+=snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-lprocfs_vars_t status_class_var[]={
- {"status/num_devices", rd_numdevices, 0},
- {0}
-};
+++ /dev/null
-#!/bin/bash
-#
-# lustre This shell script takes care of starting and stopping Lustre
-#
-# chkconfig: 345 99 1
-# description: Lustre Lite network File System. \
-# This starts both Lustre client and server functions.
-# processname: obdctl
-# config: /etc/lustre/lustre.cfg
-# pidfile: /var/run/lustre.pid
-
-SERVICE=lustre
-LOCK=/var/lock/subsys/$SERVICE
-
-# Source function library.
-if [ -f /etc/init.d/functions ] ; then
- . /etc/init.d/functions
-fi
-
-# Source networking configuration.
-if [ -f /etc/sysconfig/network ] ; then
- . /etc/sysconfig/network
-fi
-
-# Check that networking is up.
-[ "${NETWORKING}" = "no" ] && exit 0
-
-[ -f /usr/sbin/obdctl ] || exit 0
-
-start() {
- echo -n $"Starting $SERVICE: "
- /usr/sbin/llrsetup.sh
- RETVAL=$?
- echo $SERVICE
- [ $RETVAL = 0 ] && touch $LOCK
-}
-
-stop() {
- echo -n $"Shutting down $SERVICE: "
- /usr/sbin/llcleanup.sh
- echo $SERVICE
- rm -f $LOCK
-}
-
-restart() {
- stop
- start
-}
-
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- restart
- ;;
- status)
- status $SERVICE
- ;;
- *)
- echo $"Usage: $SERVICE {start|stop|restart|status}"
- exit 1
-esac
-
-exit $RETVAL
-
+++ /dev/null
-#! /bin/sh
-# nodelustre - Start and stop Lustre on MCR nodes
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Gord Eagle <gord@clusterfs.com>, 2002-09-10
-
-# Set this to the shared config file.
-MASTER_CONFIG=http://emcri/lustre.xml
-CONFIG=/etc/lustre/lustre.xml
-COMPUTE_NODE=client
-
-LCONF=/usr/local/cfs/lustre/utils/lconf
-WGET=wget
-
-case "$1" in
-start | stop)
- # Fetch the config file. We can't use --output-document because it
- # makes Wget ignore timestamping.
- if test -n "$MASTER_CONFIG"; then
- (cd `echo "$CONFIG" | sed 's%/[^/]*$%%'` && \
- $WGET --timestamping "$MASTER_CONFIG") || exit $?
- fi
-
- # Map all client nodes to the COMPUTE_NODE virtual node.
- if test -n "$COMPUTE_NODE" && nodeattr compute; then
- node=" --node $COMPUTE_NODE"
- else
- node=
- fi
-
- # If we're stopping, do the lconf cleanup.
- if test "$1" = stop; then
- cleanup=' --cleanup'
- else
- cleanup=
- fi
-
- $LCONF$cleanup$node "$CONFIG"
- ;;
-
-*)
- echo "$0 {start|stop}" 1>&2
- exit 1
- ;;
-esac
-
-exit 0
+++ /dev/null
-#!/usr/bin/perl
-$pristine=1;
-if($ARGV[0]){chdir($ARGV[0]);}
-get_linuxdir();
-get_tag();
-get_latest_mtime();
-generate_ver();
-
-sub get_tag
-{
- $tag=open(TAG,"CVS/Tag");
- if(!$tag){
- $tag="HEAD";
- } else {
- $tag=<TAG>;
- $tag=~/.(.*)$/;
- $tag=$1;
- close(TAG);
- }
-}
-sub get_latest_mtime
-{
- use Time::Local;
- %months=("Jan"=>1,"Feb"=>2,"Mar"=>3,"Apr"=>4,"May"=>5,
- "Jun"=>6,"Jul"=>7,"Aug"=>8,"Sep"=>9,"Oct"=>10,
- "Nov"=>11,"Dec"=>12);
-
- $last_mtime=0;
- @entries=`find . -name Entries`;
- foreach $entry(@entries){
- open(ENTRY,$entry);
- while(<ENTRY>) {
- $line=$_;
- @temp_file_entry=split("/",$line);
- $time_entry=$temp_file_entry[3];
- $file=$temp_file_entry[1];
-
- $cur_dir=$entry;
- $cur_dir=~s/\/CVS\/Entries$//g;
- chomp($cur_dir);
- ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
- $atime,$mtime,$ctime,$blksize,$blocks)
- = stat($cur_dir."/".$file);
- $local_date=gmtime($mtime);
- if(! ($local_date =~ /$time_entry/) &&
- !($temp_file_entry[0] =~ /D/) &&
- !($file =~ /lustre\.spec\.in/)) {
- #print "$file\n";
- $pristine=0;
- }
-
- if($time_entry &&
- $file =~ m/\.c$|\.h$|\.am$|\.in$/ &&
- !($file =~ /lustre\.spec\.in/)){
-
- @time=split(" ",$time_entry);
- ($hours,$min,$sec)=split(":",$time[3]);
- ($mday, $mon, $year)=($time[2],$time[1],
- $time[4]);
- $secs=0;
- $mon=$months{$mon};
- if($mon>0 && $mon<13){
- $secs=timelocal($sec,$min,$hours,$mday,
- $mon,$year);
- }
- if($secs>$last_mtime){
- $last_mtime=$secs;
- $show_last=$hours.$min.$sec.
- $year.$mon.$mday;
- }
-
- }
- }
- close(ENTRY);
- }
-}
-
-sub get_linuxdir
-{
- open(CONFIG,"config.status") or die "Run ./configure first \n";
- while($line=<CONFIG>){
- $line =~ /(.*)\%\@LINUX\@\%(.*)\%g/;
- if($2){$linuxdir=$2;last;}
- }
- close(CONFIG);
- open(VER,"$linuxdir/include/linux/version.h")
- or die "Run make dep on $linuxdir \n";
- while($line=<VER>){
- $line =~ /#define UTS_RELEASE "(.*)"/;
- if($1){ $kernver=$1; last;}
- }
- chomp($kernver);
- $linuxdir=~s/\//\./g;
- close(VER);
-}
-
-sub generate_ver
-{
- print "#define BUILD_VERSION \"";
- if($pristine){
- print "$tag-$show_last-PRISTINE-$linuxdir-$kernver\"\n";
- }else{
- print "$tag-$show_last-CHANGED-$linuxdir-$kernver\"\n";
- }
-}
+++ /dev/null
-#!/bin/bash
-
-config=${1:-ba-echo.xml}
-
-LMC="save_cmd"
-LMC_REAL="../../lustre/utils/lmc -m $config"
-
-PORT=988
-TCPBUF=1048576
-OST=ba-ost-1
-CLIENT=client
-
-UUIDLIST=${UUIDLIST:-/usr/local/admin/ba-ost/UUID.txt}
-
-h2ip () {
- echo "${1}"
-}
-BATCH=/tmp/lmc-batch.$$
-save_cmd() {
- echo "$@" >> $BATCH
-}
-
-[ -f $config ] && rm $config
-
-# Client node
-${LMC} --node $CLIENT --tcpbuf $TCPBUF --net '*' tcp $PORT
-
-OBD_UUID=`awk "/$OST / { print \\$3 }" $UUIDLIST`
-[ "$OBD_UUID" ] && OBD_UUID="--obduuid=$OBD_UUID" || echo "$OST: no UUID"
-
-# server node
-${LMC} --node $OST --tcpbuf $TCPBUF --net $OST tcp $PORT
-${LMC} --node $OST --obdtype=obdecho $OBD_UUID --ost
-
-# osc on client
-${LMC} --node $CLIENT --osc OSC_$OST
-
-$LMC_REAL --batch $BATCH
-rm -f $BATCH
+++ /dev/null
-#!/bin/bash
-
-# There are configurations for three machines in this config file: the OST,
-# the MDS/client, other clients
-#
-# To start your cluster using the ba-mount.xml file that this produces, first
-# run:
-# > lconf ba-mount.xml
-# on the MDS/client, and then run:
-# > lconf --node client ba-mount.xml
-# on any other clients.
-
-config=${1:-ba-mount.xml}
-
-LMC_REAL="${LMC:-../utils/lmc} -m config"
-LMC="save_cmd"
-
-PORT=988
-TCPBUF=1048576
-OST=ba-ost-1
-MDS=mds-hostname
-
-UUIDLIST=${UUIDLIST:-/usr/local/admin/ba-ost/UUID.txt}
-
-h2ip () {
- echo "${1}"
-}
-BATCH=/tmp/lmc-batch.$$
-save_cmd() {
- echo "$@" >> $BATCH
-}
-
-[ -f $config ] && rm $config
-
-# MDS/client node
-${LMC} --node $MDS --tcpbuf $TCPBUF --net '*' tcp $PORT
-${LMC} --node $MDS --mds mds1 /tmp/mds1 50000
-
-OBD_UUID=`awk "/$OST / { print \\$3 }" $UUIDLIST`
-[ "$OBD_UUID" ] && OBD_UUID="--obduuid=$OBD_UUID" || echo "$OST: no UUID"
-
-# server node
-${LMC} --node $OST --tcpbuf $TCPBUF --net $OST tcp $PORT
-${LMC} --node $OST $OBD_UUID --ost bluearc
-
-# mount point on the MDS/client
-${LMC} --node $MDS --mtpt /mnt/lustre mds1 OSC_$OST
-
-# other clients
-${LMC} --node client --tcpbuf $TCPBUF --net '*' tcp $PORT
-${LMC} --node client --mtpt /mnt/lustre mds1 OSC_$OST
-
-$LMC_REAL --batch $BATCH
-rm -f $BATCH
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <pwd.h>
-#include <grp.h>
-
-void
-usage (char *argv0, int help)
-{
- char *progname = strrchr(argv0, '/');
-
- if (progname == NULL)
- progname = argv0;
-
- fprintf (help ? stdout : stderr,
- "Usage: %s [flags] file[s]\n",
- progname);
-
- if (!help)
- {
- fprintf (stderr, " or try '-h' for help\n");
- exit (1);
- }
-
- printf ("Check given files have...\n");
- printf (" -p permission file must have required permissions\n");
- printf (" -t dir|file|link file must be of the specified type\n");
- printf (" -l link_name file must be a link to the given name\n");
- printf (" -s size file must have the given size\n");
- printf (" -u user file must be owned by given user\n");
- printf (" -g group file must be owned by given group\n");
- printf (" -f follow symlinks\n");
- printf (" -a file must be absent\n");
- printf (" -v increase verbosity\n");
- printf (" -h print help\n");
- printf (" Exit status is 0 on success, 1 on failure\n");
-}
-
-int
-main (int argc, char **argv)
-{
- int c;
- struct stat64 buf;
- int perms = -1;
- uid_t uid = (uid_t)-1;
- gid_t gid = (gid_t)-1;
- char *type = NULL;
- long absent = 0;
- char *checklink = NULL;
- int verbose = 0;
- long long size = -1;
- int follow = 0;
- char *term;
-
- while ((c = getopt (argc, argv, "p:t:l:s:u:g:avfh")) != -1)
- switch (c)
- {
- case 'p':
- perms = (int)strtol (optarg, &term, 0);
- if (term == optarg)
- {
- fprintf (stderr, "Can't parse permission %s\n", optarg);
- return (1);
- }
- break;
-
- case 'l':
- checklink = optarg;
- break;
-
- case 's':
- size = strtoll (optarg, &term, 0);
- if (term == optarg)
- {
- fprintf (stderr, "Can't parse size %s\n", optarg);
- return (1);
- }
- break;
-
- case 'u':
- if (*optarg == '#')
- {
- uid = (uid_t)strtol (optarg + 1, &term, 0);
- if (term == optarg + 1)
- {
- fprintf (stderr, "Can't parse numeric uid %s\n", optarg);
- return (1);
- }
- } else {
- struct passwd *pw = getpwnam (optarg);
-
- if (pw == NULL)
- {
- fprintf (stderr, "Can't find user %s\n", optarg);
- return (1);
- }
- uid = pw->pw_uid;
- }
- break;
-
- case 'g':
- if (*optarg == '#')
- {
- gid = (gid_t)strtol (optarg + 1, &term, 0);
- if (term == optarg + 1)
- {
- fprintf (stderr, "Can't parse numeric gid %s\n", optarg);
- return (1);
- }
- } else {
- struct group *gr = getgrnam (optarg);
-
- if (gr == NULL)
- {
- fprintf (stderr, "Can't find group %s\n", optarg);
- return (1);
- }
- uid = gr->gr_gid;
- }
- break;
-
- case 't':
- type = optarg;
- break;
-
- case 'a':
- absent = 1;
- break;
-
- case 'v':
- verbose++;
- break;
-
- case 'f':
- follow++;
- break;
-
- case 'h':
- usage (argv[0], 1);
- return (0);
-
- default:
- usage (argv[0], 0);
- }
-
- if (optind == argc)
- usage (argv[0], 0);
-
- do
- {
- char *fname = argv[optind];
- int rc = follow ? stat64 (fname, &buf) : lstat64 (fname, &buf);
-
- if (rc != 0)
- {
- if (!(absent && errno == ENOENT))
- {
- if (verbose)
- printf ("Can't %sstat %s: %s\n",
- follow ? "" : "l",
- fname, strerror (errno));
- return (1);
- }
-
- if (verbose)
- printf ("%s: absent OK\n", fname);
- continue;
- }
-
- if (absent)
- {
- if (verbose)
- printf ("%s exists\n", fname);
- return (1);
- }
-
- if (type != NULL)
- {
- if (!strcmp (type, "d") ||
- !strcmp (type, "dir"))
- {
- if (!S_ISDIR (buf.st_mode))
- {
- if (verbose)
- printf ("%s is not a directory\n",
- fname);
- return (1);
- }
- }
- else if (!strcmp (type, "f") ||
- !strcmp (type, "file"))
- {
- if (!S_ISREG (buf.st_mode))
- {
- if (verbose)
- printf ("%s is not a regular file\n",
- fname);
- return (1);
- }
- }
- else if (!strcmp (type, "l") ||
- !strcmp (type, "link"))
- {
- if (!S_ISLNK (buf.st_mode))
- {
- if (verbose)
- printf ("%s is not a link\n",
- fname);
- return (1);
- }
- }
- else
- {
- fprintf (stderr, "Can't parse file type %s\n", type);
- return (1);
- }
-
- if (verbose)
- printf ("%s has type %s OK\n", fname, type);
- }
-
- if (perms != -1)
- {
- if ((buf.st_mode & ~S_IFMT) != perms)
- {
- if (verbose)
- printf ("%s has perms 0%o, not 0%o\n",
- fname, (buf.st_mode & ~S_IFMT), perms);
- return (1);
- }
-
- if (verbose)
- printf ("%s has perms 0%o OK\n",
- fname, perms);
- }
-
- if (size != -1)
- {
- if (buf.st_size != size)
- {
- if (verbose)
- printf ("%s has size %Ld, not %Ld\n",
- fname, (long long)buf.st_size, size);
- return (1);
- }
-
- if (verbose)
- printf ("%s has size %Ld OK\n", fname, size);
- }
-
- if (checklink != NULL)
- {
- static char lname[4<<10];
-
- rc = readlink (fname, lname, sizeof (lname) - 1);
-
- if (rc < 0)
- {
- if (verbose)
- printf ("%s: can't read link: %s\n",
- fname, strerror (errno));
- return (1);
- }
-
- lname[rc] = 0;
- if (strcmp (checklink, lname))
- {
- if (verbose)
- printf ("%s is a link to %s and not %s\n",
- fname, lname, checklink);
- return (1);
- }
-
- if (verbose)
- printf ("%s links to %s OK\n", fname, checklink);
- }
-
- if (uid != (uid_t)-1)
- {
- if (buf.st_uid != uid)
- {
- if (verbose)
- printf ("%s is owned by user #%ld and not #%ld\n",
- fname, (long)buf.st_uid, (long)uid);
- return (1);
- }
-
- if (verbose)
- printf ("%s is owned by user #%ld OK\n",
- fname, (long)uid);
- }
-
- if (gid != (gid_t)-1)
- {
- if (buf.st_gid != gid)
- {
- if (verbose)
- printf ("%s is owned by group #%ld and not #%ld\n",
- fname, (long)buf.st_gid, (long)gid);
- return (1);
- }
-
- if (verbose)
- printf ("%s is owned by group #%ld OK\n",
- fname, (long)gid);
- }
- } while (++optind < argc);
-
- return (0);
-}
+++ /dev/null
-#!/bin/sh
-# Config file for mounting a client Lustre filesystem
-SETUP_MDC=y
-SETUP_OSC=y
-OSCMT=/mnt/lustre
-SETUP_MOUNT=y
+++ /dev/null
-#!/bin/bash
-
-
-config=${1:-$(basename $0 .sh)}.xml
-
-LMC=${LMC:-../utils/lmc -m $config}
-TMP=${TMP:-/tmp}
-
-MDSDEV=$TMP/mds1
-MDSSIZE=50000
-
-OSTDEV=$TMP/ost1
-OSTSIZE=200000
-
-kver=`uname -r | cut -d "." -f 1,2`
-
-case $kver in
- 2.4) FSTYPE="--fstype=extN" ;;
- 2.5) FSTYPE="--fstype=ext3" ;;
- *) echo "Kernel version $kver not supported"
- exit 1
- ;;
-esac
-
-rm -f $config
-# create nodes
-${LMC} --add node --node localhost || exit 10
-${LMC} --add net --node localhost --nid localhost --nettype tcp || exit 11
-
-# configure mds server
-${LMC} --add mds --node localhost --mds mds1 --dev $MDSDEV --size $MDSSIZE || exit 20
-
-# configure ost
-${LMC} --add ost --node localhost --obd obd1 --obdtype obdecho || exit 30
-# configure ost
-${LMC} --add ost --node localhost --obd obd2 --obdtype obdecho || exit 30
-
-${LMC} --add cobd --node localhost --real_obd obd1 --cache_obd obd2
-
-# create client config
-# ${LMC} -m $config --add mtpt --node localhost --path /mnt/lustre --mds mds1 --obd obd1 || exit 40
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-int main(int argc, char ** argv)
-{
- int i, rc, count;
- char filename[4096];
-
- if (argc < 3) {
- printf("Usage %s filenamebase count\n", argv[0]);
- return 1;
- }
-
- if (strlen(argv[1]) > 4080) {
- printf("name too long\n");
- return 1;
- }
-
- count = strtoul(argv[2], NULL, 0);
-
-
- for (i=0 ; i < count ; i++) {
- sprintf(filename, "%s-%d", argv[1], i);
- rc = mknod(filename, S_IFREG| 0444, 0);
- if (rc) {
- printf("mknod(%s) error: %s\n",
- filename, strerror(errno));
- break;
- }
- }
- return rc;
-}
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/mman.h>
-
-// not correctly in the headers yet!!
-#ifndef O_DIRECT
-#define O_DIRECT 040000 /* direct disk access hint */
-#endif
-
-#define BLOCKSIZE 4096
-
-int main(int argc, char **argv)
-{
- int fd;
- char *buf;
- int pages;
- int rc;
-
- if (argc != 3) {
- printf("Usage: %s file nr_pages\n", argv[0]);
- return 1;
- }
-
- pages = strtoul(argv[2], 0, 0);
- printf("directio on %s for %d pages \n", argv[1], pages);
-
- buf = mmap(0, pages * BLOCKSIZE, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANON, 0, 0);
- if (!buf) {
- printf("No memory %s\n", strerror(errno));
- return 1;
- }
-
- fd = open(argv[1], O_DIRECT | O_RDWR | O_CREAT);
- if (fd == -1) {
- printf("Cannot open %s: %s\n", argv[1], strerror(errno));
- return 1;
- }
-
- rc = read(fd, buf, pages * BLOCKSIZE);
- if (rc != pages * BLOCKSIZE) {
- printf("Read error: %s, rc %d\n", strerror(errno), rc);
- return 1;
- }
-
- if ( lseek(fd, 0, SEEK_SET) != 0 ) {
- printf("Cannot seek %s\n", strerror(errno));
- return 1;
- }
-
- rc = write(fd, buf, pages * BLOCKSIZE);
- if (rc != pages * BLOCKSIZE) {
- printf("Write error %s\n", strerror(errno));
- return 1;
- }
-
- return 0;
-}
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a remote server with a real OST
-NETWORK=elan
-LOCALHOST=5
-SERVER=4
-
-[ -z "$RSH" ] && RSH=ssh
-RSH_MDS="$RSH dev$SERVER"
-RSH_OST="$RSH dev$SERVER"
-RSH_OSC=eval
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a remote server with a real OST
-NETWORK=elan
-LOCALHOST=4
-SERVER=4
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`"
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-$DBGCTL get_debug > /tmp/debug.1
-cleanup_client
-$DBGCTL get_debug > /tmp/debug.2
-cleanup_server
-
-$DBGCTL get_debug > /tmp/debug.3
-cleanup_lustre
-$DBGCTL get_debug > /tmp/debug.4
-cleanup_portals
+++ /dev/null
-#!/bin/sh
-# suggested boilerplate for test script
-
-LCONF=${LCONF:-../utils/lconf}
-NAME=${NAME:-local2-hack}
-
-config=$NAME.xml
-
-${LCONF} --reformat --gdb $config || exit 2
-
-../utils/lctl <<EOF
-newdev
-attach osc OSC2_localhost OSC2_localhost_UUID
-setup OBD_localhost_UUID NET_localhost_tcp_UUID
-newdev
-attach mdc MDC2_mds1 MDC2_uuid
-setup mds1_UUID NET_localhost_tcp_UUID
-quit
-EOF
-
-mount -t lustre_lite -o osc=OSC2_localhost_UUID,mdc=MDC2_uuid none /mnt/lustre2
+++ /dev/null
-#!/bin/sh
-# suggested boilerplate for test script
-
-LCONF=${LCONF:-../utils/lconf}
-NAME=${NAME:-local2-hack}
-
-config=$NAME.xml
-
-umount /mnt/lustre1
-umount /mnt/lustre2
-../utils/lctl <<EOF
-name2dev OSC2_localhost
-cleanup
-detach
-name2dev MDC2_mds1
-cleanup
-detach
-quit
-EOF
-
-${LCONF} --cleanup $config
+++ /dev/null
-#!/bin/sh
-
-umount /mnt/lustre2
-umount /mnt/lustre1
-../utils/lctl <<EOF
-name2dev OSC2_localhost
-cleanup
-detach
-name2dev MDC2_mds1
-cleanup
-detach
-quit
-EOF
-
-LCONF=${LCONF:-../utils/lconf}
-NAME=${NAME:-local}
-
-config=$NAME.xml
-mkconfig=./$NAME.sh
-
-if [ ! -f $config -o $mkconfig -nt $config ]; then
- sh $mkconfig $config || exit 1
-fi
-
-${LCONF} --cleanup --dump /tmp/debug $config
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`"
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-setup_portals
-setup_lustre
-
-setup_server old_fs
-setup_client
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`"
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-setup_portals
-setup_lustre
-
-setup_server new_fs
-setup_client
+++ /dev/null
-<?xml version='1.0' encoding='UTF-8'?>
-<lustre>
- <ldlm name='ldlm' uuid='ldlm_UUID'/>
- <node name='localhost' uuid='localhost_UUID'>
- <profile>
- <ldlm_ref uuidref='ldlm_UUID'/>
- <network_ref uuidref='NET_localhost_tcp_UUID'/>
- <mds_ref uuidref='mds1_UUID'/>
- <obd_ref uuidref='OBD_localhost_UUID'/>
- <ost_ref uuidref='OST_localhost_UUID'/>
- <mountpoint_ref uuidref='MNT_localhost_UUID'/>
- </profile>
- <network type='tcp' name='NET_localhost_tcp' uuid='NET_localhost_tcp_UUID'>
- <server>localhost</server>
- <port>988</port>
- </network>
- </node>
- <mds name='mds1' uuid='mds1_UUID'>
- <fstype>extN</fstype>
- <device size='50000'>/tmp/mds1</device>
- <autoformat>yes</autoformat>
- <network_ref uuidref='NET_localhost_tcp_UUID'/>
- <node_ref uuidref='localhost_UUID'/>
- </mds>
- <obd type='obdfilter' name='OBD_localhost' uuid='OBD_localhost_UUID'>
- <fstype>extN</fstype>
- <device size='200000'>/tmp/ost1</device>
- <autoformat>yes</autoformat>
- </obd>
- <osc name='OSC_localhost' uuid='OSC_localhost_UUID'>
- <ost_ref uuidref='OST_localhost_UUID'/>
- <obd_ref uuidref='OBD_localhost_UUID'/>
- </osc>
- <ost name='OST_localhost' uuid='OST_localhost_UUID'>
- <network_ref uuidref='NET_localhost_tcp_UUID'/>
- <obd_ref uuidref='OBD_localhost_UUID'/>
- </ost>
- <mountpoint name='MNT_localhost' uuid='MNT_localhost_UUID'>
- <mds_ref uuidref='mds1_UUID'/>
- <osc_ref uuidref='OSC_localhost_UUID'/>
- <path>/mnt/lustre1</path>
- </mountpoint>
-</lustre>
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE lustre SYSTEM "../utils/lustre.dtd">
-
-<lustre>
- <node name="uml1" uuid="uml1-UUID">
- <network type='tcp' name='uml1' uuid="uml1-net-UUID" >
- <server>uml1</server>
- <port>666</port>
- </network>
- <profile_ref uuidref="uml1-prof-UUID"/>
- </node>
-
- <profile name="uml1-prof" uuid="uml1-prof-UUID">
- <service_ref uuidref="uml1-net-UUID"/>
- <service_ref uuidref="ldlm-srv-UUID"/>
- <service_ref uuidref="mds1-UUID"/>
- </profile>
-
- <node name="uml2" uuid="uml2-UUID">
- <network type='tcp' name='uml2' uuid="uml2-net-UUID" >
- <server>uml2</server>
- <port>666</port>
- </network>
- <profile_ref uuidref="uml2-prof-UUID"/>
- </node>
-
- <profile name="uml2-prof" uuid="uml2-prof-UUID">
- <service_ref uuidref="uml2-net-UUID"/>
- <service_ref uuidref="ldlm-srv-UUID"/>
- <service_ref uuidref="mds2-UUID"/>
- <service_ref uuidref="mdc1-UUID"/>
- <service_ref uuidref="obd1-UUID"/>
- <service_ref uuidref="ost1-UUID"/>
- <service_ref uuidref="osc1-UUID"/>
- <service_ref uuidref="mtpt1-UUID"/>
- </profile>
-
-
- <ldlm name="ldlm-srv" uuid="ldlm-srv-UUID"/>
-
- <mdc name="mdc1" uuid="mdc1-UUID">
- <network_ref uuidref='uml1-net-UUID'/> <!-- is this extra net needed ?? -->
- <mds_ref uuidref="mds1-UUID"/>
- </mdc>
-
- <mds name="mds1" uuid="mds1-UUID">
- <network_ref uuidref="uml1-UUID"/>
- <fstype>extN</fstype>
- <device size="50000">/tmp/mds</device>
- <autoformat>yes</autoformat>
- <failover_ref uuidref="mds2-UUID"/>
- </mds>
-
- <mds name="mds2" uuid="mds2-UUID">
- <network_ref uuidref="uml2-UUID"/>
- <fstype>extN</fstype>
- <device size="50000">/tmp/mds</device>
- <autoformat>yes</autoformat>
- </mds>
-
- <osc name="osc1" uuid="osc1-UUID">
- <network_ref uuidref='uml2-net-UUID'/>
- <obd_ref uuidref="obd1-UUID"/>
- </osc>
-
- <ost name="ost1" uuid="ost1-UUID">
- <network_ref uuidref='uml2-net-UUID'/>
- <obd_ref uuidref='obd1-UUID'/>
- </ost>
-
- <obd name="obd1" uuid="obd1-UUID" type="obdfilter">
- <fstype>extN</fstype>
- <device size="100000">/tmp/obd1</device>
- <autoformat>yes</autoformat>
- </obd>
-
- <obd name="obd2" uuid="obd2-UUID" type="obdfilter">
- <fstype>extN</fstype>
- <device size="100000">/tmp/obd2</device>
- <autoformat>yes</autoformat>
- </obd>
-
- <mountpoint name="mtpt1" uuid="mtpt1-UUID">
- <path>/mnt/lustre</path>
- <mdc_ref uuidref="mdc1-UUID"/>
- <osc_ref uuidref="osc1-UUID"/>
- </mountpoint>
-
-</lustre>
-
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a metadata server
-MDSFS=ext3
-MDSDEV=/tmp/mds
-MDSSIZE=10000
-SETUP_MDS=y
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-int main(int argc, char ** argv)
-{
- int i, rc, count;
- char dirname[4096];
-
- if (argc < 3) {
- printf("Usage %s dirnamebase count\n", argv[0]);
- return 1;
- }
-
- if (strlen(argv[1]) > 4080) {
- printf("name too long\n");
- return 1;
- }
-
- count = strtoul(argv[2], NULL, 0);
-
-
- for (i=0 ; i < count ; i++) {
- sprintf(dirname, "%s-%d", argv[1], i);
- rc = mkdir(dirname, 0755);
- if (rc) {
- printf("mkdir(%s) error: %s\n",
- dirname, strerror(errno));
- break;
- }
- }
- return rc;
-}
+++ /dev/null
-#!/bin/bash
-
-config=${1:-mount2.xml}
-
-LMC=${LMC:-../utils/lmc}
-TMP=${TMP:-/tmp}
-
-MDSDEV=$TMP/mds1
-MDSSIZE=50000
-
-OSTDEV=$TMP/ost1
-OSTSIZE=100000
-
-kver=`uname -r | cut -d "." -f 1,2`
-
-case $kver in
- 2.4) FSTYPE="--fstype=extN" ;;
- 2.5) FSTYPE="--fstype=ext3" ;;
- *) echo "Kernel version $kver not supported"
- exit 1
- ;;
-esac
-
-# create nodes
-${LMC} -o $config --node localhost --net localhost tcp || exit 1
-
-# configure mds server
-${LMC} -m $config --format --node localhost $FSTYPE --mds mds1 $MDSDEV $MDSSIZE || exit 2
-
-# configure ost
-${LMC} -m $config --format --node localhost $FSTYPE --ost $OSTDEV $OSTSIZE || exit 3
-
-# create client config
-${LMC} -m $config --node localhost --mtpt /mnt/lustre mds1 OSC_localhost || exit 4
-${LMC} -m $config --node localhost --mtpt /mnt/lustre2 mds1 OSC_localhost || exit 4
+++ /dev/null
-#!/bin/bash
-#
-# Test case for 2 different filesystems mounted on the same client.
-# Uses 3 umls
-
-config=${1-mds-bug.xml}
-LMC=${LMC-../utils/lmc}
-TMP=${TMP:-/tmp}
-
-MDSDEV=$TMP/mds1
-MDSDEV2=$TMP/mds2
-MDSSIZE=50000
-
-OSTDEV1=$TMP/ost1
-OSTDEV2=$TMP/ost2
-OSTSIZE=100000
-
-MDSNODE=uml1
-OSTNODE=uml2
-CLIENT=uml3
-
-# create nodes
-${LMC} -o $config --node $MDSNODE --net $MDSNODE tcp || exit 1
-${LMC} -m $config --node $OSTNODE --net $OSTNODE tcp || exit 2
-${LMC} -m $config --node $CLIENT --net $CLIENT tcp || exit 3
-
-# configure mds server
-${LMC} -m $config --format --node $MDSNODE --mds mds1 $MDSDEV $MDSSIZE ||exit 10
-${LMC} -m $config --format --node $MDSNODE --mds mds2 $MDSDEV2 $MDSSIZE ||exit 10
-
-# configure ost
-${LMC} -m $config --lov lov1 mds1 65536 0 0 || exit 20
-${LMC} -m $config --lov lov2 mds2 65536 0 0 || exit 20
-${LMC} -m $config --node $OSTNODE --lov lov1 --ost $OSTDEV1 $OSTSIZE || exit 21
-${LMC} -m $config --node $OSTNODE --lov lov2 --ost $OSTDEV2 $OSTSIZE || exit 22
-
-# create client config
-${LMC} -m $config --node $CLIENT --mtpt /mnt/lustre mds1 lov1 || exit 30
-${LMC} -m $config --node $CLIENT --mtpt /mnt/lustre2 mds2 lov2 || exit 30
-
-
-
-
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
- int fd1, fd2;
- struct stat st1, st2;
-
- if (argc != 3) {
- printf("Usage %s file1 file2\n", argv[0]);
- return 1;
- }
-
-
- fd1 = open(argv[1], O_CREAT| O_RDWR, 0666);
- if (fd1 == -1) {
- printf("Error opening %s: %s\n", argv[1], strerror(errno));
- return errno;
- }
-
- fd2 = open(argv[2], O_RDONLY);
- if (fd2 == -1) {
- printf("Error opening %s: %s\n", argv[2], strerror(errno));
- return errno;
- }
-
- sleep(1);
-
- if ( write(fd1, "hello", strlen("hello")) != strlen("hello")) {
- printf("Error writing: %s\n", strerror(errno));
- return errno;
- }
-
- if ( fstat(fd1, &st1) ) {
- printf("Error statting %s: %s\n", argv[1], strerror(errno));
- return errno;
- }
-
- if ( fstat(fd2, &st2) ) {
- printf("Error statting %s: %s\n", argv[2], strerror(errno));
- return errno;
- }
-
- if ( st1.st_size != st2.st_size ) {
- printf("Sizes don't match %ld, %ld\n",
- st1.st_size, st2.st_size);
- return 1;
- }
-
- if ( st1.st_mtime != st2.st_mtime ) {
- printf("Mtimes don't match %ld, %ld\n",
- st1.st_mtime, st2.st_mtime);
- return 1;
- }
-
- return 0;
-}
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a remote server with a real OST
-NETWORK=tcp
-LOCALHOST=dev5
-SERVER=dev4
-PORT=1234
-
-[ -z "$RSH" ] && RSH=ssh
-SERVER_DNS=dev4
-MDS_RSH="$RSH $SERVER_DNS"
-OST_RSH="$RSH $SERVER_DNS"
+++ /dev/null
-#!/bin/sh
-# Config file for running tests on a single host over loopback TCP
-NETWORK=tcp
-LOCALHOST=localhost
-SERVER=localhost
-PORT=2432
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a remote server with a real OST
-NETWORK=tcp
-LOCALHOST=dev4
-SERVER=dev4
-PORT=2432
+++ /dev/null
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#define T1 "write before unlink\n"
-#define T2 "write after unlink\n"
-char buf[128];
-
-int main(int argc, char **argv)
-{
- int fd, rc;
-
- if (argc != 2) {
- fprintf(stderr, "usage: %s filename\n", argv[0]);
- exit(1);
- } else {
- fprintf(stderr, "congratulations - program starting\n");
- }
-
- fprintf(stderr, "opening\n");
- fd = open(argv[1], O_RDWR | O_TRUNC | O_CREAT, 0644);
- if (fd == -1) {
- fprintf(stderr, "open (before) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "writing\n");
- rc = write(fd, T1, strlen(T1) + 1);
- if (rc != strlen(T1) + 1) {
- fprintf(stderr, "write (before) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "closing\n");
- rc = close(fd);
- if (rc ) {
- fprintf(stderr, "close (before) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "opening again\n");
- fd = open(argv[1], O_RDWR );
- if (fd == -1) {
- fprintf(stderr, "open (before) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "unlinking\n");
- rc = unlink(argv[1]);
- if (rc ) {
- fprintf(stderr, "open %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "reading\n");
- rc = read(fd, buf, strlen(T1) + 1);
- if (rc != strlen(T1) + 1) {
- fprintf(stderr, "read -after %s rc %d\n", strerror(errno), rc);
- exit(1);
- }
-
- fprintf(stderr, "comparing data\n");
- if (memcmp(buf, T1, strlen(T1) + 1) ) {
- fprintf(stderr, "FAILURE: read wrong data after unlink\n");
- exit(1);
- }
-
- fprintf(stderr, "truncating\n");
- rc = ftruncate(fd, 0);
- if (rc ) {
- fprintf(stderr, "truncate -after unl %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "seeking\n");
- rc = lseek(fd, 0, SEEK_SET);
- if (rc != 0 ) {
- fprintf(stderr, "seek (before write) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "writing again\n");
- rc = write(fd, T2, strlen(T2) + 1);
- if (rc != strlen(T2) + 1) {
- fprintf(stderr, "write (before) %s (rc %d)\n", strerror(errno), rc);
- exit(1);
- }
-
- fprintf(stderr, "seeking\n");
- rc = lseek(fd, 0, SEEK_SET);
- if (rc != 0 ) {
- fprintf(stderr, "seek (before read) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "reading again\n");
- rc = read(fd, buf, strlen(T2) + 1);
- if (rc != strlen(T2) + 1) {
- fprintf(stderr, "read (after trunc) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "comparing data again\n");
- if (memcmp(buf, T2, strlen(T2) + 1) ) {
- fprintf(stderr, "FAILURE: read wrong data after trunc\n");
- exit(1);
- }
-
- fprintf(stderr, "closing again\n");
- rc = close(fd);
- if (rc ) {
- fprintf(stderr, "close (before) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "SUCCESS - goto beer\n");
- return 0;
-}
+++ /dev/null
-#!/bin/sh
-
-echo `date` creating /mnt/lustre/foo
-echo 0x80000107 > /proc/sys/lustre/fail_loc
-touch /mnt/lustre/foo &
-ps axww | grep touch
-echo "touch program suspended and hanging -- sleeping 5 secs"
-sleep 5
-ls -l /mnt/lustre/foo
-
-echo 0x0000107 > /proc/sys/lustre/fail_loc
-touch /mnt/lustre/bar &
-ps axww | grep touch
-echo "touch program will have repeated failures sleeping 10"
-
-sleep 10
-
-echo 0 > /proc/sys/lustre/fail_loc
-echo "failure cleared"
-sleep 5
-ls -l /mnt/lustre/bar
+++ /dev/null
-#!/bin/sh
-export PATH=/sbin:/usr/sbin:$PATH
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-setup_opts $@
-
-setup_portals
-setup_lustre
-
-# TODO: obdctl needs to check on the progress of each forked thread
-# (IPC SHM, sockets?) to see if it hangs.
-for CMD in test_getattr test_brw_read test_brw_write; do
- case $CMD in
- test_brw_read) CMD=test_brw; RW=r ;;
- test_brw_write) CMD=test_brw; RW=w ;;
- *) RW= ;;
- esac
-
- setup_server || exit -1
- setup_client || exit -1
-
- OSC_DEVNO=`$OBDCTL name2dev OSCDEV`
-
- # We use '--threads 1 X' instead of '--device X' so that
- # obdctl can modnitor the forked thread for progress (TODO).
- $OBDCTL --threads 1 v $OSC_DEVNO $CMD 1 $RW v || exit -1
- $OBDCTL --threads 1 v $OSC_DEVNO $CMD 100 $RW v || exit -1
-
- #cleanup_client || exit -1
- #cleanup_server || exit -1
-
- #setup_server || exit -1
- #setup_client || exit -1
-
- debug_server_off
- debug_client_off
- $OBDCTL --threads 1 v $OSC_DEVNO $CMD 10000 $RW 100 || exit -1
- $OBDCTL --threads 1 v $OSC_DEVNO $CMD 1000000 $RW -10 || exit -1
-
- debug_server_on
- debug_client_on
- $OBDCTL --threads 2 v $OSC_DEVNO $CMD 100 $RW v || exit -1
-
- debug_server_off
- debug_client_off
- $OBDCTL --threads 2 v $OSC_DEVNO $CMD 10000 $RW 100 || exit -1
- $OBDCTL --threads 2 v $OSC_DEVNO $CMD 1000000 $RW -30 || exit -1
-
- $OBDCTL --threads 10 v $OSC_DEVNO $CMD 10000 $RW 1000 || exit -1
- $OBDCTL --threads 100 v $OSC_DEVNO $CMD 10000 $RW -30 || exit -1
-
- cleanup_client || exit -1
- cleanup_server || exit -1
-done
-
-cleanup_lustre
-cleanup_portals
+++ /dev/null
-!/bin/bash
-
-echo '=============================== test 1'
-mkdir /mnt/lustre/d1
-mkdir /mnt/lustre/d1/d2
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '=============================== test 2'
-mkdir /mnt/lustre/d2
-touch /mnt/lustre/d2/f
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 3
-mkdir /mnt/lustre/d3
-umount /mnt/lustre
-../utils/lconf --start 70 local.xml
-touch /mnt/lustre/d3/f
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 4
-mkdir /mnt/lustre/d4
-umount /mnt/lustre
-../utils/lconf --start 70 local.xml
-mkdir /mnt/lustre/d4/d2
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 5
-mkdir /mnt/lustre/d5
-mkdir /mnt/lustre/d5/d2
-chmod 0666 /mnt/lustre/d5/d2
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 6
-touch /mnt/lustre/f6
-chmod 0666 /mnt/lustre/f6
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 7
-mkdir /mnt/lustre/d7
-./mcreate /mnt/lustre/d7/f
-chmod 0666 /mnt/lustre/d7/f
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 8
-mkdir /mnt/lustre/d8
-touch /mnt/lustre/d8/f
-chmod 0666 /mnt/lustre/d8/f
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-
-echo '=============9=================' test 9
-mkdir /mnt/lustre/d9
-mkdir /mnt/lustre/d9/d2
-mkdir /mnt/lustre/d9/d2/d3
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-
-echo '===============================' test 10
-mkdir /mnt/lustre/d10
-mkdir /mnt/lustre/d10/d2
-touch /mnt/lustre/d10/d2/f
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 11
-mkdir /mnt/lustre/d11
-mkdir /mnt/lustre/d11/d2
-chmod 0666 /mnt/lustre/d11/d2
-chmod 0555 /mnt/lustre/d11/d2
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 12
-mkdir /mnt/lustre/d12
-touch /mnt/lustre/d12/f
-chmod 0666 /mnt/lustre/d12/f
-chmod 0555 /mnt/lustre/d12/f
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 13
-mkdir /mnt/lustre/d13
-cp /etc/passwd /mnt/lustre/d13/f
-> /mnt/lustre/d13/f
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 14
-mkdir /mnt/lustre/d14
-touch /mnt/lustre/d14/f
-rm /mnt/lustre/d14/f
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 15
-mkdir /mnt/lustre/d15
-touch /mnt/lustre/d15/f
-mv /mnt/lustre/d15/f /mnt/lustre/d15/f2
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
-
-echo '===============================' test 16
-mkdir /mnt/lustre/d16
-touch /mnt/lustre/d16/f
-rm -rf /mnt/lustre/d16/f
-umount /mnt/lustre
-dmesg | grep -i destruct
-../utils/lconf --start 70 local.xml
+++ /dev/null
-#!/bin/bash
-
-export NAME=$NAME
-clean() {
- echo -n "cleanup..."
- sh llmount2-hackcleanup.sh > /dev/null
-}
-
-CLEAN=clean
-start() {
- echo -n "mounting..."
- sh llmount2-hack.sh > /dev/null
- echo -n "mounted"
-}
-START=start
-
-error () {
- echo $1
- exit 1
-}
-
-mkdir -p /mnt/lustre2
-mount | grep /mnt/lustre2 || $START
-
-echo -n "test 1: check create on 2 mtpt's..."
-touch /mnt/lustre1/f1
-[ -f /mnt/lustre2/f1 ] || error "test 1 failure"
-echo "pass"
-
-echo -n "test 2: check attribute updates on 2 mtpt's..."
-chmod a+x /mnt/lustre2/f1
-[ -x /mnt/lustre1/f1 ] || error "test 2 failure"
-echo "pass"
-
-echo -n "test 3: check after remount attribute updates on 2 mtpt's..."
-chmod a-x /mnt/lustre2/f1
-$CLEAN
-$START
-
-[ ! -x /mnt/lustre1/f1 ] || error "test 3 failure"
-echo "pass"
-
-echo -n "test 4: symlink on one mtpt, readlink on another..."
-( cd /mnt/lustre1 ; ln -s this/is/good lnk )
-
-[ "Xthis/is/good" = X`perl -e 'print readlink("/mnt/lustre2/lnk");'` ] || error "test 4 fails"
-echo "pass"
-
-echo -n "test 5: fstat validation on multiple mount points..."
-./multifstat /mnt/lustre1/fstatfile /mnt/lustre2/fstatfile || error "test 5 fails"
-echo "pass"
-
-echo -n "test 9: remove of open file on other node..."
-touch /mnt/lustre1/f9
-tail -f /mnt/lustre1/f9 &
-rm /mnt/lustre2/f9
-kill %1
-cat /mnt/lustre1/f9 && error "test 9 fails"
-echo "pass"
-
-$CLEAN
-
-exit
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-int main(int argc, char ** argv)
-{
- int rc;
- struct stat buf;
-
- if (argc < 2) {
- printf("Usage %s filename\n", argv[0]);
- return 1;
- }
-
- rc = stat(argv[1], &buf);
- if (rc) {
- printf("stat(%s) error: %s\n", argv[1], strerror(errno));
- }
- return rc;
-}
+++ /dev/null
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
- int fd, rc;
- int i = 0;
- char buf[4096];
-
- memset(buf, 0, 4096);
-
- if (argc != 2) {
- printf("Usage openme <filename>\n");
- exit(1);
- }
-
- fd = open(argv[1], O_RDWR | O_CREAT, 0600);
- if (fd == -1) {
- printf("Error opening %s\n", argv[1]);
- exit(1);
- }
-
- while (1) {
- sprintf(buf, "write %d\n", i);
- rc = write(fd, buf, sizeof(buf));
- sleep(1);
- }
- return 0;
-}
+++ /dev/null
-#!/bin/sh
-
-if [ -z "$1" ]; then
- echo "No UUID given to Lustre upcall!" | wall
- exit 1
-fi
-
-# FIXME: OSTHOST can't be hard-coded!
-OST=$1
-OSTHOST=dev7
-LUSTRE=/home/pschwan/lustre/lustre
-
-while ( ! ping -c 1 -w 3 $OSTHOST ) ; do
- sleep 2
-done;
-
-echo -n "OST $OSTHOST UUID $OST responding to pings : "
-date
-
-$LUSTRE/utils/lctl <<EOF
-network tcp
-close_uuid $OST
-del_uuid $OST
-connect $OSTHOST 988
-add_uuid $OST $OSTHOST
-quit
-EOF
-
-$LUSTRE/utils/lctl <<EOF
-device \$RPCDEV
-probe
-newconn $OST
-quit
-EOF
+++ /dev/null
-#!/usr/bin/env python
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Author: Ravindranadh Chowdary Sahukara <s-ravindranadh_chowdary@hp.com>
-
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free 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.
-#
-# 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
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-"""
-genXml - lustre xml configurtion data generator
-
- Basic plan for genXml usage:
-#generate xml file
-./lmc --output config.xml --node <node-name> --ldapserver <server-name>
-./lmc --merge config.xml --node <node-name> --ldapserver <server-name>
-
-#This reads arguments from files in default locations and generate the xml file
-./genConfig
-
-"""
-
-import sys, os, getopt, string, socket
-import xml.dom.minidom
-from xml.dom.ext import PrettyPrint
-from lutils import *
-
-lustreNodes = {}
-lustreNode = 0
-lustreClient = 0
-lustreMds = {}
-lustreOst = {}
-#lustreOsc = 0
-tmpuuid = ""
-ConnId = 0
-
-# Determine full path to use for an external command
-# searches dirname(argv[0]) first, then PATH
-"""
-def find_prog(cmd):
- syspath = string.split(os.environ['PATH'], ':')
- cmdpath = os.path.dirname(sys.argv[0])
- syspath.insert(0, cmdpath);
- syspath.insert(0, os.path.join(cmdpath, '../../portals/linux/utils/'))
- for d in syspath:
- prog = os.path.join(d,cmd)
- if os.access(prog, os.X_OK):
- return prog
- return ''
-"""
-# ============================================================
-# handle lmc interface
-class LMCInterface:
- """
- Manage communication with lmc
- """
-
- def __init__(self, cmd):
- """
- Initialize close by finding the lmc script.
- """
- self.lmc = find_prog(cmd)
- if not self.lmc:
- debug('! lmc not found')
- raise CommandError('lmc', "unable to find lmc script .")
- self.lmc = 'lmc'
-
- def run(self, cmds):
- """
- run lmc
- the cmds are written to stdin of lmc
- """
- debug("+", self.lmc, cmds)
- p = popen2.Popen3(self.lmc, 1)
- p.tochild.write(cmds + "\n")
- p.tochild.close()
- out = p.fromchild.readlines()
- err = p.childerr.readlines()
- ret = p.wait()
- if os.WIFEXITED(ret):
- rc = os.WEXITSTATUS(ret)
- else:
- rc = 0
- if rc or len(err):
- print err, rc
- raise CommandError(self.lmc, err, rc)
- return rc, out
-
- def runcmd(self, *args):
- """
- run lmc using the command line
- """
- cmd = string.join(map(str,args))
- debug("+", self.lmc, cmd)
- rc, out = run(self.lmc, cmd)
- if rc:
- raise CommandError(self.lmc, out, rc)
- return rc, out
-
-
-def genXml(nodename, ldapserver, port, options):
- global ldlm_name
- global ldlm_uuid
- global lustreNode
- global lustreClient
- global lustreMds
- global lustreOst
- global ConnId
- lovs = []
- if options.has_key('output'):
- outFile = options['output']
- elif options.has_key('merge'):
- outFile = options['merge']
-
- LMC = LMCInterface('lmc')
- base = "fs=lustre"
- myCon=MyConn(ldapserver,port)
- myCon.open()
- ConnId=myCon.id
- lustreNode = LustreNode(nodename)
- if not options.has_key('add'):
- lustreNode.getEntry_from_ldap(ConnId,base)
- for i in range(len(lustreNode.netUUIDs)):
- NET = lustreNode.lustreNet[i]
- if options.has_key('output'):
- cmds = """ --output %s --node %s --net %s %s """ % (outFile, lustreNode.id, NET.id, NET.netType)
- elif options.has_key('merge'):
- cmds = """ --merge %s --node %s --net %s %s """ % (outFile, lustreNode.id, NET.netType)
- LMC.runcmd(cmds)
-
-
-
- mds_uuids = lustreNode.lustreNodeProfile.mdsUUIDs
- for tmpuuid in mds_uuids:
- lustreMds[tmpuuid]=LustreMds()
- lustreMds[tmpuuid].getEntry_from_ldap(ConnId,base,tmpuuid)
- MDS = lustreMds[tmpuuid]
- Dev = lustreMds[tmpuuid].lustreDev
- cmds = """ --merge %s --node %s --mds %s %s %s """ % (outFile, lustreNode.id, lustreMds[tmpuuid].devName,Dev.device,Dev.size)
- LMC.runcmd(cmds)
- LOV = lustreMds[tmpuuid].lustreLov
- lovs.append(LOV)
- cmds = """ --merge %s --lov %s %s %s %s %s""" % (outFile, LOV.devName, MDS.devName, LOV.stripeSize, LOV.stripeCount, LOV.pattern)
- LMC.runcmd(cmds)
-
-
- ost_uuids = lustreNode.lustreNodeProfile.ostUUIDs
- for tmpuuid in ost_uuids:
- lustreOst[tmpuuid] = LustreOst()
- lustreOst[tmpuuid].getEntry_from_ldap(ConnId,base,tmpuuid)
- OST = lustreOst[tmpuuid]
- DEV = OST.lustreObd.lustreDev
- for i in range(len(lovs)):
- for oscuuid in lovs[i].oscUUIDs:
- OSC = lovs[i].lustreOsc[oscuuid]
- if OST.ostUUID == OSC.ostUUID:
- cmds = """ --merge %s --node %s --lov %s --ost %s %s """ % (outFile, lustreNode.id, LOV.devName, DEV.device, DEV.size)
- LMC.runcmd(cmds)
- else:
- pass
- #print "not matched:", OSC.ostUUID
-
-
- if lustreNode.lustreNodeProfile.clientUUID:
- client_uuid = ""
- lustreClient = LustreClient(lustreNode)
- client_uuid = lustreNode.lustreNodeProfile.clientUUID
- lustreClient.getEntry_from_ldap(ConnId,base,str(client_uuid))
- for mnt_uuid in lustreClient.mountUUIDs:
- tmpuuid = mnt_uuid
- MTPT = lustreClient.lustreMount[mnt_uuid]
- MDS = MTPT.lustreMds
- LOV = MTPT.lustreLov
- cmds = """ --merge %s --node %s --mtpt %s %s %s """ % (outFile, lustreNode.id, MTPT.mountPath, MDS.devName, LOV.devName)
- LMC.runcmd(cmds)
-
-
-
-############################################################
-# Command line processing
-#
-def parse_cmdline(argv):
- short_opts = "ho:i:m:"
- long_opts = ["node=", "merge=", "output=", "ldapserver=", "port="]
- opts = []
- args = []
- options = {}
- try:
- opts, args = getopt.getopt(argv, short_opts, long_opts)
- except getopt.error:
- print "invalid opt"
- usage()
-
- for o, a in opts:
- # Commands to create new devices
- if o == "--node":
- options['node'] = a
- if o == "--ldapserver":
- options['ldapserver'] = a
- if o == "--port":
- options['port'] = a
-
- # Options for commands
-
- # lmc options
- if o in ("-h", "--help"):
- usage()
- if o in ("-o", "--output"):
- options['output'] = a
- if o in ("-m", "--merge"):
- options['merge'] = a
- if o == "--add":
- options['add'] = a
-
- return options, args
-
-
-program_name = ""
-def main():
- global program_name
- arglist = string.split(sys.argv[0], '/')
- program_name = arglist[len(arglist)-1]
- if program_name != 'genConfig':
- options, args = parse_cmdline(sys.argv[1:])
- outFile = '-'
- if options.has_key('ldapserver'):
- ldapserver = options['ldapserver']
-
- if options.has_key('node'):
- nodename = options['node']
- else:
- nodename = socket.gethostname()
-
- if options.has_key('port'):
- port = int(options['port'])
- else:
- port = 389
-
- if options.has_key('add'):
- outFile = options['add']
-
- genXml(nodename,ldapserver,port,options)
- else:
- options = {}
- args = []
- outFile = '/etc/lustre/config.xml'
- fp=open("/etc/lustre/ldapserver","r")
- line=fp.readline()
- fp.close()
- ldapinfo=string.split(line,':')
- ldapserver=ldapinfo[0]
- port=ldapinfo[1]
- nodename = socket.gethostname()
- nodename = 'lustre4'
- genXml(nodename,ldapserver,port,options)
-
-if __name__ == "__main__":
- main()
-
-
+++ /dev/null
-#!/bin/sh
-
-echo -n `date` >> /tmp/halog
-echo "- please supply a new mds" >> /tmp/halog
-
-echo "- suppose we have a new one" >> /tmp/halog
-sleep 1
-
-/usr/src/obd/utils/obdctl <<EOF
-name2dev RPCDEV
-newconn
-EOF
-
+++ /dev/null
-#!/usr/bin/python2
-# Author: Ravindranadh Chowdary Sahukara <s-ravindranadh_chowdary@hp.com>
-
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free 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.
-#
-# 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
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-import lustreLdap, sys, os, socket, string, popen2
-
-
-
-# Determine full path to use for an external command
-# searches dirname(argv[0]) first, then PATH
-def find_prog(cmd):
- syspath = string.split(os.environ['PATH'], ':')
- cmdpath = os.path.dirname(sys.argv[0])
- syspath.insert(0, cmdpath);
- syspath.insert(0, os.path.join(cmdpath, '../../portals/linux/utils/'))
- for d in syspath:
- prog = os.path.join(d,cmd)
- if os.access(prog, os.X_OK):
- return prog
- return ''
-
-# handle lctl interface
-class LCTLInterface:
- """
- Manage communication with lctl
- """
-
- def __init__(self, cmd):
- """
- Initialize close by finding the lctl binary.
- """
- self.lctl = find_prog(cmd)
- if not self.lctl:
- lustreLdap.debug('! lctl not found')
- self.lctl = 'lctl'
-
- def run(self, cmds):
- """
- run lctl
- the cmds are written to stdin of lctl
- lctl doesn't return errors when run in script mode, so
- stderr is checked
- should modify command line to accept multiple commands, or
- create complex command line options
- """
- lustreLdap.debug("+", self.lctl, cmds)
- p = popen2.Popen3(self.lctl, 1)
- p.tochild.write(cmds + "\n")
- p.tochild.close()
- out = p.fromchild.readlines()
- err = p.childerr.readlines()
- ret = p.wait()
- if os.WIFEXITED(ret):
- rc = os.WEXITSTATUS(ret)
- else:
- rc = 0
- if rc or len(err):
- lustreLdap.debug(self.lctl, err, rc)
- sys.exit(1)
- return rc, out
-
- def runcmd(self, *args):
- """
- run lctl using the command line
- """
- cmd = string.join(map(str,args))
- debug("+", self.lctl, cmd)
- rc, out = run(self.lctl, cmd)
- if rc:
- lustreLdap.debug(self.lctl, out, rc)
- sys.exit(1)
- return rc, out
-
-def network(failedUUID, failoverUUID, failoverNode, failovernetType, failoverPort):
- lctl=LCTLInterface('lctl')
- if failovernetType == 'tcp':
- cmd = """
- network %s
- close_uuid %s
- del_uuid %s
- connect %s %d
- add_uuid %s %s
- name2dev RPCDEV
- probe
- newconn %s
- quit""" % (failovernetType, failedUUID, failedUUID, failoverNode, int(failoverPort), failoverUUID, failoverNode, failoverUUID)
- print cmd
- lctl.run(cmd)
-
-
-def main():
- FailedNetUUID = sys.argv[1:][0]
- print FailedNetUUID
- print "ha assist checking for problems"
- if not os.access("/tmp/halog", os.R_OK):
- print "no problems ..exiting"
- sys.exit(1)
-
- try:
- fp = open("/etc/lustre/ldapserver", "r")
- line = fp.readline()
- fp.close()
- except IOError, e:
- log(e)
-
- ldapinfo = string.split(line,':')
- server = ldapinfo[0]
- port = ldapinfo[1]
- base = "fs=lustre"
- myCon = lustreLdap.MyConn(server, port)
- myCon.open()
-
- connId = myCon.id
- # initilize the new network object class
- lustreNet = lustreLdap.LustreNet()
- # brings the failed network object class from LDAP the query is
- lustreNet.getEntry_from_ldap(connId, base, FailedNetUUID)
-
- nodename = socket.gethostname()
-
- nodename = lustreNet.id
- failoverNetUUID = lustreNet.fnetUUID
- #Query the failover network information
- lustreNet = lustreLdap.LustreNet()
- lustreNet.getEntry_from_ldap(connId, base, failoverNetUUID)
-
- network(FailedNetUUID, failoverNetUUID, lustreNet.id, lustreNet.netType, lustreNet.port)
-
-
-
-if __name__ == "__main__":
- main()
-
-
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Author: Robert Read <rread@clusterfs.com>
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free 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.
-#
-# 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
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# lconf - lustre configuration tool
-#
-# lconf is the main driver script for starting and stopping
-# lustre filesystem services.
-#
-# Based in part on the XML obdctl modifications done by Brian Behlendorf
-
-import sys, getopt
-import string, os, stat, popen2, socket, time, random
-import re, exceptions
-import xml.dom.minidom
-
-# Global parameters
-TCP_ACCEPTOR = ''
-MAXTCPBUF = 1048576
-DEFAULT_TCPBUF = 1048576
-#
-# Maximum number of devices to search for.
-# (the /dev/loop* nodes need to be created beforehand)
-MAX_LOOP_DEVICES = 256
-PORTALS_DIR = '@PORTALSLOC@'
-
-first_cleanup_error = 0
-def cleanup_error(rc):
- global first_cleanup_error
- if not first_cleanup_error:
- first_cleanup_error = rc
-
-
-def usage():
- print """usage: lconf config.xml
-
-config.xml Lustre configuration in xml format.
---get <url> URL to fetch a config file
---node <nodename> Load config for <nodename>
--d | --cleanup Cleans up config. (Shutdown)
--f | --force Forced unmounting and/or obd detach during cleanup
--v | --verbose Print system commands as they are run
--h | --help Print this help
---gdb Prints message after creating gdb module script
- and sleeps for 5 seconds.
--n | --noexec Prints the commands and steps that will be run for a
- config without executing them. This can used to check if a
- config file is doing what it should be doing. (Implies -v)
---nomod Skip load/unload module step.
---nosetup Skip device setup/cleanup step.
---reformat Reformat all devices (without question)
---dump <file> Dump the kernel debug log before portals is unloaded
---minlevel <num> Specify the minimum level of services to configure/cleanup (default 0)
---maxlevel <num> Specify the maximum level of services to configure/cleanup (default 100)
- Levels are aproximatly like:
- 10 - network
- 20 - device, ldlm
- 30 - obd, mdd
- 40 - mds, ost
- 50 - mdc, osc
- 60 - lov, lovconfig
- 70 - mountpoint, echo_client
-"""
- TODO = """
---ldap server LDAP server with lustre config database
---makeldiff Translate xml source to LDIFF
-This are perhaps not needed:
---lustre="src dir" Base directory of lustre sources. Used to search
- for modules.
---portals=src Portals source
-"""
- sys.exit()
-
-# ============================================================
-# Config parameters, encapsulated in a class
-class Config:
- def __init__(self):
- # flags
- self._noexec = 0
- self._verbose = 0
- self._reformat = 0
- self._cleanup = 0
- self._gdb = 0
- self._nomod = 0
- self._nosetup = 0
- self._force = 0
- # parameters
- self._modules = None
- self._node = None
- self._url = None
- self._gdb_script = '/tmp/ogdb'
- self._debug_path = '/tmp/lustre-log'
- self._dump_file = None
- self._src_dir = None
- self._minlevel = 0
- self._maxlevel = 100
-
- def verbose(self, flag = None):
- if flag: self._verbose = flag
- return self._verbose
-
- def noexec(self, flag = None):
- if flag: self._noexec = flag
- return self._noexec
-
- def reformat(self, flag = None):
- if flag: self._reformat = flag
- return self._reformat
-
- def cleanup(self, flag = None):
- if flag: self._cleanup = flag
- return self._cleanup
-
- def gdb(self, flag = None):
- if flag: self._gdb = flag
- return self._gdb
-
- def nomod(self, flag = None):
- if flag: self._nomod = flag
- return self._nomod
-
- def nosetup(self, flag = None):
- if flag: self._nosetup = flag
- return self._nosetup
-
- def force(self, flag = None):
- if flag: self._force = flag
- return self._force
-
- def node(self, val = None):
- if val: self._node = val
- return self._node
-
- def url(self, val = None):
- if val: self._url = val
- return self._url
-
- def gdb_script(self):
- if os.path.isdir('/r'):
- return '/r' + self._gdb_script
- else:
- return self._gdb_script
-
- def debug_path(self):
- if os.path.isdir('/r'):
- return '/r' + self._debug_path
- else:
- return self._debug_path
-
- def src_dir(self, val = None):
- if val: self._src_dir = val
- return self._src_dir
-
- def dump_file(self, val = None):
- if val: self._dump_file = val
- return self._dump_file
-
- def minlevel(self, val = None):
- if val: self._minlevel = int(val)
- return self._minlevel
-
- def maxlevel(self, val = None):
- if val: self._maxlevel = int(val)
- return self._maxlevel
-
-
-
-config = Config()
-
-# ============================================================
-# debugging and error funcs
-
-def fixme(msg = "this feature"):
- raise LconfError, msg + ' not implmemented yet.'
-
-def panic(*args):
- msg = string.join(map(str,args))
- if not config.noexec():
- raise LconfError(msg)
- else:
- print "! " + msg
-
-def log(*args):
- msg = string.join(map(str,args))
- print msg
-
-def logall(msgs):
- for s in msgs:
- print string.strip(s)
-
-def debug(*args):
- if config.verbose():
- msg = string.join(map(str,args))
- print msg
-
-# ============================================================
-# locally defined exceptions
-class CommandError (exceptions.Exception):
- def __init__(self, cmd_name, cmd_err, rc=None):
- self.cmd_name = cmd_name
- self.cmd_err = cmd_err
- self.rc = rc
-
- def dump(self):
- import types
- if type(self.cmd_err) == types.StringType:
- if self.rc:
- print "! %s (%d): %s" % (self.cmd_name, self.rc, self.cmd_err)
- else:
- print "! %s: %s" % (self.cmd_name, self.cmd_err)
- elif type(self.cmd_err) == types.ListType:
- if self.rc:
- print "! %s (error %d):" % (self.cmd_name, self.rc)
- else:
- print "! %s:" % (self.cmd_name)
- for s in self.cmd_err:
- print "> %s" %(string.strip(s))
- else:
- print self.cmd_err
-
-class LconfError (exceptions.Exception):
- def __init__(self, args):
- self.args = args
-
-
-# ============================================================
-# handle lctl interface
-class LCTLInterface:
- """
- Manage communication with lctl
- """
-
- def __init__(self, cmd):
- """
- Initialize close by finding the lctl binary.
- """
- self.lctl = find_prog(cmd)
- if not self.lctl:
- if config.noexec():
- debug('! lctl not found')
- self.lctl = 'lctl'
- else:
- raise CommandError('lctl', "unable to find lctl binary.")
-
- def run(self, cmds):
- """
- run lctl
- the cmds are written to stdin of lctl
- lctl doesn't return errors when run in script mode, so
- stderr is checked
- should modify command line to accept multiple commands, or
- create complex command line options
- """
- debug("+", self.lctl, cmds)
- if config.noexec(): return (0, [])
- p = popen2.Popen3(self.lctl, 1)
- p.tochild.write(cmds + "\n")
- p.tochild.close()
- out = p.fromchild.readlines()
- err = p.childerr.readlines()
- ret = p.wait()
- if os.WIFEXITED(ret):
- rc = os.WEXITSTATUS(ret)
- else:
- rc = 0
- if rc or len(err):
- raise CommandError(self.lctl, err, rc)
- return rc, out
-
- def runcmd(self, *args):
- """
- run lctl using the command line
- """
- cmd = string.join(map(str,args))
- debug("+", self.lctl, cmd)
- rc, out = run(self.lctl, cmd)
- if rc:
- raise CommandError(self.lctl, out, rc)
- return rc, out
-
-
- def network(self, net, nid):
- """ initialized network and add "self" """
- # Idea: "mynid" could be used for all network types to add "self," and then
- # this special case would be gone and the "self" hack would be hidden.
- if net in ('tcp', 'toe'):
- cmds = """
- network %s
- mynid %s
- add_uuid self %s
- quit""" % (net, nid, nid)
- else:
- cmds = """
- network %s
- add_uuid self %s
- quit""" % (net, nid)
-
- self.run(cmds)
-
- # create a new connection
- def connect(self, net, nid, port, servuuid, send_mem, recv_mem):
- if net in ('tcp', 'toe'):
- cmds = """
- network %s
- add_uuid %s %s
- send_mem %d
- recv_mem %d
- connect %s %d
- quit""" % (net, servuuid, nid, send_mem, recv_mem, nid, port, )
- else:
- cmds = """
- network %s
- add_uuid %s %s
- connect %s %d
- quit""" % (net, servuuid, nid, nid, port, )
-
- self.run(cmds)
-
- # add a route to a range
- def add_route(self, net, gw, lo, hi):
- cmds = """
- network %s
- add_route %s %s %s
- quit """ % (net, gw, lo, hi)
- self.run(cmds)
-
-
- def del_route(self, net, gw, lo, hi):
- cmds = """
- ignore_errors
- network %s
- del_route %s
- quit """ % (net, lo)
- self.run(cmds)
-
- # add a route to a host
- def add_route_host(self, net, uuid, gw, tgt):
- cmds = """
- network %s
- add_uuid %s %s
- add_route %s %s
- quit """ % (net, uuid, tgt, gw, tgt)
- self.run(cmds)
-
- # add a route to a range
- def del_route_host(self, net, uuid, gw, tgt):
- cmds = """
- ignore_errors
- network %s
- del_uuid %s
- del_route %s
- quit """ % (net, uuid, tgt)
- self.run(cmds)
-
- # disconnect one connection
- def disconnect(self, net, nid, port, servuuid):
- cmds = """
- ignore_errors
- network %s
- disconnect %s
- del_uuid %s
- quit""" % (net, nid, servuuid)
- self.run(cmds)
-
- # disconnect all
- def disconnectAll(self, net):
- cmds = """
- ignore_errors
- network %s
- del_uuid self
- disconnect
- quit""" % (net)
- self.run(cmds)
-
- # create a new device with lctl
- def newdev(self, attach, setup = ""):
- cmds = """
- newdev
- attach %s
- setup %s
- quit""" % (attach, setup)
- self.run(cmds)
-
- # cleanup a device
- def cleanup(self, name, uuid):
- cmds = """
- ignore_errors
- device $%s
- cleanup
- detach %s
- quit""" % (name, ('', 'force')[config.force()])
- self.run(cmds)
-
- # create an lov
- def lov_setconfig(self, uuid, mdsuuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist):
- cmds = """
- device $%s
- probe
- lov_setconfig %s %d %d %d %s %s
- quit""" % (mdsuuid, uuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist)
- self.run(cmds)
-
- # dump the log file
- def dump(self, dump_file):
- cmds = """
- debug_kernel %s 1
- quit""" % (dump_file)
- self.run(cmds)
-
- # get list of devices
- def device_list(self):
- rc, out = self.runcmd('device_list')
- return out
-
- # get lustre version
- def lustre_version(self):
- rc, out = self.runcmd('version')
- return out
-
-# ============================================================
-# Various system-level functions
-# (ideally moved to their own module)
-
-# Run a command and return the output and status.
-# stderr is sent to /dev/null, could use popen3 to
-# save it if necessary
-def run(*args):
- cmd = string.join(map(str,args))
- debug ("+", cmd)
- if config.noexec(): return (0, [])
- f = os.popen(cmd + ' 2>&1')
- out = f.readlines()
- ret = f.close()
- if ret:
- ret = ret >> 8
- else:
- ret = 0
- return (ret, out)
-
-# Run a command in the background.
-def run_daemon(*args):
- cmd = string.join(map(str,args))
- debug ("+", cmd)
- if config.noexec(): return 0
- f = os.popen(cmd + ' 2>&1')
- ret = f.close()
- if ret:
- ret = ret >> 8
- else:
- ret = 0
- return ret
-
-# Determine full path to use for an external command
-# searches dirname(argv[0]) first, then PATH
-def find_prog(cmd):
- syspath = string.split(os.environ['PATH'], ':')
- cmdpath = os.path.dirname(sys.argv[0])
- syspath.insert(0, cmdpath);
- syspath.insert(0, os.path.join(cmdpath, PORTALS_DIR+'/linux/utils/'))
- for d in syspath:
- prog = os.path.join(d,cmd)
- debug(prog)
- if os.access(prog, os.X_OK):
- return prog
- return ''
-
-# Recursively look for file starting at base dir
-def do_find_file(base, mod):
- fullname = os.path.join(base, mod)
- if os.access(fullname, os.R_OK):
- return fullname
- for d in os.listdir(base):
- dir = os.path.join(base,d)
- if os.path.isdir(dir):
- module = do_find_file(dir, mod)
- if module:
- return module
-
-def find_module(dev_dir, modname):
- mod = '%s.o' % (modname)
-
- module = dev_dir +'/'+ mod
- try:
- if os.access(module, os.R_OK):
- return module
- except OSError:
- pass
- return None
-
-# is the path a block device?
-def is_block(path):
- s = ()
- try:
- s = os.stat(path)
- except OSError:
- return 0
- return stat.S_ISBLK(s[stat.ST_MODE])
-
-# build fs according to type
-# fixme: dangerous
-def mkfs(fstype, dev):
- if(fstype in ('ext3', 'extN')):
- mkfs = 'mkfs.ext2 -j -b 4096'
- elif (fstype == 'reiserfs'):
- mkfs = 'mkfs.reiserfs -f'
- else:
- print 'unsupported fs type: ', fstype
- if not is_block(dev):
- if(fstype in ('ext3', 'extN')):
- force = '-F'
- elif (fstype == 'reiserfs'):
- force = ''
- else:
- print 'unsupported fs type: ', fstype
- else:
- force = ''
- (ret, out) = run (mkfs, force, dev)
- if ret:
- panic("Unable to build fs:", dev)
- # enable hash tree indexing on fsswe
- # FIXME: this check can probably go away on 2.5
- if fstype == 'extN':
- htree = 'echo "feature FEATURE_C5" | debugfs -w'
- (ret, out) = run (htree, dev)
- if ret:
- panic("Unable to enable htree:", dev)
-
-# some systems use /dev/loopN, some /dev/loop/N
-def loop_base():
- import re
- loop = '/dev/loop'
- if not os.access(loop + str(0), os.R_OK):
- loop = loop + '/'
- if not os.access(loop + str(0), os.R_OK):
- panic ("can't access loop devices")
- return loop
-
-# find loop device assigned to thefile
-def find_loop(file):
- loop = loop_base()
- for n in xrange(0, MAX_LOOP_DEVICES):
- dev = loop + str(n)
- if os.access(dev, os.R_OK):
- (stat, out) = run('losetup', dev)
- if (out and stat == 0):
- m = re.search(r'\((.*)\)', out[0])
- if m and file == m.group(1):
- return dev
- else:
- break
- return ''
-
-# create file if necessary and assign the first free loop device
-def init_loop(file, size, fstype):
- dev = find_loop(file)
- if dev:
- print 'WARNING file:', file, 'already mapped to', dev
- return dev
- if config.reformat() or not os.access(file, os.R_OK | os.W_OK):
- run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size, file))
- loop = loop_base()
- # find next free loop
- for n in xrange(0, MAX_LOOP_DEVICES):
- dev = loop + str(n)
- if os.access(dev, os.R_OK):
- (stat, out) = run('losetup', dev)
- if (stat):
- run('losetup', dev, file)
- return dev
- else:
- print "out of loop devices"
- return ''
- print "out of loop devices"
- return ''
-
-# undo loop assignment
-def clean_loop(file):
- dev = find_loop(file)
- if dev:
- ret, out = run('losetup -d', dev)
- if ret:
- log('unable to clean loop device:', dev, 'for file:', file)
- logall(out)
-
-# determine if dev is formatted as a <fstype> filesystem
-def need_format(fstype, dev):
- # FIXME don't know how to implement this
- return 0
-
-# initialize a block device if needed
-def block_dev(dev, size, fstype, format):
- if config.noexec(): return dev
- if not is_block(dev):
- dev = init_loop(dev, size, fstype)
- if config.reformat() or (need_format(fstype, dev) and format == 'yes'):
- mkfs(fstype, dev)
-
-# else:
-# panic("device:", dev,
-# "not prepared, and autoformat is not set.\n",
-# "Rerun with --reformat option to format ALL filesystems")
-
- return dev
-
-def if2addr(iface):
- """lookup IP address for an interface"""
- rc, out = run("/sbin/ifconfig", iface)
- if rc or not out:
- return None
- addr = string.split(out[1])[1]
- ip = string.split(addr, ':')[1]
- return ip
-
-def get_local_address(net_type, wildcard):
- """Return the local address for the network type."""
- local = ""
- if net_type in ('tcp', 'toe'):
- if ':' in wildcard:
- iface, star = string.split(wildcard, ':')
- local = if2addr(iface)
- if not local:
- panic ("unable to determine ip for:", wildcard)
- else:
- host = socket.gethostname()
- local = socket.gethostbyname(host)
- elif net_type == 'elan':
- # awk '/NodeId/ { print $2 }' '/proc/elan/device0/position'
- try:
- fp = open('/proc/elan/device0/position', 'r')
- lines = fp.readlines()
- fp.close()
- for l in lines:
- a = string.split(l)
- if a[0] == 'NodeId':
- local = a[1]
- break
- except IOError, e:
- log(e)
- elif net_type == 'gm':
- fixme("automatic local address for GM")
- return local
-
-
-def is_prepared(uuid):
- """Return true if a device exists for the uuid"""
- # expect this format:
- # 1 UP ldlm ldlm ldlm_UUID 2
- try:
- out = lctl.device_list()
- for s in out:
- if uuid == string.split(s)[4]:
- return 1
- except CommandError, e:
- e.dump()
- return 0
-
-
-# ============================================================
-# Classes to prepare and cleanup the various objects
-#
-class Module:
- """ Base class for the rest of the modules. The default cleanup method is
- defined here, as well as some utilitiy funcs.
- """
- def __init__(self, module_name, dom_node):
- self.dom_node = dom_node
- self.module_name = module_name
- self.name = get_attr(dom_node, 'name')
- self.uuid = get_attr(dom_node, 'uuid')
- self.kmodule_list = []
- self._server = None
- self._connected = 0
-
- def info(self, *args):
- msg = string.join(map(str,args))
- print self.module_name + ":", self.name, self.uuid, msg
-
-
- def lookup_server(self, srv_uuid):
- """ Lookup a server's network information """
- net = get_ost_net(self.dom_node.parentNode, srv_uuid)
- if not net:
- panic ("Unable to find a server for:", srv_uuid)
- self._server = Network(net)
-
- def get_server(self):
- return self._server
-
- def cleanup(self):
- """ default cleanup, used for most modules """
- self.info()
- srv = self.get_server()
- if srv and local_net(srv):
- try:
- lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
- except CommandError, e:
- log(self.module_name, "disconnect failed: ", self.name)
- e.dump()
- cleanup_error(e.rc)
- try:
- lctl.cleanup(self.name, self.uuid)
- except CommandError, e:
- log(self.module_name, "cleanup failed: ", self.name)
- e.dump()
- cleanup_error(e.rc)
-
- def add_module(self, dev_dir, modname):
- """Append a module to list of modules to load."""
- self.kmodule_list.append((dev_dir, modname))
-
- def mod_loaded(self, modname):
- """Check if a module is already loaded. Look in /proc/modules for it."""
- fp = open('/proc/modules')
- lines = fp.readlines()
- fp.close()
- # please forgive my tired fingers for this one
- ret = filter(lambda word, mod=modname: word == mod,
- map(lambda line: string.split(line)[0], lines))
- return ret
-
- def load_module(self):
- """Load all the modules in the list in the order they appear."""
- for dev_dir, mod in self.kmodule_list:
- # (rc, out) = run ('/sbin/lsmod | grep -s', mod)
- if self.mod_loaded(mod) and not config.noexec():
- continue
- log ('loading module:', mod)
- if config.src_dir():
- module = find_module(dev_dir, mod)
- if not module:
- panic('module not found:', mod)
- (rc, out) = run('/sbin/insmod', module)
- if rc:
- raise CommandError('insmod', out, rc)
- else:
- (rc, out) = run('/sbin/modprobe', mod)
- if rc:
- raise CommandError('modprobe', out, rc)
-
- def cleanup_module(self):
- """Unload the modules in the list in reverse order."""
- rev = self.kmodule_list
- rev.reverse()
- for dev_dir, mod in rev:
- if not self.mod_loaded(mod):
- continue
- # debug hack
- if mod == 'portals' and config.dump_file():
- lctl.dump(config.dump_file())
- log('unloading module:', mod)
- if config.noexec():
- continue
- (rc, out) = run('/sbin/rmmod', mod)
- if rc:
- log('! unable to unload module:', mod)
- logall(out)
-
-
-class Network(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'NETWORK', dom_node)
- self.net_type = get_attr(dom_node,'type')
- self.nid = get_text(dom_node, 'server', '*')
- self.port = get_text_int(dom_node, 'port', 0)
- self.send_mem = get_text_int(dom_node, 'send_mem', DEFAULT_TCPBUF)
- self.recv_mem = get_text_int(dom_node, 'recv_mem', DEFAULT_TCPBUF)
- if '*' in self.nid:
- self.nid = get_local_address(self.net_type, self.nid)
- if not self.nid:
- panic("unable to set nid for", self.net_type, self.nid)
- debug("nid:", self.nid)
-
- self.add_module(PORTALS_DIR+"/linux/oslib", 'portals')
- if node_needs_router():
- self.add_module(PORTALS_DIR+"/linux/router", 'kptlrouter')
- if self.net_type == 'tcp':
- self.add_module(PORTALS_DIR+"/linux/socknal", 'ksocknal')
- if self.net_type == 'toe':
- self.add_module(PORTALS_DIR+"/linux/toenal", 'ktoenal')
- if self.net_type == 'elan':
- self.add_module(PORTALS_DIR+"/linux/rqswnal", 'kqswnal')
- if self.net_type == 'gm':
- self.add_module(PORTALS_DIR+"/linux/gmnal", 'kgmnal')
- self.add_module(config.src_dir()+'obdclass', 'obdclass')
- self.add_module(config.src_dir()+'ptlrpc', 'ptlrpc')
-
- def prepare(self):
- self.info(self.net_type, self.nid, self.port)
- if self.net_type in ('tcp', 'toe'):
- nal_id = '' # default is socknal
- if self.net_type == 'toe':
- nal_id = '-N 4'
- ret, out = run(TCP_ACCEPTOR, '-s', self.send_mem, '-r', self.recv_mem, nal_id, self.port)
- if ret:
- raise CommandError(TCP_ACCEPTOR, out, ret)
- ret = self.dom_node.getElementsByTagName('route_tbl')
- for a in ret:
- for r in a.getElementsByTagName('route'):
- net_type = get_attr(r, 'type')
- gw = get_attr(r, 'gw')
- lo = get_attr(r, 'lo')
- hi = get_attr(r,'hi', '')
- lctl.add_route(net_type, gw, lo, hi)
- if net_type in ('tcp', 'toe') and net_type == self.net_type and hi == '':
- srv = nid2server(self.dom_node.parentNode.parentNode, lo)
- if not srv:
- panic("no server for nid", lo)
- else:
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
-
-
- lctl.network(self.net_type, self.nid)
- lctl.newdev(attach = "ptlrpc RPCDEV RPCDEV_UUID")
-
- def cleanup(self):
- self.info(self.net_type, self.nid, self.port)
- ret = self.dom_node.getElementsByTagName('route_tbl')
- for a in ret:
- for r in a.getElementsByTagName('route'):
- lo = get_attr(r, 'lo')
- hi = get_attr(r,'hi', '')
- if self.net_type in ('tcp', 'toe') and hi == '':
- srv = nid2server(self.dom_node.parentNode.parentNode, lo)
- if not srv:
- panic("no server for nid", lo)
- else:
- try:
- lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
- except CommandError, e:
- print "disconnect failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- try:
- lctl.del_route(self.net_type, self.nid, lo, hi)
- except CommandError, e:
- print "del_route failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
-
- try:
- lctl.cleanup("RPCDEV", "RPCDEV_UUID")
- except CommandError, e:
- print "cleanup failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- try:
- lctl.disconnectAll(self.net_type)
- except CommandError, e:
- print "disconnectAll failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- if self.net_type in ('tcp', 'toe'):
- # yikes, this ugly! need to save pid in /var/something
- run("killall acceptor")
-
-class LDLM(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LDLM', dom_node)
- self.add_module(config.src_dir()+'ldlm', 'ldlm')
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info()
- lctl.newdev(attach="ldlm %s %s" % (self.name, self.uuid),
- setup ="")
-
-class LOV(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LOV', dom_node)
- self.mds_uuid = get_first_ref(dom_node, 'mds')
- mds= lookup(dom_node.parentNode, self.mds_uuid)
- self.mds_name = getName(mds)
- devs = dom_node.getElementsByTagName('devices')
- if len(devs) > 0:
- dev_node = devs[0]
- self.stripe_sz = get_attr_int(dev_node, 'stripesize', 65536)
- self.stripe_off = get_attr_int(dev_node, 'stripeoffset', 0)
- self.pattern = get_attr_int(dev_node, 'pattern', 0)
- self.devlist = get_all_refs(dev_node, 'osc')
- self.stripe_cnt = get_attr_int(dev_node, 'stripecount', len(self.devlist))
- self.add_module(config.src_dir()+'mdc', 'mdc')
- self.add_module(config.src_dir()+'lov', 'lov')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- try:
- # Ignore connection failures, because the LOV will DTRT with
- # an unconnected OSC.
- n.prepare(ignore_connect_failure=1)
- except CommandError:
- print "Error preparing OSC %s (inactive)\n" % osc_uuid
- else:
- panic('osc not found:', osc_uuid)
- mdc_uuid = prepare_mdc(self.dom_node.parentNode, self.mds_uuid)
- self.info(self.mds_uuid, self.stripe_cnt, self.stripe_sz,
- self.stripe_off, self.pattern, self.devlist, self.mds_name)
- lctl.newdev(attach="lov %s %s" % (self.name, self.uuid),
- setup ="%s" % (mdc_uuid))
-
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.cleanup()
- else:
- panic('osc not found:', osc_uuid)
- Module.cleanup(self)
- cleanup_mdc(self.dom_node.parentNode, self.mds_uuid)
-
-
- def load_module(self):
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.load_module()
- break
- else:
- panic('osc not found:', osc_uuid)
- Module.load_module(self)
-
-
- def cleanup_module(self):
- Module.cleanup_module(self)
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.cleanup_module()
- break
- else:
- panic('osc not found:', osc_uuid)
-
-class LOVConfig(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LOVConfig', dom_node)
- self.lov_uuid = get_first_ref(dom_node, 'lov')
- l = lookup(dom_node.parentNode, self.lov_uuid)
- self.lov = LOV(l)
-
- def prepare(self):
- lov = self.lov
- self.info(lov.mds_uuid, lov.stripe_cnt, lov.stripe_sz, lov.stripe_off,
- lov.pattern, lov.devlist, lov.mds_name)
- lctl.lov_setconfig(lov.uuid, lov.mds_name, lov.stripe_cnt,
- lov.stripe_sz, lov.stripe_off, lov.pattern,
- string.join(lov.devlist))
-
- def cleanup(self):
- #nothing to do here
- pass
-
-
-class MDS(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'MDS', dom_node)
- self.devname, self.size = get_device(dom_node)
- self.fstype = get_text(dom_node, 'fstype')
- # FIXME: if fstype not set, then determine based on kernel version
- self.format = get_text(dom_node, 'autoformat', "no")
- if self.fstype == 'extN':
- self.add_module(config.src_dir()+'extN', 'extN')
- self.add_module(config.src_dir()+'mds', 'mds')
- self.add_module(config.src_dir()+'obdclass', 'fsfilt_%s'%(self.fstype))
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.devname, self.fstype, self.format)
- blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
- if not is_prepared('MDT_UUID'):
- lctl.newdev(attach="mdt %s %s" % ('MDT', 'MDT_UUID'),
- setup ="")
- lctl.newdev(attach="mds %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(blkdev, self.fstype))
- def cleanup(self):
- if is_prepared('MDT_UUID'):
- try:
- lctl.cleanup("MDT", "MDT_UUID")
- except CommandError, e:
- print "cleanup failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- if not is_prepared(self.uuid):
- return
- Module.cleanup(self)
- clean_loop(self.devname)
-
-# Very unusual case, as there is no MDC element in the XML anymore
-# Builds itself from an MDS node
-class MDC(Module):
- def __init__(self,dom_node):
- self.mds = MDS(dom_node)
- self.dom_node = dom_node
- self.module_name = 'MDC'
- self.kmodule_list = []
- self._server = None
- self._connected = 0
-
- host = socket.gethostname()
- self.name = 'MDC_%s' % (self.mds.name)
- self.uuid = '%s_%05x_%05x' % (self.name, int(random.random() * 1048576),
- int(random.random() * 1048576))
-
- self.lookup_server(self.mds.uuid)
- self.add_module(config.src_dir()+'mdc', 'mdc')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.mds.uuid)
- srv = self.get_server()
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
- lctl.newdev(attach="mdc %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(self.mds.uuid, srv.uuid))
-
-class OBD(Module):
- def __init__(self, dom_node):
- Module.__init__(self, 'OBD', dom_node)
- self.obdtype = get_attr(dom_node, 'type')
- self.devname, self.size = get_device(dom_node)
- self.fstype = get_text(dom_node, 'fstype')
- # FIXME: if fstype not set, then determine based on kernel version
- self.format = get_text(dom_node, 'autoformat', 'yes')
- if self.fstype == 'extN':
- self.add_module(config.src_dir()+'extN', 'extN')
- self.add_module(config.src_dir()+'' + self.obdtype, self.obdtype)
- self.add_module(config.src_dir()+'obdclass' , 'fsfilt_%s' % (self.fstype))
-
- # need to check /proc/mounts and /etc/mtab before
- # formatting anything.
- # FIXME: check if device is already formatted.
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.obdtype, self.devname, self.size, self.fstype, self.format)
- if self.obdtype == 'obdecho':
- blkdev = ''
- else:
- blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
- lctl.newdev(attach="%s %s %s" % (self.obdtype, self.name, self.uuid),
- setup ="%s %s" %(blkdev, self.fstype))
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- Module.cleanup(self)
- if not self.obdtype == 'obdecho':
- clean_loop(self.devname)
-
-class OST(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'OST', dom_node)
- self.obd_uuid = get_first_ref(dom_node, 'obd')
- self.add_module(config.src_dir()+'ost', 'ost')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.obd_uuid)
- lctl.newdev(attach="ost %s %s" % (self.name, self.uuid),
- setup ="%s" % (self.obd_uuid))
-
-
-# virtual interface for OSC and LOV
-class VOSC(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'VOSC', dom_node)
- if dom_node.nodeName == 'lov':
- self.osc = LOV(dom_node)
- else:
- self.osc = OSC(dom_node)
- def prepare(self):
- self.osc.prepare()
- def cleanup(self):
- self.osc.cleanup()
- def load_module(self):
- self.osc.load_module()
- def cleanup_module(self):
- self.osc.cleanup_module()
-
-
-class OSC(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'OSC', dom_node)
- self.obd_uuid = get_first_ref(dom_node, 'obd')
- self.ost_uuid = get_first_ref(dom_node, 'ost')
- self.lookup_server(self.ost_uuid)
- self.add_module(config.src_dir()+'osc', 'osc')
-
- def prepare(self, ignore_connect_failure = 0):
- if is_prepared(self.uuid):
- return
- self.info(self.obd_uuid, self.ost_uuid)
- srv = self.get_server()
- try:
- if local_net(srv):
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
- else:
- r = find_route(srv)
- if r:
- lctl.add_route_host(r[0], srv.uuid, r[1], r[2])
- else:
- panic ("no route to", srv.nid)
- except CommandError:
- if (ignore_connect_failure == 0):
- pass
-
- lctl.newdev(attach="osc %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(self.obd_uuid, srv.uuid))
-
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- srv = self.get_server()
- if local_net(srv):
- Module.cleanup(self)
- else:
- self.info(self.obd_uuid, self.ost_uuid)
- r = find_route(srv)
- if r:
- try:
- lctl.del_route_host(r[0], srv.uuid, r[1], r[2])
- except CommandError, e:
- print "del_route failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- Module.cleanup(self)
-
-
-class ECHO_CLIENT(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'ECHO_CLIENT', dom_node)
- self.add_module('lustre/obdecho', 'obdecho')
- self.lov_uuid = get_first_ref(dom_node, 'osc')
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- self.osc = VOSC(l)
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.osc.prepare() # XXX This is so cheating. -p
- self.info(self.lov_uuid)
-
- lctl.newdev(attach="echo_client %s %s" % (self.name, self.uuid),
- setup = self.lov_uuid)
-
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- self.osc.cleanup()
-
- def load_module(self):
- self.osc.load_module()
- Module.load_module(self)
- def cleanup_module(self):
- Module.cleanup_module(self)
- self.osc.cleanup_module()
-
-
-class Mountpoint(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'MTPT', dom_node)
- self.path = get_text(dom_node, 'path')
- self.mds_uuid = get_first_ref(dom_node, 'mds')
- self.lov_uuid = get_first_ref(dom_node, 'osc')
- self.add_module(config.src_dir()+'mdc', 'mdc')
- self.add_module(config.src_dir()+'llite', 'llite')
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- self.osc = VOSC(l)
-
- def prepare(self):
- self.osc.prepare()
- mdc_uuid = prepare_mdc(self.dom_node.parentNode, self.mds_uuid)
- self.info(self.path, self.mds_uuid, self.lov_uuid)
- cmd = "mount -t lustre_lite -o osc=%s,mdc=%s none %s" % \
- (self.lov_uuid, mdc_uuid, self.path)
- run("mkdir", self.path)
- ret, val = run(cmd)
- if ret:
- panic("mount failed:", self.path)
-
- def cleanup(self):
- self.info(self.path, self.mds_uuid,self.lov_uuid)
- if config.force():
- (rc, out) = run("umount -f", self.path)
- else:
- (rc, out) = run("umount", self.path)
- if rc:
- log("umount failed, cleanup will most likely not work.")
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- self.osc.cleanup()
- cleanup_mdc(self.dom_node.parentNode, self.mds_uuid)
-
- def load_module(self):
- self.osc.load_module()
- Module.load_module(self)
- def cleanup_module(self):
- Module.cleanup_module(self)
- self.osc.cleanup_module()
-
-
-# ============================================================
-# XML processing and query
-# TODO: Change query funcs to use XPath, which is muc cleaner
-
-def get_device(obd):
- list = obd.getElementsByTagName('device')
- if len(list) > 0:
- dev = list[0]
- dev.normalize();
- size = get_attr_int(dev, 'size', 0)
- return dev.firstChild.data, size
- return '', 0
-
-# Get the text content from the first matching child
-# If there is no content (or it is all whitespace), return
-# the default
-def get_text(dom_node, tag, default=""):
- list = dom_node.getElementsByTagName(tag)
- if len(list) > 0:
- dom_node = list[0]
- dom_node.normalize()
- if dom_node.firstChild:
- txt = string.strip(dom_node.firstChild.data)
- if txt:
- return txt
- return default
-
-def get_text_int(dom_node, tag, default=0):
- list = dom_node.getElementsByTagName(tag)
- n = default
- if len(list) > 0:
- dom_node = list[0]
- dom_node.normalize()
- if dom_node.firstChild:
- txt = string.strip(dom_node.firstChild.data)
- if txt:
- try:
- n = int(txt)
- except ValueError:
- panic("text value is not integer:", txt)
- return n
-
-def get_attr(dom_node, attr, default=""):
- v = dom_node.getAttribute(attr)
- if v:
- return v
- return default
-
-def get_attr_int(dom_node, attr, default=0):
- n = default
- v = dom_node.getAttribute(attr)
- if v:
- try:
- n = int(v)
- except ValueError:
- panic("attr value is not integer", v)
- return n
-
-def get_first_ref(dom_node, tag):
- """ Get the first uuidref of the type TAG. Used one only
- one is expected. Returns the uuid."""
- uuid = None
- refname = '%s_ref' % tag
- list = dom_node.getElementsByTagName(refname)
- if len(list) > 0:
- uuid = getRef(list[0])
- return uuid
-
-def get_all_refs(dom_node, tag):
- """ Get all the refs of type TAG. Returns list of uuids. """
- uuids = []
- refname = '%s_ref' % tag
- list = dom_node.getElementsByTagName(refname)
- if len(list) > 0:
- for i in list:
- uuids.append(getRef(i))
- return uuids
-
-def get_ost_net(dom_node, uuid):
- ost = lookup(dom_node, uuid)
- uuid = get_first_ref(ost, 'network')
- if not uuid:
- return None
- return lookup(dom_node, uuid)
-
-def nid2server(dom_node, nid):
- netlist = dom_node.getElementsByTagName('network')
- for net_node in netlist:
- if get_text(net_node, 'server') == nid:
- return Network(net_node)
- return None
-
-def lookup(dom_node, uuid):
- for n in dom_node.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- if getUUID(n) == uuid:
- return n
- else:
- n = lookup(n, uuid)
- if n: return n
- return None
-
-# Get name attribute of dom_node
-def getName(dom_node):
- return dom_node.getAttribute('name')
-
-def getRef(dom_node):
- return dom_node.getAttribute('uuidref')
-
-# Get name attribute of dom_node
-def getUUID(dom_node):
- return dom_node.getAttribute('uuid')
-
-# the tag name is the service type
-# fixme: this should do some checks to make sure the dom_node is a service
-def getServiceType(dom_node):
- return dom_node.nodeName
-
-#
-# determine what "level" a particular node is at.
-# the order of iniitailization is based on level.
-def getServiceLevel(dom_node):
- type = getServiceType(dom_node)
- ret=0;
- if type in ('network',):
- ret = 10
- elif type in ('device', 'ldlm'):
- ret = 20
- elif type in ('obd', 'mdd'):
- ret = 30
- elif type in ('mds','ost'):
- ret = 40
- elif type in ('mdc','osc'):
- ret = 50
- elif type in ('lov', 'lovconfig'):
- ret = 60
- elif type in ('mountpoint', 'echo_client'):
- ret = 70
-
- if ret < config.minlevel() or ret > config.maxlevel():
- ret = 0
- return ret
-
-#
-# return list of services in a profile. list is a list of tuples
-# [(level, dom_node),]
-def getServices(lustreNode, profileNode):
- list = []
- for n in profileNode.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- servNode = lookup(lustreNode, getRef(n))
- if not servNode:
- print n
- panic('service not found: ' + getRef(n))
- level = getServiceLevel(servNode)
- if level > 0:
- list.append((level, servNode))
- list.sort()
- return list
-
-def getByName(lustreNode, name, tag):
- ndList = lustreNode.getElementsByTagName(tag)
- for nd in ndList:
- if getName(nd) == name:
- return nd
- return None
-
-
-############################################################
-# MDC UUID hack -
-# FIXME: clean this mess up!
-#
-saved_mdc = {}
-def prepare_mdc(dom_node, mds_uuid):
- global saved_mdc
- mds_node = lookup(dom_node, mds_uuid);
- if not mds_node:
- panic("no mds:", mds_uuid)
- if saved_mdc.has_key(mds_uuid):
- return saved_mdc[mds_uuid]
- mdc = MDC(mds_node)
- mdc.prepare()
- saved_mdc[mds_uuid] = mdc.uuid
- return mdc.uuid
-
-def cleanup_mdc(dom_node, mds_uuid):
- global saved_mdc
- mds_node = lookup(dom_node, mds_uuid);
- if not mds_node:
- panic("no mds:", mds_uuid)
- if not saved_mdc.has_key(mds_uuid):
- mdc = MDC(mds_node)
- mdc.cleanup()
- saved_mdc[mds_uuid] = mdc.uuid
-
-
-############################################################
-# routing ("rooting")
-#
-routes = []
-local_node = []
-router_flag = 0
-
-def init_node(dom_node):
- global local_node, router_flag
- netlist = dom_node.getElementsByTagName('network')
- for dom_net in netlist:
- type = get_attr(dom_net, 'type')
- gw = get_text(dom_net, 'server')
- local_node.append((type, gw))
-
-def node_needs_router():
- return router_flag
-
-def get_routes(type, gw, dom_net):
- """ Return the routes as a list of tuples of the form:
- [(type, gw, lo, hi),]"""
- res = []
- tbl = dom_net.getElementsByTagName('route_tbl')
- for t in tbl:
- routes = t.getElementsByTagName('route')
- for r in routes:
- lo = get_attr(r, 'lo')
- hi = get_attr(r, 'hi', '')
- res.append((type, gw, lo, hi))
- return res
-
-
-def init_route_config(lustre):
- """ Scan the lustre config looking for routers. Build list of
- routes. """
- global routes, router_flag
- routes = []
- list = lustre.getElementsByTagName('node')
- for node in list:
- if get_attr(node, 'router'):
- router_flag = 1
- for (local_type, local_nid) in local_node:
- gw = None
- netlist = node.getElementsByTagName('network')
- for dom_net in netlist:
- if local_type == get_attr(dom_net, 'type'):
- gw = get_text(dom_net, 'server')
- break
- if not gw:
- continue
- for dom_net in netlist:
- if local_type != get_attr(dom_net, 'type'):
- for route in get_routes(local_type, gw, dom_net):
- routes.append(route)
-
-
-def local_net(net):
- global local_node
- for iface in local_node:
- if net.net_type == iface[0]:
- return 1
- return 0
-
-def find_route(net):
- global local_node, routes
- frm_type = local_node[0][0]
- to_type = net.net_type
- to = net.nid
- debug ('looking for route to', to_type,to)
- for r in routes:
- if r[2] == to:
- return r
- return None
-
-
-
-
-############################################################
-# lconf level logic
-# Start a service.
-def startService(dom_node, module_flag):
- type = getServiceType(dom_node)
- debug('Service:', type, getName(dom_node), getUUID(dom_node))
- # there must be a more dynamic way of doing this...
- n = None
- if type == 'ldlm':
- n = LDLM(dom_node)
- elif type == 'lov':
- n = LOV(dom_node)
- elif type == 'lovconfig':
- n = LOVConfig(dom_node)
- elif type == 'network':
- n = Network(dom_node)
- elif type == 'obd':
- n = OBD(dom_node)
- elif type == 'ost':
- n = OST(dom_node)
- elif type == 'mds':
- n = MDS(dom_node)
- elif type == 'osc':
- n = VOSC(dom_node)
- elif type == 'mdc':
- n = MDC(dom_node)
- elif type == 'mountpoint':
- n = Mountpoint(dom_node)
- elif type == 'echo_client':
- n = ECHO_CLIENT(dom_node)
- else:
- panic ("unknown service type:", type)
-
- if module_flag:
- if config.nomod():
- return
- if config.cleanup():
- n.cleanup_module()
- else:
- n.load_module()
- else:
- if config.nosetup():
- return
- if config.cleanup():
- n.cleanup()
- else:
- n.prepare()
-
-#
-# Prepare the system to run lustre using a particular profile
-# in a the configuration.
-# * load & the modules
-# * setup networking for the current node
-# * make sure partitions are in place and prepared
-# * initialize devices with lctl
-# Levels is important, and needs to be enforced.
-def startProfile(lustreNode, profileNode, module_flag):
- if not profileNode:
- panic("profile:", profile, "not found.")
- services = getServices(lustreNode, profileNode)
- if config.cleanup():
- services.reverse()
- for s in services:
- startService(s[1], module_flag)
-
-
-#
-# Load profile for
-def doHost(lustreNode, hosts):
- global routes
- dom_node = None
- for h in hosts:
- dom_node = getByName(lustreNode, h, 'node')
- if dom_node:
- break
- if not dom_node:
- print 'lconf: No host entry found in '+sys.argv[1]
- return
-
- if not get_attr(dom_node, 'router'):
- init_node(dom_node)
- init_route_config(lustreNode)
- else:
- global router_flag
- router_flag = 1
-
- # Two step process: (1) load modules, (2) setup lustre
- # if not cleaning, load modules first.
- module_flag = not config.cleanup()
- reflist = dom_node.getElementsByTagName('profile')
- for profile in reflist:
- startProfile(lustreNode, profile, module_flag)
-
- if not config.cleanup():
- sys_set_debug_path()
- script = config.gdb_script()
- run(lctl.lctl, ' modules >', script)
- if config.gdb():
- # dump /tmp/ogdb and sleep/pause here
- log ("The GDB module script is in", script)
- time.sleep(5)
-
- module_flag = not module_flag
- for profile in reflist:
- startProfile(lustreNode, profile, module_flag)
-
-############################################################
-# Command line processing
-#
-def parse_cmdline(argv):
- short_opts = "hdnvf"
- long_opts = ["ldap", "reformat", "lustre=", "verbose", "gdb",
- "portals=", "makeldiff", "cleanup", "noexec",
- "help", "node=", "nomod", "nosetup",
- "dump=", "force", "minlevel=", "maxlevel="]
- opts = []
- args = []
- try:
- opts, args = getopt.getopt(argv, short_opts, long_opts)
- except getopt.error:
- print "invalid opt"
- usage()
-
- for o, a in opts:
- if o in ("-h", "--help"):
- usage()
- if o in ("-d","--cleanup"):
- config.cleanup(1)
- if o in ("-v", "--verbose"):
- config.verbose(1)
- if o in ("-n", "--noexec"):
- config.noexec(1)
- config.verbose(1)
- if o == "--portals":
- config.portals = a
- if o == "--lustre":
- config.lustre = a
- if o == "--reformat":
- config.reformat(1)
- if o == "--node":
- config.node(a)
- if o == "--gdb":
- config.gdb(1)
- if o == "--nomod":
- config.nomod(1)
- if o == "--nosetup":
- config.nosetup(1)
- if o == "--dump":
- config.dump_file(a)
- if o in ("-f", "--force"):
- config.force(1)
- if o in ("--minlevel",):
- config.minlevel(a)
- if o in ("--maxlevel",):
- config.maxlevel(a)
-
- return args
-
-def fetch(url):
- import urllib
- data = ""
- try:
- s = urllib.urlopen(url)
- data = s.read()
- except:
- usage()
- return data
-
-def setupModulePath(cmd):
- global PORTALS_DIR
- base = os.path.dirname(cmd)
- if os.access(base+"/Makefile", os.R_OK):
- config.src_dir(base + "/../")
- if PORTALS_DIR[0] != '/':
- PORTALS_DIR= config.src_dir()+PORTALS_DIR
-
-def sys_set_debug_path():
- debug("debug path: ", config.debug_path())
- if config.noexec():
- return
- try:
- fp = open('/proc/sys/portals/debug_path', 'w')
- fp.write(config.debug_path())
- fp.close()
- except IOError, e:
- print e
-
-#/proc/sys/net/core/rmem_max
-#/proc/sys/net/core/wmem_max
-def sys_set_netmem_max(path, max):
- debug("setting", path, "to at least", max)
- if config.noexec():
- return
- fp = open(path)
- str = fp.readline()
- fp.close
- cur = int(str)
- if max > cur:
- fp = open(path, 'w')
- fp.write('%d\n' %(max))
- fp.close()
-
-
-def sys_make_devices():
- if not os.access('/dev/portals', os.R_OK):
- run('mknod /dev/portals c 10 240')
- if not os.access('/dev/obd', os.R_OK):
- run('mknod /dev/obd c 10 241')
-
-
-# Add dir to the global PATH, if not already there.
-def add_to_path(new_dir):
- syspath = string.split(os.environ['PATH'], ':')
- if new_dir in syspath:
- return
- os.environ['PATH'] = os.environ['PATH'] + ':' + new_dir
-
-
-DEFAULT_PATH = ('/sbin', '/usr/sbin', '/bin', '/usr/bin')
-# ensure basic elements are in the system path
-def sanitise_path():
- for dir in DEFAULT_PATH:
- add_to_path(dir)
-
-# Initialize or shutdown lustre according to a configuration file
-# * prepare the system for lustre
-# * configure devices with lctl
-# Shutdown does steps in reverse
-#
-def main():
- global TCP_ACCEPTOR, lctl, MAXTCPBUF
- setupModulePath(sys.argv[0])
-
- host = socket.gethostname()
-
- # the PRNG is normally seeded with time(), which is not so good for starting
- # time-synchronized clusters
- input = open('/dev/urandom', 'r')
- if not input:
- print 'Unable to open /dev/urandom!'
- sys.exit(1)
- seed = input.read(32)
- input.close()
- random.seed(seed)
-
- sanitise_path()
-
- args = parse_cmdline(sys.argv[1:])
- if len(args) > 0:
- if not os.access(args[0], os.R_OK):
- print 'File not found or readable:', args[0]
- sys.exit(1)
- dom = xml.dom.minidom.parse(args[0])
- elif config.url():
- xmldata = fetch(config.url())
- dom = xml.dom.minidom.parseString(xmldata)
- else:
- usage()
-
- node_list = []
- if config.node():
- node_list.append(config.node())
- else:
- if len(host) > 0:
- node_list.append(host)
- node_list.append('localhost')
- debug("configuring for host: ", node_list)
-
- if len(host) > 0:
- config._debug_path = config._debug_path + '-' + host
- config._gdb_script = config._gdb_script + '-' + host
-
- TCP_ACCEPTOR = find_prog('acceptor')
- if not TCP_ACCEPTOR:
- if config.noexec():
- TCP_ACCEPTOR = 'acceptor'
- debug('! acceptor not found')
- else:
- panic('acceptor not found')
-
- lctl = LCTLInterface('lctl')
-
- sys_make_devices()
- sys_set_netmem_max('/proc/sys/net/core/rmem_max', MAXTCPBUF)
- sys_set_netmem_max('/proc/sys/net/core/wmem_max', MAXTCPBUF)
- doHost(dom.documentElement, node_list)
-
-if __name__ == "__main__":
- try:
- main()
- except LconfError, e:
- print e
- except CommandError, e:
- e.dump()
- sys.exit(e.rc)
-
- if first_cleanup_error:
- sys.exit(first_cleanup_error)
-
+++ /dev/null
-#!/usr/bin/perl
-# Author: Hariharan Thantry
-# Date: 12/13/2002
-
-package llparser;
-require Exporter;
-@ISA = qw(Exporter);
-@EXPORT = qw(parse_file $e_subsys $e_mask $e_processor $e_time $e_file $e_line $e_function $e_pid $e_stack $e_fmtstr $e_backref $e_treeparent $e_numchildren $e_youngestchild $e_next $e_pidhead);
-
-($e_subsys,
- $e_mask,
- $e_processor,
- $e_time,
- $e_file,
- $e_line,
- $e_function,
- $e_pid,
- $e_stack,
- $e_fmtstr,
- $e_treeparent,
- $e_numchildren,
- $e_youngestchild,
- $e_pidhead,
- $e_next,
- $e_backref) = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
-
-$MAX_STACK_SIZE = 8192;
-
-$REGEX=qr/^\s*(\w+)\s*:\s*(\d+)\s*:\s*(\d+)\s*:\s*(\d+\.(?:\d+))\s*\(\s*([^:]+)\s*:\s*(\d+)\s*:\s*([^()]+)\s*\(\)\s*(\d+)\s*\+\s*(\d+)\s*(?:.*)\):(.*)$/;
-
-# Create backlinks between array entries based on the calling sequence
-# For each new PID encountered, the first entry will be present in the
-# PID hash.
-
-sub create_links {
- my $arrayref = shift @_;
- my $pidhashref = shift @_;
- my $pidparent;
- my %local_hash;
- my $hash_lineref;
- #my $lineref;
- my $bool = 0;
-
- foreach $lineref (@$arrayref) {
- $pidparent = $pidhashref->{$lineref->[$e_pid]};
- if ($pidparent->[$e_next] == 0) {
- $pidparent->[$e_next] = $lineref;
- if (exists $local_hash{$lineref->[$e_pid]} && $bool) {
- $hash_lineref=$local_hash{$lineref->[$e_pid]};
- $hash_lineref->[$e_next] =$lineref;
- $bool = 0;
- #print "LINE UPDATED: [@$hash_lineref]\n";
- #print "NEXT LINE ADDR:$lineref, CONTENT: @$lineref \n";
- }
- } elsif ($local_hash{$lineref->[$e_pid]} == 0) {
- # True only for the first line, the marker line.
- $local_hash{$lineref->[$e_pid]}=$lineref;
- #print "LINE ADDED TO HASH: @$lineref\n";
- $bool = 1;
- }
-
- if ($lineref->[$e_stack] < $pidparent->[$e_stack]) {
- $lineref->[$e_backref] = $pidparent;
- $pidparent->[$e_numchildren]++;
- $pidhashref->{$lineref->[$e_pid]}=$lineref;
-
- } elsif ($lineref->[$e_stack] > $pidparent->[$e_stack]) {
- LINE: while($lineref->[$e_stack] > $pidparent->[$e_stack]) {
- last LINE if ($pidparent->[$e_backref] == 0);
- $pidparent = $pidparent->[$e_backref];
- }
- $lineref->[$e_backref] = $pidparent;
- $pidparent->[$e_numchildren]++;
- $pidhashref->{$lineref->[$e_pid]}=$lineref;
-
- } else {
- $lineref->[$e_numchildren] = 0;
- $lineref->[$e_backref] = $pidparent->[$e_backref];
- $pidhashref->{$lineref->[$e_pid]} = $lineref;
- ($lineref->[$e_backref])->[$e_numchildren]++;
- }
- $lineref->[$e_youngestchild] = $lineref;
- while ($pidparent->[$e_backref] != 0) {
- $pidparent->[$e_youngestchild] = $lineref;
- $pidparent = $pidparent->[$e_backref];
- }
- $pidparent->[$e_youngestchild] = $lineref;
- $lineref->[$e_pidhead]=$pidparent;
- }
- return $arrayref;
-}
-
-# Main loop, parses the debug log
-
-sub parse_file {
- my %hasharray;
- $backref = 0;
- $treeparent = 0;
- $numchildren = 0;
- $youngestchild = 0;
- $next = 0;
- $pidhead = 0;
-
- while(<>){
- if (/$REGEX/) {
- @parsed_line=($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $treeparent, $numchildren, $youngestchild, $pidhead, $next, $backref);
- if (!exists($hasharray{$parsed_line[$e_pid]})) {
- # Push a marker for the beginning of this PID
- my @marker_line;
- $marker_line[$e_subsys] = 0;
- $marker_line[$e_mask] = 0;
- $marker_line[$e_processor] = 0;
- $marker_line[$e_time] = $parsed_line[$e_time];
- $marker_line[$e_file] = 0;
- $marker_line[$e_line] = 0;
- $marker_line[$e_function] = 0;
- $marker_line[$e_pid] = $parsed_line[$e_pid];
- $marker_line[$e_stack] = $MAX_STACK_SIZE;
- $marker_line[$e_fmtstr] = "";
- $marker_line[$e_treeparent] = 0;
- $marker_line[$e_numchildren] = 0;
- $marker_line[$e_youngestchild] = 0;
- $marker_line[$e_pidhead] = 0;
- $marker_line[$e_next]= \@parsed_line;
- $marker_line[$e_backref] = 0;
- $hasharray{$parsed_line[$e_pid]} = \@marker_line;
- push @$array_parsed, [ @marker_line ];
-
- }
- push @$array_parsed, [ @parsed_line ];
- }
- }
- $array_parsed=create_links($array_parsed, \%hasharray);
- #print_array($array_parsed);
- return $array_parsed;
-}
-
-sub print_array {
-
- my $arrayref = shift;
- foreach $lineref(@$arrayref){
- if ($lineref->[$e_backref]==0){
- print "MARKER LINE(addr): $lineref contents: [ @$lineref ]\n";
- } else {
-
- print "REGULAR LINE (addr) :$lineref contents: [ @$lineref ]\n";
- }
- }
-
-}
-1;
-#$array_parsed=parse_file();
-#print_array($array_parsed);
+++ /dev/null
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-
-/****************** Custom includes ********************/
-#include <linux/lustre_lite.h>
-#include <linux/lustre_idl.h>
-
-
-/****************** Functions ******************/
-
-void usage(char *pgm)
-{
- fprintf(stderr, "\nIncorrect parameters! Correct usage:\n\n" );
- fprintf(stderr, "%s <output filename> <stripe size> <OST #> <stripe #>\n", pgm);
-
- fprintf(stderr, "\n\nArgument explanations:\n---------------------\n\n");
- fprintf(stderr, "<output filename> = the full name and path of the output file to create\n");
- fprintf(stderr, "<stripe size> = the number of bytes to have in each stripe.\n");
- fprintf(stderr, "<OST #> = the OST number to start the striping on.\n");
- fprintf(stderr, "<stripe #> = the number of stripes to use.\n");
-
- fprintf(stderr, "\n\nExamples:\n---------\n\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost1 131072 0 1\n", pgm);
- fprintf(stderr, "\t\tcreates a file only on ost1.\n\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost2 131072 1 1\n", pgm);
- fprintf(stderr, "\t\tcreates a file only on ost2.\n\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost1and2 131072 0 2\n", pgm);
- fprintf(stderr, "\t\tcreates a 128k file with 2 stripes, on ost1 and ost2.\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost1and2 131072 1 2\n", pgm);
- fprintf(stderr, "\t\tcreates a 128k file with 2 stripes, on ost2 and ost1.\n");
-}
-
-int create_file(char *name, long stripe_size, int stripe_offset,
- int stripe_count)
-{
- struct lov_mds_md a_striping;
- int fd, result = 0;
-
- /* Initialize IOCTL striping pattern structure */
- a_striping.lmm_magic = LOV_MAGIC;
- a_striping.lmm_stripe_pattern = 0;
- a_striping.lmm_stripe_size = stripe_size;
- a_striping.lmm_stripe_offset = stripe_offset;
- a_striping.lmm_stripe_count = stripe_count;
-
- fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
- if (fd < 0) {
- fprintf(stderr, "\nUnable to open '%s': %s\n",
- name, strerror(errno));
- result = -errno;
- } else if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &a_striping)) {
- fprintf(stderr, "\nError on ioctl for '%s' (%d): %s\n",
- name, fd, strerror(errno));
- result = -errno;
- } else if (close(fd) < 0) {
- fprintf(stderr, "\nError on close for '%s' (%d): %s\n",
- name, fd, strerror(errno));
- result = -errno;
- }
-
- return result;
-}
-
-int main(int argc, char *argv[])
-{
- int result;
- long st_size;
- int st_offset,
- st_count;
-
- /* Check to make sure we have enough parameters */
- if (argc != 5) {
- usage(argv[0]);
- return(-1);
- }
-
- /* Get the stripe size */
- st_size = atol(argv[2]);
-
- /* Get the stripe offset*/
- st_offset = atoi(argv[3]);
-
- /* Get the stripe count */
- st_count = atoi(argv[4]);
-
- /* Create the file, as specified. Return and display any errors. */
- result = create_file(argv[1], st_size, st_offset, st_count);
-
- return result;
-}
+++ /dev/null
-<!-- Lustre Management DTD -->\r
-\r
-<!-- basic entities -->\r
-<!ENTITY % basic.content '#PCDATA'>\r
-<!ENTITY % id.content 'num | id | uuid'>\r
-\r
-<!-- main elements -->\r
-<!ELEMENT lustre (node | profile | mountpoint |\r
- mds | obd | ost | osc | lov | router)*>\r
-\r
-<!ELEMENT profile (mountpoint_id, service_id)>\r
-<!ATTLIST profile id #CDATA #REQUIRED uuid #CDATA #REQUIRED>\r
-\r
-<!ELEMENT mountpoint (mntpt, fileset, mds_id, lov_id)>\r
-<!ATTLIST mountpoint id #CDATA #REQUIRED uuid #CDATA #REQUIRED>\r
-\r
-<!ELEMENT node (profile_id)>\r
-<!ATTLIST node id #CDATA #REQUIRED uuid #CDATA #REQUIRED>\r
-\r
-<!ELEMENT mds (fstype | device | server_id | failover_id)*>\r
-<!ATTLIST mds id #CDATA #REQUIRED uuid #CDATA #REQUIRED>\r
-\r
-<!ELEMENT obd (fstype | device | autoformat)*>\r
-<!ATTLIST obd id #CDATA #REQUIRED uuid #CDATA #REQUIRED\r
- type (obdfilter | obdext2 | obdecho) 'obdfilter'>\r
-\r
-<!ELEMENT ost (server_id | failover_id)*>\r
-<!ATTLIST ost id #CDATA #REQUIRED uuid #CDATA #REQUIRED>\r
- \r
-<!ELEMENT osc (network)*>\r
-<!ATTLIST osc id #CDATA #REQUIRED uuid #CDATA #REQUIRED>\r
-\r
-<!ELEMENT lov (osc_id | obd_id | mdc_id)*>\r
-<!ATTLIST lov id #CDATA #REQUIRED uuid #CDATA #REQUIRED>\r
-\r
-<!ELEMENT router (misc)*>\r
-<!ATTLIST router id #CDATA #REQUIRED uuid #CDATA #REQUIRED>\r
-\r
-<!-- basic elements -->\r
-<!ELEMENT network (%basic.content;)*>\r
-<!ATTLIST network type (ip | elan | myrinet) 'ip'\r
- address #CDATA 'localhost'>\r
-\r
-<!ELEMENT fstype (%basic.content;)*>\r
-<!ELEMENT device (%basic.content;)*>\r
-<!ELEMENT server (%basic.content;)*>\r
-<!ELEMENT autoformat (%basic.content;)*>\r
-<!ELEMENT mntpt (%basic.content;)*>\r
-<!ELEMENT fileset (%basic.content;)*>\r
-\r
-<!ELEMENT profile_id (%basic.content;)*>\r
-<!ATTLIST profile_id (%id.content;)* #CDATA #IMPLIED>\r
-<!ELEMENT mds_id (%basic.content;)*>\r
-<!ATTLIST mds_id (%id.content;)* #CDATA #IMPLIED>\r
-<!ELEMENT obd_id (%basic.content;)*>\r
-<!ATTLIST obd_id (%id.content;)* #CDATA #IMPLIED>\r
-<!ELEMENT osc_id (%basic.content;)*>\r
-<!ATTLIST osc_id (%id.content;)* #CDATA #IMPLIED>\r
-<!ELEMENT lov_id (%basic.content;)*>\r
-<!ATTLIST lov_id (%id.content;)* #CDATA #IMPLIED>\r
-<!ELEMENT mdc_id (%basic.content;)*>\r
-<!ATTLIST mdc_id (%id.content;)* #CDATA #IMPLIED>\r
-<!ELEMENT mountpoint_id (%basic.content;)*>\r
-<!ATTLIST mountpoint_id (%id.content;)* #CDATA #IMPLIED>\r
-<!ELEMENT service_id (%basic.content;)*>\r
-<!ATTLIST service_id (%id.content;)* #CDATA #IMPLIED>\r
-<!ELEMENT server_id (%basic.content;)*>\r
-<!ATTLIST server_id (%id.content;)* #CDATA #IMPLIED>\r
-<!ELEMENT failover_id (%basic.content;)*>\r
-<!ATTLIST failover_id (%id.content;)* #CDATA #IMPLIED>\r
-\r
+++ /dev/null
-#!/usr/bin/env python
-#
-# Author: Ravindranadh Chowdary Sahukara <s-ravindranadh.chowdary@hp.com>
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free 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.
-#
-# 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
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# lconf - lustre configuration tool
-#
-# lconf is the main driver script for starting and stopping
-# lustre filesystem services.
-#
-# Based in part on the XML obdctl modifications done by Brian Behlendorf
-
-from types import DictType, ListType, TupleType, StringType
-import string, os, stat, popen2, socket, time, random
-import sys, getopt
-import re, exceptions
-import xml.dom.minidom
-from sys import exit
-from string import split,join
-
-
-# Global parameters
-DEFAULT_TCPBUF = 0
-
-
-def panic(*args):
- msg = string.join(map(str,args))
- print "! " + msg
- exit(1)
-
-def debug(*args):
- msg = string.join(map(str,args))
- print msg
-
-
-names = {}
-uuids = {}
-
-
-def new_name(bas):
- ctr = 2
- ret = bas
- while names.has_key(ret):
- ret = "%s_%d" % (bas, ctr)
- ctr = 1 + ctr
- names[ret] = 1
- return str(ret)
-
-def new_uuid(name):
- return "%s_UUID" % (name)
-
-
-def getServices(lustreNode, profileNode):
- list = []
- for n in profileNode.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- servNode = lookup(lustreNode, getRef(n))
- if not servNode:
- print n
- panic('service not found: ' + getRef(n))
- list.append((servNode))
- #list.sort()
- return list
-
-def getByName(lustreNode, name, tag):
- ndList = lustreNode.getElementsByTagName(tag)
- for nd in ndList:
- if getName(nd) == name:
- return nd
- return None
-
-
-
-class Module:
- """ Base class for the rest of the modules. """
- def __init__(self, module_name, dom_node):
- self.dom_node = dom_node
- self.module_name = module_name
- self.name = get_attr(dom_node, 'name')
- self.uuid = get_attr(dom_node, 'uuid')
- self.kmodule_list = []
- self._server = None
- self._connected = 0
-
- def info(self, *args):
- msg = string.join(map(str,args))
- print self.module_name + ":", self.name, self.uuid, msg
-
-
- def lookup_server(self, srv_uuid):
- """ Lookup a servers network information """
- net = get_ost_net(self.dom_node.parentNode, srv_uuid)
- if not net:
- panic ("Unable to find a server for:", srv_uuid)
- self._server = Network(net)
-
- def get_server(self):
- return self._server
-
-
-class Network(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'NETWORK', dom_node)
- self.net_type = get_attr(dom_node,'type')
- self.nid = get_text(dom_node, 'server', '*')
- self.port = get_text_int(dom_node, 'port', 0)
- self.send_mem = get_text_int(dom_node, 'send_mem', DEFAULT_TCPBUF)
- self.recv_mem = get_text_int(dom_node, 'recv_mem', DEFAULT_TCPBUF)
- if '*' in self.nid:
- self.nid = get_local_address(self.net_type, self.nid)
- if not self.nid:
- panic("unable to set nid for", self.net_type, self.nid)
- debug("nid:", self.nid)
-
-
-class LDLM(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LDLM', dom_node)
-
-class LOV(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LOV', dom_node)
- self.mds_uuid = get_first_ref(dom_node, 'mds')
- mds= lookup(dom_node.parentNode, self.mds_uuid)
- self.mds_name = getName(mds)
- devs = dom_node.getElementsByTagName('devices')
- if len(devs) > 0:
- dev_node = devs[0]
- self.stripe_sz = get_attr_int(dev_node, 'stripesize', 65536)
- self.stripe_off = get_attr_int(dev_node, 'stripeoffset', 0)
- self.pattern = get_attr_int(dev_node, 'pattern', 0)
- self.devlist = get_all_refs(dev_node, 'osc')
- self.stripe_cnt = get_attr_int(dev_node, 'stripecount', len(self.devlist))
-
-class LOVConfig(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LOVConfig', dom_node)
- self.lov_uuid = get_first_ref(dom_node, 'lov')
- l = lookup(dom_node.parentNode, self.lov_uuid)
- self.lov = LOV(l)
-
-
-class MDS(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'MDS', dom_node)
- self.devname, self.size = get_device(dom_node)
- self.fstype = get_text(dom_node, 'fstype')
- # FIXME: if fstype not set, then determine based on kernel version
- self.format = get_text(dom_node, 'autoformat', "no")
- self.lookup_server(self.uuid)
-
-# Very unusual case, as there is no MDC element in the XML anymore
-# Builds itself from an MDS node
-class OBD(Module):
- def __init__(self, dom_node):
- Module.__init__(self, 'OBD', dom_node)
- self.obdtype = get_attr(dom_node, 'type')
- self.devname, self.size = get_device(dom_node)
- self.fstype = get_text(dom_node, 'fstype')
- # FIXME: if fstype not set, then determine based on kernel version
- self.format = get_text(dom_node, 'autoformat', 'yes')
-
-class OST(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'OST', dom_node)
- self.obd_uuid = get_first_ref(dom_node, 'obd')
-
-
-# virtual interface for OSC and LOV
-class VOSC(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'VOSC', dom_node)
- if dom_node.nodeName == 'lov':
- self.osc = LOV(dom_node)
- else:
- self.osc = OSC(dom_node)
-
-class OSC(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'OSC', dom_node)
- self.obd_uuid = get_first_ref(dom_node, 'obd')
- self.ost_uuid = get_first_ref(dom_node, 'ost')
- self.lookup_server(self.ost_uuid)
-
-class Mountpoint(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'MTPT', dom_node)
- self.path = get_text(dom_node, 'path')
- self.mds_uuid = get_first_ref(dom_node, 'mds')
- self.lov_uuid = get_first_ref(dom_node, 'osc')
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- self.osc = VOSC(l)
-
-# ============================================================
-
-def get_device(obd):
- list = obd.getElementsByTagName('device')
- if len(list) > 0:
- dev = list[0]
- dev.normalize();
- size = get_attr_int(dev, 'size', 0)
- return str(dev.firstChild.data), str(size)
- return '', 0
-
-# Get the text content from the first matching child
-# If there is no content (or it is all whitespace), return
-# the default
-def get_text(dom_node, tag, default=""):
- list = dom_node.getElementsByTagName(tag)
- if len(list) > 0:
- dom_node = list[0]
- dom_node.normalize()
- if dom_node.firstChild:
- txt = string.strip(dom_node.firstChild.data)
- if txt:
- return txt
- return default
-
-def get_text_int(dom_node, tag, default=0):
- list = dom_node.getElementsByTagName(tag)
- n = default
- if len(list) > 0:
- dom_node = list[0]
- dom_node.normalize()
- if dom_node.firstChild:
- txt = string.strip(dom_node.firstChild.data)
- if txt:
- try:
- n = int(txt)
- except ValueError:
- panic("text value is not integer:", txt)
- return n
-
-def get_attr(dom_node, attr, default=""):
- v = dom_node.getAttribute(attr)
- if v:
- return str(v)
- return str(default)
-
-def get_attr_int(dom_node, attr, default=0):
- n = default
- v = dom_node.getAttribute(attr)
- if v:
- try:
- n = int(v)
- except ValueError:
- panic("attr value is not integer", v)
- return n
-
-def get_first_ref(dom_node, tag):
- """ Get the first uuidref of the type TAG. Used one only
- one is expected. Returns the uuid."""
- uuid = None
- refname = '%s_ref' % tag
- list = dom_node.getElementsByTagName(refname)
- if len(list) > 0:
- uuid = getRef(list[0])
- return uuid
-
-def get_all_refs(dom_node, tag):
- """ Get all the refs of type TAG. Returns list of uuids. """
- uuids = []
- refname = '%s_ref' % tag
- list = dom_node.getElementsByTagName(refname)
- if len(list) > 0:
- for i in list:
- uuids.append(getRef(i))
- return uuids
-
-def get_ost_net(dom_node, uuid):
- ost = lookup(dom_node, uuid)
- uuid = get_first_ref(ost, 'network')
- if not uuid:
- return None
- return lookup(dom_node, uuid)
-
-def lookup(dom_node, uuid):
- for n in dom_node.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- if getUUID(n) == uuid:
- return n
- else:
- n = lookup(n, uuid)
- if n: return n
- return None
-
-# Get name attribute of dom_node
-def getName(dom_node):
- return str(dom_node.getAttribute('name'))
-
-def getRef(dom_node):
- return dom_node.getAttribute('uuidref')
-
-# Get name attribute of dom_node
-def getUUID(dom_node):
- return str(dom_node.getAttribute('uuid'))
-
-# the tag name is the service type
-def getServiceType(dom_node):
- return dom_node.nodeName
-
-
-
-##############################################################################
-# LDAP related stuff tarts here...
-
-import ldap
-import _ldap
-
-#returns the lustre ldap specific filters
-
-class lustre_ldap:
- def __init__(self):
- self.filter=0
-
- def get_filter(self,lustreRdn):
- filter="(&"+lustreRdn+")"
- return filter
-
-# make a connection to LDAP server and abd bind
-class MyConn:
- def __init__(self,host,port):
- self.id = 0
- self.host = host
- self.port = port
- self.base = "fs=lustre"
-
- def open(self):
- self.id = ldap.open(self.host)
- if self.id == None:
- print "unable to open a connection"
-
- try:
- # lustre tree starts from here...the DN is (cn=Manager ,fs=lustre)
- status = self.id.simple_bind("cn=Manager, fs=lustre","secret")
- except _ldap.LDAPError:
- print "unable to bind"
-
-
-
-# Lustre Node object class definition as per defined in the lustre.schema
-
-class LustreNode:
- def __init__(self, nodename):
- self.objectClass = "lustreNode"
- self.nodeUUID = 0
- self.id = nodename
- self.netUUIDs = []
- self.profileUUID = 0
- self.routerUUID = 0
- self.ldlmUUID = 0
-
- self.lustreNet = {}
- self.lustreNodeProfile = 0
- self.lustreLdlm = 0
-
- self.nodeUUID_str = "nodeUUID"
- self.id_str = "id"
- self.netUUIDs_str = "netUUIDs"
- self.ldlmUUID_str = "ldlmUUID"
- self.profileUUID_str = "profileUUID"
- self.routerUUID_str = "routerUUID"
- self.node_str = "node"
-
- def get_object_class(self):
- return self.objectClass
-
- def get_rdn(self):
- retval = "(objectClass="+self.objectClass+") (id="+self.id+")"
- return retval
-
- # Initilize lustre Node Object class after read drom LDAP server
- def init_node(self, node_entry):
- self.id = node_entry[0][1][self.id_str][0]
- self.nodeUUID = node_entry[0][1][self.nodeUUID_str][0]
- for i in range(len(node_entry[0][1][self.netUUIDs_str])):
- self.netUUIDs.append(node_entry[0][1][self.netUUIDs_str][i])
- if node_entry[0][1].has_key(self.profileUUID_str):
- self.profileUUID = node_entry[0][1][self.profileUUID_str][0]
- if node_entry[0][1].has_key(self.ldlmUUID_str):
- self.ldlmUUID = node_entry[0][1][self.ldlmUUID_str][0]
-
- if node_entry[0][1].has_key(self.routerUUID_str):
- self.routerUUID = node_entry[0][1][self.routerUUID_str][0]
-
- # Brings the lustre Node object entries from LDAP server
- def getEntry_from_ldap(self, conn_id, base):
- try:
- lustre_util = lustre_ldap()
- # the filter has id=<nodename>,type=node,fs=lustre
- # base is "fs=lustre"
- filter = lustre_util.get_filter(self.get_rdn())
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
- #network object class
- if self.netUUIDs:
- for netuuid in self.netUUIDs:
- # loading the network object class from LDAP, since this related to lustre node class
- self.lustreNet[netuuid] = LustreNet()
- self.lustreNet[netuuid].getEntry_from_ldap(conn_id, base, netuuid)
-
- # The ldlm object class
- if self.ldlmUUID:
- # loading the ldlm object class from LDAP, since this related to lustre node class
- self.lustreLdlm = LustreLdlm()
- self.lustreLdlm.getEntry_from_ldap(conn_id, base, self.ldlmUUID)
-
- # The lustre node profile object class
- if self.profileUUID:
- # loading the node profile object class from LDAP, since this related to lustre node class
- # The node profile contains the clientUUID, mdsUUIDs (multiple) and ostUUIDs(multiple)
- # the rest of the object class queried from LDAP server useing above UUIDs
- self.lustreNodeProfile = LustreNodeProfile()
- self.lustreNodeProfile.getEntry_from_ldap(conn_id, base, self.profileUUID)
-
- except ldap.NO_SUCH_OBJECT:
- print "no results Found"
- exit(1)
-
- def get_dn(self,id):
- return self.id_str+"="+id+",type="+self.node_str+",fs=lustre"
-
- # add entries into LDAP server, All of them are must fields
- def addEntry_into_ldap(self, conn_id, id, nodeUUID, netUUIDs, profileUUID, routerUUID, ldlmUUID):
- modlist = []
- dn = self.get_dn(self.id)
- modlist.append(("objectClass", [self.objectClass]))
- modlist.append((self.id_str, id))
- modlist.append((self.nodeUUID_str, nodeUUID))
- modlist.append((self.netUUIDs_str, netUUIDs))
- modlist.append((self.profileUUID_str, profileUUID))
- modlist.append((self.routerUUID_str, routerUUID))
- modlist.append((self.ldlmUUID_str, ldlmUUID))
- modlist.append(("fs", ["lustre"]))
- status = 0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- debug("lustre Node: "+ id +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
- # print values of object class
- def print_node(self):
- print "lustre Node Attributes......"
- print "objectClass: %s" % self.objectClass
- print "node UUID: %s" % self.nodeUUID
- print "node name: %s" % self.id
- for i in range(len(self.netUUIDs)):
- print "network UUID%d: %s" % (i,self.netUUIDs[i])
- print "Node Profile UUID: %s" % self.profileUUID
- print "Router UUID: %s" % self.routerUUID
- print "Ldlm UUID: %s" % self.ldlmUUID
- print
- for i in range(len(self.netUUIDs)):
- self.lustreNet[i].print_net()
-
- self.lustreNodeProfile.print_profile()
- self.lustreLdlm.print_ldlm()
-
-
-
-# lustre Client object class It have mount uuid and net uuid, but the net uuid may not required at present.
-class LustreClient:
- def __init__(self,lustreNode):
- self.objectClass = "lustreClient"
- self.clientUUID = 0
- self.mountUUIDs = []
- self.netUUID = 0
-
- self.lustreNode = lustreNode
- self.lustreNet = 0
- self.lustreMount = {}
-
-
- self.clientUUID_attr = "clientUUID"
- self.mountUUID_attr = "mountUUIDs"
- self.netUUID_attr = "netUUID"
- self.client_attr = "client"
-
- def ge_object_class(self):
- return self.objectClass
-
- def get_rdn(self,attr_value):
- retval = "(objectClass="+self.objectClass+") (clientUUID="+attr_value+")"
- return retval
-
-
- # load the object class with client config params
- def init_node(self,node_entry):
- self.clientUUID = node_entry[0][1][self.clientUUID_attr][0]
- for i in range(len(node_entry[0][1][self.mountUUID_attr])):
- self.mountUUIDs.append(node_entry[0][1][self.mountUUID_attr][i])
- self.netUUID = node_entry[0][1][self.netUUID_attr][0]
-
-
- # brings the client config params from LDAP, here the search criteria is clientUUID=lustre1_client_UUID,type=client,fs=lustre, this is called as dn
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util = lustre_ldap()
- # filter has "clientUUID=lustre1_client_UUID,type=client,fs=lustre"
- # the base is "fs=lustre"
- filter = lustre_util.get_filter(self.get_rdn(attr_val))
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Client Error No Results found"
- sys.exit(1)
-
- self.init_node(result)
-
- if self.netUUID:
- self.lustreNet = LustreNet()
- self.lustreNet.getEntry_from_ldap(conn_id, base, self.netUUID)
- else:
- print "Unable to find the LDLM uuid in Client Object Class..."
-
- if self.mountUUIDs:
- for mntuuid in self.mountUUIDs:
- self.lustreMount[mntuuid] = LustreMount()
- self.lustreMount[mntuuid].getEntry_from_ldap(conn_id, base, mntuuid)
-
-
- def get_dn(self, uuid):
- retval = self.clientUUID_attr+"="+uuid+",type="+self.client_attr+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id, clientUUID, mountUUIDs, netUUID):
- modlist = []
- dn = self.get_dn(clientUUID)
- modlist.append(("objectClass", [self.objectClass]))
- modlist.append((self.clientUUID_attr, clientUUID))
- modlist.append((self.mountUUID_attr, mountUUIDs))
- modlist.append((self.netUUID_attr, netUUID[0]))
- modlist.append(("fs", ["lustre"]))
- status = 0
- try:
- conn_id.add_s(dn, modlist)
- except _ldap.LDAPError:
- debug("lustre client: "+ clientUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_client(self):
- print "Lustre Client Configurations..............."
- print "client Object Calss: %s" % self.objectClass
- print "client UUID: %s" % self.clientUUID
- print "This client supporting %d file systems" % len(self.mountUUIDs)
- if self.lustreNet:
- self.lustreNet.print_net()
-
- if self.mountUUIDs:
- for mntuuid in self.mountUUIDs:
- self.lustreMount[mntuuid].print_mount()
-
-
-
-
-class LustreMount:
- def __init__(self):
- self.objectClass = "lustreMount"
- self.mountUUID = 0
- self.mdsUUID = 0
- self.lovUUID = 0
- self.mountPath = ""
- self.default = 0
-
- self.lustreMds = 0
- self.lustreLov = 0
-
- self.mountUUID_attr = "mountUUID"
- self.mdsUUID_attr = "mdsUUID"
- self.lovUUID_attr = "lovUUID"
- self.mountPath_attr = "mountPath"
- self.default_attr = "default"
- self.type = "mountPoint"
-
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self, attr_value):
- retval = "(objectClass="+self.objectClass+") (mountUUID="+attr_value+")"
- return retval
-
-
- def init_node(self, record):
- self.mdsUUID = record[0][1][self.mdsUUID_attr][0]
- self.mountUUID = record[0][1][self.mountUUID_attr][0]
- self.lovUUID = record[0][1][self.lovUUID_attr][0]
- self.mountPath = record[0][1][self.mountPath_attr][0]
- self.default = record[0][1][self.default_attr][0]
-
- def getEntry_from_ldap(self, conn_id, base, attr_val):
- lustre_util = lustre_ldap()
- filter = lustre_util.get_filter(self.get_rdn(attr_val))
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Mount Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.mdsUUID:
- self.lustreMds = LustreMds()
- self.lustreMds.getEntry_from_ldap(conn_id, base, self.mdsUUID)
-
- if self.lovUUID:
- self.lustreLov = LustreLov()
- self.lustreLov.getEntry_from_ldap(conn_id, base, self.lovUUID)
-
- def get_dn(self, uuid):
- retval = self.mountUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self, conn_id, mountUUID, mdsUUID, lovUUID, mountPath, default = 0):
- modlist = []
- dn=self.get_dn(mountUUID)
- modlist.append(("objectClass", [self.objectClass]))
- modlist.append((self.mountUUID_attr, mountUUID))
- modlist.append((self.mdsUUID_attr, mdsUUID))
- modlist.append((self.lovUUID_attr, lovUUID))
- modlist.append((self.mountPath_attr, mountPath))
- modlist.append((self.default_attr, default))
- modlist.append(("fs", ["lustre"]))
- status = 0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- debug("lustre Mount: "+ mountUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_mount(self):
-
- print "Lustre mount point attributes......"
- print "mount object class: %s" % self.objectClass
- print "mount UUID: %s" % self.mountUUID
- print "mds UUID: %s" % self.mdsUUID
- print "lov UUID: %s" % self.lovUUID
- print "mount point: %s" % self.mountPath
- if self.default:
- print "This file system is default file system for this cleint"
- else:
- print "This file system is not a default file system for this cleint"
-
- if self.lustreMds:
- self.lustreMds.print_mds()
- if self.lustreLov:
- self.lustreLov.print_lov()
-
-
-class LustreOsc:
- def __init__(self):
- self.objectClass = "lustreOSC"
- self.oscUUID = 0
- self.devName = ""
- self.obdUUID = 0
- self.ostUUID = 0
-
- self.lustreObd = 0
- self.lustreOst = 0
-
- self.oscUUID_attr = "oscUUID"
- self.devName_attr = "devName"
- self.obdUUID_attr = "obdUUID"
- self.ostUUID_attr = "ostUUID"
- self.type = "OSC"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self, attr_value):
- retval = "(objectClass="+self.objectClass+") (oscUUID="+attr_value+")"
- return retval
-
-
- def init_node(self, record):
- self.oscUUID=record[0][1][self.oscUUID_attr][0]
- self.obdUUID=record[0][1][self.obdUUID_attr][0]
- self.ostUUID=record[0][1][self.ostUUID_attr][0]
- self.devName=record[0][1][self.devName_attr][0]
-
-
- def getEntry_from_ldap(self, conn_id, base, attr_val):
- lustre_util = lustre_ldap()
- filter = lustre_util.get_filter(self.get_rdn(attr_val))
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.obdUUID:
- self.lustreObd = LustreObd()
- self.lustreObd.getEntry_from_ldap(conn_id, base, self.obdUUID)
-
- if self.ostUUID:
- self.lustreOst = LustreOst()
- self.lustreOst.getEntry_from_ldap(conn_id, base, self.ostUUID)
-
- def get_dn(self, uuid):
- retval = self.oscUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self, conn_id, oscUUID, devName, obdUUID, ostUUID):
- modlist = []
- dn=self.get_dn(oscUUID)
- modlist.append(("objectClass", [self.objectClass]))
- modlist.append((self.oscUUID_attr, oscUUID))
- modlist.append((self.devName_attr, devName))
- modlist.append((self.obdUUID_attr, obdUUID))
- modlist.append((self.ostUUID_attr, ostUUID))
- modlist.append(("fs", ["lustre"]))
- status = 0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- debug("lustre OSC : "+ oscUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_osc(self):
- print "Lustre Osc Attrributes.."
- print "object class: %s" % self.objectClass
- print "oscUUID: %s" % self.oscUUID
- print "devName: %s" % self.devName
- print "obdUUID: %s" % self.obdUUID
- print "ostUUID: %s" % self.ostUUID
- print
- if self.lustreObd:
- self.lustreObd.print_obd()
- print
- if self.lustreOst:
- self.lustreOst.print_ost()
- print
-
-
-class LustreMdc:
- def __init__(self):
- self.objectClass="lustreMDC"
- self.mdcUUID=0
- self.devName=""
- self.mdsUUID=0
-
- self.lustreMds=0
-
- self.mdcUUID_attr="mdcUUID"
- self.devName_attr="devName"
- self.mdsUUID_attr="mdsUUID"
- self.type="MDC"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (mdcUUID="+attr_value+")"
- return retval
-
-
- def init_node(self,record):
- self.mdcUUID=record[0][1][self.mdcUUID_attr][0]
- self.mdsUUID=record[0][1][self.mdsUUID_attr][0]
- self.devName=record[0][1][self.devName_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.mdsUUID:
- self.lustreMds=LustreMds()
- self.lustreMds.getEntry_from_ldap(conn_id,base,self.mdsUUID)
-
-
- def get_dn(self,uuid):
- retval=self.mdcUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.mdcUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.mdcUUID_attr,[self.mdcUUID]))
- modlist.append((self.devName_attr,self.devName))
- modlist.append((self.mdsUUID_attr,[self.mdsUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_mdc(self):
- print "Lustre Mdc attributes....."
- print "Mdc UUID: %s" % self.mdcUUID
- print "dev name: %s" % self.devName
- print "Mds UUId: %s" % self.mdsUUID
- print
- if self.lustreMds:
- self.lustreMds.print_mds()
-
-
-
-class LustreOst:
- def __init__(self):
- self.objectClass = "lustreOST"
- self.ostUUID = 0
- self.devName = ""
- self.obdUUID = 0
-
- self.lustreObd = 0
-
- self.ostUUID_attr = "ostUUID"
- self.devName_attr = "devName"
- self.obdUUID_attr = "obdUUID"
- self.type = "OST"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval = "(objectClass="+self.objectClass+") (ostUUID="+attr_value+")"
- return retval
-
- def init_node(self, record):
- self.ostUUID = record[0][1][self.ostUUID_attr][0]
- self.obdUUID = record[0][1][self.obdUUID_attr][0]
- self.devName = record[0][1][self.devName_attr][0]
-
- def getEntry_from_ldap(self, conn_id, base, attr_val):
- lustre_util = lustre_ldap()
- filter = lustre_util.get_filter(self.get_rdn(attr_val))
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.obdUUID:
- self.lustreObd = LustreObd()
- self.lustreObd.getEntry_from_ldap(conn_id, base, self.obdUUID)
-
-
- def get_dn(self,uuid):
- retval = self.ostUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self, conn_id, ostUUID, devName, obdUUID):
- modlist = []
- dn=self.get_dn(ostUUID)
- modlist.append(("objectClass", [self.objectClass]))
- modlist.append((self.ostUUID_attr, ostUUID))
- modlist.append((self.devName_attr, devName))
- modlist.append((self.obdUUID_attr, obdUUID))
- modlist.append(("fs", ["lustre"]))
- status=0
- try:
- conn_id.add_s(dn, modlist)
- except _ldap.LDAPError:
- debug("lustre OST : "+ ostUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_ost(self):
- print "Lustre Ost Attributes...."
- print "object class: %s" % self.objectClass
- print "ostUUID: %s" % self.ostUUID
- print "devName: %s" % self.devName
- print "obdUUID: %s" % self.obdUUID
- print
- if self.lustreObd:
- self.lustreObd.print_obd()
-
-
-
-class LustreMds:
- def __init__(self):
- self.objectClass = "lustreMDS"
- self.mdsUUID = 0
- self.devName = ""
- self.devUUID = 0
- self.lovUUID = 0
- self.fUUID = 0
-
- self.lustreDev = 0
- self.lustreLov = 0
-
- self.mdsUUID_attr = "mdsUUID"
- self.devName_attr = "devName"
- self.devUUID_attr = "devUUID"
- self.lovUUID_attr = "lovUUID"
- self.fUUID_attr = "fUUID"
- self.type = "MDS"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self, attr_value):
- retval = "(objectClass="+self.objectClass+") (mdsUUID="+attr_value+")"
- return retval
-
-
- def init_node(self,record):
- self.mdsUUID = record[0][1][self.mdsUUID_attr][0]
- self.devUUID = record[0][1][self.devUUID_attr][0]
- self.lovUUID = record[0][1][self.lovUUID_attr][0]
- #self.fUUID = record[0][1][self.fUUID_attr][0]
- self.devName = record[0][1][self.devName_attr][0]
-
- def getEntry_from_ldap(self, conn_id, base, attr_val):
- lustre_util = lustre_ldap()
- filter = lustre_util.get_filter(self.get_rdn(attr_val))
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
-
- if self.devUUID:
- self.lustreDev = LustreDevice()
- self.lustreDev.getEntry_from_ldap(conn_id, base, self.devUUID)
-
- if self.lovUUID:
- self.lustreLov = LustreLov()
- self.lustreLov.getEntry_from_ldap(conn_id, base, self.lovUUID)
-
-
- def get_dn(self, uuid):
- retval = self.mdsUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self, conn_id, mdsUUID, devName, devUUID, lovUUID, fUUID):
- modlist = []
- dn = self.get_dn(mdsUUID)
- modlist.append(("objectClass", [self.objectClass]))
- modlist.append((self.mdsUUID_attr, mdsUUID))
- modlist.append((self.devName_attr, devName))
- modlist.append((self.devUUID_attr, devUUID))
- if lovUUID:
- modlist.append((self.lovUUID_attr, lovUUID))
- modlist.append((self.fUUID_attr, fUUID))
- modlist.append(("fs", ["lustre"]))
- status = 0
-
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- debug("lustre MDS : "+ mdsUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_mds(self):
- print "Lustre Mds Attributes..."
- print "object Class: %s" % self.objectClass
- print "mdsUUID: %s" % self.mdsUUID
- print "devName: %s" % self.devName
- print "devUUID: %s" % self.devUUID
- #print "fUUID: %s" % self.fUUID
- print "lovUUID: %s" % self.lovUUID
- print
- if self.lustreLov:
- self.lustreLov.print_lov()
- print
-
-
-class LustreLov:
- def __init__(self):
- self.objectClass = "lustreLOV"
- self.lovUUID = 0
- self.devName = ""
- self.oscUUIDs = []
- self.stripeOffset = 0
- self.stripeSize = 0
- self.stripeCount = 0
- self.pattern = 0
-
- self.lustreOsc = {}
-
- self.lovUUID_attr = "lovUUID"
- self.devName_attr = "devName"
- self.oscUUID_attr = "oscUUIDs"
- self.stripeOffset_attr = "stripeOffset"
- self.stripeSize_attr = "stripeSize"
- self.stripeCount_attr = "stripeCount"
- self.pattern_attr = "pattern"
- self.type = "LOV"
-
- def get_object_class(self):
- return self.objectCalss
-
-
-
- def get_rdn(self,attr_value):
- retval = "(objectClass="+self.objectClass+") (lovUUID="+attr_value+")"
- return retval
-
-
- def init_node(self, record):
- nofvals = len(record[0][1][self.oscUUID_attr])
- for i in range(nofvals):
- self.oscUUIDs.append(record[0][1][self.oscUUID_attr][i])
-
- self.stripeOffset = record[0][1][self.stripeOffset_attr][0]
- self.lovUUID = record[0][1][self.lovUUID_attr][0]
- self.devName = record[0][1][self.devName_attr][0]
- self.stripeSize = record[0][1][self.stripeSize_attr][0]
- self.stripeCount = record[0][1][self.stripeCount_attr][0]
- self.pattern = record[0][1][self.pattern_attr][0]
-
- def getEntry_from_ldap(self, conn_id, base, attr_val):
- lustre_util = lustre_ldap()
- filter = lustre_util.get_filter(self.get_rdn(attr_val))
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
-
- if self.oscUUIDs:
- for uuid in self.oscUUIDs:
- self.lustreOsc[uuid] = LustreOsc()
- self.lustreOsc[uuid].getEntry_from_ldap(conn_id, base, uuid)
-
- def get_dn(self,uuid):
- retval = self.lovUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self, conn_id, lovUUID, devName, oscUUIDs, stripeOffset, stripeSize, stripeCount, pattern):
- modlist = []
- dn=self.get_dn(lovUUID)
- modlist.append(("objectClass", [self.objectClass]))
- modlist.append((self.lovUUID_attr, lovUUID))
- modlist.append((self.devName_attr, devName))
- modlist.append((self.oscUUID_attr, oscUUIDs))
- modlist.append((self.stripeOffset_attr, stripeOffset))
- modlist.append((self.stripeSize_attr, stripeSize))
- modlist.append((self.stripeCount_attr, stripeCount))
- modlist.append((self.pattern_attr, pattern))
- modlist.append(("fs", ["lustre"]))
- status = 0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- debug("lustre LOV: "+ lovUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_lov(self):
- print "Lustre LOV attributes..."
- print "object class: %s" % self.objectClass
- print "lovUUID: %s" % self.lovUUID
- print "devName: %s" % self.devName
- print "oscUUIDs are"
- for i in range(len(self.oscUUIDs)):
- print "oscUUID[%d]: %s" % (i,self.oscUUIDs[i])
- print "stripeOffset: %s" % self.stripeOffset
- print "stripe Size: %s" % self.stripeSize
- print "stripe Count: %s" % self.stripeCount
- print "pattern: %s" % self.pattern
-
- print
- if self.oscUUIDs:
- for uuid in self.oscUUIDs:
- if self.lustreOsc:
- self.lustreOsc[uuid].print_osc()
- print
-
-
-class LustreDevice:
- def __init__(self):
- self.objectClass = "lustreDevice"
- self.id = ""
- self.fid = ""
- self.devUUID = 0
- self.netUUID = 0
- self.fnetUUID = 0
- self.device = ""
- self.auto = 0
- self.fsType = ""
- self.size = 0
-
- self.id_attr = "id"
- self.fid_attr = "fid"
- self.devUUID_attr = "devUUID"
- self.netUUID_attr = "netUUID"
- self.fnetUUID_attr = "fnetUUID"
- self.device_attr = "device"
- self.auto_attr = "auto"
- self.fsType_attr = "fsType"
- self.size_attr = "size"
- self.type = "device"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self, attr_value):
- retval = "(objectClass="+self.objectClass+") (devUUID="+attr_value+")"
- return retval
-
- def init_node(self, record):
- self.devUUID = record[0][1][self.devUUID_attr][0]
- self.netUUID = record[0][1][self.netUUID_attr][0]
- self.fnetUUID = record[0][1][self.fnetUUID_attr][0]
- self.id = record[0][1][self.id_attr][0]
- self.fid = record[0][1][self.fid_attr][0]
- self.device = record[0][1][self.device_attr][0]
- self.auto = record[0][1][self.auto_attr][0]
- self.fsType = record[0][1][self.fsType_attr][0]
- self.size = record[0][1][self.size_attr][0]
-
- def getEntry_from_ldap(self, conn_id, base, attr_val):
- lustre_util = lustre_ldap()
- filter = lustre_util.get_filter(self.get_rdn(attr_val))
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- def get_dn(self,uuid):
- retval = self.devUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self, conn_id, devUUID, netUUID, fnetUUID, id, fid, device, auto, fsType, size):
- modlist = []
- dn = self.get_dn(devUUID)
- modlist.append(("objectClass", [self.objectClass]))
- modlist.append((self.devUUID_attr, devUUID))
- modlist.append((self.netUUID_attr, netUUID))
- modlist.append((self.fnetUUID_attr, fnetUUID))
- modlist.append((self.id_attr, id))
- modlist.append((self.fid_attr, fid))
- modlist.append((self.device_attr, device))
- modlist.append((self.auto_attr, auto))
- modlist.append((self.fsType_attr, fsType))
- modlist.append((self.size_attr, size))
- modlist.append(("fs", ["lustre"]))
- status = 0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- debug("lustre Device : "+ devUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_device(self):
- print "lustre Device object...."
- print "object Calss: %s" % self.objectClass
- print "node name: %s" % self.id
- print "failover node name: %s" % self.fid
- print "devUUID: %s" % self.devUUID
- print "netUUID: %s" % self.netUUID
- print "failover netUUID: %s" % self.fnetUUID
- print "device: %s" % self.device
- print "autoformat: %s" % self.auto
- print "fs type: %s" % self.fsType
- print "size of device: %s" % self.size
-
-
-
-class LustreObd:
- def __init__(self):
- self.objectClass = "lustreOBD"
- self.obdUUID = 0
- self.devName = ""
- self.devUUID = 0
- self.fUUID = 0
-
- self.lustreDev = 0
-
- self.obdUUID_attr = "obdUUID"
- self.devName_attr = "devName"
- self.devUUID_attr = "devUUID"
- self.fUUID_attr = "fUUID"
- self.type = "OBD"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval = "(objectClass="+self.objectClass+") (obdUUID="+attr_value+")"
- return retval
-
- def init_node(self, record):
- self.obdUUID = record[0][1][self.obdUUID_attr][0]
- self.devName = record[0][1][self.devName_attr][0]
- self.devUUID = record[0][1][self.devUUID_attr][0]
- self.fUUID = record[0][1][self.fUUID_attr][0]
-
- def getEntry_from_ldap(self, conn_id, base, attr_val):
- lustre_util = lustre_ldap()
- filter = lustre_util.get_filter(self.get_rdn(attr_val))
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.devUUID:
- self.lustreDev = LustreDevice()
- self.lustreDev.getEntry_from_ldap(conn_id, base, self.devUUID)
-
-
- def get_dn(self,uuid):
- retval = self.obdUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self, conn_id, obdUUID, devName, devUUID, fUUID):
- modlist = []
- dn=self.get_dn(obdUUID)
- modlist.append(("objectClass", [self.objectClass]))
- modlist.append((self.obdUUID_attr, obdUUID))
- modlist.append((self.devName_attr, devName))
- modlist.append((self.devUUID_attr, devUUID))
- modlist.append((self.fUUID_attr, fUUID))
- modlist.append(("fs", ["lustre"]))
- status = 0
- try:
- conn_id.add_s(dn, modlist)
- except _ldap.LDAPError:
- debug("lustre OBD : "+ obdUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_obd(self):
- print "Lustre Obd attributes...."
- print "object Class: %s" % self.objectClass
- print "obdUUID: %s" % self.obdUUID
- print "devName: %s" % self.devName
- print "devUUID: %s" % self.devUUID
- print "fUUID: %s" % self.fUUID
- print
- if self.lustreDev:
- self.lustreDev.print_device()
- print
-
-
-class LustreLdlm:
- def __init__(self):
- self.objectClass="lustreLDLM"
- self.ldlmUUID=0
- self.devName=""
-
- self.ldlmUUID_attr="ldlmUUID"
- self.devName_attr="devName"
- self.type="LDLM"
-
- def get_object_class(self):
- return self.objectCalss
-
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (ldlmUUID="+attr_value+")"
- return retval
-
- def init_node(self,record):
- self.ldlmUUID=record[0][1][self.ldlmUUID_attr][0]
- self.devName=record[0][1][self.devName_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
-
- def get_dn(self,uuid):
- retval=self.ldlmUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self, conn_id, ldlmUUID, devName):
- modlist=[]
- dn=self.get_dn(ldlmUUID)
- modlist.append(("objectClass", self.objectClass))
- modlist.append((self.ldlmUUID_attr, ldlmUUID))
- modlist.append((self.devName_attr, devName))
- modlist.append(("fs", "lustre"))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- debug("LDLM UUID: "+ ldlmUUID +" already added")
- #debug("LDLM UUID: "+ _ldap.LDAPError +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_ldlm(self):
- print "Printing LDLM attributes..........."
- print "ldlm Object Class: %s" % self.objectClass
- print "ldlm UUID: %s" % self.ldlmUUID
- print "ldlm Name: %s" % self.devName
- print "\n" * 5
-
-
-class LustreNet:
- def __init__(self):
- self.objectClass = "lustreNetwork"
- self.netUUID = 0
- self.id = 0
- self.fnetUUID = 0
- self.netType = ""
- self.netAddress = ""
- self.port = 0
- self.recvMem = 0
- self.sendMem = 0
-
- self.netUUID_attr = "netUUID"
- self.fnetUUID_attr = "fnetUUID"
- self.id_attr = "id"
- self.netType_attr = "netType"
- self.netAddress_attr = "netAddress"
- self.port_attr = "port"
- self.recvMem_attr = "recvMem"
- self.sendMem_attr = "sendMem"
- self.type = "net"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self, attr_value):
- retval = "(objectClass="+self.objectClass+") (netUUID="+attr_value+")"
- return retval
-
- def init_node(self, record):
- self.netUUID = record[0][1][self.netUUID_attr][0]
- self.fnetUUID = record[0][1][self.fnetUUID_attr][0]
- self.id = record[0][1][self.id_attr][0]
- self.netType = record[0][1][self.netType_attr][0]
- self.netAddress = record[0][1][self.netAddress_attr][0]
- self.port = record[0][1][self.port_attr][0]
- self.recvMem = record[0][1][self.recvMem_attr][0]
- self.sendMem = record[0][1][self.sendMem_attr][0]
-
- def getEntry_from_ldap(self, conn_id, base, attr_val):
- lustre_util = lustre_ldap()
- filter = lustre_util.get_filter(self.get_rdn(attr_val))
- result = conn_id.search_s(base, ldap.SCOPE_SUBTREE, filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
-
- def get_dn(self, uuid):
- retval = self.netUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id, id, netUUID, fnetUUID, netType, netAddress, port, recvMem, sendMem):
- modlist = []
- dn=self.get_dn(netUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.netUUID_attr,[netUUID]))
- modlist.append((self.fnetUUID_attr,[fnetUUID]))
- modlist.append((self.id_attr,[id]))
- modlist.append((self.netType_attr,[netType]))
- modlist.append((self.netAddress_attr,[netAddress]))
- modlist.append((self.port_attr,[port]))
- modlist.append((self.recvMem_attr,[recvMem]))
- modlist.append((self.sendMem_attr,[sendMem]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- debug("lustre Network : "+ netUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_net(self):
- print "Lustre Network Attributes:......"
- print "object Class: %s" % self.objectClass
- print "network UUID: %s" % self.netUUID
- print "failover network UUID: %s" % self.fnetUUID
- print "node name : %s" % self.id
- print "network Type: %s" % self.netType
- print "IP Address: %s" % self.netAddress
- print "port: %s" % self.port
- print "receive memory: %s" % self.recvMem
- print "send memory: %s" % self.sendMem
- print
-
-
-class LustreNodeProfile:
- def __init__(self):
- self.objectClass="lustreNodeProfile"
- self.profileUUID=0
- self.mdsUUIDs=[]
- self.ostUUIDs=[]
- self.clientUUID=0
-
- self.profileUUID_str="profileUUID"
- self.mdsUUIDs_str="mdsUUIDs"
- self.ostUUIDs_str="ostUUIDs"
- self.clientUUID_str="clientUUID"
- self.type="profile"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (profileUUID="+attr_value+")"
- return retval
-
- def init_node(self,node_entry):
- self.profileUUID=node_entry[0][1][self.profileUUID_str][0]
- if node_entry[0][1].has_key(self.mdsUUIDs_str):
- for i in range(len(node_entry[0][1][self.mdsUUIDs_str])):
- self.mdsUUIDs.append(node_entry[0][1][self.mdsUUIDs_str][i])
-
- if node_entry[0][1].has_key(self.ostUUIDs_str):
- for i in range(len(node_entry[0][1][self.ostUUIDs_str])):
- self.ostUUIDs.append(node_entry[0][1][self.ostUUIDs_str][i])
-
- if node_entry[0][1].has_key(self.clientUUID_str):
- self.clientUUID=node_entry[0][1][self.clientUUID_str][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- def get_dn(self,uuid):
- retval=self.profileUUID_str+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id,profileUUID,mdsUUIDs,ostUUIDs,clientUUID):
- modlist=[]
- dn=self.get_dn(profileUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.profileUUID_str,[profileUUID]))
- if mdsUUIDs:
- modlist.append((self.mdsUUIDs_str,mdsUUIDs))
- if ostUUIDs:
- modlist.append((self.ostUUIDs_str,ostUUIDs))
- if clientUUID:
- modlist.append((self.clientUUID_str,[clientUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- debug("lustre Profile: "+ profileUUID +" already added")
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_profile(self):
- print "Lustre Node Profile Attributes:......"
- print "object Class: %s" % self.objectClass
- print "profile UUID: %s" % self.profileUUID
- print "This node supports %d mds servers:" % len(self.mdsUUIDs)
- for i in range(len(self.mdsUUIDs)):
- print "Mds UUID%d: %s" % (i,self.mdsUUIDs[i])
- print "This node supports %d ost servers:" % len(self.ostUUIDs)
- for i in range(len(self.ostUUIDs)):
- print "Ost UUID%d: %s" % (i,self.ostUUIDs[i])
- print "Client UUID: %s" % self.clientUUID
- print
-
-
-def get_matched_osc(ConnId,ostuuid):
- result = ConnId.search_s("fs=lustre",ldap.SCOPE_SUBTREE,"objectclass=lustreOSC")
- lustreOSC = 0
- if result:
- for i in range(len(result)):
- tmpuuid = result[i][1]['ostUUID'][0]
- if ostuuid == tmpuuid:
- lustreOSC = LustreOsc()
- lustreOSC.init_node([result[i]])
- break
-
- else:
- print "no result"
-
- return lustreOSC
-
-
-def get_matched_lov(ConnId,oscuuid):
- result = ConnId.search_s("fs=lustre",ldap.SCOPE_SUBTREE,"objectclass=lustreLOV")
- lustreLOV = 0
- tmpuuids = []
- if result:
- for i in range(len(result)):
- tmpuuids = result[i][1]['oscUUIDs']
- for uuid in tmpuuids:
- if oscuuid == uuid:
- lustreLOV = LustreLov()
- lustreLOV.init_node([result[i]])
- return lustreLOV
- return 0
-
-
-
-
-
-
-
-
-net_uuids = []
-def loadNetworkconfig(dom_node,node):
- global net_uuids
- node_name = get_attr(node,'name')
- net = Network(dom_node)
- net_uuids.append(net.uuid)
- failnetUUID = net.uuid
- lustreNet = LustreNet()
- lustreNet.addEntry_into_ldap(connId, node_name, net.uuid, failnetUUID, net.net_type, str(net.nid), str(net.port), str(net.send_mem), str(net.recv_mem))
-
-
-ldlm_uuid = 0
-def loadLDLMconfig(dom_node,node):
- "This is fill LDLM details...:"
- global ldlm_uuid
- ldlm = LDLM(dom_node)
- ldlm_uuid = ldlm.uuid
- lustreLdlm = LustreLdlm()
- lustreLdlm.addEntry_into_ldap(connId, ldlm.uuid, ldlm.name)
-
-lov_uuids = []
-lovUUID = 0
-def loadLOVconfig(dom_node,node):
- global lov_uuids
- global lovUUID
- lov_uuid = get_first_ref(dom_node, 'lov')
- lov_node = lookup(dom_node.parentNode, lov_uuid)
- lov = LOV(lov_node)
- lov_uuids.append(lov.uuid)
- lovUUID = lov.uuid
- node_name = get_attr(node,'name')
- osc_uuids = []
- for uuid in lov.devlist:
- osc_uuids.append(str(uuid))
- objlov = LustreLov()
- objlov.addEntry_into_ldap(connId, lov.uuid, lov.name, osc_uuids, str(lov.stripe_off), str(lov.stripe_sz), str(lov.stripe_cnt), str(lov.pattern))
-
- lov_devs = lov_node.getElementsByTagName('devices')
- devlist = get_all_refs(lov_devs[0], 'osc')
- for osc_uuid in devlist:
- osc_node = lookup(dom_node.parentNode,osc_uuid)
- osc = OSC(osc_node)
- lustreOsc = LustreOsc()
- lustreOsc .addEntry_into_ldap(connId, osc.uuid, osc.name, str(osc.obd_uuid), str(osc.ost_uuid))
-
-mds_uuids = []
-def loadMDSconfig( dom_node,node):
- global mds_uuids
- global lovUUID
- node_name = getName(node)
- mds = MDS(dom_node)
- mds_net = mds.get_server()
-
- netuuid = mds_net.uuid
- failnetuuid = netuuid
- fid = mds_net.nid
- device_name = new_name('DEVICE_'+node_name)
- devuuid = new_uuid(device_name)
- lov_uuid = get_first_ref(dom_node, 'lov')
-
- objdevice = LustreDevice()
- objdevice.addEntry_into_ldap(connId, devuuid, netuuid, netuuid, node_name, node_name, str(mds.devname), str(mds.format), str(mds.fstype), str(mds.size))
-
- lovcfg_uuids = get_all_refs(node, 'lovconfig')
- for lovcfg_uuid in lovcfg_uuids:
- lovcfg = 0
- if lovcfg_uuid:
- lovcfg_node = lookup(dom_node.parentNode, lovcfg_uuid )
- lovcfg = LOVConfig(lovcfg_node)
- lov_uuid = 0
- if lovcfg:
- lov_uuid = str(lovcfg.lov_uuid)
- lov_node = lookup(dom_node.parentNode, lov_uuid)
- lov = LOV(lov_node)
- if mds.uuid == lov.mds_uuid:
- #print "Match found"
- break
-
- lustreMds = LustreMds()
- lustreMds.addEntry_into_ldap(connId, mds.uuid, mds.name, devuuid, lov_uuid, mds.uuid)
- mds_uuids.append(mds.uuid)
-
-
-def loadOBDconfig(dom_node,node):
- global net_uuids
- node_name = get_attr(node,'name')
- obd = OBD(dom_node)
- device_name = new_name('DEVICE_'+node_name)
- devuuid = new_uuid(device_name)
-
- lustreDev = LustreDevice()
- lustreDev.addEntry_into_ldap(connId, devuuid, net_uuids[0], net_uuids[0], node_name, node_name, str(obd.devname), str(obd.format), str(obd.fstype), str(obd.size))
-
- lustreObd = LustreObd()
- lustreObd.addEntry_into_ldap(connId, obd.uuid, obd.name, devuuid, obd.uuid)
-
-
-mount_uuids = []
-def loadMountpointconfig(dom_node,node):
- global mount_uuids
- node_name = get_attr(node,'name')
- mount = Mountpoint(dom_node)
-
- mountuuid = new_uuid(mount.name)
- mount_uuids.append(mountuuid)
- lustreMount = LustreMount()
- lustreMount.addEntry_into_ldap(connId, mountuuid, str(mount.mds_uuid), str(mount.lov_uuid),str(mount.path), "No")
-
-
-
-ost_uuids = []
-def loadOSTconfig(dom_node,node):
- global ost_uuids
- ost = OST(dom_node)
- node_name = get_attr(node,'name')
-
- lustreOst = LustreOst()
- lustreOst.addEntry_into_ldap(connId, ost.uuid, ost.name, str(ost.obd_uuid))
- ost_uuids.append(ost.uuid)
-
-############################################################
-# lconf level logic
-# Start a service.
-
-
-
-
-def LoadProfile(lustreNode,profileNode,node):
- global mount_uuids
- global profile_uuid
- node_name = get_attr(node,'name')
- if not profileNode:
- panic("profile:",profile,"not found.")
- services = getServices(lustreNode,profileNode)
- if services:
- for service in services:
- dom_node = service
- type = getServiceType(dom_node)
- if type == 'ldlm':
- loadLDLMconfig(dom_node,node)
- elif type == 'obd':
- loadOBDconfig(dom_node,node)
- elif type == 'lovconfig':
- loadLOVconfig(dom_node,node)
- elif type == 'network':
- loadNetworkconfig(dom_node,node)
- elif type == 'ost':
- loadOSTconfig(dom_node,node)
- elif type == 'mds':
- loadMDSconfig(dom_node,node)
- elif type == 'mountpoint':
- loadMountpointconfig(dom_node,node)
- else:
- panic ("unknown service type:", type)
-
-
- clientuuid = 0
- if mount_uuids:
- clientuuid = node_name + "clientUUID"
- lustre_Node = LustreNode(node_name)
- lustreClient = LustreClient(lustre_Node)
- lustreClient.addEntry_into_ldap(connId, clientuuid, mount_uuids, net_uuids)
-
-
- profile_uuid = str(node_name+"profileUUID")
- nodeprofile = LustreNodeProfile()
- nodeprofile.addEntry_into_ldap(connId, profile_uuid, mds_uuids, ost_uuids, clientuuid)
-
-def Initilize_globals():
- global mds_uuids
- global ost_uuids
- global net_uuids
- global clientuuid
- global profile_uuid
- global ldlm_uuid
- global mount_uuids
- mount_uuids = []
- mds_uuids = []
- ost_uuids = []
- net_uuids = []
- lov_uuids = []
- clientuuid = 0
- profile_uuid = 0
- ldlm_uuid = 0
-
-def print_globals():
- global mds_uuids
- global ost_uuids
- global net_uuids
- global clientuuid
- global profile_uuid
- global ldlm_uuid
- print "mds_uuids :", mds_uuids
- print "ost_uuids :", ost_uuids
- print "net_uuids :", net_uuids
- print "client uuid :", clientuuid
- print "profile_uuid :", profile_uuid
- print "ldlm_uuid :", ldlm_uuid
-
-connId = 0
-def loadXml(lustreNode):
- global net_uuids
- global ldlm_uuid
- global profile_uuid
- dom_node = None
- Initilize_globals()
-
- global connId
- server = "blackswan.india.hp.com"
- port=389
- binddn="cn=Manager,fs=lustre"
- base="fs=lustre"
- myCon=MyConn(server,port)
- myCon.open()
- connId=myCon.id
-
- nodelist = []
- nodelist = lustreNode.getElementsByTagName('node')
- for i in range(len(nodelist)):
- node_name = getName(nodelist[i])
- node_uuid = getUUID(nodelist[i])
- dom_node = getByName(lustreNode, node_name, 'node')
- if dom_node == None:
- break
- Node = LustreNode(node_name)
- reflist = dom_node.getElementsByTagName('profile')
- if reflist:
- for profile in reflist:
- LoadProfile(lustreNode,profile,dom_node)
- Node.addEntry_into_ldap(connId,node_name,node_uuid,net_uuids,profile_uuid,net_uuids,ldlm_uuid)
- Initilize_globals()
-
-
+++ /dev/null
-
-#!/usr/bin/env python
-#
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Author: Robert Read <rread@clusterfs.com>
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free 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.
-#
-# 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
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# lconf - lustre configuration tool
-#
-# lconf is the main driver script for starting and stopping
-# lustre filesystem services.
-#
-# Based in part on the XML obdctl modifications done by Brian Behlendorf
-
-import sys, getopt
-import string, os, stat, popen2, socket, time, random
-import re, exceptions
-import xml.dom.minidom
-
-# Global parameters
-TCP_ACCEPTOR = ''
-MAXTCPBUF = 1048576
-DEFAULT_TCPBUF = 1048576
-#
-# Maximum number of devices to search for.
-# (the /dev/loop* nodes need to be created beforehand)
-MAX_LOOP_DEVICES = 256
-
-
-first_cleanup_error = 0
-def cleanup_error(rc):
- global first_cleanup_error
- if not first_cleanup_error:
- first_cleanup_error = rc
-
-
-
-
-# ============================================================
-# Config parameters, encapsulated in a class
-class Config:
- def __init__(self):
- # flags
- self._noexec = 0
- self._verbose = 0
- self._reformat = 0
- self._cleanup = 0
- self._gdb = 0
- self._nomod = 0
- self._nosetup = 0
- self._force = 0
- # parameters
- self._modules = None
- self._node = None
- self._url = None
- self._gdb_script = '/tmp/ogdb'
- self._debug_path = '/tmp/lustre-log'
- self._dump_file = None
- self._src_dir = None
- self._minlevel = 0
- self._maxlevel = 100
- self._ldap = 0
-
- def ldapadd(self, flag = None):
- if flag: self._ldap= flag
- return self._ldap
-
- def verbose(self, flag = None):
- if flag: self._verbose = flag
- return self._verbose
-
- def noexec(self, flag = None):
- if flag: self._noexec = flag
- return self._noexec
-
- def reformat(self, flag = None):
- if flag: self._reformat = flag
- return self._reformat
-
- def cleanup(self, flag = None):
- if flag: self._cleanup = flag
- return self._cleanup
-
- def gdb(self, flag = None):
- if flag: self._gdb = flag
- return self._gdb
-
- def nomod(self, flag = None):
- if flag: self._nomod = flag
- return self._nomod
-
- def nosetup(self, flag = None):
- if flag: self._nosetup = flag
- return self._nosetup
-
- def force(self, flag = None):
- if flag: self._force = flag
- return self._force
-
- def node(self, val = None):
- if val: self._node = val
- return self._node
-
- def url(self, val = None):
- if val: self._url = val
- return self._url
-
- def gdb_script(self):
- if os.path.isdir('/r'):
- return '/r' + self._gdb_script
- else:
- return self._gdb_script
-
- def debug_path(self):
- if os.path.isdir('/r'):
- return '/r' + self._debug_path
- else:
- return self._debug_path
-
- def src_dir(self, val = None):
- if val: self._src_dir = val
- return self._src_dir
-
- def dump_file(self, val = None):
- if val: self._dump_file = val
- return self._dump_file
-
- def minlevel(self, val = None):
- if val: self._minlevel = int(val)
- return self._minlevel
-
- def maxlevel(self, val = None):
- if val: self._maxlevel = int(val)
- return self._maxlevel
-
-
-
-config = Config()
-
-# ============================================================
-# debugging and error funcs
-
-def fixme(msg = "this feature"):
- raise LconfError, msg + ' not implmemented yet.'
-
-def panic(*args):
- msg = string.join(map(str,args))
- if not config.noexec():
- raise LconfError(msg)
- else:
- print "! " + msg
-
-def log(*args):
- msg = string.join(map(str,args))
- print msg
-
-def logall(msgs):
- for s in msgs:
- print string.strip(s)
-
-def debug(*args):
- if config.verbose():
- msg = string.join(map(str,args))
- print msg
-
-# ============================================================
-# locally defined exceptions
-class CommandError (exceptions.Exception):
- def __init__(self, cmd_name, cmd_err, rc=None):
- self.cmd_name = cmd_name
- self.cmd_err = cmd_err
- self.rc = rc
-
- def dump(self):
- import types
- if type(self.cmd_err) == types.StringType:
- if self.rc:
- print "! %s (%d): %s" % (self.cmd_name, self.rc, self.cmd_err)
- else:
- print "! %s: %s" % (self.cmd_name, self.cmd_err)
- elif type(self.cmd_err) == types.ListType:
- if self.rc:
- print "! %s (error %d):" % (self.cmd_name, self.rc)
- else:
- print "! %s:" % (self.cmd_name)
- for s in self.cmd_err:
- print "> %s" %(string.strip(s))
- else:
- print self.cmd_err
-
-class LconfError (exceptions.Exception):
- def __init__(self, args):
- self.args = args
-
-# Determine full path to use for an external command
-# searches dirname(argv[0]) first, then PATH
-def find_prog(cmd):
- syspath = string.split(os.environ['PATH'], ':')
- cmdpath = os.path.dirname(sys.argv[0])
- syspath.insert(0, cmdpath);
- syspath.insert(0, os.path.join(cmdpath, '../../portals/linux/utils/'))
- for d in syspath:
- prog = os.path.join(d,cmd)
- if os.access(prog, os.X_OK):
- return prog
- return ''
-
-# ============================================================
-# handle lctl interface
-class LCTLInterface:
- """
- Manage communication with lctl
- """
-
- def __init__(self, cmd):
- """
- Initialize close by finding the lctl binary.
- """
- self.lctl = find_prog(cmd)
- if not self.lctl:
- if config.noexec():
- debug('! lctl not found')
- self.lctl = 'lctl'
- else:
- raise CommandError('lctl', "unable to find lctl binary.")
-
- def run(self, cmds):
- """
- run lctl
- the cmds are written to stdin of lctl
- lctl doesn't return errors when run in script mode, so
- stderr is checked
- should modify command line to accept multiple commands, or
- create complex command line options
- """
- debug("+", self.lctl, cmds)
- if config.noexec(): return (0, [])
- p = popen2.Popen3(self.lctl, 1)
- p.tochild.write(cmds + "\n")
- p.tochild.close()
- out = p.fromchild.readlines()
- err = p.childerr.readlines()
- ret = p.wait()
- if os.WIFEXITED(ret):
- rc = os.WEXITSTATUS(ret)
- else:
- rc = 0
- if rc or len(err):
- raise CommandError(self.lctl, err, rc)
- return rc, out
-
- def runcmd(self, *args):
- """
- run lctl using the command line
- """
- cmd = string.join(map(str,args))
- debug("+", self.lctl, cmd)
- rc, out = run(self.lctl, cmd)
- if rc:
- raise CommandError(self.lctl, out, rc)
- return rc, out
-
-
- def network(self, net, nid):
- """ initialized network and add "self" """
- # Idea: "mynid" could be used for all network types to add "self," and then
- # this special case would be gone and the "self" hack would be hidden.
- global lctl
- if net in ('tcp', 'toe'):
- cmds = """
- network %s
- mynid %s
- add_uuid self %s
- quit""" % (net, nid, nid)
- else:
- cmds = """
- network %s
- add_uuid self %s
- quit""" % (net, nid)
-
- self.run(cmds)
-
- # create a new connection
- def connect(self, net, nid, port, servuuid, send_mem, recv_mem):
- if net in ('tcp', 'toe'):
- cmds = """
- network %s
- add_uuid %s %s
- send_mem %d
- recv_mem %d
- connect %s %d
- quit""" % (net, servuuid, nid, send_mem, recv_mem, nid, port, )
- else:
- cmds = """
- network %s
- add_uuid %s %s
- connect %s %d
- quit""" % (net, servuuid, nid, nid, port, )
-
- self.run(cmds)
-
- # add a route to a range
- def add_route(self, net, gw, lo, hi):
- cmds = """
- network %s
- add_route %s %s %s
- quit """ % (net, gw, lo, hi)
- self.run(cmds)
-
-
- def del_route(self, net, gw, lo, hi):
- cmds = """
- ignore_errors
- network %s
- del_route %s
- quit """ % (net, lo)
- self.run(cmds)
-
- # add a route to a host
- def add_route_host(self, net, uuid, gw, tgt):
- cmds = """
- network %s
- add_uuid %s %s
- add_route %s %s
- quit """ % (net, uuid, tgt, gw, tgt)
- self.run(cmds)
-
- # add a route to a range
- def del_route_host(self, net, uuid, gw, tgt):
- cmds = """
- ignore_errors
- network %s
- del_uuid %s
- del_route %s
- quit """ % (net, uuid, tgt)
- self.run(cmds)
-
- # disconnect one connection
- def disconnect(self, net, nid, port, servuuid):
- cmds = """
- ignore_errors
- network %s
- disconnect %s
- del_uuid %s
- quit""" % (net, nid, servuuid)
- self.run(cmds)
-
- # disconnect all
- def disconnectAll(self, net):
- cmds = """
- ignore_errors
- network %s
- del_uuid self
- disconnect
- quit""" % (net)
- self.run(cmds)
-
- # create a new device with lctl
- def newdev(self, attach, setup = ""):
- cmds = """
- newdev
- attach %s
- setup %s
- quit""" % (attach, setup)
- self.run(cmds)
-
- # cleanup a device
- def cleanup(self, name, uuid):
- cmds = """
- ignore_errors
- device $%s
- cleanup
- detach %s
- quit""" % (name, ('', 'force')[config.force()])
- self.run(cmds)
-
- # create an lov
- def lov_setconfig(self, uuid, mdsuuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist):
- cmds = """
- device $%s
- probe
- lov_setconfig %s %d %d %d %s %s
- quit""" % (mdsuuid, uuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist)
- self.run(cmds)
-
- # dump the log file
- def dump(self, dump_file):
- cmds = """
- debug_kernel %s 1
- quit""" % (dump_file)
- self.run(cmds)
-
- # get list of devices
- def device_list(self):
- rc, out = self.runcmd('device_list')
- return out
-
-lctl = LCTLInterface('lctl')
-# ============================================================
-# Various system-level functions
-# (ideally moved to their own module)
-
-# Run a command and return the output and status.
-# stderr is sent to /dev/null, could use popen3 to
-# save it if necessary
-def run(*args):
- cmd = string.join(map(str,args))
- debug ("+", cmd)
- if config.noexec(): return (0, [])
- f = os.popen(cmd + ' 2>&1')
- out = f.readlines()
- ret = f.close()
- if ret:
- ret = ret >> 8
- else:
- ret = 0
- return (ret, out)
-
-# Run a command in the background.
-def run_daemon(*args):
- cmd = string.join(map(str,args))
- debug ("+", cmd)
- if config.noexec(): return 0
- f = os.popen(cmd + ' 2>&1')
- ret = f.close()
- if ret:
- ret = ret >> 8
- else:
- ret = 0
- return ret
-
-
-# Recursively look for file starting at base dir
-def do_find_file(base, mod):
- fullname = os.path.join(base, mod)
- if os.access(fullname, os.R_OK):
- return fullname
- for d in os.listdir(base):
- dir = os.path.join(base,d)
- if os.path.isdir(dir):
- module = do_find_file(dir, mod)
- if module:
- return module
-
-def find_module(src_dir, dev_dir, modname):
- mod = '%s.o' % (modname)
- module = src_dir +'/'+ dev_dir +'/'+ mod
- try:
- if os.access(module, os.R_OK):
- return module
- except OSError:
- pass
- return None
-
-# is the path a block device?
-def is_block(path):
- s = ()
- try:
- s = os.stat(path)
- except OSError:
- return 0
- return stat.S_ISBLK(s[stat.ST_MODE])
-
-# build fs according to type
-# fixme: dangerous
-def mkfs(fstype, dev):
- if(fstype in ('ext3', 'extN')):
- mkfs = 'mkfs.ext2 -j -b 4096'
- else:
- print 'unsupported fs type: ', fstype
- if not is_block(dev):
- force = '-F'
- else:
- force = ''
- (ret, out) = run (mkfs, force, dev)
- if ret:
- panic("Unable to build fs:", dev)
- # enable hash tree indexing on fsswe
- # FIXME: this check can probably go away on 2.5
- if fstype == 'extN':
- htree = 'echo "feature FEATURE_C5" | debugfs -w'
- (ret, out) = run (htree, dev)
- if ret:
- panic("Unable to enable htree:", dev)
-
-# some systems use /dev/loopN, some /dev/loop/N
-def loop_base():
- import re
- loop = '/dev/loop'
- if not os.access(loop + str(0), os.R_OK):
- loop = loop + '/'
- if not os.access(loop + str(0), os.R_OK):
- panic ("can't access loop devices")
- return loop
-
-# find loop device assigned to thefile
-def find_loop(file):
- loop = loop_base()
- for n in xrange(0, MAX_LOOP_DEVICES):
- dev = loop + str(n)
- if os.access(dev, os.R_OK):
- (stat, out) = run('losetup', dev)
- if (out and stat == 0):
- m = re.search(r'\((.*)\)', out[0])
- if m and file == m.group(1):
- return dev
- else:
- break
- return ''
-
-# create file if necessary and assign the first free loop device
-def init_loop(file, size, fstype):
- dev = find_loop(file)
- if dev:
- print 'WARNING file:', file, 'already mapped to', dev
- return dev
- if config.reformat() or not os.access(file, os.R_OK | os.W_OK):
- run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size, file))
- loop = loop_base()
- # find next free loop
- for n in xrange(0, MAX_LOOP_DEVICES):
- dev = loop + str(n)
- if os.access(dev, os.R_OK):
- (stat, out) = run('losetup', dev)
- if (stat):
- run('losetup', dev, file)
- return dev
- else:
- print "out of loop devices"
- return ''
- print "out of loop devices"
- return ''
-
-# undo loop assignment
-def clean_loop(file):
- dev = find_loop(file)
- if dev:
- ret, out = run('losetup -d', dev)
- if ret:
- log('unable to clean loop device:', dev, 'for file:', file)
- logall(out)
-
-# determine if dev is formatted as a <fstype> filesystem
-def need_format(fstype, dev):
- # FIXME don't know how to implement this
- return 0
-
-# initialize a block device if needed
-def block_dev(dev, size, fstype, format):
- if config.noexec(): return dev
- if not is_block(dev):
- dev = init_loop(dev, size, fstype)
- if config.reformat() or (need_format(fstype, dev) and format == 'yes'):
- mkfs(fstype, dev)
-
-# else:
-# panic("device:", dev,
-# "not prepared, and autoformat is not set.\n",
-# "Rerun with --reformat option to format ALL filesystems")
-
- return dev
-
-def if2addr(iface):
- """lookup IP address for an interface"""
- rc, out = run("/sbin/ifconfig", iface)
- if rc or not out:
- return None
- addr = string.split(out[1])[1]
- ip = string.split(addr, ':')[1]
- return ip
-
-def get_local_address(net_type, wildcard):
- """Return the local address for the network type."""
- local = ""
- if net_type in ('tcp', 'toe'):
- if ':' in wildcard:
- iface, star = string.split(wildcard, ':')
- local = if2addr(iface)
- if not local:
- panic ("unable to determine ip for:", wildcard)
- else:
- host = socket.gethostname()
- local = socket.gethostbyname(host)
- elif net_type == 'elan':
- # awk '/NodeId/ { print $2 }' '/proc/elan/device0/position'
- try:
- fp = open('/proc/elan/device0/position', 'r')
- lines = fp.readlines()
- fp.close()
- for l in lines:
- a = string.split(l)
- if a[0] == 'NodeId':
- local = a[1]
- break
- except IOError, e:
- log(e)
- elif net_type == 'gm':
- fixme("automatic local address for GM")
- return local
-
-
-def is_prepared(uuid):
- """Return true if a device exists for the uuid"""
- # expect this format:
- # 1 UP ldlm ldlm ldlm_UUID 2
- try:
- out = lctl.device_list()
- for s in out:
- if uuid == string.split(s)[4]:
- return 1
- except CommandError, e:
- e.dump()
- return 0
-
-
-
-############################################################
-# MDC UUID hack -
-# FIXME: clean this mess up!
-#
-saved_mdc = {}
-def prepare_mdc(dom_node, mds_uuid):
- global saved_mdc
- mds_node = lookup(dom_node, mds_uuid);
- if not mds_node:
- panic("no mds:", mds_uuid)
- if saved_mdc.has_key(mds_uuid):
- return saved_mdc[mds_uuid]
- mdc = MDC(mds_node)
- mdc.prepare()
- saved_mdc[mds_uuid] = mdc.uuid
- return mdc.uuid
-
-def cleanup_mdc(dom_node, mds_uuid):
- global saved_mdc
- mds_node = lookup(dom_node, mds_uuid);
- if not mds_node:
- panic("no mds:", mds_uuid)
- if not saved_mdc.has_key(mds_uuid):
- mdc = MDC(mds_node)
- mdc.cleanup()
- saved_mdc[mds_uuid] = mdc.uuid
-
-
-# ============================================================
-# Classes to prepare and cleanup the various objects
-#
-class Module:
- """ Base class for the rest of the modules. The default cleanup method is
- defined here, as well as some utilitiy funcs.
- """
- def __init__(self, module_name, dom_node):
- self.dom_node = dom_node
- self.module_name = module_name
- self.name = get_attr(dom_node, 'name')
- self.uuid = get_attr(dom_node, 'uuid')
- self.kmodule_list = []
- self._server = None
- self._connected = 0
-
- def info(self, *args):
- msg = string.join(map(str,args))
- print self.module_name + ":", self.name, self.uuid, msg
-
-
- def lookup_server(self, srv_uuid):
- """ Lookup a server's network information """
- net = get_ost_net(self.dom_node.parentNode, srv_uuid)
- if not net:
- panic ("Unable to find a server for:", srv_uuid)
- self._server = Network(net)
-
- def get_server(self):
- return self._server
-
- def cleanup(self):
- """ default cleanup, used for most modules """
- self.info()
- srv = self.get_server()
- if srv and local_net(srv):
- try:
- lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
- except CommandError, e:
- log(self.module_name, "disconnect failed: ", self.name)
- e.dump()
- cleanup_error(e.rc)
- try:
- lctl.cleanup(self.name, self.uuid)
- except CommandError, e:
- log(self.module_name, "cleanup failed: ", self.name)
- e.dump()
- cleanup_error(e.rc)
-
- def add_module(self, dev_dir, modname):
- """Append a module to list of modules to load."""
- self.kmodule_list.append((dev_dir, modname))
-
- def mod_loaded(self, modname):
- """Check if a module is already loaded. Look in /proc/modules for it."""
- fp = open('/proc/modules')
- lines = fp.readlines()
- fp.close()
- # please forgive my tired fingers for this one
- ret = filter(lambda word, mod=modname: word == mod,
- map(lambda line: string.split(line)[0], lines))
- return ret
-
- def load_module(self):
- """Load all the modules in the list in the order they appear."""
- for dev_dir, mod in self.kmodule_list:
- # (rc, out) = run ('/sbin/lsmod | grep -s', mod)
- if self.mod_loaded(mod) and not config.noexec():
- continue
- log ('loading module:', mod)
- if config.src_dir():
- module = find_module(config.src_dir(),dev_dir, mod)
- if not module:
- panic('module not found:', mod)
- (rc, out) = run('/sbin/insmod', module)
- if rc:
- raise CommandError('insmod', out, rc)
- else:
- (rc, out) = run('/sbin/modprobe', mod)
- if rc:
- raise CommandError('modprobe', out, rc)
-
- def cleanup_module(self):
- """Unload the modules in the list in reverse order."""
- rev = self.kmodule_list
- rev.reverse()
- for dev_dir, mod in rev:
- if not self.mod_loaded(mod):
- continue
- # debug hack
- if mod == 'portals' and config.dump_file():
- lctl.dump(config.dump_file())
- log('unloading module:', mod)
- if config.noexec():
- continue
- (rc, out) = run('/sbin/rmmod', mod)
- if rc:
- log('! unable to unload module:', mod)
- logall(out)
-
-
-class Network(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'NETWORK', dom_node)
- self.net_type = get_attr(dom_node,'type')
- self.nid = get_text(dom_node, 'server', '*')
- self.port = get_text_int(dom_node, 'port', 0)
- self.send_mem = get_text_int(dom_node, 'send_mem', DEFAULT_TCPBUF)
- self.recv_mem = get_text_int(dom_node, 'recv_mem', DEFAULT_TCPBUF)
- if '*' in self.nid:
- self.nid = get_local_address(self.net_type, self.nid)
- if not self.nid:
- panic("unable to set nid for", self.net_type, self.nid)
- debug("nid:", self.nid)
-
- if config.ldapadd():
- return
-
- self.add_module('portals/linux/oslib/', 'portals')
- if node_needs_router():
- self.add_module('portals/linux/router', 'kptlrouter')
- if self.net_type == 'tcp':
- self.add_module('portals/linux/socknal', 'ksocknal')
- if self.net_type == 'toe':
- self.add_module('portals/linux/toenal', 'ktoenal')
- if self.net_type == 'elan':
- self.add_module('portals/linux/rqswnal', 'kqswnal')
- if self.net_type == 'gm':
- self.add_module('portals/linux/gmnal', 'kgmnal')
- self.add_module('lustre/obdclass', 'obdclass')
- self.add_module('lustre/ptlrpc', 'ptlrpc')
-
- def prepare(self):
- global lctl
- self.info(self.net_type, self.nid, self.port)
- if self.net_type in ('tcp', 'toe'):
- nal_id = '' # default is socknal
- if self.net_type == 'toe':
- nal_id = '-N 4'
- ret, out = run(TCP_ACCEPTOR, '-s', self.send_mem, '-r', self.recv_mem, nal_id, self.port)
- if ret:
- raise CommandError(TCP_ACCEPTOR, out, ret)
- ret = self.dom_node.getElementsByTagName('route_tbl')
- for a in ret:
- for r in a.getElementsByTagName('route'):
- net_type = get_attr(r, 'type')
- gw = get_attr(r, 'gw')
- lo = get_attr(r, 'lo')
- hi = get_attr(r,'hi', '')
- lctl.add_route(net_type, gw, lo, hi)
- if net_type in ('tcp', 'toe') and net_type == self.net_type and hi == '':
- srv = nid2server(self.dom_node.parentNode.parentNode, lo)
- if not srv:
- panic("no server for nid", lo)
- else:
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
-
- lctl.network(self.net_type, self.nid)
- lctl.newdev(attach = "ptlrpc RPCDEV RPCDEV_UUID")
-
- def cleanup(self):
- self.info(self.net_type, self.nid, self.port)
- ret = self.dom_node.getElementsByTagName('route_tbl')
- for a in ret:
- for r in a.getElementsByTagName('route'):
- lo = get_attr(r, 'lo')
- hi = get_attr(r,'hi', '')
- if self.net_type in ('tcp', 'toe') and hi == '':
- srv = nid2server(self.dom_node.parentNode.parentNode, lo)
- if not srv:
- panic("no server for nid", lo)
- else:
- try:
- lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
- except CommandError, e:
- print "disconnect failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- try:
- lctl.del_route(self.net_type, self.nid, lo, hi)
- except CommandError, e:
- print "del_route failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
-
- try:
- lctl.cleanup("RPCDEV", "RPCDEV_UUID")
- except CommandError, e:
- print "cleanup failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- try:
- lctl.disconnectAll(self.net_type)
- except CommandError, e:
- print "disconnectAll failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- if self.net_type in ('tcp', 'toe'):
- # yikes, this ugly! need to save pid in /var/something
- run("killall acceptor")
-
-class LDLM(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LDLM', dom_node)
- if config.ldapadd():
- return
- self.add_module('lustre/ldlm', 'ldlm')
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info()
- lctl.newdev(attach="ldlm %s %s" % (self.name, self.uuid),
- setup ="")
-
-class LOV(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LOV', dom_node)
- self.mds_uuid = get_first_ref(dom_node, 'mds')
- mds= lookup(dom_node.parentNode, self.mds_uuid)
- self.mds_name = getName(mds)
- devs = dom_node.getElementsByTagName('devices')
- if len(devs) > 0:
- dev_node = devs[0]
- self.stripe_sz = get_attr_int(dev_node, 'stripesize', 65536)
- self.stripe_off = get_attr_int(dev_node, 'stripeoffset', 0)
- self.pattern = get_attr_int(dev_node, 'pattern', 0)
- self.devlist = get_all_refs(dev_node, 'osc')
- self.stripe_cnt = get_attr_int(dev_node, 'stripecount', len(self.devlist))
- if config.ldapadd():
- return
- self.add_module('lustre/mdc', 'mdc')
- self.add_module('lustre/lov', 'lov')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.prepare()
- else:
- panic('osc not found:', osc_uuid)
- mdc_uuid = prepare_mdc(self.dom_node.parentNode, self.mds_uuid)
- self.info(self.mds_uuid, self.stripe_cnt, self.stripe_sz,
- self.stripe_off, self.pattern, self.devlist, self.mds_name)
- lctl.newdev(attach="lov %s %s" % (self.name, self.uuid),
- setup ="%s" % (mdc_uuid))
-
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.cleanup()
- else:
- panic('osc not found:', osc_uuid)
- Module.cleanup(self)
- cleanup_mdc(self.dom_node.parentNode, self.mds_uuid)
-
-
- def load_module(self):
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.load_module()
- break
- else:
- panic('osc not found:', osc_uuid)
- Module.load_module(self)
-
-
- def cleanup_module(self):
- Module.cleanup_module(self)
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.cleanup_module()
- break
- else:
- panic('osc not found:', osc_uuid)
-
-class LOVConfig(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LOVConfig', dom_node)
- self.lov_uuid = get_first_ref(dom_node, 'lov')
- l = lookup(dom_node.parentNode, self.lov_uuid)
- self.lov = LOV(l)
-
- def prepare(self):
- lov = self.lov
- self.info(lov.mds_uuid, lov.stripe_cnt, lov.stripe_sz, lov.stripe_off,
- lov.pattern, lov.devlist, lov.mds_name)
- lctl.lov_setconfig(lov.uuid, lov.mds_name, lov.stripe_cnt,
- lov.stripe_sz, lov.stripe_off, lov.pattern,
- string.join(lov.devlist))
-
- def cleanup(self):
- #nothing to do here
- pass
-
-
-class MDS(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'MDS', dom_node)
- self.devname, self.size = get_device(dom_node)
- self.fstype = get_text(dom_node, 'fstype')
- # FIXME: if fstype not set, then determine based on kernel version
- self.format = get_text(dom_node, 'autoformat', "no")
- if config.ldapadd():
- return
- if self.fstype == 'extN':
- self.add_module('lustre/extN', 'extN')
- self.add_module('lustre/mds', 'mds')
- self.add_module('lustre/mds', 'mds_%s' % (self.fstype))
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.devname, self.fstype, self.format)
- blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
- if not is_prepared('MDT_UUID'):
- lctl.newdev(attach="mdt %s %s" % ('MDT', 'MDT_UUID'),
- setup ="")
- lctl.newdev(attach="mds %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(blkdev, self.fstype))
- def cleanup(self):
- if is_prepared('MDT_UUID'):
- try:
- lctl.cleanup("MDT", "MDT_UUID")
- except CommandError, e:
- print "cleanup failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- if not is_prepared(self.uuid):
- return
- Module.cleanup(self)
- clean_loop(self.devname)
-
-# Very unusual case, as there is no MDC element in the XML anymore
-# Builds itself from an MDS node
-class MDC(Module):
- def __init__(self,dom_node):
- self.mds = MDS(dom_node)
- self.dom_node = dom_node
- self.module_name = 'MDC'
- self.kmodule_list = []
- self._server = None
- self._connected = 0
-
- host = socket.gethostname()
- self.name = 'MDC_%s' % (self.mds.name)
- self.uuid = '%s_%05x_%05x' % (self.name, int(random.random() * 1048576),
- int(random.random() * 1048576))
-
- self.lookup_server(self.mds.uuid)
- if config.ldapadd():
- return
- self.add_module('lustre/mdc', 'mdc')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.mds.uuid)
- srv = self.get_server()
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
- lctl.newdev(attach="mdc %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(self.mds.uuid, srv.uuid))
-
-class OBD(Module):
- def __init__(self, dom_node):
- Module.__init__(self, 'OBD', dom_node)
- self.obdtype = get_attr(dom_node, 'type')
- self.devname, self.size = get_device(dom_node)
- self.fstype = get_text(dom_node, 'fstype')
- # FIXME: if fstype not set, then determine based on kernel version
- self.format = get_text(dom_node, 'autoformat', 'yes')
- if config.ldapadd():
- return
- if self.fstype == 'extN':
- self.add_module('lustre/extN', 'extN')
- self.add_module('lustre/' + self.obdtype, self.obdtype)
-
- # need to check /proc/mounts and /etc/mtab before
- # formatting anything.
- # FIXME: check if device is already formatted.
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.obdtype, self.devname, self.size, self.fstype, self.format)
- if self.obdtype == 'obdecho':
- blkdev = ''
- else:
- blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
- lctl.newdev(attach="%s %s %s" % (self.obdtype, self.name, self.uuid),
- setup ="%s %s" %(blkdev, self.fstype))
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- Module.cleanup(self)
- if not self.obdtype == 'obdecho':
- clean_loop(self.devname)
-
-class OST(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'OST', dom_node)
- self.obd_uuid = get_first_ref(dom_node, 'obd')
- if config.ldapadd():
- return
- self.add_module('lustre/ost', 'ost')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.obd_uuid)
- lctl.newdev(attach="ost %s %s" % (self.name, self.uuid),
- setup ="%s" % (self.obd_uuid))
-
-
-# virtual interface for OSC and LOV
-class VOSC(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'VOSC', dom_node)
- if dom_node.nodeName == 'lov':
- self.osc = LOV(dom_node)
- else:
- self.osc = OSC(dom_node)
- def prepare(self):
- self.osc.prepare()
- def cleanup(self):
- self.osc.cleanup()
- def load_module(self):
- self.osc.load_module()
- def cleanup_module(self):
- self.osc.cleanup_module()
-
-
-class OSC(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'OSC', dom_node)
- self.obd_uuid = get_first_ref(dom_node, 'obd')
- self.ost_uuid = get_first_ref(dom_node, 'ost')
- self.lookup_server(self.ost_uuid)
- if config.ldapadd():
- return
- self.add_module('lustre/osc', 'osc')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.obd_uuid, self.ost_uuid)
- srv = self.get_server()
- if local_net(srv):
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
- else:
- r = find_route(srv)
- if r:
- lctl.add_route_host(r[0], srv.uuid, r[1], r[2])
- else:
- panic ("no route to", srv.nid)
-
- lctl.newdev(attach="osc %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(self.obd_uuid, srv.uuid))
-
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- srv = self.get_server()
- if local_net(srv):
- Module.cleanup(self)
- else:
- self.info(self.obd_uuid, self.ost_uuid)
- r = find_route(srv)
- if r:
- try:
- lctl.del_route_host(r[0], srv.uuid, r[1], r[2])
- except CommandError, e:
- print "del_route failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- Module.cleanup(self)
-
-
-class ECHO_CLIENT(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'ECHO_CLIENT', dom_node)
- self.obd_uuid = get_first_ref(dom_node, 'osc')
- debug("HERE",self.obd_uuid)
- self.add_module('lustre/obdecho', 'obdecho')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.obd_uuid)
-
- lctl.newdev(attach="echo_client %s %s" % (self.name, self.uuid),
- setup = self.obd_uuid)
-
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- Module.cleanup(self)
-
-
-class Mountpoint(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'MTPT', dom_node)
- self.path = get_text(dom_node, 'path')
- self.mds_uuid = get_first_ref(dom_node, 'mds')
- self.lov_uuid = get_first_ref(dom_node, 'osc')
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- self.osc = VOSC(l)
- if config.ldapadd():
- return
- self.add_module('lustre/mdc', 'mdc')
- self.add_module('lustre/llite', 'llite')
-
- def prepare(self):
- self.osc.prepare()
- mdc_uuid = prepare_mdc(self.dom_node.parentNode, self.mds_uuid)
- self.info(self.path, self.mds_uuid, self.lov_uuid)
- cmd = "mount -t lustre_lite -o osc=%s,mdc=%s none %s" % \
- (self.lov_uuid, mdc_uuid, self.path)
- run("mkdir", self.path)
- ret, val = run(cmd)
- if ret:
- panic("mount failed:", self.path)
-
- def cleanup(self):
- self.info(self.path, self.mds_uuid,self.lov_uuid)
- if config.force():
- (rc, out) = run("umount -f", self.path)
- else:
- (rc, out) = run("umount", self.path)
- if rc:
- log("umount failed, cleanup will most likely not work.")
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- self.osc.cleanup()
- cleanup_mdc(self.dom_node.parentNode, self.mds_uuid)
-
- def load_module(self):
- self.osc.load_module()
- Module.load_module(self)
- def cleanup_module(self):
- Module.cleanup_module(self)
- self.osc.cleanup_module()
-
-
-# ============================================================
-# XML processing and query
-# TODO: Change query funcs to use XPath, which is muc cleaner
-
-def get_device(obd):
- list = obd.getElementsByTagName('device')
- if len(list) > 0:
- dev = list[0]
- dev.normalize();
- size = get_attr_int(dev, 'size', 0)
- return dev.firstChild.data, size
- return '', 0
-
-# Get the text content from the first matching child
-# If there is no content (or it is all whitespace), return
-# the default
-def get_text(dom_node, tag, default=""):
- list = dom_node.getElementsByTagName(tag)
- if len(list) > 0:
- dom_node = list[0]
- dom_node.normalize()
- if dom_node.firstChild:
- txt = string.strip(dom_node.firstChild.data)
- if txt:
- return txt
- return default
-
-def get_text_int(dom_node, tag, default=0):
- list = dom_node.getElementsByTagName(tag)
- n = default
- if len(list) > 0:
- dom_node = list[0]
- dom_node.normalize()
- if dom_node.firstChild:
- txt = string.strip(dom_node.firstChild.data)
- if txt:
- try:
- n = int(txt)
- except ValueError:
- panic("text value is not integer:", txt)
- return n
-
-def get_attr(dom_node, attr, default=""):
- v = dom_node.getAttribute(attr)
- if v:
- return v
- return default
-
-def get_attr_int(dom_node, attr, default=0):
- n = default
- v = dom_node.getAttribute(attr)
- if v:
- try:
- n = int(v)
- except ValueError:
- panic("attr value is not integer", v)
- return n
-
-def get_first_ref(dom_node, tag):
- """ Get the first uuidref of the type TAG. Used one only
- one is expected. Returns the uuid."""
- uuid = None
- refname = '%s_ref' % tag
- list = dom_node.getElementsByTagName(refname)
- if len(list) > 0:
- uuid = getRef(list[0])
- return uuid
-
-def get_all_refs(dom_node, tag):
- """ Get all the refs of type TAG. Returns list of uuids. """
- uuids = []
- refname = '%s_ref' % tag
- list = dom_node.getElementsByTagName(refname)
- if len(list) > 0:
- for i in list:
- uuids.append(getRef(i))
- return uuids
-
-def get_ost_net(dom_node, uuid):
- ost = lookup(dom_node, uuid)
- uuid = get_first_ref(ost, 'network')
- if not uuid:
- return None
- return lookup(dom_node, uuid)
-
-def nid2server(dom_node, nid):
- netlist = dom_node.getElementsByTagName('network')
- for net_node in netlist:
- if get_text(net_node, 'server') == nid:
- return Network(net_node)
- return None
-
-def lookup(dom_node, uuid):
- for n in dom_node.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- if getUUID(n) == uuid:
- return n
- else:
- n = lookup(n, uuid)
- if n: return n
- return None
-
-# Get name attribute of dom_node
-def getName(dom_node):
- return dom_node.getAttribute('name')
-
-def getRef(dom_node):
- return dom_node.getAttribute('uuidref')
-
-# Get name attribute of dom_node
-def getUUID(dom_node):
- return dom_node.getAttribute('uuid')
-
-# the tag name is the service type
-# fixme: this should do some checks to make sure the dom_node is a service
-def getServiceType(dom_node):
- return dom_node.nodeName
-
-
-############################################################
-# routing ("rooting")
-#
-routes = []
-local_node = []
-router_flag = 0
-
-def init_node(dom_node):
- global local_node, router_flag
- netlist = dom_node.getElementsByTagName('network')
- for dom_net in netlist:
- type = get_attr(dom_net, 'type')
- gw = get_text(dom_net, 'server')
- local_node.append((type, gw))
-
-def node_needs_router():
- return router_flag
-
-def get_routes(type, gw, dom_net):
- """ Return the routes as a list of tuples of the form:
- [(type, gw, lo, hi),]"""
- res = []
- tbl = dom_net.getElementsByTagName('route_tbl')
- for t in tbl:
- routes = t.getElementsByTagName('route')
- for r in routes:
- lo = get_attr(r, 'lo')
- hi = get_attr(r, 'hi', '')
- res.append((type, gw, lo, hi))
- return res
-
-
-def init_route_config(lustre):
- """ Scan the lustre config looking for routers. Build list of
- routes. """
- global routes, router_flag
- routes = []
- list = lustre.getElementsByTagName('node')
- for node in list:
- if get_attr(node, 'router'):
- router_flag = 1
- for (local_type, local_nid) in local_node:
- gw = None
- netlist = node.getElementsByTagName('network')
- for dom_net in netlist:
- if local_type == get_attr(dom_net, 'type'):
- gw = get_text(dom_net, 'server')
- break
- if not gw:
- continue
- for dom_net in netlist:
- if local_type != get_attr(dom_net, 'type'):
- for route in get_routes(local_type, gw, dom_net):
- routes.append(route)
-
-
-def local_net(net):
- global local_node
- for iface in local_node:
- if net.net_type == iface[0]:
- return 1
- return 0
-
-def find_route(net):
- global local_node, routes
- frm_type = local_node[0][0]
- to_type = net.net_type
- to = net.nid
- debug ('looking for route to', to_type,to)
- for r in routes:
- if r[2] == to:
- return r
- return None
-
-
-
-
-##############################################################################
-# Here it starts LDAP related stuff.
-
-import ldap
-import _ldap
-
-#returns the lustre ldap specific filters
-
-class lustre_ldap:
- def __init__(self):
- self.filter=0
-
- def get_filter(self,lustreRdn):
- filter="(&"+lustreRdn+")"
- return filter
-
-# make a connection to LDAP server and abd bind
-class MyConn:
- def __init__(self,host,port):
- self.id=0
- self.host=host
- self.port=port
- self.base="fs=lustre"
-
- def open(self):
- self.id=ldap.open(self.host)
- if self.id == None:
- print "unable to open a connection"
-
- try:
- # lustre tree starts from here...the DN is (cn=Manager ,fs=lustre)
- status=self.id.simple_bind("cn=Manager, fs=lustre","secret")
- except _ldap.LDAPError:
- print "unable to bind"
-
-
-
-# Lustre Node object class definition as per defined in the lustre.schema
-
-class LustreNode:
- def __init__(self,nodename):
- self.objectClass="lustreNode"
- self.nodeUUID = 0
- self.id= nodename
- self.netUUIDs = []
- self.profileUUID = 0
- self.routerUUID = 0
- self.ldlmUUID = 0
-
- self.lustreNet = {}
- self.lustreNodeProfile = 0
- self.lustreLdlm = 0
-
- self.nodeUUID_str="nodeUUID"
- self.id_str="id"
- self.netUUIDs_str="netUUIDs"
- self.ldlmUUID_str="ldlmUUID"
- self.profileUUID_str="profileUUID"
- self.routerUUID_str="routerUUID"
- self.node_str="node"
-
- def get_object_class(self):
- return self.objectClass
-
- def get_rdn(self):
- retval="(objectClass="+self.objectClass+") (id="+self.id+")"
- return retval
-
- # Initilize lustre Node Object class after read drom LDAP server
- def init_node(self,node_entry):
- self.id=node_entry[0][1][self.id_str][0]
- self.nodeUUID=node_entry[0][1][self.nodeUUID_str][0]
- for i in range(len(node_entry[0][1][self.netUUIDs_str])):
- self.netUUIDs.append(node_entry[0][1][self.netUUIDs_str][i])
- if node_entry[0][1].has_key(self.profileUUID_str):
- self.profileUUID=node_entry[0][1][self.profileUUID_str][0]
- if node_entry[0][1].has_key(self.ldlmUUID_str):
- self.ldlmUUID=node_entry[0][1][self.ldlmUUID_str][0]
-
- if node_entry[0][1].has_key(self.routerUUID_str):
- self.routerUUID=node_entry[0][1][self.routerUUID_str][0]
-
- # Brings the lustre Node object entries from LDAP server
- def getEntry_from_ldap(self,conn_id,base):
- try:
- lustre_util=lustre_ldap()
- # the filter has id=<nodename>,type=node,fs=lustre
- # base is "fs=lustre"
- filter=lustre_util.get_filter(self.get_rdn())
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
- #network object class
- if self.netUUIDs:
- for i in range(len(self.netUUIDs)):
- # loading the network object class from LDAP, since this related to lustre node class
- self.lustreNet[i]=LustreNet()
- self.lustreNet[i].getEntry_from_ldap(conn_id,base,self.netUUIDs[i])
-
- # The ldlm object class
- if self.ldlmUUID:
- # loading the ldlm object class from LDAP, since this related to lustre node class
- self.lustreLdlm=LustreLdlm()
- self.lustreLdlm.getEntry_from_ldap(conn_id,base,self.ldlmUUID)
-
- # The lustre node profile object class
- if self.profileUUID:
- # loading the node profile object class from LDAP, since this related to lustre node class
- # The node profile contains the clientUUID, mdsUUIDs (multiple) and ostUUIDs(multiple)
- # the rest of the object class queried from LDAP server useing above UUIDs
- self.lustreNodeProfile=LustreNodeProfile()
- self.lustreNodeProfile.getEntry_from_ldap(conn_id,base,self.profileUUID)
-
- except ldap.NO_SUCH_OBJECT:
- print "no results Found"
- exit(1)
-
- def get_dn(self,id):
- return self.id_str+"="+id+",type="+self.node_str+",fs=lustre"
-
- # add entries into LDAP server, All of them are must fields
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.id)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.id_str,[self.id]))
- modlist.append((self.nodeUUID_str,[self.nodeUUID]))
- modlist.append((self.netUUIDs_str,self.netUUIDs))
- modlist.append((self.profileUUID_str,[self.profileUUID]))
- modlist.append((self.routerUUID_str,[self.routerUUID]))
- modlist.append((self.ldlmUUID_str,[self.ldlmUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- return status
-
- def initobj(self,*args):
- print "init obj :", args
- # print values of object class
- def print_node(self):
- print "lustre Node Attributes......"
- print "objectClass: %s" % self.objectClass
- print "node UUID: %s" % self.nodeUUID
- print "node name: %s" % self.id
- for i in range(len(self.netUUIDs)):
- print "network UUID%d: %s" % (i,self.netUUIDs[i])
- print "Node Profile UUID: %s" % self.profileUUID
- print "Router UUID: %s" % self.routerUUID
- print "Ldlm UUID: %s" % self.ldlmUUID
- print
- for i in range(len(self.netUUIDs)):
- self.lustreNet[i].print_net()
-
- self.lustreNodeProfile.print_profile()
- self.lustreLdlm.print_ldlm()
-
-
-
-# lustre Client object class It have mount uuid and net uuid, but the net uuid may not required at present.
-class LustreClient:
- def __init__(self,lustreNode):
- self.objectClass="lustreClient"
- self.clientUUID=0
- self.mountUUIDs=[]
- self.netUUID=0
-
- self.lustreNode=lustreNode
- self.lustreNet= 0
- self.lustreMount={}
-
-
- self.clientUUID_attr="clientUUID"
- self.mountUUID_attr="mountUUIDs"
- self.netUUID_attr="netUUID"
- self.client_attr="client"
-
- def ge_object_class(self):
- return self.objectClass
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (clientUUID="+attr_value+")"
- return retval
-
-
- # load the object class with client config params
- def init_node(self,node_entry):
- self.clientUUID=node_entry[0][1][self.clientUUID_attr][0]
- for i in range(len(node_entry[0][1][self.mountUUID_attr])):
- self.mountUUIDs.append(node_entry[0][1][self.mountUUID_attr][i])
- self.netUUID=node_entry[0][1][self.netUUID_attr][0]
-
-
- # brings the client config params from LDAP, here the search criteria is clientUUID=lustre1_client_UUID,type=client,fs=lustre, this is called as dn
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- # filter has "clientUUID=lustre1_client_UUID,type=client,fs=lustre"
- # the base is "fs=lustre"
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Client Error No Results found"
- sys.exit(1)
-
- self.init_node(result)
-
- if self.netUUID:
- self.lustreNet=LustreNet()
- self.lustreNet.getEntry_from_ldap(conn_id,base,self.netUUID)
- else:
- print "Unable to find the LDLM uuid in Client Object Class..."
-
- if self.mountUUIDs:
- for mntuuid in self.mountUUIDs:
- self.lustreMount[mntuuid]=LustreMount()
- self.lustreMount[mntuuid].getEntry_from_ldap(conn_id,base,mntuuid)
-
-
- def get_dn(self,uuid):
- retval=self.clientUUID_attr+"="+uuid+",type="+self.client_attr+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.clientUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.clientUUID_attr,[self.clientUUID]))
- modlist.append((self.mountUUID_attr,self.mountUUIDs))
- modlist.append((self.netUUID_attr,[self.netUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_client(self):
- print "Lustre Client Configurations..............."
- print "client Object Calss: %s" % self.objectClass
- print "client UUID: %s" % self.clientUUID
- print "This client supporting %d file systems" % len(self.mountUUIDs)
- if self.lustreNet:
- self.lustreNet.print_net()
-
- if self.mountUUIDs:
- for mntuuid in self.mountUUIDs:
- self.lustreMount[mntuuid].print_mount()
-
-
-
-
-class LustreMount:
- def __init__(self):
- self.objectClass="lustreMount"
- self.mountUUID=0
- self.mdsUUID=0
- self.lovUUID=0
- self.mountPath=""
- self.default=0
-
- self.lustreMds=0
- self.lustreLov=0
-
- self.mountUUID_attr="mountUUID"
- self.mdsUUID_attr="mdsUUID"
- self.lovUUID_attr="lovUUID"
- self.mountPath_attr="mountPath"
- self.default_attr="default"
- self.type="mountPoint"
-
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (mountUUID="+attr_value+")"
- return retval
-
-
- def init_node(self,record):
- self.mdsUUID=record[0][1][self.mdsUUID_attr][0]
- self.mountUUID=record[0][1][self.mountUUID_attr][0]
- self.lovUUID=record[0][1][self.lovUUID_attr][0]
- self.mountPath=record[0][1][self.mountPath_attr][0]
- self.default=record[0][1][self.default_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Mount Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.mdsUUID:
- self.lustreMds=LustreMds()
- self.lustreMds.getEntry_from_ldap(conn_id,base,self.mdsUUID)
-
- if self.lovUUID:
- self.lustreLov=LustreLov()
- self.lustreLov.getEntry_from_ldap(conn_id,base,self.lovUUID)
-
- def get_dn(self,uuid):
- retval=self.mountUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.mountUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.mountUUID_attr,[self.mountUUID]))
- modlist.append((self.mdcUUID_attr,self.mdcUUID))
- modlist.append((self.lovUUID_attr,[self.lovUUID]))
- modlist.append((self.mountPath_attr,[self.mountPath]))
- modlist.append((self.default_attr,[self.default]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_mount(self):
-
- print "Lustre mount point attributes......"
- print "mount object class: %s" % self.objectClass
- print "mount UUID: %s" % self.mountUUID
- print "mds UUID: %s" % self.mdsUUID
- print "lov UUID: %s" % self.lovUUID
- print "mount point: %s" % self.mountPath
- if self.default:
- print "This file system is default file system for this cleint"
- else:
- print "This file system is not a default file system for this cleint"
-
- if self.lustreMds:
- self.lustreMds.print_mds()
- if self.lustreLov:
- self.lustreLov.print_lov()
-
-
-class LustreOsc:
- def __init__(self):
- self.objectClass="lustreOSC"
- self.oscUUID=0
- self.devName=""
- self.obdUUID=0
- self.ostUUID=0
-
- self.lustreObd=0
- self.lustreOst=0
-
- self.oscUUID_attr="oscUUID"
- self.devName_attr="devName"
- self.obdUUID_attr="obdUUID"
- self.ostUUID_attr="ostUUID"
- self.type="OSC"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (oscUUID="+attr_value+")"
- return retval
-
-
- def init_node(self,record):
- self.oscUUID=record[0][1][self.oscUUID_attr][0]
- self.obdUUID=record[0][1][self.obdUUID_attr][0]
- self.ostUUID=record[0][1][self.ostUUID_attr][0]
- self.devName=record[0][1][self.devName_attr][0]
-
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.obdUUID:
- self.lustreObd=LustreObd()
- self.lustreObd.getEntry_from_ldap(conn_id,base,self.obdUUID)
-
- if self.ostUUID:
- self.lustreOst=LustreOst()
- self.lustreOst.getEntry_from_ldap(conn_id,base,self.ostUUID)
-
- def get_dn(self,uuid):
- retval=self.oscUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.oscUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.oscUUID_attr,[self.oscUUID]))
- modlist.append((self.devName_attr,self.devName))
- modlist.append((self.obdUUID_attr,[self.obdUUID]))
- modlist.append((self.ostUUID_attr,[self.ostUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_osc(self):
- print "Lustre Osc Attrributes.."
- print "object class: %s" % self.objectClass
- print "oscUUID: %s" % self.oscUUID
- print "devName: %s" % self.devName
- print "obdUUID: %s" % self.obdUUID
- print "ostUUID: %s" % self.ostUUID
- print
- if self.lustreObd:
- self.lustreObd.print_obd()
- print
- if self.lustreOst:
- self.lustreOst.print_ost()
- print
-
-
-class LustreMdc:
- def __init__(self):
- self.objectClass="lustreMDC"
- self.mdcUUID=0
- self.devName=""
- self.mdsUUID=0
-
- self.lustreMds=0
-
- self.mdcUUID_attr="mdcUUID"
- self.devName_attr="devName"
- self.mdsUUID_attr="mdsUUID"
- self.type="MDC"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (mdcUUID="+attr_value+")"
- return retval
-
-
- def init_node(self,record):
- self.mdcUUID=record[0][1][self.mdcUUID_attr][0]
- self.mdsUUID=record[0][1][self.mdsUUID_attr][0]
- self.devName=record[0][1][self.devName_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.mdsUUID:
- self.lustreMds=LustreMds()
- self.lustreMds.getEntry_from_ldap(conn_id,base,self.mdsUUID)
-
-
- def get_dn(self,uuid):
- retval=self.mdcUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.mdcUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.mdcUUID_attr,[self.mdcUUID]))
- modlist.append((self.devName_attr,self.devName))
- modlist.append((self.mdsUUID_attr,[self.mdsUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_mdc(self):
- print "Lustre Mdc attributes....."
- print "Mdc UUID: %s" % self.mdcUUID
- print "dev name: %s" % self.devName
- print "Mds UUId: %s" % self.mdsUUID
- print
- if self.lustreMds:
- self.lustreMds.print_mds()
-
-
-
-class LustreOst:
- def __init__(self):
- self.objectClass="lustreOST"
- self.ostUUID=0
- self.devName=""
- self.obdUUID=0
-
- self.lustreObd=0
-
- self.ostUUID_attr="ostUUID"
- self.devName_attr="devName"
- self.obdUUID_attr="obdUUID"
- self.type="OST"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (ostUUID="+attr_value+")"
- return retval
-
- def init_node(self,record):
- self.ostUUID=record[0][1][self.ostUUID_attr][0]
- self.obdUUID=record[0][1][self.obdUUID_attr][0]
- self.devName=record[0][1][self.devName_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.obdUUID:
- self.lustreObd=LustreObd()
- self.lustreObd.getEntry_from_ldap(conn_id,base,self.obdUUID)
-
-
- def get_dn(self,uuid):
- retval=self.ostUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.ostUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.ostUUID_attr,[self.ostUUID]))
- modlist.append((self.devName_attr,[self.devName]))
- modlist.append((self.obdUUID_attr,[self.obdUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_ost(self):
- print "Lustre Ost Attributes...."
- print "object class: %s" % self.objectClass
- print "ostUUID: %s" % self.ostUUID
- print "devName: %s" % self.devName
- print "obdUUID: %s" % self.obdUUID
- print
- if self.lustreObd:
- self.lustreObd.print_obd()
-
-
-
-class LustreMds:
- def __init__(self):
- self.objectClass="lustreMDS"
- self.mdsUUID=0
- self.devName=""
- self.devUUID=0
- self.lovUUID=0
- self.fUUID=0
-
- self.lustreDev=0
- self.lustreLov=0
-
- self.mdsUUID_attr="mdsUUID"
- self.devName_attr="devName"
- self.devUUID_attr="devUUID"
- self.lovUUID_attr="lovUUID"
- self.fUUID_attr="fUUID"
- self.type="MDS"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (mdsUUID="+attr_value+")"
- return retval
-
-
- def init_node(self,record):
- self.mdsUUID=record[0][1][self.mdsUUID_attr][0]
- self.devUUID=record[0][1][self.devUUID_attr][0]
- self.lovUUID=record[0][1][self.lovUUID_attr][0]
- #self.fUUID=record[0][1][self.fUUID_attr][0]
- self.devName=record[0][1][self.devName_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
-
- if self.devUUID:
- self.lustreDev=LustreDevice()
- self.lustreDev.getEntry_from_ldap(conn_id,base,self.devUUID)
-
- if self.lovUUID:
- self.lustreLov=LustreLov()
- self.lustreLov.getEntry_from_ldap(conn_id,base,self.lovUUID)
-
-
- def get_dn(self,uuid):
- retval=self.mdsUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.mdsUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.mdsUUID_attr,[self.mdsUUID]))
- modlist.append((self.devName_attr,[self.devName]))
- modlist.append((self.devUUID_attr,[self.devUUID]))
- modlist.append((self.lovUUID_attr,[self.lovUUID]))
- modlist.append((self.fUUID_attr,[self.fUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_mds(self):
- print "Lustre Mds Attributes..."
- print "object Class: %s" % self.objectClass
- print "mdsUUID: %s" % self.mdsUUID
- print "devName: %s" % self.devName
- print "devUUID: %s" % self.devUUID
- #print "fUUID: %s" % self.fUUID
- print "lovUUID: %s" % self.lovUUID
- print
- if self.lustreLov:
- self.lustreLov.print_lov()
- print
-
-
-class LustreLov:
- def __init__(self):
- self.objectClass="lustreLOV"
- self.lovUUID=0
- self.devName = ""
- self.oscUUIDs= []
- self.stripeOffset=0
- self.stripeSize=0
- self.stripeCount=0
- self.pattern=0
-
- self.lustreOsc = {}
-
- self.lovUUID_attr="lovUUID"
- self.devName_attr="devName"
- self.oscUUID_attr="oscUUIDs"
- self.stripeOffset_attr="stripeOffset"
- self.stripeSize_attr="stripeSize"
- self.stripeCount_attr="stripeCount"
- self.pattern_attr="pattern"
- self.type="LOV"
-
- def get_object_class(self):
- return self.objectCalss
-
-
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (lovUUID="+attr_value+")"
- return retval
-
-
- def init_node(self,record):
- nofvals=len(record[0][1][self.oscUUID_attr])
- for i in range(nofvals):
- self.oscUUIDs.append(record[0][1][self.oscUUID_attr][i])
-
- self.stripeOffset=record[0][1][self.stripeOffset_attr][0]
- self.lovUUID=record[0][1][self.lovUUID_attr][0]
- self.devName = record[0][1][self.devName_attr][0]
- self.stripeSize=record[0][1][self.stripeSize_attr][0]
- self.stripeCount=record[0][1][self.stripeCount_attr][0]
- self.pattern=record[0][1][self.pattern_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
-
- if self.oscUUIDs:
- for uuid in self.oscUUIDs:
- self.lustreOsc[uuid]=LustreOsc()
- self.lustreOsc[uuid].getEntry_from_ldap(conn_id,base,uuid)
-
- def get_dn(self,uuid):
- retval=self.lovUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.lovUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.lovUUID_attr,[self.lovUUID]))
- modlist.append((self.devName_attr,[self.devName]))
- modlist.append((self.oscUUID_attr,self.oscUUIDs))
- modlist.append((self.stripeOffset_attr,[self.stripeOffset]))
- modlist.append((self.stripeSize_attr,[self.stripeSize]))
- modlist.append((self.stripeCount_attr,[self.stripeCount]))
- modlist.append((self.pattern_attr,[self.pattern]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_lov(self):
- print "Lustre LOV attributes..."
- print "object class: %s" % self.objectClass
- print "lovUUID: %s" % self.lovUUID
- print "devName: %s" % self.devName
- print "oscUUIDs are"
- for i in range(len(self.oscUUIDs)):
- print "oscUUID[%d]: %s" % (i,self.oscUUIDs[i])
- print "stripeOffset: %s" % self.stripeOffset
- print "stripe Size: %s" % self.stripeSize
- print "stripe Count: %s" % self.stripeCount
- print "pattern: %s" % self.pattern
-
- print
- if self.oscUUIDs:
- for uuid in self.oscUUIDs:
- if self.lustreOsc:
- self.lustreOsc[uuid].print_osc()
- print
-
-
-class LustreDevice:
- def __init__(self):
- self.objectClass="lustreDevice"
- self.id=""
- self.fid=""
- self.devUUID=0
- self.netUUID=0
- self.fnetUUID=0
- self.device=""
- self.auto=0
- self.fsType=""
- self.size=0
-
- self.id_attr="id"
- self.fid_attr="fid"
- self.devUUID_attr="devUUID"
- self.netUUID_attr="netUUID"
- self.fnetUUID_attr="fnetUUID"
- self.device_attr="device"
- self.auto_attr="auto"
- self.fsType_attr="fsType"
- self.size_attr="size"
- self.type="device"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (devUUID="+attr_value+")"
- return retval
-
- def init_node(self,record):
- self.devUUID=record[0][1][self.devUUID_attr][0]
- self.netUUID=record[0][1][self.netUUID_attr][0]
- self.fnetUUID=record[0][1][self.fnetUUID_attr][0]
- self.id=record[0][1][self.id_attr][0]
- self.fid=record[0][1][self.fid_attr][0]
- self.device=record[0][1][self.device_attr][0]
- self.auto=record[0][1][self.auto_attr][0]
- self.fsType=record[0][1][self.fsType_attr][0]
- self.size=record[0][1][self.size_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- def get_dn(self,uuid):
- retval=self.devUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.devUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.devUUID_attr,[self.devUUID]))
- modlist.append((self.netUUID_attr,[self.netUUID]))
- modlist.append((self.fnetUUID_attr,[self.fnetUUID]))
- modlist.append((self.id_attr,[self.id]))
- modlist.append((self.fid_attr,[self.fid]))
- modlist.append((self.device_attr,self.device))
- modlist.append((self.auto_attr,[self.auto]))
- modlist.append((self.fsType_attr,[self.fsType]))
- modlist.append((self.size_attr,[self.size]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_device(self):
- print "lustre Device object...."
- print "object Calss: %s" % self.objectClass
- print "node name: %s" % self.id
- print "failover node name: %s" % self.fid
- print "devUUID: %s" % self.devUUID
- print "netUUID: %s" % self.netUUID
- print "failover netUUID: %s" % self.fnetUUID
- print "device: %s" % self.device
- print "autoformat: %s" % self.auto
- print "fs type: %s" % self.fsType
- print "size of device: %s" % self.size
-
-
-
-class LustreObd:
- def __init__(self):
- self.objectClass="lustreOBD"
- self.obdUUID=0
- self.devName=""
- self.devUUID=0
- self.fUUID=0
-
- self.lustreDev = 0
-
- self.obdUUID_attr="obdUUID"
- self.devName_attr="devName"
- self.devUUID_attr="devUUID"
- self.fUUID_attr="fUUID"
- self.type="OBD"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (obdUUID="+attr_value+")"
- return retval
-
- def init_node(self,record):
- self.obdUUID=record[0][1][self.obdUUID_attr][0]
- self.devName=record[0][1][self.devName_attr][0]
- self.devUUID=record[0][1][self.devUUID_attr][0]
- self.fUUID=record[0][1][self.fUUID_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- if self.devUUID:
- self.lustreDev=LustreDevice()
- self.lustreDev.getEntry_from_ldap(conn_id,base,self.devUUID)
-
-
- def get_dn(self,uuid):
- retval=self.obdUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.obdUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.obdUUID_attr,[self.obdUUID]))
- modlist.append((self.devName_attr,[self.devName]))
- modlist.append((self.devUUID_attr,[self.devUUID]))
- modlist.append((self.fUUID_attr,[self.fUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_obd(self):
- print "Lustre Obd attributes...."
- print "object Class: %s" % self.objectClass
- print "obdUUID: %s" % self.obdUUID
- print "devName: %s" % self.devName
- print "devUUID: %s" % self.devUUID
- print "fUUID: %s" % self.fUUID
- print
- if self.lustreDev:
- self.lustreDev.print_device()
- print
-
-
-class LustreLdlm:
- def __init__(self):
- self.objectClass="lustreLDLM"
- self.ldlmUUID=0
- self.devName=""
-
- self.ldlmUUID_attr="ldlmUUID"
- self.devName_attr="devName"
- self.type="LDLM"
-
- def get_object_class(self):
- return self.objectCalss
-
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (ldlmUUID="+attr_value+")"
- return retval
-
- def init_node(self,record):
- self.ldlmUUID=record[0][1][self.ldlmUUID_attr][0]
- self.devName=record[0][1][self.devName_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
-
- def get_dn(self,uuid):
- retval=self.ldlmUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id):
- modlist=[]
- dn=self.get_dn(self.ldlmUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.ldlmUUID_attr,[self.ldlmUUID]))
- modlist.append((self.devName_attr,[self.devName]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_ldlm(self):
- print "Printing LDLM attributes..........."
- print "ldlm Object Class: %s" % self.objectClass
- print "ldlm UUID: %s" % self.ldlmUUID
- print "ldlm Name: %s" % self.devName
- print "\n" * 5
-
-
-class LustreNet:
- def __init__(self):
- self.objectClass="lustreNetwork"
- self.netUUID=0
- self.id=0
- self.fnetUUID=0
- self.netType=""
- self.netAddress=""
- self.port=0
- self.recvMem=0
- self.sendMem=0
-
- self.netUUID_attr="netUUID"
- self.fnetUUID_attr="fnetUUID"
- self.id_attr="id"
- self.netType_attr="netType"
- self.netAddress_attr="netAddress"
- self.port_attr="port"
- self.recvMem_attr="recvMem"
- self.sendMem_attr="sendMem"
- self.type="net"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (netUUID="+attr_value+")"
- return retval
-
- def init_node(self,record):
- self.netUUID=record[0][1][self.netUUID_attr][0]
- self.fnetUUID=record[0][1][self.fnetUUID_attr][0]
- self.id=record[0][1][self.id_attr][0]
- self.netType=record[0][1][self.netType_attr][0]
- self.netAddress=record[0][1][self.netAddress_attr][0]
- self.port=record[0][1][self.port_attr][0]
- self.recvMem=record[0][1][self.recvMem_attr][0]
- self.sendMem=record[0][1][self.sendMem_attr][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
-
- def get_dn(self,uuid):
- retval=self.netUUID_attr+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id,id,fnetUUID,netUUID,netType,netAddress,port,recvMem,sendMem):
- modlist=[]
- dn=self.get_dn(netUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.netUUID_attr,[netUUID]))
- modlist.append((self.fnetUUID_attr,[fnetUUID]))
- modlist.append((self.id_attr,[id]))
- modlist.append((self.netType_attr,[netType]))
- modlist.append((self.netAddress_attr,[netAddress]))
- modlist.append((self.port_attr,[port]))
- modlist.append((self.recvMem_attr,[recvMem]))
- modlist.append((self.sendMem_attr,[sendMem]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_net(self):
- print "Lustre Network Attributes:......"
- print "object Class: %s" % self.objectClass
- print "network UUID: %s" % self.netUUID
- print "failover network UUID: %s" % self.fnetUUID
- print "node name : %s" % self.id
- print "network Type: %s" % self.netType
- print "IP Address: %s" % self.netAddress
- print "port: %s" % self.port
- print "receive memory: %s" % self.recvMem
- print "send memory: %s" % self.sendMem
- print
-
-
-class LustreNodeProfile:
- def __init__(self):
- self.objectClass="lustreNodeProfile"
- self.profileUUID=0
- self.mdsUUIDs=[]
- self.ostUUIDs=[]
- self.clientUUID=0
-
- self.profileUUID_str="profileUUID"
- self.mdsUUIDs_str="mdsUUIDs"
- self.ostUUIDs_str="ostUUIDs"
- self.clientUUID_str="clientUUID"
- self.type="profile"
-
- def get_object_class(self):
- return self.objectCalss
-
- def get_rdn(self,attr_value):
- retval="(objectClass="+self.objectClass+") (profileUUID="+attr_value+")"
- return retval
-
- def init_node(self,node_entry):
- self.profileUUID=node_entry[0][1][self.profileUUID_str][0]
- if node_entry[0][1].has_key(self.mdsUUIDs_str):
- for i in range(len(node_entry[0][1][self.mdsUUIDs_str])):
- self.mdsUUIDs.append(node_entry[0][1][self.mdsUUIDs_str][i])
-
- if node_entry[0][1].has_key(self.ostUUIDs_str):
- for i in range(len(node_entry[0][1][self.ostUUIDs_str])):
- self.ostUUIDs.append(node_entry[0][1][self.ostUUIDs_str][i])
-
- if node_entry[0][1].has_key(self.clientUUID_str):
- self.clientUUID=node_entry[0][1][self.clientUUID_str][0]
-
- def getEntry_from_ldap(self,conn_id,base,attr_val):
- lustre_util=lustre_ldap()
- filter=lustre_util.get_filter(self.get_rdn(attr_val))
- result=conn_id.search_s(base,ldap.SCOPE_SUBTREE,filter)
- if result == []:
- print "Error No Results found"
- sys.exit(1)
- self.init_node(result)
-
- def get_dn(self,uuid):
- retval=self.profileUUID_str+"="+uuid+",type="+self.type+",fs=lustre"
- return retval
-
- def addEntry_into_ldap(self,conn_id,profileUUID,mdsUUIDs,ostUUIDs,clientUUID):
- modlist=[]
- dn=self.get_dn(profileUUID)
- modlist.append(("objectClass",[self.objectClass]))
- modlist.append((self.profileUUID_str,[profileUUID]))
- modlist.append((self.mdsUUIDs_str,mdsUUIDs))
- modlist.append((self.ostUUIDs_str,ostUUIDs))
- modlist.append((self.clientUUID_str,[clientUUID]))
- modlist.append(("fs",["lustre"]))
- status=0
- try:
- conn_id.add_s(dn,modlist)
- except _ldap.LDAPError:
- print "not added"
- sys.exit(1)
- return status
-
- def initobj(self,*args):
- print "init obj :", args
-
- def print_profile(self):
- print "Lustre Node Profile Attributes:......"
- print "object Class: %s" % self.objectClass
- print "profile UUID: %s" % self.profileUUID
- print "This node supports %d mds servers:" % len(self.mdsUUIDs)
- for i in range(len(self.mdsUUIDs)):
- print "Mds UUID%d: %s" % (i,self.mdsUUIDs[i])
- print "This node supports %d ost servers:" % len(self.ostUUIDs)
- for i in range(len(self.ostUUIDs)):
- print "Ost UUID%d: %s" % (i,self.ostUUIDs[i])
- print "Client UUID: %s" % self.clientUUID
- print
-
-
-def get_matched_osc(ConnId,ostuuid):
- result = ConnId.search_s("fs=lustre",ldap.SCOPE_SUBTREE,"objectclass=lustreOSC")
- lustreOSC = 0
- if result:
- for i in range(len(result)):
- tmpuuid = result[i][1]['ostUUID'][0]
- if ostuuid == tmpuuid:
- lustreOSC = LustreOsc()
- lustreOSC.init_node([result[i]])
- break
-
- else:
- print "no result"
-
- return lustreOSC
-
-
-def get_matched_lov(ConnId,oscuuid):
- print "inside.. get matched lov:", oscuuid
- result = ConnId.search_s("fs=lustre",ldap.SCOPE_SUBTREE,"objectclass=lustreLOV")
- lustreLOV = 0
- tmpuuids = []
- if result:
- for i in range(len(result)):
- tmpuuids = result[i][1]['oscUUIDs']
- for uuid in tmpuuids:
- if oscuuid == uuid:
- lustreLOV = LustreLov()
- lustreLOV.init_node([result[i]])
- return lustreLOV
- return 0
-
-
-
-