===================================================================
--- linux-2.6.5-sles9.orig/fs/ext3/extents.c 2005-02-17 22:07:57.023609040 +0300
+++ linux-2.6.5-sles9/fs/ext3/extents.c 2005-02-23 01:02:37.396435640 +0300
-@@ -0,0 +1,2356 @@
+@@ -0,0 +1,2349 @@
+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+{
+ if (eh->eh_magic != EXT3_EXT_MAGIC) {
+ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
-+ (unsigned) eh->eh_magic);
++ (unsigned)eh->eh_magic);
+ return -EIO;
+ }
+ if (eh->eh_max == 0) {
+ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
-+ (unsigned) eh->eh_max);
++ (unsigned)eh->eh_max);
+ return -EIO;
+ }
+ if (eh->eh_entries > eh->eh_max) {
+ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
-+ (unsigned) eh->eh_entries);
++ (unsigned)eh->eh_entries);
+ return -EIO;
+ }
+ return 0;
+ * - ENOMEM
+ */
+static int ext3_ext_get_access(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path)
+{
+ int err;
+
+ * - EIO
+ */
+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int err;
+ if (path->p_bh) {
+
+static int inline
+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, struct ext3_extent *ex,
-+ int *err)
++ struct ext3_ext_path *path, struct ext3_extent *ex,
++ int *err)
+{
+ int goal, depth, newblock;
+ struct inode *inode;
+ unsigned long colour;
+
+ bg_start = (ei->i_block_group *
-+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
+ colour = (current->pid % 16) *
+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 6;
+#endif
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 5;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len - sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 3;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 4;
+#endif
+}
+
+static void ext3_ext_show_path(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int k, l = path->p_depth;
+ for (k = 0; k <= l; k++, path++) {
+ if (path->p_idx) {
+ ext_debug(tree, " %d->%d", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ } else if (path->p_ext) {
+ ext_debug(tree, " %d:%d:%d",
-+ path->p_ext->ee_block,
-+ path->p_ext->ee_len,
-+ path->p_ext->ee_start);
++ path->p_ext->ee_block,
++ path->p_ext->ee_len,
++ path->p_ext->ee_start);
+ } else
+ ext_debug(tree, " []");
+ }
+}
+
+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int depth = EXT_DEPTH(tree);
+
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ ext_debug(tree, "%d:%d:%d ",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ }
+ ext_debug(tree, "\n");
+#endif
+ int depth = path->p_depth;
+ int i;
+
-+ for (i = 0; i <= depth; i++, path++)
++ for (i = 0; i <= depth; i++, path++) {
+ if (path->p_bh) {
+ brelse(path->p_bh);
+ path->p_bh = NULL;
+ }
++ }
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent_idx *ix;
+
+ ix += l;
+ path->p_idx = ix;
-+ ext_debug(tree, " -> %d->%d ", path->p_idx->ei_block, path->p_idx->ei_leaf);
++ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
+
+ while (l++ < r) {
+ if (block < ix->ei_block)
+ path->p_idx = ix++;
+ }
+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+
+#ifdef CHECK_BINSEARCH
+ {
+ for (k = 0; k < eh->eh_entries; k++, ix++) {
+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
+ printk("k=%d, ix=0x%p, first=0x%p\n", k,
-+ ix, EXT_FIRST_INDEX(eh));
++ ix, EXT_FIRST_INDEX(eh));
+ printk("%u <= %u\n",
-+ ix->ei_block,ix[-1].ei_block);
++ ix->ei_block,ix[-1].ei_block);
+ }
+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
+ if (block < ix->ei_block)
+ EXT_ASSERT(chix == path->p_idx);
+ }
+#endif
-+
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent *ex;
+ ex += l;
+ path->p_ext = ex;
+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+ while (l++ < r) {
+ if (block < ex->ee_block)
+ path->p_ext = ex++;
+ }
+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+#ifdef CHECK_BINSEARCH
+ {
+ EXT_ASSERT(chex == path->p_ext);
+ }
+#endif
-+
+}
+
+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
+
+struct ext3_ext_path *
+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ struct buffer_head *bh;
+ /* account possible depth increase */
+ if (!path) {
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+ GFP_NOFS);
++ GFP_NOFS);
+ if (!path)
+ return ERR_PTR(-ENOMEM);
+ }
+ /* walk through the tree */
+ while (i) {
+ ext_debug(tree, "depth %d: num %d, max %d\n",
-+ ppos, eh->eh_entries, eh->eh_max);
++ ppos, eh->eh_entries, eh->eh_max);
+ ext3_ext_binsearch_idx(tree, path + ppos, block);
+ path[ppos].p_block = path[ppos].p_idx->ei_leaf;
+ path[ppos].p_depth = i;
+ * it check where to insert: before curp or after curp
+ */
+static int ext3_ext_insert_index(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *curp,
-+ int logical, int ptr)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *curp,
++ int logical, int ptr)
+{
+ struct ext3_extent_idx *ix;
+ int len, err;
+ len = (len - 1) * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d after: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ (curp->p_idx + 1), (curp->p_idx + 2));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ (curp->p_idx + 1), (curp->p_idx + 2));
+ memmove(curp->p_idx + 2, curp->p_idx + 1, len);
+ }
+ ix = curp->p_idx + 1;
+ len = len * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d before: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ curp->p_idx, (curp->p_idx + 1));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ curp->p_idx, (curp->p_idx + 1));
+ memmove(curp->p_idx + 1, curp->p_idx, len);
+ ix = curp->p_idx;
+ }
+ * - initialize subtree
+ */
+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext, int at)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext, int at)
+{
+ struct buffer_head *bh = NULL;
+ int depth = EXT_DEPTH(tree);
+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ border = path[depth].p_ext[1].ee_block;
+ ext_debug(tree, "leaf will be splitted."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ } else {
+ border = newext->ee_block;
+ ext_debug(tree, "leaf will be added."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ }
+
+ /*
+ while (path[depth].p_ext <=
+ EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
-+ path[depth].p_ext->ee_block,
-+ path[depth].p_ext->ee_start,
-+ path[depth].p_ext->ee_len,
-+ newblock);
-+ memmove(ex++, path[depth].p_ext++,
-+ sizeof(struct ext3_extent));
++ path[depth].p_ext->ee_block,
++ path[depth].p_ext->ee_start,
++ path[depth].p_ext->ee_len,
++ newblock);
++ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
+ neh->eh_entries++;
+ m++;
+ }
+ fidx->ei_leaf = oldblock;
+
+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
-+ i, newblock, border, oldblock);
++ i, newblock, border, oldblock);
+ /* copy indexes */
+ m = 0;
+ path[i].p_idx++;
+
+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+ EXT_MAX_INDEX(path[i].p_hdr));
++ EXT_MAX_INDEX(path[i].p_hdr));
+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+ EXT_LAST_INDEX(path[i].p_hdr));
++ EXT_LAST_INDEX(path[i].p_hdr));
+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
+ ext_debug(tree, "%d: move %d:%d in new index %lu\n",
-+ i, path[i].p_idx->ei_block,
-+ path[i].p_idx->ei_leaf, newblock);
++ i, path[i].p_idx->ei_block,
++ path[i].p_idx->ei_leaf, newblock);
+ memmove(++fidx, path[i].p_idx++,
-+ sizeof(struct ext3_extent_idx));
++ sizeof(struct ext3_extent_idx));
+ neh->eh_entries++;
+ EXT_ASSERT(neh->eh_entries <= neh->eh_max);
+ m++;
+ /* insert new index */
+ if (!err)
+ err = ext3_ext_insert_index(handle, tree, path + at,
-+ border, newblock);
++ border, newblock);
+
+cleanup:
+ if (bh) {
+ * just created block
+ */
+static int ext3_ext_grow_indepth(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp = path;
+ struct ext3_extent_header *neh;
+ /* set size of new block */
+ neh = EXT_BLOCK_HDR(bh);
+ /* old root could have indexes or leaves
-+ * so calculate e_max right way */
++ * so calculate eh_max right way */
+ if (EXT_DEPTH(tree))
+ neh->eh_max = ext3_ext_space_block_idx(tree);
+ else
+ neh = EXT_ROOT_HDR(tree);
+ fidx = EXT_FIRST_INDEX(neh);
+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
-+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
++ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
+
+ neh->eh_depth = path->p_depth + 1;
+ err = ext3_ext_dirty(handle, tree, curp);
+ * then it requests in-depth growing
+ */
+static int ext3_ext_create_new_leaf(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp;
+ int depth, i, err = 0;
+ if (depth == path->p_depth) {
+ /* leaf */
+ if (path[depth].p_ext !=
-+ EXT_LAST_EXTENT(path[depth].p_hdr))
++ EXT_LAST_EXTENT(path[depth].p_hdr))
+ return path[depth].p_ext[1].ee_block;
+ } else {
+ /* index */
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ }
+ depth--;
+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
+ */
+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth;
+
+
+ while (depth >= 0) {
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ depth--;
+ }
+ * TODO: do we need to correct tree in all cases?
+ */
+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ int depth = EXT_DEPTH(tree);
+
+static int inline
+ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex1,
++ struct ext3_extent *ex2)
+{
+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
+ return 0;
+ * creating new leaf in no-space case
+ */
+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_extent_header * eh;
+ struct ext3_extent *ex, *fex;
+ /* try to insert block into found extent and return */
+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
+ ext_debug(tree, "append %d block to %d:%d (from %d)\n",
-+ newext->ee_len, ex->ee_block, ex->ee_len,
-+ ex->ee_start);
++ newext->ee_len, ex->ee_block, ex->ee_len,
++ ex->ee_start);
+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
+ return err;
+ ex->ee_len += newext->ee_len;
+ eh = npath[depth].p_hdr;
+ if (eh->eh_entries < eh->eh_max) {
+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->eh_entries);
++ eh->eh_entries);
+ path = npath;
+ goto repeat;
+ }
+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->eh_entries, eh->eh_max);
++ eh->eh_entries, eh->eh_max);
+ }
+
+ /*
+ if (!nearex) {
+ /* there is no extent in this leaf, create first one */
+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len);
++ newext->ee_block, newext->ee_start,
++ newext->ee_len);
+ path[depth].p_ext = EXT_FIRST_EXTENT(eh);
+ } else if (newext->ee_block > nearex->ee_block) {
+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
+ len = (len - 1) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start,
++ newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 2, nearex + 1, len);
+ }
+ path[depth].p_ext = nearex + 1;
+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start, newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start, newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 1, nearex, len);
+ path[depth].p_ext = nearex;
+ }
+ /* merge with next extent! */
+ nearex->ee_len += nearex[1].ee_len;
+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
-+ len = (EXT_LAST_EXTENT(eh) - nearex - 1)
-+ * sizeof(struct ext3_extent);
++ len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++ sizeof(struct ext3_extent);
+ memmove(nearex + 1, nearex + 2, len);
+ }
+ eh->eh_entries--;
+
+static inline void
+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
-+ __u32 len, __u32 start, int type)
++ __u32 len, __u32 start, int type)
+{
+ EXT_ASSERT(len > 0);
+ if (tree->cex) {
+ */
+static inline void
+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ unsigned long block)
++ struct ext3_ext_path *path,
++ unsigned long block)
+{
+ int depth = EXT_DEPTH(tree);
+ unsigned long lblock, len;
+ lblock = block;
+ len = ex->ee_block - block;
+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len);
+ } else if (block >= ex->ee_block + ex->ee_len) {
+ lblock = ex->ee_block + ex->ee_len;
+ len = ext3_ext_next_allocated_block(path);
+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) block);
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) block);
+ EXT_ASSERT(len > lblock);
+ len = len - lblock;
+ } else {
+
+static inline int
+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
-+ struct ext3_extent *ex)
++ struct ext3_extent *ex)
+{
+ struct ext3_ext_cache *cex = tree->cex;
+
+ return EXT3_EXT_CACHE_NO;
+
+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
-+ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+ ex->ee_block = cex->ec_block;
+ ex->ee_start = cex->ec_start;
+ ex->ee_len = cex->ec_len;
+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) ex->ee_start);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) ex->ee_start);
+ return cex->ec_type;
+ }
+
+ * last index in the block only
+ */
+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct buffer_head *bh;
+ int err;
+ if ((err = ext3_ext_dirty(handle, tree, path)))
+ return err;
+ ext_debug(tree, "index is empty, remove it, free block %d\n",
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
+}
+
+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth = EXT_DEPTH(tree);
+ int needed;
+
+static int
+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, tex;
+ struct ext3_ext_path *npath;
+ /* FIXME: some callback to free underlying resource
+ * and correct ee_start? */
+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
-+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
+
+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
+ if (IS_ERR(npath))
+ kfree(npath);
+
+ return err;
-+
+}
+
+static int
+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, *fu = NULL, *lu, *le;
+ int err = 0, correct_index = 0;
+ }
+
+ lu = ex;
-+ while (ex >= EXT_FIRST_EXTENT(eh) &&
-+ ex->ee_block + ex->ee_len > start) {
++ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
+ path[depth].p_ext = ex;
+
+ block = ex->ee_block;
+ num = 0;
+ EXT_ASSERT(a == ex->ee_block &&
-+ b == ex->ee_block + ex->ee_len - 1);
++ b == ex->ee_block + ex->ee_len - 1);
+ }
+
+ if (ex == EXT_FIRST_EXTENT(eh))
+ goto out;
+
+ ext_debug(tree, "new extent: %u:%u:%u\n",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ ex--;
+ }
+
+}
+
+int ext3_ext_remove_space(struct ext3_extents_tree *tree,
-+ unsigned long start, unsigned long end)
++ unsigned long start, unsigned long end)
+{
+ struct inode *inode = tree->inode;
+ struct super_block *sb = inode->i_sb;
+ */
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
+ if (IS_ERR(path)) {
-+ ext3_error(sb, "ext3_ext_remove_space",
-+ "Can't allocate path array");
++ ext3_error(sb, __FUNCTION__, "Can't allocate path array");
+ ext3_journal_stop(handle);
+ return -ENOMEM;
+ }
+ ext3_ext_last_covered(path[i].p_hdr, end);
+ path[i].p_block = path[i].p_hdr->eh_entries + 1;
+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
-+ path[i].p_hdr, path[i].p_hdr->eh_entries);
++ path[i].p_hdr, path[i].p_hdr->eh_entries);
+ } else {
+ /* we've already was here, see at next index */
+ path[i].p_idx--;
+ }
+
+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
-+ i, EXT_FIRST_INDEX(path[i].p_hdr),
-+ path[i].p_idx);
++ i, EXT_FIRST_INDEX(path[i].p_hdr),
++ path[i].p_idx);
+ if (ext3_ext_more_to_rm(path + i)) {
+ /* go to the next level */
+ ext_debug(tree, "move to level %d (block %d)\n",
-+ i + 1, path[i].p_idx->ei_leaf);
++ i + 1, path[i].p_idx->ei_leaf);
+ memset(path + i + 1, 0, sizeof(*path));
+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
+ if (!path[i+1].p_bh) {
+}
+
+static int ext3_ext_mergable(struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex2)
+{
+ /* FIXME: support for large fs */
+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
+
+static int
+ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed;
+
+
+static int
+ext3_remove_blocks(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+ handle_t *handle = ext3_journal_start(tree->inode, needed);
+ num = ex->ee_block + ex->ee_len - from;
+ start = ex->ee_start + ex->ee_len - num;
+ ext_debug(tree, "free last %lu blocks starting %lu\n",
-+ num, start);
++ num, start);
+ for (i = 0; i < num; i++) {
+ bh = sb_find_get_block(tree->inode->i_sb, start + i);
+ ext3_forget(handle, 0, tree->inode, bh, start + i);
+ ext3_free_blocks(handle, tree->inode, start, num);
+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+ printk("strange request: removal %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ } else {
+ printk("strange request: removal(2) %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ }
+ ext3_journal_stop(handle);
+ return 0;
+}
+
+static int ext3_ext_find_goal(struct inode *inode,
-+ struct ext3_ext_path *path, unsigned long block)
++ struct ext3_ext_path *path, unsigned long block)
+{
+ struct ext3_inode_info *ei = EXT3_I(inode);
+ unsigned long bg_start;
+}
+
+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int *err)
++ struct ext3_ext_path *path,
++ struct ext3_extent *ex, int *err)
+{
+ struct inode *inode = tree->inode;
+ int newblock, goal;
+};
+
+void ext3_init_tree_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode)
++ struct inode *inode)
+{
+ tree->inode = inode;
+ tree->root = (void *) EXT3_I(inode)->i_data;
+}
+
+int ext3_ext_get_block(handle_t *handle, struct inode *inode,
-+ long iblock, struct buffer_head *bh_result,
-+ int create, int extend_disksize)
++ long iblock, struct buffer_head *bh_result,
++ int create, int extend_disksize)
+{
+ struct ext3_ext_path *path = NULL;
+ struct ext3_extent newex;
+ __clear_bit(BH_New, &bh_result->b_state);
+ ext3_init_tree_desc(&tree, inode);
+ ext_debug(&tree, "block %d requested for inode %u\n",
-+ (int) iblock, (unsigned) inode->i_ino);
++ (int) iblock, (unsigned) inode->i_ino);
+ down(&EXT3_I(inode)->truncate_sem);
+
+ /* check in cache */
+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
+ newblock = iblock - ex->ee_block + ex->ee_start;
+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
-+ (int) iblock, ex->ee_block, ex->ee_len,
-+ newblock);
++ (int) iblock, ex->ee_block, ex->ee_len,
++ newblock);
+ ext3_ext_put_in_cache(&tree, ex->ee_block,
-+ ex->ee_len, ex->ee_start,
-+ EXT3_EXT_CACHE_EXTENT);
++ ex->ee_len, ex->ee_start,
++ EXT3_EXT_CACHE_EXTENT);
+ goto out;
+ }
+ }
+ if (!newblock)
+ goto out2;
+ ext_debug(&tree, "allocate new block: goal %d, found %d\n",
-+ goal, newblock);
++ goal, newblock);
+
+ /* try to insert new extent into found leaf and return */
+ newex.ee_block = iblock;
+ __set_bit(BH_New, &bh_result->b_state);
+
+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
-+ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
+out:
+ ext3_ext_show_leaf(&tree, path);
+ __set_bit(BH_Mapped, &bh_result->b_state);
+ EXT3_I(inode)->i_disksize = inode->i_size;
+ ext3_mark_inode_dirty(handle, inode);
+
-+ last_block = (inode->i_size + sb->s_blocksize - 1)
-+ >> EXT3_BLOCK_SIZE_BITS(sb);
++ last_block = (inode->i_size + sb->s_blocksize - 1) >>
++ EXT3_BLOCK_SIZE_BITS(sb);
+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
+
+ /* In a multi-transaction truncate, we only make the final
+
+static int
+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_ext_cache *newex)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *newex)
+{
+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
+
+
+static int
+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_ext_cache *ex)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *ex)
+{
+ struct ext3_extent_tree_stats *buf =
+ (struct ext3_extent_tree_stats *) tree->private;
+}
+
+int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-+ unsigned long arg)
++ unsigned long arg)
+{
+ int err = 0;
+
+ tree.private = &buf;
+ down(&EXT3_I(inode)->truncate_sem);
+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
++ ext3_ext_store_extent_cb);
+ up(&EXT3_I(inode)->truncate_sem);
+ if (err == 0)
+ err = buf.err;
+ buf.leaf_num = 0;
+ tree.private = &buf;
+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
++ ext3_ext_collect_stats_cb);
+ up(&EXT3_I(inode)->truncate_sem);
+ if (!err)
+ err = copy_to_user((void *) arg, &buf, sizeof(buf));
+EXPORT_SYMBOL(ext3_ext_walk_space);
+EXPORT_SYMBOL(ext3_ext_find_goal);
+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
-+
Index: linux-2.6.5-sles9/fs/ext3/ialloc.c
===================================================================
--- linux-2.6.5-sles9.orig/fs/ext3/ialloc.c 2005-02-23 01:01:52.366281264 +0300
+++ linux-2.6.5-sles9/fs/ext3/ialloc.c 2005-02-23 01:02:37.398435336 +0300
-@@ -647,6 +647,10 @@
+@@ -647,6 +647,18 @@
DQUOT_FREE_INODE(inode);
goto fail2;
}
-+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, inode);
-+ }
++ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++ ext3_extents_initialize_blockmap(handle, inode);
++ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
++ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++ if (err) goto fail;
++ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
++ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
++ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
++ }
++ }
++
err = ext3_mark_inode_dirty(handle, inode);
if (err) {
ext3_std_error(sb, err);
+static inline int
+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+ struct buffer_head *bh, int create, int extend_disksize)
++ struct buffer_head *bh, int create, int extend_disksize)
+{
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
+ return ext3_ext_get_block(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+ return ext3_get_block_handle(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+}
+
static int ext3_get_block(struct inode *inode, sector_t iblock,
- ret = ext3_get_block_handle(handle, inode, iblock,
- bh_result, create, 1);
+ ret = ext3_get_block_wrap(handle, inode, iblock,
-+ bh_result, create, 1);
++ bh_result, create, 1);
return ret;
}
- ret = ext3_get_block_handle(handle, inode, iblock,
- bh_result, create, 0);
+ ret = ext3_get_block_wrap(handle, inode, iblock,
-+ bh_result, create, 0);
++ bh_result, create, 0);
if (ret == 0)
bh_result->b_size = (1 << inode->i_blkbits);
return ret;
int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
int ret;
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_writepage_trans_blocks(inode, bpp);
-+
++ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++ return ext3_ext_writepage_trans_blocks(inode, bpp);
++
if (ext3_should_journal_data(inode))
ret = 3 * (bpp + indirects) + 2;
else
struct ext3_super_block *es = sbi->s_es;
int i;
-+ ext3_ext_release(sb);
++ ext3_ext_release(sb);
ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
if (!(sb->s_flags & MS_RDONLY)) {
percpu_counter_mod(&sbi->s_dirs_counter,
ext3_count_dirs(sb));
-+ ext3_ext_init(sb);
-+
++ ext3_ext_init(sb);
++
return 0;
failed_mount3:
===================================================================
--- linux-2.6.5-sles9.orig/include/linux/ext3_fs.h 2005-02-23 01:02:35.823674736 +0300
+++ linux-2.6.5-sles9/include/linux/ext3_fs.h 2005-02-23 01:02:37.414432904 +0300
-@@ -186,6 +186,7 @@
+@@ -186,8 +186,9 @@
+ #define EXT3_NOTAIL_FL 0x00008000 /* don't merge file tail */
#define EXT3_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
#define EXT3_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
- #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
+ #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
- #define EXT3_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
+-#define EXT3_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
#define EXT3_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
+
@@ -211,6 +212,9 @@
#endif
#define EXT3_IOC_GETRSVSZ _IOR('f', 5, long)
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef clear_opt
+@@ -503,11 +509,13 @@
+ #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG 0x0010
++#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
+
+ #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+ EXT3_FEATURE_INCOMPAT_RECOVER| \
+- EXT3_FEATURE_INCOMPAT_META_BG)
++ EXT3_FEATURE_INCOMPAT_META_BG| \
++ EXT3_FEATURE_INCOMPAT_EXTENTS)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
@@ -729,6 +735,7 @@
+/* extents.c */
+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+ struct buffer_head *, int, int);
++ struct buffer_head *, int, int);
+extern void ext3_ext_truncate(struct inode *, struct page *);
+extern void ext3_ext_init(struct super_block *);
+extern void ext3_ext_release(struct super_block *);
===================================================================
--- linux-2.6.5-sles9.orig/include/linux/ext3_extents.h 2005-02-17 22:07:57.023609040 +0300
+++ linux-2.6.5-sles9/include/linux/ext3_extents.h 2005-02-23 01:02:37.416432600 +0300
-@@ -0,0 +1,265 @@
+@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ */
+#define EXT_DEBUG_
+#ifdef EXT_DEBUG
-+#define ext_debug(tree,fmt,a...) \
++#define ext_debug(tree,fmt,a...) \
+do { \
+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
+ printk(fmt, ##a); \
+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
+ int (*remove_extent_credits)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*remove_extent)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*new_block)(handle_t *, struct ext3_extents_tree *,
-+ struct ext3_ext_path *, struct ext3_extent *,
-+ int *);
++ struct ext3_ext_path *, struct ext3_extent *,
++ int *);
+};
+
+/*
+ * callback must return valid extent (passed or newly created)
+ */
+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
-+ struct ext3_ext_path *,
-+ struct ext3_ext_cache *);
++ struct ext3_ext_path *,
++ struct ext3_ext_cache *);
+
+#define EXT_CONTINUE 0
+#define EXT_BREAK 1
+ && depth != 0); \
+ BUG_ON((path)[0].p_depth != depth); \
+}
-+
++
+
+/*
+ * this structure is used to gather extents from the tree via ioctl
+ int leaf_num;
+};
+
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
-+extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_ext_calc_blockmap_metadata(struct inode *, int);
+
+static inline void
+
+
+#endif /* _LINUX_EXT3_EXTENTS */
-+
Index: linux-2.6.5-sles9/include/linux/ext3_fs_i.h
===================================================================
--- linux-2.6.5-sles9.orig/include/linux/ext3_fs_i.h 2005-02-23 01:01:52.425272296 +0300
===================================================================
--- linux-stage.orig/fs/ext3/extents.c 2005-02-25 15:33:48.890198160 +0200
+++ linux-stage/fs/ext3/extents.c 2005-02-25 15:33:48.917194056 +0200
-@@ -0,0 +1,2313 @@
+@@ -0,0 +1,2347 @@
+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+#include <linux/ext3_extents.h>
+#include <asm/uaccess.h>
+
++
++static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
++{
++ if (eh->eh_magic != EXT3_EXT_MAGIC) {
++ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
++ (unsigned)eh->eh_magic);
++ return -EIO;
++ }
++ if (eh->eh_max == 0) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
++ (unsigned)eh->eh_max);
++ return -EIO;
++ }
++ if (eh->eh_entries > eh->eh_max) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
++ (unsigned)eh->eh_entries);
++ return -EIO;
++ }
++ return 0;
++}
++
+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
+{
+ int err;
+ * - ENOMEM
+ */
+static int ext3_ext_get_access(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path)
+{
+ int err;
+
+ * - EIO
+ */
+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int err;
+ if (path->p_bh) {
+
+static int inline
+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, struct ext3_extent *ex,
-+ int *err)
++ struct ext3_ext_path *path, struct ext3_extent *ex,
++ int *err)
+{
+ int goal, depth, newblock;
+ struct inode *inode;
+ unsigned long colour;
+
+ bg_start = (ei->i_block_group *
-+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
+ colour = (current->pid % 16) *
+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 6;
+#endif
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 5;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len - sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 3;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 4;
+#endif
+}
+
+static void ext3_ext_show_path(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int k, l = path->p_depth;
+ for (k = 0; k <= l; k++, path++) {
+ if (path->p_idx) {
+ ext_debug(tree, " %d->%d", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ } else if (path->p_ext) {
+ ext_debug(tree, " %d:%d:%d",
-+ path->p_ext->ee_block,
-+ path->p_ext->ee_len,
-+ path->p_ext->ee_start);
++ path->p_ext->ee_block,
++ path->p_ext->ee_len,
++ path->p_ext->ee_start);
+ } else
+ ext_debug(tree, " []");
+ }
+}
+
+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int depth = EXT_DEPTH(tree);
+
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ ext_debug(tree, "%d:%d:%d ",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ }
+ ext_debug(tree, "\n");
+#endif
+ int depth = path->p_depth;
+ int i;
+
-+ for (i = 0; i <= depth; i++, path++)
++ for (i = 0; i <= depth; i++, path++) {
+ if (path->p_bh) {
+ brelse(path->p_bh);
+ path->p_bh = NULL;
+ }
++ }
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent_idx *ix;
+
+ ix += l;
+ path->p_idx = ix;
-+ ext_debug(tree, " -> %d->%d ", path->p_idx->ei_block, path->p_idx->ei_leaf);
++ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
+
+ while (l++ < r) {
+ if (block < ix->ei_block)
+ path->p_idx = ix++;
+ }
+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+
+#ifdef CHECK_BINSEARCH
+ {
+ for (k = 0; k < eh->eh_entries; k++, ix++) {
+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
+ printk("k=%d, ix=0x%p, first=0x%p\n", k,
-+ ix, EXT_FIRST_INDEX(eh));
++ ix, EXT_FIRST_INDEX(eh));
+ printk("%u <= %u\n",
-+ ix->ei_block,ix[-1].ei_block);
++ ix->ei_block,ix[-1].ei_block);
+ }
+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
+ if (block < ix->ei_block)
+ EXT_ASSERT(chix == path->p_idx);
+ }
+#endif
-+
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent *ex;
+ ex += l;
+ path->p_ext = ex;
+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+ while (l++ < r) {
+ if (block < ex->ee_block)
+ path->p_ext = ex++;
+ }
+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+#ifdef CHECK_BINSEARCH
+ {
+ EXT_ASSERT(chex == path->p_ext);
+ }
+#endif
-+
+}
+
+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
+
+struct ext3_ext_path *
+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ struct buffer_head *bh;
+
+ eh = EXT_ROOT_HDR(tree);
+ EXT_ASSERT(eh);
++ if (ext3_ext_check_header(eh))
++ goto err;
++
+ i = depth = EXT_DEPTH(tree);
+ EXT_ASSERT(eh->eh_max);
+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(i == 0 || eh->eh_entries > 0);
+
+ /* account possible depth increase */
+ if (!path) {
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+ GFP_NOFS);
++ GFP_NOFS);
+ if (!path)
+ return ERR_PTR(-ENOMEM);
+ }
+ /* walk through the tree */
+ while (i) {
+ ext_debug(tree, "depth %d: num %d, max %d\n",
-+ ppos, eh->eh_entries, eh->eh_max);
++ ppos, eh->eh_entries, eh->eh_max);
+ ext3_ext_binsearch_idx(tree, path + ppos, block);
+ path[ppos].p_block = path[ppos].p_idx->ei_leaf;
+ path[ppos].p_depth = i;
+ path[ppos].p_ext = NULL;
+
+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
-+ if (!bh) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ return ERR_PTR(-EIO);
-+ }
++ if (!bh)
++ goto err;
++
+ eh = EXT_BLOCK_HDR(bh);
+ ppos++;
+ EXT_ASSERT(ppos <= depth);
+ path[ppos].p_bh = bh;
+ path[ppos].p_hdr = eh;
+ i--;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+ }
+
+ path[ppos].p_depth = i;
+ path[ppos].p_hdr = eh;
+ path[ppos].p_ext = NULL;
++ path[ppos].p_idx = NULL;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+
+ /* find extent */
+ ext3_ext_binsearch(tree, path + ppos, block);
+ ext3_ext_show_path(tree, path);
+
+ return path;
++
++err:
++ printk(KERN_ERR "EXT3-fs: header is corrupted!\n");
++ ext3_ext_drop_refs(path);
++ kfree(path);
++ return ERR_PTR(-EIO);
+}
+
+/*
+ * it check where to insert: before curp or after curp
+ */
+static int ext3_ext_insert_index(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *curp,
-+ int logical, int ptr)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *curp,
++ int logical, int ptr)
+{
+ struct ext3_extent_idx *ix;
+ int len, err;
+ len = (len - 1) * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d after: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ (curp->p_idx + 1), (curp->p_idx + 2));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ (curp->p_idx + 1), (curp->p_idx + 2));
+ memmove(curp->p_idx + 2, curp->p_idx + 1, len);
+ }
+ ix = curp->p_idx + 1;
+ len = len * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d before: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ curp->p_idx, (curp->p_idx + 1));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ curp->p_idx, (curp->p_idx + 1));
+ memmove(curp->p_idx + 1, curp->p_idx, len);
+ ix = curp->p_idx;
+ }
+ * - initialize subtree
+ */
+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext, int at)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext, int at)
+{
+ struct buffer_head *bh = NULL;
+ int depth = EXT_DEPTH(tree);
+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ border = path[depth].p_ext[1].ee_block;
+ ext_debug(tree, "leaf will be splitted."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ } else {
+ border = newext->ee_block;
+ ext_debug(tree, "leaf will be added."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ }
+
+ /*
+ while (path[depth].p_ext <=
+ EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
-+ path[depth].p_ext->ee_block,
-+ path[depth].p_ext->ee_start,
-+ path[depth].p_ext->ee_len,
-+ newblock);
-+ memmove(ex++, path[depth].p_ext++,
-+ sizeof(struct ext3_extent));
++ path[depth].p_ext->ee_block,
++ path[depth].p_ext->ee_start,
++ path[depth].p_ext->ee_len,
++ newblock);
++ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
+ neh->eh_entries++;
+ m++;
+ }
+ fidx->ei_leaf = oldblock;
+
+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
-+ i, newblock, border, oldblock);
++ i, newblock, border, oldblock);
+ /* copy indexes */
+ m = 0;
+ path[i].p_idx++;
+
+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+ EXT_MAX_INDEX(path[i].p_hdr));
++ EXT_MAX_INDEX(path[i].p_hdr));
+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+ EXT_LAST_INDEX(path[i].p_hdr));
++ EXT_LAST_INDEX(path[i].p_hdr));
+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
+ ext_debug(tree, "%d: move %d:%d in new index %lu\n",
-+ i, path[i].p_idx->ei_block,
-+ path[i].p_idx->ei_leaf, newblock);
++ i, path[i].p_idx->ei_block,
++ path[i].p_idx->ei_leaf, newblock);
+ memmove(++fidx, path[i].p_idx++,
-+ sizeof(struct ext3_extent_idx));
++ sizeof(struct ext3_extent_idx));
+ neh->eh_entries++;
+ EXT_ASSERT(neh->eh_entries <= neh->eh_max);
+ m++;
+ /* insert new index */
+ if (!err)
+ err = ext3_ext_insert_index(handle, tree, path + at,
-+ border, newblock);
++ border, newblock);
+
+cleanup:
+ if (bh) {
+ * just created block
+ */
+static int ext3_ext_grow_indepth(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp = path;
+ struct ext3_extent_header *neh;
+ /* set size of new block */
+ neh = EXT_BLOCK_HDR(bh);
+ /* old root could have indexes or leaves
-+ * so calculate e_max right way */
++ * so calculate eh_max right way */
+ if (EXT_DEPTH(tree))
+ neh->eh_max = ext3_ext_space_block_idx(tree);
+ else
+ neh = EXT_ROOT_HDR(tree);
+ fidx = EXT_FIRST_INDEX(neh);
+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
-+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
++ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
+
+ neh->eh_depth = path->p_depth + 1;
+ err = ext3_ext_dirty(handle, tree, curp);
+ * then it requests in-depth growing
+ */
+static int ext3_ext_create_new_leaf(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp;
+ int depth, i, err = 0;
+ if (depth == path->p_depth) {
+ /* leaf */
+ if (path[depth].p_ext !=
-+ EXT_LAST_EXTENT(path[depth].p_hdr))
++ EXT_LAST_EXTENT(path[depth].p_hdr))
+ return path[depth].p_ext[1].ee_block;
+ } else {
+ /* index */
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ }
+ depth--;
+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
+ */
+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth;
+
+
+ while (depth >= 0) {
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ depth--;
+ }
+ * TODO: do we need to correct tree in all cases?
+ */
+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ int depth = EXT_DEPTH(tree);
+
+static int inline
+ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex1,
++ struct ext3_extent *ex2)
+{
+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
+ return 0;
+ * creating new leaf in no-space case
+ */
+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_extent_header * eh;
+ struct ext3_extent *ex, *fex;
+ int depth, len, err, next;
+
+ EXT_ASSERT(newext->ee_len > 0);
-+ EXT_ASSERT(newext->ee_len < EXT_CACHE_MARK);
+ depth = EXT_DEPTH(tree);
+ ex = path[depth].p_ext;
+ EXT_ASSERT(path[depth].p_hdr);
+ /* try to insert block into found extent and return */
+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
+ ext_debug(tree, "append %d block to %d:%d (from %d)\n",
-+ newext->ee_len, ex->ee_block, ex->ee_len,
-+ ex->ee_start);
++ newext->ee_len, ex->ee_block, ex->ee_len,
++ ex->ee_start);
+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
+ return err;
+ ex->ee_len += newext->ee_len;
+ eh = npath[depth].p_hdr;
+ if (eh->eh_entries < eh->eh_max) {
+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->eh_entries);
++ eh->eh_entries);
+ path = npath;
+ goto repeat;
+ }
+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->eh_entries, eh->eh_max);
++ eh->eh_entries, eh->eh_max);
+ }
+
+ /*
+ if (!nearex) {
+ /* there is no extent in this leaf, create first one */
+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len);
++ newext->ee_block, newext->ee_start,
++ newext->ee_len);
+ path[depth].p_ext = EXT_FIRST_EXTENT(eh);
+ } else if (newext->ee_block > nearex->ee_block) {
+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
+ len = (len - 1) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start,
++ newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 2, nearex + 1, len);
+ }
+ path[depth].p_ext = nearex + 1;
+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start, newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start, newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 1, nearex, len);
+ path[depth].p_ext = nearex;
+ }
+ /* merge with next extent! */
+ nearex->ee_len += nearex[1].ee_len;
+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
-+ len = (EXT_LAST_EXTENT(eh) - nearex - 1)
-+ * sizeof(struct ext3_extent);
++ len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++ sizeof(struct ext3_extent);
+ memmove(nearex + 1, nearex + 2, len);
+ }
+ eh->eh_entries--;
+ unsigned long num, ext_prepare_callback func)
+{
+ struct ext3_ext_path *path = NULL;
-+ struct ext3_extent *ex, cbex;
++ struct ext3_ext_cache cbex;
++ struct ext3_extent *ex;
+ unsigned long next, start = 0, end = 0;
+ unsigned long last = block + num;
+ int depth, exists, err = 0;
+ EXT_ASSERT(end > start);
+
+ if (!exists) {
-+ cbex.ee_block = start;
-+ cbex.ee_len = end - start;
-+ cbex.ee_start = 0;
-+ } else
-+ cbex = *ex;
++ cbex.ec_block = start;
++ cbex.ec_len = end - start;
++ cbex.ec_start = 0;
++ cbex.ec_type = EXT3_EXT_CACHE_GAP;
++ } else {
++ cbex.ec_block = ex->ee_block;
++ cbex.ec_len = ex->ee_len;
++ cbex.ec_start = ex->ee_start;
++ cbex.ec_type = EXT3_EXT_CACHE_EXTENT;
++ }
+
++ EXT_ASSERT(cbex.ec_len > 0);
+ EXT_ASSERT(path[depth].p_hdr);
-+ err = func(tree, path, &cbex, exists);
++ err = func(tree, path, &cbex);
+ ext3_ext_drop_refs(path);
+
+ if (err < 0)
+ path = NULL;
+ }
+
-+ block = cbex.ee_block + cbex.ee_len;
++ block = cbex.ec_block + cbex.ec_len;
+ }
+
+ if (path) {
+
+static inline void
+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
-+ __u32 len, __u32 start, int type)
++ __u32 len, __u32 start, int type)
+{
+ EXT_ASSERT(len > 0);
+ if (tree->cex) {
+ */
+static inline void
+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ unsigned long block)
++ struct ext3_ext_path *path,
++ unsigned long block)
+{
+ int depth = EXT_DEPTH(tree);
+ unsigned long lblock, len;
+ lblock = block;
+ len = ex->ee_block - block;
+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len);
+ } else if (block >= ex->ee_block + ex->ee_len) {
+ lblock = ex->ee_block + ex->ee_len;
+ len = ext3_ext_next_allocated_block(path);
+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) block);
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) block);
+ EXT_ASSERT(len > lblock);
+ len = len - lblock;
+ } else {
+
+static inline int
+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
-+ struct ext3_extent *ex)
++ struct ext3_extent *ex)
+{
+ struct ext3_ext_cache *cex = tree->cex;
+
+ return EXT3_EXT_CACHE_NO;
+
+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
-+ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+ ex->ee_block = cex->ec_block;
+ ex->ee_start = cex->ec_start;
+ ex->ee_len = cex->ec_len;
+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) ex->ee_start);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) ex->ee_start);
+ return cex->ec_type;
+ }
+
+ * last index in the block only
+ */
+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct buffer_head *bh;
+ int err;
+ if ((err = ext3_ext_dirty(handle, tree, path)))
+ return err;
+ ext_debug(tree, "index is empty, remove it, free block %d\n",
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
+}
+
+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth = EXT_DEPTH(tree);
+ int needed;
+
+static int
+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, tex;
+ struct ext3_ext_path *npath;
+ /* FIXME: some callback to free underlying resource
+ * and correct ee_start? */
+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
-+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
+
+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
+ if (IS_ERR(npath))
+ kfree(npath);
+
+ return err;
-+
+}
+
+static int
+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, *fu = NULL, *lu, *le;
+ int err = 0, correct_index = 0;
+ }
+
+ lu = ex;
-+ while (ex >= EXT_FIRST_EXTENT(eh) &&
-+ ex->ee_block + ex->ee_len > start) {
++ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
+ path[depth].p_ext = ex;
+
+ block = ex->ee_block;
+ num = 0;
+ EXT_ASSERT(a == ex->ee_block &&
-+ b == ex->ee_block + ex->ee_len - 1);
++ b == ex->ee_block + ex->ee_len - 1);
+ }
+
+ if (ex == EXT_FIRST_EXTENT(eh))
+ goto out;
+
+ ext_debug(tree, "new extent: %u:%u:%u\n",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ ex--;
+ }
+
+}
+
+int ext3_ext_remove_space(struct ext3_extents_tree *tree,
-+ unsigned long start, unsigned long end)
++ unsigned long start, unsigned long end)
+{
+ struct inode *inode = tree->inode;
+ struct super_block *sb = inode->i_sb;
+ */
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
+ if (IS_ERR(path)) {
-+ ext3_error(sb, "ext3_ext_remove_space",
-+ "Can't allocate path array");
++ ext3_error(sb, __FUNCTION__, "Can't allocate path array");
+ ext3_journal_stop(handle);
+ return -ENOMEM;
+ }
+ ext3_ext_last_covered(path[i].p_hdr, end);
+ path[i].p_block = path[i].p_hdr->eh_entries + 1;
+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
-+ path[i].p_hdr, path[i].p_hdr->eh_entries);
++ path[i].p_hdr, path[i].p_hdr->eh_entries);
+ } else {
+ /* we've already was here, see at next index */
+ path[i].p_idx--;
+ }
+
+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
-+ i, EXT_FIRST_INDEX(path[i].p_hdr),
-+ path[i].p_idx);
++ i, EXT_FIRST_INDEX(path[i].p_hdr),
++ path[i].p_idx);
+ if (ext3_ext_more_to_rm(path + i)) {
+ /* go to the next level */
+ ext_debug(tree, "move to level %d (block %d)\n",
-+ i + 1, path[i].p_idx->ei_leaf);
++ i + 1, path[i].p_idx->ei_leaf);
+ memset(path + i + 1, 0, sizeof(*path));
+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
+ if (!path[i+1].p_bh) {
+}
+
+static int ext3_ext_mergable(struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex2)
+{
+ /* FIXME: support for large fs */
+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
+
+static int
+ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed;
+
+
+static int
+ext3_remove_blocks(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+ handle_t *handle = ext3_journal_start(tree->inode, needed);
+ num = ex->ee_block + ex->ee_len - from;
+ start = ex->ee_start + ex->ee_len - num;
+ ext_debug(tree, "free last %lu blocks starting %lu\n",
-+ num, start);
++ num, start);
+ for (i = 0; i < num; i++) {
+ bh = sb_find_get_block(tree->inode->i_sb, start + i);
+ ext3_forget(handle, 0, tree->inode, bh, start + i);
+ ext3_free_blocks(handle, tree->inode, start, num);
+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+ printk("strange request: removal %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ } else {
+ printk("strange request: removal(2) %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ }
+ ext3_journal_stop(handle);
+ return 0;
+}
+
+static int ext3_ext_find_goal(struct inode *inode,
-+ struct ext3_ext_path *path, unsigned long block)
++ struct ext3_ext_path *path, unsigned long block)
+{
+ struct ext3_inode_info *ei = EXT3_I(inode);
+ unsigned long bg_start;
+}
+
+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int *err)
++ struct ext3_ext_path *path,
++ struct ext3_extent *ex, int *err)
+{
+ struct inode *inode = tree->inode;
+ int newblock, goal;
+};
+
+void ext3_init_tree_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode)
++ struct inode *inode)
+{
+ tree->inode = inode;
+ tree->root = (void *) EXT3_I(inode)->i_data;
+}
+
+int ext3_ext_get_block(handle_t *handle, struct inode *inode,
-+ long iblock, struct buffer_head *bh_result,
-+ int create, int extend_disksize)
++ long iblock, struct buffer_head *bh_result,
++ int create, int extend_disksize)
+{
+ struct ext3_ext_path *path = NULL;
+ struct ext3_extent newex;
+ clear_buffer_new(bh_result);
+ ext3_init_tree_desc(&tree, inode);
+ ext_debug(&tree, "block %d requested for inode %u\n",
-+ (int) iblock, (unsigned) inode->i_ino);
++ (int) iblock, (unsigned) inode->i_ino);
+ down(&EXT3_I(inode)->truncate_sem);
+
+ /* check in cache */
+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
+ newblock = iblock - ex->ee_block + ex->ee_start;
+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
-+ (int) iblock, ex->ee_block, ex->ee_len,
-+ newblock);
++ (int) iblock, ex->ee_block, ex->ee_len,
++ newblock);
+ ext3_ext_put_in_cache(&tree, ex->ee_block,
-+ ex->ee_len, ex->ee_start,
-+ EXT3_EXT_CACHE_EXTENT);
++ ex->ee_len, ex->ee_start,
++ EXT3_EXT_CACHE_EXTENT);
+ goto out;
+ }
+ }
+ if (!newblock)
+ goto out2;
+ ext_debug(&tree, "allocate new block: goal %d, found %d\n",
-+ goal, newblock);
++ goal, newblock);
+
+ /* try to insert new extent into found leaf and return */
+ newex.ee_block = iblock;
+ set_buffer_new(bh_result);
+
+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
-+ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
+out:
+ ext3_ext_show_leaf(&tree, path);
+ map_bh(bh_result, inode->i_sb, newblock);
+ EXT3_I(inode)->i_disksize = inode->i_size;
+ ext3_mark_inode_dirty(handle, inode);
+
-+ last_block = (inode->i_size + sb->s_blocksize - 1)
-+ >> EXT3_BLOCK_SIZE_BITS(sb);
++ last_block = (inode->i_size + sb->s_blocksize - 1) >>
++ EXT3_BLOCK_SIZE_BITS(sb);
+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
+
+ /* In a multi-transaction truncate, we only make the final
+
+static int
+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *newex)
+{
+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
+
-+ if (!exist)
++ if (newex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
++
+ if (buf->err < 0)
+ return EXT_BREAK;
+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
+
+static int
+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *ex)
+{
+ struct ext3_extent_tree_stats *buf =
+ (struct ext3_extent_tree_stats *) tree->private;
+ int depth;
+
-+ if (!exist)
++ if (ex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
+
+ depth = EXT_DEPTH(tree);
+ tree.private = &buf;
+ down(&EXT3_I(inode)->truncate_sem);
+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
++ ext3_ext_store_extent_cb);
+ up(&EXT3_I(inode)->truncate_sem);
+ if (err == 0)
+ err = buf.err;
+ buf.leaf_num = 0;
+ tree.private = &buf;
+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
++ ext3_ext_collect_stats_cb);
+ up(&EXT3_I(inode)->truncate_sem);
+ if (!err)
+ err = copy_to_user((void *) arg, &buf, sizeof(buf));
+EXPORT_SYMBOL(ext3_ext_walk_space);
+EXPORT_SYMBOL(ext3_ext_find_goal);
+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
-+
Index: linux-stage/fs/ext3/ialloc.c
===================================================================
--- linux-stage.orig/fs/ext3/ialloc.c 2005-02-25 14:50:50.304202816 +0200
+++ linux-stage/fs/ext3/ialloc.c 2005-02-25 15:33:48.920193600 +0200
-@@ -646,6 +646,10 @@
+@@ -646,6 +646,18 @@
DQUOT_FREE_INODE(inode);
goto fail2;
}
-+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, inode);
-+ }
++ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++ ext3_extents_initialize_blockmap(handle, inode);
++ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
++ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++ if (err) goto fail;
++ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
++ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
++ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
++ }
++ }
++
err = ext3_mark_inode_dirty(handle, inode);
if (err) {
ext3_std_error(sb, err);
+static inline int
+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+ struct buffer_head *bh, int create, int extend_disksize)
++ struct buffer_head *bh, int create, int extend_disksize)
+{
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
+ return ext3_ext_get_block(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+ return ext3_get_block_handle(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+}
+
static int ext3_get_block(struct inode *inode, sector_t iblock,
- ret = ext3_get_block_handle(handle, inode, iblock,
- bh_result, create, 1);
+ ret = ext3_get_block_wrap(handle, inode, iblock,
-+ bh_result, create, 1);
++ bh_result, create, 1);
return ret;
}
int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
int ret;
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_writepage_trans_blocks(inode, bpp);
-+
++ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++ return ext3_ext_writepage_trans_blocks(inode, bpp);
++
if (ext3_should_journal_data(inode))
ret = 3 * (bpp + indirects) + 2;
else
struct ext3_super_block *es = sbi->s_es;
int i;
-+ ext3_ext_release(sb);
++ ext3_ext_release(sb);
ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
if (!(sb->s_flags & MS_RDONLY)) {
-@@ -457,6 +458,10 @@
+@@ -457,6 +458,8 @@
#endif
ei->i_rsv_window.rsv_end = EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
ei->vfs_inode.i_version = 1;
-+ ei->i_cached_extent[0] = 0;
-+ ei->i_cached_extent[1] = 0;
-+ ei->i_cached_extent[2] = 0;
-+ ei->i_cached_extent[3] = 0;
++
++ memset(&ei->i_cached_extent, 0, sizeof(ei->i_cached_extent));
return &ei->vfs_inode;
}
percpu_counter_mod(&sbi->s_dirs_counter,
ext3_count_dirs(sb));
-+ ext3_ext_init(sb);
-+
++ ext3_ext_init(sb);
++
return 0;
failed_mount3:
===================================================================
--- linux-stage.orig/include/linux/ext3_fs.h 2005-02-25 14:53:56.424908168 +0200
+++ linux-stage/include/linux/ext3_fs.h 2005-02-25 15:39:12.841950008 +0200
-@@ -186,6 +186,7 @@
+@@ -186,8 +186,9 @@
#define EXT3_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
#define EXT3_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
#define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
- #define EXT3_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
+-#define EXT3_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
#define EXT3_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
+
+ /*
@@ -237,6 +238,9 @@
#endif
#define EXT3_IOC_GETRSVSZ _IOR('f', 5, long)
/*
* Structure of an inode on the disk
-@@ -359,6 +363,9 @@
+@@ -359,6 +363,8 @@
#define EXT3_MOUNT_RESERVATION 0x20000 /* Preallocation */
#define EXT3_MOUNT_IOPEN 0x40000 /* Allow access via iopen */
#define EXT3_MOUNT_IOPEN_NOPRIV 0x80000 /* Make iopen world-readable */
+#define EXT3_MOUNT_EXTENTS 0x100000/* Extents support */
+#define EXT3_MOUNT_EXTDEBUG 0x200000/* Extents debug */
-+
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H
+@@ -503,11 +509,13 @@
+ #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG 0x0010
++#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
+
+ #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+ EXT3_FEATURE_INCOMPAT_RECOVER| \
+- EXT3_FEATURE_INCOMPAT_META_BG)
++ EXT3_FEATURE_INCOMPAT_META_BG| \
++ EXT3_FEATURE_INCOMPAT_EXTENTS)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
@@ -756,6 +763,7 @@
+/* extents.c */
+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+ struct buffer_head *, int, int);
++ struct buffer_head *, int, int);
+extern void ext3_ext_truncate(struct inode *, struct page *);
+extern void ext3_ext_init(struct super_block *);
+extern void ext3_ext_release(struct super_block *);
===================================================================
--- linux-stage.orig/include/linux/ext3_extents.h 2005-02-25 15:33:48.891198008 +0200
+++ linux-stage/include/linux/ext3_extents.h 2005-02-25 15:33:48.944189952 +0200
-@@ -0,0 +1,252 @@
+@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ */
+#define EXT_DEBUG_
+#ifdef EXT_DEBUG
-+#define ext_debug(tree,fmt,a...) \
++#define ext_debug(tree,fmt,a...) \
+do { \
+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
+ printk(fmt, ##a); \
+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
+ int (*remove_extent_credits)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*remove_extent)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*new_block)(handle_t *, struct ext3_extents_tree *,
-+ struct ext3_ext_path *, struct ext3_extent *,
-+ int *);
++ struct ext3_ext_path *, struct ext3_extent *,
++ int *);
+};
+
+/*
+ * callback must return valid extent (passed or newly created)
+ */
+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
-+ struct ext3_ext_path *,
-+ struct ext3_extent *, int);
++ struct ext3_ext_path *,
++ struct ext3_ext_cache *);
+
+#define EXT_CONTINUE 0
+#define EXT_BREAK 1
+
+
+#define EXT_MAX_BLOCK 0xffffffff
-+#define EXT_CACHE_MARK 0xffff
+
+
+#define EXT_FIRST_EXTENT(__hdr__) \
+
+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
+
++#define EXT_CHECK_PATH(tree,path) \
++{ \
++ int depth = EXT_DEPTH(tree); \
++ BUG_ON((unsigned long) (path) < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_idx < \
++ __PAGE_OFFSET && (path)[depth].p_idx != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_ext < \
++ __PAGE_OFFSET && (path)[depth].p_ext != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET \
++ && depth != 0); \
++ BUG_ON((path)[0].p_depth != depth); \
++}
++
+
+/*
+ * this structure is used to gather extents from the tree via ioctl
+ int leaf_num;
+};
+
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
-+extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_ext_calc_blockmap_metadata(struct inode *, int);
+
+static inline void
+
+
+#endif /* _LINUX_EXT3_EXTENTS */
-+
Index: linux-stage/include/linux/ext3_fs_i.h
===================================================================
--- linux-stage.orig/include/linux/ext3_fs_i.h 2005-02-25 14:50:50.320200384 +0200
struct semaphore truncate_sem;
struct inode vfs_inode;
+
-+ __u32 i_cached_extent[4];
++ __u32 i_cached_extent[4];
};
#endif /* _LINUX_EXT3_FS_I */
-Index: linux-2.6.5-sles9/fs/ext3/mballoc.c
+Index: linux-2.6.5-suse/fs/ext3/mballoc.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/mballoc.c 2005-02-17 22:07:57.023609040 +0300
-+++ linux-2.6.5-sles9/fs/ext3/mballoc.c 2005-02-23 01:56:19.101662000 +0300
-@@ -0,0 +1,1835 @@
+--- linux-2.6.5-suse.orig/fs/ext3/mballoc.c 2005-03-02 22:42:20.659360368 +0300
++++ linux-2.6.5-suse/fs/ext3/mballoc.c 2005-03-11 16:13:13.000000000 +0300
+@@ -0,0 +1,1863 @@
+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+
+/*
+ * TODO:
++ * - bitmap/buddy read-ahead (proposed by Oleg Drokin aka green)
+ * - track min/max extents in each group for better group selection
+ * - is it worthwhile to use buddies directly if req is 2^N blocks?
+ * - mb_mark_used() may allocate chunk right after splitting buddy
+ __u32 mh_magic;
+};
+
-+#define EXT3_MB_MAGIC_V1 0xbaad16fc
++#define EXT3_MB_MAGIC_V1 0xbabd16fd
+
+
+struct ext3_free_extent {
+ struct super_block *ac_sb;
+
+ /* search goals */
-+struct ext3_free_extent ac_g_ex;
++ struct ext3_free_extent ac_g_ex;
+
+ /* the best found extent */
+ struct ext3_free_extent ac_b_ex;
+void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
+void ext3_mb_free_committed_blocks(struct super_block *);
+
-+#define mb_correct_addr_and_bit(bit,addr) \
-+{ \
-+ if ((unsigned long)addr & 1) { \
-+ bit += 8; \
-+ addr--; \
-+ } \
-+ if ((unsigned long)addr & 2) { \
-+ bit += 16; \
-+ addr--; \
-+ addr--; \
-+ } \
++#if BITS_PER_LONG == 64
++#define mb_correct_addr_and_bit(bit,addr) \
++{ \
++ bit += ((unsigned long) addr & 7UL) << 3; \
++ addr = (void *) ((unsigned long) addr & ~7UL); \
+}
++#elif BITS_PER_LONG == 32
++#define mb_correct_addr_and_bit(bit,addr) \
++{ \
++ bit += ((unsigned long) addr & 3UL) << 3; \
++ addr = (void *) ((unsigned long) addr & ~3UL); \
++}
++#else
++#error "how many bits you are?!"
++#endif
+
+static inline int mb_test_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ return test_bit(bit, addr);
++ return ext2_test_bit(bit, addr);
+}
+
+static inline void mb_set_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ __set_bit(bit, addr);
++ ext2_set_bit(bit, addr);
+}
+
+static inline void mb_set_bit_atomic(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ set_bit(bit, addr);
++ ext2_set_bit_atomic(NULL, bit, addr);
+}
+
+static inline void mb_clear_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ __clear_bit(bit, addr);
++ ext2_clear_bit(bit, addr);
+}
+
+static inline void mb_clear_bit_atomic(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ clear_bit(bit, addr);
++ ext2_clear_bit_atomic(NULL, bit, addr);
+}
+
+static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
+ J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
+ J_ASSERT(max != NULL);
+
-+ if (order > e3b->bd_blkbits + 1)
++ if (order > e3b->bd_blkbits + 1) {
++ *max = 0;
+ return NULL;
++ }
+
+ /* at order 0 we see each particular block */
+ *max = 1 << (e3b->bd_blkbits + 3);
+ "can't get block for buddy bitmap\n");
+ goto out;
+ }
-+ if (!buffer_uptodate(e3b->bd_bh)) {
-+ ll_rw_block(READ, 1, &e3b->bd_bh);
-+ wait_on_buffer(e3b->bd_bh);
-+ }
-+ J_ASSERT(buffer_uptodate(e3b->bd_bh));
-+
+ /* load buddy */
+ e3b->bd_bh2 = sb_getblk(sb, sbi->s_buddy_blocks[group]->bb_buddy);
+ if (e3b->bd_bh2 == NULL) {
+ "can't get block for buddy bitmap\n");
+ goto out;
+ }
-+ if (!buffer_uptodate(e3b->bd_bh2)) {
++
++ if (!buffer_uptodate(e3b->bd_bh))
++ ll_rw_block(READ, 1, &e3b->bd_bh);
++ if (!buffer_uptodate(e3b->bd_bh2))
+ ll_rw_block(READ, 1, &e3b->bd_bh2);
-+ wait_on_buffer(e3b->bd_bh2);
-+ }
++
++ wait_on_buffer(e3b->bd_bh);
++ J_ASSERT(buffer_uptodate(e3b->bd_bh));
++ wait_on_buffer(e3b->bd_bh2);
+ J_ASSERT(buffer_uptodate(e3b->bd_bh2));
+
+ e3b->bd_blkbits = sb->s_blocksize_bits;
+ count = 0;
+ for (i = 0; i < max; i++) {
+
-+ if (!mb_test_bit(i, buddy)) {
++ if (mb_test_bit(i, buddy)) {
+ /* only single bit in buddy2 may be 1 */
-+ if (mb_test_bit(i << 1, buddy2))
-+ J_ASSERT(!mb_test_bit((i<<1)+1, buddy2));
-+ else if (mb_test_bit((i << 1) + 1, buddy2))
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
++ if (!mb_test_bit(i << 1, buddy2))
++ J_ASSERT(mb_test_bit((i<<1)+1, buddy2));
++ else if (!mb_test_bit((i << 1) + 1, buddy2))
++ J_ASSERT(mb_test_bit(i << 1, buddy2));
+ continue;
+ }
+
+ /* both bits in buddy2 must be 0 */
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
-+ J_ASSERT(!mb_test_bit((i << 1) + 1, buddy2));
++ J_ASSERT(mb_test_bit(i << 1, buddy2));
++ J_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
+
+ for (j = 0; j < (1 << order); j++) {
+ k = (i * (1 << order)) + j;
-+ J_ASSERT(mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
++ J_ASSERT(!mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
+ }
+ count++;
+ }
+
+ buddy = mb_find_buddy(e3b, 0, &max);
+ for (i = 0; i < max; i++) {
-+ if (mb_test_bit(i, buddy))
++ if (!mb_test_bit(i, buddy))
+ continue;
+ /* check used bits only */
+ for (j = 0; j < e3b->bd_blkbits + 1; j++) {
+ buddy2 = mb_find_buddy(e3b, j, &max2);
+ k = i >> j;
+ J_ASSERT(k < max2);
-+ J_ASSERT(!mb_test_bit(k, buddy2));
++ J_ASSERT(mb_test_bit(k, buddy2));
+ }
+ }
+}
+ bb = EXT3_MB_BUDDY(e3b);
+ while (order <= e3b->bd_blkbits + 1) {
+ block = block >> 1;
-+ if (mb_test_bit(block, bb)) {
++ if (!mb_test_bit(block, bb)) {
+ /* this block is part of buddy of order 'order' */
+ return order;
+ }
+ block = first++;
+ order = 0;
+
-+ J_ASSERT(!mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
-+ mb_set_bit(block, EXT3_MB_BITMAP(e3b));
++ J_ASSERT(mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
++ mb_clear_bit(block, EXT3_MB_BITMAP(e3b));
+ e3b->bd_bd->bb_counters[order]++;
+
+ /* start of the buddy */
+
+ do {
+ block &= ~1UL;
-+ if (!mb_test_bit(block, buddy) ||
-+ !mb_test_bit(block + 1, buddy))
++ if (mb_test_bit(block, buddy) ||
++ mb_test_bit(block + 1, buddy))
+ break;
+
+ /* both the buddies are free, try to coalesce them */
+ break;
+
+ if (order > 0) {
-+ /* for special purposes, we don't clear
++ /* for special purposes, we don't set
+ * free bits in bitmap */
-+ mb_clear_bit(block, buddy);
-+ mb_clear_bit(block + 1, buddy);
++ mb_set_bit(block, buddy);
++ mb_set_bit(block + 1, buddy);
+ }
+ e3b->bd_bd->bb_counters[order]--;
+ e3b->bd_bd->bb_counters[order]--;
+ order++;
+ e3b->bd_bd->bb_counters[order]++;
+
-+ mb_set_bit(block, buddy2);
++ mb_clear_bit(block, buddy2);
+ buddy = buddy2;
+ } while (1);
+ }
+}
+
+static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
-+ int needed, struct ext3_free_extent *ex)
++ int needed, struct ext3_free_extent *ex)
+{
+ int next, max, ord;
+ void *buddy;
+ buddy = mb_find_buddy(e3b, order, &max);
+ J_ASSERT(buddy);
+ J_ASSERT(block < max);
-+ if (!mb_test_bit(block, buddy)) {
++ if (mb_test_bit(block, buddy)) {
+ ex->fe_len = 0;
+ ex->fe_start = 0;
+ ex->fe_group = 0;
+ break;
+
+ next = (block + 1) * (1 << order);
-+ if (!mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
++ if (mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
+ break;
+
+ ord = mb_find_order_for_block(e3b, next);
+ mlen = 1 << ord;
+ buddy = mb_find_buddy(e3b, ord, &max);
+ J_ASSERT((start >> ord) < max);
-+ mb_clear_bit(start >> ord, buddy);
++ mb_set_bit(start >> ord, buddy);
+ e3b->bd_bd->bb_counters[ord]--;
+ start += mlen;
+ len -= mlen;
+ /* we have to split large buddy */
+ J_ASSERT(ord > 0);
+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_clear_bit(start >> ord, buddy);
++ mb_set_bit(start >> ord, buddy);
+ e3b->bd_bd->bb_counters[ord]--;
+
+ ord--;
+ cur = (start >> ord) & ~1U;
+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_set_bit(cur, buddy);
-+ mb_set_bit(cur + 1, buddy);
++ mb_clear_bit(cur, buddy);
++ mb_clear_bit(cur + 1, buddy);
+ e3b->bd_bd->bb_counters[ord]++;
+ e3b->bd_bd->bb_counters[ord]++;
+ }
+
+ /* now drop all the bits in bitmap */
-+ mb_clear_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
++ mb_set_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
+
+ mb_check_buddy(e3b);
+
+ i = e3b->bd_bd->bb_first_free;
+
+ while (free && ac->ac_status != AC_STATUS_FOUND) {
-+ i = find_next_bit(bitmap, sb->s_blocksize * 8, i);
++ i = ext2_find_next_zero_bit(bitmap, sb->s_blocksize * 8, i);
+ if (i >= sb->s_blocksize * 8) {
+ J_ASSERT(free == 0);
+ break;
+ /*
+ * We aren't lucky definitely
+ */
-+ J_ASSERT(ac.ac_b_ex.fe_len == 0);
+ DQUOT_FREE_BLOCK(inode, *len);
+ *errp = -ENOSPC;
+ block = 0;
+ ext3_error(sb, "ext3_new_block",
+ "Allocating block in system zone - "
+ "block = %u", block);
-+#if AGGRESSIVE_CHECK
-+ for (i = 0; i < ac.ac_b_len; i++)
++#ifdef AGGRESSIVE_CHECK
++ for (i = 0; i < ac.ac_b_ex.fe_len; i++)
+ J_ASSERT(!mb_test_bit(ac.ac_b_ex.fe_start + i, bitmap_bh->b_data));
+#endif
+ mb_set_bits(bitmap_bh->b_data, ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len);
+
+ e3b->bd_bd->bb_first_free = grp->mgd_first_free;
+ e3b->bd_bd->bb_free = grp->mgd_free;
-+ for (i = 0; i < e3b->bd_blkbits; i++) {
++ for (i = 0; i <= e3b->bd_blkbits + 1; i++) {
+ J_ASSERT(i < 16);
+ e3b->bd_bd->bb_counters[i] = grp->mgd_counters[i];
+ }
+ printk(KERN_ERR "EXT3-fs: mbgroup %d corrupted (%d != %d)\n",
+ e3b->bd_group, e3b->bd_bd->bb_free,
+ le16_to_cpu(gdp->bg_free_blocks_count));
-+ BUG();
+ return -ENODATA;
+ }
+
+int ext3_mb_update_descr(struct ext3_buddy *e3b)
+{
+ struct ext3_mb_group_descr *grp;
-+ struct ext3_group_desc *ogdp;
++ struct ext3_group_desc *gdp;
+ struct buffer_head *bh;
+ handle_t *handle;
+ int err, i;
+
+ /* additional checks against old group descriptor */
-+ ogdp = ext3_get_group_desc(e3b->bd_sb, e3b->bd_group, NULL);
-+ if (!ogdp)
++ gdp = ext3_get_group_desc(e3b->bd_sb, e3b->bd_group, NULL);
++ if (!gdp)
+ return -EIO;
-+ if (e3b->bd_bd->bb_free != le16_to_cpu(ogdp->bg_free_blocks_count)) {
++ if (e3b->bd_bd->bb_free != le16_to_cpu(gdp->bg_free_blocks_count)) {
+ printk(KERN_ERR "EXT3-fs: mbgroup %d corrupted (%d != %d)\n",
+ e3b->bd_group, e3b->bd_bd->bb_free,
-+ le16_to_cpu(ogdp->bg_free_blocks_count));
-+ BUG();
++ le16_to_cpu(gdp->bg_free_blocks_count));
+ return -ENODATA;
+ }
+
+ if (err)
+ return err;
+
-+ handle = journal_start(EXT3_SB(e3b->bd_sb)->s_journal, 1);
++ handle = ext3_journal_start(EXT3_SB(e3b->bd_sb)->s_buddy, 1);
+ if (IS_ERR(handle)) {
+ err = PTR_ERR(handle);
+ handle = NULL;
+ goto out;
+ grp->mgd_first_free = e3b->bd_bd->bb_first_free;
+ grp->mgd_free = e3b->bd_bd->bb_free;
-+ for (i = 0; i < e3b->bd_blkbits; i++) {
++ for (i = 0; i <= e3b->bd_blkbits + 1; i++) {
+ J_ASSERT(i < 16);
+ grp->mgd_counters[i] = e3b->bd_bd->bb_counters[i];
+ }
+ struct super_block *sb = e3b->bd_sb;
+ struct buffer_head *bh;
+ int i, count = 0;
-+
-+ memset(e3b->bd_bh->b_data, 0, sb->s_blocksize);
-+ memset(e3b->bd_bh2->b_data, 0, sb->s_blocksize);
++
++ mb_debug("generate buddy for group %d\n", e3b->bd_group);
++ memset(e3b->bd_bh->b_data, 0xff, sb->s_blocksize);
++ memset(e3b->bd_bh2->b_data, 0xff, sb->s_blocksize);
+
+ bh = read_block_bitmap(sb, e3b->bd_group);
+ if (bh == NULL)
+ return -EIO;
+
+ /* mb_free_blocks will set real free */
++ e3b->bd_bd->bb_free = 0;
+ e3b->bd_bd->bb_first_free = 1 << 15;
++ /*
++ * if change bb_counters size, don't forget about
++ * ext3_mb_init_backend() -bzzz
++ */
++ memset(e3b->bd_bd->bb_counters, 0,
++ sizeof(unsigned) * (sb->s_blocksize_bits + 2));
+
+ /* loop over the blocks, and create buddies for free ones */
+ for (i = 0; i < sb->s_blocksize * 8; i++) {
+ }
+ db->d_inode->i_flags |= S_IMMUTABLE | S_NOATIME;
+ *created = 1;
-+ printk("EXT3-fs: no buddy file, regenerate\n");
++ mb_debug("no buddy file, regenerate\n");
+ }
+ up(&root->i_sem);
+ sbi->s_buddy = igrab(db->d_inode);
+ len = sbi->s_groups_count * sb->s_blocksize * 2 +
+ buddy_offset * sb->s_blocksize;
+ if (len != i_size_read(sbi->s_buddy)) {
-+ printk("EXT3-fs: wrong i_size (%u != %u), regenerate\n",
-+ (unsigned) len, (unsigned) i_size_read(sbi->s_buddy));
++ if (*created == 0)
++ printk("EXT3-fs: wrong i_size (%u != %u), regenerate\n",
++ (unsigned) len,
++ (unsigned) i_size_read(sbi->s_buddy));
+ *created = 1;
+ }
+
+ for (i = 0; i < buddy_offset; i++) {
+ handle = ext3_journal_start(sbi->s_buddy, MB_CREDITS);
+ if (IS_ERR(handle)) {
-+ printk(KERN_ERR "EXT3-fs: can't start transaction\n");
++ printk(KERN_ERR "EXT3-fs: cant start transaction\n");
+ err = PTR_ERR(handle);
+ goto err_out;
+ }
+
+ bh = ext3_bread(handle, sbi->s_buddy, i, 1, &err);
+ if (bh == NULL) {
-+ printk(KERN_ERR "EXT3-fs: can't getblk grp: %d\n", err);
++ printk(KERN_ERR "EXT3-fs: cant getblk grp: %d\n", err);
+ goto err_out;
+ }
+ hdr = (struct ext3_mb_grp_header *) bh->b_data;
+ err = ext3_journal_get_write_access(handle, bh);
+ if (err)
+ goto err_out;
++ if (*created == 0)
++ printk(KERN_ERR
++ "EXT3-fs: invalid header 0x%x in %d,"
++ "regenerate\n", hdr->mh_magic, i);
+ *created = 1;
-+ printk("EXT3-fs: invalid header %#x in %d regenerate\n",
-+ hdr->mh_magic, i);
+ hdr->mh_magic = EXT3_MB_MAGIC_V1;
+ err = ext3_journal_dirty_metadata(handle, bh);
+ if (err)
+ ext3_journal_stop(handle);
+ }
+
++ /*
++ * if change bb_counters size, don't forget about ext3_mb_generate_buddy()
++ */
+ len = sizeof(struct ext3_buddy_group_blocks);
+ len += sizeof(unsigned) * (sb->s_blocksize_bits + 2);
+ for (i = 0; i < sbi->s_groups_count; i++) {
++
+ sbi->s_buddy_blocks[i] = kmalloc(len, GFP_KERNEL);
+ if (sbi->s_buddy_blocks[i] == NULL) {
-+ printk(KERN_ERR "EXT3-fs: can't allocate buddy mem\n");
++ printk(KERN_ERR "EXT3-fs: cant allocate mem for buddy\n");
+ err = -ENOMEM;
+ goto out2;
+ }
+
+ handle = ext3_journal_start(sbi->s_buddy, MB_CREDITS);
+ if (IS_ERR(handle)) {
-+ printk(KERN_ERR "EXT3-fs: can't start transaction\n");
++ printk(KERN_ERR "EXT3-fs: cant start transaction\n");
+ err = PTR_ERR(handle);
+ goto out2;
+ }
+ block = buddy_offset + i * 2;
+ bh = ext3_getblk(handle, sbi->s_buddy, block, 1, &err);
+ if (bh == NULL) {
-+ printk(KERN_ERR "EXT3-fs: can't getblk bitmap: %d\n",
-+ err);
++ printk(KERN_ERR "EXT3-fs: cant getblk bitmap: %d\n", err);
+ goto out2;
+ }
+ sbi->s_buddy_blocks[i]->bb_bitmap = bh->b_blocknr;
+ block = buddy_offset + i * 2 + 1;
+ bh = ext3_getblk(handle, sbi->s_buddy, block, 1, &err);
+ if (bh == NULL) {
-+ printk(KERN_ERR "EXT3-fs: can't getblk for buddy: %d\n",+ err);
++ printk(KERN_ERR "EXT3-fs: cant getblk for buddy: %d\n", err);
+ goto out2;
+ }
+ sbi->s_buddy_blocks[i]->bb_buddy = bh->b_blocknr;
+ if (err)
+ goto error_return;
+
++#ifdef AGGRESSIVE_CHECK
++ {
++ int i;
++ for (i = 0; i < count; i++)
++ J_ASSERT(mb_test_bit(bit + i, bitmap_bh->b_data));
++ }
++#endif
++ mb_clear_bits(bitmap_bh->b_data, bit, count);
++
++ /* We dirtied the bitmap block */
++ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
++ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++
+ if (metadata) {
+ /* blocks being freed are metadata. these blocks shouldn't
+ * be used until this transaction is committed */
+ mb_free_blocks(&e3b, bit, count);
+ ext3_unlock_group(sb, block_group);
+ }
++
+ spin_lock(sb_bgl_lock(sbi, block_group));
+ gdp->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
+ spin_unlock(sb_bgl_lock(sbi, block_group));
++ percpu_counter_mod(&sbi->s_freeblocks_counter, count);
+
+ ext3_mb_dirty_buddy(&e3b);
+ ext3_mb_release_desc(&e3b);
+
-+ mb_clear_bits(bitmap_bh->b_data, bit, count);
+ *freed = count;
+
-+ /* We dirtied the bitmap block */
-+ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
-+ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
-+
+ /* And the group descriptor block */
+ BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
+ ret = ext3_journal_dirty_metadata(handle, gd_bh);
+ return ret;
+}
+
++
+extern void ext3_free_blocks_old(handle_t *, struct inode *,
+ unsigned long, unsigned long);
+void ext3_free_blocks(handle_t *handle, struct inode * inode,
+ return;
+}
+
-Index: linux-2.6.5-sles9/fs/ext3/super.c
+Index: linux-2.6.5-suse/fs/ext3/super.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/super.c 2005-02-23 01:47:15.291333736 +0300
-+++ linux-2.6.5-sles9/fs/ext3/super.c 2005-02-23 01:48:54.515249408 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/super.c 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/super.c 2005-02-26 18:40:26.000000000 +0300
@@ -389,6 +389,7 @@
struct ext3_super_block *es = sbi->s_es;
int i;
+ ext3_mb_release(sb);
- ext3_ext_release(sb);
+ ext3_ext_release(sb);
ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
-@@ -540,6 +541,7 @@
+@@ -543,6 +544,7 @@
Opt_commit, Opt_journal_update, Opt_journal_inum,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_ignore, Opt_barrier, Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
Opt_err, Opt_extents, Opt_extdebug
};
-@@ -587,6 +589,8 @@
+@@ -590,6 +592,8 @@
{Opt_iopen_nopriv, "iopen_nopriv"},
{Opt_extents, "extents"},
{Opt_extdebug, "extdebug"},
{Opt_err, NULL}
};
-@@ -808,6 +812,16 @@
+@@ -811,6 +815,16 @@
case Opt_extdebug:
set_opt (sbi->s_mount_opt, EXTDEBUG);
break;
default:
printk (KERN_ERR
"EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1461,7 +1475,8 @@
+@@ -1464,6 +1478,7 @@
ext3_count_dirs(sb));
- ext3_ext_init(sb);
--
+ ext3_ext_init(sb);
+ ext3_mb_init(sb, needs_recovery);
-+
+
return 0;
- failed_mount3:
-Index: linux-2.6.5-sles9/fs/ext3/Makefile
+Index: linux-2.6.5-suse/fs/ext3/Makefile
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/Makefile 2005-02-23 01:02:37.405434272 +0300
-+++ linux-2.6.5-sles9/fs/ext3/Makefile 2005-02-23 01:48:54.517249104 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/Makefile 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/Makefile 2005-02-26 18:40:26.000000000 +0300
@@ -5,7 +5,7 @@
obj-$(CONFIG_EXT3_FS) += ext3.o
ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
-Index: linux-2.6.5-sles9/fs/ext3/balloc.c
+Index: linux-2.6.5-suse/fs/ext3/balloc.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/balloc.c 2004-11-03 08:36:51.000000000 +0300
-+++ linux-2.6.5-sles9/fs/ext3/balloc.c 2005-02-23 01:48:54.520248648 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/balloc.c 2005-02-02 00:55:47.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/balloc.c 2005-02-26 18:40:26.000000000 +0300
@@ -78,7 +78,7 @@
*
* Return buffer_head on success or NULL in case of failure.
unsigned long goal, int *errp)
{
struct buffer_head *bitmap_bh = NULL;
-Index: linux-2.6.5-sles9/fs/ext3/namei.c
+Index: linux-2.6.5-suse/fs/ext3/namei.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/namei.c 2005-02-23 01:01:46.551165296 +0300
-+++ linux-2.6.5-sles9/fs/ext3/namei.c 2005-02-23 01:48:54.523248192 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/namei.c 2005-02-26 18:40:19.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/namei.c 2005-02-26 18:40:26.000000000 +0300
@@ -1640,7 +1640,7 @@
* If the create succeeds, we fill in the inode information
* with d_instantiate().
struct nameidata *nd)
{
handle_t *handle;
-Index: linux-2.6.5-sles9/fs/ext3/inode.c
+Index: linux-2.6.5-suse/fs/ext3/inode.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/inode.c 2005-02-23 01:02:37.404434424 +0300
-+++ linux-2.6.5-sles9/fs/ext3/inode.c 2005-02-23 01:48:54.529247280 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/inode.c 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/inode.c 2005-02-26 18:40:26.000000000 +0300
@@ -572,7 +572,7 @@
ext3_journal_forget(handle, branch[i].bh);
}
return err;
}
-@@ -1829,7 +1829,7 @@
+@@ -1830,7 +1830,7 @@
}
}
}
/**
-@@ -2000,7 +2000,7 @@
+@@ -2001,7 +2001,7 @@
ext3_journal_test_restart(handle, inode);
}
if (parent_bh) {
/*
-Index: linux-2.6.5-sles9/fs/ext3/extents.c
+Index: linux-2.6.5-suse/fs/ext3/extents.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/extents.c 2005-02-23 01:02:37.396435640 +0300
-+++ linux-2.6.5-sles9/fs/ext3/extents.c 2005-02-23 01:48:54.533246672 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/extents.c 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/extents.c 2005-02-26 18:40:26.000000000 +0300
@@ -774,7 +774,7 @@
for (i = 0; i < depth; i++) {
if (!ablocks[i])
} else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
printk("strange request: removal %lu-%lu from %u:%u\n",
from, to, ex->ee_block, ex->ee_len);
-Index: linux-2.6.5-sles9/fs/ext3/xattr.c
+Index: linux-2.6.5-suse/fs/ext3/xattr.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/xattr.c 2005-02-23 01:01:52.387278072 +0300
-+++ linux-2.6.5-sles9/fs/ext3/xattr.c 2005-02-23 01:48:54.537246064 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/xattr.c 2005-02-26 18:40:22.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/xattr.c 2005-02-26 18:40:26.000000000 +0300
@@ -1366,7 +1366,7 @@
new_bh = sb_getblk(sb, block);
if (!new_bh) {
get_bh(bh);
ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
} else {
-Index: linux-2.6.5-sles9/include/linux/ext3_fs.h
+Index: linux-2.6.5-suse/include/linux/ext3_fs.h
===================================================================
---- linux-2.6.5-sles9.orig/include/linux/ext3_fs.h 2005-02-23 01:02:37.414432904 +0300
-+++ linux-2.6.5-sles9/include/linux/ext3_fs.h 2005-02-23 01:48:54.539245760 +0300
+--- linux-2.6.5-suse.orig/include/linux/ext3_fs.h 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/include/linux/ext3_fs.h 2005-02-26 18:40:26.000000000 +0300
@@ -57,6 +57,14 @@
#define ext3_debug(f, a...) do {} while (0)
#endif
#define EXT3_MOUNT_IOPEN_NOPRIV 0x80000 /* Make iopen world-readable */
#define EXT3_MOUNT_EXTENTS 0x100000/* Extents support */
#define EXT3_MOUNT_EXTDEBUG 0x200000/* Extents debug */
-+#define EXT3_MOUNT_MBALLOC 0x100000/* Buddy allocation support */
++#define EXT3_MOUNT_MBALLOC 0x400000/* Buddy allocation support */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef clear_opt
#endif /* __KERNEL__ */
#define EXT3_IOC_CREATE_INUM _IOW('f', 5, long)
-Index: linux-2.6.5-sles9/include/linux/ext3_fs_sb.h
+Index: linux-2.6.5-suse/include/linux/ext3_fs_sb.h
===================================================================
---- linux-2.6.5-sles9.orig/include/linux/ext3_fs_sb.h 2005-02-23 01:01:48.242908112 +0300
-+++ linux-2.6.5-sles9/include/linux/ext3_fs_sb.h 2005-02-23 01:48:54.541245456 +0300
+--- linux-2.6.5-suse.orig/include/linux/ext3_fs_sb.h 2005-02-26 18:40:20.000000000 +0300
++++ linux-2.6.5-suse/include/linux/ext3_fs_sb.h 2005-02-26 18:40:26.000000000 +0300
@@ -23,10 +23,30 @@
#define EXT_INCLUDE
#include <linux/blockgroup_lock.h>
===================================================================
--- linux-stage.orig/fs/ext3/mballoc.c 2005-02-25 17:28:41.836311072 +0200
+++ linux-stage/fs/ext3/mballoc.c 2005-02-25 17:28:41.859307576 +0200
-@@ -0,0 +1,1847 @@
+@@ -0,0 +1,1860 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+
+/*
+ * TODO:
++ * - bitmap/buddy read-ahead (proposed by Oleg Drokin aka green)
+ * - track min/max extents in each group for better group selection
+ * - is it worthwhile to use buddies directly if req is 2^N blocks?
+ * - mb_mark_used() may allocate chunk right after splitting buddy
+ __u32 mh_magic;
+};
+
-+#define EXT3_MB_MAGIC_V1 0xbaad16fc
++#define EXT3_MB_MAGIC_V1 0xbabd16fd
+
+
+struct ext3_free_extent {
+void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
+void ext3_mb_free_committed_blocks(struct super_block *);
+
-+#define mb_correct_addr_and_bit(bit,addr) \
-+{ \
-+ if ((unsigned long)addr & 1) { \
-+ bit += 8; \
-+ addr--; \
-+ } \
-+ if ((unsigned long)addr & 2) { \
-+ bit += 16; \
-+ addr--; \
-+ addr--; \
-+ } \
++#if BITS_PER_LONG == 64
++#define mb_correct_addr_and_bit(bit,addr) \
++{ \
++ bit += ((unsigned long) addr & 7UL) << 3; \
++ addr = (void *) ((unsigned long) addr & ~7UL); \
+}
++#elif BITS_PER_LONG == 32
++#define mb_correct_addr_and_bit(bit,addr) \
++{ \
++ bit += ((unsigned long) addr & 3UL) << 3; \
++ addr = (void *) ((unsigned long) addr & ~3UL); \
++}
++#else
++#error "how many bits you are?!"
++#endif
+
+static inline int mb_test_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ return test_bit(bit, addr);
++ return ext2_test_bit(bit, addr);
+}
+
+static inline void mb_set_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ __set_bit(bit, addr);
++ ext2_set_bit(bit, addr);
+}
+
+static inline void mb_set_bit_atomic(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ set_bit(bit, addr);
++ ext2_set_bit_atomic(NULL, bit, addr);
+}
+
+static inline void mb_clear_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ __clear_bit(bit, addr);
++ ext2_clear_bit(bit, addr);
+}
+
+static inline void mb_clear_bit_atomic(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ clear_bit(bit, addr);
++ ext2_clear_bit_atomic(NULL, bit, addr);
+}
+
+static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
+ J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
+ J_ASSERT(max != NULL);
+
-+ if (order > e3b->bd_blkbits + 1)
++ if (order > e3b->bd_blkbits + 1) {
++ *max = 0;
+ return NULL;
++ }
+
+ /* at order 0 we see each particular block */
+ *max = 1 << (e3b->bd_blkbits + 3);
+ "can't get block for buddy bitmap\n");
+ goto out;
+ }
-+ if (!buffer_uptodate(e3b->bd_bh)) {
-+ ll_rw_block(READ, 1, &e3b->bd_bh);
-+ wait_on_buffer(e3b->bd_bh);
-+ }
-+ J_ASSERT(buffer_uptodate(e3b->bd_bh));
-+
+ /* load buddy */
+ e3b->bd_bh2 = sb_getblk(sb, sbi->s_buddy_blocks[group]->bb_buddy);
+ if (e3b->bd_bh2 == NULL) {
+ "can't get block for buddy bitmap\n");
+ goto out;
+ }
-+ if (!buffer_uptodate(e3b->bd_bh2)) {
++
++ if (!buffer_uptodate(e3b->bd_bh))
++ ll_rw_block(READ, 1, &e3b->bd_bh);
++ if (!buffer_uptodate(e3b->bd_bh2))
+ ll_rw_block(READ, 1, &e3b->bd_bh2);
-+ wait_on_buffer(e3b->bd_bh2);
-+ }
++
++ wait_on_buffer(e3b->bd_bh);
++ J_ASSERT(buffer_uptodate(e3b->bd_bh));
++ wait_on_buffer(e3b->bd_bh2);
+ J_ASSERT(buffer_uptodate(e3b->bd_bh2));
+
+ e3b->bd_blkbits = sb->s_blocksize_bits;
+ count = 0;
+ for (i = 0; i < max; i++) {
+
-+ if (!mb_test_bit(i, buddy)) {
++ if (mb_test_bit(i, buddy)) {
+ /* only single bit in buddy2 may be 1 */
-+ if (mb_test_bit(i << 1, buddy2))
-+ J_ASSERT(!mb_test_bit((i<<1)+1, buddy2));
-+ else if (mb_test_bit((i << 1) + 1, buddy2))
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
++ if (!mb_test_bit(i << 1, buddy2))
++ J_ASSERT(mb_test_bit((i<<1)+1, buddy2));
++ else if (!mb_test_bit((i << 1) + 1, buddy2))
++ J_ASSERT(mb_test_bit(i << 1, buddy2));
+ continue;
+ }
+
+ /* both bits in buddy2 must be 0 */
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
-+ J_ASSERT(!mb_test_bit((i << 1) + 1, buddy2));
++ J_ASSERT(mb_test_bit(i << 1, buddy2));
++ J_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
+
+ for (j = 0; j < (1 << order); j++) {
+ k = (i * (1 << order)) + j;
-+ J_ASSERT(mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
++ J_ASSERT(!mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
+ }
+ count++;
+ }
+
+ buddy = mb_find_buddy(e3b, 0, &max);
+ for (i = 0; i < max; i++) {
-+ if (mb_test_bit(i, buddy))
++ if (!mb_test_bit(i, buddy))
+ continue;
+ /* check used bits only */
+ for (j = 0; j < e3b->bd_blkbits + 1; j++) {
+ buddy2 = mb_find_buddy(e3b, j, &max2);
+ k = i >> j;
+ J_ASSERT(k < max2);
-+ J_ASSERT(!mb_test_bit(k, buddy2));
++ J_ASSERT(mb_test_bit(k, buddy2));
+ }
+ }
+}
+ bb = EXT3_MB_BUDDY(e3b);
+ while (order <= e3b->bd_blkbits + 1) {
+ block = block >> 1;
-+ if (mb_test_bit(block, bb)) {
++ if (!mb_test_bit(block, bb)) {
+ /* this block is part of buddy of order 'order' */
+ return order;
+ }
+ block = first++;
+ order = 0;
+
-+ J_ASSERT(!mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
-+ mb_set_bit(block, EXT3_MB_BITMAP(e3b));
++ J_ASSERT(mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
++ mb_clear_bit(block, EXT3_MB_BITMAP(e3b));
+ e3b->bd_bd->bb_counters[order]++;
+
+ /* start of the buddy */
+
+ do {
+ block &= ~1UL;
-+ if (!mb_test_bit(block, buddy) ||
-+ !mb_test_bit(block + 1, buddy))
++ if (mb_test_bit(block, buddy) ||
++ mb_test_bit(block + 1, buddy))
+ break;
+
+ /* both the buddies are free, try to coalesce them */
+ break;
+
+ if (order > 0) {
-+ /* for special purposes, we don't clear
++ /* for special purposes, we don't set
+ * free bits in bitmap */
-+ mb_clear_bit(block, buddy);
-+ mb_clear_bit(block + 1, buddy);
++ mb_set_bit(block, buddy);
++ mb_set_bit(block + 1, buddy);
+ }
+ e3b->bd_bd->bb_counters[order]--;
+ e3b->bd_bd->bb_counters[order]--;
+ order++;
+ e3b->bd_bd->bb_counters[order]++;
+
-+ mb_set_bit(block, buddy2);
++ mb_clear_bit(block, buddy2);
+ buddy = buddy2;
+ } while (1);
+ }
+ buddy = mb_find_buddy(e3b, order, &max);
+ J_ASSERT(buddy);
+ J_ASSERT(block < max);
-+ if (!mb_test_bit(block, buddy)) {
++ if (mb_test_bit(block, buddy)) {
+ ex->fe_len = 0;
+ ex->fe_start = 0;
+ ex->fe_group = 0;
+ break;
+
+ next = (block + 1) * (1 << order);
-+ if (!mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
++ if (mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
+ break;
+
+ ord = mb_find_order_for_block(e3b, next);
+ mlen = 1 << ord;
+ buddy = mb_find_buddy(e3b, ord, &max);
+ J_ASSERT((start >> ord) < max);
-+ mb_clear_bit(start >> ord, buddy);
++ mb_set_bit(start >> ord, buddy);
+ e3b->bd_bd->bb_counters[ord]--;
+ start += mlen;
+ len -= mlen;
+ /* we have to split large buddy */
+ J_ASSERT(ord > 0);
+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_clear_bit(start >> ord, buddy);
++ mb_set_bit(start >> ord, buddy);
+ e3b->bd_bd->bb_counters[ord]--;
+
+ ord--;
+ cur = (start >> ord) & ~1U;
+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_set_bit(cur, buddy);
-+ mb_set_bit(cur + 1, buddy);
++ mb_clear_bit(cur, buddy);
++ mb_clear_bit(cur + 1, buddy);
+ e3b->bd_bd->bb_counters[ord]++;
+ e3b->bd_bd->bb_counters[ord]++;
+ }
+
+ /* now drop all the bits in bitmap */
-+ mb_clear_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
++ mb_set_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
+
+ mb_check_buddy(e3b);
+
+ i = e3b->bd_bd->bb_first_free;
+
+ while (free && ac->ac_status != AC_STATUS_FOUND) {
-+ i = find_next_bit(bitmap, sb->s_blocksize * 8, i);
++ i = ext2_find_next_zero_bit(bitmap, sb->s_blocksize * 8, i);
+ if (i >= sb->s_blocksize * 8) {
+ J_ASSERT(free == 0);
+ break;
+ /*
+ * We aren't lucky definitely
+ */
-+ J_ASSERT(ac.ac_b_ex.fe_len == 0);
+ DQUOT_FREE_BLOCK(inode, *len);
+ *errp = -ENOSPC;
+ block = 0;
+ ext3_error(sb, "ext3_new_block",
+ "Allocating block in system zone - "
+ "block = %u", block);
-+#if AGGRESSIVE_CHECK
-+ for (i = 0; i < ac.ac_b_len; i++)
++#ifdef AGGRESSIVE_CHECK
++ for (i = 0; i < ac.ac_b_ex.fe_len; i++)
+ J_ASSERT(!mb_test_bit(ac.ac_b_ex.fe_start + i, bitmap_bh->b_data));
+#endif
+ mb_set_bits(bitmap_bh->b_data, ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len);
+
+ e3b->bd_bd->bb_first_free = grp->mgd_first_free;
+ e3b->bd_bd->bb_free = grp->mgd_free;
-+ for (i = 0; i < e3b->bd_blkbits; i++) {
++ for (i = 0; i <= e3b->bd_blkbits + 1; i++) {
+ J_ASSERT(i < 16);
+ e3b->bd_bd->bb_counters[i] = grp->mgd_counters[i];
+ }
+ goto out;
+ grp->mgd_first_free = e3b->bd_bd->bb_first_free;
+ grp->mgd_free = e3b->bd_bd->bb_free;
-+ for (i = 0; i < e3b->bd_blkbits; i++) {
++ for (i = 0; i <= e3b->bd_blkbits + 1; i++) {
+ J_ASSERT(i < 16);
+ grp->mgd_counters[i] = e3b->bd_bd->bb_counters[i];
+ }
+ struct super_block *sb = e3b->bd_sb;
+ struct buffer_head *bh;
+ int i, count = 0;
-+
-+ memset(e3b->bd_bh->b_data, 0, sb->s_blocksize);
-+ memset(e3b->bd_bh2->b_data, 0, sb->s_blocksize);
++
++ mb_debug("generate buddy for group %d\n", e3b->bd_group);
++ memset(e3b->bd_bh->b_data, 0xff, sb->s_blocksize);
++ memset(e3b->bd_bh2->b_data, 0xff, sb->s_blocksize);
+
+ bh = read_block_bitmap(sb, e3b->bd_group);
+ if (bh == NULL)
+ if (err)
+ goto error_return;
+
++#ifdef AGGRESSIVE_CHECK
++ {
++ int i;
++ for (i = 0; i < count; i++)
++ J_ASSERT(mb_test_bit(bit + i, bitmap_bh->b_data));
++ }
++#endif
++ mb_clear_bits(bitmap_bh->b_data, bit, count);
++
++ /* We dirtied the bitmap block */
++ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
++ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++
+ if (metadata) {
+ /* blocks being freed are metadata. these blocks shouldn't
+ * be used until this transaction is committed */
+ mb_free_blocks(&e3b, bit, count);
+ ext3_unlock_group(sb, block_group);
+ }
++
+ spin_lock(sb_bgl_lock(sbi, block_group));
+ gdp->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
+ spin_unlock(sb_bgl_lock(sbi, block_group));
++ percpu_counter_mod(&sbi->s_freeblocks_counter, count);
+
+ ext3_mb_dirty_buddy(&e3b);
+ ext3_mb_release_desc(&e3b);
+
-+ mb_clear_bits(bitmap_bh->b_data, bit, count);
+ *freed = count;
+
-+ /* We dirtied the bitmap block */
-+ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
-+ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
-+
+ /* And the group descriptor block */
+ BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
+ ret = ext3_journal_dirty_metadata(handle, gd_bh);
+ return ret;
+}
+
-+
+void ext3_free_blocks(handle_t *handle, struct inode * inode,
+ unsigned long block, unsigned long count, int metadata)
+{
+ DQUOT_FREE_BLOCK(inode, freed);
+ return;
+}
-+
Index: linux-stage/fs/ext3/super.c
===================================================================
--- linux-stage.orig/fs/ext3/super.c 2005-02-25 17:27:00.231757312 +0200
int i;
+ ext3_mb_release(sb);
- ext3_ext_release(sb);
+ ext3_ext_release(sb);
ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
@@ -592,7 +593,7 @@
default:
printk (KERN_ERR
"EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1639,7 +1652,8 @@
+@@ -1639,6 +1652,7 @@
ext3_count_dirs(sb));
- ext3_ext_init(sb);
--
+ ext3_ext_init(sb);
+ ext3_mb_init(sb, needs_recovery);
-+
+
return 0;
- failed_mount3:
Index: linux-stage/fs/ext3/Makefile
===================================================================
--- linux-stage.orig/fs/ext3/Makefile 2005-02-25 17:27:00.228757768 +0200
#define EXT3_MOUNT_EXTDEBUG 0x200000/* Extents debug */
+#define EXT3_MOUNT_MBALLOC 0x400000/* Buddy allocation support */
-
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef _LINUX_EXT2_FS_H
@@ -725,7 +734,7 @@
extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *);
#endif
#include <linux/rbtree.h>
-+#define EXT3_BB_MAX_BLOCKS 30
++#define EXT3_BB_MAX_BLOCKS 30
+struct ext3_free_metadata {
+ unsigned short group;
+ unsigned short num;
+ spinlock_t s_md_lock;
+ tid_t s_last_transaction;
+ int s_mb_factor;
-+
++
+ /* stats for buddy allocator */
+ spinlock_t s_bal_lock;
+ unsigned long s_bal_reqs; /* number of reqs with len > 1 */
- fix several locking issues related to i_size (5492,5624,5654,5672)
- don't move pending lock onto export if it is already evicted (5683)
- fix kernel oops when creating .foo in unlinked directory (5548)
+ - fix deadlock in obdfilter statistics vs. object create (5811)
+ - use time_{before,after} to avoid timer jiffies wrap (5882)
+ - shutdown --force/--failover stability (3607,3651,4797,5203,4834)
+ - Do not leak request if server was not able to process it (5154)
+ - If mds_open unable to find parent dir, make that negative lookup(5154)
* miscellania
- fix lustre/lustrefs init scripts for SuSE (patch from Scali, 5702)
- don't hold the pinger_sem in ptlrpc_pinger_sending_on_import
- change obd_increase_kms to obd_adjust_kms (up or down) (5654)
- lconf, lmc search both /usr/lib and /usr/lib64 for Python libs (5800)
+ - support for RHEL4 kernel on i686 (5773)
+ - provide error messages when incompatible logs are encountered (5898)
2005-02-18 Cluster File Systems, Inc. <info@clusterfs.com>
* version 1.4.0.10 (1.4.1 release candidate 1)
])
#
+# LC_FUNC_DEV_SET_RDONLY
+#
+# check for the old-style dev_set_rdonly which took an extra "devno" param
+# and can only set a single device to discard writes at one time
+#
+AC_DEFUN([LC_FUNC_DEV_SET_RDONLY],
+[AC_MSG_CHECKING([if kernel has old single-device dev_set_rdonly])
+HAVE_OLD_DSR="`grep -c -s 'dev_set_rdonly.*no_write' $LINUX/drivers/block/ll_rw_blk.c`"
+if test x$HAVE_OLD_DSR != "x1" ; then
+ HAVE_OLD_DSR="`grep -c -s 'dev_set_rdonly.*no_write' $LINUX/drivers/block/blkpg.c`"
+fi
+if test x$HAVE_OLD_DSR = "x1" ; then
+ AC_DEFINE(HAVE_OLD_DEV_SET_RDONLY, 1,
+ [kernel has old single-device dev_set_rdonly])
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+])
+
+#
# LC_CONFIG_BACKINGFS
#
# whether to use extN or ldiskfs instead of ext3
LC_FSHOOKS([
LDISKFS_SERIES="2.6-suse.series"
],[
- AC_MSG_ERROR([Only SuSE 2.6 kernels (with fshooks) are supported at this time])
- LDISKFS_SERIES="2.6-vanilla.series"
+ LDISKFS_SERIES="2.6-rhel4.series"
])
AC_SUBST(LDISKFS_SERIES)
;;
LC_STRUCT_INODE
LC_FUNC_REGISTER_CACHE
LC_FUNC_GRAB_CACHE_PAGE_NOWAIT_GFP
+LC_FUNC_DEV_SET_RDONLY
])
#
lustre/include/lustre/Makefile
lustre/kernel_patches/targets/2.6-suse.target
lustre/kernel_patches/targets/2.6-vanilla.target
+lustre/kernel_patches/targets/2.6-rhel4.target
lustre/kernel_patches/targets/hp_pnnl-2.4.target
lustre/kernel_patches/targets/rh-2.4.target
lustre/kernel_patches/targets/rhel-2.4.target
-m4_define([LUSTRE_VERSION],[1.4.0.10])
+m4_define([LUSTRE_VERSION],[1.4.1])
# sample modules.conf for autoloading lustre modules on zeroconf clients
add below kptlrouter portals
+#add below ksocknal kptlrouter
+#add below kqswnal kptlrouter
add below ptlrpc ksocknal
add below llite lov osc
alias lustre llite
})
#define time_after(a, b) ((long)(b) - (long)(a) < 0)
#define time_before(a, b) time_after(b,a)
+#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
struct timer_list {
struct list_head tl_list;
static inline int timer_pending(struct timer_list *l)
{
- if (l->expires > jiffies)
+ if (time_after(l->expires, jiffies))
return 1;
else
return 0;
extern int lprocfs_rd_u64(char *page, char **start, off_t off,
int count, int *eof, void *data);
+extern int lprocfs_rd_atomic(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
extern int lprocfs_rd_uuid(char *page, char **start, off_t off,
int count, int *eof, void *data);
extern int lprocfs_rd_name(char *page, char **start, off_t off,
char *ns_name;
__u32 ns_client; /* is this a client-side lock tree? */
struct list_head *ns_hash; /* hash table for ns */
- __u32 ns_refcount; /* count of resources in the hash */
+ wait_queue_head_t ns_refcount_waitq; /* for cleanup */
+ atomic_t ns_refcount; /* count of resources in the hash */
struct list_head ns_root_list; /* all root resources in ns */
struct lustre_lock ns_lock; /* protects hash, refcount, list */
struct list_head ns_list_chain; /* position in global NS list */
struct list_head ns_unused_list; /* all root resources in ns */
int ns_nr_unused;
unsigned int ns_max_unused;
- unsigned long ns_next_dump; /* next dump time */
+ unsigned long ns_next_dump; /* next debug dump, jiffies */
spinlock_t ns_counter_lock;
__u64 ns_locks;
- __u64 ns_resources;
ldlm_res_policy ns_policy;
struct ldlm_valblock_ops *ns_lvbo;
void *ns_lvbp;
/* Server-side-only members */
struct list_head l_pending_chain; /* callbacks pending */
- unsigned long l_callback_timeout;
+ unsigned long l_callback_timeout; /* jiffies */
__u32 l_pid; /* pid which created this lock */
};
-#define LDLM_PLAIN 10
-#define LDLM_EXTENT 11
-#define LDLM_FLOCK 12
-
-#define LDLM_MIN_TYPE 10
-#define LDLM_MAX_TYPE 12
-
struct ldlm_resource {
struct ldlm_namespace *lr_namespace;
struct list_head lr_hash;
{
unsigned long now = jiffies;
void *parent_handle = oti ? oti->oti_handle : NULL;
- void *handle = obd->obd_fsops->fs_start(inode, op, parent_handle, logs);
+ void *handle;
+
+ if (obd->obd_fail)
+ return ERR_PTR(-EROFS);
+
+ handle = obd->obd_fsops->fs_start(inode, op, parent_handle, logs);
CDEBUG(D_INFO, "started handle %p (%p)\n", handle, parent_handle);
if (oti != NULL) {
{
unsigned long now = jiffies;
void *parent_handle = oti ? oti->oti_handle : NULL;
- void *handle = obd->obd_fsops->fs_brw_start(objcount, fso, niocount, nb,
- parent_handle, logs);
+ void *handle;
+
+ if (obd->obd_fail)
+ return ERR_PTR(-EROFS);
+
+ handle = obd->obd_fsops->fs_brw_start(objcount, fso, niocount, nb,
+ parent_handle, logs);
CDEBUG(D_INFO, "started handle %p (%p)\n", handle, parent_handle);
if (oti != NULL) {
struct inode *inode, void *bio)
{
LASSERTF(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ, "%x\n", rw);
-
+
if (rw == OBD_BRW_READ)
return obd->obd_fsops->fs_send_bio(READ, inode, bio);
- else
- return obd->obd_fsops->fs_send_bio(WRITE, inode, bio);
+ return obd->obd_fsops->fs_send_bio(WRITE, inode, bio);
}
static inline ssize_t fsfilt_readpage(struct obd_device *obd,
LCK_NL = 32
} ldlm_mode_t;
+typedef enum {
+ LDLM_PLAIN = 10,
+ LDLM_EXTENT = 11,
+ LDLM_FLOCK = 12,
+ LDLM_MAX_TYPE
+} ldlm_type_t;
+
+#define LDLM_MIN_TYPE LDLM_PLAIN
+
struct ldlm_extent {
__u64 start;
__u64 end;
extern void lustre_swab_ldlm_intent (struct ldlm_intent *i);
struct ldlm_resource_desc {
- __u32 lr_type;
+ ldlm_type_t lr_type;
__u32 lr_padding;
struct ldlm_res_id lr_name;
};
__u64 imp_peer_committed_transno;
struct obd_uuid imp_target_uuid; /* XXX -> lustre_name */
struct lustre_handle imp_remote_handle;
- unsigned long imp_next_ping;
-
+ unsigned long imp_next_ping; /* jiffies */
+
/* Protects flags, level, generation, conn_cnt, *_list */
spinlock_t imp_lock;
#define OBD_IOC_STATFS _IOWR('f', 113, long)
-#define OBD_IOC_SYNC _IOR ('f', 114, long)
+#define OBD_IOC_SYNC _IOW ('f', 114, long)
#define OBD_IOC_READ2 _IOWR('f', 115, long)
#define OBD_IOC_FORMAT _IOWR('f', 116, long)
#define OBD_IOC_PARTITION _IOWR('f', 117, long)
/* careful, this is easy to screw up */
#define PAGE_CACHE_MAXBYTES ((__u64)(~0UL) << PAGE_CACHE_SHIFT)
-
-/*
-struct lustre_intent_data {
- __u64 it_lock_handle[2];
- __u32 it_disposition;
- __u32 it_status;
- __u32 it_lock_mode;
- }; */
-
-#define LL_IT2STR(it) ((it) ? ldlm_it2str((it)->it_op) : "0")
-
-static inline struct lookup_intent *ll_nd2it(struct nameidata *nd)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
- return &nd->intent;
-#else
- return nd->intent;
-#endif
-}
-
-struct ll_dentry_data {
- int lld_cwd_count;
- int lld_mnt_count;
- struct obd_client_handle lld_cwd_och;
- struct obd_client_handle lld_mnt_och;
-};
-
-#define ll_d2d(de) ((struct ll_dentry_data*) de->d_fsdata)
-
-extern struct file_operations ll_pgcache_seq_fops;
-
-#define LLI_INODE_MAGIC 0x111d0de5
-#define LLI_INODE_DEAD 0xdeadd00d
-#define LLI_F_HAVE_OST_SIZE_LOCK 0
-#define LLI_F_HAVE_MDS_SIZE_LOCK 1
-struct ll_inode_info {
- int lli_inode_magic;
- struct lov_stripe_md *lli_smd;
- char *lli_symlink_name;
- struct semaphore lli_open_sem;
- struct semaphore lli_size_sem;
- __u64 lli_maxbytes;
- __u64 lli_io_epoch;
- unsigned long lli_flags;
-
- /* this lock protects s_d_w and p_w_ll and mmap_cnt */
- spinlock_t lli_lock;
- int lli_send_done_writing;
- struct list_head lli_pending_write_llaps;
- atomic_t lli_mmap_cnt;
-
- struct list_head lli_close_item;
-
- /* for writepage() only to communicate to fsync */
- int lli_async_rc;
-
- struct file_operations *ll_save_ifop;
- struct file_operations *ll_save_ffop;
- struct file_operations *ll_save_wfop;
- struct file_operations *ll_save_wrfop;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
- struct inode lli_vfs_inode;
-#endif
-};
-
-// FIXME: replace the name of this with LL_I to conform to kernel stuff
-// static inline struct ll_inode_info *LL_I(struct inode *inode)
-static inline struct ll_inode_info *ll_i2info(struct inode *inode)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
- return container_of(inode, struct ll_inode_info, lli_vfs_inode);
-#else
- return (struct ll_inode_info *)&(inode->u.generic_ip);
-#endif
-}
-
/* lprocfs.c */
enum {
LPROC_LL_DIRTY_HITS = 0,
/* mds/mds_fs.c */
int mds_fs_setup(struct obd_device *obddev, struct vfsmount *mnt);
-int mds_fs_cleanup(struct obd_device *obddev, int failover);
+int mds_fs_cleanup(struct obd_device *obddev);
#endif
/* mds/mds_lov.c */
int rq_reqlen;
struct lustre_msg *rq_reqmsg;
- int rq_timeout;
+ int rq_timeout; /* seconds */
int rq_replen;
struct lustre_msg *rq_repmsg;
__u64 rq_transno;
void *rq_cb_data;
struct ptlrpc_bulk_desc *rq_bulk; /* client side bulk */
- time_t rq_sent; /* when the request was sent */
+ time_t rq_sent; /* when request sent, seconds */
/* Multi-rpc bits */
struct list_head rq_set_chain;
/* ldlm/ldlm_lib.c */
int client_obd_setup(struct obd_device *obddev, obd_count len, void *buf);
-int client_obd_cleanup(struct obd_device * obddev, int flags);
+int client_obd_cleanup(struct obd_device * obddev);
int client_connect_import(struct lustre_handle *conn, struct obd_device *obd,
struct obd_uuid *cluuid);
-int client_disconnect_export(struct obd_export *exp, int failover);
+int client_disconnect_export(struct obd_export *exp);
/* ptlrpc/pinger.c */
int ptlrpc_pinger_add_import(struct obd_import *imp);
int obd_minor;
unsigned int obd_attached:1, obd_set_up:1, obd_recovering:1,
obd_abort_recovery:1, obd_replayable:1, obd_no_transno:1,
- obd_no_recov:1, obd_stopping:1, obd_starting:1;
+ obd_no_recov:1, obd_stopping:1, obd_starting:1,
+ obd_force:1, obd_fail:1;
atomic_t obd_refcount;
wait_queue_head_t obd_refcount_waitq;
struct proc_dir_entry *obd_proc_entry;
struct fsfilt_operations *obd_fsops;
spinlock_t obd_osfs_lock;
struct obd_statfs obd_osfs;
- unsigned long obd_osfs_age;
+ unsigned long obd_osfs_age; /* jiffies */
struct obd_run_ctxt obd_ctxt;
struct llog_ctxt *obd_llog_ctxt[LLOG_MAX_CTXTS];
struct obd_device *obd_observer;
int (*o_attach)(struct obd_device *dev, obd_count len, void *data);
int (*o_detach)(struct obd_device *dev);
int (*o_setup) (struct obd_device *dev, obd_count len, void *data);
- int (*o_precleanup)(struct obd_device *dev, int flags);
- int (*o_cleanup)(struct obd_device *dev, int flags);
+ int (*o_precleanup)(struct obd_device *dev);
+ int (*o_cleanup)(struct obd_device *dev);
int (*o_postrecov)(struct obd_device *dev);
int (*o_connect)(struct lustre_handle *conn, struct obd_device *src,
struct obd_uuid *cluuid);
- int (*o_disconnect)(struct obd_export *exp, int flags);
+ int (*o_disconnect)(struct obd_export *exp);
int (*o_statfs)(struct obd_device *obd, struct obd_statfs *osfs,
unsigned long max_age);
int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg);
int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg);
int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg);
+void class_decref(struct obd_device *obd);
/* Passed as data param to class_config_parse_llog */
struct config_llog_instance {
void class_put_type(struct obd_type *type);
int class_connect(struct lustre_handle *conn, struct obd_device *obd,
struct obd_uuid *cluuid);
-int class_disconnect(struct obd_export *exp, int failover);
-void class_disconnect_exports(struct obd_device *obddev, int failover);
-void class_disconnect_stale_exports(struct obd_device *obddev, int failover);
+int class_disconnect(struct obd_export *exp);
+void class_disconnect_exports(struct obd_device *obddev);
+void class_disconnect_stale_exports(struct obd_device *obddev);
/* generic operations shared by various OBD types */
int class_multi_setup(struct obd_device *obddev, uint32_t len, void *data);
int class_multi_cleanup(struct obd_device *obddev);
} \
} while (0)
-#define OBD_CHECK_DEV_STOPPING(obd) \
-do { \
- OBD_CHECK_DEV(obd); \
- if (!(obd)->obd_set_up) { \
- CERROR("Device %d not setup\n", \
- (obd)->obd_minor); \
- RETURN(-ENODEV); \
- } \
- \
- if (!(obd)->obd_stopping) { \
- CERROR("Device %d not stopping\n", \
- (obd)->obd_minor); \
- RETURN(-ENODEV); \
- } \
-} while (0)
-
/* ensure obd_setup and !obd_stopping */
#define OBD_CHECK_DEV_ACTIVE(obd) \
do { \
RETURN(rc);
}
-static inline int obd_precleanup(struct obd_device *obd, int flags)
+static inline int obd_precleanup(struct obd_device *obd)
{
int rc;
ENTRY;
OBD_CHECK_OP(obd, precleanup, 0);
OBD_COUNTER_INCREMENT(obd, precleanup);
- rc = OBP(obd, precleanup)(obd, flags);
+ rc = OBP(obd, precleanup)(obd);
RETURN(rc);
}
-static inline int obd_cleanup(struct obd_device *obd, int flags)
+static inline int obd_cleanup(struct obd_device *obd)
{
int rc;
ENTRY;
-
- OBD_CHECK_DEV_STOPPING(obd);
+
+ OBD_CHECK_DEV(obd);
OBD_CHECK_OP(obd, cleanup, 0);
OBD_COUNTER_INCREMENT(obd, cleanup);
- rc = OBP(obd, cleanup)(obd, flags);
+ rc = OBP(obd, cleanup)(obd);
RETURN(rc);
}
RETURN(rc);
}
-static inline int obd_disconnect(struct obd_export *exp, int flags)
+static inline int obd_disconnect(struct obd_export *exp)
{
int rc;
ENTRY;
EXP_CHECK_OP(exp, disconnect);
OBD_COUNTER_INCREMENT(exp->exp_obd, disconnect);
- rc = OBP(exp->exp_obd, disconnect)(exp, flags);
+ rc = OBP(exp->exp_obd, disconnect)(exp);
RETURN(rc);
}
#define OBD_FAIL_LDLM_CREATE_RESOURCE 0x30a
#define OBD_FAIL_LDLM_ENQUEUE_BLOCKED 0x30b
#define OBD_FAIL_LDLM_REPLY 0x30c
+#define OBD_FAIL_LDLM_RECOV_CLIENTS 0x30d
#define OBD_FAIL_OSC 0x400
#define OBD_FAIL_OSC_BRW_READ_BULK 0x401
do { \
if (OBD_FAIL_CHECK_ONCE(id)) { \
CERROR("obd_race id %x sleeping\n", (id)); \
- sleep_on(&obd_race_waitq); \
+ interruptible_sleep_on(&obd_race_waitq); \
CERROR("obd_fail_race id %x awake\n", (id)); \
} else if ((obd_fail_loc & OBD_FAIL_MASK_LOC) == \
((id) & OBD_FAIL_MASK_LOC)) { \
# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
# define BDEVNAME_DECLARE_STORAGE(foo) char foo[BDEVNAME_SIZE]
# define ll_bdevname(SB, STORAGE) __bdevname(kdev_t_to_nr(SB->s_dev), STORAGE)
-# define ll_lock_kernel lock_kernel()
-# define ll_sbdev(SB) ((SB)->s_bdev)
-void dev_set_rdonly(struct block_device *, int);
+# define ll_sbdev(SB) ((SB)->s_bdev)
+# define ll_sbdev_type struct block_device *
+ int fsync_bdev(struct block_device *);
+# define ll_sbdev_sync fsync_bdev
+# define ll_lock_kernel lock_kernel()
# else
# define BDEVNAME_DECLARE_STORAGE(foo) char __unused_##foo
-# define ll_sbdev(SB) (kdev_t_to_nr((SB)->s_dev))
# define ll_bdevname(SB,STORAGE) ((void)__unused_##STORAGE,bdevname(ll_sbdev(SB)))
+# define ll_sbdev(SB) (kdev_t_to_nr((SB)->s_dev))
+# define ll_sbdev_type kdev_t
+# define ll_sbdev_sync fsync_dev
# define ll_lock_kernel
-void dev_set_rdonly(kdev_t, int);
# endif
-void dev_clear_rdonly(int);
+
+#ifdef HAVE_OLD_DEV_SET_RDONLY
+ void dev_set_rdonly(ll_sbdev_type, int no_write);
+ void dev_clear_rdonly(int no_write);
+#else
+ void dev_set_rdonly(ll_sbdev_type);
+ void dev_clear_rdonly(ll_sbdev_type);
+#endif
+int dev_check_rdonly(ll_sbdev_type);
+#define ll_check_rdonly dev_check_rdonly
+
+static inline void ll_set_rdonly(ll_sbdev_type dev)
+{
+ CDEBUG(D_IOCTL | D_HA, "set dev %ld rdonly\n", (long)dev);
+ ll_sbdev_sync(dev);
+#ifdef HAVE_OLD_DEV_SET_RDONLY
+ dev_set_rdonly(dev, 2);
+#else
+ dev_set_rdonly(dev);
+#endif
+}
+
+static inline void ll_clear_rdonly(ll_sbdev_type dev)
+{
+ CDEBUG(D_IOCTL | D_HA, "unset dev %ld rdonly\n", (long)dev);
+ if (dev_check_rdonly(dev)) {
+ ll_sbdev_sync(dev);
+#ifdef HAVE_OLD_DEV_SET_RDONLY
+ dev_clear_rdonly(2);
+#else
+ dev_clear_rdonly(dev);
+#endif
+ }
+}
+
static inline void OBD_FAIL_WRITE(int id, struct super_block *sb)
{
BDEVNAME_DECLARE_STORAGE(tmp);
CERROR("obd_fail_loc=%x, fail write operation on %s\n",
id, ll_bdevname(sb, tmp));
- dev_set_rdonly(ll_sbdev(sb), 2);
+ ll_set_rdonly(ll_sbdev(sb));
/* We set FAIL_ONCE because we never "un-fail" a device */
obd_fail_loc |= OBD_FAILED | OBD_FAIL_ONCE;
}
--- /dev/null
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_SMP=y
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_LOCALVERSION=""
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_POSIX_MQUEUE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_YENTA=y
+CONFIG_CARDBUS=y
+# CONFIG_I82092 is not set
+CONFIG_I82365=m
+CONFIG_PD6729=m
+CONFIG_TCIC=m
+CONFIG_PCMCIA_PROBE=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_FW_LOADER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=m
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_PARTITIONS=y
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_ELAN_104NC=m
+CONFIG_MTD_SCx200_DOCFLASH=m
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_SCB2_FLASH is not set
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_DOCPROBE=m
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=m
+
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CFI_AMDSTD_RETRY=3
+# CONFIG_MTD_ICHXROM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+# CONFIG_ISAPNP is not set
+# CONFIG_PNPBIOS is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_DELKIN=y
+CONFIG_BLK_DEV_IT8212=y
+CONFIG_LBD=y
+# CONFIG_DCSSBLK is not set
+
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_GENERIC=y
+# CONFIG_HPT34X_AUTODMA is not set
+
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_PDC202XX_FORCE=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
+# SCSI low-level drivers
+#
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+# CONFIG_SCSI_AHA1542 is not set
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_SCSI_SATA=y
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_SATA_AHCI=m
+
+# CONFIG_SCSI_BUSLOGIC is not set
+CONFIG_SCSI_INITIO=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_QLOGIC_1280=m
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_SCSI_QLA2XXX=m
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_QLA6322=m
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_DPT_I2O is not set
+
+CONFIG_SCSI_LPFC=m
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+CONFIG_PCMCIA_FDOMAIN=m
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_CRYPT=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+
+#
+# Device Drivers
+#
+# CONFIG_IEEE1394_PCILYNX is not set
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+# CONFIG_IEEE1394_ETH1394 is not set
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
+# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_NETCONSOLE=m
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_NETDUMP=m
+CONFIG_DISKDUMP=m
+CONFIG_SCSI_DUMP=m
+CONFIG_SD_IOSTATS=y
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+
+
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_DECNET is not set
+CONFIG_BRIDGE=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_NAT_LOCAL=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_RAW=m
+
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_ATM=m
+CONFIG_VLAN_8021Q=m
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_IPX_INTERN is not set
+# CONFIG_ATALK is not set
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_COPS_DAYNA=y
+CONFIG_COPS_TANGENT=y
+# CONFIG_IPDDP is not set
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_ACT_POLICE is not set
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+# CONFIG_NET_CLS_ACT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+CONFIG_ETHERTAP=m
+# CONFIG_NET_SB1000 is not set
+
+#
+# ATM
+#
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_LANE=m
+CONFIG_ATM_BR2684=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+CONFIG_ATM_AMBASSADOR=m
+CONFIG_ATM_HORIZON=m
+CONFIG_ATM_FORE200E_MAYBE=m
+CONFIG_ATM_HE=m
+CONFIG_PPPOATM=m
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_IA is not set
+
+
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+# CONFIG_ATM_MPOA is not set
+# CONFIG_ATM_BR2684_IPFILTER is not set
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_ZATM_DEBUG is not set
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_FORE200E_PCA is not set
+# CONFIG_ATM_HE_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+# CONFIG_ATM_IA_DEBUG is not set
+
+
+
+
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRA is not set
+CONFIG_SMC9194=m
+CONFIG_NET_VENDOR_RACAL=y
+# CONFIG_NI52 is not set
+# CONFIG_NI65 is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_NAPI is not set
+
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_NI5010 is not set
+# CONFIG_PCMCIA_XIRTULIP is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+CONFIG_HP100=m
+# CONFIG_NET_ISA is not set
+# CONFIG_EWRK3 is not set
+CONFIG_E2100=m
+CONFIG_EEXPRESS=m
+CONFIG_EEXPRESS_PRO=m
+CONFIG_HPLAN_PLUS=m
+CONFIG_HPLAN=m
+CONFIG_LP486E=m
+CONFIG_ETH16I=m
+CONFIG_NE2000=m
+CONFIG_ZNET=m
+CONFIG_SEEQ8005=m
+CONFIG_LNE390=m
+CONFIG_NE3210=m
+CONFIG_ES3210=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+CONFIG_APRICOT=m
+CONFIG_B44=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+# CONFIG_EEPRO100_PIO is not set
+CONFIG_E100=m
+CONFIG_E100_NAPI=y
+CONFIG_FEALNX=m
+CONFIG_FORCEDETH=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_VELOCITY=m
+CONFIG_NET_POCKET=y
+# CONFIG_ATP is not set
+# CONFIG_DE600 is not set
+# CONFIG_DE620 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=m
+CONFIG_TIGON3=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+# CONFIG_SKFP is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_IPPP_FILTER=y
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+CONFIG_WAVELAN=m
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT=m
+CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IPW2100=m
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_PROMISC=y
+# CONFIG_IPW2100_LEGACY_FW_LOAD is not set
+CONFIG_IPW2200=m
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PRISM54=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_NET_WIRELESS=y
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+CONFIG_TMS380TR=m
+CONFIG_TMSPCI=m
+CONFIG_ABYSS=m
+CONFIG_IBMTR=m
+CONFIG_IBMLS=m
+CONFIG_SKISA=m
+CONFIG_PROTEON=m
+CONFIG_SMCTR=m
+CONFIG_PCMCIA_IBMTR=m
+
+
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+# CONFIG_IRDA is not set
+# CONFIG_IRDA_DEBUG is not set
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRTTY_SIR=m
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_IRPORT_SIR=m
+# CONFIG_DONGLE_OLD is not set
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+CONFIG_USB_IRDA=m
+CONFIG_NSC_FIR=m
+CONFIG_SIGMATEL_FIR=m
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+# CONFIG_VIA_FIR is not set
+
+
+
+#
+# Bluetooth support
+#
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_CMTP=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_BCSP_TXCRC=y
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_USB_BLUETOOTH_TTY=m
+
+#
+# ISDN subsystem
+#
+
+CONFIG_ISDN=m
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_DRV_AVMB1_B1ISA=m
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_T1ISA=m
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_TTY_FAX=y
+CONFIG_DE_AOC=y
+
+CONFIG_ISDN_AUDIO=y
+
+CONFIG_ISDN_DRV_HISAX=m
+CONFIG_ISDN_DRV_ICN=m
+CONFIG_ISDN_DRV_PCBIT=m
+CONFIG_ISDN_DRV_SC=m
+CONFIG_ISDN_DRV_ACT2000=m
+CONFIG_ISDN_DRV_TPAM=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+CONFIG_HISAX_EURO=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+CONFIG_HISAX_16_0=y
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_AVM_A1=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_IX1MICROR2=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_ASUSCOM=y
+CONFIG_HISAX_TELEINT=y
+CONFIG_HISAX_HFCS=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_SPORTSTER=y
+CONFIG_HISAX_MIC=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_ISURF=y
+CONFIG_HISAX_HSTSAPHIR=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_ST5481=m
+CONFIG_HISAX_HFCUSB=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_VORTEX=m
+CONFIG_GAMEPORT_FM801=m
+CONFIG_GAMEPORT_CS461x=m
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_INPORT=m
+CONFIG_MOUSE_ATIXL=y
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_IFORCE_USB=y
+# CONFIG_JOYSTICK_IFORCE_232=y
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_N_HDLC=m
+CONFIG_STALDRV=y
+# CONFIG_FTAPE is not set
+CONFIG_IBM_ASM=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_MULTIPORT=y
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_DIGI is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALLION is not set
+# CONFIG_ISTALLION is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_DEBUG_ALGO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_I2C_PARPORT is not set
+CONFIG_I2C_ALI1563=m
+# CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_ALGOPCA=m
+# CONFIG_I2C_PCA_ISA is not set
+
+
+
+#
+# I2C Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_RTC8564=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_SMSC47M1=m
+
+# CONFIG_W1 is not set
+
+#
+# Mice
+#
+CONFIG_CRASH=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_WDT=m
+# CONFIG_WDT_501 is not set
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+CONFIG_PCWATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_MIXCOMWD is not set
+# CONFIG_SCx200_WDT is not set
+# CONFIG_60XX_WDT is not set
+CONFIG_W83877F_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_SC1200_WDT=m
+CONFIG_WAFER_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_USBPCWATCHDOG=m
+
+
+CONFIG_HW_RANDOM=m
+CONFIG_NVRAM=m
+CONFIG_RTC=y
+CONFIG_DTLK=m
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+CONFIG_SONYPI=m
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_INTEL_MCH=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_MGA=m
+# CONFIG_DRM_SIS is not set
+CONFIG_DRM_I915=m
+
+
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+
+
+
+# CONFIG_MWAVE is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=8192
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA_PP is not set
+# CONFIG_VIDEO_CPIA_USB is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_DC30 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZORAN_LML33R10 is not set
+# CONFIG_VIDEO_MEYE is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_MIROPCM20_RDS is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_TYPHOON_PROC_FS=y
+# CONFIG_RADIO_ZOLTRIX is not set
+
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+CONFIG_DVB_CORE=m
+
+#
+# Supported Frontend Modules
+#
+CONFIG_DVB_STV0299=m
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_ALPS_TDLB7 is not set
+CONFIG_DVB_ALPS_TDMB7=m
+CONFIG_DVB_ATMEL_AT76C651=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_GRUNDIG_29504_491=m
+CONFIG_DVB_GRUNDIG_29504_401=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TWINHAN_DST=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_BT8XX=m
+# CONFIG_DVB_TDA1004X is not set
+CONFIG_DVB_NXT6000=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+# CONFIG_DVB_AV7110_FIRMWARE is not set
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_TTUSB_BUDGET=m
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_SKYSTAR=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BTCX=m
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_DEBUG is not set
+# CONFIG_FB_RIVA_I2C is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G450=y
+CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_ATY_XL_INIT is not set
+# CONFIG_FB_SIS is not set
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_KYRO=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_HGA_ACCEL is not set
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_TRIDENT_ACCEL is not set
+CONFIG_FB_CIRRUS=m
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_MDA_CONSOLE=m
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_BIT32_EMUL=y
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SB16_CSP=y
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_ALI5451=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS4281=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_NM256=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_FM801=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VX222=m
+CONFIG_SND_BT87X=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_PDAUDIOCF=m
+
+
+#
+# ALSA USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_VXP440 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+
+#
+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+#
+CONFIG_USB_MIDI=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_RW_DETECT=y
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_XPAD=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_HPUSBSCSI=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_STV680=m
+CONFIG_USB_SN9C102=m
+
+#
+# USB Network adaptors
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_SPEEDTOUCH=m
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_EMI62=m
+CONFIG_USB_LED=m
+CONFIG_USB_G_SERIAL=m
+
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LCD=m
+CONFIG_USB_TEST=m
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_PWC=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_MTOUCH=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ALI_M5632=y
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_EGALAX=m
+CONFIG_USB_PHIDGETSERVO=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_JFS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_SECURITY=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not seta
+# CONFIG_AFFS_FS is not set
+# uses sleepon and needs a major update
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_NAND=y
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_RXRPC is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_NLS_ASCII=y
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Tux
+#
+CONFIG_TUX=m
+CONFIG_TUX_EXTCGI=y
+# CONFIG_TUX_EXTENDED_LOG is not set
+# CONFIG_TUX_DEBUG is not set
+
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_HIGHMEM=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+# CONFIG_SECURITY_SELINUX_MLS is not set
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_LIBCRC32C=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Library routines
+#
+CONFIG_CRC32=m
+CONFIG_CRC_CCITT=m
+
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PC=y
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_ATALK is not set
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPX is not set
+# CONFIG_IPDDP is not set
+# CONFIG_IRDA is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_WD80x3 is not set
+# CONFIG_IRDA is not set
+# CONFIG_GAMEPORT is not set
+# CONFIG_DVB is not set
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SB16_CSP=y
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_R3964 is not set
+# CONFIG_TIPAR is not set
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_IFORCE_USB=y
+# CONFIG_JOYSTICK_IFORCE_232=y
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_MIROPCM20_RDS is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_TYPHOON_PROC_FS=y
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_PLIP is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_AHA1542 is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA_PP is not set
+# CONFIG_VIDEO_CPIA_USB is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_DC30 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZORAN_LML33R10 is not set
+# CONFIG_VIDEO_MEYE is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_I82092 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_ULTRA is not set
+# CONFIG_SKFP is not set
+# CONFIG_DE600 is not set
+# CONFIG_DE620 is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_AC3200 is not set
+# CONFIG_NI52 is not set
+# CONFIG_NI65 is not set
+# CONFIG_LANCE is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+# CONFIG_HAMACHI is not set
+CONFIG_HP100=m
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_ATP is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_INFTL is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_HGA_ACCEL is not set
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_TRIDENT_ACCEL is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_AUDIT=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_RAW_DRIVER=y
+# CONFIG_MTD_SCB2_FLASH is not set
+CONFIG_UID16=y
+# CONFIG_X86_PC is not set
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+CONFIG_X86_GENERICARCH=y
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+# CONFIG_HPET is not set
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_NR_CPUS=32
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_TSC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+CONFIG_X86_MCE_P4THERMAL=y
+CONFIG_TOSHIBA=m
+CONFIG_I8K=m
+CONFIG_SONYPI=m
+CONFIG_MICROCODE=m
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+CONFIG_EDD=m
+# CONFIG_NUMA is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+CONFIG_HIGHMEM64G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_HIGHMEM=y
+CONFIG_HIGHPTE=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_HAVE_DEC_LOCK=y
+# CONFIG_X86_UP_APIC is not set
+CONFIG_X86_PM_TIMER=y
+# CONFIG_X86_4G is not set
+# CONFIG_EFI is not set
+CONFIG_REGPARM=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+CONFIG_PCI_GOANY=y
+CONFIG_MDA_CONSOLE=m
+CONFIG_SYNCLINK_CS=m
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_HP100=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_CRASH=m
+CONFIG_CAPI_EICON=y
+CONFIG_I2O=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+CONFIG_I2O_CONFIG=y
+CONFIG_APM=y
+# CONFIG_APM_IGNORE_USER_SUSPEND is not set
+# CONFIG_APM_DO_ENABLE is not set
+CONFIG_APM_CPU_IDLE=y
+# CONFIG_APM_DISPLAY_BLANK is not set
+CONFIG_APM_RTC_IS_GMT=y
+# CONFIG_APM_ALLOW_INTS is not set
+# CONFIG_APM_REAL_MODE_POWER_OFF is not set
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_ACPI=y
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_TOSHIBA=m
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=2001
+CONFIG_X86_ACPI_CPUFREQ=y
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_X86_POWERNOW_K6=m
+CONFIG_X86_POWERNOW_K7=y
+CONFIG_X86_POWERNOW_K8=m
+# CONFIG_X86_GX_SUSPMOD is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+CONFIG_X86_SPEEDSTEP_ICH=y
+CONFIG_X86_SPEEDSTEP_SMI=m
+CONFIG_X86_SPEEDSTEP_LIB=y
+# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set
+CONFIG_X86_P4_CLOCKMOD=m
+CONFIG_X86_LONGRUN=y
+CONFIG_X86_LONGHAUL=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_TUX=m
+CONFIG_NVRAM=m
+CONFIG_IBM_ASM=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_SCHED_SMT=y
+# CONFIG_IRQBALANCE is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_PROC_INTF is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+# CONFIG_CPU_FREQ_24_API is not set
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_KPROBES is not set
+CONFIG_KEXEC=y
+CONFIG_NETDUMP=m
+# CONFIG_SCHEDSTATS is not set
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_BIOS=y
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_COMPAQ=m
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+CONFIG_HOTPLUG_PCI_IBM=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+# CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY is not set
+CONFIG_PM=y
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT=m
+CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IPW2100=m
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_PROMISC=y
+# CONFIG_IPW2100_LEGACY_FW_LOAD is not set
+CONFIG_IPW2200=m
+CONFIG_M686=y
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM64G=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_COMPAQ=m
+CONFIG_HOTPLUG_PCI_IBM=m
+# CONFIG_HIGHMEM64G is not set
+# CONFIG_EWRK3 is not set
+CONFIG_NR_CPUS=32
+# CONFIG_X86_PC is not set
+CONFIG_X86_GENERICARCH=y
--- /dev/null
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+# CONFIG_SMP is not set
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_LOCALVERSION=""
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_POSIX_MQUEUE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_YENTA=y
+CONFIG_CARDBUS=y
+# CONFIG_I82092 is not set
+CONFIG_I82365=m
+CONFIG_PD6729=m
+CONFIG_TCIC=m
+CONFIG_PCMCIA_PROBE=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_FW_LOADER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=m
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_PARTITIONS=y
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_ELAN_104NC=m
+CONFIG_MTD_SCx200_DOCFLASH=m
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_SCB2_FLASH is not set
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_DOCPROBE=m
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=m
+
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CFI_AMDSTD_RETRY=3
+# CONFIG_MTD_ICHXROM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+# CONFIG_ISAPNP is not set
+# CONFIG_PNPBIOS is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_DELKIN=y
+CONFIG_BLK_DEV_IT8212=y
+CONFIG_LBD=y
+# CONFIG_DCSSBLK is not set
+
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_GENERIC=y
+# CONFIG_HPT34X_AUTODMA is not set
+
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_PDC202XX_FORCE=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
+# SCSI low-level drivers
+#
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+# CONFIG_SCSI_AHA1542 is not set
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_SCSI_SATA=y
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_SATA_AHCI=m
+
+# CONFIG_SCSI_BUSLOGIC is not set
+CONFIG_SCSI_INITIO=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_QLOGIC_1280=m
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_SCSI_QLA2XXX=m
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_QLA6322=m
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_DPT_I2O is not set
+
+CONFIG_SCSI_LPFC=m
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+CONFIG_PCMCIA_FDOMAIN=m
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_CRYPT=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+
+#
+# Device Drivers
+#
+# CONFIG_IEEE1394_PCILYNX is not set
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+# CONFIG_IEEE1394_ETH1394 is not set
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
+# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_NETCONSOLE=m
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_NETDUMP=m
+CONFIG_DISKDUMP=m
+CONFIG_SCSI_DUMP=m
+CONFIG_SD_IOSTATS=y
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+
+
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_DECNET is not set
+CONFIG_BRIDGE=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_NAT_LOCAL=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_RAW=m
+
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_ATM=m
+CONFIG_VLAN_8021Q=m
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_IPX_INTERN is not set
+# CONFIG_ATALK is not set
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_COPS_DAYNA=y
+CONFIG_COPS_TANGENT=y
+# CONFIG_IPDDP is not set
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_ACT_POLICE is not set
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+# CONFIG_NET_CLS_ACT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+CONFIG_ETHERTAP=m
+# CONFIG_NET_SB1000 is not set
+
+#
+# ATM
+#
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_LANE=m
+CONFIG_ATM_BR2684=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+CONFIG_ATM_AMBASSADOR=m
+CONFIG_ATM_HORIZON=m
+CONFIG_ATM_FORE200E_MAYBE=m
+CONFIG_ATM_HE=m
+CONFIG_PPPOATM=m
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_IA is not set
+
+
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+# CONFIG_ATM_MPOA is not set
+# CONFIG_ATM_BR2684_IPFILTER is not set
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_ZATM_DEBUG is not set
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_FORE200E_PCA is not set
+# CONFIG_ATM_HE_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+# CONFIG_ATM_IA_DEBUG is not set
+
+
+
+
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRA is not set
+CONFIG_SMC9194=m
+CONFIG_NET_VENDOR_RACAL=y
+# CONFIG_NI52 is not set
+# CONFIG_NI65 is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_NAPI is not set
+
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_NI5010 is not set
+# CONFIG_PCMCIA_XIRTULIP is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+CONFIG_HP100=m
+# CONFIG_NET_ISA is not set
+CONFIG_EWRK3=m
+CONFIG_E2100=m
+CONFIG_EEXPRESS=m
+CONFIG_EEXPRESS_PRO=m
+CONFIG_HPLAN_PLUS=m
+CONFIG_HPLAN=m
+CONFIG_LP486E=m
+CONFIG_ETH16I=m
+CONFIG_NE2000=m
+CONFIG_ZNET=m
+CONFIG_SEEQ8005=m
+CONFIG_LNE390=m
+CONFIG_NE3210=m
+CONFIG_ES3210=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+CONFIG_APRICOT=m
+CONFIG_B44=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+# CONFIG_EEPRO100_PIO is not set
+CONFIG_E100=m
+CONFIG_E100_NAPI=y
+CONFIG_FEALNX=m
+CONFIG_FORCEDETH=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_VELOCITY=m
+CONFIG_NET_POCKET=y
+# CONFIG_ATP is not set
+# CONFIG_DE600 is not set
+# CONFIG_DE620 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=m
+CONFIG_TIGON3=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+# CONFIG_SKFP is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_IPPP_FILTER=y
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+CONFIG_WAVELAN=m
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT=m
+CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IPW2100=m
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_PROMISC=y
+# CONFIG_IPW2100_LEGACY_FW_LOAD is not set
+CONFIG_IPW2200=m
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PRISM54=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_NET_WIRELESS=y
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+CONFIG_TMS380TR=m
+CONFIG_TMSPCI=m
+CONFIG_ABYSS=m
+CONFIG_IBMTR=m
+CONFIG_IBMLS=m
+CONFIG_SKISA=m
+CONFIG_PROTEON=m
+CONFIG_SMCTR=m
+CONFIG_PCMCIA_IBMTR=m
+
+
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+# CONFIG_IRDA is not set
+# CONFIG_IRDA_DEBUG is not set
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRTTY_SIR=m
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_IRPORT_SIR=m
+# CONFIG_DONGLE_OLD is not set
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+CONFIG_USB_IRDA=m
+CONFIG_NSC_FIR=m
+CONFIG_SIGMATEL_FIR=m
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+# CONFIG_VIA_FIR is not set
+
+
+
+#
+# Bluetooth support
+#
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_CMTP=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_BCSP_TXCRC=y
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_USB_BLUETOOTH_TTY=m
+
+#
+# ISDN subsystem
+#
+
+CONFIG_ISDN=m
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_DRV_AVMB1_B1ISA=m
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_T1ISA=m
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_TTY_FAX=y
+CONFIG_DE_AOC=y
+
+CONFIG_ISDN_AUDIO=y
+
+CONFIG_ISDN_DRV_HISAX=m
+CONFIG_ISDN_DRV_ICN=m
+CONFIG_ISDN_DRV_PCBIT=m
+CONFIG_ISDN_DRV_SC=m
+CONFIG_ISDN_DRV_ACT2000=m
+CONFIG_ISDN_DRV_TPAM=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+CONFIG_HISAX_EURO=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+CONFIG_HISAX_16_0=y
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_AVM_A1=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_IX1MICROR2=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_ASUSCOM=y
+CONFIG_HISAX_TELEINT=y
+CONFIG_HISAX_HFCS=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_SPORTSTER=y
+CONFIG_HISAX_MIC=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_ISURF=y
+CONFIG_HISAX_HSTSAPHIR=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_ST5481=m
+CONFIG_HISAX_HFCUSB=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_VORTEX=m
+CONFIG_GAMEPORT_FM801=m
+CONFIG_GAMEPORT_CS461x=m
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_INPORT=m
+CONFIG_MOUSE_ATIXL=y
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_IFORCE_USB=y
+# CONFIG_JOYSTICK_IFORCE_232=y
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_N_HDLC=m
+CONFIG_STALDRV=y
+# CONFIG_FTAPE is not set
+CONFIG_IBM_ASM=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_MULTIPORT=y
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_DIGI is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALLION is not set
+# CONFIG_ISTALLION is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_DEBUG_ALGO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_I2C_PARPORT is not set
+CONFIG_I2C_ALI1563=m
+# CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_ALGOPCA=m
+# CONFIG_I2C_PCA_ISA is not set
+
+
+
+#
+# I2C Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_RTC8564=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_SMSC47M1=m
+
+# CONFIG_W1 is not set
+
+#
+# Mice
+#
+CONFIG_CRASH=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_WDT=m
+# CONFIG_WDT_501 is not set
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+CONFIG_PCWATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_MIXCOMWD is not set
+# CONFIG_SCx200_WDT is not set
+# CONFIG_60XX_WDT is not set
+CONFIG_W83877F_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_SC1200_WDT=m
+CONFIG_WAFER_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_USBPCWATCHDOG=m
+
+
+CONFIG_HW_RANDOM=m
+CONFIG_NVRAM=m
+CONFIG_RTC=y
+CONFIG_DTLK=m
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+CONFIG_SONYPI=m
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_INTEL_MCH=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_MGA=m
+# CONFIG_DRM_SIS is not set
+CONFIG_DRM_I915=m
+
+
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+
+
+
+# CONFIG_MWAVE is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=8192
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA_PP is not set
+# CONFIG_VIDEO_CPIA_USB is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_DC30 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZORAN_LML33R10 is not set
+# CONFIG_VIDEO_MEYE is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_MIROPCM20_RDS is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_TYPHOON_PROC_FS=y
+# CONFIG_RADIO_ZOLTRIX is not set
+
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+CONFIG_DVB_CORE=m
+
+#
+# Supported Frontend Modules
+#
+CONFIG_DVB_STV0299=m
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_ALPS_TDLB7 is not set
+CONFIG_DVB_ALPS_TDMB7=m
+CONFIG_DVB_ATMEL_AT76C651=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_GRUNDIG_29504_491=m
+CONFIG_DVB_GRUNDIG_29504_401=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TWINHAN_DST=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_BT8XX=m
+# CONFIG_DVB_TDA1004X is not set
+CONFIG_DVB_NXT6000=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+# CONFIG_DVB_AV7110_FIRMWARE is not set
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_TTUSB_BUDGET=m
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_SKYSTAR=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BTCX=m
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_DEBUG is not set
+# CONFIG_FB_RIVA_I2C is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G450=y
+CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_ATY_XL_INIT is not set
+# CONFIG_FB_SIS is not set
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_KYRO=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_HGA_ACCEL is not set
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_TRIDENT_ACCEL is not set
+CONFIG_FB_CIRRUS=m
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_MDA_CONSOLE=m
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_BIT32_EMUL=y
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SB16_CSP=y
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_ALI5451=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS4281=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_NM256=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_FM801=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VX222=m
+CONFIG_SND_BT87X=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_PDAUDIOCF=m
+
+
+#
+# ALSA USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_VXP440 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+
+#
+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+#
+CONFIG_USB_MIDI=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_RW_DETECT=y
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_XPAD=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_HPUSBSCSI=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_STV680=m
+CONFIG_USB_SN9C102=m
+
+#
+# USB Network adaptors
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_SPEEDTOUCH=m
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_EMI62=m
+CONFIG_USB_LED=m
+CONFIG_USB_G_SERIAL=m
+
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LCD=m
+CONFIG_USB_TEST=m
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_PWC=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_MTOUCH=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ALI_M5632=y
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_EGALAX=m
+CONFIG_USB_PHIDGETSERVO=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_JFS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_SECURITY=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not seta
+# CONFIG_AFFS_FS is not set
+# uses sleepon and needs a major update
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_NAND=y
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_RXRPC is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_NLS_ASCII=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_OPROFILE is not set
+
+#
+# Tux
+#
+CONFIG_TUX=m
+CONFIG_TUX_EXTCGI=y
+# CONFIG_TUX_EXTENDED_LOG is not set
+# CONFIG_TUX_DEBUG is not set
+
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_HIGHMEM=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+# CONFIG_SECURITY_SELINUX_MLS is not set
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_LIBCRC32C=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Library routines
+#
+CONFIG_CRC32=m
+CONFIG_CRC_CCITT=m
+
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PC=y
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_ATALK is not set
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPX is not set
+# CONFIG_IPDDP is not set
+# CONFIG_IRDA is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_WD80x3 is not set
+# CONFIG_IRDA is not set
+# CONFIG_GAMEPORT is not set
+# CONFIG_DVB is not set
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SB16_CSP=y
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_R3964 is not set
+# CONFIG_TIPAR is not set
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_IFORCE_USB=y
+# CONFIG_JOYSTICK_IFORCE_232=y
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_MIROPCM20_RDS is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_TYPHOON_PROC_FS=y
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_PLIP is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_AHA1542 is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA_PP is not set
+# CONFIG_VIDEO_CPIA_USB is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_DC30 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZORAN_LML33R10 is not set
+# CONFIG_VIDEO_MEYE is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_I82092 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_ULTRA is not set
+# CONFIG_SKFP is not set
+# CONFIG_DE600 is not set
+# CONFIG_DE620 is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_AC3200 is not set
+# CONFIG_NI52 is not set
+# CONFIG_NI65 is not set
+# CONFIG_LANCE is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+# CONFIG_HAMACHI is not set
+CONFIG_HP100=m
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_ATP is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_INFTL is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_HGA_ACCEL is not set
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_TRIDENT_ACCEL is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_AUDIT=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_RAW_DRIVER=y
+# CONFIG_MTD_SCB2_FLASH is not set
+CONFIG_UID16=y
+CONFIG_X86_PC=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+# CONFIG_HPET is not set
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_NR_CPUS=8
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_TSC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+CONFIG_X86_MCE_P4THERMAL=y
+CONFIG_TOSHIBA=m
+CONFIG_I8K=m
+CONFIG_SONYPI=m
+CONFIG_MICROCODE=m
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+CONFIG_EDD=m
+# CONFIG_NUMA is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_HIGHMEM=y
+CONFIG_HIGHPTE=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_HAVE_DEC_LOCK=y
+# CONFIG_X86_UP_APIC is not set
+CONFIG_X86_PM_TIMER=y
+# CONFIG_X86_4G is not set
+# CONFIG_EFI is not set
+CONFIG_REGPARM=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+CONFIG_PCI_GOANY=y
+CONFIG_MDA_CONSOLE=m
+CONFIG_SYNCLINK_CS=m
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_HP100=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_CRASH=m
+CONFIG_CAPI_EICON=y
+CONFIG_I2O=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+CONFIG_I2O_CONFIG=y
+CONFIG_APM=y
+# CONFIG_APM_IGNORE_USER_SUSPEND is not set
+# CONFIG_APM_DO_ENABLE is not set
+CONFIG_APM_CPU_IDLE=y
+# CONFIG_APM_DISPLAY_BLANK is not set
+CONFIG_APM_RTC_IS_GMT=y
+# CONFIG_APM_ALLOW_INTS is not set
+# CONFIG_APM_REAL_MODE_POWER_OFF is not set
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_ACPI=y
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_TOSHIBA=m
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=2001
+CONFIG_X86_ACPI_CPUFREQ=y
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_X86_POWERNOW_K6=m
+CONFIG_X86_POWERNOW_K7=y
+CONFIG_X86_POWERNOW_K8=m
+# CONFIG_X86_GX_SUSPMOD is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+CONFIG_X86_SPEEDSTEP_ICH=y
+CONFIG_X86_SPEEDSTEP_SMI=m
+CONFIG_X86_SPEEDSTEP_LIB=y
+# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set
+CONFIG_X86_P4_CLOCKMOD=m
+CONFIG_X86_LONGRUN=y
+CONFIG_X86_LONGHAUL=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_TUX=m
+CONFIG_NVRAM=m
+CONFIG_IBM_ASM=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_SCHED_SMT=y
+# CONFIG_IRQBALANCE is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_PROC_INTF is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+# CONFIG_CPU_FREQ_24_API is not set
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_KPROBES is not set
+CONFIG_KEXEC=y
+CONFIG_NETDUMP=m
+# CONFIG_SCHEDSTATS is not set
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_BIOS=y
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_COMPAQ=m
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+CONFIG_HOTPLUG_PCI_IBM=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+# CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY is not set
+CONFIG_PM=y
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT=m
+CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IPW2100=m
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_PROMISC=y
+# CONFIG_IPW2100_LEGACY_FW_LOAD is not set
+CONFIG_IPW2200=m
+CONFIG_M686=y
+# CONFIG_NOHIGHMEM is not set
+# CONFIG_SMP is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+# CONFIG_PROFILING is not set
+# CONFIG_OPROFILE is not set
--- /dev/null
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-5.0.3.EL_lustre-b1_4_rhel4.200503031449smp
+# Thu Mar 3 14:52:42 2005
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_NUMA=y
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_FORCE_MAX_ZONEORDER=18
+CONFIG_SMP=y
+CONFIG_NR_CPUS=64
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HAVE_DEC_LOCK=y
+# CONFIG_IA32_SUPPORT is not set
+CONFIG_IA64_MCA_RECOVERY=m
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=2001
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_YENTA=m
+CONFIG_CARDBUS=y
+CONFIG_PD6729=m
+# CONFIG_I82092 is not set
+CONFIG_TCIC=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_SX8=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_DISKDUMP=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_DELKIN=m
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT8212=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_PDC202XX_FORCE=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SGIIOC4=m
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_SCSI_DUMP=m
+CONFIG_SD_IOSTATS=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_SCSI_SATA=y
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA2XXX=m
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_QLA6322=m
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_LOCAL=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+# CONFIG_ATM_MPOA is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_BCSP_TXCRC=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+# CONFIG_TUX_EXTENDED_LOG is not set
+# CONFIG_TUX_DEBUG is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+CONFIG_ETHERTAP=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+# CONFIG_EEPRO100_PIO is not set
+CONFIG_E100=m
+CONFIG_E100_NAPI=y
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=m
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+CONFIG_TMS380TR=m
+CONFIG_TMSPCI=m
+CONFIG_ABYSS=m
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IEEE80211 is not set
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+# CONFIG_SKFP is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_SLIP is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETDUMP=m
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+CONFIG_HISAX_HFCUSB=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+CONFIG_ISDN_DRV_TPAM=m
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+CONFIG_N_HDLC=m
+CONFIG_STALDRV=y
+CONFIG_SGI_SNSC=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_NR_UARTS=20
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_MULTIPORT=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_SGI_L1_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_I8XX_TCO=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+CONFIG_DTLK=m
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_I460=y
+CONFIG_AGP_HP_ZX1=y
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+# CONFIG_DRM_SIS is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_RAW_DRIVER=y
+# CONFIG_HPET is not set
+CONFIG_MAX_RAW_DEVS=8192
+# CONFIG_MMTIMER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_RTC8564=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+CONFIG_FB_KYRO=m
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS4281=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VX222=m
+
+#
+# ALSA USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+
+#
+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+#
+CONFIG_USB_MIDI=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_MTOUCH=m
+CONFIG_USB_EGALAX=m
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_HPUSBSCSI=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_PWC=m
+
+#
+# USB Network adaptors
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_TEST=m
+
+#
+# USB ATM/DSL drivers
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+
+#
+# HP Simulator drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+# CONFIG_HP_SIMSCSI is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+# CONFIG_SECURITY_SELINUX_MLS is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
--- /dev/null
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-5.0.3.EL_lustre-b1_4_rhel4.200503031449smp
+# Thu Mar 3 14:52:42 2005
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_NUMA=y
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_FORCE_MAX_ZONEORDER=18
+CONFIG_SMP=y
+CONFIG_NR_CPUS=64
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HAVE_DEC_LOCK=y
+# CONFIG_IA32_SUPPORT is not set
+CONFIG_IA64_MCA_RECOVERY=m
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=2001
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_YENTA=m
+CONFIG_CARDBUS=y
+CONFIG_PD6729=m
+# CONFIG_I82092 is not set
+CONFIG_TCIC=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_SX8=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_DISKDUMP=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_DELKIN=m
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT8212=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_PDC202XX_FORCE=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SGIIOC4=m
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_SCSI_DUMP=m
+CONFIG_SD_IOSTATS=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_SCSI_SATA=y
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA2XXX=m
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_QLA6322=m
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_LOCAL=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+# CONFIG_ATM_MPOA is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_BCSP_TXCRC=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+# CONFIG_TUX_EXTENDED_LOG is not set
+# CONFIG_TUX_DEBUG is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+CONFIG_ETHERTAP=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+# CONFIG_EEPRO100_PIO is not set
+CONFIG_E100=m
+CONFIG_E100_NAPI=y
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=m
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+CONFIG_TMS380TR=m
+CONFIG_TMSPCI=m
+CONFIG_ABYSS=m
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IEEE80211 is not set
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+# CONFIG_SKFP is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_SLIP is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETDUMP=m
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+CONFIG_HISAX_HFCUSB=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+CONFIG_ISDN_DRV_TPAM=m
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+CONFIG_N_HDLC=m
+CONFIG_STALDRV=y
+CONFIG_SGI_SNSC=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_NR_UARTS=20
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_MULTIPORT=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_SGI_L1_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_I8XX_TCO=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+CONFIG_DTLK=m
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_I460=y
+CONFIG_AGP_HP_ZX1=y
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+# CONFIG_DRM_SIS is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_RAW_DRIVER=y
+# CONFIG_HPET is not set
+CONFIG_MAX_RAW_DEVS=8192
+# CONFIG_MMTIMER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_RTC8564=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+CONFIG_FB_KYRO=m
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS4281=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VX222=m
+
+#
+# ALSA USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+
+#
+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+#
+CONFIG_USB_MIDI=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_MTOUCH=m
+CONFIG_USB_EGALAX=m
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_HPUSBSCSI=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_PWC=m
+
+#
+# USB Network adaptors
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_TEST=m
+
+#
+# USB ATM/DSL drivers
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+
+#
+# HP Simulator drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+# CONFIG_HP_SIMSCSI is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+# CONFIG_SECURITY_SELINUX_MLS is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
--- /dev/null
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_SMP=y
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_LOCALVERSION=""
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_POSIX_MQUEUE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_YENTA=y
+CONFIG_CARDBUS=y
+# CONFIG_I82092 is not set
+CONFIG_I82365=m
+CONFIG_PD6729=m
+CONFIG_TCIC=m
+CONFIG_PCMCIA_PROBE=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_FW_LOADER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=m
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_PARTITIONS=y
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_ELAN_104NC=m
+CONFIG_MTD_SCx200_DOCFLASH=m
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_SCB2_FLASH is not set
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_DOCPROBE=m
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=m
+
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CFI_AMDSTD_RETRY=3
+# CONFIG_MTD_ICHXROM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+# CONFIG_ISAPNP is not set
+# CONFIG_PNPBIOS is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_DELKIN=y
+CONFIG_BLK_DEV_IT8212=y
+CONFIG_LBD=y
+# CONFIG_DCSSBLK is not set
+
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_GENERIC=y
+# CONFIG_HPT34X_AUTODMA is not set
+
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_PDC202XX_FORCE=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
+# SCSI low-level drivers
+#
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+# CONFIG_SCSI_AHA1542 is not set
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_SCSI_SATA=y
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_SATA_AHCI=m
+
+# CONFIG_SCSI_BUSLOGIC is not set
+CONFIG_SCSI_INITIO=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_QLOGIC_1280=m
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_SCSI_QLA2XXX=m
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_QLA6322=m
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_DPT_I2O is not set
+
+CONFIG_SCSI_LPFC=m
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_CRYPT=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+
+#
+# Device Drivers
+#
+# CONFIG_IEEE1394_PCILYNX is not set
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+# CONFIG_IEEE1394_ETH1394 is not set
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
+# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_NETCONSOLE=m
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_NETDUMP=m
+CONFIG_DISKDUMP=m
+CONFIG_SCSI_DUMP=m
+CONFIG_SD_IOSTATS=y
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+
+
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_DECNET is not set
+CONFIG_BRIDGE=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_NAT_LOCAL=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_RAW=m
+
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_ATM=m
+CONFIG_VLAN_8021Q=m
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_IPX_INTERN is not set
+# CONFIG_ATALK is not set
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_COPS_DAYNA=y
+CONFIG_COPS_TANGENT=y
+# CONFIG_IPDDP is not set
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_ACT_POLICE is not set
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+# CONFIG_NET_CLS_ACT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+CONFIG_ETHERTAP=m
+# CONFIG_NET_SB1000 is not set
+
+#
+# ATM
+#
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_LANE=m
+CONFIG_ATM_BR2684=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+CONFIG_ATM_AMBASSADOR=m
+CONFIG_ATM_HORIZON=m
+CONFIG_ATM_FORE200E_MAYBE=m
+CONFIG_ATM_HE=m
+CONFIG_PPPOATM=m
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_IA is not set
+
+
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+# CONFIG_ATM_MPOA is not set
+# CONFIG_ATM_BR2684_IPFILTER is not set
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_ZATM_DEBUG is not set
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_FORE200E_PCA is not set
+# CONFIG_ATM_HE_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+# CONFIG_ATM_IA_DEBUG is not set
+
+
+
+
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRA is not set
+CONFIG_SMC9194=m
+CONFIG_NET_VENDOR_RACAL=y
+# CONFIG_NI52 is not set
+# CONFIG_NI65 is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_NAPI is not set
+
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_NI5010 is not set
+# CONFIG_PCMCIA_XIRTULIP is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_EWRK3=m
+CONFIG_E2100=m
+CONFIG_EEXPRESS=m
+CONFIG_EEXPRESS_PRO=m
+CONFIG_HPLAN_PLUS=m
+CONFIG_HPLAN=m
+CONFIG_LP486E=m
+CONFIG_ETH16I=m
+CONFIG_NE2000=m
+CONFIG_ZNET=m
+CONFIG_SEEQ8005=m
+CONFIG_LNE390=m
+CONFIG_NE3210=m
+CONFIG_ES3210=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+CONFIG_APRICOT=m
+CONFIG_B44=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+# CONFIG_EEPRO100_PIO is not set
+CONFIG_E100=m
+CONFIG_E100_NAPI=y
+CONFIG_FEALNX=m
+CONFIG_FORCEDETH=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_VELOCITY=m
+CONFIG_NET_POCKET=y
+# CONFIG_ATP is not set
+# CONFIG_DE600 is not set
+# CONFIG_DE620 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=m
+CONFIG_TIGON3=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+# CONFIG_SKFP is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_IPPP_FILTER=y
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+CONFIG_WAVELAN=m
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT=m
+CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IPW2100=m
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_PROMISC=y
+# CONFIG_IPW2100_LEGACY_FW_LOAD is not set
+CONFIG_IPW2200=m
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PRISM54=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_NET_WIRELESS=y
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+CONFIG_TMS380TR=m
+CONFIG_TMSPCI=m
+CONFIG_ABYSS=m
+CONFIG_IBMTR=m
+CONFIG_IBMLS=m
+CONFIG_SKISA=m
+CONFIG_PROTEON=m
+CONFIG_SMCTR=m
+CONFIG_PCMCIA_IBMTR=m
+
+
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+# CONFIG_IRDA is not set
+# CONFIG_IRDA_DEBUG is not set
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRTTY_SIR=m
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_IRPORT_SIR=m
+# CONFIG_DONGLE_OLD is not set
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+CONFIG_USB_IRDA=m
+CONFIG_NSC_FIR=m
+CONFIG_SIGMATEL_FIR=m
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+# CONFIG_VIA_FIR is not set
+
+
+
+#
+# Bluetooth support
+#
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_CMTP=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_BCSP_TXCRC=y
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_USB_BLUETOOTH_TTY=m
+
+#
+# ISDN subsystem
+#
+
+CONFIG_ISDN=m
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_DRV_AVMB1_B1ISA=m
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_T1ISA=m
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_TTY_FAX=y
+CONFIG_DE_AOC=y
+
+CONFIG_ISDN_AUDIO=y
+
+CONFIG_ISDN_DRV_HISAX=m
+CONFIG_ISDN_DRV_ICN=m
+CONFIG_ISDN_DRV_PCBIT=m
+CONFIG_ISDN_DRV_SC=m
+CONFIG_ISDN_DRV_ACT2000=m
+CONFIG_ISDN_DRV_TPAM=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+CONFIG_HISAX_EURO=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+CONFIG_HISAX_16_0=y
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_AVM_A1=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_IX1MICROR2=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_ASUSCOM=y
+CONFIG_HISAX_TELEINT=y
+CONFIG_HISAX_HFCS=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_SPORTSTER=y
+CONFIG_HISAX_MIC=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_ISURF=y
+CONFIG_HISAX_HSTSAPHIR=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_ST5481=m
+CONFIG_HISAX_HFCUSB=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_VORTEX=m
+CONFIG_GAMEPORT_FM801=m
+CONFIG_GAMEPORT_CS461x=m
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_INPORT=m
+CONFIG_MOUSE_ATIXL=y
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_IFORCE_USB=y
+# CONFIG_JOYSTICK_IFORCE_232=y
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+CONFIG_N_HDLC=m
+CONFIG_STALDRV=y
+# CONFIG_FTAPE is not set
+# CONFIG_IBM_ASM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_MULTIPORT=y
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_DIGI is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALLION is not set
+# CONFIG_ISTALLION is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_DEBUG_ALGO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_I2C_PARPORT is not set
+CONFIG_I2C_ALI1563=m
+# CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_ALGOPCA=m
+# CONFIG_I2C_PCA_ISA is not set
+
+
+
+#
+# I2C Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_RTC8564=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_SMSC47M1=m
+
+# CONFIG_W1 is not set
+
+#
+# Mice
+#
+CONFIG_CRASH=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_WDT=m
+# CONFIG_WDT_501 is not set
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+CONFIG_PCWATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_MIXCOMWD is not set
+# CONFIG_SCx200_WDT is not set
+# CONFIG_60XX_WDT is not set
+CONFIG_W83877F_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_SC1200_WDT=m
+CONFIG_WAFER_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_USBPCWATCHDOG=m
+
+
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+CONFIG_DTLK=m
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_INTEL_MCH=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_MGA=m
+# CONFIG_DRM_SIS is not set
+CONFIG_DRM_I915=m
+
+
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+
+
+
+# CONFIG_MWAVE is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=8192
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA_PP is not set
+# CONFIG_VIDEO_CPIA_USB is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_DC30 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZORAN_LML33R10 is not set
+# CONFIG_VIDEO_MEYE is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_MIROPCM20_RDS is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_TYPHOON_PROC_FS=y
+# CONFIG_RADIO_ZOLTRIX is not set
+
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+CONFIG_DVB_CORE=m
+
+#
+# Supported Frontend Modules
+#
+CONFIG_DVB_STV0299=m
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_ALPS_TDLB7 is not set
+CONFIG_DVB_ALPS_TDMB7=m
+CONFIG_DVB_ATMEL_AT76C651=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_GRUNDIG_29504_491=m
+CONFIG_DVB_GRUNDIG_29504_401=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TWINHAN_DST=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_BT8XX=m
+# CONFIG_DVB_TDA1004X is not set
+CONFIG_DVB_NXT6000=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+# CONFIG_DVB_AV7110_FIRMWARE is not set
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_TTUSB_BUDGET=m
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_SKYSTAR=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BTCX=m
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_DEBUG is not set
+# CONFIG_FB_RIVA_I2C is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G450=y
+CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_ATY_XL_INIT is not set
+# CONFIG_FB_SIS is not set
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_KYRO=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_HGA_ACCEL is not set
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_TRIDENT_ACCEL is not set
+CONFIG_FB_CIRRUS=m
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_BIT32_EMUL=y
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SB16_CSP=y
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_ALI5451=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS4281=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_NM256=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_FM801=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VX222=m
+CONFIG_SND_BT87X=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_PDAUDIOCF=m
+
+
+#
+# ALSA USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_VXP440 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+
+#
+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+#
+CONFIG_USB_MIDI=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_RW_DETECT=y
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_XPAD=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_HPUSBSCSI=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_STV680=m
+CONFIG_USB_SN9C102=m
+
+#
+# USB Network adaptors
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_SPEEDTOUCH=m
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_EMI62=m
+CONFIG_USB_LED=m
+CONFIG_USB_G_SERIAL=m
+
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LCD=m
+CONFIG_USB_TEST=m
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_PWC=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_MTOUCH=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ALI_M5632=y
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_EGALAX=m
+CONFIG_USB_PHIDGETSERVO=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_JFS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_SECURITY=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not seta
+# CONFIG_AFFS_FS is not set
+# uses sleepon and needs a major update
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_NAND=y
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_RXRPC is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_NLS_ASCII=y
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Tux
+#
+CONFIG_TUX=m
+CONFIG_TUX_EXTCGI=y
+# CONFIG_TUX_EXTENDED_LOG is not set
+# CONFIG_TUX_DEBUG is not set
+
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_HIGHMEM=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+# CONFIG_SECURITY_SELINUX_MLS is not set
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_LIBCRC32C=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Library routines
+#
+CONFIG_CRC32=m
+CONFIG_CRC_CCITT=m
+
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PC=y
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_ATALK is not set
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPX is not set
+# CONFIG_IPDDP is not set
+# CONFIG_IRDA is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_WD80x3 is not set
+# CONFIG_IRDA is not set
+# CONFIG_GAMEPORT is not set
+# CONFIG_DVB is not set
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SB16_CSP=y
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_R3964 is not set
+# CONFIG_TIPAR is not set
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_IFORCE_USB=y
+# CONFIG_JOYSTICK_IFORCE_232=y
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_MIROPCM20_RDS is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_TYPHOON_PROC_FS=y
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_PLIP is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA_PP is not set
+# CONFIG_VIDEO_CPIA_USB is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_DC30 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZORAN_LML33R10 is not set
+# CONFIG_VIDEO_MEYE is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_I82092 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_ULTRA is not set
+# CONFIG_SKFP is not set
+# CONFIG_DE600 is not set
+# CONFIG_DE620 is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_AC3200 is not set
+# CONFIG_NI52 is not set
+# CONFIG_NI65 is not set
+# CONFIG_LANCE is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_HP100 is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_ATP is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_INFTL is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_HGA_ACCEL is not set
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_TRIDENT_ACCEL is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_AUDIT=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_RAW_DRIVER=y
+# CONFIG_MTD_SCB2_FLASH is not set
+CONFIG_UID16=y
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_MTRR=y
+CONFIG_NUMA=y
+CONFIG_K8_NUMA=y
+CONFIG_NR_CPUS=8
+CONFIG_GART_IOMMU=y
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_INIT_DEBUG=y
+# CONFIG_IOMMU_DEBUG is not set
+# CONFIG_CHECKING is not set
+CONFIG_MICROCODE=m
+CONFIG_SWIOTLB=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_I2O=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+CONFIG_I2O_CONFIG=y
+CONFIG_TUX=m
+# CONFIG_UNORDERED_IO is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+CONFIG_X86_ACPI_CPUFREQ=y
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_SCHED_SMT=y
+# CONFIG_SOFTWARE_SUSPEND is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_PROC_INTF is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+# CONFIG_CPU_FREQ_24_API is not set
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_ACPI=y
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_TOSHIBA=m
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=2001
+# CONFIG_SCHEDSTATS is not set
+CONFIG_EDD=m
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_KEXEC=y
+CONFIG_NETDUMP=m
+CONFIG_CRASH=m
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_COMPAQ=m
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+CONFIG_HOTPLUG_PCI_IBM=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+# CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY is not set
+# CONFIG_HPET is not set
+CONFIG_PM=y
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT=m
+CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IPW2100=m
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_PROMISC=y
+# CONFIG_IPW2100_LEGACY_FW_LOAD is not set
+CONFIG_IPW2200=m
--- /dev/null
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+# CONFIG_SMP is not set
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_LOCALVERSION=""
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_POSIX_MQUEUE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_YENTA=y
+CONFIG_CARDBUS=y
+# CONFIG_I82092 is not set
+CONFIG_I82365=m
+CONFIG_PD6729=m
+CONFIG_TCIC=m
+CONFIG_PCMCIA_PROBE=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_FW_LOADER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=m
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_PARTITIONS=y
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_ELAN_104NC=m
+CONFIG_MTD_SCx200_DOCFLASH=m
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_SCB2_FLASH is not set
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_DOCPROBE=m
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=m
+
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CFI_AMDSTD_RETRY=3
+# CONFIG_MTD_ICHXROM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+# CONFIG_ISAPNP is not set
+# CONFIG_PNPBIOS is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_DELKIN=y
+CONFIG_BLK_DEV_IT8212=y
+CONFIG_LBD=y
+# CONFIG_DCSSBLK is not set
+
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_GENERIC=y
+# CONFIG_HPT34X_AUTODMA is not set
+
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+CONFIG_BLK_DEV_CY82C693=y
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_PDC202XX_FORCE=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+CONFIG_BLK_DEV_SLC90E66=y
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
+# SCSI low-level drivers
+#
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+# CONFIG_SCSI_AHA1542 is not set
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_SCSI_SATA=y
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_SATA_AHCI=m
+
+# CONFIG_SCSI_BUSLOGIC is not set
+CONFIG_SCSI_INITIO=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_QLOGIC_1280=m
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_SCSI_QLA2XXX=m
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_QLA6322=m
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_DPT_I2O is not set
+
+CONFIG_SCSI_LPFC=m
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_CRYPT=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+
+#
+# Device Drivers
+#
+# CONFIG_IEEE1394_PCILYNX is not set
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+# CONFIG_IEEE1394_ETH1394 is not set
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
+# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_NETCONSOLE=m
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_NETDUMP=m
+CONFIG_DISKDUMP=m
+CONFIG_SCSI_DUMP=m
+CONFIG_SD_IOSTATS=y
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+
+
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_DECNET is not set
+CONFIG_BRIDGE=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_NAT_LOCAL=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_RAW=m
+
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_ATM=m
+CONFIG_VLAN_8021Q=m
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_IPX_INTERN is not set
+# CONFIG_ATALK is not set
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_COPS_DAYNA=y
+CONFIG_COPS_TANGENT=y
+# CONFIG_IPDDP is not set
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_ACT_POLICE is not set
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+# CONFIG_NET_CLS_ACT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+CONFIG_ETHERTAP=m
+# CONFIG_NET_SB1000 is not set
+
+#
+# ATM
+#
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_LANE=m
+CONFIG_ATM_BR2684=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+CONFIG_ATM_AMBASSADOR=m
+CONFIG_ATM_HORIZON=m
+CONFIG_ATM_FORE200E_MAYBE=m
+CONFIG_ATM_HE=m
+CONFIG_PPPOATM=m
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_IA is not set
+
+
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+# CONFIG_ATM_MPOA is not set
+# CONFIG_ATM_BR2684_IPFILTER is not set
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_ZATM_DEBUG is not set
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_FORE200E_PCA is not set
+# CONFIG_ATM_HE_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+# CONFIG_ATM_IA_DEBUG is not set
+
+
+
+
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRA is not set
+CONFIG_SMC9194=m
+CONFIG_NET_VENDOR_RACAL=y
+# CONFIG_NI52 is not set
+# CONFIG_NI65 is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_NAPI is not set
+
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_NI5010 is not set
+# CONFIG_PCMCIA_XIRTULIP is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_EWRK3=m
+CONFIG_E2100=m
+CONFIG_EEXPRESS=m
+CONFIG_EEXPRESS_PRO=m
+CONFIG_HPLAN_PLUS=m
+CONFIG_HPLAN=m
+CONFIG_LP486E=m
+CONFIG_ETH16I=m
+CONFIG_NE2000=m
+CONFIG_ZNET=m
+CONFIG_SEEQ8005=m
+CONFIG_LNE390=m
+CONFIG_NE3210=m
+CONFIG_ES3210=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+CONFIG_APRICOT=m
+CONFIG_B44=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+# CONFIG_EEPRO100_PIO is not set
+CONFIG_E100=m
+CONFIG_E100_NAPI=y
+CONFIG_FEALNX=m
+CONFIG_FORCEDETH=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_VELOCITY=m
+CONFIG_NET_POCKET=y
+# CONFIG_ATP is not set
+# CONFIG_DE600 is not set
+# CONFIG_DE620 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+CONFIG_NS83820=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=m
+CONFIG_TIGON3=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+# CONFIG_SKFP is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_IPPP_FILTER=y
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+CONFIG_WAVELAN=m
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT=m
+CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IPW2100=m
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_PROMISC=y
+# CONFIG_IPW2100_LEGACY_FW_LOAD is not set
+CONFIG_IPW2200=m
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PRISM54=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_NET_WIRELESS=y
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+CONFIG_TMS380TR=m
+CONFIG_TMSPCI=m
+CONFIG_ABYSS=m
+CONFIG_IBMTR=m
+CONFIG_IBMLS=m
+CONFIG_SKISA=m
+CONFIG_PROTEON=m
+CONFIG_SMCTR=m
+CONFIG_PCMCIA_IBMTR=m
+
+
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+# CONFIG_IRDA is not set
+# CONFIG_IRDA_DEBUG is not set
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRTTY_SIR=m
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_IRPORT_SIR=m
+# CONFIG_DONGLE_OLD is not set
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+CONFIG_USB_IRDA=m
+CONFIG_NSC_FIR=m
+CONFIG_SIGMATEL_FIR=m
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+# CONFIG_VIA_FIR is not set
+
+
+
+#
+# Bluetooth support
+#
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_CMTP=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_BCSP_TXCRC=y
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_USB_BLUETOOTH_TTY=m
+
+#
+# ISDN subsystem
+#
+
+CONFIG_ISDN=m
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_DRV_AVMB1_B1ISA=m
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_T1ISA=m
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_TTY_FAX=y
+CONFIG_DE_AOC=y
+
+CONFIG_ISDN_AUDIO=y
+
+CONFIG_ISDN_DRV_HISAX=m
+CONFIG_ISDN_DRV_ICN=m
+CONFIG_ISDN_DRV_PCBIT=m
+CONFIG_ISDN_DRV_SC=m
+CONFIG_ISDN_DRV_ACT2000=m
+CONFIG_ISDN_DRV_TPAM=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+CONFIG_HISAX_EURO=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+CONFIG_HISAX_16_0=y
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_AVM_A1=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_IX1MICROR2=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_ASUSCOM=y
+CONFIG_HISAX_TELEINT=y
+CONFIG_HISAX_HFCS=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_SPORTSTER=y
+CONFIG_HISAX_MIC=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_ISURF=y
+CONFIG_HISAX_HSTSAPHIR=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_ST5481=m
+CONFIG_HISAX_HFCUSB=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_VORTEX=m
+CONFIG_GAMEPORT_FM801=m
+CONFIG_GAMEPORT_CS461x=m
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_INPORT=m
+CONFIG_MOUSE_ATIXL=y
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_IFORCE_USB=y
+# CONFIG_JOYSTICK_IFORCE_232=y
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+CONFIG_N_HDLC=m
+CONFIG_STALDRV=y
+# CONFIG_FTAPE is not set
+# CONFIG_IBM_ASM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_MULTIPORT=y
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_DIGI is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALLION is not set
+# CONFIG_ISTALLION is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_DEBUG_ALGO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_I2C_PARPORT is not set
+CONFIG_I2C_ALI1563=m
+# CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_ALGOPCA=m
+# CONFIG_I2C_PCA_ISA is not set
+
+
+
+#
+# I2C Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_RTC8564=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_SMSC47M1=m
+
+# CONFIG_W1 is not set
+
+#
+# Mice
+#
+CONFIG_CRASH=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_WDT=m
+# CONFIG_WDT_501 is not set
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+CONFIG_PCWATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_MIXCOMWD is not set
+# CONFIG_SCx200_WDT is not set
+# CONFIG_60XX_WDT is not set
+CONFIG_W83877F_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_SC1200_WDT=m
+CONFIG_WAFER_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_USBPCWATCHDOG=m
+
+
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+CONFIG_DTLK=m
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_INTEL_MCH=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_MGA=m
+# CONFIG_DRM_SIS is not set
+CONFIG_DRM_I915=m
+
+
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+
+
+
+# CONFIG_MWAVE is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=8192
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA_PP is not set
+# CONFIG_VIDEO_CPIA_USB is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_DC30 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZORAN_LML33R10 is not set
+# CONFIG_VIDEO_MEYE is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_MIROPCM20_RDS is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_TYPHOON_PROC_FS=y
+# CONFIG_RADIO_ZOLTRIX is not set
+
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+CONFIG_DVB_CORE=m
+
+#
+# Supported Frontend Modules
+#
+CONFIG_DVB_STV0299=m
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_ALPS_TDLB7 is not set
+CONFIG_DVB_ALPS_TDMB7=m
+CONFIG_DVB_ATMEL_AT76C651=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_GRUNDIG_29504_491=m
+CONFIG_DVB_GRUNDIG_29504_401=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TWINHAN_DST=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_BT8XX=m
+# CONFIG_DVB_TDA1004X is not set
+CONFIG_DVB_NXT6000=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+# CONFIG_DVB_AV7110_FIRMWARE is not set
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_TTUSB_BUDGET=m
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_SKYSTAR=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BTCX=m
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+CONFIG_VIDEO_SELECT=y
+# CONFIG_FB_HGA is not set
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_DEBUG is not set
+# CONFIG_FB_RIVA_I2C is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G450=y
+CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_ATY_XL_INIT is not set
+# CONFIG_FB_SIS is not set
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_KYRO=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_HGA_ACCEL is not set
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_TRIDENT_ACCEL is not set
+CONFIG_FB_CIRRUS=m
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_BIT32_EMUL=y
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SB16_CSP=y
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_ALI5451=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS4281=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_NM256=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_FM801=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VX222=m
+CONFIG_SND_BT87X=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_PDAUDIOCF=m
+
+
+#
+# ALSA USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_VXP440 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+
+#
+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+#
+CONFIG_USB_MIDI=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_RW_DETECT=y
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_XPAD=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_HPUSBSCSI=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_STV680=m
+CONFIG_USB_SN9C102=m
+
+#
+# USB Network adaptors
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_SPEEDTOUCH=m
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_EMI62=m
+CONFIG_USB_LED=m
+CONFIG_USB_G_SERIAL=m
+
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LCD=m
+CONFIG_USB_TEST=m
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_PWC=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_MTOUCH=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ALI_M5632=y
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_EGALAX=m
+CONFIG_USB_PHIDGETSERVO=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_JFS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_SECURITY=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not seta
+# CONFIG_AFFS_FS is not set
+# uses sleepon and needs a major update
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_NAND=y
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_RXRPC is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_NLS_ASCII=y
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Tux
+#
+CONFIG_TUX=m
+CONFIG_TUX_EXTCGI=y
+# CONFIG_TUX_EXTENDED_LOG is not set
+# CONFIG_TUX_DEBUG is not set
+
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_HIGHMEM=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+# CONFIG_SECURITY_SELINUX_MLS is not set
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_LIBCRC32C=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Library routines
+#
+CONFIG_CRC32=m
+CONFIG_CRC_CCITT=m
+
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PC=y
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_ATALK is not set
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPX is not set
+# CONFIG_IPDDP is not set
+# CONFIG_IRDA is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_WD80x3 is not set
+# CONFIG_IRDA is not set
+# CONFIG_GAMEPORT is not set
+# CONFIG_DVB is not set
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SB16_CSP=y
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_R3964 is not set
+# CONFIG_TIPAR is not set
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_IFORCE_USB=y
+# CONFIG_JOYSTICK_IFORCE_232=y
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDDLER is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_MIROPCM20_RDS is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_TYPHOON_PROC_FS=y
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_PLIP is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA_PP is not set
+# CONFIG_VIDEO_CPIA_USB is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_DC30 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZORAN_LML33R10 is not set
+# CONFIG_VIDEO_MEYE is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_I82092 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_ULTRA is not set
+# CONFIG_SKFP is not set
+# CONFIG_DE600 is not set
+# CONFIG_DE620 is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_AC3200 is not set
+# CONFIG_NI52 is not set
+# CONFIG_NI65 is not set
+# CONFIG_LANCE is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_HP100 is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_ATP is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_INFTL is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_HGA_ACCEL is not set
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_TRIDENT_ACCEL is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_AUDIT=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_RAW_DRIVER=y
+# CONFIG_MTD_SCB2_FLASH is not set
+CONFIG_UID16=y
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_MTRR=y
+CONFIG_NUMA=y
+CONFIG_K8_NUMA=y
+CONFIG_NR_CPUS=8
+CONFIG_GART_IOMMU=y
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_INIT_DEBUG=y
+# CONFIG_IOMMU_DEBUG is not set
+# CONFIG_CHECKING is not set
+CONFIG_MICROCODE=m
+CONFIG_SWIOTLB=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_I2O=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+CONFIG_I2O_CONFIG=y
+CONFIG_TUX=m
+# CONFIG_UNORDERED_IO is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+CONFIG_X86_ACPI_CPUFREQ=y
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_SCHED_SMT=y
+# CONFIG_SOFTWARE_SUSPEND is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_PROC_INTF is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+# CONFIG_CPU_FREQ_24_API is not set
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_ACPI=y
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_TOSHIBA=m
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=2001
+# CONFIG_SCHEDSTATS is not set
+CONFIG_EDD=m
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_KEXEC=y
+CONFIG_NETDUMP=m
+CONFIG_CRASH=m
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_COMPAQ=m
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+CONFIG_HOTPLUG_PCI_IBM=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+# CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY is not set
+# CONFIG_HPET is not set
+CONFIG_PM=y
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT=m
+CONFIG_IEEE80211_WPA=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IPW2100=m
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2100_PROMISC=y
+# CONFIG_IPW2100_LEGACY_FW_LOAD is not set
+CONFIG_IPW2200=m
+# CONFIG_SMP is not set
+++ /dev/null
-Index: linux-2.4.20-rh-20.9/arch/i386/kernel/entry.S
-===================================================================
---- linux-2.4.20-rh-20.9.orig/arch/i386/kernel/entry.S 2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9/arch/i386/kernel/entry.S 2003-12-01 18:02:14.000000000 +0300
-@@ -45,6 +45,7 @@
- #include <linux/linkage.h>
- #include <asm/segment.h>
- #include <asm/smp.h>
-+#include <asm/current.h>
-
- EBX = 0x00
- ECX = 0x04
-@@ -130,10 +131,6 @@
- .long 3b,6b; \
- .previous
-
--#define GET_CURRENT(reg) \
-- movl $-8192, reg; \
-- andl %esp, reg
--
- ENTRY(lcall7)
- pushfl # We get a different stack layout with call gates,
- pushl %eax # which has to be cleaned up later..
-@@ -149,7 +146,7 @@
- movl %ecx,CS(%esp) #
- movl %esp,%ebx
- pushl %ebx
-- andl $-8192,%ebx # GET_CURRENT
-+ andl $-THREAD_SIZE,%ebx # GET_CURRENT
- movl exec_domain(%ebx),%edx # Get the execution domain
- movl 4(%edx),%edx # Get the lcall7 handler for the domain
- pushl $0x7
-@@ -173,7 +170,7 @@
- movl %ecx,CS(%esp) #
- movl %esp,%ebx
- pushl %ebx
-- andl $-8192,%ebx # GET_CURRENT
-+ andl $-THREAD_SIZE,%ebx # GET_CURRENT
- movl exec_domain(%ebx),%edx # Get the execution domain
- movl 4(%edx),%edx # Get the lcall7 handler for the domain
- pushl $0x27
-Index: linux-2.4.20-rh-20.9/arch/i386/kernel/smpboot.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/arch/i386/kernel/smpboot.c 2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9/arch/i386/kernel/smpboot.c 2003-12-01 18:02:14.000000000 +0300
-@@ -811,7 +811,7 @@
-
- /* So we see what's up */
- printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
-- stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle);
-+ stack_start.esp = (void *)idle->thread.esp;
-
- /*
- * This grunge runs the startup process for
-@@ -884,7 +884,7 @@
- Dprintk("CPU has booted.\n");
- } else {
- boot_error= 1;
-- if (*((volatile unsigned char *)phys_to_virt(8192))
-+ if (*((volatile unsigned char *)phys_to_virt(THREAD_SIZE))
- == 0xA5)
- /* trampoline started but...? */
- printk("Stuck ??\n");
-@@ -907,7 +907,7 @@
- }
-
- /* mark "stuck" area as not stuck */
-- *((volatile unsigned long *)phys_to_virt(8192)) = 0;
-+ *((volatile unsigned long *)phys_to_virt(THREAD_SIZE)) = 0;
-
- if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
- printk("Restoring NMI vector\n");
-Index: linux-2.4.20-rh-20.9/arch/i386/kernel/traps.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/arch/i386/kernel/traps.c 2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9/arch/i386/kernel/traps.c 2003-12-01 18:02:14.000000000 +0300
-@@ -161,7 +161,7 @@
- unsigned long esp = tsk->thread.esp;
-
- /* User space on another CPU? */
-- if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
-+ if ((esp ^ (unsigned long)tsk) & ~(THREAD_SIZE - 1))
- return;
- show_trace((unsigned long *)esp);
- }
-Index: linux-2.4.20-rh-20.9/arch/i386/kernel/head.S
-===================================================================
---- linux-2.4.20-rh-20.9.orig/arch/i386/kernel/head.S 2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9/arch/i386/kernel/head.S 2003-12-01 18:02:14.000000000 +0300
-@@ -15,6 +15,7 @@
- #include <asm/page.h>
- #include <asm/pgtable.h>
- #include <asm/desc.h>
-+#include <asm/current.h>
-
- #define OLD_CL_MAGIC_ADDR 0x90020
- #define OLD_CL_MAGIC 0xA33F
-@@ -315,7 +316,7 @@
- ret
-
- ENTRY(stack_start)
-- .long SYMBOL_NAME(init_task_union)+8192
-+ .long SYMBOL_NAME(init_task_union)+THREAD_SIZE
- .long __KERNEL_DS
-
- /* This is the default interrupt "handler" :-) */
-Index: linux-2.4.20-rh-20.9/arch/i386/kernel/irq.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/arch/i386/kernel/irq.c 2003-12-01 17:42:59.000000000 +0300
-+++ linux-2.4.20-rh-20.9/arch/i386/kernel/irq.c 2003-12-01 18:02:14.000000000 +0300
-@@ -581,7 +581,10 @@
- long esp;
-
- /* Debugging check for stack overflow: is there less than 1KB free? */
-- __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191));
-+ __asm__ __volatile__(
-+ "andl %%esp,%0"
-+ : "=r" (esp) : "0" (THREAD_SIZE-1));
-+
- if (unlikely(esp < (sizeof(struct task_struct) + 1024))) {
- extern void show_stack(unsigned long *);
-
-Index: linux-2.4.20-rh-20.9/arch/i386/lib/getuser.S
-===================================================================
---- linux-2.4.20-rh-20.9.orig/arch/i386/lib/getuser.S 1998-01-13 00:42:52.000000000 +0300
-+++ linux-2.4.20-rh-20.9/arch/i386/lib/getuser.S 2003-12-01 18:02:14.000000000 +0300
-@@ -21,6 +21,10 @@
- * as they get called from within inline assembly.
- */
-
-+/* Duplicated from asm/processor.h */
-+#include <asm/current.h>
-+#include <linux/config.h>
-+
- addr_limit = 12
-
- .text
-@@ -28,7 +32,7 @@
- .globl __get_user_1
- __get_user_1:
- movl %esp,%edx
-- andl $0xffffe000,%edx
-+ andl $~(THREAD_SIZE - 1),%edx
- cmpl addr_limit(%edx),%eax
- jae bad_get_user
- 1: movzbl (%eax),%edx
-@@ -41,7 +45,7 @@
- addl $1,%eax
- movl %esp,%edx
- jc bad_get_user
-- andl $0xffffe000,%edx
-+ andl $~(THREAD_SIZE - 1),%edx
- cmpl addr_limit(%edx),%eax
- jae bad_get_user
- 2: movzwl -1(%eax),%edx
-@@ -54,7 +58,7 @@
- addl $3,%eax
- movl %esp,%edx
- jc bad_get_user
-- andl $0xffffe000,%edx
-+ andl $~(THREAD_SIZE - 1),%edx
- cmpl addr_limit(%edx),%eax
- jae bad_get_user
- 3: movl -3(%eax),%edx
-Index: linux-2.4.20-rh-20.9/arch/i386/config.in
-===================================================================
---- linux-2.4.20-rh-20.9.orig/arch/i386/config.in 2003-09-13 19:34:34.000000000 +0400
-+++ linux-2.4.20-rh-20.9/arch/i386/config.in 2003-12-01 18:02:14.000000000 +0300
-@@ -266,6 +266,29 @@
- if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
- define_bool CONFIG_HAVE_DEC_LOCK y
- fi
-+
-+choice 'Bigger Stack Size Support' \
-+ "off CONFIG_NOBIGSTACK \
-+ 16KB CONFIG_STACK_SIZE_16KB \
-+ 32KB CONFIG_STACK_SIZE_32KB \
-+ 64KB CONFIG_STACK_SIZE_64KB" off
-+
-+if [ "$CONFIG_NOBIGSTACK" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 1
-+else
-+ if [ "$CONFIG_STACK_SIZE_16KB" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 2
-+ else
-+ if [ "$CONFIG_STACK_SIZE_32KB" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 3
-+ else
-+ if [ "$CONFIG_STACK_SIZE_64KB" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 4
-+ fi
-+ fi
-+ fi
-+fi
-+
- endmenu
-
- mainmenu_option next_comment
-Index: linux-2.4.20-rh-20.9/arch/i386/vmlinux.lds
-===================================================================
---- linux-2.4.20-rh-20.9.orig/arch/i386/vmlinux.lds 2003-09-13 19:34:24.000000000 +0400
-+++ linux-2.4.20-rh-20.9/arch/i386/vmlinux.lds 2003-12-01 18:02:14.000000000 +0300
-@@ -38,7 +38,8 @@
-
- _edata = .; /* End of data section */
-
-- . = ALIGN(8192); /* init_task */
-+/* chose the biggest of the possible stack sizes here? */
-+ . = ALIGN(65536); /* init_task */
- .data.init_task : { *(.data.init_task) }
-
- . = ALIGN(4096); /* Init code and data */
-Index: linux-2.4.20-rh-20.9/include/asm-i386/current.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/asm-i386/current.h 1998-08-15 03:35:22.000000000 +0400
-+++ linux-2.4.20-rh-20.9/include/asm-i386/current.h 2003-12-01 18:03:28.000000000 +0300
-@@ -1,15 +1,43 @@
- #ifndef _I386_CURRENT_H
- #define _I386_CURRENT_H
-+#include <asm/page.h>
-+
-+/*
-+ * Configurable page sizes on i386, mainly for debugging purposes.
-+ * (c) Balbir Singh
-+ */
-+
-+#ifdef __ASSEMBLY__
-+
-+#define PAGE_SIZE 4096 /* as cannot handle 1UL << 12 */
-+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE)
-+
-+#define GET_CURRENT(reg) \
-+ movl $-THREAD_SIZE, reg; \
-+ andl %esp, reg
-+
-+#else /* __ASSEMBLY__ */
-+
-+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE)
-+#define __alloc_task_struct() \
-+ ((struct task_struct *) __get_free_pages(GFP_KERNEL,CONFIG_STACK_SIZE_SHIFT))
-+
-+#define __free_task_struct(p) \
-+ free_pages((unsigned long) (p), CONFIG_STACK_SIZE_SHIFT)
-+
-+#define INIT_TASK_SIZE THREAD_SIZE
-
- struct task_struct;
-
- static inline struct task_struct * get_current(void)
- {
- struct task_struct *current;
-- __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
-+ __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~(THREAD_SIZE - 1)));
- return current;
- }
-
- #define current get_current()
-
-+#endif /* __ASSEMBLY__ */
-+
- #endif /* !(_I386_CURRENT_H) */
-Index: linux-2.4.20-rh-20.9/include/asm-i386/hw_irq.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/asm-i386/hw_irq.h 2003-11-13 17:35:48.000000000 +0300
-+++ linux-2.4.20-rh-20.9/include/asm-i386/hw_irq.h 2003-12-01 18:02:14.000000000 +0300
-@@ -116,10 +116,6 @@
- #define IRQ_NAME2(nr) nr##_interrupt(void)
- #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
-
--#define GET_CURRENT \
-- "movl %esp, %ebx\n\t" \
-- "andl $-8192, %ebx\n\t"
--
- /*
- * SMP has a few special interrupts for IPI messages
- */
-Index: linux-2.4.20-rh-20.9/include/asm-i386/processor.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/asm-i386/processor.h 2003-10-08 12:29:57.000000000 +0400
-+++ linux-2.4.20-rh-20.9/include/asm-i386/processor.h 2003-12-01 18:02:14.000000000 +0300
-@@ -14,6 +14,7 @@
- #include <asm/types.h>
- #include <asm/sigcontext.h>
- #include <asm/cpufeature.h>
-+#include <asm/current.h>
- #include <linux/cache.h>
- #include <linux/config.h>
- #include <linux/threads.h>
-@@ -469,10 +470,6 @@
- #define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
- #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-
--#define THREAD_SIZE (2*PAGE_SIZE)
--#define __alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
--#define __free_task_struct(p) do { BUG_ON((p)->state < TASK_ZOMBIE); free_pages((unsigned long) (p), 1); } while (0)
--
- #define init_task (init_task_union.task)
- #define init_stack (init_task_union.stack)
-
-Index: linux-2.4.20-rh-20.9/include/linux/sched.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/linux/sched.h 2003-11-13 17:35:48.000000000 +0300
-+++ linux-2.4.20-rh-20.9/include/linux/sched.h 2003-12-01 18:02:14.000000000 +0300
-@@ -2,6 +2,7 @@
- #define _LINUX_SCHED_H
-
- #include <asm/param.h> /* for HZ */
-+#include <asm/current.h> /* maybe for INIT_TASK_SIZE */
-
- extern unsigned long event;
-
+++ /dev/null
-Index: linux-2.4.22-ac1/arch/i386/kernel/entry.S
-===================================================================
---- linux-2.4.22-ac1.orig/arch/i386/kernel/entry.S 2003-09-25 14:16:34.000000000 +0400
-+++ linux-2.4.22-ac1/arch/i386/kernel/entry.S 2003-12-01 18:34:08.000000000 +0300
-@@ -46,6 +46,7 @@
- #include <asm/segment.h>
- #include <asm/smp.h>
- #include <asm/unistd.h>
-+#include <asm/current.h>
-
- EBX = 0x00
- ECX = 0x04
-@@ -131,10 +132,6 @@
- .long 3b,6b; \
- .previous
-
--#define GET_CURRENT(reg) \
-- movl $-8192, reg; \
-- andl %esp, reg
--
- ENTRY(lcall7)
- pushfl # We get a different stack layout with call gates,
- pushl %eax # which has to be cleaned up later..
-@@ -150,7 +147,7 @@
- movl %ecx,CS(%esp) #
- movl %esp,%ebx
- pushl %ebx
-- andl $-8192,%ebx # GET_CURRENT
-+ andl $-THREAD_SIZE,%ebx # GET_CURRENT
- movl exec_domain(%ebx),%edx # Get the execution domain
- movl 4(%edx),%edx # Get the lcall7 handler for the domain
- pushl $0x7
-@@ -174,7 +171,7 @@
- movl %ecx,CS(%esp) #
- movl %esp,%ebx
- pushl %ebx
-- andl $-8192,%ebx # GET_CURRENT
-+ andl $-THREAD_SIZE,%ebx # GET_CURRENT
- movl exec_domain(%ebx),%edx # Get the execution domain
- movl 4(%edx),%edx # Get the lcall7 handler for the domain
- pushl $0x27
-Index: linux-2.4.22-ac1/arch/i386/kernel/smpboot.c
-===================================================================
---- linux-2.4.22-ac1.orig/arch/i386/kernel/smpboot.c 2003-09-25 14:16:28.000000000 +0400
-+++ linux-2.4.22-ac1/arch/i386/kernel/smpboot.c 2003-12-01 18:34:08.000000000 +0300
-@@ -814,7 +814,7 @@
-
- /* So we see what's up */
- printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
-- stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle);
-+ stack_start.esp = (void *)idle->thread.esp;
-
- /*
- * This grunge runs the startup process for
-@@ -887,7 +887,7 @@
- Dprintk("CPU has booted.\n");
- } else {
- boot_error= 1;
-- if (*((volatile unsigned char *)phys_to_virt(8192))
-+ if (*((volatile unsigned char *)phys_to_virt(THREAD_SIZE))
- == 0xA5)
- /* trampoline started but...? */
- printk("Stuck ??\n");
-@@ -910,7 +910,7 @@
- }
-
- /* mark "stuck" area as not stuck */
-- *((volatile unsigned long *)phys_to_virt(8192)) = 0;
-+ *((volatile unsigned long *)phys_to_virt(THREAD_SIZE)) = 0;
-
- if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
- printk("Restoring NMI vector\n");
-Index: linux-2.4.22-ac1/arch/i386/kernel/traps.c
-===================================================================
---- linux-2.4.22-ac1.orig/arch/i386/kernel/traps.c 2003-09-25 14:16:29.000000000 +0400
-+++ linux-2.4.22-ac1/arch/i386/kernel/traps.c 2003-12-01 18:34:08.000000000 +0300
-@@ -161,7 +161,7 @@
- unsigned long esp = tsk->thread.esp;
-
- /* User space on another CPU? */
-- if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
-+ if ((esp ^ (unsigned long)tsk) & ~(THREAD_SIZE - 1))
- return;
- show_trace((unsigned long *)esp);
- }
-Index: linux-2.4.22-ac1/arch/i386/kernel/head.S
-===================================================================
---- linux-2.4.22-ac1.orig/arch/i386/kernel/head.S 2003-09-25 14:16:27.000000000 +0400
-+++ linux-2.4.22-ac1/arch/i386/kernel/head.S 2003-12-01 18:34:08.000000000 +0300
-@@ -15,6 +15,7 @@
- #include <asm/page.h>
- #include <asm/pgtable.h>
- #include <asm/desc.h>
-+#include <asm/current.h>
-
- #define OLD_CL_MAGIC_ADDR 0x90020
- #define OLD_CL_MAGIC 0xA33F
-@@ -315,7 +316,7 @@
- ret
-
- ENTRY(stack_start)
-- .long SYMBOL_NAME(init_task_union)+8192
-+ .long SYMBOL_NAME(init_task_union)+THREAD_SIZE
- .long __KERNEL_DS
-
- /* This is the default interrupt "handler" :-) */
-Index: linux-2.4.22-ac1/arch/i386/kernel/irq.c
-===================================================================
---- linux-2.4.22-ac1.orig/arch/i386/kernel/irq.c 2003-09-25 14:16:18.000000000 +0400
-+++ linux-2.4.22-ac1/arch/i386/kernel/irq.c 2003-12-01 18:34:08.000000000 +0300
-@@ -581,7 +581,10 @@
- long esp;
-
- /* Debugging check for stack overflow: is there less than 1KB free? */
-- __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191));
-+ __asm__ __volatile__(
-+ "andl %%esp,%0"
-+ : "=r" (esp) : "0" (THREAD_SIZE-1));
-+
- if (unlikely(esp < (sizeof(struct task_struct) + 1024))) {
- extern void show_stack(unsigned long *);
-
-Index: linux-2.4.22-ac1/arch/i386/lib/getuser.S
-===================================================================
---- linux-2.4.22-ac1.orig/arch/i386/lib/getuser.S 1998-01-13 00:42:52.000000000 +0300
-+++ linux-2.4.22-ac1/arch/i386/lib/getuser.S 2003-12-01 18:34:08.000000000 +0300
-@@ -21,6 +21,10 @@
- * as they get called from within inline assembly.
- */
-
-+/* Duplicated from asm/processor.h */
-+#include <asm/current.h>
-+#include <linux/config.h>
-+
- addr_limit = 12
-
- .text
-@@ -28,7 +32,7 @@
- .globl __get_user_1
- __get_user_1:
- movl %esp,%edx
-- andl $0xffffe000,%edx
-+ andl $~(THREAD_SIZE - 1),%edx
- cmpl addr_limit(%edx),%eax
- jae bad_get_user
- 1: movzbl (%eax),%edx
-@@ -41,7 +45,7 @@
- addl $1,%eax
- movl %esp,%edx
- jc bad_get_user
-- andl $0xffffe000,%edx
-+ andl $~(THREAD_SIZE - 1),%edx
- cmpl addr_limit(%edx),%eax
- jae bad_get_user
- 2: movzwl -1(%eax),%edx
-@@ -54,7 +58,7 @@
- addl $3,%eax
- movl %esp,%edx
- jc bad_get_user
-- andl $0xffffe000,%edx
-+ andl $~(THREAD_SIZE - 1),%edx
- cmpl addr_limit(%edx),%eax
- jae bad_get_user
- 3: movl -3(%eax),%edx
-Index: linux-2.4.22-ac1/arch/i386/config.in
-===================================================================
---- linux-2.4.22-ac1.orig/arch/i386/config.in 2003-09-25 14:16:34.000000000 +0400
-+++ linux-2.4.22-ac1/arch/i386/config.in 2003-12-01 18:34:08.000000000 +0300
-@@ -304,6 +304,29 @@
- if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
- define_bool CONFIG_HAVE_DEC_LOCK y
- fi
-+
-+choice 'Bigger Stack Size Support' \
-+ "off CONFIG_NOBIGSTACK \
-+ 16KB CONFIG_STACK_SIZE_16KB \
-+ 32KB CONFIG_STACK_SIZE_32KB \
-+ 64KB CONFIG_STACK_SIZE_64KB" off
-+
-+if [ "$CONFIG_NOBIGSTACK" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 1
-+else
-+ if [ "$CONFIG_STACK_SIZE_16KB" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 2
-+ else
-+ if [ "$CONFIG_STACK_SIZE_32KB" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 3
-+ else
-+ if [ "$CONFIG_STACK_SIZE_64KB" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 4
-+ fi
-+ fi
-+ fi
-+fi
-+
- endmenu
-
- mainmenu_option next_comment
-Index: linux-2.4.22-ac1/arch/i386/vmlinux.lds
-===================================================================
---- linux-2.4.22-ac1.orig/arch/i386/vmlinux.lds 2003-09-25 14:16:28.000000000 +0400
-+++ linux-2.4.22-ac1/arch/i386/vmlinux.lds 2003-12-01 18:34:08.000000000 +0300
-@@ -38,7 +38,8 @@
-
- _edata = .; /* End of data section */
-
-- . = ALIGN(8192); /* init_task */
-+/* chose the biggest of the possible stack sizes here? */
-+ . = ALIGN(65536); /* init_task */
- .data.init_task : { *(.data.init_task) }
-
- . = ALIGN(4096); /* Init code and data */
-Index: linux-2.4.22-ac1/include/asm-i386/current.h
-===================================================================
---- linux-2.4.22-ac1.orig/include/asm-i386/current.h 1998-08-15 03:35:22.000000000 +0400
-+++ linux-2.4.22-ac1/include/asm-i386/current.h 2003-12-01 18:34:16.000000000 +0300
-@@ -1,15 +1,43 @@
- #ifndef _I386_CURRENT_H
- #define _I386_CURRENT_H
-+#include <asm/page.h>
-+
-+/*
-+ * Configurable page sizes on i386, mainly for debugging purposes.
-+ * (c) Balbir Singh
-+ */
-+
-+#ifdef __ASSEMBLY__
-+
-+#define PAGE_SIZE 4096 /* as cannot handle 1UL << 12 */
-+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE)
-+
-+#define GET_CURRENT(reg) \
-+ movl $-THREAD_SIZE, reg; \
-+ andl %esp, reg
-+
-+#else /* __ASSEMBLY__ */
-+
-+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE)
-+#define __alloc_task_struct() \
-+ ((struct task_struct *) __get_free_pages(GFP_KERNEL,CONFIG_STACK_SIZE_SHIFT))
-+
-+#define __free_task_struct(p) \
-+ free_pages((unsigned long) (p), CONFIG_STACK_SIZE_SHIFT)
-+
-+#define INIT_TASK_SIZE THREAD_SIZE
-
- struct task_struct;
-
- static inline struct task_struct * get_current(void)
- {
- struct task_struct *current;
-- __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
-+ __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~(THREAD_SIZE - 1)));
- return current;
- }
-
- #define current get_current()
-
-+#endif /* __ASSEMBLY__ */
-+
- #endif /* !(_I386_CURRENT_H) */
-Index: linux-2.4.22-ac1/include/asm-i386/hw_irq.h
-===================================================================
---- linux-2.4.22-ac1.orig/include/asm-i386/hw_irq.h 2003-09-26 00:54:45.000000000 +0400
-+++ linux-2.4.22-ac1/include/asm-i386/hw_irq.h 2003-12-01 18:34:08.000000000 +0300
-@@ -114,10 +114,6 @@
- #define IRQ_NAME2(nr) nr##_interrupt(void)
- #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
-
--#define GET_CURRENT \
-- "movl %esp, %ebx\n\t" \
-- "andl $-8192, %ebx\n\t"
--
- /*
- * SMP has a few special interrupts for IPI messages
- */
-Index: linux-2.4.22-ac1/include/asm-i386/processor.h
-===================================================================
---- linux-2.4.22-ac1.orig/include/asm-i386/processor.h 2003-09-26 00:54:44.000000000 +0400
-+++ linux-2.4.22-ac1/include/asm-i386/processor.h 2003-12-01 18:34:08.000000000 +0300
-@@ -14,6 +14,7 @@
- #include <asm/types.h>
- #include <asm/sigcontext.h>
- #include <asm/cpufeature.h>
-+#include <asm/current.h>
- #include <linux/cache.h>
- #include <linux/config.h>
- #include <linux/threads.h>
-@@ -465,10 +466,6 @@
- #define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
- #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-
--#define THREAD_SIZE (2*PAGE_SIZE)
--#define __alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
--#define __free_task_struct(p) do { BUG_ON((p)->state < TASK_ZOMBIE); free_pages((unsigned long) (p), 1); } while (0)
--
- #define init_task (init_task_union.task)
- #define init_stack (init_task_union.stack)
-
-Index: linux-2.4.22-ac1/include/linux/sched.h
-===================================================================
---- linux-2.4.22-ac1.orig/include/linux/sched.h 2003-11-13 18:21:42.000000000 +0300
-+++ linux-2.4.22-ac1/include/linux/sched.h 2003-12-01 18:34:08.000000000 +0300
-@@ -2,6 +2,7 @@
- #define _LINUX_SCHED_H
-
- #include <asm/param.h> /* for HZ */
-+#include <asm/current.h> /* maybe for INIT_TASK_SIZE */
-
- extern unsigned long event;
-
--- /dev/null
+--- linux-2.6.5.orig/drivers/block/ll_rw_blk.c 2005-03-16 10:09:28.000000000 -0800
++++ linux-2.6.5/drivers/block/ll_rw_blk.c 2005-03-16 10:57:38.197357003 -0800
+@@ -2458,7 +2458,7 @@ static inline void blk_partition_remap(s
+ }
+ }
+
+-int dev_check_rdonly(dev_t dev);
++int dev_check_rdonly(struct block_device *bdev);
+
+ /**
+ * generic_make_request: hand a buffer to its device driver for I/O
+@@ -2550,9 +2550,9 @@ end_io:
+
+ /* this is cfs's dev_rdonly check */
+ if (bio->bi_rw == WRITE &&
+- dev_check_rdonly(bio->bi_bdev->bd_dev)) {
+- bio_endio(bio, bio->bi_size, 0);
+- break;
++ dev_check_rdonly(bio->bi_bdev)) {
++ bio_endio(bio, bio->bi_size, 0);
++ break;
+ }
+
+ /*
+@@ -3086,53 +3086,85 @@ void swap_io_context(struct io_context *
+ *ioc2 = temp;
+ }
+
+-#define MAX_RDONLY_DEVS 16
+-
+-static dev_t rdonly_devs[MAX_RDONLY_DEVS] = {0, };
+-
+ /*
+ * Debug code for turning block devices "read-only" (will discard writes
+ * silently). This is for filesystem crash/recovery testing.
+ */
+-void dev_set_rdonly(struct block_device *bdev, int no_write)
+-{
+- if (no_write >= MAX_RDONLY_DEVS) {
+- printk(KERN_ALERT "%s:%d illegal arg %d (max %d)\n",
+- __FILE__, __LINE__, no_write, MAX_RDONLY_DEVS);
+- return;
+- }
+-
+- if (bdev) {
+- printk(KERN_WARNING "Turning device %s read-only at %d\n",
+- bdev->bd_disk ? bdev->bd_disk->disk_name : "?",
+- no_write);
+- rdonly_devs[no_write] = bdev->bd_dev;
+- }
+-}
++struct deventry {
++ dev_t dev;
++ struct deventry *next;
++};
+
+-void dev_clear_rdonly(int no_write)
+-{
+- if (no_write >= MAX_RDONLY_DEVS) {
+- printk(KERN_ALERT "%s:%d illegal arg %d (max %d)\n",
+- __FILE__, __LINE__, no_write, MAX_RDONLY_DEVS);
+- return;
+- }
++static struct deventry *devlist = NULL;
++static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
+
+- if (rdonly_devs[no_write] == 0)
+- return;
+-
+- printk(KERN_WARNING "Clearing read-only at %d\n", no_write);
+- rdonly_devs[no_write] = 0;
+-}
+-
+-int dev_check_rdonly(dev_t dev)
++int dev_check_rdonly(struct block_device *bdev)
+ {
+- int i;
+-
+- for (i = 0; i < MAX_RDONLY_DEVS; i++)
+- if (rdonly_devs[i] == dev)
+- return 1;
+- return 0;
++ struct deventry *cur;
++ if (!bdev) return 0;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (bdev->bd_dev == cur->dev) {
++ spin_unlock(&devlock);
++ return 1;
++ }
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
++ return 0;
++}
++
++void dev_set_rdonly(struct block_device *bdev)
++{
++ struct deventry *newdev, *cur;
++
++ if (!bdev)
++ return;
++ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
++ if (!newdev)
++ return;
++
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (bdev->bd_dev == cur->dev) {
++ spin_unlock(&devlock);
++ kfree(newdev);
++ return;
++ }
++ cur = cur->next;
++ }
++ newdev->dev = bdev->bd_dev;
++ newdev->next = devlist;
++ devlist = newdev;
++ spin_unlock(&devlock);
++ printk(KERN_WARNING "Turning device %s read-only\n",
++ bdev->bd_disk ? bdev->bd_disk->disk_name : "?");
++}
++
++void dev_clear_rdonly(struct block_device *bdev)
++{
++ struct deventry *cur, *last = NULL;
++ if (!bdev) return;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (bdev->bd_dev == cur->dev) {
++ if (last)
++ last->next = cur->next;
++ else
++ devlist = cur->next;
++ spin_unlock(&devlock);
++ kfree(cur);
++ printk(KERN_WARNING "Removing read-only on %s\n",
++ bdev->bd_disk ? bdev->bd_disk->disk_name : "?");
++ return;
++ }
++ last = cur;
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
+ }
+
+ EXPORT_SYMBOL(dev_set_rdonly);
- drivers/block/ll_rw_blk.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++
- include/linux/blkdev.h | 1
- 2 files changed, 50 insertions(+)
-
-Index: linux-2.6.0/drivers/block/ll_rw_blk.c
-===================================================================
---- linux-2.6.0.orig/drivers/block/ll_rw_blk.c 2004-01-04 15:27:35.000000000 +0300
-+++ linux-2.6.0/drivers/block/ll_rw_blk.c 2004-01-07 17:35:57.000000000 +0300
-@@ -2298,6 +2298,13 @@
+--- linux-2.6.5.orig/drivers/block/ll_rw_blk.c 2005-03-16 11:08:47.404935605 -0800
++++ linux-2.6.5/drivers/block/ll_rw_blk.c 2005-03-16 10:57:38.197357003 -0800
+@@ -2458,6 +2458,8 @@ static inline void blk_partition_remap(s
+ }
+ }
+
++int dev_check_rdonly(struct block_device *bdev);
++
+ /**
+ * generic_make_request: hand a buffer to its device driver for I/O
+ * @bio: The bio describing the location in memory and on the device.
+@@ -2546,6 +2548,13 @@ end_io:
if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))
goto end_io;
+ /* this is cfs's dev_rdonly check */
+ if (bio->bi_rw == WRITE &&
-+ dev_check_rdonly(bio->bi_bdev->bd_dev)) {
-+ bio_endio(bio, bio->bi_size, 0);
-+ break;
++ dev_check_rdonly(bio->bi_bdev)) {
++ bio_endio(bio, bio->bi_size, 0);
++ break;
+ }
+
/*
* If this device has partitions, remap block n
* of partition p to block n+start(p) of the disk.
-@@ -2805,6 +2812,58 @@
- *ioc2 = temp;
+@@ -3078,6 +3087,91 @@ void swap_io_context(struct io_context *
}
-+#define MAX_RDONLY_DEVS 16
-+
-+static dev_t rdonly_devs[MAX_RDONLY_DEVS] = {0, };
-+
-+/*
+ /*
+ * Debug code for turning block devices "read-only" (will discard writes
+ * silently). This is for filesystem crash/recovery testing.
+ */
-+void dev_set_rdonly(struct block_device *bdev, int no_write)
-+{
-+ if (no_write >= MAX_RDONLY_DEVS) {
-+ printk(KERN_ALERT "%s:%d illegal arg %d (max %d)\n",
-+ __FILE__, __LINE__, no_write, MAX_RDONLY_DEVS);
-+ return;
-+ }
++struct deventry {
++ dev_t dev;
++ struct deventry *next;
++};
+
-+ if (bdev) {
-+ printk(KERN_WARNING "Turning device %s read-only at %d\n",
-+ bdev->bd_disk ? bdev->bd_disk->disk_name : "?",
-+ no_write);
-+ rdonly_devs[no_write] = bdev->bd_dev;
-+ }
++static struct deventry *devlist = NULL;
++static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
++
++int dev_check_rdonly(struct block_device *bdev)
++{
++ struct deventry *cur;
++ if (!bdev) return 0;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (bdev->bd_dev == cur->dev) {
++ spin_unlock(&devlock);
++ return 1;
++ }
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
++ return 0;
+}
+
-+void dev_clear_rdonly(int no_write)
++void dev_set_rdonly(struct block_device *bdev)
+{
-+ if (no_write >= MAX_RDONLY_DEVS) {
-+ printk(KERN_ALERT "%s:%d illegal arg %d (max %d)\n",
-+ __FILE__, __LINE__, no_write, MAX_RDONLY_DEVS);
-+ return;
-+ }
++ struct deventry *newdev, *cur;
+
-+ if (rdonly_devs[no_write] == 0)
-+ return;
-+
-+ printk(KERN_WARNING "Clearing read-only at %d\n", no_write);
-+ rdonly_devs[no_write] = 0;
++ if (!bdev)
++ return;
++ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
++ if (!newdev)
++ return;
++
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (bdev->bd_dev == cur->dev) {
++ spin_unlock(&devlock);
++ kfree(newdev);
++ return;
++ }
++ cur = cur->next;
++ }
++ newdev->dev = bdev->bd_dev;
++ newdev->next = devlist;
++ devlist = newdev;
++ spin_unlock(&devlock);
++ printk(KERN_WARNING "Turning device %s read-only\n",
++ bdev->bd_disk ? bdev->bd_disk->disk_name : "?");
+}
+
-+int dev_check_rdonly(dev_t dev)
++void dev_clear_rdonly(struct block_device *bdev)
+{
-+ int i;
-+
-+ for (i = 0; i < MAX_RDONLY_DEVS; i++)
-+ if (rdonly_devs[i] == dev)
-+ return 1;
-+ return 0;
++ struct deventry *cur, *last = NULL;
++ if (!bdev) return;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (bdev->bd_dev == cur->dev) {
++ if (last)
++ last->next = cur->next;
++ else
++ devlist = cur->next;
++ spin_unlock(&devlock);
++ kfree(cur);
++ printk(KERN_WARNING "Removing read-only on %s\n",
++ bdev->bd_disk ? bdev->bd_disk->disk_name : "?");
++ return;
++ }
++ last = cur;
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
+}
+
+EXPORT_SYMBOL(dev_set_rdonly);
+EXPORT_SYMBOL(dev_clear_rdonly);
+EXPORT_SYMBOL(dev_check_rdonly);
-
- /*
++
++/*
* sysfs parts below
+ */
+ struct queue_sysfs_entry {
-Index: linux-2.4.20-rh/drivers/block/blkpg.c
-===================================================================
---- linux-2.4.20-rh.orig/drivers/block/blkpg.c 2003-07-22 16:02:29.000000000 +0800
-+++ linux-2.4.20-rh/drivers/block/blkpg.c 2003-12-09 17:33:09.000000000 +0800
-@@ -297,3 +297,38 @@
+--- linux-2.4.20-rh.orig/drivers/block/ll_rw_blk.c 2005-01-19 10:59:48.000000000 -0800
++++ linux-2.4.20-rh/drivers/block/ll_rw_blk.c 2005-01-19 12:13:39.325347995 -0800
+@@ -645,6 +645,86 @@ void set_device_ro(kdev_t dev,int flag)
+ else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
}
- 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.
++ * Debug code for turning block devices read-only *silently* (will
++ * discard writes silently). This is only 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;
-+ }
-+}
++struct deventry {
++ kdev_t dev;
++ struct deventry *next;
++};
++
++static struct deventry *devlist = NULL;
++static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
+
+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;
++ struct deventry *cur;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (dev == cur->dev) {
++ spin_unlock(&devlock);
++ return 1;
++ }
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
++ return 0;
+}
+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
++void dev_set_rdonly(kdev_t dev)
++{
++ struct deventry *newdev, *cur;
++ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
++ if (!newdev) return;
++
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (dev == cur->dev) {
++ spin_unlock(&devlock);
++ kfree(newdev);
++ return;
++ }
++ cur = cur->next;
++ }
++ newdev->dev = dev;
++ newdev->next = devlist;
++ devlist = newdev;
++ spin_unlock(&devlock);
++ printk(KERN_WARNING "Turning device %s read-only\n",
++ bdevname(dev));
++}
++
++void dev_clear_rdonly(kdev_t dev) {
++ struct deventry *cur, *last = NULL;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (dev == cur->dev) {
++ if (last)
++ last->next = cur->next;
++ else
++ devlist = cur->next;
++ spin_unlock(&devlock);
++ kfree(cur);
++ printk(KERN_WARNING "Removing read-only on %s\n",
++ bdevname(dev));
++ return;
++ }
++ last = cur;
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
+}
+
+EXPORT_SYMBOL(dev_set_rdonly);
+EXPORT_SYMBOL(dev_check_rdonly);
+EXPORT_SYMBOL(dev_clear_rdonly);
-Index: linux-2.4.20-rh/drivers/block/ll_rw_blk.c
-===================================================================
---- linux-2.4.20-rh.orig/drivers/block/ll_rw_blk.c 2003-07-22 16:02:34.000000000 +0800
-+++ linux-2.4.20-rh/drivers/block/ll_rw_blk.c 2003-12-09 17:39:38.000000000 +0800
-@@ -1183,6 +1183,10 @@
++
++
+ inline void drive_stat_acct (kdev_t dev, int rw,
+ unsigned long nr_sectors, int new_io)
+ {
+@@ -1183,6 +1263,10 @@ void generic_make_request (int rw, struc
buffer_IO_error(bh);
break;
}
- drivers/block/blkpg.c | 35 +++++++++++++++++++++++++++++++++++
- drivers/block/loop.c | 3 +++
- drivers/ide/ide-disk.c | 5 +++++
- 3 files changed, 43 insertions(+)
-
-Index: linux-2.4.21-chaos/drivers/block/blkpg.c
-===================================================================
---- linux-2.4.21-chaos.orig/drivers/block/blkpg.c 2003-09-19 03:49:42.000000000 +0400
-+++ linux-2.4.21-chaos/drivers/block/blkpg.c 2003-12-12 16:17:49.000000000 +0300
-@@ -535,3 +535,38 @@
+--- linux-2.4.21-p4smp-75chaos/drivers/block/ll_rw_blk.c.orig 2004-10-28 14:41:07.000000000 -0700
++++ linux-2.4.21-p4smp-75chaos/drivers/block/ll_rw_blk.c 2005-01-19 12:24:53.946853178 -0800
+@@ -679,6 +679,86 @@ void set_device_ro(kdev_t dev,int flag)
+ else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
+ }
- #endif /* CONFIG_IA64 */
-
-+
-+#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.
++ * Debug code for turning block devices read-only *silently* (will
++ * discard writes silently). This is only 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;
-+ }
-+}
++struct deventry {
++ kdev_t dev;
++ struct deventry *next;
++};
++
++static struct deventry *devlist = NULL;
++static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
+
+int dev_check_rdonly(kdev_t dev) {
-+ int i;
++ struct deventry *cur;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (dev == cur->dev) {
++ spin_unlock(&devlock);
++ return 1;
++ }
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
++ return 0;
++}
+
-+ 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_set_rdonly(kdev_t dev)
++{
++ struct deventry *newdev, *cur;
++ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
++ if (!newdev) return;
++
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (dev == cur->dev) {
++ spin_unlock(&devlock);
++ kfree(newdev);
++ return;
++ }
++ cur = cur->next;
++ }
++ newdev->dev = dev;
++ newdev->next = devlist;
++ devlist = newdev;
++ spin_unlock(&devlock);
++ printk(KERN_WARNING "Turning device %s read-only\n",
++ bdevname(dev));
+}
+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
++void dev_clear_rdonly(kdev_t dev) {
++ struct deventry *cur, *last = NULL;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (dev == cur->dev) {
++ if (last)
++ last->next = cur->next;
++ else
++ devlist = cur->next;
++ spin_unlock(&devlock);
++ kfree(cur);
++ printk(KERN_WARNING "Removing read-only on %s\n",
++ bdevname(dev));
++ return;
++ }
++ last = cur;
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
+}
+
+EXPORT_SYMBOL(dev_set_rdonly);
+EXPORT_SYMBOL(dev_check_rdonly);
+EXPORT_SYMBOL(dev_clear_rdonly);
-Index: linux-2.4.21-chaos/drivers/block/loop.c
-===================================================================
---- linux-2.4.21-chaos.orig/drivers/block/loop.c 2003-09-19 03:49:42.000000000 +0400
-+++ linux-2.4.21-chaos/drivers/block/loop.c 2003-12-12 16:17:49.000000000 +0300
-@@ -491,6 +491,9 @@
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
-Index: linux-2.4.21-chaos/drivers/ide/ide-disk.c
-===================================================================
---- linux-2.4.21-chaos.orig/drivers/ide/ide-disk.c 2003-07-15 02:08:42.000000000 +0400
-+++ linux-2.4.21-chaos/drivers/ide/ide-disk.c 2003-12-12 16:17:49.000000000 +0300
-@@ -371,6 +371,11 @@
- if (driver_blocked)
- panic("Request while ide driver is blocked?");
-
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(drive, 1);
-+ return ide_stopped;
-+ }
+
- if (IDE_CONTROL_REG)
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+ inline void drive_stat_acct (kdev_t dev, int rw,
+ unsigned long nr_sectors, int new_io)
+ {
+@@ -1257,6 +1337,10 @@ void generic_make_request (int rw, struc
+ break;
+ }
+
++ if ((rw & WRITE)&&(dev_check_rdonly(bh->b_rdev))) {
++ bh->b_end_io(bh, 0);
++ break;
++ }
+ } while (q->make_request_fn(q, rw, bh));
+ }
+++ /dev/null
- drivers/block/blkpg.c | 36 ++++++++++++++++++++++++++++++++++++
- drivers/block/loop.c | 3 +++
- drivers/ide/ide-disk.c | 4 ++++
- 3 files changed, 43 insertions(+)
-
---- linux/drivers/block/blkpg.c~dev_read_only_hp_2.4.20 Mon May 19 07:07:52 2003
-+++ linux-mmonroe/drivers/block/blkpg.c Mon May 19 07:37:22 2003
-@@ -310,6 +310,42 @@ int blk_ioctl(kdev_t dev, unsigned int c
-
- 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/drivers/block/loop.c~dev_read_only_hp_2.4.20 Thu Nov 28 15:53:12 2002
-+++ linux-mmonroe/drivers/block/loop.c Mon May 19 07:28:29 2003
-@@ -474,6 +474,9 @@ static int loop_make_request(request_que
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
-+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
---- linux/drivers/ide/ide-disk.c~dev_read_only_hp_2.4.20 Thu Nov 28 15:53:13 2002
-+++ linux-mmonroe/drivers/ide/ide-disk.c Mon May 19 07:28:29 2003
-@@ -558,6 +558,10 @@ static ide_startstop_t lba_48_rw_disk (i
- */
- static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
- {
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(1, HWGROUP(drive));
-+ return ide_stopped;
-+ }
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
-
-
-_
+++ /dev/null
- arch/i386/kernel/crash.c | 24 +++++++++++++++++-------
- arch/i386/kernel/nmi.c | 2 +-
- include/asm-i386/apic.h | 1 +
- include/linux/crash.h | 2 +-
- kernel/bootimg.c | 13 ++++++++++++-
- kernel/bootimg_pic.c | 6 ++++--
- 6 files changed, 36 insertions(+), 12 deletions(-)
-
-Index: linux-2.4.20-rh/kernel/bootimg.c
-===================================================================
---- linux-2.4.20-rh.orig/kernel/bootimg.c 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/kernel/bootimg.c 2003-10-29 23:56:17.000000000 +0800
-@@ -238,9 +238,20 @@
- int error = -ENOMEM;
-
- if (bootimg_checksum(__va(bootimg_dsc.page_dir),bootimg_dsc.pages)
-- != bootimg_dsc.csum)
-+ != bootimg_dsc.csum) {
- printk("Checksum of kernel image failed. Rebooting via BIOS\n");
-
-+ /* Before calling machine_restart(), make sure it will not
-+ * simply call this function recursively.
-+ */
-+ bootimg_dsc.page_dir = NULL;
-+ machine_restart(NULL);
-+
-+ /* We should never get here, but just in case... */
-+ for (; ; )
-+ __asm__ __volatile__ ("hlt");
-+ }
-+
- code_page = get_identity_mapped_page();
- if (!code_page) goto out3;
- code = (relocate_and_jump_t) virt_to_phys((void *) code_page);
-Index: linux-2.4.20-rh/kernel/bootimg_pic.c
-===================================================================
---- linux-2.4.20-rh.orig/kernel/bootimg_pic.c 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/kernel/bootimg_pic.c 2003-10-29 23:56:17.000000000 +0800
-@@ -69,7 +69,8 @@
- for (j = i+1; j < dsc.pages; j++) {
- table = dsc.page_dir+FROM_TABLE(j);
- if (((unsigned long) *table) == to) {
-- copy_and_swap(*table,dsc.scratch);
-+ copy_and_swap((unsigned long) (*table),
-+ dsc.scratch);
- break;
- }
- if ((*table)[PAGE_NR(j)] == to) {
-@@ -79,7 +80,8 @@
- }
- table = dsc.page_dir+TO_TABLE(j);
- if (((unsigned long) *table) == to) {
-- copy_and_swap(*table,dsc.scratch);
-+ copy_and_swap((unsigned long) (*table),
-+ dsc.scratch);
- break;
- }
- }
-Index: linux-2.4.20-rh/include/asm-i386/apic.h
-===================================================================
---- linux-2.4.20-rh.orig/include/asm-i386/apic.h 2003-10-29 23:58:49.000000000 +0800
-+++ linux-2.4.20-rh/include/asm-i386/apic.h 2003-10-29 23:59:40.000000000 +0800
-@@ -86,6 +86,9 @@
- extern void apic_pm_unregister(struct pm_dev*);
-
- extern int check_nmi_watchdog (void);
-+extern void disable_apic_nmi_watchdog(void);
-+
-+
-
- extern unsigned int nmi_watchdog;
- #define NMI_NONE 0
-Index: linux-2.4.20-rh/include/linux/crash.h
-===================================================================
---- linux-2.4.20-rh.orig/include/linux/crash.h 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/include/linux/crash.h 2003-10-29 23:56:17.000000000 +0800
-@@ -71,7 +71,7 @@
- #define CRASH_ZALLOC_PAGES 16*5*2 /* 2 to handle crash in crash */
- #define CRASH_LOW_WATER_PAGES 100
-
--#define CRASH_CPU_TIMEOUT 5000 /* 5 sec wait for other cpus to stop */
-+#define CRASH_CPU_TIMEOUT 15000 /* 15 sec wait for other cpus to stop */
-
- #define CRASH_MARK_RESERVED(addr) (set_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags))
- #define CRASH_CLEAR_RESERVED(addr) (clear_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags))
-Index: linux-2.4.20-rh/arch/i386/kernel/crash.c
-===================================================================
---- linux-2.4.20-rh.orig/arch/i386/kernel/crash.c 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/arch/i386/kernel/crash.c 2003-10-29 23:56:17.000000000 +0800
-@@ -9,6 +9,8 @@
- #include <linux/crash.h>
- #include <linux/reboot.h>
- #include <linux/bootimg.h>
-+#include <asm/fixmap.h>
-+#include <asm/apic.h>
-
- inline void crash_save_regs(void) {
- static unsigned long regs[8];
-@@ -30,15 +32,23 @@
- */
- void crash_save_current_state(struct task_struct *tp)
- {
-+ if (tp != NULL) {
-+ /*
-+ * Here we save ebp instead of esp just in case the compiler
-+ * decides to put an extra push in before we execute this
-+ * instruction (thus invalidating our frame pointer).
-+ */
-+ asm volatile("movl %%ebp,%0":"=m" (*(u_long *)&tp->thread.esp));
-+ tp->thread.eip = (u_long)crash_save_current_state;
-+ panic_ksp[smp_processor_id()] = tp->thread.esp;
-+ mb();
-+ }
-+
- /*
-- * Here we save ebp instead of esp just in case the compiler
-- * decides to put an extra push in before we execute this
-- * instruction (thus invalidating our frame pointer).
-+ * Just to be safe, disable the NMI watchdog on the calling CPU so it
-+ * doesn't get in the way while we are trying to save a dump.
- */
-- asm volatile("movl %%ebp,%0":"=m" (*(u_long *)&tp->thread.esp));
-- tp->thread.eip = (u_long)crash_save_current_state;
-- panic_ksp[smp_processor_id()] = tp->thread.esp;
-- mb();
-+ disable_apic_nmi_watchdog();
-
- save_core();
-
-Index: linux-2.4.20-rh/arch/i386/kernel/nmi.c
-===================================================================
---- linux-2.4.20-rh.orig/arch/i386/kernel/nmi.c 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/arch/i386/kernel/nmi.c 2003-10-29 23:56:17.000000000 +0800
-@@ -138,7 +138,7 @@
-
- struct pm_dev *nmi_pmdev;
-
--static void disable_apic_nmi_watchdog(void)
-+void disable_apic_nmi_watchdog(void)
- {
- switch (boot_cpu_data.x86_vendor) {
- case X86_VENDOR_AMD:
+++ /dev/null
- include/linux/dynlocks.h | 33 ++++++++++
- lib/Makefile | 4 -
- lib/dynlocks.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 187 insertions(+), 2 deletions(-)
-
-Index: linux-2.4.20-rh/include/linux/dynlocks.h
-===================================================================
---- linux-2.4.20-rh.orig/include/linux/dynlocks.h 2003-09-04 18:25:49.000000000 +0800
-+++ linux-2.4.20-rh/include/linux/dynlocks.h 2003-09-04 18:25:49.000000000 +0800
-@@ -0,0 +1,33 @@
-+#ifndef _LINUX_DYNLOCKS_H
-+#define _LINUX_DYNLOCKS_H
-+
-+#include <linux/list.h>
-+#include <linux/wait.h>
-+
-+struct dynlock_member {
-+ struct list_head dl_list;
-+ unsigned long dl_value; /* lock value */
-+ int dl_refcount; /* number of users */
-+ int dl_readers;
-+ int dl_writers;
-+ int dl_pid; /* holder of the lock */
-+ wait_queue_head_t dl_wait;
-+};
-+
-+/*
-+ * lock's namespace:
-+ * - list of locks
-+ * - lock to protect this list
-+ */
-+struct dynlock {
-+ struct list_head dl_list;
-+ spinlock_t dl_list_lock;
-+};
-+
-+void dynlock_init(struct dynlock *dl);
-+void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp);
-+void dynlock_unlock(struct dynlock *dl, void *lock);
-+
-+
-+#endif
-+
-Index: linux-2.4.20-rh/lib/dynlocks.c
-===================================================================
---- linux-2.4.20-rh.orig/lib/dynlocks.c 2003-09-04 18:25:49.000000000 +0800
-+++ linux-2.4.20-rh/lib/dynlocks.c 2003-09-04 18:25:49.000000000 +0800
-@@ -0,0 +1,152 @@
-+/*
-+ * Dynamic Locks
-+ *
-+ * struct dynlock is lockspace
-+ * one may request lock (exclusive or shared) for some value
-+ * in that lockspace
-+ *
-+ */
-+
-+#include <linux/dynlocks.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+
-+/*
-+ * dynlock_init
-+ *
-+ * initialize lockspace
-+ *
-+ */
-+void dynlock_init(struct dynlock *dl)
-+{
-+ spin_lock_init(&dl->dl_list_lock);
-+ INIT_LIST_HEAD(&dl->dl_list);
-+}
-+
-+/*
-+ * dynlock_lock
-+ *
-+ * acquires lock (exclusive or shared) in specified lockspace
-+ * each lock in lockspace is allocated separately, so user have
-+ * to specify GFP flags.
-+ * routine returns pointer to lock. this pointer is intended to
-+ * be passed to dynlock_unlock
-+ *
-+ */
-+void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp)
-+{
-+ struct dynlock_member *nhl = NULL;
-+ struct dynlock_member *hl;
-+ struct list_head *cur;
-+
-+repeat:
-+ /* find requested lock in lockspace */
-+ spin_lock(&dl->dl_list_lock);
-+ list_for_each(cur, &dl->dl_list) {
-+ hl = list_entry(cur, struct dynlock_member, dl_list);
-+ if (hl->dl_value == value) {
-+ /* lock is found */
-+ if (nhl) {
-+ /* someone else just allocated
-+ * lock we didn't find and just created
-+ * so, we drop our lock
-+ */
-+ kfree(nhl);
-+ nhl = NULL;
-+ }
-+ hl->dl_refcount++;
-+ goto found;
-+ }
-+ }
-+ /* lock not found */
-+ if (nhl) {
-+ /* we already have allocated lock. use it */
-+ hl = nhl;
-+ nhl = NULL;
-+ list_add(&hl->dl_list, &dl->dl_list);
-+ goto found;
-+ }
-+ spin_unlock(&dl->dl_list_lock);
-+
-+ /* lock not found and we haven't allocated lock yet. allocate it */
-+ nhl = kmalloc(sizeof(struct dynlock_member), gfp);
-+ if (nhl == NULL)
-+ return NULL;
-+ nhl->dl_refcount = 1;
-+ nhl->dl_value = value;
-+ nhl->dl_readers = 0;
-+ nhl->dl_writers = 0;
-+ init_waitqueue_head(&nhl->dl_wait);
-+
-+ /* while lock is being allocated, someone else may allocate it
-+ * and put onto to list. check this situation
-+ */
-+ goto repeat;
-+
-+found:
-+ if (rw) {
-+ /* exclusive lock: user don't want to share lock at all
-+ * NOTE: one process may take the same lock several times
-+ * this functionaly is useful for rename operations */
-+ while ((hl->dl_writers && hl->dl_pid != current->pid) ||
-+ hl->dl_readers) {
-+ spin_unlock(&dl->dl_list_lock);
-+ wait_event(hl->dl_wait,
-+ hl->dl_writers == 0 && hl->dl_readers == 0);
-+ spin_lock(&dl->dl_list_lock);
-+ }
-+ hl->dl_writers++;
-+ } else {
-+ /* shared lock: user do not want to share lock with writer */
-+ while (hl->dl_writers) {
-+ spin_unlock(&dl->dl_list_lock);
-+ wait_event(hl->dl_wait, hl->dl_writers == 0);
-+ spin_lock(&dl->dl_list_lock);
-+ }
-+ hl->dl_readers++;
-+ }
-+ hl->dl_pid = current->pid;
-+ spin_unlock(&dl->dl_list_lock);
-+
-+ return hl;
-+}
-+
-+
-+/*
-+ * dynlock_unlock
-+ *
-+ * user have to specify lockspace (dl) and pointer to lock structure
-+ * returned by dynlock_lock()
-+ *
-+ */
-+void dynlock_unlock(struct dynlock *dl, void *lock)
-+{
-+ struct dynlock_member *hl = lock;
-+ int wakeup = 0;
-+
-+ spin_lock(&dl->dl_list_lock);
-+ if (hl->dl_writers) {
-+ hl->dl_writers--;
-+ if (hl->dl_writers == 0)
-+ wakeup = 1;
-+ } else {
-+ hl->dl_readers--;
-+ if (hl->dl_readers == 0)
-+ wakeup = 1;
-+ }
-+ if (wakeup) {
-+ hl->dl_pid = 0;
-+ wake_up(&hl->dl_wait);
-+ }
-+ if (--(hl->dl_refcount) == 0)
-+ list_del(&hl->dl_list);
-+ spin_unlock(&dl->dl_list_lock);
-+ if (hl->dl_refcount == 0)
-+ kfree(hl);
-+}
-+
-+EXPORT_SYMBOL(dynlock_init);
-+EXPORT_SYMBOL(dynlock_lock);
-+EXPORT_SYMBOL(dynlock_unlock);
-+
-Index: linux-2.4.20-rh/lib/Makefile
-===================================================================
---- linux-2.4.20-rh.orig/lib/Makefile 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-rh/lib/Makefile 2003-09-04 18:27:26.000000000 +0800
-@@ -8,10 +8,10 @@
-
- L_TARGET := lib.a
-
--export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o rbtree.o
-+export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o rbtree.o dynlocks.o
-
- obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
-- bust_spinlocks.o rbtree.o dump_stack.o
-+ bust_spinlocks.o rbtree.o dump_stack.o dynlocks.o
-
- obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
- obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+++ /dev/null
-
-
-
- fs/ext3/Makefile | 2 ++
- fs/ext3/super.c | 2 +-
- include/linux/fs.h | 1 +
- kernel/ksyms.c | 5 +++++
- 4 files changed, 9 insertions(+), 1 deletion(-)
-
---- linux-2.4.18-18/fs/ext3/Makefile~exports Sat Apr 5 02:51:27 2003
-+++ linux-2.4.18-18-braam/fs/ext3/Makefile Sat Apr 5 02:54:45 2003
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o inode.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-18/fs/ext3/super.c~exports Sat Apr 5 02:51:27 2003
-+++ linux-2.4.18-18-braam/fs/ext3/super.c Sat Apr 5 02:54:28 2003
-@@ -1746,7 +1746,7 @@ static void __exit exit_ext3_fs(void)
- 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-18/include/linux/fs.h~exports Sat Apr 5 02:51:27 2003
-+++ linux-2.4.18-18-braam/include/linux/fs.h Sat Apr 5 02:54:29 2003
-@@ -1046,6 +1046,7 @@ extern int unregister_filesystem(struct
- 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
---- linux-2.4.18-18/kernel/ksyms.c~exports Sat Apr 5 02:51:27 2003
-+++ linux-2.4.18-18-braam/kernel/ksyms.c Sat Apr 5 02:54:29 2003
-@@ -306,6 +306,11 @@ EXPORT_SYMBOL_GPL(buffermem_pages);
- EXPORT_SYMBOL_GPL(nr_free_pages);
- EXPORT_SYMBOL_GPL(page_cache_size);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(do_kern_mount);
-+
- /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
- EXPORT_SYMBOL(default_llseek);
- EXPORT_SYMBOL(dentry_open);
-
-_
+++ /dev/null
- fs/ext3/file.c | 4
- fs/ext3/inode.c | 116 ++++++++++++++++++++++
- fs/ext3/super.c | 230 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/ext3_fs.h | 5
- include/linux/ext3_fs_sb.h | 10 +
- 5 files changed, 365 insertions(+)
-
-Index: linux-2.4.21-suse/fs/ext3/super.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/super.c 2004-01-12 19:49:25.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/super.c 2004-01-13 17:39:59.000000000 +0300
-@@ -400,6 +400,221 @@
- }
- }
-
-+#ifdef EXT3_DELETE_THREAD
-+/*
-+ * Delete inodes in a loop until there are no more to be deleted.
-+ * Normally, we run in the background doing the deletes and sleeping again,
-+ * and clients just add new inodes to be deleted onto the end of the list.
-+ * If someone is concerned about free space (e.g. block allocation or similar)
-+ * then they can sleep on s_delete_waiter_queue and be woken up when space
-+ * has been freed.
-+ */
-+int ext3_delete_thread(void *data)
-+{
-+ struct super_block *sb = data;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct task_struct *tsk = current;
-+
-+ /* Almost like daemonize, but not quite */
-+ exit_mm(current);
-+ tsk->session = 1;
-+ tsk->pgrp = 1;
-+ tsk->tty = NULL;
-+ exit_files(current);
-+ reparent_to_init();
-+
-+ sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev));
-+ sigfillset(&tsk->blocked);
-+
-+ /*tsk->flags |= PF_KERNTHREAD;*/
-+
-+ INIT_LIST_HEAD(&sbi->s_delete_list);
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev));
-+
-+ /* main loop */
-+ for (;;) {
-+ wait_event_interruptible(sbi->s_delete_thread_queue,
-+ !list_empty(&sbi->s_delete_list) ||
-+ !test_opt(sb, ASYNCDEL));
-+ ext3_debug("%s woken up: %lu inodes, %lu blocks\n",
-+ tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ if (list_empty(&sbi->s_delete_list)) {
-+ clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+ memset(&sbi->s_delete_list, 0,
-+ sizeof(sbi->s_delete_list));
-+ spin_unlock(&sbi->s_delete_lock);
-+ ext3_debug("delete thread on %s exiting\n",
-+ kdevname(sb->s_dev));
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ break;
-+ }
-+
-+ while (!list_empty(&sbi->s_delete_list)) {
-+ struct inode *inode=list_entry(sbi->s_delete_list.next,
-+ struct inode, i_dentry);
-+ unsigned long blocks = inode->i_blocks >>
-+ (inode->i_blkbits - 9);
-+
-+ list_del_init(&inode->i_dentry);
-+ spin_unlock(&sbi->s_delete_lock);
-+ ext3_debug("%s delete ino %lu blk %lu\n",
-+ tsk->comm, inode->i_ino, blocks);
-+
-+ iput(inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ sbi->s_delete_blocks -= blocks;
-+ sbi->s_delete_inodes--;
-+ }
-+ if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) {
-+ ext3_warning(sb, __FUNCTION__,
-+ "%lu blocks, %lu inodes on list?\n",
-+ sbi->s_delete_blocks,sbi->s_delete_inodes);
-+ sbi->s_delete_blocks = 0;
-+ sbi->s_delete_inodes = 0;
-+ }
-+ spin_unlock(&sbi->s_delete_lock);
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ }
-+
-+ return 0;
-+}
-+
-+static void ext3_start_delete_thread(struct super_block *sb)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ int rc;
-+
-+ spin_lock_init(&sbi->s_delete_lock);
-+ init_waitqueue_head(&sbi->s_delete_thread_queue);
-+ init_waitqueue_head(&sbi->s_delete_waiter_queue);
-+
-+ if (!test_opt(sb, ASYNCDEL))
-+ return;
-+
-+ rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES);
-+ if (rc < 0)
-+ printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n",
-+ rc);
-+ else
-+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next);
-+}
-+
-+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi)
-+{
-+ if (sbi->s_delete_list.next == 0) /* thread never started */
-+ return;
-+
-+ clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+ wake_up(&sbi->s_delete_thread_queue);
-+ wait_event(sbi->s_delete_waiter_queue,
-+ sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0);
-+}
-+
-+/* Instead of playing games with the inode flags, destruction, etc we just
-+ * create a new inode locally and put it on a list for the truncate thread.
-+ * We need large parts of the inode struct in order to complete the
-+ * truncate and unlink, so we may as well just have a real inode to do it.
-+ *
-+ * If we have any problem deferring the delete, just delete it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+static void ext3_delete_inode_thread(struct inode *old_inode)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+ struct inode *new_inode;
-+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+ if (is_bad_inode(old_inode)) {
-+ clear_inode(old_inode);
-+ return;
-+ }
-+
-+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+ goto out_delete;
-+
-+ /* We may want to delete the inode immediately and not defer it */
-+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS)
-+ goto out_delete;
-+
-+ /* We can't use the delete thread as-is during real orphan recovery,
-+ * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+ * to loop endlessly. It would be nice to do so, but needs work.
-+ */
-+ if (oei->i_state & EXT3_STATE_DELETE ||
-+ sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+ old_inode->i_ino, blocks);
-+ goto out_delete;
-+ }
-+
-+ /* We can iget this inode again here, because our caller has unhashed
-+ * old_inode, so new_inode will be in a different inode struct.
-+ *
-+ * We need to ensure that the i_orphan pointers in the other inodes
-+ * point at the new inode copy instead of the old one so the orphan
-+ * list doesn't get corrupted when the old orphan inode is freed.
-+ */
-+ down(&sbi->s_orphan_lock);
-+
-+ sbi->s_mount_state |= EXT3_ORPHAN_FS;
-+ new_inode = iget(old_inode->i_sb, old_inode->i_ino);
-+ sbi->s_mount_state &= ~EXT3_ORPHAN_FS;
-+ if (is_bad_inode(new_inode)) {
-+ printk(KERN_WARNING "read bad inode %lu\n", old_inode->i_ino);
-+ iput(new_inode);
-+ new_inode = NULL;
-+ }
-+ if (!new_inode) {
-+ up(&sbi->s_orphan_lock);
-+ ext3_debug("delete inode %lu directly (bad read)\n",
-+ old_inode->i_ino);
-+ goto out_delete;
-+ }
-+ J_ASSERT(new_inode != old_inode);
-+
-+ J_ASSERT(!list_empty(&oei->i_orphan));
-+
-+ nei = EXT3_I(new_inode);
-+ /* Ugh. We need to insert new_inode into the same spot on the list
-+ * as old_inode was, to ensure the in-memory orphan list is still
-+ * in the same order as the on-disk orphan list (badness otherwise).
-+ */
-+ nei->i_orphan = oei->i_orphan;
-+ nei->i_orphan.next->prev = &nei->i_orphan;
-+ nei->i_orphan.prev->next = &nei->i_orphan;
-+ nei->i_state |= EXT3_STATE_DELETE;
-+ up(&sbi->s_orphan_lock);
-+
-+ clear_inode(old_inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ J_ASSERT(list_empty(&new_inode->i_dentry));
-+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+ sbi->s_delete_blocks += blocks;
-+ sbi->s_delete_inodes++;
-+ spin_unlock(&sbi->s_delete_lock);
-+
-+ ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+ new_inode->i_ino, blocks);
-+
-+ wake_up(&sbi->s_delete_thread_queue);
-+ return;
-+
-+out_delete:
-+ ext3_delete_inode(old_inode);
-+}
-+#else
-+#define ext3_start_delete_thread(sbi) do {} while(0)
-+#define ext3_stop_delete_thread(sbi) do {} while(0)
-+#endif /* EXT3_DELETE_THREAD */
-+
- void ext3_put_super (struct super_block * sb)
- {
- struct ext3_sb_info *sbi = EXT3_SB(sb);
-@@ -407,6 +622,7 @@
- kdev_t j_dev = sbi->s_journal->j_dev;
- int i;
-
-+ J_ASSERT(sbi->s_delete_inodes == 0);
- ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
-@@ -455,7 +671,11 @@
- write_inode: ext3_write_inode, /* BKL not held. Don't need */
- dirty_inode: ext3_dirty_inode, /* BKL not held. We take it */
- put_inode: ext3_put_inode, /* BKL not held. Don't need */
-+#ifdef EXT3_DELETE_THREAD
-+ delete_inode: ext3_delete_inode_thread,/* BKL not held. We take it */
-+#else
- delete_inode: ext3_delete_inode, /* BKL not held. We take it */
-+#endif
- put_super: ext3_put_super, /* BKL held */
- write_super: ext3_write_super, /* BKL held */
- sync_fs: ext3_sync_fs,
-@@ -524,6 +744,13 @@
- clear_opt (*mount_options, XATTR_USER);
- else
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+ if (!strcmp(this_char, "asyncdel"))
-+ set_opt(*mount_options, ASYNCDEL);
-+ else if (!strcmp(this_char, "noasyncdel"))
-+ clear_opt(*mount_options, ASYNCDEL);
-+ else
-+#endif
- if (!strcmp (this_char, "bsddf"))
- clear_opt (*mount_options, MINIX_DF);
- else if (!strcmp (this_char, "nouid32")) {
-@@ -1223,6 +1450,7 @@
- }
-
- ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-+ ext3_start_delete_thread(sb);
- /*
- * akpm: core read_super() calls in here with the superblock locked.
- * That deadlocks, because orphan cleanup needs to lock the superblock
-@@ -1614,7 +1842,12 @@
- static int ext3_sync_fs(struct super_block *sb)
- {
- tid_t target;
--
-+
-+ if (atomic_read(&sb->s_active) == 0) {
-+ /* fs is being umounted: time to stop delete thread */
-+ ext3_stop_delete_thread(EXT3_SB(sb));
-+ }
-+
- sb->s_dirt = 0;
- target = log_start_commit(EXT3_SB(sb)->s_journal, NULL);
- log_wait_commit(EXT3_SB(sb)->s_journal, target);
-@@ -1678,6 +1911,9 @@
- if (!parse_options(data, &tmp, sbi, &tmp, 1))
- return -EINVAL;
-
-+ if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY))
-+ ext3_stop_delete_thread(sbi);
-+
- if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
- ext3_abort(sb, __FUNCTION__, "Abort forced by user");
-
-Index: linux-2.4.21-suse/fs/ext3/inode.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/inode.c 2004-01-13 17:38:09.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/inode.c 2004-01-13 17:38:10.000000000 +0300
-@@ -2552,6 +2552,118 @@
- return err;
- }
-
-+#ifdef EXT3_DELETE_THREAD
-+/* Move blocks from to-be-truncated inode over to a new inode, and delete
-+ * that one from the delete thread instead. This avoids a lot of latency
-+ * when truncating large files.
-+ *
-+ * If we have any problem deferring the truncate, just truncate it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+void ext3_truncate_thread(struct inode *old_inode)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+ struct inode *new_inode;
-+ handle_t *handle;
-+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+ goto out_truncate;
-+
-+ /* XXX This is a temporary limitation for code simplicity.
-+ * We could truncate to arbitrary sizes at some later time.
-+ */
-+ if (old_inode->i_size != 0)
-+ goto out_truncate;
-+
-+ /* We may want to truncate the inode immediately and not defer it */
-+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS ||
-+ old_inode->i_size > oei->i_disksize)
-+ goto out_truncate;
-+
-+ /* We can't use the delete thread as-is during real orphan recovery,
-+ * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+ * to loop endlessly. It would be nice to do so, but needs work.
-+ */
-+ if (oei->i_state & EXT3_STATE_DELETE ||
-+ sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+ old_inode->i_ino, blocks);
-+ goto out_truncate;
-+ }
-+
-+ ext3_discard_prealloc(old_inode);
-+
-+ /* old_inode = 1
-+ * new_inode = sb + GDT + ibitmap
-+ * orphan list = 1 inode/superblock for add, 2 inodes for del
-+ * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS
-+ */
-+ handle = ext3_journal_start(old_inode, 7);
-+ if (IS_ERR(handle))
-+ goto out_truncate;
-+
-+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode);
-+ if (IS_ERR(new_inode)) {
-+ ext3_debug("truncate inode %lu directly (no new inodes)\n",
-+ old_inode->i_ino);
-+ goto out_journal;
-+ }
-+
-+ nei = EXT3_I(new_inode);
-+
-+ down_write(&oei->truncate_sem);
-+ new_inode->i_size = old_inode->i_size;
-+ new_inode->i_blocks = old_inode->i_blocks;
-+ new_inode->i_uid = old_inode->i_uid;
-+ new_inode->i_gid = old_inode->i_gid;
-+ new_inode->i_nlink = 0;
-+
-+ /* FIXME when we do arbitrary truncates */
-+ old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0;
-+ old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME;
-+
-+ memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data));
-+ memset(oei->i_data, 0, sizeof(oei->i_data));
-+
-+ nei->i_disksize = oei->i_disksize;
-+ nei->i_state |= EXT3_STATE_DELETE;
-+ up_write(&oei->truncate_sem);
-+
-+ if (ext3_orphan_add(handle, new_inode) < 0)
-+ goto out_journal;
-+
-+ if (ext3_orphan_del(handle, old_inode) < 0) {
-+ ext3_orphan_del(handle, new_inode);
-+ iput(new_inode);
-+ goto out_journal;
-+ }
-+
-+ ext3_journal_stop(handle, old_inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ J_ASSERT(list_empty(&new_inode->i_dentry));
-+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+ sbi->s_delete_blocks += blocks;
-+ sbi->s_delete_inodes++;
-+ spin_unlock(&sbi->s_delete_lock);
-+
-+ ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+ new_inode->i_ino, blocks);
-+
-+ wake_up(&sbi->s_delete_thread_queue);
-+ return;
-+
-+out_journal:
-+ ext3_journal_stop(handle, old_inode);
-+out_truncate:
-+ ext3_truncate(old_inode);
-+}
-+#endif /* EXT3_DELETE_THREAD */
-+
- /*
- * On success, We end up with an outstanding reference count against
- * iloc->bh. This _must_ be cleaned up later.
-Index: linux-2.4.21-suse/fs/ext3/file.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/file.c 2004-01-12 19:49:25.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/file.c 2004-01-13 17:38:10.000000000 +0300
-@@ -125,7 +125,11 @@
- };
-
- struct inode_operations ext3_file_inode_operations = {
-+#ifdef EXT3_DELETE_THREAD
-+ truncate: ext3_truncate_thread, /* BKL held */
-+#else
- truncate: ext3_truncate, /* BKL held */
-+#endif
- setattr: ext3_setattr, /* BKL held */
- setxattr: ext3_setxattr, /* BKL held */
- getxattr: ext3_getxattr, /* BKL held */
-Index: linux-2.4.21-suse/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.21-suse.orig/include/linux/ext3_fs.h 2004-01-13 17:38:09.000000000 +0300
-+++ linux-2.4.21-suse/include/linux/ext3_fs.h 2004-01-13 17:38:10.000000000 +0300
-@@ -193,6 +193,7 @@
- */
- #define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */
- #define EXT3_STATE_NEW 0x00000002 /* inode is newly created */
-+#define EXT3_STATE_DELETE 0x00000010 /* deferred delete inode */
-
- /*
- * ioctl commands
-@@ -320,6 +321,7 @@
- #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 */
-+#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -697,6 +699,9 @@
- extern void ext3_dirty_inode(struct inode *);
- extern int ext3_change_inode_journal_flag(struct inode *, int);
- extern void ext3_truncate (struct inode *);
-+#ifdef EXT3_DELETE_THREAD
-+extern void ext3_truncate_thread(struct inode *inode);
-+#endif
- extern void ext3_set_inode_flags(struct inode *);
-
- /* ioctl.c */
-Index: linux-2.4.21-suse/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.21-suse.orig/include/linux/ext3_fs_sb.h 2004-01-12 19:49:25.000000000 +0300
-+++ linux-2.4.21-suse/include/linux/ext3_fs_sb.h 2004-01-13 17:38:10.000000000 +0300
-@@ -29,6 +29,8 @@
-
- #define EXT3_MAX_GROUP_LOADED 8
-
-+#define EXT3_DELETE_THREAD
-+
- /*
- * third extended-fs super-block data in memory
- */
-@@ -76,6 +78,14 @@
- struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */
- wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+ spinlock_t s_delete_lock;
-+ struct list_head s_delete_list;
-+ unsigned long s_delete_blocks;
-+ unsigned long s_delete_inodes;
-+ wait_queue_head_t s_delete_thread_queue;
-+ wait_queue_head_t s_delete_waiter_queue;
-+#endif
- };
-
- #endif /* _LINUX_EXT3_FS_SB */
--- /dev/null
+ fs/ext3/ialloc.c | 6
+ fs/ext3/inode.c | 12
+ fs/ext3/super.c | 6
+ fs/ext3/xattr.c | 597 +++++++++++++++++++++++++++++++++++++++++++++-
+ include/linux/ext3_fs.h | 2
+ include/linux/ext3_fs_i.h | 3
+ 6 files changed, 615 insertions(+), 11 deletions(-)
+
+Index: linux-2.4.21-chaos/fs/ext3/ialloc.c
+===================================================================
+--- linux-2.4.21-chaos.orig/fs/ext3/ialloc.c 2003-12-12 17:39:10.000000000 +0300
++++ linux-2.4.21-chaos/fs/ext3/ialloc.c 2003-12-12 17:39:55.000000000 +0300
+@@ -580,6 +580,12 @@
+ insert_inode_hash(inode);
+ inode->i_generation = sbi->s_next_generation++;
+
++ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
++ EXT3_I(inode)->i_extra_isize = sizeof(__u16) /* i_extra_isize */
++ + sizeof(__u16); /* i_pad1 */
++ } else
++ EXT3_I(inode)->i_extra_isize = 0;
++
+ inode->u.ext3_i.i_state = EXT3_STATE_NEW;
+ err = ext3_get_inode_loc_new(inode, &iloc, 1);
+ if (err) goto fail;
+Index: linux-2.4.21-chaos/fs/ext3/inode.c
+===================================================================
+--- linux-2.4.21-chaos.orig/fs/ext3/inode.c 2003-12-12 17:39:11.000000000 +0300
++++ linux-2.4.21-chaos/fs/ext3/inode.c 2003-12-12 17:39:55.000000000 +0300
+@@ -2502,6 +2502,12 @@
+ ei->i_data[block] = iloc.raw_inode->i_block[block];
+ INIT_LIST_HEAD(&ei->i_orphan);
+
++ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
++ EXT3_I(inode)->i_extra_isize =
++ le16_to_cpu(raw_inode->i_extra_isize);
++ else
++ EXT3_I(inode)->i_extra_isize = 0;
++
+ if (S_ISREG(inode->i_mode)) {
+ inode->i_op = &ext3_file_inode_operations;
+ inode->i_fop = &ext3_file_operations;
+@@ -2564,6 +2570,8 @@
+ if (err)
+ goto out_brelse;
+ }
++ if (EXT3_I(inode)->i_state & EXT3_STATE_NEW)
++ memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb));
+ raw_inode->i_mode = cpu_to_le16(inode->i_mode);
+ if(!(test_opt(inode->i_sb, NO_UID32))) {
+ raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
+@@ -2646,6 +2654,10 @@
+ else for (block = 0; block < EXT3_N_BLOCKS; block++)
+ raw_inode->i_block[block] = ei->i_data[block];
+
++ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
++ raw_inode->i_extra_isize =
++ cpu_to_le16(EXT3_I(inode)->i_extra_isize);
++
+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ rc = ext3_journal_dirty_metadata(handle, bh);
+ if (!err)
+Index: linux-2.4.21-chaos/fs/ext3/xattr.c
+===================================================================
+--- linux-2.4.21-chaos.orig/fs/ext3/xattr.c 2003-12-12 17:38:44.000000000 +0300
++++ linux-2.4.21-chaos/fs/ext3/xattr.c 2003-12-12 17:42:58.000000000 +0300
+@@ -88,6 +88,9 @@
+ struct buffer_head *,
+ struct ext3_xattr_header *);
+
++int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,
++ const void *, size_t, int);
++
+ #ifdef CONFIG_EXT3_FS_XATTR_SHARING
+
+ static int ext3_xattr_cache_insert(struct buffer_head *);
+@@ -256,17 +259,12 @@
+ }
+
+ /*
+- * 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.
++ * ext3_xattr_block_get()
+ *
+- * Returns a negative error number on failure, or the number of bytes
+- * used / required on success.
++ * routine looks for attribute in EA block and returns it's value and size
+ */
+ int
+-ext3_xattr_get(struct inode *inode, int name_index, const char *name,
++ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ void *buffer, size_t buffer_size)
+ {
+ struct buffer_head *bh = NULL;
+@@ -359,6 +357,94 @@
+ }
+
+ /*
++ * ext3_xattr_ibody_get()
++ *
++ * routine looks for attribute in inode body and returns it's value and size
++ */
++int
++ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
++ void *buffer, size_t buffer_size)
++{
++ int size, name_len = strlen(name), storage_size;
++ struct ext3_xattr_entry *last;
++ struct ext3_inode *raw_inode;
++ struct ext3_iloc iloc;
++ char *start, *end;
++ int ret = -ENOENT;
++
++ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
++ return -ENOENT;
++
++ ret = ext3_get_inode_loc(inode, &iloc);
++ if (ret)
++ return ret;
++ raw_inode = iloc.raw_inode;
++
++ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
++ EXT3_GOOD_OLD_INODE_SIZE -
++ EXT3_I(inode)->i_extra_isize -
++ sizeof(__u32);
++ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
++ EXT3_I(inode)->i_extra_isize;
++ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
++ brelse(iloc.bh);
++ return -ENOENT;
++ }
++ start += sizeof(__u32);
++ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
++
++ last = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(last)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
++ if (le32_to_cpu(last->e_value_size) > storage_size ||
++ (char *) next >= end) {
++ ext3_error(inode->i_sb, "ext3_xattr_ibody_get",
++ "inode %ld", inode->i_ino);
++ brelse(iloc.bh);
++ return -EIO;
++ }
++ if (name_index == last->e_name_index &&
++ name_len == last->e_name_len &&
++ !memcmp(name, last->e_name, name_len))
++ goto found;
++ last = next;
++ }
++
++ /* can't find EA */
++ brelse(iloc.bh);
++ return -ENOENT;
++
++found:
++ size = le32_to_cpu(last->e_value_size);
++ if (buffer) {
++ ret = -ERANGE;
++ if (buffer_size >= size) {
++ memcpy(buffer, start + le16_to_cpu(last->e_value_offs),
++ size);
++ ret = size;
++ }
++ } else
++ ret = size;
++ brelse(iloc.bh);
++ return ret;
++}
++
++int ext3_xattr_get(struct inode *inode, int name_index, const char *name,
++ void *buffer, size_t buffer_size)
++{
++ int err;
++
++ /* try to find attribute in inode body */
++ err = ext3_xattr_ibody_get(inode, name_index, name,
++ buffer, buffer_size);
++ if (err < 0)
++ /* search was unsuccessful, try to find EA in dedicated block */
++ err = ext3_xattr_block_get(inode, name_index, name,
++ buffer, buffer_size);
++ return err;
++}
++
++/*
+ * ext3_xattr_list()
+ *
+ * Copy a list of attribute names into the buffer
+@@ -369,7 +455,7 @@
+ * used / required on success.
+ */
+ int
+-ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
++ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+ {
+ struct buffer_head *bh = NULL;
+ struct ext3_xattr_entry *entry;
+@@ -446,6 +532,131 @@
+ return error;
+ }
+
++/* ext3_xattr_ibody_list()
++ *
++ * generate list of attributes stored in inode body
++ */
++int
++ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
++{
++ struct ext3_xattr_entry *last;
++ struct ext3_inode *raw_inode;
++ char *start, *end, *buf;
++ struct ext3_iloc iloc;
++ int storage_size;
++ int ret;
++ int size = 0;
++
++ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
++ return 0;
++
++ ret = ext3_get_inode_loc(inode, &iloc);
++ if (ret)
++ return ret;
++ raw_inode = iloc.raw_inode;
++
++ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
++ EXT3_GOOD_OLD_INODE_SIZE -
++ EXT3_I(inode)->i_extra_isize -
++ sizeof(__u32);
++ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
++ EXT3_I(inode)->i_extra_isize;
++ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
++ brelse(iloc.bh);
++ return 0;
++ }
++ start += sizeof(__u32);
++ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
++
++ last = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(last)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
++ struct ext3_xattr_handler *handler;
++ if (le32_to_cpu(last->e_value_size) > storage_size ||
++ (char *) next >= end) {
++ ext3_error(inode->i_sb, "ext3_xattr_ibody_list",
++ "inode %ld", inode->i_ino);
++ brelse(iloc.bh);
++ return -EIO;
++ }
++ handler = ext3_xattr_handler(last->e_name_index);
++ if (handler)
++ size += handler->list(NULL, inode, last->e_name,
++ last->e_name_len);
++ last = next;
++ }
++
++ if (!buffer) {
++ ret = size;
++ goto cleanup;
++ } else {
++ ret = -ERANGE;
++ if (size > buffer_size)
++ goto cleanup;
++ }
++
++ last = (struct ext3_xattr_entry *) start;
++ buf = buffer;
++ while (!IS_LAST_ENTRY(last)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
++ struct ext3_xattr_handler *handler;
++ handler = ext3_xattr_handler(last->e_name_index);
++ if (handler)
++ buf += handler->list(buf, inode, last->e_name,
++ last->e_name_len);
++ last = next;
++ }
++ ret = size;
++cleanup:
++ brelse(iloc.bh);
++ return ret;
++}
++
++/*
++ * 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)
++{
++ int error;
++ int size = buffer_size;
++
++ /* get list of attributes stored in inode body */
++ error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
++ if (error < 0) {
++ /* some error occured while collecting
++ * attributes in inode body */
++ size = 0;
++ goto cleanup;
++ }
++ size = error;
++
++ /* get list of attributes stored in dedicated block */
++ if (buffer) {
++ buffer_size -= error;
++ if (buffer_size <= 0) {
++ buffer = NULL;
++ buffer_size = 0;
++ } else
++ buffer += error;
++ }
++
++ error = ext3_xattr_block_list(inode, buffer, buffer_size);
++ if (error < 0)
++ /* listing was successful, so we return len */
++ size = 0;
++
++cleanup:
++ return error + size;
++}
++
+ /*
+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
+ * not set, set it.
+@@ -480,6 +691,102 @@
+ */
+ int
+ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
++ const char *name, const void *value, size_t value_len,
++ int flags)
++{
++ struct ext3_xattr_entry entry;
++ int err, where = 0, found = 0, total;
++ int free1 = -1, free2 = -1;
++ int name_len;
++
++ 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 > inode->i_sb->s_blocksize)
++ return -ERANGE;
++
++ /* try to find attribute in inode body */
++ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
++ if (err == 0) {
++ /* found EA in inode */
++ found = 1;
++ where = 0;
++ } else if (err == -ENOENT) {
++ /* there is no such attribute in inode body */
++ /* try to find attribute in dedicated block */
++ err = ext3_xattr_block_find(inode, name_index, name,
++ &entry, &free2);
++ if (err != 0 && err != -ENOENT) {
++ /* not found EA in block */
++ goto finish;
++ } else if (err == 0) {
++ /* found EA in block */
++ where = 1;
++ found = 1;
++ }
++ } else
++ goto finish;
++
++ /* check flags: may replace? may create ? */
++ if (found && (flags & XATTR_CREATE)) {
++ err = -EEXIST;
++ goto finish;
++ } else if (!found && (flags & XATTR_REPLACE)) {
++ err = -ENODATA;
++ goto finish;
++ }
++
++ /* check if we have enough space to store attribute */
++ total = EXT3_XATTR_LEN(strlen(name)) + value_len;
++ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) {
++ /* have no enough space */
++ err = -ENOSPC;
++ goto finish;
++ }
++
++ /* time to remove attribute */
++ if (found) {
++ if (where == 0) {
++ /* EA is stored in inode body */
++ ext3_xattr_ibody_set(handle, inode, name_index, name,
++ NULL, 0, flags);
++ } else {
++ /* EA is stored in separated block */
++ ext3_xattr_block_set(handle, inode, name_index, name,
++ NULL, 0, flags);
++ }
++ }
++
++ /* try to store EA in inode body */
++ err = ext3_xattr_ibody_set(handle, inode, name_index, name,
++ value, value_len, flags);
++ if (err) {
++ /* can't store EA in inode body */
++ /* try to store in block */
++ err = ext3_xattr_block_set(handle, inode, name_index,
++ name, value, value_len, flags);
++ }
++
++finish:
++ return err;
++}
++
++/*
++ * ext3_xattr_block_set()
++ *
++ * this routine add/remove/replace attribute in EA block
++ */
++int
++ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index,
+ const char *name, const void *value, size_t value_len,
+ int flags)
+ {
+@@ -868,6 +1174,279 @@
+ }
+
+ /*
++ * ext3_xattr_ibody_find()
++ *
++ * search attribute and calculate free space in inode body
++ * NOTE: free space includes space our attribute hold
++ */
++int
++ext3_xattr_ibody_find(struct inode *inode, int name_index,
++ const char *name, struct ext3_xattr_entry *rentry, int *free)
++{
++ struct ext3_xattr_entry *last;
++ struct ext3_inode *raw_inode;
++ int name_len = strlen(name);
++ int err, storage_size;
++ struct ext3_iloc iloc;
++ char *start, *end;
++ int ret = -ENOENT;
++
++ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
++ return ret;
++
++ err = ext3_get_inode_loc(inode, &iloc);
++ if (err)
++ return -EIO;
++ raw_inode = iloc.raw_inode;
++
++ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
++ EXT3_GOOD_OLD_INODE_SIZE -
++ EXT3_I(inode)->i_extra_isize -
++ sizeof(__u32);
++ *free = storage_size - sizeof(__u32);
++ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
++ EXT3_I(inode)->i_extra_isize;
++ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
++ brelse(iloc.bh);
++ return -ENOENT;
++ }
++ start += sizeof(__u32);
++ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
++
++ last = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(last)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
++ if (le32_to_cpu(last->e_value_size) > storage_size ||
++ (char *) next >= end) {
++ ext3_error(inode->i_sb, "ext3_xattr_ibody_find",
++ "inode %ld", inode->i_ino);
++ brelse(iloc.bh);
++ return -EIO;
++ }
++
++ if (name_index == last->e_name_index &&
++ name_len == last->e_name_len &&
++ !memcmp(name, last->e_name, name_len)) {
++ memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
++ ret = 0;
++ } else {
++ *free -= EXT3_XATTR_LEN(last->e_name_len);
++ *free -= le32_to_cpu(last->e_value_size);
++ }
++ last = next;
++ }
++
++ brelse(iloc.bh);
++ return ret;
++}
++
++/*
++ * ext3_xattr_block_find()
++ *
++ * search attribute and calculate free space in EA block (if it allocated)
++ * NOTE: free space includes space our attribute hold
++ */
++int
++ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
++ struct ext3_xattr_entry *rentry, int *free)
++{
++ struct buffer_head *bh = NULL;
++ struct ext3_xattr_entry *entry;
++ char *end;
++ int name_len, error = -ENOENT;
++
++ if (!EXT3_I(inode)->i_file_acl) {
++ *free = inode->i_sb->s_blocksize -
++ sizeof(struct ext3_xattr_header) -
++ sizeof(__u32);
++ return -ENOENT;
++ }
++ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
++ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
++ 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,
++ EXT3_I(inode)->i_file_acl);
++ brelse(bh);
++ return -EIO;
++ }
++ /* find named attribute */
++ name_len = strlen(name);
++ *free = bh->b_size - sizeof(__u32);
++
++ 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) {
++ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
++ error = 0;
++ } else {
++ *free -= EXT3_XATTR_LEN(entry->e_name_len);
++ *free -= le32_to_cpu(entry->e_value_size);
++ }
++ entry = next;
++ }
++ brelse(bh);
++
++ return error;
++}
++
++/*
++ * ext3_xattr_inode_set()
++ *
++ * this routine add/remove/replace attribute in inode body
++ */
++int
++ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index,
++ const char *name, const void *value, size_t value_len,
++ int flags)
++{
++ struct ext3_xattr_entry *last, *next, *here = NULL;
++ struct ext3_inode *raw_inode;
++ int name_len = strlen(name);
++ int esize = EXT3_XATTR_LEN(name_len);
++ struct buffer_head *bh;
++ int err, storage_size;
++ struct ext3_iloc iloc;
++ int free, min_offs;
++ char *start, *end;
++
++ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
++ return -ENOSPC;
++
++ err = ext3_get_inode_loc(inode, &iloc);
++ if (err)
++ return err;
++ raw_inode = iloc.raw_inode;
++ bh = iloc.bh;
++
++ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
++ EXT3_GOOD_OLD_INODE_SIZE -
++ EXT3_I(inode)->i_extra_isize -
++ sizeof(__u32);
++ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
++ EXT3_I(inode)->i_extra_isize;
++ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) {
++ /* inode had no attributes before */
++ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC);
++ }
++ start += sizeof(__u32);
++ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
++ min_offs = storage_size;
++ free = storage_size - sizeof(__u32);
++
++ last = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(last)) {
++ next = EXT3_XATTR_NEXT(last);
++ if (le32_to_cpu(last->e_value_size) > storage_size ||
++ (char *) next >= end) {
++ ext3_error(inode->i_sb, "ext3_xattr_ibody_set",
++ "inode %ld", inode->i_ino);
++ brelse(bh);
++ return -EIO;
++ }
++
++ if (last->e_value_size) {
++ int offs = le16_to_cpu(last->e_value_offs);
++ if (offs < min_offs)
++ min_offs = offs;
++ }
++ if (name_index == last->e_name_index &&
++ name_len == last->e_name_len &&
++ !memcmp(name, last->e_name, name_len))
++ here = last;
++ else {
++ /* we calculate all but our attribute
++ * because it will be removed before changing */
++ free -= EXT3_XATTR_LEN(last->e_name_len);
++ free -= le32_to_cpu(last->e_value_size);
++ }
++ last = next;
++ }
++
++ if (value && (esize + value_len > free)) {
++ brelse(bh);
++ return -ENOSPC;
++ }
++
++ err = ext3_reserve_inode_write(handle, inode, &iloc);
++ if (err) {
++ brelse(bh);
++ return err;
++ }
++
++ if (here) {
++ /* time to remove old value */
++ struct ext3_xattr_entry *e;
++ int size = le32_to_cpu(here->e_value_size);
++ int border = le16_to_cpu(here->e_value_offs);
++ char *src;
++
++ /* move tail */
++ memmove(start + min_offs + size, start + min_offs,
++ border - min_offs);
++
++ /* recalculate offsets */
++ e = (struct ext3_xattr_entry *) start;
++ while (!IS_LAST_ENTRY(e)) {
++ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e);
++ int offs = le16_to_cpu(e->e_value_offs);
++ if (offs < border)
++ e->e_value_offs =
++ cpu_to_le16(offs + size);
++ e = next;
++ }
++ min_offs += size;
++
++ /* remove entry */
++ border = EXT3_XATTR_LEN(here->e_name_len);
++ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len);
++ size = (char *) last - src;
++ if ((char *) here + size > end)
++ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n",
++ __FILE__, __LINE__, here, size, end);
++ memmove(here, src, size);
++ last = (struct ext3_xattr_entry *) ((char *) last - border);
++ *((__u32 *) last) = 0;
++ }
++
++ if (value) {
++ int offs = min_offs - value_len;
++ /* use last to create new entry */
++ last->e_name_len = strlen(name);
++ last->e_name_index = name_index;
++ last->e_value_offs = cpu_to_le16(offs);
++ last->e_value_size = cpu_to_le32(value_len);
++ last->e_hash = last->e_value_block = 0;
++ memset(last->e_name, 0, esize);
++ memcpy(last->e_name, name, last->e_name_len);
++ if (start + offs + value_len > end)
++ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n",
++ __FILE__, __LINE__, start, offs,
++ value_len, end);
++ memcpy(start + offs, value, value_len);
++ last = EXT3_XATTR_NEXT(last);
++ *((__u32 *) last) = 0;
++ }
++
++ ext3_mark_iloc_dirty(handle, inode, &iloc);
++ brelse(bh);
++
++ return 0;
++}
++
++/*
+ * ext3_xattr_set_trans()
+ *
+ * Like ext3_xattr_set_handle, but start from an inode. This extended
+Index: linux-2.4.21-chaos/fs/ext3/super.c
+===================================================================
+--- linux-2.4.21-chaos.orig/fs/ext3/super.c 2003-12-12 17:39:11.000000000 +0300
++++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-12 17:39:55.000000000 +0300
+@@ -1354,8 +1354,10 @@
+ } else {
+ sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
+ sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
+- if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) {
+- printk (KERN_ERR
++ if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
++ (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
++ (sbi->s_inode_size > blocksize)) {
++ printk (KERN_ERR
+ "EXT3-fs: unsupported inode size: %d\n",
+ sbi->s_inode_size);
+ goto failed_mount;
+Index: linux-2.4.21-chaos/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h 2003-12-12 17:39:10.000000000 +0300
++++ linux-2.4.21-chaos/include/linux/ext3_fs.h 2003-12-12 17:39:55.000000000 +0300
+@@ -268,6 +268,8 @@
+ __u32 m_i_reserved2[2];
+ } masix2;
+ } osd2; /* OS dependent 2 */
++ __u16 i_extra_isize;
++ __u16 i_pad1;
+ };
+
+ #define i_size_high i_dir_acl
+Index: linux-2.4.21-chaos/include/linux/ext3_fs_i.h
+===================================================================
+--- linux-2.4.21-chaos.orig/include/linux/ext3_fs_i.h 2003-12-05 16:54:33.000000000 +0300
++++ linux-2.4.21-chaos/include/linux/ext3_fs_i.h 2003-12-12 17:39:55.000000000 +0300
+@@ -76,6 +76,9 @@
+ */
+ loff_t i_disksize;
+
++ /* on-disk additional length */
++ __u16 i_extra_isize;
++
+ /*
+ * truncate_sem is for serialising ext3_truncate() against
+ * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's
+++ /dev/null
-Index: linux-2.4.20-rh-20.9/fs/ext3/extents.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/fs/ext3/extents.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.20-rh-20.9/fs/ext3/extents.c 2004-11-03 00:31:41.927134640 +0300
-@@ -0,0 +1,2269 @@
-+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
-+ * Written by Alex Tomas <alex@clusterfs.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program 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 Licens
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
-+ */
-+
-+/*
-+ * Extents support for EXT3
-+ *
-+ * TODO:
-+ * - ext3_ext_walk_space() sould not use ext3_ext_find_extent()
-+ * - ext3_ext_calc_credits() could take 'mergable' into account
-+ * - ext3*_error() should be used in some situations
-+ * - find_goal() [to be tested and improved]
-+ * - smart tree reduction
-+ * - arch-independence
-+ * common on-disk format for big/little-endian arch
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/time.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/jbd.h>
-+#include <linux/locks.h>
-+#include <linux/smp_lock.h>
-+#include <linux/highuid.h>
-+#include <linux/pagemap.h>
-+#include <linux/quotaops.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
-+#include <linux/ext3_extents.h>
-+#include <asm/uaccess.h>
-+
-+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
-+{
-+ int err;
-+
-+ if (handle->h_buffer_credits > needed)
-+ return handle;
-+ if (!ext3_journal_extend(handle, needed))
-+ return handle;
-+ err = ext3_journal_restart(handle, needed);
-+
-+ return handle;
-+}
-+
-+static int inline
-+ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree)
-+{
-+ if (tree->ops->get_write_access)
-+ return tree->ops->get_write_access(h,tree->buffer);
-+ else
-+ return 0;
-+}
-+
-+static int inline
-+ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree)
-+{
-+ if (tree->ops->mark_buffer_dirty)
-+ return tree->ops->mark_buffer_dirty(h,tree->buffer);
-+ else
-+ return 0;
-+}
-+
-+/*
-+ * could return:
-+ * - EROFS
-+ * - ENOMEM
-+ */
-+static int ext3_ext_get_access(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ int err;
-+
-+ if (path->p_bh) {
-+ /* path points to block */
-+ err = ext3_journal_get_write_access(handle, path->p_bh);
-+ } else {
-+ /* path points to leaf/index in inode body */
-+ err = ext3_ext_get_access_for_root(handle, tree);
-+ }
-+ return err;
-+}
-+
-+/*
-+ * could return:
-+ * - EROFS
-+ * - ENOMEM
-+ * - EIO
-+ */
-+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ int err;
-+ if (path->p_bh) {
-+ /* path points to block */
-+ err =ext3_journal_dirty_metadata(handle, path->p_bh);
-+ } else {
-+ /* path points to leaf/index in inode body */
-+ err = ext3_ext_mark_root_dirty(handle, tree);
-+ }
-+ return err;
-+}
-+
-+static int inline
-+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, struct ext3_extent *ex,
-+ int *err)
-+{
-+ int goal, depth, newblock;
-+ struct inode *inode;
-+
-+ EXT_ASSERT(tree);
-+ if (tree->ops->new_block)
-+ return tree->ops->new_block(handle, tree, path, ex, err);
-+
-+ inode = tree->inode;
-+ depth = EXT_DEPTH(tree);
-+ if (path && depth > 0) {
-+ goal = path[depth-1].p_block;
-+ } else {
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+ unsigned long bg_start;
-+ unsigned long colour;
-+
-+ bg_start = (ei->i_block_group *
-+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
-+ colour = (current->pid % 16) *
-+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
-+ goal = bg_start + colour;
-+ }
-+
-+ newblock = ext3_new_block(handle, inode, goal, 0, 0, err);
-+ return newblock;
-+}
-+
-+static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree)
-+{
-+ struct ext3_extent_header *neh;
-+ neh = EXT_ROOT_HDR(tree);
-+ neh->eh_generation++;
-+}
-+
-+static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
-+{
-+ int size;
-+
-+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
-+#ifdef AGRESSIVE_TEST
-+ size = 6;
-+#endif
-+ return size;
-+}
-+
-+static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree)
-+{
-+ int size;
-+
-+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
-+#ifdef AGRESSIVE_TEST
-+ size = 5;
-+#endif
-+ return size;
-+}
-+
-+static inline int ext3_ext_space_root(struct ext3_extents_tree *tree)
-+{
-+ int size;
-+
-+ size = (tree->buffer_len - sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
-+#ifdef AGRESSIVE_TEST
-+ size = 3;
-+#endif
-+ return size;
-+}
-+
-+static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree)
-+{
-+ int size;
-+
-+ size = (tree->buffer_len -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
-+#ifdef AGRESSIVE_TEST
-+ size = 4;
-+#endif
-+ return size;
-+}
-+
-+static void ext3_ext_show_path(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+#ifdef EXT_DEBUG
-+ int k, l = path->p_depth;
-+
-+ ext_debug(tree, "path:");
-+ for (k = 0; k <= l; k++, path++) {
-+ if (path->p_idx) {
-+ ext_debug(tree, " %d->%d", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
-+ } else if (path->p_ext) {
-+ ext_debug(tree, " %d:%d:%d",
-+ path->p_ext->ee_block,
-+ path->p_ext->ee_len,
-+ path->p_ext->ee_start);
-+ } else
-+ ext_debug(tree, " []");
-+ }
-+ ext_debug(tree, "\n");
-+#endif
-+}
-+
-+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+#ifdef EXT_DEBUG
-+ int depth = EXT_DEPTH(tree);
-+ struct ext3_extent_header *eh;
-+ struct ext3_extent *ex;
-+ int i;
-+
-+ if (!path)
-+ return;
-+
-+ eh = path[depth].p_hdr;
-+ ex = EXT_FIRST_EXTENT(eh);
-+
-+ for (i = 0; i < eh->eh_entries; i++, ex++) {
-+ ext_debug(tree, "%d:%d:%d ",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
-+ }
-+ ext_debug(tree, "\n");
-+#endif
-+}
-+
-+static void ext3_ext_drop_refs(struct ext3_ext_path *path)
-+{
-+ int depth = path->p_depth;
-+ int i;
-+
-+ for (i = 0; i <= depth; i++, path++)
-+ if (path->p_bh) {
-+ brelse(path->p_bh);
-+ path->p_bh = NULL;
-+ }
-+}
-+
-+/*
-+ * binary search for closest index by given block
-+ */
-+static inline void
-+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
-+{
-+ struct ext3_extent_header *eh = path->p_hdr;
-+ struct ext3_extent_idx *ix;
-+ int l = 0, k, r;
-+
-+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(eh->eh_entries <= eh->eh_max);
-+ EXT_ASSERT(eh->eh_entries > 0);
-+
-+ ext_debug(tree, "binsearch for %d(idx): ", block);
-+
-+ path->p_idx = ix = EXT_FIRST_INDEX(eh);
-+
-+ r = k = eh->eh_entries;
-+ while (k > 1) {
-+ k = (r - l) / 2;
-+ if (block < ix[l + k].ei_block)
-+ r -= k;
-+ else
-+ l += k;
-+ ext_debug(tree, "%d:%d:%d ", k, l, r);
-+ }
-+
-+ ix += l;
-+ path->p_idx = ix;
-+ ext_debug(tree, " -> %d->%d ", path->p_idx->ei_block, path->p_idx->ei_leaf);
-+
-+ while (l++ < r) {
-+ if (block < ix->ei_block)
-+ break;
-+ path->p_idx = ix++;
-+ }
-+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
-+
-+#ifdef CHECK_BINSEARCH
-+ {
-+ struct ext3_extent_idx *chix;
-+
-+ chix = ix = EXT_FIRST_INDEX(eh);
-+ for (k = 0; k < eh->eh_entries; k++, ix++) {
-+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
-+ printk("k=%d, ix=0x%p, first=0x%p\n", k,
-+ ix, EXT_FIRST_INDEX(eh));
-+ printk("%u <= %u\n",
-+ ix->ei_block,ix[-1].ei_block);
-+ }
-+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
-+ if (block < ix->ei_block)
-+ break;
-+ chix = ix;
-+ }
-+ EXT_ASSERT(chix == path->p_idx);
-+ }
-+#endif
-+
-+}
-+
-+/*
-+ * binary search for closest extent by given block
-+ */
-+static inline void
-+ext3_ext_binsearch(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
-+{
-+ struct ext3_extent_header *eh = path->p_hdr;
-+ struct ext3_extent *ex;
-+ int l = 0, k, r;
-+
-+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(eh->eh_entries <= eh->eh_max);
-+
-+ if (eh->eh_entries == 0) {
-+ /*
-+ * this leaf is empty yet:
-+ * we get such a leaf in split/add case
-+ */
-+ return;
-+ }
-+
-+ ext_debug(tree, "binsearch for %d: ", block);
-+
-+ path->p_ext = ex = EXT_FIRST_EXTENT(eh);
-+
-+ r = k = eh->eh_entries;
-+ while (k > 1) {
-+ k = (r - l) / 2;
-+ if (block < ex[l + k].ee_block)
-+ r -= k;
-+ else
-+ l += k;
-+ ext_debug(tree, "%d:%d:%d ", k, l, r);
-+ }
-+
-+ ex += l;
-+ path->p_ext = ex;
-+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
-+
-+ while (l++ < r) {
-+ if (block < ex->ee_block)
-+ break;
-+ path->p_ext = ex++;
-+ }
-+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
-+
-+#ifdef CHECK_BINSEARCH
-+ {
-+ struct ext3_extent *chex;
-+
-+ chex = ex = EXT_FIRST_EXTENT(eh);
-+ for (k = 0; k < eh->eh_entries; k++, ex++) {
-+ EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block);
-+ if (block < ex->ee_block)
-+ break;
-+ chex = ex;
-+ }
-+ EXT_ASSERT(chex == path->p_ext);
-+ }
-+#endif
-+
-+}
-+
-+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
-+{
-+ struct ext3_extent_header *eh;
-+
-+ BUG_ON(tree->buffer_len == 0);
-+ ext3_ext_get_access_for_root(handle, tree);
-+ eh = EXT_ROOT_HDR(tree);
-+ eh->eh_depth = 0;
-+ eh->eh_entries = 0;
-+ eh->eh_magic = EXT3_EXT_MAGIC;
-+ eh->eh_max = ext3_ext_space_root(tree);
-+ ext3_ext_mark_root_dirty(handle, tree);
-+ ext3_ext_invalidate_cache(tree);
-+ return 0;
-+}
-+
-+struct ext3_ext_path *
-+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
-+ struct ext3_ext_path *path)
-+{
-+ struct ext3_extent_header *eh;
-+ struct buffer_head *bh;
-+ int depth, i, ppos = 0;
-+
-+ EXT_ASSERT(tree);
-+ EXT_ASSERT(tree->inode);
-+ EXT_ASSERT(tree->root);
-+
-+ eh = EXT_ROOT_HDR(tree);
-+ EXT_ASSERT(eh);
-+ i = depth = EXT_DEPTH(tree);
-+ EXT_ASSERT(eh->eh_max);
-+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(i == 0 || eh->eh_entries > 0);
-+
-+ /* account possible depth increase */
-+ if (!path) {
-+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+ GFP_NOFS);
-+ if (!path)
-+ return ERR_PTR(-ENOMEM);
-+ }
-+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
-+ path[0].p_hdr = eh;
-+
-+ /* walk through the tree */
-+ while (i) {
-+ ext_debug(tree, "depth %d: num %d, max %d\n",
-+ ppos, eh->eh_entries, eh->eh_max);
-+ ext3_ext_binsearch_idx(tree, path + ppos, block);
-+ path[ppos].p_block = path[ppos].p_idx->ei_leaf;
-+ path[ppos].p_depth = i;
-+ path[ppos].p_ext = NULL;
-+
-+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
-+ if (!bh) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ return ERR_PTR(-EIO);
-+ }
-+ eh = EXT_BLOCK_HDR(bh);
-+ ppos++;
-+ EXT_ASSERT(ppos <= depth);
-+ path[ppos].p_bh = bh;
-+ path[ppos].p_hdr = eh;
-+ i--;
-+ }
-+
-+ path[ppos].p_depth = i;
-+ path[ppos].p_hdr = eh;
-+ path[ppos].p_ext = NULL;
-+
-+ /* find extent */
-+ ext3_ext_binsearch(tree, path + ppos, block);
-+
-+ ext3_ext_show_path(tree, path);
-+
-+ return path;
-+}
-+
-+/*
-+ * insert new index [logical;ptr] into the block at cupr
-+ * it check where to insert: before curp or after curp
-+ */
-+static int ext3_ext_insert_index(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *curp,
-+ int logical, int ptr)
-+{
-+ struct ext3_extent_idx *ix;
-+ int len, err;
-+
-+ if ((err = ext3_ext_get_access(handle, tree, curp)))
-+ return err;
-+
-+ EXT_ASSERT(logical != curp->p_idx->ei_block);
-+ len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
-+ if (logical > curp->p_idx->ei_block) {
-+ /* insert after */
-+ if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) {
-+ len = (len - 1) * sizeof(struct ext3_extent_idx);
-+ len = len < 0 ? 0 : len;
-+ ext_debug(tree, "insert new index %d after: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ (curp->p_idx + 1), (curp->p_idx + 2));
-+ memmove(curp->p_idx + 2, curp->p_idx + 1, len);
-+ }
-+ ix = curp->p_idx + 1;
-+ } else {
-+ /* insert before */
-+ len = len * sizeof(struct ext3_extent_idx);
-+ len = len < 0 ? 0 : len;
-+ ext_debug(tree, "insert new index %d before: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ curp->p_idx, (curp->p_idx + 1));
-+ memmove(curp->p_idx + 1, curp->p_idx, len);
-+ ix = curp->p_idx;
-+ }
-+
-+ ix->ei_block = logical;
-+ ix->ei_leaf = ptr;
-+ curp->p_hdr->eh_entries++;
-+
-+ EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
-+ EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr));
-+
-+ err = ext3_ext_dirty(handle, tree, curp);
-+ ext3_std_error(tree->inode->i_sb, err);
-+
-+ return err;
-+}
-+
-+/*
-+ * routine inserts new subtree into the path, using free index entry
-+ * at depth 'at:
-+ * - allocates all needed blocks (new leaf and all intermediate index blocks)
-+ * - makes decision where to split
-+ * - moves remaining extens and index entries (right to the split point)
-+ * into the newly allocated blocks
-+ * - initialize subtree
-+ */
-+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext, int at)
-+{
-+ struct buffer_head *bh = NULL;
-+ int depth = EXT_DEPTH(tree);
-+ struct ext3_extent_header *neh;
-+ struct ext3_extent_idx *fidx;
-+ struct ext3_extent *ex;
-+ int i = at, k, m, a;
-+ unsigned long newblock, oldblock, border;
-+ int *ablocks = NULL; /* array of allocated blocks */
-+ int err = 0;
-+
-+ /* make decision: where to split? */
-+ /* FIXME: now desicion is simplest: at current extent */
-+
-+ /* if current leaf will be splitted, then we should use
-+ * border from split point */
-+ EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr));
-+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
-+ border = path[depth].p_ext[1].ee_block;
-+ ext_debug(tree, "leaf will be splitted."
-+ " next leaf starts at %d\n",
-+ (int)border);
-+ } else {
-+ border = newext->ee_block;
-+ ext_debug(tree, "leaf will be added."
-+ " next leaf starts at %d\n",
-+ (int)border);
-+ }
-+
-+ /*
-+ * if error occurs, then we break processing
-+ * and turn filesystem read-only. so, index won't
-+ * be inserted and tree will be in consistent
-+ * state. next mount will repair buffers too
-+ */
-+
-+ /*
-+ * get array to track all allocated blocks
-+ * we need this to handle errors and free blocks
-+ * upon them
-+ */
-+ ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS);
-+ if (!ablocks)
-+ return -ENOMEM;
-+ memset(ablocks, 0, sizeof(unsigned long) * depth);
-+
-+ /* allocate all needed blocks */
-+ ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at);
-+ for (a = 0; a < depth - at; a++) {
-+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
-+ if (newblock == 0)
-+ goto cleanup;
-+ ablocks[a] = newblock;
-+ }
-+
-+ /* initialize new leaf */
-+ newblock = ablocks[--a];
-+ EXT_ASSERT(newblock);
-+ bh = sb_getblk(tree->inode->i_sb, newblock);
-+ if (!bh) {
-+ err = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(bh);
-+
-+ if ((err = ext3_journal_get_create_access(handle, bh)))
-+ goto cleanup;
-+
-+ neh = EXT_BLOCK_HDR(bh);
-+ neh->eh_entries = 0;
-+ neh->eh_max = ext3_ext_space_block(tree);
-+ neh->eh_magic = EXT3_EXT_MAGIC;
-+ neh->eh_depth = 0;
-+ ex = EXT_FIRST_EXTENT(neh);
-+
-+ /* move remain of path[depth] to the new leaf */
-+ EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max);
-+ /* start copy from next extent */
-+ /* TODO: we could do it by single memmove */
-+ m = 0;
-+ path[depth].p_ext++;
-+ while (path[depth].p_ext <=
-+ EXT_MAX_EXTENT(path[depth].p_hdr)) {
-+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
-+ path[depth].p_ext->ee_block,
-+ path[depth].p_ext->ee_start,
-+ path[depth].p_ext->ee_len,
-+ newblock);
-+ memmove(ex++, path[depth].p_ext++,
-+ sizeof(struct ext3_extent));
-+ neh->eh_entries++;
-+ m++;
-+ }
-+ mark_buffer_uptodate(bh, 1);
-+ unlock_buffer(bh);
-+
-+ if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+ goto cleanup;
-+ brelse(bh);
-+ bh = NULL;
-+
-+ /* correct old leaf */
-+ if (m) {
-+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
-+ goto cleanup;
-+ path[depth].p_hdr->eh_entries -= m;
-+ if ((err = ext3_ext_dirty(handle, tree, path + depth)))
-+ goto cleanup;
-+
-+ }
-+
-+ /* create intermediate indexes */
-+ k = depth - at - 1;
-+ EXT_ASSERT(k >= 0);
-+ if (k)
-+ ext_debug(tree, "create %d intermediate indices\n", k);
-+ /* insert new index into current index block */
-+ /* current depth stored in i var */
-+ i = depth - 1;
-+ while (k--) {
-+ oldblock = newblock;
-+ newblock = ablocks[--a];
-+ bh = sb_getblk(tree->inode->i_sb, newblock);
-+ if (!bh) {
-+ err = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(bh);
-+
-+ if ((err = ext3_journal_get_create_access(handle, bh)))
-+ goto cleanup;
-+
-+ neh = EXT_BLOCK_HDR(bh);
-+ neh->eh_entries = 1;
-+ neh->eh_magic = EXT3_EXT_MAGIC;
-+ neh->eh_max = ext3_ext_space_block_idx(tree);
-+ neh->eh_depth = depth - i;
-+ fidx = EXT_FIRST_INDEX(neh);
-+ fidx->ei_block = border;
-+ fidx->ei_leaf = oldblock;
-+
-+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
-+ i, newblock, border, oldblock);
-+ /* copy indexes */
-+ m = 0;
-+ path[i].p_idx++;
-+
-+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+ EXT_MAX_INDEX(path[i].p_hdr));
-+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+ EXT_LAST_INDEX(path[i].p_hdr));
-+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
-+ ext_debug(tree, "%d: move %d:%d in new index %lu\n",
-+ i, path[i].p_idx->ei_block,
-+ path[i].p_idx->ei_leaf, newblock);
-+ memmove(++fidx, path[i].p_idx++,
-+ sizeof(struct ext3_extent_idx));
-+ neh->eh_entries++;
-+ EXT_ASSERT(neh->eh_entries <= neh->eh_max);
-+ m++;
-+ }
-+ mark_buffer_uptodate(bh, 1);
-+ unlock_buffer(bh);
-+
-+ if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+ goto cleanup;
-+ brelse(bh);
-+ bh = NULL;
-+
-+ /* correct old index */
-+ if (m) {
-+ err = ext3_ext_get_access(handle, tree, path + i);
-+ if (err)
-+ goto cleanup;
-+ path[i].p_hdr->eh_entries -= m;
-+ err = ext3_ext_dirty(handle, tree, path + i);
-+ if (err)
-+ goto cleanup;
-+ }
-+
-+ i--;
-+ }
-+
-+ /* insert new index */
-+ if (!err)
-+ err = ext3_ext_insert_index(handle, tree, path + at,
-+ border, newblock);
-+
-+cleanup:
-+ if (bh) {
-+ if (buffer_locked(bh))
-+ unlock_buffer(bh);
-+ brelse(bh);
-+ }
-+
-+ if (err) {
-+ /* free all allocated blocks in error case */
-+ for (i = 0; i < depth; i++) {
-+ if (!ablocks[i])
-+ continue;
-+ ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
-+ }
-+ }
-+ kfree(ablocks);
-+
-+ return err;
-+}
-+
-+/*
-+ * routine implements tree growing procedure:
-+ * - allocates new block
-+ * - moves top-level data (index block or leaf) into the new block
-+ * - initialize new top-level, creating index that points to the
-+ * just created block
-+ */
-+static int ext3_ext_grow_indepth(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
-+{
-+ struct ext3_ext_path *curp = path;
-+ struct ext3_extent_header *neh;
-+ struct ext3_extent_idx *fidx;
-+ struct buffer_head *bh;
-+ unsigned long newblock;
-+ int err = 0;
-+
-+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
-+ if (newblock == 0)
-+ return err;
-+
-+ bh = sb_getblk(tree->inode->i_sb, newblock);
-+ if (!bh) {
-+ err = -EIO;
-+ ext3_std_error(tree->inode->i_sb, err);
-+ return err;
-+ }
-+ lock_buffer(bh);
-+
-+ if ((err = ext3_journal_get_create_access(handle, bh))) {
-+ unlock_buffer(bh);
-+ goto out;
-+ }
-+
-+ /* move top-level index/leaf into new block */
-+ memmove(bh->b_data, curp->p_hdr, tree->buffer_len);
-+
-+ /* set size of new block */
-+ neh = EXT_BLOCK_HDR(bh);
-+ /* old root could have indexes or leaves
-+ * so calculate eh_max right way */
-+ if (EXT_DEPTH(tree))
-+ neh->eh_max = ext3_ext_space_block_idx(tree);
-+ else
-+ neh->eh_max = ext3_ext_space_block(tree);
-+ neh->eh_magic = EXT3_EXT_MAGIC;
-+ mark_buffer_uptodate(bh, 1);
-+ unlock_buffer(bh);
-+
-+ if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+ goto out;
-+
-+ /* create index in new top-level index: num,max,pointer */
-+ if ((err = ext3_ext_get_access(handle, tree, curp)))
-+ goto out;
-+
-+ curp->p_hdr->eh_magic = EXT3_EXT_MAGIC;
-+ curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree);
-+ curp->p_hdr->eh_entries = 1;
-+ curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
-+ /* FIXME: it works, but actually path[0] can be index */
-+ curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
-+ curp->p_idx->ei_leaf = newblock;
-+
-+ neh = EXT_ROOT_HDR(tree);
-+ fidx = EXT_FIRST_INDEX(neh);
-+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
-+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
-+
-+ neh->eh_depth = path->p_depth + 1;
-+ err = ext3_ext_dirty(handle, tree, curp);
-+out:
-+ brelse(bh);
-+
-+ return err;
-+}
-+
-+/*
-+ * routine finds empty index and adds new leaf. if no free index found
-+ * then it requests in-depth growing
-+ */
-+static int ext3_ext_create_new_leaf(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
-+{
-+ struct ext3_ext_path *curp;
-+ int depth, i, err = 0;
-+
-+repeat:
-+ i = depth = EXT_DEPTH(tree);
-+
-+ /* walk up to the tree and look for free index entry */
-+ curp = path + depth;
-+ while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {
-+ i--;
-+ curp--;
-+ }
-+
-+ /* we use already allocated block for index block
-+ * so, subsequent data blocks should be contigoues */
-+ if (EXT_HAS_FREE_INDEX(curp)) {
-+ /* if we found index with free entry, then use that
-+ * entry: create all needed subtree and add new leaf */
-+ err = ext3_ext_split(handle, tree, path, newext, i);
-+
-+ /* refill path */
-+ ext3_ext_drop_refs(path);
-+ path = ext3_ext_find_extent(tree, newext->ee_block, path);
-+ if (IS_ERR(path))
-+ err = PTR_ERR(path);
-+ } else {
-+ /* tree is full, time to grow in depth */
-+ err = ext3_ext_grow_indepth(handle, tree, path, newext);
-+
-+ /* refill path */
-+ ext3_ext_drop_refs(path);
-+ path = ext3_ext_find_extent(tree, newext->ee_block, path);
-+ if (IS_ERR(path))
-+ err = PTR_ERR(path);
-+
-+ /*
-+ * only first (depth 0 -> 1) produces free space
-+ * in all other cases we have to split growed tree
-+ */
-+ depth = EXT_DEPTH(tree);
-+ if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
-+ /* now we need split */
-+ goto repeat;
-+ }
-+ }
-+
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+/*
-+ * returns allocated block in subsequent extent or EXT_MAX_BLOCK
-+ * NOTE: it consider block number from index entry as
-+ * allocated block. thus, index entries have to be consistent
-+ * with leafs
-+ */
-+static unsigned long
-+ext3_ext_next_allocated_block(struct ext3_ext_path *path)
-+{
-+ int depth;
-+
-+ EXT_ASSERT(path != NULL);
-+ depth = path->p_depth;
-+
-+ if (depth == 0 && path->p_ext == NULL)
-+ return EXT_MAX_BLOCK;
-+
-+ /* FIXME: what if index isn't full ?! */
-+ while (depth >= 0) {
-+ if (depth == path->p_depth) {
-+ /* leaf */
-+ if (path[depth].p_ext !=
-+ EXT_LAST_EXTENT(path[depth].p_hdr))
-+ return path[depth].p_ext[1].ee_block;
-+ } else {
-+ /* index */
-+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
-+ return path[depth].p_idx[1].ei_block;
-+ }
-+ depth--;
-+ }
-+
-+ return EXT_MAX_BLOCK;
-+}
-+
-+/*
-+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
-+ */
-+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ int depth;
-+
-+ EXT_ASSERT(path != NULL);
-+ depth = path->p_depth;
-+
-+ /* zero-tree has no leaf blocks at all */
-+ if (depth == 0)
-+ return EXT_MAX_BLOCK;
-+
-+ /* go to index block */
-+ depth--;
-+
-+ while (depth >= 0) {
-+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
-+ return path[depth].p_idx[1].ei_block;
-+ depth--;
-+ }
-+
-+ return EXT_MAX_BLOCK;
-+}
-+
-+/*
-+ * if leaf gets modified and modified extent is first in the leaf
-+ * then we have to correct all indexes above
-+ * TODO: do we need to correct tree in all cases?
-+ */
-+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ struct ext3_extent_header *eh;
-+ int depth = EXT_DEPTH(tree);
-+ struct ext3_extent *ex;
-+ unsigned long border;
-+ int k, err = 0;
-+
-+ eh = path[depth].p_hdr;
-+ ex = path[depth].p_ext;
-+ EXT_ASSERT(ex);
-+ EXT_ASSERT(eh);
-+
-+ if (depth == 0) {
-+ /* there is no tree at all */
-+ return 0;
-+ }
-+
-+ if (ex != EXT_FIRST_EXTENT(eh)) {
-+ /* we correct tree if first leaf got modified only */
-+ return 0;
-+ }
-+
-+ /*
-+ * TODO: we need correction if border is smaller then current one
-+ */
-+ k = depth - 1;
-+ border = path[depth].p_ext->ee_block;
-+ if ((err = ext3_ext_get_access(handle, tree, path + k)))
-+ return err;
-+ path[k].p_idx->ei_block = border;
-+ if ((err = ext3_ext_dirty(handle, tree, path + k)))
-+ return err;
-+
-+ while (k--) {
-+ /* change all left-side indexes */
-+ if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
-+ break;
-+ if ((err = ext3_ext_get_access(handle, tree, path + k)))
-+ break;
-+ path[k].p_idx->ei_block = border;
-+ if ((err = ext3_ext_dirty(handle, tree, path + k)))
-+ break;
-+ }
-+
-+ return err;
-+}
-+
-+static int inline
-+ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
-+{
-+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
-+ return 0;
-+
-+#ifdef AGRESSIVE_TEST
-+ if (ex1->ee_len >= 4)
-+ return 0;
-+#endif
-+
-+ if (!tree->ops->mergable)
-+ return 1;
-+
-+ return tree->ops->mergable(ex1, ex2);
-+}
-+
-+/*
-+ * this routine tries to merge requsted extent into the existing
-+ * extent or inserts requested extent as new one into the tree,
-+ * creating new leaf in no-space case
-+ */
-+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
-+{
-+ struct ext3_extent_header * eh;
-+ struct ext3_extent *ex, *fex;
-+ struct ext3_extent *nearex; /* nearest extent */
-+ struct ext3_ext_path *npath = NULL;
-+ int depth, len, err, next;
-+
-+ EXT_ASSERT(newext->ee_len > 0);
-+ EXT_ASSERT(newext->ee_len < EXT_CACHE_MARK);
-+ depth = EXT_DEPTH(tree);
-+ ex = path[depth].p_ext;
-+ EXT_ASSERT(path[depth].p_hdr);
-+
-+ /* try to insert block into found extent and return */
-+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
-+ ext_debug(tree, "append %d block to %d:%d (from %d)\n",
-+ newext->ee_len, ex->ee_block, ex->ee_len,
-+ ex->ee_start);
-+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
-+ return err;
-+ ex->ee_len += newext->ee_len;
-+ eh = path[depth].p_hdr;
-+ nearex = ex;
-+ goto merge;
-+ }
-+
-+repeat:
-+ depth = EXT_DEPTH(tree);
-+ eh = path[depth].p_hdr;
-+ if (eh->eh_entries < eh->eh_max)
-+ goto has_space;
-+
-+ /* probably next leaf has space for us? */
-+ fex = EXT_LAST_EXTENT(eh);
-+ next = ext3_ext_next_leaf_block(tree, path);
-+ if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) {
-+ ext_debug(tree, "next leaf block - %d\n", next);
-+ EXT_ASSERT(!npath);
-+ npath = ext3_ext_find_extent(tree, next, NULL);
-+ if (IS_ERR(npath))
-+ return PTR_ERR(npath);
-+ EXT_ASSERT(npath->p_depth == path->p_depth);
-+ eh = npath[depth].p_hdr;
-+ if (eh->eh_entries < eh->eh_max) {
-+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->eh_entries);
-+ path = npath;
-+ goto repeat;
-+ }
-+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->eh_entries, eh->eh_max);
-+ }
-+
-+ /*
-+ * there is no free space in found leaf
-+ * we're gonna add new leaf in the tree
-+ */
-+ err = ext3_ext_create_new_leaf(handle, tree, path, newext);
-+ if (err)
-+ goto cleanup;
-+ depth = EXT_DEPTH(tree);
-+ eh = path[depth].p_hdr;
-+
-+has_space:
-+ nearex = path[depth].p_ext;
-+
-+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
-+ goto cleanup;
-+
-+ if (!nearex) {
-+ /* there is no extent in this leaf, create first one */
-+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len);
-+ path[depth].p_ext = EXT_FIRST_EXTENT(eh);
-+ } else if (newext->ee_block > nearex->ee_block) {
-+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
-+ if (nearex != EXT_LAST_EXTENT(eh)) {
-+ len = EXT_MAX_EXTENT(eh) - nearex;
-+ len = (len - 1) * sizeof(struct ext3_extent);
-+ len = len < 0 ? 0 : len;
-+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
-+ memmove(nearex + 2, nearex + 1, len);
-+ }
-+ path[depth].p_ext = nearex + 1;
-+ } else {
-+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
-+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
-+ len = len < 0 ? 0 : len;
-+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start, newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
-+ memmove(nearex + 1, nearex, len);
-+ path[depth].p_ext = nearex;
-+ }
-+
-+ eh->eh_entries++;
-+ nearex = path[depth].p_ext;
-+ nearex->ee_block = newext->ee_block;
-+ nearex->ee_start = newext->ee_start;
-+ nearex->ee_len = newext->ee_len;
-+ /* FIXME: support for large fs */
-+ nearex->ee_start_hi = 0;
-+
-+merge:
-+ /* try to merge extents to the right */
-+ while (nearex < EXT_LAST_EXTENT(eh)) {
-+ if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1))
-+ break;
-+ /* merge with next extent! */
-+ nearex->ee_len += nearex[1].ee_len;
-+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
-+ len = (EXT_LAST_EXTENT(eh) - nearex - 1)
-+ * sizeof(struct ext3_extent);
-+ memmove(nearex + 1, nearex + 2, len);
-+ }
-+ eh->eh_entries--;
-+ EXT_ASSERT(eh->eh_entries > 0);
-+ }
-+
-+ /* try to merge extents to the left */
-+
-+ /* time to correct all indexes above */
-+ err = ext3_ext_correct_indexes(handle, tree, path);
-+ if (err)
-+ goto cleanup;
-+
-+ err = ext3_ext_dirty(handle, tree, path + depth);
-+
-+cleanup:
-+ if (npath) {
-+ ext3_ext_drop_refs(npath);
-+ kfree(npath);
-+ }
-+ ext3_ext_tree_changed(tree);
-+ ext3_ext_invalidate_cache(tree);
-+ return err;
-+}
-+
-+int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block,
-+ unsigned long num, ext_prepare_callback func)
-+{
-+ struct ext3_ext_path *path = NULL;
-+ struct ext3_extent *ex, cbex;
-+ unsigned long next, start = 0, end = 0;
-+ unsigned long last = block + num;
-+ int depth, exists, err = 0;
-+
-+ EXT_ASSERT(tree);
-+ EXT_ASSERT(func);
-+ EXT_ASSERT(tree->inode);
-+ EXT_ASSERT(tree->root);
-+
-+ while (block < last && block != EXT_MAX_BLOCK) {
-+ num = last - block;
-+ /* find extent for this block */
-+ path = ext3_ext_find_extent(tree, block, path);
-+ if (IS_ERR(path)) {
-+ err = PTR_ERR(path);
-+ path = NULL;
-+ break;
-+ }
-+
-+ depth = EXT_DEPTH(tree);
-+ EXT_ASSERT(path[depth].p_hdr);
-+ ex = path[depth].p_ext;
-+ next = ext3_ext_next_allocated_block(path);
-+
-+ exists = 0;
-+ if (!ex) {
-+ /* there is no extent yet, so try to allocate
-+ * all requested space */
-+ start = block;
-+ end = block + num;
-+ } else if (ex->ee_block > block) {
-+ /* need to allocate space before found extent */
-+ start = block;
-+ end = ex->ee_block;
-+ if (block + num < end)
-+ end = block + num;
-+ } else if (block >= ex->ee_block + ex->ee_len) {
-+ /* need to allocate space after found extent */
-+ start = block;
-+ end = block + num;
-+ if (end >= next)
-+ end = next;
-+ } else if (block >= ex->ee_block) {
-+ /*
-+ * some part of requested space is covered
-+ * by found extent
-+ */
-+ start = block;
-+ end = ex->ee_block + ex->ee_len;
-+ if (block + num < end)
-+ end = block + num;
-+ exists = 1;
-+ } else {
-+ BUG();
-+ }
-+ EXT_ASSERT(end > start);
-+
-+ if (!exists) {
-+ cbex.ee_block = start;
-+ cbex.ee_len = end - start;
-+ cbex.ee_start = 0;
-+ } else
-+ cbex = *ex;
-+
-+ EXT_ASSERT(path[depth].p_hdr);
-+ err = func(tree, path, &cbex, exists);
-+ ext3_ext_drop_refs(path);
-+
-+ if (err < 0)
-+ break;
-+ if (err == EXT_REPEAT)
-+ continue;
-+ else if (err == EXT_BREAK) {
-+ err = 0;
-+ break;
-+ }
-+
-+ if (EXT_DEPTH(tree) != depth) {
-+ /* depth was changed. we have to realloc path */
-+ kfree(path);
-+ path = NULL;
-+ }
-+
-+ block = cbex.ee_block + cbex.ee_len;
-+ }
-+
-+ if (path) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ }
-+
-+ return err;
-+}
-+
-+static inline void
-+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
-+ __u32 len, __u32 start, int type)
-+{
-+ EXT_ASSERT(len > 0);
-+ if (tree->cex) {
-+ tree->cex->ec_type = type;
-+ tree->cex->ec_block = block;
-+ tree->cex->ec_len = len;
-+ tree->cex->ec_start = start;
-+ }
-+}
-+
-+/*
-+ * this routine calculate boundaries of the gap requested block fits into
-+ * and cache this gap
-+ */
-+static inline void
-+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ unsigned long block)
-+{
-+ int depth = EXT_DEPTH(tree);
-+ unsigned long lblock, len;
-+ struct ext3_extent *ex;
-+
-+ if (!tree->cex)
-+ return;
-+
-+ ex = path[depth].p_ext;
-+ if (ex == NULL) {
-+ /* there is no extent yet, so gap is [0;-] */
-+ lblock = 0;
-+ len = EXT_MAX_BLOCK;
-+ ext_debug(tree, "cache gap(whole file):");
-+ } else if (block < ex->ee_block) {
-+ lblock = block;
-+ len = ex->ee_block - block;
-+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len);
-+ } else if (block >= ex->ee_block + ex->ee_len) {
-+ lblock = ex->ee_block + ex->ee_len;
-+ len = ext3_ext_next_allocated_block(path);
-+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) block);
-+ EXT_ASSERT(len > lblock);
-+ len = len - lblock;
-+ } else {
-+ lblock = len = 0;
-+ BUG();
-+ }
-+
-+ ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len);
-+ ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP);
-+}
-+
-+static inline int
-+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
-+ struct ext3_extent *ex)
-+{
-+ struct ext3_ext_cache *cex = tree->cex;
-+
-+ /* is there cache storage at all? */
-+ if (!cex)
-+ return EXT3_EXT_CACHE_NO;
-+
-+ /* has cache valid data? */
-+ if (cex->ec_type == EXT3_EXT_CACHE_NO)
-+ return EXT3_EXT_CACHE_NO;
-+
-+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
-+ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
-+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
-+ ex->ee_block = cex->ec_block;
-+ ex->ee_start = cex->ec_start;
-+ ex->ee_len = cex->ec_len;
-+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) ex->ee_start);
-+ return cex->ec_type;
-+ }
-+
-+ /* not in cache */
-+ return EXT3_EXT_CACHE_NO;
-+}
-+
-+/*
-+ * routine removes index from the index block
-+ * it's used in truncate case only. thus all requests are for
-+ * last index in the block only
-+ */
-+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ struct buffer_head *bh;
-+ int err;
-+
-+ /* free index block */
-+ path--;
-+ EXT_ASSERT(path->p_hdr->eh_entries);
-+ if ((err = ext3_ext_get_access(handle, tree, path)))
-+ return err;
-+ path->p_hdr->eh_entries--;
-+ if ((err = ext3_ext_dirty(handle, tree, path)))
-+ return err;
-+ ext_debug(tree, "index is empty, remove it, free block %d\n",
-+ path->p_idx->ei_leaf);
-+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->ei_leaf);
-+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
-+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
-+ return err;
-+}
-+
-+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ int depth = EXT_DEPTH(tree);
-+ int needed;
-+
-+ if (path) {
-+ /* probably there is space in leaf? */
-+ if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max)
-+ return 1;
-+ }
-+
-+ /*
-+ * the worste case we're expecting is creation of the
-+ * new root (growing in depth) with index splitting
-+ * for splitting we have to consider depth + 1 because
-+ * previous growing could increase it
-+ */
-+ depth = depth + 1;
-+
-+ /*
-+ * growing in depth:
-+ * block allocation + new root + old root
-+ */
-+ needed = EXT3_ALLOC_NEEDED + 2;
-+
-+ /* index split. we may need:
-+ * allocate intermediate indexes and new leaf
-+ * change two blocks at each level, but root
-+ * modify root block (inode)
-+ */
-+ needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1;
-+
-+ return needed;
-+}
-+
-+static int
-+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
-+{
-+ struct ext3_extent *ex, tex;
-+ struct ext3_ext_path *npath;
-+ int depth, creds, err;
-+
-+ depth = EXT_DEPTH(tree);
-+ ex = path[depth].p_ext;
-+ EXT_ASSERT(ex);
-+ EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1);
-+ EXT_ASSERT(ex->ee_block < start);
-+
-+ /* calculate tail extent */
-+ tex.ee_block = end + 1;
-+ EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len);
-+ tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block;
-+
-+ creds = ext3_ext_calc_credits_for_insert(tree, path);
-+ handle = ext3_ext_journal_restart(handle, creds);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+
-+ /* calculate head extent. use primary extent */
-+ err = ext3_ext_get_access(handle, tree, path + depth);
-+ if (err)
-+ return err;
-+ ex->ee_len = start - ex->ee_block;
-+ err = ext3_ext_dirty(handle, tree, path + depth);
-+ if (err)
-+ return err;
-+
-+ /* FIXME: some callback to free underlying resource
-+ * and correct ee_start? */
-+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
-+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
-+
-+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
-+ if (IS_ERR(npath))
-+ return PTR_ERR(npath);
-+ depth = EXT_DEPTH(tree);
-+ EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block);
-+ EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len);
-+
-+ err = ext3_ext_insert_extent(handle, tree, npath, &tex);
-+ ext3_ext_drop_refs(npath);
-+ kfree(npath);
-+
-+ return err;
-+
-+}
-+
-+static int
-+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
-+{
-+ struct ext3_extent *ex, *fu = NULL, *lu, *le;
-+ int err = 0, correct_index = 0;
-+ int depth = EXT_DEPTH(tree), credits;
-+ struct ext3_extent_header *eh;
-+ unsigned a, b, block, num;
-+
-+ ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
-+ if (!path[depth].p_hdr)
-+ path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
-+ eh = path[depth].p_hdr;
-+ EXT_ASSERT(eh);
-+ EXT_ASSERT(eh->eh_entries <= eh->eh_max);
-+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+
-+ /* find where to start removing */
-+ le = ex = EXT_LAST_EXTENT(eh);
-+ while (ex != EXT_FIRST_EXTENT(eh)) {
-+ if (ex->ee_block <= end)
-+ break;
-+ ex--;
-+ }
-+
-+ if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) {
-+ /* removal of internal part of the extent requested
-+ * tail and head must be placed in different extent
-+ * so, we have to insert one more extent */
-+ path[depth].p_ext = ex;
-+ return ext3_ext_split_for_rm(handle, tree, path, start, end);
-+ }
-+
-+ lu = ex;
-+ while (ex >= EXT_FIRST_EXTENT(eh) &&
-+ ex->ee_block + ex->ee_len > start) {
-+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
-+ path[depth].p_ext = ex;
-+
-+ a = ex->ee_block > start ? ex->ee_block : start;
-+ b = ex->ee_block + ex->ee_len - 1 < end ?
-+ ex->ee_block + ex->ee_len - 1 : end;
-+
-+ ext_debug(tree, " border %u:%u\n", a, b);
-+
-+ if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) {
-+ block = 0;
-+ num = 0;
-+ BUG();
-+ } else if (a != ex->ee_block) {
-+ /* remove tail of the extent */
-+ block = ex->ee_block;
-+ num = a - block;
-+ } else if (b != ex->ee_block + ex->ee_len - 1) {
-+ /* remove head of the extent */
-+ block = a;
-+ num = b - a;
-+ } else {
-+ /* remove whole extent: excelent! */
-+ block = ex->ee_block;
-+ num = 0;
-+ EXT_ASSERT(a == ex->ee_block &&
-+ b == ex->ee_block + ex->ee_len - 1);
-+ }
-+
-+ if (ex == EXT_FIRST_EXTENT(eh))
-+ correct_index = 1;
-+
-+ credits = 1;
-+ if (correct_index)
-+ credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1;
-+ if (tree->ops->remove_extent_credits)
-+ credits+=tree->ops->remove_extent_credits(tree,ex,a,b);
-+
-+ handle = ext3_ext_journal_restart(handle, credits);
-+ if (IS_ERR(handle)) {
-+ err = PTR_ERR(handle);
-+ goto out;
-+ }
-+
-+ err = ext3_ext_get_access(handle, tree, path + depth);
-+ if (err)
-+ goto out;
-+
-+ if (tree->ops->remove_extent)
-+ err = tree->ops->remove_extent(tree, ex, a, b);
-+ if (err)
-+ goto out;
-+
-+ if (num == 0) {
-+ /* this extent is removed entirely mark slot unused */
-+ ex->ee_start = 0;
-+ eh->eh_entries--;
-+ fu = ex;
-+ }
-+
-+ ex->ee_block = block;
-+ ex->ee_len = num;
-+
-+ err = ext3_ext_dirty(handle, tree, path + depth);
-+ if (err)
-+ goto out;
-+
-+ ext_debug(tree, "new extent: %u:%u:%u\n",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
-+ ex--;
-+ }
-+
-+ if (fu) {
-+ /* reuse unused slots */
-+ while (lu < le) {
-+ if (lu->ee_start) {
-+ *fu = *lu;
-+ lu->ee_start = 0;
-+ fu++;
-+ }
-+ lu++;
-+ }
-+ }
-+
-+ if (correct_index && eh->eh_entries)
-+ err = ext3_ext_correct_indexes(handle, tree, path);
-+
-+ /* if this leaf is free, then we should
-+ * remove it from index block above */
-+ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
-+ err = ext3_ext_rm_idx(handle, tree, path + depth);
-+
-+out:
-+ return err;
-+}
-+
-+
-+static struct ext3_extent_idx *
-+ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block)
-+{
-+ struct ext3_extent_idx *ix;
-+
-+ ix = EXT_LAST_INDEX(hdr);
-+ while (ix != EXT_FIRST_INDEX(hdr)) {
-+ if (ix->ei_block <= block)
-+ break;
-+ ix--;
-+ }
-+ return ix;
-+}
-+
-+/*
-+ * returns 1 if current index have to be freed (even partial)
-+ */
-+static int inline
-+ext3_ext_more_to_rm(struct ext3_ext_path *path)
-+{
-+ EXT_ASSERT(path->p_idx);
-+
-+ if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
-+ return 0;
-+
-+ /*
-+ * if truncate on deeper level happened it it wasn't partial
-+ * so we have to consider current index for truncation
-+ */
-+ if (path->p_hdr->eh_entries == path->p_block)
-+ return 0;
-+ return 1;
-+}
-+
-+int ext3_ext_remove_space(struct ext3_extents_tree *tree,
-+ unsigned long start, unsigned long end)
-+{
-+ struct inode *inode = tree->inode;
-+ struct super_block *sb = inode->i_sb;
-+ int depth = EXT_DEPTH(tree);
-+ struct ext3_ext_path *path;
-+ handle_t *handle;
-+ int i = 0, err = 0;
-+
-+ ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
-+
-+ /* probably first extent we're gonna free will be last in block */
-+ handle = ext3_journal_start(inode, depth + 1);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+
-+ ext3_ext_invalidate_cache(tree);
-+
-+ /*
-+ * we start scanning from right side freeing all the blocks
-+ * after i_size and walking into the deep
-+ */
-+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
-+ if (IS_ERR(path)) {
-+ ext3_error(sb, "ext3_ext_remove_space",
-+ "Can't allocate path array");
-+ ext3_journal_stop(handle, inode);
-+ return -ENOMEM;
-+ }
-+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
-+ path[i].p_hdr = EXT_ROOT_HDR(tree);
-+
-+ while (i >= 0 && err == 0) {
-+ if (i == depth) {
-+ /* this is leaf block */
-+ err = ext3_ext_rm_leaf(handle, tree, path, start, end);
-+ /* root level have p_bh == NULL, brelse() eats this */
-+ brelse(path[i].p_bh);
-+ i--;
-+ continue;
-+ }
-+
-+ /* this is index block */
-+ if (!path[i].p_hdr) {
-+ ext_debug(tree, "initialize header\n");
-+ path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
-+ }
-+
-+ EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
-+ EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
-+
-+ if (!path[i].p_idx) {
-+ /* this level hasn't touched yet */
-+ path[i].p_idx =
-+ ext3_ext_last_covered(path[i].p_hdr, end);
-+ path[i].p_block = path[i].p_hdr->eh_entries + 1;
-+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
-+ path[i].p_hdr, path[i].p_hdr->eh_entries);
-+ } else {
-+ /* we've already was here, see at next index */
-+ path[i].p_idx--;
-+ }
-+
-+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
-+ i, EXT_FIRST_INDEX(path[i].p_hdr),
-+ path[i].p_idx);
-+ if (ext3_ext_more_to_rm(path + i)) {
-+ /* go to the next level */
-+ ext_debug(tree, "move to level %d (block %d)\n",
-+ i + 1, path[i].p_idx->ei_leaf);
-+ memset(path + i + 1, 0, sizeof(*path));
-+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
-+ if (!path[i+1].p_bh) {
-+ /* should we reset i_size? */
-+ err = -EIO;
-+ break;
-+ }
-+ /* put actual number of indexes to know is this
-+ * number got changed at the next iteration */
-+ path[i].p_block = path[i].p_hdr->eh_entries;
-+ i++;
-+ } else {
-+ /* we finish processing this index, go up */
-+ if (path[i].p_hdr->eh_entries == 0 && i > 0) {
-+ /* index is empty, remove it
-+ * handle must be already prepared by the
-+ * truncatei_leaf() */
-+ err = ext3_ext_rm_idx(handle, tree, path + i);
-+ }
-+ /* root level have p_bh == NULL, brelse() eats this */
-+ brelse(path[i].p_bh);
-+ i--;
-+ ext_debug(tree, "return to level %d\n", i);
-+ }
-+ }
-+
-+ /* TODO: flexible tree reduction should be here */
-+ if (path->p_hdr->eh_entries == 0) {
-+ /*
-+ * truncate to zero freed all the tree
-+ * so, we need to correct eh_depth
-+ */
-+ err = ext3_ext_get_access(handle, tree, path);
-+ if (err == 0) {
-+ EXT_ROOT_HDR(tree)->eh_depth = 0;
-+ EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree);
-+ err = ext3_ext_dirty(handle, tree, path);
-+ }
-+ }
-+ ext3_ext_tree_changed(tree);
-+
-+ kfree(path);
-+ ext3_journal_stop(handle, inode);
-+
-+ return err;
-+}
-+
-+/*
-+ * called at mount time
-+ */
-+void ext3_ext_init(struct super_block *sb)
-+{
-+ /*
-+ * possible initialization would be here
-+ */
-+
-+ if (test_opt(sb, EXTENTS)) {
-+ printk("EXT3-fs: file extents enabled");
-+#ifdef AGRESSIVE_TEST
-+ printk(", agressive tests");
-+#endif
-+#ifdef CHECK_BINSEARCH
-+ printk(", check binsearch");
-+#endif
-+ printk("\n");
-+ }
-+}
-+
-+/*
-+ * called at umount time
-+ */
-+void ext3_ext_release(struct super_block *sb)
-+{
-+}
-+
-+/************************************************************************
-+ * VFS related routines
-+ ************************************************************************/
-+
-+static int ext3_get_inode_write_access(handle_t *handle, void *buffer)
-+{
-+ /* we use in-core data, not bh */
-+ return 0;
-+}
-+
-+static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer)
-+{
-+ struct inode *inode = buffer;
-+ return ext3_mark_inode_dirty(handle, inode);
-+}
-+
-+static int ext3_ext_mergable(struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
-+{
-+ /* FIXME: support for large fs */
-+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
-+ return 1;
-+ return 0;
-+}
-+
-+static int
-+ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
-+{
-+ int needed;
-+
-+ /* at present, extent can't cross block group */;
-+ needed = 4; /* bitmap + group desc + sb + inode */
-+
-+#ifdef CONFIG_QUOTA
-+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
-+#endif
-+ return needed;
-+}
-+
-+static int
-+ext3_remove_blocks(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
-+{
-+ int needed = ext3_remove_blocks_credits(tree, ex, from, to);
-+ handle_t *handle = ext3_journal_start(tree->inode, needed);
-+ struct buffer_head *bh;
-+ int i;
-+
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+ if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
-+ /* tail removal */
-+ unsigned long num, start;
-+ num = ex->ee_block + ex->ee_len - from;
-+ start = ex->ee_start + ex->ee_len - num;
-+ ext_debug(tree, "free last %lu blocks starting %lu\n",
-+ num, start);
-+ for (i = 0; i < num; i++) {
-+ bh = sb_get_hash_table(tree->inode->i_sb, start + i);
-+ ext3_forget(handle, 0, tree->inode, bh, start + i);
-+ }
-+ ext3_free_blocks(handle, tree->inode, start, num);
-+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
-+ printk("strange request: removal %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
-+ } else {
-+ printk("strange request: removal(2) %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
-+ }
-+ ext3_journal_stop(handle, tree->inode);
-+ return 0;
-+}
-+
-+int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path,
-+ unsigned long block)
-+{
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+ unsigned long bg_start;
-+ unsigned long colour;
-+ int depth;
-+
-+ if (path) {
-+ struct ext3_extent *ex;
-+ depth = path->p_depth;
-+
-+ /* try to predict block placement */
-+ if ((ex = path[depth].p_ext))
-+ return ex->ee_start + (block - ex->ee_block);
-+
-+ /* it looks index is empty
-+ * try to find starting from index itself */
-+ if (path[depth].p_bh)
-+ return path[depth].p_bh->b_blocknr;
-+ }
-+
-+ /* OK. use inode's group */
-+ bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
-+ colour = (current->pid % 16) *
-+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
-+ return bg_start + colour + block;
-+}
-+
-+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int *err)
-+{
-+ struct inode *inode = tree->inode;
-+ int newblock, goal;
-+
-+ EXT_ASSERT(path);
-+ EXT_ASSERT(ex);
-+ EXT_ASSERT(ex->ee_start);
-+ EXT_ASSERT(ex->ee_len);
-+
-+ /* reuse block from the extent to order data/metadata */
-+ newblock = ex->ee_start++;
-+ ex->ee_len--;
-+ if (ex->ee_len == 0) {
-+ ex->ee_len = 1;
-+ /* allocate new block for the extent */
-+ goal = ext3_ext_find_goal(inode, path, ex->ee_block);
-+ ex->ee_start = ext3_new_block(handle, inode, goal, 0, 0, err);
-+ if (ex->ee_start == 0) {
-+ /* error occured: restore old extent */
-+ ex->ee_start = newblock;
-+ return 0;
-+ }
-+ }
-+ return newblock;
-+}
-+
-+static struct ext3_extents_helpers ext3_blockmap_helpers = {
-+ .get_write_access = ext3_get_inode_write_access,
-+ .mark_buffer_dirty = ext3_mark_buffer_dirty,
-+ .mergable = ext3_ext_mergable,
-+ .new_block = ext3_new_block_cb,
-+ .remove_extent = ext3_remove_blocks,
-+ .remove_extent_credits = ext3_remove_blocks_credits,
-+};
-+
-+void ext3_init_tree_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode)
-+{
-+ tree->inode = inode;
-+ tree->root = (void *) EXT3_I(inode)->i_data;
-+ tree->buffer = (void *) inode;
-+ tree->buffer_len = sizeof(EXT3_I(inode)->i_data);
-+ tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent;
-+ tree->ops = &ext3_blockmap_helpers;
-+}
-+
-+int ext3_ext_get_block(handle_t *handle, struct inode *inode,
-+ long iblock, struct buffer_head *bh_result, int create)
-+{
-+ struct ext3_ext_path *path = NULL;
-+ struct ext3_extent newex;
-+ struct ext3_extent *ex;
-+ int goal, newblock, err = 0, depth;
-+ struct ext3_extents_tree tree;
-+
-+ clear_bit(BH_New, &bh_result->b_state);
-+ ext3_init_tree_desc(&tree, inode);
-+ ext_debug(&tree, "block %d requested for inode %u\n",
-+ (int) iblock, (unsigned) inode->i_ino);
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+
-+ /* check in cache */
-+ if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) {
-+ if (goal == EXT3_EXT_CACHE_GAP) {
-+ if (!create) {
-+ /* block isn't allocated yet and
-+ * user don't want to allocate it */
-+ goto out2;
-+ }
-+ /* we should allocate requested block */
-+ } else if (goal == EXT3_EXT_CACHE_EXTENT) {
-+ /* block is already allocated */
-+ newblock = iblock - newex.ee_block + newex.ee_start;
-+ goto out;
-+ } else {
-+ EXT_ASSERT(0);
-+ }
-+ }
-+
-+ /* find extent for this block */
-+ path = ext3_ext_find_extent(&tree, iblock, NULL);
-+ if (IS_ERR(path)) {
-+ err = PTR_ERR(path);
-+ path = NULL;
-+ goto out2;
-+ }
-+
-+ depth = EXT_DEPTH(&tree);
-+
-+ /*
-+ * consistent leaf must not be empty
-+ * this situations is possible, though, _during_ tree modification
-+ * this is why assert can't be put in ext3_ext_find_extent()
-+ */
-+ EXT_ASSERT(path[depth].p_ext != NULL || depth == 0);
-+
-+ if ((ex = path[depth].p_ext)) {
-+ /* if found exent covers block, simple return it */
-+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
-+ newblock = iblock - ex->ee_block + ex->ee_start;
-+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
-+ (int) iblock, ex->ee_block, ex->ee_len,
-+ newblock);
-+ ext3_ext_put_in_cache(&tree, ex->ee_block,
-+ ex->ee_len, ex->ee_start,
-+ EXT3_EXT_CACHE_EXTENT);
-+ goto out;
-+ }
-+ }
-+
-+ /*
-+ * requested block isn't allocated yet
-+ * we couldn't try to create block if create flag is zero
-+ */
-+ if (!create) {
-+ /* put just found gap into cache to speedup subsequest reqs */
-+ ext3_ext_put_gap_in_cache(&tree, path, iblock);
-+ goto out2;
-+ }
-+
-+ /* allocate new block */
-+ goal = ext3_ext_find_goal(inode, path, iblock);
-+ newblock = ext3_new_block(handle, inode, goal, 0, 0, &err);
-+ if (!newblock)
-+ goto out2;
-+ ext_debug(&tree, "allocate new block: goal %d, found %d\n",
-+ goal, newblock);
-+
-+ /* try to insert new extent into found leaf and return */
-+ newex.ee_block = iblock;
-+ newex.ee_start = newblock;
-+ newex.ee_len = 1;
-+ err = ext3_ext_insert_extent(handle, &tree, path, &newex);
-+ if (err)
-+ goto out2;
-+
-+ if (inode->i_size > EXT3_I(inode)->i_disksize)
-+ EXT3_I(inode)->i_disksize = inode->i_size;
-+
-+ /* previous routine could use block we allocated */
-+ newblock = newex.ee_start;
-+ set_bit(BH_New, &bh_result->b_state);
-+
-+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
-+ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
-+out:
-+ ext3_ext_show_leaf(&tree, path);
-+ set_bit(BH_Mapped, &bh_result->b_state);
-+ bh_result->b_dev = inode->i_sb->s_dev;
-+ bh_result->b_blocknr = newblock;
-+out2:
-+ if (path) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ }
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+
-+ return err;
-+}
-+
-+void ext3_ext_truncate(struct inode * inode)
-+{
-+ struct address_space *mapping = inode->i_mapping;
-+ struct super_block *sb = inode->i_sb;
-+ struct ext3_extents_tree tree;
-+ unsigned long last_block;
-+ handle_t *handle;
-+ int err = 0;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+
-+ /*
-+ * probably first extent we're gonna free will be last in block
-+ */
-+ err = ext3_writepage_trans_blocks(inode) + 3;
-+ handle = ext3_journal_start(inode, err);
-+ if (IS_ERR(handle))
-+ return;
-+
-+ ext3_block_truncate_page(handle, mapping, inode->i_size);
-+
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ ext3_ext_invalidate_cache(&tree);
-+
-+ /*
-+ * TODO: optimization is possible here
-+ * probably we need not scaning at all,
-+ * because page truncation is enough
-+ */
-+ if (ext3_orphan_add(handle, inode))
-+ goto out_stop;
-+
-+ /* we have to know where to truncate from in crash case */
-+ EXT3_I(inode)->i_disksize = inode->i_size;
-+ ext3_mark_inode_dirty(handle, inode);
-+
-+ last_block = (inode->i_size + sb->s_blocksize - 1)
-+ >> EXT3_BLOCK_SIZE_BITS(sb);
-+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
-+
-+ /* In a multi-transaction truncate, we only make the final
-+ * transaction synchronous */
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+
-+out_stop:
-+ /*
-+ * If this was a simple ftruncate(), and the file will remain alive
-+ * then we need to clear up the orphan record which we created above.
-+ * However, if this was a real unlink then we were called by
-+ * ext3_delete_inode(), and we allow that function to clean up the
-+ * orphan info for us.
-+ */
-+ if (inode->i_nlink)
-+ ext3_orphan_del(handle, inode);
-+
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ ext3_journal_stop(handle, inode);
-+}
-+
-+/*
-+ * this routine calculate max number of blocks we could modify
-+ * in order to allocate new block for an inode
-+ */
-+int ext3_ext_writepage_trans_blocks(struct inode *inode, int num)
-+{
-+ struct ext3_extents_tree tree;
-+ int needed;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+
-+ needed = ext3_ext_calc_credits_for_insert(&tree, NULL);
-+
-+ /* caller want to allocate num blocks */
-+ needed *= num;
-+
-+#ifdef CONFIG_QUOTA
-+ /*
-+ * FIXME: real calculation should be here
-+ * it depends on blockmap format of qouta file
-+ */
-+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
-+#endif
-+
-+ return needed;
-+}
-+
-+void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode)
-+{
-+ struct ext3_extents_tree tree;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+ ext3_extent_tree_init(handle, &tree);
-+}
-+
-+static int
-+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newex, int exist)
-+{
-+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
-+
-+ if (!exist)
-+ return EXT_CONTINUE;
-+ if (buf->err < 0)
-+ return EXT_BREAK;
-+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
-+ return EXT_BREAK;
-+
-+ if (!copy_to_user(buf->cur, newex, sizeof(*newex))) {
-+ buf->err++;
-+ buf->cur += sizeof(*newex);
-+ } else {
-+ buf->err = -EFAULT;
-+ return EXT_BREAK;
-+ }
-+ return EXT_CONTINUE;
-+}
-+
-+static int
-+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int exist)
-+{
-+ struct ext3_extent_tree_stats *buf =
-+ (struct ext3_extent_tree_stats *) tree->private;
-+ int depth;
-+
-+ if (!exist)
-+ return EXT_CONTINUE;
-+
-+ depth = EXT_DEPTH(tree);
-+ buf->extents_num++;
-+ if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr))
-+ buf->leaf_num++;
-+ return EXT_CONTINUE;
-+}
-+
-+int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ int err = 0;
-+
-+ if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL))
-+ return -EINVAL;
-+
-+ if (cmd == EXT3_IOC_GET_EXTENTS) {
-+ struct ext3_extent_buf buf;
-+ struct ext3_extents_tree tree;
-+
-+ if (copy_from_user(&buf, (void *) arg, sizeof(buf)))
-+ return -EFAULT;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+ buf.cur = buf.buffer;
-+ buf.err = 0;
-+ tree.private = &buf;
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ if (err == 0)
-+ err = buf.err;
-+ } else if (cmd == EXT3_IOC_GET_TREE_STATS) {
-+ struct ext3_extent_tree_stats buf;
-+ struct ext3_extents_tree tree;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ buf.depth = EXT_DEPTH(&tree);
-+ buf.extents_num = 0;
-+ buf.leaf_num = 0;
-+ tree.private = &buf;
-+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ if (!err)
-+ err = copy_to_user((void *) arg, &buf, sizeof(buf));
-+ } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) {
-+ struct ext3_extents_tree tree;
-+ ext3_init_tree_desc(&tree, inode);
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ err = EXT_DEPTH(&tree);
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ }
-+
-+ return err;
-+}
-+
-+EXPORT_SYMBOL(ext3_init_tree_desc);
-+EXPORT_SYMBOL(ext3_mark_inode_dirty);
-+EXPORT_SYMBOL(ext3_ext_invalidate_cache);
-+EXPORT_SYMBOL(ext3_ext_insert_extent);
-+EXPORT_SYMBOL(ext3_ext_walk_space);
-+EXPORT_SYMBOL(ext3_ext_find_goal);
-+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
-+
-Index: linux-2.4.20-rh-20.9/fs/ext3/ialloc.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/fs/ext3/ialloc.c 2004-11-02 21:01:47.000000000 +0300
-+++ linux-2.4.20-rh-20.9/fs/ext3/ialloc.c 2004-11-02 21:03:00.000000000 +0300
-@@ -593,10 +593,22 @@
- iloc.bh = NULL;
- goto fail;
- }
-- err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-- if (err) goto fail;
-
-+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
-+ ext3_extents_initialize_blockmap(handle, inode);
-+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
-+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-+ if (err) goto fail;
-+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
-+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
-+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-+ }
-+ }
-
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err) goto fail;
-
- unlock_super (sb);
- if(DQUOT_ALLOC_INODE(inode)) {
-Index: linux-2.4.20-rh-20.9/fs/ext3/inode.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/fs/ext3/inode.c 2004-11-02 21:01:55.000000000 +0300
-+++ linux-2.4.20-rh-20.9/fs/ext3/inode.c 2004-11-02 21:03:00.000000000 +0300
-@@ -852,6 +852,16 @@
- goto reread;
- }
-
-+static inline int
-+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+ struct buffer_head *bh, int create, int extend_disksize)
-+{
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_get_block(handle, inode, block, bh, create);
-+ return ext3_get_block_handle(handle, inode, block, bh, create,
-+ extend_disksize);
-+}
-+
- /*
- * The BKL is not held on entry here.
- */
-@@ -865,7 +875,7 @@
- handle = ext3_journal_current_handle();
- J_ASSERT(handle != 0);
- }
-- ret = ext3_get_block_handle(handle, inode, iblock,
-+ ret = ext3_get_block_wrap(handle, inode, iblock,
- bh_result, create, 1);
- return ret;
- }
-@@ -892,7 +902,7 @@
- }
- }
- if (ret == 0)
-- ret = ext3_get_block_handle(handle, inode, iblock,
-+ ret = ext3_get_block_wrap(handle, inode, iblock,
- bh_result, create, 0);
- if (ret == 0)
- bh_result->b_size = (1 << inode->i_blkbits);
-@@ -914,7 +924,7 @@
- dummy.b_state = 0;
- dummy.b_blocknr = -1000;
- buffer_trace_init(&dummy.b_history);
-- *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1);
-+ *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create, 1);
- if (!*errp && buffer_mapped(&dummy)) {
- struct buffer_head *bh;
- bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
-@@ -1502,7 +1512,7 @@
- * This required during truncate. We need to physically zero the tail end
- * of that block so it doesn't yield old data if the file is later grown.
- */
--static int ext3_block_truncate_page(handle_t *handle,
-+int ext3_block_truncate_page(handle_t *handle,
- struct address_space *mapping, loff_t from)
- {
- unsigned long index = from >> PAGE_CACHE_SHIFT;
-@@ -1990,6 +2000,9 @@
-
- ext3_discard_prealloc(inode);
-
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_truncate(inode);
-+
- handle = start_transaction(inode);
- if (IS_ERR(handle))
- return; /* AKPM: return what? */
-@@ -2426,6 +2439,7 @@
- for (block = 0; block < EXT3_N_BLOCKS; block++)
- inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
-
- if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
- inode->u.ext3_i.i_extra_isize =
-@@ -2758,6 +2772,9 @@
- int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
- int ret;
-
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_writepage_trans_blocks(inode, bpp);
-+
- if (ext3_should_journal_data(inode))
- ret = 3 * (bpp + indirects) + 2;
- else
-@@ -3082,7 +3099,7 @@
-
- /* alloc blocks one by one */
- for (i = 0; i < nblocks; i++) {
-- ret = ext3_get_block_handle(handle, inode, blocks[i],
-+ ret = ext3_get_block_wrap(handle, inode, blocks[i],
- &bh_tmp, 1, 1);
- if (ret)
- break;
-@@ -3158,7 +3175,7 @@
- if (blocks[i] != 0)
- continue;
-
-- rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1, 1);
-+ rc = ext3_get_block_wrap(handle, inode, iblock, &bh, 1, 1);
- if (rc) {
- printk(KERN_INFO "ext3_map_inode_page: error %d "
- "allocating block %ld\n", rc, iblock);
-Index: linux-2.4.20-rh-20.9/fs/ext3/Makefile
-===================================================================
---- linux-2.4.20-rh-20.9.orig/fs/ext3/Makefile 2004-11-02 21:01:49.000000000 +0300
-+++ linux-2.4.20-rh-20.9/fs/ext3/Makefile 2004-11-02 21:01:58.000000000 +0300
-@@ -13,7 +13,9 @@
-
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
-- xattr_trusted.o
-+ xattr_trusted.o extents.o
-+export-objs += extents.o
-+
- obj-m := $(O_TARGET)
-
- export-objs += xattr.o
-Index: linux-2.4.20-rh-20.9/fs/ext3/super.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/fs/ext3/super.c 2004-11-02 21:01:47.000000000 +0300
-+++ linux-2.4.20-rh-20.9/fs/ext3/super.c 2004-11-02 21:01:58.000000000 +0300
-@@ -623,6 +623,7 @@
- int i;
-
- J_ASSERT(sbi->s_delete_inodes == 0);
-+ ext3_ext_release(sb);
- ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
-@@ -798,6 +799,10 @@
- }
- else if (!strcmp (this_char, "pdirops"))
- set_opt (sbi->s_mount_opt, PDIROPS);
-+ else if (!strcmp (this_char, "extents"))
-+ set_opt (*mount_options, EXTENTS);
-+ else if (!strcmp (this_char, "extdebug"))
-+ set_opt (*mount_options, EXTDEBUG);
- else if (!strcmp (this_char, "grpid") ||
- !strcmp (this_char, "bsdgroups"))
- set_opt (*mount_options, GRPID);
-@@ -1499,6 +1504,8 @@
- printk (KERN_INFO "EXT3-fs: mounted filesystem with parallel dirops\n");
- sb->s_flags |= S_PDIROPS;
- }
-+
-+ ext3_ext_init(sb);
-
- return sb;
-
-Index: linux-2.4.20-rh-20.9/fs/ext3/ioctl.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/fs/ext3/ioctl.c 2004-11-02 21:01:31.000000000 +0300
-+++ linux-2.4.20-rh-20.9/fs/ext3/ioctl.c 2004-11-02 21:01:58.000000000 +0300
-@@ -189,6 +189,10 @@
- return ret;
- }
- #endif
-+ case EXT3_IOC_GET_EXTENTS:
-+ case EXT3_IOC_GET_TREE_STATS:
-+ case EXT3_IOC_GET_TREE_DEPTH:
-+ return ext3_ext_ioctl(inode, filp, cmd, arg);
- default:
- return -ENOTTY;
- }
-Index: linux-2.4.20-rh-20.9/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/linux/ext3_fs.h 2004-11-02 21:01:47.000000000 +0300
-+++ linux-2.4.20-rh-20.9/include/linux/ext3_fs.h 2004-11-02 21:01:58.000000000 +0300
-@@ -184,6 +184,7 @@
- #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */
- #define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
- #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
-+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
-
- #define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */
- #define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
-@@ -208,6 +209,9 @@
- #ifdef CONFIG_JBD_DEBUG
- #define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long)
- #endif
-+#define EXT3_IOC_GET_EXTENTS _IOR('f', 5, long)
-+#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long)
-+#define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long)
-
- /*
- * Structure of an inode on the disk
-@@ -328,6 +332,8 @@
- #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
- #define EXT3_MOUNT_IOPEN 0x40000 /* Allow access via iopen */
- #define EXT3_MOUNT_IOPEN_NOPRIV 0x80000 /* Make iopen world-readable */
-+#define EXT3_MOUNT_EXTENTS 0x100000/* Extents support */
-+#define EXT3_MOUNT_EXTDEBUG 0x200000/* Extents debug */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -504,10 +510,12 @@
- #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-+#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
-
- #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
-- EXT3_FEATURE_INCOMPAT_RECOVER)
-+ EXT3_FEATURE_INCOMPAT_RECOVER| \
-+ EXT3_FEATURE_INCOMPAT_EXTENTS)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
- EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -689,6 +697,7 @@
- extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
-
- /* inode.c */
-+extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t);
- 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 *);
-@@ -770,6 +779,16 @@
- extern struct inode_operations ext3_symlink_inode_operations;
- extern struct inode_operations ext3_fast_symlink_inode_operations;
-
-+/* extents.c */
-+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
-+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+ struct buffer_head *, int);
-+extern void ext3_ext_truncate(struct inode *);
-+extern void ext3_ext_init(struct super_block *);
-+extern void ext3_ext_release(struct super_block *);
-+extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *);
-+extern int ext3_ext_ioctl(struct inode *inode, struct file *filp,
-+ unsigned int cmd, unsigned long arg);
-
- #endif /* __KERNEL__ */
-
-Index: linux-2.4.20-rh-20.9/include/linux/ext3_extents.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/linux/ext3_extents.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.20-rh-20.9/include/linux/ext3_extents.h 2004-11-02 21:03:00.000000000 +0300
-@@ -0,0 +1,251 @@
-+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
-+ * Written by Alex Tomas <alex@clusterfs.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program 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 Licens
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
-+ */
-+
-+#ifndef _LINUX_EXT3_EXTENTS
-+#define _LINUX_EXT3_EXTENTS
-+
-+/*
-+ * with AGRESSIVE_TEST defined capacity of index/leaf blocks
-+ * become very little, so index split, in-depth growing and
-+ * other hard changes happens much more often
-+ * this is for debug purposes only
-+ */
-+#define AGRESSIVE_TEST_
-+
-+/*
-+ * if CHECK_BINSEARCH defined, then results of binary search
-+ * will be checked by linear search
-+ */
-+#define CHECK_BINSEARCH_
-+
-+/*
-+ * if EXT_DEBUG is defined you can use 'extdebug' mount option
-+ * to get lots of info what's going on
-+ */
-+#define EXT_DEBUG_
-+#ifdef EXT_DEBUG
-+#define ext_debug(tree,fmt,a...) \
-+do { \
-+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
-+ printk(fmt, ##a); \
-+} while (0);
-+#else
-+#define ext_debug(tree,fmt,a...)
-+#endif
-+
-+/*
-+ * if EXT_STATS is defined then stats numbers are collected
-+ * these number will be displayed at umount time
-+ */
-+#define EXT_STATS_
-+
-+
-+#define EXT3_ALLOC_NEEDED 3 /* block bitmap + group desc. + sb */
-+
-+/*
-+ * ext3_inode has i_block array (total 60 bytes)
-+ * first 4 bytes are used to store:
-+ * - tree depth (0 mean there is no tree yet. all extents in the inode)
-+ * - number of alive extents in the inode
-+ */
-+
-+/*
-+ * this is extent on-disk structure
-+ * it's used at the bottom of the tree
-+ */
-+struct ext3_extent {
-+ __u32 ee_block; /* first logical block extent covers */
-+ __u16 ee_len; /* number of blocks covered by extent */
-+ __u16 ee_start_hi; /* high 16 bits of physical block */
-+ __u32 ee_start; /* low 32 bigs of physical block */
-+};
-+
-+/*
-+ * this is index on-disk structure
-+ * it's used at all the levels, but the bottom
-+ */
-+struct ext3_extent_idx {
-+ __u32 ei_block; /* index covers logical blocks from 'block' */
-+ __u32 ei_leaf; /* pointer to the physical block of the next *
-+ * level. leaf or next index could bet here */
-+ __u16 ei_leaf_hi; /* high 16 bits of physical block */
-+ __u16 ei_unused;
-+};
-+
-+/*
-+ * each block (leaves and indexes), even inode-stored has header
-+ */
-+struct ext3_extent_header {
-+ __u16 eh_magic; /* probably will support different formats */
-+ __u16 eh_entries; /* number of valid entries */
-+ __u16 eh_max; /* capacity of store in entries */
-+ __u16 eh_depth; /* has tree real underlaying blocks? */
-+ __u32 eh_generation; /* generation of the tree */
-+};
-+
-+#define EXT3_EXT_MAGIC 0xf30a
-+
-+/*
-+ * array of ext3_ext_path contains path to some extent
-+ * creation/lookup routines use it for traversal/splitting/etc
-+ * truncate uses it to simulate recursive walking
-+ */
-+struct ext3_ext_path {
-+ __u32 p_block;
-+ __u16 p_depth;
-+ struct ext3_extent *p_ext;
-+ struct ext3_extent_idx *p_idx;
-+ struct ext3_extent_header *p_hdr;
-+ struct buffer_head *p_bh;
-+};
-+
-+/*
-+ * structure for external API
-+ */
-+
-+/*
-+ * storage for cached extent
-+ */
-+struct ext3_ext_cache {
-+ __u32 ec_start;
-+ __u32 ec_block;
-+ __u32 ec_len;
-+ __u32 ec_type;
-+};
-+
-+#define EXT3_EXT_CACHE_NO 0
-+#define EXT3_EXT_CACHE_GAP 1
-+#define EXT3_EXT_CACHE_EXTENT 2
-+
-+/*
-+ * ext3_extents_tree is used to pass initial information
-+ * to top-level extents API
-+ */
-+struct ext3_extents_helpers;
-+struct ext3_extents_tree {
-+ struct inode *inode; /* inode which tree belongs to */
-+ void *root; /* ptr to data top of tree resides at */
-+ void *buffer; /* will be passed as arg to ^^ routines */
-+ int buffer_len;
-+ void *private;
-+ struct ext3_ext_cache *cex;/* last found extent */
-+ struct ext3_extents_helpers *ops;
-+};
-+
-+struct ext3_extents_helpers {
-+ int (*get_write_access)(handle_t *h, void *buffer);
-+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
-+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
-+ int (*remove_extent_credits)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
-+ int (*remove_extent)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
-+ int (*new_block)(handle_t *, struct ext3_extents_tree *,
-+ struct ext3_ext_path *, struct ext3_extent *,
-+ int *);
-+};
-+
-+/*
-+ * to be called by ext3_ext_walk_space()
-+ * negative retcode - error
-+ * positive retcode - signal for ext3_ext_walk_space(), see below
-+ * callback must return valid extent (passed or newly created)
-+ */
-+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
-+ struct ext3_ext_path *,
-+ struct ext3_extent *, int);
-+
-+#define EXT_CONTINUE 0
-+#define EXT_BREAK 1
-+#define EXT_REPEAT 2
-+
-+
-+#define EXT_MAX_BLOCK 0xffffffff
-+#define EXT_CACHE_MARK 0xffff
-+
-+
-+#define EXT_FIRST_EXTENT(__hdr__) \
-+ ((struct ext3_extent *) (((char *) (__hdr__)) + \
-+ sizeof(struct ext3_extent_header)))
-+#define EXT_FIRST_INDEX(__hdr__) \
-+ ((struct ext3_extent_idx *) (((char *) (__hdr__)) + \
-+ sizeof(struct ext3_extent_header)))
-+#define EXT_HAS_FREE_INDEX(__path__) \
-+ ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
-+#define EXT_LAST_EXTENT(__hdr__) \
-+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
-+#define EXT_LAST_INDEX(__hdr__) \
-+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
-+#define EXT_MAX_EXTENT(__hdr__) \
-+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_MAX_INDEX(__hdr__) \
-+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+
-+#define EXT_ROOT_HDR(tree) \
-+ ((struct ext3_extent_header *) (tree)->root)
-+#define EXT_BLOCK_HDR(bh) \
-+ ((struct ext3_extent_header *) (bh)->b_data)
-+#define EXT_DEPTH(_t_) \
-+ (((struct ext3_extent_header *)((_t_)->root))->eh_depth)
-+#define EXT_GENERATION(_t_) \
-+ (((struct ext3_extent_header *)((_t_)->root))->eh_generation)
-+
-+
-+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
-+
-+
-+/*
-+ * this structure is used to gather extents from the tree via ioctl
-+ */
-+struct ext3_extent_buf {
-+ unsigned long start;
-+ int buflen;
-+ void *buffer;
-+ void *cur;
-+ int err;
-+};
-+
-+/*
-+ * this structure is used to collect stats info about the tree
-+ */
-+struct ext3_extent_tree_stats {
-+ int depth;
-+ int extents_num;
-+ int leaf_num;
-+};
-+
-+void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
-+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
-+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
-+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
-+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
-+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
-+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
-+
-+static inline void
-+ext3_ext_invalidate_cache(struct ext3_extents_tree *tree)
-+{
-+ if (tree->cex)
-+ tree->cex->ec_type = EXT3_EXT_CACHE_NO;
-+}
-+
-+
-+#endif /* _LINUX_EXT3_EXTENTS */
-+
-Index: linux-2.4.20-rh-20.9/include/linux/ext3_fs_i.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/linux/ext3_fs_i.h 2004-11-02 21:01:47.000000000 +0300
-+++ linux-2.4.20-rh-20.9/include/linux/ext3_fs_i.h 2004-11-02 21:06:02.000000000 +0300
-@@ -82,6 +82,8 @@
- struct dynlock i_htree_lock;
- struct semaphore i_append_sem;
- struct semaphore i_rename_sem;
-+
-+ __u32 i_cached_extent[4];
- };
-
- #endif /* _LINUX_EXT3_FS_I */
-Index: linux-2.4.21-20.EL/fs/ext3/extents.c
+Index: linux-2.4.21-rhel/fs/ext3/extents.c
===================================================================
---- linux-2.4.21-20.EL.orig/fs/ext3/extents.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.21-20.EL/fs/ext3/extents.c 2004-11-03 00:35:30.644364336 +0300
-@@ -0,0 +1,2278 @@
+--- linux-2.4.21-rhel.orig/fs/ext3/extents.c 2005-03-02 22:42:20.659360368 +0300
++++ linux-2.4.21-rhel/fs/ext3/extents.c 2005-03-04 02:34:52.000000000 +0300
+@@ -0,0 +1,2312 @@
+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+#include <linux/time.h>
+#include <linux/ext3_jbd.h>
+#include <linux/jbd.h>
++#include <linux/locks.h>
+#include <linux/smp_lock.h>
+#include <linux/highuid.h>
+#include <linux/pagemap.h>
+#include <linux/quotaops.h>
+#include <linux/string.h>
+#include <linux/slab.h>
-+#include <linux/locks.h>
+#include <linux/ext3_extents.h>
+#include <asm/uaccess.h>
+
++
++static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
++{
++ if (eh->eh_magic != EXT3_EXT_MAGIC) {
++ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
++ (unsigned)eh->eh_magic);
++ return -EIO;
++ }
++ if (eh->eh_max == 0) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
++ (unsigned)eh->eh_max);
++ return -EIO;
++ }
++ if (eh->eh_entries > eh->eh_max) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
++ (unsigned)eh->eh_entries);
++ return -EIO;
++ }
++ return 0;
++}
++
+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
+{
+ int err;
+ * - ENOMEM
+ */
+static int ext3_ext_get_access(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path)
+{
+ int err;
+
+ * - EIO
+ */
+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int err;
+ if (path->p_bh) {
+
+static int inline
+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, struct ext3_extent *ex,
-+ int *err)
++ struct ext3_ext_path *path, struct ext3_extent *ex,
++ int *err)
+{
+ int goal, depth, newblock;
+ struct inode *inode;
+ unsigned long colour;
+
+ bg_start = (ei->i_block_group *
-+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
+ colour = (current->pid % 16) *
+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 6;
+#endif
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 5;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len - sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 3;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 4;
+#endif
+}
+
+static void ext3_ext_show_path(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int k, l = path->p_depth;
+ for (k = 0; k <= l; k++, path++) {
+ if (path->p_idx) {
+ ext_debug(tree, " %d->%d", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ } else if (path->p_ext) {
+ ext_debug(tree, " %d:%d:%d",
-+ path->p_ext->ee_block,
-+ path->p_ext->ee_len,
-+ path->p_ext->ee_start);
++ path->p_ext->ee_block,
++ path->p_ext->ee_len,
++ path->p_ext->ee_start);
+ } else
+ ext_debug(tree, " []");
+ }
+}
+
+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int depth = EXT_DEPTH(tree);
+
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ ext_debug(tree, "%d:%d:%d ",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ }
+ ext_debug(tree, "\n");
+#endif
+ int depth = path->p_depth;
+ int i;
+
-+ for (i = 0; i <= depth; i++, path++)
++ for (i = 0; i <= depth; i++, path++) {
+ if (path->p_bh) {
+ brelse(path->p_bh);
+ path->p_bh = NULL;
+ }
++ }
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent_idx *ix;
+
+ ix += l;
+ path->p_idx = ix;
-+ ext_debug(tree, " -> %d->%d ", path->p_idx->ei_block, path->p_idx->ei_leaf);
++ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
+
+ while (l++ < r) {
+ if (block < ix->ei_block)
+ path->p_idx = ix++;
+ }
+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+
+#ifdef CHECK_BINSEARCH
+ {
+ for (k = 0; k < eh->eh_entries; k++, ix++) {
+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
+ printk("k=%d, ix=0x%p, first=0x%p\n", k,
-+ ix, EXT_FIRST_INDEX(eh));
++ ix, EXT_FIRST_INDEX(eh));
+ printk("%u <= %u\n",
-+ ix->ei_block,ix[-1].ei_block);
++ ix->ei_block,ix[-1].ei_block);
+ }
+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
+ if (block < ix->ei_block)
+ EXT_ASSERT(chix == path->p_idx);
+ }
+#endif
-+
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent *ex;
+ ex += l;
+ path->p_ext = ex;
+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+ while (l++ < r) {
+ if (block < ex->ee_block)
+ path->p_ext = ex++;
+ }
+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+#ifdef CHECK_BINSEARCH
+ {
+ EXT_ASSERT(chex == path->p_ext);
+ }
+#endif
-+
+}
+
+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
+
+struct ext3_ext_path *
+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ struct buffer_head *bh;
+
+ eh = EXT_ROOT_HDR(tree);
+ EXT_ASSERT(eh);
++ if (ext3_ext_check_header(eh))
++ goto err;
++
+ i = depth = EXT_DEPTH(tree);
+ EXT_ASSERT(eh->eh_max);
+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(i == 0 || eh->eh_entries > 0);
+
+ /* account possible depth increase */
+ if (!path) {
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+ GFP_NOFS);
++ GFP_NOFS);
+ if (!path)
+ return ERR_PTR(-ENOMEM);
+ }
+ /* walk through the tree */
+ while (i) {
+ ext_debug(tree, "depth %d: num %d, max %d\n",
-+ ppos, eh->eh_entries, eh->eh_max);
++ ppos, eh->eh_entries, eh->eh_max);
+ ext3_ext_binsearch_idx(tree, path + ppos, block);
+ path[ppos].p_block = path[ppos].p_idx->ei_leaf;
+ path[ppos].p_depth = i;
+ path[ppos].p_ext = NULL;
+
+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
-+ if (!bh) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ return ERR_PTR(-EIO);
-+ }
++ if (!bh)
++ goto err;
++
+ eh = EXT_BLOCK_HDR(bh);
+ ppos++;
+ EXT_ASSERT(ppos <= depth);
+ path[ppos].p_bh = bh;
+ path[ppos].p_hdr = eh;
+ i--;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+ }
+
+ path[ppos].p_depth = i;
+ path[ppos].p_hdr = eh;
+ path[ppos].p_ext = NULL;
++ path[ppos].p_idx = NULL;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+
+ /* find extent */
+ ext3_ext_binsearch(tree, path + ppos, block);
+ ext3_ext_show_path(tree, path);
+
+ return path;
++
++err:
++ printk(KERN_ERR "EXT3-fs: header is corrupted!\n");
++ ext3_ext_drop_refs(path);
++ kfree(path);
++ return ERR_PTR(-EIO);
+}
+
+/*
+ * it check where to insert: before curp or after curp
+ */
+static int ext3_ext_insert_index(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *curp,
-+ int logical, int ptr)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *curp,
++ int logical, int ptr)
+{
+ struct ext3_extent_idx *ix;
+ int len, err;
+ len = (len - 1) * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d after: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ (curp->p_idx + 1), (curp->p_idx + 2));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ (curp->p_idx + 1), (curp->p_idx + 2));
+ memmove(curp->p_idx + 2, curp->p_idx + 1, len);
+ }
+ ix = curp->p_idx + 1;
+ len = len * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d before: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ curp->p_idx, (curp->p_idx + 1));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ curp->p_idx, (curp->p_idx + 1));
+ memmove(curp->p_idx + 1, curp->p_idx, len);
+ ix = curp->p_idx;
+ }
+ * - initialize subtree
+ */
+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext, int at)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext, int at)
+{
+ struct buffer_head *bh = NULL;
+ int depth = EXT_DEPTH(tree);
+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ border = path[depth].p_ext[1].ee_block;
+ ext_debug(tree, "leaf will be splitted."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ } else {
+ border = newext->ee_block;
+ ext_debug(tree, "leaf will be added."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ }
+
+ /*
+ while (path[depth].p_ext <=
+ EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
-+ path[depth].p_ext->ee_block,
-+ path[depth].p_ext->ee_start,
-+ path[depth].p_ext->ee_len,
-+ newblock);
-+ memmove(ex++, path[depth].p_ext++,
-+ sizeof(struct ext3_extent));
++ path[depth].p_ext->ee_block,
++ path[depth].p_ext->ee_start,
++ path[depth].p_ext->ee_len,
++ newblock);
++ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
+ neh->eh_entries++;
+ m++;
+ }
+ fidx->ei_leaf = oldblock;
+
+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
-+ i, newblock, border, oldblock);
++ i, newblock, border, oldblock);
+ /* copy indexes */
+ m = 0;
+ path[i].p_idx++;
+
+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+ EXT_MAX_INDEX(path[i].p_hdr));
++ EXT_MAX_INDEX(path[i].p_hdr));
+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+ EXT_LAST_INDEX(path[i].p_hdr));
++ EXT_LAST_INDEX(path[i].p_hdr));
+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
+ ext_debug(tree, "%d: move %d:%d in new index %lu\n",
-+ i, path[i].p_idx->ei_block,
-+ path[i].p_idx->ei_leaf, newblock);
++ i, path[i].p_idx->ei_block,
++ path[i].p_idx->ei_leaf, newblock);
+ memmove(++fidx, path[i].p_idx++,
-+ sizeof(struct ext3_extent_idx));
++ sizeof(struct ext3_extent_idx));
+ neh->eh_entries++;
+ EXT_ASSERT(neh->eh_entries <= neh->eh_max);
+ m++;
+ /* insert new index */
+ if (!err)
+ err = ext3_ext_insert_index(handle, tree, path + at,
-+ border, newblock);
++ border, newblock);
+
+cleanup:
+ if (bh) {
+ * just created block
+ */
+static int ext3_ext_grow_indepth(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp = path;
+ struct ext3_extent_header *neh;
+ neh = EXT_ROOT_HDR(tree);
+ fidx = EXT_FIRST_INDEX(neh);
+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
-+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
++ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
+
+ neh->eh_depth = path->p_depth + 1;
+ err = ext3_ext_dirty(handle, tree, curp);
+ * then it requests in-depth growing
+ */
+static int ext3_ext_create_new_leaf(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp;
+ int depth, i, err = 0;
+ if (depth == path->p_depth) {
+ /* leaf */
+ if (path[depth].p_ext !=
-+ EXT_LAST_EXTENT(path[depth].p_hdr))
++ EXT_LAST_EXTENT(path[depth].p_hdr))
+ return path[depth].p_ext[1].ee_block;
+ } else {
+ /* index */
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ }
+ depth--;
+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
+ */
+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth;
+
+
+ while (depth >= 0) {
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ depth--;
+ }
+ * TODO: do we need to correct tree in all cases?
+ */
+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ int depth = EXT_DEPTH(tree);
+
+static int inline
+ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex1,
++ struct ext3_extent *ex2)
+{
+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
+ return 0;
+ * creating new leaf in no-space case
+ */
+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_extent_header * eh;
+ struct ext3_extent *ex, *fex;
+ int depth, len, err, next;
+
+ EXT_ASSERT(newext->ee_len > 0);
-+ EXT_ASSERT(newext->ee_len < EXT_CACHE_MARK);
+ depth = EXT_DEPTH(tree);
+ ex = path[depth].p_ext;
+ EXT_ASSERT(path[depth].p_hdr);
+ /* try to insert block into found extent and return */
+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
+ ext_debug(tree, "append %d block to %d:%d (from %d)\n",
-+ newext->ee_len, ex->ee_block, ex->ee_len,
-+ ex->ee_start);
++ newext->ee_len, ex->ee_block, ex->ee_len,
++ ex->ee_start);
+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
+ return err;
+ ex->ee_len += newext->ee_len;
+ eh = npath[depth].p_hdr;
+ if (eh->eh_entries < eh->eh_max) {
+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->eh_entries);
++ eh->eh_entries);
+ path = npath;
+ goto repeat;
+ }
+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->eh_entries, eh->eh_max);
++ eh->eh_entries, eh->eh_max);
+ }
+
+ /*
+ if (!nearex) {
+ /* there is no extent in this leaf, create first one */
+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len);
++ newext->ee_block, newext->ee_start,
++ newext->ee_len);
+ path[depth].p_ext = EXT_FIRST_EXTENT(eh);
+ } else if (newext->ee_block > nearex->ee_block) {
+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
+ len = (len - 1) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start,
++ newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 2, nearex + 1, len);
+ }
+ path[depth].p_ext = nearex + 1;
+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start, newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start, newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 1, nearex, len);
+ path[depth].p_ext = nearex;
+ }
+ /* merge with next extent! */
+ nearex->ee_len += nearex[1].ee_len;
+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
-+ len = (EXT_LAST_EXTENT(eh) - nearex - 1)
-+ * sizeof(struct ext3_extent);
++ len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++ sizeof(struct ext3_extent);
+ memmove(nearex + 1, nearex + 2, len);
+ }
+ eh->eh_entries--;
+ unsigned long num, ext_prepare_callback func)
+{
+ struct ext3_ext_path *path = NULL;
-+ struct ext3_extent *ex, cbex;
++ struct ext3_ext_cache cbex;
++ struct ext3_extent *ex;
+ unsigned long next, start = 0, end = 0;
+ unsigned long last = block + num;
+ int depth, exists, err = 0;
+ EXT_ASSERT(end > start);
+
+ if (!exists) {
-+ cbex.ee_block = start;
-+ cbex.ee_len = end - start;
-+ cbex.ee_start = 0;
-+ } else
-+ cbex = *ex;
++ cbex.ec_block = start;
++ cbex.ec_len = end - start;
++ cbex.ec_start = 0;
++ cbex.ec_type = EXT3_EXT_CACHE_GAP;
++ } else {
++ cbex.ec_block = ex->ee_block;
++ cbex.ec_len = ex->ee_len;
++ cbex.ec_start = ex->ee_start;
++ cbex.ec_type = EXT3_EXT_CACHE_EXTENT;
++ }
+
++ EXT_ASSERT(cbex.ec_len > 0);
+ EXT_ASSERT(path[depth].p_hdr);
-+ err = func(tree, path, &cbex, exists);
++ err = func(tree, path, &cbex);
+ ext3_ext_drop_refs(path);
+
+ if (err < 0)
+ path = NULL;
+ }
+
-+ block = cbex.ee_block + cbex.ee_len;
++ block = cbex.ec_block + cbex.ec_len;
+ }
+
+ if (path) {
+
+static inline void
+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
-+ __u32 len, __u32 start, int type)
++ __u32 len, __u32 start, int type)
+{
+ EXT_ASSERT(len > 0);
+ if (tree->cex) {
+ */
+static inline void
+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ unsigned long block)
++ struct ext3_ext_path *path,
++ unsigned long block)
+{
+ int depth = EXT_DEPTH(tree);
+ unsigned long lblock, len;
+ lblock = block;
+ len = ex->ee_block - block;
+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len);
+ } else if (block >= ex->ee_block + ex->ee_len) {
+ lblock = ex->ee_block + ex->ee_len;
+ len = ext3_ext_next_allocated_block(path);
+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) block);
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) block);
+ EXT_ASSERT(len > lblock);
+ len = len - lblock;
+ } else {
+
+static inline int
+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
-+ struct ext3_extent *ex)
++ struct ext3_extent *ex)
+{
+ struct ext3_ext_cache *cex = tree->cex;
+
+ return EXT3_EXT_CACHE_NO;
+
+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
-+ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+ ex->ee_block = cex->ec_block;
+ ex->ee_start = cex->ec_start;
+ ex->ee_len = cex->ec_len;
+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) ex->ee_start);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) ex->ee_start);
+ return cex->ec_type;
+ }
+
+ * last index in the block only
+ */
+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct buffer_head *bh;
+ int err;
+ if ((err = ext3_ext_dirty(handle, tree, path)))
+ return err;
+ ext_debug(tree, "index is empty, remove it, free block %d\n",
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->ei_leaf);
+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
+}
+
+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth = EXT_DEPTH(tree);
+ int needed;
+
+static int
+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, tex;
+ struct ext3_ext_path *npath;
+ /* FIXME: some callback to free underlying resource
+ * and correct ee_start? */
+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
-+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
+
+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
+ if (IS_ERR(npath))
+ kfree(npath);
+
+ return err;
-+
+}
+
+static int
+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, *fu = NULL, *lu, *le;
+ int err = 0, correct_index = 0;
+ }
+
+ lu = ex;
-+ while (ex >= EXT_FIRST_EXTENT(eh) &&
-+ ex->ee_block + ex->ee_len > start) {
++ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
+ path[depth].p_ext = ex;
+
+ block = ex->ee_block;
+ num = 0;
+ EXT_ASSERT(a == ex->ee_block &&
-+ b == ex->ee_block + ex->ee_len - 1);
++ b == ex->ee_block + ex->ee_len - 1);
+ }
+
+ if (ex == EXT_FIRST_EXTENT(eh))
+ goto out;
+
+ ext_debug(tree, "new extent: %u:%u:%u\n",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ ex--;
+ }
+
+}
+
+int ext3_ext_remove_space(struct ext3_extents_tree *tree,
-+ unsigned long start, unsigned long end)
++ unsigned long start, unsigned long end)
+{
+ struct inode *inode = tree->inode;
+ struct super_block *sb = inode->i_sb;
+ */
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
+ if (IS_ERR(path)) {
-+ ext3_error(sb, "ext3_ext_remove_space",
-+ "Can't allocate path array");
++ ext3_error(sb, __FUNCTION__, "Can't allocate path array");
+ ext3_journal_stop(handle, inode);
+ return -ENOMEM;
+ }
+ ext3_ext_last_covered(path[i].p_hdr, end);
+ path[i].p_block = path[i].p_hdr->eh_entries + 1;
+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
-+ path[i].p_hdr, path[i].p_hdr->eh_entries);
++ path[i].p_hdr, path[i].p_hdr->eh_entries);
+ } else {
+ /* we've already was here, see at next index */
+ path[i].p_idx--;
+ }
+
+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
-+ i, EXT_FIRST_INDEX(path[i].p_hdr),
-+ path[i].p_idx);
++ i, EXT_FIRST_INDEX(path[i].p_hdr),
++ path[i].p_idx);
+ if (ext3_ext_more_to_rm(path + i)) {
+ /* go to the next level */
+ ext_debug(tree, "move to level %d (block %d)\n",
-+ i + 1, path[i].p_idx->ei_leaf);
++ i + 1, path[i].p_idx->ei_leaf);
+ memset(path + i + 1, 0, sizeof(*path));
+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
+ if (!path[i+1].p_bh) {
+}
+
+static int ext3_ext_mergable(struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex2)
+{
+ /* FIXME: support for large fs */
+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
+
+static int
+ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed;
+
+
+static int
+ext3_remove_blocks(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+ handle_t *handle = ext3_journal_start(tree->inode, needed);
+ num = ex->ee_block + ex->ee_len - from;
+ start = ex->ee_start + ex->ee_len - num;
+ ext_debug(tree, "free last %lu blocks starting %lu\n",
-+ num, start);
++ num, start);
+ for (i = 0; i < num; i++) {
+ bh = sb_get_hash_table(tree->inode->i_sb, start + i);
+ ext3_forget(handle, 0, tree->inode, bh, start + i);
+ ext3_free_blocks(handle, tree->inode, start, num);
+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+ printk("strange request: removal %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ } else {
+ printk("strange request: removal(2) %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ }
+ ext3_journal_stop(handle, tree->inode);
+ return 0;
+}
+
+int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path,
-+ unsigned long block)
++ unsigned long block)
+{
+ struct ext3_inode_info *ei = EXT3_I(inode);
+ unsigned long bg_start;
+}
+
+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int *err)
++ struct ext3_ext_path *path,
++ struct ext3_extent *ex, int *err)
+{
+ struct inode *inode = tree->inode;
+ int newblock, goal;
+};
+
+void ext3_init_tree_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode)
++ struct inode *inode)
+{
+ tree->inode = inode;
+ tree->root = (void *) EXT3_I(inode)->i_data;
+}
+
+int ext3_ext_get_block(handle_t *handle, struct inode *inode,
-+ long iblock, struct buffer_head *bh_result, int create)
++ long iblock, struct buffer_head *bh_result, int create)
+{
+ struct ext3_ext_path *path = NULL;
+ struct ext3_extent newex;
+ clear_bit(BH_New, &bh_result->b_state);
+ ext3_init_tree_desc(&tree, inode);
+ ext_debug(&tree, "block %d requested for inode %u\n",
-+ (int) iblock, (unsigned) inode->i_ino);
++ (int) iblock, (unsigned) inode->i_ino);
+ down_write(&EXT3_I(inode)->truncate_sem);
+
+ /* check in cache */
+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
+ newblock = iblock - ex->ee_block + ex->ee_start;
+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
-+ (int) iblock, ex->ee_block, ex->ee_len,
-+ newblock);
++ (int) iblock, ex->ee_block, ex->ee_len,
++ newblock);
+ ext3_ext_put_in_cache(&tree, ex->ee_block,
-+ ex->ee_len, ex->ee_start,
-+ EXT3_EXT_CACHE_EXTENT);
++ ex->ee_len, ex->ee_start,
++ EXT3_EXT_CACHE_EXTENT);
+ goto out;
+ }
+ }
+ if (!newblock)
+ goto out2;
+ ext_debug(&tree, "allocate new block: goal %d, found %d\n",
-+ goal, newblock);
++ goal, newblock);
+
+ /* try to insert new extent into found leaf and return */
+ newex.ee_block = iblock;
+ set_bit(BH_New, &bh_result->b_state);
+
+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
-+ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
+out:
+ ext3_ext_show_leaf(&tree, path);
+ set_bit(BH_Mapped, &bh_result->b_state);
+
+ if (page)
+ ext3_block_truncate_page(handle, mapping, inode->i_size, page,
-+ inode->i_sb->s_blocksize);
++ inode->i_sb->s_blocksize);
+
+ down_write(&EXT3_I(inode)->truncate_sem);
+ ext3_ext_invalidate_cache(&tree);
+ EXT3_I(inode)->i_disksize = inode->i_size;
+ ext3_mark_inode_dirty(handle, inode);
+
-+ last_block = (inode->i_size + sb->s_blocksize - 1)
-+ >> EXT3_BLOCK_SIZE_BITS(sb);
++ last_block = (inode->i_size + sb->s_blocksize - 1) >>
++ EXT3_BLOCK_SIZE_BITS(sb);
+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
+
+ /* In a multi-transaction truncate, we only make the final
+
+static int
+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *newex)
+{
+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
+
-+ if (!exist)
++ if (newex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
++
+ if (buf->err < 0)
+ return EXT_BREAK;
+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
+
+static int
+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *ex)
+{
+ struct ext3_extent_tree_stats *buf =
+ (struct ext3_extent_tree_stats *) tree->private;
+ int depth;
+
-+ if (!exist)
++ if (ex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
+
+ depth = EXT_DEPTH(tree);
+ tree.private = &buf;
+ down_write(&EXT3_I(inode)->truncate_sem);
+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
++ ext3_ext_store_extent_cb);
+ up_write(&EXT3_I(inode)->truncate_sem);
+ if (err == 0)
+ err = buf.err;
+ buf.leaf_num = 0;
+ tree.private = &buf;
+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
++ ext3_ext_collect_stats_cb);
+ up_write(&EXT3_I(inode)->truncate_sem);
+ if (!err)
+ err = copy_to_user((void *) arg, &buf, sizeof(buf));
+EXPORT_SYMBOL(ext3_ext_walk_space);
+EXPORT_SYMBOL(ext3_ext_find_goal);
+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
-+
-Index: linux-2.4.21-20.EL/fs/ext3/ialloc.c
+Index: linux-2.4.21-rhel/fs/ext3/ialloc.c
===================================================================
---- linux-2.4.21-20.EL.orig/fs/ext3/ialloc.c 2004-11-02 20:43:27.000000000 +0300
-+++ linux-2.4.21-20.EL/fs/ext3/ialloc.c 2004-11-02 20:53:34.000000000 +0300
-@@ -596,9 +596,22 @@
+--- linux-2.4.21-rhel.orig/fs/ext3/ialloc.c 2005-03-04 00:44:34.000000000 +0300
++++ linux-2.4.21-rhel/fs/ext3/ialloc.c 2005-03-04 00:44:35.000000000 +0300
+@@ -596,6 +596,19 @@
iloc.bh = NULL;
goto fail;
}
-- err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-- if (err) goto fail;
-
-+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
-+ ext3_extents_initialize_blockmap(handle, inode);
++ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4);
++ ext3_extents_initialize_blockmap(handle, inode);
+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
+ if (err) goto fail;
+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+ }
-+ }
-+
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err) goto fail;
-
-
- #ifdef CONFIG_EXT3_FS_XATTR
-Index: linux-2.4.21-20.EL/fs/ext3/inode.c
++ }
++
+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
+ if (err) goto fail;
+
+Index: linux-2.4.21-rhel/fs/ext3/inode.c
===================================================================
---- linux-2.4.21-20.EL.orig/fs/ext3/inode.c 2004-11-02 20:43:31.000000000 +0300
-+++ linux-2.4.21-20.EL/fs/ext3/inode.c 2004-11-02 20:53:34.000000000 +0300
+--- linux-2.4.21-rhel.orig/fs/ext3/inode.c 2005-03-04 00:44:34.000000000 +0300
++++ linux-2.4.21-rhel/fs/ext3/inode.c 2005-03-04 00:44:35.000000000 +0300
@@ -859,6 +859,16 @@
goto reread;
}
+static inline int
+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+ struct buffer_head *bh, int create, int extend_disksize)
++ struct buffer_head *bh, int create, int extend_disksize)
+{
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
+ return ext3_ext_get_block(handle, inode, block, bh, create);
+ return ext3_get_block_handle(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+}
+
/*
if (IS_ERR(page))
return;
+
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_truncate(inode, page);
++ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++ return ext3_ext_truncate(inode, page);
handle = start_transaction(inode);
if (IS_ERR(handle))
for (block = 0; block < EXT3_N_BLOCKS; block++)
ei->i_data[block] = iloc.raw_inode->i_block[block];
INIT_LIST_HEAD(&ei->i_orphan);
-+ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
++ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4);
if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
EXT3_I(inode)->i_extra_isize =
if (rc) {
printk(KERN_INFO "ext3_map_inode_page: error %d "
"allocating block %ld\n", rc, iblock);
-Index: linux-2.4.21-20.EL/fs/ext3/Makefile
+Index: linux-2.4.21-rhel/fs/ext3/Makefile
===================================================================
---- linux-2.4.21-20.EL.orig/fs/ext3/Makefile 2004-11-02 20:43:19.000000000 +0300
-+++ linux-2.4.21-20.EL/fs/ext3/Makefile 2004-11-02 20:53:34.000000000 +0300
+--- linux-2.4.21-rhel.orig/fs/ext3/Makefile 2005-03-04 00:44:33.000000000 +0300
++++ linux-2.4.21-rhel/fs/ext3/Makefile 2005-03-04 00:44:35.000000000 +0300
@@ -9,10 +9,11 @@
O_TARGET := ext3.o
obj-m := $(O_TARGET)
export-objs += xattr.o
-Index: linux-2.4.21-20.EL/fs/ext3/super.c
+Index: linux-2.4.21-rhel/fs/ext3/super.c
===================================================================
---- linux-2.4.21-20.EL.orig/fs/ext3/super.c 2004-11-02 20:43:27.000000000 +0300
-+++ linux-2.4.21-20.EL/fs/ext3/super.c 2004-11-02 20:53:34.000000000 +0300
-@@ -648,6 +648,7 @@
+--- linux-2.4.21-rhel.orig/fs/ext3/super.c 2005-03-04 00:44:34.000000000 +0300
++++ linux-2.4.21-rhel/fs/ext3/super.c 2005-03-04 00:44:35.000000000 +0300
+@@ -556,6 +556,7 @@
#ifdef EXT3_DELETE_THREAD
J_ASSERT(sbi->s_delete_inodes == 0);
#endif
ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
if (!(sb->s_flags & MS_RDONLY)) {
-@@ -851,6 +852,10 @@
+@@ -755,6 +756,10 @@
return 0;
}
}
else if (!strcmp (this_char, "grpid") ||
!strcmp (this_char, "bsdgroups"))
set_opt (*mount_options, GRPID);
-@@ -1546,6 +1551,8 @@
+@@ -1450,6 +1455,8 @@
test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
"writeback");
return sb;
failed_mount3:
-Index: linux-2.4.21-20.EL/fs/ext3/ioctl.c
+Index: linux-2.4.21-rhel/fs/ext3/ioctl.c
===================================================================
---- linux-2.4.21-20.EL.orig/fs/ext3/ioctl.c 2004-11-02 20:43:14.000000000 +0300
-+++ linux-2.4.21-20.EL/fs/ext3/ioctl.c 2004-11-02 20:53:34.000000000 +0300
+--- linux-2.4.21-rhel.orig/fs/ext3/ioctl.c 2005-03-04 00:44:32.000000000 +0300
++++ linux-2.4.21-rhel/fs/ext3/ioctl.c 2005-03-04 00:44:35.000000000 +0300
@@ -173,6 +173,10 @@
return ret;
}
default:
return -ENOTTY;
}
-Index: linux-2.4.21-20.EL/include/linux/ext3_fs.h
+Index: linux-2.4.21-rhel/include/linux/ext3_fs.h
===================================================================
---- linux-2.4.21-20.EL.orig/include/linux/ext3_fs.h 2004-11-02 20:43:27.000000000 +0300
-+++ linux-2.4.21-20.EL/include/linux/ext3_fs.h 2004-11-02 20:53:34.000000000 +0300
-@@ -188,6 +188,7 @@
+--- linux-2.4.21-rhel.orig/include/linux/ext3_fs.h 2005-03-04 00:44:34.000000000 +0300
++++ linux-2.4.21-rhel/include/linux/ext3_fs.h 2005-03-04 00:44:35.000000000 +0300
+@@ -188,8 +188,9 @@
#define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
#define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
- #define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */
+-#define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE 0x00085FFF /* User visible flags */
#define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
+
+ /*
@@ -212,6 +213,9 @@
#ifdef CONFIG_JBD_DEBUG
#define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long)
#endif
-+#define EXT3_IOC_GET_EXTENTS _IOR('f', 5, long)
-+#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long)
-+#define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long)
++#define EXT3_IOC_GET_EXTENTS _IOR('f', 5, long)
++#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long)
++#define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long)
/*
* Structure of an inode on the disk
extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
/* inode.c */
-+int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t,
++extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t,
+ struct page *, unsigned);
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 *);
+/* extents.c */
+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+ struct buffer_head *, int);
++ struct buffer_head *, int);
+extern void ext3_ext_truncate(struct inode *, struct page *);
+extern void ext3_ext_init(struct super_block *);
+extern void ext3_ext_release(struct super_block *);
#endif /* __KERNEL__ */
-Index: linux-2.4.21-20.EL/include/linux/ext3_extents.h
+Index: linux-2.4.21-rhel/include/linux/ext3_extents.h
===================================================================
---- linux-2.4.21-20.EL.orig/include/linux/ext3_extents.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.21-20.EL/include/linux/ext3_extents.h 2004-11-02 20:53:34.000000000 +0300
-@@ -0,0 +1,251 @@
+--- linux-2.4.21-rhel.orig/include/linux/ext3_extents.h 2005-03-02 22:42:20.659360368 +0300
++++ linux-2.4.21-rhel/include/linux/ext3_extents.h 2005-03-04 02:34:52.000000000 +0300
+@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ */
+#define EXT_DEBUG_
+#ifdef EXT_DEBUG
-+#define ext_debug(tree,fmt,a...) \
++#define ext_debug(tree,fmt,a...) \
+do { \
+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
+ printk(fmt, ##a); \
+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
+ int (*remove_extent_credits)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*remove_extent)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*new_block)(handle_t *, struct ext3_extents_tree *,
-+ struct ext3_ext_path *, struct ext3_extent *,
-+ int *);
++ struct ext3_ext_path *, struct ext3_extent *,
++ int *);
+};
+
+/*
+ * callback must return valid extent (passed or newly created)
+ */
+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
-+ struct ext3_ext_path *,
-+ struct ext3_extent *, int);
++ struct ext3_ext_path *,
++ struct ext3_ext_cache *);
+
+#define EXT_CONTINUE 0
+#define EXT_BREAK 1
+
+
+#define EXT_MAX_BLOCK 0xffffffff
-+#define EXT_CACHE_MARK 0xffff
+
+
+#define EXT_FIRST_EXTENT(__hdr__) \
+
+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
+
++#define EXT_CHECK_PATH(tree,path) \
++{ \
++ int depth = EXT_DEPTH(tree); \
++ BUG_ON((unsigned long) (path) < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_idx < \
++ __PAGE_OFFSET && (path)[depth].p_idx != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_ext < \
++ __PAGE_OFFSET && (path)[depth].p_ext != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET \
++ && depth != 0); \
++ BUG_ON((path)[0].p_depth != depth); \
++}
++
+
+/*
+ * this structure is used to gather extents from the tree via ioctl
+ int leaf_num;
+};
+
-+void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
+
+
+#endif /* _LINUX_EXT3_EXTENTS */
-+
-Index: linux-2.4.21-20.EL/include/linux/ext3_fs_i.h
+Index: linux-2.4.21-rhel/include/linux/ext3_fs_i.h
===================================================================
---- linux-2.4.21-20.EL.orig/include/linux/ext3_fs_i.h 2004-11-02 20:43:27.000000000 +0300
-+++ linux-2.4.21-20.EL/include/linux/ext3_fs_i.h 2004-11-02 20:58:19.000000000 +0300
+--- linux-2.4.21-rhel.orig/include/linux/ext3_fs_i.h 2005-03-04 00:44:34.000000000 +0300
++++ linux-2.4.21-rhel/include/linux/ext3_fs_i.h 2005-03-04 01:56:36.000000000 +0300
@@ -90,6 +90,8 @@
* by other means, so we have truncate_sem.
*/
struct rw_semaphore truncate_sem;
+
-+ __u32 i_cached_extent[4];
++ __u32 i_cached_extent[4];
};
#endif /* _LINUX_EXT3_FS_I */
===================================================================
--- linux-2.4.21-suse2.orig/fs/ext3/extents.c 2003-01-30 13:24:37.000000000 +0300
+++ linux-2.4.21-suse2/fs/ext3/extents.c 2004-11-03 00:34:45.404241880 +0300
-@@ -0,0 +1,2269 @@
+@@ -0,0 +1,2303 @@
+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+#include <linux/ext3_extents.h>
+#include <asm/uaccess.h>
+
++
++static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
++{
++ if (eh->eh_magic != EXT3_EXT_MAGIC) {
++ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
++ (unsigned)eh->eh_magic);
++ return -EIO;
++ }
++ if (eh->eh_max == 0) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
++ (unsigned)eh->eh_max);
++ return -EIO;
++ }
++ if (eh->eh_entries > eh->eh_max) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
++ (unsigned)eh->eh_entries);
++ return -EIO;
++ }
++ return 0;
++}
++
+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
+{
+ int err;
+ * - ENOMEM
+ */
+static int ext3_ext_get_access(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path)
+{
+ int err;
+
+ * - EIO
+ */
+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int err;
+ if (path->p_bh) {
+
+static int inline
+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, struct ext3_extent *ex,
-+ int *err)
++ struct ext3_ext_path *path, struct ext3_extent *ex,
++ int *err)
+{
+ int goal, depth, newblock;
+ struct inode *inode;
+ unsigned long colour;
+
+ bg_start = (ei->i_block_group *
-+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
+ colour = (current->pid % 16) *
+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 6;
+#endif
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 5;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len - sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 3;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 4;
+#endif
+}
+
+static void ext3_ext_show_path(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int k, l = path->p_depth;
+ for (k = 0; k <= l; k++, path++) {
+ if (path->p_idx) {
+ ext_debug(tree, " %d->%d", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ } else if (path->p_ext) {
+ ext_debug(tree, " %d:%d:%d",
-+ path->p_ext->ee_block,
-+ path->p_ext->ee_len,
-+ path->p_ext->ee_start);
++ path->p_ext->ee_block,
++ path->p_ext->ee_len,
++ path->p_ext->ee_start);
+ } else
+ ext_debug(tree, " []");
+ }
+}
+
+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int depth = EXT_DEPTH(tree);
+
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ ext_debug(tree, "%d:%d:%d ",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ }
+ ext_debug(tree, "\n");
+#endif
+ int depth = path->p_depth;
+ int i;
+
-+ for (i = 0; i <= depth; i++, path++)
++ for (i = 0; i <= depth; i++, path++) {
+ if (path->p_bh) {
+ brelse(path->p_bh);
+ path->p_bh = NULL;
+ }
++ }
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent_idx *ix;
+
+ ix += l;
+ path->p_idx = ix;
-+ ext_debug(tree, " -> %d->%d ", path->p_idx->ei_block, path->p_idx->ei_leaf);
++ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
+
+ while (l++ < r) {
+ if (block < ix->ei_block)
+ path->p_idx = ix++;
+ }
+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+
+#ifdef CHECK_BINSEARCH
+ {
+ for (k = 0; k < eh->eh_entries; k++, ix++) {
+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
+ printk("k=%d, ix=0x%p, first=0x%p\n", k,
-+ ix, EXT_FIRST_INDEX(eh));
++ ix, EXT_FIRST_INDEX(eh));
+ printk("%u <= %u\n",
-+ ix->ei_block,ix[-1].ei_block);
++ ix->ei_block,ix[-1].ei_block);
+ }
+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
+ if (block < ix->ei_block)
+ EXT_ASSERT(chix == path->p_idx);
+ }
+#endif
-+
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent *ex;
+ ex += l;
+ path->p_ext = ex;
+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+ while (l++ < r) {
+ if (block < ex->ee_block)
+ path->p_ext = ex++;
+ }
+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+#ifdef CHECK_BINSEARCH
+ {
+ EXT_ASSERT(chex == path->p_ext);
+ }
+#endif
-+
+}
+
+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
+
+struct ext3_ext_path *
+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ struct buffer_head *bh;
+
+ eh = EXT_ROOT_HDR(tree);
+ EXT_ASSERT(eh);
++ if (ext3_ext_check_header(eh))
++ goto err;
++
+ i = depth = EXT_DEPTH(tree);
+ EXT_ASSERT(eh->eh_max);
+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(i == 0 || eh->eh_entries > 0);
+
+ /* account possible depth increase */
+ if (!path) {
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+ GFP_NOFS);
++ GFP_NOFS);
+ if (!path)
+ return ERR_PTR(-ENOMEM);
+ }
+ /* walk through the tree */
+ while (i) {
+ ext_debug(tree, "depth %d: num %d, max %d\n",
-+ ppos, eh->eh_entries, eh->eh_max);
++ ppos, eh->eh_entries, eh->eh_max);
+ ext3_ext_binsearch_idx(tree, path + ppos, block);
+ path[ppos].p_block = path[ppos].p_idx->ei_leaf;
+ path[ppos].p_depth = i;
+ path[ppos].p_ext = NULL;
+
+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
-+ if (!bh) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ return ERR_PTR(-EIO);
-+ }
++ if (!bh)
++ goto err;
++
+ eh = EXT_BLOCK_HDR(bh);
+ ppos++;
+ EXT_ASSERT(ppos <= depth);
+ path[ppos].p_bh = bh;
+ path[ppos].p_hdr = eh;
+ i--;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+ }
+
+ path[ppos].p_depth = i;
+ path[ppos].p_hdr = eh;
+ path[ppos].p_ext = NULL;
++ path[ppos].p_idx = NULL;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+
+ /* find extent */
+ ext3_ext_binsearch(tree, path + ppos, block);
+ ext3_ext_show_path(tree, path);
+
+ return path;
++
++err:
++ printk(KERN_ERR "EXT3-fs: header is corrupted!\n");
++ ext3_ext_drop_refs(path);
++ kfree(path);
++ return ERR_PTR(-EIO);
+}
+
+/*
+ * it check where to insert: before curp or after curp
+ */
+static int ext3_ext_insert_index(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *curp,
-+ int logical, int ptr)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *curp,
++ int logical, int ptr)
+{
+ struct ext3_extent_idx *ix;
+ int len, err;
+ len = (len - 1) * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d after: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ (curp->p_idx + 1), (curp->p_idx + 2));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ (curp->p_idx + 1), (curp->p_idx + 2));
+ memmove(curp->p_idx + 2, curp->p_idx + 1, len);
+ }
+ ix = curp->p_idx + 1;
+ len = len * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d before: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ curp->p_idx, (curp->p_idx + 1));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ curp->p_idx, (curp->p_idx + 1));
+ memmove(curp->p_idx + 1, curp->p_idx, len);
+ ix = curp->p_idx;
+ }
+ * - initialize subtree
+ */
+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext, int at)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext, int at)
+{
+ struct buffer_head *bh = NULL;
+ int depth = EXT_DEPTH(tree);
+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ border = path[depth].p_ext[1].ee_block;
+ ext_debug(tree, "leaf will be splitted."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ } else {
+ border = newext->ee_block;
+ ext_debug(tree, "leaf will be added."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ }
+
+ /*
+ while (path[depth].p_ext <=
+ EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
-+ path[depth].p_ext->ee_block,
-+ path[depth].p_ext->ee_start,
-+ path[depth].p_ext->ee_len,
-+ newblock);
-+ memmove(ex++, path[depth].p_ext++,
-+ sizeof(struct ext3_extent));
++ path[depth].p_ext->ee_block,
++ path[depth].p_ext->ee_start,
++ path[depth].p_ext->ee_len,
++ newblock);
++ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
+ neh->eh_entries++;
+ m++;
+ }
+ fidx->ei_leaf = oldblock;
+
+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
-+ i, newblock, border, oldblock);
++ i, newblock, border, oldblock);
+ /* copy indexes */
+ m = 0;
+ path[i].p_idx++;
+
+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+ EXT_MAX_INDEX(path[i].p_hdr));
++ EXT_MAX_INDEX(path[i].p_hdr));
+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+ EXT_LAST_INDEX(path[i].p_hdr));
++ EXT_LAST_INDEX(path[i].p_hdr));
+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
+ ext_debug(tree, "%d: move %d:%d in new index %lu\n",
-+ i, path[i].p_idx->ei_block,
-+ path[i].p_idx->ei_leaf, newblock);
++ i, path[i].p_idx->ei_block,
++ path[i].p_idx->ei_leaf, newblock);
+ memmove(++fidx, path[i].p_idx++,
-+ sizeof(struct ext3_extent_idx));
++ sizeof(struct ext3_extent_idx));
+ neh->eh_entries++;
+ EXT_ASSERT(neh->eh_entries <= neh->eh_max);
+ m++;
+ /* insert new index */
+ if (!err)
+ err = ext3_ext_insert_index(handle, tree, path + at,
-+ border, newblock);
++ border, newblock);
+
+cleanup:
+ if (bh) {
+ * just created block
+ */
+static int ext3_ext_grow_indepth(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp = path;
+ struct ext3_extent_header *neh;
+ neh = EXT_ROOT_HDR(tree);
+ fidx = EXT_FIRST_INDEX(neh);
+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
-+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
++ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
+
+ neh->eh_depth = path->p_depth + 1;
+ err = ext3_ext_dirty(handle, tree, curp);
+ * then it requests in-depth growing
+ */
+static int ext3_ext_create_new_leaf(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp;
+ int depth, i, err = 0;
+ if (depth == path->p_depth) {
+ /* leaf */
+ if (path[depth].p_ext !=
-+ EXT_LAST_EXTENT(path[depth].p_hdr))
++ EXT_LAST_EXTENT(path[depth].p_hdr))
+ return path[depth].p_ext[1].ee_block;
+ } else {
+ /* index */
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ }
+ depth--;
+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
+ */
+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth;
+
+
+ while (depth >= 0) {
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ depth--;
+ }
+ * TODO: do we need to correct tree in all cases?
+ */
+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ int depth = EXT_DEPTH(tree);
+
+static int inline
+ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex1,
++ struct ext3_extent *ex2)
+{
+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
+ return 0;
+ * creating new leaf in no-space case
+ */
+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_extent_header * eh;
+ struct ext3_extent *ex, *fex;
+ int depth, len, err, next;
+
+ EXT_ASSERT(newext->ee_len > 0);
-+ EXT_ASSERT(newext->ee_len < EXT_CACHE_MARK);
+ depth = EXT_DEPTH(tree);
+ ex = path[depth].p_ext;
+ EXT_ASSERT(path[depth].p_hdr);
+ /* try to insert block into found extent and return */
+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
+ ext_debug(tree, "append %d block to %d:%d (from %d)\n",
-+ newext->ee_len, ex->ee_block, ex->ee_len,
-+ ex->ee_start);
++ newext->ee_len, ex->ee_block, ex->ee_len,
++ ex->ee_start);
+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
+ return err;
+ ex->ee_len += newext->ee_len;
+ eh = npath[depth].p_hdr;
+ if (eh->eh_entries < eh->eh_max) {
+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->eh_entries);
++ eh->eh_entries);
+ path = npath;
+ goto repeat;
+ }
+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->eh_entries, eh->eh_max);
++ eh->eh_entries, eh->eh_max);
+ }
+
+ /*
+ if (!nearex) {
+ /* there is no extent in this leaf, create first one */
+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len);
++ newext->ee_block, newext->ee_start,
++ newext->ee_len);
+ path[depth].p_ext = EXT_FIRST_EXTENT(eh);
+ } else if (newext->ee_block > nearex->ee_block) {
+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
+ len = (len - 1) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start,
++ newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 2, nearex + 1, len);
+ }
+ path[depth].p_ext = nearex + 1;
+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start, newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start, newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 1, nearex, len);
+ path[depth].p_ext = nearex;
+ }
+ /* merge with next extent! */
+ nearex->ee_len += nearex[1].ee_len;
+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
-+ len = (EXT_LAST_EXTENT(eh) - nearex - 1)
-+ * sizeof(struct ext3_extent);
++ len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++ sizeof(struct ext3_extent);
+ memmove(nearex + 1, nearex + 2, len);
+ }
+ eh->eh_entries--;
+ unsigned long num, ext_prepare_callback func)
+{
+ struct ext3_ext_path *path = NULL;
-+ struct ext3_extent *ex, cbex;
++ struct ext3_ext_cache cbex;
++ struct ext3_extent *ex;
+ unsigned long next, start = 0, end = 0;
+ unsigned long last = block + num;
+ int depth, exists, err = 0;
+ EXT_ASSERT(end > start);
+
+ if (!exists) {
-+ cbex.ee_block = start;
-+ cbex.ee_len = end - start;
-+ cbex.ee_start = 0;
-+ } else
-+ cbex = *ex;
++ cbex.ec_block = start;
++ cbex.ec_len = end - start;
++ cbex.ec_start = 0;
++ cbex.ec_type = EXT3_EXT_CACHE_GAP;
++ } else {
++ cbex.ec_block = ex->ee_block;
++ cbex.ec_len = ex->ee_len;
++ cbex.ec_start = ex->ee_start;
++ cbex.ec_type = EXT3_EXT_CACHE_EXTENT;
++ }
+
++ EXT_ASSERT(cbex.ec_len > 0);
+ EXT_ASSERT(path[depth].p_hdr);
-+ err = func(tree, path, &cbex, exists);
++ err = func(tree, path, &cbex);
+ ext3_ext_drop_refs(path);
+
+ if (err < 0)
+ path = NULL;
+ }
+
-+ block = cbex.ee_block + cbex.ee_len;
++ block = cbex.ec_block + cbex.ec_len;
+ }
+
+ if (path) {
+
+static inline void
+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
-+ __u32 len, __u32 start, int type)
++ __u32 len, __u32 start, int type)
+{
+ EXT_ASSERT(len > 0);
+ if (tree->cex) {
+ */
+static inline void
+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ unsigned long block)
++ struct ext3_ext_path *path,
++ unsigned long block)
+{
+ int depth = EXT_DEPTH(tree);
+ unsigned long lblock, len;
+ lblock = block;
+ len = ex->ee_block - block;
+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len);
+ } else if (block >= ex->ee_block + ex->ee_len) {
+ lblock = ex->ee_block + ex->ee_len;
+ len = ext3_ext_next_allocated_block(path);
+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) block);
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) block);
+ EXT_ASSERT(len > lblock);
+ len = len - lblock;
+ } else {
+
+static inline int
+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
-+ struct ext3_extent *ex)
++ struct ext3_extent *ex)
+{
+ struct ext3_ext_cache *cex = tree->cex;
+
+ return EXT3_EXT_CACHE_NO;
+
+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
-+ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+ ex->ee_block = cex->ec_block;
+ ex->ee_start = cex->ec_start;
+ ex->ee_len = cex->ec_len;
+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) ex->ee_start);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) ex->ee_start);
+ return cex->ec_type;
+ }
+
+ * last index in the block only
+ */
+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct buffer_head *bh;
+ int err;
+ if ((err = ext3_ext_dirty(handle, tree, path)))
+ return err;
+ ext_debug(tree, "index is empty, remove it, free block %d\n",
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->ei_leaf);
+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
+}
+
+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth = EXT_DEPTH(tree);
+ int needed;
+
+static int
+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, tex;
+ struct ext3_ext_path *npath;
+ /* FIXME: some callback to free underlying resource
+ * and correct ee_start? */
+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
-+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
+
+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
+ if (IS_ERR(npath))
+ kfree(npath);
+
+ return err;
-+
+}
+
+static int
+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, *fu = NULL, *lu, *le;
+ int err = 0, correct_index = 0;
+ }
+
+ lu = ex;
-+ while (ex >= EXT_FIRST_EXTENT(eh) &&
-+ ex->ee_block + ex->ee_len > start) {
++ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
+ path[depth].p_ext = ex;
+
+ block = ex->ee_block;
+ num = 0;
+ EXT_ASSERT(a == ex->ee_block &&
-+ b == ex->ee_block + ex->ee_len - 1);
++ b == ex->ee_block + ex->ee_len - 1);
+ }
+
+ if (ex == EXT_FIRST_EXTENT(eh))
+ goto out;
+
+ ext_debug(tree, "new extent: %u:%u:%u\n",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ ex--;
+ }
+
+}
+
+int ext3_ext_remove_space(struct ext3_extents_tree *tree,
-+ unsigned long start, unsigned long end)
++ unsigned long start, unsigned long end)
+{
+ struct inode *inode = tree->inode;
+ struct super_block *sb = inode->i_sb;
+ */
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
+ if (IS_ERR(path)) {
-+ ext3_error(sb, "ext3_ext_remove_space",
-+ "Can't allocate path array");
++ ext3_error(sb, __FUNCTION__, "Can't allocate path array");
+ ext3_journal_stop(handle, inode);
+ return -ENOMEM;
+ }
+ ext3_ext_last_covered(path[i].p_hdr, end);
+ path[i].p_block = path[i].p_hdr->eh_entries + 1;
+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
-+ path[i].p_hdr, path[i].p_hdr->eh_entries);
++ path[i].p_hdr, path[i].p_hdr->eh_entries);
+ } else {
+ /* we've already was here, see at next index */
+ path[i].p_idx--;
+ }
+
+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
-+ i, EXT_FIRST_INDEX(path[i].p_hdr),
-+ path[i].p_idx);
++ i, EXT_FIRST_INDEX(path[i].p_hdr),
++ path[i].p_idx);
+ if (ext3_ext_more_to_rm(path + i)) {
+ /* go to the next level */
+ ext_debug(tree, "move to level %d (block %d)\n",
-+ i + 1, path[i].p_idx->ei_leaf);
++ i + 1, path[i].p_idx->ei_leaf);
+ memset(path + i + 1, 0, sizeof(*path));
+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
+ if (!path[i+1].p_bh) {
+}
+
+static int ext3_ext_mergable(struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex2)
+{
+ /* FIXME: support for large fs */
+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
+
+static int
+ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed;
+
+
+static int
+ext3_remove_blocks(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+ handle_t *handle = ext3_journal_start(tree->inode, needed);
+ num = ex->ee_block + ex->ee_len - from;
+ start = ex->ee_start + ex->ee_len - num;
+ ext_debug(tree, "free last %lu blocks starting %lu\n",
-+ num, start);
++ num, start);
+ for (i = 0; i < num; i++) {
+ bh = sb_get_hash_table(tree->inode->i_sb, start + i);
+ ext3_forget(handle, 0, tree->inode, bh, start + i);
+ ext3_free_blocks(handle, tree->inode, start, num);
+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+ printk("strange request: removal %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ } else {
+ printk("strange request: removal(2) %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ }
+ ext3_journal_stop(handle, tree->inode);
+ return 0;
+}
+
+int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path,
-+ unsigned long block)
++ unsigned long block)
+{
+ struct ext3_inode_info *ei = EXT3_I(inode);
+ unsigned long bg_start;
+}
+
+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int *err)
++ struct ext3_ext_path *path,
++ struct ext3_extent *ex, int *err)
+{
+ struct inode *inode = tree->inode;
+ int newblock, goal;
+};
+
+void ext3_init_tree_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode)
++ struct inode *inode)
+{
+ tree->inode = inode;
+ tree->root = (void *) EXT3_I(inode)->i_data;
+}
+
+int ext3_ext_get_block(handle_t *handle, struct inode *inode,
-+ long iblock, struct buffer_head *bh_result, int create)
++ long iblock, struct buffer_head *bh_result, int create)
+{
+ struct ext3_ext_path *path = NULL;
+ struct ext3_extent newex;
+ clear_bit(BH_New, &bh_result->b_state);
+ ext3_init_tree_desc(&tree, inode);
+ ext_debug(&tree, "block %d requested for inode %u\n",
-+ (int) iblock, (unsigned) inode->i_ino);
++ (int) iblock, (unsigned) inode->i_ino);
+ down_write(&EXT3_I(inode)->truncate_sem);
+
+ /* check in cache */
+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
+ newblock = iblock - ex->ee_block + ex->ee_start;
+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
-+ (int) iblock, ex->ee_block, ex->ee_len,
-+ newblock);
++ (int) iblock, ex->ee_block, ex->ee_len,
++ newblock);
+ ext3_ext_put_in_cache(&tree, ex->ee_block,
-+ ex->ee_len, ex->ee_start,
-+ EXT3_EXT_CACHE_EXTENT);
++ ex->ee_len, ex->ee_start,
++ EXT3_EXT_CACHE_EXTENT);
+ goto out;
+ }
+ }
+ if (!newblock)
+ goto out2;
+ ext_debug(&tree, "allocate new block: goal %d, found %d\n",
-+ goal, newblock);
++ goal, newblock);
+
+ /* try to insert new extent into found leaf and return */
+ newex.ee_block = iblock;
+ set_bit(BH_New, &bh_result->b_state);
+
+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
-+ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
+out:
+ ext3_ext_show_leaf(&tree, path);
+ set_bit(BH_Mapped, &bh_result->b_state);
+ EXT3_I(inode)->i_disksize = inode->i_size;
+ ext3_mark_inode_dirty(handle, inode);
+
-+ last_block = (inode->i_size + sb->s_blocksize - 1)
-+ >> EXT3_BLOCK_SIZE_BITS(sb);
++ last_block = (inode->i_size + sb->s_blocksize - 1) >>
++ EXT3_BLOCK_SIZE_BITS(sb);
+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
+
+ /* In a multi-transaction truncate, we only make the final
+
+static int
+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *newex)
+{
+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
+
-+ if (!exist)
++ if (newex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
++
+ if (buf->err < 0)
+ return EXT_BREAK;
+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
+
+static int
+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *ex)
+{
+ struct ext3_extent_tree_stats *buf =
+ (struct ext3_extent_tree_stats *) tree->private;
+ int depth;
+
-+ if (!exist)
++ if (ex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
+
+ depth = EXT_DEPTH(tree);
+ tree.private = &buf;
+ down_write(&EXT3_I(inode)->truncate_sem);
+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
++ ext3_ext_store_extent_cb);
+ up_write(&EXT3_I(inode)->truncate_sem);
+ if (err == 0)
+ err = buf.err;
+ buf.leaf_num = 0;
+ tree.private = &buf;
+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
++ ext3_ext_collect_stats_cb);
+ up_write(&EXT3_I(inode)->truncate_sem);
+ if (!err)
+ err = copy_to_user((void *) arg, &buf, sizeof(buf));
+EXPORT_SYMBOL(ext3_ext_walk_space);
+EXPORT_SYMBOL(ext3_ext_find_goal);
+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
-+
Index: linux-2.4.21-suse2/fs/ext3/ialloc.c
===================================================================
--- linux-2.4.21-suse2.orig/fs/ext3/ialloc.c 2004-11-02 20:31:37.000000000 +0300
+++ linux-2.4.21-suse2/fs/ext3/ialloc.c 2004-11-02 20:34:00.000000000 +0300
-@@ -592,10 +592,22 @@
+@@ -592,6 +592,19 @@
iloc.bh = NULL;
goto fail;
}
-- err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-- if (err) goto fail;
--
-
-+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
-+ ext3_extents_initialize_blockmap(handle, inode);
++ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4);
++ ext3_extents_initialize_blockmap(handle, inode);
+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
+ if (err) goto fail;
+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+ }
-+ }
-+
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err) goto fail;
-
- #ifdef CONFIG_EXT3_FS_XATTR
- init_rwsem(&inode->u.ext3_i.xattr_sem);
++ }
++
+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
+ if (err) goto fail;
+
Index: linux-2.4.21-suse2/fs/ext3/inode.c
===================================================================
--- linux-2.4.21-suse2.orig/fs/ext3/inode.c 2004-11-02 20:31:38.000000000 +0300
+static inline int
+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+ struct buffer_head *bh, int create, int extend_disksize)
++ struct buffer_head *bh, int create, int extend_disksize)
+{
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
+ return ext3_ext_get_block(handle, inode, block, bh, create);
+ return ext3_get_block_handle(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+}
+
/*
for (block = 0; block < EXT3_N_BLOCKS; block++)
inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
++ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4);
brelse (iloc.bh);
===================================================================
--- linux-2.4.21-suse2.orig/include/linux/ext3_fs.h 2004-11-02 20:31:37.000000000 +0300
+++ linux-2.4.21-suse2/include/linux/ext3_fs.h 2004-11-02 20:31:39.000000000 +0300
-@@ -184,6 +184,7 @@
+@@ -184,8 +184,9 @@
#define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
#define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
- #define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */
+-#define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE 0x00085FFF /* User visible flags */
#define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
+
+ /*
@@ -208,6 +209,9 @@
#ifdef CONFIG_JBD_DEBUG
#define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long)
#endif
-+#define EXT3_IOC_GET_EXTENTS _IOR('f', 5, long)
-+#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long)
-+#define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long)
++#define EXT3_IOC_GET_EXTENTS _IOR('f', 5, long)
++#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long)
++#define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long)
/*
* Structure of an inode on the disk
+/* extents.c */
+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+ struct buffer_head *, int);
++ struct buffer_head *, int);
+extern void ext3_ext_truncate(struct inode *);
+extern void ext3_ext_init(struct super_block *);
+extern void ext3_ext_release(struct super_block *);
===================================================================
--- linux-2.4.21-suse2.orig/include/linux/ext3_extents.h 2003-01-30 13:24:37.000000000 +0300
+++ linux-2.4.21-suse2/include/linux/ext3_extents.h 2004-11-02 20:34:00.000000000 +0300
-@@ -0,0 +1,251 @@
+@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ */
+#define EXT_DEBUG_
+#ifdef EXT_DEBUG
-+#define ext_debug(tree,fmt,a...) \
++#define ext_debug(tree,fmt,a...) \
+do { \
+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
+ printk(fmt, ##a); \
+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
+ int (*remove_extent_credits)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*remove_extent)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*new_block)(handle_t *, struct ext3_extents_tree *,
-+ struct ext3_ext_path *, struct ext3_extent *,
-+ int *);
++ struct ext3_ext_path *, struct ext3_extent *,
++ int *);
+};
+
+/*
+ * callback must return valid extent (passed or newly created)
+ */
+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
-+ struct ext3_ext_path *,
-+ struct ext3_extent *, int);
++ struct ext3_ext_path *,
++ struct ext3_ext_cache *);
+
+#define EXT_CONTINUE 0
+#define EXT_BREAK 1
+
+
+#define EXT_MAX_BLOCK 0xffffffff
-+#define EXT_CACHE_MARK 0xffff
+
+
+#define EXT_FIRST_EXTENT(__hdr__) \
+
+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
+
++#define EXT_CHECK_PATH(tree,path) \
++{ \
++ int depth = EXT_DEPTH(tree); \
++ BUG_ON((unsigned long) (path) < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_idx < \
++ __PAGE_OFFSET && (path)[depth].p_idx != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_ext < \
++ __PAGE_OFFSET && (path)[depth].p_ext != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET \
++ && depth != 0); \
++ BUG_ON((path)[0].p_depth != depth); \
++}
++
+
+/*
+ * this structure is used to gather extents from the tree via ioctl
+ int leaf_num;
+};
+
-+void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
*/
struct rw_semaphore truncate_sem;
+
-+ __u32 i_cached_extent[4];
++ __u32 i_cached_extent[4];
};
#endif /* _LINUX_EXT3_FS_I */
===================================================================
--- linux-2.4.24.orig/fs/ext3/extents.c 2003-01-30 13:24:37.000000000 +0300
+++ linux-2.4.24/fs/ext3/extents.c 2004-11-03 00:36:44.894076664 +0300
-@@ -0,0 +1,2269 @@
+@@ -0,0 +1,2302 @@
+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+#include <linux/ext3_extents.h>
+#include <asm/uaccess.h>
+
++
++static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
++{
++ if (eh->eh_magic != EXT3_EXT_MAGIC) {
++ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
++ (unsigned)eh->eh_magic);
++ return -EIO;
++ }
++ if (eh->eh_max == 0) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
++ (unsigned)eh->eh_max);
++ return -EIO;
++ }
++ if (eh->eh_entries > eh->eh_max) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
++ (unsigned)eh->eh_entries);
++ return -EIO;
++ }
++ return 0;
++}
++
+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
+{
+ int err;
+ * - ENOMEM
+ */
+static int ext3_ext_get_access(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path)
+{
+ int err;
+
+ * - EIO
+ */
+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int err;
+ if (path->p_bh) {
+
+static int inline
+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, struct ext3_extent *ex,
-+ int *err)
++ struct ext3_ext_path *path, struct ext3_extent *ex,
++ int *err)
+{
+ int goal, depth, newblock;
+ struct inode *inode;
+ unsigned long colour;
+
+ bg_start = (ei->i_block_group *
-+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
+ colour = (current->pid % 16) *
+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 6;
+#endif
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 5;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len - sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 3;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 4;
+#endif
+}
+
+static void ext3_ext_show_path(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int k, l = path->p_depth;
+ for (k = 0; k <= l; k++, path++) {
+ if (path->p_idx) {
+ ext_debug(tree, " %d->%d", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ } else if (path->p_ext) {
+ ext_debug(tree, " %d:%d:%d",
-+ path->p_ext->ee_block,
-+ path->p_ext->ee_len,
-+ path->p_ext->ee_start);
++ path->p_ext->ee_block,
++ path->p_ext->ee_len,
++ path->p_ext->ee_start);
+ } else
+ ext_debug(tree, " []");
+ }
+}
+
+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int depth = EXT_DEPTH(tree);
+
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ ext_debug(tree, "%d:%d:%d ",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ }
+ ext_debug(tree, "\n");
+#endif
+ int depth = path->p_depth;
+ int i;
+
-+ for (i = 0; i <= depth; i++, path++)
++ for (i = 0; i <= depth; i++, path++) {
+ if (path->p_bh) {
+ brelse(path->p_bh);
+ path->p_bh = NULL;
+ }
++ }
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent_idx *ix;
+
+ ix += l;
+ path->p_idx = ix;
-+ ext_debug(tree, " -> %d->%d ", path->p_idx->ei_block, path->p_idx->ei_leaf);
++ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
+
+ while (l++ < r) {
+ if (block < ix->ei_block)
+ path->p_idx = ix++;
+ }
+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+
+#ifdef CHECK_BINSEARCH
+ {
+ for (k = 0; k < eh->eh_entries; k++, ix++) {
+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
+ printk("k=%d, ix=0x%p, first=0x%p\n", k,
-+ ix, EXT_FIRST_INDEX(eh));
++ ix, EXT_FIRST_INDEX(eh));
+ printk("%u <= %u\n",
-+ ix->ei_block,ix[-1].ei_block);
++ ix->ei_block,ix[-1].ei_block);
+ }
+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
+ if (block < ix->ei_block)
+ EXT_ASSERT(chix == path->p_idx);
+ }
+#endif
-+
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent *ex;
+ ex += l;
+ path->p_ext = ex;
+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+ while (l++ < r) {
+ if (block < ex->ee_block)
+ path->p_ext = ex++;
+ }
+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+#ifdef CHECK_BINSEARCH
+ {
+ EXT_ASSERT(chex == path->p_ext);
+ }
+#endif
-+
+}
+
+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
+
+struct ext3_ext_path *
+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ struct buffer_head *bh;
+
+ eh = EXT_ROOT_HDR(tree);
+ EXT_ASSERT(eh);
++ if (ext3_ext_check_header(eh))
++ goto err;
++
+ i = depth = EXT_DEPTH(tree);
+ EXT_ASSERT(eh->eh_max);
+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(i == 0 || eh->eh_entries > 0);
+
+ /* account possible depth increase */
+ if (!path) {
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+ GFP_NOFS);
++ GFP_NOFS);
+ if (!path)
+ return ERR_PTR(-ENOMEM);
+ }
+ /* walk through the tree */
+ while (i) {
+ ext_debug(tree, "depth %d: num %d, max %d\n",
-+ ppos, eh->eh_entries, eh->eh_max);
++ ppos, eh->eh_entries, eh->eh_max);
+ ext3_ext_binsearch_idx(tree, path + ppos, block);
+ path[ppos].p_block = path[ppos].p_idx->ei_leaf;
+ path[ppos].p_depth = i;
+ path[ppos].p_ext = NULL;
+
+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
-+ if (!bh) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ return ERR_PTR(-EIO);
-+ }
++ if (!bh)
++ goto err;
+ eh = EXT_BLOCK_HDR(bh);
+ ppos++;
+ EXT_ASSERT(ppos <= depth);
+ path[ppos].p_bh = bh;
+ path[ppos].p_hdr = eh;
+ i--;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+ }
+
+ path[ppos].p_depth = i;
+ path[ppos].p_hdr = eh;
+ path[ppos].p_ext = NULL;
++ path[ppos].p_idx = NULL;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+
+ /* find extent */
+ ext3_ext_binsearch(tree, path + ppos, block);
+ ext3_ext_show_path(tree, path);
+
+ return path;
++
++err:
++ printk(KERN_ERR "EXT3-fs: header is corrupted!\n");
++ ext3_ext_drop_refs(path);
++ kfree(path);
++ return ERR_PTR(-EIO);
+}
+
+/*
+ * it check where to insert: before curp or after curp
+ */
+static int ext3_ext_insert_index(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *curp,
-+ int logical, int ptr)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *curp,
++ int logical, int ptr)
+{
+ struct ext3_extent_idx *ix;
+ int len, err;
+ len = (len - 1) * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d after: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ (curp->p_idx + 1), (curp->p_idx + 2));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ (curp->p_idx + 1), (curp->p_idx + 2));
+ memmove(curp->p_idx + 2, curp->p_idx + 1, len);
+ }
+ ix = curp->p_idx + 1;
+ len = len * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d before: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ curp->p_idx, (curp->p_idx + 1));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ curp->p_idx, (curp->p_idx + 1));
+ memmove(curp->p_idx + 1, curp->p_idx, len);
+ ix = curp->p_idx;
+ }
+ * - initialize subtree
+ */
+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext, int at)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext, int at)
+{
+ struct buffer_head *bh = NULL;
+ int depth = EXT_DEPTH(tree);
+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ border = path[depth].p_ext[1].ee_block;
+ ext_debug(tree, "leaf will be splitted."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ } else {
+ border = newext->ee_block;
+ ext_debug(tree, "leaf will be added."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ }
+
+ /*
+ while (path[depth].p_ext <=
+ EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
-+ path[depth].p_ext->ee_block,
-+ path[depth].p_ext->ee_start,
-+ path[depth].p_ext->ee_len,
-+ newblock);
-+ memmove(ex++, path[depth].p_ext++,
-+ sizeof(struct ext3_extent));
++ path[depth].p_ext->ee_block,
++ path[depth].p_ext->ee_start,
++ path[depth].p_ext->ee_len,
++ newblock);
++ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
+ neh->eh_entries++;
+ m++;
+ }
+ fidx->ei_leaf = oldblock;
+
+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
-+ i, newblock, border, oldblock);
++ i, newblock, border, oldblock);
+ /* copy indexes */
+ m = 0;
+ path[i].p_idx++;
+
+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+ EXT_MAX_INDEX(path[i].p_hdr));
++ EXT_MAX_INDEX(path[i].p_hdr));
+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+ EXT_LAST_INDEX(path[i].p_hdr));
++ EXT_LAST_INDEX(path[i].p_hdr));
+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
+ ext_debug(tree, "%d: move %d:%d in new index %lu\n",
-+ i, path[i].p_idx->ei_block,
-+ path[i].p_idx->ei_leaf, newblock);
++ i, path[i].p_idx->ei_block,
++ path[i].p_idx->ei_leaf, newblock);
+ memmove(++fidx, path[i].p_idx++,
-+ sizeof(struct ext3_extent_idx));
++ sizeof(struct ext3_extent_idx));
+ neh->eh_entries++;
+ EXT_ASSERT(neh->eh_entries <= neh->eh_max);
+ m++;
+ /* insert new index */
+ if (!err)
+ err = ext3_ext_insert_index(handle, tree, path + at,
-+ border, newblock);
++ border, newblock);
+
+cleanup:
+ if (bh) {
+ * just created block
+ */
+static int ext3_ext_grow_indepth(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp = path;
+ struct ext3_extent_header *neh;
+ neh = EXT_ROOT_HDR(tree);
+ fidx = EXT_FIRST_INDEX(neh);
+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
-+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
++ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
+
+ neh->eh_depth = path->p_depth + 1;
+ err = ext3_ext_dirty(handle, tree, curp);
+ * then it requests in-depth growing
+ */
+static int ext3_ext_create_new_leaf(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp;
+ int depth, i, err = 0;
+ if (depth == path->p_depth) {
+ /* leaf */
+ if (path[depth].p_ext !=
-+ EXT_LAST_EXTENT(path[depth].p_hdr))
++ EXT_LAST_EXTENT(path[depth].p_hdr))
+ return path[depth].p_ext[1].ee_block;
+ } else {
+ /* index */
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ }
+ depth--;
+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
+ */
+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth;
+
+
+ while (depth >= 0) {
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ depth--;
+ }
+ * TODO: do we need to correct tree in all cases?
+ */
+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ int depth = EXT_DEPTH(tree);
+
+static int inline
+ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex1,
++ struct ext3_extent *ex2)
+{
+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
+ return 0;
+ * creating new leaf in no-space case
+ */
+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_extent_header * eh;
+ struct ext3_extent *ex, *fex;
+ int depth, len, err, next;
+
+ EXT_ASSERT(newext->ee_len > 0);
-+ EXT_ASSERT(newext->ee_len < EXT_CACHE_MARK);
+ depth = EXT_DEPTH(tree);
+ ex = path[depth].p_ext;
+ EXT_ASSERT(path[depth].p_hdr);
+ /* try to insert block into found extent and return */
+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
+ ext_debug(tree, "append %d block to %d:%d (from %d)\n",
-+ newext->ee_len, ex->ee_block, ex->ee_len,
-+ ex->ee_start);
++ newext->ee_len, ex->ee_block, ex->ee_len,
++ ex->ee_start);
+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
+ return err;
+ ex->ee_len += newext->ee_len;
+ eh = npath[depth].p_hdr;
+ if (eh->eh_entries < eh->eh_max) {
+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->eh_entries);
++ eh->eh_entries);
+ path = npath;
+ goto repeat;
+ }
+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->eh_entries, eh->eh_max);
++ eh->eh_entries, eh->eh_max);
+ }
+
+ /*
+ if (!nearex) {
+ /* there is no extent in this leaf, create first one */
+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len);
++ newext->ee_block, newext->ee_start,
++ newext->ee_len);
+ path[depth].p_ext = EXT_FIRST_EXTENT(eh);
+ } else if (newext->ee_block > nearex->ee_block) {
+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
+ len = (len - 1) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start,
++ newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 2, nearex + 1, len);
+ }
+ path[depth].p_ext = nearex + 1;
+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start, newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start, newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 1, nearex, len);
+ path[depth].p_ext = nearex;
+ }
+ /* merge with next extent! */
+ nearex->ee_len += nearex[1].ee_len;
+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
-+ len = (EXT_LAST_EXTENT(eh) - nearex - 1)
-+ * sizeof(struct ext3_extent);
++ len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++ sizeof(struct ext3_extent);
+ memmove(nearex + 1, nearex + 2, len);
+ }
+ eh->eh_entries--;
+ unsigned long num, ext_prepare_callback func)
+{
+ struct ext3_ext_path *path = NULL;
-+ struct ext3_extent *ex, cbex;
++ struct ext3_ext_cache cbex;
++ struct ext3_extent *ex;
+ unsigned long next, start = 0, end = 0;
+ unsigned long last = block + num;
+ int depth, exists, err = 0;
+ EXT_ASSERT(end > start);
+
+ if (!exists) {
-+ cbex.ee_block = start;
-+ cbex.ee_len = end - start;
-+ cbex.ee_start = 0;
-+ } else
-+ cbex = *ex;
++ cbex.ec_block = start;
++ cbex.ec_len = end - start;
++ cbex.ec_start = 0;
++ cbex.ec_type = EXT3_EXT_CACHE_GAP;
++ } else {
++ cbex.ec_block = ex->ee_block;
++ cbex.ec_len = ex->ee_len;
++ cbex.ec_start = ex->ee_start;
++ cbex.ec_type = EXT3_EXT_CACHE_EXTENT;
++ }
+
++ EXT_ASSERT(cbex.ec_len > 0);
+ EXT_ASSERT(path[depth].p_hdr);
-+ err = func(tree, path, &cbex, exists);
++ err = func(tree, path, &cbex);
+ ext3_ext_drop_refs(path);
+
+ if (err < 0)
+ path = NULL;
+ }
+
-+ block = cbex.ee_block + cbex.ee_len;
++ block = cbex.ec_block + cbex.ec_len;
+ }
+
+ if (path) {
+
+static inline void
+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
-+ __u32 len, __u32 start, int type)
++ __u32 len, __u32 start, int type)
+{
+ EXT_ASSERT(len > 0);
+ if (tree->cex) {
+ */
+static inline void
+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ unsigned long block)
++ struct ext3_ext_path *path,
++ unsigned long block)
+{
+ int depth = EXT_DEPTH(tree);
+ unsigned long lblock, len;
+ lblock = block;
+ len = ex->ee_block - block;
+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len);
+ } else if (block >= ex->ee_block + ex->ee_len) {
+ lblock = ex->ee_block + ex->ee_len;
+ len = ext3_ext_next_allocated_block(path);
+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) block);
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) block);
+ EXT_ASSERT(len > lblock);
+ len = len - lblock;
+ } else {
+
+static inline int
+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
-+ struct ext3_extent *ex)
++ struct ext3_extent *ex)
+{
+ struct ext3_ext_cache *cex = tree->cex;
+
+ return EXT3_EXT_CACHE_NO;
+
+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
-+ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+ ex->ee_block = cex->ec_block;
+ ex->ee_start = cex->ec_start;
+ ex->ee_len = cex->ec_len;
+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) ex->ee_start);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) ex->ee_start);
+ return cex->ec_type;
+ }
+
+ * last index in the block only
+ */
+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct buffer_head *bh;
+ int err;
+ if ((err = ext3_ext_dirty(handle, tree, path)))
+ return err;
+ ext_debug(tree, "index is empty, remove it, free block %d\n",
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->ei_leaf);
+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
+}
+
+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth = EXT_DEPTH(tree);
+ int needed;
+
+static int
+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, tex;
+ struct ext3_ext_path *npath;
+ /* FIXME: some callback to free underlying resource
+ * and correct ee_start? */
+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
-+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
+
+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
+ if (IS_ERR(npath))
+ kfree(npath);
+
+ return err;
-+
+}
+
+static int
+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, *fu = NULL, *lu, *le;
+ int err = 0, correct_index = 0;
+ }
+
+ lu = ex;
-+ while (ex >= EXT_FIRST_EXTENT(eh) &&
-+ ex->ee_block + ex->ee_len > start) {
++ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
+ path[depth].p_ext = ex;
+
+ block = ex->ee_block;
+ num = 0;
+ EXT_ASSERT(a == ex->ee_block &&
-+ b == ex->ee_block + ex->ee_len - 1);
++ b == ex->ee_block + ex->ee_len - 1);
+ }
+
+ if (ex == EXT_FIRST_EXTENT(eh))
+ goto out;
+
+ ext_debug(tree, "new extent: %u:%u:%u\n",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ ex--;
+ }
+
+}
+
+int ext3_ext_remove_space(struct ext3_extents_tree *tree,
-+ unsigned long start, unsigned long end)
++ unsigned long start, unsigned long end)
+{
+ struct inode *inode = tree->inode;
+ struct super_block *sb = inode->i_sb;
+ */
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
+ if (IS_ERR(path)) {
-+ ext3_error(sb, "ext3_ext_remove_space",
-+ "Can't allocate path array");
++ ext3_error(sb, __FUNCTION__, "Can't allocate path array");
+ ext3_journal_stop(handle, inode);
+ return -ENOMEM;
+ }
+ ext3_ext_last_covered(path[i].p_hdr, end);
+ path[i].p_block = path[i].p_hdr->eh_entries + 1;
+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
-+ path[i].p_hdr, path[i].p_hdr->eh_entries);
++ path[i].p_hdr, path[i].p_hdr->eh_entries);
+ } else {
+ /* we've already was here, see at next index */
+ path[i].p_idx--;
+ }
+
+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
-+ i, EXT_FIRST_INDEX(path[i].p_hdr),
-+ path[i].p_idx);
++ i, EXT_FIRST_INDEX(path[i].p_hdr),
++ path[i].p_idx);
+ if (ext3_ext_more_to_rm(path + i)) {
+ /* go to the next level */
+ ext_debug(tree, "move to level %d (block %d)\n",
-+ i + 1, path[i].p_idx->ei_leaf);
++ i + 1, path[i].p_idx->ei_leaf);
+ memset(path + i + 1, 0, sizeof(*path));
+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
+ if (!path[i+1].p_bh) {
+}
+
+static int ext3_ext_mergable(struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex2)
+{
+ /* FIXME: support for large fs */
+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
+
+static int
+ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed;
+
+
+static int
+ext3_remove_blocks(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+ handle_t *handle = ext3_journal_start(tree->inode, needed);
+ num = ex->ee_block + ex->ee_len - from;
+ start = ex->ee_start + ex->ee_len - num;
+ ext_debug(tree, "free last %lu blocks starting %lu\n",
-+ num, start);
++ num, start);
+ for (i = 0; i < num; i++) {
+ bh = sb_get_hash_table(tree->inode->i_sb, start + i);
+ ext3_forget(handle, 0, tree->inode, bh, start + i);
+ ext3_free_blocks(handle, tree->inode, start, num);
+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+ printk("strange request: removal %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ } else {
+ printk("strange request: removal(2) %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ }
+ ext3_journal_stop(handle, tree->inode);
+ return 0;
+}
+
+int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path,
-+ unsigned long block)
++ unsigned long block)
+{
+ struct ext3_inode_info *ei = EXT3_I(inode);
+ unsigned long bg_start;
+}
+
+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int *err)
++ struct ext3_ext_path *path,
++ struct ext3_extent *ex, int *err)
+{
+ struct inode *inode = tree->inode;
+ int newblock, goal;
+};
+
+void ext3_init_tree_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode)
++ struct inode *inode)
+{
+ tree->inode = inode;
+ tree->root = (void *) EXT3_I(inode)->i_data;
+}
+
+int ext3_ext_get_block(handle_t *handle, struct inode *inode,
-+ long iblock, struct buffer_head *bh_result, int create)
++ long iblock, struct buffer_head *bh_result, int create)
+{
+ struct ext3_ext_path *path = NULL;
+ struct ext3_extent newex;
+ clear_bit(BH_New, &bh_result->b_state);
+ ext3_init_tree_desc(&tree, inode);
+ ext_debug(&tree, "block %d requested for inode %u\n",
-+ (int) iblock, (unsigned) inode->i_ino);
++ (int) iblock, (unsigned) inode->i_ino);
+ down_write(&EXT3_I(inode)->truncate_sem);
+
+ /* check in cache */
+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
+ newblock = iblock - ex->ee_block + ex->ee_start;
+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
-+ (int) iblock, ex->ee_block, ex->ee_len,
-+ newblock);
++ (int) iblock, ex->ee_block, ex->ee_len,
++ newblock);
+ ext3_ext_put_in_cache(&tree, ex->ee_block,
-+ ex->ee_len, ex->ee_start,
-+ EXT3_EXT_CACHE_EXTENT);
++ ex->ee_len, ex->ee_start,
++ EXT3_EXT_CACHE_EXTENT);
+ goto out;
+ }
+ }
+ if (!newblock)
+ goto out2;
+ ext_debug(&tree, "allocate new block: goal %d, found %d\n",
-+ goal, newblock);
++ goal, newblock);
+
+ /* try to insert new extent into found leaf and return */
+ newex.ee_block = iblock;
+ set_bit(BH_New, &bh_result->b_state);
+
+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
-+ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
+out:
+ ext3_ext_show_leaf(&tree, path);
+ set_bit(BH_Mapped, &bh_result->b_state);
+ EXT3_I(inode)->i_disksize = inode->i_size;
+ ext3_mark_inode_dirty(handle, inode);
+
-+ last_block = (inode->i_size + sb->s_blocksize - 1)
-+ >> EXT3_BLOCK_SIZE_BITS(sb);
++ last_block = (inode->i_size + sb->s_blocksize - 1) >>
++ EXT3_BLOCK_SIZE_BITS(sb);
+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
+
+ /* In a multi-transaction truncate, we only make the final
+
+static int
+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *newex)
+{
+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
+
-+ if (!exist)
++ if (newex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
++
+ if (buf->err < 0)
+ return EXT_BREAK;
+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
+
+static int
+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *ex)
+{
+ struct ext3_extent_tree_stats *buf =
+ (struct ext3_extent_tree_stats *) tree->private;
+ int depth;
+
-+ if (!exist)
++ if (ex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
+
+ depth = EXT_DEPTH(tree);
+ tree.private = &buf;
+ down_write(&EXT3_I(inode)->truncate_sem);
+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
++ ext3_ext_store_extent_cb);
+ up_write(&EXT3_I(inode)->truncate_sem);
+ if (err == 0)
+ err = buf.err;
+ buf.leaf_num = 0;
+ tree.private = &buf;
+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
++ ext3_ext_collect_stats_cb);
+ up_write(&EXT3_I(inode)->truncate_sem);
+ if (!err)
+ err = copy_to_user((void *) arg, &buf, sizeof(buf));
+EXPORT_SYMBOL(ext3_ext_walk_space);
+EXPORT_SYMBOL(ext3_ext_find_goal);
+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
-+
Index: linux-2.4.24/fs/ext3/ialloc.c
===================================================================
--- linux-2.4.24.orig/fs/ext3/ialloc.c 2004-11-02 20:28:32.000000000 +0300
+++ linux-2.4.24/fs/ext3/ialloc.c 2004-11-02 20:32:17.000000000 +0300
-@@ -592,10 +592,22 @@
+@@ -592,6 +592,19 @@
iloc.bh = NULL;
goto fail;
}
-- err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-- if (err) goto fail;
-
-+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
-+ ext3_extents_initialize_blockmap(handle, inode);
++ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4);
++ ext3_extents_initialize_blockmap(handle, inode);
+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
+ if (err) goto fail;
+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+ }
-+ }
++ }
++
+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
+ if (err) goto fail;
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err) goto fail;
-
- unlock_super (sb);
- if(DQUOT_ALLOC_INODE(inode)) {
Index: linux-2.4.24/fs/ext3/inode.c
===================================================================
--- linux-2.4.24.orig/fs/ext3/inode.c 2004-11-02 20:28:33.000000000 +0300
+static inline int
+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+ struct buffer_head *bh, int create)
++ struct buffer_head *bh, int create)
+{
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
+ return ext3_ext_get_block(handle, inode, block, bh, create);
for (block = 0; block < EXT3_N_BLOCKS; block++)
inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
++ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4);
if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
inode->u.ext3_i.i_extra_isize =
===================================================================
--- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-11-02 20:28:32.000000000 +0300
+++ linux-2.4.24/include/linux/ext3_fs.h 2004-11-02 20:32:17.000000000 +0300
-@@ -184,6 +184,7 @@
+@@ -184,8 +184,9 @@
#define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
#define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
- #define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */
+-#define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE 0x00085FFF /* User visible flags */
#define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
+
+ /*
@@ -208,6 +209,9 @@
#ifdef CONFIG_JBD_DEBUG
#define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long)
#endif
-+#define EXT3_IOC_GET_EXTENTS _IOR('f', 5, long)
-+#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long)
-+#define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long)
++#define EXT3_IOC_GET_EXTENTS _IOR('f', 5, long)
++#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long)
++#define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long)
/*
* Structure of an inode on the disk
+/* extents.c */
+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+ struct buffer_head *, int);
++ struct buffer_head *, int);
+extern void ext3_ext_truncate(struct inode *);
+extern void ext3_ext_init(struct super_block *);
+extern void ext3_ext_release(struct super_block *);
===================================================================
--- linux-2.4.24.orig/include/linux/ext3_extents.h 2003-01-30 13:24:37.000000000 +0300
+++ linux-2.4.24/include/linux/ext3_extents.h 2004-11-02 20:32:17.000000000 +0300
-@@ -0,0 +1,251 @@
+@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ */
+#define EXT_DEBUG_
+#ifdef EXT_DEBUG
-+#define ext_debug(tree,fmt,a...) \
++#define ext_debug(tree,fmt,a...) \
+do { \
+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
+ printk(fmt, ##a); \
+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
+ int (*remove_extent_credits)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*remove_extent)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*new_block)(handle_t *, struct ext3_extents_tree *,
-+ struct ext3_ext_path *, struct ext3_extent *,
-+ int *);
++ struct ext3_ext_path *, struct ext3_extent *,
++ int *);
+};
+
+/*
+ * callback must return valid extent (passed or newly created)
+ */
+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
-+ struct ext3_ext_path *,
-+ struct ext3_extent *, int);
++ struct ext3_ext_path *,
++ struct ext3_ext_cache *);
+
+#define EXT_CONTINUE 0
+#define EXT_BREAK 1
+
+
+#define EXT_MAX_BLOCK 0xffffffff
-+#define EXT_CACHE_MARK 0xffff
+
+
+#define EXT_FIRST_EXTENT(__hdr__) \
+
+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
+
++#define EXT_CHECK_PATH(tree,path) \
++{ \
++ int depth = EXT_DEPTH(tree); \
++ BUG_ON((unsigned long) (path) < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_idx < \
++ __PAGE_OFFSET && (path)[depth].p_idx != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_ext < \
++ __PAGE_OFFSET && (path)[depth].p_ext != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET \
++ && depth != 0); \
++ BUG_ON((path)[0].p_depth != depth); \
++}
++
+
+/*
+ * this structure is used to gather extents from the tree via ioctl
+ int leaf_num;
+};
+
-+void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
+
+
+#endif /* _LINUX_EXT3_EXTENTS */
-+
Index: linux-2.4.24/include/linux/ext3_fs_i.h
===================================================================
--- linux-2.4.24.orig/include/linux/ext3_fs_i.h 2004-11-02 20:28:32.000000000 +0300
*/
struct rw_semaphore truncate_sem;
+
-+ __u32 i_cached_extent[4];
++ __u32 i_cached_extent[4];
};
#endif /* _LINUX_EXT3_FS_I */
===================================================================
--- linux-2.6.5-sles9.orig/fs/ext3/extents.c 2005-02-17 22:07:57.023609040 +0300
+++ linux-2.6.5-sles9/fs/ext3/extents.c 2005-02-23 01:02:37.396435640 +0300
-@@ -0,0 +1,2356 @@
+@@ -0,0 +1,2349 @@
+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+{
+ if (eh->eh_magic != EXT3_EXT_MAGIC) {
+ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
-+ (unsigned) eh->eh_magic);
++ (unsigned)eh->eh_magic);
+ return -EIO;
+ }
+ if (eh->eh_max == 0) {
+ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
-+ (unsigned) eh->eh_max);
++ (unsigned)eh->eh_max);
+ return -EIO;
+ }
+ if (eh->eh_entries > eh->eh_max) {
+ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
-+ (unsigned) eh->eh_entries);
++ (unsigned)eh->eh_entries);
+ return -EIO;
+ }
+ return 0;
+ * - ENOMEM
+ */
+static int ext3_ext_get_access(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path)
+{
+ int err;
+
+ * - EIO
+ */
+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int err;
+ if (path->p_bh) {
+
+static int inline
+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, struct ext3_extent *ex,
-+ int *err)
++ struct ext3_ext_path *path, struct ext3_extent *ex,
++ int *err)
+{
+ int goal, depth, newblock;
+ struct inode *inode;
+ unsigned long colour;
+
+ bg_start = (ei->i_block_group *
-+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
+ colour = (current->pid % 16) *
+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 6;
+#endif
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 5;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len - sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 3;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 4;
+#endif
+}
+
+static void ext3_ext_show_path(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int k, l = path->p_depth;
+ for (k = 0; k <= l; k++, path++) {
+ if (path->p_idx) {
+ ext_debug(tree, " %d->%d", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ } else if (path->p_ext) {
+ ext_debug(tree, " %d:%d:%d",
-+ path->p_ext->ee_block,
-+ path->p_ext->ee_len,
-+ path->p_ext->ee_start);
++ path->p_ext->ee_block,
++ path->p_ext->ee_len,
++ path->p_ext->ee_start);
+ } else
+ ext_debug(tree, " []");
+ }
+}
+
+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int depth = EXT_DEPTH(tree);
+
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ ext_debug(tree, "%d:%d:%d ",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ }
+ ext_debug(tree, "\n");
+#endif
+ int depth = path->p_depth;
+ int i;
+
-+ for (i = 0; i <= depth; i++, path++)
++ for (i = 0; i <= depth; i++, path++) {
+ if (path->p_bh) {
+ brelse(path->p_bh);
+ path->p_bh = NULL;
+ }
++ }
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent_idx *ix;
+
+ ix += l;
+ path->p_idx = ix;
-+ ext_debug(tree, " -> %d->%d ", path->p_idx->ei_block, path->p_idx->ei_leaf);
++ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
+
+ while (l++ < r) {
+ if (block < ix->ei_block)
+ path->p_idx = ix++;
+ }
+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+
+#ifdef CHECK_BINSEARCH
+ {
+ for (k = 0; k < eh->eh_entries; k++, ix++) {
+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
+ printk("k=%d, ix=0x%p, first=0x%p\n", k,
-+ ix, EXT_FIRST_INDEX(eh));
++ ix, EXT_FIRST_INDEX(eh));
+ printk("%u <= %u\n",
-+ ix->ei_block,ix[-1].ei_block);
++ ix->ei_block,ix[-1].ei_block);
+ }
+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
+ if (block < ix->ei_block)
+ EXT_ASSERT(chix == path->p_idx);
+ }
+#endif
-+
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent *ex;
+ ex += l;
+ path->p_ext = ex;
+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+ while (l++ < r) {
+ if (block < ex->ee_block)
+ path->p_ext = ex++;
+ }
+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+#ifdef CHECK_BINSEARCH
+ {
+ EXT_ASSERT(chex == path->p_ext);
+ }
+#endif
-+
+}
+
+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
+
+struct ext3_ext_path *
+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ struct buffer_head *bh;
+ /* account possible depth increase */
+ if (!path) {
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+ GFP_NOFS);
++ GFP_NOFS);
+ if (!path)
+ return ERR_PTR(-ENOMEM);
+ }
+ /* walk through the tree */
+ while (i) {
+ ext_debug(tree, "depth %d: num %d, max %d\n",
-+ ppos, eh->eh_entries, eh->eh_max);
++ ppos, eh->eh_entries, eh->eh_max);
+ ext3_ext_binsearch_idx(tree, path + ppos, block);
+ path[ppos].p_block = path[ppos].p_idx->ei_leaf;
+ path[ppos].p_depth = i;
+ * it check where to insert: before curp or after curp
+ */
+static int ext3_ext_insert_index(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *curp,
-+ int logical, int ptr)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *curp,
++ int logical, int ptr)
+{
+ struct ext3_extent_idx *ix;
+ int len, err;
+ len = (len - 1) * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d after: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ (curp->p_idx + 1), (curp->p_idx + 2));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ (curp->p_idx + 1), (curp->p_idx + 2));
+ memmove(curp->p_idx + 2, curp->p_idx + 1, len);
+ }
+ ix = curp->p_idx + 1;
+ len = len * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d before: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ curp->p_idx, (curp->p_idx + 1));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ curp->p_idx, (curp->p_idx + 1));
+ memmove(curp->p_idx + 1, curp->p_idx, len);
+ ix = curp->p_idx;
+ }
+ * - initialize subtree
+ */
+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext, int at)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext, int at)
+{
+ struct buffer_head *bh = NULL;
+ int depth = EXT_DEPTH(tree);
+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ border = path[depth].p_ext[1].ee_block;
+ ext_debug(tree, "leaf will be splitted."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ } else {
+ border = newext->ee_block;
+ ext_debug(tree, "leaf will be added."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ }
+
+ /*
+ while (path[depth].p_ext <=
+ EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
-+ path[depth].p_ext->ee_block,
-+ path[depth].p_ext->ee_start,
-+ path[depth].p_ext->ee_len,
-+ newblock);
-+ memmove(ex++, path[depth].p_ext++,
-+ sizeof(struct ext3_extent));
++ path[depth].p_ext->ee_block,
++ path[depth].p_ext->ee_start,
++ path[depth].p_ext->ee_len,
++ newblock);
++ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
+ neh->eh_entries++;
+ m++;
+ }
+ fidx->ei_leaf = oldblock;
+
+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
-+ i, newblock, border, oldblock);
++ i, newblock, border, oldblock);
+ /* copy indexes */
+ m = 0;
+ path[i].p_idx++;
+
+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+ EXT_MAX_INDEX(path[i].p_hdr));
++ EXT_MAX_INDEX(path[i].p_hdr));
+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+ EXT_LAST_INDEX(path[i].p_hdr));
++ EXT_LAST_INDEX(path[i].p_hdr));
+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
+ ext_debug(tree, "%d: move %d:%d in new index %lu\n",
-+ i, path[i].p_idx->ei_block,
-+ path[i].p_idx->ei_leaf, newblock);
++ i, path[i].p_idx->ei_block,
++ path[i].p_idx->ei_leaf, newblock);
+ memmove(++fidx, path[i].p_idx++,
-+ sizeof(struct ext3_extent_idx));
++ sizeof(struct ext3_extent_idx));
+ neh->eh_entries++;
+ EXT_ASSERT(neh->eh_entries <= neh->eh_max);
+ m++;
+ /* insert new index */
+ if (!err)
+ err = ext3_ext_insert_index(handle, tree, path + at,
-+ border, newblock);
++ border, newblock);
+
+cleanup:
+ if (bh) {
+ * just created block
+ */
+static int ext3_ext_grow_indepth(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp = path;
+ struct ext3_extent_header *neh;
+ /* set size of new block */
+ neh = EXT_BLOCK_HDR(bh);
+ /* old root could have indexes or leaves
-+ * so calculate e_max right way */
++ * so calculate eh_max right way */
+ if (EXT_DEPTH(tree))
+ neh->eh_max = ext3_ext_space_block_idx(tree);
+ else
+ neh = EXT_ROOT_HDR(tree);
+ fidx = EXT_FIRST_INDEX(neh);
+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
-+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
++ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
+
+ neh->eh_depth = path->p_depth + 1;
+ err = ext3_ext_dirty(handle, tree, curp);
+ * then it requests in-depth growing
+ */
+static int ext3_ext_create_new_leaf(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp;
+ int depth, i, err = 0;
+ if (depth == path->p_depth) {
+ /* leaf */
+ if (path[depth].p_ext !=
-+ EXT_LAST_EXTENT(path[depth].p_hdr))
++ EXT_LAST_EXTENT(path[depth].p_hdr))
+ return path[depth].p_ext[1].ee_block;
+ } else {
+ /* index */
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ }
+ depth--;
+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
+ */
+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth;
+
+
+ while (depth >= 0) {
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ depth--;
+ }
+ * TODO: do we need to correct tree in all cases?
+ */
+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ int depth = EXT_DEPTH(tree);
+
+static int inline
+ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex1,
++ struct ext3_extent *ex2)
+{
+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
+ return 0;
+ * creating new leaf in no-space case
+ */
+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_extent_header * eh;
+ struct ext3_extent *ex, *fex;
+ /* try to insert block into found extent and return */
+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
+ ext_debug(tree, "append %d block to %d:%d (from %d)\n",
-+ newext->ee_len, ex->ee_block, ex->ee_len,
-+ ex->ee_start);
++ newext->ee_len, ex->ee_block, ex->ee_len,
++ ex->ee_start);
+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
+ return err;
+ ex->ee_len += newext->ee_len;
+ eh = npath[depth].p_hdr;
+ if (eh->eh_entries < eh->eh_max) {
+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->eh_entries);
++ eh->eh_entries);
+ path = npath;
+ goto repeat;
+ }
+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->eh_entries, eh->eh_max);
++ eh->eh_entries, eh->eh_max);
+ }
+
+ /*
+ if (!nearex) {
+ /* there is no extent in this leaf, create first one */
+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len);
++ newext->ee_block, newext->ee_start,
++ newext->ee_len);
+ path[depth].p_ext = EXT_FIRST_EXTENT(eh);
+ } else if (newext->ee_block > nearex->ee_block) {
+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
+ len = (len - 1) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start,
++ newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 2, nearex + 1, len);
+ }
+ path[depth].p_ext = nearex + 1;
+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start, newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start, newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 1, nearex, len);
+ path[depth].p_ext = nearex;
+ }
+ /* merge with next extent! */
+ nearex->ee_len += nearex[1].ee_len;
+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
-+ len = (EXT_LAST_EXTENT(eh) - nearex - 1)
-+ * sizeof(struct ext3_extent);
++ len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++ sizeof(struct ext3_extent);
+ memmove(nearex + 1, nearex + 2, len);
+ }
+ eh->eh_entries--;
+
+static inline void
+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
-+ __u32 len, __u32 start, int type)
++ __u32 len, __u32 start, int type)
+{
+ EXT_ASSERT(len > 0);
+ if (tree->cex) {
+ */
+static inline void
+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ unsigned long block)
++ struct ext3_ext_path *path,
++ unsigned long block)
+{
+ int depth = EXT_DEPTH(tree);
+ unsigned long lblock, len;
+ lblock = block;
+ len = ex->ee_block - block;
+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len);
+ } else if (block >= ex->ee_block + ex->ee_len) {
+ lblock = ex->ee_block + ex->ee_len;
+ len = ext3_ext_next_allocated_block(path);
+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) block);
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) block);
+ EXT_ASSERT(len > lblock);
+ len = len - lblock;
+ } else {
+
+static inline int
+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
-+ struct ext3_extent *ex)
++ struct ext3_extent *ex)
+{
+ struct ext3_ext_cache *cex = tree->cex;
+
+ return EXT3_EXT_CACHE_NO;
+
+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
-+ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+ ex->ee_block = cex->ec_block;
+ ex->ee_start = cex->ec_start;
+ ex->ee_len = cex->ec_len;
+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) ex->ee_start);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) ex->ee_start);
+ return cex->ec_type;
+ }
+
+ * last index in the block only
+ */
+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct buffer_head *bh;
+ int err;
+ if ((err = ext3_ext_dirty(handle, tree, path)))
+ return err;
+ ext_debug(tree, "index is empty, remove it, free block %d\n",
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
+}
+
+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth = EXT_DEPTH(tree);
+ int needed;
+
+static int
+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, tex;
+ struct ext3_ext_path *npath;
+ /* FIXME: some callback to free underlying resource
+ * and correct ee_start? */
+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
-+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
+
+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
+ if (IS_ERR(npath))
+ kfree(npath);
+
+ return err;
-+
+}
+
+static int
+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, *fu = NULL, *lu, *le;
+ int err = 0, correct_index = 0;
+ }
+
+ lu = ex;
-+ while (ex >= EXT_FIRST_EXTENT(eh) &&
-+ ex->ee_block + ex->ee_len > start) {
++ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
+ path[depth].p_ext = ex;
+
+ block = ex->ee_block;
+ num = 0;
+ EXT_ASSERT(a == ex->ee_block &&
-+ b == ex->ee_block + ex->ee_len - 1);
++ b == ex->ee_block + ex->ee_len - 1);
+ }
+
+ if (ex == EXT_FIRST_EXTENT(eh))
+ goto out;
+
+ ext_debug(tree, "new extent: %u:%u:%u\n",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ ex--;
+ }
+
+}
+
+int ext3_ext_remove_space(struct ext3_extents_tree *tree,
-+ unsigned long start, unsigned long end)
++ unsigned long start, unsigned long end)
+{
+ struct inode *inode = tree->inode;
+ struct super_block *sb = inode->i_sb;
+ */
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
+ if (IS_ERR(path)) {
-+ ext3_error(sb, "ext3_ext_remove_space",
-+ "Can't allocate path array");
++ ext3_error(sb, __FUNCTION__, "Can't allocate path array");
+ ext3_journal_stop(handle);
+ return -ENOMEM;
+ }
+ ext3_ext_last_covered(path[i].p_hdr, end);
+ path[i].p_block = path[i].p_hdr->eh_entries + 1;
+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
-+ path[i].p_hdr, path[i].p_hdr->eh_entries);
++ path[i].p_hdr, path[i].p_hdr->eh_entries);
+ } else {
+ /* we've already was here, see at next index */
+ path[i].p_idx--;
+ }
+
+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
-+ i, EXT_FIRST_INDEX(path[i].p_hdr),
-+ path[i].p_idx);
++ i, EXT_FIRST_INDEX(path[i].p_hdr),
++ path[i].p_idx);
+ if (ext3_ext_more_to_rm(path + i)) {
+ /* go to the next level */
+ ext_debug(tree, "move to level %d (block %d)\n",
-+ i + 1, path[i].p_idx->ei_leaf);
++ i + 1, path[i].p_idx->ei_leaf);
+ memset(path + i + 1, 0, sizeof(*path));
+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
+ if (!path[i+1].p_bh) {
+}
+
+static int ext3_ext_mergable(struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex2)
+{
+ /* FIXME: support for large fs */
+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
+
+static int
+ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed;
+
+
+static int
+ext3_remove_blocks(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+ handle_t *handle = ext3_journal_start(tree->inode, needed);
+ num = ex->ee_block + ex->ee_len - from;
+ start = ex->ee_start + ex->ee_len - num;
+ ext_debug(tree, "free last %lu blocks starting %lu\n",
-+ num, start);
++ num, start);
+ for (i = 0; i < num; i++) {
+ bh = sb_find_get_block(tree->inode->i_sb, start + i);
+ ext3_forget(handle, 0, tree->inode, bh, start + i);
+ ext3_free_blocks(handle, tree->inode, start, num);
+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+ printk("strange request: removal %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ } else {
+ printk("strange request: removal(2) %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ }
+ ext3_journal_stop(handle);
+ return 0;
+}
+
+static int ext3_ext_find_goal(struct inode *inode,
-+ struct ext3_ext_path *path, unsigned long block)
++ struct ext3_ext_path *path, unsigned long block)
+{
+ struct ext3_inode_info *ei = EXT3_I(inode);
+ unsigned long bg_start;
+}
+
+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int *err)
++ struct ext3_ext_path *path,
++ struct ext3_extent *ex, int *err)
+{
+ struct inode *inode = tree->inode;
+ int newblock, goal;
+};
+
+void ext3_init_tree_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode)
++ struct inode *inode)
+{
+ tree->inode = inode;
+ tree->root = (void *) EXT3_I(inode)->i_data;
+}
+
+int ext3_ext_get_block(handle_t *handle, struct inode *inode,
-+ long iblock, struct buffer_head *bh_result,
-+ int create, int extend_disksize)
++ long iblock, struct buffer_head *bh_result,
++ int create, int extend_disksize)
+{
+ struct ext3_ext_path *path = NULL;
+ struct ext3_extent newex;
+ __clear_bit(BH_New, &bh_result->b_state);
+ ext3_init_tree_desc(&tree, inode);
+ ext_debug(&tree, "block %d requested for inode %u\n",
-+ (int) iblock, (unsigned) inode->i_ino);
++ (int) iblock, (unsigned) inode->i_ino);
+ down(&EXT3_I(inode)->truncate_sem);
+
+ /* check in cache */
+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
+ newblock = iblock - ex->ee_block + ex->ee_start;
+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
-+ (int) iblock, ex->ee_block, ex->ee_len,
-+ newblock);
++ (int) iblock, ex->ee_block, ex->ee_len,
++ newblock);
+ ext3_ext_put_in_cache(&tree, ex->ee_block,
-+ ex->ee_len, ex->ee_start,
-+ EXT3_EXT_CACHE_EXTENT);
++ ex->ee_len, ex->ee_start,
++ EXT3_EXT_CACHE_EXTENT);
+ goto out;
+ }
+ }
+ if (!newblock)
+ goto out2;
+ ext_debug(&tree, "allocate new block: goal %d, found %d\n",
-+ goal, newblock);
++ goal, newblock);
+
+ /* try to insert new extent into found leaf and return */
+ newex.ee_block = iblock;
+ __set_bit(BH_New, &bh_result->b_state);
+
+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
-+ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
+out:
+ ext3_ext_show_leaf(&tree, path);
+ __set_bit(BH_Mapped, &bh_result->b_state);
+ EXT3_I(inode)->i_disksize = inode->i_size;
+ ext3_mark_inode_dirty(handle, inode);
+
-+ last_block = (inode->i_size + sb->s_blocksize - 1)
-+ >> EXT3_BLOCK_SIZE_BITS(sb);
++ last_block = (inode->i_size + sb->s_blocksize - 1) >>
++ EXT3_BLOCK_SIZE_BITS(sb);
+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
+
+ /* In a multi-transaction truncate, we only make the final
+
+static int
+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_ext_cache *newex)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *newex)
+{
+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
+
+
+static int
+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_ext_cache *ex)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *ex)
+{
+ struct ext3_extent_tree_stats *buf =
+ (struct ext3_extent_tree_stats *) tree->private;
+}
+
+int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-+ unsigned long arg)
++ unsigned long arg)
+{
+ int err = 0;
+
+ tree.private = &buf;
+ down(&EXT3_I(inode)->truncate_sem);
+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
++ ext3_ext_store_extent_cb);
+ up(&EXT3_I(inode)->truncate_sem);
+ if (err == 0)
+ err = buf.err;
+ buf.leaf_num = 0;
+ tree.private = &buf;
+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
++ ext3_ext_collect_stats_cb);
+ up(&EXT3_I(inode)->truncate_sem);
+ if (!err)
+ err = copy_to_user((void *) arg, &buf, sizeof(buf));
+EXPORT_SYMBOL(ext3_ext_walk_space);
+EXPORT_SYMBOL(ext3_ext_find_goal);
+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
-+
Index: linux-2.6.5-sles9/fs/ext3/ialloc.c
===================================================================
--- linux-2.6.5-sles9.orig/fs/ext3/ialloc.c 2005-02-23 01:01:52.366281264 +0300
+++ linux-2.6.5-sles9/fs/ext3/ialloc.c 2005-02-23 01:02:37.398435336 +0300
-@@ -647,6 +647,10 @@
+@@ -647,6 +647,18 @@
DQUOT_FREE_INODE(inode);
goto fail2;
}
-+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, inode);
-+ }
++ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++ ext3_extents_initialize_blockmap(handle, inode);
++ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
++ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++ if (err) goto fail;
++ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
++ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
++ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
++ }
++ }
++
err = ext3_mark_inode_dirty(handle, inode);
if (err) {
ext3_std_error(sb, err);
+static inline int
+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+ struct buffer_head *bh, int create, int extend_disksize)
++ struct buffer_head *bh, int create, int extend_disksize)
+{
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
+ return ext3_ext_get_block(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+ return ext3_get_block_handle(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+}
+
static int ext3_get_block(struct inode *inode, sector_t iblock,
- ret = ext3_get_block_handle(handle, inode, iblock,
- bh_result, create, 1);
+ ret = ext3_get_block_wrap(handle, inode, iblock,
-+ bh_result, create, 1);
++ bh_result, create, 1);
return ret;
}
- ret = ext3_get_block_handle(handle, inode, iblock,
- bh_result, create, 0);
+ ret = ext3_get_block_wrap(handle, inode, iblock,
-+ bh_result, create, 0);
++ bh_result, create, 0);
if (ret == 0)
bh_result->b_size = (1 << inode->i_blkbits);
return ret;
int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
int ret;
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_writepage_trans_blocks(inode, bpp);
-+
++ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++ return ext3_ext_writepage_trans_blocks(inode, bpp);
++
if (ext3_should_journal_data(inode))
ret = 3 * (bpp + indirects) + 2;
else
struct ext3_super_block *es = sbi->s_es;
int i;
-+ ext3_ext_release(sb);
++ ext3_ext_release(sb);
ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
if (!(sb->s_flags & MS_RDONLY)) {
percpu_counter_mod(&sbi->s_dirs_counter,
ext3_count_dirs(sb));
-+ ext3_ext_init(sb);
-+
++ ext3_ext_init(sb);
++
return 0;
failed_mount3:
===================================================================
--- linux-2.6.5-sles9.orig/include/linux/ext3_fs.h 2005-02-23 01:02:35.823674736 +0300
+++ linux-2.6.5-sles9/include/linux/ext3_fs.h 2005-02-23 01:02:37.414432904 +0300
-@@ -186,6 +186,7 @@
+@@ -186,8 +186,9 @@
+ #define EXT3_NOTAIL_FL 0x00008000 /* don't merge file tail */
#define EXT3_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
#define EXT3_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
- #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
+ #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
- #define EXT3_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
+-#define EXT3_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
#define EXT3_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
+
@@ -211,6 +212,9 @@
#endif
#define EXT3_IOC_GETRSVSZ _IOR('f', 5, long)
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef clear_opt
+@@ -503,11 +509,13 @@
+ #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG 0x0010
++#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
+
+ #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+ EXT3_FEATURE_INCOMPAT_RECOVER| \
+- EXT3_FEATURE_INCOMPAT_META_BG)
++ EXT3_FEATURE_INCOMPAT_META_BG| \
++ EXT3_FEATURE_INCOMPAT_EXTENTS)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
@@ -729,6 +735,7 @@
+/* extents.c */
+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+ struct buffer_head *, int, int);
++ struct buffer_head *, int, int);
+extern void ext3_ext_truncate(struct inode *, struct page *);
+extern void ext3_ext_init(struct super_block *);
+extern void ext3_ext_release(struct super_block *);
===================================================================
--- linux-2.6.5-sles9.orig/include/linux/ext3_extents.h 2005-02-17 22:07:57.023609040 +0300
+++ linux-2.6.5-sles9/include/linux/ext3_extents.h 2005-02-23 01:02:37.416432600 +0300
-@@ -0,0 +1,265 @@
+@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ */
+#define EXT_DEBUG_
+#ifdef EXT_DEBUG
-+#define ext_debug(tree,fmt,a...) \
++#define ext_debug(tree,fmt,a...) \
+do { \
+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
+ printk(fmt, ##a); \
+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
+ int (*remove_extent_credits)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*remove_extent)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*new_block)(handle_t *, struct ext3_extents_tree *,
-+ struct ext3_ext_path *, struct ext3_extent *,
-+ int *);
++ struct ext3_ext_path *, struct ext3_extent *,
++ int *);
+};
+
+/*
+ * callback must return valid extent (passed or newly created)
+ */
+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
-+ struct ext3_ext_path *,
-+ struct ext3_ext_cache *);
++ struct ext3_ext_path *,
++ struct ext3_ext_cache *);
+
+#define EXT_CONTINUE 0
+#define EXT_BREAK 1
+ && depth != 0); \
+ BUG_ON((path)[0].p_depth != depth); \
+}
-+
++
+
+/*
+ * this structure is used to gather extents from the tree via ioctl
+ int leaf_num;
+};
+
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
-+extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_ext_calc_blockmap_metadata(struct inode *, int);
+
+static inline void
+
+
+#endif /* _LINUX_EXT3_EXTENTS */
-+
Index: linux-2.6.5-sles9/include/linux/ext3_fs_i.h
===================================================================
--- linux-2.6.5-sles9.orig/include/linux/ext3_fs_i.h 2005-02-23 01:01:52.425272296 +0300
===================================================================
--- linux-stage.orig/fs/ext3/extents.c 2005-02-25 15:33:48.890198160 +0200
+++ linux-stage/fs/ext3/extents.c 2005-02-25 15:33:48.917194056 +0200
-@@ -0,0 +1,2313 @@
+@@ -0,0 +1,2347 @@
+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+#include <linux/ext3_extents.h>
+#include <asm/uaccess.h>
+
++
++static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
++{
++ if (eh->eh_magic != EXT3_EXT_MAGIC) {
++ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
++ (unsigned)eh->eh_magic);
++ return -EIO;
++ }
++ if (eh->eh_max == 0) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
++ (unsigned)eh->eh_max);
++ return -EIO;
++ }
++ if (eh->eh_entries > eh->eh_max) {
++ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
++ (unsigned)eh->eh_entries);
++ return -EIO;
++ }
++ return 0;
++}
++
+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
+{
+ int err;
+ * - ENOMEM
+ */
+static int ext3_ext_get_access(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path)
+{
+ int err;
+
+ * - EIO
+ */
+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int err;
+ if (path->p_bh) {
+
+static int inline
+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, struct ext3_extent *ex,
-+ int *err)
++ struct ext3_ext_path *path, struct ext3_extent *ex,
++ int *err)
+{
+ int goal, depth, newblock;
+ struct inode *inode;
+ unsigned long colour;
+
+ bg_start = (ei->i_block_group *
-+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
++ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
+ colour = (current->pid % 16) *
+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 6;
+#endif
+ int size;
+
+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 5;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len - sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent);
+#ifdef AGRESSIVE_TEST
+ size = 3;
+#endif
+{
+ int size;
+
-+ size = (tree->buffer_len -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
++ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent_idx);
+#ifdef AGRESSIVE_TEST
+ size = 4;
+#endif
+}
+
+static void ext3_ext_show_path(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int k, l = path->p_depth;
+ for (k = 0; k <= l; k++, path++) {
+ if (path->p_idx) {
+ ext_debug(tree, " %d->%d", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ } else if (path->p_ext) {
+ ext_debug(tree, " %d:%d:%d",
-+ path->p_ext->ee_block,
-+ path->p_ext->ee_len,
-+ path->p_ext->ee_start);
++ path->p_ext->ee_block,
++ path->p_ext->ee_len,
++ path->p_ext->ee_start);
+ } else
+ ext_debug(tree, " []");
+ }
+}
+
+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+#ifdef EXT_DEBUG
+ int depth = EXT_DEPTH(tree);
+
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ ext_debug(tree, "%d:%d:%d ",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ }
+ ext_debug(tree, "\n");
+#endif
+ int depth = path->p_depth;
+ int i;
+
-+ for (i = 0; i <= depth; i++, path++)
++ for (i = 0; i <= depth; i++, path++) {
+ if (path->p_bh) {
+ brelse(path->p_bh);
+ path->p_bh = NULL;
+ }
++ }
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent_idx *ix;
+
+ ix += l;
+ path->p_idx = ix;
-+ ext_debug(tree, " -> %d->%d ", path->p_idx->ei_block, path->p_idx->ei_leaf);
++ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf);
+
+ while (l++ < r) {
+ if (block < ix->ei_block)
+ path->p_idx = ix++;
+ }
+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+
+#ifdef CHECK_BINSEARCH
+ {
+ for (k = 0; k < eh->eh_entries; k++, ix++) {
+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
+ printk("k=%d, ix=0x%p, first=0x%p\n", k,
-+ ix, EXT_FIRST_INDEX(eh));
++ ix, EXT_FIRST_INDEX(eh));
+ printk("%u <= %u\n",
-+ ix->ei_block,ix[-1].ei_block);
++ ix->ei_block,ix[-1].ei_block);
+ }
+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
+ if (block < ix->ei_block)
+ EXT_ASSERT(chix == path->p_idx);
+ }
+#endif
-+
+}
+
+/*
+ */
+static inline void
+ext3_ext_binsearch(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
++ struct ext3_ext_path *path, int block)
+{
+ struct ext3_extent_header *eh = path->p_hdr;
+ struct ext3_extent *ex;
+ ex += l;
+ path->p_ext = ex;
+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+ while (l++ < r) {
+ if (block < ex->ee_block)
+ path->p_ext = ex++;
+ }
+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
++ path->p_ext->ee_start, path->p_ext->ee_len);
+
+#ifdef CHECK_BINSEARCH
+ {
+ EXT_ASSERT(chex == path->p_ext);
+ }
+#endif
-+
+}
+
+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
+
+struct ext3_ext_path *
+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ struct buffer_head *bh;
+
+ eh = EXT_ROOT_HDR(tree);
+ EXT_ASSERT(eh);
++ if (ext3_ext_check_header(eh))
++ goto err;
++
+ i = depth = EXT_DEPTH(tree);
+ EXT_ASSERT(eh->eh_max);
+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(i == 0 || eh->eh_entries > 0);
+
+ /* account possible depth increase */
+ if (!path) {
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+ GFP_NOFS);
++ GFP_NOFS);
+ if (!path)
+ return ERR_PTR(-ENOMEM);
+ }
+ /* walk through the tree */
+ while (i) {
+ ext_debug(tree, "depth %d: num %d, max %d\n",
-+ ppos, eh->eh_entries, eh->eh_max);
++ ppos, eh->eh_entries, eh->eh_max);
+ ext3_ext_binsearch_idx(tree, path + ppos, block);
+ path[ppos].p_block = path[ppos].p_idx->ei_leaf;
+ path[ppos].p_depth = i;
+ path[ppos].p_ext = NULL;
+
+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
-+ if (!bh) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ return ERR_PTR(-EIO);
-+ }
++ if (!bh)
++ goto err;
++
+ eh = EXT_BLOCK_HDR(bh);
+ ppos++;
+ EXT_ASSERT(ppos <= depth);
+ path[ppos].p_bh = bh;
+ path[ppos].p_hdr = eh;
+ i--;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+ }
+
+ path[ppos].p_depth = i;
+ path[ppos].p_hdr = eh;
+ path[ppos].p_ext = NULL;
++ path[ppos].p_idx = NULL;
++
++ if (ext3_ext_check_header(eh))
++ goto err;
+
+ /* find extent */
+ ext3_ext_binsearch(tree, path + ppos, block);
+ ext3_ext_show_path(tree, path);
+
+ return path;
++
++err:
++ printk(KERN_ERR "EXT3-fs: header is corrupted!\n");
++ ext3_ext_drop_refs(path);
++ kfree(path);
++ return ERR_PTR(-EIO);
+}
+
+/*
+ * it check where to insert: before curp or after curp
+ */
+static int ext3_ext_insert_index(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *curp,
-+ int logical, int ptr)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *curp,
++ int logical, int ptr)
+{
+ struct ext3_extent_idx *ix;
+ int len, err;
+ len = (len - 1) * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d after: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ (curp->p_idx + 1), (curp->p_idx + 2));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ (curp->p_idx + 1), (curp->p_idx + 2));
+ memmove(curp->p_idx + 2, curp->p_idx + 1, len);
+ }
+ ix = curp->p_idx + 1;
+ len = len * sizeof(struct ext3_extent_idx);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert new index %d before: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ curp->p_idx, (curp->p_idx + 1));
++ "move %d from 0x%p to 0x%p\n",
++ logical, ptr, len,
++ curp->p_idx, (curp->p_idx + 1));
+ memmove(curp->p_idx + 1, curp->p_idx, len);
+ ix = curp->p_idx;
+ }
+ * - initialize subtree
+ */
+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext, int at)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext, int at)
+{
+ struct buffer_head *bh = NULL;
+ int depth = EXT_DEPTH(tree);
+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ border = path[depth].p_ext[1].ee_block;
+ ext_debug(tree, "leaf will be splitted."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ } else {
+ border = newext->ee_block;
+ ext_debug(tree, "leaf will be added."
-+ " next leaf starts at %d\n",
-+ (int)border);
++ " next leaf starts at %d\n",
++ (int)border);
+ }
+
+ /*
+ while (path[depth].p_ext <=
+ EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
-+ path[depth].p_ext->ee_block,
-+ path[depth].p_ext->ee_start,
-+ path[depth].p_ext->ee_len,
-+ newblock);
-+ memmove(ex++, path[depth].p_ext++,
-+ sizeof(struct ext3_extent));
++ path[depth].p_ext->ee_block,
++ path[depth].p_ext->ee_start,
++ path[depth].p_ext->ee_len,
++ newblock);
++ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));
+ neh->eh_entries++;
+ m++;
+ }
+ fidx->ei_leaf = oldblock;
+
+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
-+ i, newblock, border, oldblock);
++ i, newblock, border, oldblock);
+ /* copy indexes */
+ m = 0;
+ path[i].p_idx++;
+
+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+ EXT_MAX_INDEX(path[i].p_hdr));
++ EXT_MAX_INDEX(path[i].p_hdr));
+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+ EXT_LAST_INDEX(path[i].p_hdr));
++ EXT_LAST_INDEX(path[i].p_hdr));
+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
+ ext_debug(tree, "%d: move %d:%d in new index %lu\n",
-+ i, path[i].p_idx->ei_block,
-+ path[i].p_idx->ei_leaf, newblock);
++ i, path[i].p_idx->ei_block,
++ path[i].p_idx->ei_leaf, newblock);
+ memmove(++fidx, path[i].p_idx++,
-+ sizeof(struct ext3_extent_idx));
++ sizeof(struct ext3_extent_idx));
+ neh->eh_entries++;
+ EXT_ASSERT(neh->eh_entries <= neh->eh_max);
+ m++;
+ /* insert new index */
+ if (!err)
+ err = ext3_ext_insert_index(handle, tree, path + at,
-+ border, newblock);
++ border, newblock);
+
+cleanup:
+ if (bh) {
+ * just created block
+ */
+static int ext3_ext_grow_indepth(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp = path;
+ struct ext3_extent_header *neh;
+ /* set size of new block */
+ neh = EXT_BLOCK_HDR(bh);
+ /* old root could have indexes or leaves
-+ * so calculate e_max right way */
++ * so calculate eh_max right way */
+ if (EXT_DEPTH(tree))
+ neh->eh_max = ext3_ext_space_block_idx(tree);
+ else
+ neh = EXT_ROOT_HDR(tree);
+ fidx = EXT_FIRST_INDEX(neh);
+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
-+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
++ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
+
+ neh->eh_depth = path->p_depth + 1;
+ err = ext3_ext_dirty(handle, tree, curp);
+ * then it requests in-depth growing
+ */
+static int ext3_ext_create_new_leaf(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_extents_tree *tree,
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_ext_path *curp;
+ int depth, i, err = 0;
+ if (depth == path->p_depth) {
+ /* leaf */
+ if (path[depth].p_ext !=
-+ EXT_LAST_EXTENT(path[depth].p_hdr))
++ EXT_LAST_EXTENT(path[depth].p_hdr))
+ return path[depth].p_ext[1].ee_block;
+ } else {
+ /* index */
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ }
+ depth--;
+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
+ */
+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth;
+
+
+ while (depth >= 0) {
+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
++ EXT_LAST_INDEX(path[depth].p_hdr))
+ return path[depth].p_idx[1].ei_block;
+ depth--;
+ }
+ * TODO: do we need to correct tree in all cases?
+ */
+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct ext3_extent_header *eh;
+ int depth = EXT_DEPTH(tree);
+
+static int inline
+ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex1,
++ struct ext3_extent *ex2)
+{
+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
+ return 0;
+ * creating new leaf in no-space case
+ */
+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
++ struct ext3_ext_path *path,
++ struct ext3_extent *newext)
+{
+ struct ext3_extent_header * eh;
+ struct ext3_extent *ex, *fex;
+ int depth, len, err, next;
+
+ EXT_ASSERT(newext->ee_len > 0);
-+ EXT_ASSERT(newext->ee_len < EXT_CACHE_MARK);
+ depth = EXT_DEPTH(tree);
+ ex = path[depth].p_ext;
+ EXT_ASSERT(path[depth].p_hdr);
+ /* try to insert block into found extent and return */
+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
+ ext_debug(tree, "append %d block to %d:%d (from %d)\n",
-+ newext->ee_len, ex->ee_block, ex->ee_len,
-+ ex->ee_start);
++ newext->ee_len, ex->ee_block, ex->ee_len,
++ ex->ee_start);
+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
+ return err;
+ ex->ee_len += newext->ee_len;
+ eh = npath[depth].p_hdr;
+ if (eh->eh_entries < eh->eh_max) {
+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->eh_entries);
++ eh->eh_entries);
+ path = npath;
+ goto repeat;
+ }
+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->eh_entries, eh->eh_max);
++ eh->eh_entries, eh->eh_max);
+ }
+
+ /*
+ if (!nearex) {
+ /* there is no extent in this leaf, create first one */
+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len);
++ newext->ee_block, newext->ee_start,
++ newext->ee_len);
+ path[depth].p_ext = EXT_FIRST_EXTENT(eh);
+ } else if (newext->ee_block > nearex->ee_block) {
+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
+ len = (len - 1) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start,
++ newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 2, nearex + 1, len);
+ }
+ path[depth].p_ext = nearex + 1;
+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
+ len = len < 0 ? 0 : len;
+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start, newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
++ "move %d from 0x%p to 0x%p\n",
++ newext->ee_block, newext->ee_start, newext->ee_len,
++ nearex, len, nearex + 1, nearex + 2);
+ memmove(nearex + 1, nearex, len);
+ path[depth].p_ext = nearex;
+ }
+ /* merge with next extent! */
+ nearex->ee_len += nearex[1].ee_len;
+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
-+ len = (EXT_LAST_EXTENT(eh) - nearex - 1)
-+ * sizeof(struct ext3_extent);
++ len = (EXT_LAST_EXTENT(eh) - nearex - 1) *
++ sizeof(struct ext3_extent);
+ memmove(nearex + 1, nearex + 2, len);
+ }
+ eh->eh_entries--;
+ unsigned long num, ext_prepare_callback func)
+{
+ struct ext3_ext_path *path = NULL;
-+ struct ext3_extent *ex, cbex;
++ struct ext3_ext_cache cbex;
++ struct ext3_extent *ex;
+ unsigned long next, start = 0, end = 0;
+ unsigned long last = block + num;
+ int depth, exists, err = 0;
+ EXT_ASSERT(end > start);
+
+ if (!exists) {
-+ cbex.ee_block = start;
-+ cbex.ee_len = end - start;
-+ cbex.ee_start = 0;
-+ } else
-+ cbex = *ex;
++ cbex.ec_block = start;
++ cbex.ec_len = end - start;
++ cbex.ec_start = 0;
++ cbex.ec_type = EXT3_EXT_CACHE_GAP;
++ } else {
++ cbex.ec_block = ex->ee_block;
++ cbex.ec_len = ex->ee_len;
++ cbex.ec_start = ex->ee_start;
++ cbex.ec_type = EXT3_EXT_CACHE_EXTENT;
++ }
+
++ EXT_ASSERT(cbex.ec_len > 0);
+ EXT_ASSERT(path[depth].p_hdr);
-+ err = func(tree, path, &cbex, exists);
++ err = func(tree, path, &cbex);
+ ext3_ext_drop_refs(path);
+
+ if (err < 0)
+ path = NULL;
+ }
+
-+ block = cbex.ee_block + cbex.ee_len;
++ block = cbex.ec_block + cbex.ec_len;
+ }
+
+ if (path) {
+
+static inline void
+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
-+ __u32 len, __u32 start, int type)
++ __u32 len, __u32 start, int type)
+{
+ EXT_ASSERT(len > 0);
+ if (tree->cex) {
+ */
+static inline void
+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ unsigned long block)
++ struct ext3_ext_path *path,
++ unsigned long block)
+{
+ int depth = EXT_DEPTH(tree);
+ unsigned long lblock, len;
+ lblock = block;
+ len = ex->ee_block - block;
+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len);
+ } else if (block >= ex->ee_block + ex->ee_len) {
+ lblock = ex->ee_block + ex->ee_len;
+ len = ext3_ext_next_allocated_block(path);
+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) block);
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) block);
+ EXT_ASSERT(len > lblock);
+ len = len - lblock;
+ } else {
+
+static inline int
+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
-+ struct ext3_extent *ex)
++ struct ext3_extent *ex)
+{
+ struct ext3_ext_cache *cex = tree->cex;
+
+ return EXT3_EXT_CACHE_NO;
+
+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
-+ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+ ex->ee_block = cex->ec_block;
+ ex->ee_start = cex->ec_start;
+ ex->ee_len = cex->ec_len;
+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) ex->ee_start);
++ (unsigned long) block,
++ (unsigned long) ex->ee_block,
++ (unsigned long) ex->ee_len,
++ (unsigned long) ex->ee_start);
+ return cex->ec_type;
+ }
+
+ * last index in the block only
+ */
+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ struct buffer_head *bh;
+ int err;
+ if ((err = ext3_ext_dirty(handle, tree, path)))
+ return err;
+ ext_debug(tree, "index is empty, remove it, free block %d\n",
-+ path->p_idx->ei_leaf);
++ path->p_idx->ei_leaf);
+ bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
+}
+
+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
++ struct ext3_ext_path *path)
+{
+ int depth = EXT_DEPTH(tree);
+ int needed;
+
+static int
+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, tex;
+ struct ext3_ext_path *npath;
+ /* FIXME: some callback to free underlying resource
+ * and correct ee_start? */
+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
-+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
++ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
+
+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
+ if (IS_ERR(npath))
+ kfree(npath);
+
+ return err;
-+
+}
+
+static int
+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
++ struct ext3_ext_path *path, unsigned long start,
++ unsigned long end)
+{
+ struct ext3_extent *ex, *fu = NULL, *lu, *le;
+ int err = 0, correct_index = 0;
+ }
+
+ lu = ex;
-+ while (ex >= EXT_FIRST_EXTENT(eh) &&
-+ ex->ee_block + ex->ee_len > start) {
++ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) {
+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
+ path[depth].p_ext = ex;
+
+ block = ex->ee_block;
+ num = 0;
+ EXT_ASSERT(a == ex->ee_block &&
-+ b == ex->ee_block + ex->ee_len - 1);
++ b == ex->ee_block + ex->ee_len - 1);
+ }
+
+ if (ex == EXT_FIRST_EXTENT(eh))
+ goto out;
+
+ ext_debug(tree, "new extent: %u:%u:%u\n",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
++ ex->ee_block, ex->ee_len, ex->ee_start);
+ ex--;
+ }
+
+}
+
+int ext3_ext_remove_space(struct ext3_extents_tree *tree,
-+ unsigned long start, unsigned long end)
++ unsigned long start, unsigned long end)
+{
+ struct inode *inode = tree->inode;
+ struct super_block *sb = inode->i_sb;
+ */
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
+ if (IS_ERR(path)) {
-+ ext3_error(sb, "ext3_ext_remove_space",
-+ "Can't allocate path array");
++ ext3_error(sb, __FUNCTION__, "Can't allocate path array");
+ ext3_journal_stop(handle);
+ return -ENOMEM;
+ }
+ ext3_ext_last_covered(path[i].p_hdr, end);
+ path[i].p_block = path[i].p_hdr->eh_entries + 1;
+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
-+ path[i].p_hdr, path[i].p_hdr->eh_entries);
++ path[i].p_hdr, path[i].p_hdr->eh_entries);
+ } else {
+ /* we've already was here, see at next index */
+ path[i].p_idx--;
+ }
+
+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
-+ i, EXT_FIRST_INDEX(path[i].p_hdr),
-+ path[i].p_idx);
++ i, EXT_FIRST_INDEX(path[i].p_hdr),
++ path[i].p_idx);
+ if (ext3_ext_more_to_rm(path + i)) {
+ /* go to the next level */
+ ext_debug(tree, "move to level %d (block %d)\n",
-+ i + 1, path[i].p_idx->ei_leaf);
++ i + 1, path[i].p_idx->ei_leaf);
+ memset(path + i + 1, 0, sizeof(*path));
+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
+ if (!path[i+1].p_bh) {
+}
+
+static int ext3_ext_mergable(struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
++ struct ext3_extent *ex2)
+{
+ /* FIXME: support for large fs */
+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
+
+static int
+ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed;
+
+
+static int
+ext3_remove_blocks(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
++ struct ext3_extent *ex,
++ unsigned long from, unsigned long to)
+{
+ int needed = ext3_remove_blocks_credits(tree, ex, from, to);
+ handle_t *handle = ext3_journal_start(tree->inode, needed);
+ num = ex->ee_block + ex->ee_len - from;
+ start = ex->ee_start + ex->ee_len - num;
+ ext_debug(tree, "free last %lu blocks starting %lu\n",
-+ num, start);
++ num, start);
+ for (i = 0; i < num; i++) {
+ bh = sb_find_get_block(tree->inode->i_sb, start + i);
+ ext3_forget(handle, 0, tree->inode, bh, start + i);
+ ext3_free_blocks(handle, tree->inode, start, num);
+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
+ printk("strange request: removal %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ } else {
+ printk("strange request: removal(2) %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
++ from, to, ex->ee_block, ex->ee_len);
+ }
+ ext3_journal_stop(handle);
+ return 0;
+}
+
+static int ext3_ext_find_goal(struct inode *inode,
-+ struct ext3_ext_path *path, unsigned long block)
++ struct ext3_ext_path *path, unsigned long block)
+{
+ struct ext3_inode_info *ei = EXT3_I(inode);
+ unsigned long bg_start;
+}
+
+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int *err)
++ struct ext3_ext_path *path,
++ struct ext3_extent *ex, int *err)
+{
+ struct inode *inode = tree->inode;
+ int newblock, goal;
+};
+
+void ext3_init_tree_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode)
++ struct inode *inode)
+{
+ tree->inode = inode;
+ tree->root = (void *) EXT3_I(inode)->i_data;
+}
+
+int ext3_ext_get_block(handle_t *handle, struct inode *inode,
-+ long iblock, struct buffer_head *bh_result,
-+ int create, int extend_disksize)
++ long iblock, struct buffer_head *bh_result,
++ int create, int extend_disksize)
+{
+ struct ext3_ext_path *path = NULL;
+ struct ext3_extent newex;
+ clear_buffer_new(bh_result);
+ ext3_init_tree_desc(&tree, inode);
+ ext_debug(&tree, "block %d requested for inode %u\n",
-+ (int) iblock, (unsigned) inode->i_ino);
++ (int) iblock, (unsigned) inode->i_ino);
+ down(&EXT3_I(inode)->truncate_sem);
+
+ /* check in cache */
+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
+ newblock = iblock - ex->ee_block + ex->ee_start;
+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
-+ (int) iblock, ex->ee_block, ex->ee_len,
-+ newblock);
++ (int) iblock, ex->ee_block, ex->ee_len,
++ newblock);
+ ext3_ext_put_in_cache(&tree, ex->ee_block,
-+ ex->ee_len, ex->ee_start,
-+ EXT3_EXT_CACHE_EXTENT);
++ ex->ee_len, ex->ee_start,
++ EXT3_EXT_CACHE_EXTENT);
+ goto out;
+ }
+ }
+ if (!newblock)
+ goto out2;
+ ext_debug(&tree, "allocate new block: goal %d, found %d\n",
-+ goal, newblock);
++ goal, newblock);
+
+ /* try to insert new extent into found leaf and return */
+ newex.ee_block = iblock;
+ set_buffer_new(bh_result);
+
+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
-+ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
++ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
+out:
+ ext3_ext_show_leaf(&tree, path);
+ map_bh(bh_result, inode->i_sb, newblock);
+ EXT3_I(inode)->i_disksize = inode->i_size;
+ ext3_mark_inode_dirty(handle, inode);
+
-+ last_block = (inode->i_size + sb->s_blocksize - 1)
-+ >> EXT3_BLOCK_SIZE_BITS(sb);
++ last_block = (inode->i_size + sb->s_blocksize - 1) >>
++ EXT3_BLOCK_SIZE_BITS(sb);
+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
+
+ /* In a multi-transaction truncate, we only make the final
+
+static int
+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *newex)
+{
+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
+
-+ if (!exist)
++ if (newex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
++
+ if (buf->err < 0)
+ return EXT_BREAK;
+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
+
+static int
+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int exist)
++ struct ext3_ext_path *path,
++ struct ext3_ext_cache *ex)
+{
+ struct ext3_extent_tree_stats *buf =
+ (struct ext3_extent_tree_stats *) tree->private;
+ int depth;
+
-+ if (!exist)
++ if (ex->ec_type != EXT3_EXT_CACHE_EXTENT)
+ return EXT_CONTINUE;
+
+ depth = EXT_DEPTH(tree);
+ tree.private = &buf;
+ down(&EXT3_I(inode)->truncate_sem);
+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
++ ext3_ext_store_extent_cb);
+ up(&EXT3_I(inode)->truncate_sem);
+ if (err == 0)
+ err = buf.err;
+ buf.leaf_num = 0;
+ tree.private = &buf;
+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
++ ext3_ext_collect_stats_cb);
+ up(&EXT3_I(inode)->truncate_sem);
+ if (!err)
+ err = copy_to_user((void *) arg, &buf, sizeof(buf));
+EXPORT_SYMBOL(ext3_ext_walk_space);
+EXPORT_SYMBOL(ext3_ext_find_goal);
+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
-+
Index: linux-stage/fs/ext3/ialloc.c
===================================================================
--- linux-stage.orig/fs/ext3/ialloc.c 2005-02-25 14:50:50.304202816 +0200
+++ linux-stage/fs/ext3/ialloc.c 2005-02-25 15:33:48.920193600 +0200
-@@ -646,6 +646,10 @@
+@@ -646,6 +646,18 @@
DQUOT_FREE_INODE(inode);
goto fail2;
}
-+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, inode);
-+ }
++ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) {
++ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++ ext3_extents_initialize_blockmap(handle, inode);
++ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
++ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++ if (err) goto fail;
++ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
++ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
++ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
++ }
++ }
++
err = ext3_mark_inode_dirty(handle, inode);
if (err) {
ext3_std_error(sb, err);
+static inline int
+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+ struct buffer_head *bh, int create, int extend_disksize)
++ struct buffer_head *bh, int create, int extend_disksize)
+{
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
+ return ext3_ext_get_block(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+ return ext3_get_block_handle(handle, inode, block, bh, create,
-+ extend_disksize);
++ extend_disksize);
+}
+
static int ext3_get_block(struct inode *inode, sector_t iblock,
- ret = ext3_get_block_handle(handle, inode, iblock,
- bh_result, create, 1);
+ ret = ext3_get_block_wrap(handle, inode, iblock,
-+ bh_result, create, 1);
++ bh_result, create, 1);
return ret;
}
int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
int ret;
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_writepage_trans_blocks(inode, bpp);
-+
++ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
++ return ext3_ext_writepage_trans_blocks(inode, bpp);
++
if (ext3_should_journal_data(inode))
ret = 3 * (bpp + indirects) + 2;
else
struct ext3_super_block *es = sbi->s_es;
int i;
-+ ext3_ext_release(sb);
++ ext3_ext_release(sb);
ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
if (!(sb->s_flags & MS_RDONLY)) {
-@@ -457,6 +458,10 @@
+@@ -457,6 +458,8 @@
#endif
ei->i_rsv_window.rsv_end = EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
ei->vfs_inode.i_version = 1;
-+ ei->i_cached_extent[0] = 0;
-+ ei->i_cached_extent[1] = 0;
-+ ei->i_cached_extent[2] = 0;
-+ ei->i_cached_extent[3] = 0;
++
++ memset(&ei->i_cached_extent, 0, sizeof(ei->i_cached_extent));
return &ei->vfs_inode;
}
percpu_counter_mod(&sbi->s_dirs_counter,
ext3_count_dirs(sb));
-+ ext3_ext_init(sb);
-+
++ ext3_ext_init(sb);
++
return 0;
failed_mount3:
===================================================================
--- linux-stage.orig/include/linux/ext3_fs.h 2005-02-25 14:53:56.424908168 +0200
+++ linux-stage/include/linux/ext3_fs.h 2005-02-25 15:39:12.841950008 +0200
-@@ -186,6 +186,7 @@
+@@ -186,8 +186,9 @@
#define EXT3_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
#define EXT3_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
#define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
- #define EXT3_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
+-#define EXT3_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
++#define EXT3_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
#define EXT3_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
+
+ /*
@@ -237,6 +238,9 @@
#endif
#define EXT3_IOC_GETRSVSZ _IOR('f', 5, long)
/*
* Structure of an inode on the disk
-@@ -359,6 +363,9 @@
+@@ -359,6 +363,8 @@
#define EXT3_MOUNT_RESERVATION 0x20000 /* Preallocation */
#define EXT3_MOUNT_IOPEN 0x40000 /* Allow access via iopen */
#define EXT3_MOUNT_IOPEN_NOPRIV 0x80000 /* Make iopen world-readable */
+#define EXT3_MOUNT_EXTENTS 0x100000/* Extents support */
+#define EXT3_MOUNT_EXTDEBUG 0x200000/* Extents debug */
-+
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H
+@@ -503,11 +509,13 @@
+ #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
+ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
+ #define EXT3_FEATURE_INCOMPAT_META_BG 0x0010
++#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
+
+ #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
+ EXT3_FEATURE_INCOMPAT_RECOVER| \
+- EXT3_FEATURE_INCOMPAT_META_BG)
++ EXT3_FEATURE_INCOMPAT_META_BG| \
++ EXT3_FEATURE_INCOMPAT_EXTENTS)
+ #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
@@ -756,6 +763,7 @@
+/* extents.c */
+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+ struct buffer_head *, int, int);
++ struct buffer_head *, int, int);
+extern void ext3_ext_truncate(struct inode *, struct page *);
+extern void ext3_ext_init(struct super_block *);
+extern void ext3_ext_release(struct super_block *);
===================================================================
--- linux-stage.orig/include/linux/ext3_extents.h 2005-02-25 15:33:48.891198008 +0200
+++ linux-stage/include/linux/ext3_extents.h 2005-02-25 15:33:48.944189952 +0200
-@@ -0,0 +1,252 @@
+@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ */
+#define EXT_DEBUG_
+#ifdef EXT_DEBUG
-+#define ext_debug(tree,fmt,a...) \
++#define ext_debug(tree,fmt,a...) \
+do { \
+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
+ printk(fmt, ##a); \
+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
+ int (*remove_extent_credits)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*remove_extent)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
++ struct ext3_extent *, unsigned long,
++ unsigned long);
+ int (*new_block)(handle_t *, struct ext3_extents_tree *,
-+ struct ext3_ext_path *, struct ext3_extent *,
-+ int *);
++ struct ext3_ext_path *, struct ext3_extent *,
++ int *);
+};
+
+/*
+ * callback must return valid extent (passed or newly created)
+ */
+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
-+ struct ext3_ext_path *,
-+ struct ext3_extent *, int);
++ struct ext3_ext_path *,
++ struct ext3_ext_cache *);
+
+#define EXT_CONTINUE 0
+#define EXT_BREAK 1
+
+
+#define EXT_MAX_BLOCK 0xffffffff
-+#define EXT_CACHE_MARK 0xffff
+
+
+#define EXT_FIRST_EXTENT(__hdr__) \
+
+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
+
++#define EXT_CHECK_PATH(tree,path) \
++{ \
++ int depth = EXT_DEPTH(tree); \
++ BUG_ON((unsigned long) (path) < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_idx < \
++ __PAGE_OFFSET && (path)[depth].p_idx != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_ext < \
++ __PAGE_OFFSET && (path)[depth].p_ext != NULL); \
++ BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET); \
++ BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET \
++ && depth != 0); \
++ BUG_ON((path)[0].p_depth != depth); \
++}
++
+
+/*
+ * this structure is used to gather extents from the tree via ioctl
+ int leaf_num;
+};
+
++extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
-+extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
+extern int ext3_ext_calc_blockmap_metadata(struct inode *, int);
+
+static inline void
+
+
+#endif /* _LINUX_EXT3_EXTENTS */
-+
Index: linux-stage/include/linux/ext3_fs_i.h
===================================================================
--- linux-stage.orig/include/linux/ext3_fs_i.h 2005-02-25 14:50:50.320200384 +0200
struct semaphore truncate_sem;
struct inode vfs_inode;
+
-+ __u32 i_cached_extent[4];
++ __u32 i_cached_extent[4];
};
#endif /* _LINUX_EXT3_FS_I */
+++ /dev/null
-Index: linux-2.4.20-30.9/fs/ext3/inode.c
-===================================================================
---- linux-2.4.20-30.9.orig/fs/ext3/inode.c 2004-05-18 13:55:49.000000000 -0700
-+++ linux-2.4.20-30.9/fs/ext3/inode.c 2004-05-18 13:59:46.000000000 -0700
-@@ -2217,6 +2217,10 @@
-
- memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data));
- memset(oei->i_data, 0, sizeof(oei->i_data));
-+ if (EXT3_I(old_inode)->i_flags & EXT3_EXTENTS_FL) {
-+ EXT3_I(new_inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, old_inode);
-+ }
-
- nei->i_disksize = oei->i_disksize;
- nei->i_state |= EXT3_STATE_DELETE;
-@@ -2447,6 +2451,13 @@
-
- brelse (iloc.bh);
-
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
-+ inode->u.ext3_i.i_cached_extent[0] = 0;
-+ inode->u.ext3_i.i_cached_extent[1] = 0;
-+ inode->u.ext3_i.i_cached_extent[2] = 0;
-+ inode->u.ext3_i.i_cached_extent[3] = 0;
-+ }
-+
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data));
memset(oei->i_data, 0, sizeof(oei->i_data));
-+ if (EXT3_I(old_inode)->i_flags & EXT3_EXTENTS_FL) {
-+ EXT3_I(new_inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, old_inode);
-+ }
++ if (EXT3_I(old_inode)->i_flags & EXT3_EXTENTS_FL) {
++ EXT3_I(new_inode)->i_flags |= EXT3_EXTENTS_FL;
++ ext3_extents_initialize_blockmap(handle, old_inode);
++ }
nei->i_disksize = oei->i_disksize;
nei->i_state |= EXT3_STATE_DELETE;
memset(oei->i_data, 0, sizeof(oei->i_data));
+ if (EXT3_I(old_inode)->i_flags & EXT3_EXTENTS_FL) {
+ EXT3_I(new_inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, old_inode);
++ ext3_extents_initialize_blockmap(handle, old_inode);
+ }
nei->i_disksize = oei->i_disksize;
+++ /dev/null
- fs/ext3/Makefile | 2
- fs/ext3/dir.c | 302 +++++++++
- fs/ext3/file.c | 3
- fs/ext3/hash.c | 215 ++++++
- fs/ext3/namei.c | 1420 ++++++++++++++++++++++++++++++++++++++++-----
- fs/ext3/super.c | 7
- include/linux/ext3_fs.h | 85 ++
- include/linux/ext3_fs_sb.h | 2
- include/linux/ext3_jbd.h | 2
- include/linux/rbtree.h | 2
- lib/rbtree.c | 42 +
- 11 files changed, 1921 insertions(+), 161 deletions(-)
-
-Index: linux-2.4.21-suse/fs/ext3/dir.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/dir.c 2001-11-10 01:25:04.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/dir.c 2003-10-29 23:17:20.000000000 +0300
-@@ -21,12 +21,16 @@
- #include <linux/fs.h>
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
-+#include <linux/slab.h>
-+#include <linux/rbtree.h>
-
- static unsigned char ext3_filetype_table[] = {
- 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);
-+static int ext3_dx_readdir(struct file * filp,
-+ void * dirent, filldir_t filldir);
-
- struct file_operations ext3_dir_operations = {
- read: generic_read_dir,
-@@ -35,6 +39,17 @@
- fsync: ext3_sync_file, /* BKL held */
- };
-
-+
-+static unsigned char get_dtype(struct super_block *sb, int filetype)
-+{
-+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) ||
-+ (filetype >= EXT3_FT_MAX))
-+ return DT_UNKNOWN;
-+
-+ return (ext3_filetype_table[filetype]);
-+}
-+
-+
- int ext3_check_dir_entry (const char * function, struct inode * dir,
- struct ext3_dir_entry_2 * de,
- struct buffer_head * bh,
-@@ -79,6 +94,16 @@
-
- sb = inode->i_sb;
-
-+ if (is_dx(inode)) {
-+ err = ext3_dx_readdir(filp, dirent, filldir);
-+ if (err != ERR_BAD_DX_DIR)
-+ return err;
-+ /*
-+ * We don't set the inode dirty flag since it's not
-+ * critical that it get flushed back to the disk.
-+ */
-+ EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL;
-+ }
- stored = 0;
- bh = NULL;
- offset = filp->f_pos & (sb->s_blocksize - 1);
-@@ -162,18 +187,12 @@
- * during the copy operation.
- */
- unsigned long version = filp->f_version;
-- unsigned char d_type = DT_UNKNOWN;
-
-- if (EXT3_HAS_INCOMPAT_FEATURE(sb,
-- EXT3_FEATURE_INCOMPAT_FILETYPE)
-- && de->file_type < EXT3_FT_MAX)
-- d_type =
-- ext3_filetype_table[de->file_type];
- error = filldir(dirent, de->name,
- de->name_len,
- filp->f_pos,
- le32_to_cpu(de->inode),
-- d_type);
-+ get_dtype(sb, de->file_type));
- if (error)
- break;
- if (version != filp->f_version)
-@@ -188,3 +207,272 @@
- UPDATE_ATIME(inode);
- return 0;
- }
-+
-+#ifdef CONFIG_EXT3_INDEX
-+/*
-+ * These functions convert from the major/minor hash to an f_pos
-+ * value.
-+ *
-+ * Currently we only use major hash numer. This is unfortunate, but
-+ * on 32-bit machines, the same VFS interface is used for lseek and
-+ * llseek, so if we use the 64 bit offset, then the 32-bit versions of
-+ * lseek/telldir/seekdir will blow out spectacularly, and from within
-+ * the ext2 low-level routine, we don't know if we're being called by
-+ * a 64-bit version of the system call or the 32-bit version of the
-+ * system call. Worse yet, NFSv2 only allows for a 32-bit readdir
-+ * cookie. Sigh.
-+ */
-+#define hash2pos(major, minor) (major >> 1)
-+#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff)
-+#define pos2min_hash(pos) (0)
-+
-+/*
-+ * This structure holds the nodes of the red-black tree used to store
-+ * the directory entry in hash order.
-+ */
-+struct fname {
-+ __u32 hash;
-+ __u32 minor_hash;
-+ rb_node_t rb_hash;
-+ struct fname *next;
-+ __u32 inode;
-+ __u8 name_len;
-+ __u8 file_type;
-+ char name[0];
-+};
-+
-+/*
-+ * This functoin implements a non-recursive way of freeing all of the
-+ * nodes in the red-black tree.
-+ */
-+static void free_rb_tree_fname(rb_root_t *root)
-+{
-+ rb_node_t *n = root->rb_node;
-+ rb_node_t *parent;
-+ struct fname *fname;
-+
-+ while (n) {
-+ /* Do the node's children first */
-+ if ((n)->rb_left) {
-+ n = n->rb_left;
-+ continue;
-+ }
-+ if (n->rb_right) {
-+ n = n->rb_right;
-+ continue;
-+ }
-+ /*
-+ * The node has no children; free it, and then zero
-+ * out parent's link to it. Finally go to the
-+ * beginning of the loop and try to free the parent
-+ * node.
-+ */
-+ parent = n->rb_parent;
-+ fname = rb_entry(n, struct fname, rb_hash);
-+ kfree(fname);
-+ if (!parent)
-+ root->rb_node = 0;
-+ else if (parent->rb_left == n)
-+ parent->rb_left = 0;
-+ else if (parent->rb_right == n)
-+ parent->rb_right = 0;
-+ n = parent;
-+ }
-+ root->rb_node = 0;
-+}
-+
-+
-+struct dir_private_info *create_dir_info(loff_t pos)
-+{
-+ struct dir_private_info *p;
-+
-+ p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL);
-+ if (!p)
-+ return NULL;
-+ p->root.rb_node = 0;
-+ p->curr_node = 0;
-+ p->extra_fname = 0;
-+ p->last_pos = 0;
-+ p->curr_hash = pos2maj_hash(pos);
-+ p->curr_minor_hash = pos2min_hash(pos);
-+ p->next_hash = 0;
-+ return p;
-+}
-+
-+void ext3_htree_free_dir_info(struct dir_private_info *p)
-+{
-+ free_rb_tree_fname(&p->root);
-+ kfree(p);
-+}
-+
-+/*
-+ * Given a directory entry, enter it into the fname rb tree.
-+ */
-+int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
-+ __u32 minor_hash,
-+ struct ext3_dir_entry_2 *dirent)
-+{
-+ rb_node_t **p, *parent = NULL;
-+ struct fname * fname, *new_fn;
-+ struct dir_private_info *info;
-+ int len;
-+
-+ info = (struct dir_private_info *) dir_file->private_data;
-+ p = &info->root.rb_node;
-+
-+ /* Create and allocate the fname structure */
-+ len = sizeof(struct fname) + dirent->name_len + 1;
-+ new_fn = kmalloc(len, GFP_KERNEL);
-+ if (!new_fn)
-+ return -ENOMEM;
-+ memset(new_fn, 0, len);
-+ new_fn->hash = hash;
-+ new_fn->minor_hash = minor_hash;
-+ new_fn->inode = le32_to_cpu(dirent->inode);
-+ new_fn->name_len = dirent->name_len;
-+ new_fn->file_type = dirent->file_type;
-+ memcpy(new_fn->name, dirent->name, dirent->name_len);
-+ new_fn->name[dirent->name_len] = 0;
-+
-+ while (*p) {
-+ parent = *p;
-+ fname = rb_entry(parent, struct fname, rb_hash);
-+
-+ /*
-+ * If the hash and minor hash match up, then we put
-+ * them on a linked list. This rarely happens...
-+ */
-+ if ((new_fn->hash == fname->hash) &&
-+ (new_fn->minor_hash == fname->minor_hash)) {
-+ new_fn->next = fname->next;
-+ fname->next = new_fn;
-+ return 0;
-+ }
-+
-+ if (new_fn->hash < fname->hash)
-+ p = &(*p)->rb_left;
-+ else if (new_fn->hash > fname->hash)
-+ p = &(*p)->rb_right;
-+ else if (new_fn->minor_hash < fname->minor_hash)
-+ p = &(*p)->rb_left;
-+ else /* if (new_fn->minor_hash > fname->minor_hash) */
-+ p = &(*p)->rb_right;
-+ }
-+
-+ rb_link_node(&new_fn->rb_hash, parent, p);
-+ rb_insert_color(&new_fn->rb_hash, &info->root);
-+ return 0;
-+}
-+
-+
-+
-+/*
-+ * This is a helper function for ext3_dx_readdir. It calls filldir
-+ * for all entres on the fname linked list. (Normally there is only
-+ * one entry on the linked list, unless there are 62 bit hash collisions.)
-+ */
-+static int call_filldir(struct file * filp, void * dirent,
-+ filldir_t filldir, struct fname *fname)
-+{
-+ struct dir_private_info *info = filp->private_data;
-+ loff_t curr_pos;
-+ struct inode *inode = filp->f_dentry->d_inode;
-+ struct super_block * sb;
-+ int error;
-+
-+ sb = inode->i_sb;
-+
-+ if (!fname) {
-+ printk("call_filldir: called with null fname?!?\n");
-+ return 0;
-+ }
-+ curr_pos = hash2pos(fname->hash, fname->minor_hash);
-+ while (fname) {
-+ error = filldir(dirent, fname->name,
-+ fname->name_len, curr_pos,
-+ fname->inode,
-+ get_dtype(sb, fname->file_type));
-+ if (error) {
-+ filp->f_pos = curr_pos;
-+ info->extra_fname = fname->next;
-+ return error;
-+ }
-+ fname = fname->next;
-+ }
-+ return 0;
-+}
-+
-+static int ext3_dx_readdir(struct file * filp,
-+ void * dirent, filldir_t filldir)
-+{
-+ struct dir_private_info *info = filp->private_data;
-+ struct inode *inode = filp->f_dentry->d_inode;
-+ struct fname *fname;
-+ int ret;
-+
-+ if (!info) {
-+ info = create_dir_info(filp->f_pos);
-+ if (!info)
-+ return -ENOMEM;
-+ filp->private_data = info;
-+ }
-+
-+ /* Some one has messed with f_pos; reset the world */
-+ if (info->last_pos != filp->f_pos) {
-+ free_rb_tree_fname(&info->root);
-+ info->curr_node = 0;
-+ info->extra_fname = 0;
-+ info->curr_hash = pos2maj_hash(filp->f_pos);
-+ info->curr_minor_hash = pos2min_hash(filp->f_pos);
-+ }
-+
-+ /*
-+ * If there are any leftover names on the hash collision
-+ * chain, return them first.
-+ */
-+ if (info->extra_fname &&
-+ call_filldir(filp, dirent, filldir, info->extra_fname))
-+ goto finished;
-+
-+ if (!info->curr_node)
-+ info->curr_node = rb_get_first(&info->root);
-+
-+ while (1) {
-+ /*
-+ * Fill the rbtree if we have no more entries,
-+ * or the inode has changed since we last read in the
-+ * cached entries.
-+ */
-+ if ((!info->curr_node) ||
-+ (filp->f_version != inode->i_version)) {
-+ info->curr_node = 0;
-+ free_rb_tree_fname(&info->root);
-+ filp->f_version = inode->i_version;
-+ ret = ext3_htree_fill_tree(filp, info->curr_hash,
-+ info->curr_minor_hash,
-+ &info->next_hash);
-+ if (ret < 0)
-+ return ret;
-+ if (ret == 0)
-+ break;
-+ info->curr_node = rb_get_first(&info->root);
-+ }
-+
-+ fname = rb_entry(info->curr_node, struct fname, rb_hash);
-+ info->curr_hash = fname->hash;
-+ info->curr_minor_hash = fname->minor_hash;
-+ if (call_filldir(filp, dirent, filldir, fname))
-+ break;
-+
-+ info->curr_node = rb_get_next(info->curr_node);
-+ if (!info->curr_node) {
-+ info->curr_hash = info->next_hash;
-+ info->curr_minor_hash = 0;
-+ }
-+ }
-+finished:
-+ info->last_pos = filp->f_pos;
-+ UPDATE_ATIME(inode);
-+ return 0;
-+}
-+#endif
-Index: linux-2.4.21-suse/fs/ext3/file.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/file.c 2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/file.c 2003-10-29 23:17:20.000000000 +0300
-@@ -35,6 +35,9 @@
- {
- if (filp->f_mode & FMODE_WRITE)
- ext3_discard_prealloc (inode);
-+ if (is_dx(inode) && filp->private_data)
-+ ext3_htree_free_dir_info(filp->private_data);
-+
- return 0;
- }
-
-Index: linux-2.4.21-suse/fs/ext3/hash.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/hash.c 2003-10-29 23:17:20.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/hash.c 2003-10-29 23:17:20.000000000 +0300
-@@ -0,0 +1,215 @@
-+/*
-+ * linux/fs/ext3/hash.c
-+ *
-+ * Copyright (C) 2002 by Theodore Ts'o
-+ *
-+ * This file is released under the GPL v2.
-+ *
-+ * This file may be redistributed under the terms of the GNU Public
-+ * License.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/sched.h>
-+#include <linux/ext3_fs.h>
-+
-+#define DELTA 0x9E3779B9
-+
-+static void TEA_transform(__u32 buf[4], __u32 const in[])
-+{
-+ __u32 sum = 0;
-+ __u32 b0 = buf[0], b1 = buf[1];
-+ __u32 a = in[0], b = in[1], c = in[2], d = in[3];
-+ int n = 16;
-+
-+ do {
-+ sum += DELTA;
-+ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
-+ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
-+ } while(--n);
-+
-+ buf[0] += b0;
-+ buf[1] += b1;
-+}
-+
-+/* F, G and H are basic MD4 functions: selection, majority, parity */
-+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-+#define H(x, y, z) ((x) ^ (y) ^ (z))
-+
-+/*
-+ * The generic round function. The application is so specific that
-+ * we don't bother protecting all the arguments with parens, as is generally
-+ * good macro practice, in favor of extra legibility.
-+ * Rotation is separate from addition to prevent recomputation
-+ */
-+#define ROUND(f, a, b, c, d, x, s) \
-+ (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
-+#define K1 0
-+#define K2 013240474631UL
-+#define K3 015666365641UL
-+
-+/*
-+ * Basic cut-down MD4 transform. Returns only 32 bits of result.
-+ */
-+static void halfMD4Transform (__u32 buf[4], __u32 const in[])
-+{
-+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-+
-+ /* Round 1 */
-+ ROUND(F, a, b, c, d, in[0] + K1, 3);
-+ ROUND(F, d, a, b, c, in[1] + K1, 7);
-+ ROUND(F, c, d, a, b, in[2] + K1, 11);
-+ ROUND(F, b, c, d, a, in[3] + K1, 19);
-+ ROUND(F, a, b, c, d, in[4] + K1, 3);
-+ ROUND(F, d, a, b, c, in[5] + K1, 7);
-+ ROUND(F, c, d, a, b, in[6] + K1, 11);
-+ ROUND(F, b, c, d, a, in[7] + K1, 19);
-+
-+ /* Round 2 */
-+ ROUND(G, a, b, c, d, in[1] + K2, 3);
-+ ROUND(G, d, a, b, c, in[3] + K2, 5);
-+ ROUND(G, c, d, a, b, in[5] + K2, 9);
-+ ROUND(G, b, c, d, a, in[7] + K2, 13);
-+ ROUND(G, a, b, c, d, in[0] + K2, 3);
-+ ROUND(G, d, a, b, c, in[2] + K2, 5);
-+ ROUND(G, c, d, a, b, in[4] + K2, 9);
-+ ROUND(G, b, c, d, a, in[6] + K2, 13);
-+
-+ /* Round 3 */
-+ ROUND(H, a, b, c, d, in[3] + K3, 3);
-+ ROUND(H, d, a, b, c, in[7] + K3, 9);
-+ ROUND(H, c, d, a, b, in[2] + K3, 11);
-+ ROUND(H, b, c, d, a, in[6] + K3, 15);
-+ ROUND(H, a, b, c, d, in[1] + K3, 3);
-+ ROUND(H, d, a, b, c, in[5] + K3, 9);
-+ ROUND(H, c, d, a, b, in[0] + K3, 11);
-+ ROUND(H, b, c, d, a, in[4] + K3, 15);
-+
-+ buf[0] += a;
-+ buf[1] += b;
-+ buf[2] += c;
-+ buf[3] += d;
-+}
-+
-+#undef ROUND
-+#undef F
-+#undef G
-+#undef H
-+#undef K1
-+#undef K2
-+#undef K3
-+
-+/* The old legacy hash */
-+static __u32 dx_hack_hash (const char *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 (hash0 << 1);
-+}
-+
-+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
-+{
-+ __u32 pad, val;
-+ int i;
-+
-+ pad = (__u32)len | ((__u32)len << 8);
-+ pad |= pad << 16;
-+
-+ val = pad;
-+ if (len > num*4)
-+ len = num * 4;
-+ for (i=0; i < len; i++) {
-+ if ((i % 4) == 0)
-+ val = pad;
-+ val = msg[i] + (val << 8);
-+ if ((i % 4) == 3) {
-+ *buf++ = val;
-+ val = pad;
-+ num--;
-+ }
-+ }
-+ if (--num >= 0)
-+ *buf++ = val;
-+ while (--num >= 0)
-+ *buf++ = pad;
-+}
-+
-+/*
-+ * Returns the hash of a filename. If len is 0 and name is NULL, then
-+ * this function can be used to test whether or not a hash version is
-+ * supported.
-+ *
-+ * The seed is an 4 longword (32 bits) "secret" which can be used to
-+ * uniquify a hash. If the seed is all zero's, then some default seed
-+ * may be used.
-+ *
-+ * A particular hash version specifies whether or not the seed is
-+ * represented, and whether or not the returned hash is 32 bits or 64
-+ * bits. 32 bit hashes will return 0 for the minor hash.
-+ */
-+int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
-+{
-+ __u32 hash;
-+ __u32 minor_hash = 0;
-+ const char *p;
-+ int i;
-+ __u32 in[8], buf[4];
-+
-+ /* Initialize the default seed for the hash checksum functions */
-+ buf[0] = 0x67452301;
-+ buf[1] = 0xefcdab89;
-+ buf[2] = 0x98badcfe;
-+ buf[3] = 0x10325476;
-+
-+ /* Check to see if the seed is all zero's */
-+ if (hinfo->seed) {
-+ for (i=0; i < 4; i++) {
-+ if (hinfo->seed[i])
-+ break;
-+ }
-+ if (i < 4)
-+ memcpy(buf, hinfo->seed, sizeof(buf));
-+ }
-+
-+ switch (hinfo->hash_version) {
-+ case DX_HASH_LEGACY:
-+ hash = dx_hack_hash(name, len);
-+ break;
-+ case DX_HASH_HALF_MD4:
-+ p = name;
-+ while (len > 0) {
-+ str2hashbuf(p, len, in, 8);
-+ halfMD4Transform(buf, in);
-+ len -= 32;
-+ p += 32;
-+ }
-+ minor_hash = buf[2];
-+ hash = buf[1];
-+ break;
-+ case DX_HASH_TEA:
-+ p = name;
-+ while (len > 0) {
-+ str2hashbuf(p, len, in, 4);
-+ TEA_transform(buf, in);
-+ len -= 16;
-+ p += 16;
-+ }
-+ hash = buf[0];
-+ minor_hash = buf[1];
-+ break;
-+ default:
-+ hinfo->hash = 0;
-+ return -1;
-+ }
-+ hinfo->hash = hash & ~1;
-+ hinfo->minor_hash = minor_hash;
-+ return 0;
-+}
-Index: linux-2.4.21-suse/fs/ext3/Makefile
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/Makefile 2003-10-29 22:39:14.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/Makefile 2003-10-29 23:17:20.000000000 +0300
-@@ -12,7 +12,7 @@
- export-objs := super.o inode.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
-+ ioctl.o namei.o super.o symlink.o hash.o
- obj-m := $(O_TARGET)
-
- include $(TOPDIR)/Rules.make
-Index: linux-2.4.21-suse/fs/ext3/namei.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/namei.c 2003-06-13 18:51:37.000000000 +0400
-+++ linux-2.4.21-suse/fs/ext3/namei.c 2003-10-29 23:25:23.000000000 +0300
-@@ -16,6 +16,12 @@
- * 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
-+ * Hash Tree Directory indexing cleanup
-+ * Theodore Ts'o, 2002
- */
-
- #include <linux/fs.h>
-@@ -38,6 +44,642 @@
- #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
- #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
-
-+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_I(inode)->i_disksize = inode->i_size;
-+ ext3_journal_get_write_access(handle,bh);
-+ }
-+ return bh;
-+}
-+
-+#ifndef assert
-+#define assert(test) J_ASSERT(test)
-+#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;
-+
-+#ifdef DX_DEBUG
-+#define dxtrace(command) command
-+#else
-+#define dxtrace(command)
-+#endif
-+
-+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 dot;
-+ char dot_name[4];
-+ struct fake_dirent dotdot;
-+ char dotdot_name[4];
-+ struct dx_root_info
-+ {
-+ le_u32 reserved_zero;
-+ u8 hash_version;
-+ 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;
-+};
-+
-+#ifdef CONFIG_EXT3_INDEX
-+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 struct dx_frame *dx_probe(struct dentry *dentry,
-+ struct inode *dir,
-+ struct dx_hash_info *hinfo,
-+ struct dx_frame *frame,
-+ int *err);
-+static void dx_release (struct dx_frame *frames);
-+static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
-+ struct dx_hash_info *hinfo, struct dx_map_entry map[]);
-+static void dx_sort_map(struct dx_map_entry *map, unsigned count);
-+static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to,
-+ struct dx_map_entry *offsets, int count);
-+static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
-+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
-+static int ext3_htree_next_block(struct inode *dir, __u32 hash,
-+ struct dx_frame *frame,
-+ struct dx_frame *frames, int *err,
-+ __u32 *start_hash);
-+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-+ struct ext3_dir_entry_2 **res_dir, int *err);
-+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
-+ struct inode *inode);
-+
-+/*
-+ * 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) & 0x00ffffff;
-+}
-+
-+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 - EXT3_DIR_REC_LEN(1) -
-+ EXT3_DIR_REC_LEN(2) - 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 - EXT3_DIR_REC_LEN(0);
-+ return 0? 22: entry_space / sizeof(struct dx_entry);
-+}
-+
-+/*
-+ * Debug
-+ */
-+#ifdef DX_DEBUG
-+struct stats
-+{
-+ unsigned names;
-+ unsigned space;
-+ unsigned bcount;
-+};
-+
-+static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_entry_2 *de,
-+ int size, int show_names)
-+{
-+ unsigned names = 0, space = 0;
-+ char *base = (char *) de;
-+ struct dx_hash_info h = *hinfo;
-+
-+ 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++);
-+ ext3fs_dirhash(de->name, de->name_len, &h);
-+ printk(":%x.%u ", h.hash,
-+ ((char *) de - base));
-+ }
-+ space += EXT3_DIR_REC_LEN(de->name_len);
-+ names++;
-+ }
-+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-+ }
-+ printk("(%i)\n", names);
-+ return (struct stats) { names, space, 1 };
-+}
-+
-+struct stats dx_show_entries(struct dx_hash_info *hinfo, 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(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
-+ dx_show_leaf(hinfo, (struct ext3_dir_entry_2 *) 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};
-+}
-+#endif /* DX_DEBUG */
-+
-+/*
-+ * Probe for a directory leaf block to search.
-+ *
-+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
-+ * error in the directory index, and the caller should fall back to
-+ * searching the directory normally. The callers of dx_probe **MUST**
-+ * check for this error code, and make sure it never gets reflected
-+ * back to userspace.
-+ */
-+static struct dx_frame *
-+dx_probe(struct dentry *dentry, struct inode *dir,
-+ struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
-+{
-+ unsigned count, indirect;
-+ struct dx_entry *at, *entries, *p, *q, *m;
-+ struct dx_root *root;
-+ struct buffer_head *bh;
-+ struct dx_frame *frame = frame_in;
-+ u32 hash;
-+
-+ frame->bh = NULL;
-+ if (dentry)
-+ dir = dentry->d_parent->d_inode;
-+ if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
-+ goto fail;
-+ root = (struct dx_root *) bh->b_data;
-+ if (root->info.hash_version != DX_HASH_TEA &&
-+ root->info.hash_version != DX_HASH_HALF_MD4 &&
-+ root->info.hash_version != DX_HASH_LEGACY) {
-+ ext3_warning(dir->i_sb, __FUNCTION__,
-+ "Unrecognised inode hash code %d",
-+ root->info.hash_version);
-+ brelse(bh);
-+ *err = ERR_BAD_DX_DIR;
-+ goto fail;
-+ }
-+ hinfo->hash_version = root->info.hash_version;
-+ hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed;
-+ if (dentry)
-+ ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
-+ hash = hinfo->hash;
-+
-+ if (root->info.unused_flags & 1) {
-+ ext3_warning(dir->i_sb, __FUNCTION__,
-+ "Unimplemented inode hash flags: %#06x",
-+ root->info.unused_flags);
-+ brelse(bh);
-+ *err = ERR_BAD_DX_DIR;
-+ goto fail;
-+ }
-+
-+ if ((indirect = root->info.indirect_levels) > 1) {
-+ ext3_warning(dir->i_sb, __FUNCTION__,
-+ "Unimplemented inode hash depth: %#06x",
-+ root->info.indirect_levels);
-+ brelse(bh);
-+ *err = ERR_BAD_DX_DIR;
-+ 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:
-+ while (frame >= frame_in) {
-+ brelse(frame->bh);
-+ frame--;
-+ }
-+fail:
-+ return NULL;
-+}
-+
-+static void dx_release (struct dx_frame *frames)
-+{
-+ if (frames[0].bh == NULL)
-+ return;
-+
-+ if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
-+ brelse(frames[1].bh);
-+ brelse(frames[0].bh);
-+}
-+
-+/*
-+ * This function increments the frame pointer to search the next leaf
-+ * block, and reads in the necessary intervening nodes if the search
-+ * should be necessary. Whether or not the search is necessary is
-+ * controlled by the hash parameter. If the hash value is even, then
-+ * the search is only continued if the next block starts with that
-+ * hash value. This is used if we are searching for a specific file.
-+ *
-+ * If the hash value is HASH_NB_ALWAYS, then always go to the next block.
-+ *
-+ * This function returns 1 if the caller should continue to search,
-+ * or 0 if it should not. If there is an error reading one of the
-+ * index blocks, it will return -1.
-+ *
-+ * If start_hash is non-null, it will be filled in with the starting
-+ * hash of the next page.
-+ */
-+static int ext3_htree_next_block(struct inode *dir, __u32 hash,
-+ struct dx_frame *frame,
-+ struct dx_frame *frames, int *err,
-+ __u32 *start_hash)
-+{
-+ struct dx_frame *p;
-+ struct buffer_head *bh;
-+ int num_frames = 0;
-+ __u32 bhash;
-+
-+ *err = ENOENT;
-+ p = frame;
-+ /*
-+ * Find the next leaf page by incrementing the frame pointer.
-+ * If we run out of entries in the interior node, loop around and
-+ * increment pointer in the parent node. When we break out of
-+ * this loop, num_frames indicates the number of interior
-+ * nodes need to be read.
-+ */
-+ while (1) {
-+ if (++(p->at) < p->entries + dx_get_count(p->entries))
-+ break;
-+ if (p == frames)
-+ return 0;
-+ num_frames++;
-+ p--;
-+ }
-+
-+ /*
-+ * If the hash is 1, then continue only if the next page has a
-+ * continuation hash of any value. This is used for readdir
-+ * handling. Otherwise, check to see if the hash matches the
-+ * desired contiuation hash. If it doesn't, return since
-+ * there's no point to read in the successive index pages.
-+ */
-+ bhash = dx_get_hash(p->at);
-+ if (start_hash)
-+ *start_hash = bhash;
-+ if ((hash & 1) == 0) {
-+ if ((bhash & ~1) != hash)
-+ return 0;
-+ }
-+ /*
-+ * If the hash is HASH_NB_ALWAYS, we always go to the next
-+ * block so no check is necessary
-+ */
-+ while (num_frames--) {
-+ if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at),
-+ 0, err)))
-+ return -1; /* Failure */
-+ p++;
-+ brelse (p->bh);
-+ p->bh = bh;
-+ p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
-+ }
-+ return 1;
-+}
-+
-+
-+/*
-+ * p is at least 6 bytes before the end of page
-+ */
-+static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p)
-+{
-+ return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len));
-+}
-+
-+/*
-+ * This function fills a red-black tree with information from a
-+ * directory. We start scanning the directory in hash order, starting
-+ * at start_hash and start_minor_hash.
-+ *
-+ * This function returns the number of entries inserted into the tree,
-+ * or a negative error code.
-+ */
-+int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-+ __u32 start_minor_hash, __u32 *next_hash)
-+{
-+ struct dx_hash_info hinfo;
-+ struct buffer_head *bh;
-+ struct ext3_dir_entry_2 *de, *top;
-+ static struct dx_frame frames[2], *frame;
-+ struct inode *dir;
-+ int block, err;
-+ int count = 0;
-+ int ret;
-+ __u32 hashval;
-+
-+ dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
-+ start_minor_hash));
-+ dir = dir_file->f_dentry->d_inode;
-+ hinfo.hash = start_hash;
-+ hinfo.minor_hash = 0;
-+ frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
-+ if (!frame)
-+ return err;
-+
-+ /* Add '.' and '..' from the htree header */
-+ if (!start_hash && !start_minor_hash) {
-+ de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data;
-+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0)
-+ goto errout;
-+ de = ext3_next_entry(de);
-+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0)
-+ goto errout;
-+ count += 2;
-+ }
-+
-+ while (1) {
-+ block = dx_get_block(frame->at);
-+ dxtrace(printk("Reading block %d\n", block));
-+ if (!(bh = ext3_bread (NULL, dir, block, 0, &err)))
-+ goto errout;
-+
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ top = (struct ext3_dir_entry_2 *) ((char *) de + dir->i_sb->s_blocksize -
-+ EXT3_DIR_REC_LEN(0));
-+ for (; de < top; de = ext3_next_entry(de)) {
-+ ext3fs_dirhash(de->name, de->name_len, &hinfo);
-+ if ((hinfo.hash < start_hash) ||
-+ ((hinfo.hash == start_hash) &&
-+ (hinfo.minor_hash < start_minor_hash)))
-+ continue;
-+ if ((err = ext3_htree_store_dirent(dir_file,
-+ hinfo.hash, hinfo.minor_hash, de)) != 0)
-+ goto errout;
-+ count++;
-+ }
-+ brelse (bh);
-+ hashval = ~1;
-+ ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS,
-+ frame, frames, &err, &hashval);
-+ if (next_hash)
-+ *next_hash = hashval;
-+ if (ret == -1)
-+ goto errout;
-+ /*
-+ * Stop if: (a) there are no more entries, or
-+ * (b) we have inserted at least one entry and the
-+ * next hash value is not a continuation
-+ */
-+ if ((ret == 0) ||
-+ (count && ((hashval & 1) == 0)))
-+ break;
-+ }
-+ dx_release(frames);
-+ dxtrace(printk("Fill tree: returned %d entries\n", count));
-+ return count;
-+errout:
-+ dx_release(frames);
-+ return (err);
-+}
-+
-+
-+/*
-+ * Directory block splitting, compacting
-+ */
-+
-+static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
-+ struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
-+{
-+ int count = 0;
-+ char *base = (char *) de;
-+ struct dx_hash_info h = *hinfo;
-+
-+ while ((char *) de < base + size)
-+ {
-+ if (de->name_len && de->inode) {
-+ ext3fs_dirhash(de->name, de->name_len, &h);
-+ map_tail--;
-+ map_tail->hash = h.hash;
-+ map_tail->offs = (u32) ((char *) de - base);
-+ count++;
-+ }
-+ /* XXX: do we need to check rec_len == 0 case? -Chris */
-+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-+ }
-+ 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;
-+ struct dx_entry *old = frame->at, *new = old + 1;
-+ int count = dx_get_count(entries);
-+
-+ assert(count < dx_get_limit(entries));
-+ assert(old < entries + count);
-+ memmove(new + 1, new, (char *)(entries + count) - (char *)(new));
-+ dx_set_hash(new, hash);
-+ dx_set_block(new, block);
-+ dx_set_count(entries, count + 1);
-+}
-+#endif
-+
-+
-+static void ext3_update_dx_flag(struct inode *inode)
-+{
-+ if (!EXT3_HAS_COMPAT_FEATURE(inode->i_sb,
-+ EXT3_FEATURE_COMPAT_DIR_INDEX))
-+ EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL;
-+}
-+
- /*
- * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure.
- *
-@@ -94,6 +736,7 @@
- return 0;
- }
-
-+
- /*
- * ext3_find_entry()
- *
-@@ -105,6 +748,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,12 +764,32 @@
- int num = 0;
- int nblocks, i, err;
- struct inode *dir = dentry->d_parent->d_inode;
-+ int namelen;
-+ const u8 *name;
-+ unsigned blocksize;
-
- *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;
-+#ifdef CONFIG_EXT3_INDEX
-+ if (is_dx(dir)) {
-+ bh = ext3_dx_find_entry(dentry, res_dir, &err);
-+ /*
-+ * On success, or if the error was file not found,
-+ * return. Otherwise, fall back to doing a search the
-+ * old fashioned way.
-+ */
-+ if (bh || (err != ERR_BAD_DX_DIR))
-+ return bh;
-+ dxtrace(printk("ext3_find_entry: dx failed, falling back\n"));
-+ }
-+#endif
- nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
-- start = dir->u.ext3_i.i_dir_start_lookup;
-+ start = EXT3_I(dir)->i_dir_start_lookup;
- if (start >= nblocks)
- start = 0;
- block = start;
-@@ -165,7 +830,7 @@
- i = search_dirblock(bh, dir, dentry,
- block << EXT3_BLOCK_SIZE_BITS(sb), res_dir);
- if (i == 1) {
-- dir->u.ext3_i.i_dir_start_lookup = block;
-+ EXT3_I(dir)->i_dir_start_lookup = block;
- ret = bh;
- goto cleanup_and_exit;
- } else {
-@@ -196,6 +861,66 @@
- return ret;
- }
-
-+#ifdef CONFIG_EXT3_INDEX
-+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-+ struct ext3_dir_entry_2 **res_dir, int *err)
-+{
-+ struct super_block * sb;
-+ struct dx_hash_info hinfo;
-+ u32 hash;
-+ struct dx_frame frames[2], *frame;
-+ struct ext3_dir_entry_2 *de, *top;
-+ struct buffer_head *bh;
-+ unsigned long block;
-+ int retval;
-+ int namelen = dentry->d_name.len;
-+ const u8 *name = dentry->d_name.name;
-+ struct inode *dir = dentry->d_parent->d_inode;
-+
-+ sb = dir->i_sb;
-+ if (!(frame = dx_probe (dentry, 0, &hinfo, frames, err)))
-+ return NULL;
-+ hash = hinfo.hash;
-+ do {
-+ block = dx_get_block(frame->at);
-+ if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
-+ goto errout;
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_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 errout;
-+ }
-+ *res_dir = de;
-+ dx_release (frames);
-+ return bh;
-+ }
-+ brelse (bh);
-+ /* Check to see if we should continue to search */
-+ retval = ext3_htree_next_block(dir, hash, frame,
-+ frames, err, 0);
-+ if (retval == -1) {
-+ ext3_warning(sb, __FUNCTION__,
-+ "error reading index page in directory #%lu",
-+ dir->i_ino);
-+ goto errout;
-+ }
-+ } while (retval == 1);
-+
-+ *err = -ENOENT;
-+errout:
-+ dxtrace(printk("%s not found\n", name));
-+ dx_release (frames);
-+ return NULL;
-+}
-+#endif
-+
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
- {
- struct inode * inode;
-@@ -212,8 +937,9 @@
- brelse (bh);
- inode = iget(dir->i_sb, ino);
-
-- if (!inode)
-+ if (!inode) {
- return ERR_PTR(-EACCES);
-+ }
- }
- d_add(dentry, inode);
- return NULL;
-@@ -237,6 +963,301 @@
- de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
- }
-
-+#ifdef CONFIG_EXT3_INDEX
-+static struct ext3_dir_entry_2 *
-+dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
-+{
-+ unsigned rec_len = 0;
-+
-+ while (count--) {
-+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs);
-+ rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ memcpy (to, de, rec_len);
-+ ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len);
-+ de->inode = 0;
-+ map++;
-+ to += rec_len;
-+ }
-+ return (struct ext3_dir_entry_2 *) (to - rec_len);
-+}
-+
-+static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
-+{
-+ struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base;
-+ unsigned rec_len = 0;
-+
-+ prev = to = de;
-+ while ((char*)de < base + size) {
-+ next = (struct ext3_dir_entry_2 *) ((char *) de +
-+ le16_to_cpu(de->rec_len));
-+ if (de->inode && de->name_len) {
-+ rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ if (de > to)
-+ memmove(to, de, rec_len);
-+ to->rec_len = cpu_to_le16(rec_len);
-+ prev = to;
-+ to = (struct ext3_dir_entry_2 *)((char *)to + rec_len);
-+ }
-+ de = next;
-+ }
-+ return prev;
-+}
-+
-+static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
-+ struct buffer_head **bh,struct dx_frame *frame,
-+ struct dx_hash_info *hinfo, int *error)
-+{
-+ unsigned blocksize = dir->i_sb->s_blocksize;
-+ unsigned count, continued;
-+ struct buffer_head *bh2;
-+ u32 newblock;
-+ u32 hash2;
-+ struct dx_map_entry *map;
-+ char *data1 = (*bh)->b_data, *data2;
-+ unsigned split;
-+ struct ext3_dir_entry_2 *de = NULL, *de2;
-+ int err;
-+
-+ bh2 = ext3_append (handle, dir, &newblock, error);
-+ if (!(bh2)) {
-+ brelse(*bh);
-+ *bh = NULL;
-+ goto errout;
-+ }
-+
-+ BUFFER_TRACE(*bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, *bh);
-+ if (err) {
-+ journal_error:
-+ brelse(*bh);
-+ brelse(bh2);
-+ *bh = NULL;
-+ ext3_std_error(dir->i_sb, err);
-+ goto errout;
-+ }
-+ BUFFER_TRACE(frame->bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, frame->bh);
-+ if (err)
-+ goto journal_error;
-+
-+ data2 = bh2->b_data;
-+
-+ /* create map in the end of data2 block */
-+ map = (struct dx_map_entry *) (data2 + blocksize);
-+ count = dx_make_map ((struct ext3_dir_entry_2 *) data1,
-+ blocksize, hinfo, map);
-+ map -= count;
-+ 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_move_dirents(data1, data2, map + split, count - split);
-+ de = dx_pack_dirents(data1,blocksize);
-+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
-+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
-+
-+ /* Which block gets the new entry? */
-+ if (hinfo->hash >= hash2)
-+ {
-+ swap(*bh, bh2);
-+ de = de2;
-+ }
-+ dx_insert_block (frame, hash2 + continued, newblock);
-+ err = ext3_journal_dirty_metadata (handle, bh2);
-+ if (err)
-+ goto journal_error;
-+ err = ext3_journal_dirty_metadata (handle, frame->bh);
-+ if (err)
-+ goto journal_error;
-+ brelse (bh2);
-+ dxtrace(dx_show_index ("frame", frame->entries));
-+errout:
-+ return de;
-+}
-+#endif
-+
-+
-+/*
-+ * Add a new entry into a directory (leaf) block. If de is non-NULL,
-+ * it points to a directory entry which is guaranteed to be large
-+ * enough for new directory entry. If de is NULL, then
-+ * add_dirent_to_buf will attempt search the directory block for
-+ * space. It will return -ENOSPC if no space is available, and -EIO
-+ * and -EEXIST if directory entry already exists.
-+ *
-+ * NOTE! bh is NOT released in the case where ENOSPC is returned. In
-+ * all other cases bh is released.
-+ */
-+static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
-+ struct inode *inode, struct ext3_dir_entry_2 *de,
-+ struct buffer_head * bh)
-+{
-+ struct inode *dir = dentry->d_parent->d_inode;
-+ const char *name = dentry->d_name.name;
-+ int namelen = dentry->d_name.len;
-+ unsigned long offset = 0;
-+ unsigned short reclen;
-+ int nlen, rlen, err;
-+ char *top;
-+
-+ reclen = EXT3_DIR_REC_LEN(namelen);
-+ if (!de) {
-+ de = (struct ext3_dir_entry_2 *)bh->b_data;
-+ top = bh->b_data + dir->i_sb->s_blocksize - reclen;
-+ while ((char *) de <= top) {
-+ if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
-+ bh, offset)) {
-+ brelse (bh);
-+ return -EIO;
-+ }
-+ if (ext3_match (namelen, name, de)) {
-+ brelse (bh);
-+ return -EEXIST;
-+ }
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ if ((de->inode? rlen - nlen: rlen) >= reclen)
-+ break;
-+ de = (struct ext3_dir_entry_2 *)((char *)de + rlen);
-+ offset += rlen;
-+ }
-+ if ((char *) de > top)
-+ return -ENOSPC;
-+ }
-+ BUFFER_TRACE(bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, bh);
-+ if (err) {
-+ ext3_std_error(dir->i_sb, err);
-+ brelse(bh);
-+ return err;
-+ }
-+
-+ /* By now the buffer is marked for journaling */
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ if (de->inode) {
-+ struct ext3_dir_entry_2 *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_update_dx_flag(dir);
-+ dir->i_version = ++event;
-+ ext3_mark_inode_dirty(handle, dir);
-+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-+ err = ext3_journal_dirty_metadata(handle, bh);
-+ if (err)
-+ ext3_std_error(dir->i_sb, err);
-+ brelse(bh);
-+ return 0;
-+}
-+
-+#ifdef CONFIG_EXT3_INDEX
-+/*
-+ * This converts a one block unindexed directory to a 3 block indexed
-+ * directory, and adds the dentry to the indexed directory.
-+ */
-+static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
-+ struct inode *inode, struct buffer_head *bh)
-+{
-+ struct inode *dir = dentry->d_parent->d_inode;
-+ const char *name = dentry->d_name.name;
-+ int namelen = dentry->d_name.len;
-+ struct buffer_head *bh2;
-+ struct dx_root *root;
-+ struct dx_frame frames[2], *frame;
-+ struct dx_entry *entries;
-+ struct ext3_dir_entry_2 *de, *de2;
-+ char *data1, *top;
-+ unsigned len;
-+ int retval;
-+ unsigned blocksize;
-+ struct dx_hash_info hinfo;
-+ u32 block;
-+
-+ blocksize = dir->i_sb->s_blocksize;
-+ dxtrace(printk("Creating index\n"));
-+ retval = ext3_journal_get_write_access(handle, bh);
-+ if (retval) {
-+ ext3_std_error(dir->i_sb, retval);
-+ brelse(bh);
-+ return retval;
-+ }
-+ root = (struct dx_root *) bh->b_data;
-+
-+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
-+ bh2 = ext3_append (handle, dir, &block, &retval);
-+ if (!(bh2)) {
-+ brelse(bh);
-+ return retval;
-+ }
-+ data1 = bh2->b_data;
-+
-+ /* The 0th block becomes the root, move the dirents out */
-+ de = (struct ext3_dir_entry_2 *)&root->dotdot;
-+ de = (struct ext3_dir_entry_2 *)((char *)de + le16_to_cpu(de->rec_len));
-+ len = ((char *) root) + blocksize - (char *) de;
-+ memcpy (data1, de, len);
-+ de = (struct ext3_dir_entry_2 *) 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 = (struct ext3_dir_entry_2 *) (&root->dotdot);
-+ 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);
-+ root->info.hash_version = dir->i_sb->u.ext3_sb.s_def_hash_version;
-+ 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 */
-+ hinfo.hash_version = root->info.hash_version;
-+ hinfo.seed = dir->i_sb->u.ext3_sb.s_hash_seed;
-+ ext3fs_dirhash(name, namelen, &hinfo);
-+ frame = frames;
-+ frame->entries = entries;
-+ frame->at = entries;
-+ frame->bh = bh;
-+ bh = bh2;
-+ de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
-+ dx_release (frames);
-+ if (!(de))
-+ return retval;
-+
-+ return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+}
-+#endif
-+
- /*
- * ext3_add_entry()
- *
-@@ -247,127 +1268,198 @@
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
--
--/*
-- * 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)
- {
- struct inode *dir = dentry->d_parent->d_inode;
-- 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 ext3_dir_entry_2 *de;
- struct super_block * sb;
- int retval;
-+#ifdef CONFIG_EXT3_INDEX
-+ int dx_fallback=0;
-+#endif
-+ unsigned blocksize;
-+ unsigned nlen, rlen;
-+ u32 block, blocks;
-
- sb = dir->i_sb;
--
-- if (!namelen)
-+ blocksize = sb->s_blocksize;
-+ if (!dentry->d_name.len)
- return -EINVAL;
-- bh = ext3_bread (handle, dir, 0, 0, &retval);
-+#ifdef CONFIG_EXT3_INDEX
-+ if (is_dx(dir)) {
-+ retval = ext3_dx_add_entry(handle, dentry, inode);
-+ if (!retval || (retval != ERR_BAD_DX_DIR))
-+ return retval;
-+ EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL;
-+ dx_fallback++;
-+ ext3_mark_inode_dirty(handle, dir);
-+ }
-+#endif
-+ blocks = dir->i_size >> sb->s_blocksize_bits;
-+ for (block = 0, offset = 0; block < blocks; block++) {
-+ bh = ext3_bread(handle, dir, block, 0, &retval);
-+ if(!bh)
-+ return retval;
-+ retval = add_dirent_to_buf(handle, dentry, inode, 0, bh);
-+ if (retval != -ENOSPC)
-+ return retval;
-+
-+#ifdef CONFIG_EXT3_INDEX
-+ if (blocks == 1 && !dx_fallback &&
-+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
-+ return make_indexed_dir(handle, dentry, inode, bh);
-+#endif
-+ brelse(bh);
-+ }
-+ bh = ext3_append(handle, dir, &block, &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;
-- }
-+ de->inode = 0;
-+ de->rec_len = cpu_to_le16(rlen = blocksize);
-+ nlen = 0;
-+ return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+}
-
-- ext3_debug ("creating next block\n");
-+#ifdef CONFIG_EXT3_INDEX
-+/*
-+ * Returns 0 for success, or a negative error value
-+ */
-+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
-+ struct inode *inode)
-+{
-+ struct dx_frame frames[2], *frame;
-+ struct dx_entry *entries, *at;
-+ struct dx_hash_info hinfo;
-+ struct buffer_head * bh;
-+ struct inode *dir = dentry->d_parent->d_inode;
-+ struct super_block * sb = dir->i_sb;
-+ struct ext3_dir_entry_2 *de;
-+ int err;
-
-- 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);
-- } else {
-+ frame = dx_probe(dentry, 0, &hinfo, frames, &err);
-+ if (!frame)
-+ return err;
-+ entries = frame->entries;
-+ at = frame->at;
-
-- ext3_debug ("skipping to next block\n");
-+ if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
-+ goto cleanup;
-
-- de = (struct ext3_dir_entry_2 *) bh->b_data;
-- }
-- }
-- 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;
-+ BUFFER_TRACE(bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, bh);
-+ if (err)
-+ goto journal_error;
-+
-+ err = add_dirent_to_buf(handle, dentry, inode, 0, bh);
-+ if (err != -ENOSPC) {
-+ bh = 0;
-+ goto cleanup;
-+ }
-+
-+ /* 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);
-+ int levels = frame - frames;
-+ struct dx_entry *entries2;
-+ struct dx_node *node2;
-+ struct buffer_head *bh2;
-+
-+ if (levels && (dx_get_count(frames->entries) ==
-+ dx_get_limit(frames->entries))) {
-+ ext3_warning(sb, __FUNCTION__,
-+ "Directory index full!\n");
-+ err = -ENOSPC;
-+ goto cleanup;
- }
-- 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;
-+ bh2 = ext3_append (handle, dir, &newblock, &err);
-+ if (!(bh2))
-+ goto cleanup;
-+ node2 = (struct dx_node *)(bh2->b_data);
-+ entries2 = node2->entries;
-+ node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
-+ node2->fake.inode = 0;
-+ BUFFER_TRACE(frame->bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, frame->bh);
-+ if (err)
-+ goto journal_error;
-+ 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 */
-+ err = ext3_journal_get_write_access(handle,
-+ frames[0].bh);
-+ if (err)
-+ goto journal_error;
-+
-+ 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);
- }
-- 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;
-- dir->i_version = ++event;
-- ext3_mark_inode_dirty(handle, dir);
-- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-- ext3_journal_dirty_metadata(handle, bh);
-- brelse(bh);
-- return 0;
-+ 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));
-+ err = ext3_journal_dirty_metadata(handle, bh2);
-+ if (err)
-+ goto journal_error;
-+ brelse (bh2);
-+ } else {
-+ 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;
-+ err = ext3_journal_get_write_access(handle,
-+ frame->bh);
-+ if (err)
-+ goto journal_error;
- }
-- offset += le16_to_cpu(de->rec_len);
-- de = (struct ext3_dir_entry_2 *)
-- ((char *) de + le16_to_cpu(de->rec_len));
-+ ext3_journal_dirty_metadata(handle, frames[0].bh);
- }
-- brelse (bh);
-- return -ENOSPC;
-+ de = do_split(handle, dir, &bh, frame, &hinfo, &err);
-+ if (!de)
-+ goto cleanup;
-+ err = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ bh = 0;
-+ goto cleanup;
-+
-+journal_error:
-+ ext3_std_error(dir->i_sb, err);
-+cleanup:
-+ if (bh)
-+ brelse(bh);
-+ dx_release(frames);
-+ return err;
- }
-+#endif
-
- /*
- * ext3_delete_entry deletes a directory entry by merging it with the
-@@ -454,9 +1546,11 @@
- struct inode * inode;
- int err;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -480,9 +1574,11 @@
- struct inode *inode;
- int err;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -508,9 +1604,11 @@
- if (dir->i_nlink >= EXT3_LINK_MAX)
- return -EMLINK;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -522,7 +1620,7 @@
-
- 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_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) {
-@@ -555,21 +1653,19 @@
- inode->i_mode |= S_ISGID;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_entry (handle, dentry, inode);
-- if (err)
-- goto out_no_entry;
-+ if (err) {
-+ inode->i_nlink = 0;
-+ ext3_mark_inode_dirty(handle, inode);
-+ iput (inode);
-+ goto out_stop;
-+ }
- dir->i_nlink++;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
- d_instantiate(dentry, inode);
- out_stop:
- ext3_journal_stop(handle, dir);
- return err;
--
--out_no_entry:
-- inode->i_nlink = 0;
-- ext3_mark_inode_dirty(handle, inode);
-- iput (inode);
-- goto out_stop;
- }
-
- /*
-@@ -656,7 +1752,7 @@
- int err = 0, rc;
-
- lock_super(sb);
-- if (!list_empty(&inode->u.ext3_i.i_orphan))
-+ if (!list_empty(&EXT3_I(inode)->i_orphan))
- goto out_unlock;
-
- /* Orphan handling is only valid for files with data blocks
-@@ -697,7 +1793,7 @@
- * This is safe: on error we're going to ignore the orphan list
- * anyway on the next recovery. */
- if (!err)
-- list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan);
-+ list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
-
- jbd_debug(4, "superblock will point to %ld\n", inode->i_ino);
- jbd_debug(4, "orphan inode %ld will point to %d\n",
-@@ -794,8 +1890,9 @@
- handle_t *handle;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
-- if (IS_ERR(handle))
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- retval = -ENOENT;
- bh = ext3_find_entry (dentry, &de);
-@@ -833,7 +1930,7 @@
- dir->i_nlink--;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- ext3_mark_inode_dirty(handle, inode);
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
-
- end_rmdir:
-@@ -851,8 +1948,9 @@
- handle_t *handle;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
-- if (IS_ERR(handle))
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -879,7 +1977,7 @@
- if (retval)
- goto end_unlink;
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
- inode->i_nlink--;
- if (!inode->i_nlink)
-@@ -905,9 +2003,11 @@
- if (l > dir->i_sb->s_blocksize)
- return -ENAMETOOLONG;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -917,7 +2017,7 @@
- if (IS_ERR(inode))
- goto out_stop;
-
-- if (l > sizeof (inode->u.ext3_i.i_data)) {
-+ if (l > sizeof (EXT3_I(inode)->i_data)) {
- inode->i_op = &page_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext3_aops;
- /*
-@@ -926,8 +2026,12 @@
- * i_size in generic_commit_write().
- */
- err = block_symlink(inode, symname, l);
-- if (err)
-- goto out_no_entry;
-+ if (err) {
-+ ext3_dec_count(handle, inode);
-+ ext3_mark_inode_dirty(handle, inode);
-+ iput (inode);
-+ goto out_stop;
-+ }
- } else {
- inode->i_op = &ext3_fast_symlink_inode_operations;
- memcpy((char*)&inode->u.ext3_i.i_data,symname,l);
-@@ -938,12 +2042,6 @@
- out_stop:
- ext3_journal_stop(handle, dir);
- return err;
--
--out_no_entry:
-- ext3_dec_count(handle, inode);
-- ext3_mark_inode_dirty(handle, inode);
-- iput (inode);
-- goto out_stop;
- }
-
- static int ext3_link (struct dentry * old_dentry,
-@@ -956,12 +2054,15 @@
- if (S_ISDIR(inode->i_mode))
- return -EPERM;
-
-- if (inode->i_nlink >= EXT3_LINK_MAX)
-+ if (inode->i_nlink >= EXT3_LINK_MAX) {
- return -EMLINK;
-+ }
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -994,9 +2095,11 @@
-
- old_bh = new_bh = dir_bh = NULL;
-
-- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2);
-- if (IS_ERR(handle))
-+ 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);
-+ }
-
- if (IS_SYNC(old_dir) || IS_SYNC(new_dir))
- handle->h_sync = 1;
-@@ -1069,14 +2172,37 @@
- /*
- * ok, that's it
- */
-- ext3_delete_entry(handle, old_dir, old_de, old_bh);
-+ if (le32_to_cpu(old_de->inode) != old_inode->i_ino ||
-+ old_de->name_len != old_dentry->d_name.len ||
-+ strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) ||
-+ (retval = ext3_delete_entry(handle, old_dir,
-+ old_de, old_bh)) == -ENOENT) {
-+ /* old_de could have moved from under us during htree split, so
-+ * make sure that we are deleting the right entry. We might
-+ * also be pointing to a stale entry in the unused part of
-+ * old_bh so just checking inum and the name isn't enough. */
-+ struct buffer_head *old_bh2;
-+ struct ext3_dir_entry_2 *old_de2;
-+
-+ old_bh2 = ext3_find_entry(old_dentry, &old_de2);
-+ if (old_bh2) {
-+ retval = ext3_delete_entry(handle, old_dir,
-+ old_de2, old_bh2);
-+ brelse(old_bh2);
-+ }
-+ }
-+ if (retval) {
-+ ext3_warning(old_dir->i_sb, "ext3_rename",
-+ "Deleting old file (%lu), %d, error=%d",
-+ old_dir->i_ino, old_dir->i_nlink, retval);
-+ }
-
- if (new_inode) {
- new_inode->i_nlink--;
- 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_update_dx_flag(old_dir);
- if (dir_bh) {
- BUFFER_TRACE(dir_bh, "get_write_access");
- ext3_journal_get_write_access(handle, dir_bh);
-@@ -1088,7 +2210,7 @@
- new_inode->i_nlink--;
- } else {
- new_dir->i_nlink++;
-- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(new_dir);
- ext3_mark_inode_dirty(handle, new_dir);
- }
- }
-Index: linux-2.4.21-suse/fs/ext3/super.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/super.c 2003-10-29 22:39:14.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/super.c 2003-10-29 23:17:20.000000000 +0300
-@@ -710,6 +710,7 @@
- es->s_mtime = cpu_to_le32(CURRENT_TIME);
- ext3_update_dynamic_rev(sb);
- EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-+
- ext3_commit_super (sb, es, 1);
- if (test_opt (sb, DEBUG))
- printk (KERN_INFO
-@@ -720,6 +721,7 @@
- EXT3_BLOCKS_PER_GROUP(sb),
- EXT3_INODES_PER_GROUP(sb),
- sbi->s_mount_opt);
-+
- printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ",
- bdevname(sb->s_dev));
- if (EXT3_SB(sb)->s_journal->j_inode == NULL) {
-@@ -893,6 +895,7 @@
- return res;
- }
-
-+
- struct super_block * ext3_read_super (struct super_block * sb, void * data,
- int silent)
- {
-@@ -1069,6 +1072,9 @@
- sbi->s_mount_state = le16_to_cpu(es->s_state);
- sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb));
- sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb));
-+ for (i=0; i < 4; i++)
-+ sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
-+ sbi->s_def_hash_version = es->s_def_hash_version;
-
- if (sbi->s_blocks_per_group > blocksize * 8) {
- printk (KERN_ERR
-@@ -1770,6 +1776,7 @@
- unregister_filesystem(&ext3_fs_type);
- }
-
-+EXPORT_SYMBOL(ext3_force_commit);
- EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
-Index: linux-2.4.21-suse/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.21-suse.orig/include/linux/ext3_fs.h 2003-06-14 02:28:25.000000000 +0400
-+++ linux-2.4.21-suse/include/linux/ext3_fs.h 2003-10-29 23:17:20.000000000 +0300
-@@ -40,6 +40,11 @@
- #define EXT3FS_VERSION "2.4-0.9.19"
-
- /*
-+ * Always enable hashed directories
-+ */
-+#define CONFIG_EXT3_INDEX
-+
-+/*
- * Debug code
- */
- #ifdef EXT3FS_DEBUG
-@@ -438,8 +443,11 @@
- /*E0*/ __u32 s_journal_inum; /* inode number of journal file */
- __u32 s_journal_dev; /* device number of journal file */
- __u32 s_last_orphan; /* start of list of inodes to delete */
--
--/*EC*/ __u32 s_reserved[197]; /* Padding to the end of the block */
-+ __u32 s_hash_seed[4]; /* HTREE hash seed */
-+ __u8 s_def_hash_version; /* Default hash version to use */
-+ __u8 s_reserved_char_pad;
-+ __u16 s_reserved_word_pad;
-+ __u32 s_reserved[192]; /* Padding to the end of the block */
- };
-
- #ifdef __KERNEL__
-@@ -576,9 +584,46 @@
- #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
-+ */
-+
-+#ifdef CONFIG_EXT3_INDEX
-+ #define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \
-+ EXT3_FEATURE_COMPAT_DIR_INDEX) && \
-+ (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
-+ #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
-+
-+/* Legal values for the dx_root hash_version field: */
-+
-+#define DX_HASH_LEGACY 0
-+#define DX_HASH_HALF_MD4 1
-+#define DX_HASH_TEA 2
-+
-+/* hash info structure used by the directory hash */
-+struct dx_hash_info
-+{
-+ u32 hash;
-+ u32 minor_hash;
-+ int hash_version;
-+ u32 *seed;
-+};
-
- #ifdef __KERNEL__
- /*
-+ * Control parameters used by ext3_htree_next_block
-+ */
-+#define HASH_NB_ALWAYS 1
-+
-+
-+/*
- * Describe an inode's exact location on disk and in memory
- */
- struct ext3_iloc
-@@ -588,6 +633,27 @@
- unsigned long block_group;
- };
-
-+
-+/*
-+ * This structure is stuffed into the struct file's private_data field
-+ * for directories. It is where we put information so that we can do
-+ * readdir operations in hash tree order.
-+ */
-+struct dir_private_info {
-+ rb_root_t root;
-+ rb_node_t *curr_node;
-+ struct fname *extra_fname;
-+ loff_t last_pos;
-+ __u32 curr_hash;
-+ __u32 curr_minor_hash;
-+ __u32 next_hash;
-+};
-+
-+/*
-+ * Special error return code only used by dx_probe() and its callers.
-+ */
-+#define ERR_BAD_DX_DIR -75000
-+
- /*
- * Function prototypes
- */
-@@ -615,11 +681,20 @@
-
- /* dir.c */
- extern int ext3_check_dir_entry(const char *, struct inode *,
-- struct ext3_dir_entry_2 *, struct buffer_head *,
-- unsigned long);
-+ struct ext3_dir_entry_2 *,
-+ struct buffer_head *, unsigned long);
-+extern int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
-+ __u32 minor_hash,
-+ struct ext3_dir_entry_2 *dirent);
-+extern void ext3_htree_free_dir_info(struct dir_private_info *p);
-+
- /* fsync.c */
- extern int ext3_sync_file (struct file *, struct dentry *, int);
-
-+/* hash.c */
-+extern int ext3fs_dirhash(const char *name, int len, struct
-+ dx_hash_info *hinfo);
-+
- /* ialloc.c */
- extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int);
- extern void ext3_free_inode (handle_t *, struct inode *);
-@@ -652,6 +727,8 @@
- /* namei.c */
- extern int ext3_orphan_add(handle_t *, struct inode *);
- extern int ext3_orphan_del(handle_t *, struct inode *);
-+extern int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-+ __u32 start_minor_hash, __u32 *next_hash);
-
- /* super.c */
- extern void ext3_error (struct super_block *, const char *, const char *, ...)
-Index: linux-2.4.21-suse/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.21-suse.orig/include/linux/ext3_fs_sb.h 2003-06-14 02:26:52.000000000 +0400
-+++ linux-2.4.21-suse/include/linux/ext3_fs_sb.h 2003-10-29 23:17:20.000000000 +0300
-@@ -62,6 +62,8 @@
- int s_inode_size;
- int s_first_ino;
- u32 s_next_generation;
-+ u32 s_hash_seed[4];
-+ int s_def_hash_version;
-
- /* Journaling */
- struct inode * s_journal_inode;
-Index: linux-2.4.21-suse/include/linux/ext3_jbd.h
-===================================================================
---- linux-2.4.21-suse.orig/include/linux/ext3_jbd.h 2003-06-14 02:28:25.000000000 +0400
-+++ linux-2.4.21-suse/include/linux/ext3_jbd.h 2003-10-29 23:17:20.000000000 +0300
-@@ -63,6 +63,8 @@
-
- #define EXT3_RESERVE_TRANS_BLOCKS 12U
-
-+#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8
-+
- int
- ext3_mark_iloc_dirty(handle_t *handle,
- struct inode *inode,
-Index: linux-2.4.21-suse/include/linux/rbtree.h
-===================================================================
---- linux-2.4.21-suse.orig/include/linux/rbtree.h 2003-06-14 02:26:51.000000000 +0400
-+++ linux-2.4.21-suse/include/linux/rbtree.h 2003-10-29 23:17:20.000000000 +0300
-@@ -120,6 +120,8 @@
-
- extern void rb_insert_color(rb_node_t *, rb_root_t *);
- extern void rb_erase(rb_node_t *, rb_root_t *);
-+extern rb_node_t *rb_get_first(rb_root_t *root);
-+extern rb_node_t *rb_get_next(rb_node_t *n);
-
- static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link)
- {
-Index: linux-2.4.21-suse/lib/rbtree.c
-===================================================================
---- linux-2.4.21-suse.orig/lib/rbtree.c 2002-08-03 04:39:46.000000000 +0400
-+++ linux-2.4.21-suse/lib/rbtree.c 2003-10-29 23:17:20.000000000 +0300
-@@ -17,6 +17,8 @@
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- linux/lib/rbtree.c
-+
-+ rb_get_first and rb_get_next written by Theodore Ts'o, 9/8/2002
- */
-
- #include <linux/rbtree.h>
-@@ -294,3 +296,43 @@
- __rb_erase_color(child, parent, root);
- }
- EXPORT_SYMBOL(rb_erase);
-+
-+/*
-+ * This function returns the first node (in sort order) of the tree.
-+ */
-+rb_node_t *rb_get_first(rb_root_t *root)
-+{
-+ rb_node_t *n;
-+
-+ n = root->rb_node;
-+ if (!n)
-+ return 0;
-+ while (n->rb_left)
-+ n = n->rb_left;
-+ return n;
-+}
-+EXPORT_SYMBOL(rb_get_first);
-+
-+/*
-+ * Given a node, this function will return the next node in the tree.
-+ */
-+rb_node_t *rb_get_next(rb_node_t *n)
-+{
-+ rb_node_t *parent;
-+
-+ if (n->rb_right) {
-+ n = n->rb_right;
-+ while (n->rb_left)
-+ n = n->rb_left;
-+ return n;
-+ } else {
-+ while ((parent = n->rb_parent)) {
-+ if (n == parent->rb_left)
-+ return parent;
-+ n = parent;
-+ }
-+ return 0;
-+ }
-+}
-+EXPORT_SYMBOL(rb_get_next);
-+
+++ /dev/null
-Index: linux-2.6.0/fs/ext3/super.c
-===================================================================
---- linux-2.6.0.orig/fs/ext3/super.c 2003-12-31 16:00:58.000000000 +0300
-+++ linux-2.6.0/fs/ext3/super.c 2004-01-03 11:25:32.000000000 +0300
-@@ -1068,6 +1068,7 @@
- sbi->s_mount_opt = 0;
- sbi->s_resuid = EXT3_DEF_RESUID;
- sbi->s_resgid = EXT3_DEF_RESGID;
-+ sbi->s_next_generation = jiffies;
-
- blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
- if (!blocksize) {
-Index: linux-2.6.5-sles9/fs/ext3/mballoc.c
+Index: linux-2.6.5-suse/fs/ext3/mballoc.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/mballoc.c 2005-02-17 22:07:57.023609040 +0300
-+++ linux-2.6.5-sles9/fs/ext3/mballoc.c 2005-02-23 01:56:19.101662000 +0300
-@@ -0,0 +1,1835 @@
+--- linux-2.6.5-suse.orig/fs/ext3/mballoc.c 2005-03-02 22:42:20.659360368 +0300
++++ linux-2.6.5-suse/fs/ext3/mballoc.c 2005-03-11 16:13:13.000000000 +0300
+@@ -0,0 +1,1863 @@
+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
++ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+
+/*
+ * TODO:
++ * - bitmap/buddy read-ahead (proposed by Oleg Drokin aka green)
+ * - track min/max extents in each group for better group selection
+ * - is it worthwhile to use buddies directly if req is 2^N blocks?
+ * - mb_mark_used() may allocate chunk right after splitting buddy
+ __u32 mh_magic;
+};
+
-+#define EXT3_MB_MAGIC_V1 0xbaad16fc
++#define EXT3_MB_MAGIC_V1 0xbabd16fd
+
+
+struct ext3_free_extent {
+ struct super_block *ac_sb;
+
+ /* search goals */
-+struct ext3_free_extent ac_g_ex;
++ struct ext3_free_extent ac_g_ex;
+
+ /* the best found extent */
+ struct ext3_free_extent ac_b_ex;
+void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
+void ext3_mb_free_committed_blocks(struct super_block *);
+
-+#define mb_correct_addr_and_bit(bit,addr) \
-+{ \
-+ if ((unsigned long)addr & 1) { \
-+ bit += 8; \
-+ addr--; \
-+ } \
-+ if ((unsigned long)addr & 2) { \
-+ bit += 16; \
-+ addr--; \
-+ addr--; \
-+ } \
++#if BITS_PER_LONG == 64
++#define mb_correct_addr_and_bit(bit,addr) \
++{ \
++ bit += ((unsigned long) addr & 7UL) << 3; \
++ addr = (void *) ((unsigned long) addr & ~7UL); \
+}
++#elif BITS_PER_LONG == 32
++#define mb_correct_addr_and_bit(bit,addr) \
++{ \
++ bit += ((unsigned long) addr & 3UL) << 3; \
++ addr = (void *) ((unsigned long) addr & ~3UL); \
++}
++#else
++#error "how many bits you are?!"
++#endif
+
+static inline int mb_test_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ return test_bit(bit, addr);
++ return ext2_test_bit(bit, addr);
+}
+
+static inline void mb_set_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ __set_bit(bit, addr);
++ ext2_set_bit(bit, addr);
+}
+
+static inline void mb_set_bit_atomic(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ set_bit(bit, addr);
++ ext2_set_bit_atomic(NULL, bit, addr);
+}
+
+static inline void mb_clear_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ __clear_bit(bit, addr);
++ ext2_clear_bit(bit, addr);
+}
+
+static inline void mb_clear_bit_atomic(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ clear_bit(bit, addr);
++ ext2_clear_bit_atomic(NULL, bit, addr);
+}
+
+static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
+ J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
+ J_ASSERT(max != NULL);
+
-+ if (order > e3b->bd_blkbits + 1)
++ if (order > e3b->bd_blkbits + 1) {
++ *max = 0;
+ return NULL;
++ }
+
+ /* at order 0 we see each particular block */
+ *max = 1 << (e3b->bd_blkbits + 3);
+ "can't get block for buddy bitmap\n");
+ goto out;
+ }
-+ if (!buffer_uptodate(e3b->bd_bh)) {
-+ ll_rw_block(READ, 1, &e3b->bd_bh);
-+ wait_on_buffer(e3b->bd_bh);
-+ }
-+ J_ASSERT(buffer_uptodate(e3b->bd_bh));
-+
+ /* load buddy */
+ e3b->bd_bh2 = sb_getblk(sb, sbi->s_buddy_blocks[group]->bb_buddy);
+ if (e3b->bd_bh2 == NULL) {
+ "can't get block for buddy bitmap\n");
+ goto out;
+ }
-+ if (!buffer_uptodate(e3b->bd_bh2)) {
++
++ if (!buffer_uptodate(e3b->bd_bh))
++ ll_rw_block(READ, 1, &e3b->bd_bh);
++ if (!buffer_uptodate(e3b->bd_bh2))
+ ll_rw_block(READ, 1, &e3b->bd_bh2);
-+ wait_on_buffer(e3b->bd_bh2);
-+ }
++
++ wait_on_buffer(e3b->bd_bh);
++ J_ASSERT(buffer_uptodate(e3b->bd_bh));
++ wait_on_buffer(e3b->bd_bh2);
+ J_ASSERT(buffer_uptodate(e3b->bd_bh2));
+
+ e3b->bd_blkbits = sb->s_blocksize_bits;
+ count = 0;
+ for (i = 0; i < max; i++) {
+
-+ if (!mb_test_bit(i, buddy)) {
++ if (mb_test_bit(i, buddy)) {
+ /* only single bit in buddy2 may be 1 */
-+ if (mb_test_bit(i << 1, buddy2))
-+ J_ASSERT(!mb_test_bit((i<<1)+1, buddy2));
-+ else if (mb_test_bit((i << 1) + 1, buddy2))
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
++ if (!mb_test_bit(i << 1, buddy2))
++ J_ASSERT(mb_test_bit((i<<1)+1, buddy2));
++ else if (!mb_test_bit((i << 1) + 1, buddy2))
++ J_ASSERT(mb_test_bit(i << 1, buddy2));
+ continue;
+ }
+
+ /* both bits in buddy2 must be 0 */
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
-+ J_ASSERT(!mb_test_bit((i << 1) + 1, buddy2));
++ J_ASSERT(mb_test_bit(i << 1, buddy2));
++ J_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
+
+ for (j = 0; j < (1 << order); j++) {
+ k = (i * (1 << order)) + j;
-+ J_ASSERT(mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
++ J_ASSERT(!mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
+ }
+ count++;
+ }
+
+ buddy = mb_find_buddy(e3b, 0, &max);
+ for (i = 0; i < max; i++) {
-+ if (mb_test_bit(i, buddy))
++ if (!mb_test_bit(i, buddy))
+ continue;
+ /* check used bits only */
+ for (j = 0; j < e3b->bd_blkbits + 1; j++) {
+ buddy2 = mb_find_buddy(e3b, j, &max2);
+ k = i >> j;
+ J_ASSERT(k < max2);
-+ J_ASSERT(!mb_test_bit(k, buddy2));
++ J_ASSERT(mb_test_bit(k, buddy2));
+ }
+ }
+}
+ bb = EXT3_MB_BUDDY(e3b);
+ while (order <= e3b->bd_blkbits + 1) {
+ block = block >> 1;
-+ if (mb_test_bit(block, bb)) {
++ if (!mb_test_bit(block, bb)) {
+ /* this block is part of buddy of order 'order' */
+ return order;
+ }
+ block = first++;
+ order = 0;
+
-+ J_ASSERT(!mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
-+ mb_set_bit(block, EXT3_MB_BITMAP(e3b));
++ J_ASSERT(mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
++ mb_clear_bit(block, EXT3_MB_BITMAP(e3b));
+ e3b->bd_bd->bb_counters[order]++;
+
+ /* start of the buddy */
+
+ do {
+ block &= ~1UL;
-+ if (!mb_test_bit(block, buddy) ||
-+ !mb_test_bit(block + 1, buddy))
++ if (mb_test_bit(block, buddy) ||
++ mb_test_bit(block + 1, buddy))
+ break;
+
+ /* both the buddies are free, try to coalesce them */
+ break;
+
+ if (order > 0) {
-+ /* for special purposes, we don't clear
++ /* for special purposes, we don't set
+ * free bits in bitmap */
-+ mb_clear_bit(block, buddy);
-+ mb_clear_bit(block + 1, buddy);
++ mb_set_bit(block, buddy);
++ mb_set_bit(block + 1, buddy);
+ }
+ e3b->bd_bd->bb_counters[order]--;
+ e3b->bd_bd->bb_counters[order]--;
+ order++;
+ e3b->bd_bd->bb_counters[order]++;
+
-+ mb_set_bit(block, buddy2);
++ mb_clear_bit(block, buddy2);
+ buddy = buddy2;
+ } while (1);
+ }
+}
+
+static int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
-+ int needed, struct ext3_free_extent *ex)
++ int needed, struct ext3_free_extent *ex)
+{
+ int next, max, ord;
+ void *buddy;
+ buddy = mb_find_buddy(e3b, order, &max);
+ J_ASSERT(buddy);
+ J_ASSERT(block < max);
-+ if (!mb_test_bit(block, buddy)) {
++ if (mb_test_bit(block, buddy)) {
+ ex->fe_len = 0;
+ ex->fe_start = 0;
+ ex->fe_group = 0;
+ break;
+
+ next = (block + 1) * (1 << order);
-+ if (!mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
++ if (mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
+ break;
+
+ ord = mb_find_order_for_block(e3b, next);
+ mlen = 1 << ord;
+ buddy = mb_find_buddy(e3b, ord, &max);
+ J_ASSERT((start >> ord) < max);
-+ mb_clear_bit(start >> ord, buddy);
++ mb_set_bit(start >> ord, buddy);
+ e3b->bd_bd->bb_counters[ord]--;
+ start += mlen;
+ len -= mlen;
+ /* we have to split large buddy */
+ J_ASSERT(ord > 0);
+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_clear_bit(start >> ord, buddy);
++ mb_set_bit(start >> ord, buddy);
+ e3b->bd_bd->bb_counters[ord]--;
+
+ ord--;
+ cur = (start >> ord) & ~1U;
+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_set_bit(cur, buddy);
-+ mb_set_bit(cur + 1, buddy);
++ mb_clear_bit(cur, buddy);
++ mb_clear_bit(cur + 1, buddy);
+ e3b->bd_bd->bb_counters[ord]++;
+ e3b->bd_bd->bb_counters[ord]++;
+ }
+
+ /* now drop all the bits in bitmap */
-+ mb_clear_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
++ mb_set_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
+
+ mb_check_buddy(e3b);
+
+ i = e3b->bd_bd->bb_first_free;
+
+ while (free && ac->ac_status != AC_STATUS_FOUND) {
-+ i = find_next_bit(bitmap, sb->s_blocksize * 8, i);
++ i = ext2_find_next_zero_bit(bitmap, sb->s_blocksize * 8, i);
+ if (i >= sb->s_blocksize * 8) {
+ J_ASSERT(free == 0);
+ break;
+ /*
+ * We aren't lucky definitely
+ */
-+ J_ASSERT(ac.ac_b_ex.fe_len == 0);
+ DQUOT_FREE_BLOCK(inode, *len);
+ *errp = -ENOSPC;
+ block = 0;
+ ext3_error(sb, "ext3_new_block",
+ "Allocating block in system zone - "
+ "block = %u", block);
-+#if AGGRESSIVE_CHECK
-+ for (i = 0; i < ac.ac_b_len; i++)
++#ifdef AGGRESSIVE_CHECK
++ for (i = 0; i < ac.ac_b_ex.fe_len; i++)
+ J_ASSERT(!mb_test_bit(ac.ac_b_ex.fe_start + i, bitmap_bh->b_data));
+#endif
+ mb_set_bits(bitmap_bh->b_data, ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len);
+
+ e3b->bd_bd->bb_first_free = grp->mgd_first_free;
+ e3b->bd_bd->bb_free = grp->mgd_free;
-+ for (i = 0; i < e3b->bd_blkbits; i++) {
++ for (i = 0; i <= e3b->bd_blkbits + 1; i++) {
+ J_ASSERT(i < 16);
+ e3b->bd_bd->bb_counters[i] = grp->mgd_counters[i];
+ }
+ printk(KERN_ERR "EXT3-fs: mbgroup %d corrupted (%d != %d)\n",
+ e3b->bd_group, e3b->bd_bd->bb_free,
+ le16_to_cpu(gdp->bg_free_blocks_count));
-+ BUG();
+ return -ENODATA;
+ }
+
+int ext3_mb_update_descr(struct ext3_buddy *e3b)
+{
+ struct ext3_mb_group_descr *grp;
-+ struct ext3_group_desc *ogdp;
++ struct ext3_group_desc *gdp;
+ struct buffer_head *bh;
+ handle_t *handle;
+ int err, i;
+
+ /* additional checks against old group descriptor */
-+ ogdp = ext3_get_group_desc(e3b->bd_sb, e3b->bd_group, NULL);
-+ if (!ogdp)
++ gdp = ext3_get_group_desc(e3b->bd_sb, e3b->bd_group, NULL);
++ if (!gdp)
+ return -EIO;
-+ if (e3b->bd_bd->bb_free != le16_to_cpu(ogdp->bg_free_blocks_count)) {
++ if (e3b->bd_bd->bb_free != le16_to_cpu(gdp->bg_free_blocks_count)) {
+ printk(KERN_ERR "EXT3-fs: mbgroup %d corrupted (%d != %d)\n",
+ e3b->bd_group, e3b->bd_bd->bb_free,
-+ le16_to_cpu(ogdp->bg_free_blocks_count));
-+ BUG();
++ le16_to_cpu(gdp->bg_free_blocks_count));
+ return -ENODATA;
+ }
+
+ if (err)
+ return err;
+
-+ handle = journal_start(EXT3_SB(e3b->bd_sb)->s_journal, 1);
++ handle = ext3_journal_start(EXT3_SB(e3b->bd_sb)->s_buddy, 1);
+ if (IS_ERR(handle)) {
+ err = PTR_ERR(handle);
+ handle = NULL;
+ goto out;
+ grp->mgd_first_free = e3b->bd_bd->bb_first_free;
+ grp->mgd_free = e3b->bd_bd->bb_free;
-+ for (i = 0; i < e3b->bd_blkbits; i++) {
++ for (i = 0; i <= e3b->bd_blkbits + 1; i++) {
+ J_ASSERT(i < 16);
+ grp->mgd_counters[i] = e3b->bd_bd->bb_counters[i];
+ }
+ struct super_block *sb = e3b->bd_sb;
+ struct buffer_head *bh;
+ int i, count = 0;
-+
-+ memset(e3b->bd_bh->b_data, 0, sb->s_blocksize);
-+ memset(e3b->bd_bh2->b_data, 0, sb->s_blocksize);
++
++ mb_debug("generate buddy for group %d\n", e3b->bd_group);
++ memset(e3b->bd_bh->b_data, 0xff, sb->s_blocksize);
++ memset(e3b->bd_bh2->b_data, 0xff, sb->s_blocksize);
+
+ bh = read_block_bitmap(sb, e3b->bd_group);
+ if (bh == NULL)
+ return -EIO;
+
+ /* mb_free_blocks will set real free */
++ e3b->bd_bd->bb_free = 0;
+ e3b->bd_bd->bb_first_free = 1 << 15;
++ /*
++ * if change bb_counters size, don't forget about
++ * ext3_mb_init_backend() -bzzz
++ */
++ memset(e3b->bd_bd->bb_counters, 0,
++ sizeof(unsigned) * (sb->s_blocksize_bits + 2));
+
+ /* loop over the blocks, and create buddies for free ones */
+ for (i = 0; i < sb->s_blocksize * 8; i++) {
+ }
+ db->d_inode->i_flags |= S_IMMUTABLE | S_NOATIME;
+ *created = 1;
-+ printk("EXT3-fs: no buddy file, regenerate\n");
++ mb_debug("no buddy file, regenerate\n");
+ }
+ up(&root->i_sem);
+ sbi->s_buddy = igrab(db->d_inode);
+ len = sbi->s_groups_count * sb->s_blocksize * 2 +
+ buddy_offset * sb->s_blocksize;
+ if (len != i_size_read(sbi->s_buddy)) {
-+ printk("EXT3-fs: wrong i_size (%u != %u), regenerate\n",
-+ (unsigned) len, (unsigned) i_size_read(sbi->s_buddy));
++ if (*created == 0)
++ printk("EXT3-fs: wrong i_size (%u != %u), regenerate\n",
++ (unsigned) len,
++ (unsigned) i_size_read(sbi->s_buddy));
+ *created = 1;
+ }
+
+ for (i = 0; i < buddy_offset; i++) {
+ handle = ext3_journal_start(sbi->s_buddy, MB_CREDITS);
+ if (IS_ERR(handle)) {
-+ printk(KERN_ERR "EXT3-fs: can't start transaction\n");
++ printk(KERN_ERR "EXT3-fs: cant start transaction\n");
+ err = PTR_ERR(handle);
+ goto err_out;
+ }
+
+ bh = ext3_bread(handle, sbi->s_buddy, i, 1, &err);
+ if (bh == NULL) {
-+ printk(KERN_ERR "EXT3-fs: can't getblk grp: %d\n", err);
++ printk(KERN_ERR "EXT3-fs: cant getblk grp: %d\n", err);
+ goto err_out;
+ }
+ hdr = (struct ext3_mb_grp_header *) bh->b_data;
+ err = ext3_journal_get_write_access(handle, bh);
+ if (err)
+ goto err_out;
++ if (*created == 0)
++ printk(KERN_ERR
++ "EXT3-fs: invalid header 0x%x in %d,"
++ "regenerate\n", hdr->mh_magic, i);
+ *created = 1;
-+ printk("EXT3-fs: invalid header %#x in %d regenerate\n",
-+ hdr->mh_magic, i);
+ hdr->mh_magic = EXT3_MB_MAGIC_V1;
+ err = ext3_journal_dirty_metadata(handle, bh);
+ if (err)
+ ext3_journal_stop(handle);
+ }
+
++ /*
++ * if change bb_counters size, don't forget about ext3_mb_generate_buddy()
++ */
+ len = sizeof(struct ext3_buddy_group_blocks);
+ len += sizeof(unsigned) * (sb->s_blocksize_bits + 2);
+ for (i = 0; i < sbi->s_groups_count; i++) {
++
+ sbi->s_buddy_blocks[i] = kmalloc(len, GFP_KERNEL);
+ if (sbi->s_buddy_blocks[i] == NULL) {
-+ printk(KERN_ERR "EXT3-fs: can't allocate buddy mem\n");
++ printk(KERN_ERR "EXT3-fs: cant allocate mem for buddy\n");
+ err = -ENOMEM;
+ goto out2;
+ }
+
+ handle = ext3_journal_start(sbi->s_buddy, MB_CREDITS);
+ if (IS_ERR(handle)) {
-+ printk(KERN_ERR "EXT3-fs: can't start transaction\n");
++ printk(KERN_ERR "EXT3-fs: cant start transaction\n");
+ err = PTR_ERR(handle);
+ goto out2;
+ }
+ block = buddy_offset + i * 2;
+ bh = ext3_getblk(handle, sbi->s_buddy, block, 1, &err);
+ if (bh == NULL) {
-+ printk(KERN_ERR "EXT3-fs: can't getblk bitmap: %d\n",
-+ err);
++ printk(KERN_ERR "EXT3-fs: cant getblk bitmap: %d\n", err);
+ goto out2;
+ }
+ sbi->s_buddy_blocks[i]->bb_bitmap = bh->b_blocknr;
+ block = buddy_offset + i * 2 + 1;
+ bh = ext3_getblk(handle, sbi->s_buddy, block, 1, &err);
+ if (bh == NULL) {
-+ printk(KERN_ERR "EXT3-fs: can't getblk for buddy: %d\n",+ err);
++ printk(KERN_ERR "EXT3-fs: cant getblk for buddy: %d\n", err);
+ goto out2;
+ }
+ sbi->s_buddy_blocks[i]->bb_buddy = bh->b_blocknr;
+ if (err)
+ goto error_return;
+
++#ifdef AGGRESSIVE_CHECK
++ {
++ int i;
++ for (i = 0; i < count; i++)
++ J_ASSERT(mb_test_bit(bit + i, bitmap_bh->b_data));
++ }
++#endif
++ mb_clear_bits(bitmap_bh->b_data, bit, count);
++
++ /* We dirtied the bitmap block */
++ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
++ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++
+ if (metadata) {
+ /* blocks being freed are metadata. these blocks shouldn't
+ * be used until this transaction is committed */
+ mb_free_blocks(&e3b, bit, count);
+ ext3_unlock_group(sb, block_group);
+ }
++
+ spin_lock(sb_bgl_lock(sbi, block_group));
+ gdp->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
+ spin_unlock(sb_bgl_lock(sbi, block_group));
++ percpu_counter_mod(&sbi->s_freeblocks_counter, count);
+
+ ext3_mb_dirty_buddy(&e3b);
+ ext3_mb_release_desc(&e3b);
+
-+ mb_clear_bits(bitmap_bh->b_data, bit, count);
+ *freed = count;
+
-+ /* We dirtied the bitmap block */
-+ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
-+ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
-+
+ /* And the group descriptor block */
+ BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
+ ret = ext3_journal_dirty_metadata(handle, gd_bh);
+ return ret;
+}
+
++
+extern void ext3_free_blocks_old(handle_t *, struct inode *,
+ unsigned long, unsigned long);
+void ext3_free_blocks(handle_t *handle, struct inode * inode,
+ return;
+}
+
-Index: linux-2.6.5-sles9/fs/ext3/super.c
+Index: linux-2.6.5-suse/fs/ext3/super.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/super.c 2005-02-23 01:47:15.291333736 +0300
-+++ linux-2.6.5-sles9/fs/ext3/super.c 2005-02-23 01:48:54.515249408 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/super.c 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/super.c 2005-02-26 18:40:26.000000000 +0300
@@ -389,6 +389,7 @@
struct ext3_super_block *es = sbi->s_es;
int i;
+ ext3_mb_release(sb);
- ext3_ext_release(sb);
+ ext3_ext_release(sb);
ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
-@@ -540,6 +541,7 @@
+@@ -543,6 +544,7 @@
Opt_commit, Opt_journal_update, Opt_journal_inum,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_ignore, Opt_barrier, Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
Opt_err, Opt_extents, Opt_extdebug
};
-@@ -587,6 +589,8 @@
+@@ -590,6 +592,8 @@
{Opt_iopen_nopriv, "iopen_nopriv"},
{Opt_extents, "extents"},
{Opt_extdebug, "extdebug"},
{Opt_err, NULL}
};
-@@ -808,6 +812,16 @@
+@@ -811,6 +815,16 @@
case Opt_extdebug:
set_opt (sbi->s_mount_opt, EXTDEBUG);
break;
default:
printk (KERN_ERR
"EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1461,7 +1475,8 @@
+@@ -1464,6 +1478,7 @@
ext3_count_dirs(sb));
- ext3_ext_init(sb);
--
+ ext3_ext_init(sb);
+ ext3_mb_init(sb, needs_recovery);
-+
+
return 0;
- failed_mount3:
-Index: linux-2.6.5-sles9/fs/ext3/Makefile
+Index: linux-2.6.5-suse/fs/ext3/Makefile
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/Makefile 2005-02-23 01:02:37.405434272 +0300
-+++ linux-2.6.5-sles9/fs/ext3/Makefile 2005-02-23 01:48:54.517249104 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/Makefile 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/Makefile 2005-02-26 18:40:26.000000000 +0300
@@ -5,7 +5,7 @@
obj-$(CONFIG_EXT3_FS) += ext3.o
ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
-Index: linux-2.6.5-sles9/fs/ext3/balloc.c
+Index: linux-2.6.5-suse/fs/ext3/balloc.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/balloc.c 2004-11-03 08:36:51.000000000 +0300
-+++ linux-2.6.5-sles9/fs/ext3/balloc.c 2005-02-23 01:48:54.520248648 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/balloc.c 2005-02-02 00:55:47.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/balloc.c 2005-02-26 18:40:26.000000000 +0300
@@ -78,7 +78,7 @@
*
* Return buffer_head on success or NULL in case of failure.
unsigned long goal, int *errp)
{
struct buffer_head *bitmap_bh = NULL;
-Index: linux-2.6.5-sles9/fs/ext3/namei.c
+Index: linux-2.6.5-suse/fs/ext3/namei.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/namei.c 2005-02-23 01:01:46.551165296 +0300
-+++ linux-2.6.5-sles9/fs/ext3/namei.c 2005-02-23 01:48:54.523248192 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/namei.c 2005-02-26 18:40:19.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/namei.c 2005-02-26 18:40:26.000000000 +0300
@@ -1640,7 +1640,7 @@
* If the create succeeds, we fill in the inode information
* with d_instantiate().
struct nameidata *nd)
{
handle_t *handle;
-Index: linux-2.6.5-sles9/fs/ext3/inode.c
+Index: linux-2.6.5-suse/fs/ext3/inode.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/inode.c 2005-02-23 01:02:37.404434424 +0300
-+++ linux-2.6.5-sles9/fs/ext3/inode.c 2005-02-23 01:48:54.529247280 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/inode.c 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/inode.c 2005-02-26 18:40:26.000000000 +0300
@@ -572,7 +572,7 @@
ext3_journal_forget(handle, branch[i].bh);
}
return err;
}
-@@ -1829,7 +1829,7 @@
+@@ -1830,7 +1830,7 @@
}
}
}
/**
-@@ -2000,7 +2000,7 @@
+@@ -2001,7 +2001,7 @@
ext3_journal_test_restart(handle, inode);
}
if (parent_bh) {
/*
-Index: linux-2.6.5-sles9/fs/ext3/extents.c
+Index: linux-2.6.5-suse/fs/ext3/extents.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/extents.c 2005-02-23 01:02:37.396435640 +0300
-+++ linux-2.6.5-sles9/fs/ext3/extents.c 2005-02-23 01:48:54.533246672 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/extents.c 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/extents.c 2005-02-26 18:40:26.000000000 +0300
@@ -774,7 +774,7 @@
for (i = 0; i < depth; i++) {
if (!ablocks[i])
} else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
printk("strange request: removal %lu-%lu from %u:%u\n",
from, to, ex->ee_block, ex->ee_len);
-Index: linux-2.6.5-sles9/fs/ext3/xattr.c
+Index: linux-2.6.5-suse/fs/ext3/xattr.c
===================================================================
---- linux-2.6.5-sles9.orig/fs/ext3/xattr.c 2005-02-23 01:01:52.387278072 +0300
-+++ linux-2.6.5-sles9/fs/ext3/xattr.c 2005-02-23 01:48:54.537246064 +0300
+--- linux-2.6.5-suse.orig/fs/ext3/xattr.c 2005-02-26 18:40:22.000000000 +0300
++++ linux-2.6.5-suse/fs/ext3/xattr.c 2005-02-26 18:40:26.000000000 +0300
@@ -1366,7 +1366,7 @@
new_bh = sb_getblk(sb, block);
if (!new_bh) {
get_bh(bh);
ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
} else {
-Index: linux-2.6.5-sles9/include/linux/ext3_fs.h
+Index: linux-2.6.5-suse/include/linux/ext3_fs.h
===================================================================
---- linux-2.6.5-sles9.orig/include/linux/ext3_fs.h 2005-02-23 01:02:37.414432904 +0300
-+++ linux-2.6.5-sles9/include/linux/ext3_fs.h 2005-02-23 01:48:54.539245760 +0300
+--- linux-2.6.5-suse.orig/include/linux/ext3_fs.h 2005-02-26 18:40:25.000000000 +0300
++++ linux-2.6.5-suse/include/linux/ext3_fs.h 2005-02-26 18:40:26.000000000 +0300
@@ -57,6 +57,14 @@
#define ext3_debug(f, a...) do {} while (0)
#endif
#define EXT3_MOUNT_IOPEN_NOPRIV 0x80000 /* Make iopen world-readable */
#define EXT3_MOUNT_EXTENTS 0x100000/* Extents support */
#define EXT3_MOUNT_EXTDEBUG 0x200000/* Extents debug */
-+#define EXT3_MOUNT_MBALLOC 0x100000/* Buddy allocation support */
++#define EXT3_MOUNT_MBALLOC 0x400000/* Buddy allocation support */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef clear_opt
#endif /* __KERNEL__ */
#define EXT3_IOC_CREATE_INUM _IOW('f', 5, long)
-Index: linux-2.6.5-sles9/include/linux/ext3_fs_sb.h
+Index: linux-2.6.5-suse/include/linux/ext3_fs_sb.h
===================================================================
---- linux-2.6.5-sles9.orig/include/linux/ext3_fs_sb.h 2005-02-23 01:01:48.242908112 +0300
-+++ linux-2.6.5-sles9/include/linux/ext3_fs_sb.h 2005-02-23 01:48:54.541245456 +0300
+--- linux-2.6.5-suse.orig/include/linux/ext3_fs_sb.h 2005-02-26 18:40:20.000000000 +0300
++++ linux-2.6.5-suse/include/linux/ext3_fs_sb.h 2005-02-26 18:40:26.000000000 +0300
@@ -23,10 +23,30 @@
#define EXT_INCLUDE
#include <linux/blockgroup_lock.h>
+++ /dev/null
-Index: linux-2.6.7/fs/ext3/mballoc.c
-===================================================================
---- linux-2.6.7.orig/fs/ext3/mballoc.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.6.7/fs/ext3/mballoc.c 2004-09-06 12:51:42.000000000 +0400
-@@ -0,0 +1,1428 @@
-+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
-+ * Written by Alex Tomas <alex@clusterfs.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program 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 Licens
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
-+ */
-+
-+
-+/*
-+ * mballoc.c contains the multiblocks allocation routines
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/time.h>
-+#include <linux/fs.h>
-+#include <linux/namei.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/quotaops.h>
-+#include <linux/buffer_head.h>
-+#include <linux/module.h>
-+
-+/*
-+ * TODO:
-+ * - do not scan from the beginning, try to remember first free block
-+ * - mb_mark_used_* may allocate chunk right after splitting buddy
-+ * - special flag to advice allocator to look for requested + N blocks
-+ * this may improve interaction between extents and mballoc
-+ */
-+
-+/*
-+ * with AGRESSIVE_CHECK allocator runs consistency checks over
-+ * structures. this checks slow things down a lot
-+ */
-+#define AGGRESSIVE_CHECK__
-+
-+/*
-+ */
-+#define MB_DEBUG__
-+#ifdef MB_DEBUG
-+#define mb_debug(fmt,a...) printk(fmt, ##a)
-+#else
-+#define mb_debug(fmt,a...)
-+#endif
-+
-+/*
-+ * where to save buddies structures beetween umount/mount (clean case only)
-+ */
-+#define EXT3_BUDDY_FILE ".buddy"
-+
-+/*
-+ * max. number of chunks to be tracked in ext3_free_extent struct
-+ */
-+#define MB_ARR_SIZE 32
-+
-+struct ext3_allocation_context {
-+ struct super_block *ac_sb;
-+
-+ /* search goals */
-+ int ac_g_group;
-+ int ac_g_start;
-+ int ac_g_len;
-+ int ac_g_flags;
-+
-+ /* the best found extent */
-+ int ac_b_group;
-+ int ac_b_start;
-+ int ac_b_len;
-+
-+ /* number of iterations done. we have to track to limit searching */
-+ int ac_repeats;
-+ int ac_groups_scanned;
-+ int ac_status;
-+};
-+
-+#define AC_STATUS_CONTINUE 1
-+#define AC_STATUS_FOUND 2
-+
-+
-+struct ext3_buddy {
-+ void *bd_bitmap;
-+ void *bd_buddy;
-+ int bd_blkbits;
-+ struct buffer_head *bd_bh;
-+ struct buffer_head *bd_bh2;
-+ struct ext3_buddy_group_blocks *bd_bd;
-+ struct super_block *bd_sb;
-+};
-+
-+struct ext3_free_extent {
-+ int fe_start;
-+ int fe_len;
-+ unsigned char fe_orders[MB_ARR_SIZE];
-+ unsigned char fe_nums;
-+ unsigned char fe_back;
-+};
-+
-+#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
-+
-+
-+int ext3_create (struct inode *, struct dentry *, int, struct nameidata *);
-+struct buffer_head * read_block_bitmap(struct super_block *, unsigned int);
-+void ext3_free_blocks_old(handle_t *, struct inode *, unsigned long, unsigned long);
-+int ext3_new_block_old(handle_t *, struct inode *, unsigned long, u32 *, u32 *, int *);
-+int ext3_mb_reserve_blocks(struct super_block *, int);
-+void ext3_mb_release_blocks(struct super_block *, int);
-+void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
-+void ext3_mb_free_committed_blocks(struct super_block *);
-+
-+#define mb_correct_addr_and_bit(bit,addr) \
-+{ \
-+ if ((unsigned) addr & 1) { \
-+ bit += 8; \
-+ addr--; \
-+ } \
-+ if ((unsigned) addr & 2) { \
-+ bit += 16; \
-+ addr--; \
-+ addr--; \
-+ } \
-+}
-+
-+static inline int mb_test_bit(int bit, void *addr)
-+{
-+ mb_correct_addr_and_bit(bit,addr);
-+ return test_bit(bit, addr);
-+}
-+
-+static inline void mb_set_bit(int bit, void *addr)
-+{
-+ mb_correct_addr_and_bit(bit,addr);
-+ set_bit(bit, addr);
-+}
-+
-+static inline void mb_clear_bit(int bit, void *addr)
-+{
-+ mb_correct_addr_and_bit(bit,addr);
-+ clear_bit(bit, addr);
-+}
-+
-+static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
-+{
-+ int i = 1;
-+ void *bb;
-+
-+ J_ASSERT(e3b->bd_bitmap != e3b->bd_buddy);
-+ J_ASSERT(max != NULL);
-+
-+ if (order > e3b->bd_blkbits + 1)
-+ return NULL;
-+
-+ /* at order 0 we see each particular block */
-+ *max = 1 << (e3b->bd_blkbits + 3);
-+ if (order == 0)
-+ return e3b->bd_bitmap;
-+
-+ bb = e3b->bd_buddy;
-+ *max = *max >> 1;
-+ while (i < order) {
-+ bb += 1 << (e3b->bd_blkbits - i);
-+ i++;
-+ *max = *max >> 1;
-+ }
-+ return bb;
-+}
-+
-+static int ext3_mb_load_desc(struct super_block *sb, int group,
-+ struct ext3_buddy *e3b)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+
-+ J_ASSERT(sbi->s_buddy_blocks[group].bb_bitmap);
-+ J_ASSERT(sbi->s_buddy_blocks[group].bb_buddy);
-+
-+ /* load bitmap */
-+ e3b->bd_bh = sb_getblk(sb, sbi->s_buddy_blocks[group].bb_bitmap);
-+ if (e3b->bd_bh == NULL) {
-+ ext3_error(sb, "ext3_mb_load_desc",
-+ "can't get block for buddy bitmap\n");
-+ goto out;
-+ }
-+ if (!buffer_uptodate(e3b->bd_bh)) {
-+ ll_rw_block(READ, 1, &e3b->bd_bh);
-+ wait_on_buffer(e3b->bd_bh);
-+ }
-+ J_ASSERT(buffer_uptodate(e3b->bd_bh));
-+
-+ /* load buddy */
-+ e3b->bd_bh2 = sb_getblk(sb, sbi->s_buddy_blocks[group].bb_buddy);
-+ if (e3b->bd_bh2 == NULL) {
-+ ext3_error(sb, "ext3_mb_load_desc",
-+ "can't get block for buddy bitmap\n");
-+ goto out;
-+ }
-+ if (!buffer_uptodate(e3b->bd_bh2)) {
-+ ll_rw_block(READ, 1, &e3b->bd_bh2);
-+ wait_on_buffer(e3b->bd_bh2);
-+ }
-+ J_ASSERT(buffer_uptodate(e3b->bd_bh2));
-+
-+ e3b->bd_bitmap = e3b->bd_bh->b_data;
-+ e3b->bd_buddy = e3b->bd_bh2->b_data;
-+ e3b->bd_blkbits = sb->s_blocksize_bits;
-+ e3b->bd_bd = sbi->s_buddy_blocks + group;
-+ e3b->bd_sb = sb;
-+
-+ return 0;
-+out:
-+ brelse(e3b->bd_bh);
-+ brelse(e3b->bd_bh2);
-+ e3b->bd_bh = NULL;
-+ e3b->bd_bh2 = NULL;
-+ return -EIO;
-+}
-+
-+static void ext3_mb_dirty_buddy(struct ext3_buddy *e3b)
-+{
-+ mark_buffer_dirty(e3b->bd_bh);
-+ mark_buffer_dirty(e3b->bd_bh2);
-+}
-+
-+static void ext3_mb_release_desc(struct ext3_buddy *e3b)
-+{
-+ brelse(e3b->bd_bh);
-+ brelse(e3b->bd_bh2);
-+}
-+
-+#ifdef AGGRESSIVE_CHECK
-+static void mb_check_buddy(struct ext3_buddy *e3b)
-+{
-+ int order = e3b->bd_blkbits + 1;
-+ int max, max2, i, j, k, count;
-+ void *buddy, *buddy2;
-+
-+ if (!test_opt(e3b->bd_sb, MBALLOC))
-+ return;
-+
-+ while (order > 1) {
-+ buddy = mb_find_buddy(e3b, order, &max);
-+ J_ASSERT(buddy);
-+ buddy2 = mb_find_buddy(e3b, order - 1, &max2);
-+ J_ASSERT(buddy2);
-+ J_ASSERT(buddy != buddy2);
-+ J_ASSERT(max * 2 == max2);
-+
-+ count = 0;
-+ for (i = 0; i < max; i++) {
-+
-+ if (!mb_test_bit(i, buddy)) {
-+ /* only single bit in buddy2 may be 1 */
-+ if (mb_test_bit(i << 1, buddy2))
-+ J_ASSERT(!mb_test_bit((i<<1)+1, buddy2));
-+ else if (mb_test_bit((i << 1) + 1, buddy2))
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
-+ continue;
-+ }
-+
-+ /* both bits in buddy2 must be 0 */
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
-+ J_ASSERT(!mb_test_bit((i << 1) + 1, buddy2));
-+
-+ for (j = 0; j < (1 << order); j++) {
-+ k = (i * (1 << order)) + j;
-+ J_ASSERT(mb_test_bit(k, e3b->bd_bitmap));
-+ }
-+ count++;
-+ }
-+ J_ASSERT(e3b->bd_bd->bb_counters[order] == count);
-+ order--;
-+ }
-+
-+ buddy = mb_find_buddy(e3b, 0, &max);
-+ for (i = 0; i < max; i++) {
-+ if (mb_test_bit(i, buddy))
-+ continue;
-+ /* check used bits only */
-+ for (j = 0; j < e3b->bd_blkbits + 1; j++) {
-+ buddy2 = mb_find_buddy(e3b, j, &max2);
-+ k = i >> j;
-+ J_ASSERT(k < max2);
-+ J_ASSERT(!mb_test_bit(k, buddy2));
-+ }
-+ }
-+}
-+#else
-+#define mb_check_buddy(e3b)
-+#endif
-+
-+static inline void
-+ext3_lock_group(struct super_block *sb, int group)
-+{
-+ spin_lock(&EXT3_SB(sb)->s_buddy_blocks[group].bb_lock);
-+}
-+
-+static inline void
-+ext3_unlock_group(struct super_block *sb, int group)
-+{
-+ spin_unlock(&EXT3_SB(sb)->s_buddy_blocks[group].bb_lock);
-+}
-+
-+static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
-+{
-+ int order = 1;
-+ void *bb;
-+
-+ J_ASSERT(e3b->bd_bitmap != e3b->bd_buddy);
-+ J_ASSERT(block < (1 << (e3b->bd_blkbits + 3)));
-+
-+ bb = e3b->bd_buddy;
-+ while (order <= e3b->bd_blkbits + 1) {
-+ block = block >> 1;
-+ if (mb_test_bit(block, bb)) {
-+ /* this block is part of buddy of order 'order' */
-+ return order;
-+ }
-+ bb += 1 << (e3b->bd_blkbits - order);
-+ order++;
-+ }
-+ return 0;
-+}
-+
-+static inline void mb_clear_bits(void *bm, int cur, int len)
-+{
-+ __u32 *addr;
-+
-+ len = cur + len;
-+ while (cur < len) {
-+ if ((cur & 31) == 0 && (len - cur) >= 32) {
-+ /* fast path: clear whole word at once */
-+ addr = bm + (cur >> 3);
-+ *addr = 0;
-+ cur += 32;
-+ continue;
-+ }
-+ mb_clear_bit(cur, bm);
-+ cur++;
-+ }
-+}
-+
-+static inline void mb_set_bits(void *bm, int cur, int len)
-+{
-+ __u32 *addr;
-+
-+ len = cur + len;
-+ while (cur < len) {
-+ if ((cur & 31) == 0 && (len - cur) >= 32) {
-+ /* fast path: clear whole word at once */
-+ addr = bm + (cur >> 3);
-+ *addr = 0xffffffff;
-+ cur += 32;
-+ continue;
-+ }
-+ mb_set_bit(cur, bm);
-+ cur++;
-+ }
-+}
-+
-+static int mb_free_blocks(struct ext3_buddy *e3b, int first, int count)
-+{
-+ int block, max, order;
-+ void *buddy, *buddy2;
-+
-+ mb_check_buddy(e3b);
-+ while (count-- > 0) {
-+ block = first++;
-+ order = 0;
-+
-+ J_ASSERT(!mb_test_bit(block, e3b->bd_bitmap));
-+ mb_set_bit(block, e3b->bd_bitmap);
-+ e3b->bd_bd->bb_counters[order]++;
-+
-+ /* start of the buddy */
-+ buddy = mb_find_buddy(e3b, order, &max);
-+
-+ do {
-+ block &= ~1UL;
-+ if (!mb_test_bit(block, buddy) ||
-+ !mb_test_bit(block + 1, buddy))
-+ break;
-+
-+ /* both the buddies are free, try to coalesce them */
-+ buddy2 = mb_find_buddy(e3b, order + 1, &max);
-+
-+ if (!buddy2)
-+ break;
-+
-+ if (order > 0) {
-+ /* for special purposes, we don't clear
-+ * free bits in bitmap */
-+ mb_clear_bit(block, buddy);
-+ mb_clear_bit(block + 1, buddy);
-+ }
-+ e3b->bd_bd->bb_counters[order]--;
-+ e3b->bd_bd->bb_counters[order]--;
-+
-+ block = block >> 1;
-+ order++;
-+ e3b->bd_bd->bb_counters[order]++;
-+
-+ mb_set_bit(block, buddy2);
-+ buddy = buddy2;
-+ } while (1);
-+ }
-+ mb_check_buddy(e3b);
-+
-+ return 0;
-+}
-+
-+/*
-+ * returns 1 if out extent is enough to fill needed space
-+ */
-+int mb_make_backward_extent(struct ext3_free_extent *in,
-+ struct ext3_free_extent *out, int needed)
-+{
-+ int i;
-+
-+ J_ASSERT(in);
-+ J_ASSERT(out);
-+ J_ASSERT(in->fe_nums < MB_ARR_SIZE);
-+
-+ out->fe_len = 0;
-+ out->fe_start = in->fe_start + in->fe_len;
-+ out->fe_nums = 0;
-+
-+ /* for single-chunk extent we need not back order
-+ * also, if an extent doesn't fill needed space
-+ * then it makes no sense to try back order becase
-+ * if we select this extent then it'll be use as is */
-+ if (in->fe_nums < 2 || in->fe_len < needed)
-+ return 0;
-+
-+ i = in->fe_nums - 1;
-+ while (i >= 0 && out->fe_len < needed) {
-+ out->fe_len += (1 << in->fe_orders[i]);
-+ out->fe_start -= (1 << in->fe_orders[i]);
-+ i--;
-+ }
-+ /* FIXME: in some situation fe_orders may be too small to hold
-+ * all the buddies */
-+ J_ASSERT(out->fe_len >= needed);
-+
-+ for (i++; i < in->fe_nums; i++)
-+ out->fe_orders[out->fe_nums++] = in->fe_orders[i];
-+ J_ASSERT(out->fe_nums < MB_ARR_SIZE);
-+ out->fe_back = 1;
-+
-+ return 1;
-+}
-+
-+int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
-+ int needed, struct ext3_free_extent *ex)
-+{
-+ int space = needed;
-+ int next, max, ord;
-+ void *buddy;
-+
-+ J_ASSERT(ex != NULL);
-+
-+ ex->fe_nums = 0;
-+ ex->fe_len = 0;
-+
-+ buddy = mb_find_buddy(e3b, order, &max);
-+ J_ASSERT(buddy);
-+ J_ASSERT(block < max);
-+ if (!mb_test_bit(block, buddy))
-+ goto nofree;
-+
-+ if (order == 0) {
-+ /* find actual order */
-+ order = mb_find_order_for_block(e3b, block);
-+ block = block >> order;
-+ }
-+
-+ ex->fe_orders[ex->fe_nums++] = order;
-+ ex->fe_len = 1 << order;
-+ ex->fe_start = block << order;
-+ ex->fe_back = 0;
-+
-+ while ((space = space - (1 << order)) > 0) {
-+
-+ buddy = mb_find_buddy(e3b, order, &max);
-+ J_ASSERT(buddy);
-+
-+ if (block + 1 >= max)
-+ break;
-+
-+ next = (block + 1) * (1 << order);
-+ if (!mb_test_bit(next, e3b->bd_bitmap))
-+ break;
-+
-+ ord = mb_find_order_for_block(e3b, next);
-+
-+ if ((1 << ord) >= needed) {
-+ /* we dont want to coalesce with self-enough buddies */
-+ break;
-+ }
-+ order = ord;
-+ block = next >> order;
-+ ex->fe_len += 1 << order;
-+
-+ if (ex->fe_nums < MB_ARR_SIZE)
-+ ex->fe_orders[ex->fe_nums++] = order;
-+ }
-+
-+nofree:
-+ J_ASSERT(ex->fe_start + ex->fe_len <= (1 << (e3b->bd_blkbits + 3)));
-+ return ex->fe_len;
-+}
-+
-+static int mb_mark_used_backward(struct ext3_buddy *e3b,
-+ struct ext3_free_extent *ex, int len)
-+{
-+ int start = ex->fe_start, len0 = len;
-+ int ord, mlen, max, cur;
-+ void *buddy;
-+
-+ start = ex->fe_start + ex->fe_len - 1;
-+ while (len) {
-+ ord = mb_find_order_for_block(e3b, start);
-+ if (((start >> ord) << ord) == (start - (1 << ord) + 1) &&
-+ len >= (1 << ord)) {
-+ /* the whole chunk may be allocated at once! */
-+ mlen = 1 << ord;
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ J_ASSERT((start >> ord) < max);
-+ mb_clear_bit(start >> ord, buddy);
-+ e3b->bd_bd->bb_counters[ord]--;
-+ start -= mlen;
-+ len -= mlen;
-+ J_ASSERT(len >= 0);
-+ J_ASSERT(start >= 0);
-+ continue;
-+ }
-+
-+ /* we have to split large buddy */
-+ J_ASSERT(ord > 0);
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_clear_bit(start >> ord, buddy);
-+ e3b->bd_bd->bb_counters[ord]--;
-+
-+ ord--;
-+ cur = (start >> ord) & ~1U;
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_set_bit(cur, buddy);
-+ mb_set_bit(cur + 1, buddy);
-+ e3b->bd_bd->bb_counters[ord]++;
-+ e3b->bd_bd->bb_counters[ord]++;
-+ }
-+
-+ /* now drop all the bits in bitmap */
-+ mb_clear_bits(e3b->bd_bitmap, ex->fe_start + ex->fe_len - len0, len0);
-+
-+ mb_check_buddy(e3b);
-+
-+ return 0;
-+}
-+
-+static int mb_mark_used_forward(struct ext3_buddy *e3b,
-+ struct ext3_free_extent *ex, int len)
-+{
-+ int start = ex->fe_start, len0 = len;
-+ int ord, mlen, max, cur;
-+ void *buddy;
-+
-+ while (len) {
-+ ord = mb_find_order_for_block(e3b, start);
-+
-+ if (((start >> ord) << ord) == start && len >= (1 << ord)) {
-+ /* the whole chunk may be allocated at once! */
-+ mlen = 1 << ord;
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ J_ASSERT((start >> ord) < max);
-+ mb_clear_bit(start >> ord, buddy);
-+ e3b->bd_bd->bb_counters[ord]--;
-+ start += mlen;
-+ len -= mlen;
-+ J_ASSERT(len >= 0);
-+ continue;
-+ }
-+
-+ /* we have to split large buddy */
-+ J_ASSERT(ord > 0);
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_clear_bit(start >> ord, buddy);
-+ e3b->bd_bd->bb_counters[ord]--;
-+
-+ ord--;
-+ cur = (start >> ord) & ~1U;
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_set_bit(cur, buddy);
-+ mb_set_bit(cur + 1, buddy);
-+ e3b->bd_bd->bb_counters[ord]++;
-+ e3b->bd_bd->bb_counters[ord]++;
-+ }
-+
-+ /* now drop all the bits in bitmap */
-+ mb_clear_bits(e3b->bd_bitmap, ex->fe_start, len0);
-+
-+ mb_check_buddy(e3b);
-+
-+ return 0;
-+}
-+
-+int inline mb_mark_used(struct ext3_buddy *e3b,
-+ struct ext3_free_extent *ex, int len)
-+{
-+ int err;
-+
-+ J_ASSERT(ex);
-+ if (ex->fe_back == 0)
-+ err = mb_mark_used_forward(e3b, ex, len);
-+ else
-+ err = mb_mark_used_backward(e3b, ex, len);
-+ return err;
-+}
-+
-+int ext3_mb_new_in_group(struct ext3_allocation_context *ac,
-+ struct ext3_buddy *e3b, int group)
-+{
-+ struct super_block *sb = ac->ac_sb;
-+ int err, gorder, max, i;
-+ struct ext3_free_extent curex;
-+
-+ /* let's know order of allocation */
-+ gorder = 0;
-+ while (ac->ac_g_len > (1 << gorder))
-+ gorder++;
-+
-+ if ((ac->ac_g_flags & 1) && ac->ac_g_group == group) {
-+ /* someone asks for space at this specified block
-+ * probably he wants to merge it into existing extent */
-+ if (mb_test_bit(ac->ac_g_start, e3b->bd_bitmap)) {
-+ /* good. at least one block is free */
-+ max = mb_find_extent(e3b, 0, ac->ac_g_start,
-+ ac->ac_g_len, &curex);
-+ max = min(curex.fe_len, ac->ac_g_len);
-+ mb_mark_used(e3b, &curex, max);
-+
-+ ac->ac_b_group = group;
-+ ac->ac_b_start = curex.fe_start;
-+ ac->ac_b_len = max;
-+ ac->ac_status = AC_STATUS_FOUND;
-+ err = 0;
-+ goto out;
-+ }
-+ /* don't try to find goal anymore */
-+ ac->ac_g_flags &= ~1;
-+ }
-+
-+ i = 0;
-+ while (1) {
-+ i = find_next_bit(e3b->bd_bitmap, sb->s_blocksize * 8, i);
-+ if (i >= sb->s_blocksize * 8)
-+ break;
-+
-+ max = mb_find_extent(e3b, 0, i, ac->ac_g_len, &curex);
-+ if (max >= ac->ac_g_len) {
-+ max = min(curex.fe_len, ac->ac_g_len);
-+ mb_mark_used(e3b, &curex, max);
-+
-+ ac->ac_b_group = group;
-+ ac->ac_b_start = curex.fe_start;
-+ ac->ac_b_len = max;
-+ ac->ac_status = AC_STATUS_FOUND;
-+ break;
-+ }
-+ i += max;
-+ }
-+
-+ return 0;
-+
-+out:
-+ return err;
-+}
-+
-+int mb_good_group(struct ext3_allocation_context *ac, int group, int cr)
-+{
-+ struct ext3_group_desc *gdp;
-+ int free_blocks;
-+
-+ gdp = ext3_get_group_desc(ac->ac_sb, group, NULL);
-+ if (!gdp)
-+ return 0;
-+ free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
-+ if (free_blocks == 0)
-+ return 0;
-+
-+ /* someone wants this block very much */
-+ if ((ac->ac_g_flags & 1) && ac->ac_g_group == group)
-+ return 1;
-+
-+ /* FIXME: I'd like to take fragmentation into account here */
-+ if (cr == 0) {
-+ if (free_blocks >= ac->ac_g_len >> 1)
-+ return 1;
-+ } else if (cr == 1) {
-+ if (free_blocks >= ac->ac_g_len >> 2)
-+ return 1;
-+ } else if (cr == 2) {
-+ return 1;
-+ } else {
-+ BUG();
-+ }
-+ return 0;
-+}
-+
-+int ext3_mb_new_blocks(handle_t *handle, struct inode *inode,
-+ unsigned long goal, int *len, int flags, int *errp)
-+{
-+ struct buffer_head *bitmap_bh = NULL;
-+ struct ext3_allocation_context ac;
-+ int i, group, block, cr, err = 0;
-+ struct ext3_group_desc *gdp;
-+ struct ext3_super_block *es;
-+ struct buffer_head *gdp_bh;
-+ struct ext3_sb_info *sbi;
-+ struct super_block *sb;
-+ struct ext3_buddy e3b;
-+
-+ J_ASSERT(len != NULL);
-+ J_ASSERT(*len > 0);
-+
-+ sb = inode->i_sb;
-+ if (!sb) {
-+ printk("ext3_mb_new_nblocks: nonexistent device");
-+ return 0;
-+ }
-+
-+ if (!test_opt(sb, MBALLOC)) {
-+ static int ext3_mballoc_warning = 0;
-+ if (ext3_mballoc_warning == 0) {
-+ printk(KERN_ERR "EXT3-fs: multiblock request with "
-+ "mballoc disabled!\n");
-+ ext3_mballoc_warning++;
-+ }
-+ *len = 1;
-+ err = ext3_new_block_old(handle, inode, goal, NULL,NULL, errp);
-+ return err;
-+ }
-+
-+ ext3_mb_poll_new_transaction(sb, handle);
-+
-+ sbi = EXT3_SB(sb);
-+ es = EXT3_SB(sb)->s_es;
-+
-+ if (!(flags & 2)) {
-+ /* someone asks for non-reserved blocks */
-+ BUG_ON(*len > 1);
-+ err = ext3_mb_reserve_blocks(sb, 1);
-+ if (err) {
-+ *errp = err;
-+ return 0;
-+ }
-+ }
-+
-+ /*
-+ * Check quota for allocation of this blocks.
-+ */
-+ while (*len && DQUOT_ALLOC_BLOCK(inode, *len))
-+ *len -= 1;
-+ if (*len == 0) {
-+ *errp = -EDQUOT;
-+ block = 0;
-+ goto out;
-+ }
-+
-+ /* start searching from the goal */
-+ if (goal < le32_to_cpu(es->s_first_data_block) ||
-+ goal >= le32_to_cpu(es->s_blocks_count))
-+ goal = le32_to_cpu(es->s_first_data_block);
-+ group = (goal - le32_to_cpu(es->s_first_data_block)) /
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ block = ((goal - le32_to_cpu(es->s_first_data_block)) %
-+ EXT3_BLOCKS_PER_GROUP(sb));
-+
-+ /* set up allocation goals */
-+ ac.ac_b_group = ac.ac_b_start = ac.ac_b_len = 0;
-+ ac.ac_status = 0;
-+ ac.ac_groups_scanned = 0;
-+ ac.ac_sb = inode->i_sb;
-+ ac.ac_g_group = group;
-+ ac.ac_g_start = block;
-+ ac.ac_g_len = *len;
-+ ac.ac_g_flags = flags;
-+
-+ /* loop over the groups */
-+ for (cr = 0; cr < 3 && ac.ac_status != AC_STATUS_FOUND; cr++) {
-+ for (i = 0; i < EXT3_SB(sb)->s_groups_count; group++, i++) {
-+ if (group == EXT3_SB(sb)->s_groups_count)
-+ group = 0;
-+
-+ /* check is group good for our criteries */
-+ if (!mb_good_group(&ac, group, cr))
-+ continue;
-+
-+ err = ext3_mb_load_desc(ac.ac_sb, group, &e3b);
-+ if (err)
-+ goto out_err;
-+
-+ ext3_lock_group(sb, group);
-+ if (!mb_good_group(&ac, group, cr)) {
-+ /* someone did allocation from this group */
-+ ext3_unlock_group(sb, group);
-+ ext3_mb_release_desc(&e3b);
-+ continue;
-+ }
-+
-+ err = ext3_mb_new_in_group(&ac, &e3b, group);
-+ ext3_unlock_group(sb, group);
-+ if (ac.ac_status == AC_STATUS_FOUND)
-+ ext3_mb_dirty_buddy(&e3b);
-+ ext3_mb_release_desc(&e3b);
-+ if (err)
-+ goto out_err;
-+ if (ac.ac_status == AC_STATUS_FOUND)
-+ break;
-+ }
-+ }
-+
-+ if (ac.ac_status != AC_STATUS_FOUND) {
-+ /* unfortunately, we can't satisfy this request */
-+ J_ASSERT(ac.ac_b_len == 0);
-+ DQUOT_FREE_BLOCK(inode, *len);
-+ *errp = -ENOSPC;
-+ block = 0;
-+ goto out;
-+ }
-+
-+ /* good news - free block(s) have been found. now it's time
-+ * to mark block(s) in good old journaled bitmap */
-+ block = ac.ac_b_group * EXT3_BLOCKS_PER_GROUP(sb)
-+ + ac.ac_b_start + le32_to_cpu(es->s_first_data_block);
-+
-+ /* we made a desicion, now mark found blocks in good old
-+ * bitmap to be journaled */
-+
-+ ext3_debug("using block group %d(%d)\n",
-+ ac.ac_b_group.group, gdp->bg_free_blocks_count);
-+
-+ bitmap_bh = read_block_bitmap(sb, ac.ac_b_group);
-+ if (!bitmap_bh) {
-+ *errp = -EIO;
-+ goto out_err;
-+ }
-+
-+ err = ext3_journal_get_write_access(handle, bitmap_bh);
-+ if (err) {
-+ *errp = err;
-+ goto out_err;
-+ }
-+
-+ gdp = ext3_get_group_desc(sb, ac.ac_b_group, &gdp_bh);
-+ if (!gdp) {
-+ *errp = -EIO;
-+ goto out_err;
-+ }
-+
-+ err = ext3_journal_get_write_access(handle, gdp_bh);
-+ if (err)
-+ goto out_err;
-+
-+ block = ac.ac_b_start + ac.ac_b_group * EXT3_BLOCKS_PER_GROUP(sb)
-+ + le32_to_cpu(es->s_first_data_block);
-+
-+ if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
-+ block == le32_to_cpu(gdp->bg_inode_bitmap) ||
-+ in_range(block, le32_to_cpu(gdp->bg_inode_table),
-+ EXT3_SB(sb)->s_itb_per_group))
-+ ext3_error(sb, "ext3_new_block",
-+ "Allocating block in system zone - "
-+ "block = %u", block);
-+#if 0
-+ for (i = 0; i < ac.ac_b_len; i++)
-+ J_ASSERT(!mb_test_bit(ac.ac_b_start + i, bitmap_bh->b_data));
-+#endif
-+ mb_set_bits(bitmap_bh->b_data, ac.ac_b_start, ac.ac_b_len);
-+
-+ ext3_lock_group(sb, ac.ac_b_group);
-+ gdp->bg_free_blocks_count =
-+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) -
-+ ac.ac_b_len);
-+ ext3_unlock_group(sb, ac.ac_b_group);
-+ percpu_counter_mod(&sbi->s_freeblocks_counter, -ac.ac_b_len);
-+
-+ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
-+ if (err)
-+ goto out_err;
-+ err = ext3_journal_dirty_metadata(handle, gdp_bh);
-+ if (err)
-+ goto out_err;
-+
-+ sb->s_dirt = 1;
-+ *errp = 0;
-+ brelse(bitmap_bh);
-+
-+ /* drop non-allocated, but dquote'd blocks */
-+ J_ASSERT(*len >= ac.ac_b_len);
-+ DQUOT_FREE_BLOCK(inode, *len - ac.ac_b_len);
-+
-+ *len = ac.ac_b_len;
-+ J_ASSERT(block != 0);
-+ goto out;
-+
-+out_err:
-+ /* if we've already allocated something, roll it back */
-+ if (ac.ac_status == AC_STATUS_FOUND) {
-+ /* FIXME: free blocks here */
-+ }
-+
-+ DQUOT_FREE_BLOCK(inode, *len);
-+ brelse(bitmap_bh);
-+ *errp = err;
-+ block = 0;
-+out:
-+ if (!(flags & 2)) {
-+ /* block wasn't reserved before and we reserved it
-+ * at the beginning of allocation. it doesn't matter
-+ * whether we allocated anything or we failed: time
-+ * to release reservation. NOTE: because I expect
-+ * any multiblock request from delayed allocation
-+ * path only, here is single block always */
-+ ext3_mb_release_blocks(sb, 1);
-+ }
-+ return block;
-+}
-+
-+int ext3_mb_generate_buddy(struct super_block *sb, int group)
-+{
-+ struct buffer_head *bh;
-+ int i, err, count = 0;
-+ struct ext3_buddy e3b;
-+
-+ err = ext3_mb_load_desc(sb, group, &e3b);
-+ if (err)
-+ goto out;
-+ memset(e3b.bd_bh->b_data, 0, sb->s_blocksize);
-+ memset(e3b.bd_bh2->b_data, 0, sb->s_blocksize);
-+
-+ bh = read_block_bitmap(sb, group);
-+ if (bh == NULL) {
-+ err = -EIO;
-+ goto out2;
-+ }
-+
-+ /* loop over the blocks, nad create buddies for free ones */
-+ for (i = 0; i < sb->s_blocksize * 8; i++) {
-+ if (!mb_test_bit(i, (void *) bh->b_data)) {
-+ mb_free_blocks(&e3b, i, 1);
-+ count++;
-+ }
-+ }
-+ brelse(bh);
-+ mb_check_buddy(&e3b);
-+ ext3_mb_dirty_buddy(&e3b);
-+
-+out2:
-+ ext3_mb_release_desc(&e3b);
-+out:
-+ return err;
-+}
-+
-+EXPORT_SYMBOL(ext3_mb_new_blocks);
-+
-+#define MB_CREDITS \
-+ (EXT3_DATA_TRANS_BLOCKS + 3 + EXT3_INDEX_EXTRA_TRANS_BLOCKS + \
-+ 2 * EXT3_QUOTA_INIT_BLOCKS)
-+
-+int ext3_mb_init_backend(struct super_block *sb)
-+{
-+ struct inode *root = sb->s_root->d_inode;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct dentry *db;
-+ tid_t target;
-+ int err, i;
-+
-+ sbi->s_buddy_blocks = kmalloc(sizeof(struct ext3_buddy_group_blocks) *
-+ sbi->s_groups_count, GFP_KERNEL);
-+ if (sbi->s_buddy_blocks == NULL) {
-+ printk("can't allocate mem for buddy maps\n");
-+ return -ENOMEM;
-+ }
-+ memset(sbi->s_buddy_blocks, 0,
-+ sizeof(struct ext3_buddy_group_blocks) * sbi->s_groups_count);
-+ sbi->s_buddy = NULL;
-+
-+ down(&root->i_sem);
-+ db = lookup_one_len(EXT3_BUDDY_FILE, sb->s_root,
-+ strlen(EXT3_BUDDY_FILE));
-+ if (IS_ERR(db)) {
-+ err = PTR_ERR(db);
-+ printk("can't lookup buddy file: %d\n", err);
-+ goto out;
-+ }
-+
-+ if (db->d_inode != NULL) {
-+ sbi->s_buddy = igrab(db->d_inode);
-+ goto map;
-+ }
-+
-+ err = ext3_create(root, db, S_IFREG, NULL);
-+ if (err) {
-+ printk("error while creation buddy file: %d\n", err);
-+ } else {
-+ sbi->s_buddy = igrab(db->d_inode);
-+ }
-+
-+map:
-+ for (i = 0; i < sbi->s_groups_count; i++) {
-+ struct buffer_head *bh = NULL;
-+ handle_t *handle;
-+
-+ handle = ext3_journal_start(sbi->s_buddy, MB_CREDITS);
-+ if (IS_ERR(handle)) {
-+ err = PTR_ERR(handle);
-+ goto out2;
-+ }
-+
-+ /* allocate block for bitmap */
-+ bh = ext3_getblk(handle, sbi->s_buddy, i * 2, 1, &err);
-+ if (bh == NULL) {
-+ printk("can't get block for buddy bitmap: %d\n", err);
-+ goto out2;
-+ }
-+ sbi->s_buddy_blocks[i].bb_bitmap = bh->b_blocknr;
-+ brelse(bh);
-+
-+ /* allocate block for buddy */
-+ bh = ext3_getblk(handle, sbi->s_buddy, i * 2 + 1, 1, &err);
-+ if (bh == NULL) {
-+ printk("can't get block for buddy: %d\n", err);
-+ goto out2;
-+ }
-+ sbi->s_buddy_blocks[i].bb_buddy = bh->b_blocknr;
-+ brelse(bh);
-+ ext3_journal_stop(handle);
-+ spin_lock_init(&sbi->s_buddy_blocks[i].bb_lock);
-+ sbi->s_buddy_blocks[i].bb_md_cur = NULL;
-+ sbi->s_buddy_blocks[i].bb_tid = 0;
-+ }
-+
-+ if (journal_start_commit(sbi->s_journal, &target))
-+ log_wait_commit(sbi->s_journal, target);
-+
-+out2:
-+ dput(db);
-+out:
-+ up(&root->i_sem);
-+ return err;
-+}
-+
-+int ext3_mb_release(struct super_block *sb)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+
-+ if (!test_opt(sb, MBALLOC))
-+ return 0;
-+
-+ /* release freed, non-committed blocks */
-+ spin_lock(&sbi->s_md_lock);
-+ list_splice_init(&sbi->s_closed_transaction,
-+ &sbi->s_committed_transaction);
-+ list_splice_init(&sbi->s_active_transaction,
-+ &sbi->s_committed_transaction);
-+ spin_unlock(&sbi->s_md_lock);
-+ ext3_mb_free_committed_blocks(sb);
-+
-+ if (sbi->s_buddy_blocks)
-+ kfree(sbi->s_buddy_blocks);
-+ if (sbi->s_buddy)
-+ iput(sbi->s_buddy);
-+ if (sbi->s_blocks_reserved)
-+ printk("ext3-fs: %ld blocks being reserved at umount!\n",
-+ sbi->s_blocks_reserved);
-+ return 0;
-+}
-+
-+int ext3_mb_init(struct super_block *sb)
-+{
-+ struct ext3_super_block *es;
-+ int i;
-+
-+ if (!test_opt(sb, MBALLOC))
-+ return 0;
-+
-+ /* init file for buddy data */
-+ clear_opt(EXT3_SB(sb)->s_mount_opt, MBALLOC);
-+ ext3_mb_init_backend(sb);
-+
-+ es = EXT3_SB(sb)->s_es;
-+ for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
-+ ext3_mb_generate_buddy(sb, i);
-+ spin_lock_init(&EXT3_SB(sb)->s_reserve_lock);
-+ spin_lock_init(&EXT3_SB(sb)->s_md_lock);
-+ INIT_LIST_HEAD(&EXT3_SB(sb)->s_active_transaction);
-+ INIT_LIST_HEAD(&EXT3_SB(sb)->s_closed_transaction);
-+ INIT_LIST_HEAD(&EXT3_SB(sb)->s_committed_transaction);
-+ set_opt(EXT3_SB(sb)->s_mount_opt, MBALLOC);
-+ printk("EXT3-fs: mballoc enabled\n");
-+ return 0;
-+}
-+
-+void ext3_mb_free_committed_blocks(struct super_block *sb)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ int err, i, count = 0, count2 = 0;
-+ struct ext3_free_metadata *md;
-+ struct ext3_buddy e3b;
-+
-+ if (list_empty(&sbi->s_committed_transaction))
-+ return;
-+
-+ /* there is committed blocks to be freed yet */
-+ do {
-+ /* get next array of blocks */
-+ md = NULL;
-+ spin_lock(&sbi->s_md_lock);
-+ if (!list_empty(&sbi->s_committed_transaction)) {
-+ md = list_entry(sbi->s_committed_transaction.next,
-+ struct ext3_free_metadata, list);
-+ list_del(&md->list);
-+ }
-+ spin_unlock(&sbi->s_md_lock);
-+
-+ if (md == NULL)
-+ break;
-+
-+ mb_debug("gonna free %u blocks in group %u (0x%p):",
-+ md->num, md->group, md);
-+
-+ err = ext3_mb_load_desc(sb, md->group, &e3b);
-+ BUG_ON(err != 0);
-+
-+ /* there are blocks to put in buddy to make them really free */
-+ count += md->num;
-+ count2++;
-+ ext3_lock_group(sb, md->group);
-+ for (i = 0; i < md->num; i++) {
-+ mb_debug(" %u", md->blocks[i]);
-+ mb_free_blocks(&e3b, md->blocks[i], 1);
-+ }
-+ mb_debug("\n");
-+ ext3_unlock_group(sb, md->group);
-+
-+ kfree(md);
-+ ext3_mb_dirty_buddy(&e3b);
-+ ext3_mb_release_desc(&e3b);
-+
-+ } while (md);
-+ mb_debug("freed %u blocks in %u structures\n", count, count2);
-+}
-+
-+void ext3_mb_poll_new_transaction(struct super_block *sb, handle_t *handle)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+
-+ if (sbi->s_last_transaction == handle->h_transaction->t_tid)
-+ return;
-+
-+ /* new transaction! time to close last one and free blocks for
-+ * committed transaction. we know that only transaction can be
-+ * active, so previos transaction can be being logged and we
-+ * know that transaction before previous is known to be alreade
-+ * logged. this means that now we may free blocks freed in all
-+ * transactions before previous one. hope I'm clear enough ... */
-+
-+ spin_lock(&sbi->s_md_lock);
-+ if (sbi->s_last_transaction != handle->h_transaction->t_tid) {
-+ mb_debug("new transaction %lu, old %lu\n",
-+ (unsigned long) handle->h_transaction->t_tid,
-+ (unsigned long) sbi->s_last_transaction);
-+ list_splice_init(&sbi->s_closed_transaction,
-+ &sbi->s_committed_transaction);
-+ list_splice_init(&sbi->s_active_transaction,
-+ &sbi->s_closed_transaction);
-+ sbi->s_last_transaction = handle->h_transaction->t_tid;
-+ }
-+ spin_unlock(&sbi->s_md_lock);
-+
-+ ext3_mb_free_committed_blocks(sb);
-+}
-+
-+int ext3_mb_free_metadata(handle_t *handle, struct ext3_buddy *e3b,
-+ int group, int block, int count)
-+{
-+ struct ext3_buddy_group_blocks *db = e3b->bd_bd;
-+ struct super_block *sb = e3b->bd_sb;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct ext3_free_metadata *md;
-+ int i;
-+
-+ ext3_lock_group(sb, group);
-+ for (i = 0; i < count; i++) {
-+ md = db->bb_md_cur;
-+ if (md && db->bb_tid != handle->h_transaction->t_tid) {
-+ db->bb_md_cur = NULL;
-+ md = NULL;
-+ }
-+
-+ if (md == NULL) {
-+ ext3_unlock_group(sb, group);
-+ md = kmalloc(sizeof(*md), GFP_KERNEL);
-+ if (md == NULL)
-+ return -ENOMEM;
-+ md->num = 0;
-+ md->group = group;
-+
-+ ext3_lock_group(sb, group);
-+ if (db->bb_md_cur == NULL) {
-+ spin_lock(&sbi->s_md_lock);
-+ list_add(&md->list, &sbi->s_active_transaction);
-+ spin_unlock(&sbi->s_md_lock);
-+ db->bb_md_cur = md;
-+ db->bb_tid = handle->h_transaction->t_tid;
-+ mb_debug("new md 0x%p for group %u\n",
-+ md, md->group);
-+ } else {
-+ kfree(md);
-+ md = db->bb_md_cur;
-+ }
-+ }
-+
-+ BUG_ON(md->num >= EXT3_BB_MAX_BLOCKS);
-+ md->blocks[md->num] = block + i;
-+ md->num++;
-+ if (md->num == EXT3_BB_MAX_BLOCKS) {
-+ /* no more space, put full container on a sb's list */
-+ db->bb_md_cur = NULL;
-+ }
-+ }
-+ ext3_unlock_group(sb, group);
-+ return 0;
-+}
-+
-+void ext3_mb_free_blocks(handle_t *handle, struct inode *inode,
-+ unsigned long block, unsigned long count, int metadata)
-+{
-+ struct buffer_head *bitmap_bh = NULL;
-+ struct ext3_group_desc *gdp;
-+ struct ext3_super_block *es;
-+ unsigned long bit, overflow;
-+ struct buffer_head *gd_bh;
-+ unsigned long block_group;
-+ struct ext3_sb_info *sbi;
-+ struct super_block *sb;
-+ struct ext3_buddy e3b;
-+ int err = 0, ret;
-+
-+ sb = inode->i_sb;
-+ if (!sb) {
-+ printk ("ext3_free_blocks: nonexistent device");
-+ return;
-+ }
-+
-+ ext3_mb_poll_new_transaction(sb, handle);
-+
-+ sbi = EXT3_SB(sb);
-+ es = EXT3_SB(sb)->s_es;
-+ if (block < le32_to_cpu(es->s_first_data_block) ||
-+ block + count < block ||
-+ block + count > le32_to_cpu(es->s_blocks_count)) {
-+ ext3_error (sb, "ext3_free_blocks",
-+ "Freeing blocks not in datazone - "
-+ "block = %lu, count = %lu", block, count);
-+ goto error_return;
-+ }
-+
-+ ext3_debug("freeing block %lu\n", block);
-+
-+do_more:
-+ overflow = 0;
-+ block_group = (block - le32_to_cpu(es->s_first_data_block)) /
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ bit = (block - le32_to_cpu(es->s_first_data_block)) %
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ /*
-+ * Check to see if we are freeing blocks across a group
-+ * boundary.
-+ */
-+ if (bit + count > EXT3_BLOCKS_PER_GROUP(sb)) {
-+ overflow = bit + count - EXT3_BLOCKS_PER_GROUP(sb);
-+ count -= overflow;
-+ }
-+ brelse(bitmap_bh);
-+ bitmap_bh = read_block_bitmap(sb, block_group);
-+ if (!bitmap_bh)
-+ goto error_return;
-+ gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
-+ if (!gdp)
-+ goto error_return;
-+
-+ if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
-+ in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
-+ in_range (block, le32_to_cpu(gdp->bg_inode_table),
-+ EXT3_SB(sb)->s_itb_per_group) ||
-+ in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
-+ EXT3_SB(sb)->s_itb_per_group))
-+ ext3_error (sb, "ext3_free_blocks",
-+ "Freeing blocks in system zones - "
-+ "Block = %lu, count = %lu",
-+ block, count);
-+
-+ BUFFER_TRACE(bitmap_bh, "getting write access");
-+ err = ext3_journal_get_write_access(handle, bitmap_bh);
-+ if (err)
-+ goto error_return;
-+
-+ /*
-+ * We are about to modify some metadata. Call the journal APIs
-+ * to unshare ->b_data if a currently-committing transaction is
-+ * using it
-+ */
-+ BUFFER_TRACE(gd_bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, gd_bh);
-+ if (err)
-+ goto error_return;
-+
-+ err = ext3_mb_load_desc(sb, block_group, &e3b);
-+ if (err)
-+ goto error_return;
-+
-+ if (metadata) {
-+ /* blocks being freed are metadata. these blocks shouldn't
-+ * be used until this transaction is committed */
-+ ext3_mb_free_metadata(handle, &e3b, block_group, bit, count);
-+ } else {
-+ ext3_lock_group(sb, block_group);
-+ mb_free_blocks(&e3b, bit, count);
-+ gdp->bg_free_blocks_count =
-+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
-+ ext3_unlock_group(sb, block_group);
-+ percpu_counter_mod(&sbi->s_freeblocks_counter, count);
-+ }
-+
-+ ext3_mb_dirty_buddy(&e3b);
-+ ext3_mb_release_desc(&e3b);
-+
-+ /* FIXME: undo logic will be implemented later and another way */
-+ mb_clear_bits(bitmap_bh->b_data, bit, count);
-+ DQUOT_FREE_BLOCK(inode, count);
-+
-+ /* We dirtied the bitmap block */
-+ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
-+ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
-+
-+ /* And the group descriptor block */
-+ BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
-+ ret = ext3_journal_dirty_metadata(handle, gd_bh);
-+ if (!err) err = ret;
-+
-+ if (overflow && !err) {
-+ block += count;
-+ count = overflow;
-+ goto do_more;
-+ }
-+ sb->s_dirt = 1;
-+error_return:
-+ brelse(bitmap_bh);
-+ ext3_std_error(sb, err);
-+ return;
-+}
-+
-+int ext3_mb_reserve_blocks(struct super_block *sb, int blocks)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ int free, ret = -ENOSPC;
-+
-+ BUG_ON(blocks < 0);
-+ spin_lock(&sbi->s_reserve_lock);
-+ free = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
-+ if (blocks <= free - sbi->s_blocks_reserved) {
-+ sbi->s_blocks_reserved += blocks;
-+ ret = 0;
-+ }
-+ spin_unlock(&sbi->s_reserve_lock);
-+ return ret;
-+}
-+
-+void ext3_mb_release_blocks(struct super_block *sb, int blocks)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+
-+ BUG_ON(blocks < 0);
-+ spin_lock(&sbi->s_reserve_lock);
-+ sbi->s_blocks_reserved -= blocks;
-+ WARN_ON(sbi->s_blocks_reserved < 0);
-+ if (sbi->s_blocks_reserved < 0)
-+ sbi->s_blocks_reserved = 0;
-+ spin_unlock(&sbi->s_reserve_lock);
-+}
-+
-+int ext3_new_block(handle_t *handle, struct inode *inode,
-+ unsigned long goal, u32 *pc, u32 *pb, int *errp)
-+{
-+ int ret, len;
-+
-+ if (!test_opt(inode->i_sb, MBALLOC)) {
-+ ret = ext3_new_block_old(handle, inode, goal, pc, pb, errp);
-+ goto out;
-+ }
-+ len = 1;
-+ ret = ext3_mb_new_blocks(handle, inode, goal, &len, 0, errp);
-+out:
-+ return ret;
-+}
-+
-+
-+void ext3_free_blocks(handle_t *handle, struct inode * inode,
-+ unsigned long block, unsigned long count, int metadata)
-+{
-+ if (!test_opt(inode->i_sb, MBALLOC))
-+ ext3_free_blocks_old(handle, inode, block, count);
-+ else
-+ ext3_mb_free_blocks(handle, inode, block, count, metadata);
-+ return;
-+}
-+
-Index: linux-2.6.7/fs/ext3/super.c
-===================================================================
---- linux-2.6.7.orig/fs/ext3/super.c 2004-09-03 08:46:59.000000000 +0400
-+++ linux-2.6.7/fs/ext3/super.c 2004-09-03 08:46:59.000000000 +0400
-@@ -392,6 +392,7 @@
- struct ext3_super_block *es = sbi->s_es;
- int i;
-
-+ ext3_mb_release(sb);
- ext3_ext_release(sb);
- ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
-@@ -594,7 +595,7 @@
- Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
- Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
- Opt_iopen, Opt_noiopen, Opt_iopen_nopriv,
-- Opt_ignore, Opt_err, Opt_extents, Opt_extdebug
-+ Opt_ignore, Opt_err, Opt_extents, Opt_extdebug, Opt_mballoc,
- };
-
- static match_table_t tokens = {
-@@ -644,6 +645,7 @@
- {Opt_iopen_nopriv, "iopen_nopriv"},
- {Opt_extents, "extents"},
- {Opt_extdebug, "extdebug"},
-+ {Opt_mballoc, "mballoc"},
- {Opt_err, NULL}
- };
-
-@@ -929,6 +931,9 @@
- case Opt_extdebug:
- set_opt (sbi->s_mount_opt, EXTDEBUG);
- break;
-+ case Opt_mballoc:
-+ set_opt (sbi->s_mount_opt, MBALLOC);
-+ break;
- default:
- printk (KERN_ERR
- "EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1602,7 +1607,8 @@
- ext3_count_dirs(sb));
-
- ext3_ext_init(sb);
--
-+ ext3_mb_init(sb);
-+
- return 0;
-
- failed_mount3:
-Index: linux-2.6.7/fs/ext3/Makefile
-===================================================================
---- linux-2.6.7.orig/fs/ext3/Makefile 2004-09-03 08:46:59.000000000 +0400
-+++ linux-2.6.7/fs/ext3/Makefile 2004-09-03 08:46:59.000000000 +0400
-@@ -5,7 +5,7 @@
- obj-$(CONFIG_EXT3_FS) += ext3.o
-
- ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
-- ioctl.o namei.o super.o symlink.o hash.o extents.o
-+ ioctl.o namei.o super.o symlink.o hash.o extents.o mballoc.o
-
- ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
- ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
-Index: linux-2.6.7/fs/ext3/balloc.c
-===================================================================
---- linux-2.6.7.orig/fs/ext3/balloc.c 2004-08-26 17:11:16.000000000 +0400
-+++ linux-2.6.7/fs/ext3/balloc.c 2004-09-03 08:46:59.000000000 +0400
-@@ -78,7 +78,7 @@
- *
- * Return buffer_head on success or NULL in case of failure.
- */
--static struct buffer_head *
-+struct buffer_head *
- read_block_bitmap(struct super_block *sb, unsigned int block_group)
- {
- struct ext3_group_desc * desc;
-@@ -98,8 +98,8 @@
- }
-
- /* Free given blocks, update quota and i_blocks field */
--void ext3_free_blocks (handle_t *handle, struct inode * inode,
-- unsigned long block, unsigned long count)
-+void ext3_free_blocks_old (handle_t *handle, struct inode * inode,
-+ unsigned long block, unsigned long count)
- {
- struct buffer_head *bitmap_bh = NULL;
- struct buffer_head *gd_bh;
-@@ -474,8 +474,8 @@
- * This function also updates quota and i_blocks field.
- */
- int
--ext3_new_block(handle_t *handle, struct inode *inode, unsigned long goal,
-- u32 *prealloc_count, u32 *prealloc_block, int *errp)
-+ext3_new_block_old(handle_t *handle, struct inode *inode, unsigned long goal,
-+ u32 *prealloc_count, u32 *prealloc_block, int *errp)
- {
- struct buffer_head *bitmap_bh = NULL; /* bh */
- struct buffer_head *gdp_bh; /* bh2 */
-Index: linux-2.6.7/fs/ext3/namei.c
-===================================================================
---- linux-2.6.7.orig/fs/ext3/namei.c 2004-09-03 08:46:59.000000000 +0400
-+++ linux-2.6.7/fs/ext3/namei.c 2004-09-03 08:46:59.000000000 +0400
-@@ -1640,7 +1640,7 @@
- * If the create succeeds, we fill in the inode information
- * with d_instantiate().
- */
--static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
-+int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
- struct nameidata *nd)
- {
- handle_t *handle;
-Index: linux-2.6.7/fs/ext3/inode.c
-===================================================================
---- linux-2.6.7.orig/fs/ext3/inode.c 2004-09-03 08:46:59.000000000 +0400
-+++ linux-2.6.7/fs/ext3/inode.c 2004-09-03 08:46:59.000000000 +0400
-@@ -254,7 +254,7 @@
- ei->i_prealloc_count = 0;
- ei->i_prealloc_block = 0;
- /* Writer: end */
-- ext3_free_blocks (inode, block, total);
-+ ext3_free_blocks (inode, block, total, 1);
- }
- #endif
- }
-@@ -633,7 +633,7 @@
- ext3_journal_forget(handle, branch[i].bh);
- }
- for (i = 0; i < keys; i++)
-- ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1);
-+ ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1, 1);
- return err;
- }
-
-@@ -734,7 +734,7 @@
- if (err == -EAGAIN)
- for (i = 0; i < num; i++)
- ext3_free_blocks(handle, inode,
-- le32_to_cpu(where[i].key), 1);
-+ le32_to_cpu(where[i].key), 1, 1);
- return err;
- }
-
-@@ -1911,7 +1911,7 @@
- }
- }
-
-- ext3_free_blocks(handle, inode, block_to_free, count);
-+ ext3_free_blocks(handle, inode, block_to_free, count, 1);
- }
-
- /**
-@@ -2082,7 +2082,7 @@
- ext3_journal_test_restart(handle, inode);
- }
-
-- ext3_free_blocks(handle, inode, nr, 1);
-+ ext3_free_blocks(handle, inode, nr, 1, 1);
-
- if (parent_bh) {
- /*
-Index: linux-2.6.7/fs/ext3/extents.c
-===================================================================
---- linux-2.6.7.orig/fs/ext3/extents.c 2004-09-03 08:46:59.000000000 +0400
-+++ linux-2.6.7/fs/ext3/extents.c 2004-09-03 08:46:59.000000000 +0400
-@@ -740,7 +740,7 @@
- for (i = 0; i < depth; i++) {
- if (!ablocks[i])
- continue;
-- ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
-+ ext3_free_blocks(handle, tree->inode, ablocks[i], 1, 1);
- }
- }
- kfree(ablocks);
-@@ -1388,7 +1388,7 @@
- path->p_idx->ei_leaf);
- bh = sb_find_get_block(tree->inode->i_sb, path->p_idx->ei_leaf);
- ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
-- ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
-+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1, 1);
- return err;
- }
-
-@@ -1876,10 +1876,12 @@
- int needed = ext3_remove_blocks_credits(tree, ex, from, to);
- handle_t *handle = ext3_journal_start(tree->inode, needed);
- struct buffer_head *bh;
-- int i;
-+ int i, metadata = 0;
-
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-+ if (S_ISDIR(tree->inode->i_mode))
-+ metadata = 1;
- if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
- /* tail removal */
- unsigned long num, start;
-@@ -1891,7 +1893,7 @@
- bh = sb_find_get_block(tree->inode->i_sb, start + i);
- ext3_forget(handle, 0, tree->inode, bh, start + i);
- }
-- ext3_free_blocks(handle, tree->inode, start, num);
-+ ext3_free_blocks(handle, tree->inode, start, num, metadata);
- } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
- printk("strange request: removal %lu-%lu from %u:%u\n",
- from, to, ex->ee_block, ex->ee_len);
-Index: linux-2.6.7/fs/ext3/xattr.c
-===================================================================
---- linux-2.6.7.orig/fs/ext3/xattr.c 2004-09-03 08:46:59.000000000 +0400
-+++ linux-2.6.7/fs/ext3/xattr.c 2004-09-03 08:46:59.000000000 +0400
-@@ -1366,7 +1366,7 @@
- new_bh = sb_getblk(sb, block);
- if (!new_bh) {
- getblk_failed:
-- ext3_free_blocks(handle, inode, block, 1);
-+ ext3_free_blocks(handle, inode, block, 1, 1);
- error = -EIO;
- goto cleanup;
- }
-@@ -1408,7 +1408,7 @@
- if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
- /* Free the old block. */
- ea_bdebug(old_bh, "freeing");
-- ext3_free_blocks(handle, inode, old_bh->b_blocknr, 1);
-+ ext3_free_blocks(handle, inode, old_bh->b_blocknr, 1, 1);
-
- /* ext3_forget() calls bforget() for us, but we
- let our caller release old_bh, so we need to
-@@ -1497,7 +1497,7 @@
- lock_buffer(bh);
- if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
- ext3_xattr_cache_remove(bh);
-- ext3_free_blocks(handle, inode, EXT3_I(inode)->i_file_acl, 1);
-+ ext3_free_blocks(handle, inode, EXT3_I(inode)->i_file_acl, 1, 1);
- get_bh(bh);
- ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
- } else {
-Index: linux-2.6.7/include/linux/ext3_fs.h
-===================================================================
---- linux-2.6.7.orig/include/linux/ext3_fs.h 2004-09-03 08:46:59.000000000 +0400
-+++ linux-2.6.7/include/linux/ext3_fs.h 2004-09-03 08:47:35.000000000 +0400
-@@ -57,6 +57,8 @@
- #define ext3_debug(f, a...) do {} while (0)
- #endif
-
-+#define EXT3_MULTIBLOCK_ALLOCATOR 1
-+
- /*
- * Special inodes numbers
- */
-@@ -335,6 +337,7 @@
- #define EXT3_MOUNT_IOPEN_NOPRIV 0x80000 /* Make iopen world-readable */
- #define EXT3_MOUNT_EXTENTS 0x100000/* Extents support */
- #define EXT3_MOUNT_EXTDEBUG 0x200000/* Extents debug */
-+#define EXT3_MOUNT_MBALLOC 0x400000/* Buddy allocation support */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef clear_opt
-@@ -695,7 +698,7 @@
- extern int ext3_new_block (handle_t *, struct inode *, unsigned long,
- __u32 *, __u32 *, int *);
- extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
-- unsigned long);
-+ unsigned long, int);
- extern unsigned long ext3_count_free_blocks (struct super_block *);
- extern void ext3_check_blocks_bitmap (struct super_block *);
- extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
-Index: linux-2.6.7/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.6.7.orig/include/linux/ext3_fs_sb.h 2004-09-03 08:46:59.000000000 +0400
-+++ linux-2.6.7/include/linux/ext3_fs_sb.h 2004-09-03 08:46:59.000000000 +0400
-@@ -23,9 +23,29 @@
- #define EXT_INCLUDE
- #include <linux/blockgroup_lock.h>
- #include <linux/percpu_counter.h>
-+#include <linux/list.h>
- #endif
- #endif
-
-+#define EXT3_BB_MAX_BLOCKS 30
-+struct ext3_free_metadata {
-+ unsigned short group;
-+ unsigned short num;
-+ unsigned short blocks[EXT3_BB_MAX_BLOCKS];
-+ struct list_head list;
-+};
-+
-+#define EXT3_BB_MAX_ORDER 14
-+
-+struct ext3_buddy_group_blocks {
-+ sector_t bb_bitmap;
-+ sector_t bb_buddy;
-+ spinlock_t bb_lock;
-+ unsigned bb_counters[EXT3_BB_MAX_ORDER];
-+ struct ext3_free_metadata *bb_md_cur;
-+ unsigned long bb_tid;
-+};
-+
- /*
- * third extended-fs super-block data in memory
- */
-@@ -76,6 +96,17 @@
- char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */
- int s_jquota_fmt; /* Format of quota to use */
- #endif
-+
-+ /* for buddy allocator */
-+ struct ext3_buddy_group_blocks *s_buddy_blocks;
-+ struct inode *s_buddy;
-+ long s_blocks_reserved;
-+ spinlock_t s_reserve_lock;
-+ struct list_head s_active_transaction;
-+ struct list_head s_closed_transaction;
-+ struct list_head s_committed_transaction;
-+ spinlock_t s_md_lock;
-+ tid_t s_last_transaction;
- };
-
- #endif /* _LINUX_EXT3_FS_SB */
===================================================================
--- linux-stage.orig/fs/ext3/mballoc.c 2005-02-25 17:28:41.836311072 +0200
+++ linux-stage/fs/ext3/mballoc.c 2005-02-25 17:28:41.859307576 +0200
-@@ -0,0 +1,1847 @@
+@@ -0,0 +1,1860 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+
+/*
+ * TODO:
++ * - bitmap/buddy read-ahead (proposed by Oleg Drokin aka green)
+ * - track min/max extents in each group for better group selection
+ * - is it worthwhile to use buddies directly if req is 2^N blocks?
+ * - mb_mark_used() may allocate chunk right after splitting buddy
+ __u32 mh_magic;
+};
+
-+#define EXT3_MB_MAGIC_V1 0xbaad16fc
++#define EXT3_MB_MAGIC_V1 0xbabd16fd
+
+
+struct ext3_free_extent {
+void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
+void ext3_mb_free_committed_blocks(struct super_block *);
+
-+#define mb_correct_addr_and_bit(bit,addr) \
-+{ \
-+ if ((unsigned long)addr & 1) { \
-+ bit += 8; \
-+ addr--; \
-+ } \
-+ if ((unsigned long)addr & 2) { \
-+ bit += 16; \
-+ addr--; \
-+ addr--; \
-+ } \
++#if BITS_PER_LONG == 64
++#define mb_correct_addr_and_bit(bit,addr) \
++{ \
++ bit += ((unsigned long) addr & 7UL) << 3; \
++ addr = (void *) ((unsigned long) addr & ~7UL); \
+}
++#elif BITS_PER_LONG == 32
++#define mb_correct_addr_and_bit(bit,addr) \
++{ \
++ bit += ((unsigned long) addr & 3UL) << 3; \
++ addr = (void *) ((unsigned long) addr & ~3UL); \
++}
++#else
++#error "how many bits you are?!"
++#endif
+
+static inline int mb_test_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ return test_bit(bit, addr);
++ return ext2_test_bit(bit, addr);
+}
+
+static inline void mb_set_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ __set_bit(bit, addr);
++ ext2_set_bit(bit, addr);
+}
+
+static inline void mb_set_bit_atomic(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ set_bit(bit, addr);
++ ext2_set_bit_atomic(NULL, bit, addr);
+}
+
+static inline void mb_clear_bit(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ __clear_bit(bit, addr);
++ ext2_clear_bit(bit, addr);
+}
+
+static inline void mb_clear_bit_atomic(int bit, void *addr)
+{
+ mb_correct_addr_and_bit(bit,addr);
-+ clear_bit(bit, addr);
++ ext2_clear_bit_atomic(NULL, bit, addr);
+}
+
+static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
+ J_ASSERT(EXT3_MB_BITMAP(e3b) != EXT3_MB_BUDDY(e3b));
+ J_ASSERT(max != NULL);
+
-+ if (order > e3b->bd_blkbits + 1)
++ if (order > e3b->bd_blkbits + 1) {
++ *max = 0;
+ return NULL;
++ }
+
+ /* at order 0 we see each particular block */
+ *max = 1 << (e3b->bd_blkbits + 3);
+ "can't get block for buddy bitmap\n");
+ goto out;
+ }
-+ if (!buffer_uptodate(e3b->bd_bh)) {
-+ ll_rw_block(READ, 1, &e3b->bd_bh);
-+ wait_on_buffer(e3b->bd_bh);
-+ }
-+ J_ASSERT(buffer_uptodate(e3b->bd_bh));
-+
+ /* load buddy */
+ e3b->bd_bh2 = sb_getblk(sb, sbi->s_buddy_blocks[group]->bb_buddy);
+ if (e3b->bd_bh2 == NULL) {
+ "can't get block for buddy bitmap\n");
+ goto out;
+ }
-+ if (!buffer_uptodate(e3b->bd_bh2)) {
++
++ if (!buffer_uptodate(e3b->bd_bh))
++ ll_rw_block(READ, 1, &e3b->bd_bh);
++ if (!buffer_uptodate(e3b->bd_bh2))
+ ll_rw_block(READ, 1, &e3b->bd_bh2);
-+ wait_on_buffer(e3b->bd_bh2);
-+ }
++
++ wait_on_buffer(e3b->bd_bh);
++ J_ASSERT(buffer_uptodate(e3b->bd_bh));
++ wait_on_buffer(e3b->bd_bh2);
+ J_ASSERT(buffer_uptodate(e3b->bd_bh2));
+
+ e3b->bd_blkbits = sb->s_blocksize_bits;
+ count = 0;
+ for (i = 0; i < max; i++) {
+
-+ if (!mb_test_bit(i, buddy)) {
++ if (mb_test_bit(i, buddy)) {
+ /* only single bit in buddy2 may be 1 */
-+ if (mb_test_bit(i << 1, buddy2))
-+ J_ASSERT(!mb_test_bit((i<<1)+1, buddy2));
-+ else if (mb_test_bit((i << 1) + 1, buddy2))
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
++ if (!mb_test_bit(i << 1, buddy2))
++ J_ASSERT(mb_test_bit((i<<1)+1, buddy2));
++ else if (!mb_test_bit((i << 1) + 1, buddy2))
++ J_ASSERT(mb_test_bit(i << 1, buddy2));
+ continue;
+ }
+
+ /* both bits in buddy2 must be 0 */
-+ J_ASSERT(!mb_test_bit(i << 1, buddy2));
-+ J_ASSERT(!mb_test_bit((i << 1) + 1, buddy2));
++ J_ASSERT(mb_test_bit(i << 1, buddy2));
++ J_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
+
+ for (j = 0; j < (1 << order); j++) {
+ k = (i * (1 << order)) + j;
-+ J_ASSERT(mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
++ J_ASSERT(!mb_test_bit(k, EXT3_MB_BITMAP(e3b)));
+ }
+ count++;
+ }
+
+ buddy = mb_find_buddy(e3b, 0, &max);
+ for (i = 0; i < max; i++) {
-+ if (mb_test_bit(i, buddy))
++ if (!mb_test_bit(i, buddy))
+ continue;
+ /* check used bits only */
+ for (j = 0; j < e3b->bd_blkbits + 1; j++) {
+ buddy2 = mb_find_buddy(e3b, j, &max2);
+ k = i >> j;
+ J_ASSERT(k < max2);
-+ J_ASSERT(!mb_test_bit(k, buddy2));
++ J_ASSERT(mb_test_bit(k, buddy2));
+ }
+ }
+}
+ bb = EXT3_MB_BUDDY(e3b);
+ while (order <= e3b->bd_blkbits + 1) {
+ block = block >> 1;
-+ if (mb_test_bit(block, bb)) {
++ if (!mb_test_bit(block, bb)) {
+ /* this block is part of buddy of order 'order' */
+ return order;
+ }
+ block = first++;
+ order = 0;
+
-+ J_ASSERT(!mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
-+ mb_set_bit(block, EXT3_MB_BITMAP(e3b));
++ J_ASSERT(mb_test_bit(block, EXT3_MB_BITMAP(e3b)));
++ mb_clear_bit(block, EXT3_MB_BITMAP(e3b));
+ e3b->bd_bd->bb_counters[order]++;
+
+ /* start of the buddy */
+
+ do {
+ block &= ~1UL;
-+ if (!mb_test_bit(block, buddy) ||
-+ !mb_test_bit(block + 1, buddy))
++ if (mb_test_bit(block, buddy) ||
++ mb_test_bit(block + 1, buddy))
+ break;
+
+ /* both the buddies are free, try to coalesce them */
+ break;
+
+ if (order > 0) {
-+ /* for special purposes, we don't clear
++ /* for special purposes, we don't set
+ * free bits in bitmap */
-+ mb_clear_bit(block, buddy);
-+ mb_clear_bit(block + 1, buddy);
++ mb_set_bit(block, buddy);
++ mb_set_bit(block + 1, buddy);
+ }
+ e3b->bd_bd->bb_counters[order]--;
+ e3b->bd_bd->bb_counters[order]--;
+ order++;
+ e3b->bd_bd->bb_counters[order]++;
+
-+ mb_set_bit(block, buddy2);
++ mb_clear_bit(block, buddy2);
+ buddy = buddy2;
+ } while (1);
+ }
+ buddy = mb_find_buddy(e3b, order, &max);
+ J_ASSERT(buddy);
+ J_ASSERT(block < max);
-+ if (!mb_test_bit(block, buddy)) {
++ if (mb_test_bit(block, buddy)) {
+ ex->fe_len = 0;
+ ex->fe_start = 0;
+ ex->fe_group = 0;
+ break;
+
+ next = (block + 1) * (1 << order);
-+ if (!mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
++ if (mb_test_bit(next, EXT3_MB_BITMAP(e3b)))
+ break;
+
+ ord = mb_find_order_for_block(e3b, next);
+ mlen = 1 << ord;
+ buddy = mb_find_buddy(e3b, ord, &max);
+ J_ASSERT((start >> ord) < max);
-+ mb_clear_bit(start >> ord, buddy);
++ mb_set_bit(start >> ord, buddy);
+ e3b->bd_bd->bb_counters[ord]--;
+ start += mlen;
+ len -= mlen;
+ /* we have to split large buddy */
+ J_ASSERT(ord > 0);
+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_clear_bit(start >> ord, buddy);
++ mb_set_bit(start >> ord, buddy);
+ e3b->bd_bd->bb_counters[ord]--;
+
+ ord--;
+ cur = (start >> ord) & ~1U;
+ buddy = mb_find_buddy(e3b, ord, &max);
-+ mb_set_bit(cur, buddy);
-+ mb_set_bit(cur + 1, buddy);
++ mb_clear_bit(cur, buddy);
++ mb_clear_bit(cur + 1, buddy);
+ e3b->bd_bd->bb_counters[ord]++;
+ e3b->bd_bd->bb_counters[ord]++;
+ }
+
+ /* now drop all the bits in bitmap */
-+ mb_clear_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
++ mb_set_bits(EXT3_MB_BITMAP(e3b), ex->fe_start, len0);
+
+ mb_check_buddy(e3b);
+
+ i = e3b->bd_bd->bb_first_free;
+
+ while (free && ac->ac_status != AC_STATUS_FOUND) {
-+ i = find_next_bit(bitmap, sb->s_blocksize * 8, i);
++ i = ext2_find_next_zero_bit(bitmap, sb->s_blocksize * 8, i);
+ if (i >= sb->s_blocksize * 8) {
+ J_ASSERT(free == 0);
+ break;
+ /*
+ * We aren't lucky definitely
+ */
-+ J_ASSERT(ac.ac_b_ex.fe_len == 0);
+ DQUOT_FREE_BLOCK(inode, *len);
+ *errp = -ENOSPC;
+ block = 0;
+ ext3_error(sb, "ext3_new_block",
+ "Allocating block in system zone - "
+ "block = %u", block);
-+#if AGGRESSIVE_CHECK
-+ for (i = 0; i < ac.ac_b_len; i++)
++#ifdef AGGRESSIVE_CHECK
++ for (i = 0; i < ac.ac_b_ex.fe_len; i++)
+ J_ASSERT(!mb_test_bit(ac.ac_b_ex.fe_start + i, bitmap_bh->b_data));
+#endif
+ mb_set_bits(bitmap_bh->b_data, ac.ac_b_ex.fe_start, ac.ac_b_ex.fe_len);
+
+ e3b->bd_bd->bb_first_free = grp->mgd_first_free;
+ e3b->bd_bd->bb_free = grp->mgd_free;
-+ for (i = 0; i < e3b->bd_blkbits; i++) {
++ for (i = 0; i <= e3b->bd_blkbits + 1; i++) {
+ J_ASSERT(i < 16);
+ e3b->bd_bd->bb_counters[i] = grp->mgd_counters[i];
+ }
+ goto out;
+ grp->mgd_first_free = e3b->bd_bd->bb_first_free;
+ grp->mgd_free = e3b->bd_bd->bb_free;
-+ for (i = 0; i < e3b->bd_blkbits; i++) {
++ for (i = 0; i <= e3b->bd_blkbits + 1; i++) {
+ J_ASSERT(i < 16);
+ grp->mgd_counters[i] = e3b->bd_bd->bb_counters[i];
+ }
+ struct super_block *sb = e3b->bd_sb;
+ struct buffer_head *bh;
+ int i, count = 0;
-+
-+ memset(e3b->bd_bh->b_data, 0, sb->s_blocksize);
-+ memset(e3b->bd_bh2->b_data, 0, sb->s_blocksize);
++
++ mb_debug("generate buddy for group %d\n", e3b->bd_group);
++ memset(e3b->bd_bh->b_data, 0xff, sb->s_blocksize);
++ memset(e3b->bd_bh2->b_data, 0xff, sb->s_blocksize);
+
+ bh = read_block_bitmap(sb, e3b->bd_group);
+ if (bh == NULL)
+ if (err)
+ goto error_return;
+
++#ifdef AGGRESSIVE_CHECK
++ {
++ int i;
++ for (i = 0; i < count; i++)
++ J_ASSERT(mb_test_bit(bit + i, bitmap_bh->b_data));
++ }
++#endif
++ mb_clear_bits(bitmap_bh->b_data, bit, count);
++
++ /* We dirtied the bitmap block */
++ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
++ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
++
+ if (metadata) {
+ /* blocks being freed are metadata. these blocks shouldn't
+ * be used until this transaction is committed */
+ mb_free_blocks(&e3b, bit, count);
+ ext3_unlock_group(sb, block_group);
+ }
++
+ spin_lock(sb_bgl_lock(sbi, block_group));
+ gdp->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
+ spin_unlock(sb_bgl_lock(sbi, block_group));
++ percpu_counter_mod(&sbi->s_freeblocks_counter, count);
+
+ ext3_mb_dirty_buddy(&e3b);
+ ext3_mb_release_desc(&e3b);
+
-+ mb_clear_bits(bitmap_bh->b_data, bit, count);
+ *freed = count;
+
-+ /* We dirtied the bitmap block */
-+ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
-+ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
-+
+ /* And the group descriptor block */
+ BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
+ ret = ext3_journal_dirty_metadata(handle, gd_bh);
+ return ret;
+}
+
-+
+void ext3_free_blocks(handle_t *handle, struct inode * inode,
+ unsigned long block, unsigned long count, int metadata)
+{
+ DQUOT_FREE_BLOCK(inode, freed);
+ return;
+}
-+
Index: linux-stage/fs/ext3/super.c
===================================================================
--- linux-stage.orig/fs/ext3/super.c 2005-02-25 17:27:00.231757312 +0200
int i;
+ ext3_mb_release(sb);
- ext3_ext_release(sb);
+ ext3_ext_release(sb);
ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
@@ -592,7 +593,7 @@
default:
printk (KERN_ERR
"EXT3-fs: Unrecognized mount option \"%s\" "
-@@ -1639,7 +1652,8 @@
+@@ -1639,6 +1652,7 @@
ext3_count_dirs(sb));
- ext3_ext_init(sb);
--
+ ext3_ext_init(sb);
+ ext3_mb_init(sb, needs_recovery);
-+
+
return 0;
- failed_mount3:
Index: linux-stage/fs/ext3/Makefile
===================================================================
--- linux-stage.orig/fs/ext3/Makefile 2005-02-25 17:27:00.228757768 +0200
#define EXT3_MOUNT_EXTDEBUG 0x200000/* Extents debug */
+#define EXT3_MOUNT_MBALLOC 0x400000/* Buddy allocation support */
-
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+ #ifndef _LINUX_EXT2_FS_H
@@ -725,7 +734,7 @@
extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *);
#endif
#include <linux/rbtree.h>
-+#define EXT3_BB_MAX_BLOCKS 30
++#define EXT3_BB_MAX_BLOCKS 30
+struct ext3_free_metadata {
+ unsigned short group;
+ unsigned short num;
+ spinlock_t s_md_lock;
+ tid_t s_last_transaction;
+ int s_mb_factor;
-+
++
+ /* stats for buddy allocator */
+ spinlock_t s_bal_lock;
+ unsigned long s_bal_reqs; /* number of reqs with len > 1 */
+++ /dev/null
-
-Index: linux-2.4.20-rh/fs/ext3/inode.c
-===================================================================
---- linux-2.4.20-rh.orig/fs/ext3/inode.c 2003-09-04 18:01:41.000000000 +0800
-+++ linux-2.4.20-rh/fs/ext3/inode.c 2003-09-04 18:18:54.000000000 +0800
-@@ -27,6 +27,7 @@
- #include <linux/ext3_jbd.h>
- #include <linux/jbd.h>
- #include <linux/locks.h>
-+#include <linux/iobuf.h>
- #include <linux/smp_lock.h>
- #include <linux/highuid.h>
- #include <linux/quotaops.h>
-@@ -743,9 +744,9 @@
- * The BKL may not be held on entry here. Be sure to take it early.
- */
-
--static int ext3_get_block_handle(handle_t *handle, struct inode *inode,
-- long iblock,
-- struct buffer_head *bh_result, int create)
-+static int
-+ext3_get_block_handle(handle_t *handle, struct inode *inode, long iblock,
-+ struct buffer_head *bh_result, int create, int extend_disksize)
- {
- int err = -EIO;
- int offsets[4];
-@@ -825,15 +826,18 @@
- if (err)
- goto cleanup;
-
-- new_size = inode->i_size;
-- /*
-- * This is not racy against ext3_truncate's modification of i_disksize
-- * because VM/VFS ensures that the file cannot be extended while
-- * truncate is in progress. It is racy between multiple parallel
-- * instances of get_block, but we have the BKL.
-- */
-- if (new_size > inode->u.ext3_i.i_disksize)
-- inode->u.ext3_i.i_disksize = new_size;
-+ if (extend_disksize) {
-+ /*
-+ * This is not racy against ext3_truncate's modification of
-+ * i_disksize because VM/VFS ensures that the file cannot be
-+ * extended while truncate is in progress. It is racy between
-+ * multiple parallel instances of get_block, but we have BKL.
-+ */
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+ new_size = inode->i_size;
-+ if (new_size > ei->i_disksize)
-+ ei->i_disksize = new_size;
-+ }
-
- bh_result->b_state |= (1UL << BH_New);
- goto got_it;
-@@ -861,7 +865,38 @@
- handle = ext3_journal_current_handle();
- J_ASSERT(handle != 0);
- }
-- ret = ext3_get_block_handle(handle, inode, iblock, bh_result, create);
-+ ret = ext3_get_block_handle(handle, inode, iblock,
-+ bh_result, create, 1);
-+ return ret;
-+}
-+
-+#define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
-+
-+static int
-+ext3_direct_io_get_block(struct inode *inode, long iblock,
-+ struct buffer_head *bh_result, int create)
-+{
-+ handle_t *handle = journal_current_handle();
-+ int ret = 0;
-+
-+ lock_kernel();
-+ if (handle && handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) {
-+ /*
-+ * Getting low on buffer credits...
-+ */
-+ if (!ext3_journal_extend(handle, DIO_CREDITS)) {
-+ /*
-+ * Couldn't extend the transaction. Start a new one
-+ */
-+ ret = ext3_journal_restart(handle, DIO_CREDITS);
-+ }
-+ }
-+ if (ret == 0)
-+ ret = ext3_get_block_handle(handle, inode, iblock,
-+ bh_result, create, 0);
-+ if (ret == 0)
-+ bh_result->b_size = (1 << inode->i_blkbits);
-+ unlock_kernel();
- return ret;
- }
-
-@@ -879,7 +914,7 @@
- dummy.b_state = 0;
- dummy.b_blocknr = -1000;
- buffer_trace_init(&dummy.b_history);
-- *errp = ext3_get_block_handle(handle, inode, block, &dummy, create);
-+ *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1);
- if (!*errp && buffer_mapped(&dummy)) {
- struct buffer_head *bh;
- bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
-@@ -1387,6 +1422,67 @@
- return journal_try_to_free_buffers(journal, page, wait);
- }
-
-+static int
-+ext3_direct_IO(int rw, struct inode *inode, struct kiobuf *iobuf,
-+ unsigned long blocknr, int blocksize)
-+{
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+ handle_t *handle = NULL;
-+ int ret;
-+ int orphan = 0;
-+ loff_t offset = (loff_t)blocknr << inode->i_blkbits; /* ugh */
-+ ssize_t count = iobuf->length; /* ditto */
-+
-+ if (rw == WRITE) {
-+ loff_t final_size = offset + count;
-+
-+ lock_kernel();
-+ handle = ext3_journal_start(inode, DIO_CREDITS);
-+ unlock_kernel();
-+ if (IS_ERR(handle)) {
-+ ret = PTR_ERR(handle);
-+ goto out;
-+ }
-+ if (final_size > inode->i_size) {
-+ lock_kernel();
-+ ret = ext3_orphan_add(handle, inode);
-+ unlock_kernel();
-+ if (ret)
-+ goto out_stop;
-+ orphan = 1;
-+ ei->i_disksize = inode->i_size;
-+ }
-+ }
-+
-+ ret = generic_direct_IO(rw, inode, iobuf, blocknr,
-+ blocksize, ext3_direct_io_get_block);
-+
-+out_stop:
-+ if (handle) {
-+ int err;
-+
-+ lock_kernel();
-+ if (orphan)
-+ ext3_orphan_del(handle, inode);
-+ if (orphan && ret > 0) {
-+ loff_t end = offset + ret;
-+ if (end > inode->i_size) {
-+ ei->i_disksize = end;
-+ inode->i_size = end;
-+ err = ext3_mark_inode_dirty(handle, inode);
-+ if (!ret)
-+ ret = err;
-+ }
-+ }
-+ err = ext3_journal_stop(handle, inode);
-+ if (ret == 0)
-+ ret = err;
-+ unlock_kernel();
-+ }
-+out:
-+ return ret;
-+
-+}
-
- struct address_space_operations ext3_aops = {
- readpage: ext3_readpage, /* BKL not held. Don't need */
-@@ -1397,6 +1493,7 @@
- bmap: ext3_bmap, /* BKL held */
- flushpage: ext3_flushpage, /* BKL not held. Don't need */
- releasepage: ext3_releasepage, /* BKL not held. Don't need */
-+ direct_IO: ext3_direct_IO, /* BKL not held. Don't need */
- };
-
- /*
-@@ -2970,7 +3067,7 @@
- /* alloc blocks one by one */
- for (i = 0; i < nblocks; i++) {
- ret = ext3_get_block_handle(handle, inode, blocks[i],
-- &bh_tmp, 1);
-+ &bh_tmp, 1, 1);
- if (ret)
- break;
-
-@@ -3030,7 +3127,7 @@
- if (blocks[i] != 0)
- continue;
-
-- rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1);
-+ rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1, 1);
- if (rc) {
- printk(KERN_INFO "ext3_map_inode_page: error %d "
- "allocating block %ld\n", rc, iblock);
+++ /dev/null
-Index: linux-2.4.21-suse/fs/ext3/namei.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/namei.c 2003-10-30 02:17:22.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/namei.c 2003-10-30 02:20:53.000000000 +0300
-@@ -1747,8 +1747,8 @@
- struct super_block *sb = inode->i_sb;
- struct ext3_iloc iloc;
- int err = 0, rc;
--
-- lock_super(sb);
-+
-+ down(&EXT3_SB(sb)->s_orphan_lock);
- if (!list_empty(&EXT3_I(inode)->i_orphan))
- goto out_unlock;
-
-@@ -1796,7 +1796,7 @@
- jbd_debug(4, "orphan inode %ld will point to %d\n",
- inode->i_ino, NEXT_ORPHAN(inode));
- out_unlock:
-- unlock_super(sb);
-+ up(&EXT3_SB(sb)->s_orphan_lock);
- ext3_std_error(inode->i_sb, err);
- return err;
- }
-@@ -1808,20 +1808,19 @@
- int ext3_orphan_del(handle_t *handle, struct inode *inode)
- {
- struct list_head *prev;
-- struct ext3_sb_info *sbi;
-+ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb);
- unsigned long ino_next;
- struct ext3_iloc iloc;
- int err = 0;
-
-- lock_super(inode->i_sb);
-+ down(&sbi->s_orphan_lock);
- if (list_empty(&inode->u.ext3_i.i_orphan)) {
-- unlock_super(inode->i_sb);
-+ up(&sbi->s_orphan_lock);
- return 0;
- }
-
- ino_next = NEXT_ORPHAN(inode);
- prev = inode->u.ext3_i.i_orphan.prev;
-- sbi = EXT3_SB(inode->i_sb);
-
- jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
-
-@@ -1870,7 +1869,7 @@
- out_err:
- ext3_std_error(inode->i_sb, err);
- out:
-- unlock_super(inode->i_sb);
-+ up(&sbi->s_orphan_lock);
- return err;
-
- out_brelse:
-Index: linux-2.4.21-suse/fs/ext3/super.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/super.c 2003-10-30 02:17:22.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/super.c 2003-10-30 02:17:22.000000000 +0300
-@@ -1151,6 +1151,7 @@
- */
- sb->s_op = &ext3_sops;
- INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
-+ sema_init(&sbi->s_orphan_lock, 1);
-
- sb->s_root = 0;
-
-Index: linux-2.4.21-suse/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.21-suse.orig/include/linux/ext3_fs_sb.h 2003-10-30 02:17:22.000000000 +0300
-+++ linux-2.4.21-suse/include/linux/ext3_fs_sb.h 2003-10-30 02:17:22.000000000 +0300
-@@ -69,6 +69,7 @@
- struct inode * s_journal_inode;
- struct journal_s * s_journal;
- struct list_head s_orphan;
-+ struct semaphore s_orphan_lock;
- unsigned long s_commit_interval;
- struct block_device *journal_bdev;
- #ifdef CONFIG_JBD_DEBUG
+++ /dev/null
- fs/ext3/ialloc.c | 3
- fs/ext3/inode.c | 3
- fs/ext3/namei.c | 582 +++++++++++++++++++++++++++++++++++++---------
- fs/ext3/super.c | 14 +
- include/linux/ext3_fs.h | 1
- include/linux/ext3_fs_i.h | 6
- 6 files changed, 500 insertions(+), 109 deletions(-)
-
-Index: linux-2.4.20/fs/ext3/namei.c
-===================================================================
---- linux-2.4.20.orig/fs/ext3/namei.c 2004-05-27 15:10:40.000000000 -0400
-+++ linux-2.4.20/fs/ext3/namei.c 2004-05-27 15:29:52.000000000 -0400
-@@ -51,6 +51,9 @@
- {
- struct buffer_head *bh;
-
-+ /* with parallel dir operations all appends
-+ * have to be serialized -bzzz */
-+ down(&EXT3_I(inode)->i_append_sem);
- *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
-
- if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
-@@ -58,6 +61,8 @@
- EXT3_I(inode)->i_disksize = inode->i_size;
- ext3_journal_get_write_access(handle,bh);
- }
-+ up(&EXT3_I(inode)->i_append_sem);
-+
- return bh;
- }
-
-@@ -134,6 +139,8 @@
- struct buffer_head *bh;
- struct dx_entry *entries;
- struct dx_entry *at;
-+ unsigned long leaf;
-+ unsigned int curidx;
- };
-
- struct dx_map_entry
-@@ -142,6 +149,30 @@
- u32 offs;
- };
-
-+/* FIXME: this should be reworked using bb_spin_lock
-+ * introduced in -mm tree
-+ */
-+#define BH_DXLock 25
-+
-+static inline void dx_lock_bh(struct buffer_head volatile *bh)
-+{
-+#ifdef CONFIG_SMP
-+ while (test_and_set_bit(BH_DXLock, &bh->b_state)) {
-+ while (test_bit(BH_DXLock, &bh->b_state))
-+ cpu_relax();
-+ }
-+#endif
-+}
-+
-+static inline void dx_unlock_bh(struct buffer_head *bh)
-+{
-+#ifdef CONFIG_SMP
-+ smp_mb__before_clear_bit();
-+ clear_bit(BH_DXLock, &bh->b_state);
-+#endif
-+}
-+
-+
- #ifdef CONFIG_EXT3_INDEX
- static inline unsigned dx_get_block (struct dx_entry *entry);
- static void dx_set_block (struct dx_entry *entry, unsigned value);
-@@ -153,7 +184,7 @@
- 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 struct dx_frame *dx_probe(struct dentry *dentry,
-+static struct dx_frame *dx_probe(struct qstr *name,
- struct inode *dir,
- struct dx_hash_info *hinfo,
- struct dx_frame *frame,
-@@ -165,15 +196,18 @@
- static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to,
- struct dx_map_entry *offsets, int count);
- static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
--static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
-+static void dx_insert_block (struct inode *, struct dx_frame *, u32, u32, u32);
- static int ext3_htree_next_block(struct inode *dir, __u32 hash,
- struct dx_frame *frame,
- struct dx_frame *frames, int *err,
- __u32 *start_hash);
- static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-- struct ext3_dir_entry_2 **res_dir, int *err);
-+ struct ext3_dir_entry_2 **res_dir, int *err,
-+ int rwlock, void **lock);
- static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
- struct inode *inode);
-+static inline void *ext3_lock_htree(struct inode *, unsigned long, int);
-+static inline void ext3_unlock_htree(struct inode *, void *);
-
- /*
- * Future: use high four bits of block for coalesce-on-delete flags
-@@ -306,6 +340,94 @@
- #endif /* DX_DEBUG */
-
- /*
-+ * dx_find_position
-+ *
-+ * search position of specified hash in index
-+ *
-+ */
-+
-+struct dx_entry * dx_find_position(struct dx_entry * entries, u32 hash)
-+{
-+ struct dx_entry *p, *q, *m;
-+ int count;
-+
-+ count = dx_get_count(entries);
-+ p = entries + 1;
-+ q = entries + count - 1;
-+ while (p <= q)
-+ {
-+ m = p + (q - p)/2;
-+ if (dx_get_hash(m) > hash)
-+ q = m - 1;
-+ else
-+ p = m + 1;
-+ }
-+ return p - 1;
-+}
-+
-+/*
-+ * returns 1 if path is unchanged
-+ */
-+int dx_check_path(struct dx_frame *frame, u32 hash)
-+{
-+ struct dx_entry *p;
-+ int ret = 1;
-+
-+ dx_lock_bh(frame->bh);
-+ p = dx_find_position(frame->entries, hash);
-+ if (frame->leaf != dx_get_block(p))
-+ ret = 0;
-+ dx_unlock_bh(frame->bh);
-+
-+ return ret;
-+}
-+
-+/*
-+ * 0 - changed
-+ * 1 - hasn't changed
-+ */
-+static int
-+dx_check_full_path(struct dx_frame *frames, struct dx_hash_info *hinfo)
-+{
-+ struct dx_entry *p;
-+ struct dx_frame *frame = frames;
-+ u32 leaf;
-+
-+ /* check first level */
-+ dx_lock_bh(frame->bh);
-+ p = dx_find_position(frame->entries, hinfo->hash);
-+ leaf = dx_get_block(p);
-+ dx_unlock_bh(frame->bh);
-+
-+ if (leaf != frame->leaf)
-+ return 0;
-+
-+ /* is there 2nd level? */
-+ frame++;
-+ if (frame->bh == NULL)
-+ return 1;
-+
-+ /* check second level */
-+ dx_lock_bh(frame->bh);
-+
-+ /* probably 1st level got changed, check it */
-+ if (!dx_check_path(frames, hinfo->hash)) {
-+ /* path changed */
-+ dx_unlock_bh(frame->bh);
-+ return 0;
-+ }
-+
-+ p = dx_find_position(frame->entries, hinfo->hash);
-+ leaf = dx_get_block(p);
-+ dx_unlock_bh(frame->bh);
-+
-+ if (leaf != frame->leaf)
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/*
- * Probe for a directory leaf block to search.
- *
- * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
-@@ -315,19 +437,20 @@
- * back to userspace.
- */
- static struct dx_frame *
--dx_probe(struct dentry *dentry, struct inode *dir,
-+dx_probe(struct qstr *name, struct inode *dir,
- struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
- {
-- unsigned count, indirect;
-- struct dx_entry *at, *entries, *p, *q, *m;
-+ unsigned indirect;
-+ struct dx_entry *at, *entries;
- struct dx_root *root;
- struct buffer_head *bh;
- struct dx_frame *frame = frame_in;
- u32 hash;
-+ unsigned int curidx;
-
- frame->bh = NULL;
-- if (dentry)
-- dir = dentry->d_parent->d_inode;
-+ frame[1].bh = NULL;
-+
- if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
- goto fail;
- root = (struct dx_root *) bh->b_data;
-@@ -343,8 +466,8 @@
- }
- hinfo->hash_version = root->info.hash_version;
- hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed;
-- if (dentry)
-- ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
-+ if (name)
-+ ext3fs_dirhash(name->name, name->len, hinfo);
- hash = hinfo->hash;
-
- if (root->info.unused_flags & 1) {
-@@ -356,7 +479,19 @@
- goto fail;
- }
-
-+repeat:
-+ curidx = 0;
-+ 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));
-+ dx_lock_bh(bh);
-+ /* indirect must be initialized under bh lock because
-+ * 2nd level creation procedure may change it and dx_probe()
-+ * will suggest htree is still single-level -bzzz */
- if ((indirect = root->info.indirect_levels) > 1) {
-+ dx_unlock_bh(bh);
- ext3_warning(dir->i_sb, __FUNCTION__,
- "Unimplemented inode hash depth: %#06x",
- root->info.indirect_levels);
-@@ -364,56 +499,46 @@
- *err = ERR_BAD_DX_DIR;
- 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)));
-+ at = dx_find_position(entries, hinfo->hash);
-+ 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)))
-+ frame->curidx = curidx;
-+ frame->leaf = dx_get_block(at);
-+ if (!indirect--) {
-+ dx_unlock_bh(bh);
-+ return frame;
-+ }
-+
-+ /* step into next htree level */
-+ curidx = dx_get_block(at);
-+ dx_unlock_bh(bh);
-+ if (!(bh = ext3_bread (NULL,dir, frame->leaf, 0, err)))
- goto fail2;
-+
-+ dx_lock_bh(bh);
-+ /* splitting may change root index block and move
-+ * hash we're looking for into another index block
-+ * so, we have to check this situation and repeat
-+ * from begining if path got changed -bzzz */
-+ if (!dx_check_path(frame, hash)) {
-+ dx_unlock_bh(bh);
-+ bh = frame->bh;
-+ indirect++;
-+ goto repeat;
-+ }
-+
- at = entries = ((struct dx_node *) bh->b_data)->entries;
- assert (dx_get_limit(entries) == dx_node_limit (dir));
- frame++;
- }
-+ dx_unlock_bh(bh);
- fail2:
- while (frame >= frame_in) {
- brelse(frame->bh);
-@@ -427,8 +552,7 @@
- {
- if (frames[0].bh == NULL)
- return;
--
-- if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
-+ if (frames[1].bh != NULL)
- brelse(frames[1].bh);
- brelse(frames[0].bh);
- }
-@@ -470,8 +594,10 @@
- * nodes need to be read.
- */
- while (1) {
-- if (++(p->at) < p->entries + dx_get_count(p->entries))
-+ if (++(p->at) < p->entries + dx_get_count(p->entries)) {
-+ p->leaf = dx_get_block(p->at);
- break;
-+ }
- if (p == frames)
- return 0;
- num_frames++;
-@@ -497,13 +623,17 @@
- * block so no check is necessary
- */
- while (num_frames--) {
-- if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at),
-- 0, err)))
-+ u32 idx;
-+
-+ idx = p->leaf = dx_get_block(p->at);
-+ if (!(bh = ext3_bread(NULL, dir, idx, 0, err)))
- return -1; /* Failure */
- p++;
- brelse (p->bh);
- p->bh = bh;
- p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
-+ p->curidx = idx;
-+ p->leaf = dx_get_block(p->at);
- }
- return 1;
- }
-@@ -543,7 +673,7 @@
- dir = dir_file->f_dentry->d_inode;
- hinfo.hash = start_hash;
- hinfo.minor_hash = 0;
-- frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
-+ frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
- if (!frame)
- return err;
-
-@@ -625,7 +755,8 @@
- count++;
- }
- /* XXX: do we need to check rec_len == 0 case? -Chris */
-- de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-+ de = (struct ext3_dir_entry_2 *)((char*)de +
-+ le16_to_cpu(de->rec_len));
- }
- return count;
- }
-@@ -658,7 +789,8 @@
- } while(more);
- }
-
--static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
-+static void dx_insert_block(struct inode *dir, struct dx_frame *frame,
-+ u32 hash, u32 block, u32 idx)
- {
- struct dx_entry *entries = frame->entries;
- struct dx_entry *old = frame->at, *new = old + 1;
-@@ -670,6 +802,7 @@
- dx_set_hash(new, hash);
- dx_set_block(new, block);
- dx_set_count(entries, count + 1);
-+
- }
- #endif
-
-@@ -752,7 +885,8 @@
-
-
- static struct buffer_head * ext3_find_entry (struct dentry *dentry,
-- struct ext3_dir_entry_2 ** res_dir)
-+ struct ext3_dir_entry_2 ** res_dir,
-+ int rwlock, void **lock)
- {
- struct super_block * sb;
- struct buffer_head * bh_use[NAMEI_RA_SIZE];
-@@ -768,6 +902,7 @@
- int namelen;
- const u8 *name;
- unsigned blocksize;
-+ int do_not_use_dx = 0;
-
- *res_dir = NULL;
- sb = dir->i_sb;
-@@ -776,9 +911,10 @@
- name = dentry->d_name.name;
- if (namelen > EXT3_NAME_LEN)
- return NULL;
-+repeat:
- #ifdef CONFIG_EXT3_INDEX
- if (is_dx(dir)) {
-- bh = ext3_dx_find_entry(dentry, res_dir, &err);
-+ bh = ext3_dx_find_entry(dentry, res_dir, &err, rwlock, lock);
- /*
- * On success, or if the error was file not found,
- * return. Otherwise, fall back to doing a search the
-@@ -787,8 +923,14 @@
- if (bh || (err != ERR_BAD_DX_DIR))
- return bh;
- dxtrace(printk("ext3_find_entry: dx failed, falling back\n"));
-+ do_not_use_dx = 1;
- }
- #endif
-+ *lock = ext3_lock_htree(dir, 0, rwlock);
-+ if (is_dx(dir) && !do_not_use_dx) {
-+ ext3_unlock_htree(dir, *lock);
-+ goto repeat;
-+ }
- nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
- start = EXT3_I(dir)->i_dir_start_lookup;
- if (start >= nblocks)
-@@ -860,12 +1002,17 @@
- /* Clean up the read-ahead blocks */
- for (; ra_ptr < ra_max; ra_ptr++)
- brelse (bh_use[ra_ptr]);
-+ if (!ret) {
-+ ext3_unlock_htree(dir, *lock);
-+ *lock = NULL;
-+ }
- return ret;
- }
-
- #ifdef CONFIG_EXT3_INDEX
- static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-- struct ext3_dir_entry_2 **res_dir, int *err)
-+ struct ext3_dir_entry_2 **res_dir, int *err,
-+ int rwlock, void **lock)
- {
- struct super_block * sb;
- struct dx_hash_info hinfo;
-@@ -880,11 +1027,22 @@
- struct inode *dir = dentry->d_parent->d_inode;
-
- sb = dir->i_sb;
-- if (!(frame = dx_probe (dentry, 0, &hinfo, frames, err)))
-+repeat:
-+ if (!(frame = dx_probe (&dentry->d_name, dir, &hinfo, frames, err)))
- return NULL;
-+
-+ *lock = ext3_lock_htree(dir, frame->leaf, rwlock);
-+ /* while locking leaf we just found may get splitted
-+ * so, we need another leaf. check this */
-+ if (!dx_check_full_path(frames, &hinfo)) {
-+ ext3_unlock_htree(dir, *lock);
-+ dx_release(frames);
-+ goto repeat;
-+ }
-+
- hash = hinfo.hash;
- do {
-- block = dx_get_block(frame->at);
-+ block = frame->leaf;
- if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
- goto errout;
- de = (struct ext3_dir_entry_2 *) bh->b_data;
-@@ -918,6 +1076,8 @@
- *err = -ENOENT;
- errout:
- dxtrace(printk("%s not found\n", name));
-+ ext3_unlock_htree(dir, *lock);
-+ *lock = NULL;
- dx_release (frames);
- return NULL;
- }
-@@ -928,6 +1088,7 @@
- struct inode * inode;
- struct ext3_dir_entry_2 * de;
- struct buffer_head * bh;
-+ void *lock = NULL;
-
- if (dentry->d_name.len > EXT3_NAME_LEN)
- return ERR_PTR(-ENAMETOOLONG);
-@@ -935,10 +1096,11 @@
- if (ext3_check_for_iopen(dir, dentry))
- return NULL;
-
-- bh = ext3_find_entry(dentry, &de);
-+ bh = ext3_find_entry(dentry, &de, 0, &lock);
- inode = NULL;
- if (bh) {
- unsigned long ino = le32_to_cpu(de->inode);
-+ ext3_unlock_htree(dir, lock);
- brelse (bh);
- inode = iget(dir->i_sb, ino);
-
-@@ -975,7 +1137,8 @@
- unsigned rec_len = 0;
-
- while (count--) {
-- struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs);
-+ struct ext3_dir_entry_2 *de =
-+ (struct ext3_dir_entry_2 *) (from + map->offs);
- rec_len = EXT3_DIR_REC_LEN(de->name_len);
- memcpy (to, de, rec_len);
- ((struct ext3_dir_entry_2 *) to)->rec_len = rec_len;
-@@ -988,7 +1151,8 @@
-
- static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
- {
-- struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base;
-+ struct ext3_dir_entry_2 *next, *to, *prev;
-+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) base;
- unsigned rec_len = 0;
-
- prev = to = de;
-@@ -1010,7 +1174,8 @@
-
- static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
- struct buffer_head **bh,struct dx_frame *frame,
-- struct dx_hash_info *hinfo, int *error)
-+ struct dx_hash_info *hinfo, void **target,
-+ int *error)
- {
- unsigned blocksize = dir->i_sb->s_blocksize;
- unsigned count, continued;
-@@ -1057,23 +1222,30 @@
- 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));
--
-+ frame->leaf, hash2, split, count-split));
-+
- /* Fancy dance to stay within two buffers */
- de2 = dx_move_dirents(data1, data2, map + split, count - split);
- de = dx_pack_dirents(data1,blocksize);
- de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
- de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-- dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
-- dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
-+ dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data1, blocksize, 1));
-+ dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data2, blocksize, 1));
-
- /* Which block gets the new entry? */
-+ *target = NULL;
- if (hinfo->hash >= hash2)
- {
- swap(*bh, bh2);
- de = de2;
-- }
-- dx_insert_block (frame, hash2 + continued, newblock);
-+
-+ /* entry will be stored into new block
-+ * we have to lock it before add_dirent_to_buf */
-+ *target = ext3_lock_htree(dir, newblock, 1);
-+ }
-+ dx_lock_bh(frame->bh);
-+ dx_insert_block (dir, frame, hash2 + continued, newblock, frame->curidx);
-+ dx_unlock_bh(frame->bh);
- err = ext3_journal_dirty_metadata (handle, bh2);
- if (err)
- goto journal_error;
-@@ -1147,7 +1319,8 @@
- nlen = EXT3_DIR_REC_LEN(de->name_len);
- rlen = le16_to_cpu(de->rec_len);
- if (de->inode) {
-- struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen);
-+ struct ext3_dir_entry_2 *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;
-@@ -1205,7 +1378,8 @@
- unsigned blocksize;
- struct dx_hash_info hinfo;
- u32 block;
--
-+ void *lock, *new_lock;
-+
- blocksize = dir->i_sb->s_blocksize;
- dxtrace(printk("Creating index\n"));
- retval = ext3_journal_get_write_access(handle, bh);
-@@ -1216,7 +1390,6 @@
- }
- root = (struct dx_root *) bh->b_data;
-
-- EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
- bh2 = ext3_append (handle, dir, &block, &retval);
- if (!(bh2)) {
- brelse(bh);
-@@ -1224,6 +1397,8 @@
- }
- data1 = bh2->b_data;
-
-+ lock = ext3_lock_htree(dir, block, 1);
-+
- /* The 0th block becomes the root, move the dirents out */
- de = (struct ext3_dir_entry_2 *) &root->dotdot;
- de = (struct ext3_dir_entry_2 *) ((char *)de + de->rec_len);
-@@ -1253,13 +1428,25 @@
- frame->entries = entries;
- frame->at = entries;
- frame->bh = bh;
-+ frame->curidx = 0;
-+ frame->leaf = 0;
-+ frame[1].bh = NULL;
- bh = bh2;
-- de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
-+ de = do_split(handle,dir, &bh, frame, &hinfo, &new_lock, &retval);
- dx_release (frames);
- if (!(de))
-- return retval;
-+ goto cleanup;
-+
-+ retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+cleanup:
-+ if (new_lock)
-+ ext3_unlock_htree(dir, new_lock);
-+ /* we mark directory indexed in order to
-+ * avoid races while htree being created -bzzz */
-+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
-+ ext3_unlock_htree(dir, lock);
-
-- return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ return retval;
- }
- #endif
-
-@@ -1288,11 +1475,13 @@
- unsigned blocksize;
- unsigned nlen, rlen;
- u32 block, blocks;
-+ void *lock;
-
- sb = dir->i_sb;
- blocksize = sb->s_blocksize;
- if (!dentry->d_name.len)
- return -EINVAL;
-+repeat:
- #ifdef CONFIG_EXT3_INDEX
- if (is_dx(dir)) {
- retval = ext3_dx_add_entry(handle, dentry, inode);
-@@ -1303,36 +1492,53 @@
- ext3_mark_inode_dirty(handle, dir);
- }
- #endif
-+ lock = ext3_lock_htree(dir, 0, 1);
-+ if (is_dx(dir)) {
-+ /* we got lock for block 0
-+ * probably previous holder of the lock
-+ * created htree -bzzz */
-+ ext3_unlock_htree(dir, lock);
-+ goto repeat;
-+ }
-+
- blocks = dir->i_size >> sb->s_blocksize_bits;
- for (block = 0, offset = 0; block < blocks; block++) {
- bh = ext3_bread(handle, dir, block, 0, &retval);
-- if(!bh)
-+ if(!bh) {
-+ ext3_unlock_htree(dir, lock);
- return retval;
-+ }
- retval = add_dirent_to_buf(handle, dentry, inode, 0, bh);
-- if (retval != -ENOSPC)
-+ if (retval != -ENOSPC) {
-+ ext3_unlock_htree(dir, lock);
- return retval;
-+ }
-
- #ifdef CONFIG_EXT3_INDEX
- if (blocks == 1 && !dx_fallback &&
-- EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
-- return make_indexed_dir(handle, dentry, inode, bh);
-+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) {
-+ retval = make_indexed_dir(handle, dentry, inode, bh);
-+ ext3_unlock_htree(dir, lock);
-+ return retval;
-+ }
- #endif
- brelse(bh);
- }
- bh = ext3_append(handle, dir, &block, &retval);
-- if (!bh)
-+ if (!bh) {
-+ ext3_unlock_htree(dir, lock);
- return retval;
-+ }
- de = (struct ext3_dir_entry_2 *) bh->b_data;
- de->inode = 0;
- de->rec_len = cpu_to_le16(rlen = blocksize);
- nlen = 0;
-- return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ ext3_unlock_htree(dir, lock);
-+ return retval;
- }
-
- #ifdef CONFIG_EXT3_INDEX
--/*
-- * Returns 0 for success, or a negative error value
-- */
- static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
- struct inode *inode)
- {
-@@ -1344,15 +1550,28 @@
- struct super_block * sb = dir->i_sb;
- struct ext3_dir_entry_2 *de;
- int err;
--
-- frame = dx_probe(dentry, 0, &hinfo, frames, &err);
-+ int curidx;
-+ void *idx_lock, *leaf_lock, *newleaf_lock;
-+
-+repeat:
-+ frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err);
- if (!frame)
- return err;
-- entries = frame->entries;
-- at = frame->at;
-
-- if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
-+ /* we're going to chage leaf, so lock it first */
-+ leaf_lock = ext3_lock_htree(dir, frame->leaf, 1);
-+
-+ /* while locking leaf we just found may get splitted
-+ * so we need to check this */
-+ if (!dx_check_full_path(frames, &hinfo)) {
-+ ext3_unlock_htree(dir, leaf_lock);
-+ dx_release(frames);
-+ goto repeat;
-+ }
-+ if (!(bh = ext3_bread(handle,dir, frame->leaf, 0, &err))) {
-+ printk("can't ext3_bread(%d) = %d\n", (int) frame->leaf, err);
- goto cleanup;
-+ }
-
- BUFFER_TRACE(bh, "get_write_access");
- err = ext3_journal_get_write_access(handle, bh);
-@@ -1365,6 +1584,35 @@
- goto cleanup;
- }
-
-+ /* our leaf has no enough space. hence, we have to
-+ * split it. so lock index for this leaf first */
-+ curidx = frame->curidx;
-+ idx_lock = ext3_lock_htree(dir, curidx, 1);
-+
-+ /* now check did path get changed? */
-+ dx_release(frames);
-+
-+ frame = dx_probe(&dentry->d_name, dentry->d_parent->d_inode,
-+ &hinfo, frames, &err);
-+ if (!frame) {
-+ /* FIXME: error handling here */
-+ brelse(bh);
-+ ext3_unlock_htree(dir, idx_lock);
-+ return err;
-+ }
-+
-+ if (frame->curidx != curidx) {
-+ /* path has been changed. we have to drop old lock
-+ * and repeat */
-+ brelse(bh);
-+ ext3_unlock_htree(dir, idx_lock);
-+ ext3_unlock_htree(dir, leaf_lock);
-+ dx_release(frames);
-+ goto repeat;
-+ }
-+ entries = frame->entries;
-+ at = frame->at;
-+
- /* 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)));
-@@ -1376,7 +1624,8 @@
- struct dx_entry *entries2;
- struct dx_node *node2;
- struct buffer_head *bh2;
--
-+ void *nb_lock;
-+
- if (levels && (dx_get_count(frames->entries) ==
- dx_get_limit(frames->entries))) {
- ext3_warning(sb, __FUNCTION__,
-@@ -1387,6 +1636,7 @@
- bh2 = ext3_append (handle, dir, &newblock, &err);
- if (!(bh2))
- goto cleanup;
-+ nb_lock = ext3_lock_htree(dir, newblock, 1);
- node2 = (struct dx_node *)(bh2->b_data);
- entries2 = node2->entries;
- node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
-@@ -1398,27 +1648,73 @@
- if (levels) {
- unsigned icount1 = icount/2, icount2 = icount - icount1;
- unsigned hash2 = dx_get_hash(entries + icount1);
-+ void *ri_lock;
-+
-+ /* we have to protect root htree index against
-+ * another dx_add_entry() which would want to
-+ * split it too -bzzz */
-+ ri_lock = ext3_lock_htree(dir, 0, 1);
-+
-+ /* as root index block blocked we must repeat
-+ * searching for current position of our 2nd index -bzzz */
-+ dx_lock_bh(frame->bh);
-+ frames->at = dx_find_position(frames->entries, hinfo.hash);
-+ dx_unlock_bh(frame->bh);
-+
- dxtrace(printk("Split index %i/%i\n", icount1, icount2));
--
-- BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
-+
-+ BUFFER_TRACE(frame->bh, "get_write_access");
- err = ext3_journal_get_write_access(handle,
- frames[0].bh);
- if (err)
- goto journal_error;
--
-+
-+ /* copy index into new one */
- 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) {
-+ /* unlock index we won't use */
-+ ext3_unlock_htree(dir, idx_lock);
-+ idx_lock = nb_lock;
- frame->at = at = at - entries - icount1 + entries2;
-- frame->entries = entries = entries2;
-+ frame->entries = entries2;
-+ frame->curidx = curidx = newblock;
- swap(frame->bh, bh2);
-+ } else {
-+ /* we'll use old index,so new one may be freed */
-+ ext3_unlock_htree(dir, nb_lock);
- }
-- dx_insert_block (frames + 0, hash2, newblock);
-+
-+ /* NOTE: very subtle piece of code
-+ * competing dx_probe() may find 2nd level index in root
-+ * index, then we insert new index here and set new count
-+ * in that 2nd level index. so, dx_probe() may see 2nd
-+ * level index w/o hash it looks for. the solution is
-+ * to check root index after we locked just founded 2nd
-+ * level index -bzzz */
-+ dx_lock_bh(frames[0].bh);
-+ dx_insert_block (dir, frames + 0, hash2, newblock, 0);
-+ dx_unlock_bh(frames[0].bh);
-+
-+ /* now old and new 2nd level index blocks contain
-+ * all pointers, so dx_probe() may find it in the both.
-+ * it's OK -bzzz */
-+
-+ dx_lock_bh(frame->bh);
-+ dx_set_count(entries, icount1);
-+ dx_unlock_bh(frame->bh);
-+
-+ /* now old 2nd level index block points to first half
-+ * of leafs. it's importand that dx_probe() must
-+ * check root index block for changes under
-+ * dx_lock_bh(frame->bh) -bzzz */
-+
-+ ext3_unlock_htree(dir, ri_lock);
-+
- dxtrace(dx_show_index ("node", frames[1].entries));
- dxtrace(dx_show_index ("node",
- ((struct dx_node *) bh2->b_data)->entries));
-@@ -1427,38 +1723,61 @@
- goto journal_error;
- brelse (bh2);
- } else {
-+ unsigned long leaf = frame->leaf;
-+
- 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_lock_bh(frames[0].bh);
- dx_set_count(entries, 1);
- dx_set_block(entries + 0, newblock);
- ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
-+ dx_unlock_bh(frames[0].bh);
-
- /* Add new access path frame */
- frame = frames + 1;
- frame->at = at = at - entries + entries2;
- frame->entries = entries = entries2;
- frame->bh = bh2;
-+ frame->curidx = newblock;
-+ frame->leaf = leaf;
- err = ext3_journal_get_write_access(handle,
- frame->bh);
- if (err)
- goto journal_error;
-+
-+ /* first level index was root. it's already initialized */
-+ /* we my unlock it now */
-+ ext3_unlock_htree(dir, idx_lock);
-+
-+ /* current index is just created 2nd level index */
-+ curidx = newblock;
-+ idx_lock = nb_lock;
- }
- ext3_journal_dirty_metadata(handle, frames[0].bh);
- }
-- de = do_split(handle, dir, &bh, frame, &hinfo, &err);
-+ de = do_split(handle, dir, &bh, frame, &hinfo, &newleaf_lock, &err);
- if (!de)
- goto cleanup;
-+
-+ /* index splitted */
-+ ext3_unlock_htree(dir, idx_lock);
-+
- err = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+
-+ if (newleaf_lock)
-+ ext3_unlock_htree(dir, newleaf_lock);
-+
- bh = 0;
- goto cleanup;
-
- journal_error:
- ext3_std_error(dir->i_sb, err);
- cleanup:
-+ ext3_unlock_htree(dir, leaf_lock);
- if (bh)
- brelse(bh);
- dx_release(frames);
-@@ -1902,6 +2221,7 @@
- struct buffer_head * bh;
- struct ext3_dir_entry_2 * de;
- handle_t *handle;
-+ void *lock;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
- if (IS_ERR(handle)) {
-@@ -1909,7 +2229,7 @@
- }
-
- retval = -ENOENT;
-- bh = ext3_find_entry (dentry, &de);
-+ bh = ext3_find_entry (dentry, &de, 1, &lock);
- if (!bh)
- goto end_rmdir;
-
-@@ -1920,14 +2240,19 @@
- DQUOT_INIT(inode);
-
- retval = -EIO;
-- if (le32_to_cpu(de->inode) != inode->i_ino)
-+ if (le32_to_cpu(de->inode) != inode->i_ino) {
-+ ext3_unlock_htree(dir, lock);
- goto end_rmdir;
-+ }
-
- retval = -ENOTEMPTY;
-- if (!empty_dir (inode))
-+ if (!empty_dir (inode)) {
-+ ext3_unlock_htree(dir, lock);
- goto end_rmdir;
-+ }
-
- retval = ext3_delete_entry(handle, dir, de, bh);
-+ ext3_unlock_htree(dir, lock);
- if (retval)
- goto end_rmdir;
- if (inode->i_nlink != 2)
-@@ -1956,6 +2281,7 @@
- struct buffer_head * bh;
- struct ext3_dir_entry_2 * de;
- handle_t *handle;
-+ void *lock;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
- if (IS_ERR(handle)) {
-@@ -1966,7 +2292,7 @@
- handle->h_sync = 1;
-
- retval = -ENOENT;
-- bh = ext3_find_entry (dentry, &de);
-+ bh = ext3_find_entry (dentry, &de, 1, &lock);
- if (!bh)
- goto end_unlink;
-
-@@ -1974,8 +2300,10 @@
- DQUOT_INIT(inode);
-
- retval = -EIO;
-- if (le32_to_cpu(de->inode) != inode->i_ino)
-+ if (le32_to_cpu(de->inode) != inode->i_ino) {
-+ ext3_unlock_htree(dir, lock);
- goto end_unlink;
-+ }
-
- if (!inode->i_nlink) {
- ext3_warning (inode->i_sb, "ext3_unlink",
-@@ -1984,6 +2312,7 @@
- inode->i_nlink = 1;
- }
- retval = ext3_delete_entry(handle, dir, de, bh);
-+ ext3_unlock_htree(dir, lock);
- if (retval)
- goto end_unlink;
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-@@ -2121,6 +2450,7 @@
- struct buffer_head * old_bh, * new_bh, * dir_bh;
- struct ext3_dir_entry_2 * old_de, * new_de;
- int retval;
-+ void *lock1 = NULL, *lock2 = NULL, *lock3 = NULL;
-
- old_bh = new_bh = dir_bh = NULL;
-
-@@ -2133,7 +2463,10 @@
- if (IS_SYNC(old_dir) || IS_SYNC(new_dir))
- handle->h_sync = 1;
-
-- old_bh = ext3_find_entry (old_dentry, &old_de);
-+ if (old_dentry->d_parent == new_dentry->d_parent)
-+ down(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem);
-+
-+ old_bh = ext3_find_entry (old_dentry, &old_de, 1, &lock1 /* FIXME */);
- /*
- * Check for inode number is _not_ due to possible IO errors.
- * We might rmdir the source, keep it as pwd of some process
-@@ -2146,7 +2479,7 @@
- goto end_rename;
-
- new_inode = new_dentry->d_inode;
-- new_bh = ext3_find_entry (new_dentry, &new_de);
-+ new_bh = ext3_find_entry (new_dentry, &new_de, 1, &lock2 /* FIXME */);
- if (new_bh) {
- if (!new_inode) {
- brelse (new_bh);
-@@ -2213,7 +2546,7 @@
- struct buffer_head *old_bh2;
- struct ext3_dir_entry_2 *old_de2;
-
-- old_bh2 = ext3_find_entry(old_dentry, &old_de2);
-+ old_bh2 = ext3_find_entry(old_dentry, &old_de2, 1, &lock3 /* FIXME */);
- if (old_bh2) {
- retval = ext3_delete_entry(handle, old_dir,
- old_de2, old_bh2);
-@@ -2256,6 +2589,14 @@
- retval = 0;
-
- end_rename:
-+ if (lock1)
-+ ext3_unlock_htree(old_dentry->d_parent->d_inode, lock1);
-+ if (lock2)
-+ ext3_unlock_htree(new_dentry->d_parent->d_inode, lock2);
-+ if (lock3)
-+ ext3_unlock_htree(old_dentry->d_parent->d_inode, lock3);
-+ if (old_dentry->d_parent == new_dentry->d_parent)
-+ up(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem);
- brelse (dir_bh);
- brelse (old_bh);
- brelse (new_bh);
-@@ -2264,6 +2605,29 @@
- }
-
- /*
-+ * this locking primitives are used to protect parts
-+ * of dir's htree. protection unit is block: leaf or index
-+ */
-+static inline void *ext3_lock_htree(struct inode *dir,
-+ unsigned long value, int rwlock)
-+{
-+ void *lock;
-+
-+ if (!test_opt(dir->i_sb, PDIROPS))
-+ return NULL;
-+ lock = dynlock_lock(&EXT3_I(dir)->i_htree_lock, value, 1, GFP_KERNEL);
-+ return lock;
-+}
-+
-+static inline void ext3_unlock_htree(struct inode *dir,
-+ void *lock)
-+{
-+ if (!test_opt(dir->i_sb, PDIROPS) || !lock)
-+ return;
-+ dynlock_unlock(&EXT3_I(dir)->i_htree_lock, lock);
-+}
-+
-+/*
- * directories can handle most operations...
- */
- struct inode_operations ext3_dir_inode_operations = {
-Index: linux-2.4.20/fs/ext3/super.c
-===================================================================
---- linux-2.4.20.orig/fs/ext3/super.c 2004-05-27 15:10:41.000000000 -0400
-+++ linux-2.4.20/fs/ext3/super.c 2004-05-27 15:10:45.000000000 -0400
-@@ -796,6 +796,8 @@
- return 0;
- }
- }
-+ else if (!strcmp (this_char, "pdirops"))
-+ set_opt (sbi->s_mount_opt, PDIROPS);
- else if (!strcmp (this_char, "grpid") ||
- !strcmp (this_char, "bsdgroups"))
- set_opt (*mount_options, GRPID);
-@@ -822,6 +824,9 @@
- if (want_numeric(value, "sb", sb_block))
- return 0;
- }
-+ else if (!strcmp (this_char, "pdirops")) {
-+ set_opt (sbi->s_mount_opt, PDIROPS);
-+ }
- #ifdef CONFIG_JBD_DEBUG
- else if (!strcmp (this_char, "ro-after")) {
- unsigned long v;
-@@ -985,6 +990,10 @@
- ext3_check_inodes_bitmap (sb);
- }
- #endif
-+#ifdef S_PDIROPS
-+ if (test_opt (sb, PDIROPS))
-+ sb->s_flags |= S_PDIROPS;
-+#endif
- setup_ro_after(sb);
- return res;
- }
-@@ -1484,6 +1493,11 @@
- test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
- "writeback");
-
-+ if (test_opt(sb, PDIROPS)) {
-+ printk (KERN_INFO "EXT3-fs: mounted filesystem with parallel dirops\n");
-+ sb->s_flags |= S_PDIROPS;
-+ }
-+
- return sb;
-
- failed_mount3:
-Index: linux-2.4.20/fs/ext3/inode.c
-===================================================================
---- linux-2.4.20.orig/fs/ext3/inode.c 2004-05-27 15:10:41.000000000 -0400
-+++ linux-2.4.20/fs/ext3/inode.c 2004-05-27 15:10:45.000000000 -0400
-@@ -2435,6 +2435,9 @@
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
-+ dynlock_init(&EXT3_I(inode)->i_htree_lock);
-+ sema_init(&EXT3_I(inode)->i_rename_sem, 1);
-+ sema_init(&EXT3_I(inode)->i_append_sem, 1);
- } else if (S_ISLNK(inode->i_mode)) {
- if (ext3_inode_is_fast_symlink(inode))
- inode->i_op = &ext3_fast_symlink_inode_operations;
-Index: linux-2.4.20/fs/ext3/ialloc.c
-===================================================================
---- linux-2.4.20.orig/fs/ext3/ialloc.c 2004-05-27 15:10:39.000000000 -0400
-+++ linux-2.4.20/fs/ext3/ialloc.c 2004-05-27 15:10:45.000000000 -0400
-@@ -601,6 +601,9 @@
- return ERR_PTR(-EDQUOT);
- }
- ext3_debug ("allocating inode %lu\n", inode->i_ino);
-+ dynlock_init(&EXT3_I(inode)->i_htree_lock);
-+ sema_init(&EXT3_I(inode)->i_rename_sem, 1);
-+ sema_init(&EXT3_I(inode)->i_append_sem, 1);
- return inode;
-
- fail:
-Index: linux-2.4.20/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.20.orig/include/linux/ext3_fs.h 2004-05-27 15:10:40.000000000 -0400
-+++ linux-2.4.20/include/linux/ext3_fs.h 2004-05-27 15:10:45.000000000 -0400
-@@ -306,6 +306,7 @@
- /*
- * Mount flags
- */
-+#define EXT3_MOUNT_PDIROPS 0x800000/* Parallel dir operations */
- #define EXT3_MOUNT_CHECK 0x0001 /* Do mount-time checks */
- #define EXT3_MOUNT_GRPID 0x0004 /* Create files with directory's group */
- #define EXT3_MOUNT_DEBUG 0x0008 /* Some debugging messages */
-Index: linux-2.4.20/include/linux/ext3_fs_i.h
-===================================================================
---- linux-2.4.20.orig/include/linux/ext3_fs_i.h 2001-11-22 14:46:19.000000000 -0500
-+++ linux-2.4.20/include/linux/ext3_fs_i.h 2004-05-27 15:10:45.000000000 -0400
-@@ -17,6 +17,7 @@
- #define _LINUX_EXT3_FS_I
-
- #include <linux/rwsem.h>
-+#include <linux/dynlocks.h>
-
- /*
- * second extended file system inode data in memory
-@@ -73,6 +74,11 @@
- * by other means, so we have truncate_sem.
- */
- struct rw_semaphore truncate_sem;
-+
-+ /* following fields for parallel directory operations -bzzz */
-+ struct dynlock i_htree_lock;
-+ struct semaphore i_append_sem;
-+ struct semaphore i_rename_sem;
- };
-
- #endif /* _LINUX_EXT3_FS_I */
+++ /dev/null
- fs/ext3/file.c | 4
- fs/ext3/inode.c | 116 ++++++++++++++++++++++
- fs/ext3/super.c | 230 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/ext3_fs.h | 5
- include/linux/ext3_fs_sb.h | 10 +
- 5 files changed, 365 insertions(+)
-
-Index: linux-2.4.20-rh-20.9/fs/ext3/super.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/fs/ext3/super.c 2004-01-12 19:27:46.000000000 +0300
-+++ linux-2.4.20-rh-20.9/fs/ext3/super.c 2004-01-13 17:20:31.000000000 +0300
-@@ -400,6 +400,221 @@
- }
- }
-
-+#ifdef EXT3_DELETE_THREAD
-+/*
-+ * Delete inodes in a loop until there are no more to be deleted.
-+ * Normally, we run in the background doing the deletes and sleeping again,
-+ * and clients just add new inodes to be deleted onto the end of the list.
-+ * If someone is concerned about free space (e.g. block allocation or similar)
-+ * then they can sleep on s_delete_waiter_queue and be woken up when space
-+ * has been freed.
-+ */
-+int ext3_delete_thread(void *data)
-+{
-+ struct super_block *sb = data;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct task_struct *tsk = current;
-+
-+ /* Almost like daemonize, but not quite */
-+ exit_mm(current);
-+ tsk->session = 1;
-+ tsk->pgrp = 1;
-+ tsk->tty = NULL;
-+ exit_files(current);
-+ reparent_to_init();
-+
-+ sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev));
-+ sigfillset(&tsk->blocked);
-+
-+ /*tsk->flags |= PF_KERNTHREAD;*/
-+
-+ INIT_LIST_HEAD(&sbi->s_delete_list);
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev));
-+
-+ /* main loop */
-+ for (;;) {
-+ wait_event_interruptible(sbi->s_delete_thread_queue,
-+ !list_empty(&sbi->s_delete_list) ||
-+ !test_opt(sb, ASYNCDEL));
-+ ext3_debug("%s woken up: %lu inodes, %lu blocks\n",
-+ tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ if (list_empty(&sbi->s_delete_list)) {
-+ clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+ memset(&sbi->s_delete_list, 0,
-+ sizeof(sbi->s_delete_list));
-+ spin_unlock(&sbi->s_delete_lock);
-+ ext3_debug("delete thread on %s exiting\n",
-+ kdevname(sb->s_dev));
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ break;
-+ }
-+
-+ while (!list_empty(&sbi->s_delete_list)) {
-+ struct inode *inode=list_entry(sbi->s_delete_list.next,
-+ struct inode, i_dentry);
-+ unsigned long blocks = inode->i_blocks >>
-+ (inode->i_blkbits - 9);
-+
-+ list_del_init(&inode->i_dentry);
-+ spin_unlock(&sbi->s_delete_lock);
-+ ext3_debug("%s delete ino %lu blk %lu\n",
-+ tsk->comm, inode->i_ino, blocks);
-+
-+ iput(inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ sbi->s_delete_blocks -= blocks;
-+ sbi->s_delete_inodes--;
-+ }
-+ if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) {
-+ ext3_warning(sb, __FUNCTION__,
-+ "%lu blocks, %lu inodes on list?\n",
-+ sbi->s_delete_blocks,sbi->s_delete_inodes);
-+ sbi->s_delete_blocks = 0;
-+ sbi->s_delete_inodes = 0;
-+ }
-+ spin_unlock(&sbi->s_delete_lock);
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ }
-+
-+ return 0;
-+}
-+
-+static void ext3_start_delete_thread(struct super_block *sb)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ int rc;
-+
-+ spin_lock_init(&sbi->s_delete_lock);
-+ init_waitqueue_head(&sbi->s_delete_thread_queue);
-+ init_waitqueue_head(&sbi->s_delete_waiter_queue);
-+
-+ if (!test_opt(sb, ASYNCDEL))
-+ return;
-+
-+ rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES);
-+ if (rc < 0)
-+ printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n",
-+ rc);
-+ else
-+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next);
-+}
-+
-+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi)
-+{
-+ if (sbi->s_delete_list.next == 0) /* thread never started */
-+ return;
-+
-+ clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+ wake_up(&sbi->s_delete_thread_queue);
-+ wait_event(sbi->s_delete_waiter_queue,
-+ sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0);
-+}
-+
-+/* Instead of playing games with the inode flags, destruction, etc we just
-+ * create a new inode locally and put it on a list for the truncate thread.
-+ * We need large parts of the inode struct in order to complete the
-+ * truncate and unlink, so we may as well just have a real inode to do it.
-+ *
-+ * If we have any problem deferring the delete, just delete it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+static void ext3_delete_inode_thread(struct inode *old_inode)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+ struct inode *new_inode;
-+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+ if (is_bad_inode(old_inode)) {
-+ clear_inode(old_inode);
-+ return;
-+ }
-+
-+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+ goto out_delete;
-+
-+ /* We may want to delete the inode immediately and not defer it */
-+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS)
-+ goto out_delete;
-+
-+ /* We can't use the delete thread as-is during real orphan recovery,
-+ * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+ * to loop endlessly. It would be nice to do so, but needs work.
-+ */
-+ if (oei->i_state & EXT3_STATE_DELETE ||
-+ sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+ old_inode->i_ino, blocks);
-+ goto out_delete;
-+ }
-+
-+ /* We can iget this inode again here, because our caller has unhashed
-+ * old_inode, so new_inode will be in a different inode struct.
-+ *
-+ * We need to ensure that the i_orphan pointers in the other inodes
-+ * point at the new inode copy instead of the old one so the orphan
-+ * list doesn't get corrupted when the old orphan inode is freed.
-+ */
-+ down(&sbi->s_orphan_lock);
-+
-+ sbi->s_mount_state |= EXT3_ORPHAN_FS;
-+ new_inode = iget(old_inode->i_sb, old_inode->i_ino);
-+ sbi->s_mount_state &= ~EXT3_ORPHAN_FS;
-+ if (is_bad_inode(new_inode)) {
-+ printk(KERN_WARNING "read bad inode %lu\n", old_inode->i_ino);
-+ iput(new_inode);
-+ new_inode = NULL;
-+ }
-+ if (!new_inode) {
-+ up(&sbi->s_orphan_lock);
-+ ext3_debug("delete inode %lu directly (bad read)\n",
-+ old_inode->i_ino);
-+ goto out_delete;
-+ }
-+ J_ASSERT(new_inode != old_inode);
-+
-+ J_ASSERT(!list_empty(&oei->i_orphan));
-+
-+ nei = EXT3_I(new_inode);
-+ /* Ugh. We need to insert new_inode into the same spot on the list
-+ * as old_inode was, to ensure the in-memory orphan list is still
-+ * in the same order as the on-disk orphan list (badness otherwise).
-+ */
-+ nei->i_orphan = oei->i_orphan;
-+ nei->i_orphan.next->prev = &nei->i_orphan;
-+ nei->i_orphan.prev->next = &nei->i_orphan;
-+ nei->i_state |= EXT3_STATE_DELETE;
-+ up(&sbi->s_orphan_lock);
-+
-+ clear_inode(old_inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ J_ASSERT(list_empty(&new_inode->i_dentry));
-+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+ sbi->s_delete_blocks += blocks;
-+ sbi->s_delete_inodes++;
-+ spin_unlock(&sbi->s_delete_lock);
-+
-+ ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+ new_inode->i_ino, blocks);
-+
-+ wake_up(&sbi->s_delete_thread_queue);
-+ return;
-+
-+out_delete:
-+ ext3_delete_inode(old_inode);
-+}
-+#else
-+#define ext3_start_delete_thread(sbi) do {} while(0)
-+#define ext3_stop_delete_thread(sbi) do {} while(0)
-+#endif /* EXT3_DELETE_THREAD */
-+
- void ext3_put_super (struct super_block * sb)
- {
- struct ext3_sb_info *sbi = EXT3_SB(sb);
-@@ -407,6 +622,7 @@
- kdev_t j_dev = sbi->s_journal->j_dev;
- int i;
-
-+ J_ASSERT(sbi->s_delete_inodes == 0);
- ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
-@@ -455,7 +671,11 @@
- write_inode: ext3_write_inode, /* BKL not held. Don't need */
- dirty_inode: ext3_dirty_inode, /* BKL not held. We take it */
- put_inode: ext3_put_inode, /* BKL not held. Don't need */
-+#ifdef EXT3_DELETE_THREAD
-+ delete_inode: ext3_delete_inode_thread,/* BKL not held. We take it */
-+#else
- delete_inode: ext3_delete_inode, /* BKL not held. We take it */
-+#endif
- put_super: ext3_put_super, /* BKL held */
- write_super: ext3_write_super, /* BKL held */
- sync_fs: ext3_sync_fs,
-@@ -524,6 +744,13 @@
- clear_opt (*mount_options, XATTR_USER);
- else
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+ if (!strcmp(this_char, "asyncdel"))
-+ set_opt(*mount_options, ASYNCDEL);
-+ else if (!strcmp(this_char, "noasyncdel"))
-+ clear_opt(*mount_options, ASYNCDEL);
-+ else
-+#endif
- if (!strcmp (this_char, "bsddf"))
- clear_opt (*mount_options, MINIX_DF);
- else if (!strcmp (this_char, "nouid32")) {
-@@ -1223,6 +1450,7 @@
- }
-
- ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-+ ext3_start_delete_thread(sb);
- /*
- * akpm: core read_super() calls in here with the superblock locked.
- * That deadlocks, because orphan cleanup needs to lock the superblock
-@@ -1614,7 +1842,12 @@
- static int ext3_sync_fs(struct super_block *sb)
- {
- tid_t target;
--
-+
-+ if (atomic_read(&sb->s_active) == 0) {
-+ /* fs is being umounted: time to stop delete thread */
-+ ext3_stop_delete_thread(EXT3_SB(sb));
-+ }
-+
- sb->s_dirt = 0;
- target = log_start_commit(EXT3_SB(sb)->s_journal, NULL);
- log_wait_commit(EXT3_SB(sb)->s_journal, target);
-@@ -1678,6 +1911,9 @@
- if (!parse_options(data, &tmp, sbi, &tmp, 1))
- return -EINVAL;
-
-+ if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY))
-+ ext3_stop_delete_thread(sbi);
-+
- if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
- ext3_abort(sb, __FUNCTION__, "Abort forced by user");
-
-Index: linux-2.4.20-rh-20.9/fs/ext3/inode.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/fs/ext3/inode.c 2004-01-12 19:27:46.000000000 +0300
-+++ linux-2.4.20-rh-20.9/fs/ext3/inode.c 2004-01-13 17:15:48.000000000 +0300
-@@ -2017,6 +2017,122 @@
- ext3_journal_stop(handle, inode);
- }
-
-+#ifdef EXT3_DELETE_THREAD
-+/* Move blocks from to-be-truncated inode over to a new inode, and delete
-+ * that one from the delete thread instead. This avoids a lot of latency
-+ * when truncating large files.
-+ *
-+ * If we have any problem deferring the truncate, just truncate it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ *
-+ * During normal filesystem usage, we are always called here with a
-+ * transaction already started. The only time ext3_truncate is called
-+ * without a started transaction is from ext3_orphan_cleanup(), and we
-+ * currently just do a direct truncate in that case.
-+ */
-+void ext3_truncate_thread(struct inode *old_inode)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+ struct inode *new_inode;
-+ handle_t *handle;
-+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+ goto out_truncate;
-+
-+ /* XXX This is a temporary limitation for code simplicity.
-+ * We could truncate to arbitrary sizes at some later time.
-+ */
-+ if (old_inode->i_size != 0)
-+ goto out_truncate;
-+
-+ /* We may want to truncate the inode immediately and not defer it */
-+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS ||
-+ old_inode->i_size > oei->i_disksize)
-+ goto out_truncate;
-+
-+ /* We can't use the delete thread as-is during real orphan recovery,
-+ * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+ * to loop endlessly. It would be nice to do so, but needs work.
-+ */
-+ if (oei->i_state & EXT3_STATE_DELETE ||
-+ sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+ old_inode->i_ino, blocks);
-+ goto out_truncate;
-+ }
-+
-+ ext3_discard_prealloc(old_inode);
-+
-+ /* old_inode = 1
-+ * new_inode = sb + GDT + ibitmap
-+ * orphan list = 1 inode/superblock for add, 2 inodes for del
-+ * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS
-+ */
-+ handle = ext3_journal_start(old_inode, 7);
-+ if (IS_ERR(handle))
-+ goto out_truncate;
-+
-+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode);
-+ if (IS_ERR(new_inode)) {
-+ ext3_debug("truncate inode %lu directly (no new inodes)\n",
-+ old_inode->i_ino);
-+ goto out_journal;
-+ }
-+
-+ if (ext3_orphan_add(handle, new_inode) < 0)
-+ goto out_journal;
-+
-+ if (ext3_orphan_del(handle, old_inode) < 0) {
-+ ext3_orphan_del(handle, new_inode);
-+ iput(new_inode);
-+ goto out_journal;
-+ }
-+
-+ nei = EXT3_I(new_inode);
-+
-+ down_write(&oei->truncate_sem);
-+ new_inode->i_size = old_inode->i_size;
-+ new_inode->i_blocks = old_inode->i_blocks;
-+ new_inode->i_uid = old_inode->i_uid;
-+ new_inode->i_gid = old_inode->i_gid;
-+ new_inode->i_nlink = 0;
-+
-+ /* FIXME when we do arbitrary truncates */
-+ old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0;
-+
-+ memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data));
-+ memset(oei->i_data, 0, sizeof(oei->i_data));
-+
-+ nei->i_disksize = oei->i_disksize;
-+ nei->i_state |= EXT3_STATE_DELETE;
-+ up_write(&oei->truncate_sem);
-+
-+ ext3_journal_stop(handle, old_inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ J_ASSERT(list_empty(&new_inode->i_dentry));
-+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+ sbi->s_delete_blocks += blocks;
-+ sbi->s_delete_inodes++;
-+ spin_unlock(&sbi->s_delete_lock);
-+
-+ ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+ new_inode->i_ino, blocks);
-+
-+ wake_up(&sbi->s_delete_thread_queue);
-+ return;
-+
-+out_journal:
-+ ext3_journal_stop(handle, old_inode);
-+out_truncate:
-+ ext3_truncate(old_inode);
-+}
-+#endif /* EXT3_DELETE_THREAD */
-+
- /*
- * ext3_get_inode_loc returns with an extra refcount against the
- * inode's underlying buffer_head on success.
-Index: linux-2.4.20-rh-20.9/fs/ext3/file.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/fs/ext3/file.c 2004-01-12 19:27:46.000000000 +0300
-+++ linux-2.4.20-rh-20.9/fs/ext3/file.c 2004-01-13 17:15:48.000000000 +0300
-@@ -125,7 +125,11 @@
- };
-
- struct inode_operations ext3_file_inode_operations = {
-+#ifdef EXT3_DELETE_THREAD
-+ truncate: ext3_truncate_thread, /* BKL held */
-+#else
- truncate: ext3_truncate, /* BKL held */
-+#endif
- setattr: ext3_setattr, /* BKL held */
- setxattr: ext3_setxattr, /* BKL held */
- getxattr: ext3_getxattr, /* BKL held */
-Index: linux-2.4.20-rh-20.9/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/linux/ext3_fs.h 2004-01-12 19:27:46.000000000 +0300
-+++ linux-2.4.20-rh-20.9/include/linux/ext3_fs.h 2004-01-13 17:15:48.000000000 +0300
-@@ -193,6 +193,7 @@
- */
- #define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */
- #define EXT3_STATE_NEW 0x00000002 /* inode is newly created */
-+#define EXT3_STATE_DELETE 0x00000010 /* deferred delete inode */
-
- /*
- * ioctl commands
-@@ -320,6 +321,7 @@
- #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 */
-+#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -695,6 +697,9 @@
- extern void ext3_dirty_inode(struct inode *);
- extern int ext3_change_inode_journal_flag(struct inode *, int);
- extern void ext3_truncate (struct inode *);
-+#ifdef EXT3_DELETE_THREAD
-+extern void ext3_truncate_thread(struct inode *inode);
-+#endif
- extern void ext3_set_inode_flags(struct inode *);
-
- /* ioctl.c */
-Index: linux-2.4.20-rh-20.9/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/linux/ext3_fs_sb.h 2004-01-12 19:27:46.000000000 +0300
-+++ linux-2.4.20-rh-20.9/include/linux/ext3_fs_sb.h 2004-01-13 17:15:48.000000000 +0300
-@@ -29,6 +29,8 @@
-
- #define EXT3_MAX_GROUP_LOADED 32
-
-+#define EXT3_DELETE_THREAD
-+
- /*
- * third extended-fs super-block data in memory
- */
-@@ -76,6 +78,14 @@
- struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */
- wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+ spinlock_t s_delete_lock;
-+ struct list_head s_delete_list;
-+ unsigned long s_delete_blocks;
-+ unsigned long s_delete_inodes;
-+ wait_queue_head_t s_delete_thread_queue;
-+ wait_queue_head_t s_delete_waiter_queue;
-+#endif
- };
-
- #endif /* _LINUX_EXT3_FS_SB */
+++ /dev/null
- fs/ext3/namei.c | 15 +++++++--------
- fs/ext3/super.c | 1 +
- include/linux/ext3_fs_sb.h | 1 +
- 3 files changed, 9 insertions(+), 8 deletions(-)
-
---- linux-rh-2.4.20-8/fs/ext3/namei.c~ext3_orphan_lock-2.4.20-rh 2003-05-05 19:49:15.000000000 +0800
-+++ linux-rh-2.4.20-8-root/fs/ext3/namei.c 2003-05-05 20:01:28.000000000 +0800
-@@ -1747,8 +1747,8 @@ int ext3_orphan_add(handle_t *handle, st
- struct super_block *sb = inode->i_sb;
- struct ext3_iloc iloc;
- int err = 0, rc;
--
-- lock_super(sb);
-+
-+ down(&EXT3_SB(sb)->s_orphan_lock);
- if (!list_empty(&EXT3_I(inode)->i_orphan))
- goto out_unlock;
-
-@@ -1796,7 +1796,7 @@ int ext3_orphan_add(handle_t *handle, st
- jbd_debug(4, "orphan inode %ld will point to %d\n",
- inode->i_ino, NEXT_ORPHAN(inode));
- out_unlock:
-- unlock_super(sb);
-+ up(&EXT3_SB(sb)->s_orphan_lock);
- ext3_std_error(inode->i_sb, err);
- return err;
- }
-@@ -1809,20 +1809,19 @@ int ext3_orphan_del(handle_t *handle, st
- {
- struct list_head *prev;
- struct ext3_inode_info *ei = EXT3_I(inode);
-- struct ext3_sb_info *sbi;
-+ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb);
- unsigned long ino_next;
- struct ext3_iloc iloc;
- int err = 0;
-
-- lock_super(inode->i_sb);
-+ down(&sbi->s_orphan_lock);
- if (list_empty(&ei->i_orphan)) {
-- unlock_super(inode->i_sb);
-+ up(&sbi->s_orphan_lock);
- return 0;
- }
-
- ino_next = NEXT_ORPHAN(inode);
- prev = ei->i_orphan.prev;
-- sbi = EXT3_SB(inode->i_sb);
-
- jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
-
-@@ -1871,7 +1870,7 @@ int ext3_orphan_del(handle_t *handle, st
- out_err:
- ext3_std_error(inode->i_sb, err);
- out:
-- unlock_super(inode->i_sb);
-+ up(&sbi->s_orphan_lock);
- return err;
-
- out_brelse:
---- linux-rh-2.4.20-8/fs/ext3/super.c~ext3_orphan_lock-2.4.20-rh 2003-05-05 19:49:15.000000000 +0800
-+++ linux-rh-2.4.20-8-root/fs/ext3/super.c 2003-05-05 19:54:09.000000000 +0800
-@@ -1151,6 +1151,7 @@ struct super_block * ext3_read_super (st
- */
- sb->s_op = &ext3_sops;
- INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
-+ sema_init(&sbi->s_orphan_lock, 1);
-
- sb->s_root = 0;
-
---- linux-rh-2.4.20-8/include/linux/ext3_fs_sb.h~ext3_orphan_lock-2.4.20-rh 2003-05-05 19:49:07.000000000 +0800
-+++ linux-rh-2.4.20-8-root/include/linux/ext3_fs_sb.h 2003-05-05 19:54:09.000000000 +0800
-@@ -69,6 +69,7 @@ struct ext3_sb_info {
- struct inode * s_journal_inode;
- struct journal_s * s_journal;
- struct list_head s_orphan;
-+ struct semaphore s_orphan_lock;
- unsigned long s_commit_interval;
- struct block_device *journal_bdev;
- #ifdef CONFIG_JBD_DEBUG
-
-_
+++ /dev/null
- fs/ext3/ialloc.c | 41 +++++++++++++++++++++++++++++++++++++++--
- fs/ext3/inode.c | 2 +-
- fs/ext3/ioctl.c | 25 +++++++++++++++++++++++++
- fs/ext3/namei.c | 21 +++++++++++++++++----
- include/linux/dcache.h | 5 +++++
- include/linux/ext3_fs.h | 5 ++++-
- 6 files changed, 91 insertions(+), 8 deletions(-)
-
---- linux-2.4.22-ac1/fs/ext3/ialloc.c~extN-wantedi-2.4.22-rh 2003-09-26 00:57:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/ialloc.c 2003-09-26 01:00:17.000000000 +0400
-@@ -524,7 +524,8 @@ static int find_group_other(struct super
- * group to find a free inode.
- */
- struct inode * ext3_new_inode (handle_t *handle,
-- const struct inode * dir, int mode)
-+ const struct inode * dir, int mode,
-+ unsigned long goal)
- {
- struct super_block * sb;
- struct buffer_head * bh;
-@@ -549,7 +550,41 @@ struct inode * ext3_new_inode (handle_t
- init_rwsem(&inode->u.ext3_i.truncate_sem);
-
- lock_super (sb);
-- es = sb->u.ext3_sb.s_es;
-+ es = EXT3_SB(sb)->s_es;
-+
-+ if (goal) {
-+ group = (goal - 1) / EXT3_INODES_PER_GROUP(sb);
-+ ino = (goal - 1) % EXT3_INODES_PER_GROUP(sb);
-+ gdp = ext3_get_group_desc(sb, group, &bh2);
-+
-+ bitmap_nr = load_inode_bitmap (sb, group);
-+ if (bitmap_nr < 0) {
-+ err = bitmap_nr;
-+ goto fail;
-+ }
-+
-+ bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr];
-+
-+ BUFFER_TRACE(bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, bh);
-+ if (err) goto fail;
-+
-+ if (ext3_set_bit(ino, bh->b_data)) {
-+ printk(KERN_ERR "goal inode %lu unavailable\n", goal);
-+ /* Oh well, we tried. */
-+ goto repeat;
-+ }
-+
-+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-+ err = ext3_journal_dirty_metadata(handle, bh);
-+ if (err) goto fail;
-+
-+ /* We've shortcircuited the allocation system successfully,
-+ * now finish filling in the inode.
-+ */
-+ goto have_bit_and_group;
-+ }
-+
- repeat:
- if (S_ISDIR(mode)) {
- if (test_opt (sb, OLDALLOC))
-@@ -606,6 +641,8 @@ repeat:
- }
- goto repeat;
- }
-+
-+have_bit_and_group:
- ino += group * EXT3_INODES_PER_GROUP(sb) + 1;
- if (ino < EXT3_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
- ext3_error (sb, "ext3_new_inode",
---- linux-2.4.22-ac1/fs/ext3/inode.c~extN-wantedi-2.4.22-rh 2003-09-26 00:57:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/inode.c 2003-09-26 00:57:29.000000000 +0400
-@@ -2614,7 +2614,7 @@ void ext3_truncate_thread(struct inode *
- if (IS_ERR(handle))
- goto out_truncate;
-
-- new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode);
-+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode, 0);
- if (IS_ERR(new_inode)) {
- ext3_debug("truncate inode %lu directly (no new inodes)\n",
- old_inode->i_ino);
---- linux-2.4.22-ac1/fs/ext3/ioctl.c~extN-wantedi-2.4.22-rh 2003-09-25 14:16:23.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/ioctl.c 2003-09-26 00:57:29.000000000 +0400
-@@ -23,6 +23,31 @@ int ext3_ioctl (struct inode * inode, st
- ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
-
- switch (cmd) {
-+ case EXT3_IOC_CREATE_INUM: {
-+ char name[32];
-+ struct dentry *dchild, *dparent;
-+ int rc = 0;
-+
-+ dparent = list_entry(inode->i_dentry.next, struct dentry,
-+ d_alias);
-+ snprintf(name, sizeof name, "%lu", arg);
-+ dchild = lookup_one_len(name, dparent, strlen(name));
-+ if (dchild->d_inode) {
-+ printk(KERN_ERR "%*s/%lu already exists (ino %lu)\n",
-+ dparent->d_name.len, dparent->d_name.name, arg,
-+ dchild->d_inode->i_ino);
-+ rc = -EEXIST;
-+ } else {
-+ dchild->d_fsdata = (void *)arg;
-+ rc = vfs_create(inode, dchild, 0644);
-+ if (rc)
-+ printk(KERN_ERR "vfs_create: %d\n", rc);
-+ else if (dchild->d_inode->i_ino != arg)
-+ rc = -EEXIST;
-+ }
-+ dput(dchild);
-+ return rc;
-+ }
- case EXT3_IOC_GETFLAGS:
- flags = inode->u.ext3_i.i_flags & EXT3_FL_USER_VISIBLE;
- return put_user(flags, (int *) arg);
---- linux-2.4.22-ac1/fs/ext3/namei.c~extN-wantedi-2.4.22-rh 2003-09-26 00:57:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/namei.c 2003-09-26 00:57:29.000000000 +0400
-@@ -1534,6 +1534,19 @@ static int ext3_add_nondir(handle_t *han
- return err;
- }
-
-+static struct inode * ext3_new_inode_wantedi(handle_t *handle, struct inode *dir,
-+ int mode, struct dentry *dentry)
-+{
-+ unsigned long inum = 0;
-+
-+ if (dentry->d_fsdata != NULL) {
-+ struct dentry_params *param =
-+ (struct dentry_params *) dentry->d_fsdata;
-+ inum = param->p_inum;
-+ }
-+ return ext3_new_inode(handle, dir, mode, inum);
-+}
-+
- /*
- * By the time this is called, we already have created
- * the directory cache entry for the new file, but it
-@@ -1557,7 +1570,7 @@ static int ext3_create (struct inode * d
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, mode);
-+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry);
- err = PTR_ERR(inode);
- if (!IS_ERR(inode)) {
- inode->i_op = &ext3_file_inode_operations;
-@@ -1585,7 +1598,7 @@ static int ext3_mknod (struct inode * di
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, mode);
-+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry);
- err = PTR_ERR(inode);
- if (!IS_ERR(inode)) {
- init_special_inode(inode, mode, rdev);
-@@ -1615,7 +1628,7 @@ static int ext3_mkdir(struct inode * dir
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
-+ inode = ext3_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
-@@ -2010,7 +2023,7 @@ static int ext3_symlink (struct inode *
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
-+ inode = ext3_new_inode_wantedi (handle, dir, S_IFLNK|S_IRWXUGO, dentry);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
---- linux-2.4.22-ac1/include/linux/dcache.h~extN-wantedi-2.4.22-rh 2003-09-26 00:57:27.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/dcache.h 2003-09-26 00:57:29.000000000 +0400
-@@ -63,6 +63,11 @@ static inline void intent_init(struct lo
-
- #define IS_ROOT(x) ((x) == (x)->d_parent)
-
-+struct dentry_params {
-+ unsigned long p_inum;
-+ void *p_ptr;
-+};
-+
- /*
- * "quick string" -- eases parameter passing, but more importantly
- * saves "metadata" about the string (ie length and the hash).
---- linux-2.4.22-ac1/include/linux/ext3_fs.h~extN-wantedi-2.4.22-rh 2003-09-26 00:57:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs.h 2003-09-26 00:57:29.000000000 +0400
-@@ -203,6 +203,7 @@ struct ext3_group_desc
- #define EXT3_IOC_SETFLAGS _IOW('f', 2, long)
- #define EXT3_IOC_GETVERSION _IOR('f', 3, long)
- #define EXT3_IOC_SETVERSION _IOW('f', 4, long)
-+/* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
- #define EXT3_IOC_GETVERSION_OLD _IOR('v', 1, long)
- #define EXT3_IOC_SETVERSION_OLD _IOW('v', 2, long)
- #ifdef CONFIG_JBD_DEBUG
-@@ -676,7 +677,8 @@ extern int ext3fs_dirhash(const char *na
- dx_hash_info *hinfo);
-
- /* ialloc.c */
--extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int);
-+extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int,
-+ unsigned long);
- extern void ext3_free_inode (handle_t *, struct inode *);
- extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);
- extern unsigned long ext3_count_free_inodes (struct super_block *);
-@@ -769,4 +771,5 @@ extern struct inode_operations ext3_fast
-
- #endif /* __KERNEL__ */
-
-+#define EXT3_IOC_CREATE_INUM _IOW('f', 5, long)
- #endif /* _LINUX_EXT3_FS_H */
-
-_
+++ /dev/null
---- kernel-2.4.20-6chaos_18_7/include/linux/module.h~gpl-header Wed Jul 16 03:54:37 2003
-+++ kernel-2.4.20-6chaos_18_7/include/linux/module.h Wed Jul 16 03:55:45 2003
-@@ -288,7 +288,7 @@
- "license=" license
-
- #define GPL_HEADER() \
--static const char cpyright="This software may be freely redistributed under the terms of the GNU General Public License.";
-+static const char cpyright[]="This software may be freely redistributed under the terms of the GNU General Public License.";
-
- /* Define the module variable, and usage macros. */
- extern struct module __this_module;
+++ /dev/null
- fs/Makefile | 4 +++-
- fs/inode.c | 4 +++-
- mm/Makefile | 2 +-
- mm/page_alloc.c | 1 +
- mm/vmscan.c | 3 +++
- 5 files changed, 11 insertions(+), 3 deletions(-)
-
---- linux-rh-2.4.20-6/fs/inode.c~iod-rmap-exports Tue Apr 1 01:01:56 2003
-+++ linux-rh-2.4.20-6-braam/fs/inode.c Tue Apr 1 01:01:56 2003
-@@ -5,6 +5,7 @@
- */
-
- #include <linux/config.h>
-+#include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/string.h>
- #include <linux/mm.h>
-@@ -66,7 +67,8 @@ static LIST_HEAD(anon_hash_chain); /* fo
- * NOTE! You also have to own the lock if you change
- * the i_state of an inode while it is in use..
- */
--static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+EXPORT_SYMBOL(inode_lock);
-
- /*
- * Statistics gathering..
---- linux-rh-2.4.20-6/fs/Makefile~iod-rmap-exports Tue Apr 1 01:01:56 2003
-+++ linux-rh-2.4.20-6-braam/fs/Makefile Tue Apr 1 01:02:34 2003
-@@ -1,3 +1,5 @@
-+
-+
- #
- # Makefile for the Linux filesystems.
- #
-@@ -7,7 +9,7 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o
-+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o inode.o
- mod-subdirs := nls
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
---- linux-rh-2.4.20-6/mm/vmscan.c~iod-rmap-exports Tue Apr 1 01:01:56 2003
-+++ linux-rh-2.4.20-6-braam/mm/vmscan.c Tue Apr 1 01:01:56 2003
-@@ -15,6 +15,8 @@
- * O(1) rmap vm, Arjan van de ven <arjanv@redhat.com>
- */
-
-+#include <linux/config.h>
-+#include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
-@@ -1061,6 +1063,7 @@ void wakeup_kswapd(unsigned int gfp_mask
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&kswapd_done, &wait);
- }
-+EXPORT_SYMBOL(wakeup_kswapd);
-
- static void wakeup_memwaiters(void)
- {
---- linux-rh-2.4.20-6/mm/Makefile~iod-rmap-exports Tue Apr 1 01:01:56 2003
-+++ linux-rh-2.4.20-6-braam/mm/Makefile Tue Apr 1 01:01:56 2003
-@@ -9,7 +9,7 @@
-
- O_TARGET := mm.o
-
--export-objs := shmem.o filemap.o memory.o page_alloc.o mempool.o
-+export-objs := shmem.o filemap.o memory.o page_alloc.o mempool.o vmscan.o
-
- obj-y := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \
- vmalloc.o slab.o bootmem.o swap.o vmscan.o page_io.o \
---- linux-rh-2.4.20-6/mm/page_alloc.c~iod-rmap-exports Tue Apr 1 01:01:56 2003
-+++ linux-rh-2.4.20-6-braam/mm/page_alloc.c Tue Apr 1 01:01:56 2003
-@@ -27,6 +27,7 @@
-
- int nr_swap_pages;
- pg_data_t *pgdat_list;
-+EXPORT_SYMBOL(pgdat_list);
-
- /*
- *
-
-_
+++ /dev/null
- fs/Makefile | 2 +-
- fs/inode.c | 4 +++-
- mm/page_alloc.c | 1 +
- 3 files changed, 5 insertions(+), 2 deletions(-)
-
---- linux-2.4.20/fs/inode.c~iod-stock-24-exports Wed Apr 2 23:21:20 2003
-+++ linux-2.4.20-braam/fs/inode.c Wed Apr 2 23:21:20 2003
-@@ -5,6 +5,7 @@
- */
-
- #include <linux/config.h>
-+#include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/string.h>
- #include <linux/mm.h>
-@@ -66,7 +67,8 @@ static LIST_HEAD(anon_hash_chain); /* fo
- * NOTE! You also have to own the lock if you change
- * the i_state of an inode while it is in use..
- */
--static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+EXPORT_SYMBOL(inode_lock);
-
- /*
- * Statistics gathering..
---- linux-2.4.20/fs/Makefile~iod-stock-24-exports Wed Apr 2 23:21:20 2003
-+++ linux-2.4.20-braam/fs/Makefile Wed Apr 2 23:21:53 2003
-@@ -7,7 +7,7 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o
-+export-objs := filesystems.o open.o dcache.o buffer.o inode.o
- mod-subdirs := nls
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
---- linux-2.4.20/mm/page_alloc.c~iod-stock-24-exports Wed Apr 2 23:21:20 2003
-+++ linux-2.4.20-braam/mm/page_alloc.c Wed Apr 2 23:21:20 2003
-@@ -28,6 +28,7 @@ int nr_inactive_pages;
- LIST_HEAD(inactive_list);
- LIST_HEAD(active_list);
- pg_data_t *pgdat_list;
-+EXPORT_SYMBOL(pgdat_list);
-
- /*
- *
-
-_
+++ /dev/null
- fs/Makefile | 2 +-
- fs/inode.c | 4 +++-
- mm/page_alloc.c | 1 +
- 3 files changed, 5 insertions(+), 2 deletions(-)
-
---- linux-2.4.22-ac1/fs/inode.c~iod-stock-exports-2.4.22-rh 2003-09-25 14:45:32.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/inode.c 2003-09-25 14:49:41.000000000 +0400
-@@ -5,6 +5,7 @@
- */
-
- #include <linux/config.h>
-+#include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/string.h>
- #include <linux/mm.h>
-@@ -68,7 +69,8 @@ static LIST_HEAD(anon_hash_chain); /* fo
- * NOTE! You also have to own the lock if you change
- * the i_state of an inode while it is in use..
- */
--static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+EXPORT_SYMBOL(inode_lock);
-
- /*
- * Statistics gathering..
---- linux-2.4.22-ac1/fs/Makefile~iod-stock-exports-2.4.22-rh 2003-09-25 14:16:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/Makefile 2003-09-25 14:50:00.000000000 +0400
-@@ -7,7 +7,7 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o
-+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o inode.o
- mod-subdirs := nls xfs
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
---- linux-2.4.22-ac1/mm/page_alloc.c~iod-stock-exports-2.4.22-rh 2003-09-25 14:16:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/mm/page_alloc.c 2003-09-25 14:49:41.000000000 +0400
-@@ -28,6 +28,7 @@ int nr_inactive_pages;
- LIST_HEAD(inactive_list);
- LIST_HEAD(active_list);
- pg_data_t *pgdat_list;
-+EXPORT_SYMBOL(pgdat_list);
-
- /*
- *
-
-_
+++ /dev/null
-Index: linux-2.4.21-241/arch/um/kernel/Makefile
-===================================================================
---- linux-2.4.21-241.orig/arch/um/kernel/Makefile 2004-10-03 17:30:07.000000000 -0400
-+++ linux-2.4.21-241/arch/um/kernel/Makefile 2004-10-04 02:51:20.000000000 -0400
-@@ -37,7 +37,8 @@
- export-objs-$(CONFIG_GPROF) += gprof_syms.o
- export-objs-$(CONFIG_GCOV) += gmon_syms.o
-
--export-objs = ksyms.o process_kern.o signal_kern.o user_syms.o $(export-objs-y)
-+export-objs = ksyms.o process_kern.o signal_kern.o user_syms.o sysrq.o \
-+ $(export-objs-y)
-
- CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \
- -I/usr/include -I../include
-Index: linux-2.4.21-241/arch/um/kernel/sysrq.c
-===================================================================
---- linux-2.4.21-241.orig/arch/um/kernel/sysrq.c 2004-10-03 17:30:07.000000000 -0400
-+++ linux-2.4.21-241/arch/um/kernel/sysrq.c 2004-10-04 02:51:20.000000000 -0400
-@@ -86,6 +86,37 @@
- show_trace((unsigned long *)esp);
- }
-
-+#ifdef CONFIG_MODULES
-+extern struct module *module_list;
-+extern struct module kernel_module;
-+#endif
-+
-+int is_kernel_text_address(unsigned long addr)
-+{
-+ int retval = 0;
-+#ifdef CONFIG_MODULES
-+ struct module *mod;
-+#endif
-+ if (addr >= (unsigned long) &_stext &&
-+ addr <= (unsigned long) &_etext)
-+ return 1;
-+
-+#ifdef CONFIG_MODULES
-+ for (mod = module_list; mod != &kernel_module; mod = mod->next) {
-+ /* mod_bound tests for addr being inside the vmalloc'ed
-+ * module area. Of course it'd be better to test only
-+ * for the .text subset... */
-+ if (mod_bound(addr, 0, mod)) {
-+ retval = 1;
-+ break;
-+ }
-+ }
-+#endif
-+ return retval;
-+}
-+
-+EXPORT_SYMBOL(is_kernel_text_address);
-+
- /*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
-Index: linux-2.4.21-241/arch/i386/kernel/Makefile
-===================================================================
---- linux-2.4.21-241.orig/arch/i386/kernel/Makefile 2004-10-03 17:31:39.000000000 -0400
-+++ linux-2.4.21-241/arch/i386/kernel/Makefile 2004-10-04 02:52:04.000000000 -0400
-@@ -20,7 +20,8 @@
-
- O_TARGET := kernel.o
-
--export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o dr_alloc.o
-+export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o \
-+ traps.o dr_alloc.o
-
- ifdef CONFIG_X86_SPEEDSTEP_ICH
- export-objs += speedstep-lib.o
-Index: linux-2.4.21-241/arch/i386/kernel/traps.c
-===================================================================
---- linux-2.4.21-241.orig/arch/i386/kernel/traps.c 2004-10-04 02:48:05.000000000 -0400
-+++ linux-2.4.21-241/arch/i386/kernel/traps.c 2004-10-04 02:51:20.000000000 -0400
-@@ -1339,3 +1339,41 @@
- cobalt_init();
- #endif
- }
-+
-+#ifdef CONFIG_MODULES
-+extern struct module *module_list;
-+extern struct module kernel_module;
-+#endif
-+
-+int is_kernel_text_address(unsigned long addr)
-+{
-+ int retval = 0;
-+#ifdef CONFIG_MODULES
-+ struct module *mod;
-+#endif
-+ if (addr >= (unsigned long) &_stext &&
-+ addr <= (unsigned long) &_etext);
-+ return 1;
-+
-+#ifdef CONFIG_MODULES
-+ for (mod = module_list; mod != &kernel_module; mod = mod->next) {
-+ /* mod_bound tests for addr being inside the vmalloc'ed
-+ * module area. Of course it'd be better to test only
-+ * for the .text subset... */
-+ if (mod_bound(addr, 0, mod)) {
-+ retval = 1;
-+ break;
-+ }
-+ }
-+#endif
-+
-+ return retval;
-+}
-+
-+int lookup_symbol(unsigned long address, char *buf, int buflen)
-+{
-+ return -ENOSYS;
-+}
-+
-+EXPORT_SYMBOL_GPL(is_kernel_text_address);
-+EXPORT_SYMBOL_GPL(lookup_symbol);
+++ /dev/null
- Documentation/Configure.help | 66 ++
- arch/alpha/defconfig | 7
- arch/alpha/kernel/entry.S | 12
- arch/arm/defconfig | 7
- arch/arm/kernel/calls.S | 24
- arch/i386/defconfig | 7
- arch/ia64/defconfig | 7
- arch/m68k/defconfig | 7
- arch/mips/defconfig | 7
- arch/mips64/defconfig | 7
- arch/ppc/defconfig | 14
- arch/ppc64/kernel/misc.S | 2
- arch/s390/defconfig | 7
- arch/s390/kernel/entry.S | 24
- arch/s390x/defconfig | 7
- arch/s390x/kernel/entry.S | 24
- arch/s390x/kernel/wrapper32.S | 92 +++
- arch/sparc/defconfig | 7
- arch/sparc/kernel/systbls.S | 10
- arch/sparc64/defconfig | 7
- arch/sparc64/kernel/systbls.S | 20
- fs/Config.in | 14
- fs/Makefile | 3
- fs/ext2/Makefile | 4
- fs/ext2/file.c | 5
- fs/ext2/ialloc.c | 2
- fs/ext2/inode.c | 34 -
- fs/ext2/namei.c | 14
- fs/ext2/super.c | 29
- fs/ext2/symlink.c | 14
- fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++
- fs/ext2/xattr_user.c | 103 +++
- fs/ext3/Makefile | 10
- fs/ext3/ext3-exports.c | 13
- fs/ext3/file.c | 5
- fs/ext3/ialloc.c | 2
- fs/ext3/inode.c | 35 -
- fs/ext3/namei.c | 21
- fs/ext3/super.c | 36 +
- fs/ext3/symlink.c | 14
- fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++
- fs/ext3/xattr_user.c | 111 +++
- fs/jfs/jfs_xattr.h | 6
- fs/jfs/xattr.c | 6
- fs/mbcache.c | 648 ++++++++++++++++++++++
- include/asm-arm/unistd.h | 2
- include/asm-ppc64/unistd.h | 2
- include/asm-s390/unistd.h | 15
- include/asm-s390x/unistd.h | 15
- include/asm-sparc/unistd.h | 24
- include/asm-sparc64/unistd.h | 24
- include/linux/cache_def.h | 15
- include/linux/errno.h | 4
- include/linux/ext2_fs.h | 31 -
- include/linux/ext2_xattr.h | 157 +++++
- include/linux/ext3_fs.h | 31 -
- include/linux/ext3_jbd.h | 8
- include/linux/ext3_xattr.h | 157 +++++
- include/linux/fs.h | 2
- include/linux/mbcache.h | 69 ++
- kernel/ksyms.c | 4
- mm/vmscan.c | 36 +
- 62 files changed, 4344 insertions(+), 183 deletions(-)
-
---- kernel-2.4.20-6chaos_18_7/Documentation/Configure.help~linux-2.4.20-xattr-0.8.54-chaos 2003-06-23 10:39:21.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/Documentation/Configure.help 2003-07-12 15:34:44.000000000 -0600
-@@ -15253,6 +15253,39 @@ CONFIG_EXT2_FS
- be compiled as a module, and so this could be dangerous. Most
- everyone wants to say Y here.
-
-+Ext2 extended attributes
-+CONFIG_EXT2_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.
-+
-+Ext2 extended attribute block sharing
-+CONFIG_EXT2_FS_XATTR_SHARING
-+ This options enables code for sharing identical extended attribute
-+ blocks among multiple inodes.
-+
-+ Usually, say Y.
-+
-+Ext2 extended user attributes
-+CONFIG_EXT2_FS_XATTR_USER
-+ This option enables extended user attributes on ext2. Processes can
-+ associate extended user attributes with inodes to store additional
-+ information such as the character encoding of files, etc. (see the
-+ attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext2 trusted extended attributes
-+CONFIG_EXT2_FS_XATTR_TRUSTED
-+ This option enables extended attributes on ext2 that are accessible
-+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
-+ is only the super user. Trusted extended attributes are meant for
-+ implementing system/security services.
-+
-+ If unsure, say N.
-+
- Ext3 journalling file system support (EXPERIMENTAL)
- CONFIG_EXT3_FS
- This is the journalling version of the Second extended file system
-@@ -15285,6 +15318,39 @@ CONFIG_EXT3_FS
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this may be dangerous.
-
-+Ext3 extended attributes
-+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.
-+
-+Ext3 extended attribute block sharing
-+CONFIG_EXT3_FS_XATTR_SHARING
-+ This options enables code for sharing identical extended attribute
-+ blocks among multiple inodes.
-+
-+ Usually, say Y.
-+
-+Ext3 extended user attributes
-+CONFIG_EXT3_FS_XATTR_USER
-+ This option enables extended user attributes on ext3. Processes can
-+ associate extended user attributes with inodes to store additional
-+ information such as the character encoding of files, etc. (see the
-+ attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext3 trusted extended attributes
-+CONFIG_EXT3_FS_XATTR_TRUSTED
-+ This option enables extended attributes on ext3 that are accessible
-+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
-+ is only the super user. Trusted extended attributes are meant for
-+ implementing system/security services.
-+
-+ If unsure, say N.
-+
- Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
- CONFIG_JBD
- This is a generic journalling layer for block devices. It is
---- kernel-2.4.20-6chaos_18_7/arch/alpha/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:54.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/alpha/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_ALPHA=y
- # CONFIG_UID16 is not set
- # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
---- kernel-2.4.20-6chaos_18_7/arch/alpha/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:11:53.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/alpha/kernel/entry.S 2003-07-12 15:34:44.000000000 -0600
-@@ -1162,6 +1162,18 @@ sys_call_table:
- .quad sys_readahead
- .quad sys_ni_syscall /* 380, sys_security */
- .quad sys_tkill
-+ .quad sys_setxattr
-+ .quad sys_lsetxattr
-+ .quad sys_fsetxattr
-+ .quad sys_getxattr /* 385 */
-+ .quad sys_lgetxattr
-+ .quad sys_fgetxattr
-+ .quad sys_listxattr
-+ .quad sys_llistxattr
-+ .quad sys_flistxattr /* 390 */
-+ .quad sys_removexattr
-+ .quad sys_lremovexattr
-+ .quad sys_fremovexattr
-
- /* Remember to update everything, kids. */
- .ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
---- kernel-2.4.20-6chaos_18_7/arch/arm/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:56.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/arm/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_ARM=y
- # CONFIG_EISA is not set
- # CONFIG_SBUS is not set
---- kernel-2.4.20-6chaos_18_7/arch/arm/kernel/calls.S~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:09:16.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/arm/kernel/calls.S 2003-07-12 15:34:44.000000000 -0600
-@@ -240,18 +240,18 @@ __syscall_start:
- .long SYMBOL_NAME(sys_ni_syscall) /* Security */
- .long SYMBOL_NAME(sys_gettid)
- /* 225 */ .long SYMBOL_NAME(sys_readahead)
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_setxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_lsetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_fsetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_getxattr */
--/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_lgetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_fgetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_listxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_llistxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_flistxattr */
--/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_removexattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_lremovexattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_fremovexattr */
-+ .long SYMBOL_NAME(sys_setxattr)
-+ .long SYMBOL_NAME(sys_lsetxattr)
-+ .long SYMBOL_NAME(sys_fsetxattr)
-+ .long SYMBOL_NAME(sys_getxattr)
-+/* 230 */ .long SYMBOL_NAME(sys_lgetxattr)
-+ .long SYMBOL_NAME(sys_fgetxattr)
-+ .long SYMBOL_NAME(sys_listxattr)
-+ .long SYMBOL_NAME(sys_llistxattr)
-+ .long SYMBOL_NAME(sys_flistxattr)
-+/* 235 */ .long SYMBOL_NAME(sys_removexattr)
-+ .long SYMBOL_NAME(sys_lremovexattr)
-+ .long SYMBOL_NAME(sys_fremovexattr)
- .long SYMBOL_NAME(sys_tkill)
- /*
- * Please check 2.5 _before_ adding calls here,
---- kernel-2.4.20-6chaos_18_7/arch/i386/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:12:00.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/i386/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_X86=y
- CONFIG_ISA=y
- # CONFIG_SBUS is not set
---- kernel-2.4.20-6chaos_18_7/arch/ia64/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:12:04.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/ia64/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
-
- #
- # Code maturity level options
---- kernel-2.4.20-6chaos_18_7/arch/m68k/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:55.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/m68k/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_UID16=y
-
- #
---- kernel-2.4.20-6chaos_18_7/arch/mips/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:06.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/mips/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_MIPS=y
- CONFIG_MIPS32=y
- # CONFIG_MIPS64 is not set
---- kernel-2.4.20-6chaos_18_7/arch/mips64/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:11.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/mips64/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_MIPS=y
- # CONFIG_MIPS32 is not set
- CONFIG_MIPS64=y
---- kernel-2.4.20-6chaos_18_7/arch/ppc/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:12:20.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/ppc/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_UID16 is not set
- # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
- CONFIG_RWSEM_XCHGADD_ALGORITHM=y
---- kernel-2.4.20-6chaos_18_7/arch/ppc64/kernel/misc.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:20.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/ppc64/kernel/misc.S 2003-07-12 15:34:44.000000000 -0600
-@@ -731,6 +731,7 @@ _GLOBAL(sys_call_table32)
- .llong .sys_gettid /* 207 */
- #if 0 /* Reserved syscalls */
- .llong .sys_tkill /* 208 */
-+#endif
- .llong .sys_setxattr
- .llong .sys_lsetxattr /* 210 */
- .llong .sys_fsetxattr
-@@ -743,6 +744,7 @@ _GLOBAL(sys_call_table32)
- .llong .sys_removexattr
- .llong .sys_lremovexattr
- .llong .sys_fremovexattr /* 220 */
-+#if 0 /* Reserved syscalls */
- .llong .sys_futex
- #endif
- .llong .sys_perfmonctl /* Put this here for now ... */
---- kernel-2.4.20-6chaos_18_7/arch/s390/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:20.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/s390/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_ISA is not set
- # CONFIG_EISA is not set
- # CONFIG_MCA is not set
---- kernel-2.4.20-6chaos_18_7/arch/s390/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:20.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/s390/kernel/entry.S 2003-07-12 15:34:44.000000000 -0600
-@@ -558,18 +558,18 @@ sys_call_table:
- .long sys_fcntl64
- .long sys_ni_syscall
- .long sys_ni_syscall
-- .long sys_ni_syscall /* 224 - reserved for setxattr */
-- .long sys_ni_syscall /* 225 - reserved for lsetxattr */
-- .long sys_ni_syscall /* 226 - reserved for fsetxattr */
-- .long sys_ni_syscall /* 227 - reserved for getxattr */
-- .long sys_ni_syscall /* 228 - reserved for lgetxattr */
-- .long sys_ni_syscall /* 229 - reserved for fgetxattr */
-- .long sys_ni_syscall /* 230 - reserved for listxattr */
-- .long sys_ni_syscall /* 231 - reserved for llistxattr */
-- .long sys_ni_syscall /* 232 - reserved for flistxattr */
-- .long sys_ni_syscall /* 233 - reserved for removexattr */
-- .long sys_ni_syscall /* 234 - reserved for lremovexattr */
-- .long sys_ni_syscall /* 235 - reserved for fremovexattr */
-+ .long sys_setxattr
-+ .long sys_lsetxattr /* 225 */
-+ .long sys_fsetxattr
-+ .long sys_getxattr
-+ .long sys_lgetxattr
-+ .long sys_fgetxattr
-+ .long sys_listxattr /* 230 */
-+ .long sys_llistxattr
-+ .long sys_flistxattr
-+ .long sys_removexattr
-+ .long sys_lremovexattr
-+ .long sys_fremovexattr /* 235 */
- .long sys_gettid
- .long sys_tkill
- .rept 255-237
---- kernel-2.4.20-6chaos_18_7/arch/s390x/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:21.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_ISA is not set
- # CONFIG_EISA is not set
- # CONFIG_MCA is not set
---- kernel-2.4.20-6chaos_18_7/arch/s390x/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:21.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/kernel/entry.S 2003-07-12 15:34:44.000000000 -0600
-@@ -591,18 +591,18 @@ sys_call_table:
- .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
- .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
- .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
-+ .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
-+ .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
-+ .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
-+ .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
-+ .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
-+ .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
-+ .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
-+ .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
-+ .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
-+ .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
-+ .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
-+ .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
- .long SYSCALL(sys_gettid,sys_gettid)
- .long SYSCALL(sys_tkill,sys_tkill)
- .rept 255-237
---- kernel-2.4.20-6chaos_18_7/arch/s390x/kernel/wrapper32.S~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:59.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/kernel/wrapper32.S 2003-07-12 15:34:44.000000000 -0600
-@@ -1091,3 +1091,95 @@ sys32_fstat64_wrapper:
- llgtr %r3,%r3 # struct stat64 *
- llgfr %r4,%r4 # long
- jg sys32_fstat64 # branch to system call
-+
-+ .globl sys32_setxattr_wrapper
-+sys32_setxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_setxattr
-+
-+ .globl sys32_lsetxattr_wrapper
-+sys32_lsetxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_lsetxattr
-+
-+ .globl sys32_fsetxattr_wrapper
-+sys32_fsetxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_fsetxattr
-+
-+ .globl sys32_getxattr_wrapper
-+sys32_getxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_getxattr
-+
-+ .globl sys32_lgetxattr_wrapper
-+sys32_lgetxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_lgetxattr
-+
-+ .globl sys32_fgetxattr_wrapper
-+sys32_fgetxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_fgetxattr
-+
-+ .globl sys32_listxattr_wrapper
-+sys32_listxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_listxattr
-+
-+ .globl sys32_llistxattr_wrapper
-+sys32_llistxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_llistxattr
-+
-+ .globl sys32_flistxattr_wrapper
-+sys32_flistxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_flistxattr
-+
-+ .globl sys32_removexattr_wrapper
-+sys32_removexattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ jg sys_removexattr
-+
-+ .globl sys32_lremovexattr_wrapper
-+sys32_lremovexattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ jg sys_lremovexattr
-+
-+ .globl sys32_fremovexattr_wrapper
-+sys32_fremovexattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ jg sys_fremovexattr
-+
-+
---- kernel-2.4.20-6chaos_18_7/arch/sparc/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:10:50.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_UID16=y
- CONFIG_HIGHMEM=y
-
---- kernel-2.4.20-6chaos_18_7/arch/sparc/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:10:52.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc/kernel/systbls.S 2003-07-12 15:34:44.000000000 -0600
-@@ -51,11 +51,11 @@ sys_call_table:
- /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
- /*155*/ .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
- /*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
--/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
--/*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
--/*175*/ .long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
--/*180*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
--/*185*/ .long sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sys_newuname
-+/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
-+/*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
-+/*175*/ .long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
-+/*180*/ .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_query_module
-+/*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sys_newuname
- /*190*/ .long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
- /*195*/ .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
- /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
---- kernel-2.4.20-6chaos_18_7/arch/sparc64/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:12:29.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc64/defconfig 2003-07-12 15:34:44.000000000 -0600
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
-
- #
- # Code maturity level options
---- kernel-2.4.20-6chaos_18_7/arch/sparc64/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:10:55.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc64/kernel/systbls.S 2003-07-12 15:34:44.000000000 -0600
-@@ -52,11 +52,11 @@ sys_call_table32:
- /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
- .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
- /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
-- .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
--/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
-- .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
--/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
-- .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
-+ .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
-+/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
-+ .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
-+/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module
-+ .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
- /*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
- .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
- /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
-@@ -111,11 +111,11 @@ sys_call_table:
- /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
- .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
- /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
-- .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
--/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
-- .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
--/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
-- .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
-+ .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
-+/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
-+ .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
-+/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module
-+ .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
- /*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
- .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
- /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
---- kernel-2.4.20-6chaos_18_7/fs/Config.in~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:24.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/Config.in 2003-07-12 15:34:44.000000000 -0600
-@@ -34,6 +34,11 @@ dep_mbool ' Debug Befs' CONFIG_BEFS_DEB
- 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
-+dep_bool ' Ext3 extended attribute block sharing' \
-+ CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
-+dep_bool ' Ext3 extended user attributes' \
-+ CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
- # 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
-@@ -93,6 +98,11 @@ dep_mbool ' QNX4FS write support (DANGE
- tristate 'ROM file system support' CONFIG_ROMFS_FS
-
- tristate 'Second extended fs support' CONFIG_EXT2_FS
-+dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
-+dep_bool ' Ext2 extended attribute block sharing' \
-+ CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
-+dep_bool ' Ext2 extended user attributes' \
-+ CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
-
- tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
-
-@@ -164,6 +174,10 @@ else
- define_tristate CONFIG_ZISOFS_FS n
- fi
-
-+# Meta block cache for Extended Attributes (ext2/ext3)
-+#tristate 'Meta block cache' CONFIG_FS_MBCACHE
-+define_tristate CONFIG_FS_MBCACHE y
-+
- mainmenu_option next_comment
- comment 'Partition Types'
- source fs/partitions/Config.in
---- kernel-2.4.20-6chaos_18_7/fs/Makefile~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:34.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/Makefile 2003-07-12 15:34:44.000000000 -0600
-@@ -84,6 +84,9 @@ obj-y += binfmt_script.o
-
- obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
-
-+export-objs += mbcache.o
-+obj-$(CONFIG_FS_MBCACHE) += mbcache.o
-+
- # persistent filesystems
- obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
-
---- kernel-2.4.20-6chaos_18_7/fs/ext2/Makefile~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/Makefile 2003-07-12 15:34:44.000000000 -0600
-@@ -13,4 +13,8 @@ obj-y := balloc.o bitmap.o dir.o file
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
-
-+export-objs += xattr.o
-+obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
-+obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
-+
- include $(TOPDIR)/Rules.make
---- kernel-2.4.20-6chaos_18_7/fs/ext2/file.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/file.c 2003-07-12 15:34:44.000000000 -0600
-@@ -20,6 +20,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/sched.h>
-
- /*
-@@ -51,4 +52,8 @@ struct file_operations ext2_file_operati
-
- struct inode_operations ext2_file_inode_operations = {
- truncate: ext2_truncate,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
---- kernel-2.4.20-6chaos_18_7/fs/ext2/ialloc.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:09.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/ialloc.c 2003-07-12 15:34:44.000000000 -0600
-@@ -15,6 +15,7 @@
- #include <linux/config.h>
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/locks.h>
- #include <linux/quotaops.h>
-
-@@ -167,6 +168,7 @@ void ext2_free_inode (struct inode * ino
- */
- if (!is_bad_inode(inode)) {
- /* Quota is already initialized in iput() */
-+ ext2_xattr_delete_inode(inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
- }
---- kernel-2.4.20-6chaos_18_7/fs/ext2/inode.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:09.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/inode.c 2003-07-12 15:34:44.000000000 -0600
-@@ -39,6 +39,18 @@ MODULE_LICENSE("GPL");
- static int ext2_update_inode(struct inode * inode, int do_sync);
-
- /*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext2_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = inode->u.ext2_i.i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
-+/*
- * Called at each iput()
- */
- void ext2_put_inode (struct inode * inode)
-@@ -53,9 +65,7 @@ void ext2_delete_inode (struct inode * i
- {
- lock_kernel();
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT2_ACL_IDX_INO ||
-- inode->i_ino == EXT2_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
- inode->u.ext2_i.i_dtime = CURRENT_TIME;
- mark_inode_dirty(inode);
-@@ -801,6 +811,8 @@ void ext2_truncate (struct inode * inode
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext2_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -888,8 +900,7 @@ void ext2_read_inode (struct inode * ino
- unsigned long offset;
- struct ext2_group_desc * gdp;
-
-- if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
-- inode->i_ino != EXT2_ACL_DATA_INO &&
-+ if ((inode->i_ino != EXT2_ROOT_INO &&
- inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
- ext2_error (inode->i_sb, "ext2_read_inode",
-@@ -974,10 +985,7 @@ void ext2_read_inode (struct inode * ino
- for (block = 0; block < EXT2_N_BLOCKS; block++)
- inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
-
-- if (inode->i_ino == EXT2_ACL_IDX_INO ||
-- inode->i_ino == EXT2_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext2_file_inode_operations;
- inode->i_fop = &ext2_file_operations;
- inode->i_mapping->a_ops = &ext2_aops;
-@@ -986,15 +994,17 @@ void ext2_read_inode (struct inode * ino
- inode->i_fop = &ext2_dir_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext2_inode_is_fast_symlink(inode))
- inode->i_op = &ext2_fast_symlink_inode_operations;
- else {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext2_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- }
-- } else
-+ } else {
-+ inode->i_op = &ext2_special_inode_operations;
- init_special_inode(inode, inode->i_mode,
- le32_to_cpu(raw_inode->i_block[0]));
-+ }
- brelse (bh);
- inode->i_attr_flags = 0;
- if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
---- kernel-2.4.20-6chaos_18_7/fs/ext2/namei.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/namei.c 2003-07-12 15:34:44.000000000 -0600
-@@ -31,6 +31,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/pagemap.h>
-
- /*
-@@ -136,7 +137,7 @@ static int ext2_symlink (struct inode *
-
- if (l > sizeof (inode->u.ext2_i.i_data)) {
- /* slow symlink */
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext2_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- err = block_symlink(inode, symname, l);
- if (err)
-@@ -345,4 +346,15 @@ struct inode_operations ext2_dir_inode_o
- rmdir: ext2_rmdir,
- mknod: ext2_mknod,
- rename: ext2_rename,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
-+};
-+
-+struct inode_operations ext2_special_inode_operations = {
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
---- kernel-2.4.20-6chaos_18_7/fs/ext2/super.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:09.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/super.c 2003-07-12 15:34:44.000000000 -0600
-@@ -21,6 +21,7 @@
- #include <linux/string.h>
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/locks.h>
-@@ -125,6 +126,7 @@ void ext2_put_super (struct super_block
- int db_count;
- int i;
-
-+ ext2_xattr_put_super(sb);
- if (!(sb->s_flags & MS_RDONLY)) {
- struct ext2_super_block *es = EXT2_SB(sb)->s_es;
-
-@@ -175,6 +177,13 @@ static int parse_options (char * options
- this_char = strtok (NULL, ",")) {
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT2_FS_XATTR_USER
-+ 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")) {
-@@ -424,6 +433,9 @@ struct super_block * ext2_read_super (st
- blocksize = BLOCK_SIZE;
-
- sb->u.ext2_sb.s_mount_opt = 0;
-+#ifdef CONFIG_EXT2_FS_XATTR_USER
-+ /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
-+#endif
- if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
- &sb->u.ext2_sb.s_mount_opt)) {
- return NULL;
-@@ -813,12 +825,27 @@ static DECLARE_FSTYPE_DEV(ext2_fs_type,
-
- static int __init init_ext2_fs(void)
- {
-- return register_filesystem(&ext2_fs_type);
-+ int error = init_ext2_xattr();
-+ if (error)
-+ return error;
-+ error = init_ext2_xattr_user();
-+ if (error)
-+ goto fail;
-+ error = register_filesystem(&ext2_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext2_xattr_user();
-+fail:
-+ exit_ext2_xattr();
-+ return error;
- }
-
- static void __exit exit_ext2_fs(void)
- {
- unregister_filesystem(&ext2_fs_type);
-+ exit_ext2_xattr_user();
-+ exit_ext2_xattr();
- }
-
- EXPORT_NO_SYMBOLS;
---- kernel-2.4.20-6chaos_18_7/fs/ext2/symlink.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/symlink.c 2003-07-12 15:34:44.000000000 -0600
-@@ -19,6 +19,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-
- static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-@@ -32,7 +33,20 @@ static int ext2_follow_link(struct dentr
- return vfs_follow_link(nd, s);
- }
-
-+struct inode_operations ext2_symlink_inode_operations = {
-+ readlink: page_readlink,
-+ follow_link: page_follow_link,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
-+};
-+
- struct inode_operations ext2_fast_symlink_inode_operations = {
- readlink: ext2_readlink,
- follow_link: ext2_follow_link,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/xattr.c 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,1212 @@
-+/*
-+ * linux/fs/ext2/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * 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 EXT2_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 EXT2_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 ext2_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/module.h>
-+#include <linux/locks.h>
-+#include <linux/slab.h>
-+#include <linux/fs.h>
-+#include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-+#include <linux/mbcache.h>
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include <linux/compatmac.h>
-+
-+/* These symbols may be needed by a module. */
-+EXPORT_SYMBOL(ext2_xattr_register);
-+EXPORT_SYMBOL(ext2_xattr_unregister);
-+EXPORT_SYMBOL(ext2_xattr_get);
-+EXPORT_SYMBOL(ext2_xattr_list);
-+EXPORT_SYMBOL(ext2_xattr_set);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
-+#endif
-+
-+#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT2_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 ext2_xattr_set2(struct inode *, struct buffer_head *,
-+ struct ext2_xattr_header *);
-+
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+
-+static int ext2_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext2_xattr_cache_find(struct inode *,
-+ struct ext2_xattr_header *);
-+static void ext2_xattr_cache_remove(struct buffer_head *);
-+static void ext2_xattr_rehash(struct ext2_xattr_header *,
-+ struct ext2_xattr_entry *);
-+
-+static struct mb_cache *ext2_xattr_cache;
-+
-+#else
-+# define ext2_xattr_cache_insert(bh) 0
-+# define ext2_xattr_cache_find(inode, header) NULL
-+# define ext2_xattr_cache_remove(bh) while(0) {}
-+# define ext2_xattr_rehash(header, entry) while(0) {}
-+#endif
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext2_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+DECLARE_MUTEX(ext2_xattr_sem);
-+
-+static inline int
-+ext2_xattr_new_block(struct inode *inode, int * errp, int force)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
-+ EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
-+
-+ /* How can we enforce the allocation? */
-+ int block = ext2_new_block(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
-+ext2_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
-+ext2_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
-+ext2_xattr_free_block(struct inode * inode, unsigned long block)
-+{
-+ ext2_free_blocks(inode, block, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+#else
-+# define ext2_xattr_quota_free(inode) \
-+ DQUOT_FREE_BLOCK(inode, 1)
-+# define ext2_xattr_free_block(inode, block) \
-+ ext2_free_blocks(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 ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
-+rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ write_lock(&ext2_handler_lock);
-+ if (!ext2_xattr_handlers[name_index-1]) {
-+ ext2_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext2_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
-+{
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ write_lock(&ext2_handler_lock);
-+ ext2_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext2_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 struct ext2_xattr_handler *
-+ext2_xattr_resolve_name(const char **name)
-+{
-+ struct ext2_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext2_handler_lock);
-+ for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
-+ if (ext2_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext2_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext2_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext2_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext2_xattr_handler *
-+ext2_xattr_handler(int name_index)
-+{
-+ struct ext2_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ read_lock(&ext2_handler_lock);
-+ handler = ext2_xattr_handlers[name_index-1];
-+ read_unlock(&ext2_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext2_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext2_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
-+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext2_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext2_setxattr(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext2_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
-+ext2_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext2_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext2_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 (!EXT2_I(inode)->i_file_acl)
-+ return -ENOATTR;
-+ block = EXT2_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(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(inode->i_sb, "ext2_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 ext2_xattr_entry *next =
-+ EXT2_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 ext2_xattr_entry *next =
-+ EXT2_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext2_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 (ext2_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;
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext2_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 (!EXT2_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT2_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(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(inode->i_sb, "ext2_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 = EXT2_XATTR_NEXT(entry)) {
-+ struct ext2_xattr_handler *handler;
-+ struct ext2_xattr_entry *next =
-+ EXT2_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext2_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+
-+ if (ext2_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 = EXT2_XATTR_NEXT(entry)) {
-+ struct ext2_xattr_handler *handler;
-+
-+ handler = ext2_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext2_xattr_update_super_block(struct super_block *sb)
-+{
-+ if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+ EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
-+#endif
-+ EXT2_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_set(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 ext2_xattr_header *header = NULL;
-+ struct ext2_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int block = EXT2_I(inode)->i_file_acl;
-+ 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(&ext2_xattr_sem);
-+
-+ if (block) {
-+ /* The inode already has an extended attribute block. */
-+
-+ 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(EXT2_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(sb, "ext2_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 ext2_xattr_entry *next = EXT2_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 ext2_xattr_entry *next = EXT2_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 ext2_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 -= EXT2_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 += EXT2_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT2_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");
-+ ext2_xattr_cache_remove(bh);
-+ } 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(EXT2_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 = EXT2_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 = EXT2_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 = EXT2_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext2_xattr_set2(inode, bh, NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT2_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 = EXT2_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 - EXT2_XATTR_PAD, 0,
-+ EXT2_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext2_xattr_rehash(header, here);
-+
-+ error = ext2_xattr_set2(inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ up(&ext2_xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext2_xattr_set(): Update the file system.
-+ */
-+static int
-+ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
-+ struct ext2_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext2_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 (ext2_xattr_quota_alloc(inode, 1))
-+ 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;
-+ (void)ext2_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int force = EXT2_I(inode)->i_file_acl != 0;
-+ int block = ext2_xattr_new_block(inode, &error, force);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+ ext2_xattr_free_block(inode, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ mark_buffer_uptodate(new_bh, 1);
-+ unlock_buffer(new_bh);
-+ (void)ext2_xattr_cache_insert(new_bh);
-+
-+ ext2_xattr_update_super_block(sb);
-+ }
-+ mark_buffer_dirty(new_bh);
-+ if (IS_SYNC(inode)) {
-+ ll_rw_block(WRITE, 1, &new_bh);
-+ wait_on_buffer(new_bh);
-+ error = -EIO;
-+ if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
-+ goto cleanup;
-+ }
-+ }
-+
-+ /* Update the inode. */
-+ EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ if (IS_SYNC(inode)) {
-+ error = ext2_sync_inode (inode);
-+ if (error)
-+ goto cleanup;
-+ } else
-+ mark_inode_dirty(inode);
-+
-+ 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);
-+
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext2_xattr_free_block(inode, old_bh->b_blocknr);
-+ mark_buffer_clean(old_bh);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ ext2_xattr_quota_free(inode);
-+ mark_buffer_dirty(old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext2_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext2_xattr_delete_inode(struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT2_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ down(&ext2_xattr_sem);
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext2_error(inode->i_sb, "ext2_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(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext2_xattr_cache_remove(bh);
-+ ext2_xattr_free_block(inode, block);
-+ bforget(bh);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ mark_buffer_dirty(bh);
-+ if (IS_SYNC(inode)) {
-+ ll_rw_block(WRITE, 1, &bh);
-+ wait_on_buffer(bh);
-+ }
-+ ext2_xattr_quota_free(inode);
-+ }
-+ EXT2_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ up(&ext2_xattr_sem);
-+}
-+
-+/*
-+ * ext2_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext2_xattr_put_super(struct super_block *sb)
-+{
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+ mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
-+#endif
-+}
-+
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+
-+/*
-+ * ext2_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
-+ext2_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(ext2_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(&ext2_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext2_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_cmp(struct ext2_xattr_header *header1,
-+ struct ext2_xattr_header *header2)
-+{
-+ struct ext2_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 = EXT2_XATTR_NEXT(entry1);
-+ entry2 = EXT2_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext2_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 *
-+ext2_xattr_cache_find(struct inode *inode, struct ext2_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(ext2_xattr_cache, 0, inode->i_dev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext2_error(inode->i_sb, "ext2_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT2_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT2_XATTR_REFCOUNT_MAX);
-+ } else if (!ext2_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;
-+}
-+
-+/*
-+ * ext2_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext2_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext2_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
-+
-+/*
-+ * ext2_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
-+ struct ext2_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) +
-+ EXT2_XATTR_ROUND) >> EXT2_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
-+
-+/*
-+ * ext2_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext2_xattr_rehash(struct ext2_xattr_header *header,
-+ struct ext2_xattr_entry *entry)
-+{
-+ struct ext2_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext2_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 = EXT2_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+
-+int __init
-+init_ext2_xattr(void)
-+{
-+ ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 61);
-+ if (!ext2_xattr_cache)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext2_xattr(void)
-+{
-+ mb_cache_destroy(ext2_xattr_cache);
-+}
-+
-+#else /* CONFIG_EXT2_FS_XATTR_SHARING */
-+
-+int __init
-+init_ext2_xattr(void)
-+{
-+ return 0;
-+}
-+
-+void
-+exit_ext2_xattr(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/xattr_user.c 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,103 @@
-+/*
-+ * linux/fs/ext2/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/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-+
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+# include <linux/ext2_acl.h>
-+#endif
-+
-+#define XATTR_USER_PREFIX "user."
-+
-+static size_t
-+ext2_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);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return prefix_len + name_len + 1;
-+}
-+
-+static int
-+ext2_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 -ENOTSUP;
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+ error = ext2_permission_locked(inode, MAY_READ);
-+#else
-+ error = permission(inode, MAY_READ);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
-+ buffer, size);
-+}
-+
-+static int
-+ext2_xattr_user_set(struct inode *inode, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -ENOTSUP;
-+ if ( !S_ISREG(inode->i_mode) &&
-+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-+ return -EPERM;
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+ error = ext2_permission_locked(inode, MAY_WRITE);
-+#else
-+ error = permission(inode, MAY_WRITE);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
-+ value, size, flags);
-+}
-+
-+struct ext2_xattr_handler ext2_xattr_user_handler = {
-+ prefix: XATTR_USER_PREFIX,
-+ list: ext2_xattr_user_list,
-+ get: ext2_xattr_user_get,
-+ set: ext2_xattr_user_set,
-+};
-+
-+int __init
-+init_ext2_xattr_user(void)
-+{
-+ return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
-+ &ext2_xattr_user_handler);
-+}
-+
-+void
-+exit_ext2_xattr_user(void)
-+{
-+ ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
-+ &ext2_xattr_user_handler);
-+}
---- kernel-2.4.20-6chaos_18_7/fs/ext3/Makefile~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/Makefile 2003-07-12 15:34:44.000000000 -0600
-@@ -1,5 +1,5 @@
- #
--# Makefile for the linux ext2-filesystem routines.
-+# Makefile for the linux ext3-filesystem routines.
- #
- # Note! Dependencies are done automagically by 'make dep', which also
- # removes any old dependencies. DON'T put your own dependencies here
-@@ -9,10 +9,14 @@
-
- O_TARGET := ext3.o
-
--export-objs := super.o inode.o
-+export-objs := ext3-exports.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 hash.o
-+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
- obj-m := $(O_TARGET)
-
-+export-objs += xattr.o
-+obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
-+obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
-+
- include $(TOPDIR)/Rules.make
---- kernel-2.4.20-6chaos_18_7/fs/ext3/file.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/file.c 2003-07-12 15:34:44.000000000 -0600
-@@ -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>
-
-@@ -126,5 +127,9 @@ struct file_operations ext3_file_operati
- 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 */
- };
-
---- kernel-2.4.20-6chaos_18_7/fs/ext3/ialloc.c~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:30.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/ialloc.c 2003-07-12 15:34:44.000000000 -0600
-@@ -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 @@ void ext3_free_inode (handle_t *handle,
- * 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);
-
---- kernel-2.4.20-6chaos_18_7/fs/ext3/inode.c~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:30.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/inode.c 2003-07-12 15:34:44.000000000 -0600
-@@ -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 = inode->u.ext3_i.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)
- {
-@@ -179,9 +191,7 @@ void ext3_delete_inode (struct inode * i
- {
- 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();
-@@ -1874,6 +1884,8 @@ void ext3_truncate(struct inode * inode)
- 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;
-
-@@ -2021,8 +2033,6 @@ int ext3_get_inode_loc (struct inode *in
- 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(
-@@ -2149,10 +2159,7 @@ void ext3_read_inode(struct inode * inod
-
- 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;
-@@ -2160,15 +2167,17 @@ void ext3_read_inode(struct inode * inod
- 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 */
- if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
- /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
---- kernel-2.4.20-6chaos_18_7/fs/ext3/namei.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:43.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/namei.c 2003-07-12 15:34:44.000000000 -0600
-@@ -29,6 +29,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>
-@@ -1613,7 +1614,7 @@ static int ext3_mkdir(struct inode * dir
- 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;
-@@ -1621,7 +1622,6 @@ static int ext3_mkdir(struct inode * dir
- 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? */
-@@ -1648,9 +1648,6 @@ static int ext3_mkdir(struct inode * dir
- 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) {
-@@ -2019,7 +2016,7 @@ static int ext3_symlink (struct inode *
- 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;
- inode->i_mapping->a_ops = &ext3_aops;
- /*
- * block_symlink() calls back into ext3_prepare/commit_write.
-@@ -2245,4 +2242,16 @@ struct inode_operations ext3_dir_inode_o
- 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 */
-+};
-+
---- kernel-2.4.20-6chaos_18_7/fs/ext3/super.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/super.c 2003-07-12 15:34:44.000000000 -0600
-@@ -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>
-@@ -406,6 +407,7 @@ void ext3_put_super (struct super_block
- 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);
-@@ -502,6 +504,7 @@ static int parse_options (char * options
- 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;
-@@ -514,6 +517,13 @@ static int parse_options (char * options
- this_char = strtok (NULL, ",")) {
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT3_FS_XATTR_USER
-+ 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")) {
-@@ -931,6 +941,12 @@ struct super_block * ext3_read_super (st
- 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_USER
-+ /* set_opt(sbi->s_mount_opt, XATTR_USER); */
-+#endif
-+
- if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
- sb->s_dev = 0;
- goto out_fail;
-@@ -1768,17 +1784,29 @@ static DECLARE_FSTYPE_DEV(ext3_fs_type,
-
- static int __init init_ext3_fs(void)
- {
-- return register_filesystem(&ext3_fs_type);
-+ int error = init_ext3_xattr();
-+ if (error)
-+ return error;
-+ error = init_ext3_xattr_user();
-+ if (error)
-+ goto fail;
-+ error = register_filesystem(&ext3_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext3_xattr_user();
-+fail:
-+ exit_ext3_xattr();
-+ return error;
- }
-
- static void __exit exit_ext3_fs(void)
- {
- unregister_filesystem(&ext3_fs_type);
-+ exit_ext3_xattr_user();
-+ exit_ext3_xattr();
- }
-
--EXPORT_SYMBOL(ext3_force_commit);
--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");
- MODULE_LICENSE("GPL");
---- kernel-2.4.20-6chaos_18_7/fs/ext3/symlink.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/symlink.c 2003-07-12 15:34:44.000000000 -0600
-@@ -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 @@ static int ext3_follow_link(struct dentr
- 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 */
- };
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/xattr.c 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,1225 @@
-+/*
-+ * 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/module.h>
-+#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>
-+#include <linux/mbcache.h>
-+#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) while(0) {}
-+# define ext3_xattr_rehash(header, entry) 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 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,
-+ const 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);
-+ }
-+
-+ 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);
-+ }
-+ 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, 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 block = EXT3_I(inode)->i_file_acl;
-+ 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 (block) {
-+ /* The inode already has an extended attribute block. */
-+ 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);
-+ 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 (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;
-+ (void)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);
-+ (void)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_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_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);
-+ 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)
-+{
-+#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 */
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/xattr_user.c 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,111 @@
-+/*
-+ * 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/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_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);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return prefix_len + name_len + 1;
-+}
-+
-+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 -ENOTSUP;
-+#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 -ENOTSUP;
-+ 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;
-+
-+ 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);
-+
-+ 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,
-+};
-+
-+int __init
-+init_ext3_xattr_user(void)
-+{
-+ return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
-+ &ext3_xattr_user_handler);
-+}
-+
-+void
-+exit_ext3_xattr_user(void)
-+{
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
-+ &ext3_xattr_user_handler);
-+}
---- kernel-2.4.20-6chaos_18_7/fs/jfs/jfs_xattr.h~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:11.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/jfs/jfs_xattr.h 2003-07-12 15:34:44.000000000 -0600
-@@ -52,8 +52,10 @@ struct jfs_ea_list {
- #define END_EALIST(ealist) \
- ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
-
--extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
--extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
-+extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
-+ int);
-+extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
-+ int);
- extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
- extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
- extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
---- kernel-2.4.20-6chaos_18_7/fs/jfs/xattr.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:11.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/jfs/xattr.c 2003-07-12 15:34:44.000000000 -0600
-@@ -641,7 +641,7 @@ static int ea_put(struct inode *inode, s
- }
-
- static int can_set_xattr(struct inode *inode, const char *name,
-- void *value, size_t value_len)
-+ const void *value, size_t value_len)
- {
- if (IS_RDONLY(inode))
- return -EROFS;
-@@ -660,7 +660,7 @@ static int can_set_xattr(struct inode *i
- return permission(inode, MAY_WRITE);
- }
-
--int __jfs_setxattr(struct inode *inode, const char *name, void *value,
-+int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
- size_t value_len, int flags)
- {
- struct jfs_ea_list *ealist;
-@@ -799,7 +799,7 @@ int __jfs_setxattr(struct inode *inode,
- return rc;
- }
-
--int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
-+int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
- size_t value_len, int flags)
- {
- if (value == NULL) { /* empty EA, do not remove */
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/mbcache.c 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,648 @@
-+/*
-+ * 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. Entries that cannot be freed immediately are put
-+ * back on the lru list.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/cache_def.h>
-+#include <linux/version.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)");
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-+MODULE_LICENSE("GPL");
-+#endif
-+
-+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 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 void
-+mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
-+
-+static struct cache_definition mb_cache_definition = {
-+ "mb_cache",
-+ mb_cache_memory_pressure
-+};
-+
-+
-+static inline int
-+__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
-+{
-+ return !list_empty(&ce->e_block_list);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_unhash(struct mb_cache_entry *ce)
-+{
-+ int n;
-+
-+ if (__mb_cache_entry_is_hashed(ce)) {
-+ 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 void
-+__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+
-+ mb_assert(atomic_read(&ce->e_used) == 0);
-+ if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
-+ /* free failed -- put back on the lru list
-+ for freeing later. */
-+ spin_lock(&mb_cache_spinlock);
-+ list_add(&ce->e_lru_list, &mb_cache_lru_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ } else {
-+ kmem_cache_free(cache->c_entry_cache, ce);
-+ atomic_dec(&cache->c_entry_count);
-+ }
-+}
-+
-+
-+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_hashed(ce))
-+ list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
-+ else {
-+ spin_unlock(&mb_cache_spinlock);
-+ __mb_cache_entry_forget(ce, GFP_KERNEL);
-+ return;
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+}
-+
-+
-+/*
-+ * mb_cache_memory_pressure() memory pressure callback
-+ *
-+ * This function is called by the kernel memory management when memory
-+ * gets low.
-+ *
-+ * @priority: Amount by which to shrink the cache (0 = highes priority)
-+ * @gfp_mask: (ignored)
-+ */
-+static void
-+mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l, *ltmp;
-+ int count = 0;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(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 of %d entries",
-+ count / (priority ? priority : 1), count);
-+ if (priority)
-+ count /= priority;
-+ while (count-- && !list_empty(&mb_cache_lru_list)) {
-+ struct mb_cache_entry *ce =
-+ list_entry(mb_cache_lru_list.next,
-+ struct mb_cache_entry, e_lru_list);
-+ list_del(&ce->e_lru_list);
-+ __mb_cache_entry_unhash(ce);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), gfp_mask);
-+ }
-+}
-+
-+
-+/*
-+ * 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_count: 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_count)
-+{
-+ int m=0, n;
-+ struct mb_cache *cache = NULL;
-+
-+ if(entry_size < sizeof(struct mb_cache_entry) +
-+ indexes_count * sizeof(struct mb_cache_entry_index))
-+ return NULL;
-+
-+ MOD_INC_USE_COUNT;
-+ cache = kmalloc(sizeof(struct mb_cache) +
-+ indexes_count * sizeof(struct list_head), GFP_KERNEL);
-+ if (!cache)
-+ goto fail;
-+ cache->c_name = name;
-+ cache->c_op.free = NULL;
-+ if (cache_op)
-+ cache->c_op.free = cache_op->free;
-+ atomic_set(&cache->c_entry_count, 0);
-+ cache->c_bucket_count = bucket_count;
-+#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);
-+ 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);
-+ }
-+ MOD_DEC_USE_COUNT;
-+ 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.
-+ *
-+ * @cache: which cache to shrink
-+ * @dev: which device's cache entries to shrink
-+ */
-+void
-+mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l, *ltmp;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ if (ce->e_dev == dev) {
-+ list_del(&ce->e_lru_list);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ __mb_cache_entry_unhash(ce);
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), GFP_KERNEL);
-+ }
-+}
-+
-+
-+/*
-+ * 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, *ltmp;
-+ int n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ if (ce->e_cache == cache) {
-+ list_del(&ce->e_lru_list);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ __mb_cache_entry_unhash(ce);
-+ }
-+ }
-+ list_del(&cache->c_cache_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), GFP_KERNEL);
-+ }
-+
-+ if (atomic_read(&cache->c_entry_count) > 0) {
-+ mb_error("cache %s: %d orphaned entries",
-+ cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ }
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
-+ /* We don't have kmem_cache_destroy() in 2.2.x */
-+ kmem_cache_shrink(cache->c_entry_cache);
-+#else
-+ kmem_cache_destroy(cache->c_entry_cache);
-+#endif
-+ for (n=0; n < mb_cache_indexes(cache); n++)
-+ kfree(cache->c_indexes_hash[n]);
-+ kfree(cache->c_block_hash);
-+ kfree(cache);
-+
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+
-+/*
-+ * 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, if another process has
-+ * inserted the same cache entry in the meantime).
-+ *
-+ * @dev: 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, kdev_t dev,
-+ unsigned long block, unsigned int keys[])
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
-+ struct list_head *l;
-+ int error = -EBUSY, n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(l, &cache->c_block_hash[bucket]) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_dev == dev && ce->e_block == block)
-+ goto out;
-+ }
-+ __mb_cache_entry_unhash(ce);
-+ ce->e_dev = dev;
-+ ce->e_block = block;
-+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
-+ for (n=0; n<mb_cache_indexes(cache); n++) {
-+ ce->e_indexes[n].o_key = keys[n];
-+ bucket = keys[n] % cache->c_bucket_count;
-+ list_add(&ce->e_indexes[n].o_list,
-+ &cache->c_indexes_hash[n][bucket]);
-+ }
-+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(list_empty(&ce->e_lru_list));
-+ __mb_cache_entry_unhash(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(list_empty(&ce->e_lru_list));
-+ __mb_cache_entry_unhash(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, kdev_t dev, unsigned long block)
-+{
-+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ 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_dev == dev && ce->e_block == block) {
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+ atomic_inc(&ce->e_used);
-+ 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, kdev_t dev, 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_dev == dev && ce->e_indexes[index].o_key == key) {
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+ atomic_inc(&ce->e_used);
-+ 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)
-+ * @dev: 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, kdev_t dev,
-+ unsigned int key)
-+{
-+ unsigned int bucket = key % cache->c_bucket_count;
-+ 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, dev, 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)
-+ * @dev: 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, kdev_t dev,
-+ unsigned int key)
-+{
-+ struct mb_cache *cache = prev->e_cache;
-+ unsigned int bucket = key % cache->c_bucket_count;
-+ 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, dev, key);
-+ __mb_cache_entry_release_unlock(prev);
-+ return ce;
-+}
-+
-+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
-+
-+static int __init init_mbcache(void)
-+{
-+ register_cache(&mb_cache_definition);
-+ return 0;
-+}
-+
-+static void __exit exit_mbcache(void)
-+{
-+ unregister_cache(&mb_cache_definition);
-+}
-+
-+module_init(init_mbcache)
-+module_exit(exit_mbcache)
-+
---- kernel-2.4.20-6chaos_18_7/include/asm-arm/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:42.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/asm-arm/unistd.h 2003-07-12 15:34:44.000000000 -0600
-@@ -244,7 +244,6 @@
- #define __NR_security (__NR_SYSCALL_BASE+223)
- #define __NR_gettid (__NR_SYSCALL_BASE+224)
- #define __NR_readahead (__NR_SYSCALL_BASE+225)
--#if 0 /* allocated in 2.5 */
- #define __NR_setxattr (__NR_SYSCALL_BASE+226)
- #define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
- #define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
-@@ -257,7 +256,6 @@
- #define __NR_removexattr (__NR_SYSCALL_BASE+235)
- #define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
- #define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
--#endif
- #define __NR_tkill (__NR_SYSCALL_BASE+238)
- /*
- * Please check 2.5 _before_ adding calls here,
---- kernel-2.4.20-6chaos_18_7/include/asm-ppc64/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:42.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/asm-ppc64/unistd.h 2003-07-12 15:34:44.000000000 -0600
-@@ -218,6 +218,7 @@
- #define __NR_gettid 207
- #if 0 /* Reserved syscalls */
- #define __NR_tkill 208
-+#endif
- #define __NR_setxattr 209
- #define __NR_lsetxattr 210
- #define __NR_fsetxattr 211
-@@ -230,6 +231,7 @@
- #define __NR_removexattr 218
- #define __NR_lremovexattr 219
- #define __NR_fremovexattr 220
-+#if 0 /* Reserved syscalls */
- #define __NR_futex 221
- #endif
-
---- kernel-2.4.20-6chaos_18_7/include/asm-s390/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:44.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/asm-s390/unistd.h 2003-07-12 15:34:44.000000000 -0600
-@@ -212,9 +212,18 @@
- #define __NR_madvise 219
- #define __NR_getdents64 220
- #define __NR_fcntl64 221
--/*
-- * Numbers 224-235 are reserved for posix acl
-- */
-+#define __NR_setxattr 224
-+#define __NR_lsetxattr 225
-+#define __NR_fsetxattr 226
-+#define __NR_getxattr 227
-+#define __NR_lgetxattr 228
-+#define __NR_fgetxattr 229
-+#define __NR_listxattr 230
-+#define __NR_llistxattr 231
-+#define __NR_flistxattr 232
-+#define __NR_removexattr 233
-+#define __NR_lremovexattr 234
-+#define __NR_fremovexattr 235
- #define __NR_gettid 236
- #define __NR_tkill 237
-
---- kernel-2.4.20-6chaos_18_7/include/asm-s390x/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:45.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/asm-s390x/unistd.h 2003-07-12 15:34:44.000000000 -0600
-@@ -180,9 +180,18 @@
- #define __NR_pivot_root 217
- #define __NR_mincore 218
- #define __NR_madvise 219
--/*
-- * Numbers 224-235 are reserved for posix acl
-- */
-+#define __NR_setxattr 224
-+#define __NR_lsetxattr 225
-+#define __NR_fsetxattr 226
-+#define __NR_getxattr 227
-+#define __NR_lgetxattr 228
-+#define __NR_fgetxattr 229
-+#define __NR_listxattr 230
-+#define __NR_llistxattr 231
-+#define __NR_flistxattr 232
-+#define __NR_removexattr 233
-+#define __NR_lremovexattr 234
-+#define __NR_fremovexattr 235
- #define __NR_gettid 236
- #define __NR_tkill 237
-
---- kernel-2.4.20-6chaos_18_7/include/asm-sparc/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:46.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/asm-sparc/unistd.h 2003-07-12 15:34:44.000000000 -0600
-@@ -184,24 +184,24 @@
- /* #define __NR_exportfs 166 SunOS Specific */
- #define __NR_mount 167 /* Common */
- #define __NR_ustat 168 /* Common */
--/* #define __NR_semsys 169 SunOS Specific */
--/* #define __NR_msgsys 170 SunOS Specific */
--/* #define __NR_shmsys 171 SunOS Specific */
--/* #define __NR_auditsys 172 SunOS Specific */
--/* #define __NR_rfssys 173 SunOS Specific */
-+#define __NR_setxattr 169 /* SunOS: semsys */
-+#define __NR_lsetxattr 170 /* SunOS: msgsys */
-+#define __NR_fsetxattr 171 /* SunOS: shmsys */
-+#define __NR_getxattr 172 /* SunOS: auditsys */
-+#define __NR_lgetxattr 173 /* SunOS: rfssys */
- #define __NR_getdents 174 /* Common */
- #define __NR_setsid 175 /* Common */
- #define __NR_fchdir 176 /* Common */
--/* #define __NR_fchroot 177 SunOS Specific */
--/* #define __NR_vpixsys 178 SunOS Specific */
--/* #define __NR_aioread 179 SunOS Specific */
--/* #define __NR_aiowrite 180 SunOS Specific */
--/* #define __NR_aiowait 181 SunOS Specific */
--/* #define __NR_aiocancel 182 SunOS Specific */
-+#define __NR_fgetxattr 177 /* SunOS: fchroot */
-+#define __NR_listxattr 178 /* SunOS: vpixsys */
-+#define __NR_llistxattr 179 /* SunOS: aioread */
-+#define __NR_flistxattr 180 /* SunOS: aiowrite */
-+#define __NR_removexattr 181 /* SunOS: aiowait */
-+#define __NR_lremovexattr 182 /* SunOS: aiocancel */
- #define __NR_sigpending 183 /* Common */
- #define __NR_query_module 184 /* Linux Specific */
- #define __NR_setpgid 185 /* Common */
--/* #define __NR_pathconf 186 SunOS Specific */
-+#define __NR_fremovexattr 186 /* SunOS: pathconf */
- #define __NR_tkill 187 /* SunOS: fpathconf */
- /* #define __NR_sysconf 188 SunOS Specific */
- #define __NR_uname 189 /* Linux Specific */
---- kernel-2.4.20-6chaos_18_7/include/asm-sparc64/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:48.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/asm-sparc64/unistd.h 2003-07-12 15:34:44.000000000 -0600
-@@ -184,24 +184,24 @@
- /* #define __NR_exportfs 166 SunOS Specific */
- #define __NR_mount 167 /* Common */
- #define __NR_ustat 168 /* Common */
--/* #define __NR_semsys 169 SunOS Specific */
--/* #define __NR_msgsys 170 SunOS Specific */
--/* #define __NR_shmsys 171 SunOS Specific */
--/* #define __NR_auditsys 172 SunOS Specific */
--/* #define __NR_rfssys 173 SunOS Specific */
-+#define __NR_setxattr 169 /* SunOS: semsys */
-+#define __NR_lsetxattr 170 /* SunOS: msgsys */
-+#define __NR_fsetxattr 171 /* SunOS: shmsys */
-+#define __NR_getxattr 172 /* SunOS: auditsys */
-+#define __NR_lgetxattr 173 /* SunOS: rfssys */
- #define __NR_getdents 174 /* Common */
- #define __NR_setsid 175 /* Common */
- #define __NR_fchdir 176 /* Common */
--/* #define __NR_fchroot 177 SunOS Specific */
--/* #define __NR_vpixsys 178 SunOS Specific */
--/* #define __NR_aioread 179 SunOS Specific */
--/* #define __NR_aiowrite 180 SunOS Specific */
--/* #define __NR_aiowait 181 SunOS Specific */
--/* #define __NR_aiocancel 182 SunOS Specific */
-+#define __NR_fgetxattr 177 /* SunOS: fchroot */
-+#define __NR_listxattr 178 /* SunOS: vpixsys */
-+#define __NR_llistxattr 179 /* SunOS: aioread */
-+#define __NR_flistxattr 180 /* SunOS: aiowrite */
-+#define __NR_removexattr 181 /* SunOS: aiowait */
-+#define __NR_lremovexattr 182 /* SunOS: aiocancel */
- #define __NR_sigpending 183 /* Common */
- #define __NR_query_module 184 /* Linux Specific */
- #define __NR_setpgid 185 /* Common */
--/* #define __NR_pathconf 186 SunOS Specific */
-+#define __NR_fremovexattr 186 /* SunOS: pathconf */
- #define __NR_tkill 187 /* SunOS: fpathconf */
- /* #define __NR_sysconf 188 SunOS Specific */
- #define __NR_uname 189 /* Linux Specific */
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/include/linux/cache_def.h 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,15 @@
-+/*
-+ * linux/cache_def.h
-+ * Handling of caches defined in drivers, filesystems, ...
-+ *
-+ * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+struct cache_definition {
-+ const char *name;
-+ void (*shrink)(int, unsigned int);
-+ struct list_head link;
-+};
-+
-+extern void register_cache(struct cache_definition *);
-+extern void unregister_cache(struct cache_definition *);
---- kernel-2.4.20-6chaos_18_7/include/linux/errno.h~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:15:06.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/linux/errno.h 2003-07-12 15:34:44.000000000 -0600
-@@ -26,4 +26,8 @@
-
- #endif
-
-+/* Defined for extended attributes */
-+#define ENOATTR ENODATA /* No such attribute */
-+#define ENOTSUP EOPNOTSUPP /* Operation not supported */
-+
- #endif
---- kernel-2.4.20-6chaos_18_7/include/linux/ext2_fs.h~linux-2.4.20-xattr-0.8.54-chaos 2003-06-24 11:31:16.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext2_fs.h 2003-07-12 15:34:44.000000000 -0600
-@@ -57,8 +57,6 @@
- */
- #define EXT2_BAD_INO 1 /* Bad blocks inode */
- #define EXT2_ROOT_INO 2 /* Root inode */
--#define EXT2_ACL_IDX_INO 3 /* ACL inode */
--#define EXT2_ACL_DATA_INO 4 /* ACL inode */
- #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
-
-@@ -86,7 +84,6 @@
- #else
- # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
- #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -121,28 +118,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext2_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext2_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 ext2_group_desc
-@@ -314,6 +289,7 @@ struct ext2_inode {
- #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
- #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
- #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
-+#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-
- #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
- #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
-@@ -397,6 +373,7 @@ struct ext2_super_block {
-
- #ifdef __KERNEL__
- #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
-+#define EXT2_I(inode) (&((inode)->u.ext2_i))
- #else
- /* Assume that user mode programs are passing in an ext2fs superblock, not
- * a kernel struct super_block. This will allow us to call the feature-test
-@@ -466,7 +443,7 @@ struct ext2_super_block {
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
- #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
-
--#define EXT2_FEATURE_COMPAT_SUPP 0
-+#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
- #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
-@@ -624,8 +601,10 @@ extern struct address_space_operations e
-
- /* namei.c */
- extern struct inode_operations ext2_dir_inode_operations;
-+extern struct inode_operations ext2_special_inode_operations;
-
- /* symlink.c */
-+extern struct inode_operations ext2_symlink_inode_operations;
- extern struct inode_operations ext2_fast_symlink_inode_operations;
-
- #endif /* __KERNEL__ */
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext2_xattr.h 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,157 @@
-+/*
-+ File: linux/ext2_xattr.h
-+
-+ On-disk format of extended attributes for the ext2 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 EXT2_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT2_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT2_XATTR_INDEX_MAX 10
-+#define EXT2_XATTR_INDEX_USER 1
-+#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
-+#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+
-+struct ext2_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 ext2_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 EXT2_XATTR_PAD_BITS 2
-+#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
-+#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
-+#define EXT2_XATTR_LEN(name_len) \
-+ (((name_len) + EXT2_XATTR_ROUND + \
-+ sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
-+#define EXT2_XATTR_NEXT(entry) \
-+ ( (struct ext2_xattr_entry *)( \
-+ (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT2_XATTR_SIZE(size) \
-+ (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
-+
-+#ifdef __KERNEL__
-+
-+# ifdef CONFIG_EXT2_FS_XATTR
-+
-+struct ext2_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 ext2_xattr_register(int, struct ext2_xattr_handler *);
-+extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
-+
-+extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
-+extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
-+extern int ext2_removexattr(struct dentry *, const char *);
-+
-+extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext2_xattr_list(struct inode *, char *, size_t);
-+extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
-+
-+extern void ext2_xattr_delete_inode(struct inode *);
-+extern void ext2_xattr_put_super(struct super_block *);
-+
-+extern int init_ext2_xattr(void) __init;
-+extern void exit_ext2_xattr(void);
-+
-+# else /* CONFIG_EXT2_FS_XATTR */
-+# define ext2_setxattr NULL
-+# define ext2_getxattr NULL
-+# define ext2_listxattr NULL
-+# define ext2_removexattr NULL
-+
-+static inline int
-+ext2_xattr_get(struct inode *inode, int name_index,
-+ const char *name, void *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext2_xattr_set(struct inode *inode, int name_index, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline void
-+ext2_xattr_delete_inode(struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext2_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext2_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext2_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT2_FS_XATTR */
-+
-+# ifdef CONFIG_EXT2_FS_XATTR_USER
-+
-+extern int init_ext2_xattr_user(void) __init;
-+extern void exit_ext2_xattr_user(void);
-+
-+# else /* CONFIG_EXT2_FS_XATTR_USER */
-+
-+static inline int
-+init_ext2_xattr_user(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext2_xattr_user(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT2_FS_XATTR_USER */
-+
-+#endif /* __KERNEL__ */
-+
---- kernel-2.4.20-6chaos_18_7/include/linux/ext3_fs.h~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:41.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_fs.h 2003-07-12 15:34:44.000000000 -0600
-@@ -63,8 +63,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 */
-@@ -94,7 +92,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)
-@@ -129,28 +126,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
-@@ -344,6 +319,7 @@ struct ext3_inode {
- #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
-@@ -521,7 +497,7 @@ struct ext3_super_block {
- #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| \
-@@ -704,6 +680,7 @@ extern void ext3_check_inodes_bitmap (st
- 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 *);
-
-@@ -773,8 +750,10 @@ extern struct address_space_operations e
-
- /* 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;
-
-
---- kernel-2.4.20-6chaos_18_7/include/linux/ext3_jbd.h~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_jbd.h 2003-07-12 15:34:44.000000000 -0600
-@@ -30,13 +30,19 @@
-
- #define EXT3_SINGLEDATA_TRANS_BLOCKS 8U
-
-+/* 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);
-
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_xattr.h 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,157 @@
-+/*
-+ 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
-+#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 __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, 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 *, const 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) __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)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+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 -ENOTSUP;
-+}
-+
-+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 */
-+
-+# 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__ */
-+
---- kernel-2.4.20-6chaos_18_7/include/linux/fs.h~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:31:35.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/include/linux/fs.h 2003-07-12 15:34:44.000000000 -0600
-@@ -914,7 +914,7 @@ struct inode_operations {
- int (*setattr) (struct dentry *, struct iattr *);
- int (*setattr_raw) (struct inode *, struct iattr *);
- int (*getattr) (struct dentry *, struct iattr *);
-- int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
-+ int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
- ssize_t (*listxattr) (struct dentry *, char *, size_t);
- int (*removexattr) (struct dentry *, const char *);
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/include/linux/mbcache.h 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,69 @@
-+/*
-+ 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 {
-+ int (*free)(struct mb_cache_entry *, int);
-+};
-+
-+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_count;
-+#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;
-+ kdev_t e_dev;
-+ unsigned long 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 *, kdev_t);
-+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 *, kdev_t, unsigned long,
-+ 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 *, kdev_t,
-+ unsigned long);
-+#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,
-+ kdev_t, unsigned int);
-+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
-+ kdev_t, unsigned int);
-+#endif
---- kernel-2.4.20-6chaos_18_7/kernel/ksyms.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:14:02.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/kernel/ksyms.c 2003-07-12 15:35:19.000000000 -0600
-@@ -12,6 +12,7 @@
- #define __KERNEL_SYSCALLS__
- #include <linux/config.h>
- #include <linux/slab.h>
-+#include <linux/cache_def.h>
- #include <linux/smp.h>
- #include <linux/module.h>
- #include <linux/blkdev.h>
-@@ -106,6 +107,7 @@ EXPORT_SYMBOL(do_brk);
- EXPORT_SYMBOL(exit_mm);
- EXPORT_SYMBOL(exit_files);
- EXPORT_SYMBOL(exit_fs);
-+EXPORT_SYMBOL(copy_fs_struct);
- EXPORT_SYMBOL(exit_sighand);
- EXPORT_SYMBOL_GPL(make_pages_present);
-
-@@ -126,6 +128,8 @@ EXPORT_SYMBOL(kmem_cache_alloc);
- EXPORT_SYMBOL(kmem_cache_free);
- EXPORT_SYMBOL(kmem_cache_validate);
- EXPORT_SYMBOL(kmem_cache_size);
-+EXPORT_SYMBOL(register_cache);
-+EXPORT_SYMBOL(unregister_cache);
- EXPORT_SYMBOL(kmalloc);
- EXPORT_SYMBOL(kfree);
- EXPORT_SYMBOL(vfree);
---- kernel-2.4.20-6chaos_18_7/mm/vmscan.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:34.000000000 -0600
-+++ kernel-2.4.20-6chaos_18_7-braam/mm/vmscan.c 2003-07-12 15:34:44.000000000 -0600
-@@ -21,6 +21,7 @@
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
- #include <linux/swapctl.h>
-+#include <linux/cache_def.h>
- #include <linux/smp_lock.h>
- #include <linux/pagemap.h>
- #include <linux/init.h>
-@@ -444,6 +445,39 @@ static inline void kachunk_cache(struct
-
- #define BATCH_WORK_AMOUNT 64
-
-+static DECLARE_MUTEX(other_caches_sem);
-+static LIST_HEAD(cache_definitions);
-+
-+void register_cache(struct cache_definition *cache)
-+{
-+ down(&other_caches_sem);
-+ list_add(&cache->link, &cache_definitions);
-+ up(&other_caches_sem);
-+}
-+
-+void unregister_cache(struct cache_definition *cache)
-+{
-+ down(&other_caches_sem);
-+ list_del(&cache->link);
-+ up(&other_caches_sem);
-+}
-+
-+static void shrink_other_caches(unsigned int priority, int gfp_mask)
-+{
-+ struct list_head *p;
-+
-+ if (down_trylock(&other_caches_sem))
-+ return;
-+
-+ list_for_each_prev(p, &cache_definitions) {
-+ struct cache_definition *cache =
-+ list_entry(p, struct cache_definition, link);
-+
-+ cache->shrink(priority, gfp_mask);
-+ }
-+ up(&other_caches_sem);
-+}
-+
- /*
- * returns the active cache ratio relative to the total active list
- * times 10 (eg. 30% cache returns 3)
-@@ -887,7 +921,7 @@ static int do_try_to_free_pages_kswapd(u
-
- ret += shrink_dcache_memory(DEF_PRIORITY, gfp_mask);
- ret += shrink_icache_memory(DEF_PRIORITY, gfp_mask);
-- // ret += shrink_other_caches(DEF_PRIORITY, gfp_mask);
-+ shrink_other_caches(DEF_PRIORITY, gfp_mask);
- #ifdef CONFIG_QUOTA
- ret += shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
- #endif
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/ext3-exports.c 2003-07-12 15:34:44.000000000 -0600
-@@ -0,0 +1,13 @@
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
-+
-+EXPORT_SYMBOL(ext3_force_commit);
-+EXPORT_SYMBOL(ext3_bread);
-+EXPORT_SYMBOL(ext3_xattr_register);
-+EXPORT_SYMBOL(ext3_xattr_unregister);
-+EXPORT_SYMBOL(ext3_xattr_get);
-+EXPORT_SYMBOL(ext3_xattr_list);
-+EXPORT_SYMBOL(ext3_xattr_set);
-
-_
+++ /dev/null
- Documentation/Configure.help | 66 ++
- arch/alpha/defconfig | 7
- arch/alpha/kernel/entry.S | 12
- arch/arm/defconfig | 7
- arch/arm/kernel/calls.S | 24
- arch/i386/defconfig | 7
- arch/ia64/defconfig | 7
- arch/ia64/kernel/entry.S | 24
- arch/m68k/defconfig | 7
- arch/mips/defconfig | 7
- arch/mips64/defconfig | 7
- arch/ppc/defconfig | 14
- arch/ppc64/kernel/misc.S | 2
- arch/s390/defconfig | 7
- arch/s390/kernel/entry.S | 24
- arch/s390x/defconfig | 7
- arch/s390x/kernel/entry.S | 24
- arch/s390x/kernel/wrapper32.S | 92 +++
- arch/sparc/defconfig | 7
- arch/sparc/kernel/systbls.S | 10
- arch/sparc64/defconfig | 7
- arch/sparc64/kernel/systbls.S | 20
- fs/Config.in | 14
- fs/Makefile | 3
- fs/ext2/Makefile | 4
- fs/ext2/file.c | 5
- fs/ext2/ialloc.c | 2
- fs/ext2/inode.c | 34 -
- fs/ext2/namei.c | 14
- fs/ext2/super.c | 29
- fs/ext2/symlink.c | 14
- fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++
- fs/ext2/xattr_user.c | 103 +++
- fs/ext3/Makefile | 10
- fs/ext3/file.c | 5
- fs/ext3/ialloc.c | 2
- fs/ext3/inode.c | 35 -
- fs/ext3/namei.c | 21
- fs/ext3/super.c | 36 +
- fs/ext3/symlink.c | 14
- fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++
- fs/ext3/xattr_user.c | 111 +++
- fs/jfs/jfs_xattr.h | 6
- fs/jfs/xattr.c | 6
- fs/mbcache.c | 648 ++++++++++++++++++++++
- include/asm-arm/unistd.h | 2
- include/asm-ia64/unistd.h | 13
- include/asm-ppc64/unistd.h | 2
- include/asm-s390/unistd.h | 15
- include/asm-s390x/unistd.h | 15
- include/asm-sparc/unistd.h | 24
- include/asm-sparc64/unistd.h | 24
- include/linux/cache_def.h | 15
- include/linux/errno.h | 4
- include/linux/ext2_fs.h | 31 -
- include/linux/ext2_xattr.h | 157 +++++
- include/linux/ext3_fs.h | 31 -
- include/linux/ext3_jbd.h | 8
- include/linux/ext3_xattr.h | 157 +++++
- include/linux/fs.h | 2
- include/linux/mbcache.h | 69 ++
- kernel/ksyms.c | 4
- mm/vmscan.c | 35 +
- fs/ext3/ext3-exports.c | 14 +
- 64 files changed, 4355 insertions(+), 195 deletions(-)
-
---- linux-2.4.20/Documentation/Configure.help~linux-2.4.20-xattr-0.8.54 2003-05-05 17:43:06.000000000 +0800
-+++ linux-2.4.20-root/Documentation/Configure.help 2003-05-07 18:08:03.000000000 +0800
-@@ -15242,6 +15242,39 @@ CONFIG_EXT2_FS
- be compiled as a module, and so this could be dangerous. Most
- everyone wants to say Y here.
-
-+Ext2 extended attributes
-+CONFIG_EXT2_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.
-+
-+Ext2 extended attribute block sharing
-+CONFIG_EXT2_FS_XATTR_SHARING
-+ This options enables code for sharing identical extended attribute
-+ blocks among multiple inodes.
-+
-+ Usually, say Y.
-+
-+Ext2 extended user attributes
-+CONFIG_EXT2_FS_XATTR_USER
-+ This option enables extended user attributes on ext2. Processes can
-+ associate extended user attributes with inodes to store additional
-+ information such as the character encoding of files, etc. (see the
-+ attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext2 trusted extended attributes
-+CONFIG_EXT2_FS_XATTR_TRUSTED
-+ This option enables extended attributes on ext2 that are accessible
-+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
-+ is only the super user. Trusted extended attributes are meant for
-+ implementing system/security services.
-+
-+ If unsure, say N.
-+
- Ext3 journalling file system support (EXPERIMENTAL)
- CONFIG_EXT3_FS
- This is the journalling version of the Second extended file system
-@@ -15274,6 +15307,39 @@ CONFIG_EXT3_FS
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this may be dangerous.
-
-+Ext3 extended attributes
-+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.
-+
-+Ext3 extended attribute block sharing
-+CONFIG_EXT3_FS_XATTR_SHARING
-+ This options enables code for sharing identical extended attribute
-+ blocks among multiple inodes.
-+
-+ Usually, say Y.
-+
-+Ext3 extended user attributes
-+CONFIG_EXT3_FS_XATTR_USER
-+ This option enables extended user attributes on ext3. Processes can
-+ associate extended user attributes with inodes to store additional
-+ information such as the character encoding of files, etc. (see the
-+ attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext3 trusted extended attributes
-+CONFIG_EXT3_FS_XATTR_TRUSTED
-+ This option enables extended attributes on ext3 that are accessible
-+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
-+ is only the super user. Trusted extended attributes are meant for
-+ implementing system/security services.
-+
-+ If unsure, say N.
-+
- Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
- CONFIG_JBD
- This is a generic journalling layer for block devices. It is
---- linux-2.4.20/arch/alpha/defconfig~linux-2.4.20-xattr-0.8.54 2001-11-20 07:19:42.000000000 +0800
-+++ linux-2.4.20-root/arch/alpha/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_ALPHA=y
- # CONFIG_UID16 is not set
- # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
---- linux-2.4.20/arch/alpha/kernel/entry.S~linux-2.4.20-xattr-0.8.54 2002-08-03 08:39:42.000000000 +0800
-+++ linux-2.4.20-root/arch/alpha/kernel/entry.S 2003-05-07 18:08:03.000000000 +0800
-@@ -1154,6 +1154,18 @@ sys_call_table:
- .quad sys_readahead
- .quad sys_ni_syscall /* 380, sys_security */
- .quad sys_tkill
-+ .quad sys_setxattr
-+ .quad sys_lsetxattr
-+ .quad sys_fsetxattr
-+ .quad sys_getxattr /* 385 */
-+ .quad sys_lgetxattr
-+ .quad sys_fgetxattr
-+ .quad sys_listxattr
-+ .quad sys_llistxattr
-+ .quad sys_flistxattr /* 390 */
-+ .quad sys_removexattr
-+ .quad sys_lremovexattr
-+ .quad sys_fremovexattr
-
- /* Remember to update everything, kids. */
- .ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
---- linux-2.4.20/arch/arm/defconfig~linux-2.4.20-xattr-0.8.54 2001-05-20 08:43:05.000000000 +0800
-+++ linux-2.4.20-root/arch/arm/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_ARM=y
- # CONFIG_EISA is not set
- # CONFIG_SBUS is not set
---- linux-2.4.20/arch/arm/kernel/calls.S~linux-2.4.20-xattr-0.8.54 2002-08-03 08:39:42.000000000 +0800
-+++ linux-2.4.20-root/arch/arm/kernel/calls.S 2003-05-07 18:08:03.000000000 +0800
-@@ -240,18 +240,18 @@ __syscall_start:
- .long SYMBOL_NAME(sys_ni_syscall) /* Security */
- .long SYMBOL_NAME(sys_gettid)
- /* 225 */ .long SYMBOL_NAME(sys_readahead)
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_setxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_lsetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_fsetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_getxattr */
--/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_lgetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_fgetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_listxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_llistxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_flistxattr */
--/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_removexattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_lremovexattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* sys_fremovexattr */
-+ .long SYMBOL_NAME(sys_setxattr)
-+ .long SYMBOL_NAME(sys_lsetxattr)
-+ .long SYMBOL_NAME(sys_fsetxattr)
-+ .long SYMBOL_NAME(sys_getxattr)
-+/* 230 */ .long SYMBOL_NAME(sys_lgetxattr)
-+ .long SYMBOL_NAME(sys_fgetxattr)
-+ .long SYMBOL_NAME(sys_listxattr)
-+ .long SYMBOL_NAME(sys_llistxattr)
-+ .long SYMBOL_NAME(sys_flistxattr)
-+/* 235 */ .long SYMBOL_NAME(sys_removexattr)
-+ .long SYMBOL_NAME(sys_lremovexattr)
-+ .long SYMBOL_NAME(sys_fremovexattr)
- .long SYMBOL_NAME(sys_tkill)
- /*
- * Please check 2.5 _before_ adding calls here,
---- linux-2.4.20/arch/i386/defconfig~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:09.000000000 +0800
-+++ linux-2.4.20-root/arch/i386/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_X86=y
- CONFIG_ISA=y
- # CONFIG_SBUS is not set
---- linux-2.4.20/arch/ia64/defconfig~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:09.000000000 +0800
-+++ linux-2.4.20-root/arch/ia64/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
-
- #
- # Code maturity level options
---- linux-2.4.20/arch/m68k/defconfig~linux-2.4.20-xattr-0.8.54 2000-06-20 03:56:08.000000000 +0800
-+++ linux-2.4.20-root/arch/m68k/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_UID16=y
-
- #
---- linux-2.4.20/arch/mips/defconfig~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:10.000000000 +0800
-+++ linux-2.4.20-root/arch/mips/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_MIPS=y
- CONFIG_MIPS32=y
- # CONFIG_MIPS64 is not set
---- linux-2.4.20/arch/mips64/defconfig~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:10.000000000 +0800
-+++ linux-2.4.20-root/arch/mips64/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_MIPS=y
- # CONFIG_MIPS32 is not set
- CONFIG_MIPS64=y
---- linux-2.4.20/arch/s390/defconfig~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:11.000000000 +0800
-+++ linux-2.4.20-root/arch/s390/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_ISA is not set
- # CONFIG_EISA is not set
- # CONFIG_MCA is not set
---- linux-2.4.20/arch/s390/kernel/entry.S~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:11.000000000 +0800
-+++ linux-2.4.20-root/arch/s390/kernel/entry.S 2003-05-07 18:08:03.000000000 +0800
-@@ -558,18 +558,18 @@ sys_call_table:
- .long sys_fcntl64
- .long sys_ni_syscall
- .long sys_ni_syscall
-- .long sys_ni_syscall /* 224 - reserved for setxattr */
-- .long sys_ni_syscall /* 225 - reserved for lsetxattr */
-- .long sys_ni_syscall /* 226 - reserved for fsetxattr */
-- .long sys_ni_syscall /* 227 - reserved for getxattr */
-- .long sys_ni_syscall /* 228 - reserved for lgetxattr */
-- .long sys_ni_syscall /* 229 - reserved for fgetxattr */
-- .long sys_ni_syscall /* 230 - reserved for listxattr */
-- .long sys_ni_syscall /* 231 - reserved for llistxattr */
-- .long sys_ni_syscall /* 232 - reserved for flistxattr */
-- .long sys_ni_syscall /* 233 - reserved for removexattr */
-- .long sys_ni_syscall /* 234 - reserved for lremovexattr */
-- .long sys_ni_syscall /* 235 - reserved for fremovexattr */
-+ .long sys_setxattr
-+ .long sys_lsetxattr /* 225 */
-+ .long sys_fsetxattr
-+ .long sys_getxattr
-+ .long sys_lgetxattr
-+ .long sys_fgetxattr
-+ .long sys_listxattr /* 230 */
-+ .long sys_llistxattr
-+ .long sys_flistxattr
-+ .long sys_removexattr
-+ .long sys_lremovexattr
-+ .long sys_fremovexattr /* 235 */
- .long sys_gettid
- .long sys_tkill
- .rept 255-237
---- linux-2.4.20/arch/s390x/defconfig~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:11.000000000 +0800
-+++ linux-2.4.20-root/arch/s390x/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_ISA is not set
- # CONFIG_EISA is not set
- # CONFIG_MCA is not set
---- linux-2.4.20/arch/s390x/kernel/entry.S~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:11.000000000 +0800
-+++ linux-2.4.20-root/arch/s390x/kernel/entry.S 2003-05-07 18:08:03.000000000 +0800
-@@ -591,18 +591,18 @@ sys_call_table:
- .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
- .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
- .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
-+ .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
-+ .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
-+ .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
-+ .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
-+ .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
-+ .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
-+ .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
-+ .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
-+ .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
-+ .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
-+ .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
-+ .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
- .long SYSCALL(sys_gettid,sys_gettid)
- .long SYSCALL(sys_tkill,sys_tkill)
- .rept 255-237
---- linux-2.4.20/arch/s390x/kernel/wrapper32.S~linux-2.4.20-xattr-0.8.54 2002-02-26 03:37:56.000000000 +0800
-+++ linux-2.4.20-root/arch/s390x/kernel/wrapper32.S 2003-05-07 18:08:03.000000000 +0800
-@@ -1091,3 +1091,95 @@ sys32_fstat64_wrapper:
- llgtr %r3,%r3 # struct stat64 *
- llgfr %r4,%r4 # long
- jg sys32_fstat64 # branch to system call
-+
-+ .globl sys32_setxattr_wrapper
-+sys32_setxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_setxattr
-+
-+ .globl sys32_lsetxattr_wrapper
-+sys32_lsetxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_lsetxattr
-+
-+ .globl sys32_fsetxattr_wrapper
-+sys32_fsetxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_fsetxattr
-+
-+ .globl sys32_getxattr_wrapper
-+sys32_getxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_getxattr
-+
-+ .globl sys32_lgetxattr_wrapper
-+sys32_lgetxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_lgetxattr
-+
-+ .globl sys32_fgetxattr_wrapper
-+sys32_fgetxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_fgetxattr
-+
-+ .globl sys32_listxattr_wrapper
-+sys32_listxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_listxattr
-+
-+ .globl sys32_llistxattr_wrapper
-+sys32_llistxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_llistxattr
-+
-+ .globl sys32_flistxattr_wrapper
-+sys32_flistxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_flistxattr
-+
-+ .globl sys32_removexattr_wrapper
-+sys32_removexattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ jg sys_removexattr
-+
-+ .globl sys32_lremovexattr_wrapper
-+sys32_lremovexattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ jg sys_lremovexattr
-+
-+ .globl sys32_fremovexattr_wrapper
-+sys32_fremovexattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ jg sys_fremovexattr
-+
-+
---- linux-2.4.20/arch/sparc64/defconfig~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:12.000000000 +0800
-+++ linux-2.4.20-root/arch/sparc64/defconfig 2003-05-07 18:08:03.000000000 +0800
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
-
- #
- # Code maturity level options
---- linux-2.4.20/fs/Config.in~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-root/fs/Config.in 2003-05-07 18:08:03.000000000 +0800
-@@ -25,6 +25,11 @@ dep_mbool ' Debug Befs' CONFIG_BEFS_DEB
- 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
-+dep_bool ' Ext3 extended attribute block sharing' \
-+ CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
-+dep_bool ' Ext3 extended user attributes' \
-+ CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
- # 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
-@@ -84,6 +89,11 @@ dep_mbool ' QNX4FS write support (DANGE
- tristate 'ROM file system support' CONFIG_ROMFS_FS
-
- tristate 'Second extended fs support' CONFIG_EXT2_FS
-+dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
-+dep_bool ' Ext2 extended attribute block sharing' \
-+ CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
-+dep_bool ' Ext2 extended user attributes' \
-+ CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
-
- tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
-
-@@ -155,6 +165,10 @@ else
- define_tristate CONFIG_ZISOFS_FS n
- fi
-
-+# Meta block cache for Extended Attributes (ext2/ext3)
-+#tristate 'Meta block cache' CONFIG_FS_MBCACHE
-+define_tristate CONFIG_FS_MBCACHE y
-+
- mainmenu_option next_comment
- comment 'Partition Types'
- source fs/partitions/Config.in
---- linux-2.4.20/fs/Makefile~linux-2.4.20-xattr-0.8.54 2003-05-05 19:00:58.000000000 +0800
-+++ linux-2.4.20-root/fs/Makefile 2003-05-07 18:08:03.000000000 +0800
-@@ -79,6 +79,9 @@ obj-y += binfmt_script.o
-
- obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
-
-+export-objs += mbcache.o
-+obj-$(CONFIG_FS_MBCACHE) += mbcache.o
-+
- # persistent filesystems
- obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
-
---- linux-2.4.20/fs/ext2/Makefile~linux-2.4.20-xattr-0.8.54 2001-10-11 23:05:18.000000000 +0800
-+++ linux-2.4.20-root/fs/ext2/Makefile 2003-05-07 18:08:03.000000000 +0800
-@@ -13,4 +13,8 @@ obj-y := balloc.o bitmap.o dir.o file
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
-
-+export-objs += xattr.o
-+obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
-+obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
-+
- include $(TOPDIR)/Rules.make
---- linux-2.4.20/fs/ext2/file.c~linux-2.4.20-xattr-0.8.54 2001-10-11 23:05:18.000000000 +0800
-+++ linux-2.4.20-root/fs/ext2/file.c 2003-05-07 18:08:03.000000000 +0800
-@@ -20,6 +20,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/sched.h>
-
- /*
-@@ -51,4 +52,8 @@ struct file_operations ext2_file_operati
-
- struct inode_operations ext2_file_inode_operations = {
- truncate: ext2_truncate,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
---- linux-2.4.20/fs/ext2/ialloc.c~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-root/fs/ext2/ialloc.c 2003-05-07 18:08:03.000000000 +0800
-@@ -15,6 +15,7 @@
- #include <linux/config.h>
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/locks.h>
- #include <linux/quotaops.h>
-
-@@ -167,6 +168,7 @@ void ext2_free_inode (struct inode * ino
- */
- if (!is_bad_inode(inode)) {
- /* Quota is already initialized in iput() */
-+ ext2_xattr_delete_inode(inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
- }
---- linux-2.4.20/fs/ext2/inode.c~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-root/fs/ext2/inode.c 2003-05-07 18:08:03.000000000 +0800
-@@ -39,6 +39,18 @@ MODULE_LICENSE("GPL");
- static int ext2_update_inode(struct inode * inode, int do_sync);
-
- /*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext2_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = inode->u.ext2_i.i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
-+/*
- * Called at each iput()
- */
- void ext2_put_inode (struct inode * inode)
-@@ -53,9 +65,7 @@ void ext2_delete_inode (struct inode * i
- {
- lock_kernel();
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT2_ACL_IDX_INO ||
-- inode->i_ino == EXT2_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
- inode->u.ext2_i.i_dtime = CURRENT_TIME;
- mark_inode_dirty(inode);
-@@ -801,6 +811,8 @@ void ext2_truncate (struct inode * inode
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext2_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -888,8 +900,7 @@ void ext2_read_inode (struct inode * ino
- unsigned long offset;
- struct ext2_group_desc * gdp;
-
-- if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
-- inode->i_ino != EXT2_ACL_DATA_INO &&
-+ if ((inode->i_ino != EXT2_ROOT_INO &&
- inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
- ext2_error (inode->i_sb, "ext2_read_inode",
-@@ -974,10 +985,7 @@ void ext2_read_inode (struct inode * ino
- for (block = 0; block < EXT2_N_BLOCKS; block++)
- inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
-
-- if (inode->i_ino == EXT2_ACL_IDX_INO ||
-- inode->i_ino == EXT2_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext2_file_inode_operations;
- inode->i_fop = &ext2_file_operations;
- inode->i_mapping->a_ops = &ext2_aops;
-@@ -986,15 +994,17 @@ void ext2_read_inode (struct inode * ino
- inode->i_fop = &ext2_dir_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext2_inode_is_fast_symlink(inode))
- inode->i_op = &ext2_fast_symlink_inode_operations;
- else {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext2_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- }
-- } else
-+ } else {
-+ inode->i_op = &ext2_special_inode_operations;
- init_special_inode(inode, inode->i_mode,
- le32_to_cpu(raw_inode->i_block[0]));
-+ }
- brelse (bh);
- inode->i_attr_flags = 0;
- if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
---- linux-2.4.20/fs/ext2/namei.c~linux-2.4.20-xattr-0.8.54 2001-10-04 13:57:36.000000000 +0800
-+++ linux-2.4.20-root/fs/ext2/namei.c 2003-05-07 18:08:03.000000000 +0800
-@@ -31,6 +31,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/pagemap.h>
-
- /*
-@@ -136,7 +137,7 @@ static int ext2_symlink (struct inode *
-
- if (l > sizeof (inode->u.ext2_i.i_data)) {
- /* slow symlink */
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext2_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- err = block_symlink(inode, symname, l);
- if (err)
-@@ -345,4 +346,15 @@ struct inode_operations ext2_dir_inode_o
- rmdir: ext2_rmdir,
- mknod: ext2_mknod,
- rename: ext2_rename,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
-+};
-+
-+struct inode_operations ext2_special_inode_operations = {
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
---- linux-2.4.20/fs/ext2/super.c~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-root/fs/ext2/super.c 2003-05-07 18:08:03.000000000 +0800
-@@ -21,6 +21,7 @@
- #include <linux/string.h>
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/locks.h>
-@@ -125,6 +126,7 @@ void ext2_put_super (struct super_block
- int db_count;
- int i;
-
-+ ext2_xattr_put_super(sb);
- if (!(sb->s_flags & MS_RDONLY)) {
- struct ext2_super_block *es = EXT2_SB(sb)->s_es;
-
-@@ -175,6 +177,13 @@ static int parse_options (char * options
- this_char = strtok (NULL, ",")) {
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT2_FS_XATTR_USER
-+ 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")) {
-@@ -424,6 +433,9 @@ struct super_block * ext2_read_super (st
- blocksize = BLOCK_SIZE;
-
- sb->u.ext2_sb.s_mount_opt = 0;
-+#ifdef CONFIG_EXT2_FS_XATTR_USER
-+ /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
-+#endif
- if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
- &sb->u.ext2_sb.s_mount_opt)) {
- return NULL;
-@@ -813,12 +825,27 @@ static DECLARE_FSTYPE_DEV(ext2_fs_type,
-
- static int __init init_ext2_fs(void)
- {
-- return register_filesystem(&ext2_fs_type);
-+ int error = init_ext2_xattr();
-+ if (error)
-+ return error;
-+ error = init_ext2_xattr_user();
-+ if (error)
-+ goto fail;
-+ error = register_filesystem(&ext2_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext2_xattr_user();
-+fail:
-+ exit_ext2_xattr();
-+ return error;
- }
-
- static void __exit exit_ext2_fs(void)
- {
- unregister_filesystem(&ext2_fs_type);
-+ exit_ext2_xattr_user();
-+ exit_ext2_xattr();
- }
-
- EXPORT_NO_SYMBOLS;
---- linux-2.4.20/fs/ext2/symlink.c~linux-2.4.20-xattr-0.8.54 2000-09-28 04:41:33.000000000 +0800
-+++ linux-2.4.20-root/fs/ext2/symlink.c 2003-05-07 18:08:03.000000000 +0800
-@@ -19,6 +19,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-
- static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-@@ -32,7 +33,20 @@ static int ext2_follow_link(struct dentr
- return vfs_follow_link(nd, s);
- }
-
-+struct inode_operations ext2_symlink_inode_operations = {
-+ readlink: page_readlink,
-+ follow_link: page_follow_link,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
-+};
-+
- struct inode_operations ext2_fast_symlink_inode_operations = {
- readlink: ext2_readlink,
- follow_link: ext2_follow_link,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-root/fs/ext2/xattr.c 2003-05-07 18:08:03.000000000 +0800
-@@ -0,0 +1,1212 @@
-+/*
-+ * linux/fs/ext2/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * 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 EXT2_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 EXT2_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 ext2_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/module.h>
-+#include <linux/locks.h>
-+#include <linux/slab.h>
-+#include <linux/fs.h>
-+#include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-+#include <linux/mbcache.h>
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include <linux/compatmac.h>
-+
-+/* These symbols may be needed by a module. */
-+EXPORT_SYMBOL(ext2_xattr_register);
-+EXPORT_SYMBOL(ext2_xattr_unregister);
-+EXPORT_SYMBOL(ext2_xattr_get);
-+EXPORT_SYMBOL(ext2_xattr_list);
-+EXPORT_SYMBOL(ext2_xattr_set);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
-+#endif
-+
-+#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT2_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 ext2_xattr_set2(struct inode *, struct buffer_head *,
-+ struct ext2_xattr_header *);
-+
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+
-+static int ext2_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext2_xattr_cache_find(struct inode *,
-+ struct ext2_xattr_header *);
-+static void ext2_xattr_cache_remove(struct buffer_head *);
-+static void ext2_xattr_rehash(struct ext2_xattr_header *,
-+ struct ext2_xattr_entry *);
-+
-+static struct mb_cache *ext2_xattr_cache;
-+
-+#else
-+# define ext2_xattr_cache_insert(bh) 0
-+# define ext2_xattr_cache_find(inode, header) NULL
-+# define ext2_xattr_cache_remove(bh) while(0) {}
-+# define ext2_xattr_rehash(header, entry) while(0) {}
-+#endif
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext2_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+DECLARE_MUTEX(ext2_xattr_sem);
-+
-+static inline int
-+ext2_xattr_new_block(struct inode *inode, int * errp, int force)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
-+ EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
-+
-+ /* How can we enforce the allocation? */
-+ int block = ext2_new_block(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
-+ext2_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
-+ext2_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
-+ext2_xattr_free_block(struct inode * inode, unsigned long block)
-+{
-+ ext2_free_blocks(inode, block, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+#else
-+# define ext2_xattr_quota_free(inode) \
-+ DQUOT_FREE_BLOCK(inode, 1)
-+# define ext2_xattr_free_block(inode, block) \
-+ ext2_free_blocks(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 ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
-+rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ write_lock(&ext2_handler_lock);
-+ if (!ext2_xattr_handlers[name_index-1]) {
-+ ext2_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext2_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
-+{
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ write_lock(&ext2_handler_lock);
-+ ext2_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext2_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 struct ext2_xattr_handler *
-+ext2_xattr_resolve_name(const char **name)
-+{
-+ struct ext2_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext2_handler_lock);
-+ for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
-+ if (ext2_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext2_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext2_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext2_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext2_xattr_handler *
-+ext2_xattr_handler(int name_index)
-+{
-+ struct ext2_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ read_lock(&ext2_handler_lock);
-+ handler = ext2_xattr_handlers[name_index-1];
-+ read_unlock(&ext2_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext2_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext2_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
-+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext2_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext2_setxattr(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext2_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
-+ext2_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext2_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext2_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 (!EXT2_I(inode)->i_file_acl)
-+ return -ENOATTR;
-+ block = EXT2_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(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(inode->i_sb, "ext2_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 ext2_xattr_entry *next =
-+ EXT2_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 ext2_xattr_entry *next =
-+ EXT2_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext2_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 (ext2_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;
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext2_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 (!EXT2_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT2_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(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(inode->i_sb, "ext2_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 = EXT2_XATTR_NEXT(entry)) {
-+ struct ext2_xattr_handler *handler;
-+ struct ext2_xattr_entry *next =
-+ EXT2_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext2_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+
-+ if (ext2_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 = EXT2_XATTR_NEXT(entry)) {
-+ struct ext2_xattr_handler *handler;
-+
-+ handler = ext2_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext2_xattr_update_super_block(struct super_block *sb)
-+{
-+ if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+ EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
-+#endif
-+ EXT2_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_set(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 ext2_xattr_header *header = NULL;
-+ struct ext2_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int block = EXT2_I(inode)->i_file_acl;
-+ 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(&ext2_xattr_sem);
-+
-+ if (block) {
-+ /* The inode already has an extended attribute block. */
-+
-+ 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(EXT2_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(sb, "ext2_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 ext2_xattr_entry *next = EXT2_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 ext2_xattr_entry *next = EXT2_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 ext2_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 -= EXT2_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 += EXT2_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT2_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");
-+ ext2_xattr_cache_remove(bh);
-+ } 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(EXT2_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 = EXT2_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 = EXT2_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 = EXT2_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext2_xattr_set2(inode, bh, NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT2_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 = EXT2_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 - EXT2_XATTR_PAD, 0,
-+ EXT2_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext2_xattr_rehash(header, here);
-+
-+ error = ext2_xattr_set2(inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ up(&ext2_xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext2_xattr_set(): Update the file system.
-+ */
-+static int
-+ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
-+ struct ext2_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext2_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 (ext2_xattr_quota_alloc(inode, 1))
-+ 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;
-+ (void)ext2_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int force = EXT2_I(inode)->i_file_acl != 0;
-+ int block = ext2_xattr_new_block(inode, &error, force);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+ ext2_xattr_free_block(inode, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ mark_buffer_uptodate(new_bh, 1);
-+ unlock_buffer(new_bh);
-+ (void)ext2_xattr_cache_insert(new_bh);
-+
-+ ext2_xattr_update_super_block(sb);
-+ }
-+ mark_buffer_dirty(new_bh);
-+ if (IS_SYNC(inode)) {
-+ ll_rw_block(WRITE, 1, &new_bh);
-+ wait_on_buffer(new_bh);
-+ error = -EIO;
-+ if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
-+ goto cleanup;
-+ }
-+ }
-+
-+ /* Update the inode. */
-+ EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ if (IS_SYNC(inode)) {
-+ error = ext2_sync_inode (inode);
-+ if (error)
-+ goto cleanup;
-+ } else
-+ mark_inode_dirty(inode);
-+
-+ 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);
-+
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext2_xattr_free_block(inode, old_bh->b_blocknr);
-+ mark_buffer_clean(old_bh);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ ext2_xattr_quota_free(inode);
-+ mark_buffer_dirty(old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext2_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext2_xattr_delete_inode(struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT2_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ down(&ext2_xattr_sem);
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext2_error(inode->i_sb, "ext2_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(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext2_xattr_cache_remove(bh);
-+ ext2_xattr_free_block(inode, block);
-+ bforget(bh);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ mark_buffer_dirty(bh);
-+ if (IS_SYNC(inode)) {
-+ ll_rw_block(WRITE, 1, &bh);
-+ wait_on_buffer(bh);
-+ }
-+ ext2_xattr_quota_free(inode);
-+ }
-+ EXT2_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ up(&ext2_xattr_sem);
-+}
-+
-+/*
-+ * ext2_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext2_xattr_put_super(struct super_block *sb)
-+{
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+ mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
-+#endif
-+}
-+
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+
-+/*
-+ * ext2_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
-+ext2_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(ext2_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(&ext2_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext2_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_cmp(struct ext2_xattr_header *header1,
-+ struct ext2_xattr_header *header2)
-+{
-+ struct ext2_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 = EXT2_XATTR_NEXT(entry1);
-+ entry2 = EXT2_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext2_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 *
-+ext2_xattr_cache_find(struct inode *inode, struct ext2_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(ext2_xattr_cache, 0, inode->i_dev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext2_error(inode->i_sb, "ext2_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT2_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT2_XATTR_REFCOUNT_MAX);
-+ } else if (!ext2_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;
-+}
-+
-+/*
-+ * ext2_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext2_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext2_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
-+
-+/*
-+ * ext2_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
-+ struct ext2_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) +
-+ EXT2_XATTR_ROUND) >> EXT2_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
-+
-+/*
-+ * ext2_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext2_xattr_rehash(struct ext2_xattr_header *header,
-+ struct ext2_xattr_entry *entry)
-+{
-+ struct ext2_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext2_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 = EXT2_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+
-+int __init
-+init_ext2_xattr(void)
-+{
-+ ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 61);
-+ if (!ext2_xattr_cache)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext2_xattr(void)
-+{
-+ mb_cache_destroy(ext2_xattr_cache);
-+}
-+
-+#else /* CONFIG_EXT2_FS_XATTR_SHARING */
-+
-+int __init
-+init_ext2_xattr(void)
-+{
-+ return 0;
-+}
-+
-+void
-+exit_ext2_xattr(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-root/fs/ext2/xattr_user.c 2003-05-07 18:08:03.000000000 +0800
-@@ -0,0 +1,103 @@
-+/*
-+ * linux/fs/ext2/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/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-+
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+# include <linux/ext2_acl.h>
-+#endif
-+
-+#define XATTR_USER_PREFIX "user."
-+
-+static size_t
-+ext2_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);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return prefix_len + name_len + 1;
-+}
-+
-+static int
-+ext2_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 -ENOTSUP;
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+ error = ext2_permission_locked(inode, MAY_READ);
-+#else
-+ error = permission(inode, MAY_READ);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
-+ buffer, size);
-+}
-+
-+static int
-+ext2_xattr_user_set(struct inode *inode, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -ENOTSUP;
-+ if ( !S_ISREG(inode->i_mode) &&
-+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-+ return -EPERM;
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+ error = ext2_permission_locked(inode, MAY_WRITE);
-+#else
-+ error = permission(inode, MAY_WRITE);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
-+ value, size, flags);
-+}
-+
-+struct ext2_xattr_handler ext2_xattr_user_handler = {
-+ prefix: XATTR_USER_PREFIX,
-+ list: ext2_xattr_user_list,
-+ get: ext2_xattr_user_get,
-+ set: ext2_xattr_user_set,
-+};
-+
-+int __init
-+init_ext2_xattr_user(void)
-+{
-+ return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
-+ &ext2_xattr_user_handler);
-+}
-+
-+void
-+exit_ext2_xattr_user(void)
-+{
-+ ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
-+ &ext2_xattr_user_handler);
-+}
---- linux-2.4.20/fs/ext3/Makefile~linux-2.4.20-xattr-0.8.54 2003-05-05 19:01:02.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/Makefile 2003-05-07 18:10:33.000000000 +0800
-@@ -1,5 +1,5 @@
- #
--# Makefile for the linux ext2-filesystem routines.
-+# Makefile for the linux ext3-filesystem routines.
- #
- # Note! Dependencies are done automagically by 'make dep', which also
- # removes any old dependencies. DON'T put your own dependencies here
-@@ -9,10 +9,14 @@
-
- O_TARGET := ext3.o
-
--export-objs := super.o inode.o
-+export-objs := ext3-exports.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 hash.o
-+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
- obj-m := $(O_TARGET)
-
-+export-objs += xattr.o
-+obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
-+obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
-+
- include $(TOPDIR)/Rules.make
---- linux-2.4.20/fs/ext3/file.c~linux-2.4.20-xattr-0.8.54 2003-05-05 19:01:02.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/file.c 2003-05-07 18:08:03.000000000 +0800
-@@ -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>
-
-@@ -126,5 +127,9 @@ struct file_operations ext3_file_operati
- 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 */
- };
-
---- linux-2.4.20/fs/ext3/ialloc.c~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/ialloc.c 2003-05-07 18:08:03.000000000 +0800
-@@ -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 @@ void ext3_free_inode (handle_t *handle,
- * 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);
-
---- linux-2.4.20/fs/ext3/inode.c~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/inode.c 2003-05-07 18:08:03.000000000 +0800
-@@ -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 = inode->u.ext3_i.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 @@ void ext3_delete_inode (struct inode * i
- {
- 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();
-@@ -1855,6 +1865,8 @@ void ext3_truncate(struct inode * inode)
- 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;
-
-@@ -2002,8 +2014,6 @@ int ext3_get_inode_loc (struct inode *in
- 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(
-@@ -2130,10 +2140,7 @@ void ext3_read_inode(struct inode * inod
-
- 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;
-@@ -2141,15 +2148,17 @@ void ext3_read_inode(struct inode * inod
- 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]));
-+ }
- ext3_set_inode_flags(inode);
- return;
-
---- linux-2.4.20/fs/ext3/namei.c~linux-2.4.20-xattr-0.8.54 2003-05-05 19:01:05.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/namei.c 2003-05-07 18:08:03.000000000 +0800
-@@ -29,6 +29,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>
-@@ -1611,7 +1612,7 @@ static int ext3_mkdir(struct inode * dir
- 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;
-@@ -1619,7 +1620,6 @@ static int ext3_mkdir(struct inode * dir
- 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? */
-@@ -1646,9 +1646,6 @@ static int ext3_mkdir(struct inode * dir
- 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) {
-@@ -2017,7 +2014,7 @@ static int ext3_symlink (struct inode *
- 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;
- inode->i_mapping->a_ops = &ext3_aops;
- /*
- * block_symlink() calls back into ext3_prepare/commit_write.
-@@ -2244,4 +2241,16 @@ struct inode_operations ext3_dir_inode_o
- 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 */
-+};
-+
---- linux-2.4.20/fs/ext3/super.c~linux-2.4.20-xattr-0.8.54 2003-05-05 19:01:02.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/super.c 2003-05-07 18:08:39.000000000 +0800
-@@ -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 @@ void ext3_put_super (struct super_block
- 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);
-@@ -499,6 +501,7 @@ static int parse_options (char * options
- 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;
-@@ -511,6 +514,13 @@ static int parse_options (char * options
- this_char = strtok (NULL, ",")) {
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT3_FS_XATTR_USER
-+ 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")) {
-@@ -928,6 +938,12 @@ struct super_block * ext3_read_super (st
- 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_USER
-+ /* set_opt(sbi->s_mount_opt, XATTR_USER); */
-+#endif
-+
- if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
- sb->s_dev = 0;
- goto out_fail;
-@@ -1767,17 +1783,29 @@ static DECLARE_FSTYPE_DEV(ext3_fs_type,
-
- static int __init init_ext3_fs(void)
- {
-- return register_filesystem(&ext3_fs_type);
-+ int error = init_ext3_xattr();
-+ if (error)
-+ return error;
-+ error = init_ext3_xattr_user();
-+ if (error)
-+ goto fail;
-+ error = register_filesystem(&ext3_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext3_xattr_user();
-+fail:
-+ exit_ext3_xattr();
-+ return error;
- }
-
- static void __exit exit_ext3_fs(void)
- {
- unregister_filesystem(&ext3_fs_type);
-+ exit_ext3_xattr_user();
-+ exit_ext3_xattr();
- }
-
--EXPORT_SYMBOL(ext3_force_commit);
--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");
- MODULE_LICENSE("GPL");
---- linux-2.4.20/fs/ext3/symlink.c~linux-2.4.20-xattr-0.8.54 2001-11-10 06:25:04.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/symlink.c 2003-05-07 18:08:03.000000000 +0800
-@@ -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 @@ static int ext3_follow_link(struct dentr
- 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 */
- };
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/xattr.c 2003-05-07 18:09:23.000000000 +0800
-@@ -0,0 +1,1225 @@
-+/*
-+ * 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/module.h>
-+#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>
-+#include <linux/mbcache.h>
-+#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) while(0) {}
-+# define ext3_xattr_rehash(header, entry) 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 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,
-+ const 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);
-+ }
-+
-+ 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);
-+ }
-+ 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, 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 block = EXT3_I(inode)->i_file_acl;
-+ 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 (block) {
-+ /* The inode already has an extended attribute block. */
-+ 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);
-+ 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 (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;
-+ (void)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);
-+ (void)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_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_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);
-+ 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)
-+{
-+#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 */
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/xattr_user.c 2003-05-07 18:08:03.000000000 +0800
-@@ -0,0 +1,111 @@
-+/*
-+ * 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/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_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);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return prefix_len + name_len + 1;
-+}
-+
-+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 -ENOTSUP;
-+#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 -ENOTSUP;
-+ 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;
-+
-+ 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);
-+
-+ 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,
-+};
-+
-+int __init
-+init_ext3_xattr_user(void)
-+{
-+ return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
-+ &ext3_xattr_user_handler);
-+}
-+
-+void
-+exit_ext3_xattr_user(void)
-+{
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
-+ &ext3_xattr_user_handler);
-+}
---- linux-2.4.20/fs/jfs/jfs_xattr.h~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-root/fs/jfs/jfs_xattr.h 2003-05-07 18:08:03.000000000 +0800
-@@ -52,8 +52,10 @@ struct jfs_ea_list {
- #define END_EALIST(ealist) \
- ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
-
--extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
--extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
-+extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
-+ int);
-+extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
-+ int);
- extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
- extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
- extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
---- linux-2.4.20/fs/jfs/xattr.c~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-root/fs/jfs/xattr.c 2003-05-07 18:08:03.000000000 +0800
-@@ -641,7 +641,7 @@ static int ea_put(struct inode *inode, s
- }
-
- static int can_set_xattr(struct inode *inode, const char *name,
-- void *value, size_t value_len)
-+ const void *value, size_t value_len)
- {
- if (IS_RDONLY(inode))
- return -EROFS;
-@@ -660,7 +660,7 @@ static int can_set_xattr(struct inode *i
- return permission(inode, MAY_WRITE);
- }
-
--int __jfs_setxattr(struct inode *inode, const char *name, void *value,
-+int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
- size_t value_len, int flags)
- {
- struct jfs_ea_list *ealist;
-@@ -799,7 +799,7 @@ int __jfs_setxattr(struct inode *inode,
- return rc;
- }
-
--int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
-+int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
- size_t value_len, int flags)
- {
- if (value == NULL) { /* empty EA, do not remove */
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-root/fs/mbcache.c 2003-05-07 18:08:03.000000000 +0800
-@@ -0,0 +1,648 @@
-+/*
-+ * 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. Entries that cannot be freed immediately are put
-+ * back on the lru list.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/cache_def.h>
-+#include <linux/version.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)");
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-+MODULE_LICENSE("GPL");
-+#endif
-+
-+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 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 void
-+mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
-+
-+static struct cache_definition mb_cache_definition = {
-+ "mb_cache",
-+ mb_cache_memory_pressure
-+};
-+
-+
-+static inline int
-+__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
-+{
-+ return !list_empty(&ce->e_block_list);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_unhash(struct mb_cache_entry *ce)
-+{
-+ int n;
-+
-+ if (__mb_cache_entry_is_hashed(ce)) {
-+ 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 void
-+__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+
-+ mb_assert(atomic_read(&ce->e_used) == 0);
-+ if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
-+ /* free failed -- put back on the lru list
-+ for freeing later. */
-+ spin_lock(&mb_cache_spinlock);
-+ list_add(&ce->e_lru_list, &mb_cache_lru_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ } else {
-+ kmem_cache_free(cache->c_entry_cache, ce);
-+ atomic_dec(&cache->c_entry_count);
-+ }
-+}
-+
-+
-+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_hashed(ce))
-+ list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
-+ else {
-+ spin_unlock(&mb_cache_spinlock);
-+ __mb_cache_entry_forget(ce, GFP_KERNEL);
-+ return;
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+}
-+
-+
-+/*
-+ * mb_cache_memory_pressure() memory pressure callback
-+ *
-+ * This function is called by the kernel memory management when memory
-+ * gets low.
-+ *
-+ * @priority: Amount by which to shrink the cache (0 = highes priority)
-+ * @gfp_mask: (ignored)
-+ */
-+static void
-+mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l, *ltmp;
-+ int count = 0;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(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 of %d entries",
-+ count / (priority ? priority : 1), count);
-+ if (priority)
-+ count /= priority;
-+ while (count-- && !list_empty(&mb_cache_lru_list)) {
-+ struct mb_cache_entry *ce =
-+ list_entry(mb_cache_lru_list.next,
-+ struct mb_cache_entry, e_lru_list);
-+ list_del(&ce->e_lru_list);
-+ __mb_cache_entry_unhash(ce);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), gfp_mask);
-+ }
-+}
-+
-+
-+/*
-+ * 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_count: 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_count)
-+{
-+ int m=0, n;
-+ struct mb_cache *cache = NULL;
-+
-+ if(entry_size < sizeof(struct mb_cache_entry) +
-+ indexes_count * sizeof(struct mb_cache_entry_index))
-+ return NULL;
-+
-+ MOD_INC_USE_COUNT;
-+ cache = kmalloc(sizeof(struct mb_cache) +
-+ indexes_count * sizeof(struct list_head), GFP_KERNEL);
-+ if (!cache)
-+ goto fail;
-+ cache->c_name = name;
-+ cache->c_op.free = NULL;
-+ if (cache_op)
-+ cache->c_op.free = cache_op->free;
-+ atomic_set(&cache->c_entry_count, 0);
-+ cache->c_bucket_count = bucket_count;
-+#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);
-+ 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);
-+ }
-+ MOD_DEC_USE_COUNT;
-+ 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.
-+ *
-+ * @cache: which cache to shrink
-+ * @dev: which device's cache entries to shrink
-+ */
-+void
-+mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l, *ltmp;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ if (ce->e_dev == dev) {
-+ list_del(&ce->e_lru_list);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ __mb_cache_entry_unhash(ce);
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), GFP_KERNEL);
-+ }
-+}
-+
-+
-+/*
-+ * 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, *ltmp;
-+ int n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ if (ce->e_cache == cache) {
-+ list_del(&ce->e_lru_list);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ __mb_cache_entry_unhash(ce);
-+ }
-+ }
-+ list_del(&cache->c_cache_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), GFP_KERNEL);
-+ }
-+
-+ if (atomic_read(&cache->c_entry_count) > 0) {
-+ mb_error("cache %s: %d orphaned entries",
-+ cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ }
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
-+ /* We don't have kmem_cache_destroy() in 2.2.x */
-+ kmem_cache_shrink(cache->c_entry_cache);
-+#else
-+ kmem_cache_destroy(cache->c_entry_cache);
-+#endif
-+ for (n=0; n < mb_cache_indexes(cache); n++)
-+ kfree(cache->c_indexes_hash[n]);
-+ kfree(cache->c_block_hash);
-+ kfree(cache);
-+
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+
-+/*
-+ * 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, if another process has
-+ * inserted the same cache entry in the meantime).
-+ *
-+ * @dev: 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, kdev_t dev,
-+ unsigned long block, unsigned int keys[])
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
-+ struct list_head *l;
-+ int error = -EBUSY, n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(l, &cache->c_block_hash[bucket]) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_dev == dev && ce->e_block == block)
-+ goto out;
-+ }
-+ __mb_cache_entry_unhash(ce);
-+ ce->e_dev = dev;
-+ ce->e_block = block;
-+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
-+ for (n=0; n<mb_cache_indexes(cache); n++) {
-+ ce->e_indexes[n].o_key = keys[n];
-+ bucket = keys[n] % cache->c_bucket_count;
-+ list_add(&ce->e_indexes[n].o_list,
-+ &cache->c_indexes_hash[n][bucket]);
-+ }
-+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(list_empty(&ce->e_lru_list));
-+ __mb_cache_entry_unhash(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(list_empty(&ce->e_lru_list));
-+ __mb_cache_entry_unhash(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, kdev_t dev, unsigned long block)
-+{
-+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ 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_dev == dev && ce->e_block == block) {
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+ atomic_inc(&ce->e_used);
-+ 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, kdev_t dev, 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_dev == dev && ce->e_indexes[index].o_key == key) {
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+ atomic_inc(&ce->e_used);
-+ 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)
-+ * @dev: 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, kdev_t dev,
-+ unsigned int key)
-+{
-+ unsigned int bucket = key % cache->c_bucket_count;
-+ 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, dev, 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)
-+ * @dev: 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, kdev_t dev,
-+ unsigned int key)
-+{
-+ struct mb_cache *cache = prev->e_cache;
-+ unsigned int bucket = key % cache->c_bucket_count;
-+ 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, dev, key);
-+ __mb_cache_entry_release_unlock(prev);
-+ return ce;
-+}
-+
-+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
-+
-+static int __init init_mbcache(void)
-+{
-+ register_cache(&mb_cache_definition);
-+ return 0;
-+}
-+
-+static void __exit exit_mbcache(void)
-+{
-+ unregister_cache(&mb_cache_definition);
-+}
-+
-+module_init(init_mbcache)
-+module_exit(exit_mbcache)
-+
---- linux-2.4.20/include/asm-arm/unistd.h~linux-2.4.20-xattr-0.8.54 2002-08-03 08:39:45.000000000 +0800
-+++ linux-2.4.20-root/include/asm-arm/unistd.h 2003-05-07 18:08:03.000000000 +0800
-@@ -244,7 +244,6 @@
- #define __NR_security (__NR_SYSCALL_BASE+223)
- #define __NR_gettid (__NR_SYSCALL_BASE+224)
- #define __NR_readahead (__NR_SYSCALL_BASE+225)
--#if 0 /* allocated in 2.5 */
- #define __NR_setxattr (__NR_SYSCALL_BASE+226)
- #define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
- #define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
-@@ -257,7 +256,6 @@
- #define __NR_removexattr (__NR_SYSCALL_BASE+235)
- #define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
- #define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
--#endif
- #define __NR_tkill (__NR_SYSCALL_BASE+238)
- /*
- * Please check 2.5 _before_ adding calls here,
---- linux-2.4.20/include/asm-ppc64/unistd.h~linux-2.4.20-xattr-0.8.54 2002-08-03 08:39:45.000000000 +0800
-+++ linux-2.4.20-root/include/asm-ppc64/unistd.h 2003-05-07 18:08:03.000000000 +0800
-@@ -218,6 +218,7 @@
- #define __NR_gettid 207
- #if 0 /* Reserved syscalls */
- #define __NR_tkill 208
-+#endif
- #define __NR_setxattr 209
- #define __NR_lsetxattr 210
- #define __NR_fsetxattr 211
-@@ -230,6 +231,7 @@
- #define __NR_removexattr 218
- #define __NR_lremovexattr 219
- #define __NR_fremovexattr 220
-+#if 0 /* Reserved syscalls */
- #define __NR_futex 221
- #endif
-
---- linux-2.4.20/include/asm-s390/unistd.h~linux-2.4.20-xattr-0.8.54 2002-08-03 08:39:45.000000000 +0800
-+++ linux-2.4.20-root/include/asm-s390/unistd.h 2003-05-07 18:08:03.000000000 +0800
-@@ -212,9 +212,18 @@
- #define __NR_getdents64 220
- #define __NR_fcntl64 221
- #define __NR_readahead 222
--/*
-- * Numbers 224-235 are reserved for posix acl
-- */
-+#define __NR_setxattr 224
-+#define __NR_lsetxattr 225
-+#define __NR_fsetxattr 226
-+#define __NR_getxattr 227
-+#define __NR_lgetxattr 228
-+#define __NR_fgetxattr 229
-+#define __NR_listxattr 230
-+#define __NR_llistxattr 231
-+#define __NR_flistxattr 232
-+#define __NR_removexattr 233
-+#define __NR_lremovexattr 234
-+#define __NR_fremovexattr 235
- #define __NR_gettid 236
- #define __NR_tkill 237
-
---- linux-2.4.20/include/asm-s390x/unistd.h~linux-2.4.20-xattr-0.8.54 2002-08-03 08:39:45.000000000 +0800
-+++ linux-2.4.20-root/include/asm-s390x/unistd.h 2003-05-07 18:08:03.000000000 +0800
-@@ -180,9 +180,18 @@
- #define __NR_mincore 218
- #define __NR_madvise 219
- #define __NR_readahead 222
--/*
-- * Numbers 224-235 are reserved for posix acl
-- */
-+#define __NR_setxattr 224
-+#define __NR_lsetxattr 225
-+#define __NR_fsetxattr 226
-+#define __NR_getxattr 227
-+#define __NR_lgetxattr 228
-+#define __NR_fgetxattr 229
-+#define __NR_listxattr 230
-+#define __NR_llistxattr 231
-+#define __NR_flistxattr 232
-+#define __NR_removexattr 233
-+#define __NR_lremovexattr 234
-+#define __NR_fremovexattr 235
- #define __NR_gettid 236
- #define __NR_tkill 237
-
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-root/include/linux/cache_def.h 2003-05-07 18:08:03.000000000 +0800
-@@ -0,0 +1,15 @@
-+/*
-+ * linux/cache_def.h
-+ * Handling of caches defined in drivers, filesystems, ...
-+ *
-+ * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+struct cache_definition {
-+ const char *name;
-+ void (*shrink)(int, unsigned int);
-+ struct list_head link;
-+};
-+
-+extern void register_cache(struct cache_definition *);
-+extern void unregister_cache(struct cache_definition *);
---- linux-2.4.20/include/linux/errno.h~linux-2.4.20-xattr-0.8.54 2003-04-14 16:39:03.000000000 +0800
-+++ linux-2.4.20-root/include/linux/errno.h 2003-05-07 18:08:03.000000000 +0800
-@@ -23,4 +23,8 @@
-
- #endif
-
-+/* Defined for extended attributes */
-+#define ENOATTR ENODATA /* No such attribute */
-+#define ENOTSUP EOPNOTSUPP /* Operation not supported */
-+
- #endif
---- linux-2.4.20/include/linux/ext2_fs.h~linux-2.4.20-xattr-0.8.54 2003-04-14 16:39:08.000000000 +0800
-+++ linux-2.4.20-root/include/linux/ext2_fs.h 2003-05-07 18:08:03.000000000 +0800
-@@ -57,8 +57,6 @@
- */
- #define EXT2_BAD_INO 1 /* Bad blocks inode */
- #define EXT2_ROOT_INO 2 /* Root inode */
--#define EXT2_ACL_IDX_INO 3 /* ACL inode */
--#define EXT2_ACL_DATA_INO 4 /* ACL inode */
- #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
-
-@@ -86,7 +84,6 @@
- #else
- # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
- #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -121,28 +118,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext2_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext2_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 ext2_group_desc
-@@ -314,6 +289,7 @@ struct ext2_inode {
- #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
- #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
- #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
-+#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-
- #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
- #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
-@@ -397,6 +373,7 @@ struct ext2_super_block {
-
- #ifdef __KERNEL__
- #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
-+#define EXT2_I(inode) (&((inode)->u.ext2_i))
- #else
- /* Assume that user mode programs are passing in an ext2fs superblock, not
- * a kernel struct super_block. This will allow us to call the feature-test
-@@ -466,7 +443,7 @@ struct ext2_super_block {
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
- #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
-
--#define EXT2_FEATURE_COMPAT_SUPP 0
-+#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
- #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
-@@ -623,8 +600,10 @@ extern struct address_space_operations e
-
- /* namei.c */
- extern struct inode_operations ext2_dir_inode_operations;
-+extern struct inode_operations ext2_special_inode_operations;
-
- /* symlink.c */
-+extern struct inode_operations ext2_symlink_inode_operations;
- extern struct inode_operations ext2_fast_symlink_inode_operations;
-
- #endif /* __KERNEL__ */
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-root/include/linux/ext2_xattr.h 2003-05-07 18:08:03.000000000 +0800
-@@ -0,0 +1,157 @@
-+/*
-+ File: linux/ext2_xattr.h
-+
-+ On-disk format of extended attributes for the ext2 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 EXT2_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT2_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT2_XATTR_INDEX_MAX 10
-+#define EXT2_XATTR_INDEX_USER 1
-+#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
-+#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+
-+struct ext2_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 ext2_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 EXT2_XATTR_PAD_BITS 2
-+#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
-+#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
-+#define EXT2_XATTR_LEN(name_len) \
-+ (((name_len) + EXT2_XATTR_ROUND + \
-+ sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
-+#define EXT2_XATTR_NEXT(entry) \
-+ ( (struct ext2_xattr_entry *)( \
-+ (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT2_XATTR_SIZE(size) \
-+ (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
-+
-+#ifdef __KERNEL__
-+
-+# ifdef CONFIG_EXT2_FS_XATTR
-+
-+struct ext2_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 ext2_xattr_register(int, struct ext2_xattr_handler *);
-+extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
-+
-+extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
-+extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
-+extern int ext2_removexattr(struct dentry *, const char *);
-+
-+extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext2_xattr_list(struct inode *, char *, size_t);
-+extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
-+
-+extern void ext2_xattr_delete_inode(struct inode *);
-+extern void ext2_xattr_put_super(struct super_block *);
-+
-+extern int init_ext2_xattr(void) __init;
-+extern void exit_ext2_xattr(void);
-+
-+# else /* CONFIG_EXT2_FS_XATTR */
-+# define ext2_setxattr NULL
-+# define ext2_getxattr NULL
-+# define ext2_listxattr NULL
-+# define ext2_removexattr NULL
-+
-+static inline int
-+ext2_xattr_get(struct inode *inode, int name_index,
-+ const char *name, void *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext2_xattr_set(struct inode *inode, int name_index, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline void
-+ext2_xattr_delete_inode(struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext2_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext2_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext2_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT2_FS_XATTR */
-+
-+# ifdef CONFIG_EXT2_FS_XATTR_USER
-+
-+extern int init_ext2_xattr_user(void) __init;
-+extern void exit_ext2_xattr_user(void);
-+
-+# else /* CONFIG_EXT2_FS_XATTR_USER */
-+
-+static inline int
-+init_ext2_xattr_user(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext2_xattr_user(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT2_FS_XATTR_USER */
-+
-+#endif /* __KERNEL__ */
-+
---- linux-2.4.20/include/linux/ext3_fs.h~linux-2.4.20-xattr-0.8.54 2003-05-05 19:01:04.000000000 +0800
-+++ linux-2.4.20-root/include/linux/ext3_fs.h 2003-05-07 18:08:03.000000000 +0800
-@@ -63,8 +63,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 */
-@@ -94,7 +92,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)
-@@ -129,28 +126,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
-@@ -344,6 +319,7 @@ struct ext3_inode {
- #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
-@@ -520,7 +496,7 @@ struct ext3_super_block {
- #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| \
-@@ -703,6 +679,7 @@ extern void ext3_check_inodes_bitmap (st
- 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 *);
-
-@@ -771,8 +748,10 @@ extern struct address_space_operations e
-
- /* 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;
-
-
---- linux-2.4.20/include/linux/ext3_jbd.h~linux-2.4.20-xattr-0.8.54 2003-05-05 19:01:02.000000000 +0800
-+++ linux-2.4.20-root/include/linux/ext3_jbd.h 2003-05-07 18:08:03.000000000 +0800
-@@ -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);
-
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-root/include/linux/ext3_xattr.h 2003-05-07 18:08:03.000000000 +0800
-@@ -0,0 +1,157 @@
-+/*
-+ 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
-+#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 __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, 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 *, const 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) __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)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+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 -ENOTSUP;
-+}
-+
-+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 */
-+
-+# 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__ */
-+
---- linux-2.4.20/include/linux/fs.h~linux-2.4.20-xattr-0.8.54 2003-05-05 19:00:55.000000000 +0800
-+++ linux-2.4.20-root/include/linux/fs.h 2003-05-07 18:08:03.000000000 +0800
-@@ -888,7 +888,7 @@ struct inode_operations {
- int (*setattr) (struct dentry *, struct iattr *);
- int (*setattr_raw) (struct inode *, struct iattr *);
- int (*getattr) (struct dentry *, struct iattr *);
-- int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
-+ int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
- ssize_t (*listxattr) (struct dentry *, char *, size_t);
- int (*removexattr) (struct dentry *, const char *);
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-root/include/linux/mbcache.h 2003-05-07 18:08:03.000000000 +0800
-@@ -0,0 +1,69 @@
-+/*
-+ 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 {
-+ int (*free)(struct mb_cache_entry *, int);
-+};
-+
-+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_count;
-+#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;
-+ kdev_t e_dev;
-+ unsigned long 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 *, kdev_t);
-+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 *, kdev_t, unsigned long,
-+ 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 *, kdev_t,
-+ unsigned long);
-+#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,
-+ kdev_t, unsigned int);
-+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
-+ kdev_t, unsigned int);
-+#endif
---- linux-2.4.20/kernel/ksyms.c~linux-2.4.20-xattr-0.8.54 2003-05-05 17:43:15.000000000 +0800
-+++ linux-2.4.20-root/kernel/ksyms.c 2003-05-07 18:08:03.000000000 +0800
-@@ -11,6 +11,7 @@
-
- #include <linux/config.h>
- #include <linux/slab.h>
-+#include <linux/cache_def.h>
- #include <linux/module.h>
- #include <linux/blkdev.h>
- #include <linux/cdrom.h>
-@@ -89,6 +90,7 @@ EXPORT_SYMBOL(exit_mm);
- EXPORT_SYMBOL(exit_files);
- EXPORT_SYMBOL(exit_fs);
- EXPORT_SYMBOL(exit_sighand);
-+EXPORT_SYMBOL(copy_fs_struct);
-
- /* internal kernel memory management */
- EXPORT_SYMBOL(_alloc_pages);
-@@ -107,6 +109,8 @@ EXPORT_SYMBOL(kmem_cache_validate);
- EXPORT_SYMBOL(kmem_cache_alloc);
- EXPORT_SYMBOL(kmem_cache_free);
- EXPORT_SYMBOL(kmem_cache_size);
-+EXPORT_SYMBOL(register_cache);
-+EXPORT_SYMBOL(unregister_cache);
- EXPORT_SYMBOL(kmalloc);
- EXPORT_SYMBOL(kfree);
- EXPORT_SYMBOL(vfree);
---- linux-2.4.20/mm/vmscan.c~linux-2.4.20-xattr-0.8.54 2002-11-29 07:53:15.000000000 +0800
-+++ linux-2.4.20-root/mm/vmscan.c 2003-05-07 18:08:03.000000000 +0800
-@@ -18,6 +18,7 @@
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
- #include <linux/swapctl.h>
-+#include <linux/cache_def.h>
- #include <linux/smp_lock.h>
- #include <linux/pagemap.h>
- #include <linux/init.h>
-@@ -34,6 +35,39 @@
- */
- #define DEF_PRIORITY (6)
-
-+static DECLARE_MUTEX(other_caches_sem);
-+static LIST_HEAD(cache_definitions);
-+
-+void register_cache(struct cache_definition *cache)
-+{
-+ down(&other_caches_sem);
-+ list_add(&cache->link, &cache_definitions);
-+ up(&other_caches_sem);
-+}
-+
-+void unregister_cache(struct cache_definition *cache)
-+{
-+ down(&other_caches_sem);
-+ list_del(&cache->link);
-+ up(&other_caches_sem);
-+}
-+
-+static void shrink_other_caches(unsigned int priority, int gfp_mask)
-+{
-+ struct list_head *p;
-+
-+ if (down_trylock(&other_caches_sem))
-+ return;
-+
-+ list_for_each_prev(p, &cache_definitions) {
-+ struct cache_definition *cache =
-+ list_entry(p, struct cache_definition, link);
-+
-+ cache->shrink(priority, gfp_mask);
-+ }
-+ up(&other_caches_sem);
-+}
-+
- /*
- * The swap-out function returns 1 if it successfully
- * scanned all the pages it was asked to (`count').
-@@ -577,6 +611,7 @@ static int shrink_caches(zone_t * classz
-
- shrink_dcache_memory(priority, gfp_mask);
- shrink_icache_memory(priority, gfp_mask);
-+ shrink_other_caches(priority, gfp_mask);
- #ifdef CONFIG_QUOTA
- shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
- #endif
---- /dev/null 2003-01-30 18:24:37.000000000 +0800
-+++ linux-root/fs/ext3/ext3-exports.c 2003-05-05 18:19:11.000000000 +0800
-@@ -0,0 +1,13 @@
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
-+
-+EXPORT_SYMBOL(ext3_force_commit);
-+EXPORT_SYMBOL(ext3_bread);
-+EXPORT_SYMBOL(ext3_xattr_register);
-+EXPORT_SYMBOL(ext3_xattr_unregister);
-+EXPORT_SYMBOL(ext3_xattr_get);
-+EXPORT_SYMBOL(ext3_xattr_list);
-+EXPORT_SYMBOL(ext3_xattr_set);
-
-_
+Version 45: more robust and general dev_read_only for failover (b=4834)
Version 44: fix link_path_walk_it() oops creating .foo in deleted "." (b=5548)
Version 43: fix remove_suid to not crash 2.6, and do anything on 2.4 (b=5695)
Version 42: export show_task()
--- /dev/null Fri Aug 30 17:31:37 2002
+++ linux-2.4.18-18.8.0-l12-braam/include/linux/lustre_version.h Thu Feb 13 07:58:33 2003
@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 44
++#define LUSTRE_KERNEL_VERSION 45
_
+++ /dev/null
-Index: linux-2.4.20-rh/drivers/net/netconsole.c
-===================================================================
---- linux-2.4.20-rh.orig/drivers/net/netconsole.c 2003-07-22 16:02:23.000000000 +0800
-+++ linux-2.4.20-rh/drivers/net/netconsole.c 2003-11-11 07:42:33.000000000 +0800
-@@ -12,6 +12,8 @@
- *
- * 2001-09-17 started by Ingo Molnar.
- * 2002-03-14 simultaneous syslog packet option by Michael K. Johnson
-+ * 2003-10-30 Add sysrq command processing by Wangdi <wangdi@clusterfs.com>
-+ *
- */
-
- /****************************************************************
-@@ -51,6 +53,7 @@
- #include <linux/tty_driver.h>
- #include <linux/etherdevice.h>
- #include <linux/elf.h>
-+#include "netconsole.h"
-
- static struct net_device *netconsole_dev;
- static u16 source_port, netdump_target_port, netlog_target_port, syslog_target_port;
-@@ -62,12 +65,11 @@
- static unsigned int mhz = 500, idle_timeout;
- static unsigned long long mhz_cycles, jiffy_cycles;
-
--#include "netconsole.h"
-
- #define MAX_UDP_CHUNK 1460
- #define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN)
-
--#define DEBUG 0
-+#define DEBUG 0
- #if DEBUG
- # define Dprintk(x...) printk(KERN_INFO x)
- #else
-@@ -187,6 +189,22 @@
- }
- }
- }
-+void (*irqfunc)(int, void *, struct pt_regs *);
-+
-+static void netdump_poll(struct net_device *dev)
-+{
-+ int budget = 1;
-+
-+ disable_irq(dev->irq);
-+
-+ irqfunc(dev->irq, dev, 0);
-+
-+ if(dev->poll && test_bit(__LINK_STATE_RX_SCHED, &dev->state))
-+ dev->poll(dev, &budget);
-+
-+ enable_irq(dev->irq);
-+
-+}
-
- static struct sk_buff * alloc_netconsole_skb(struct net_device *dev, int len, int reserve)
- {
-@@ -209,7 +227,7 @@
- once = 0;
- }
- Dprintk("alloc skb: polling controller ...\n");
-- dev->poll_controller(dev);
-+ netdump_poll(dev);
- goto repeat;
- }
- }
-@@ -231,7 +249,7 @@
- spin_unlock(&dev->xmit_lock);
-
- Dprintk("xmit skb: polling controller ...\n");
-- dev->poll_controller(dev);
-+ netdump_poll(dev);
- zap_completion_queue();
- goto repeat_poll;
- }
-@@ -426,18 +444,79 @@
- static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
- static unsigned int log_offset;
-
-+static int thread_stopped = 0;
-+/*Interrupt function for netdump */
-+static int sysrq_mode = 0;
-+static int stop_sysrq_thread = 0;
-+#define Set_Sysrq_mode() (sysrq_mode = 1)
-+#define Clear_Sysrq_mode() (sysrq_mode = 0)
-+static char send_cache[MAX_PRINT_CHUNK];
-+static unsigned int send_cache_pos = 0;
-+wait_queue_head_t sysrq_thread_queue;
-+wait_queue_head_t sysrq_thread_waiter_queue;
-+
-+#define SEND_MSG_BUFFER(buf, len) \
-+do \
-+{ \
-+ reply_t reply; \
-+ unsigned int flags; \
-+ __save_flags(flags); \
-+ __cli(); \
-+ reply.code = REPLY_LOG; \
-+ reply.nr = 0; \
-+ reply.info = 0; \
-+ spin_lock(&sequence_lock); \
-+ send_netlog_skb(dev, buf, len, &reply); \
-+ spin_unlock(&sequence_lock); \
-+ __restore_flags(flags); \
-+}while(0);
-+
-+void netconsole_do_sysrq(req_t *req)
-+{
-+ struct pt_regs regs;
-+ struct net_device *dev = netconsole_dev;
-+
-+ if (!dev)
-+ return;
-+ Set_Sysrq_mode();
-+ get_current_regs(®s);
-+ handle_sysrq((int)req->from, ®s, NULL);
-+
-+ if (send_cache_pos != 0){
-+ SEND_MSG_BUFFER(send_cache, send_cache_pos);
-+ memset(send_cache, 0, MAX_PRINT_CHUNK);
-+ send_cache_pos = 0;
-+ }
-+
-+ Clear_Sysrq_mode();
-+}
- static void write_netconsole_msg(struct console *con, const char *msg0, unsigned int msg_len)
- {
- int len, left, i;
- struct net_device *dev;
- const char *msg = msg0;
- reply_t reply;
--
-+
- dev = netconsole_dev;
- if (!dev || netdump_mode)
- return;
--
-- if (dev->poll_controller && netif_running(dev)) {
-+ if (sysrq_mode){
-+ unsigned long total_len = send_cache_pos + msg_len;
-+ unsigned long left_len = msg_len;
-+ while (total_len >= MAX_PRINT_CHUNK){
-+ unsigned long send_len = MAX_PRINT_CHUNK - send_cache_pos;
-+ memcpy(send_cache + send_cache_pos, msg, send_len);
-+ SEND_MSG_BUFFER(send_cache, MAX_PRINT_CHUNK);
-+ send_cache_pos = 0;
-+ total_len -= MAX_PRINT_CHUNK;
-+ left_len -= send_len;
-+ }
-+ if (left_len > 0){
-+ memcpy(send_cache + send_cache_pos, msg + (msg_len -left_len), left_len);
-+ send_cache_pos += left_len;
-+ }
-+ return;
-+ }else if (netif_running(dev)) {
- unsigned long flags;
-
- __save_flags(flags);
-@@ -567,8 +646,6 @@
- req_t *req;
- struct net_device *dev;
-
-- if (!netdump_mode)
-- return NET_RX_SUCCESS;
- #if DEBUG
- {
- static int packet_count;
-@@ -722,8 +799,16 @@
- Dprintk("... netdump from: %08x.\n", req->from);
- Dprintk("... netdump to: %08x.\n", req->to);
-
-- add_new_req(req);
-+ if (netdump_mode)
-+ add_new_req(req);
-+ else if (req->command == COMM_SYSRQ){
-+ add_new_req(req);
-+ wake_up(&sysrq_thread_queue);
-+ return NET_RX_DROP;
-+ }
- out:
-+ if (!netdump_mode)
-+ return NET_RX_SUCCESS;
- return NET_RX_DROP;
- }
-
-@@ -763,6 +848,7 @@
- kunmap_atomic(kaddr, KM_NETDUMP);
- }
-
-+
- /*
- * This function waits for the client to acknowledge the receipt
- * of the netdump startup reply, with the possibility of packets
-@@ -792,7 +878,7 @@
- // wait 1 sec.
- udelay(100);
- Dprintk("handshake: polling controller ...\n");
-- dev->poll_controller(dev);
-+ netdump_poll(dev);
- zap_completion_queue();
- req = get_new_req();
- if (req)
-@@ -904,7 +990,7 @@
- while (netdump_mode) {
- __cli();
- Dprintk("main netdump loop: polling controller ...\n");
-- dev->poll_controller(dev);
-+ netdump_poll(dev);
- zap_completion_queue();
- #if !CLI
- __sti();
-@@ -1009,6 +1095,32 @@
- printk("NETDUMP END!\n");
- __restore_flags(flags);
- }
-+static int netconsole_sysrq_schedule(void *arg)
-+{
-+ struct task_struct *tsk = current;
-+
-+ sprintf(tsk->comm, "sysrq_schedule");
-+ sigfillset(&tsk->blocked);
-+
-+ /* main loop */
-+ thread_stopped = 0;
-+ for (;;) {
-+ wait_event_interruptible(sysrq_thread_queue,
-+ !list_empty(&request_list) || stop_sysrq_thread);
-+ while (!list_empty(&request_list)) {
-+ req_t *req = get_new_req();
-+ if (req->command == COMM_SYSRQ)
-+ netconsole_do_sysrq(req);
-+ }
-+ if (stop_sysrq_thread)
-+ break;
-+ wake_up(&sysrq_thread_waiter_queue);
-+ }
-+ thread_stopped = 1;
-+ wake_up(&sysrq_thread_waiter_queue);
-+ return 0;
-+}
-+
-
- static char *dev;
- static int netdump_target_eth_byte0 = 255;
-@@ -1087,11 +1199,12 @@
-
- static struct console netconsole =
- { flags: CON_ENABLED, write: write_netconsole_msg };
--
- static int init_netconsole(void)
- {
- struct net_device *ndev = NULL;
- struct in_device *in_dev;
-+ struct irqaction *action;
-+ int rc = 0;
-
- printk(KERN_INFO "netlog: using network device <%s>\n", dev);
- // this will be valid once the device goes up.
-@@ -1101,10 +1214,6 @@
- printk(KERN_ERR "netlog: network device %s does not exist, aborting.\n", dev);
- return -1;
- }
-- if (!ndev->poll_controller) {
-- printk(KERN_ERR "netlog: %s's network driver does not implement netlogging yet, aborting.\n", dev);
-- return -1;
-- }
- in_dev = in_dev_get(ndev);
- if (!in_dev) {
- printk(KERN_ERR "netlog: network device %s is not an IP protocol device, aborting.\n", dev);
-@@ -1137,8 +1246,6 @@
- if (!netdump_target_ip && !netlog_target_ip && !syslog_target_ip) {
- printk(KERN_ERR "netlog: target_ip parameter not specified, aborting.\n");
- return -1;
-- }
-- if (netdump_target_ip) {
- #define IP(x) ((unsigned char *)&netdump_target_ip)[x]
- printk(KERN_INFO "netlog: using netdump target IP %u.%u.%u.%u\n",
- IP(3), IP(2), IP(1), IP(0));
-@@ -1214,12 +1321,27 @@
-
- mhz_cycles = (unsigned long long)mhz * 1000000ULL;
- jiffy_cycles = (unsigned long long)mhz * (1000000/HZ);
--
-- INIT_LIST_HEAD(&request_list);
--
-+
- ndev->rx_hook = netconsole_rx_hook;
- netdump_func = netconsole_netdump;
- netconsole_dev = ndev;
-+ /* find irq function of the ndev*/
-+ action=find_irq_action(ndev->irq, ndev);
-+ if (!action) {
-+ printk(KERN_ERR "couldn't find irq handler for <%s>", dev);
-+ return -1;
-+ }
-+ irqfunc = action->handler;
-+
-+ stop_sysrq_thread = 0;
-+ INIT_LIST_HEAD(&request_list);
-+ init_waitqueue_head(&sysrq_thread_queue);
-+ init_waitqueue_head(&sysrq_thread_waiter_queue);
-+ if ((rc = kernel_thread(netconsole_sysrq_schedule, NULL, 0)) < 0 ){
-+ printk(KERN_ERR "Can not start netconsole sysrq thread: rc %d\n", rc);
-+ return -1;
-+ }
-+
- #define STARTUP_MSG "[...network console startup...]\n"
- write_netconsole_msg(NULL, STARTUP_MSG, strlen(STARTUP_MSG));
-
-@@ -1230,7 +1352,11 @@
-
- static void cleanup_netconsole(void)
- {
-- printk(KERN_INFO "netlog: network logging shut down.\n");
-+ stop_sysrq_thread = 1;
-+
-+ wake_up(&sysrq_thread_queue);
-+ wait_event(sysrq_thread_waiter_queue, thread_stopped);
-+ printk(KERN_INFO"netlog: network logging shut down.\n");
- unregister_console(&netconsole);
-
- #define SHUTDOWN_MSG "[...network console shutdown...]\n"
-Index: linux-2.4.20-rh/drivers/net/netconsole.h
-===================================================================
---- linux-2.4.20-rh.orig/drivers/net/netconsole.h 2003-07-22 16:02:23.000000000 +0800
-+++ linux-2.4.20-rh/drivers/net/netconsole.h 2003-10-30 01:48:45.000000000 +0800
-@@ -29,7 +29,7 @@
- *
- ****************************************************************/
-
--#define NETCONSOLE_VERSION 0x04
-+#define NETCONSOLE_VERSION 0x03
-
- enum netdump_commands {
- COMM_NONE = 0,
-@@ -42,6 +42,8 @@
- COMM_START_NETDUMP_ACK = 7,
- COMM_GET_REGS = 8,
- COMM_SHOW_STATE = 9,
-+ COMM_START_WRITE_NETDUMP_ACK = 10,
-+ COMM_SYSRQ = 11,
- };
-
- #define NETDUMP_REQ_SIZE (8+4*4)
-@@ -69,6 +71,7 @@
- REPLY_REGS = 10,
- REPLY_MAGIC = 11,
- REPLY_SHOW_STATE = 12,
-+ REPLY_SYSRQ = 13,
- };
-
- typedef struct netdump_reply_s {
-@@ -78,4 +81,22 @@
- } reply_t;
-
- #define HEADER_LEN (1 + sizeof(reply_t))
--
-+/* for netconsole */
-+static inline void get_current_regs(struct pt_regs *regs)
-+{
-+ __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
-+ __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
-+ __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
-+ __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
-+ __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
-+ __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
-+ __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
-+ __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
-+ __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
-+ __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
-+ __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
-+ __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
-+ __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
-+ regs->eip = (unsigned long)current_text_addr();
-+}
-+
-Index: linux-2.4.20-rh/arch/i386/kernel/irq.c
-===================================================================
---- linux-2.4.20-rh.orig/arch/i386/kernel/irq.c 2003-10-30 08:29:38.000000000 +0800
-+++ linux-2.4.20-rh/arch/i386/kernel/irq.c 2003-10-30 08:30:13.000000000 +0800
-@@ -1043,7 +1043,20 @@
- register_irq_proc(irq);
- return 0;
- }
-+struct irqaction *find_irq_action(unsigned int irq, void *dev_id)
-+{
-+ struct irqaction *a, *r=0;
-
-+ spin_lock_irq(&irq_desc[irq].lock);
-+ for(a=irq_desc[irq].action; a; a=a->next) {
-+ if(a->dev_id == dev_id) {
-+ r=a;
-+ break;
-+ }
-+ }
-+ spin_unlock_irq(&irq_desc[irq].lock);
-+ return r;
-+}
-
- static struct proc_dir_entry * root_irq_dir;
- static struct proc_dir_entry * irq_dir [NR_IRQS];
-Index: linux-2.4.20-rh/net/core/dev.c
-===================================================================
---- linux-2.4.20-rh.orig/net/core/dev.c 2003-10-29 01:40:26.000000000 +0800
-+++ linux-2.4.20-rh/net/core/dev.c 2003-10-30 01:48:45.000000000 +0800
-@@ -1475,6 +1475,16 @@
-
- skb_bond(skb);
-
-+ if (unlikely(skb->dev->rx_hook != NULL)) {
-+ int ret;
-+
-+ ret = skb->dev->rx_hook(skb);
-+ if (ret == NET_RX_DROP){
-+ kfree_skb(skb);
-+ return ret;
-+ }
-+ }
-+
- netdev_rx_stat[smp_processor_id()].total++;
-
- #ifdef CONFIG_NET_FASTROUTE
-Index: linux-2.4.20-rh/include/asm-i386/irq.h
-===================================================================
---- linux-2.4.20-rh.orig/include/asm-i386/irq.h 2003-10-28 16:18:18.000000000 +0800
-+++ linux-2.4.20-rh/include/asm-i386/irq.h 2003-10-30 10:24:49.000000000 +0800
-@@ -38,7 +38,7 @@
- extern void disable_irq_nosync(unsigned int);
- extern void enable_irq(unsigned int);
- extern void release_x86_irqs(struct task_struct *);
--
-+extern struct irqaction *find_irq_action(unsigned int irq, void *dev_id);
- #ifdef CONFIG_X86_LOCAL_APIC
- #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
- #endif
-Index: linux-2.4.20-rh/arch/i386/kernel/i386_ksyms.c
-===================================================================
---- linux-2.4.20-rh.orig/arch/i386/kernel/i386_ksyms.c 2003-10-28 19:44:57.000000000 +0800
-+++ linux-2.4.20-rh/arch/i386/kernel/i386_ksyms.c 2003-10-30 11:14:55.000000000 +0800
-@@ -68,6 +68,7 @@
- EXPORT_SYMBOL(iounmap);
- EXPORT_SYMBOL(enable_irq);
- EXPORT_SYMBOL(disable_irq);
-+EXPORT_SYMBOL(find_irq_action);
- EXPORT_SYMBOL(disable_irq_nosync);
- EXPORT_SYMBOL(probe_irq_mask);
- EXPORT_SYMBOL(kernel_thread);
-@@ -199,7 +200,6 @@
- EXPORT_SYMBOL(edd);
- EXPORT_SYMBOL(eddnr);
- #endif
--
- EXPORT_SYMBOL_GPL(show_mem);
- EXPORT_SYMBOL_GPL(show_state);
- EXPORT_SYMBOL_GPL(show_regs);
-Index: linux-2.4.20-rh/kernel/panic.c
-===================================================================
---- linux-2.4.20-rh.orig/kernel/panic.c 2003-10-31 07:25:19.000000000 +0800
-+++ linux-2.4.20-rh/kernel/panic.c 2003-10-31 07:25:59.000000000 +0800
-@@ -219,8 +219,6 @@
- }
- #endif
-
-- if (netdump_func)
-- BUG();
- if (in_interrupt())
- printk(KERN_EMERG "In interrupt handler - not syncing\n");
- else if (!current->pid)
+++ /dev/null
- fs/Makefile | 3
- fs/file_table.c | 11 ++
- fs/inode.c | 23 ++++-
- fs/namei.c | 12 ++
- fs/nfsd/export.c | 5 +
- fs/nfsd/nfsfh.c | 65 +++++++++++++-
- fs/nfsd/vfs.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++-----
- include/linux/fs.h | 10 ++
- kernel/ksyms.c | 2
- 9 files changed, 337 insertions(+), 34 deletions(-)
-
---- linux-2.4.20-rh-20.9/fs/file_table.c~nfs_export_kernel-2.4.20-rh 2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.20-rh-20.9-alexey/fs/file_table.c 2003-10-08 10:48:38.000000000 +0400
-@@ -82,7 +82,8 @@ struct file * get_empty_filp(void)
- * and call the open function (if any). The caller must verify that
- * inode->i_fop is not NULL.
- */
--int init_private_file(struct file *filp, struct dentry *dentry, int mode)
-+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode,
-+ struct lookup_intent *it)
- {
- memset(filp, 0, sizeof(*filp));
- filp->f_mode = mode;
-@@ -90,12 +91,20 @@ int init_private_file(struct file *filp,
- filp->f_dentry = dentry;
- filp->f_uid = current->fsuid;
- filp->f_gid = current->fsgid;
-+ if (it)
-+ filp->f_it = it;
- filp->f_op = dentry->d_inode->i_fop;
- if (filp->f_op->open)
- return filp->f_op->open(dentry->d_inode, filp);
- else
- return 0;
- }
-+EXPORT_SYMBOL(init_private_file_it);
-+
-+int init_private_file(struct file *filp, struct dentry *dentry, int mode)
-+{
-+ return init_private_file_it(filp, dentry, mode, NULL);
-+}
-
- void fput(struct file * file)
- {
---- linux-2.4.20-rh-20.9/fs/inode.c~nfs_export_kernel-2.4.20-rh 2003-09-14 17:35:22.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/inode.c 2003-10-08 10:48:38.000000000 +0400
-@@ -1063,9 +1063,10 @@ struct inode *igrab(struct inode *inode)
- }
-
-
--struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
-+static inline struct inode *ifind(struct super_block *sb, unsigned long ino,
-+ struct list_head *head,
-+ find_inode_t find_actor, void *opaque)
- {
-- struct list_head * head = inode_hashtable + hash(sb,ino);
- struct inode * inode;
-
- spin_lock(&inode_lock);
-@@ -1078,6 +1079,24 @@ struct inode *iget4(struct super_block *
- }
- spin_unlock(&inode_lock);
-
-+ return NULL;
-+}
-+
-+struct inode *ilookup4(struct super_block *sb, unsigned long ino,
-+ find_inode_t find_actor, void *opaque)
-+{
-+ struct list_head * head = inode_hashtable + hash(sb,ino);
-+ return ifind(sb, ino, head, find_actor, opaque);
-+}
-+
-+struct inode *iget4(struct super_block *sb, unsigned long ino,
-+ find_inode_t find_actor, void *opaque)
-+{
-+ struct list_head * head = inode_hashtable + hash(sb,ino);
-+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque);
-+ if (inode)
-+ return inode;
-+
- /*
- * get_new_inode() will do the right thing, re-trying the search
- * in case it had to block at any point.
---- linux-2.4.20-rh-20.9/fs/Makefile~nfs_export_kernel-2.4.20-rh 2003-09-14 17:35:20.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/Makefile 2003-10-08 10:49:33.000000000 +0400
-@@ -9,7 +9,8 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o inode.o
-+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o inode.o \
-+ namei.o file_table.o
- mod-subdirs := nls
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
---- linux-2.4.20-rh-20.9/fs/namei.c~nfs_export_kernel-2.4.20-rh 2003-09-14 17:35:22.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/namei.c 2003-10-08 10:48:38.000000000 +0400
-@@ -22,6 +22,7 @@
- #include <linux/dnotify.h>
- #include <linux/smp_lock.h>
- #include <linux/personality.h>
-+#include <linux/module.h>
-
- #include <asm/namei.h>
- #include <asm/uaccess.h>
-@@ -100,6 +101,7 @@ void intent_release(struct lookup_intent
- it->it_op_release(it);
-
- }
-+EXPORT_SYMBOL(intent_release);
-
- static void *lock_dir(struct inode *dir, struct qstr *name)
- {
-@@ -959,7 +961,8 @@ struct dentry * lookup_hash(struct qstr
-
-
- /* 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;
-@@ -979,11 +982,16 @@ struct dentry * lookup_one_len(const cha
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash_it(&this, base, NULL);
-+ return lookup_hash_it(&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()
- *
---- linux-2.4.20-rh-20.9/fs/nfsd/export.c~nfs_export_kernel-2.4.20-rh 2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/nfsd/export.c 2003-10-08 10:48:38.000000000 +0400
-@@ -222,6 +222,11 @@ exp_export(struct nfsctl_export *nxp)
- inode = nd.dentry->d_inode;
- dev = inode->i_dev;
- ino = inode->i_ino;
-+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) &&
-+ !(nxp->ex_flags & NFSEXP_FSID)) {
-+ nxp->ex_dev = inode->i_sb->s_dev;
-+ nxp->ex_flags |= NFSEXP_FSID;
-+ }
- err = -EINVAL;
-
- exp = exp_get(clp, dev, ino);
---- linux-2.4.20-rh-20.9/fs/nfsd/nfsfh.c~nfs_export_kernel-2.4.20-rh 2003-09-13 19:34:15.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/nfsd/nfsfh.c 2003-10-08 10:48:38.000000000 +0400
-@@ -36,6 +36,13 @@ struct nfsd_getdents_callback {
- int sequence; /* sequence counter */
- };
-
-+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry)
-+{
-+ if (inode->i_op->lookup_it)
-+ return inode->i_op->lookup_it(inode, dentry, NULL, 0);
-+ return inode->i_op->lookup(inode, dentry);
-+}
-+
- /*
- * A rather strange filldir function to capture
- * the name matching the specified inode number.
-@@ -75,6 +84,8 @@ static int nfsd_get_name(struct dentry *
- int error;
- struct file file;
- struct nfsd_getdents_callback buffer;
-+ struct lookup_intent it;
-+ struct file *filp = NULL;
-
- error = -ENOTDIR;
- if (!dir || !S_ISDIR(dir->i_mode))
-@@ -85,9 +96,37 @@ static int nfsd_get_name(struct dentry *
- /*
- * Open the directory ...
- */
-- error = init_private_file(&file, dentry, FMODE_READ);
-- if (error)
-+ if (dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) &&
-+ (dentry->d_parent == dentry) ) {
-+ it.it_op_release = NULL;
-+ /*
-+ * XXX Temporary Hack: Simulate init_private_file without
-+ * f_op->open for disconnected dentry as we don't have
-+ * actual dentry->d_name to revalidate in revalidate_it()
-+ */
-+ filp = &file;
-+ memset(filp, 0, sizeof(*filp));
-+ filp->f_mode = FMODE_READ;
-+ atomic_set(&filp->f_count, 1);
-+ filp->f_dentry = dentry;
-+ filp->f_uid = current->fsuid;
-+ filp->f_gid = current->fsgid;
-+ filp->f_op = dentry->d_inode->i_fop;
-+ error = 0;
-+ } else {
-+ intent_init(&it, IT_OPEN, 0);
-+ error = revalidate_it(dentry, &it);
-+ if (error)
-+ goto out;
-+ error = init_private_file_it(&file, dentry, FMODE_READ, &it);
-+ }
-+ } else {
-+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL);
-+ }
-+ if (error)
- goto out;
-+
- error = -EINVAL;
- if (!file.f_op->readdir)
- goto out_close;
-@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry *
- }
-
- out_close:
-- if (file.f_op->release)
-+ if (file.f_op->release && !filp)
- file.f_op->release(dir, &file);
- out:
-+ if (dentry->d_op && dentry->d_op->d_revalidate_it &&
-+ it.it_op_release && !filp)
-+ intent_release(&it);
- return error;
- }
-
-@@ -274,7 +317,7 @@ struct dentry *nfsd_findparent(struct de
- * it is well connected. But nobody returns different dentrys do they?
- */
- down(&child->d_inode->i_sem);
-- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
-+ pdentry = lookup_it(child->d_inode, tdentry);
- up(&child->d_inode->i_sem);
- d_drop(tdentry); /* we never want ".." hashed */
- if (!pdentry && tdentry->d_inode == NULL) {
-@@ -306,6 +349,8 @@ struct dentry *nfsd_findparent(struct de
- igrab(tdentry->d_inode);
- pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
- }
-+ if (child->d_op && child->d_op->d_revalidate_it)
-+ pdentry->d_op = child->d_op;
- }
- if (pdentry == NULL)
- pdentry = ERR_PTR(-ENOMEM);
-@@ -463,6 +508,8 @@ find_fh_dentry(struct super_block *sb, _
- struct dentry *pdentry;
- struct inode *parent;
-
-+ if (result->d_op && result->d_op->d_revalidate_it)
-+ dentry->d_op = result->d_op;
- pdentry = nfsd_findparent(dentry);
- err = PTR_ERR(pdentry);
- if (IS_ERR(pdentry))
-@@ -669,6 +716,10 @@ fh_verify(struct svc_rqst *rqstp, struct
-
- inode = dentry->d_inode;
-
-+ /* cache coherency for non-device filesystems */
-+ if (inode->i_op && inode->i_op->revalidate_it)
-+ inode->i_op->revalidate_it(dentry, NULL);
-+
- /* Type check. The correct error return for type mismatches
- * does not seem to be generally agreed upon. SunOS seems to
- * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
-@@ -912,8 +964,9 @@ out_negative:
- dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
- out_uptodate:
-- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
-- dentry->d_parent->d_name.name, dentry->d_name.name);
-+ if (!dentry->d_parent->d_inode->i_op->mkdir_raw)
-+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
-+ dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
- }
-
---- linux-2.4.20-rh-20.9/fs/nfsd/vfs.c~nfs_export_kernel-2.4.20-rh 2003-09-13 19:34:15.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/nfsd/vfs.c 2003-10-08 10:48:38.000000000 +0400
-@@ -77,6 +77,126 @@ struct raparms {
- static struct raparms * raparml;
- static struct raparms * raparm_cache;
-
-+static int link_raw(struct dentry *dold, struct dentry *ddir,
-+ struct dentry *dnew)
-+{
-+ int err;
-+
-+ struct nameidata old_nd = { .dentry = dold };
-+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->link_raw(&old_nd, &nd);
-+ d_instantiate(dnew, dold->d_inode);
-+ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it)
-+ dold->d_inode->i_op->revalidate_it(dnew, NULL);
-+
-+ return err;
-+}
-+
-+static int unlink_raw(struct dentry *dentry, char *fname, int flen,
-+ struct dentry *rdentry)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->unlink_raw(&nd);
-+ if (!err)
-+ d_delete(rdentry);
-+
-+ return err;
-+}
-+
-+static int rmdir_raw(struct dentry *dentry, char *fname, int flen,
-+ struct dentry *rdentry)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->rmdir_raw(&nd);
-+ if (!err) {
-+ rdentry->d_inode->i_flags |= S_DEAD;
-+ d_delete(rdentry);
-+ }
-+
-+ return err;
-+}
-+
-+static int symlink_raw(struct dentry *dentry, char *fname, int flen,
-+ char *path)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->symlink_raw(&nd, path);
-+
-+ return err;
-+}
-+
-+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->mkdir_raw(&nd, mode);
-+
-+ return err;
-+}
-+
-+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode,
-+ dev_t dev)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->mknod_raw(&nd, mode, dev);
-+
-+ return err;
-+}
-+
-+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry,
-+ struct dentry *odentry, struct dentry *ndentry)
-+{
-+ int err;
-+
-+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name};
-+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name};
-+ struct inode_operations *op = old_nd.dentry->d_inode->i_op;
-+ err = op->rename_raw(&old_nd, &new_nd);
-+ d_move(odentry, ndentry);
-+
-+ return err;
-+}
-+
-+static int setattr_raw(struct inode *inode, struct iattr *iap)
-+{
-+ int err;
-+
-+ iap->ia_valid |= ATTR_RAW;
-+ err = inode->i_op->setattr_raw(inode, iap);
-+
-+ return err;
-+}
-+
-+int revalidate_it(struct dentry *dentry, struct lookup_intent *it)
-+{
-+ int err = 0;
-+
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it) &&
-+ !d_invalidate(dentry)) {
-+ err = -EINVAL;
-+ return err;
-+ }
-+ }
-+
-+ return err;
-+}
-+
- /*
- * Look up one component of a pathname.
- * N.B. After this call _both_ fhp and resfh need an fh_put
-@@ -302,7 +424,10 @@ nfsd_setattr(struct svc_rqst *rqstp, str
- }
- err = nfserr_notsync;
- if (!check_guard || guardtime == inode->i_ctime) {
-- err = notify_change(dentry, iap);
-+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw)
-+ err = setattr_raw(dentry->d_inode, iap);
-+ else
-+ err = notify_change(dentry, iap);
- err = nfserrno(err);
- }
- if (size_change) {
-@@ -429,6 +554,7 @@ nfsd_open(struct svc_rqst *rqstp, struct
- {
- struct dentry *dentry;
- struct inode *inode;
-+ struct lookup_intent it;
- int err;
-
- /* If we get here, then the client has already done an "open", and (hopefully)
-@@ -475,6 +601,18 @@ nfsd_open(struct svc_rqst *rqstp, struct
- filp->f_mode = FMODE_READ;
- }
-
-+#ifndef O_OWNER_OVERRIDE
-+#define O_OWNER_OVERRIDE 0200000000
-+#endif
-+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode |
-+ O_OWNER_OVERRIDE);
-+
-+ err = revalidate_it(dentry, &it);
-+ if (err)
-+ goto out_nfserr;
-+
-+ filp->f_it = ⁢
-+
- err = 0;
- if (filp->f_op && filp->f_op->open) {
- err = filp->f_op->open(inode, filp);
-@@ -489,6 +623,9 @@ nfsd_open(struct svc_rqst *rqstp, struct
- }
- }
- out_nfserr:
-+ if (it.it_op_release)
-+ intent_release(&it);
-+
- if (err)
- err = nfserrno(err);
- out:
-@@ -820,7 +958,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
- {
- struct dentry *dentry, *dchild;
- struct inode *dirp;
-- int err;
-+ int err, error = -EOPNOTSUPP;
-
- err = nfserr_perm;
- if (!flen)
-@@ -836,20 +974,47 @@ nfsd_create(struct svc_rqst *rqstp, stru
- dentry = fhp->fh_dentry;
- dirp = dentry->d_inode;
-
-+ switch (type) {
-+ case S_IFDIR:
-+ if (dirp->i_op->mkdir_raw)
-+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode);
-+ break;
-+ case S_IFCHR:
-+ case S_IFBLK:
-+ case S_IFIFO:
-+ case S_IFSOCK:
-+ case S_IFREG:
-+ if (dirp->i_op->mknod_raw) {
-+ if (type == S_IFREG)
-+ rdev = 0;
-+ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev);
-+ }
-+ break;
-+ default:
-+ printk("nfsd: bad file type %o in nfsd_create\n", type);
-+ }
-+ if (error && error != -EOPNOTSUPP) {
-+ err = error;
-+ goto out_nfserr;
-+ }
-+
- err = nfserr_notdir;
-- if(!dirp->i_op || !dirp->i_op->lookup)
-+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
- goto out;
- /*
- * Check whether the response file handle has been verified yet.
- * If it has, the parent directory should already be locked.
- */
-- if (!resfhp->fh_dentry) {
-- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
-- fh_lock(fhp);
-+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) {
-+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create
-+ * and nfsd_proc_create in case of lustre */
-+ if (!resfhp->fh_dentry)
-+ fh_lock(fhp);
- dchild = lookup_one_len(fname, dentry, flen);
- err = PTR_ERR(dchild);
- if (IS_ERR(dchild))
- goto out_nfserr;
-+ resfhp->fh_dentry = NULL;
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
- if (err)
- goto out;
-@@ -870,10 +1032,12 @@ nfsd_create(struct svc_rqst *rqstp, stru
- * Make sure the child dentry is still negative ...
- */
- err = nfserr_exist;
-- if (dchild->d_inode) {
-- dprintk("nfsd_create: dentry %s/%s not negative!\n",
-- dentry->d_name.name, dchild->d_name.name);
-- goto out;
-+ if (error == -EOPNOTSUPP) {
-+ if (dchild->d_inode) {
-+ dprintk("nfsd_create: dentry %s/%s not negative!\n",
-+ dentry->d_name.name, dchild->d_name.name);
-+ goto out;
-+ }
- }
-
- if (!(iap->ia_valid & ATTR_MODE))
-@@ -886,16 +1050,19 @@ nfsd_create(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- switch (type) {
- case S_IFREG:
-- err = vfs_create(dirp, dchild, iap->ia_mode);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_create(dirp, dchild, iap->ia_mode);
- break;
- case S_IFDIR:
-- err = vfs_mkdir(dirp, dchild, iap->ia_mode);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_mkdir(dirp, dchild, iap->ia_mode);
- break;
- case S_IFCHR:
- case S_IFBLK:
- case S_IFIFO:
- case S_IFSOCK:
-- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
- break;
- default:
- printk("nfsd: bad file type %o in nfsd_create\n", type);
-@@ -964,7 +1131,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
- /* Get all the sanity checks out of the way before
- * we lock the parent. */
- err = nfserr_notdir;
-- if(!dirp->i_op || !dirp->i_op->lookup)
-+ if (dirp->i_op->mknod_raw) {
-+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0);
-+ if (err && err != -EOPNOTSUPP)
-+ goto out_nfserr;
-+ }
-+
-+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
- goto out;
- fh_lock(fhp);
-
-@@ -1015,6 +1188,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
- case NFS3_CREATE_GUARDED:
- err = nfserr_exist;
- }
-+ if (dirp->i_op->mknod_raw)
-+ err = 0;
- goto out;
- }
-
-@@ -1121,7 +1296,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
- struct iattr *iap)
- {
- struct dentry *dentry, *dnew;
-- int err, cerr;
-+ int err, cerr, error = -EOPNOTSUPP;
-
- err = nfserr_noent;
- if (!flen || !plen)
-@@ -1135,12 +1310,18 @@ nfsd_symlink(struct svc_rqst *rqstp, str
- goto out;
- fh_lock(fhp);
- dentry = fhp->fh_dentry;
-+
-+ if (dentry->d_inode->i_op->symlink_raw)
-+ error = symlink_raw(dentry, fname, flen, path);
-+
- dnew = lookup_one_len(fname, dentry, flen);
- err = PTR_ERR(dnew);
- if (IS_ERR(dnew))
- goto out_nfserr;
-
-- err = vfs_symlink(dentry->d_inode, dnew, path);
-+ err = error;
-+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw)
-+ err = vfs_symlink(dentry->d_inode, dnew, path);
- if (!err) {
- if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
-@@ -1150,7 +1331,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str
- iap->ia_valid |= ATTR_CTIME;
- iap->ia_mode = (iap->ia_mode&S_IALLUGO)
- | S_IFLNK;
-- err = notify_change(dnew, iap);
-+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw)
-+ err = setattr_raw(dnew->d_inode, iap);
-+ else
-+ err = notify_change(dnew, iap);
- if (!err && EX_ISSYNC(fhp->fh_export))
- write_inode_now(dentry->d_inode, 1);
- }
-@@ -1208,7 +1392,10 @@ nfsd_link(struct svc_rqst *rqstp, struct
- dold = tfhp->fh_dentry;
- dest = dold->d_inode;
-
-- err = vfs_link(dold, dirp, dnew);
-+ if (dirp->i_op->link_raw)
-+ err = link_raw(dold, ddir, dnew);
-+ else
-+ err = vfs_link(dold, dirp, dnew);
- if (!err) {
- if (EX_ISSYNC(ffhp->fh_export)) {
- nfsd_sync_dir(ddir);
-@@ -1293,7 +1480,10 @@ nfsd_rename(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ if (fdir->i_op->rename_raw)
-+ err = rename_raw(fdentry, tdentry, odentry, ndentry);
-+ else
-+ err = vfs_rename(fdir, odentry, tdir, ndentry);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
-@@ -1314,7 +1504,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
- fill_post_wcc(tfhp);
- double_up(&tdir->i_sem, &fdir->i_sem);
- ffhp->fh_locked = tfhp->fh_locked = 0;
--
-+
- out:
- return err;
- }
-@@ -1360,9 +1550,15 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_unlink(dirp, rdentry);
-+ if (dirp->i_op->unlink_raw)
-+ err = unlink_raw(dentry, fname, flen, rdentry);
-+ else
-+ err = vfs_unlink(dirp, rdentry);
- } else { /* It's RMDIR */
-- err = vfs_rmdir(dirp, rdentry);
-+ if (dirp->i_op->rmdir_raw)
-+ err = rmdir_raw(dentry, fname, flen, rdentry);
-+ else
-+ err = vfs_rmdir(dirp, rdentry);
- }
-
- dput(rdentry);
---- linux-2.4.20-rh-20.9/include/linux/fs.h~nfs_export_kernel-2.4.20-rh 2003-09-14 17:35:22.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/include/linux/fs.h 2003-10-08 10:48:38.000000000 +0400
-@@ -94,6 +94,8 @@ extern int leases_enable, dir_notify_ena
- #define FS_SINGLE 8 /* Filesystem that can have only one superblock */
- #define FS_NOMOUNT 16 /* Never mount from userland */
- #define FS_LITTER 32 /* Keeps the tree in dcache */
-+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for
-+ * exporting non device filesystems. */
- #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
- * as nfs_rename() will be cleaned up
- */
-@@ -1124,6 +1127,9 @@ extern int open_namei_it(const char *fil
- struct nameidata *nd, struct lookup_intent *it);
- extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
- int flags, struct lookup_intent *it);
-+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it);
-+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode,
-+ struct lookup_intent *it);
- extern int filp_close(struct file *, fl_owner_t id);
- extern char * getname(const char *);
-
-@@ -1423,6 +1429,8 @@ extern void path_release(struct nameidat
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int,
-+ struct lookup_intent *);
- 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)
-@@ -1439,6 +1447,8 @@ extern ino_t iunique(struct super_block
-
- typedef int (*find_inode_t)(struct inode *, unsigned long, void *);
- extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *);
-+extern struct inode * ilookup4(struct super_block *, unsigned long,
-+ find_inode_t, void *);
- static inline struct inode *iget(struct super_block *sb, unsigned long ino)
- {
- return iget4(sb, ino, NULL, NULL);
---- linux-2.4.20-rh-20.9/kernel/ksyms.c~nfs_export_kernel-2.4.20-rh 2003-09-14 17:35:20.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/kernel/ksyms.c 2003-10-08 10:48:38.000000000 +0400
-@@ -164,6 +164,7 @@ EXPORT_SYMBOL(fget);
- EXPORT_SYMBOL(igrab);
- EXPORT_SYMBOL(iunique);
- EXPORT_SYMBOL(iget4);
-+EXPORT_SYMBOL(ilookup4);
- EXPORT_SYMBOL(iput);
- EXPORT_SYMBOL(inode_init_once);
- EXPORT_SYMBOL(force_delete);
-@@ -175,6 +176,7 @@ EXPORT_SYMBOL(path_walk);
- EXPORT_SYMBOL(path_release);
- EXPORT_SYMBOL(__user_walk);
- EXPORT_SYMBOL(lookup_one_len);
-+EXPORT_SYMBOL(lookup_one_len_it);
- EXPORT_SYMBOL(lookup_hash);
- EXPORT_SYMBOL(sys_close);
- EXPORT_SYMBOL(sys_read);
-
-_
+++ /dev/null
-diff -uprN linux/fs/Makefile linux-2.4.20/fs/Makefile
---- linux/fs/Makefile Sun Oct 5 21:52:51 2003
-+++ linux-2.4.20/fs/Makefile Sun Oct 5 21:47:45 2003
-@@ -7,7 +7,8 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o inode.o
-+export-objs := filesystems.o open.o dcache.o buffer.o inode.o namei.o \
-+ file_table.o
- mod-subdirs := nls
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
-diff -uprN linux/fs/file_table.c linux-2.4.20/fs/file_table.c
---- linux/fs/file_table.c Fri Nov 29 05:23:15 2002
-+++ linux-2.4.20/fs/file_table.c Sun Oct 5 21:47:45 2003
-@@ -82,7 +82,8 @@ struct file * get_empty_filp(void)
- * and call the open function (if any). The caller must verify that
- * inode->i_fop is not NULL.
- */
--int init_private_file(struct file *filp, struct dentry *dentry, int mode)
-+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode,
-+ struct lookup_intent *it)
- {
- memset(filp, 0, sizeof(*filp));
- filp->f_mode = mode;
-@@ -90,12 +91,20 @@ int init_private_file(struct file *filp,
- filp->f_dentry = dentry;
- filp->f_uid = current->fsuid;
- filp->f_gid = current->fsgid;
-+ if (it)
-+ filp->f_it = it;
- filp->f_op = dentry->d_inode->i_fop;
- if (filp->f_op->open)
- return filp->f_op->open(dentry->d_inode, filp);
- else
- return 0;
- }
-+EXPORT_SYMBOL(init_private_file_it);
-+
-+int init_private_file(struct file *filp, struct dentry *dentry, int mode)
-+{
-+ return init_private_file_it(filp, dentry, mode, NULL);
-+}
-
- void fput(struct file * file)
- {
-diff -uprN linux/fs/inode.c linux-2.4.20/fs/inode.c
---- linux/fs/inode.c Sun Oct 5 21:52:49 2003
-+++ linux-2.4.20/fs/inode.c Sun Oct 5 21:47:45 2003
-@@ -970,9 +970,10 @@ struct inode *igrab(struct inode *inode)
- }
-
-
--struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
-+static inline struct inode *ifind(struct super_block *sb, unsigned long ino,
-+ struct list_head *head,
-+ find_inode_t find_actor, void *opaque)
- {
-- struct list_head * head = inode_hashtable + hash(sb,ino);
- struct inode * inode;
-
- spin_lock(&inode_lock);
-@@ -985,6 +986,24 @@ struct inode *iget4(struct super_block *
- }
- spin_unlock(&inode_lock);
-
-+ return NULL;
-+}
-+
-+struct inode *ilookup4(struct super_block *sb, unsigned long ino,
-+ find_inode_t find_actor, void *opaque)
-+{
-+ struct list_head * head = inode_hashtable + hash(sb,ino);
-+ return ifind(sb, ino, head, find_actor, opaque);
-+}
-+
-+struct inode *iget4(struct super_block *sb, unsigned long ino,
-+ find_inode_t find_actor, void *opaque)
-+{
-+ struct list_head * head = inode_hashtable + hash(sb,ino);
-+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque);
-+ if (inode)
-+ return inode;
-+
- /*
- * get_new_inode() will do the right thing, re-trying the search
- * in case it had to block at any point.
-diff -uprN linux/fs/namei.c linux-2.4.20/fs/namei.c
---- linux/fs/namei.c Sun Oct 5 21:52:48 2003
-+++ linux-2.4.20/fs/namei.c Sun Oct 5 21:47:45 2003
-@@ -22,6 +22,7 @@
- #include <linux/dnotify.h>
- #include <linux/smp_lock.h>
- #include <linux/personality.h>
-+#include <linux/module.h>
-
- #include <asm/namei.h>
- #include <asm/uaccess.h>
-@@ -100,6 +101,7 @@ void intent_release(struct lookup_intent
- it->it_op_release(it);
-
- }
-+EXPORT_SYMBOL(intent_release);
-
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
-@@ -900,7 +902,8 @@ struct dentry * lookup_hash(struct qstr
-
-
- /* 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;
-@@ -920,11 +923,16 @@ struct dentry * lookup_one_len(const cha
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash_it(&this, base, NULL);
-+ return lookup_hash_it(&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()
- *
-diff -uprN linux/fs/nfsd/export.c linux-2.4.20/fs/nfsd/export.c
---- linux/fs/nfsd/export.c Fri Nov 29 05:23:15 2002
-+++ linux-2.4.20/fs/nfsd/export.c Sun Oct 5 22:25:20 2003
-@@ -222,6 +222,11 @@ exp_export(struct nfsctl_export *nxp)
- inode = nd.dentry->d_inode;
- dev = inode->i_dev;
- ino = inode->i_ino;
-+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) &&
-+ !(nxp->ex_flags & NFSEXP_FSID)) {
-+ nxp->ex_dev = inode->i_sb->s_dev;
-+ nxp->ex_flags |= NFSEXP_FSID;
-+ }
- err = -EINVAL;
-
- exp = exp_get(clp, dev, ino);
-diff -uprN linux/fs/nfsd/nfsfh.c linux-2.4.20/fs/nfsd/nfsfh.c
---- linux/fs/nfsd/nfsfh.c Fri Nov 29 05:23:15 2002
-+++ linux-2.4.20/fs/nfsd/nfsfh.c Sun Oct 5 21:47:45 2003
-@@ -36,6 +36,13 @@ struct nfsd_getdents_callback {
- int sequence; /* sequence counter */
- };
-
-+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry)
-+{
-+ if (inode->i_op->lookup_it)
-+ return inode->i_op->lookup_it(inode, dentry, NULL, 0);
-+ return inode->i_op->lookup(inode, dentry);
-+}
-+
- /*
- * A rather strange filldir function to capture
- * the name matching the specified inode number.
-@@ -75,6 +84,8 @@ static int nfsd_get_name(struct dentry *
- int error;
- struct file file;
- struct nfsd_getdents_callback buffer;
-+ struct lookup_intent it;
-+ struct file *filp = NULL;
-
- error = -ENOTDIR;
- if (!dir || !S_ISDIR(dir->i_mode))
-@@ -85,9 +96,37 @@ static int nfsd_get_name(struct dentry *
- /*
- * Open the directory ...
- */
-- error = init_private_file(&file, dentry, FMODE_READ);
-- if (error)
-+ if (dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) &&
-+ (dentry->d_parent == dentry) ) {
-+ it.it_op_release = NULL;
-+ /*
-+ * XXX Temporary Hack: Simulate init_private_file without
-+ * f_op->open for disconnected dentry as we don't have
-+ * actual dentry->d_name to revalidate in revalidate_it()
-+ */
-+ filp = &file;
-+ memset(filp, 0, sizeof(*filp));
-+ filp->f_mode = FMODE_READ;
-+ atomic_set(&filp->f_count, 1);
-+ filp->f_dentry = dentry;
-+ filp->f_uid = current->fsuid;
-+ filp->f_gid = current->fsgid;
-+ filp->f_op = dentry->d_inode->i_fop;
-+ error = 0;
-+ } else {
-+ intent_init(&it, IT_OPEN, 0);
-+ error = revalidate_it(dentry, &it);
-+ if (error)
-+ goto out;
-+ error = init_private_file_it(&file, dentry, FMODE_READ, &it);
-+ }
-+ } else {
-+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL);
-+ }
-+ if (error)
- goto out;
-+
- error = -EINVAL;
- if (!file.f_op->readdir)
- goto out_close;
-@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry *
- }
-
- out_close:
-- if (file.f_op->release)
-+ if (file.f_op->release && !filp)
- file.f_op->release(dir, &file);
- out:
-+ if (dentry->d_op && dentry->d_op->d_revalidate_it &&
-+ it.it_op_release && !filp)
-+ intent_release(&it);
- return error;
- }
-
-@@ -274,7 +317,7 @@ struct dentry *nfsd_findparent(struct de
- * it is well connected. But nobody returns different dentrys do they?
- */
- down(&child->d_inode->i_sem);
-- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
-+ pdentry = lookup_it(child->d_inode, tdentry);
- up(&child->d_inode->i_sem);
- d_drop(tdentry); /* we never want ".." hashed */
- if (!pdentry && tdentry->d_inode == NULL) {
-@@ -306,6 +349,8 @@ struct dentry *nfsd_findparent(struct de
- igrab(tdentry->d_inode);
- pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
- }
-+ if (child->d_op && child->d_op->d_revalidate_it)
-+ pdentry->d_op = child->d_op;
- }
- if (pdentry == NULL)
- pdentry = ERR_PTR(-ENOMEM);
-@@ -463,6 +508,8 @@ find_fh_dentry(struct super_block *sb, _
- struct dentry *pdentry;
- struct inode *parent;
-
-+ if (result->d_op && result->d_op->d_revalidate_it)
-+ dentry->d_op = result->d_op;
- pdentry = nfsd_findparent(dentry);
- err = PTR_ERR(pdentry);
- if (IS_ERR(pdentry))
-@@ -662,6 +709,10 @@ fh_verify(struct svc_rqst *rqstp, struct
-
- inode = dentry->d_inode;
-
-+ /* cache coherency for non-device filesystems */
-+ if (inode->i_op && inode->i_op->revalidate_it)
-+ inode->i_op->revalidate_it(dentry, NULL);
-+
- /* Type check. The correct error return for type mismatches
- * does not seem to be generally agreed upon. SunOS seems to
- * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
-@@ -900,8 +952,9 @@ out_negative:
- dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
- out_uptodate:
-- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
-- dentry->d_parent->d_name.name, dentry->d_name.name);
-+ if (!dentry->d_parent->d_inode->i_op->mkdir_raw)
-+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
-+ dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
- }
-
-diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c
---- linux/fs/nfsd/vfs.c Fri Nov 29 05:23:15 2002
-+++ linux-2.4.20/fs/nfsd/vfs.c Sun Oct 5 21:47:45 2003
-@@ -77,6 +77,126 @@ struct raparms {
- static struct raparms * raparml;
- static struct raparms * raparm_cache;
-
-+static int link_raw(struct dentry *dold, struct dentry *ddir,
-+ struct dentry *dnew)
-+{
-+ int err;
-+
-+ struct nameidata old_nd = { .dentry = dold };
-+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->link_raw(&old_nd, &nd);
-+ d_instantiate(dnew, dold->d_inode);
-+ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it)
-+ dold->d_inode->i_op->revalidate_it(dnew, NULL);
-+
-+ return err;
-+}
-+
-+static int unlink_raw(struct dentry *dentry, char *fname, int flen,
-+ struct dentry *rdentry)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->unlink_raw(&nd);
-+ if (!err)
-+ d_delete(rdentry);
-+
-+ return err;
-+}
-+
-+static int rmdir_raw(struct dentry *dentry, char *fname, int flen,
-+ struct dentry *rdentry)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->rmdir_raw(&nd);
-+ if (!err) {
-+ rdentry->d_inode->i_flags |= S_DEAD;
-+ d_delete(rdentry);
-+ }
-+
-+ return err;
-+}
-+
-+static int symlink_raw(struct dentry *dentry, char *fname, int flen,
-+ char *path)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->symlink_raw(&nd, path);
-+
-+ return err;
-+}
-+
-+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->mkdir_raw(&nd, mode);
-+
-+ return err;
-+}
-+
-+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode,
-+ dev_t dev)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->mknod_raw(&nd, mode, dev);
-+
-+ return err;
-+}
-+
-+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry,
-+ struct dentry *odentry, struct dentry *ndentry)
-+{
-+ int err;
-+
-+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name};
-+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name};
-+ struct inode_operations *op = old_nd.dentry->d_inode->i_op;
-+ err = op->rename_raw(&old_nd, &new_nd);
-+ d_move(odentry, ndentry);
-+
-+ return err;
-+}
-+
-+static int setattr_raw(struct inode *inode, struct iattr *iap)
-+{
-+ int err;
-+
-+ iap->ia_valid |= ATTR_RAW;
-+ err = inode->i_op->setattr_raw(inode, iap);
-+
-+ return err;
-+}
-+
-+int revalidate_it(struct dentry *dentry, struct lookup_intent *it)
-+{
-+ int err = 0;
-+
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it) &&
-+ !d_invalidate(dentry)) {
-+ err = -EINVAL;
-+ return err;
-+ }
-+ }
-+
-+ return err;
-+}
-+
- /*
- * Look up one component of a pathname.
- * N.B. After this call _both_ fhp and resfh need an fh_put
-@@ -300,7 +422,10 @@ nfsd_setattr(struct svc_rqst *rqstp, str
- }
- err = nfserr_notsync;
- if (!check_guard || guardtime == inode->i_ctime) {
-- err = notify_change(dentry, iap);
-+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw)
-+ err = setattr_raw(dentry->d_inode, iap);
-+ else
-+ err = notify_change(dentry, iap);
- err = nfserrno(err);
- }
- if (size_change) {
-@@ -427,6 +552,7 @@ nfsd_open(struct svc_rqst *rqstp, struct
- {
- struct dentry *dentry;
- struct inode *inode;
-+ struct lookup_intent it;
- int err;
-
- /* If we get here, then the client has already done an "open", and (hopefully)
-@@ -473,6 +599,18 @@ nfsd_open(struct svc_rqst *rqstp, struct
- filp->f_mode = FMODE_READ;
- }
-
-+#ifndef O_OWNER_OVERRIDE
-+#define O_OWNER_OVERRIDE 0200000000
-+#endif
-+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode |
-+ O_OWNER_OVERRIDE);
-+
-+ err = revalidate_it(dentry, &it);
-+ if (err)
-+ goto out_nfserr;
-+
-+ filp->f_it = ⁢
-+
- err = 0;
- if (filp->f_op && filp->f_op->open) {
- err = filp->f_op->open(inode, filp);
-@@ -487,6 +621,9 @@ nfsd_open(struct svc_rqst *rqstp, struct
- }
- }
- out_nfserr:
-+ if (it.it_op_release)
-+ intent_release(&it);
-+
- if (err)
- err = nfserrno(err);
- out:
-@@ -818,7 +956,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
- {
- struct dentry *dentry, *dchild;
- struct inode *dirp;
-- int err;
-+ int err, error = -EOPNOTSUPP;
-
- err = nfserr_perm;
- if (!flen)
-@@ -834,20 +972,47 @@ nfsd_create(struct svc_rqst *rqstp, stru
- dentry = fhp->fh_dentry;
- dirp = dentry->d_inode;
-
-+ switch (type) {
-+ case S_IFDIR:
-+ if (dirp->i_op->mkdir_raw)
-+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode);
-+ break;
-+ case S_IFCHR:
-+ case S_IFBLK:
-+ case S_IFIFO:
-+ case S_IFSOCK:
-+ case S_IFREG:
-+ if (dirp->i_op->mknod_raw) {
-+ if (type == S_IFREG)
-+ rdev = 0;
-+ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev);
-+ }
-+ break;
-+ default:
-+ printk("nfsd: bad file type %o in nfsd_create\n", type);
-+ }
-+ if (error && error != -EOPNOTSUPP) {
-+ err = error;
-+ goto out_nfserr;
-+ }
-+
- err = nfserr_notdir;
-- if(!dirp->i_op || !dirp->i_op->lookup)
-+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
- goto out;
- /*
- * Check whether the response file handle has been verified yet.
- * If it has, the parent directory should already be locked.
- */
-- if (!resfhp->fh_dentry) {
-- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
-- fh_lock(fhp);
-+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) {
-+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create
-+ * and nfsd_proc_create in case of lustre */
-+ if (!resfhp->fh_dentry)
-+ fh_lock(fhp);
- dchild = lookup_one_len(fname, dentry, flen);
- err = PTR_ERR(dchild);
- if (IS_ERR(dchild))
- goto out_nfserr;
-+ resfhp->fh_dentry = NULL;
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
- if (err)
- goto out;
-@@ -868,10 +1030,12 @@ nfsd_create(struct svc_rqst *rqstp, stru
- * Make sure the child dentry is still negative ...
- */
- err = nfserr_exist;
-- if (dchild->d_inode) {
-- dprintk("nfsd_create: dentry %s/%s not negative!\n",
-- dentry->d_name.name, dchild->d_name.name);
-- goto out;
-+ if (error == -EOPNOTSUPP) {
-+ if (dchild->d_inode) {
-+ dprintk("nfsd_create: dentry %s/%s not negative!\n",
-+ dentry->d_name.name, dchild->d_name.name);
-+ goto out;
-+ }
- }
-
- if (!(iap->ia_valid & ATTR_MODE))
-@@ -884,16 +1048,19 @@ nfsd_create(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- switch (type) {
- case S_IFREG:
-- err = vfs_create(dirp, dchild, iap->ia_mode);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_create(dirp, dchild, iap->ia_mode);
- break;
- case S_IFDIR:
-- err = vfs_mkdir(dirp, dchild, iap->ia_mode);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_mkdir(dirp, dchild, iap->ia_mode);
- break;
- case S_IFCHR:
- case S_IFBLK:
- case S_IFIFO:
- case S_IFSOCK:
-- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
- break;
- default:
- printk("nfsd: bad file type %o in nfsd_create\n", type);
-@@ -962,7 +1129,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
- /* Get all the sanity checks out of the way before
- * we lock the parent. */
- err = nfserr_notdir;
-- if(!dirp->i_op || !dirp->i_op->lookup)
-+ if (dirp->i_op->mknod_raw) {
-+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0);
-+ if (err && err != -EOPNOTSUPP)
-+ goto out_nfserr;
-+ }
-+
-+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
- goto out;
- fh_lock(fhp);
-
-@@ -1013,6 +1186,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
- case NFS3_CREATE_GUARDED:
- err = nfserr_exist;
- }
-+ if (dirp->i_op->mknod_raw)
-+ err = 0;
- goto out;
- }
-
-@@ -1119,7 +1294,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
- struct iattr *iap)
- {
- struct dentry *dentry, *dnew;
-- int err, cerr;
-+ int err, cerr, error = -EOPNOTSUPP;
-
- err = nfserr_noent;
- if (!flen || !plen)
-@@ -1133,12 +1308,18 @@ nfsd_symlink(struct svc_rqst *rqstp, str
- goto out;
- fh_lock(fhp);
- dentry = fhp->fh_dentry;
-+
-+ if (dentry->d_inode->i_op->symlink_raw)
-+ error = symlink_raw(dentry, fname, flen, path);
-+
- dnew = lookup_one_len(fname, dentry, flen);
- err = PTR_ERR(dnew);
- if (IS_ERR(dnew))
- goto out_nfserr;
-
-- err = vfs_symlink(dentry->d_inode, dnew, path);
-+ err = error;
-+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw)
-+ err = vfs_symlink(dentry->d_inode, dnew, path);
- if (!err) {
- if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
-@@ -1148,7 +1329,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str
- iap->ia_valid |= ATTR_CTIME;
- iap->ia_mode = (iap->ia_mode&S_IALLUGO)
- | S_IFLNK;
-- err = notify_change(dnew, iap);
-+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw)
-+ err = setattr_raw(dnew->d_inode, iap);
-+ else
-+ err = notify_change(dnew, iap);
- if (!err && EX_ISSYNC(fhp->fh_export))
- write_inode_now(dentry->d_inode, 1);
- }
-@@ -1206,7 +1390,10 @@ nfsd_link(struct svc_rqst *rqstp, struct
- dold = tfhp->fh_dentry;
- dest = dold->d_inode;
-
-- err = vfs_link(dold, dirp, dnew);
-+ if (dirp->i_op->link_raw)
-+ err = link_raw(dold, ddir, dnew);
-+ else
-+ err = vfs_link(dold, dirp, dnew);
- if (!err) {
- if (EX_ISSYNC(ffhp->fh_export)) {
- nfsd_sync_dir(ddir);
-@@ -1291,7 +1478,10 @@ nfsd_rename(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ if (fdir->i_op->rename_raw)
-+ err = rename_raw(fdentry, tdentry, odentry, ndentry);
-+ else
-+ err = vfs_rename(fdir, odentry, tdir, ndentry);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
-@@ -1312,7 +1502,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
- fill_post_wcc(tfhp);
- double_up(&tdir->i_sem, &fdir->i_sem);
- ffhp->fh_locked = tfhp->fh_locked = 0;
--
-+
- out:
- return err;
- }
-@@ -1358,9 +1548,15 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_unlink(dirp, rdentry);
-+ if (dirp->i_op->unlink_raw)
-+ err = unlink_raw(dentry, fname, flen, rdentry);
-+ else
-+ err = vfs_unlink(dirp, rdentry);
- } else { /* It's RMDIR */
-- err = vfs_rmdir(dirp, rdentry);
-+ if (dirp->i_op->rmdir_raw)
-+ err = rmdir_raw(dentry, fname, flen, rdentry);
-+ else
-+ err = vfs_rmdir(dirp, rdentry);
- }
-
- dput(rdentry);
-diff -uprN linux/include/linux/fs.h linux-2.4.20/include/linux/fs.h
---- linux/include/linux/fs.h Sun Oct 5 21:52:56 2003
-+++ linux-2.4.20/include/linux/fs.h Sun Oct 5 22:25:20 2003
-@@ -93,6 +93,8 @@ extern int leases_enable, dir_notify_ena
- #define FS_SINGLE 8 /* Filesystem that can have only one superblock */
- #define FS_NOMOUNT 16 /* Never mount from userland */
- #define FS_LITTER 32 /* Keeps the tree in dcache */
-+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for
-+ * exporting non device filesystems. */
- #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
- * as nfs_rename() will be cleaned up
- */
-@@ -1099,6 +1102,9 @@ extern int open_namei_it(const char *fil
- struct nameidata *nd, struct lookup_intent *it);
- extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
- int flags, struct lookup_intent *it);
-+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it);
-+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode,
-+ struct lookup_intent *it);
- extern int filp_close(struct file *, fl_owner_t id);
- extern char * getname(const char *);
-
-@@ -1369,6 +1375,8 @@ extern void path_release(struct nameidat
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int,
-+ struct lookup_intent *);
- 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)
-@@ -1382,6 +1390,8 @@ extern ino_t iunique(struct super_block
-
- typedef int (*find_inode_t)(struct inode *, unsigned long, void *);
- extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *);
-+extern struct inode * ilookup4(struct super_block *, unsigned long,
-+ find_inode_t, void *);
- static inline struct inode *iget(struct super_block *sb, unsigned long ino)
- {
- return iget4(sb, ino, NULL, NULL);
-diff -uprN linux/kernel/ksyms.c linux-2.4.20/kernel/ksyms.c
---- linux/kernel/ksyms.c Sun Oct 5 21:52:51 2003
-+++ linux-2.4.20/kernel/ksyms.c Sun Oct 5 22:25:20 2003
-@@ -146,6 +146,7 @@ EXPORT_SYMBOL(fget);
- EXPORT_SYMBOL(igrab);
- EXPORT_SYMBOL(iunique);
- EXPORT_SYMBOL(iget4);
-+EXPORT_SYMBOL(ilookup4);
- EXPORT_SYMBOL(iput);
- EXPORT_SYMBOL(force_delete);
- EXPORT_SYMBOL(follow_up);
-@@ -156,6 +157,7 @@ EXPORT_SYMBOL(path_walk);
- EXPORT_SYMBOL(path_release);
- EXPORT_SYMBOL(__user_walk);
- EXPORT_SYMBOL(lookup_one_len);
-+EXPORT_SYMBOL(lookup_one_len_it);
- EXPORT_SYMBOL(lookup_hash);
- EXPORT_SYMBOL(sys_close);
- EXPORT_SYMBOL(dcache_lock);
+++ /dev/null
- fs/Makefile | 3
- fs/file_table.c | 11 ++
- fs/inode.c | 23 ++++-
- fs/namei.c | 12 ++
- fs/nfsd/export.c | 5 +
- fs/nfsd/nfsfh.c | 65 +++++++++++++-
- fs/nfsd/vfs.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++-----
- include/linux/fs.h | 11 ++
- kernel/ksyms.c | 2
- 9 files changed, 333 insertions(+), 34 deletions(-)
-
---- linux-2.4.22-ac1/fs/file_table.c~nfs_export_kernel-2.4.22-rh 2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/file_table.c 2003-10-08 13:41:27.000000000 +0400
-@@ -82,7 +82,8 @@ struct file * get_empty_filp(void)
- * and call the open function (if any). The caller must verify that
- * inode->i_fop is not NULL.
- */
--int init_private_file(struct file *filp, struct dentry *dentry, int mode)
-+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode,
-+ struct lookup_intent *it)
- {
- memset(filp, 0, sizeof(*filp));
- filp->f_mode = mode;
-@@ -90,12 +91,20 @@ int init_private_file(struct file *filp,
- filp->f_dentry = dentry;
- filp->f_uid = current->fsuid;
- filp->f_gid = current->fsgid;
-+ if (it)
-+ filp->f_it = it;
- filp->f_op = dentry->d_inode->i_fop;
- if (filp->f_op->open)
- return filp->f_op->open(dentry->d_inode, filp);
- else
- return 0;
- }
-+EXPORT_SYMBOL(init_private_file_it);
-+
-+int init_private_file(struct file *filp, struct dentry *dentry, int mode)
-+{
-+ return init_private_file_it(filp, dentry, mode, NULL);
-+}
-
- void fput(struct file * file)
- {
---- linux-2.4.22-ac1/fs/inode.c~nfs_export_kernel-2.4.22-rh 2003-09-26 00:57:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/inode.c 2003-10-08 13:43:31.000000000 +0400
-@@ -998,9 +998,10 @@ struct inode *igrab(struct inode *inode)
- return inode;
- }
-
--struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
-+struct inode *ifind(struct super_block *sb, unsigned long ino,
-+ struct list_head *head,
-+ find_inode_t find_actor, void *opaque)
- {
-- struct list_head * head = inode_hashtable + hash(sb,ino);
- struct inode * inode;
-
- spin_lock(&inode_lock);
-@@ -1013,6 +1014,24 @@ struct inode *iget4_locked(struct super_
- }
- spin_unlock(&inode_lock);
-
-+ return NULL;
-+}
-+
-+struct inode *ilookup4(struct super_block *sb, unsigned long ino,
-+ find_inode_t find_actor, void *opaque)
-+{
-+ struct list_head * head = inode_hashtable + hash(sb,ino);
-+ return ifind(sb, ino, head, find_actor, opaque);
-+}
-+
-+struct inode *iget4_locked(struct super_block *sb, unsigned long ino,
-+ find_inode_t find_actor, void *opaque)
-+{
-+ struct list_head * head = inode_hashtable + hash(sb,ino);
-+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque);
-+ if (inode)
-+ return inode;
-+
- /*
- * get_new_inode() will do the right thing, re-trying the search
- * in case it had to block at any point.
---- linux-2.4.22-ac1/fs/Makefile~nfs_export_kernel-2.4.22-rh 2003-09-26 00:57:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/Makefile 2003-10-08 13:41:55.000000000 +0400
-@@ -7,7 +7,8 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o inode.o
-+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o inode.o \
-+ namei.o file_table.o
- mod-subdirs := nls xfs
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
---- linux-2.4.22-ac1/fs/namei.c~nfs_export_kernel-2.4.22-rh 2003-09-26 00:57:27.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/namei.c 2003-10-08 13:41:27.000000000 +0400
-@@ -22,6 +22,7 @@
- #include <linux/dnotify.h>
- #include <linux/smp_lock.h>
- #include <linux/personality.h>
-+#include <linux/module.h>
-
- #include <asm/namei.h>
- #include <asm/uaccess.h>
-@@ -100,6 +101,7 @@ void intent_release(struct lookup_intent
- it->it_op_release(it);
-
- }
-+EXPORT_SYMBOL(intent_release);
-
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
-@@ -903,7 +905,8 @@ struct dentry * lookup_hash(struct qstr
-
-
- /* 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;
-@@ -923,11 +926,16 @@ struct dentry * lookup_one_len(const cha
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash_it(&this, base, NULL);
-+ return lookup_hash_it(&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()
- *
---- linux-2.4.22-ac1/fs/nfsd/export.c~nfs_export_kernel-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/nfsd/export.c 2003-10-08 13:41:27.000000000 +0400
-@@ -223,6 +223,11 @@ exp_export(struct nfsctl_export *nxp)
- inode = nd.dentry->d_inode;
- dev = inode->i_dev;
- ino = inode->i_ino;
-+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) &&
-+ !(nxp->ex_flags & NFSEXP_FSID)) {
-+ nxp->ex_dev = inode->i_sb->s_dev;
-+ nxp->ex_flags |= NFSEXP_FSID;
-+ }
- err = -EINVAL;
-
- exp = exp_get(clp, dev, ino);
---- linux-2.4.22-ac1/fs/nfsd/nfsfh.c~nfs_export_kernel-2.4.22-rh 2003-08-25 15:44:43.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/nfsd/nfsfh.c 2003-10-08 13:41:27.000000000 +0400
-@@ -36,6 +36,13 @@ struct nfsd_getdents_callback {
- int sequence; /* sequence counter */
- };
-
-+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry)
-+{
-+ if (inode->i_op->lookup_it)
-+ return inode->i_op->lookup_it(inode, dentry, NULL, 0);
-+ return inode->i_op->lookup(inode, dentry);
-+}
-+
- /*
- * A rather strange filldir function to capture
- * the name matching the specified inode number.
-@@ -75,6 +84,8 @@ static int nfsd_get_name(struct dentry *
- int error;
- struct file file;
- struct nfsd_getdents_callback buffer;
-+ struct lookup_intent it;
-+ struct file *filp = NULL;
-
- error = -ENOTDIR;
- if (!dir || !S_ISDIR(dir->i_mode))
-@@ -85,9 +96,37 @@ static int nfsd_get_name(struct dentry *
- /*
- * Open the directory ...
- */
-- error = init_private_file(&file, dentry, FMODE_READ);
-- if (error)
-+ if (dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) &&
-+ (dentry->d_parent == dentry) ) {
-+ it.it_op_release = NULL;
-+ /*
-+ * XXX Temporary Hack: Simulate init_private_file without
-+ * f_op->open for disconnected dentry as we don't have
-+ * actual dentry->d_name to revalidate in revalidate_it()
-+ */
-+ filp = &file;
-+ memset(filp, 0, sizeof(*filp));
-+ filp->f_mode = FMODE_READ;
-+ atomic_set(&filp->f_count, 1);
-+ filp->f_dentry = dentry;
-+ filp->f_uid = current->fsuid;
-+ filp->f_gid = current->fsgid;
-+ filp->f_op = dentry->d_inode->i_fop;
-+ error = 0;
-+ } else {
-+ intent_init(&it, IT_OPEN, 0);
-+ error = revalidate_it(dentry, &it);
-+ if (error)
-+ goto out;
-+ error = init_private_file_it(&file, dentry, FMODE_READ, &it);
-+ }
-+ } else {
-+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL);
-+ }
-+ if (error)
- goto out;
-+
- error = -EINVAL;
- if (!file.f_op->readdir)
- goto out_close;
-@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry *
- }
-
- out_close:
-- if (file.f_op->release)
-+ if (file.f_op->release && !filp)
- file.f_op->release(dir, &file);
- out:
-+ if (dentry->d_op && dentry->d_op->d_revalidate_it &&
-+ it.it_op_release && !filp)
-+ intent_release(&it);
- return error;
- }
-
-@@ -274,7 +317,7 @@ struct dentry *nfsd_findparent(struct de
- * it is well connected. But nobody returns different dentrys do they?
- */
- down(&child->d_inode->i_sem);
-- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
-+ pdentry = lookup_it(child->d_inode, tdentry);
- up(&child->d_inode->i_sem);
- d_drop(tdentry); /* we never want ".." hashed */
- if (!pdentry && tdentry->d_inode == NULL) {
-@@ -306,6 +349,8 @@ struct dentry *nfsd_findparent(struct de
- igrab(tdentry->d_inode);
- pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
- }
-+ if (child->d_op && child->d_op->d_revalidate_it)
-+ pdentry->d_op = child->d_op;
- }
- if (pdentry == NULL)
- pdentry = ERR_PTR(-ENOMEM);
-@@ -463,6 +508,8 @@ find_fh_dentry(struct super_block *sb, _
- struct dentry *pdentry;
- struct inode *parent;
-
-+ if (result->d_op && result->d_op->d_revalidate_it)
-+ dentry->d_op = result->d_op;
- pdentry = nfsd_findparent(dentry);
- err = PTR_ERR(pdentry);
- if (IS_ERR(pdentry))
-@@ -669,6 +716,10 @@ fh_verify(struct svc_rqst *rqstp, struct
-
- inode = dentry->d_inode;
-
-+ /* cache coherency for non-device filesystems */
-+ if (inode->i_op && inode->i_op->revalidate_it)
-+ inode->i_op->revalidate_it(dentry, NULL);
-+
- /* Type check. The correct error return for type mismatches
- * does not seem to be generally agreed upon. SunOS seems to
- * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
-@@ -902,8 +954,9 @@ out_negative:
- dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
- out_uptodate:
-- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
-- dentry->d_parent->d_name.name, dentry->d_name.name);
-+ if (!dentry->d_parent->d_inode->i_op->mkdir_raw)
-+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
-+ dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
- }
-
---- linux-2.4.22-ac1/fs/nfsd/vfs.c~nfs_export_kernel-2.4.22-rh 2003-08-25 15:44:43.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/nfsd/vfs.c 2003-10-08 13:41:27.000000000 +0400
-@@ -77,6 +77,126 @@ struct raparms {
- static struct raparms * raparml;
- static struct raparms * raparm_cache;
-
-+static int link_raw(struct dentry *dold, struct dentry *ddir,
-+ struct dentry *dnew)
-+{
-+ int err;
-+
-+ struct nameidata old_nd = { .dentry = dold };
-+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->link_raw(&old_nd, &nd);
-+ d_instantiate(dnew, dold->d_inode);
-+ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it)
-+ dold->d_inode->i_op->revalidate_it(dnew, NULL);
-+
-+ return err;
-+}
-+
-+static int unlink_raw(struct dentry *dentry, char *fname, int flen,
-+ struct dentry *rdentry)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->unlink_raw(&nd);
-+ if (!err)
-+ d_delete(rdentry);
-+
-+ return err;
-+}
-+
-+static int rmdir_raw(struct dentry *dentry, char *fname, int flen,
-+ struct dentry *rdentry)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->rmdir_raw(&nd);
-+ if (!err) {
-+ rdentry->d_inode->i_flags |= S_DEAD;
-+ d_delete(rdentry);
-+ }
-+
-+ return err;
-+}
-+
-+static int symlink_raw(struct dentry *dentry, char *fname, int flen,
-+ char *path)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->symlink_raw(&nd, path);
-+
-+ return err;
-+}
-+
-+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->mkdir_raw(&nd, mode);
-+
-+ return err;
-+}
-+
-+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode,
-+ dev_t dev)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->mknod_raw(&nd, mode, dev);
-+
-+ return err;
-+}
-+
-+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry,
-+ struct dentry *odentry, struct dentry *ndentry)
-+{
-+ int err;
-+
-+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name};
-+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name};
-+ struct inode_operations *op = old_nd.dentry->d_inode->i_op;
-+ err = op->rename_raw(&old_nd, &new_nd);
-+ d_move(odentry, ndentry);
-+
-+ return err;
-+}
-+
-+static int setattr_raw(struct inode *inode, struct iattr *iap)
-+{
-+ int err;
-+
-+ iap->ia_valid |= ATTR_RAW;
-+ err = inode->i_op->setattr_raw(inode, iap);
-+
-+ return err;
-+}
-+
-+int revalidate_it(struct dentry *dentry, struct lookup_intent *it)
-+{
-+ int err = 0;
-+
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it) &&
-+ !d_invalidate(dentry)) {
-+ err = -EINVAL;
-+ return err;
-+ }
-+ }
-+
-+ return err;
-+}
-+
- /*
- * Look up one component of a pathname.
- * N.B. After this call _both_ fhp and resfh need an fh_put
-@@ -302,7 +424,10 @@ nfsd_setattr(struct svc_rqst *rqstp, str
- }
- err = nfserr_notsync;
- if (!check_guard || guardtime == inode->i_ctime) {
-- err = notify_change(dentry, iap);
-+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw)
-+ err = setattr_raw(dentry->d_inode, iap);
-+ else
-+ err = notify_change(dentry, iap);
- err = nfserrno(err);
- }
- if (size_change) {
-@@ -429,6 +554,7 @@ nfsd_open(struct svc_rqst *rqstp, struct
- {
- struct dentry *dentry;
- struct inode *inode;
-+ struct lookup_intent it;
- int err;
-
- /* If we get here, then the client has already done an "open", and (hopefully)
-@@ -475,6 +601,18 @@ nfsd_open(struct svc_rqst *rqstp, struct
- filp->f_mode = FMODE_READ;
- }
-
-+#ifndef O_OWNER_OVERRIDE
-+#define O_OWNER_OVERRIDE 0200000000
-+#endif
-+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode |
-+ O_OWNER_OVERRIDE);
-+
-+ err = revalidate_it(dentry, &it);
-+ if (err)
-+ goto out_nfserr;
-+
-+ filp->f_it = ⁢
-+
- err = 0;
- if (filp->f_op && filp->f_op->open) {
- err = filp->f_op->open(inode, filp);
-@@ -489,6 +623,9 @@ nfsd_open(struct svc_rqst *rqstp, struct
- }
- }
- out_nfserr:
-+ if (it.it_op_release)
-+ intent_release(&it);
-+
- if (err)
- err = nfserrno(err);
- out:
-@@ -820,7 +958,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
- {
- struct dentry *dentry, *dchild;
- struct inode *dirp;
-- int err;
-+ int err, error = -EOPNOTSUPP;
-
- err = nfserr_perm;
- if (!flen)
-@@ -836,20 +974,47 @@ nfsd_create(struct svc_rqst *rqstp, stru
- dentry = fhp->fh_dentry;
- dirp = dentry->d_inode;
-
-+ switch (type) {
-+ case S_IFDIR:
-+ if (dirp->i_op->mkdir_raw)
-+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode);
-+ break;
-+ case S_IFCHR:
-+ case S_IFBLK:
-+ case S_IFIFO:
-+ case S_IFSOCK:
-+ case S_IFREG:
-+ if (dirp->i_op->mknod_raw) {
-+ if (type == S_IFREG)
-+ rdev = 0;
-+ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev);
-+ }
-+ break;
-+ default:
-+ printk("nfsd: bad file type %o in nfsd_create\n", type);
-+ }
-+ if (error && error != -EOPNOTSUPP) {
-+ err = error;
-+ goto out_nfserr;
-+ }
-+
- err = nfserr_notdir;
-- if(!dirp->i_op || !dirp->i_op->lookup)
-+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
- goto out;
- /*
- * Check whether the response file handle has been verified yet.
- * If it has, the parent directory should already be locked.
- */
-- if (!resfhp->fh_dentry) {
-- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
-- fh_lock(fhp);
-+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) {
-+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create
-+ * and nfsd_proc_create in case of lustre */
-+ if (!resfhp->fh_dentry)
-+ fh_lock(fhp);
- dchild = lookup_one_len(fname, dentry, flen);
- err = PTR_ERR(dchild);
- if (IS_ERR(dchild))
- goto out_nfserr;
-+ resfhp->fh_dentry = NULL;
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
- if (err)
- goto out;
-@@ -870,10 +1032,12 @@ nfsd_create(struct svc_rqst *rqstp, stru
- * Make sure the child dentry is still negative ...
- */
- err = nfserr_exist;
-- if (dchild->d_inode) {
-- dprintk("nfsd_create: dentry %s/%s not negative!\n",
-- dentry->d_name.name, dchild->d_name.name);
-- goto out;
-+ if (error == -EOPNOTSUPP) {
-+ if (dchild->d_inode) {
-+ dprintk("nfsd_create: dentry %s/%s not negative!\n",
-+ dentry->d_name.name, dchild->d_name.name);
-+ goto out;
-+ }
- }
-
- if (!(iap->ia_valid & ATTR_MODE))
-@@ -886,16 +1050,19 @@ nfsd_create(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- switch (type) {
- case S_IFREG:
-- err = vfs_create(dirp, dchild, iap->ia_mode);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_create(dirp, dchild, iap->ia_mode);
- break;
- case S_IFDIR:
-- err = vfs_mkdir(dirp, dchild, iap->ia_mode);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_mkdir(dirp, dchild, iap->ia_mode);
- break;
- case S_IFCHR:
- case S_IFBLK:
- case S_IFIFO:
- case S_IFSOCK:
-- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
- break;
- default:
- printk("nfsd: bad file type %o in nfsd_create\n", type);
-@@ -964,7 +1131,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
- /* Get all the sanity checks out of the way before
- * we lock the parent. */
- err = nfserr_notdir;
-- if(!dirp->i_op || !dirp->i_op->lookup)
-+ if (dirp->i_op->mknod_raw) {
-+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0);
-+ if (err && err != -EOPNOTSUPP)
-+ goto out_nfserr;
-+ }
-+
-+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
- goto out;
- fh_lock(fhp);
-
-@@ -1015,6 +1188,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
- case NFS3_CREATE_GUARDED:
- err = nfserr_exist;
- }
-+ if (dirp->i_op->mknod_raw)
-+ err = 0;
- goto out;
- }
-
-@@ -1121,7 +1296,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
- struct iattr *iap)
- {
- struct dentry *dentry, *dnew;
-- int err, cerr;
-+ int err, cerr, error = -EOPNOTSUPP;
-
- err = nfserr_noent;
- if (!flen || !plen)
-@@ -1135,12 +1310,18 @@ nfsd_symlink(struct svc_rqst *rqstp, str
- goto out;
- fh_lock(fhp);
- dentry = fhp->fh_dentry;
-+
-+ if (dentry->d_inode->i_op->symlink_raw)
-+ error = symlink_raw(dentry, fname, flen, path);
-+
- dnew = lookup_one_len(fname, dentry, flen);
- err = PTR_ERR(dnew);
- if (IS_ERR(dnew))
- goto out_nfserr;
-
-- err = vfs_symlink(dentry->d_inode, dnew, path);
-+ err = error;
-+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw)
-+ err = vfs_symlink(dentry->d_inode, dnew, path);
- if (!err) {
- if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
-@@ -1148,7 +1329,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str
- iap->ia_valid |= ATTR_CTIME;
- iap->ia_mode = (iap->ia_mode&S_IALLUGO)
- | S_IFLNK;
-- err = notify_change(dnew, iap);
-+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw)
-+ err = setattr_raw(dnew->d_inode, iap);
-+ else
-+ err = notify_change(dnew, iap);
- if (err)
- err = nfserrno(err);
- else if (EX_ISSYNC(fhp->fh_export))
-@@ -1210,7 +1391,10 @@ nfsd_link(struct svc_rqst *rqstp, struct
- dold = tfhp->fh_dentry;
- dest = dold->d_inode;
-
-- err = vfs_link(dold, dirp, dnew);
-+ if (dirp->i_op->link_raw)
-+ err = link_raw(dold, ddir, dnew);
-+ else
-+ err = vfs_link(dold, dirp, dnew);
- if (!err) {
- if (EX_ISSYNC(ffhp->fh_export)) {
- nfsd_sync_dir(ddir);
-@@ -1295,7 +1479,10 @@ nfsd_rename(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ if (fdir->i_op->rename_raw)
-+ err = rename_raw(fdentry, tdentry, odentry, ndentry);
-+ else
-+ err = vfs_rename(fdir, odentry, tdir, ndentry);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
-@@ -1316,7 +1503,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
- fill_post_wcc(tfhp);
- double_up(&tdir->i_sem, &fdir->i_sem);
- ffhp->fh_locked = tfhp->fh_locked = 0;
--
-+
- out:
- return err;
- }
-@@ -1362,9 +1549,15 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_unlink(dirp, rdentry);
-+ if (dirp->i_op->unlink_raw)
-+ err = unlink_raw(dentry, fname, flen, rdentry);
-+ else
-+ err = vfs_unlink(dirp, rdentry);
- } else { /* It's RMDIR */
-- err = vfs_rmdir(dirp, rdentry);
-+ if (dirp->i_op->rmdir_raw)
-+ err = rmdir_raw(dentry, fname, flen, rdentry);
-+ else
-+ err = vfs_rmdir(dirp, rdentry);
- }
-
- dput(rdentry);
---- linux-2.4.22-ac1/include/linux/fs.h~nfs_export_kernel-2.4.22-rh 2003-09-26 01:00:26.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/fs.h 2003-10-08 13:44:53.000000000 +0400
-@@ -93,6 +93,8 @@ extern int leases_enable, dir_notify_ena
- #define FS_SINGLE 8 /* Filesystem that can have only one superblock */
- #define FS_NOMOUNT 16 /* Never mount from userland */
- #define FS_LITTER 32 /* Keeps the tree in dcache */
-+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for
-+ * exporting non device filesystems. */
- #define FS_ALWAYS_REVAL 16384 /* Always revalidate dentries returned by
- link_path_walk */
- #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
-@@ -1121,6 +1124,9 @@ extern int open_namei_it(const char *fil
- struct nameidata *nd, struct lookup_intent *it);
- extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
- int flags, struct lookup_intent *it);
-+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it);
-+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode,
-+ struct lookup_intent *it);
- extern int filp_close(struct file *, fl_owner_t id);
- extern char * getname(const char *);
-
-@@ -1420,6 +1426,8 @@ extern void path_release(struct nameidat
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int,
-+ struct lookup_intent *);
- 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)
-@@ -1439,6 +1447,8 @@ typedef int (*find_inode_t)(struct inode
-
- extern struct inode * iget4_locked(struct super_block *, unsigned long,
- find_inode_t, void *);
-+extern struct inode * ilookup4(struct super_block *, unsigned long,
-+ find_inode_t, void *);
-
- static inline struct inode *iget4(struct super_block *sb, unsigned long ino,
- find_inode_t find_actor, void *opaque)
---- linux-2.4.22-ac1/kernel/ksyms.c~nfs_export_kernel-2.4.22-rh 2003-09-26 00:57:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/kernel/ksyms.c 2003-10-08 13:45:20.000000000 +0400
-@@ -165,6 +165,7 @@ EXPORT_SYMBOL(fget);
- EXPORT_SYMBOL(igrab);
- EXPORT_SYMBOL(iunique);
- EXPORT_SYMBOL(iget4_locked);
-+EXPORT_SYMBOL(ilookup4);
- EXPORT_SYMBOL(unlock_new_inode);
- EXPORT_SYMBOL(iput);
- EXPORT_SYMBOL(inode_init_once);
-@@ -178,6 +179,7 @@ EXPORT_SYMBOL(path_walk);
- EXPORT_SYMBOL(path_release);
- EXPORT_SYMBOL(__user_walk);
- EXPORT_SYMBOL(lookup_one_len);
-+EXPORT_SYMBOL(lookup_one_len_it);
- EXPORT_SYMBOL(lookup_hash);
- EXPORT_SYMBOL(sys_close);
- EXPORT_SYMBOL(dcache_lock);
+++ /dev/null
-Index: linux/arch/i386/kernel/traps.c
-===================================================================
---- linux.orig/arch/i386/kernel/traps.c 2004-11-05 19:00:03.000000000 -0800
-+++ linux/arch/i386/kernel/traps.c 2004-11-05 19:00:06.000000000 -0800
-@@ -133,141 +133,48 @@
-
- #endif
-
--void scan_stack (unsigned long *stack)
-+void show_trace(unsigned long * stack)
- {
-+#if !CONFIG_FRAME_POINTER
- int i;
-+#endif
- unsigned long addr;
-- /* static to not take up stackspace */
-- static char buffer[NR_CPUS][512], *bufp;
-+ /* static to not take up stackspace; if we race here too bad */
-+ static char buffer[512];
-
-- bufp = buffer[smp_processor_id()];
-+ if (!stack)
-+ stack = (unsigned long*)&stack;
-
-+ printk("Call Trace: ");
- /*
- * If we have frame pointers then use them to get
- * a 100% exact backtrace, up until the entry frame:
- */
-+#if CONFIG_FRAME_POINTER
-+#define DO(n) \
-+ addr = (int)__builtin_return_address(n); \
-+ if (!kernel_text_address(addr)) \
-+ goto out; \
-+ lookup_symbol(addr, buffer, 512); \
-+ printk("[<%08lx>] %s\n", addr, buffer);
-+
-+ DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(7); DO(8); DO(9);
-+ DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(17); DO(18); DO(19);
-+out:
-+#else
- i = 1;
- while (((long) stack & (THREAD_SIZE-1)) != 0) {
- addr = *stack++;
- if (kernel_text_address(addr)) {
-- lookup_symbol(addr, bufp, 512);
-- printk("[<%08lx>] %s (0x%p)\n", addr,bufp,stack-1);
-+ lookup_symbol(addr, buffer, 512);
-+ printk("[<%08lx>] %s (0x%p)\n", addr,buffer,stack-1);
- i++;
- }
- }
--}
--
--#if CONFIG_FRAME_POINTER
--void show_stack_frame_params (int param_count, unsigned long params[])
--{
-- int i;
-- unsigned long *p, task_addr, stack_base;
--
-- if (param_count <= 0)
-- return;
--
-- task_addr = (unsigned long) current;
-- stack_base = task_addr + THREAD_SIZE - 1;
--
-- printk(" (");
--
-- for (i = 0, p = params;
-- ((param_count - i) > 1) && (p >= task_addr) && (p <= stack_base);
-- i++, p++) {
-- printk("0x%x, ", *p);
--
-- if ((i % 4) == 3)
-- printk("\n ");
-- }
--
-- if ((p >= task_addr) && (p <= stack_base))
-- printk("0x%x)\n", *p);
--}
--
--/* Display a stack trace for the currently executing task. The 'dummy'
-- * parameter serves a purpose although its value is unused. We use the
-- * address of 'dummy' as a reference point for finding the saved %ebp register
-- * value on the stack.
-- */
--void frame_pointer_walk (void *dummy)
--{
-- int i;
-- unsigned long addr, task_addr, *frame_ptr, *next_frame_ptr, *eip_ptr,
-- eip, stack_base;
-- /* static to not take up stackspace */
-- static char buffer[NR_CPUS][512], *bufp;
--
-- bufp = buffer[smp_processor_id()];
-- task_addr = (unsigned long) current;
-- stack_base = task_addr + THREAD_SIZE - 1;
-- frame_ptr = (unsigned long *) (&dummy - 2);
--
-- for (; ; ) {
-- next_frame_ptr = (unsigned long *) (*frame_ptr);
-- addr = (unsigned long) next_frame_ptr;
--
-- /* Stop when we reach a frame pointer that points to a
-- * location clearly outside our own kernel stack.
-- */
-- if ((addr < task_addr) || (addr > stack_base))
-- break;
--
-- eip_ptr = frame_ptr + 1;
-- eip = *eip_ptr;
--
-- if (kernel_text_address(eip)) {
-- lookup_symbol(eip, bufp, 512);
-- show_stack_frame_params(4, frame_ptr + 2);
-- printk("[<%08lx>] %s (0x%x)\n", eip, bufp,
-- eip_ptr);
-- }
--
-- frame_ptr = next_frame_ptr;
-- }
--}
--
--typedef void (*stack_trace_fn_t) (unsigned long *stack);
--
--void show_trace(unsigned long * stack)
--{
-- static const stack_trace_fn_t trace_fn_vector[] =
-- { scan_stack, frame_pointer_walk };
-- unsigned long addr, task_addr, stack_base;
-- int task_is_current;
--
-- if (!stack)
-- stack = (unsigned long*)&stack;
--
-- printk("Call Trace:\n");
-- addr = (unsigned long) stack;
-- task_addr = (unsigned long) current;
-- stack_base = task_addr + THREAD_SIZE - 1;
-- task_is_current = (addr >= task_addr) && (addr <= stack_base);
--
-- /* We may use frame pointers to do a stack trace only if the current
-- * task is being traced. Tracing some other task in this manner
-- * would require a saved %ebp register value. Perhaps in the future
-- * I'll consider providing a means of obtaining this.
-- */
-- trace_fn_vector[task_is_current](stack);
--
-- printk("\n");
--}
--
--#else /* CONFIG_FRAME_POINTER */
--
--void show_trace(unsigned long * stack)
--{
-- if (!stack)
-- stack = (unsigned long*)&stack;
--
-- printk("Call Trace:\n");
-- scan_stack(stack);
-+#endif
- printk("\n");
- }
-
--#endif /* CONFIG_FRAME_POINTER */
--
- void show_trace_task(struct task_struct *tsk)
- {
- unsigned long esp = tsk->thread.esp;
-Index: linux/fs/namei.c
-===================================================================
---- linux.orig/fs/namei.c 2004-11-05 19:00:03.000000000 -0800
-+++ linux/fs/namei.c 2004-11-05 19:00:06.000000000 -0800
-@@ -1022,7 +1022,7 @@
- * The simplest case - just a plain lookup.
- */
- if (!(flag & O_CREAT)) {
-- error = path_lookup_it(pathname, lookup_flags(flag), nd);
-+ error = path_lookup(pathname, lookup_flags(flag), nd);
- if (error)
- return error;
- dentry = nd->dentry;
-Index: linux/include/asm-i386/hw_irq.h
-===================================================================
---- linux.orig/include/asm-i386/hw_irq.h 2004-11-05 19:00:03.000000000 -0800
-+++ linux/include/asm-i386/hw_irq.h 2004-11-05 19:00:06.000000000 -0800
-@@ -158,9 +158,6 @@
- /* there is a second layer of macro just to get the symbolic
- name for the vector evaluated. This change is for RTLinux */
- #define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
--
--#if CONFIG_X86_HIGH_ENTRY
--
- #define XBUILD_SMP_INTERRUPT(x,v)\
- asmlinkage void x(void); \
- asmlinkage void call_##x(void); \
-@@ -173,26 +170,7 @@
- "movl $"SYMBOL_NAME_STR(smp_##x)", %ebp; call *%ebp\n\t" \
- "jmp ret_from_intr; .previous\n");
-
--#else
--
--#define XBUILD_SMP_INTERRUPT(x,v)\
--asmlinkage void x(void); \
--asmlinkage void call_##x(void); \
--__asm__( \
--".section .entry.text,\"ax\"\n"__ALIGN_STR"\n" \
--SYMBOL_NAME_STR(x) ":\n\t" \
-- "pushl $"#v"-256\n\t" \
-- SAVE_ALL_SWITCH \
-- SYMBOL_NAME_STR(call_##x)":\n\t" \
-- "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
-- "jmp ret_from_intr; .previous\n");
--
--#endif
--
- #define BUILD_SMP_TIMER_INTERRUPT(x,v) XBUILD_SMP_TIMER_INTERRUPT(x,v)
--
--#if CONFIG_X86_HIGH_ENTRY
--
- #define XBUILD_SMP_TIMER_INTERRUPT(x,v) \
- asmlinkage void x(struct pt_regs * regs); \
- asmlinkage void call_##x(void); \
-@@ -208,27 +186,6 @@
- "addl $4,%esp\n\t" \
- "jmp ret_from_intr; .previous\n");
-
--#else
--
--#define XBUILD_SMP_TIMER_INTERRUPT(x,v) \
--asmlinkage void x(struct pt_regs * regs); \
--asmlinkage void call_##x(void); \
--__asm__( \
--".section .entry.text,\"ax\"\n"__ALIGN_STR"\n" \
--SYMBOL_NAME_STR(x) ":\n\t" \
-- "pushl $"#v"-256\n\t" \
-- SAVE_ALL_SWITCH \
-- "movl %esp,%eax\n\t" \
-- "pushl %eax\n\t" \
-- SYMBOL_NAME_STR(call_##x)":\n\t" \
-- "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
-- "addl $4,%esp\n\t" \
-- "jmp ret_from_intr; .previous\n");
--
--#endif
--
--#if CONFIG_X86_HIGH_ENTRY
--
- #define BUILD_COMMON_IRQ() \
- asmlinkage void call_do_IRQ(void); \
- __asm__( \
-@@ -239,20 +196,6 @@
- "movl $"SYMBOL_NAME_STR(do_IRQ)", %ebp; call *%ebp\n\t" \
- "jmp ret_from_intr; .previous\n");
-
--#else
--
--#define BUILD_COMMON_IRQ() \
--asmlinkage void call_do_IRQ(void); \
--__asm__( \
-- ".section .entry.text,\"ax\"\n" __ALIGN_STR"\n" \
-- "common_interrupt:\n\t" \
-- SAVE_ALL_SWITCH \
-- SYMBOL_NAME_STR(call_do_IRQ)":\n\t" \
-- "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
-- "jmp ret_from_intr; .previous\n");
--
--#endif
--
- /*
- * subtle. orig_eax is used by the signal code to distinct between
- * system calls and interrupted 'random user-space'. Thus we have
-Index: linux/mm/highmem.c
-===================================================================
---- linux.orig/mm/highmem.c 2004-11-05 08:59:32.000000000 -0800
-+++ linux/mm/highmem.c 2004-11-05 19:00:06.000000000 -0800
-@@ -465,11 +465,7 @@
- /*
- * FIXME: assuming PAGE_SIZE buffer_heads
- */
--
--/*
-- * don't allow SUPERBH_MAX_USERS to go < 1 - mag
-- */
--#define SUPERBH_MAX_USERS max(POOL_SIZE * PAGE_SIZE / MAX_SUPERBH, 1)
-+#define SUPERBH_MAX_USERS (POOL_SIZE * PAGE_SIZE / MAX_SUPERBH)
-
- static int superbh_users;
- static DECLARE_WAIT_QUEUE_HEAD(superbh_wait);
--- /dev/null
+Index: linux-2.6.9-5.0.3.EL/drivers/scsi/Kconfig
+===================================================================
+--- linux-2.6.9-5.0.3.EL.orig/drivers/scsi/Kconfig 2005-02-25 03:25:42.000000000 -0500
++++ linux-2.6.9-5.0.3.EL/drivers/scsi/Kconfig 2005-03-03 16:10:10.000000000 -0500
+@@ -61,6 +61,13 @@
+ help
+ SCSI dump support
+
++config SD_IOSTATS
++ bool "Enable SCSI disk I/O stats"
++ depends on BLK_DEV_SD
++ ---help---
++ This enables SCSI disk I/O stats collection. You must also enable
++ /proc file system support if you want this feature.
++
+ config CHR_DEV_ST
+ tristate "SCSI tape support"
+ depends on SCSI
+Index: linux-2.6.9-5.0.3.EL/drivers/scsi/sd.c
+===================================================================
+--- linux-2.6.9-5.0.3.EL.orig/drivers/scsi/sd.c 2005-02-25 03:25:40.000000000 -0500
++++ linux-2.6.9-5.0.3.EL/drivers/scsi/sd.c 2005-03-03 16:11:07.000000000 -0500
+@@ -63,6 +63,38 @@
+
+ #include "scsi_logging.h"
+
++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
++# include <linux/proc_fs.h>
++# include <linux/seq_file.h>
++
++typedef struct {
++ unsigned long long iostat_size;
++ unsigned long long iostat_count;
++} iostat_counter_t;
++
++#define IOSTAT_NCOUNTERS 16
++typedef struct {
++ iostat_counter_t iostat_read_histogram[IOSTAT_NCOUNTERS];
++ iostat_counter_t iostat_write_histogram[IOSTAT_NCOUNTERS];
++ struct timeval iostat_timeval;
++} iostat_stats_t;
++
++iostat_stats_t **sd_iostats;
++spinlock_t sd_iostats_lock;
++struct proc_dir_entry *sd_iostats_procdir;
++char sd_iostats_procdir_name[] = "sd_iostats";
++
++extern void sd_iostats_init(void);
++extern void sd_iostats_init_disk(struct gendisk *);
++extern void sd_iostats_fini(void);
++extern void sd_iostats_bump(int disk, unsigned int nsect, int iswrite);
++#else
++static inline void sd_iostats_init(void) {}
++static inline void sd_iostats_init_disk(struct gendisk *) {}
++static inline void sd_iostats_fini(void) {}
++static inline void sd_iostats_bump(kdev_t dev, unsigned int nsect, int iswrite) {}
++#endif
++
+ /*
+ * More than enough for everybody ;) The huge number of majors
+ * is a leftover from 16bit dev_t days, we don't really need that
+@@ -76,6 +108,7 @@
+ */
+ #define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26)
+
++#define SD_STATS 256
+ /*
+ * Time out in seconds for disks and Magneto-opticals (which are slower).
+ */
+@@ -276,6 +309,9 @@
+ SCSI_LOG_HLQUEUE(2, printk("%s : block=%llu\n",
+ disk->disk_name, (unsigned long long)block));
+
++ sd_iostats_bump(scsi_disk(disk)->index, this_count,
++ rq_data_dir(SCpnt->request) == WRITE);
++
+ /*
+ * If we have a 1K hardware sectorsize, prevent access to single
+ * 512 byte sectors. In theory we could handle this - in fact
+@@ -472,6 +508,7 @@
+ scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
+ }
+
++ sd_iostats_init_disk(disk);
+ return 0;
+
+ error_out:
+@@ -1573,6 +1610,327 @@
+ sd_sync_cache(sdp);
+ }
+
++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
++static int
++sd_iostats_seq_show(struct seq_file *seq, void *v)
++{
++ struct timeval now;
++ struct gendisk *disk = seq->private;
++ iostat_stats_t *stats;
++ unsigned long long read_len;
++ unsigned long long read_len_tot;
++ unsigned long read_num;
++ unsigned long read_num_tot;
++ unsigned long long write_len;
++ unsigned long long write_len_tot;
++ unsigned long write_num;
++ unsigned long write_num_tot;
++ int i;
++ int maxi;
++
++ if (sd_iostats == NULL) {
++ printk(KERN_ERR "sd_iostats_seq_show: NULL stats array\n");
++ BUG();
++ }
++
++ stats = sd_iostats[scsi_disk(disk)->index];
++ if (stats == NULL) {
++ printk(KERN_ERR "sd_iostats_seq_show: NULL stats entry\n");
++ BUG();
++ }
++
++ do_gettimeofday(&now);
++ now.tv_sec -= stats->iostat_timeval.tv_sec;
++ now.tv_usec -= stats->iostat_timeval.tv_usec;
++ if (now.tv_usec < 0) {
++ now.tv_usec += 1000000;
++ now.tv_sec--;
++ }
++
++ /* this sampling races with updates */
++ seq_printf(seq, "index: %lu snapshot_time: %lu.%06lu\n",
++ scsi_disk(disk)->index, now.tv_sec, now.tv_usec);
++
++ for (i = IOSTAT_NCOUNTERS - 1; i > 0; i--)
++ if (stats->iostat_read_histogram[i].iostat_count != 0 ||
++ stats->iostat_write_histogram[i].iostat_count != 0)
++ break;
++ maxi = i;
++
++ seq_printf(seq, "%8s %8s %12s %8s %12s\n", "size",
++ "reads", "total", "writes", "total");
++
++ read_len_tot = write_len_tot = 0;
++ read_num_tot = write_num_tot = 0;
++ for (i = 0; i <= maxi; i++) {
++ read_len = stats->iostat_read_histogram[i].iostat_size;
++ read_len_tot += read_len;
++ read_num = stats->iostat_read_histogram[i].iostat_count;
++ read_num_tot += read_num;
++
++ write_len = stats->iostat_write_histogram[i].iostat_size;
++ write_len_tot += write_len;
++ write_num = stats->iostat_write_histogram[i].iostat_count;
++ write_num_tot += write_num;
++
++ seq_printf (seq, "%8d %8lu %12llu %8lu %12llu\n",
++ 512<<i, read_num, read_len, write_num, write_len);
++ }
++
++ seq_printf(seq, "%8s %8lu %12llu %8lu %12llu\n", "total",
++ read_num_tot, read_len_tot,
++ write_num_tot, write_len_tot);
++ return 0;
++}
++
++static void *
++sd_iostats_seq_start(struct seq_file *p, loff_t *pos)
++{
++ return (*pos == 0) ? (void *)1 : NULL;
++}
++
++static void *
++sd_iostats_seq_next(struct seq_file *p, void *v, loff_t *pos)
++{
++ ++*pos;
++ return NULL;
++}
++
++static void
++sd_iostats_seq_stop(struct seq_file *p, void *v)
++{
++}
++
++static struct seq_operations sd_iostats_seqops = {
++ .start = sd_iostats_seq_start,
++ .stop = sd_iostats_seq_stop,
++ .next = sd_iostats_seq_next,
++ .show = sd_iostats_seq_show,
++};
++
++static int
++sd_iostats_seq_open (struct inode *inode, struct file *file)
++{
++ int rc;
++
++ rc = seq_open(file, &sd_iostats_seqops);
++ if (rc != 0)
++ return rc;
++
++ ((struct seq_file *)file->private_data)->private = PDE(inode)->data;
++ return 0;
++}
++
++static ssize_t
++sd_iostats_seq_write(struct file *file, const char *buffer,
++ size_t len, loff_t *off)
++{
++ struct seq_file *seq = file->private_data;
++ struct gendisk *disk = seq->private;
++ iostat_stats_t *stats = sd_iostats[scsi_disk(disk)->index];
++ unsigned long flags;
++
++
++ spin_lock_irqsave (&sd_iostats_lock, flags);
++ memset (stats, 0, sizeof(*stats));
++ do_gettimeofday(&stats->iostat_timeval);
++ spin_unlock_irqrestore (&sd_iostats_lock, flags);
++
++ return len;
++}
++
++static struct file_operations sd_iostats_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = sd_iostats_seq_open,
++ .read = seq_read,
++ .write = sd_iostats_seq_write,
++ .llseek = seq_lseek,
++ .release = seq_release,
++};
++
++extern struct proc_dir_entry *proc_scsi;
++
++void
++sd_iostats_init(void)
++{
++ int i;
++
++ spin_lock_init(&sd_iostats_lock);
++
++ sd_iostats = kmalloc(SD_STATS * sizeof(iostat_stats_t *), GFP_KERNEL);
++ if (sd_iostats == NULL) {
++ printk(KERN_WARNING "Can't keep sd iostats: "
++ "ENOMEM allocating stats array size %ld\n",
++ SD_STATS * sizeof(iostat_stats_t *));
++ return;
++ }
++
++ for (i = 0; i < SD_STATS; i++)
++ sd_iostats[i] = NULL;
++
++ if (proc_scsi == NULL) {
++ printk(KERN_WARNING "No access to sd iostats: "
++ "proc_scsi is NULL\n");
++ return;
++ }
++
++ sd_iostats_procdir = create_proc_entry(sd_iostats_procdir_name,
++ S_IFDIR | S_IRUGO | S_IXUGO,
++ proc_scsi);
++ if (sd_iostats_procdir == NULL) {
++ printk(KERN_WARNING "No access to sd iostats: "
++ "can't create /proc/scsi/%s\n", sd_iostats_procdir_name);
++ return;
++ }
++}
++
++void
++sd_iostats_init_disk(struct gendisk *disk)
++{
++ struct proc_dir_entry *pde;
++ unsigned long flags;
++ iostat_stats_t *stats;
++
++ if (sd_iostats == NULL ||
++ sd_iostats_procdir == NULL)
++ return;
++
++ if (scsi_disk(disk)->index > SD_STATS) {
++ printk(KERN_ERR "sd_iostats_init_disk: "
++ "unexpected disk index %d(%d)\n",
++ scsi_disk(disk)->index, SD_STATS);
++ return;
++ }
++
++ if (sd_iostats[scsi_disk(disk)->index] != NULL)
++ return;
++
++ stats = kmalloc(sizeof(*stats), GFP_KERNEL);
++ if (stats == NULL) {
++ printk(KERN_WARNING "Can't keep %s iostats: "
++ "ENOMEM allocating stats size %ld\n",
++ disk->disk_name, sizeof(*stats));
++ return;
++ }
++
++ memset (stats, 0, sizeof(*stats));
++ do_gettimeofday(&stats->iostat_timeval);
++
++ spin_lock_irqsave(&sd_iostats_lock, flags);
++
++ if (sd_iostats[scsi_disk(disk)->index] != NULL) {
++ spin_unlock_irqrestore(&sd_iostats_lock, flags);
++ kfree (stats);
++ return;
++ }
++
++ sd_iostats[scsi_disk(disk)->index] = stats;
++
++ spin_unlock_irqrestore(&sd_iostats_lock, flags);
++
++ pde = create_proc_entry(disk->disk_name, S_IRUGO | S_IWUSR,
++ sd_iostats_procdir);
++ if (pde == NULL) {
++ printk(KERN_WARNING "Can't create /proc/scsi/%s/%s\n",
++ sd_iostats_procdir_name, disk->disk_name);
++ } else {
++ pde->proc_fops = &sd_iostats_proc_fops;
++ pde->data = disk;
++ }
++}
++
++static void sd_devname(unsigned int disknum, char *buffer)
++{
++ if (disknum < 26)
++ sprintf(buffer, "sd%c", 'a' + disknum);
++ else {
++ unsigned int min1;
++ unsigned int min2;
++ /*
++ * For larger numbers of disks, we need to go to a new
++ * naming scheme.
++ */
++ min1 = disknum / 26;
++ min2 = disknum % 26;
++ sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2);
++ }
++}
++
++void
++sd_iostats_fini(void)
++{
++ char name[6];
++ int i;
++
++ if (sd_iostats_procdir != NULL) {
++ for (i = 0; i < SD_STATS; i++) {
++ sd_devname(i, name);
++ remove_proc_entry(name, sd_iostats_procdir);
++ }
++
++ if (proc_scsi == NULL) {
++ printk(KERN_ERR "sd_iostats_fini: proc_scsi NULL\n");
++ BUG();
++ }
++ remove_proc_entry(sd_iostats_procdir_name,
++ proc_scsi);
++
++ sd_iostats_procdir = NULL;
++ }
++
++ if (sd_iostats != NULL) {
++ for (i = 0; i < SD_STATS; i++) {
++ if (sd_iostats[i] != NULL)
++ kfree (sd_iostats[i]);
++ }
++
++ kfree(sd_iostats);
++ sd_iostats = NULL;
++ }
++}
++
++void
++sd_iostats_bump(int disk, unsigned int nsect, int iswrite)
++{
++ iostat_stats_t *stats;
++ iostat_counter_t *counter;
++ int bucket;
++ int tmp;
++ unsigned long irqflags;
++
++ if (sd_iostats == NULL)
++ return;
++
++ if (disk < 0 || disk >= SD_STATS) {
++ printk(KERN_ERR "sd_iostats_bump: unexpected disk index %d([0-%d])\n",
++ disk, SD_STATS);
++ BUG();
++ }
++
++ for (bucket = 0, tmp = nsect; tmp > 1; bucket++)
++ tmp /= 2;
++
++ if (bucket >= IOSTAT_NCOUNTERS) {
++ printk (KERN_ERR "sd_iostats_bump: nsect %d too big\n", nsect);
++ BUG();
++ }
++
++ spin_lock_irqsave(&sd_iostats_lock, irqflags);
++
++ stats = sd_iostats[disk];
++ if (stats != NULL) {
++ counter = iswrite ?
++ &stats->iostat_write_histogram[bucket] :
++ &stats->iostat_read_histogram[bucket];
++
++ counter->iostat_size += nsect;
++ counter->iostat_count++;
++ }
++
++ spin_unlock_irqrestore(&sd_iostats_lock, irqflags);
++}
++#endif
++
+ /**
+ * init_sd - entry point for this driver (both when built in or when
+ * a module).
+@@ -1582,6 +1940,7 @@
+ static int __init init_sd(void)
+ {
+ int majors = 0, i;
++ int rc = 0;
+
+ SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
+
+@@ -1592,7 +1951,10 @@
+ if (!majors)
+ return -ENODEV;
+
+- return scsi_register_driver(&sd_template.gendrv);
++ rc = scsi_register_driver(&sd_template.gendrv);
++ if (rc == 0)
++ sd_iostats_init();
++ return rc;
+ }
+
+ /**
+@@ -1606,6 +1968,7 @@
+
+ SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
+
++ sd_iostats_fini();
+ scsi_unregister_driver(&sd_template.gendrv);
+ for (i = 0; i < SD_MAJORS; i++)
+ unregister_blkdev(sd_major(i), "sd");
+Index: linux-2.6.9-5.0.3.EL/drivers/scsi/scsi_proc.c
+===================================================================
+--- linux-2.6.9-5.0.3.EL.orig/drivers/scsi/scsi_proc.c 2004-10-18 17:53:11.000000000 -0400
++++ linux-2.6.9-5.0.3.EL/drivers/scsi/scsi_proc.c 2005-03-03 16:10:10.000000000 -0500
+@@ -38,7 +38,8 @@
+ /* 4K page size, but our output routines, use some slack for overruns */
+ #define PROC_BLOCK_SIZE (3*1024)
+
+-static struct proc_dir_entry *proc_scsi;
++struct proc_dir_entry *proc_scsi;
++EXPORT_SYMBOL(proc_scsi);
+
+ /* Protect sht->present and sht->proc_dir */
+ static DECLARE_MUTEX(global_host_template_sem);
+++ /dev/null
- include/linux/socket.h | 4 ++++
- net/netsyms.c | 1 +
- net/socket.c | 2 +-
- 3 files changed, 6 insertions(+), 1 deletion(-)
-
---- linux-2.4.22-ac1/include/linux/socket.h~socket-exports-2.4.22-rh 2003-06-13 18:51:39.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/socket.h 2003-09-26 00:49:43.000000000 +0400
-@@ -275,6 +275,10 @@ extern void memcpy_tokerneliovec(struct
- extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
- extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr);
- extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
-+struct socket;
-+extern int sock_map_fd(struct socket *sock);
-+extern struct socket *sockfd_lookup(int fd, int *err);
-+
- #endif
- #endif /* not kernel and not glibc */
- #endif /* _LINUX_SOCKET_H */
---- linux-2.4.22-ac1/net/netsyms.c~socket-exports-2.4.22-rh 2003-09-26 00:49:19.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/net/netsyms.c 2003-09-26 00:50:20.000000000 +0400
-@@ -163,6 +163,7 @@ EXPORT_SYMBOL(put_cmsg);
- EXPORT_SYMBOL(sock_kmalloc);
- EXPORT_SYMBOL(sock_kfree_s);
- EXPORT_SYMBOL(sockfd_lookup);
-+EXPORT_SYMBOL(sock_map_fd);
-
- #ifdef CONFIG_FILTER
- EXPORT_SYMBOL(sk_run_filter);
---- linux-2.4.22-ac1/net/socket.c~socket-exports-2.4.22-rh 2003-08-25 15:44:44.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/net/socket.c 2003-09-26 00:49:43.000000000 +0400
-@@ -325,7 +325,7 @@ static struct dentry_operations sockfs_d
- * but we take care of internal coherence yet.
- */
-
--static int sock_map_fd(struct socket *sock)
-+int sock_map_fd(struct socket *sock)
- {
- int fd;
- struct qstr this;
-
-_
+++ /dev/null
- include/linux/skbuff.h | 30 +++++
- include/net/tcp.h | 5
- net/core/skbuff.c | 25 ++++
- net/ipv4/tcp.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++-
- net/netsyms.c | 2
- 5 files changed, 311 insertions(+), 3 deletions(-)
-
-Index: linux-2.4.20-rh-20.9/include/linux/skbuff.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/linux/skbuff.h 2003-09-13 19:34:24.000000000 +0400
-+++ linux-2.4.20-rh-20.9/include/linux/skbuff.h 2003-12-19 14:14:55.000000000 +0300
-@@ -116,6 +116,30 @@
- __u16 size;
- };
-
-+/* Support for callback when skb data has been released */
-+typedef struct zccd /* Zero Copy Callback Descriptor */
-+{ /* (embed as first member of custom struct) */
-+ atomic_t zccd_count; /* reference count */
-+ void (*zccd_destructor)(struct zccd *); /* callback when refcount reaches zero */
-+} zccd_t;
-+
-+static inline void zccd_init (zccd_t *d, void (*callback)(zccd_t *))
-+{
-+ atomic_set (&d->zccd_count, 1);
-+ d->zccd_destructor = callback;
-+}
-+
-+static inline void zccd_get (zccd_t *d) /* take a reference */
-+{
-+ atomic_inc (&d->zccd_count);
-+}
-+
-+static inline void zccd_put (zccd_t *d) /* release a reference */
-+{
-+ if (atomic_dec_and_test (&d->zccd_count))
-+ (d->zccd_destructor)(d);
-+}
-+
- /* This data is invariant across clones and lives at
- * the end of the header data, ie. at skb->end.
- */
-@@ -123,6 +147,12 @@
- atomic_t dataref;
- unsigned int nr_frags;
- struct sk_buff *frag_list;
-+ zccd_t *zccd; /* zero copy descriptor */
-+ zccd_t *zccd2; /* 2nd zero copy descriptor */
-+ /* NB we expect zero-copy data to be at least 1 packet, so
-+ * having 2 zccds means we don't unneccessarily split the packet
-+ * where consecutive zero-copy sends abutt.
-+ */
- skb_frag_t frags[MAX_SKB_FRAGS];
- };
-
-Index: linux-2.4.20-rh-20.9/include/net/tcp.h
-===================================================================
---- linux-2.4.20-rh-20.9.orig/include/net/tcp.h 2003-09-13 19:34:25.000000000 +0400
-+++ linux-2.4.20-rh-20.9/include/net/tcp.h 2003-12-19 14:14:55.000000000 +0300
-@@ -643,6 +643,8 @@
-
- extern int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size);
- extern ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags);
-+extern ssize_t tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
-+ int flags, zccd_t *zccd);
-
- extern int tcp_ioctl(struct sock *sk,
- int cmd,
-@@ -737,6 +739,9 @@
- struct msghdr *msg,
- int len, int nonblock,
- int flags, int *addr_len);
-+extern int tcp_recvpackets(struct sock *sk,
-+ struct sk_buff_head *packets,
-+ int len, int nonblock);
-
- extern int tcp_listen_start(struct sock *sk);
-
-Index: linux-2.4.20-rh-20.9/net/netsyms.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/net/netsyms.c 2003-09-13 19:34:24.000000000 +0400
-+++ linux-2.4.20-rh-20.9/net/netsyms.c 2003-12-19 14:15:24.000000000 +0300
-@@ -396,7 +396,7 @@
- EXPORT_SYMBOL(sysctl_tcp_wmem);
- EXPORT_SYMBOL(sysctl_tcp_ecn);
- EXPORT_SYMBOL(tcp_cwnd_application_limited);
--EXPORT_SYMBOL(tcp_sendpage);
-+EXPORT_SYMBOL(tcp_recvpackets);
- EXPORT_SYMBOL(sysctl_tcp_low_latency);
-
- EXPORT_SYMBOL(tcp_write_xmit);
-@@ -417,6 +417,8 @@
-
- #endif
-
-+EXPORT_SYMBOL(tcp_sendpage);
-+EXPORT_SYMBOL(tcp_sendpage_zccd);
- EXPORT_SYMBOL(tcp_read_sock);
-
- EXPORT_SYMBOL(netlink_set_err);
-Index: linux-2.4.20-rh-20.9/net/core/skbuff.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/net/core/skbuff.c 2003-09-13 19:34:19.000000000 +0400
-+++ linux-2.4.20-rh-20.9/net/core/skbuff.c 2003-12-19 14:14:56.000000000 +0300
-@@ -208,6 +208,8 @@
- atomic_set(&(skb_shinfo(skb)->dataref), 1);
- skb_shinfo(skb)->nr_frags = 0;
- skb_shinfo(skb)->frag_list = NULL;
-+ skb_shinfo(skb)->zccd = NULL; /* skbuffs kick off with NO user zero copy descriptors */
-+ skb_shinfo(skb)->zccd2 = NULL;
- return skb;
-
- nodata:
-@@ -276,6 +278,10 @@
- {
- if (!skb->cloned ||
- atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) {
-+ if (skb_shinfo(skb)->zccd != NULL) /* zero copy callback descriptor? */
-+ zccd_put (skb_shinfo(skb)->zccd); /* release hold */
-+ if (skb_shinfo(skb)->zccd2 != NULL) /* 2nd zero copy callback descriptor? */
-+ zccd_put (skb_shinfo(skb)->zccd2); /* release hold */
- if (skb_shinfo(skb)->nr_frags) {
- int i;
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-@@ -532,6 +538,8 @@
- atomic_set(&(skb_shinfo(skb)->dataref), 1);
- skb_shinfo(skb)->nr_frags = 0;
- skb_shinfo(skb)->frag_list = NULL;
-+ skb_shinfo(skb)->zccd = NULL; /* copied data => no user zero copy descriptor */
-+ skb_shinfo(skb)->zccd2 = NULL;
-
- /* We are no longer a clone, even if we were. */
- skb->cloned = 0;
-@@ -578,6 +586,14 @@
- n->data_len = skb->data_len;
- n->len = skb->len;
-
-+ if (skb_shinfo(skb)->zccd != NULL) /* user zero copy descriptor? */
-+ zccd_get (skb_shinfo(skb)->zccd); /* 1 more ref (pages are shared) */
-+ skb_shinfo(n)->zccd = skb_shinfo(skb)->zccd;
-+
-+ if (skb_shinfo(skb)->zccd2 != NULL) /* 2nd user zero copy descriptor? */
-+ zccd_get (skb_shinfo(skb)->zccd2); /* 1 more ref (pages are shared) */
-+ skb_shinfo(n)->zccd2 = skb_shinfo(skb)->zccd2;
-+
- if (skb_shinfo(skb)->nr_frags) {
- int i;
-
-@@ -620,6 +636,8 @@
- u8 *data;
- int size = nhead + (skb->end - skb->head) + ntail;
- long off;
-+ zccd_t *zccd = skb_shinfo(skb)->zccd; /* stash user zero copy descriptor */
-+ zccd_t *zccd2 = skb_shinfo(skb)->zccd2; /* stash 2nd user zero copy descriptor */
-
- if (skb_shared(skb))
- BUG();
-@@ -641,6 +659,11 @@
- if (skb_shinfo(skb)->frag_list)
- skb_clone_fraglist(skb);
-
-+ if (zccd != NULL) /* user zero copy descriptor? */
-+ zccd_get (zccd); /* extra ref (pages are shared) */
-+ if (zccd2 != NULL) /* 2nd user zero copy descriptor? */
-+ zccd_get (zccd2); /* extra ref (pages are shared) */
-+
- skb_release_data(skb);
-
- off = (data+nhead) - skb->head;
-@@ -655,6 +678,8 @@
- skb->nh.raw += off;
- skb->cloned = 0;
- atomic_set(&skb_shinfo(skb)->dataref, 1);
-+ skb_shinfo(skb)->zccd = zccd;
-+ skb_shinfo(skb)->zccd2 = zccd2;
- return 0;
-
- nodata:
-Index: linux-2.4.20-rh-20.9/net/ipv4/tcp.c
-===================================================================
---- linux-2.4.20-rh-20.9.orig/net/ipv4/tcp.c 2003-09-13 19:34:25.000000000 +0400
-+++ linux-2.4.20-rh-20.9/net/ipv4/tcp.c 2003-12-19 14:14:56.000000000 +0300
-@@ -747,7 +747,7 @@
- goto out;
- }
-
--ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags);
-+ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags, zccd_t *zccd);
-
- static inline int
- can_coalesce(struct sk_buff *skb, int i, struct page *page, int off)
-@@ -826,7 +826,8 @@
- return err;
- }
-
--ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags)
-+/* Extra parameter: user zero copy descriptor (or NULL if not doing that) */
-+ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags, zccd_t *zccd)
- {
- struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
- int mss_now;
-@@ -874,6 +875,17 @@
- copy = size;
-
- i = skb_shinfo(skb)->nr_frags;
-+
-+ if (zccd != NULL && /* this is a zcc I/O */
-+ skb_shinfo(skb)->zccd != NULL && /* skb is part of a zcc I/O */
-+ skb_shinfo(skb)->zccd2 != NULL &&
-+ skb_shinfo(skb)->zccd != zccd && /* not the same one */
-+ skb_shinfo(skb)->zccd2 != zccd)
-+ {
-+ tcp_mark_push (tp, skb);
-+ goto new_segment;
-+ }
-+
- if (can_coalesce(skb, i, page, offset)) {
- skb_shinfo(skb)->frags[i-1].size += copy;
- } else if (i < MAX_SKB_FRAGS) {
-@@ -884,6 +896,20 @@
- goto new_segment;
- }
-
-+ if (zccd != NULL && /* this is a zcc I/O */
-+ skb_shinfo(skb)->zccd != zccd && /* not already referencing this zccd */
-+ skb_shinfo(skb)->zccd2 != zccd)
-+ {
-+ zccd_get (zccd); /* bump ref count */
-+
-+ BUG_TRAP (skb_shinfo(skb)->zccd2 == NULL);
-+
-+ if (skb_shinfo(skb)->zccd == NULL) /* reference this zccd */
-+ skb_shinfo(skb)->zccd = zccd;
-+ else
-+ skb_shinfo(skb)->zccd2 = zccd;
-+ }
-+
- skb->len += copy;
- skb->data_len += copy;
- skb->ip_summed = CHECKSUM_HW;
-@@ -947,7 +973,31 @@
-
- lock_sock(sk);
- TCP_CHECK_TIMER(sk);
-- res = do_tcp_sendpages(sk, &page, offset, size, flags);
-+ res = do_tcp_sendpages(sk, &page, offset, size, flags, NULL);
-+ TCP_CHECK_TIMER(sk);
-+ release_sock(sk);
-+ return res;
-+}
-+
-+ssize_t tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
-+ int flags, zccd_t *zccd)
-+{
-+ ssize_t res;
-+ struct sock *sk = sock->sk;
-+
-+#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
-+
-+ if (!(sk->route_caps & NETIF_F_SG) || /* caller shouldn't waste her time */
-+ !(sk->route_caps & TCP_ZC_CSUM_FLAGS)) /* on double mapping */
-+ BUG ();
-+
-+#undef TCP_ZC_CSUM_FLAGS
-+
-+ lock_sock(sk);
-+ TCP_CHECK_TIMER(sk);
-+
-+ res = do_tcp_sendpages(sk, &page, offset, size, flags, zccd);
-+
- TCP_CHECK_TIMER(sk);
- release_sock(sk);
- return res;
-@@ -1771,6 +1821,202 @@
- goto out;
- }
-
-+int tcp_recvpackets (struct sock *sk, struct sk_buff_head *packets,
-+ int len, int nonblock)
-+{
-+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
-+ int copied;
-+ long timeo;
-+
-+ BUG_TRAP (len > 0);
-+ /*BUG_TRAP ((flags & (MSG_OOB | MSG_PEEK | MSG_TRUNC)) == 0);*/
-+
-+ lock_sock(sk);
-+
-+ TCP_CHECK_TIMER(sk);
-+
-+ copied = -ENOTCONN;
-+ if (sk->state == TCP_LISTEN)
-+ goto out;
-+
-+ copied = 0;
-+ timeo = sock_rcvtimeo(sk, nonblock);
-+
-+ do {
-+ struct sk_buff * skb;
-+ u32 offset;
-+ unsigned long used;
-+ int exhausted;
-+ int eaten;
-+
-+ /* Are we at urgent data? Stop if we have read anything. */
-+ if (copied && tp->urg_data && tp->urg_seq == tp->copied_seq)
-+ break;
-+
-+ /* We need to check signals first, to get correct SIGURG
-+ * handling. FIXME: Need to check this doesnt impact 1003.1g
-+ * and move it down to the bottom of the loop
-+ */
-+ if (signal_pending(current)) {
-+ if (copied)
-+ break;
-+ copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
-+ break;
-+ }
-+
-+ /* Next get a buffer. */
-+
-+ skb = skb_peek(&sk->receive_queue);
-+
-+ if (skb == NULL) /* nothing ready */
-+ {
-+ if (copied) {
-+ if (sk->err ||
-+ sk->state == TCP_CLOSE ||
-+ (sk->shutdown & RCV_SHUTDOWN) ||
-+ !timeo ||
-+ (0))
-+ break;
-+ } else {
-+ if (sk->done)
-+ break;
-+
-+ if (sk->err) {
-+ copied = sock_error(sk);
-+ break;
-+ }
-+
-+ if (sk->shutdown & RCV_SHUTDOWN)
-+ break;
-+
-+ if (sk->state == TCP_CLOSE) {
-+ if (!sk->done) {
-+ /* This occurs when user tries to read
-+ * from never connected socket.
-+ */
-+ copied = -ENOTCONN;
-+ break;
-+ }
-+ break;
-+ }
-+
-+ if (!timeo) {
-+ copied = -EAGAIN;
-+ break;
-+ }
-+ }
-+
-+ cleanup_rbuf(sk, copied);
-+ timeo = tcp_data_wait(sk, timeo);
-+ continue;
-+ }
-+
-+ BUG_TRAP (atomic_read (&skb->users) == 1);
-+
-+ exhausted = eaten = 0;
-+
-+ offset = tp->copied_seq - TCP_SKB_CB(skb)->seq;
-+ if (skb->h.th->syn)
-+ offset--;
-+
-+ used = skb->len - offset;
-+
-+ if (tp->urg_data) {
-+ u32 urg_offset = tp->urg_seq - tp->copied_seq;
-+ if (urg_offset < used) {
-+ if (!urg_offset) { /* at urgent date */
-+ if (!sk->urginline) {
-+ tp->copied_seq++; /* discard the single byte of urgent data */
-+ offset++;
-+ used--;
-+ }
-+ } else /* truncate read */
-+ used = urg_offset;
-+ }
-+ }
-+
-+ BUG_TRAP (used >= 0);
-+ if (len < used)
-+ used = len;
-+
-+ if (used == 0)
-+ exhausted = 1;
-+ else
-+ {
-+ if (skb_is_nonlinear (skb))
-+ {
-+ int rc = skb_linearize (skb, GFP_KERNEL);
-+
-+ printk ("tcp_recvpackets(): linearising: %d\n", rc);
-+
-+ if (rc)
-+ {
-+ if (!copied)
-+ copied = rc;
-+ break;
-+ }
-+ }
-+
-+ if ((offset + used) == skb->len) /* consuming the whole packet */
-+ {
-+ __skb_unlink (skb, &sk->receive_queue);
-+ dst_release (skb->dst);
-+ skb_orphan (skb);
-+ __skb_pull (skb, offset);
-+ __skb_queue_tail (packets, skb);
-+ exhausted = eaten = 1;
-+ }
-+ else /* consuming only part of the packet */
-+ {
-+ struct sk_buff *skb2 = skb_clone (skb, GFP_KERNEL);
-+
-+ if (skb2 == NULL)
-+ {
-+ if (!copied)
-+ copied = -ENOMEM;
-+ break;
-+ }
-+
-+ dst_release (skb2->dst);
-+ __skb_pull (skb2, offset);
-+ __skb_trim (skb2, used);
-+ __skb_queue_tail (packets, skb2);
-+ }
-+
-+ tp->copied_seq += used;
-+ copied += used;
-+ len -= used;
-+ }
-+
-+ if (tp->urg_data && after(tp->copied_seq,tp->urg_seq)) {
-+ tp->urg_data = 0;
-+ tcp_fast_path_check(sk, tp);
-+ }
-+
-+ if (!exhausted)
-+ continue;
-+
-+ if (skb->h.th->fin)
-+ {
-+ tp->copied_seq++;
-+ if (!eaten)
-+ tcp_eat_skb (sk, skb);
-+ break;
-+ }
-+
-+ if (!eaten)
-+ tcp_eat_skb (sk, skb);
-+
-+ } while (len > 0);
-+
-+ out:
-+ /* Clean up data we have read: This will do ACK frames. */
-+ cleanup_rbuf(sk, copied);
-+ TCP_CHECK_TIMER(sk);
-+ release_sock(sk);
-+ return copied;
-+}
-+
- /*
- * State processing on a close. This implements the state shift for
- * sending our FIN frame. Note that we only send a FIN for some
+++ /dev/null
- fs/inode.c | 1
- fs/namei.c | 66 ++++++++++++++++++++++++++++++++++++++---------------
- include/linux/fs.h | 11 ++++----
- 3 files changed, 54 insertions(+), 24 deletions(-)
-
-Index: linux-2.4.20-rh/fs/namei.c
-===================================================================
---- linux-2.4.20-rh.orig/fs/namei.c 2003-09-04 20:58:33.000000000 +0800
-+++ linux-2.4.20-rh/fs/namei.c 2003-09-04 21:21:20.000000000 +0800
-@@ -101,6 +101,36 @@
-
- }
-
-+static void *lock_dir(struct inode *dir, struct qstr *name)
-+{
-+ unsigned long hash;
-+
-+ if (!IS_PDIROPS(dir)) {
-+ down(&dir->i_sem);
-+ return 0;
-+ }
-+
-+ /* OK. fs understands parallel directory operations.
-+ * so, we try to acquire lock for hash of requested
-+ * filename in order to prevent any operations with
-+ * same name in same time -bzzz */
-+
-+ /* calculate name hash */
-+ hash = full_name_hash(name->name, name->len);
-+
-+ /* lock this hash */
-+ return dynlock_lock(&dir->i_dcache_lock, hash, 1, GFP_ATOMIC);
-+}
-+
-+static void unlock_dir(struct inode *dir, void *lock)
-+{
-+ if (!IS_PDIROPS(dir)) {
-+ up(&dir->i_sem);
-+ return;
-+ }
-+ dynlock_unlock(&dir->i_dcache_lock, lock);
-+}
-+
- /* 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..
-@@ -303,10 +333,11 @@
- struct dentry * result;
- struct inode *dir = parent->d_inode;
- int counter = 0;
-+ void *lock;
-
- again:
- counter++;
-- down(&dir->i_sem);
-+ lock = lock_dir(dir, name);
- /*
- * First re-do the cached lookup just in case it was created
- * while we waited for the directory semaphore..
-@@ -329,7 +359,7 @@
- else
- result = dentry;
- }
-- up(&dir->i_sem);
-+ unlock_dir(dir, lock);
- return result;
- }
-
-@@ -337,7 +367,7 @@
- * Uhhuh! Nasty case: the cache was re-populated while
- * we waited on the semaphore. Need to revalidate.
- */
-- up(&dir->i_sem);
-+ unlock_dir(dir, lock);
- if (result->d_op && result->d_op->d_revalidate) {
- if (!result->d_op->d_revalidate(result, flags) && !d_invalidate(result)) {
- dput(result);
-@@ -1180,13 +1210,13 @@
- goto exit;
-
- dir = nd->dentry;
-- down(&dir->d_inode->i_sem);
-+ nd->lock = lock_dir(dir->d_inode, &nd->last);
- dentry = lookup_hash_it(&nd->last, nd->dentry, it);
-
- do_last:
- error = PTR_ERR(dentry);
- if (IS_ERR(dentry)) {
-- up(&dir->d_inode->i_sem);
-+ unlock_dir(dir->d_inode, nd->lock);
- goto exit;
- }
-
-@@ -1195,7 +1225,7 @@
- if (!dentry->d_inode) {
- error = vfs_create_it(dir->d_inode, dentry,
- mode & ~current->fs->umask, it);
-- up(&dir->d_inode->i_sem);
-+ unlock_dir(dir->d_inode, nd->lock);
- dput(nd->dentry);
- nd->dentry = dentry;
- if (error)
-@@ -1209,7 +1239,7 @@
- /*
- * It already exists.
- */
-- up(&dir->d_inode->i_sem);
-+ unlock_dir(dir->d_inode, nd->lock);
-
- error = -EEXIST;
- if (flag & O_EXCL)
-@@ -1362,7 +1392,7 @@
- goto exit;
- }
- dir = nd->dentry;
-- down(&dir->d_inode->i_sem);
-+ nd->lock = lock_dir(dir->d_inode, &nd->last);
- dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- putname(nd->last.name);
- goto do_last;
-@@ -1380,7 +1410,7 @@
- {
- struct dentry *dentry;
-
-- down(&nd->dentry->d_inode->i_sem);
-+ nd->lock = lock_dir(nd->dentry->d_inode, &nd->last);
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-@@ -1469,7 +1499,7 @@
- }
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- out2:
- path_release(&nd);
- out:
-@@ -1532,7 +1562,7 @@
- mode & ~current->fs->umask);
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- out2:
- path_release(&nd);
- out:
-@@ -1642,14 +1672,14 @@
- if (error != -EOPNOTSUPP)
- goto exit1;
- }
-- down(&nd.dentry->d_inode->i_sem);
-+ nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
- dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- exit1:
- path_release(&nd);
- exit:
-@@ -1708,7 +1738,7 @@
- if (error != -EOPNOTSUPP)
- goto exit1;
- }
-- down(&nd.dentry->d_inode->i_sem);
-+ nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
- dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-@@ -1719,7 +1749,7 @@
- exit2:
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- exit1:
- path_release(&nd);
- exit:
-@@ -1789,7 +1819,7 @@
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- out2:
- path_release(&nd);
- out:
-@@ -1881,7 +1911,7 @@
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
- dput(new_dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- out_release:
- path_release(&nd);
- out:
-Index: linux-2.4.20-rh/include/linux/fs.h
-===================================================================
---- linux-2.4.20-rh.orig/include/linux/fs.h 2003-09-04 20:59:14.000000000 +0800
-+++ linux-2.4.20-rh/include/linux/fs.h 2003-09-04 21:03:46.000000000 +0800
-@@ -21,6 +21,7 @@
- #include <linux/cache.h>
- #include <linux/stddef.h>
- #include <linux/string.h>
-+#include <linux/dynlocks.h>
-
- #include <asm/atomic.h>
- #include <asm/bitops.h>
-@@ -136,6 +137,7 @@
- #define S_IMMUTABLE 16 /* Immutable file */
- #define S_DEAD 32 /* removed, but still open directory */
- #define S_NOQUOTA 64 /* Inode is not counted to quota */
-+#define S_PDIROPS 256 /* Parallel directory operations */
-
- /*
- * Note that nosuid etc flags are inode-specific: setting some file-system
-@@ -162,6 +164,7 @@
- #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
- #define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
- #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
-+#define IS_PDIROPS(inode) __IS_FLG(inode, S_PDIROPS)
-
- #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
-
-@@ -489,6 +492,7 @@
- atomic_t i_writecount;
- unsigned int i_attr_flags;
- __u32 i_generation;
-+ struct dynlock i_dcache_lock; /* for parallel directory ops */
- union {
- struct minix_inode_info minix_i;
- struct ext2_inode_info ext2_i;
-@@ -708,6 +712,7 @@
- unsigned int flags;
- int last_type;
- struct lookup_intent *intent;
-+ void *lock;
- };
-
- /*
-@@ -1621,12 +1626,6 @@
- return dget(dentry->d_parent);
- }
-
--static inline void unlock_dir(struct dentry *dir)
--{
-- up(&dir->d_inode->i_sem);
-- dput(dir);
--}
--
- /*
- * Whee.. Deadlock country. Happily there are only two VFS
- * operations that does this..
-Index: linux-2.4.20-rh/fs/inode.c
-===================================================================
---- linux-2.4.20-rh.orig/fs/inode.c 2003-09-04 20:58:35.000000000 +0800
-+++ linux-2.4.20-rh/fs/inode.c 2003-09-04 21:03:46.000000000 +0800
-@@ -121,6 +121,7 @@
- mapping->host = inode;
- mapping->gfp_mask = GFP_HIGHUSER;
- inode->i_mapping = mapping;
-+ dynlock_init(&inode->i_dcache_lock);
- }
- return inode;
- }
+++ /dev/null
- fs/dcache.c | 19 ++
- fs/exec.c | 17 +-
- fs/namei.c | 333 ++++++++++++++++++++++++++++++++++++++--------
- fs/namespace.c | 28 ++-
- fs/open.c | 176 +++++++++++++++++-------
- fs/proc/base.c | 3
- fs/stat.c | 28 ++-
- include/linux/dcache.h | 60 ++++++++
- include/linux/fs.h | 32 ++++
- include/linux/fs_struct.h | 4
- kernel/exit.c | 3
- kernel/fork.c | 3
- kernel/ksyms.c | 1
- 13 files changed, 578 insertions(+), 129 deletions(-)
-
-Index: linux-2.4.20/fs/dcache.c
-===================================================================
---- linux-2.4.20.orig/fs/dcache.c Wed Mar 17 13:57:05 2004
-+++ linux-2.4.20/fs/dcache.c Wed Mar 17 13:57:11 2004
-@@ -186,6 +186,13 @@
- spin_unlock(&dcache_lock);
- return 0;
- }
-+
-+ /* network invalidation by Lustre */
-+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
-+ spin_unlock(&dcache_lock);
-+ return 0;
-+ }
-+
- /*
- * Check whether to do a partial shrink_dcache
- * to get rid of unused child entries.
-@@ -841,13 +848,19 @@
- * Adds a dentry to the hash according to its name.
- */
-
--void d_rehash(struct dentry * entry)
-+void __d_rehash(struct dentry * entry, int lock)
- {
- struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
- if (!list_empty(&entry->d_hash)) BUG();
-- spin_lock(&dcache_lock);
-+ if (lock) spin_lock(&dcache_lock);
- list_add(&entry->d_hash, list);
-- spin_unlock(&dcache_lock);
-+ if (lock) spin_unlock(&dcache_lock);
-+}
-+EXPORT_SYMBOL(__d_rehash);
-+
-+void d_rehash(struct dentry * entry)
-+{
-+ __d_rehash(entry, 1);
- }
-
- #define do_switch(x,y) do { \
-Index: linux-2.4.20/fs/exec.c
-===================================================================
---- linux-2.4.20.orig/fs/exec.c Wed Mar 17 13:57:05 2004
-+++ linux-2.4.20/fs/exec.c Wed Mar 17 13:57:11 2004
-@@ -114,8 +114,10 @@
- struct file * file;
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_OPEN,
-+ .it_flags = FMODE_READ|FMODE_EXEC };
-
-- error = user_path_walk(library, &nd);
-+ error = user_path_walk_it(library, &nd, &it);
- if (error)
- goto out;
-
-@@ -127,7 +129,8 @@
- if (error)
- goto exit;
-
-- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
-+ intent_release(&it);
- error = PTR_ERR(file);
- if (IS_ERR(file))
- goto out;
-@@ -382,8 +385,10 @@
- struct inode *inode;
- struct file *file;
- int err = 0;
-+ struct lookup_intent it = { .it_op = IT_OPEN,
-+ .it_flags = FMODE_READ|FMODE_EXEC };
-
-- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
-+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
- file = ERR_PTR(err);
- if (!err) {
- inode = nd.dentry->d_inode;
-@@ -395,7 +400,8 @@
- err = -EACCES;
- file = ERR_PTR(err);
- if (!err) {
-- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
-+ intent_release(&it);
- if (!IS_ERR(file)) {
- err = deny_write_access(file);
- if (err) {
-@@ -407,6 +413,7 @@
- return file;
- }
- }
-+ intent_release(&it);
- path_release(&nd);
- }
- goto out;
-@@ -1296,7 +1303,7 @@
- goto close_fail;
- if (!file->f_op->write)
- goto close_fail;
-- if (do_truncate(file->f_dentry, 0) != 0)
-+ if (do_truncate(file->f_dentry, 0, 0) != 0)
- goto close_fail;
-
- retval = binfmt->core_dump(signr, regs, file);
-Index: linux-2.4.20/fs/namei.c
-===================================================================
---- linux-2.4.20.orig/fs/namei.c Wed Mar 17 13:57:03 2004
-+++ linux-2.4.20/fs/namei.c Wed Mar 17 13:58:01 2004
-@@ -94,6 +94,13 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct lookup_intent *it)
-+{
-+ if (it && it->it_op_release)
-+ it->it_op_release(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 +267,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_revalidate_it) {
-+ if (!dentry->d_op->d_revalidate_it(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,11 +297,15 @@
- * 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;
-+ int counter = 0;
-
-+again:
-+ counter++;
- down(&dir->i_sem);
- /*
- * First re-do the cached lookup just in case it was created
-@@ -300,6 +320,9 @@
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup_it)
-+ result = dir->i_op->lookup_it(dir, dentry, it, flags);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +344,15 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate_it) {
-+ if (!result->d_op->d_revalidate_it(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ if (counter > 10)
-+ result = ERR_PTR(-ESTALE);
-+ if (!IS_ERR(result))
-+ goto again;
-+ }
- }
- return result;
- }
-@@ -334,7 +366,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 >= max_recursive_link)
-@@ -348,10 +381,18 @@
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-+ nd->intent = it;
- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (!err && it != NULL && !(it->d.lustre.it_int_flags & IT_FL_FOLLOWED)) {
-+ /* vfs_follow_link was never called */
-+ intent_release(it);
-+ path_release(nd);
-+ err = -ENOLINK;
-+ }
- current->link_count--;
- return err;
- loop:
-+ intent_release(it);
- path_release(nd);
- return -ELOOP;
- }
-@@ -381,15 +422,26 @@
- return __follow_up(mnt, dentry);
- }
-
--static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
-+static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry,
-+ struct lookup_intent *it)
- {
- struct vfsmount *mounted;
-
- spin_lock(&dcache_lock);
- mounted = lookup_mnt(*mnt, *dentry);
- if (mounted) {
-+ int opc = 0, mode = 0;
- *mnt = mntget(mounted);
- spin_unlock(&dcache_lock);
-+ if (it) {
-+ opc = it->it_op;
-+ mode = it->it_create_mode;
-+ }
-+ intent_release(it);
-+ if (it) {
-+ it->it_op = opc;
-+ it->it_create_mode = mode;
-+ }
- dput(*dentry);
- mntput(mounted->mnt_parent);
- *dentry = dget(mounted->mnt_root);
-@@ -401,7 +453,7 @@
-
- int follow_down(struct vfsmount **mnt, struct dentry **dentry)
- {
-- return __follow_down(mnt,dentry);
-+ return __follow_down(mnt, dentry, NULL);
- }
-
- static inline void follow_dotdot(struct nameidata *nd)
-@@ -437,7 +489,7 @@
- mntput(nd->mnt);
- nd->mnt = parent;
- }
-- while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry))
-+ while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry, NULL))
- ;
- }
-
-@@ -449,7 +501,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;
-@@ -526,18 +579,18 @@
- 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) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- 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;
- }
- /* Check mountpoints.. */
-- while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
-+ while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, NULL))
- ;
-
- err = -ENOENT;
-@@ -549,7 +601,7 @@
- goto out_dput;
-
- if (inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ err = do_follow_link(dentry, nd, NULL);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -565,7 +617,7 @@
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup_it)
- break;
- continue;
- /* here ends the main loop */
-@@ -592,22 +644,22 @@
- 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;
- }
-- while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
-+ while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, it))
- ;
- inode = dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
- && inode && inode->i_op && inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -621,7 +673,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->lookup_it))
- break;
- }
- goto return_base;
-@@ -645,6 +698,34 @@
- * Check the cached dentry for staleness.
- */
- dentry = nd->dentry;
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ err = -ESTALE;
-+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) {
-+ struct dentry *new;
-+ err = permission(dentry->d_parent->d_inode,
-+ MAY_EXEC);
-+ if (err)
-+ break;
-+ new = real_lookup(dentry->d_parent,
-+ &dentry->d_name, 0, it);
-+ if (IS_ERR(new)) {
-+ err = PTR_ERR(new);
-+ break;
-+ }
-+ d_invalidate(dentry);
-+ dput(dentry);
-+ nd->dentry = new;
-+ }
-+ if (!nd->dentry->d_inode)
-+ goto no_inode;
-+ if (lookup_flags & LOOKUP_DIRECTORY) {
-+ err = -ENOTDIR;
-+ if (!nd->dentry->d_inode->i_op ||
-+ (!nd->dentry->d_inode->i_op->lookup &&
-+ !nd->dentry->d_inode->i_op->lookup_it))
-+ break;
-+ }
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- err = -ESTALE;
- if (!dentry->d_op->d_revalidate(dentry, 0)) {
-@@ -658,15 +732,28 @@
- dput(dentry);
- break;
- }
-+ if (err)
-+ intent_release(it);
- path_release(nd);
- return_err:
- 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 */
-@@ -751,6 +838,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;
-@@ -765,6 +863,7 @@
- {
- nd->last_type = LAST_ROOT; /* if there are only slashes... */
- nd->flags = flags;
-+ nd->intent = NULL;
- if (*name=='/')
- return walk_init_root(name,nd);
- read_lock(¤t->fs->lock);
-@@ -779,7 +878,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;
-@@ -802,13 +902,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->lookup_it)
-+ dentry = inode->i_op->lookup_it(inode, new, it, 0);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -820,6 +923,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)
- {
-@@ -841,7 +950,7 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash_it(&this, base, NULL);
- access:
- return ERR_PTR(-EACCES);
- }
-@@ -872,6 +981,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.
-@@ -969,7 +1095,8 @@
- return retval;
- }
-
--int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
-+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -982,12 +1109,15 @@
- goto exit_lock;
-
- error = -EACCES; /* shouldn't it be ENOSYS? */
-- if (!dir->i_op || !dir->i_op->create)
-+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it))
- goto exit_lock;
-
- DQUOT_INIT(dir);
- lock_kernel();
-- error = dir->i_op->create(dir, dentry, mode);
-+ if (dir->i_op->create_it)
-+ error = dir->i_op->create_it(dir, dentry, mode, it);
-+ else
-+ error = dir->i_op->create(dir, dentry, mode);
- unlock_kernel();
- exit_lock:
- up(&dir->i_zombie);
-@@ -996,6 +1126,11 @@
- return error;
- }
-
-+int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
-+{
-+ return vfs_create_it(dir, dentry, mode, NULL);
-+}
-+
- /*
- * open_namei()
- *
-@@ -1010,7 +1145,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;
-@@ -1020,11 +1156,14 @@
-
- acc_mode = ACC_MODE(flag);
-
-+ if (it)
-+ it->it_flags = flag;
-+
- /*
- * 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;
-@@ -1034,6 +1173,10 @@
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_create_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1049,7 +1192,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);
-@@ -1058,10 +1201,11 @@
- goto exit;
- }
-
-+ it->it_create_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
-- error = vfs_create(dir->d_inode, dentry,
-- mode & ~current->fs->umask);
-+ error = vfs_create_it(dir->d_inode, dentry,
-+ mode & ~current->fs->umask, it);
- up(&dir->d_inode->i_sem);
- dput(nd->dentry);
- nd->dentry = dentry;
-@@ -1086,7 +1230,7 @@
- error = -ELOOP;
- if (flag & O_NOFOLLOW)
- goto exit_dput;
-- while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));
-+ while (__follow_down(&nd->mnt,&dentry,it) && d_mountpoint(dentry));
- }
- error = -ENOENT;
- if (!dentry->d_inode)
-@@ -1165,7 +1309,7 @@
- if (!error) {
- DQUOT_INIT(inode);
-
-- error = do_truncate(dentry, 0);
-+ error = do_truncate(dentry, 0, 1);
- }
- put_write_access(inode);
- if (error)
-@@ -1177,8 +1321,10 @@
- return 0;
-
- exit_dput:
-+ intent_release(it);
- dput(dentry);
- exit:
-+ intent_release(it);
- path_release(nd);
- return error;
-
-@@ -1197,7 +1343,16 @@
- * are done. Procfs-like symlinks just set LAST_BIND.
- */
- UPDATE_ATIME(dentry->d_inode);
-+ nd->intent = it;
- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error) {
-+ intent_release(it);
-+ } else if (it != NULL && !(it->d.lustre.it_int_flags & IT_FL_FOLLOWED)) {
-+ /* vfs_follow_link was never called */
-+ intent_release(it);
-+ path_release(nd);
-+ error = -ENOLINK;
-+ }
- dput(dentry);
- if (error)
- return error;
-@@ -1219,13 +1374,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;
-
-@@ -1233,7 +1395,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)
-@@ -1289,7 +1451,20 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->mknod_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mknod_raw(&nd, mode, dev);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+
-+ dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(dentry);
-
- mode &= ~current->fs->umask;
-@@ -1310,6 +1485,7 @@
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+out2:
- path_release(&nd);
- out:
- putname(tmp);
-@@ -1357,7 +1533,18 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->mkdir_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mkdir_raw(&nd, mode);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+ dentry = lookup_create(&nd, 1, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
-@@ -1365,6 +1552,7 @@
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+out2:
- path_release(&nd);
- out:
- putname(tmp);
-@@ -1465,8 +1653,16 @@
- error = -EBUSY;
- goto exit1;
- }
-+ if (nd.dentry->d_inode->i_op->rmdir_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ error = op->rmdir_raw(&nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit1;
-+ }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1524,8 +1720,15 @@
- error = -EISDIR;
- if (nd.last_type != LAST_NORM)
- goto exit1;
-+ if (nd.dentry->d_inode->i_op->unlink_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->unlink_raw(&nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit1;
-+ }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1592,15 +1795,27 @@
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->symlink_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->symlink_raw(&nd, from);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+ dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+ out2:
- path_release(&nd);
--out:
-+ out:
- putname(to);
- }
- putname(from);
-@@ -1676,7 +1891,18 @@
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out_release;
-+ }
-+ if (nd.dentry->d_inode->i_op->link_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->link_raw(&old_nd, &nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out_release;
-+ }
-+ new_dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1720,7 +1946,7 @@
- * 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)
- {
- int error;
- struct inode *target;
-@@ -1799,7 +2025,7 @@
- }
-
- 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)
- {
- int error;
-
-@@ -1887,9 +2113,18 @@
- if (newnd.last_type != LAST_NORM)
- goto exit2;
-
-+ if (old_dir->d_inode->i_op->rename_raw) {
-+ lock_kernel();
-+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd);
-+ unlock_kernel();
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit2;
-+ }
-+
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1905,16 +2140,16 @@
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL);
- 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);
- unlock_kernel();
--
- dput(new_dentry);
- exit4:
- dput(old_dentry);
-@@ -1965,20 +2200,28 @@
- }
-
- 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;
- if (IS_ERR(link))
- goto fail;
-
-+ if (it == NULL)
-+ it = nd->intent;
-+ else if (it != nd->intent)
-+ printk("it != nd->intent: tell phil@clusterfs.com\n");
-+ if (it != NULL)
-+ it->d.lustre.it_int_flags |= IT_FL_FOLLOWED;
-+
- if (*link == '/') {
- path_release(nd);
- if (!walk_init_root(link, nd))
- /* 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;
-@@ -2002,7 +2245,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 */
-@@ -2044,7 +2293,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);
-Index: linux-2.4.20/fs/namespace.c
-===================================================================
---- linux-2.4.20.orig/fs/namespace.c Wed Mar 17 13:57:05 2004
-+++ linux-2.4.20/fs/namespace.c Wed Mar 17 13:57:11 2004
-@@ -99,6 +99,7 @@
- {
- old_nd->dentry = mnt->mnt_mountpoint;
- old_nd->mnt = mnt->mnt_parent;
-+ UNPIN(old_nd->dentry, old_nd->mnt, 1);
- mnt->mnt_parent = mnt;
- mnt->mnt_mountpoint = mnt->mnt_root;
- list_del_init(&mnt->mnt_child);
-@@ -110,6 +111,7 @@
- {
- mnt->mnt_parent = mntget(nd->mnt);
- mnt->mnt_mountpoint = dget(nd->dentry);
-+ PIN(nd->dentry, nd->mnt, 1);
- list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
- list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
- nd->dentry->d_mounted++;
-@@ -485,14 +487,17 @@
- {
- struct nameidata old_nd;
- struct vfsmount *mnt = NULL;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int err = mount_is_safe(nd);
- if (err)
- return err;
- if (!old_name || !*old_name)
- return -EINVAL;
-- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd);
-- if (err)
-+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it);
-+ if (err) {
-+ intent_release(&it);
- return err;
-+ }
-
- down_write(¤t->namespace->sem);
- err = -EINVAL;
-@@ -515,6 +520,7 @@
- }
-
- up_write(¤t->namespace->sem);
-+ intent_release(&it);
- path_release(&old_nd);
- return err;
- }
-@@ -698,6 +704,7 @@
- unsigned long flags, void *data_page)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int retval = 0;
- int mnt_flags = 0;
-
-@@ -722,10 +729,11 @@
- flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
-
- /* ... and get the mountpoint */
-- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
-- if (retval)
-+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
-+ if (retval) {
-+ intent_release(&it);
- return retval;
--
-+ }
- if (flags & MS_REMOUNT)
- retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
- data_page);
-@@ -736,6 +744,8 @@
- else
- retval = do_add_mount(&nd, type_page, flags, mnt_flags,
- dev_name, data_page);
-+
-+ intent_release(&it);
- path_release(&nd);
- return retval;
- }
-@@ -901,6 +911,8 @@
- {
- struct vfsmount *tmp;
- struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
-+ struct lookup_intent new_it = { .it_op = IT_GETATTR };
-+ struct lookup_intent old_it = { .it_op = IT_GETATTR };
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
-@@ -908,14 +920,14 @@
-
- lock_kernel();
-
-- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd);
-+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it);
- if (error)
- goto out0;
- error = -EINVAL;
- if (!check_mnt(new_nd.mnt))
- goto out1;
-
-- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd);
-+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it);
- if (error)
- goto out1;
-
-@@ -970,8 +982,10 @@
- up(&old_nd.dentry->d_inode->i_zombie);
- up_write(¤t->namespace->sem);
- path_release(&user_nd);
-+ intent_release(&old_it);
- path_release(&old_nd);
- out1:
-+ intent_release(&new_it);
- path_release(&new_nd);
- out0:
- unlock_kernel();
-Index: linux-2.4.20/fs/open.c
-===================================================================
---- linux-2.4.20.orig/fs/open.c Wed Mar 17 13:57:03 2004
-+++ linux-2.4.20/fs/open.c Wed Mar 17 13:57:11 2004
-@@ -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);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -95,9 +97,10 @@
- write_unlock(&files->file_lock);
- }
-
--int do_truncate(struct dentry *dentry, loff_t length)
-+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open)
- {
- struct inode *inode = dentry->d_inode;
-+ struct inode_operations *op = dentry->d_inode->i_op;
- int error;
- struct iattr newattrs;
-
-@@ -108,7 +111,13 @@
- down(&inode->i_sem);
- newattrs.ia_size = length;
- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-- error = notify_change(dentry, &newattrs);
-+ if (called_from_open)
-+ newattrs.ia_valid |= ATTR_FROM_OPEN;
-+ if (op->setattr_raw) {
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ } else
-+ error = notify_change(dentry, &newattrs);
- up(&inode->i_sem);
- return error;
- }
-@@ -118,12 +127,13 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- 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;
-@@ -163,11 +173,13 @@
- error = locks_verify_truncate(inode, NULL, length);
- if (!error) {
- DQUOT_INIT(inode);
-- error = do_truncate(nd.dentry, length);
-+ intent_release(&it);
-+ error = do_truncate(nd.dentry, length, 0);
- }
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
-@@ -215,7 +227,7 @@
-
- error = locks_verify_truncate(inode, file, length);
- if (!error)
-- error = do_truncate(dentry, length);
-+ error = do_truncate(dentry, length, 0);
- out_putf:
- fput(file);
- out:
-@@ -260,11 +272,13 @@
- struct inode * inode;
- struct iattr newattrs;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, NULL);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ /* this is safe without a Lustre lock because it only depends
-+ on the super block */
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -279,11 +293,25 @@
- goto dput_and_out;
-
- newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
-- } else {
-+ }
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto dput_and_out;
-+ }
-+
-+ error = -EPERM;
-+ if (!times) {
- if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
- goto dput_and_out;
- }
-+
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
- path_release(&nd);
-@@ -304,12 +332,14 @@
- struct inode * inode;
- struct iattr newattrs;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, NULL);
-
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ /* this is safe without a Lustre lock because it only depends
-+ on the super block */
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -324,7 +354,20 @@
- newattrs.ia_atime = times[0].tv_sec;
- newattrs.ia_mtime = times[1].tv_sec;
- newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
-- } else {
-+ }
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto dput_and_out;
-+ }
-+
-+ error = -EPERM;
-+ if (!utimes) {
- if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
- goto dput_and_out;
-@@ -347,6 +390,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;
-@@ -364,13 +408,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(&it);
- path_release(&nd);
- }
-
-@@ -385,8 +430,9 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
-+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it);
- if (error)
- goto out;
-
-@@ -397,6 +443,7 @@
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
-@@ -436,9 +483,10 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = 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;
-
-@@ -454,39 +502,56 @@
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
- }
-
--asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
-+int chmod_common(struct dentry *dentry, mode_t mode)
- {
-- struct inode * inode;
-- struct dentry * dentry;
-- struct file * file;
-- int err = -EBADF;
-+ struct inode *inode = dentry->d_inode;
- struct iattr newattrs;
-+ int err = -EROFS;
-
-- file = fget(fd);
-- if (!file)
-+ if (IS_RDONLY(inode))
- goto out;
-
-- dentry = file->f_dentry;
-- inode = dentry->d_inode;
-+ if (inode->i_op->setattr_raw) {
-+ newattrs.ia_mode = mode;
-+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-+ newattrs.ia_valid |= ATTR_RAW;
-+ err = inode->i_op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (err != -EOPNOTSUPP)
-+ goto out;
-+ }
-
-- err = -EROFS;
-- if (IS_RDONLY(inode))
-- goto out_putf;
- err = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-- goto out_putf;
-+ goto out;
-+
- if (mode == (mode_t) -1)
- mode = inode->i_mode;
- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- err = notify_change(dentry, &newattrs);
-
--out_putf:
-+out:
-+ return err;
-+}
-+
-+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
-+{
-+ struct file * file;
-+ int err = -EBADF;
-+
-+ file = fget(fd);
-+ if (!file)
-+ goto out;
-+
-+ err = chmod_common(file->f_dentry, mode);
-+
- fput(file);
- out:
- return err;
-@@ -495,30 +560,14 @@
- asmlinkage long sys_chmod(const char * filename, mode_t mode)
- {
- struct nameidata nd;
-- struct inode * inode;
- int error;
-- struct iattr newattrs;
-
- error = user_path_walk(filename, &nd);
- if (error)
- goto out;
-- inode = nd.dentry->d_inode;
--
-- error = -EROFS;
-- if (IS_RDONLY(inode))
-- goto dput_and_out;
--
-- error = -EPERM;
-- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-- goto dput_and_out;
-
-- if (mode == (mode_t) -1)
-- mode = inode->i_mode;
-- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-- error = notify_change(nd.dentry, &newattrs);
-+ error = chmod_common(nd.dentry, mode);
-
--dput_and_out:
- path_release(&nd);
- out:
- return error;
-@@ -538,6 +587,20 @@
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto out;
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = dentry->d_inode->i_op;
-+
-+ newattrs.ia_uid = user;
-+ newattrs.ia_gid = group;
-+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ return error;
-+ }
-+
- error = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- goto out;
-@@ -642,8 +705,9 @@
- {
- int namei_flags, error;
- struct nameidata nd;
--
-- flags &= ~O_DIRECT;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-+
-+ //flags &= ~O_DIRECT;
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -651,14 +715,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;
-@@ -695,12 +760,15 @@
- }
-
- if (f->f_op && f->f_op->open) {
-+ f->f_it = it;
- error = f->f_op->open(inode,f);
-+ f->f_it = NULL;
- if (error)
- goto cleanup_all;
- }
- f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-
-+ intent_release(it);
- return f;
-
- cleanup_all:
-@@ -715,11 +783,17 @@
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(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.
- */
-Index: linux-2.4.20/fs/proc/base.c
-===================================================================
---- linux-2.4.20.orig/fs/proc/base.c Wed Mar 17 13:57:05 2004
-+++ linux-2.4.20/fs/proc/base.c Wed Mar 17 13:57:11 2004
-@@ -494,6 +494,9 @@
-
- error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
- nd->last_type = LAST_BIND;
-+
-+ if (nd->intent != NULL)
-+ nd->intent->d.lustre.it_int_flags |= IT_FL_FOLLOWED;
- out:
- return error;
- }
-Index: linux-2.4.20/fs/stat.c
-===================================================================
---- linux-2.4.20.orig/fs/stat.c Wed Mar 17 13:57:05 2004
-+++ linux-2.4.20/fs/stat.c Wed Mar 17 13:58:01 2004
-@@ -17,10 +17,12 @@
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
- static __inline__ int
--do_revalidate(struct dentry *dentry)
-+do_revalidate(struct dentry *dentry, struct lookup_intent *it)
- {
- struct inode * inode = dentry->d_inode;
-- if (inode->i_op && inode->i_op->revalidate)
-+ if (inode->i_op && inode->i_op->revalidate_it)
-+ return inode->i_op->revalidate_it(dentry, it);
-+ else if (inode->i_op && inode->i_op->revalidate)
- return inode->i_op->revalidate(dentry);
- return 0;
- }
-@@ -32,13 +34,13 @@
- return inode->i_nlink;
- }
-
--static int do_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-+static int do_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat, struct lookup_intent *it)
- {
- int res = 0;
- unsigned int blocks, indirect;
- struct inode *inode = dentry->d_inode;
-
-- res = do_revalidate(dentry);
-+ res = do_revalidate(dentry, it);
- if (res)
- return res;
-
-@@ -111,10 +113,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = 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);
-+ error = do_getattr(nd.mnt, nd.dentry, stat, &it);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -124,10 +128,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = 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);
-+ error = do_getattr(nd.mnt, nd.dentry, stat, &it);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -139,7 +145,7 @@
- int error = -EBADF;
-
- if (f) {
-- error = do_getattr(f->f_vfsmnt, f->f_dentry, stat);
-+ error = do_getattr(f->f_vfsmnt, f->f_dentry, stat, NULL);
- fput(f);
- }
- return error;
-@@ -286,7 +292,7 @@
-
- error = -EINVAL;
- if (inode->i_op && inode->i_op->readlink &&
-- !(error = do_revalidate(nd.dentry))) {
-+ !(error = do_revalidate(nd.dentry, NULL))) {
- UPDATE_ATIME(inode);
- error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
- }
-Index: linux-2.4.20/include/linux/dcache.h
-===================================================================
---- linux-2.4.20.orig/include/linux/dcache.h Wed Mar 17 13:57:04 2004
-+++ linux-2.4.20/include/linux/dcache.h Wed Mar 17 13:57:11 2004
-@@ -6,6 +6,51 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
- #include <linux/kernel.h>
-+#include <linux/string.h>
-+
-+#define IT_OPEN 0x0001
-+#define IT_CREAT 0x0002
-+#define IT_READDIR 0x0004
-+#define IT_GETATTR 0x0008
-+#define IT_LOOKUP 0x0010
-+#define IT_UNLINK 0x0020
-+#define IT_GETXATTR 0x0040
-+#define IT_EXEC 0x0080
-+#define IT_PIN 0x0100
-+
-+#define IT_FL_LOCKED 0x0001
-+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */
-+
-+#define INTENT_MAGIC 0x19620323
-+
-+
-+struct lustre_intent_data {
-+ int it_disposition;
-+ int it_status;
-+ __u64 it_lock_handle;
-+ void *it_data;
-+ int it_lock_mode;
-+ int it_int_flags;
-+};
-+struct lookup_intent {
-+ int it_magic;
-+ void (*it_op_release)(struct lookup_intent *);
-+ int it_op;
-+ int it_flags;
-+ int it_create_mode;
-+ union {
-+ struct lustre_intent_data lustre;
-+ } d;
-+};
-+
-+static inline void intent_init(struct lookup_intent *it, int op, int flags)
-+{
-+ memset(it, 0, sizeof(*it));
-+ it->it_magic = INTENT_MAGIC;
-+ it->it_op = op;
-+ it->it_flags = flags;
-+}
-+
-
- /*
- * linux/include/linux/dcache.h
-@@ -96,8 +141,22 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_pin)(struct dentry *, struct vfsmount * , int);
-+ void (*d_unpin)(struct dentry *, struct vfsmount *, int);
- };
-
-+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \
-+ de->d_op->d_pin(de, mnt, flag);
-+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \
-+ de->d_op->d_unpin(de, mnt, flag);
-+
-+
-+/* defined in fs/namei.c */
-+extern void intent_release(struct lookup_intent *it);
-+/* defined in fs/dcache.c */
-+extern void __d_rehash(struct dentry * entry, int lock);
-+
- /* the dentry parameter passed to d_hash and d_compare is the parent
- * directory of the entries to be compared. It is used in case these
- * functions need any directory specific information for determining
-@@ -129,6 +188,7 @@
- * s_nfsd_free_path semaphore will be down
- */
- #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
-+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */
-
- extern spinlock_t dcache_lock;
-
-Index: linux-2.4.20/include/linux/fs.h
-===================================================================
---- linux-2.4.20.orig/include/linux/fs.h Wed Mar 17 13:57:11 2004
-+++ linux-2.4.20/include/linux/fs.h Wed Mar 17 13:57:11 2004
-@@ -73,6 +73,7 @@
-
- #define FMODE_READ 1
- #define FMODE_WRITE 2
-+#define FMODE_EXEC 4
-
- #define READ 0
- #define WRITE 1
-@@ -338,6 +339,9 @@
- #define ATTR_MTIME_SET 256
- #define ATTR_FORCE 512 /* Not a change, but a change it */
- #define ATTR_ATTR_FLAG 1024
-+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */
-+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */
-+#define ATTR_CTIME_SET 0x2000
-
- /*
- * This is the Inode Attributes structure, used for notify_change(). It
-@@ -473,6 +477,7 @@
- struct pipe_inode_info *i_pipe;
- struct block_device *i_bdev;
- struct char_device *i_cdev;
-+ void *i_filterdata;
-
- unsigned long i_dnotify_mask; /* Directory notify events */
- struct dnotify_struct *i_dnotify; /* for directory notifications */
-@@ -575,6 +580,7 @@
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_it;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -702,6 +708,7 @@
- struct qstr last;
- unsigned int flags;
- int last_type;
-+ struct lookup_intent *intent;
- };
-
- /*
-@@ -822,7 +829,8 @@
- 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);
-
- /*
- * File types
-@@ -882,21 +890,32 @@
-
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
-+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
-+ int (*link_raw) (struct nameidata *,struct nameidata *);
- int (*unlink) (struct inode *,struct dentry *);
-+ int (*unlink_raw) (struct nameidata *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-+ int (*symlink_raw) (struct nameidata *,const char *);
- int (*mkdir) (struct inode *,struct dentry *,int);
-+ int (*mkdir_raw) (struct nameidata *,int);
- int (*rmdir) (struct inode *,struct dentry *);
-+ int (*rmdir_raw) (struct nameidata *);
- int (*mknod) (struct inode *,struct dentry *,int,int);
-+ int (*mknod_raw) (struct nameidata *,int,dev_t);
- int (*rename) (struct inode *, struct dentry *,
- struct inode *, struct dentry *);
-+ int (*rename_raw) (struct nameidata *, struct nameidata *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*revalidate) (struct dentry *);
-+ int (*revalidate_it) (struct dentry *, struct lookup_intent *);
- int (*setattr) (struct dentry *, struct iattr *);
-+ int (*setattr_raw) (struct inode *, struct iattr *);
- int (*getattr) (struct dentry *, struct iattr *);
- int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-@@ -1092,10 +1111,14 @@
-
- asmlinkage long sys_open(const char *, int, int);
- asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */
--extern int do_truncate(struct dentry *, loff_t start);
-+extern int do_truncate(struct dentry *, loff_t start, int called_from_open);
-
- extern struct file *filp_open(const char *, int, int);
- extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
- extern int filp_close(struct file *, fl_owner_t id);
- extern char * getname(const char *);
-
-@@ -1386,6 +1409,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 *));
-@@ -1397,6 +1421,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 inode_init_once(struct inode *);
- extern void iput(struct inode *);
-@@ -1504,6 +1530,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;
-Index: linux-2.4.20/include/linux/fs_struct.h
-===================================================================
---- linux-2.4.20.orig/include/linux/fs_struct.h Wed Mar 17 13:57:02 2004
-+++ linux-2.4.20/include/linux/fs_struct.h Wed Mar 17 13:57:11 2004
-@@ -37,10 +37,12 @@
- write_lock(&fs->lock);
- old_root = fs->root;
- old_rootmnt = fs->rootmnt;
-+ PIN(dentry, mnt, 1);
- fs->rootmnt = mntget(mnt);
- fs->root = dget(dentry);
- write_unlock(&fs->lock);
- if (old_root) {
-+ UNPIN(old_root, old_rootmnt, 1);
- dput(old_root);
- mntput(old_rootmnt);
- }
-@@ -60,10 +62,12 @@
- write_lock(&fs->lock);
- old_pwd = fs->pwd;
- old_pwdmnt = fs->pwdmnt;
-+ PIN(dentry, mnt, 0);
- fs->pwdmnt = mntget(mnt);
- fs->pwd = dget(dentry);
- write_unlock(&fs->lock);
- if (old_pwd) {
-+ UNPIN(old_pwd, old_pwdmnt, 0);
- dput(old_pwd);
- mntput(old_pwdmnt);
- }
-Index: linux-2.4.20/kernel/ksyms.c
-===================================================================
---- linux-2.4.20.orig/kernel/ksyms.c Wed Mar 17 13:57:11 2004
-+++ linux-2.4.20/kernel/ksyms.c Wed Mar 17 13:57:11 2004
-@@ -297,6 +297,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);
-Index: linux-2.4.20/kernel/fork.c
-===================================================================
---- linux-2.4.20.orig/kernel/fork.c Wed Mar 17 13:57:05 2004
-+++ linux-2.4.20/kernel/fork.c Wed Mar 17 13:57:11 2004
-@@ -440,10 +440,13 @@
- fs->umask = old->umask;
- read_lock(&old->lock);
- fs->rootmnt = mntget(old->rootmnt);
-+ PIN(old->pwd, old->pwdmnt, 0);
-+ PIN(old->root, old->rootmnt, 1);
- fs->root = dget(old->root);
- fs->pwdmnt = mntget(old->pwdmnt);
- fs->pwd = dget(old->pwd);
- if (old->altroot) {
-+ PIN(old->altroot, old->altrootmnt, 1);
- fs->altrootmnt = mntget(old->altrootmnt);
- fs->altroot = dget(old->altroot);
- } else {
-Index: linux-2.4.20/kernel/exit.c
-===================================================================
---- linux-2.4.20.orig/kernel/exit.c Wed Mar 17 13:57:05 2004
-+++ linux-2.4.20/kernel/exit.c Wed Mar 17 13:57:11 2004
-@@ -345,11 +345,14 @@
- {
- /* No need to hold fs->lock if we are killing it */
- if (atomic_dec_and_test(&fs->count)) {
-+ UNPIN(fs->pwd, fs->pwdmnt, 0);
-+ UNPIN(fs->root, fs->rootmnt, 1);
- dput(fs->root);
- mntput(fs->rootmnt);
- dput(fs->pwd);
- mntput(fs->pwdmnt);
- if (fs->altroot) {
-+ UNPIN(fs->altroot, fs->altrootmnt, 1);
- dput(fs->altroot);
- mntput(fs->altrootmnt);
- }
+++ /dev/null
- fs/dcache.c | 19 ++
- fs/exec.c | 17 +-
- fs/namei.c | 295 +++++++++++++++++++++++++++++++++++++++-------
- fs/namespace.c | 28 +++-
- fs/open.c | 172 +++++++++++++++++++-------
- fs/stat.c | 52 +++++---
- include/linux/dcache.h | 60 +++++++++
- include/linux/fs.h | 32 ++++
- include/linux/fs_struct.h | 4
- kernel/exit.c | 3
- kernel/fork.c | 3
- kernel/ksyms.c | 1
- 12 files changed, 558 insertions(+), 128 deletions(-)
-
-Index: linux-ia64/fs/dcache.c
-===================================================================
---- linux-ia64.orig/fs/dcache.c 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/fs/dcache.c 2004-03-17 16:05:28.000000000 -0800
-@@ -186,6 +186,13 @@ int d_invalidate(struct dentry * dentry)
- spin_unlock(&dcache_lock);
- return 0;
- }
-+
-+ /* network invalidation by Lustre */
-+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
-+ spin_unlock(&dcache_lock);
-+ return 0;
-+ }
-+
- /*
- * Check whether to do a partial shrink_dcache
- * to get rid of unused child entries.
-@@ -850,13 +857,19 @@ void d_delete(struct dentry * dentry)
- * Adds a dentry to the hash according to its name.
- */
-
--void d_rehash(struct dentry * entry)
-+void __d_rehash(struct dentry * entry, int lock)
- {
- struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
- if (!list_empty(&entry->d_hash)) BUG();
-- spin_lock(&dcache_lock);
-+ if (lock) spin_lock(&dcache_lock);
- list_add(&entry->d_hash, list);
-- spin_unlock(&dcache_lock);
-+ if (lock) spin_unlock(&dcache_lock);
-+}
-+EXPORT_SYMBOL(__d_rehash);
-+
-+void d_rehash(struct dentry * entry)
-+{
-+ __d_rehash(entry, 1);
- }
-
- #define do_switch(x,y) do { \
-Index: linux-ia64/fs/exec.c
-===================================================================
---- linux-ia64.orig/fs/exec.c 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/fs/exec.c 2004-03-17 16:05:28.000000000 -0800
-@@ -119,8 +119,10 @@ asmlinkage long sys_uselib(const char *
- struct file * file;
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_OPEN,
-+ .it_flags = FMODE_READ|FMODE_EXEC };
-
-- error = user_path_walk(library, &nd);
-+ error = user_path_walk_it(library, &nd, &it);
- if (error)
- goto out;
-
-@@ -132,7 +134,8 @@ asmlinkage long sys_uselib(const char *
- if (error)
- goto exit;
-
-- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
-+ intent_release(&it);
- error = PTR_ERR(file);
- if (IS_ERR(file))
- goto out;
-@@ -400,8 +403,10 @@ struct file *open_exec(const char *name)
- struct inode *inode;
- struct file *file;
- int err = 0;
-+ struct lookup_intent it = { .it_op = IT_OPEN,
-+ .it_flags = FMODE_READ|FMODE_EXEC };
-
-- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
-+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
- file = ERR_PTR(err);
- if (!err) {
- inode = nd.dentry->d_inode;
-@@ -413,7 +418,8 @@ struct file *open_exec(const char *name)
- err = -EACCES;
- file = ERR_PTR(err);
- if (!err) {
-- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
-+ intent_release(&it);
- if (!IS_ERR(file)) {
- err = deny_write_access(file);
- if (err) {
-@@ -425,6 +431,7 @@ out:
- return file;
- }
- }
-+ intent_release(&it);
- path_release(&nd);
- }
- goto out;
-@@ -1348,7 +1355,7 @@ int do_coredump(long signr, int exit_cod
- goto close_fail;
- if (!file->f_op->write)
- goto close_fail;
-- if (do_truncate(file->f_dentry, 0) != 0)
-+ if (do_truncate(file->f_dentry, 0, 0) != 0)
- goto close_fail;
-
- retval = binfmt->core_dump(signr, regs, file);
-Index: linux-ia64/fs/namei.c
-===================================================================
---- linux-ia64.orig/fs/namei.c 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/fs/namei.c 2004-03-17 16:06:13.000000000 -0800
-@@ -94,6 +94,13 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct lookup_intent *it)
-+{
-+ if (it && it->it_op_release)
-+ it->it_op_release(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 +267,19 @@ void path_release(struct nameidata *nd)
- * 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_revalidate_it) {
-+ if (!dentry->d_op->d_revalidate_it(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,11 +297,15 @@ static struct dentry * cached_lookup(str
- * 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;
-+ int counter = 0;
-
-+again:
-+ counter++;
- down(&dir->i_sem);
- /*
- * First re-do the cached lookup just in case it was created
-@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup_it)
-+ result = dir->i_op->lookup_it(dir, dentry, it, flags);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate_it) {
-+ if (!result->d_op->d_revalidate_it(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ if (counter > 10)
-+ result = ERR_PTR(-ESTALE);
-+ if (!IS_ERR(result))
-+ goto again;
-+ }
- }
- return result;
- }
-@@ -332,7 +364,8 @@ static struct dentry * real_lookup(struc
- * 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 >= 8)
-@@ -346,10 +379,12 @@ static inline int do_follow_link(struct
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-+ nd->intent = it;
- err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-+ intent_release(it);
- path_release(nd);
- return -ELOOP;
- }
-@@ -447,7 +482,8 @@ static inline void follow_dotdot(struct
- *
- * 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 +560,12 @@ int link_path_walk(const char * name, st
- 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) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- 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;
-@@ -547,7 +583,7 @@ int link_path_walk(const char * name, st
- goto out_dput;
-
- if (inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ err = do_follow_link(dentry, nd, NULL);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -563,7 +599,7 @@ int link_path_walk(const char * name, st
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup_it)
- break;
- continue;
- /* here ends the main loop */
-@@ -590,12 +626,12 @@ last_component:
- 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;
-@@ -605,7 +641,7 @@ last_component:
- inode = dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
- && inode && inode->i_op && inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -619,7 +655,8 @@ last_component:
- 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->lookup_it))
- break;
- }
- goto return_base;
-@@ -637,12 +672,42 @@ return_reval:
- nd->last_type = LAST_DOT;
- else if (this.len == 2 && this.name[1] == '.')
- nd->last_type = LAST_DOTDOT;
-+ else
-+ goto return_base;
- return_reval:
- /*
- * We bypassed the ordinary revalidation routines.
- * Check the cached dentry for staleness.
- */
- dentry = nd->dentry;
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ err = -ESTALE;
-+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) {
-+ struct dentry *new;
-+ err = permission(dentry->d_parent->d_inode,
-+ MAY_EXEC);
-+ if (err)
-+ break;
-+ new = real_lookup(dentry->d_parent,
-+ &dentry->d_name, 0, it);
-+ if (IS_ERR(new)) {
-+ err = PTR_ERR(new);
-+ break;
-+ }
-+ d_invalidate(dentry);
-+ dput(dentry);
-+ nd->dentry = new;
-+ }
-+ if (!nd->dentry->d_inode)
-+ goto no_inode;
-+ if (lookup_flags & LOOKUP_DIRECTORY) {
-+ err = -ENOTDIR;
-+ if (!nd->dentry->d_inode->i_op ||
-+ (!nd->dentry->d_inode->i_op->lookup &&
-+ !nd->dentry->d_inode->i_op->lookup_it))
-+ break;
-+ }
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- err = -ESTALE;
- if (!dentry->d_op->d_revalidate(dentry, 0)) {
-@@ -656,15 +714,28 @@ out_dput:
- dput(dentry);
- break;
- }
-+ if (err)
-+ intent_release(it);
- path_release(nd);
- return_err:
- 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 */
-@@ -749,6 +820,17 @@ walk_init_root(const char *name, struct
- }
-
- /* 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;
-@@ -763,6 +845,7 @@ int path_init(const char *name, unsigned
- {
- nd->last_type = LAST_ROOT; /* if there are only slashes... */
- nd->flags = flags;
-+ nd->intent = NULL;
- if (*name=='/')
- return walk_init_root(name,nd);
- read_lock(¤t->fs->lock);
-@@ -777,7 +860,8 @@ int path_init(const char *name, unsigned
- * 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 +884,16 @@ struct dentry * lookup_hash(struct qstr
- 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->lookup_it)
-+ dentry = inode->i_op->lookup_it(inode, new, it, 0);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -818,6 +905,12 @@ out:
- 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 +932,7 @@ struct dentry * lookup_one_len(const cha
- }
- 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 +963,23 @@ int __user_walk(const char *name, unsign
- 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.
-@@ -967,7 +1077,8 @@ static inline int lookup_flags(unsigned
- return retval;
- }
-
--int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
-+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -980,12 +1091,15 @@ int vfs_create(struct inode *dir, struct
- goto exit_lock;
-
- error = -EACCES; /* shouldn't it be ENOSYS? */
-- if (!dir->i_op || !dir->i_op->create)
-+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it))
- goto exit_lock;
-
- DQUOT_INIT(dir);
- lock_kernel();
-- error = dir->i_op->create(dir, dentry, mode);
-+ if (dir->i_op->create_it)
-+ error = dir->i_op->create_it(dir, dentry, mode, it);
-+ else
-+ error = dir->i_op->create(dir, dentry, mode);
- unlock_kernel();
- exit_lock:
- up(&dir->i_zombie);
-@@ -994,6 +1108,11 @@ exit_lock:
- return error;
- }
-
-+int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
-+{
-+ return vfs_create_it(dir, dentry, mode, NULL);
-+}
-+
- /*
- * open_namei()
- *
-@@ -1008,7 +1127,8 @@ exit_lock:
- * 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;
-@@ -1018,11 +1138,14 @@ int open_namei(const char * pathname, in
-
- acc_mode = ACC_MODE(flag);
-
-+ if (it)
-+ it->it_flags = flag;
-+
- /*
- * 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;
-@@ -1032,6 +1155,10 @@ int open_namei(const char * pathname, in
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_create_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1047,7 +1174,7 @@ int open_namei(const char * pathname, in
-
- 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,11 +1183,12 @@ do_last:
- goto exit;
- }
-
-+ it->it_create_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- if (!IS_POSIXACL(dir->d_inode))
- mode &= ~current->fs->umask;
-- error = vfs_create(dir->d_inode, dentry, mode);
-+ error = vfs_create_it(dir->d_inode, dentry, mode, it);
- up(&dir->d_inode->i_sem);
- dput(nd->dentry);
- nd->dentry = dentry;
-@@ -1164,7 +1292,7 @@ ok:
- if (!error) {
- DQUOT_INIT(inode);
-
-- error = do_truncate(dentry, 0);
-+ error = do_truncate(dentry, 0, 1);
- }
- put_write_access(inode);
- if (error)
-@@ -1176,8 +1304,10 @@ ok:
- return 0;
-
- exit_dput:
-+ intent_release(it);
- dput(dentry);
- exit:
-+ intent_release(it);
- path_release(nd);
- return error;
-
-@@ -1196,7 +1326,10 @@ do_link:
- * are done. Procfs-like symlinks just set LAST_BIND.
- */
- UPDATE_ATIME(dentry->d_inode);
-+ nd->intent = it;
- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(it);
- dput(dentry);
- if (error)
- return error;
-@@ -1218,13 +1351,20 @@ do_link:
- }
- 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;
-
-@@ -1232,7 +1372,7 @@ static struct dentry *lookup_create(stru
- 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)
-@@ -1288,7 +1428,20 @@ asmlinkage long sys_mknod(const char * f
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->mknod_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mknod_raw(&nd, mode, dev);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+
-+ dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(dentry);
-
- if (!IS_POSIXACL(nd.dentry->d_inode))
-@@ -1310,6 +1463,7 @@ asmlinkage long sys_mknod(const char * f
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+out2:
- path_release(&nd);
- out:
- putname(tmp);
-@@ -1357,7 +1511,18 @@ asmlinkage long sys_mkdir(const char * p
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->mkdir_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mkdir_raw(&nd, mode);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+ dentry = lookup_create(&nd, 1, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- if (!IS_POSIXACL(nd.dentry->d_inode))
-@@ -1366,6 +1531,7 @@ asmlinkage long sys_mkdir(const char * p
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+out2:
- path_release(&nd);
- out:
- putname(tmp);
-@@ -1466,8 +1632,16 @@ asmlinkage long sys_rmdir(const char * p
- error = -EBUSY;
- goto exit1;
- }
-+ if (nd.dentry->d_inode->i_op->rmdir_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ error = op->rmdir_raw(&nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit1;
-+ }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1525,8 +1699,15 @@ asmlinkage long sys_unlink(const char *
- error = -EISDIR;
- if (nd.last_type != LAST_NORM)
- goto exit1;
-+ if (nd.dentry->d_inode->i_op->unlink_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->unlink_raw(&nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit1;
-+ }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1593,15 +1774,27 @@ asmlinkage long sys_symlink(const char *
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->symlink_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->symlink_raw(&nd, from);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+ dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+ out2:
- path_release(&nd);
--out:
-+ out:
- putname(to);
- }
- putname(from);
-@@ -1677,7 +1870,18 @@ asmlinkage long sys_link(const char * ol
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out_release;
-+ }
-+ if (nd.dentry->d_inode->i_op->link_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->link_raw(&old_nd, &nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out_release;
-+ }
-+ new_dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1721,7 +1925,7 @@ exit:
- * 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)
- {
- int error;
- struct inode *target;
-@@ -1800,7 +2004,7 @@ out_unlock:
- }
-
- 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)
- {
- int error;
-
-@@ -1888,9 +2092,18 @@ static inline int do_rename(const char *
- if (newnd.last_type != LAST_NORM)
- goto exit2;
-
-+ if (old_dir->d_inode->i_op->rename_raw) {
-+ lock_kernel();
-+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd);
-+ unlock_kernel();
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit2;
-+ }
-+
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1906,16 +2119,16 @@ static inline int do_rename(const char *
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL);
- 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);
- unlock_kernel();
--
- dput(new_dentry);
- exit4:
- dput(old_dentry);
-@@ -1966,20 +2179,26 @@ out:
- }
-
- 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;
- if (IS_ERR(link))
- goto fail;
-
-+ if (it == NULL)
-+ it = nd->intent;
-+ else if (it != nd->intent)
-+ printk("it != nd->intent: tell phil@clusterfs.com\n");
-+
- if (*link == '/') {
- path_release(nd);
- if (!walk_init_root(link, nd))
- /* 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;
-@@ -2003,7 +2222,13 @@ fail:
-
- 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 */
-@@ -2045,7 +2270,7 @@ int page_follow_link(struct dentry *dent
- {
- 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);
-Index: linux-ia64/fs/namespace.c
-===================================================================
---- linux-ia64.orig/fs/namespace.c 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/fs/namespace.c 2004-03-17 16:05:28.000000000 -0800
-@@ -98,6 +98,7 @@ static void detach_mnt(struct vfsmount *
- {
- old_nd->dentry = mnt->mnt_mountpoint;
- old_nd->mnt = mnt->mnt_parent;
-+ UNPIN(old_nd->dentry, old_nd->mnt, 1);
- mnt->mnt_parent = mnt;
- mnt->mnt_mountpoint = mnt->mnt_root;
- list_del_init(&mnt->mnt_child);
-@@ -109,6 +110,7 @@ static void attach_mnt(struct vfsmount *
- {
- mnt->mnt_parent = mntget(nd->mnt);
- mnt->mnt_mountpoint = dget(nd->dentry);
-+ PIN(nd->dentry, nd->mnt, 1);
- list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
- list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
- nd->dentry->d_mounted++;
-@@ -488,14 +490,17 @@ static int do_loopback(struct nameidata
- {
- struct nameidata old_nd;
- struct vfsmount *mnt = NULL;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int err = mount_is_safe(nd);
- if (err)
- return err;
- if (!old_name || !*old_name)
- return -EINVAL;
-- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd);
-- if (err)
-+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it);
-+ if (err) {
-+ intent_release(&it);
- return err;
-+ }
-
- down_write(¤t->namespace->sem);
- err = -EINVAL;
-@@ -518,6 +523,7 @@ static int do_loopback(struct nameidata
- }
-
- up_write(¤t->namespace->sem);
-+ intent_release(&it);
- path_release(&old_nd);
- return err;
- }
-@@ -701,6 +707,7 @@ long do_mount(char * dev_name, char * di
- unsigned long flags, void *data_page)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int retval = 0;
- int mnt_flags = 0;
-
-@@ -725,10 +732,11 @@ long do_mount(char * dev_name, char * di
- flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
-
- /* ... and get the mountpoint */
-- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
-- if (retval)
-+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
-+ if (retval) {
-+ intent_release(&it);
- return retval;
--
-+ }
- if (flags & MS_REMOUNT)
- retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
- data_page);
-@@ -739,6 +747,8 @@ long do_mount(char * dev_name, char * di
- else
- retval = do_add_mount(&nd, type_page, flags, mnt_flags,
- dev_name, data_page);
-+
-+ intent_release(&it);
- path_release(&nd);
- return retval;
- }
-@@ -904,6 +914,8 @@ asmlinkage long sys_pivot_root(const cha
- {
- struct vfsmount *tmp;
- struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
-+ struct lookup_intent new_it = { .it_op = IT_GETATTR };
-+ struct lookup_intent old_it = { .it_op = IT_GETATTR };
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
-@@ -911,14 +923,14 @@ asmlinkage long sys_pivot_root(const cha
-
- lock_kernel();
-
-- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd);
-+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it);
- if (error)
- goto out0;
- error = -EINVAL;
- if (!check_mnt(new_nd.mnt))
- goto out1;
-
-- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd);
-+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it);
- if (error)
- goto out1;
-
-@@ -973,8 +985,10 @@ out2:
- up(&old_nd.dentry->d_inode->i_zombie);
- up_write(¤t->namespace->sem);
- path_release(&user_nd);
-+ intent_release(&old_it);
- path_release(&old_nd);
- out1:
-+ intent_release(&new_it);
- path_release(&new_nd);
- out0:
- unlock_kernel();
-Index: linux-ia64/fs/open.c
-===================================================================
---- linux-ia64.orig/fs/open.c 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/fs/open.c 2004-03-17 16:05:28.000000000 -0800
-@@ -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);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct
- write_unlock(&files->file_lock);
- }
-
--int do_truncate(struct dentry *dentry, loff_t length)
-+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open)
- {
- struct inode *inode = dentry->d_inode;
-+ struct inode_operations *op = dentry->d_inode->i_op;
- int error;
- struct iattr newattrs;
-
-@@ -109,7 +112,13 @@ int do_truncate(struct dentry *dentry, l
- down(&inode->i_sem);
- newattrs.ia_size = length;
- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-- error = notify_change(dentry, &newattrs);
-+ if (called_from_open)
-+ newattrs.ia_valid |= ATTR_FROM_OPEN;
-+ if (op->setattr_raw) {
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ } else
-+ error = notify_change(dentry, &newattrs);
- up(&inode->i_sem);
- up_write(&inode->i_alloc_sem);
- return error;
-@@ -120,12 +129,13 @@ static inline long do_sys_truncate(const
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- 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;
-@@ -165,11 +175,13 @@ static inline long do_sys_truncate(const
- error = locks_verify_truncate(inode, NULL, length);
- if (!error) {
- DQUOT_INIT(inode);
-- error = do_truncate(nd.dentry, length);
-+ intent_release(&it);
-+ error = do_truncate(nd.dentry, length, 0);
- }
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
-@@ -217,7 +229,7 @@ static inline long do_sys_ftruncate(unsi
-
- error = locks_verify_truncate(inode, file, length);
- if (!error)
-- error = do_truncate(dentry, length);
-+ error = do_truncate(dentry, length, 0);
- out_putf:
- fput(file);
- out:
-@@ -262,11 +274,13 @@ asmlinkage long sys_utime(char * filenam
- struct inode * inode;
- struct iattr newattrs;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, NULL);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ /* this is safe without a Lustre lock because it only depends
-+ on the super block */
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -281,11 +295,25 @@ asmlinkage long sys_utime(char * filenam
- goto dput_and_out;
-
- newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
-- } else {
-+ }
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto dput_and_out;
-+ }
-+
-+ error = -EPERM;
-+ if (!times) {
- if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
- goto dput_and_out;
- }
-+
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
- path_release(&nd);
-@@ -306,12 +334,14 @@ asmlinkage long sys_utimes(char * filena
- struct inode * inode;
- struct iattr newattrs;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, NULL);
-
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ /* this is safe without a Lustre lock because it only depends
-+ on the super block */
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -326,7 +356,20 @@ asmlinkage long sys_utimes(char * filena
- newattrs.ia_atime = times[0].tv_sec;
- newattrs.ia_mtime = times[1].tv_sec;
- newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
-- } else {
-+ }
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto dput_and_out;
-+ }
-+
-+ error = -EPERM;
-+ if (!utimes) {
- if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
- goto dput_and_out;
-@@ -349,6 +392,7 @@ asmlinkage long sys_access(const char *
- 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;
-@@ -366,13 +410,14 @@ asmlinkage long sys_access(const char *
- 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(&it);
- path_release(&nd);
- }
-
-@@ -387,8 +432,9 @@ asmlinkage long sys_chdir(const char * f
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
-+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it);
- if (error)
- goto out;
-
-@@ -399,6 +445,7 @@ asmlinkage long sys_chdir(const char * f
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
-@@ -438,9 +485,10 @@ asmlinkage long sys_chroot(const char *
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = 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;
-
-@@ -456,39 +504,56 @@ asmlinkage long sys_chroot(const char *
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
- }
-
--asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
-+int chmod_common(struct dentry *dentry, mode_t mode)
- {
-- struct inode * inode;
-- struct dentry * dentry;
-- struct file * file;
-- int err = -EBADF;
-+ struct inode *inode = dentry->d_inode;
- struct iattr newattrs;
-+ int err = -EROFS;
-
-- file = fget(fd);
-- if (!file)
-+ if (IS_RDONLY(inode))
- goto out;
-
-- dentry = file->f_dentry;
-- inode = dentry->d_inode;
-+ if (inode->i_op->setattr_raw) {
-+ newattrs.ia_mode = mode;
-+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-+ newattrs.ia_valid |= ATTR_RAW;
-+ err = inode->i_op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (err != -EOPNOTSUPP)
-+ goto out;
-+ }
-
-- err = -EROFS;
-- if (IS_RDONLY(inode))
-- goto out_putf;
- err = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-- goto out_putf;
-+ goto out;
-+
- if (mode == (mode_t) -1)
- mode = inode->i_mode;
- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- err = notify_change(dentry, &newattrs);
-
--out_putf:
-+out:
-+ return err;
-+}
-+
-+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
-+{
-+ struct file * file;
-+ int err = -EBADF;
-+
-+ file = fget(fd);
-+ if (!file)
-+ goto out;
-+
-+ err = chmod_common(file->f_dentry, mode);
-+
- fput(file);
- out:
- return err;
-@@ -497,30 +562,14 @@ out:
- asmlinkage long sys_chmod(const char * filename, mode_t mode)
- {
- struct nameidata nd;
-- struct inode * inode;
- int error;
-- struct iattr newattrs;
-
- error = user_path_walk(filename, &nd);
- if (error)
- goto out;
-- inode = nd.dentry->d_inode;
--
-- error = -EROFS;
-- if (IS_RDONLY(inode))
-- goto dput_and_out;
-
-- error = -EPERM;
-- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-- goto dput_and_out;
-+ error = chmod_common(nd.dentry, mode);
-
-- if (mode == (mode_t) -1)
-- mode = inode->i_mode;
-- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-- error = notify_change(nd.dentry, &newattrs);
--
--dput_and_out:
- path_release(&nd);
- out:
- return error;
-@@ -540,6 +589,20 @@ static int chown_common(struct dentry *
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto out;
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = dentry->d_inode->i_op;
-+
-+ newattrs.ia_uid = user;
-+ newattrs.ia_gid = group;
-+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ return error;
-+ }
-+
- error = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- goto out;
-@@ -644,6 +707,7 @@ struct file *filp_open(const char * file
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -651,14 +715,15 @@ struct file *filp_open(const char * file
- 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;
-@@ -695,7 +760,9 @@ struct file *dentry_open(struct dentry *
- }
-
- if (f->f_op && f->f_op->open) {
-+ f->f_it = it;
- error = f->f_op->open(inode,f);
-+ f->f_it = NULL;
- if (error)
- goto cleanup_all;
- }
-@@ -708,6 +775,7 @@ struct file *dentry_open(struct dentry *
- inode->i_mapping->a_ops->direct_sector_IO)))
- goto cleanup_all;
-
-+ intent_release(it);
- return f;
-
- cleanup_all:
-@@ -722,11 +790,17 @@ cleanup_all:
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(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.
- */
-Index: linux-ia64/fs/stat.c
-===================================================================
---- linux-ia64.orig/fs/stat.c 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/fs/stat.c 2004-03-17 16:06:13.000000000 -0800
-@@ -17,10 +17,12 @@
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
- static __inline__ int
--do_revalidate(struct dentry *dentry)
-+do_revalidate(struct dentry *dentry, struct lookup_intent *it)
- {
- struct inode * inode = dentry->d_inode;
-- if (inode->i_op && inode->i_op->revalidate)
-+ if (inode->i_op && inode->i_op->revalidate_it)
-+ return inode->i_op->revalidate_it(dentry, it);
-+ else if (inode->i_op && inode->i_op->revalidate)
- return inode->i_op->revalidate(dentry);
- return 0;
- }
-@@ -143,13 +145,15 @@ static int cp_new_stat(struct inode * in
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -159,13 +163,15 @@ asmlinkage long sys_stat(char * filename
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -180,13 +186,15 @@ asmlinkage long sys_newstat(char * filen
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -197,13 +205,15 @@ asmlinkage long sys_lstat(char * filenam
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -224,7 +234,7 @@ asmlinkage long sys_fstat(unsigned int f
- if (f) {
- struct dentry * dentry = f->f_dentry;
-
-- err = do_revalidate(dentry);
-+ err = do_revalidate(dentry, NULL);
- if (!err)
- err = cp_old_stat(dentry->d_inode, statbuf);
- fput(f);
-@@ -243,7 +253,7 @@ asmlinkage long sys_newfstat(unsigned in
- if (f) {
- struct dentry * dentry = f->f_dentry;
-
-- err = do_revalidate(dentry);
-+ err = do_revalidate(dentry, NULL);
- if (!err)
- err = cp_new_stat(dentry->d_inode, statbuf);
- fput(f);
-@@ -265,7 +275,7 @@ asmlinkage long sys_readlink(const char
-
- error = -EINVAL;
- if (inode->i_op && inode->i_op->readlink &&
-- !(error = do_revalidate(nd.dentry))) {
-+ !(error = do_revalidate(nd.dentry, NULL))) {
- UPDATE_ATIME(inode);
- error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
- }
-@@ -341,12 +351,14 @@ asmlinkage long sys_stat64(char * filena
- {
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -356,12 +368,14 @@ asmlinkage long sys_lstat64(char * filen
- {
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -376,7 +390,7 @@ asmlinkage long sys_fstat64(unsigned lon
- if (f) {
- struct dentry * dentry = f->f_dentry;
-
-- err = do_revalidate(dentry);
-+ err = do_revalidate(dentry, NULL);
- if (!err)
- err = cp_new_stat64(dentry->d_inode, statbuf);
- fput(f);
-Index: linux-ia64/include/linux/dcache.h
-===================================================================
---- linux-ia64.orig/include/linux/dcache.h 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/include/linux/dcache.h 2004-03-17 16:05:28.000000000 -0800
-@@ -6,6 +6,51 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
- #include <linux/kernel.h>
-+#include <linux/string.h>
-+
-+#define IT_OPEN 0x0001
-+#define IT_CREAT 0x0002
-+#define IT_READDIR 0x0004
-+#define IT_GETATTR 0x0008
-+#define IT_LOOKUP 0x0010
-+#define IT_UNLINK 0x0020
-+#define IT_GETXATTR 0x0040
-+#define IT_EXEC 0x0080
-+#define IT_PIN 0x0100
-+
-+#define IT_FL_LOCKED 0x0001
-+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */
-+
-+#define INTENT_MAGIC 0x19620323
-+
-+
-+struct lustre_intent_data {
-+ int it_disposition;
-+ int it_status;
-+ __u64 it_lock_handle;
-+ void *it_data;
-+ int it_lock_mode;
-+ int it_int_flags;
-+};
-+struct lookup_intent {
-+ int it_magic;
-+ void (*it_op_release)(struct lookup_intent *);
-+ int it_op;
-+ int it_flags;
-+ int it_create_mode;
-+ union {
-+ struct lustre_intent_data lustre;
-+ } d;
-+};
-+
-+static inline void intent_init(struct lookup_intent *it, int op, int flags)
-+{
-+ memset(it, 0, sizeof(*it));
-+ it->it_magic = INTENT_MAGIC;
-+ it->it_op = op;
-+ it->it_flags = flags;
-+}
-+
-
- /*
- * linux/include/linux/dcache.h
-@@ -96,8 +141,22 @@ struct dentry_operations {
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_pin)(struct dentry *, struct vfsmount * , int);
-+ void (*d_unpin)(struct dentry *, struct vfsmount *, int);
- };
-
-+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \
-+ de->d_op->d_pin(de, mnt, flag);
-+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \
-+ de->d_op->d_unpin(de, mnt, flag);
-+
-+
-+/* defined in fs/namei.c */
-+extern void intent_release(struct lookup_intent *it);
-+/* defined in fs/dcache.c */
-+extern void __d_rehash(struct dentry * entry, int lock);
-+
- /* the dentry parameter passed to d_hash and d_compare is the parent
- * directory of the entries to be compared. It is used in case these
- * functions need any directory specific information for determining
-@@ -129,6 +188,7 @@ d_iput: no no yes
- * s_nfsd_free_path semaphore will be down
- */
- #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
-+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */
-
- extern spinlock_t dcache_lock;
-
-Index: linux-ia64/include/linux/fs.h
-===================================================================
---- linux-ia64.orig/include/linux/fs.h 2004-03-17 16:05:28.000000000 -0800
-+++ linux-ia64/include/linux/fs.h 2004-03-17 16:05:52.000000000 -0800
-@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena
-
- #define FMODE_READ 1
- #define FMODE_WRITE 2
-+#define FMODE_EXEC 4
-
- #define READ 0
- #define WRITE 1
-@@ -359,6 +360,9 @@ extern void set_bh_page(struct buffer_he
- #define ATTR_MTIME_SET 256
- #define ATTR_FORCE 512 /* Not a change, but a change it */
- #define ATTR_ATTR_FLAG 1024
-+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */
-+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */
-+#define ATTR_CTIME_SET 0x2000
-
- /*
- * This is the Inode Attributes structure, used for notify_change(). It
-@@ -496,6 +500,7 @@ struct inode {
- struct pipe_inode_info *i_pipe;
- struct block_device *i_bdev;
- struct char_device *i_cdev;
-+ void *i_filterdata;
-
- unsigned long i_dnotify_mask; /* Directory notify events */
- struct dnotify_struct *i_dnotify; /* for directory notifications */
-@@ -598,6 +603,7 @@ struct file {
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_it;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -726,6 +732,7 @@ struct nameidata {
- struct qstr last;
- unsigned int flags;
- int last_type;
-+ struct lookup_intent *intent;
- };
-
- /*
-@@ -846,7 +853,8 @@ extern int vfs_symlink(struct inode *, s
- 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);
-
- /*
- * File types
-@@ -920,21 +928,32 @@ struct file_operations {
-
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
-+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
-+ int (*link_raw) (struct nameidata *,struct nameidata *);
- int (*unlink) (struct inode *,struct dentry *);
-+ int (*unlink_raw) (struct nameidata *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-+ int (*symlink_raw) (struct nameidata *,const char *);
- int (*mkdir) (struct inode *,struct dentry *,int);
-+ int (*mkdir_raw) (struct nameidata *,int);
- int (*rmdir) (struct inode *,struct dentry *);
-+ int (*rmdir_raw) (struct nameidata *);
- int (*mknod) (struct inode *,struct dentry *,int,int);
-+ int (*mknod_raw) (struct nameidata *,int,dev_t);
- int (*rename) (struct inode *, struct dentry *,
- struct inode *, struct dentry *);
-+ int (*rename_raw) (struct nameidata *, struct nameidata *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*revalidate) (struct dentry *);
-+ int (*revalidate_it) (struct dentry *, struct lookup_intent *);
- int (*setattr) (struct dentry *, struct iattr *);
-+ int (*setattr_raw) (struct inode *, struct iattr *);
- int (*getattr) (struct dentry *, struct iattr *);
- int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-@@ -1131,10 +1150,14 @@ static inline int get_lease(struct inode
-
- asmlinkage long sys_open(const char *, int, int);
- asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */
--extern int do_truncate(struct dentry *, loff_t start);
-+extern int do_truncate(struct dentry *, loff_t start, int called_from_open);
-
- extern struct file *filp_open(const char *, int, int);
- extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
- extern int filp_close(struct file *, fl_owner_t id);
- extern char * getname(const char *);
-
-@@ -1425,6 +1448,7 @@ typedef int (*read_actor_t)(read_descrip
- 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 *));
-@@ -1436,6 +1460,8 @@ extern struct dentry * lookup_one_len(co
- 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 inode_init_once(struct inode *);
- extern void iput(struct inode *);
-@@ -1599,6 +1625,8 @@ extern struct file_operations generic_ro
-
- 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;
-Index: linux-ia64/include/linux/fs_struct.h
-===================================================================
---- linux-ia64.orig/include/linux/fs_struct.h 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/include/linux/fs_struct.h 2004-03-17 16:05:28.000000000 -0800
-@@ -37,10 +37,12 @@ static inline void set_fs_root(struct fs
- write_lock(&fs->lock);
- old_root = fs->root;
- old_rootmnt = fs->rootmnt;
-+ PIN(dentry, mnt, 1);
- fs->rootmnt = mntget(mnt);
- fs->root = dget(dentry);
- write_unlock(&fs->lock);
- if (old_root) {
-+ UNPIN(old_root, old_rootmnt, 1);
- dput(old_root);
- mntput(old_rootmnt);
- }
-@@ -60,10 +62,12 @@ static inline void set_fs_pwd(struct fs_
- write_lock(&fs->lock);
- old_pwd = fs->pwd;
- old_pwdmnt = fs->pwdmnt;
-+ PIN(dentry, mnt, 0);
- fs->pwdmnt = mntget(mnt);
- fs->pwd = dget(dentry);
- write_unlock(&fs->lock);
- if (old_pwd) {
-+ UNPIN(old_pwd, old_pwdmnt, 0);
- dput(old_pwd);
- mntput(old_pwdmnt);
- }
-Index: linux-ia64/kernel/exit.c
-===================================================================
---- linux-ia64.orig/kernel/exit.c 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/kernel/exit.c 2004-03-17 16:05:28.000000000 -0800
-@@ -347,11 +347,14 @@ static inline void __put_fs_struct(struc
- {
- /* No need to hold fs->lock if we are killing it */
- if (atomic_dec_and_test(&fs->count)) {
-+ UNPIN(fs->pwd, fs->pwdmnt, 0);
-+ UNPIN(fs->root, fs->rootmnt, 1);
- dput(fs->root);
- mntput(fs->rootmnt);
- dput(fs->pwd);
- mntput(fs->pwdmnt);
- if (fs->altroot) {
-+ UNPIN(fs->altroot, fs->altrootmnt, 1);
- dput(fs->altroot);
- mntput(fs->altrootmnt);
- }
-Index: linux-ia64/kernel/fork.c
-===================================================================
---- linux-ia64.orig/kernel/fork.c 2004-03-17 15:47:15.000000000 -0800
-+++ linux-ia64/kernel/fork.c 2004-03-17 16:05:28.000000000 -0800
-@@ -463,10 +463,13 @@ static inline struct fs_struct *__copy_f
- fs->umask = old->umask;
- read_lock(&old->lock);
- fs->rootmnt = mntget(old->rootmnt);
-+ PIN(old->pwd, old->pwdmnt, 0);
-+ PIN(old->root, old->rootmnt, 1);
- fs->root = dget(old->root);
- fs->pwdmnt = mntget(old->pwdmnt);
- fs->pwd = dget(old->pwd);
- if (old->altroot) {
-+ PIN(old->altroot, old->altrootmnt, 1);
- fs->altrootmnt = mntget(old->altrootmnt);
- fs->altroot = dget(old->altroot);
- } else {
-Index: linux-ia64/kernel/ksyms.c
-===================================================================
---- linux-ia64.orig/kernel/ksyms.c 2004-03-17 16:05:28.000000000 -0800
-+++ linux-ia64/kernel/ksyms.c 2004-03-17 16:05:51.000000000 -0800
-@@ -318,6 +318,7 @@ EXPORT_SYMBOL(read_cache_page);
- 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);
+++ /dev/null
- fs/dcache.c | 19 ++
- fs/exec.c | 17 +-
- fs/namei.c | 295 +++++++++++++++++++++++++++++++++++++++-------
- fs/namespace.c | 28 +++-
- fs/open.c | 172 +++++++++++++++++++-------
- fs/stat.c | 52 +++++---
- include/linux/dcache.h | 60 +++++++++
- include/linux/fs.h | 32 ++++
- include/linux/fs_struct.h | 4
- kernel/exit.c | 3
- kernel/fork.c | 3
- kernel/ksyms.c | 1
- 12 files changed, 558 insertions(+), 128 deletions(-)
-
---- linux-2.4.22-ac1/fs/dcache.c~vfs_intent-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/dcache.c 2003-09-25 14:42:46.000000000 +0400
-@@ -181,6 +181,13 @@ int d_invalidate(struct dentry * dentry)
- spin_unlock(&dcache_lock);
- return 0;
- }
-+
-+ /* network invalidation by Lustre */
-+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
-+ spin_unlock(&dcache_lock);
-+ return 0;
-+ }
-+
- /*
- * Check whether to do a partial shrink_dcache
- * to get rid of unused child entries.
-@@ -833,13 +840,19 @@ void d_delete(struct dentry * dentry)
- * Adds a dentry to the hash according to its name.
- */
-
--void d_rehash(struct dentry * entry)
-+void __d_rehash(struct dentry * entry, int lock)
- {
- struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
- if (!list_empty(&entry->d_hash)) BUG();
-- spin_lock(&dcache_lock);
-+ if (lock) spin_lock(&dcache_lock);
- list_add(&entry->d_hash, list);
-- spin_unlock(&dcache_lock);
-+ if (lock) spin_unlock(&dcache_lock);
-+}
-+EXPORT_SYMBOL(__d_rehash);
-+
-+void d_rehash(struct dentry * entry)
-+{
-+ __d_rehash(entry, 1);
- }
-
- #define do_switch(x,y) do { \
---- linux-2.4.22-ac1/fs/exec.c~vfs_intent-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/exec.c 2003-09-25 14:42:46.000000000 +0400
-@@ -115,8 +115,10 @@ asmlinkage long sys_uselib(const char *
- struct file * file;
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_OPEN,
-+ .it_flags = FMODE_READ|FMODE_EXEC };
-
-- error = user_path_walk(library, &nd);
-+ error = user_path_walk_it(library, &nd, &it);
- if (error)
- goto out;
-
-@@ -128,7 +130,8 @@ asmlinkage long sys_uselib(const char *
- if (error)
- goto exit;
-
-- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
-+ intent_release(&it);
- error = PTR_ERR(file);
- if (IS_ERR(file))
- goto out;
-@@ -390,8 +393,10 @@ struct file *open_exec(const char *name)
- struct inode *inode;
- struct file *file;
- int err = 0;
-+ struct lookup_intent it = { .it_op = IT_OPEN,
-+ .it_flags = FMODE_READ|FMODE_EXEC };
-
-- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
-+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
- file = ERR_PTR(err);
- if (!err) {
- inode = nd.dentry->d_inode;
-@@ -403,7 +408,8 @@ struct file *open_exec(const char *name)
- err = -EACCES;
- file = ERR_PTR(err);
- if (!err) {
-- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
-+ intent_release(&it);
- if (!IS_ERR(file)) {
- err = deny_write_access(file);
- if (err) {
-@@ -415,6 +421,7 @@ out:
- return file;
- }
- }
-+ intent_release(&it);
- path_release(&nd);
- }
- goto out;
-@@ -1322,7 +1329,7 @@ int do_coredump(long signr, int exit_cod
- goto close_fail;
- if (!file->f_op->write)
- goto close_fail;
-- if (do_truncate(file->f_dentry, 0) != 0)
-+ if (do_truncate(file->f_dentry, 0, 0) != 0)
- goto close_fail;
-
- retval = binfmt->core_dump(signr, regs, file);
---- linux-2.4.22-ac1/fs/namei.c~vfs_intent-2.4.22-rh 2003-09-25 14:16:23.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/namei.c 2003-09-25 14:44:40.000000000 +0400
-@@ -94,6 +94,13 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct lookup_intent *it)
-+{
-+ if (it && it->it_op_release)
-+ it->it_op_release(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 +267,19 @@ void path_release(struct nameidata *nd)
- * 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_revalidate_it) {
-+ if (!dentry->d_op->d_revalidate_it(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,11 +297,15 @@ static struct dentry * cached_lookup(str
- * 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;
-+ int counter = 0;
-
-+again:
-+ counter++;
- down(&dir->i_sem);
- /*
- * First re-do the cached lookup just in case it was created
-@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup_it)
-+ result = dir->i_op->lookup_it(dir, dentry, it, flags);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate_it) {
-+ if (!result->d_op->d_revalidate_it(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ if (counter > 10)
-+ result = ERR_PTR(-ESTALE);
-+ if (!IS_ERR(result))
-+ goto again;
-+ }
- }
- return result;
- }
-@@ -332,7 +364,8 @@ static struct dentry * real_lookup(struc
- * 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 +379,12 @@ static inline int do_follow_link(struct
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-+ nd->intent = it;
- err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-+ intent_release(it);
- path_release(nd);
- return -ELOOP;
- }
-@@ -447,7 +482,8 @@ static inline void follow_dotdot(struct
- *
- * 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;
-@@ -520,9 +556,9 @@ int link_path_walk(const char * name, st
- 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;
-@@ -540,7 +576,7 @@ int link_path_walk(const char * name, st
- goto out_dput;
-
- if (inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ err = do_follow_link(dentry, nd, NULL);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -556,7 +592,7 @@ int link_path_walk(const char * name, st
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup_it)
- break;
- continue;
- /* here ends the main loop */
-@@ -583,9 +619,9 @@ last_component:
- 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;
-@@ -595,7 +631,7 @@ last_component:
- inode = dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
- && inode && inode->i_op && inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -609,7 +645,8 @@ last_component:
- 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->lookup_it))
- break;
- }
- goto return_base;
-@@ -635,6 +672,32 @@ return_reval:
- * Check the cached dentry for staleness.
- */
- dentry = nd->dentry;
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ err = -ESTALE;
-+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) {
-+ struct dentry *new;
-+ err = permission(dentry->d_parent->d_inode,
-+ MAY_EXEC);
-+ if (err)
-+ break;
-+ new = real_lookup(dentry->d_parent,
-+ &dentry->d_name, 0, it);
-+ if (IS_ERR(new)) {
-+ err = PTR_ERR(new);
-+ break;
-+ }
-+ d_invalidate(dentry);
-+ dput(dentry);
-+ nd->dentry = new;
-+ }
-+ if (lookup_flags & LOOKUP_DIRECTORY) {
-+ err = -ENOTDIR;
-+ if (!nd->dentry->d_inode->i_op ||
-+ (!nd->dentry->d_inode->i_op->lookup &&
-+ !nd->dentry->d_inode->i_op->lookup_it))
-+ break;
-+ }
-+ } else
- if (dentry && dentry->d_sb
- && (dentry->d_sb->s_type->fs_flags & FS_ALWAYS_REVAL)) {
- err = -ESTALE;
-@@ -649,15 +705,28 @@ out_dput:
- dput(dentry);
- break;
- }
-+ if (err)
-+ intent_release(it);
- path_release(nd);
- return_err:
- 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,6 +811,17 @@ walk_init_root(const char *name, struct
- }
-
- /* 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;
-@@ -756,6 +836,7 @@ int path_init(const char *name, unsigned
- {
- nd->last_type = LAST_ROOT; /* if there are only slashes... */
- nd->flags = flags;
-+ nd->intent = NULL;
- if (*name=='/')
- return walk_init_root(name,nd);
- read_lock(¤t->fs->lock);
-@@ -770,7 +851,8 @@ int path_init(const char *name, unsigned
- * 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;
-@@ -793,13 +875,16 @@ struct dentry * lookup_hash(struct qstr
- 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->lookup_it)
-+ dentry = inode->i_op->lookup_it(inode, new, it, 0);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -811,6 +896,12 @@ out:
- 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)
- {
-@@ -832,7 +923,7 @@ struct dentry * lookup_one_len(const cha
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash_it(&this, base, NULL);
- access:
- return ERR_PTR(-EACCES);
- }
-@@ -863,6 +954,23 @@ int __user_walk(const char *name, unsign
- 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.
-@@ -958,7 +1066,8 @@ static inline int lookup_flags(unsigned
- return retval;
- }
-
--int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
-+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -971,12 +1080,15 @@ int vfs_create(struct inode *dir, struct
- goto exit_lock;
-
- error = -EACCES; /* shouldn't it be ENOSYS? */
-- if (!dir->i_op || !dir->i_op->create)
-+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it))
- goto exit_lock;
-
- DQUOT_INIT(dir);
- lock_kernel();
-- error = dir->i_op->create(dir, dentry, mode);
-+ if (dir->i_op->create_it)
-+ error = dir->i_op->create_it(dir, dentry, mode, it);
-+ else
-+ error = dir->i_op->create(dir, dentry, mode);
- unlock_kernel();
- exit_lock:
- up(&dir->i_zombie);
-@@ -985,6 +1097,11 @@ exit_lock:
- return error;
- }
-
-+int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
-+{
-+ return vfs_create_it(dir, dentry, mode, NULL);
-+}
-+
- /*
- * open_namei()
- *
-@@ -999,7 +1116,8 @@ exit_lock:
- * 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;
-@@ -1009,11 +1127,14 @@ int open_namei(const char * pathname, in
-
- acc_mode = ACC_MODE(flag);
-
-+ if (it)
-+ it->it_flags = flag;
-+
- /*
- * 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;
-@@ -1023,6 +1144,10 @@ int open_namei(const char * pathname, in
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_create_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1038,7 +1163,7 @@ int open_namei(const char * pathname, in
-
- 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);
-@@ -1047,10 +1172,11 @@ do_last:
- goto exit;
- }
-
-+ it->it_create_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
-- error = vfs_create(dir->d_inode, dentry,
-- mode & ~current->fs->umask);
-+ error = vfs_create_it(dir->d_inode, dentry,
-+ mode & ~current->fs->umask, it);
- up(&dir->d_inode->i_sem);
- dput(nd->dentry);
- nd->dentry = dentry;
-@@ -1154,7 +1280,7 @@ ok:
- if (!error) {
- DQUOT_INIT(inode);
-
-- error = do_truncate(dentry, 0);
-+ error = do_truncate(dentry, 0, 1);
- }
- put_write_access(inode);
- if (error)
-@@ -1166,8 +1292,10 @@ ok:
- return 0;
-
- exit_dput:
-+ intent_release(it);
- dput(dentry);
- exit:
-+ intent_release(it);
- path_release(nd);
- return error;
-
-@@ -1186,7 +1314,10 @@ do_link:
- * are done. Procfs-like symlinks just set LAST_BIND.
- */
- UPDATE_ATIME(dentry->d_inode);
-+ nd->intent = it;
- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(it);
- dput(dentry);
- if (error)
- return error;
-@@ -1208,13 +1339,20 @@ do_link:
- }
- 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;
-
-@@ -1222,7 +1360,7 @@ static struct dentry *lookup_create(stru
- 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)
-@@ -1278,7 +1416,20 @@ asmlinkage long sys_mknod(const char * f
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->mknod_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mknod_raw(&nd, mode, dev);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+
-+ dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(dentry);
-
- mode &= ~current->fs->umask;
-@@ -1299,6 +1446,7 @@ asmlinkage long sys_mknod(const char * f
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+out2:
- path_release(&nd);
- out:
- putname(tmp);
-@@ -1346,7 +1494,20 @@ asmlinkage long sys_mkdir(const char * p
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->mkdir_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mkdir_raw(&nd, mode);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+ dentry = lookup_create(&nd, 1, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
-@@ -1354,6 +1509,7 @@ asmlinkage long sys_mkdir(const char * p
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+out2:
- path_release(&nd);
- out:
- putname(tmp);
-@@ -1454,8 +1610,16 @@ asmlinkage long sys_rmdir(const char * p
- error = -EBUSY;
- goto exit1;
- }
-+ if (nd.dentry->d_inode->i_op->rmdir_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ error = op->rmdir_raw(&nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit1;
-+ }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1513,8 +1677,15 @@ asmlinkage long sys_unlink(const char *
- error = -EISDIR;
- if (nd.last_type != LAST_NORM)
- goto exit1;
-+ if (nd.dentry->d_inode->i_op->unlink_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->unlink_raw(&nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit1;
-+ }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1581,15 +1752,27 @@ asmlinkage long sys_symlink(const char *
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->symlink_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->symlink_raw(&nd, from);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+ dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+ out2:
- path_release(&nd);
--out:
-+ out:
- putname(to);
- }
- putname(from);
-@@ -1665,7 +1844,18 @@ asmlinkage long sys_link(const char * ol
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->link_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->link_raw(&old_nd, &nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out_release;
-+ }
-+ new_dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1709,7 +1895,7 @@ exit:
- * 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)
- {
- int error;
- struct inode *target;
-@@ -1788,7 +1974,7 @@ out_unlock:
- }
-
- 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)
- {
- int error;
-
-@@ -1876,9 +2062,18 @@ static inline int do_rename(const char *
- if (newnd.last_type != LAST_NORM)
- goto exit2;
-
-+ if (old_dir->d_inode->i_op->rename_raw) {
-+ lock_kernel();
-+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd);
-+ unlock_kernel();
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit2;
-+ }
-+
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1894,16 +2089,16 @@ static inline int do_rename(const char *
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL);
- 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);
- unlock_kernel();
--
- dput(new_dentry);
- exit4:
- dput(old_dentry);
-@@ -1954,20 +2149,26 @@ out:
- }
-
- 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;
- if (IS_ERR(link))
- goto fail;
-
-+ if (it == NULL)
-+ it = nd->intent;
-+ else if (it != nd->intent)
-+ printk("it != nd->intent: tell phil@clusterfs.com\n");
-+
- if (*link == '/') {
- path_release(nd);
- if (!walk_init_root(link, nd))
- /* 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;
-@@ -1991,7 +2192,13 @@ fail:
-
- 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 */
-@@ -2033,7 +2240,7 @@ int page_follow_link(struct dentry *dent
- {
- 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-2.4.22-ac1/fs/namespace.c~vfs_intent-2.4.22-rh 2003-09-25 14:16:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/namespace.c 2003-09-25 14:42:46.000000000 +0400
-@@ -98,6 +98,7 @@ static void detach_mnt(struct vfsmount *
- {
- old_nd->dentry = mnt->mnt_mountpoint;
- old_nd->mnt = mnt->mnt_parent;
-+ UNPIN(old_nd->dentry, old_nd->mnt, 1);
- mnt->mnt_parent = mnt;
- mnt->mnt_mountpoint = mnt->mnt_root;
- list_del_init(&mnt->mnt_child);
-@@ -109,6 +110,7 @@ static void attach_mnt(struct vfsmount *
- {
- mnt->mnt_parent = mntget(nd->mnt);
- mnt->mnt_mountpoint = dget(nd->dentry);
-+ PIN(nd->dentry, nd->mnt, 1);
- list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
- list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
- nd->dentry->d_mounted++;
-@@ -488,14 +490,17 @@ static int do_loopback(struct nameidata
- {
- struct nameidata old_nd;
- struct vfsmount *mnt = NULL;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int err = mount_is_safe(nd);
- if (err)
- return err;
- if (!old_name || !*old_name)
- return -EINVAL;
-- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd);
-- if (err)
-+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it);
-+ if (err) {
-+ intent_release(&it);
- return err;
-+ }
-
- down_write(¤t->namespace->sem);
- err = -EINVAL;
-@@ -518,6 +523,7 @@ static int do_loopback(struct nameidata
- }
-
- up_write(¤t->namespace->sem);
-+ intent_release(&it);
- path_release(&old_nd);
- return err;
- }
-@@ -701,6 +707,7 @@ long do_mount(char * dev_name, char * di
- unsigned long flags, void *data_page)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int retval = 0;
- int mnt_flags = 0;
-
-@@ -725,9 +732,11 @@ long do_mount(char * dev_name, char * di
- flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
-
- /* ... and get the mountpoint */
-- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
-- if (retval)
-+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
-+ if (retval) {
-+ intent_release(&it);
- return retval;
-+ }
-
- if (flags & MS_REMOUNT)
- retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
-@@ -739,6 +747,8 @@ long do_mount(char * dev_name, char * di
- else
- retval = do_add_mount(&nd, type_page, flags, mnt_flags,
- dev_name, data_page);
-+
-+ intent_release(&it);
- path_release(&nd);
- return retval;
- }
-@@ -904,6 +914,8 @@ asmlinkage long sys_pivot_root(const cha
- {
- struct vfsmount *tmp;
- struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
-+ struct lookup_intent new_it = { .it_op = IT_GETATTR };
-+ struct lookup_intent old_it = { .it_op = IT_GETATTR };
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
-@@ -911,14 +923,14 @@ asmlinkage long sys_pivot_root(const cha
-
- lock_kernel();
-
-- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd);
-+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it);
- if (error)
- goto out0;
- error = -EINVAL;
- if (!check_mnt(new_nd.mnt))
- goto out1;
-
-- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd);
-+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it);
- if (error)
- goto out1;
-
-@@ -973,8 +985,10 @@ out2:
- up(&old_nd.dentry->d_inode->i_zombie);
- up_write(¤t->namespace->sem);
- path_release(&user_nd);
-+ intent_release(&old_it);
- path_release(&old_nd);
- out1:
-+ intent_release(&new_it);
- path_release(&new_nd);
- out0:
- unlock_kernel();
---- linux-2.4.22-ac1/fs/open.c~vfs_intent-2.4.22-rh 2003-08-25 15:44:43.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/open.c 2003-09-25 14:42:46.000000000 +0400
-@@ -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);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct
- write_unlock(&files->file_lock);
- }
-
--int do_truncate(struct dentry *dentry, loff_t length)
-+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open)
- {
- struct inode *inode = dentry->d_inode;
-+ struct inode_operations *op = dentry->d_inode->i_op;
- int error;
- struct iattr newattrs;
-
-@@ -109,7 +112,13 @@ int do_truncate(struct dentry *dentry, l
- down(&inode->i_sem);
- newattrs.ia_size = length;
- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-- error = notify_change(dentry, &newattrs);
-+ if (called_from_open)
-+ newattrs.ia_valid |= ATTR_FROM_OPEN;
-+ if (op->setattr_raw) {
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ } else
-+ error = notify_change(dentry, &newattrs);
- up(&inode->i_sem);
- up_write(&inode->i_alloc_sem);
- return error;
-@@ -120,12 +129,13 @@ static inline long do_sys_truncate(const
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- 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;
-@@ -165,11 +175,13 @@ static inline long do_sys_truncate(const
- error = locks_verify_truncate(inode, NULL, length);
- if (!error) {
- DQUOT_INIT(inode);
-- error = do_truncate(nd.dentry, length);
-+ intent_release(&it);
-+ error = do_truncate(nd.dentry, length, 0);
- }
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
-@@ -217,7 +229,7 @@ static inline long do_sys_ftruncate(unsi
-
- error = locks_verify_truncate(inode, file, length);
- if (!error)
-- error = do_truncate(dentry, length);
-+ error = do_truncate(dentry, length, 0);
- out_putf:
- fput(file);
- out:
-@@ -262,11 +274,13 @@ asmlinkage long sys_utime(char * filenam
- struct inode * inode;
- struct iattr newattrs;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, NULL);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ /* this is safe without a Lustre lock because it only depends
-+ on the super block */
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -281,11 +295,25 @@ asmlinkage long sys_utime(char * filenam
- goto dput_and_out;
-
- newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
-- } else {
-+ }
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto dput_and_out;
-+ }
-+
-+ error = -EPERM;
-+ if (!times) {
- if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
- goto dput_and_out;
- }
-+
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
- path_release(&nd);
-@@ -306,12 +334,14 @@ asmlinkage long sys_utimes(char * filena
- struct inode * inode;
- struct iattr newattrs;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, NULL);
-
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ /* this is safe without a Lustre lock because it only depends
-+ on the super block */
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -326,7 +356,20 @@ asmlinkage long sys_utimes(char * filena
- newattrs.ia_atime = times[0].tv_sec;
- newattrs.ia_mtime = times[1].tv_sec;
- newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
-- } else {
-+ }
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto dput_and_out;
-+ }
-+
-+ error = -EPERM;
-+ if (!utimes) {
- if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
- goto dput_and_out;
-@@ -349,6 +392,7 @@ asmlinkage long sys_access(const char *
- 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;
-@@ -366,13 +410,14 @@ asmlinkage long sys_access(const char *
- 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(&it);
- path_release(&nd);
- }
-
-@@ -387,8 +432,9 @@ asmlinkage long sys_chdir(const char * f
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
-+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it);
- if (error)
- goto out;
-
-@@ -399,6 +445,7 @@ asmlinkage long sys_chdir(const char * f
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
-@@ -438,9 +485,10 @@ asmlinkage long sys_chroot(const char *
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = 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;
-
-@@ -456,39 +504,56 @@ asmlinkage long sys_chroot(const char *
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
- }
-
--asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
-+int chmod_common(struct dentry *dentry, mode_t mode)
- {
-- struct inode * inode;
-- struct dentry * dentry;
-- struct file * file;
-- int err = -EBADF;
-+ struct inode *inode = dentry->d_inode;
- struct iattr newattrs;
-+ int err = -EROFS;
-
-- file = fget(fd);
-- if (!file)
-+ if (IS_RDONLY(inode))
- goto out;
-
-- dentry = file->f_dentry;
-- inode = dentry->d_inode;
-+ if (inode->i_op->setattr_raw) {
-+ newattrs.ia_mode = mode;
-+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-+ newattrs.ia_valid |= ATTR_RAW;
-+ err = inode->i_op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (err != -EOPNOTSUPP)
-+ goto out;
-+ }
-
-- err = -EROFS;
-- if (IS_RDONLY(inode))
-- goto out_putf;
- err = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-- goto out_putf;
-+ goto out;
-+
- if (mode == (mode_t) -1)
- mode = inode->i_mode;
- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- err = notify_change(dentry, &newattrs);
-
--out_putf:
-+out:
-+ return err;
-+}
-+
-+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
-+{
-+ struct file * file;
-+ int err = -EBADF;
-+
-+ file = fget(fd);
-+ if (!file)
-+ goto out;
-+
-+ err = chmod_common(file->f_dentry, mode);
-+
- fput(file);
- out:
- return err;
-@@ -497,30 +562,14 @@ out:
- asmlinkage long sys_chmod(const char * filename, mode_t mode)
- {
- struct nameidata nd;
-- struct inode * inode;
- int error;
-- struct iattr newattrs;
-
- error = user_path_walk(filename, &nd);
- if (error)
- goto out;
-- inode = nd.dentry->d_inode;
--
-- error = -EROFS;
-- if (IS_RDONLY(inode))
-- goto dput_and_out;
-
-- error = -EPERM;
-- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-- goto dput_and_out;
-+ error = chmod_common(nd.dentry, mode);
-
-- if (mode == (mode_t) -1)
-- mode = inode->i_mode;
-- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-- error = notify_change(nd.dentry, &newattrs);
--
--dput_and_out:
- path_release(&nd);
- out:
- return error;
-@@ -540,6 +589,20 @@ static int chown_common(struct dentry *
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto out;
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = dentry->d_inode->i_op;
-+
-+ newattrs.ia_uid = user;
-+ newattrs.ia_gid = group;
-+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ return error;
-+ }
-+
- error = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- goto out;
-@@ -644,6 +707,7 @@ struct file *filp_open(const char * file
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -651,14 +715,15 @@ struct file *filp_open(const char * file
- 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;
-@@ -695,12 +760,15 @@ struct file *dentry_open(struct dentry *
- }
-
- if (f->f_op && f->f_op->open) {
-+ f->f_it = it;
- error = f->f_op->open(inode,f);
-+ f->f_it = NULL;
- if (error)
- goto cleanup_all;
- }
- f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-
-+ intent_release(it);
- return f;
-
- cleanup_all:
-@@ -715,11 +783,17 @@ cleanup_all:
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(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-2.4.22-ac1/fs/stat.c~vfs_intent-2.4.22-rh 2003-09-25 14:16:27.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/stat.c 2003-09-25 14:42:46.000000000 +0400
-@@ -17,10 +17,12 @@
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
- static __inline__ int
--do_revalidate(struct dentry *dentry)
-+do_revalidate(struct dentry *dentry, struct lookup_intent *it)
- {
- struct inode * inode = dentry->d_inode;
-- if (inode->i_op && inode->i_op->revalidate)
-+ if (inode->i_op && inode->i_op->revalidate_it)
-+ return inode->i_op->revalidate_it(dentry, it);
-+ else if (inode->i_op && inode->i_op->revalidate)
- return inode->i_op->revalidate(dentry);
- return 0;
- }
-@@ -143,13 +147,15 @@ static int cp_new_stat(struct inode * in
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -159,13 +165,15 @@ asmlinkage long sys_stat(char * filename
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -180,13 +188,15 @@ asmlinkage long sys_newstat(char * filen
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -197,13 +207,15 @@ asmlinkage long sys_lstat(char * filenam
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -224,7 +236,7 @@ asmlinkage long sys_fstat(unsigned int f
- if (f) {
- struct dentry * dentry = f->f_dentry;
-
-- err = do_revalidate(dentry);
-+ err = do_revalidate(dentry, NULL);
- if (!err)
- err = cp_old_stat(dentry->d_inode, statbuf);
- fput(f);
-@@ -243,7 +255,7 @@ asmlinkage long sys_newfstat(unsigned in
- if (f) {
- struct dentry * dentry = f->f_dentry;
-
-- err = do_revalidate(dentry);
-+ err = do_revalidate(dentry, NULL);
- if (!err)
- err = cp_new_stat(dentry->d_inode, statbuf);
- fput(f);
-@@ -265,7 +277,7 @@ asmlinkage long sys_readlink(const char
-
- error = -EINVAL;
- if (inode->i_op && inode->i_op->readlink &&
-- !(error = do_revalidate(nd.dentry))) {
-+ !(error = do_revalidate(nd.dentry, NULL))) {
- UPDATE_ATIME(inode);
- error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
- }
-@@ -341,12 +353,14 @@ asmlinkage long sys_stat64(char * filena
- {
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -356,12 +370,14 @@ asmlinkage long sys_lstat64(char * filen
- {
- 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);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -376,7 +392,7 @@ asmlinkage long sys_fstat64(unsigned lon
- if (f) {
- struct dentry * dentry = f->f_dentry;
-
-- err = do_revalidate(dentry);
-+ err = do_revalidate(dentry, NULL);
- if (!err)
- err = cp_new_stat64(dentry->d_inode, statbuf);
- fput(f);
---- linux-2.4.22-ac1/include/linux/dcache.h~vfs_intent-2.4.22-rh 2003-09-25 14:16:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/dcache.h 2003-09-25 14:42:46.000000000 +0400
-@@ -6,6 +6,51 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
- #include <linux/kernel.h>
-+#include <linux/string.h>
-+
-+#define IT_OPEN 0x0001
-+#define IT_CREAT 0x0002
-+#define IT_READDIR 0x0004
-+#define IT_GETATTR 0x0008
-+#define IT_LOOKUP 0x0010
-+#define IT_UNLINK 0x0020
-+#define IT_GETXATTR 0x0040
-+#define IT_EXEC 0x0080
-+#define IT_PIN 0x0100
-+
-+#define IT_FL_LOCKED 0x0001
-+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */
-+
-+#define INTENT_MAGIC 0x19620323
-+
-+
-+struct lustre_intent_data {
-+ int it_disposition;
-+ int it_status;
-+ __u64 it_lock_handle;
-+ void *it_data;
-+ int it_lock_mode;
-+ int it_int_flags;
-+};
-+struct lookup_intent {
-+ int it_magic;
-+ void (*it_op_release)(struct lookup_intent *);
-+ int it_op;
-+ int it_flags;
-+ int it_create_mode;
-+ union {
-+ struct lustre_intent_data lustre;
-+ } d;
-+};
-+
-+static inline void intent_init(struct lookup_intent *it, int op, int flags)
-+{
-+ memset(it, 0, sizeof(*it));
-+ it->it_magic = INTENT_MAGIC;
-+ it->it_op = op;
-+ it->it_flags = flags;
-+}
-+
-
- /*
- * linux/include/linux/dcache.h
-@@ -95,8 +140,22 @@ struct dentry_operations {
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_pin)(struct dentry *, struct vfsmount * , int);
-+ void (*d_unpin)(struct dentry *, struct vfsmount *, int);
- };
-
-+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \
-+ de->d_op->d_pin(de, mnt, flag);
-+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \
-+ de->d_op->d_unpin(de, mnt, flag);
-+
-+
-+/* defined in fs/namei.c */
-+extern void intent_release(struct lookup_intent *it);
-+/* defined in fs/dcache.c */
-+extern void __d_rehash(struct dentry * entry, int lock);
-+
- /* the dentry parameter passed to d_hash and d_compare is the parent
- * directory of the entries to be compared. It is used in case these
- * functions need any directory specific information for determining
-@@ -128,6 +187,7 @@ d_iput: no no yes
- * s_nfsd_free_path semaphore will be down
- */
- #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
-+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */
-
- extern spinlock_t dcache_lock;
-
---- linux-2.4.22-ac1/include/linux/fs.h~vfs_intent-2.4.22-rh 2003-09-25 14:39:01.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/fs.h 2003-09-25 14:42:46.000000000 +0400
-@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena
-
- #define FMODE_READ 1
- #define FMODE_WRITE 2
-+#define FMODE_EXEC 4
-
- #define READ 0
- #define WRITE 1
-@@ -343,6 +344,9 @@ extern void set_bh_page(struct buffer_he
- #define ATTR_MTIME_SET 256
- #define ATTR_FORCE 512 /* Not a change, but a change it */
- #define ATTR_ATTR_FLAG 1024
-+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */
-+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */
-+#define ATTR_CTIME_SET 0x2000
-
- /*
- * This is the Inode Attributes structure, used for notify_change(). It
-@@ -481,6 +485,7 @@ struct inode {
- struct pipe_inode_info *i_pipe;
- struct block_device *i_bdev;
- struct char_device *i_cdev;
-+ void *i_filterdata;
-
- unsigned long i_dnotify_mask; /* Directory notify events */
- struct dnotify_struct *i_dnotify; /* for directory notifications */
-@@ -583,6 +588,7 @@ struct file {
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_it;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -703,6 +709,7 @@ struct nameidata {
- struct qstr last;
- unsigned int flags;
- int last_type;
-+ struct lookup_intent *intent;
- };
-
- /*
-@@ -823,7 +830,8 @@ extern int vfs_symlink(struct inode *, s
- 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);
-
- /*
- * File types
-@@ -883,21 +891,32 @@ struct file_operations {
-
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
-+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
-+ int (*link_raw) (struct nameidata *,struct nameidata *);
- int (*unlink) (struct inode *,struct dentry *);
-+ int (*unlink_raw) (struct nameidata *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-+ int (*symlink_raw) (struct nameidata *,const char *);
- int (*mkdir) (struct inode *,struct dentry *,int);
-+ int (*mkdir_raw) (struct nameidata *,int);
- int (*rmdir) (struct inode *,struct dentry *);
-+ int (*rmdir_raw) (struct nameidata *);
- int (*mknod) (struct inode *,struct dentry *,int,int);
-+ int (*mknod_raw) (struct nameidata *,int,dev_t);
- int (*rename) (struct inode *, struct dentry *,
- struct inode *, struct dentry *);
-+ int (*rename_raw) (struct nameidata *, struct nameidata *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*revalidate) (struct dentry *);
-+ int (*revalidate_it) (struct dentry *, struct lookup_intent *);
- int (*setattr) (struct dentry *, struct iattr *);
-+ int (*setattr_raw) (struct inode *, struct iattr *);
- int (*getattr) (struct dentry *, struct iattr *);
- int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-@@ -1094,10 +1113,14 @@ static inline int get_lease(struct inode
-
- asmlinkage long sys_open(const char *, int, int);
- asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */
--extern int do_truncate(struct dentry *, loff_t start);
-+extern int do_truncate(struct dentry *, loff_t start, int called_from_open);
-
- extern struct file *filp_open(const char *, int, int);
- extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
- extern int filp_close(struct file *, fl_owner_t id);
- extern char * getname(const char *);
-
-@@ -1388,6 +1411,7 @@ typedef int (*read_actor_t)(read_descrip
- 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 *));
-@@ -1399,6 +1423,8 @@ extern struct dentry * lookup_one_len(co
- 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 inode_init_once(struct inode *);
- extern void iput(struct inode *);
-@@ -1538,6 +1564,8 @@ extern struct file_operations generic_ro
-
- 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-2.4.22-ac1/include/linux/fs_struct.h~vfs_intent-2.4.22-rh 2003-09-25 14:16:24.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/fs_struct.h 2003-09-25 14:42:46.000000000 +0400
-@@ -37,10 +37,12 @@ static inline void set_fs_root(struct fs
- write_lock(&fs->lock);
- old_root = fs->root;
- old_rootmnt = fs->rootmnt;
-+ PIN(dentry, mnt, 1);
- fs->rootmnt = mntget(mnt);
- fs->root = dget(dentry);
- write_unlock(&fs->lock);
- if (old_root) {
-+ UNPIN(old_root, old_rootmnt, 1);
- dput(old_root);
- mntput(old_rootmnt);
- }
-@@ -60,10 +62,12 @@ static inline void set_fs_pwd(struct fs_
- write_lock(&fs->lock);
- old_pwd = fs->pwd;
- old_pwdmnt = fs->pwdmnt;
-+ PIN(dentry, mnt, 0);
- fs->pwdmnt = mntget(mnt);
- fs->pwd = dget(dentry);
- write_unlock(&fs->lock);
- if (old_pwd) {
-+ UNPIN(old_pwd, old_pwdmnt, 0);
- dput(old_pwd);
- mntput(old_pwdmnt);
- }
---- linux-2.4.22-ac1/kernel/exit.c~vfs_intent-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/kernel/exit.c 2003-09-25 14:42:46.000000000 +0400
-@@ -342,11 +342,14 @@ static inline void __put_fs_struct(struc
- {
- /* No need to hold fs->lock if we are killing it */
- if (atomic_dec_and_test(&fs->count)) {
-+ UNPIN(fs->pwd, fs->pwdmnt, 0);
-+ UNPIN(fs->root, fs->rootmnt, 1);
- dput(fs->root);
- mntput(fs->rootmnt);
- dput(fs->pwd);
- mntput(fs->pwdmnt);
- if (fs->altroot) {
-+ UNPIN(fs->altroot, fs->altrootmnt, 1);
- dput(fs->altroot);
- mntput(fs->altrootmnt);
- }
---- linux-2.4.22-ac1/kernel/fork.c~vfs_intent-2.4.22-rh 2003-09-25 14:16:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/kernel/fork.c 2003-09-25 14:42:46.000000000 +0400
-@@ -457,10 +457,13 @@ static inline struct fs_struct *__copy_f
- fs->umask = old->umask;
- read_lock(&old->lock);
- fs->rootmnt = mntget(old->rootmnt);
-+ PIN(old->pwd, old->pwdmnt, 0);
-+ PIN(old->root, old->rootmnt, 1);
- fs->root = dget(old->root);
- fs->pwdmnt = mntget(old->pwdmnt);
- fs->pwd = dget(old->pwd);
- if (old->altroot) {
-+ PIN(old->altroot, old->altrootmnt, 1);
- fs->altrootmnt = mntget(old->altrootmnt);
- fs->altroot = dget(old->altroot);
- } else {
---- linux-2.4.22-ac1/kernel/ksyms.c~vfs_intent-2.4.22-rh 2003-09-25 14:39:02.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/kernel/ksyms.c 2003-09-25 14:42:46.000000000 +0400
-@@ -295,6 +295,7 @@ EXPORT_SYMBOL(read_cache_page);
- 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);
-
-_
+ struct dentry *dentry = nd->dentry;
+ int err, counter = 0;
+
++ revalidate_again:
+ if (!dentry->d_op || !dentry->d_op->d_revalidate)
+ return 0;
-+ revalidate_again:
+ if (!dentry->d_op->d_revalidate(dentry, nd)) {
+ struct dentry *new;
+ if ((err = permission(dentry->d_parent->d_inode, MAY_EXEC, nd)))
+++ /dev/null
-# This is a BitKeeper generated diff -Nru style patch.
-#
-# ChangeSet
-# 2004/06/14 16:05:28-03:00 marcelo@logos.cnet
-# Alexander Nyberg/Andi/Sergey: Fix x86 "clear_cpu()" macro.
-#
-# Linus's 2.6 changelog:
-#
-# Fix x86 "clear_cpu()" macro.
-#
-# We need to clear all exceptions before synchronizing
-# with the FPU, since we aren't ready to handle a FP
-# exception here and we're getting rid of all FP state.
-#
-# Special thanks to Alexander Nyberg for reports and
-# testing. Alternate patches by Sergey Vlasov and Andi
-# Kleen, who both worked on this.
-#
-# Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-#
-# include/asm-i386/i387.h
-# 2004/06/14 16:04:08-03:00 marcelo@logos.cnet +1 -1
-# Alexander Nyberg/Andi/Sergey: Fix x86 "clear_cpu()" macro.
-#
-diff -Nru a/include/asm-i386/i387.h b/include/asm-i386/i387.h
---- a/include/asm-i386/i387.h 2004-06-16 11:49:16 -07:00
-+++ b/include/asm-i386/i387.h 2004-06-16 11:49:16 -07:00
-@@ -34,7 +34,7 @@
-
- #define clear_fpu( tsk ) do { \
- if ( tsk->flags & PF_USEDFPU ) { \
-- asm volatile("fwait"); \
-+ asm volatile("fnclex ; fwait"); \
- tsk->flags &= ~PF_USEDFPU; \
- stts(); \
- } \
+++ /dev/null
- Documentation/Configure.help | 66 ++
- arch/alpha/defconfig | 7
- arch/alpha/kernel/entry.S | 12
- arch/arm/defconfig | 7
- arch/arm/kernel/calls.S | 24
- arch/i386/defconfig | 7
- arch/ia64/defconfig | 7
- arch/m68k/defconfig | 7
- arch/mips/defconfig | 7
- arch/mips64/defconfig | 7
- arch/ppc/defconfig | 14
- arch/ppc64/kernel/misc.S | 2
- arch/s390/defconfig | 7
- arch/s390/kernel/entry.S | 24
- arch/s390x/defconfig | 7
- arch/s390x/kernel/entry.S | 24
- arch/s390x/kernel/wrapper32.S | 90 +++
- arch/sparc/defconfig | 7
- arch/sparc64/defconfig | 7
- fs/Config.in | 14
- fs/Makefile | 3
- fs/ext2/Makefile | 4
- fs/ext2/file.c | 5
- fs/ext2/ialloc.c | 2
- fs/ext2/inode.c | 34 -
- fs/ext2/namei.c | 14
- fs/ext2/super.c | 29
- fs/ext2/symlink.c | 14
- fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++
- fs/ext2/xattr_user.c | 103 +++
- fs/ext3/Makefile | 10
- fs/ext3/ext3-exports.c | 13
- fs/ext3/file.c | 5
- fs/ext3/ialloc.c | 2
- fs/ext3/inode.c | 35 -
- fs/ext3/namei.c | 21
- fs/ext3/super.c | 37 +
- fs/ext3/symlink.c | 14
- fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++
- fs/ext3/xattr_user.c | 111 +++
- fs/jfs/jfs_xattr.h | 6
- fs/jfs/xattr.c | 6
- fs/mbcache.c | 648 ++++++++++++++++++++++
- include/asm-arm/unistd.h | 2
- include/asm-ppc64/unistd.h | 2
- include/asm-s390/unistd.h | 13
- include/asm-s390x/unistd.h | 13
- include/linux/cache_def.h | 15
- include/linux/errno.h | 4
- include/linux/ext2_fs.h | 31 -
- include/linux/ext2_xattr.h | 157 +++++
- include/linux/ext3_fs.h | 31 -
- include/linux/ext3_jbd.h | 8
- include/linux/ext3_xattr.h | 157 +++++
- include/linux/fs.h | 2
- include/linux/mbcache.h | 69 ++
- kernel/ksyms.c | 4
- mm/vmscan.c | 35 +
- 58 files changed, 4306 insertions(+), 137 deletions(-)
-
---- linux-2.4.22-ac1/arch/alpha/defconfig~xattr-0.8.54-2.4.22-rh 2003-06-13 18:51:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/alpha/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_ALPHA=y
- # CONFIG_UID16 is not set
- # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
---- linux-2.4.22-ac1/arch/alpha/kernel/entry.S~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:18.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/alpha/kernel/entry.S 2003-09-25 23:57:02.000000000 +0400
-@@ -1158,6 +1158,18 @@ sys_call_table:
- .quad sys_readahead
- .quad sys_ni_syscall /* 380, sys_security */
- .quad sys_tkill
-+ .quad sys_setxattr
-+ .quad sys_lsetxattr
-+ .quad sys_fsetxattr
-+ .quad sys_getxattr /* 385 */
-+ .quad sys_lgetxattr
-+ .quad sys_fgetxattr
-+ .quad sys_listxattr
-+ .quad sys_llistxattr
-+ .quad sys_flistxattr /* 390 */
-+ .quad sys_removexattr
-+ .quad sys_lremovexattr
-+ .quad sys_fremovexattr
-
- /* Remember to update everything, kids. */
- .ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
---- linux-2.4.22-ac1/arch/arm/defconfig~xattr-0.8.54-2.4.22-rh 2001-05-20 04:43:05.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/arm/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_ARM=y
- # CONFIG_EISA is not set
- # CONFIG_SBUS is not set
---- linux-2.4.22-ac1/arch/arm/kernel/calls.S~xattr-0.8.54-2.4.22-rh 2003-08-25 15:44:39.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/arm/kernel/calls.S 2003-09-26 00:00:10.000000000 +0400
-@@ -240,18 +240,18 @@ __syscall_start:
- .long SYMBOL_NAME(sys_ni_syscall) /* Security */
- .long SYMBOL_NAME(sys_gettid)
- /* 225 */ .long SYMBOL_NAME(sys_readahead)
-- .long SYMBOL_NAME(sys_ni_syscall) /* setxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* lsetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* fsetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* getxattr */
--/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* lgetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* fgetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* listxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* llistxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* flistxattr */
--/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* removexattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* lremovexattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* fremovexattr */
-+ .long SYMBOL_NAME(sys_setxattr)
-+ .long SYMBOL_NAME(sys_lsetxattr)
-+ .long SYMBOL_NAME(sys_fsetxattr)
-+ .long SYMBOL_NAME(sys_getxattr)
-+/* 230 */ .long SYMBOL_NAME(sys_lgetxattr)
-+ .long SYMBOL_NAME(sys_fgetxattr)
-+ .long SYMBOL_NAME(sys_listxattr)
-+ .long SYMBOL_NAME(sys_llistxattr)
-+ .long SYMBOL_NAME(sys_flistxattr)
-+/* 235 */ .long SYMBOL_NAME(sys_removexattr)
-+ .long SYMBOL_NAME(sys_lremovexattr)
-+ .long SYMBOL_NAME(sys_fremovexattr)
- .long SYMBOL_NAME(sys_tkill)
- .long SYMBOL_NAME(sys_ni_syscall) /* sendfile64 */
- /* 240 */ .long SYMBOL_NAME(sys_ni_syscall) /* futex */
---- linux-2.4.22-ac1/arch/i386/defconfig~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:18.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/i386/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_X86=y
- CONFIG_ISA=y
- # CONFIG_SBUS is not set
---- linux-2.4.22-ac1/arch/ia64/defconfig~xattr-0.8.54-2.4.22-rh 2003-08-25 15:44:39.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/ia64/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
-
- #
- # Code maturity level options
---- linux-2.4.22-ac1/arch/m68k/defconfig~xattr-0.8.54-2.4.22-rh 2000-06-19 23:56:08.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/m68k/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_UID16=y
-
- #
---- linux-2.4.22-ac1/arch/mips64/defconfig~xattr-0.8.54-2.4.22-rh 2003-08-25 15:44:40.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/mips64/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_MIPS=y
- # CONFIG_MIPS32 is not set
- CONFIG_MIPS64=y
---- linux-2.4.22-ac1/arch/mips/defconfig~xattr-0.8.54-2.4.22-rh 2003-08-25 15:44:39.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/mips/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_MIPS=y
- CONFIG_MIPS32=y
- # CONFIG_MIPS64 is not set
---- linux-2.4.22-ac1/arch/ppc64/kernel/misc.S~xattr-0.8.54-2.4.22-rh 2003-08-25 15:44:40.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/ppc64/kernel/misc.S 2003-09-25 23:57:02.000000000 +0400
-@@ -805,6 +805,7 @@ _GLOBAL(sys_call_table32)
- .llong .sys_gettid /* 207 */
- #if 0 /* Reserved syscalls */
- .llong .sys_tkill /* 208 */
-+#endif
- .llong .sys_setxattr
- .llong .sys_lsetxattr /* 210 */
- .llong .sys_fsetxattr
-@@ -817,6 +818,7 @@ _GLOBAL(sys_call_table32)
- .llong .sys_removexattr
- .llong .sys_lremovexattr
- .llong .sys_fremovexattr /* 220 */
-+#if 0 /* Reserved syscalls */
- .llong .sys_futex
- #endif
- .llong .sys_perfmonctl /* Put this here for now ... */
---- linux-2.4.22-ac1/arch/ppc/defconfig~xattr-0.8.54-2.4.22-rh 2003-06-13 18:51:31.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/ppc/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_UID16 is not set
- # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
- CONFIG_RWSEM_XCHGADD_ALGORITHM=y
---- linux-2.4.22-ac1/arch/s390/defconfig~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:18.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/s390/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_ISA is not set
- # CONFIG_EISA is not set
- # CONFIG_MCA is not set
---- linux-2.4.22-ac1/arch/s390/kernel/entry.S~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:18.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/s390/kernel/entry.S 2003-09-25 23:57:02.000000000 +0400
-@@ -559,18 +559,18 @@ sys_call_table:
- .long sys_fcntl64
- .long sys_readahead
- .long sys_ni_syscall
-- .long sys_ni_syscall /* 224 - reserved for setxattr */
-- .long sys_ni_syscall /* 225 - reserved for lsetxattr */
-- .long sys_ni_syscall /* 226 - reserved for fsetxattr */
-- .long sys_ni_syscall /* 227 - reserved for getxattr */
-- .long sys_ni_syscall /* 228 - reserved for lgetxattr */
-- .long sys_ni_syscall /* 229 - reserved for fgetxattr */
-- .long sys_ni_syscall /* 230 - reserved for listxattr */
-- .long sys_ni_syscall /* 231 - reserved for llistxattr */
-- .long sys_ni_syscall /* 232 - reserved for flistxattr */
-- .long sys_ni_syscall /* 233 - reserved for removexattr */
-- .long sys_ni_syscall /* 234 - reserved for lremovexattr */
-- .long sys_ni_syscall /* 235 - reserved for fremovexattr */
-+ .long sys_setxattr
-+ .long sys_lsetxattr /* 225 */
-+ .long sys_fsetxattr
-+ .long sys_getxattr
-+ .long sys_lgetxattr
-+ .long sys_fgetxattr
-+ .long sys_listxattr /* 230 */
-+ .long sys_llistxattr
-+ .long sys_flistxattr
-+ .long sys_removexattr
-+ .long sys_lremovexattr
-+ .long sys_fremovexattr /* 235 */
- .long sys_gettid
- .long sys_tkill
- .rept 255-237
---- linux-2.4.22-ac1/arch/s390x/defconfig~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:18.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/s390x/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_ISA is not set
- # CONFIG_EISA is not set
- # CONFIG_MCA is not set
---- linux-2.4.22-ac1/arch/s390x/kernel/entry.S~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:18.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/s390x/kernel/entry.S 2003-09-25 23:57:02.000000000 +0400
-@@ -591,18 +591,18 @@ sys_call_table:
- .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
- .long SYSCALL(sys_readahead,sys32_readahead)
- .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
-+ .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
-+ .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
-+ .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
-+ .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
-+ .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
-+ .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
-+ .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
-+ .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
-+ .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
-+ .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
-+ .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
-+ .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
- .long SYSCALL(sys_gettid,sys_gettid)
- .long SYSCALL(sys_tkill,sys_tkill)
- .rept 255-237
---- linux-2.4.22-ac1/arch/s390x/kernel/wrapper32.S~xattr-0.8.54-2.4.22-rh 2003-08-25 15:44:40.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/s390x/kernel/wrapper32.S 2003-09-26 00:05:14.000000000 +0400
-@@ -1097,6 +1097,96 @@ sys32_fstat64_wrapper:
- llgtr %r3,%r3 # struct stat64 *
- llgfr %r4,%r4 # long
- jg sys32_fstat64 # branch to system call
-+
-+ .globl sys32_setxattr_wrapper
-+sys32_setxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_setxattr
-+
-+ .globl sys32_lsetxattr_wrapper
-+sys32_lsetxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_lsetxattr
-+
-+ .globl sys32_fsetxattr_wrapper
-+sys32_fsetxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_fsetxattr
-+
-+ .globl sys32_getxattr_wrapper
-+sys32_getxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_getxattr
-+
-+ .globl sys32_lgetxattr_wrapper
-+sys32_lgetxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_lgetxattr
-+
-+ .globl sys32_fgetxattr_wrapper
-+sys32_fgetxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_fgetxattr
-+
-+ .globl sys32_listxattr_wrapper
-+sys32_listxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_listxattr
-+
-+ .globl sys32_llistxattr_wrapper
-+sys32_llistxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_llistxattr
-+
-+ .globl sys32_flistxattr_wrapper
-+sys32_flistxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_flistxattr
-+
-+ .globl sys32_removexattr_wrapper
-+sys32_removexattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ jg sys_removexattr
-+
-+ .globl sys32_lremovexattr_wrapper
-+sys32_lremovexattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ jg sys_lremovexattr
-+
-+ .globl sys32_fremovexattr_wrapper
-+sys32_fremovexattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ jg sys_fremovexattr
-
- .globl sys32_stime_wrapper
- sys32_stime_wrapper:
---- linux-2.4.22-ac1/arch/sparc64/defconfig~xattr-0.8.54-2.4.22-rh 2003-08-25 15:44:40.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/sparc64/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
-
- #
- # Code maturity level options
---- linux-2.4.22-ac1/arch/sparc/defconfig~xattr-0.8.54-2.4.22-rh 2002-08-03 04:39:43.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/arch/sparc/defconfig 2003-09-25 23:57:02.000000000 +0400
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_UID16=y
- CONFIG_HIGHMEM=y
-
---- linux-2.4.22-ac1/Documentation/Configure.help~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:30.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/Documentation/Configure.help 2003-09-25 23:57:02.000000000 +0400
-@@ -16145,6 +16145,39 @@ CONFIG_EXT2_FS
- be compiled as a module, and so this could be dangerous. Most
- everyone wants to say Y here.
-
-+Ext2 extended attributes
-+CONFIG_EXT2_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.
-+
-+Ext2 extended attribute block sharing
-+CONFIG_EXT2_FS_XATTR_SHARING
-+ This options enables code for sharing identical extended attribute
-+ blocks among multiple inodes.
-+
-+ Usually, say Y.
-+
-+Ext2 extended user attributes
-+CONFIG_EXT2_FS_XATTR_USER
-+ This option enables extended user attributes on ext2. Processes can
-+ associate extended user attributes with inodes to store additional
-+ information such as the character encoding of files, etc. (see the
-+ attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext2 trusted extended attributes
-+CONFIG_EXT2_FS_XATTR_TRUSTED
-+ This option enables extended attributes on ext2 that are accessible
-+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
-+ is only the super user. Trusted extended attributes are meant for
-+ implementing system/security services.
-+
-+ If unsure, say N.
-+
- Ext3 journalling file system support (EXPERIMENTAL)
- CONFIG_EXT3_FS
- This is the journalling version of the Second extended file system
-@@ -16177,6 +16210,39 @@ CONFIG_EXT3_FS
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this may be dangerous.
-
-+Ext3 extended attributes
-+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.
-+
-+Ext3 extended attribute block sharing
-+CONFIG_EXT3_FS_XATTR_SHARING
-+ This options enables code for sharing identical extended attribute
-+ blocks among multiple inodes.
-+
-+ Usually, say Y.
-+
-+Ext3 extended user attributes
-+CONFIG_EXT3_FS_XATTR_USER
-+ This option enables extended user attributes on ext3. Processes can
-+ associate extended user attributes with inodes to store additional
-+ information such as the character encoding of files, etc. (see the
-+ attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext3 trusted extended attributes
-+CONFIG_EXT3_FS_XATTR_TRUSTED
-+ This option enables extended attributes on ext3 that are accessible
-+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
-+ is only the super user. Trusted extended attributes are meant for
-+ implementing system/security services.
-+
-+ If unsure, say N.
-+
- Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
- CONFIG_JBD
- This is a generic journalling layer for block devices. It is
---- linux-2.4.22-ac1/fs/Config.in~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:23.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/Config.in 2003-09-25 23:57:02.000000000 +0400
-@@ -29,6 +29,11 @@ dep_mbool ' Debug Befs' CONFIG_BEFS_DEB
- 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
-+dep_bool ' Ext3 extended attribute block sharing' \
-+ CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
-+dep_bool ' Ext3 extended user attributes' \
-+ CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
- # 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
-@@ -88,6 +93,11 @@ dep_mbool ' QNX4FS write support (DANGE
- tristate 'ROM file system support' CONFIG_ROMFS_FS
-
- tristate 'Second extended fs support' CONFIG_EXT2_FS
-+dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
-+dep_bool ' Ext2 extended attribute block sharing' \
-+ CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
-+dep_bool ' Ext2 extended user attributes' \
-+ CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
-
- tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
-
-@@ -164,6 +174,10 @@ else
- define_tristate CONFIG_ZISOFS_FS n
- fi
-
-+# Meta block cache for Extended Attributes (ext2/ext3)
-+#tristate 'Meta block cache' CONFIG_FS_MBCACHE
-+define_tristate CONFIG_FS_MBCACHE y
-+
- mainmenu_option next_comment
- comment 'Partition Types'
- source fs/partitions/Config.in
---- linux-2.4.22-ac1/fs/ext2/file.c~xattr-0.8.54-2.4.22-rh 2001-10-11 19:05:18.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext2/file.c 2003-09-25 23:57:02.000000000 +0400
-@@ -20,6 +20,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/sched.h>
-
- /*
-@@ -51,4 +52,8 @@ struct file_operations ext2_file_operati
-
- struct inode_operations ext2_file_inode_operations = {
- truncate: ext2_truncate,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
---- linux-2.4.22-ac1/fs/ext2/ialloc.c~xattr-0.8.54-2.4.22-rh 2003-06-13 18:51:37.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext2/ialloc.c 2003-09-25 23:57:02.000000000 +0400
-@@ -15,6 +15,7 @@
- #include <linux/config.h>
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/locks.h>
- #include <linux/quotaops.h>
-
-@@ -167,6 +168,7 @@ void ext2_free_inode (struct inode * ino
- */
- if (!is_bad_inode(inode)) {
- /* Quota is already initialized in iput() */
-+ ext2_xattr_delete_inode(inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
- }
---- linux-2.4.22-ac1/fs/ext2/inode.c~xattr-0.8.54-2.4.22-rh 2003-06-13 18:51:37.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext2/inode.c 2003-09-25 23:57:02.000000000 +0400
-@@ -39,6 +39,18 @@ MODULE_LICENSE("GPL");
- static int ext2_update_inode(struct inode * inode, int do_sync);
-
- /*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext2_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = inode->u.ext2_i.i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
-+/*
- * Called at each iput()
- */
- void ext2_put_inode (struct inode * inode)
-@@ -53,9 +65,7 @@ void ext2_delete_inode (struct inode * i
- {
- lock_kernel();
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT2_ACL_IDX_INO ||
-- inode->i_ino == EXT2_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
- inode->u.ext2_i.i_dtime = CURRENT_TIME;
- mark_inode_dirty(inode);
-@@ -801,6 +811,8 @@ void ext2_truncate (struct inode * inode
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext2_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -903,8 +915,7 @@ void ext2_read_inode (struct inode * ino
- unsigned long offset;
- struct ext2_group_desc * gdp;
-
-- if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
-- inode->i_ino != EXT2_ACL_DATA_INO &&
-+ if ((inode->i_ino != EXT2_ROOT_INO &&
- inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
- ext2_error (inode->i_sb, "ext2_read_inode",
-@@ -989,10 +1000,7 @@ void ext2_read_inode (struct inode * ino
- for (block = 0; block < EXT2_N_BLOCKS; block++)
- inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
-
-- if (inode->i_ino == EXT2_ACL_IDX_INO ||
-- inode->i_ino == EXT2_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext2_file_inode_operations;
- inode->i_fop = &ext2_file_operations;
- inode->i_mapping->a_ops = &ext2_aops;
-@@ -1001,15 +1009,17 @@ void ext2_read_inode (struct inode * ino
- inode->i_fop = &ext2_dir_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext2_inode_is_fast_symlink(inode))
- inode->i_op = &ext2_fast_symlink_inode_operations;
- else {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext2_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- }
-- } else
-+ } else {
-+ inode->i_op = &ext2_special_inode_operations;
- init_special_inode(inode, inode->i_mode,
- le32_to_cpu(raw_inode->i_block[0]));
-+ }
- brelse (bh);
- inode->i_attr_flags = 0;
- ext2_set_inode_flags(inode);
---- linux-2.4.22-ac1/fs/ext2/Makefile~xattr-0.8.54-2.4.22-rh 2001-10-11 19:05:18.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext2/Makefile 2003-09-25 23:57:02.000000000 +0400
-@@ -13,4 +13,8 @@ obj-y := balloc.o bitmap.o dir.o file
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
-
-+export-objs += xattr.o
-+obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
-+obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
-+
- include $(TOPDIR)/Rules.make
---- linux-2.4.22-ac1/fs/ext2/namei.c~xattr-0.8.54-2.4.22-rh 2001-10-04 09:57:36.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext2/namei.c 2003-09-25 23:57:02.000000000 +0400
-@@ -31,6 +31,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/pagemap.h>
-
- /*
-@@ -136,7 +137,7 @@ static int ext2_symlink (struct inode *
-
- if (l > sizeof (inode->u.ext2_i.i_data)) {
- /* slow symlink */
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext2_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- err = block_symlink(inode, symname, l);
- if (err)
-@@ -345,4 +346,15 @@ struct inode_operations ext2_dir_inode_o
- rmdir: ext2_rmdir,
- mknod: ext2_mknod,
- rename: ext2_rename,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
-+};
-+
-+struct inode_operations ext2_special_inode_operations = {
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
---- linux-2.4.22-ac1/fs/ext2/super.c~xattr-0.8.54-2.4.22-rh 2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/ext2/super.c 2003-09-25 23:57:02.000000000 +0400
-@@ -21,6 +21,7 @@
- #include <linux/string.h>
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/locks.h>
-@@ -125,6 +126,7 @@ void ext2_put_super (struct super_block
- int db_count;
- int i;
-
-+ ext2_xattr_put_super(sb);
- if (!(sb->s_flags & MS_RDONLY)) {
- struct ext2_super_block *es = EXT2_SB(sb)->s_es;
-
-@@ -175,6 +177,13 @@ static int parse_options (char * options
- this_char = strtok (NULL, ",")) {
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT2_FS_XATTR_USER
-+ 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")) {
-@@ -424,6 +433,9 @@ struct super_block * ext2_read_super (st
- blocksize = BLOCK_SIZE;
-
- sb->u.ext2_sb.s_mount_opt = 0;
-+#ifdef CONFIG_EXT2_FS_XATTR_USER
-+ /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
-+#endif
- if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
- &sb->u.ext2_sb.s_mount_opt)) {
- return NULL;
-@@ -813,12 +825,27 @@ static DECLARE_FSTYPE_DEV(ext2_fs_type,
-
- static int __init init_ext2_fs(void)
- {
-- return register_filesystem(&ext2_fs_type);
-+ int error = init_ext2_xattr();
-+ if (error)
-+ return error;
-+ error = init_ext2_xattr_user();
-+ if (error)
-+ goto fail;
-+ error = register_filesystem(&ext2_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext2_xattr_user();
-+fail:
-+ exit_ext2_xattr();
-+ return error;
- }
-
- static void __exit exit_ext2_fs(void)
- {
- unregister_filesystem(&ext2_fs_type);
-+ exit_ext2_xattr_user();
-+ exit_ext2_xattr();
- }
-
- EXPORT_NO_SYMBOLS;
---- linux-2.4.22-ac1/fs/ext2/symlink.c~xattr-0.8.54-2.4.22-rh 2000-09-28 00:41:33.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext2/symlink.c 2003-09-25 23:57:02.000000000 +0400
-@@ -19,6 +19,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-
- static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-@@ -32,7 +33,20 @@ static int ext2_follow_link(struct dentr
- return vfs_follow_link(nd, s);
- }
-
-+struct inode_operations ext2_symlink_inode_operations = {
-+ readlink: page_readlink,
-+ follow_link: page_follow_link,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
-+};
-+
- struct inode_operations ext2_fast_symlink_inode_operations = {
- readlink: ext2_readlink,
- follow_link: ext2_follow_link,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/ext2/xattr.c 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,1212 @@
-+/*
-+ * linux/fs/ext2/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * 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 EXT2_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 EXT2_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 ext2_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/module.h>
-+#include <linux/locks.h>
-+#include <linux/slab.h>
-+#include <linux/fs.h>
-+#include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-+#include <linux/mbcache.h>
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include <linux/compatmac.h>
-+
-+/* These symbols may be needed by a module. */
-+EXPORT_SYMBOL(ext2_xattr_register);
-+EXPORT_SYMBOL(ext2_xattr_unregister);
-+EXPORT_SYMBOL(ext2_xattr_get);
-+EXPORT_SYMBOL(ext2_xattr_list);
-+EXPORT_SYMBOL(ext2_xattr_set);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
-+#endif
-+
-+#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT2_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 ext2_xattr_set2(struct inode *, struct buffer_head *,
-+ struct ext2_xattr_header *);
-+
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+
-+static int ext2_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext2_xattr_cache_find(struct inode *,
-+ struct ext2_xattr_header *);
-+static void ext2_xattr_cache_remove(struct buffer_head *);
-+static void ext2_xattr_rehash(struct ext2_xattr_header *,
-+ struct ext2_xattr_entry *);
-+
-+static struct mb_cache *ext2_xattr_cache;
-+
-+#else
-+# define ext2_xattr_cache_insert(bh) 0
-+# define ext2_xattr_cache_find(inode, header) NULL
-+# define ext2_xattr_cache_remove(bh) while(0) {}
-+# define ext2_xattr_rehash(header, entry) while(0) {}
-+#endif
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext2_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+DECLARE_MUTEX(ext2_xattr_sem);
-+
-+static inline int
-+ext2_xattr_new_block(struct inode *inode, int * errp, int force)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
-+ EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
-+
-+ /* How can we enforce the allocation? */
-+ int block = ext2_new_block(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
-+ext2_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
-+ext2_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
-+ext2_xattr_free_block(struct inode * inode, unsigned long block)
-+{
-+ ext2_free_blocks(inode, block, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+#else
-+# define ext2_xattr_quota_free(inode) \
-+ DQUOT_FREE_BLOCK(inode, 1)
-+# define ext2_xattr_free_block(inode, block) \
-+ ext2_free_blocks(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 ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
-+rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ write_lock(&ext2_handler_lock);
-+ if (!ext2_xattr_handlers[name_index-1]) {
-+ ext2_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext2_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
-+{
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ write_lock(&ext2_handler_lock);
-+ ext2_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext2_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 struct ext2_xattr_handler *
-+ext2_xattr_resolve_name(const char **name)
-+{
-+ struct ext2_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext2_handler_lock);
-+ for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
-+ if (ext2_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext2_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext2_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext2_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext2_xattr_handler *
-+ext2_xattr_handler(int name_index)
-+{
-+ struct ext2_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ read_lock(&ext2_handler_lock);
-+ handler = ext2_xattr_handlers[name_index-1];
-+ read_unlock(&ext2_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext2_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext2_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
-+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext2_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext2_setxattr(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext2_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
-+ext2_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext2_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext2_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 (!EXT2_I(inode)->i_file_acl)
-+ return -ENOATTR;
-+ block = EXT2_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(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(inode->i_sb, "ext2_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 ext2_xattr_entry *next =
-+ EXT2_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 ext2_xattr_entry *next =
-+ EXT2_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext2_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 (ext2_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;
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext2_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 (!EXT2_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT2_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(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(inode->i_sb, "ext2_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 = EXT2_XATTR_NEXT(entry)) {
-+ struct ext2_xattr_handler *handler;
-+ struct ext2_xattr_entry *next =
-+ EXT2_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext2_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+
-+ if (ext2_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 = EXT2_XATTR_NEXT(entry)) {
-+ struct ext2_xattr_handler *handler;
-+
-+ handler = ext2_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext2_xattr_update_super_block(struct super_block *sb)
-+{
-+ if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+ EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
-+#endif
-+ EXT2_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_set(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 ext2_xattr_header *header = NULL;
-+ struct ext2_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int block = EXT2_I(inode)->i_file_acl;
-+ 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(&ext2_xattr_sem);
-+
-+ if (block) {
-+ /* The inode already has an extended attribute block. */
-+
-+ 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(EXT2_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(sb, "ext2_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 ext2_xattr_entry *next = EXT2_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 ext2_xattr_entry *next = EXT2_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 ext2_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 -= EXT2_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 += EXT2_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT2_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");
-+ ext2_xattr_cache_remove(bh);
-+ } 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(EXT2_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 = EXT2_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 = EXT2_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 = EXT2_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext2_xattr_set2(inode, bh, NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT2_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 = EXT2_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 - EXT2_XATTR_PAD, 0,
-+ EXT2_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext2_xattr_rehash(header, here);
-+
-+ error = ext2_xattr_set2(inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ up(&ext2_xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext2_xattr_set(): Update the file system.
-+ */
-+static int
-+ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
-+ struct ext2_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext2_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 (ext2_xattr_quota_alloc(inode, 1))
-+ 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;
-+ (void)ext2_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int force = EXT2_I(inode)->i_file_acl != 0;
-+ int block = ext2_xattr_new_block(inode, &error, force);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+ ext2_xattr_free_block(inode, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ mark_buffer_uptodate(new_bh, 1);
-+ unlock_buffer(new_bh);
-+ (void)ext2_xattr_cache_insert(new_bh);
-+
-+ ext2_xattr_update_super_block(sb);
-+ }
-+ mark_buffer_dirty(new_bh);
-+ if (IS_SYNC(inode)) {
-+ ll_rw_block(WRITE, 1, &new_bh);
-+ wait_on_buffer(new_bh);
-+ error = -EIO;
-+ if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
-+ goto cleanup;
-+ }
-+ }
-+
-+ /* Update the inode. */
-+ EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ if (IS_SYNC(inode)) {
-+ error = ext2_sync_inode (inode);
-+ if (error)
-+ goto cleanup;
-+ } else
-+ mark_inode_dirty(inode);
-+
-+ 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);
-+
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext2_xattr_free_block(inode, old_bh->b_blocknr);
-+ mark_buffer_clean(old_bh);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ ext2_xattr_quota_free(inode);
-+ mark_buffer_dirty(old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext2_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext2_xattr_delete_inode(struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT2_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ down(&ext2_xattr_sem);
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext2_error(inode->i_sb, "ext2_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(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext2_xattr_cache_remove(bh);
-+ ext2_xattr_free_block(inode, block);
-+ bforget(bh);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ mark_buffer_dirty(bh);
-+ if (IS_SYNC(inode)) {
-+ ll_rw_block(WRITE, 1, &bh);
-+ wait_on_buffer(bh);
-+ }
-+ ext2_xattr_quota_free(inode);
-+ }
-+ EXT2_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ up(&ext2_xattr_sem);
-+}
-+
-+/*
-+ * ext2_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext2_xattr_put_super(struct super_block *sb)
-+{
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+ mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
-+#endif
-+}
-+
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+
-+/*
-+ * ext2_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
-+ext2_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(ext2_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(&ext2_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext2_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext2_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
-+ext2_xattr_cmp(struct ext2_xattr_header *header1,
-+ struct ext2_xattr_header *header2)
-+{
-+ struct ext2_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 = EXT2_XATTR_NEXT(entry1);
-+ entry2 = EXT2_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext2_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 *
-+ext2_xattr_cache_find(struct inode *inode, struct ext2_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(ext2_xattr_cache, 0, inode->i_dev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext2_error(inode->i_sb, "ext2_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT2_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT2_XATTR_REFCOUNT_MAX);
-+ } else if (!ext2_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;
-+}
-+
-+/*
-+ * ext2_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext2_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext2_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
-+
-+/*
-+ * ext2_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
-+ struct ext2_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) +
-+ EXT2_XATTR_ROUND) >> EXT2_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
-+
-+/*
-+ * ext2_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext2_xattr_rehash(struct ext2_xattr_header *header,
-+ struct ext2_xattr_entry *entry)
-+{
-+ struct ext2_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext2_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 = EXT2_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+
-+int __init
-+init_ext2_xattr(void)
-+{
-+ ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 61);
-+ if (!ext2_xattr_cache)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext2_xattr(void)
-+{
-+ mb_cache_destroy(ext2_xattr_cache);
-+}
-+
-+#else /* CONFIG_EXT2_FS_XATTR_SHARING */
-+
-+int __init
-+init_ext2_xattr(void)
-+{
-+ return 0;
-+}
-+
-+void
-+exit_ext2_xattr(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/ext2/xattr_user.c 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,103 @@
-+/*
-+ * linux/fs/ext2/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/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-+
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+# include <linux/ext2_acl.h>
-+#endif
-+
-+#define XATTR_USER_PREFIX "user."
-+
-+static size_t
-+ext2_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);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return prefix_len + name_len + 1;
-+}
-+
-+static int
-+ext2_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 -ENOTSUP;
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+ error = ext2_permission_locked(inode, MAY_READ);
-+#else
-+ error = permission(inode, MAY_READ);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
-+ buffer, size);
-+}
-+
-+static int
-+ext2_xattr_user_set(struct inode *inode, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -ENOTSUP;
-+ if ( !S_ISREG(inode->i_mode) &&
-+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-+ return -EPERM;
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+ error = ext2_permission_locked(inode, MAY_WRITE);
-+#else
-+ error = permission(inode, MAY_WRITE);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
-+ value, size, flags);
-+}
-+
-+struct ext2_xattr_handler ext2_xattr_user_handler = {
-+ prefix: XATTR_USER_PREFIX,
-+ list: ext2_xattr_user_list,
-+ get: ext2_xattr_user_get,
-+ set: ext2_xattr_user_set,
-+};
-+
-+int __init
-+init_ext2_xattr_user(void)
-+{
-+ return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
-+ &ext2_xattr_user_handler);
-+}
-+
-+void
-+exit_ext2_xattr_user(void)
-+{
-+ ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
-+ &ext2_xattr_user_handler);
-+}
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/ext3/ext3-exports.c 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,13 @@
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
-+
-+EXPORT_SYMBOL(ext3_force_commit);
-+EXPORT_SYMBOL(ext3_bread);
-+EXPORT_SYMBOL(ext3_xattr_register);
-+EXPORT_SYMBOL(ext3_xattr_unregister);
-+EXPORT_SYMBOL(ext3_xattr_get);
-+EXPORT_SYMBOL(ext3_xattr_list);
-+EXPORT_SYMBOL(ext3_xattr_set);
---- linux-2.4.22-ac1/fs/ext3/file.c~xattr-0.8.54-2.4.22-rh 2003-09-25 14:55:12.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/file.c 2003-09-25 23:57:02.000000000 +0400
-@@ -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>
-
-@@ -127,5 +128,9 @@ struct file_operations ext3_file_operati
- 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 */
- };
-
---- linux-2.4.22-ac1/fs/ext3/ialloc.c~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/ialloc.c 2003-09-25 23:57:02.000000000 +0400
-@@ -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>
-@@ -217,6 +218,7 @@ void ext3_free_inode (handle_t *handle,
- * 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);
-
---- linux-2.4.22-ac1/fs/ext3/inode.c~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/inode.c 2003-09-26 00:10:09.000000000 +0400
-@@ -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 = inode->u.ext3_i.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)
- {
-@@ -179,9 +191,7 @@ void ext3_delete_inode (struct inode * i
- {
- 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();
-@@ -1874,6 +1884,8 @@ void ext3_truncate(struct inode * inode)
- 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;
-
-@@ -2021,8 +2033,6 @@ int ext3_get_inode_loc (struct inode *in
- 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(
-@@ -2163,10 +2173,7 @@ void ext3_read_inode(struct inode * inod
- inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-
-- 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;
-@@ -2174,15 +2181,17 @@ void ext3_read_inode(struct inode * inod
- 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]));
-+ }
- brelse(iloc.bh);
- ext3_set_inode_flags(inode);
- return;
---- linux-2.4.22-ac1/fs/ext3/Makefile~xattr-0.8.54-2.4.22-rh 2003-09-25 14:55:12.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/Makefile 2003-09-25 23:57:02.000000000 +0400
-@@ -1,5 +1,5 @@
- #
--# Makefile for the linux ext2-filesystem routines.
-+# Makefile for the linux ext3-filesystem routines.
- #
- # Note! Dependencies are done automagically by 'make dep', which also
- # removes any old dependencies. DON'T put your own dependencies here
-@@ -9,10 +9,14 @@
-
- O_TARGET := ext3.o
-
--export-objs := super.o inode.o
-+export-objs := ext3-exports.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 hash.o
-+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
- obj-m := $(O_TARGET)
-
-+export-objs += xattr.o
-+obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
-+obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
-+
- include $(TOPDIR)/Rules.make
---- linux-2.4.22-ac1/fs/ext3/namei.c~xattr-0.8.54-2.4.22-rh 2003-09-25 14:58:37.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/namei.c 2003-09-25 23:57:02.000000000 +0400
-@@ -29,6 +29,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>
-@@ -1614,7 +1615,7 @@ static int ext3_mkdir(struct inode * dir
- 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;
-@@ -1622,7 +1623,6 @@ static int ext3_mkdir(struct inode * dir
- 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? */
-@@ -1649,9 +1649,6 @@ static int ext3_mkdir(struct inode * dir
- 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) {
-@@ -2020,7 +2017,7 @@ static int ext3_symlink (struct inode *
- 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;
- inode->i_mapping->a_ops = &ext3_aops;
- /*
- * block_symlink() calls back into ext3_prepare/commit_write.
-@@ -2245,4 +2242,16 @@ struct inode_operations ext3_dir_inode_o
- 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 */
-+};
-+
---- linux-2.4.22-ac1/fs/ext3/super.c~xattr-0.8.54-2.4.22-rh 2003-09-25 14:55:12.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/super.c 2003-09-26 00:12:23.000000000 +0400
-@@ -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>
-@@ -406,6 +407,7 @@ void ext3_put_super (struct super_block
- 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);
-@@ -506,6 +508,7 @@ static int parse_options (char * options
- 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;
-@@ -518,6 +521,13 @@ static int parse_options (char * options
- this_char = strtok (NULL, ",")) {
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT3_FS_XATTR_USER
-+ 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")) {
-@@ -935,6 +945,12 @@ struct super_block * ext3_read_super (st
- 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_USER
-+ /* set_opt(sbi->s_mount_opt, XATTR_USER); */
-+#endif
-+
- if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
- sb->s_dev = 0;
- goto out_fail;
-@@ -1839,22 +1855,35 @@ static DECLARE_FSTYPE_DEV(ext3_fs_type,
-
- static int __init init_ext3_fs(void)
- {
-+ int error;
- #ifdef CONFIG_QUOTA
- init_dquot_operations(&ext3_qops);
- old_sync_dquot = ext3_qops.sync_dquot;
- ext3_qops.sync_dquot = ext3_sync_dquot;
- #endif
-- return register_filesystem(&ext3_fs_type);
-+ error = init_ext3_xattr();
-+ if (error)
-+ return error;
-+ error = init_ext3_xattr_user();
-+ if (error)
-+ goto fail;
-+ error = register_filesystem(&ext3_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext3_xattr_user();
-+fail:
-+ exit_ext3_xattr();
-+ return error;
- }
-
- static void __exit exit_ext3_fs(void)
- {
- unregister_filesystem(&ext3_fs_type);
-+ exit_ext3_xattr_user();
-+ exit_ext3_xattr();
- }
-
--EXPORT_SYMBOL(ext3_force_commit);
--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");
- MODULE_LICENSE("GPL");
---- linux-2.4.22-ac1/fs/ext3/symlink.c~xattr-0.8.54-2.4.22-rh 2001-11-10 01:25:04.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/ext3/symlink.c 2003-09-25 23:57:02.000000000 +0400
-@@ -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 @@ static int ext3_follow_link(struct dentr
- 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 */
- };
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/ext3/xattr.c 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,1225 @@
-+/*
-+ * 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/module.h>
-+#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>
-+#include <linux/mbcache.h>
-+#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) while(0) {}
-+# define ext3_xattr_rehash(header, entry) 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 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,
-+ const 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);
-+ }
-+
-+ 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);
-+ }
-+ 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, 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 block = EXT3_I(inode)->i_file_acl;
-+ 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 (block) {
-+ /* The inode already has an extended attribute block. */
-+ 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);
-+ 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 (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;
-+ (void)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);
-+ (void)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_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_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);
-+ 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)
-+{
-+#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 */
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/ext3/xattr_user.c 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,111 @@
-+/*
-+ * 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/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_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);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return prefix_len + name_len + 1;
-+}
-+
-+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 -ENOTSUP;
-+#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 -ENOTSUP;
-+ 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;
-+
-+ 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);
-+
-+ 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,
-+};
-+
-+int __init
-+init_ext3_xattr_user(void)
-+{
-+ return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
-+ &ext3_xattr_user_handler);
-+}
-+
-+void
-+exit_ext3_xattr_user(void)
-+{
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
-+ &ext3_xattr_user_handler);
-+}
---- linux-2.4.22-ac1/fs/jfs/jfs_xattr.h~xattr-0.8.54-2.4.22-rh 2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/jfs/jfs_xattr.h 2003-09-25 23:57:02.000000000 +0400
-@@ -52,8 +52,10 @@ struct jfs_ea_list {
- #define END_EALIST(ealist) \
- ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
-
--extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
--extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
-+extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
-+ int);
-+extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
-+ int);
- extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
- extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
- extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
---- linux-2.4.22-ac1/fs/jfs/xattr.c~xattr-0.8.54-2.4.22-rh 2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/jfs/xattr.c 2003-09-25 23:57:02.000000000 +0400
-@@ -641,7 +641,7 @@ static int ea_put(struct inode *inode, s
- }
-
- static int can_set_xattr(struct inode *inode, const char *name,
-- void *value, size_t value_len)
-+ const void *value, size_t value_len)
- {
- if (IS_RDONLY(inode))
- return -EROFS;
-@@ -660,7 +660,7 @@ static int can_set_xattr(struct inode *i
- return permission(inode, MAY_WRITE);
- }
-
--int __jfs_setxattr(struct inode *inode, const char *name, void *value,
-+int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
- size_t value_len, int flags)
- {
- struct jfs_ea_list *ealist;
-@@ -799,7 +799,7 @@ int __jfs_setxattr(struct inode *inode,
- return rc;
- }
-
--int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
-+int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
- size_t value_len, int flags)
- {
- if (value == NULL) { /* empty EA, do not remove */
---- linux-2.4.22-ac1/fs/Makefile~xattr-0.8.54-2.4.22-rh 2003-09-25 14:50:00.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/Makefile 2003-09-25 23:57:02.000000000 +0400
-@@ -82,6 +82,9 @@ obj-y += binfmt_script.o
-
- obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
-
-+export-objs += mbcache.o
-+obj-$(CONFIG_FS_MBCACHE) += mbcache.o
-+
- # persistent filesystems
- obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
-
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/mbcache.c 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,648 @@
-+/*
-+ * 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. Entries that cannot be freed immediately are put
-+ * back on the lru list.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/cache_def.h>
-+#include <linux/version.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)");
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-+MODULE_LICENSE("GPL");
-+#endif
-+
-+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 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 void
-+mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
-+
-+static struct cache_definition mb_cache_definition = {
-+ "mb_cache",
-+ mb_cache_memory_pressure
-+};
-+
-+
-+static inline int
-+__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
-+{
-+ return !list_empty(&ce->e_block_list);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_unhash(struct mb_cache_entry *ce)
-+{
-+ int n;
-+
-+ if (__mb_cache_entry_is_hashed(ce)) {
-+ 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 void
-+__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+
-+ mb_assert(atomic_read(&ce->e_used) == 0);
-+ if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
-+ /* free failed -- put back on the lru list
-+ for freeing later. */
-+ spin_lock(&mb_cache_spinlock);
-+ list_add(&ce->e_lru_list, &mb_cache_lru_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ } else {
-+ kmem_cache_free(cache->c_entry_cache, ce);
-+ atomic_dec(&cache->c_entry_count);
-+ }
-+}
-+
-+
-+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_hashed(ce))
-+ list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
-+ else {
-+ spin_unlock(&mb_cache_spinlock);
-+ __mb_cache_entry_forget(ce, GFP_KERNEL);
-+ return;
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+}
-+
-+
-+/*
-+ * mb_cache_memory_pressure() memory pressure callback
-+ *
-+ * This function is called by the kernel memory management when memory
-+ * gets low.
-+ *
-+ * @priority: Amount by which to shrink the cache (0 = highes priority)
-+ * @gfp_mask: (ignored)
-+ */
-+static void
-+mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l, *ltmp;
-+ int count = 0;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(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 of %d entries",
-+ count / (priority ? priority : 1), count);
-+ if (priority)
-+ count /= priority;
-+ while (count-- && !list_empty(&mb_cache_lru_list)) {
-+ struct mb_cache_entry *ce =
-+ list_entry(mb_cache_lru_list.next,
-+ struct mb_cache_entry, e_lru_list);
-+ list_del(&ce->e_lru_list);
-+ __mb_cache_entry_unhash(ce);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), gfp_mask);
-+ }
-+}
-+
-+
-+/*
-+ * 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_count: 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_count)
-+{
-+ int m=0, n;
-+ struct mb_cache *cache = NULL;
-+
-+ if(entry_size < sizeof(struct mb_cache_entry) +
-+ indexes_count * sizeof(struct mb_cache_entry_index))
-+ return NULL;
-+
-+ MOD_INC_USE_COUNT;
-+ cache = kmalloc(sizeof(struct mb_cache) +
-+ indexes_count * sizeof(struct list_head), GFP_KERNEL);
-+ if (!cache)
-+ goto fail;
-+ cache->c_name = name;
-+ cache->c_op.free = NULL;
-+ if (cache_op)
-+ cache->c_op.free = cache_op->free;
-+ atomic_set(&cache->c_entry_count, 0);
-+ cache->c_bucket_count = bucket_count;
-+#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);
-+ 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);
-+ }
-+ MOD_DEC_USE_COUNT;
-+ 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.
-+ *
-+ * @cache: which cache to shrink
-+ * @dev: which device's cache entries to shrink
-+ */
-+void
-+mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l, *ltmp;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ if (ce->e_dev == dev) {
-+ list_del(&ce->e_lru_list);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ __mb_cache_entry_unhash(ce);
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), GFP_KERNEL);
-+ }
-+}
-+
-+
-+/*
-+ * 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, *ltmp;
-+ int n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ if (ce->e_cache == cache) {
-+ list_del(&ce->e_lru_list);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ __mb_cache_entry_unhash(ce);
-+ }
-+ }
-+ list_del(&cache->c_cache_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), GFP_KERNEL);
-+ }
-+
-+ if (atomic_read(&cache->c_entry_count) > 0) {
-+ mb_error("cache %s: %d orphaned entries",
-+ cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ }
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
-+ /* We don't have kmem_cache_destroy() in 2.2.x */
-+ kmem_cache_shrink(cache->c_entry_cache);
-+#else
-+ kmem_cache_destroy(cache->c_entry_cache);
-+#endif
-+ for (n=0; n < mb_cache_indexes(cache); n++)
-+ kfree(cache->c_indexes_hash[n]);
-+ kfree(cache->c_block_hash);
-+ kfree(cache);
-+
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+
-+/*
-+ * 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, if another process has
-+ * inserted the same cache entry in the meantime).
-+ *
-+ * @dev: 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, kdev_t dev,
-+ unsigned long block, unsigned int keys[])
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
-+ struct list_head *l;
-+ int error = -EBUSY, n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(l, &cache->c_block_hash[bucket]) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_dev == dev && ce->e_block == block)
-+ goto out;
-+ }
-+ __mb_cache_entry_unhash(ce);
-+ ce->e_dev = dev;
-+ ce->e_block = block;
-+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
-+ for (n=0; n<mb_cache_indexes(cache); n++) {
-+ ce->e_indexes[n].o_key = keys[n];
-+ bucket = keys[n] % cache->c_bucket_count;
-+ list_add(&ce->e_indexes[n].o_list,
-+ &cache->c_indexes_hash[n][bucket]);
-+ }
-+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(list_empty(&ce->e_lru_list));
-+ __mb_cache_entry_unhash(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(list_empty(&ce->e_lru_list));
-+ __mb_cache_entry_unhash(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, kdev_t dev, unsigned long block)
-+{
-+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ 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_dev == dev && ce->e_block == block) {
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+ atomic_inc(&ce->e_used);
-+ 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, kdev_t dev, 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_dev == dev && ce->e_indexes[index].o_key == key) {
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+ atomic_inc(&ce->e_used);
-+ 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)
-+ * @dev: 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, kdev_t dev,
-+ unsigned int key)
-+{
-+ unsigned int bucket = key % cache->c_bucket_count;
-+ 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, dev, 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)
-+ * @dev: 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, kdev_t dev,
-+ unsigned int key)
-+{
-+ struct mb_cache *cache = prev->e_cache;
-+ unsigned int bucket = key % cache->c_bucket_count;
-+ 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, dev, key);
-+ __mb_cache_entry_release_unlock(prev);
-+ return ce;
-+}
-+
-+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
-+
-+static int __init init_mbcache(void)
-+{
-+ register_cache(&mb_cache_definition);
-+ return 0;
-+}
-+
-+static void __exit exit_mbcache(void)
-+{
-+ unregister_cache(&mb_cache_definition);
-+}
-+
-+module_init(init_mbcache)
-+module_exit(exit_mbcache)
-+
---- linux-2.4.22-ac1/include/asm-arm/unistd.h~xattr-0.8.54-2.4.22-rh 2003-08-25 15:44:43.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/asm-arm/unistd.h 2003-09-25 23:57:02.000000000 +0400
-@@ -250,7 +250,6 @@
- #define __NR_security (__NR_SYSCALL_BASE+223)
- #define __NR_gettid (__NR_SYSCALL_BASE+224)
- #define __NR_readahead (__NR_SYSCALL_BASE+225)
--#if 0 /* allocated in 2.5 */
- #define __NR_setxattr (__NR_SYSCALL_BASE+226)
- #define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
- #define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
-@@ -263,7 +262,6 @@
- #define __NR_removexattr (__NR_SYSCALL_BASE+235)
- #define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
- #define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
--#endif
- #define __NR_tkill (__NR_SYSCALL_BASE+238)
- #if 0 /* allocated in 2.5 */
- #define __NR_sendfile64 (__NR_SYSCALL_BASE+239)
---- linux-2.4.22-ac1/include/asm-ppc64/unistd.h~xattr-0.8.54-2.4.22-rh 2003-06-13 18:51:38.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/asm-ppc64/unistd.h 2003-09-25 23:57:02.000000000 +0400
-@@ -218,6 +218,7 @@
- #define __NR_mincore 206
- #define __NR_gettid 207
- #define __NR_tkill 208
-+#endif
- #define __NR_setxattr 209
- #define __NR_lsetxattr 210
- #define __NR_fsetxattr 211
-@@ -230,6 +231,7 @@
- #define __NR_removexattr 218
- #define __NR_lremovexattr 219
- #define __NR_fremovexattr 220
-+#if 0 /* Reserved syscalls */
- #define __NR_futex 221
- #define __NR_sched_setaffinity 222
- #define __NR_sched_getaffinity 223
---- linux-2.4.22-ac1/include/asm-s390/unistd.h~xattr-0.8.54-2.4.22-rh 2003-06-13 18:51:38.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/asm-s390/unistd.h 2003-09-26 00:14:23.000000000 +0400
-@@ -213,6 +213,19 @@
- #define __NR_getdents64 220
- #define __NR_fcntl64 221
- #define __NR_readahead 222
-+#define __NR_setxattr 224
-+#define __NR_lsetxattr 225
-+#define __NR_fsetxattr 226
-+#define __NR_getxattr 227
-+#define __NR_lgetxattr 228
-+#define __NR_fgetxattr 229
-+#define __NR_listxattr 230
-+#define __NR_llistxattr 231
-+#define __NR_flistxattr 232
-+#define __NR_removexattr 233
-+#define __NR_lremovexattr 234
-+#define __NR_fremovexattr 235
-+
- /*
- * Numbers 224-235 are reserved for posix acl
- */
---- linux-2.4.22-ac1/include/asm-s390x/unistd.h~xattr-0.8.54-2.4.22-rh 2003-06-13 18:51:38.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/asm-s390x/unistd.h 2003-09-26 00:15:11.000000000 +0400
-@@ -181,6 +181,19 @@
- #define __NR_mincore 218
- #define __NR_madvise 219
- #define __NR_readahead 222
-+#define __NR_setxattr 224
-+#define __NR_lsetxattr 225
-+#define __NR_fsetxattr 226
-+#define __NR_getxattr 227
-+#define __NR_lgetxattr 228
-+#define __NR_fgetxattr 229
-+#define __NR_listxattr 230
-+#define __NR_llistxattr 231
-+#define __NR_flistxattr 232
-+#define __NR_removexattr 233
-+#define __NR_lremovexattr 234
-+#define __NR_fremovexattr 235
-+
- /*
- * Numbers 224-235 are reserved for posix acl
- */
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/include/linux/cache_def.h 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,15 @@
-+/*
-+ * linux/cache_def.h
-+ * Handling of caches defined in drivers, filesystems, ...
-+ *
-+ * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+struct cache_definition {
-+ const char *name;
-+ void (*shrink)(int, unsigned int);
-+ struct list_head link;
-+};
-+
-+extern void register_cache(struct cache_definition *);
-+extern void unregister_cache(struct cache_definition *);
---- linux-2.4.22-ac1/include/linux/errno.h~xattr-0.8.54-2.4.22-rh 2001-02-10 01:46:13.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/include/linux/errno.h 2003-09-25 23:57:02.000000000 +0400
-@@ -23,4 +23,8 @@
-
- #endif
-
-+/* Defined for extended attributes */
-+#define ENOATTR ENODATA /* No such attribute */
-+#define ENOTSUP EOPNOTSUPP /* Operation not supported */
-+
- #endif
---- linux-2.4.22-ac1/include/linux/ext2_fs.h~xattr-0.8.54-2.4.22-rh 2003-06-13 18:51:38.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext2_fs.h 2003-09-25 23:57:02.000000000 +0400
-@@ -57,8 +57,6 @@
- */
- #define EXT2_BAD_INO 1 /* Bad blocks inode */
- #define EXT2_ROOT_INO 2 /* Root inode */
--#define EXT2_ACL_IDX_INO 3 /* ACL inode */
--#define EXT2_ACL_DATA_INO 4 /* ACL inode */
- #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
-
-@@ -86,7 +84,6 @@
- #else
- # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
- #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -121,28 +118,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext2_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext2_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 ext2_group_desc
-@@ -314,6 +289,7 @@ struct ext2_inode {
- #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
- #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
- #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
-+#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-
- #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
- #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
-@@ -397,6 +373,7 @@ struct ext2_super_block {
-
- #ifdef __KERNEL__
- #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
-+#define EXT2_I(inode) (&((inode)->u.ext2_i))
- #else
- /* Assume that user mode programs are passing in an ext2fs superblock, not
- * a kernel struct super_block. This will allow us to call the feature-test
-@@ -466,7 +443,7 @@ struct ext2_super_block {
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
- #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
-
--#define EXT2_FEATURE_COMPAT_SUPP 0
-+#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
- #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
-@@ -624,8 +601,10 @@ extern struct address_space_operations e
-
- /* namei.c */
- extern struct inode_operations ext2_dir_inode_operations;
-+extern struct inode_operations ext2_special_inode_operations;
-
- /* symlink.c */
-+extern struct inode_operations ext2_symlink_inode_operations;
- extern struct inode_operations ext2_fast_symlink_inode_operations;
-
- #endif /* __KERNEL__ */
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/include/linux/ext2_xattr.h 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,157 @@
-+/*
-+ File: linux/ext2_xattr.h
-+
-+ On-disk format of extended attributes for the ext2 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 EXT2_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT2_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT2_XATTR_INDEX_MAX 10
-+#define EXT2_XATTR_INDEX_USER 1
-+#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
-+#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+
-+struct ext2_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 ext2_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 EXT2_XATTR_PAD_BITS 2
-+#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
-+#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
-+#define EXT2_XATTR_LEN(name_len) \
-+ (((name_len) + EXT2_XATTR_ROUND + \
-+ sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
-+#define EXT2_XATTR_NEXT(entry) \
-+ ( (struct ext2_xattr_entry *)( \
-+ (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT2_XATTR_SIZE(size) \
-+ (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
-+
-+#ifdef __KERNEL__
-+
-+# ifdef CONFIG_EXT2_FS_XATTR
-+
-+struct ext2_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 ext2_xattr_register(int, struct ext2_xattr_handler *);
-+extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
-+
-+extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
-+extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
-+extern int ext2_removexattr(struct dentry *, const char *);
-+
-+extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext2_xattr_list(struct inode *, char *, size_t);
-+extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
-+
-+extern void ext2_xattr_delete_inode(struct inode *);
-+extern void ext2_xattr_put_super(struct super_block *);
-+
-+extern int init_ext2_xattr(void) __init;
-+extern void exit_ext2_xattr(void);
-+
-+# else /* CONFIG_EXT2_FS_XATTR */
-+# define ext2_setxattr NULL
-+# define ext2_getxattr NULL
-+# define ext2_listxattr NULL
-+# define ext2_removexattr NULL
-+
-+static inline int
-+ext2_xattr_get(struct inode *inode, int name_index,
-+ const char *name, void *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext2_xattr_set(struct inode *inode, int name_index, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline void
-+ext2_xattr_delete_inode(struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext2_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext2_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext2_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT2_FS_XATTR */
-+
-+# ifdef CONFIG_EXT2_FS_XATTR_USER
-+
-+extern int init_ext2_xattr_user(void) __init;
-+extern void exit_ext2_xattr_user(void);
-+
-+# else /* CONFIG_EXT2_FS_XATTR_USER */
-+
-+static inline int
-+init_ext2_xattr_user(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext2_xattr_user(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT2_FS_XATTR_USER */
-+
-+#endif /* __KERNEL__ */
-+
---- linux-2.4.22-ac1/include/linux/ext3_fs.h~xattr-0.8.54-2.4.22-rh 2003-09-25 14:58:30.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs.h 2003-09-25 23:57:02.000000000 +0400
-@@ -63,8 +63,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 */
-@@ -94,7 +92,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)
-@@ -129,28 +126,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
-@@ -346,6 +321,7 @@ struct ext3_inode {
- #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
-@@ -523,7 +499,7 @@ struct ext3_super_block {
- #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| \
-@@ -707,6 +683,7 @@ extern void ext3_check_inodes_bitmap (st
- 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 *);
-
-@@ -776,8 +753,10 @@ extern struct address_space_operations e
-
- /* 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;
-
-
---- linux-2.4.22-ac1/include/linux/ext3_jbd.h~xattr-0.8.54-2.4.22-rh 2003-09-25 14:55:12.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_jbd.h 2003-09-25 23:57:02.000000000 +0400
-@@ -30,13 +30,19 @@
-
- #define EXT3_SINGLEDATA_TRANS_BLOCKS 8U
-
-+/* 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);
-
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_xattr.h 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,157 @@
-+/*
-+ 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
-+#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 __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, 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 *, const 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) __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)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+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 -ENOTSUP;
-+}
-+
-+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 */
-+
-+# 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__ */
-+
---- linux-2.4.22-ac1/include/linux/fs.h~xattr-0.8.54-2.4.22-rh 2003-09-25 14:45:32.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/fs.h 2003-09-25 23:57:02.000000000 +0400
-@@ -918,7 +918,7 @@ struct inode_operations {
- int (*setattr) (struct dentry *, struct iattr *);
- int (*setattr_raw) (struct inode *, struct iattr *);
- int (*getattr) (struct dentry *, struct iattr *);
-- int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
-+ int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
- ssize_t (*listxattr) (struct dentry *, char *, size_t);
- int (*removexattr) (struct dentry *, const char *);
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/include/linux/mbcache.h 2003-09-25 23:57:02.000000000 +0400
-@@ -0,0 +1,69 @@
-+/*
-+ 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 {
-+ int (*free)(struct mb_cache_entry *, int);
-+};
-+
-+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_count;
-+#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;
-+ kdev_t e_dev;
-+ unsigned long 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 *, kdev_t);
-+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 *, kdev_t, unsigned long,
-+ 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 *, kdev_t,
-+ unsigned long);
-+#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,
-+ kdev_t, unsigned int);
-+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
-+ kdev_t, unsigned int);
-+#endif
---- linux-2.4.22-ac1/kernel/ksyms.c~xattr-0.8.54-2.4.22-rh 2003-09-25 14:42:46.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/kernel/ksyms.c 2003-09-26 00:19:05.000000000 +0400
-@@ -11,6 +11,7 @@
-
- #include <linux/config.h>
- #include <linux/slab.h>
-+#include <linux/cache_def.h>
- #include <linux/smp.h>
- #include <linux/module.h>
- #include <linux/blkdev.h>
-@@ -106,6 +107,7 @@ EXPORT_SYMBOL(exit_files);
- EXPORT_SYMBOL(exit_fs);
- EXPORT_SYMBOL(exit_sighand);
- EXPORT_SYMBOL(unshare_files);
-+EXPORT_SYMBOL(copy_fs_struct);
-
- /* internal kernel memory management */
- EXPORT_SYMBOL(_alloc_pages);
-@@ -124,6 +126,8 @@ EXPORT_SYMBOL(kmem_cache_validate);
- EXPORT_SYMBOL(kmem_cache_alloc);
- EXPORT_SYMBOL(kmem_cache_free);
- EXPORT_SYMBOL(kmem_cache_size);
-+EXPORT_SYMBOL(register_cache);
-+EXPORT_SYMBOL(unregister_cache);
- EXPORT_SYMBOL(kmalloc);
- EXPORT_SYMBOL(kfree);
- EXPORT_SYMBOL(vfree);
---- linux-2.4.22-ac1/mm/vmscan.c~xattr-0.8.54-2.4.22-rh 2003-09-25 14:16:28.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/mm/vmscan.c 2003-09-25 23:57:02.000000000 +0400
-@@ -18,6 +18,7 @@
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
- #include <linux/swapctl.h>
-+#include <linux/cache_def.h>
- #include <linux/smp_lock.h>
- #include <linux/pagemap.h>
- #include <linux/init.h>
-@@ -34,6 +35,39 @@
- */
- #define DEF_PRIORITY (6)
-
-+static DECLARE_MUTEX(other_caches_sem);
-+static LIST_HEAD(cache_definitions);
-+
-+void register_cache(struct cache_definition *cache)
-+{
-+ down(&other_caches_sem);
-+ list_add(&cache->link, &cache_definitions);
-+ up(&other_caches_sem);
-+}
-+
-+void unregister_cache(struct cache_definition *cache)
-+{
-+ down(&other_caches_sem);
-+ list_del(&cache->link);
-+ up(&other_caches_sem);
-+}
-+
-+static void shrink_other_caches(unsigned int priority, int gfp_mask)
-+{
-+ struct list_head *p;
-+
-+ if (down_trylock(&other_caches_sem))
-+ return;
-+
-+ list_for_each_prev(p, &cache_definitions) {
-+ struct cache_definition *cache =
-+ list_entry(p, struct cache_definition, link);
-+
-+ cache->shrink(priority, gfp_mask);
-+ }
-+ up(&other_caches_sem);
-+}
-+
- /*
- * The swap-out function returns 1 if it successfully
- * scanned all the pages it was asked to (`count').
-@@ -577,6 +611,7 @@ static int shrink_caches(zone_t * classz
-
- shrink_dcache_memory(priority, gfp_mask);
- shrink_icache_memory(priority, gfp_mask);
-+ shrink_other_caches(priority, gfp_mask);
- #ifdef CONFIG_QUOTA
- shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
- #endif
-
-_
8kstack-2.6-rhel4.patch
remove-suid-2.6-suse.patch
export-show_task-2.6-vanilla.patch
+sd_iostats-2.6-rhel4.patch
+dev_read_only-2.6-lnxi.patch
sd_iostats-2.6-suse.patch
blkdev_tunables-2.6-suse.patch
bluesmoke-2.6-suse-lnxi.patch
+++ /dev/null
-uml-2.6.7-01-bb2.patch
-lustre_version.patch
-vfs_intent-2.6-vanilla.patch
-vfs_nointent-2.6-vanilla.patch
-vfs_races-2.6-vanilla.patch
-ext3-wantedi-misc-2.6-suse.patch
-nfs-cifs-intent-2.6-vanilla.patch
-iopen-misc-2.6-suse.patch
-export-truncate-2.6-suse.patch
-export_symbols-2.6-suse.patch
-dev_read_only-2.6-suse.patch
-export-2.6-suse.patch
-header-guards-2.6-suse.patch
-lookup_bdev_init_intent.patch
-ext3-super-ntohl.patch
configurable-x86-stack-2.4.20.patch
-dev_read_only_hp_2.4.20.patch
+dev_read_only_2.4.20-rh.patch
exports_2.4.20-rh-hp.patch
lustre_version.patch
vfs_intent-2.4.20-hp.patch
dcache_refcount_debug.patch
ext3-extents-2.4.24.patch
ext3-extents-asyncdel-2.4.24.patch
-ext3-mballoc-2.4.24.patch
ext3-nlinks-2.4.20-hp_pnnl.patch
export-zap-page-range.patch
+++ /dev/null
-ext3-wantedi-2.6-suse.patch
-ext3-san-jdike-2.6-suse.patch
-iopen-2.6-vanilla.patch
-export_symbols-ext3-2.6-suse.patch
-ext3-map_inode_page-2.6-suse.patch
-ext3-ea-in-inode-2.6-suse.patch
-export-ext3-2.6-suse.patch
-ext3-include-fixes-2.6-suse.patch
-ext3-extents-2.6.7.patch
-ext3-mballoc2-2.6.7.patch
-ext3-nlinks-2.6.7.patch
+++ /dev/null
-configurable-x86-stack-2.4.20-rh.patch
-mcore-2.4.20-8.patch
-dsp.patch
-dev_read_only_2.4.20-rh.patch
-exports_2.4.20-rh-hp.patch
-lustre_version.patch
-vfs_intent-2.4.20-rh.patch
-invalidate_show-2.4.20-rh.patch
-iod-rmap-exports-2.4.20.patch
-export-truncate.patch
-ext-2.4-patch-1-chaos.patch
-ext-2.4-patch-2.patch
-ext-2.4-patch-3.patch
-ext-2.4-patch-4.patch
-linux-2.4.20-xattr-0.8.54-chaos.patch
-ext3-2.4.20-fixes.patch
-ext3_orphan_lock-2.4.20-rh.patch
-ext3_delete_thread_2.4.20_chaos.patch
-ext3-noread-2.4.20.patch
-extN-wantedi.patch
-ext3-san-2.4.20.patch
-ext3-map_inode_page.patch
-ext3-error-export.patch
-iopen-2.4.20.patch
-jbd-dont-account-blocks-twice.patch
-jbd-commit-tricks.patch
-ext3-o_direct-1.2.4.20-rh.patch
-ext3-no-write-super-chaos.patch
-dynamic-locks-2.4.20-rh.patch
-vfs-pdirops-2.4.20-rh.patch
-ext3-pdirops-2.4.20-rh.patch
-tcp_zero_copy_2.4.20_chaos.patch
-gpl_header-chaos-2.4.20.patch
-add_page_private.patch
-jbd-flushtime.patch
-jbd-get_write_access.patch
-nfs_export_kernel-2.4.20-rh.patch
-ext3-ea-in-inode-2.4.20.patch
-listman-2.4.20.patch
-ext3-trusted_ea-2.4.20.patch
-netconsole-2.4.20-rh.patch
-ext3-xattr-ptr-arith-fix.patch
-procfs-ndynamic-2.4.patch
-ext3-truncate-buffer-head.patch
-inode-max-readahead-2.4.24.patch
-mkdep-revert-rh-2.4.patch
-ext3-extents-2.4.20-rh.patch
-ext3-extents-asyncdel-2.4.20-rh.patch
-ext3-mballoc-2.4.24.patch
-x86-fpu-crash.patch
-export-show_task-2.4-rh.patch
-export-zap-page-range.patch
-grab_cache_page_nowait_gfp-rh-2.4.patch
+++ /dev/null
-configurable-x86-stack-2.4.22-rh.patch
-dev_read_only_2.4.20-rh.patch
-exports_2.4.20-rh-hp.patch
-lustre_version.patch
-vfs_intent-2.4.22-rh.patch
-invalidate_show-2.4.20-rh.patch
-export-truncate.patch
-iod-stock-exports-2.4.22-rh.patch
-ext3-htree-2.4.22-rh.patch
-xattr-0.8.54-2.4.22-rh.patch
-ext3-orphan_lock-2.4.22-rh.patch
-ext3-noread-2.4.20.patch
-ext3_delete_thread_2.4.20_chaos.patch
-extN-wantedi-2.4.22-rh.patch
-ext3-san-2.4.20.patch
-ext3-map_inode_page.patch
-ext3-error-export.patch
-iopen-2.4.20.patch
-tcp-zero-copy-2.4.22-rh.patch
-jbd-dont-account-blocks-twice.patch
-jbd-commit-tricks.patch
-add_page_private.patch
-socket-exports-2.4.22-rh.patch
-nfs_export_kernel-2.4.22-rh.patch
-ext3-ea-in-inode-2.4.22-rh.patch
-listman-2.4.20.patch
-ext3-trusted_ea-2.4.20.patch
-ext3-xattr-ptr-arith-fix.patch
-procfs-ndynamic-2.4.patch
-ext3-truncate-buffer-head.patch
+++ /dev/null
-dev_read_only_hp_2.4.20.patch
-exports_2.4.19-suse.patch
-lustre_version.patch
-vfs_intent-2.4.19-suse.patch
-invalidate_show.patch
-export-truncate.patch
-iod-stock-24-exports-2.4.19-suse.patch
-jbd-2.4.18-jcberr.patch
-ext-2.4-patch-1-chaos.patch
-ext-2.4-patch-2.patch
-ext-2.4-patch-3.patch
-ext-2.4-patch-4.patch
-linux-2.4.19-xattr-0.8.54-suse.patch
-ext3-2.4-ino_t.patch
-ext3-largefile.patch
-ext3-truncate_blocks.patch
-ext3-use-after-free-suse.patch
-ext3-orphan_lock-2.4.19-suse.patch
-ext3-delete_thread-2.4.19-suse.patch
-ext3-noread-2.4.20.patch
-extN-wantedi-2.4.19-suse.patch
-ext3-san-2.4.20.patch
-ext3-map_inode_page.patch
-ext3-error-export.patch
-iopen-2.4.19-suse.patch
-tcp-zero-copy.patch
-add_page_private.patch
-removepage-2.4.19-suse.patch
-jbd-ctx_switch.patch
-jbd-flushtime-2.4.19-suse.patch
-jbd-get_write_access.patch
-ext3-ea-in-inode-2.4.20.patch
-listman-2.4.20.patch
-ext3-trusted_ea-2.4.20.patch
-ext3-truncate-buffer-head.patch
+++ /dev/null
-configurable-x86-stack-2.4.20.patch
-dev_read_only_2.4.20-rh.patch
-exports_2.4.20-rh-hp.patch
-lustre_version.patch
-vfs_intent-2.4.20-vanilla.patch
-invalidate_show.patch
-export-truncate.patch
-iod-stock-24-exports.patch
-ext3-htree-suse.patch
-linux-2.4.21-xattr-0.8.54-suse.patch
-ext3-orphan_lock-suse.patch
-ext3-noread-2.4.20.patch
-ext3-delete_thread-suse.patch
-extN-wantedi.patch
-ext3-san-2.4.20.patch
-ext3-map_inode_page.patch
-ext3-error-export.patch
-iopen-2.4.20.patch
-tcp-zero-copy-2.4.22-rh.patch
-jbd-dont-account-blocks-twice.patch
-jbd-commit-tricks.patch
-ext3-no-write-super-chaos.patch
-add_page_private.patch
-socket-exports-vanilla.patch
-nfs_export_kernel-2.4.20.patch
-ext3-raw-lookup.patch
-ext3-ea-in-inode-2.4.20.patch
-listman-2.4.20.patch
-ext3-trusted_ea-2.4.20.patch
-ext3-xattr-ptr-arith-fix.patch
-procfs-ndynamic-2.4.patch
-ext3-truncate-buffer-head.patch
add_page_private.patch
nfs_export_kernel-2.4.21-suse2.patch
ext3-raw-lookup.patch
-ext3-ea-in-inode-2.4.21-chaos.patch
+ext3-ea-in-inode-2.4.21-suse2.patch
listman-2.4.20.patch
ext3-xattr-ptr-arith-fix.patch
procfs-ndynamic-2.4.21-suse2.patch
inode-max-readahead-2.4.24.patch
ext3-extents-2.4.24.patch
ext3-extents-asyncdel-2.4.24.patch
-ext3-mballoc-2.4.24.patch
export_num_siblings.patch
ext3-nlinks-2.4.24.patch
export-show_task-2.4-vanilla.patch
--- /dev/null
+lnxmaj="2.6.9"
+lnxrel="5.0.3.EL"
+
+KERNEL=linux-${lnxmaj}-${lnxrel}.tar.bz2
+SERIES=2.6-rhel4.series
+VERSION=${lnxmaj}
+EXTRA_VERSION=${lnxrel}_lustre.@VERSION@
+RHBUILD=1
+LINUX26=1
+
+BASE_ARCHS="i686 x86_64 ia64"
+BIGMEM_ARCHS=""
+BOOT_ARCHS=""
+JENSEN_ARCHS=""
+SMP_ARCHS="i686 x86_64 ia64"
+UP_ARCHS=""
+
+# the modules in this kernel do not build with gcc 3.3 or 2.96
+for cc in gcc32 gcc33 ; do
+ if which $cc >/dev/null 2>/dev/null ; then
+ export CC=$cc
+ break
+ fi
+done
-SERIES MNEMONIC COMMENT ARCH
+SERIES MNEMONIC COMMENT ARCH
SUPPORTED KERNELS:
-rhel-2.4.21 linux-2.4.21-20.3EL all
-2.6-suse linux-2.6 SLES9 SP1 kernel all
+rhel-2.4.21 linux-2.4.21-20.3EL RHEL3 2.4.21 all
+2.6-suse linux-2.6-suse SLES9 SP1 kernel all
+2.6-rhel4 linux-2.6-rhel4 RHEL4 2.6.9 kernel i386,x86_64
UNSUPPORTED KERNELS; BEING PHASED OUT; MAY BE MISSING CRITICAL BUG FIXES:
-hp-pnnl-2.4.20 linux-2.4.20-hp4_pnnl1 same as vanilla but no uml ia64
-vanilla-2.4.24 linux-2.4.24 patch with uml-2.4.24-6 um
-suse-2.4.21-jvn linux-2.4.21-241 sles8 2.4 kernel i386
+hp-pnnl-2.4.20 linux-2.4.20-hp4_pnnl1 same as vanilla but no uml ia64
+vanilla-2.4.24 linux-2.4.24 patch with uml-2.4.24-6 um
+suse-2.4.21-jvn linux-2.4.21-241 sles8 2.4 kernel i386
}
-int client_obd_cleanup(struct obd_device *obddev, int flags)
+int client_obd_cleanup(struct obd_device *obddev)
{
struct client_obd *cli = &obddev->u.cli;
class_destroy_import(cli->cl_import);
cli->cl_import = NULL;
- ldlm_put_ref(flags & OBD_OPT_FORCE);
+ ldlm_put_ref(obddev->obd_force);
RETURN(0);
}
obd->obd_namespace = NULL;
out_disco:
cli->cl_conn_count--;
- class_disconnect(exp, 0);
+ class_disconnect(exp);
} else {
class_export_put(exp);
}
return rc;
}
-int client_disconnect_export(struct obd_export *exp, int failover)
+int client_disconnect_export(struct obd_export *exp)
{
struct obd_device *obd = class_exp2obd(exp);
struct client_obd *cli = &obd->u.cli;
EXIT;
out_no_disconnect:
- err = class_disconnect(exp, 0);
+ err = class_disconnect(exp);
if (!rc && err)
rc = err;
out_sem:
/* keep the rq_export around so we can send the reply */
exp = class_export_get(req->rq_export);
- req->rq_status = obd_disconnect(exp, 0);
+ req->rq_status = obd_disconnect(exp);
RETURN(0);
}
struct list_head *tmp, *n;
struct ptlrpc_request *req;
+ LASSERT(obd->obd_stopping);
+
spin_lock_bh(&obd->obd_processing_task_lock);
if (!obd->obd_recovering) {
spin_unlock_bh(&obd->obd_processing_task_lock);
target_cancel_recovery_timer(obd);
spin_unlock_bh(&obd->obd_processing_task_lock);
-
list_for_each_safe(tmp, n, &obd->obd_delayed_reply_queue) {
req = list_entry(tmp, struct ptlrpc_request, rq_list);
list_del(&req->rq_list);
CERROR("%s: recovery period over; disconnecting unfinished clients.\n",
obd->obd_name);
- class_disconnect_stale_exports(obd, 0);
+ class_disconnect_stale_exports(obd);
abort_recovery_queue(obd);
target_finish_recovery(obd);
LBUG();
memcpy(saved_req, req, sizeof *saved_req);
memcpy(reqmsg, req->rq_reqmsg, req->rq_reqlen);
+
+ /* Don't race cleanup */
+ spin_lock_bh(&obd->obd_processing_task_lock);
+ if (obd->obd_stopping) {
+ spin_unlock_bh(&obd->obd_processing_task_lock);
+ OBD_FREE(reqmsg, req->rq_reqlen);
+ OBD_FREE(saved_req, sizeof *req);
+ req->rq_status = -ENOTCONN;
+ /* rv is ignored anyhow */
+ return -ENOTCONN;
+ }
ptlrpc_rs_addref(req->rq_reply_state); /* +1 ref for saved reply */
req = saved_req;
req->rq_reqmsg = reqmsg;
class_export_get(req->rq_export);
list_add(&req->rq_list, &obd->obd_delayed_reply_queue);
- spin_lock_bh(&obd->obd_processing_task_lock);
/* only count the first "replay over" request from each
export */
if (req->rq_export->exp_replay_needed) {
recovery_done = (obd->obd_recoverable_clients == 0);
spin_unlock_bh(&obd->obd_processing_task_lock);
+ OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
if (recovery_done) {
spin_lock_bh(&obd->obd_processing_task_lock);
obd->obd_recovering = obd->obd_abort_recovery = 0;
lock = list_entry(waiting_locks_list.next, struct ldlm_lock,
l_pending_chain);
- if (lock->l_callback_timeout > jiffies)
+ if (time_after(lock->l_callback_timeout, jiffies))
break;
LDLM_ERROR(lock, "lock callback timer expired: evicting client "
timeout_rounded = round_timeout(lock->l_callback_timeout);
- if (timeout_rounded < waiting_locks_timer.expires ||
+ if (time_before(timeout_rounded, waiting_locks_timer.expires) ||
!timer_pending(&waiting_locks_timer)) {
mod_timer(&waiting_locks_timer, timeout_rounded);
}
}
}
+ if (dlm_req->lock_desc.l_resource.lr_type < LDLM_MIN_TYPE ||
+ dlm_req->lock_desc.l_resource.lr_type >= LDLM_MAX_TYPE) {
+ DEBUG_REQ(D_ERROR, req, "invalid lock request type %d\n",
+ dlm_req->lock_desc.l_resource.lr_type);
+ GOTO(out, rc = -EFAULT);
+ }
+
+ if (dlm_req->lock_desc.l_req_mode < LCK_EX ||
+ dlm_req->lock_desc.l_req_mode > LCK_NL ||
+ dlm_req->lock_desc.l_req_mode & (dlm_req->lock_desc.l_req_mode-1)) {
+ DEBUG_REQ(D_ERROR, req, "invalid lock request mode %d\n",
+ dlm_req->lock_desc.l_req_mode);
+ GOTO(out, rc = -EFAULT);
+ }
+
/* The lock's callback data might be set in the policy function */
lock = ldlm_lock_create(obddev->obd_namespace, &dlm_req->lock_handle2,
dlm_req->lock_desc.l_resource.lr_name,
lock_name[MAX_STRING_SIZE] = '\0';
memset(lock_vars, 0, sizeof(lock_vars));
- lock_vars[0].read_fptr = lprocfs_rd_u64;
lock_vars[0].name = lock_name;
snprintf(lock_name, MAX_STRING_SIZE, "%s/resource_count", ns->ns_name);
- lock_vars[0].data = &ns->ns_resources;
+ lock_vars[0].data = &ns->ns_refcount;
+ lock_vars[0].read_fptr = lprocfs_rd_atomic;
lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0);
snprintf(lock_name, MAX_STRING_SIZE, "%s/lock_count", ns->ns_name);
lock_vars[0].data = &ns->ns_locks;
+ lock_vars[0].read_fptr = lprocfs_rd_u64;
lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0);
if (ns->ns_client) {
INIT_LIST_HEAD(&ns->ns_root_list);
l_lock_init(&ns->ns_lock);
- ns->ns_refcount = 0;
+ init_waitqueue_head(&ns->ns_refcount_waitq);
+ atomic_set(&ns->ns_refcount, 0);
ns->ns_client = client;
spin_lock_init(&ns->ns_counter_lock);
ns->ns_locks = 0;
- ns->ns_resources = 0;
for (bucket = ns->ns_hash + RES_HASH_SIZE - 1; bucket >= ns->ns_hash;
bucket--)
cleanup_resource(res, &res->lr_converting, flags);
cleanup_resource(res, &res->lr_waiting, flags);
- /* XXX what a mess: don't force cleanup if we're
- * local_only (which is only used by recovery). In that
- * case, we probably still have outstanding lock refs
- * which reference these resources. -phil */
- if (!ldlm_resource_putref(res) &&
- !(flags & LDLM_FL_LOCAL_ONLY)) {
+ if (!ldlm_resource_putref(res)) {
CERROR("Namespace %s resource refcount %d "
- "after lock cleanup; forcing cleanup.\n",
+ "after lock cleanup\n",
ns->ns_name,
atomic_read(&res->lr_refcount));
- ldlm_resource_dump(D_ERROR, res);
- atomic_set(&res->lr_refcount, 1);
- ldlm_resource_putref(res);
}
}
}
}
#endif
+ if (atomic_read(&ns->ns_refcount) > 0) {
+ struct l_wait_info lwi = LWI_INTR(NULL, NULL);
+ int rc;
+ CDEBUG(D_DLMTRACE,
+ "dlm namespace %s free waiting on refcount %d\n",
+ ns->ns_name, atomic_read(&ns->ns_refcount));
+ rc = l_wait_event(ns->ns_refcount_waitq,
+ atomic_read(&ns->ns_refcount) == 0, &lwi);
+ if (atomic_read(&ns->ns_refcount)) {
+ CERROR("Lock manager: waiting for the %s namespace "
+ "was aborted with %d resources in use. (%d)\n"
+ "I'm going to try to clean up anyway, but I "
+ "might require a reboot of this node.\n",
+ ns->ns_name, atomic_read(&ns->ns_refcount), rc);
+ }
+ CDEBUG(D_DLMTRACE,
+ "dlm namespace %s free done waiting\n", ns->ns_name);
+ }
+
POISON(ns->ns_hash, 0x5a, sizeof(*ns->ns_hash) * RES_HASH_SIZE);
OBD_VFREE(ns->ns_hash, sizeof(*ns->ns_hash) * RES_HASH_SIZE);
OBD_FREE(ns->ns_name, strlen(ns->ns_name) + 1);
* Returns: newly-allocated, referenced, unlocked resource */
static struct ldlm_resource *
ldlm_resource_add(struct ldlm_namespace *ns, struct ldlm_resource *parent,
- struct ldlm_res_id name, __u32 type)
+ struct ldlm_res_id name, ldlm_type_t type)
{
struct list_head *bucket;
struct ldlm_resource *res;
ENTRY;
- LASSERTF(type >= LDLM_MIN_TYPE && type <= LDLM_MAX_TYPE,
- "type: %d", type);
+ LASSERTF(type >= LDLM_MIN_TYPE && type < LDLM_MAX_TYPE,
+ "type: %d\n", type);
res = ldlm_resource_new();
if (!res)
RETURN(NULL);
- spin_lock(&ns->ns_counter_lock);
- ns->ns_resources++;
- spin_unlock(&ns->ns_counter_lock);
-
l_lock(&ns->ns_lock);
memcpy(&res->lr_name, &name, sizeof(res->lr_name));
res->lr_namespace = ns;
- ns->ns_refcount++;
+ atomic_inc(&ns->ns_refcount);
res->lr_type = type;
res->lr_most_restr = LCK_NL;
* Returns: referenced, unlocked ldlm_resource or NULL */
struct ldlm_resource *
ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
- struct ldlm_res_id name, __u32 type, int create)
+ struct ldlm_res_id name, ldlm_type_t type, int create)
{
struct list_head *bucket, *tmp;
struct ldlm_resource *res = NULL;
LASSERT(res != NULL);
LASSERT(res != LP_POISON);
atomic_inc(&res->lr_refcount);
- CDEBUG(D_INFO, "getref res: %p count: %d\n", res,
+ CDEBUG(D_DLMTRACE, "getref res: %p count: %d\n", res,
atomic_read(&res->lr_refcount));
return res;
}
int rc = 0;
ENTRY;
- CDEBUG(D_INFO, "putref res: %p count: %d\n", res,
+ CDEBUG(D_DLMTRACE, "putref res: %p count: %d\n", res,
atomic_read(&res->lr_refcount) - 1);
LASSERT(atomic_read(&res->lr_refcount) > 0);
LASSERT(atomic_read(&res->lr_refcount) < LI_POISON);
LBUG();
}
- ns->ns_refcount--;
list_del_init(&res->lr_hash);
list_del_init(&res->lr_childof);
if (res->lr_lvb_data)
OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
- spin_lock(&ns->ns_counter_lock);
- ns->ns_resources--;
- spin_unlock(&ns->ns_counter_lock);
+ if (atomic_dec_and_test(&ns->ns_refcount)) {
+ CDEBUG(D_DLMTRACE, "last ref on ns %s\n", ns->ns_name);
+ wake_up(&ns->ns_refcount_waitq);
+ }
rc = 1;
EXIT;
struct list_head *tmp;
CDEBUG(level, "--- Namespace: %s (rc: %d, client: %d)\n", ns->ns_name,
- ns->ns_refcount, ns->ns_client);
+ atomic_read(&ns->ns_refcount), ns->ns_client);
l_lock(&ns->ns_lock);
if (time_after(jiffies, ns->ns_next_dump)) {
#undef LIST_HEAD
#include <portals/api-support.h> /* needed for ptpctl.h */
-#include <portals/ptlctl.h> /* needed for parse_dump */
+#include <portals/ptlctl.h> /* needed for parse_dump */
#include <procbridge.h>
#include "llite_lib.h"
}
}
- return (0);
+ return (0);
}
int lib_ioctl(int dev_id, int opc, void * ptr)
{
int rc;
- if (dev_id == OBD_DEV_ID) {
+ if (dev_id == OBD_DEV_ID) {
struct obd_ioctl_data *ioc = ptr;
//XXX hack!!!
if (rc)
return rc;
- }
- return (0);
+ }
+ return (0);
}
int lllib_init(char *dumpfile)
CERROR("class_config_parse_llog failed: rc = %d\n", rc);
}
- err = obd_disconnect(exp, 0);
+ err = obd_disconnect(exp);
out_cleanup:
LCFG_INIT(lcfg, LCFG_CLEANUP, name);
char *root_path = "/";
unsigned mntflgs = 0;
- int err;
+ int err;
/* consider tha case of starting multiple liblustre instances
* at a same time on single node.
signal(SIGUSR1, sighandler_USR1);
- lustre_path = getenv(ENV_LUSTRE_MNTPNT);
- if (!lustre_path) {
+ lustre_path = getenv(ENV_LUSTRE_MNTPNT);
+ if (!lustre_path) {
lustre_path = "/mnt/lustre";
- }
+ }
target = getenv(ENV_LUSTRE_MNTTGT);
if (!target) {
obd_timeout);
}
- if (_sysio_init() != 0) {
- perror("init sysio");
- exit(1);
- }
+ if (_sysio_init() != 0) {
+ perror("init sysio");
+ exit(1);
+ }
/* cygwin don't need native driver */
#ifndef __CYGWIN__
_sysio_native_init();
#endif
- err = _sysio_mount_root(root_path, root_driver, mntflgs, NULL);
- if (err) {
- perror(root_driver);
- exit(1);
- }
+ err = _sysio_mount_root(root_path, root_driver, mntflgs, NULL);
+ if (err) {
+ perror(root_driver);
+ exit(1);
+ }
#if 1
- portal_debug = 0;
- portal_subsystem_debug = 0;
+ portal_debug = 0;
+ portal_subsystem_debug = 0;
#endif
- err = lllib_init(dumpfile);
- if (err) {
- perror("init llite driver");
- exit(1);
- }
+ err = lllib_init(dumpfile);
+ if (err) {
+ perror("init llite driver");
+ exit(1);
+ }
err = mount("/", lustre_path, lustre_driver, mntflgs, NULL);
- if (err) {
- errno = -err;
- perror(lustre_driver);
- exit(1);
- }
+ if (err) {
+ errno = -err;
+ perror(lustre_driver);
+ exit(1);
+ }
#if 0
__sysio_hook_sys_enter = llu_check_request;
void __liblustre_cleanup_(void)
{
- _sysio_shutdown();
+ _sysio_shutdown();
PtlFini();
}
ENTRY;
list_del(&sbi->ll_conn_chain);
- obd_disconnect(sbi->ll_osc_exp, 0);
+ obd_disconnect(sbi->ll_osc_exp);
/* NULL request to force sync on the MDS, and get the last_committed
* value to flush remaining RPCs from the sending queue on client.
if (!obd->obd_no_recov)
mdc_getstatus(sbi->ll_mdc_exp, &rootfid);
- obd_disconnect(sbi->ll_mdc_exp, 0);
+ obd_disconnect(sbi->ll_mdc_exp);
OBD_FREE(sbi, sizeof(*sbi));
out_request:
ptlrpc_req_finished(request);
out_osc:
- obd_disconnect(sbi->ll_osc_exp, 0);
+ obd_disconnect(sbi->ll_osc_exp);
out_mdc:
- obd_disconnect(sbi->ll_mdc_exp, 0);
+ obd_disconnect(sbi->ll_mdc_exp);
out_free:
OBD_FREE(sbi, sizeof(*sbi));
return err;
rc = 1;
/* unfortunately ll_intent_lock may cause a callback and revoke our
- dentry */
+ * dentry */
spin_lock(&dcache_lock);
hlist_del_init(&de->d_hash);
__d_rehash(de, 0);
spin_unlock(&dcache_lock);
out:
- if (req != NULL && rc == 1)
+ /* If we had succesful it lookup on mds, but it happened to be negative,
+ we do not free request as it will be reused during lookup (see
+ comment in mdc/mdc_locks.c::mdc_intent_lock(). But if
+ request was not completed, we need to free it. (bug 5154) */
+ if (req != NULL && (rc == 1 || !it_disposition(it, DISP_ENQ_COMPLETE)))
ptlrpc_req_finished(req);
if (rc == 0) {
ll_unhash_aliases(de->d_inode);
#include <linux/lustre_debug.h>
+/*
+struct lustre_intent_data {
+ __u64 it_lock_handle[2];
+ __u32 it_disposition;
+ __u32 it_status;
+ __u32 it_lock_mode;
+ }; */
+
+#define LL_IT2STR(it) ((it) ? ldlm_it2str((it)->it_op) : "0")
+
+static inline struct lookup_intent *ll_nd2it(struct nameidata *nd)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
+ return &nd->intent;
+#else
+ return nd->intent;
+#endif
+}
+
+struct ll_dentry_data {
+ int lld_cwd_count;
+ int lld_mnt_count;
+ struct obd_client_handle lld_cwd_och;
+ struct obd_client_handle lld_mnt_och;
+};
+
+#define ll_d2d(de) ((struct ll_dentry_data*) de->d_fsdata)
+
+extern struct file_operations ll_pgcache_seq_fops;
+
+#define LLI_INODE_MAGIC 0x111d0de5
+#define LLI_INODE_DEAD 0xdeadd00d
+#define LLI_F_HAVE_OST_SIZE_LOCK 0
+#define LLI_F_HAVE_MDS_SIZE_LOCK 1
+struct ll_inode_info {
+ int lli_inode_magic;
+ int lli_size_pid;
+ struct semaphore lli_size_sem;
+ struct semaphore lli_open_sem;
+ struct lov_stripe_md *lli_smd;
+ char *lli_symlink_name;
+ __u64 lli_maxbytes;
+ __u64 lli_io_epoch;
+ unsigned long lli_flags;
+
+ /* this lock protects s_d_w and p_w_ll and mmap_cnt */
+ spinlock_t lli_lock;
+ struct list_head lli_pending_write_llaps;
+ int lli_send_done_writing;
+ atomic_t lli_mmap_cnt;
+
+ struct list_head lli_close_item;
+
+ /* for writepage() only to communicate to fsync */
+ int lli_async_rc;
+
+ struct file_operations *ll_save_ifop;
+ struct file_operations *ll_save_ffop;
+ struct file_operations *ll_save_wfop;
+ struct file_operations *ll_save_wrfop;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
+ struct inode lli_vfs_inode;
+#endif
+};
+
+// FIXME: replace the name of this with LL_I to conform to kernel stuff
+// static inline struct ll_inode_info *LL_I(struct inode *inode)
+static inline struct ll_inode_info *ll_i2info(struct inode *inode)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
+ return container_of(inode, struct ll_inode_info, lli_vfs_inode);
+#else
+ return (struct ll_inode_info *)&(inode->u.generic_ip);
+#endif
+}
+
+
/* default to about 40meg of readahead on a given system. That much tied
* up in 512k readahead requests serviced at 40ms each is about 1GB/s. */
#define SBI_DEFAULT_READAHEAD_MAX (40UL << (20 - PAGE_CACHE_SHIFT))
if (root)
iput(root);
out_osc:
- obd_disconnect(sbi->ll_osc_exp, 0);
+ obd_disconnect(sbi->ll_osc_exp);
out_mdc:
- obd_disconnect(sbi->ll_mdc_exp, 0);
+ obd_disconnect(sbi->ll_mdc_exp);
out:
lprocfs_unregister_mountpoint(sbi);
RETURN(err);
subdirs++;
CERROR("dentry %p dump: name=%.*s parent=%.*s (%p), inode=%p, count=%u,"
- " flags=0x%x, vfs_flags=0x%lx, fsdata=%p, %d subdirs\n", dentry,
+ " flags=0x%x, vfs_flags=0x%x, fsdata=%p, %d subdirs\n", dentry,
dentry->d_name.len, dentry->d_name.name,
dentry->d_parent->d_name.len, dentry->d_parent->d_name.name,
dentry->d_parent, dentry->d_inode, atomic_read(&dentry->d_count),
- dentry->d_flags, dentry->d_vfs_flags, dentry->d_fsdata, subdirs);
+ dentry->d_flags, dentry->d_flags, dentry->d_fsdata, subdirs);
if (dentry->d_inode != NULL)
lustre_dump_inode(dentry->d_inode);
ll_close_thread_shutdown(sbi->ll_lcq);
list_del(&sbi->ll_conn_chain);
- obd_disconnect(sbi->ll_osc_exp, 0);
+ obd_disconnect(sbi->ll_osc_exp);
lprocfs_unregister_mountpoint(sbi);
if (sbi->ll_proc_root) {
sbi->ll_proc_root = NULL;
}
- obd_disconnect(sbi->ll_mdc_exp, 0);
+ obd_disconnect(sbi->ll_mdc_exp);
// We do this to get rid of orphaned dentries. That is not really trw.
hlist_for_each_safe(tmp, next, &sbi->ll_orphan_dentry_list) {
{
sema_init(&lli->lli_open_sem, 1);
sema_init(&lli->lli_size_sem, 1);
+ lli->lli_size_pid = 0;
lli->lli_flags = 0;
lli->lli_maxbytes = PAGE_CACHE_MAXBYTES;
spin_lock_init(&lli->lli_lock);
*/
rc = class_config_dump_llog(ctxt, profile, cfg);
#endif
- if (rc) {
+ switch (rc) {
+ case 0:
+ break;
+ case -EINVAL:
+ LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
+ "from the MDS. Make sure this client and the "
+ "MDS are running compatible versions of "
+ "Lustre.\n",
+ obd->obd_name, profile);
+ /* fall through */
+ default:
CERROR("class_config_parse_llog failed: rc = %d\n", rc);
+ break;
}
- err = obd_disconnect(exp, 0);
+ err = obd_disconnect(exp);
out_cleanup:
LCFG_INIT(lcfg, LCFG_CLEANUP, name);
RETURN(rc);
down(&lli->lli_size_sem);
+ lli->lli_size_pid = current->pid;
rc = vmtruncate(inode, attr->ia_size);
// if vmtruncate returned 0, then ll_truncate dropped _size_sem
if (rc != 0) {
LASSERT(atomic_read(&lli->lli_size_sem.count) <= 0);
+ lli->lli_size_pid = 0;
up(&lli->lli_size_sem);
}
CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) to %llu\n", inode->i_ino,
inode->i_generation, inode, inode->i_size);
+ if (lli->lli_size_pid != current->pid) {
+ EXIT;
+ return;
+ }
+
if (!lsm) {
CDEBUG(D_INODE, "truncate on inode %lu with no objects\n",
inode->i_ino);
GOTO(out_unlock, 0);
}
+ LASSERT(atomic_read(&lli->lli_size_sem.count) <= 0);
+
if (lov_merge_size(lsm, 0) == inode->i_size) {
CDEBUG(D_VFSTRACE, "skipping punch for "LPX64" (size = %llu)\n",
lsm->lsm_object_id, inode->i_size);
obd_adjust_kms(ll_i2obdexp(inode), lsm, inode->i_size, 1);
- LASSERT(atomic_read(&lli->lli_size_sem.count) <= 0);
+ lli->lli_size_pid = 0;
up(&lli->lli_size_sem);
rc = obd_punch(ll_i2obdexp(inode), &oa, lsm, inode->i_size,
return;
out_unlock:
- LASSERT(atomic_read(&lli->lli_size_sem.count) <= 0);
+ lli->lli_size_pid = 0;
up(&lli->lli_size_sem);
} /* ll_truncate */
lop_cancel: lov_llog_repl_cancel
};
-
int lov_llog_init(struct obd_device *obd, struct obd_device *tgt,
int count, struct llog_catid *logid)
{
int lov_llog_finish(struct obd_device *obd, int count)
{
- struct lov_obd *lov = &obd->u.lov;
- int i, rc = 0;
+ struct llog_ctxt *ctxt;
+ int rc = 0;
ENTRY;
-
- rc = llog_cleanup(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT));
- if (rc)
- RETURN(rc);
- rc = llog_cleanup(llog_get_context(obd, LLOG_SIZE_REPL_CTXT));
+ /* cleanup our llogs only if the ctxts have been setup
+ * (lov1 doesn't setup, lov_mds1 does). */
+ ctxt = llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT);
+ if (ctxt)
+ rc = llog_cleanup(ctxt);
if (rc)
RETURN(rc);
- LASSERT(lov->desc.ld_tgt_count == count);
- for (i = 0; i < lov->desc.ld_tgt_count; i++) {
- struct obd_device *child = lov->tgts[i].ltd_exp->exp_obd;
- rc = obd_llog_finish(child, 1);
- if (rc) {
- CERROR("error osc_llog_finish %d\n", i);
- break;
- }
- }
+ ctxt = llog_get_context(obd, LLOG_SIZE_REPL_CTXT);
+ if (ctxt)
+ rc = llog_cleanup(ctxt);
+
RETURN(rc);
}
if (rc) {
CERROR("Target %s register_observer error %d\n",
tgt_uuid->uuid, rc);
- obd_disconnect(tgts->ltd_exp, 0);
+ obd_disconnect(tgts->ltd_exp);
GOTO(out_disc, rc);
}
tgts->active = 0;
/* save for CERROR below; (we know it's terminated) */
uuid = tgts->uuid;
- rc2 = obd_disconnect(tgts->ltd_exp, 0);
+ rc2 = obd_disconnect(tgts->ltd_exp);
if (rc2)
CERROR("error: LOV target %s disconnect on OST idx %d: "
"rc = %d\n", uuid.uuid, i, rc2);
}
- class_disconnect(exp, 0);
+ class_disconnect(exp);
RETURN (rc);
}
-static int lov_disconnect(struct obd_export *exp, int flags)
+static int lov_disconnect(struct obd_export *exp)
{
struct obd_device *obd = class_exp2obd(exp);
struct lov_obd *lov = &obd->u.lov;
obd_register_observer(osc_exp->exp_obd, NULL);
spin_unlock(&lov->lov_lock);
- rc = obd_disconnect(osc_exp, flags);
+ rc = obd_disconnect(osc_exp);
spin_lock(&lov->lov_lock);
if (rc) {
if (lov->tgts[i].active) {
spin_unlock(&lov->lov_lock);
out_local:
- rc = class_disconnect(exp, 0);
+ rc = class_disconnect(exp);
RETURN(rc);
}
RETURN(0);
}
-static int lov_cleanup(struct obd_device *obd, int flags)
+static int lov_cleanup(struct obd_device *obd)
{
struct lov_obd *lov = &obd->u.lov;
lprocfs_obd_cleanup(obd);
+ obd_llog_finish(obd, 0);
OBD_FREE(lov->tgts, lov->bufsize);
RETURN(0);
RETURN(-EINVAL);
for (i = 0; i < lov->desc.ld_tgt_count; i++) {
/* initialize all OSCs, even inactive ones */
-
err = obd_set_info(lov->tgts[i].ltd_exp,
keylen, key, sizeof(obd_id),
((obd_id*)val) + i);
/* additional block + block bitmap + GDT for long symlink */
nblocks += 3;
/* no break */
- case FSFILT_OP_CREATE:
+ case FSFILT_OP_CREATE: {
+#if defined(EXT3_EXTENTS_FL) && defined(EXT3_INDEX_FL)
+ static int warned;
+ if (!warned) {
+ if (!test_opt(inode->i_sb, EXTENTS)) {
+ warned = 1;
+ } else if (((EXT3_I(inode)->i_flags &
+ cpu_to_le32(EXT3_EXTENTS_FL | EXT3_INDEX_FL)) ==
+ cpu_to_le32(EXT3_EXTENTS_FL | EXT3_INDEX_FL))) {
+ CWARN("extent-mapped directory found - contact "
+ "CFS: support@clusterfs.com\n");
+ warned = 1;
+ }
+ }
+#endif
/* create/update logs for each stripe */
nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
EXT3_SINGLEDATA_TRANS_BLOCKS) * logs;
/* no break */
+ }
case FSFILT_OP_MKDIR:
case FSFILT_OP_MKNOD:
/* modify one inode + block bitmap + GDT */
return ext3_force_commit(sb);
}
-#ifndef EXT3_EXT_CACHE_NO /* we need this for struct ext3_ext_cache */
-#undef EXT3_MULTIBLOCK_ALLOCATOR
+#if defined(EXT3_MULTIBLOCK_ALLOCATOR) && (!defined(EXT3_EXT_CACHE_NO) || defined(EXT_CACHE_MARK))
#warning "kernel code has old extents/mballoc patch, disabling"
+#undef EXT3_MULTIBLOCK_ALLOCATOR
#endif
#ifdef EXT3_MULTIBLOCK_ALLOCATOR
struct semaphore *optional_sem)
{
int rc;
- if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
#ifdef EXT3_MULTIBLOCK_ALLOCATOR
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
rc = fsfilt_ext3_map_ext_inode_pages(inode, page, pages,
blocks, created, create);
-#else
- CERROR("extent-mapped file with unsupported kernel\n");
- rc = -EIO;
-#endif
return rc;
}
+#endif
if (optional_sem != NULL)
down(optional_sem);
rc = fsfilt_ext3_map_bm_inode_pages(inode, page, pages, blocks,
#define REQUEST_MINOR 244
-static int mdc_cleanup(struct obd_device *obd, int flags);
+static int mdc_cleanup(struct obd_device *obd);
extern int mds_queue_req(struct ptlrpc_request *);
/* Helper that implements most of mdc_getstatus and signal_completed_replay. */
rc = obd_llog_init(obd, obd, 0, NULL);
if (rc) {
- mdc_cleanup(obd, 0);
+ mdc_cleanup(obd);
CERROR("failed to setup llogging subsystems\n");
}
RETURN(0);
}
-static int mdc_precleanup(struct obd_device *obd, int flags)
+static int mdc_precleanup(struct obd_device *obd)
{
int rc = 0;
RETURN(rc);
}
-static int mdc_cleanup(struct obd_device *obd, int flags)
+static int mdc_cleanup(struct obd_device *obd)
{
struct client_obd *cli = &obd->u.cli;
lprocfs_obd_cleanup(obd);
ptlrpcd_decref();
- return client_obd_cleanup(obd, flags);
+ return client_obd_cleanup(obd);
}
struct ldlm_lock **lockp, void *req_cookie,
ldlm_mode_t mode, int flags, void *data);
static int mds_postsetup(struct obd_device *obd);
-static int mds_cleanup(struct obd_device *obd, int flags);
+static int mds_cleanup(struct obd_device *obd);
/* Assumes caller has already pushed into the kernel filesystem context */
static int mds_sendpage(struct ptlrpc_request *req, struct file *file,
out:
if (rc) {
OBD_FREE(mcd, sizeof(*mcd));
- class_disconnect(exp, 0);
+ class_disconnect(exp);
}
class_export_put(exp);
}
spin_unlock(&med->med_open_lock);
pop_ctxt(&saved, &obd->obd_ctxt, NULL);
-
out:
mds_client_free(export, !(export->exp_flags & OBD_OPT_FAILOVER));
RETURN(rc);
}
-static int mds_disconnect(struct obd_export *exp, int flags)
+static int mds_disconnect(struct obd_export *exp)
{
unsigned long irqflags;
int rc;
LASSERT(exp);
class_export_get(exp);
- spin_lock_irqsave(&exp->exp_lock, irqflags);
- exp->exp_flags = flags;
- spin_unlock_irqrestore(&exp->exp_lock, irqflags);
-
/* Disconnect early so that clients can't keep using export */
- rc = class_disconnect(exp, flags);
+ rc = class_disconnect(exp);
ldlm_cancel_locks_for_export(exp);
/* complete all outstanding replies */
int rc = 0;
ENTRY;
- dev_clear_rdonly(2);
-
if (!lcfg->lcfg_inlbuf1 || !lcfg->lcfg_inlbuf2)
RETURN(rc = -EINVAL);
}
CDEBUG(D_SUPER, "%s: mnt = %p\n", lcfg->lcfg_inlbuf1, mnt);
-
+
+ LASSERT(!ll_check_rdonly(ll_sbdev(mnt->mnt_sb)));
+
sema_init(&mds->mds_orphan_recovery_sem, 1);
sema_init(&mds->mds_epoch_sem, 1);
spin_lock_init(&mds->mds_transno_lock);
sprintf(ns_name, "mds-%s", obd->obd_uuid.uuid);
obd->obd_namespace = ldlm_namespace_new(ns_name, LDLM_NAMESPACE_SERVER);
if (obd->obd_namespace == NULL) {
- mds_cleanup(obd, 0);
+ mds_cleanup(obd);
GOTO(err_put, rc = -ENOMEM);
}
ldlm_register_intent(obd->obd_namespace, mds_intent_policy);
err_fs:
/* No extra cleanup needed for llog_init_commit_thread() */
- mds_fs_cleanup(obd, 0);
+ mds_fs_cleanup(obd);
err_ns:
ldlm_namespace_free(obd->obd_namespace, 0);
obd->obd_namespace = NULL;
rc = class_config_parse_llog(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
mds->mds_profile, &cfg);
pop_ctxt(&saved, &obd->obd_ctxt, NULL);
- if (rc)
+ switch (rc) {
+ case 0:
+ break;
+ case -EINVAL:
+ LCONSOLE_ERROR("%s: the profile %s could not be read. "
+ "If you recently installed a new "
+ "version of Lustre, you may need to "
+ "re-run 'lconf --write_conf "
+ "<yourconfig>.xml' command line before "
+ "restarting the MDS.\n",
+ obd->obd_name, mds->mds_profile);
+ /* fall through */
+ default:
GOTO(err_llog, rc);
+ break;
+ }
lprof = class_get_profile(mds->mds_profile);
if (lprof == NULL) {
RETURN(0);
}
-static int mds_precleanup(struct obd_device *obd, int flags)
+static int mds_precleanup(struct obd_device *obd)
{
int rc = 0;
ENTRY;
- mds_lov_disconnect(obd, flags);
+ mds_lov_set_cleanup_flags(obd);
+ target_cleanup_recovery(obd);
+ mds_lov_disconnect(obd);
mds_lov_clean(obd);
llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
RETURN(rc);
}
-static int mds_cleanup(struct obd_device *obd, int flags)
+static int mds_cleanup(struct obd_device *obd)
{
struct mds_obd *mds = &obd->u.mds;
+ ll_sbdev_type save_dev;
ENTRY;
if (mds->mds_sb == NULL)
RETURN(0);
+ save_dev = ll_sbdev(mds->mds_sb);
+
+ if (mds->mds_osc_exp)
+ /* lov export was disconnected by mds_lov_clean;
+ we just need to drop our ref */
+ class_export_put(mds->mds_osc_exp);
lprocfs_obd_cleanup(obd);
OBD_FREE(mds->mds_lov_objids,
mds->mds_lov_desc.ld_tgt_count * sizeof(obd_id));
}
- mds_fs_cleanup(obd, flags);
+ mds_fs_cleanup(obd);
unlock_kernel();
atomic_read(&obd->u.mds.mds_vfsmnt->mnt_count));
mntput(mds->mds_vfsmnt);
+ mds->mds_sb = NULL;
- mds->mds_sb = 0;
-
- ldlm_namespace_free(obd->obd_namespace, flags & OBD_OPT_FORCE);
+ ldlm_namespace_free(obd->obd_namespace, obd->obd_force);
spin_lock_bh(&obd->obd_processing_task_lock);
if (obd->obd_recovering) {
}
spin_unlock_bh(&obd->obd_processing_task_lock);
+ obd_llog_finish(obd, 0);
+
+ ll_clear_rdonly(save_dev);
+
lock_kernel();
- dev_clear_rdonly(2);
fsfilt_put_ops(obd->obd_fsops);
LCONSOLE_INFO("MDT %s has stopped.\n", obd->obd_name);
return rc;
}
-static int mdt_cleanup(struct obd_device *obd, int flags)
+static int mdt_cleanup(struct obd_device *obd)
{
struct mds_obd *mds = &obd->u.mds;
ENTRY;
RETURN(0);
err_client:
- class_disconnect_exports(obd, 0);
+ class_disconnect_exports(obd);
err_msd:
mds_server_free_data(mds);
RETURN(rc);
if (mds->mds_lov_objid_filp && filp_close(mds->mds_lov_objid_filp, 0))
CERROR("can't close %s after error\n", LOV_OBJID);
err_client:
- class_disconnect_exports(obd, 0);
+ class_disconnect_exports(obd);
err_last_rcvd:
if (mds->mds_rcvd_filp && filp_close(mds->mds_rcvd_filp, 0))
CERROR("can't close %s after error\n", LAST_RCVD);
}
-int mds_fs_cleanup(struct obd_device *obd, int flags)
+int mds_fs_cleanup(struct obd_device *obd)
{
struct mds_obd *mds = &obd->u.mds;
struct obd_run_ctxt saved;
int rc = 0;
- if (flags & OBD_OPT_FAILOVER)
+ if (obd->obd_fail)
CERROR("%s: shutting down for failover; client state will"
" be preserved.\n", obd->obd_name);
- class_disconnect_exports(obd, flags); /* cleans up client info too */
- target_cleanup_recovery(obd);
+ class_disconnect_exports(obd); /* cleans up client info too */
mds_server_free_data(mds);
push_ctxt(&saved, &obd->obd_ctxt, NULL);
down(&parent_inode->i_sem);
de = lookup_one_len(fidname, mds->mds_objects_dir, namelen);
- if (IS_ERR(de) || de->d_inode == NULL) {
- rc = IS_ERR(de) ? PTR_ERR(de) : -ENOENT;
+ if (IS_ERR(de)) {
+ rc = IS_ERR(de);
+ de = NULL;
+ CERROR("error looking up object "LPU64" %s: rc %d\n",
+ oa->o_id, fidname, rc);
+ GOTO(out_dput, rc);
+ }
+ if (de->d_inode == NULL) {
CERROR("destroying non-existent object "LPU64" %s\n",
oa->o_id, fidname);
- GOTO(out_dput, rc = IS_ERR(de) ? PTR_ERR(de) : -ENOENT);
+ GOTO(out_dput, rc = -ENOENT);
}
/* Stripe count is 1 here since this is some MDS specific stuff
/* mds/mds_lov.c */
int mds_lov_connect(struct obd_device *obd, char * lov_name);
-int mds_lov_disconnect(struct obd_device *obd, int flags);
-int mds_get_lovtgts(struct obd_device *, int tgt_count, struct obd_uuid *);
+int mds_lov_disconnect(struct obd_device *obd);
+void mds_lov_set_cleanup_flags(struct obd_device *);
int mds_lov_write_objids(struct obd_device *obd);
void mds_lov_update_objids(struct obd_device *obd, obd_id *ids);
int mds_lov_set_growth(struct mds_obd *mds, int count);
int mds_llog_finish(struct obd_device *obd, int count)
{
- struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
- int rc;
+ struct llog_ctxt *ctxt;
+ int rc = 0;
ENTRY;
- rc = llog_cleanup(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT));
- if (rc)
- RETURN(rc);
-
- rc = llog_cleanup(llog_get_context(obd, LLOG_SIZE_REPL_CTXT));
+ ctxt = llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT);
+ if (ctxt)
+ rc = llog_cleanup(ctxt);
if (rc)
RETURN(rc);
- rc = obd_llog_finish(lov_obd, count);
- if (rc)
- CERROR("error lov_llog_finish\n");
-
+ ctxt = llog_get_context(obd, LLOG_SIZE_REPL_CTXT);
+ if (ctxt)
+ rc = llog_cleanup(ctxt);
+
RETURN(rc);
}
err_reg:
obd_register_observer(mds->mds_osc_obd, NULL);
err_discon:
- obd_disconnect(mds->mds_osc_exp, 0);
+ obd_disconnect(mds->mds_osc_exp);
mds->mds_osc_exp = NULL;
mds->mds_osc_obd = ERR_PTR(rc);
RETURN(rc);
}
-int mds_lov_disconnect(struct obd_device *obd, int flags)
+int mds_lov_disconnect(struct obd_device *obd)
{
struct mds_obd *mds = &obd->u.mds;
int rc = 0;
ENTRY;
if (!IS_ERR(mds->mds_osc_obd) && mds->mds_osc_exp != NULL) {
- /* cleanup all llogging subsystems */
- rc = obd_llog_finish(obd, mds->mds_lov_desc.ld_tgt_count);
- if (rc)
- CERROR("failed to cleanup llogging subsystems\n");
-
obd_register_observer(mds->mds_osc_obd, NULL);
- rc = obd_disconnect(mds->mds_osc_exp, flags);
- /* if obd_disconnect fails (probably because the
- * export was disconnected by class_disconnect_exports)
- * then we just need to drop our ref. */
- if (rc != 0)
- class_export_put(mds->mds_osc_exp);
- mds->mds_osc_exp = NULL;
- mds->mds_osc_obd = NULL;
+ /* The actual disconnect of the mds_lov will be called from
+ * class_disconnect_exports from mds_lov_clean. So we have to
+ * ensure that class_cleanup doesn't fail due to the extra ref
+ * we're holding now. The mechanism to do that already exists -
+ * the obd_force flag. We'll drop the final ref to the
+ * mds_osc_exp in mds_cleanup. */
+ mds->mds_osc_obd->obd_force = 1;
}
RETURN(rc);
}
+/* for consistency, let's make the lov and the lov's
+ * osc's see the same cleanup flags as our mds */
+void mds_lov_set_cleanup_flags(struct obd_device *obd)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct lov_obd *lov;
+
+ if (IS_ERR(mds->mds_osc_obd) || (mds->mds_osc_exp == NULL))
+ return;
+
+ lov = &mds->mds_osc_obd->u.lov;
+ mds->mds_osc_obd->obd_force = obd->obd_force;
+ mds->mds_osc_obd->obd_fail = obd->obd_fail;
+ if (lov->tgts) {
+ struct obd_export *osc_exp;
+ int i;
+ spin_lock(&lov->lov_lock);
+ for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+ if (lov->tgts[i].ltd_exp != NULL) {
+ osc_exp = lov->tgts[i].ltd_exp;
+ osc_exp->exp_obd->obd_force = obd->obd_force;
+ osc_exp->exp_obd->obd_fail = obd->obd_fail;
+ }
+ }
+ spin_unlock(&lov->lov_lock);
+ }
+}
+
int mds_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
void *karg, void *uarg)
{
RETURN(-EBUSY);
push_ctxt(&saved, &obd->obd_ctxt, NULL);
- rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
+ rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
&mds->mds_cfg_llh, NULL, name);
if (rc == 0) {
llog_init_handle(mds->mds_cfg_llh, LLOG_F_IS_PLAIN,
RETURN(rc);
}
+ case OBD_IOC_SYNC: {
+ CDEBUG(D_HA, "syncing mds %s\n", obd->obd_name);
+ rc = fsfilt_sync(obd, obd->u.mds.mds_sb);
+ RETURN(rc);
+ }
+
case OBD_IOC_SET_READONLY: {
void *handle;
struct inode *inode = obd->u.mds.mds_sb->s_root->d_inode;
ll_bdevname(obd->u.mds.mds_sb, tmp));
handle = fsfilt_start(obd, inode, FSFILT_OP_MKNOD, NULL);
- LASSERT(handle);
- rc = fsfilt_commit(obd, inode, handle, 1);
+ if (!IS_ERR(handle))
+ rc = fsfilt_commit(obd, inode, handle, 1);
+
+ CDEBUG(D_HA, "syncing mds %s\n", obd->obd_name);
+ rc = fsfilt_sync(obd, obd->u.mds.mds_sb);
- dev_set_rdonly(ll_sbdev(obd->u.mds.mds_sb), 2);
+ ll_set_rdonly(ll_sbdev(obd->u.mds.mds_sb));
RETURN(0);
}
LASSERT(obd != NULL);
LASSERT(uuid != NULL);
- rc = obd_set_info(obd->u.mds.mds_osc_exp, strlen("mds_conn"),
+ rc = obd_set_info(obd->u.mds.mds_osc_exp, strlen("mds_conn"),
"mds_conn", 0, uuid);
if (rc != 0)
RETURN(rc);
obd->u.mds.mds_lov_desc.ld_tgt_count,
NULL, NULL, uuid);
if (rc != 0) {
- CERROR("%s: failed at llog_origin_connect: %d\n",
+ CERROR("%s: failed at llog_origin_connect: %d\n",
obd->obd_name, rc);
RETURN(rc);
}
obd->obd_name, uuid->uuid);
rc = mds_lov_clearorphans(&obd->u.mds, uuid);
if (rc != 0) {
- CERROR("%s: failed at mds_lov_clearorphans: %d\n",
+ CERROR("%s: failed at mds_lov_clearorphans: %d\n",
obd->obd_name, rc);
RETURN(rc);
}
rc = kernel_thread(mds_lov_synchronize, mlsi, CLONE_VM | CLONE_FILES);
if (rc < 0)
- CERROR("%s: error starting mds_lov_synchronize: %d\n",
+ CERROR("%s: error starting mds_lov_synchronize: %d\n",
obd->obd_name, rc);
else {
- CDEBUG(D_HA, "%s: mds_lov_synchronize thread: %d\n",
+ CDEBUG(D_HA, "%s: mds_lov_synchronize thread: %d\n",
obd->obd_name, rc);
rc = 0;
}
/* replay case */
if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) {
- LASSERT (rec->ur_fid2->id);
+ if (rec->ur_fid2->id == 0) {
+ DEBUG_REQ(D_ERROR, req, "fid2 not set on open replay");
+ RETURN(-EFAULT);
+ }
+
body->valid |= OBD_MD_FLBLKSZ | OBD_MD_FLEASIZE;
lmm_size = rec->ur_eadatalen;
lmm = rec->ur_eadata;
rec, rep);
if (rc != -ENOENT)
RETURN(rc);
+
/* We didn't find the correct inode on disk either, so we
* need to re-create it via a regular replay. */
- LASSERT(rec->ur_flags & MDS_OPEN_CREAT);
- } else {
- LASSERT(!rec->ur_fid2->id);
+ if (!(rec->ur_flags & MDS_OPEN_CREAT)) {
+ DEBUG_REQ(D_ERROR, req,"OPEN_CREAT not in open replay");
+ RETURN(-EFAULT);
+ }
+ } else if (rec->ur_fid2->id) {
+ DEBUG_REQ(D_ERROR, req, "fid2 "LPU64"/%u on open non-replay",
+ rec->ur_fid2->id, rec->ur_fid2->generation);
+ RETURN(-EFAULT);
}
LASSERT(offset == 2); /* If we got here, we must be called via intent */
rec->ur_namelen - 1);
if (IS_ERR(dparent)) {
rc = PTR_ERR(dparent);
- if (rc != -ENOENT)
- CERROR("parent lookup error %d\n", rc);
+ if (rc != -ENOENT) {
+ CERROR("parent "LPU64"/%u lookup error %d\n",
+ rec->ur_fid1->id, rec->ur_fid1->generation, rc);
+ } else {
+ /* Just cannot find parent - make it look like
+ * usual negative lookup to avoid extra MDS RPC */
+ intent_set_disposition(rep, DISP_LOOKUP_EXECD);
+ intent_set_disposition(rep, DISP_LOOKUP_NEG);
+ }
GOTO(cleanup, rc);
}
LASSERT(dparent->d_inode != NULL);
/* The following are visible and mutable through /proc/sys/lustre/. */
unsigned int obd_fail_loc;
unsigned int obd_dump_on_timeout;
-unsigned int obd_timeout = 100;
-unsigned int ldlm_timeout = 6;
+unsigned int obd_timeout = 100; /* seconds */
+unsigned int ldlm_timeout = 6; /* seconds */
char obd_lustre_upcall[128] = "DEFAULT"; /* or NONE or /full/path/to/upcall */
unsigned int obd_sync_filter; /* = 0, don't sync by default */
* kernel patch */
#include <linux/lustre_version.h>
#define LUSTRE_MIN_VERSION 32
-#define LUSTRE_MAX_VERSION 44
+#define LUSTRE_MAX_VERSION 45
#if (LUSTRE_KERNEL_VERSION < LUSTRE_MIN_VERSION)
# error Cannot continue: Your Lustre kernel patch is older than the sources
#elif (LUSTRE_KERNEL_VERSION > LUSTRE_MAX_VERSION)
int minor = obd->obd_minor;
spin_lock(&obd_dev_lock);
+ memset(obd, 0x5a, sizeof(*obd));
obd->obd_type = NULL;
- //memset(obd, 0, sizeof(*obd));
obd->obd_minor = minor;
+ obd->obd_name = NULL;
spin_unlock(&obd_dev_lock);
}
obd_destroy_export(exp);
OBD_FREE(exp, sizeof(*exp));
- if (obd->obd_set_up) {
- atomic_dec(&obd->obd_refcount);
- wake_up(&obd->obd_refcount_waitq);
- }
+ class_decref(obd);
}
}
* hash entry and one for the export pointer passed in. The export
* pointer passed to this function is destroyed should not be used
* again. */
-int class_disconnect(struct obd_export *export, int flags)
+int class_disconnect(struct obd_export *export)
{
ENTRY;
while(!list_empty(list)) {
exp = list_entry(list->next, struct obd_export, exp_obd_chain);
class_export_get(exp);
+ exp->exp_flags = flags;
if (obd_uuid_equals(&exp->exp_client_uuid,
&exp->exp_obd->obd_uuid)) {
class_export_put(exp);
continue;
}
- rc = obd_disconnect(fake_exp, flags);
+ fake_exp->exp_flags = flags;
+ rc = obd_disconnect(fake_exp);
class_export_put(exp);
if (rc) {
CDEBUG(D_HA, "disconnecting export %p failed: %d\n",
EXIT;
}
-void class_disconnect_exports(struct obd_device *obd, int flags)
+static inline int get_exp_flags_from_obd(struct obd_device *obd)
+{
+ return ((obd->obd_fail ? OBD_OPT_FAILOVER : 0) |
+ (obd->obd_force ? OBD_OPT_FORCE : 0));
+}
+
+void class_disconnect_exports(struct obd_device *obd)
{
struct list_head work_list;
ENTRY;
CDEBUG(D_HA, "OBD device %d (%p) has exports, "
"disconnecting them\n", obd->obd_minor, obd);
- class_disconnect_export_list(&work_list, flags);
+ class_disconnect_export_list(&work_list, get_exp_flags_from_obd(obd));
EXIT;
}
/* Remove exports that have not completed recovery.
*/
-void class_disconnect_stale_exports(struct obd_device *obd, int flags)
+void class_disconnect_stale_exports(struct obd_device *obd)
{
struct list_head work_list;
struct list_head *pos, *n;
CDEBUG(D_ERROR, "%s: disconnecting %d stale clients\n",
obd->obd_name, cnt);
- class_disconnect_export_list(&work_list, flags);
+ class_disconnect_export_list(&work_list, get_exp_flags_from_obd(obd));
EXIT;
}
obd->obd_llog_ctxt[index] = ctxt;
ctxt->loc_obd = obd;
- ctxt->loc_exp = class_export_get(disk_obd->obd_self_export);
+ ctxt->loc_exp = disk_obd->obd_self_export;
ctxt->loc_idx = index;
ctxt->loc_logops = op;
sema_init(&ctxt->loc_sem, 1);
if (op->lop_setup)
rc = op->lop_setup(obd, index, disk_obd, count, logid);
- if (ctxt && rc)
- OBD_FREE(ctxt, sizeof(*ctxt));
RETURN(rc);
}
int rc = 0;
ENTRY;
- LASSERT(ctxt);
-
+ if (!ctxt) {
+ CERROR("No ctxt\n");
+ RETURN(-ENODEV);
+ }
+
if (CTXTP(ctxt, cleanup))
rc = CTXTP(ctxt, cleanup)(ctxt);
ctxt->loc_obd->obd_llog_ctxt[ctxt->loc_idx] = NULL;
- class_export_put(ctxt->loc_exp);
ctxt->loc_exp = NULL;
OBD_FREE(ctxt, sizeof(*ctxt));
int rc;
ENTRY;
- LASSERT(ctxt);
+ if (!ctxt) {
+ CERROR("No ctxt\n");
+ RETURN(-ENODEV);
+ }
+
CTXT_CHECK_OP(ctxt, add, -EOPNOTSUPP);
rc = CTXTP(ctxt, add)(ctxt, rec, lsm, logcookies, numcookies);
int rc;
ENTRY;
- LASSERT(ctxt);
+ if (!ctxt) {
+ CERROR("No ctxt\n");
+ RETURN(-ENODEV);
+ }
+
CTXT_CHECK_OP(ctxt, cancel, -EOPNOTSUPP);
rc = CTXTP(ctxt, cancel)(ctxt, lsm, count, cookies, flags);
RETURN(rc);
rc = llog_destroy(loghandle);
if (rc)
CERROR("failure destroying log in postsetup: %d\n", rc);
- LASSERT(rc == 0);
index = loghandle->u.phd.phd_cookie.lgc_index;
llog_free_handle(loghandle);
ENTRY;
if (!ctxt)
- return 0;
+ RETURN(0);
cathandle = ctxt->loc_handle;
if (cathandle) {
if (rc)
CERROR("failure destroying log during "
"cleanup: %d\n", rc);
- LASSERT(rc == 0);
index = loghandle->u.phd.phd_cookie.lgc_index;
llog_free_handle(loghandle);
}
llog_cat_put(ctxt->loc_handle);
}
- return 0;
+ RETURN(0);
}
EXPORT_SYMBOL(llog_obd_origin_cleanup);
CERROR("6: llog_close failed: rc = %d\n", rc);
}
- rc = obd_disconnect(exp, 0);
+ rc = obd_disconnect(exp);
RETURN(rc);
}
RETURN(rc);
}
-static int llog_test_cleanup(struct obd_device *obd, int flags)
+static int llog_test_cleanup(struct obd_device *obd)
{
int rc = obd_llog_finish(obd, 0);
if (rc)
rc = llog_run_tests(obd);
if (rc)
- llog_test_cleanup(obd, 0);
+ llog_test_cleanup(obd);
lprocfs_init_vars(llog_test, &lvars);
lprocfs_obd_setup(obd, lvars.obd_vars);
return snprintf(page, count, LPU64"\n", *(__u64 *)data);
}
+int lprocfs_rd_atomic(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ atomic_t *atom = (atomic_t *)data;
+ LASSERT(atom != NULL);
+ *eof = 1;
+ return snprintf(page, count, "%d\n", atomic_read(atom));
+}
+
int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
EXPORT_SYMBOL(lprocfs_free_obd_stats);
EXPORT_SYMBOL(lprocfs_rd_u64);
+EXPORT_SYMBOL(lprocfs_rd_atomic);
EXPORT_SYMBOL(lprocfs_rd_uuid);
EXPORT_SYMBOL(lprocfs_rd_name);
EXPORT_SYMBOL(lprocfs_rd_fstype);
spin_lock_init(&obd->obd_dev_lock);
spin_lock_init(&obd->obd_osfs_lock);
obd->obd_osfs_age = jiffies - 1000 * HZ;
- init_waitqueue_head(&obd->obd_refcount_waitq);
/* XXX belongs in setup not attach */
/* recovery data */
GOTO(out, rc = -EINVAL);
}
+ /* The attach is our first obd reference */
+ atomic_set(&obd->obd_refcount, 1);
+
obd->obd_attached = 1;
type->typ_refcnt++;
CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
obd->obd_starting = 1;
spin_unlock(&obd->obd_dev_lock);
- atomic_set(&obd->obd_refcount, 0);
-
exp = class_new_export(obd);
if (exp == NULL)
RETURN(err);
obd->obd_type->typ_refcnt++;
obd->obd_set_up = 1;
-
+ CDEBUG(D_IOCTL, "finished setup of obd %s (uuid %s)\n",
+ obd->obd_name, obd->obd_uuid.uuid);
+
RETURN(0);
err_exp:
class_unlink_export(obd->obd_self_export);
obd->obd_self_export = NULL;
+ obd->obd_starting = 0;
RETURN(err);
}
-int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
+static int __class_detach(struct obd_device *obd)
{
int err = 0;
+ if (OBP(obd, detach))
+ err = OBP(obd,detach)(obd);
+
+ if (obd->obd_name) {
+ OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
+ obd->obd_name = NULL;
+ } else {
+ CERROR("device %d: no name at detach\n", obd->obd_minor);
+ }
+
+ LASSERT(OBT(obd));
+ /* Attach took type refcount */
+ obd->obd_type->typ_refcnt--;
+ class_put_type(obd->obd_type);
+ class_release_dev(obd);
+ return (err);
+}
+
+int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
+{
ENTRY;
if (obd->obd_set_up) {
CERROR("OBD device %d still set up\n", obd->obd_minor);
obd->obd_attached = 0;
spin_unlock(&obd->obd_dev_lock);
- if (OBP(obd, detach))
- err = OBP(obd,detach)(obd);
-
- if (obd->obd_name) {
- OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
- obd->obd_name = NULL;
- } else {
- CERROR("device %d: no name at detach\n", obd->obd_minor);
- }
+ CDEBUG(D_IOCTL, "detach on obd %s (uuid %s)\n",
+ obd->obd_name, obd->obd_uuid.uuid);
- LASSERT(OBT(obd));
- obd->obd_type->typ_refcnt--;
- class_put_type(obd->obd_type);
- class_release_dev(obd);
- RETURN(err);
+ class_decref(obd);
+ RETURN(0);
}
static void dump_exports(struct obd_device *obd)
nreplies++;
}
- CERROR("%s: %p %s %d %d %d: %p %s\n",
+ CDEBUG(D_IOCTL, "%s: %p %s %d %d %d: %p %s\n",
obd->obd_name, exp, exp->exp_client_uuid.uuid,
atomic_read(&exp->exp_refcount),
exp->exp_failed, nreplies, first_reply,
int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
{
- int flags = 0;
int err = 0;
char *flag;
ENTRY;
+ OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
+
if (!obd->obd_set_up) {
CERROR("Device %d not setup\n", obd->obd_minor);
RETURN(-ENODEV);
for (flag = lcfg->lcfg_inlbuf1; *flag != 0; flag++)
switch (*flag) {
case 'F':
- flags |= OBD_OPT_FORCE;
+ obd->obd_force = 1;
break;
case 'A':
- flags |= OBD_OPT_FAILOVER;
+ obd->obd_fail = 1;
+ obd->obd_no_transno = 1;
+ LCONSOLE_WARN("Failing %s by user command\n",
+ obd->obd_name);
+ /* Set the obd readonly if we can */
+ if (OBP(obd, iocontrol))
+ obd_iocontrol(OBD_IOC_SET_READONLY,
+ obd->obd_self_export,
+ 0, NULL, NULL);
break;
default:
CERROR("unrecognised flag '%c'\n",
*flag);
}
}
-
- /* The one reference that should be remaining is the
- * obd_self_export */
- if (atomic_read(&obd->obd_refcount) > 1) {
- struct l_wait_info lwi = LWI_TIMEOUT_INTR(1 * HZ, NULL,
- NULL, NULL);
- int rc;
-
- if (!(flags & OBD_OPT_FORCE)) {
- CERROR("OBD device %d (%p) has refcount %d\n",
- obd->obd_minor, obd,
- atomic_read(&obd->obd_refcount));
+
+ /* The two references that should be remaining are the
+ * obd_self_export and the attach reference. */
+ if (atomic_read(&obd->obd_refcount) > 2) {
+ if (!(obd->obd_fail || obd->obd_force)) {
+ CERROR("OBD %s is still busy with %d references\n"
+ "You should stop active file system users,"
+ " or use the --force option to cleanup.\n",
+ obd->obd_name, atomic_read(&obd->obd_refcount));
dump_exports(obd);
GOTO(out, err = -EBUSY);
}
- class_disconnect_exports(obd, flags);
- CDEBUG(D_IOCTL,
- "%s: waiting for obd refs to go away: %d\n",
+ CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
obd->obd_name, atomic_read(&obd->obd_refcount));
-
- rc = l_wait_event(obd->obd_refcount_waitq,
- atomic_read(&obd->obd_refcount) < 2, &lwi);
- if (rc == 0) {
- LASSERT(atomic_read(&obd->obd_refcount) == 1);
- } else {
- CERROR("wait cancelled cleaning anyway. "
- "refcount: %d\n",
- atomic_read(&obd->obd_refcount));
- dump_exports(obd);
- }
- CDEBUG(D_IOCTL, "%s: awake, now finishing cleanup\n",
- obd->obd_name);
+ dump_exports(obd);
+ class_disconnect_exports(obd);
}
+ LASSERT(obd->obd_self_export);
if (obd->obd_self_export) {
- err = obd_precleanup(obd, flags);
- if (err)
- GOTO(out, err);
- class_unlink_export(obd->obd_self_export);
- obd->obd_self_export = NULL;
- }
-
- err = obd_cleanup(obd, flags);
+ /* mds_precleanup will clean up the lov (and osc's)*/
+ err = obd_precleanup(obd);
+ if (err)
+ GOTO(out, err);
+ obd->obd_self_export->exp_flags |=
+ (obd->obd_fail ? OBD_OPT_FAILOVER : 0) |
+ (obd->obd_force ? OBD_OPT_FORCE : 0);
+ class_unlink_export(obd->obd_self_export);
+ obd->obd_self_export = NULL;
+ }
+
+ obd->obd_set_up = 0;
+ obd->obd_type->typ_refcnt--;
+ RETURN(0);
out:
- if (!err) {
- obd->obd_set_up = 0;
- obd->obd_type->typ_refcnt--;
- /* XXX this should be an LASSERT */
- if (atomic_read(&obd->obd_refcount) > 0)
- CERROR("%s still has refcount %d after "
- "cleanup.\n", obd->obd_name,
- atomic_read(&obd->obd_refcount));
- } else {
- /* Allow a failed cleanup to try again. Note this may be
- unsafe, since we don't know where this one died. */
- obd->obd_stopping = 0;
- }
-
+ /* Allow a failed cleanup to try again. */
+ obd->obd_stopping = 0;
RETURN(err);
-
}
+void class_decref(struct obd_device *obd)
+{
+ if (atomic_dec_and_test(&obd->obd_refcount)) {
+ int err;
+ CDEBUG(D_IOCTL, "finishing cleanup of obd %s (%s)\n",
+ obd->obd_name, obd->obd_uuid.uuid);
+ LASSERT(!obd->obd_attached);
+ if (obd->obd_stopping) {
+ /* If we're not stopping, we never set up */
+ err = obd_cleanup(obd);
+ if (err)
+ CERROR("Cleanup returned %d\n", err);
+ }
+ err = __class_detach(obd);
+ if (err)
+ CERROR("Detach returned %d\n", err);
+ }
+}
+
LIST_HEAD(lustre_profile_list);
struct lustre_profile *class_get_profile(char * prof)
OBD_LDLM_TIMEOUT, /* LDLM timeout for ASTs before client eviction */
};
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
int proc_fail_loc(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp);
+ void *buffer, size_t *lenp)
+#else
+int proc_fail_loc(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp, loff_t *ppos)
+#endif
+{
+ int rc;
+ int old_fail_loc = obd_fail_loc;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
+ rc = proc_dointvec(table,write,filp,buffer,lenp);
+#else
+ rc = proc_dointvec(table,write,filp,buffer,lenp,ppos);
+#endif
+ if (old_fail_loc != obd_fail_loc)
+ wake_up(&obd_race_waitq);
+ return rc;
+}
static ctl_table obd_table[] = {
{OBD_FAIL_LOC, "fail_loc", &obd_fail_loc, sizeof(int), 0644, NULL,
obd_table_header = NULL;
#endif
}
-
-int proc_fail_loc(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp)
-{
- int rc;
- int old_fail_loc = obd_fail_loc;
-
- rc = proc_dointvec(table,write,filp,buffer,lenp);
- if (old_fail_loc != obd_fail_loc)
- wake_up(&obd_race_waitq);
- return rc;
-}
return class_connect(conn, obd, cluuid);
}
-static int echo_disconnect(struct obd_export *exp, int flags)
+static int echo_disconnect(struct obd_export *exp)
{
unsigned long irqflags;
ldlm_cancel_locks_for_export(exp);
- spin_lock_irqsave(&exp->exp_lock, irqflags);
- exp->exp_flags = flags;
- spin_unlock_irqrestore(&exp->exp_lock, irqflags);
-
/* complete all outstanding replies */
spin_lock_irqsave(&exp->exp_lock, irqflags);
while (!list_empty(&exp->exp_outstanding_replies)) {
}
spin_unlock_irqrestore(&exp->exp_lock, irqflags);
- return class_disconnect(exp, flags);
+ return class_disconnect(exp);
}
static int echo_destroy_export(struct obd_export *exp)
RETURN(0);
}
-static int echo_cleanup(struct obd_device *obd, int flags)
+static int echo_cleanup(struct obd_device *obd)
{
int leaked;
ENTRY;
set_current_state (TASK_UNINTERRUPTIBLE);
schedule_timeout (HZ);
- ldlm_namespace_free(obd->obd_namespace, flags & OBD_OPT_FORCE);
+ ldlm_namespace_free(obd->obd_namespace, obd->obd_force);
leaked = atomic_read(&obd->u.echo.eo_prep);
if (leaked != 0)
RETURN(rc);
}
-static int echo_client_cleanup(struct obd_device *obddev, int flags)
+static int echo_client_cleanup(struct obd_device *obddev)
{
struct list_head *el;
struct ec_object *eco;
echo_put_object(eco);
}
- rc = obd_disconnect(ec->ec_exp, 0);
+ rc = obd_disconnect(ec->ec_exp);
if (rc != 0)
CERROR("fail to disconnect device: %d\n", rc);
RETURN (rc);
}
-static int echo_client_disconnect(struct obd_export *exp, int flags)
+static int echo_client_disconnect(struct obd_export *exp)
{
struct obd_device *obd;
struct echo_client_obd *ec;
OBD_FREE (ecl, sizeof (*ecl));
}
- rc = class_disconnect(exp, 0);
+ rc = class_disconnect(exp);
GOTO(out, rc);
out:
return rc;
RETURN(0);
}
-static int filter_client_free(struct obd_export *exp, int flags)
+static int filter_client_free(struct obd_export *exp)
{
struct filter_export_data *fed = &exp->exp_filter_data;
struct filter_obd *filter = &exp->exp_obd->u.filter;
if (fed->fed_fcd == NULL)
RETURN(0);
-
- if (flags & OBD_OPT_FAILOVER)
+
+ if (exp->exp_flags & OBD_OPT_FAILOVER)
GOTO(free, 0);
/* XXX if fcd_uuid were a real obd_uuid, I could use obd_uuid_equals */
RETURN(0);
err_client:
- class_disconnect_exports(obd, 0);
+ class_disconnect_exports(obd);
err_fsd:
filter_free_server_data(filter);
RETURN(rc);
int rc = 0;
ENTRY;
- dev_clear_rdonly(2);
-
if (!lcfg->lcfg_inlbuf1 || !lcfg->lcfg_inlbuf2)
RETURN(-EINVAL);
RETURN(PTR_ERR(obd->obd_fsops));
mnt = do_kern_mount(lcfg->lcfg_inlbuf2, MS_NOATIME | MS_NODIRATIME,
- lcfg->lcfg_inlbuf1, option);
+ lcfg->lcfg_inlbuf1, (void *)option);
rc = PTR_ERR(mnt);
if (IS_ERR(mnt))
GOTO(err_ops, rc);
+ LASSERT(!ll_check_rdonly(ll_sbdev(mnt->mnt_sb)));
+
if (lcfg->lcfg_inllen3 > 0 && lcfg->lcfg_inlbuf3) {
if (*lcfg->lcfg_inlbuf3 == 'f') {
obd->obd_replayable = 1;
return rc;
}
-static int filter_cleanup(struct obd_device *obd, int flags)
+static int filter_precleanup(struct obd_device *obd)
+{
+ target_cleanup_recovery(obd);
+ return (0);
+}
+
+static int filter_cleanup(struct obd_device *obd)
{
struct filter_obd *filter = &obd->u.filter;
+ ll_sbdev_type save_dev;
ENTRY;
-
- if (flags & OBD_OPT_FAILOVER)
+
+ if (obd->obd_fail)
CERROR("%s: shutting down for failover; client state will"
" be preserved.\n", obd->obd_name);
if (!list_empty(&obd->obd_exports)) {
CERROR("%s: still has clients!\n", obd->obd_name);
- class_disconnect_exports(obd, flags);
+ class_disconnect_exports(obd);
if (!list_empty(&obd->obd_exports)) {
CERROR("still has exports after forced cleanup?\n");
RETURN(-EBUSY);
}
}
- target_cleanup_recovery(obd);
- ldlm_namespace_free(obd->obd_namespace, flags & OBD_OPT_FORCE);
+ ldlm_namespace_free(obd->obd_namespace, obd->obd_force);
if (filter->fo_sb == NULL)
RETURN(0);
+ save_dev = ll_sbdev(filter->fo_sb);
lprocfs_free_obd_stats(obd);
lprocfs_obd_cleanup(obd);
filter_post(obd);
shrink_dcache_parent(filter->fo_sb->s_root);
- filter->fo_sb = 0;
if (atomic_read(&filter->fo_vfsmnt->mnt_count) > 1)
CERROR("%s: mount point %p busy, mnt_count: %d\n",
mntput(filter->fo_vfsmnt);
//destroy_buffers(filter->fo_sb->s_dev);
filter->fo_sb = NULL;
+
+ obd_llog_finish(obd, 0);
+
+ ll_clear_rdonly(save_dev);
+
fsfilt_put_ops(obd->obd_fsops);
lock_kernel();
- dev_clear_rdonly(2);
-
LCONSOLE_INFO("OST %s has stopped.\n", obd->obd_name);
-
+
RETURN(0);
}
if (rc) {
if (fcd)
OBD_FREE(fcd, sizeof(*fcd));
- class_disconnect(exp, 0);
+ class_disconnect(exp);
} else {
class_export_put(exp);
}
return rc;
}
-static int filter_precleanup(struct obd_device *obd, int flags)
-{
- int rc = 0;
- ENTRY;
-
- rc = obd_llog_finish(obd, 0);
- if (rc)
- CERROR("failed to cleanup llogging subsystem\n");
-
- RETURN(rc);
-}
-
/* Do extra sanity checks for grant accounting. We do this at connect,
* disconnect, and statfs RPC time, so it shouldn't be too bad. We can
* always get rid of it or turn it off when we know accounting is good. */
target_destroy_export(exp);
if (exp->exp_obd->obd_replayable)
- filter_client_free(exp, exp->exp_flags);
+ filter_client_free(exp);
filter_grant_discard(exp);
+
if (!(exp->exp_flags & OBD_OPT_FORCE))
filter_grant_sanity_check(exp->exp_obd, __FUNCTION__);
}
/* also incredibly similar to mds_disconnect */
-static int filter_disconnect(struct obd_export *exp, int flags)
+static int filter_disconnect(struct obd_export *exp)
{
struct obd_device *obd = exp->exp_obd;
- unsigned long irqflags;
struct llog_ctxt *ctxt;
int rc, err;
ENTRY;
LASSERT(exp);
class_export_get(exp);
- spin_lock_irqsave(&exp->exp_lock, irqflags);
- exp->exp_flags = flags;
- spin_unlock_irqrestore(&exp->exp_lock, irqflags);
-
- if (!(flags & OBD_OPT_FORCE))
+ if (!(exp->exp_flags & OBD_OPT_FORCE))
filter_grant_sanity_check(obd, __FUNCTION__);
filter_grant_discard(exp);
/* Disconnect early so that clients can't keep using export */
- rc = class_disconnect(exp, flags);
+ rc = class_disconnect(exp);
ldlm_cancel_locks_for_export(exp);
int rc = 0;
switch (cmd) {
- case OBD_IOC_ABORT_RECOVERY:
+ case OBD_IOC_ABORT_RECOVERY: {
CERROR("aborting recovery for device %s\n", obd->obd_name);
target_abort_recovery(obd);
RETURN(0);
+ }
+
+ case OBD_IOC_SYNC: {
+ CDEBUG(D_HA, "syncing ost %s\n", obd->obd_name);
+ rc = fsfilt_sync(obd, obd->u.filter.fo_sb);
+ RETURN(rc);
+ }
case OBD_IOC_SET_READONLY: {
void *handle;
ll_bdevname(sb, tmp));
handle = fsfilt_start(obd, inode, FSFILT_OP_MKNOD, NULL);
- LASSERT(handle);
- (void)fsfilt_commit(obd, inode, handle, 1);
+ if (!IS_ERR(handle))
+ rc = fsfilt_commit(obd, inode, handle, 1);
+
+ CDEBUG(D_HA, "syncing ost %s\n", obd->obd_name);
+ rc = fsfilt_sync(obd, obd->u.filter.fo_sb);
- dev_set_rdonly(ll_sbdev(obd->u.filter.fo_sb), 2);
+ ll_set_rdonly(ll_sbdev(obd->u.filter.fo_sb));
RETURN(0);
}
request = ptlrpc_prep_req(class_exp2cliimp(exp), OST_SETATTR, 1, &size,
NULL);
if (!request)
- RETURN(-ENOMEM);
+ RETURN(-ENOMEM);
body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof(*body));
memcpy(&body->oa, oa, sizeof(*oa));
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
MOD_INC_USE_COUNT;
#else
- if (!try_module_get(THIS_MODULE)) {
- CERROR("Can't get module. Is it alive?");
- return -EINVAL;
- }
+ if (!try_module_get(THIS_MODULE)) {
+ CERROR("Can't get module. Is it alive?");
+ return -EINVAL;
+ }
#endif
switch (cmd) {
case OBD_IOC_LOV_GET_CONFIG: {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
MOD_DEC_USE_COUNT;
#else
- module_put(THIS_MODULE);
+ module_put(THIS_MODULE);
#endif
return err;
}
memcmp(key, "next_id", strlen("next_id")) == 0) {
if (vallen != sizeof(obd_id))
RETURN(-EINVAL);
- obd->u.cli.cl_oscc.oscc_next_id = *((obd_id*)val) + 1;
+ obd->u.cli.cl_oscc.oscc_next_id = *((obd_id*)val) + 1;
CDEBUG(D_HA, "%s: set oscc_next_id = "LPU64"\n",
exp->exp_obd->obd_name,
obd->u.cli.cl_oscc.oscc_next_id);
memcmp(key, "growth_count", strlen("growth_count")) == 0) {
if (vallen != sizeof(int))
RETURN(-EINVAL);
- obd->u.cli.cl_oscc.oscc_grow_count = *((int*)val);
+ obd->u.cli.cl_oscc.oscc_grow_count = *((int*)val);
RETURN(0);
}
static int osc_llog_finish(struct obd_device *obd, int count)
{
- int rc;
+ struct llog_ctxt *ctxt;
+ int rc = 0;
ENTRY;
- rc = llog_cleanup(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT));
+ ctxt = llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT);
+ if (ctxt)
+ rc = llog_cleanup(ctxt);
if (rc)
RETURN(rc);
+
+ ctxt = llog_get_context(obd, LLOG_SIZE_REPL_CTXT);
+ if (ctxt)
+ rc = llog_cleanup(ctxt);
- rc = llog_cleanup(llog_get_context(obd, LLOG_SIZE_REPL_CTXT));
RETURN(rc);
}
return rc;
}
-static int osc_disconnect(struct obd_export *exp, int flags)
+static int osc_disconnect(struct obd_export *exp)
{
struct obd_device *obd = class_exp2obd(exp);
struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_SIZE_REPL_CTXT);
/* flush any remaining cancel messages out to the target */
llog_sync(ctxt, exp);
- rc = client_disconnect_export(exp, flags);
+ rc = client_disconnect_export(exp);
return rc;
}
RETURN(rc);
}
-int osc_cleanup(struct obd_device *obd, int flags)
+int osc_cleanup(struct obd_device *obd)
{
struct osc_creator *oscc = &obd->u.cli.cl_oscc;
int rc;
oscc->oscc_flags |= OSCC_FLAG_EXITING;
spin_unlock(&oscc->oscc_lock);
- rc = client_obd_cleanup(obd, flags);
+ rc = client_obd_cleanup(obd);
ptlrpcd_decref();
+ obd_llog_finish(obd, 0);
RETURN(rc);
}
RETURN(rc);
}
-static int ost_cleanup(struct obd_device *obd, int flags)
+static int ost_cleanup(struct obd_device *obd)
{
struct ost_obd *ost = &obd->u.ost;
int err = 0;
request->rq_send_state = LUSTRE_IMP_FULL;
request->rq_type = PTL_RPC_MSG_REQUEST;
request->rq_import = class_import_get(imp);
-
+ request->rq_export = NULL;
+
request->rq_req_cbid.cbid_fn = request_out_callback;
request->rq_req_cbid.cbid_arg = request;
/* Either we've been evicted, or the server has failed for
* some reason. Try to reconnect, and if that fails, punt to the
* upcall. */
- if (rc == -ENOTCONN) {
+ if ((rc == -ENOTCONN) || (rc == -ENODEV)) {
if (req->rq_send_state != LUSTRE_IMP_FULL ||
imp->imp_obd->obd_no_recov || imp->imp_dlm_fake) {
RETURN(-ENOTCONN);
LASSERT (req->rq_repmsg == &rs->rs_msg);
LASSERT (rs->rs_cb_id.cbid_fn == reply_out_callback);
LASSERT (rs->rs_cb_id.cbid_arg == rs);
-
LASSERT (req->rq_repmsg != NULL);
+
+ if (req->rq_export && req->rq_export->exp_obd &&
+ req->rq_export->exp_obd->obd_fail) {
+ /* Failed obd's only send ENODEV */
+ req->rq_type = PTL_RPC_MSG_ERR;
+ req->rq_status = -ENODEV;
+ CDEBUG(D_HA, "sending ENODEV from failed obd %d\n",
+ req->rq_export->exp_obd->obd_minor);
+ }
+
if (req->rq_type != PTL_RPC_MSG_ERR)
req->rq_type = PTL_RPC_MSG_REPLY;
* cleanly from the previous attempt */
LASSERT (!request->rq_receiving_reply);
+ if (request->rq_import->imp_obd &&
+ request->rq_import->imp_obd->obd_fail) {
+ CDEBUG(D_HA, "muting rpc for failed imp obd %s\n",
+ request->rq_import->imp_obd->obd_name);
+ /* this prevents us from waiting in ptlrpc_queue_wait */
+ request->rq_err = 1;
+ RETURN(-ENODEV);
+ }
+
connection = request->rq_import->imp_connection;
if (request->rq_bulk != NULL) {
RETURN(rc);
}
+static inline void ptlrpc_update_next_ping(struct obd_import *imp)
+{
+ imp->imp_next_ping = jiffies + obd_timeout * HZ;
+}
+
#ifdef __KERNEL__
static int ptlrpc_pinger_main(void *arg)
{
imp->imp_force_verify = 0;
spin_unlock_irqrestore(&imp->imp_lock, flags);
- if (imp->imp_next_ping <= this_ping || force) {
+ if (force ||
+ time_after_eq(this_ping, imp->imp_next_ping)) {
if (level == LUSTRE_IMP_DISCON &&
!imp->imp_deactive) {
/* wait at least a timeout before
trying recovery again. */
- imp->imp_next_ping = jiffies +
- (obd_timeout * HZ);
+ ptlrpc_update_next_ping(imp);
ptlrpc_initiate_recovery(imp);
}
else if (level != LUSTRE_IMP_FULL ||
ptlrpc_ping(imp);
}
- } else {
- if (imp->imp_pingable)
- CDEBUG(D_HA, "don't need to ping %s "
- "(%lu > %lu)\n",
- imp->imp_target_uuid.uuid,
- imp->imp_next_ping, this_ping);
+ } else if (!imp->imp_pingable) {
+ continue;
}
+
+ CDEBUG(D_HA, "don't need to ping %s (%lu > %lu)\n",
+ imp->imp_target_uuid.uuid,
+ imp->imp_next_ping, this_ping);
+
+ /* obd_timeout might have changed */
+ if (time_after(imp->imp_next_ping,
+ this_ping + obd_timeout * HZ))
+ ptlrpc_update_next_ping(imp);
}
up(&pinger_sem);
/* Wait until the next ping time, or until we're stopped. */
time_to_next_ping = this_ping + (obd_timeout * HZ) - jiffies;
CDEBUG(D_HA, "next ping in %lu (%lu)\n", time_to_next_ping,
- this_ping + (obd_timeout * HZ));
+ this_ping + obd_timeout * HZ);
if (time_to_next_ping > 0) {
lwi = LWI_TIMEOUT(time_to_next_ping, NULL, NULL);
l_wait_event(thread->t_ctl_waitq,
void ptlrpc_pinger_sending_on_import(struct obd_import *imp)
{
- imp->imp_next_ping = jiffies + (obd_timeout * HZ);
+ ptlrpc_update_next_ping(imp);
}
int ptlrpc_pinger_add_import(struct obd_import *imp)
down(&pinger_sem);
CDEBUG(D_HA, "adding pingable import %s->%s\n",
imp->imp_obd->obd_uuid.uuid, imp->imp_target_uuid.uuid);
- imp->imp_next_ping = jiffies + (obd_timeout * HZ);
+ ptlrpc_update_next_ping(imp);
/* XXX sort, blah blah */
list_add_tail(&imp->imp_pinger_chain, &pinger_imports);
class_import_get(imp);
static struct pinger_data {
int pd_recursion;
- unsigned long pd_this_ping;
- unsigned long pd_next_ping;
+ unsigned long pd_this_ping; /* jiffies */
+ unsigned long pd_next_ping; /* jiffies */
struct ptlrpc_request_set *pd_set;
} pinger_args;
static int pinger_check_rpcs(void *arg)
{
- unsigned long curtime = time(NULL);
+ unsigned long curtime = jiffies;
struct ptlrpc_request *req;
struct ptlrpc_request_set *set;
struct list_head *iter;
}
/* have we reached ping point? */
- if (!pd->pd_set && pd->pd_next_ping > curtime) {
+ if (!pd->pd_set && time_before(curtime, pd->pd_next_ping)) {
pd->pd_recursion--;
return 0;
}
down(&pinger_sem);
list_for_each(iter, &pinger_imports) {
struct obd_import *imp =
- list_entry(iter, struct obd_import,
- imp_pinger_chain);
+ list_entry(iter, struct obd_import, imp_pinger_chain);
int generation, level;
unsigned long flags;
- if (imp->imp_next_ping <= pd->pd_this_ping) {
+ if (time_after_eq(pd->pd_this_ping, imp->imp_next_ping)) {
/* Add a ping. */
spin_lock_irqsave(&imp->imp_lock, flags);
generation = imp->imp_generation;
rc = ptlrpc_check_set(set);
/* not finished, and we are not expired, simply return */
- if (!rc && curtime < pd->pd_this_ping + obd_timeout) {
+ if (!rc && time_before(curtime, pd->pd_this_ping + obd_timeout * HZ)) {
CDEBUG(D_HA, "not finished, but also not expired\n");
pd->pd_recursion--;
return 0;
ptlrpc_set_destroy(set);
pd->pd_set = NULL;
- pd->pd_next_ping = pd->pd_this_ping + obd_timeout;
+ pd->pd_next_ping = pd->pd_this_ping + obd_timeout * HZ;
pd->pd_this_ping = 0; /* XXX for debug */
CDEBUG(D_HA, "finished a round ping\n");
void ptlrpc_pinger_sending_on_import(struct obd_import *imp)
{
down(&pinger_sem);
- imp->imp_next_ping = time(NULL) + obd_timeout;
+ ptlrpc_update_next_ping(imp);
if (pinger_args.pd_set == NULL &&
- pinger_args.pd_next_ping > imp->imp_next_ping) {
+ time_before(imp->imp_next_ping, pinger_args.pd_next_ping)) {
CDEBUG(D_HA, "set next ping to %ld(cur %ld)\n",
- imp->imp_next_ping, time(NULL));
+ imp->imp_next_ping, jiffies);
pinger_args.pd_next_ping = imp->imp_next_ping;
}
up(&pinger_sem);
* (request, for example) in addition to the one from the hash table.
* We don't have such a reference here, so make one. */
class_export_get(exp);
- rc = obd_disconnect(exp, 0);
+ rc = obd_disconnect(exp);
if (rc)
CERROR("disconnecting export %p failed: %d\n", exp, rc);
}
request->rq_export->exp_conn_cnt);
goto put_conn;
}
+ if (request->rq_export->exp_obd
+ && request->rq_export->exp_obd->obd_fail) {
+ /* Failing over, don't handle any more reqs, send
+ error response instead. */
+ CDEBUG(D_HA, "Dropping req %p for failed obd %s\n",
+ request, request->rq_export->exp_obd->obd_name);
+ request->rq_status = -ENODEV;
+ ptlrpc_error(request);
+ goto put_conn;
+ }
request->rq_export->exp_last_request_time = CURRENT_SECONDS;
}
noinst_PROGRAMS += small_write multiop sleeptest ll_sparseness_verify cmknod
noinst_PROGRAMS += ll_sparseness_write mrename ll_dirstripe_verify mkdirmany rmdirmany
noinst_PROGRAMS += openfilleddirunlink rename_many memhog iopentest1 iopentest2
-noinst_PROGRAMS += mmap_sanity
+noinst_PROGRAMS += mmap_sanity writemany
if MPITESTS
noinst_PROGRAMS += write_append_truncate createmany_mpi
endif
stat createmany statmany multifstat createtest mlink \
opendirunlink opendevunlink unlinkmany fchdir_test \
checkstat wantedi statone runas openfile \
- mcreate mkdirmany utime o_directory small_write multiop
+ mcreate mkdirmany utime o_directory small_write multiop \
+ writemany
always := $(host-progs)
o_directory-objs :=o_directory.o
small_write-objs :=small_write.o
multiop-objs :=multiop.o
+writemany-objs := writemany.o
+
ost1_HOST=${ost1_HOST:-"`hostname`"}
ost2_HOST=${ost2_HOST:-"`hostname`"}
EXTRA_OSTS=${EXTRA_OSTS:-"`hostname`"}
-client_HOST="'*'"
+client_HOST=${client_HOST:-"'*'"}
LIVE_CLIENT=${LIVE_CLIENT:-"`hostname`"}
# This should always be a list, not a regexp
FAIL_CLIENTS=${FAIL_CLIENTS:-""}
${LMC} --add net --node client --nid '*' --nettype $NETTYPE || exit 12
# configure mds server
-${LMC} --add mds --nspath /mnt/mds_ns --node localhost --mds mds1 --fstype $FSTYPE --dev $MDSDEV --size $MDSSIZE $JARG $IARG || exit 20
+${LMC} --add mds --node localhost --mds mds1 --fstype $FSTYPE \
+ --dev $MDSDEV --size $MDSSIZE $JARG $IARG $MDSOPT || exit 20
# configure ost
-${LMC} -m $config --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES --stripe_cnt $STRIPES_PER_OBJ --stripe_pattern 0 || exit 20
+${LMC} -m $config --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES \
+ --stripe_cnt $STRIPES_PER_OBJ --stripe_pattern 0 $LOVOPT || exit 20
# only specify "--mkfsoptions='-i 8192'" here because test fs is so small,
# on a real fs this is not needed unless all files tiny with many stripes
-${LMC} --add ost --nspath /mnt/ost_ns --node localhost --lov lov1 --fstype $FSTYPE --dev $OSTDEV --size $OSTSIZE --mkfsoptions="-i 8192" $JARG || exit 30
+${LMC} --add ost --nspath /mnt/ost_ns --node localhost --lov lov1 \
+ --fstype $FSTYPE --dev $OSTDEV --size $OSTSIZE \
+ --mkfsoptions="-i 8192" $JARG $OSTOPT || exit 30
# create client config
-${LMC} --add mtpt --node localhost --path $MOUNT --mds mds1 --lov lov1 || exit 40
-${LMC} --add mtpt --node client --path $MOUNT2 --mds mds1 --lov lov1 || exit 41
+${LMC} --add mtpt --node localhost --path $MOUNT --mds mds1 --lov lov1 \
+ $CLIENTOPT || exit 40
+${LMC} --add mtpt --node client --path $MOUNT2 --mds mds1 --lov lov1 \
+ $CLIENTOPT || exit 41
${LMC} --add net --node client --nid '*' --nettype $NETTYPE || exit 12
# configure mds server
-${LMC} --format --add mds --node localhost --mds mds1 --fstype $FSTYPE --dev $MDSDEV --size $MDSSIZE || exit 20
+${LMC} --format --add mds --node localhost --mds mds1 --fstype $FSTYPE \
+ --dev $MDSDEV --size $MDSSIZE $MDSOPT || exit 20
# configure ost
-${LMC} --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES --stripe_cnt $STRIPES_PER_OBJ --stripe_pattern 0 || exit 20
+${LMC} --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES \
+ --stripe_cnt $STRIPES_PER_OBJ --stripe_pattern 0 $LOVOPT || exit 20
for num in `seq $OSTCOUNT`; do
OST=ost$num
eval $DEVPTR=${!DEVPTR:=$TMP/$OST-`hostname`}
# only specify "--mkfsoptions='-i 8192'" here because test fs is so small,
# on a real fs this is not needed unless all files tiny with many stripes
- ${LMC} --add ost --node localhost --lov lov1 --ost $OST --fstype $FSTYPE --dev ${!DEVPTR} --size $OSTSIZE --mkfsoptions="-i 8192" $JARG || exit 30
+ ${LMC} --add ost --node localhost --lov lov1 --ost $OST --fstype $FSTYPE \
+ --dev ${!DEVPTR} --size $OSTSIZE --mkfsoptions="-i 8192" \
+ $JARG $OSTOPT || exit 30
done
if [ -z "$ECHO_CLIENT" ]; then
# create client config
- ${LMC} --add mtpt --node localhost --path $MOUNT --mds mds1 --lov lov1 || exit 40
- ${LMC} --add mtpt --node client --path $MOUNT2 --mds mds1 --lov lov1 || exit 41
+ ${LMC} --add mtpt --node localhost --path $MOUNT --mds mds1 --lov lov1 \
+ $CLIENTOPT || exit 40
+ ${LMC} --add mtpt --node client --path $MOUNT2 --mds mds1 --lov lov1 \
+ $CLIENTOPT || exit 41
else
${LMC} --add echo_client --node localhost --ost lov1 || exit 42
fi
# setting SETUP=" " and CLEANUP=" "
SETUP=${SETUP:-"setup"}
CLEANUP=${CLEANUP:-"cleanup"}
-
+FORCE=${FORCE:-"--force"}
make_config() {
rm -f $XMLCONFIG
sysctl -w lustre.fail_loc=0x80000503
# need to write enough to ensure we send an RPC
do_facet client dd if=/dev/zero of=$DIR/$tfile bs=1024k count=2
-
sleep $TIMEOUT
sysctl -w lustre.fail_loc=0
do_facet client "df $DIR"
test_24() { # bug 2248 - eviction fails writeback but app doesn't see it
mkdir -p $DIR/$tdir
cancel_lru_locks OSC
- multiop $DIR/$tdir/$tfile Owyw_yc &
+ multiop $DIR/$tdir/$tfile Owy_wyc &
MULTI_PID=$!
usleep 500
# OBD_FAIL_PTLRPC_BULK_PUT_NET|OBD_FAIL_ONCE
}
run_test 24 "fsync error (should return error)"
+
+test_25a() {
+ mkdir -p $DIR/$tdir
+ # put a load of file creates/writes/deletes for 10 min.
+ do_facet client "writemany -q -a $DIR/$tdir/$tfile 600 5" &
+ CLIENT_PID=$!
+ echo writemany pid $CLIENT_PID
+ sleep 10
+ FAILURE_MODE="SOFT"
+ fail mds
+ # wait for client to reconnect to MDS
+ sleep 60
+ fail mds
+ sleep 60
+ fail mds
+ # client process should see no problems even though MDS went down
+ wait $CLIENT_PID
+ rc=$?
+ echo writemany returned $rc
+ return $rc
+}
+run_test 25a "failover MDS under load"
+
+test_25b() {
+ mkdir -p $DIR/$tdir
+ # put a load of file creates/writes/deletes
+ do_facet client "writemany -q -a $DIR/$tdir/$tfile 300 5" &
+ CLIENT_PID=$!
+ echo writemany pid $CLIENT_PID
+ sleep 1
+ FAILURE_MODE="SOFT"
+ facet_failover mds
+ # failover at various points during recovery
+ sleep 1
+ facet_failover mds
+ sleep 5
+ facet_failover mds
+ sleep 10
+ facet_failover mds
+ sleep 20
+ facet_failover mds
+ # client process should see no problems even though MDS went down
+ # and recovery was interrupted
+ wait $CLIENT_PID
+ rc=$?
+ echo writemany returned $rc
+ return $rc
+}
+run_test 25b "failover MDS during recovery"
+
+test_25c_guts() {
+ do_facet client "writemany -q $DIR/$tdir/$tfile 600 5" &
+ CLIENT_PID=$!
+ echo writemany pid $CLIENT_PID
+ sleep 10
+ FAILURE_MODE="SOFT"
+ fail ost
+ rc=0
+ wait $CLIENT_PID || rc=$?
+ # active client process should see an EIO for down OST
+ [ $rc -eq 5 ] && { echo "writemany correctly failed $rc" && return 0; }
+ # but timing or failover setup may allow success
+ [ $rc -eq 0 ] && { echo "writemany succeeded" && return 0; }
+ echo "writemany returned $rc"
+ return $rc
+}
+
+test_25c() {
+ mkdir -p $DIR/$tdir
+ test_25c_guts
+ rc=$?
+ [ $rc -ne 0 ] && { return $rc; }
+ # wait for client to reconnect to OST
+ sleep 30
+ test_25c_guts
+ rc=$?
+ [ $rc -ne 0 ] && { return $rc; }
+ sleep 30
+ test_25c_guts
+ rc=$?
+ return $rc
+}
+run_test 25c "failover OST under load"
+
$CLEANUP
SETUP=${SETUP:-"setup"}
CLEANUP=${CLEANUP:-"cleanup"}
+FORCE=${FORCE:-"--force"}
gen_config() {
rm -f $XMLCONFIG
umount $MOUNT2 || true
umount $MOUNT || true
- rmmod llite
+ rmmod llite || true
stop mds ${FORCE}
stop ost2 ${FORCE}
stop ost ${FORCE} --dump $TMP/replay-dual-`hostname`.log
ONLY=${ONLY:-"$*"}
# bug number for skipped test: 2108 3637 3561 5188/5749
-ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"42a 42c 45 68"}
+ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"42a 42c 45 68"}
# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
[ "$ALWAYS_EXCEPT$EXCEPT" ] && \
clean() {
echo -n "cln.."
- sh llmountcleanup.sh > /dev/null || exit 20
+ sh llmountcleanup.sh ${FORCE} > /dev/null || exit 20
I_MOUNTED=no
}
CLEAN=${CLEAN:-:}
$TRACE rmdir $DIR/d48e || error "remove parent $DIR/d48e failed"
$TRACE touch $DIR/d48e || error "'touch $DIR/d48e' failed"
$TRACE chmod +x $DIR/d48e || error "'chmod +x $DIR/d48e' failed"
- $TRACE wait $cdpid && error "'cd ..' worked after recreate parent"
- $TRACE rm $DIR/d48e || error "'$DIR/d48e' failed"
+ $TRACE wait $cdpid && echo "'cd ..' worked after recreate parent"
+ $TRACE rm $DIR/d48e || error "rm '$DIR/d48e' failed"
}
run_test 48e "Access to recreated parent subdir (should return errors)"
clean() {
echo -n "cln.."
- sh llmountcleanup.sh > /dev/null || exit 20
+ sh llmountcleanup.sh ${FORCE} > /dev/null || exit 20
}
CLEAN=${CLEAN:-}
do_node $client mkdir $mnt 2> /dev/null || :
if [ -x /sbin/mount.lustre ] ; then
- do_node $client mount -t lustre -o nettype=$NETTYPE `facet_active_host mds`:/mds_svc/client_facet $mnt || return 1
+ do_node $client mount -t lustre -o nettype=$NETTYPE,$MOUNTOPT \
+ `facet_active_host mds`:/mds_svc/client_facet $mnt || return 1
else
- # this is so cheating
- do_node $client $LCONF --nosetup --node client_facet $XMLCONFIG > /dev/null || return 2
- do_node $client $LLMOUNT -o nettype=$NETTYPE `facet_active_host mds`:/mds_svc/client_facet $mnt || return 4
+ # this is so cheating
+ do_node $client $LCONF --nosetup --node client_facet $XMLCONFIG > \
+ /dev/null || return 2
+ do_node $client $LLMOUNT -o nettype=$NETTYPE,$MOUNTOPT \
+ `facet_active_host mds`:/mds_svc/client_facet $mnt || return 4
fi
[ -d /r ] && $LCTL modules > /r/tmp/ogdb-`hostname`
facet=$1
if [ "$FAILURE_MODE" = HARD ]; then
$POWER_UP `facet_active_host $facet`
+ else
+ sleep 10
fi
}
shift
rm -f ${facet}active
add_facet $facet
- do_lmc --add mds --node ${facet}_facet --mds ${facet}_svc --fstype $FSTYPE $*
+ do_lmc --add mds --node ${facet}_facet --mds ${facet}_svc \
+ --fstype $FSTYPE $* $MDSOPT
}
add_mdsfailover() {
facet=$1
shift
add_facet ${facet}failover --lustre_upcall $UPCALL
- do_lmc --add mds --node ${facet}failover_facet --mds ${facet}_svc --fstype $FSTYPE $*
+ do_lmc --add mds --node ${facet}failover_facet --mds ${facet}_svc \
+ --fstype $FSTYPE $* $MDSOPT
}
add_ost() {
shift
rm -f ${facet}active
add_facet $facet
- do_lmc --add ost --node ${facet}_facet --ost ${facet}_svc --fstype $FSTYPE $*
+ do_lmc --add ost --node ${facet}_facet --ost ${facet}_svc \
+ --fstype $FSTYPE $* $OSTOPT
}
add_ostfailover() {
facet=$1
shift
add_facet ${facet}failover
- do_lmc --add ost --failover --node ${facet}failover_facet --ost ${facet}_svc --fstype $FSTYPE $*
+ do_lmc --add ost --failover --node ${facet}failover_facet \
+ --ost ${facet}_svc --fstype $FSTYPE $* $OSTOPT
}
add_lov() {
lov=$1
mds_facet=$2
shift; shift
- do_lmc --add lov --mds ${mds_facet}_svc --lov $lov $*
-
+ do_lmc --add lov --mds ${mds_facet}_svc --lov $lov $* $LOVOPT
}
add_client() {
mds=$2
shift; shift
add_facet $facet --lustre_upcall $UPCALL
- do_lmc --add mtpt --node ${facet}_facet --mds ${mds}_svc $*
-
+ do_lmc --add mtpt --node ${facet}_facet --mds ${mds}_svc $* $CLIENTOPT
}
# configure mds server
echo; echo "adding MDS on: $MDSNODE"
-${LMC} -m $config --add mds --format --node $MDSNODE --mds mds1 --fstype $FSTYPE --dev $MDSDEV --size $MDSSIZE ||exit 10
+${LMC} -m $config --add mds --node $MDSNODE --mds mds1 --fstype $FSTYPE \
+ --dev $MDSDEV --size $MDSSIZE $MDSOPT || exit 10
# configure ost
-${LMC} -m $config --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES --stripe_cnt $STRIPECNT --stripe_pattern 0 || exit 20
+${LMC} -m $config --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES \
+ --stripe_cnt $STRIPECNT --stripe_pattern 0 $LOVOPT || exit 20
COUNT=1
echo -n "adding OST on:"
for NODE in $OSTNODES; do
OSTARGS="--osdtype=obdecho"
;;
esac
- ${LMC} -m $config --add ost --node $NODE --lov lov1 $OSTARGS $OSTFAILOVER || exit 21
+ ${LMC} -m $config --add ost --node $NODE --lov lov1 $OSTARGS \
+ $OSTFAILOVER $OSTOPT || exit 21
COUNT=`expr $COUNT + 1`
done
echo; echo -n "adding CLIENT on:"
for NODE in $CLIENTS; do
echo -n " $NODE"
- ${LMC} -m $config --add mtpt --node $NODE --path $MOUNT --mds mds1 --lov lov1 || exit 30
+ ${LMC} -m $config --add mtpt --node $NODE --path $MOUNT --mds mds1 \
+ --lov lov1 $CLIENTOPT || exit 30
done
echo
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+#define difftime(a, b) \
+ ((double)(a)->tv_sec - (b)->tv_sec + \
+ ((double)((a)->tv_usec - (b)->tv_usec) / 1000000))
+
+
+
+char cmdname[512];
+int o_abort = 0;
+int o_quiet = 0;
+
+struct kid_list_t {
+ pid_t kid;
+ struct kid_list_t *next;
+};
+
+struct kid_list_t *head = NULL;
+
+void push_kid(pid_t kid)
+{
+ struct kid_list_t *new;
+ new = (struct kid_list_t *)malloc(sizeof(struct kid_list_t));
+ new->kid = kid;
+ new->next = head;
+ head = new;
+}
+
+void kill_kids(void)
+{
+ while(head) {
+ kill(head->kid, SIGTERM);
+ head = head->next;
+ }
+}
+
+int wait_for_threads(int live_threads)
+{
+ int rc = 0;
+
+ while (live_threads > 0) {
+ int status;
+ pid_t ret;
+
+ ret = waitpid(0, &status, 0);
+ if (ret == 0) {
+ continue;
+ }
+
+ if (ret < 0) {
+ fprintf(stderr, "%s: error: wait - %s\n",
+ cmdname, strerror(errno));
+ if (!rc)
+ rc = errno;
+ } else {
+ /*
+ * This is a hack. We _should_ be able to use
+ * WIFEXITED(status) to see if there was an
+ * error, but it appears to be broken and it
+ * always returns 1 (OK). See wait(2).
+ */
+ int err = WEXITSTATUS(status);
+ if (err || WIFSIGNALED(status))
+ fprintf(stderr,
+ "%s: error: PID %d had rc=%d\n",
+ cmdname, ret, err);
+ /* Record first error */
+ if (!rc)
+ rc = err;
+
+ /* Give up on first error */
+ if (rc && o_abort) {
+ kill_kids();
+ break;
+ }
+
+ live_threads--;
+ }
+ }
+ if (!o_quiet)
+ printf("%s done, rc = %d\n", cmdname, rc);
+ return rc;
+}
+
+void print_err(char *op, char *filename, struct timeval *time, int err)
+{
+ fprintf(stderr, "%s: %d.%.06d error: %s(%s): %s\n",
+ cmdname, (int)(time->tv_sec), (int)(time->tv_usec), op,
+ filename, strerror(errno));
+}
+
+int run_one_child(char *file, int thread, int seconds)
+{
+ struct timeval start, cur;
+ double diff;
+ char filename[1024];
+ char buf[1024];
+ int fd, rc = 0, rand, maxrand, len;
+ long nfiles = 0, nbytes = 0;
+
+ if (!o_quiet)
+ printf("%s: running thread #%d\n", cmdname, thread);
+
+ srandom(thread);
+ /* Higher thread numbers will produce bigger random files.
+ Thread 1 will produce only 0-len files. */
+ maxrand = 1; rand = thread;
+ while (--rand)
+ maxrand *= 10;
+
+ gettimeofday(&start, NULL);
+
+ while(!rc) {
+ gettimeofday(&cur, NULL);
+ if (cur.tv_sec > (start.tv_sec + seconds))
+ break;
+
+ sprintf(filename, "%s-%d-%ld", file, thread, nfiles);
+
+ fd = open(filename, O_RDWR | O_CREAT, 0666);
+ if (fd < 0) {
+ print_err("open", filename, &cur, errno);
+ rc = errno;
+ break;
+ }
+
+ sprintf(buf, "%s %010ld %.19s.%012d\n", cmdname,
+ nfiles++, ctime(&cur.tv_sec), (int)cur.tv_usec);
+ len = strlen(buf);
+
+ rand = random() % maxrand;
+ while (rand-- > 0) {
+ if (write(fd, buf, len) != len) {
+ print_err("write", filename, &cur, errno);
+ rc = errno;
+ break;
+ }
+ nbytes += len;
+ }
+
+ if (close(fd) < 0) {
+ print_err("close", filename, &cur, errno);
+ rc = errno;
+ break;
+ }
+ if (unlink(filename) < 0) {
+ print_err("unlink", filename, &cur, errno);
+ rc = errno;
+ break;
+ }
+ }
+
+ diff = difftime(&cur, &start);
+ if (!o_quiet)
+ printf("%s: %7ld files, %4ld MB in %.2fs (%7.2f files/s, "
+ "%5.2f MB/s): rc = %d\n",
+ cmdname, nfiles, nbytes >> 20, diff,
+ (double)nfiles / diff, (double)nbytes/1024/1024 / diff,
+ rc);
+
+ return rc;
+}
+
+void usage(char *name)
+{
+ fprintf(stderr,
+ "usage: %s [opts] <dirname> <seconds> <threads>\n",
+ name);
+ fprintf(stderr, " -q quiet\n");
+ fprintf(stderr, " -a abort other children on first err\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned long duration;
+ int threads = 0;
+ char *end;
+ char *directory;
+ int i = 1, rc = 0;
+
+ sprintf(cmdname, "%s", argv[0]);
+
+ while((i < argc) && (argv[i][0] == '-')) {
+ switch (argv[i][1]) {
+ case 'q':
+ o_quiet++;
+ break;
+ case 'a':
+ o_abort++;
+ break;
+ }
+ i++;
+ }
+
+ if ((argc - i) < 3)
+ usage(argv[0]);
+
+ directory = argv[i];
+ duration = strtoul(argv[++i], &end, 0);
+ if (*end) {
+ fprintf(stderr, "%s: error: bad number of seconds '%s'\n",
+ cmdname, argv[i]);
+ exit(2);
+ }
+
+ threads = strtoul(argv[++i], &end, 0);
+ if (*end) {
+ fprintf(stderr, "%s: error: bad thread count '%s'\n",
+ cmdname, argv[i]);
+ exit(2);
+ }
+
+ for (i = 1; i <= threads; i++) {
+ rc = fork();
+ if (rc < 0) {
+ if (!o_quiet)
+ fprintf(stderr, "%s: error: #%d - %s\n",
+ cmdname, i, strerror(rc = errno));
+ return (rc);
+ }
+ if (rc == 0) {
+ /* children */
+ sprintf(cmdname, "%s-%d", argv[0], i);
+ return (run_one_child(directory, i, duration));
+ } else {
+ /* parent */
+ push_kid(rc);
+ }
+ }
+ /* parent process */
+ if (!o_quiet)
+ printf("%s will run for %ld minutes\n", cmdname, duration/60);
+ return (wait_for_threads(threads));
+}
Module.cleanup(self)
clean_loop(self.devpath)
- def msd_remaining(self):
+ def mds_remaining(self):
out = lctl.device_list()
for s in out:
if string.split(s)[2] in ('mds',):
+ if string.split(s)[1] in ('ST',):
+ return 0
return 1
def safe_to_clean(self):
return self.active
def safe_to_clean_modules(self):
- return not self.msd_remaining()
+ return not self.mds_remaining()
def cleanup(self):
if not self.active:
e.dump()
cleanup_error(e.rc)
Module.cleanup(self)
- if not self.msd_remaining() and is_prepared('MDT'):
+ if not self.mds_remaining() and is_prepared('MDT'):
try:
lctl.cleanup("MDT", "MDT_UUID", config.force,
config.failover)