+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ */
#ifndef __LVFS_LINUX_H__
#define __LVFS_LINUX_H__
int flags);
struct l_linux_dirent {
- ino_t d_ino;
- unsigned long d_off;
- unsigned short d_reclen;
- char d_name[1];
+ struct list_head lld_list;
+ ino_t lld_ino;
+ unsigned long lld_off;
+ char lld_name[LL_FID_NAMELEN];
};
-
struct l_readdir_callback {
- struct l_linux_dirent *current_dir;
- struct l_linux_dirent *previous;
- int count;
- int error;
+ struct l_linux_dirent *lrc_dirent;
+ struct list_head *lrc_list;
};
#endif
-Index: linux-2.4.20/fs/ext3/extents.c
+Index: linux-2.4.24/fs/ext3/extents.c
===================================================================
---- linux-2.4.20.orig/fs/ext3/extents.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.20/fs/ext3/extents.c 2004-01-24 14:19:29.000000000 +0300
-@@ -0,0 +1,2224 @@
+--- 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-02-06 10:18:42.000000000 +0300
+@@ -0,0 +1,2347 @@
+/*
+ * Copyright (C) 2003 Alex Tomas <alex@clusterfs.com>
+ *
+ struct ext3_extents_tree *tree,
+ struct ext3_ext_path *path)
+{
++ int err;
++
+ if (path->p_bh) {
+ /* path points to block */
-+ return ext3_journal_get_write_access(handle, path->p_bh);
++ 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);
+ }
-+
-+ /* path points to leaf/index in inode body */
-+ return ext3_ext_get_access_for_root(handle, tree);
++ return err;
+}
+
+/*
+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 */
-+ return ext3_journal_dirty_metadata(handle, path->p_bh);
++ 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);
+ }
-+
-+ /* path points to leaf/index in inode body */
-+ return ext3_ext_mark_root_dirty(handle, tree);
++ return err;
+}
+
+static int inline
+ 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->e_generation++;
++}
++
+static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
+{
+ int size;
+ struct ext3_extent_idx *ix;
+ int l = 0, k, r;
+
++ EXT_ASSERT(eh->e_magic == EXT3_EXT_MAGIC);
+ EXT_ASSERT(eh->e_num <= eh->e_max);
+ EXT_ASSERT(eh->e_num > 0);
+
+
+ chix = ix = EXT_FIRST_INDEX(eh);
+ for (k = 0; k < eh->e_num; k++, ix++) {
++ if (k != 0 && ix->e_block <= ix[-1].e_block) {
++ printk("k=%d, ix=0x%p, first=0x%p\n", k,
++ ix, EXT_FIRST_INDEX(eh));
++ printk("%u <= %u\n",
++ ix->e_block,ix[-1].e_block);
++ }
+ EXT_ASSERT(k == 0 || ix->e_block > ix[-1].e_block);
+ if (block < ix->e_block)
+ break;
+ struct ext3_extent *ex;
+ int l = 0, k, r;
+
++ EXT_ASSERT(eh->e_magic == EXT3_EXT_MAGIC);
+ EXT_ASSERT(eh->e_num <= eh->e_max);
+
+ if (eh->e_num == 0) {
+ eh = EXT_ROOT_HDR(tree);
+ eh->e_depth = 0;
+ eh->e_num = 0;
++ eh->e_magic = EXT3_EXT_MAGIC;
+ eh->e_max = ext3_ext_space_root(tree);
+ ext3_ext_mark_root_dirty(handle, tree);
+ return 0;
+ EXT_ASSERT(tree->root);
+
+ eh = EXT_ROOT_HDR(tree);
++ EXT_ASSERT(eh);
+ i = depth = EXT_DEPTH(tree);
+ EXT_ASSERT(eh->e_max);
++ EXT_ASSERT(eh->e_magic == EXT3_EXT_MAGIC);
+ EXT_ASSERT(i == 0 || eh->e_num > 0);
+
+ /* account possible depth increase */
+ ix->e_leaf = ptr;
+ curp->p_hdr->e_num++;
+
++ EXT_ASSERT(curp->p_hdr->e_num <= curp->p_hdr->e_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);
+
+
+ /* 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].e_block;
+ ext_debug(tree, "leaf will be splitted."
+ neh = EXT_BLOCK_HDR(bh);
+ neh->e_num = 0;
+ neh->e_max = ext3_ext_space_block(tree);
++ neh->e_magic = EXT3_EXT_MAGIC;
++ neh->e_depth = 0;
+ ex = EXT_FIRST_EXTENT(neh);
+
+ /* move remain of path[depth] to the new leaf */
+ 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\n",
++ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
+ path[depth].p_ext->e_block,
+ path[depth].p_ext->e_start,
-+ path[depth].p_ext->e_num);
++ path[depth].p_ext->e_num,
++ newblock);
+ memmove(ex++, path[depth].p_ext++,
+ sizeof(struct ext3_extent));
+ neh->e_num++;
+
+ /* correct old leaf */
+ if (m) {
-+ if ((err = ext3_ext_get_access(handle, tree, path)))
++ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
+ goto cleanup;
+ path[depth].p_hdr->e_num -= m;
-+ if ((err = ext3_ext_dirty(handle, tree, path)))
++ if ((err = ext3_ext_dirty(handle, tree, path + depth)))
+ goto cleanup;
+
+ }
+
+ neh = EXT_BLOCK_HDR(bh);
+ neh->e_num = 1;
++ neh->e_magic = EXT3_EXT_MAGIC;
+ neh->e_max = ext3_ext_space_block_idx(tree);
++ neh->e_depth = depth - i;
+ fidx = EXT_FIRST_INDEX(neh);
+ fidx->e_block = border;
+ fidx->e_leaf = oldblock;
+
-+ ext_debug(tree, "int.index at %d (block %u): %d -> %d\n",
-+ i, (unsigned) newblock,
-+ (int) border,
-+ (int) 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\n",
++ 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->e_block,
-+ path[i].p_idx->e_leaf);
++ path[i].p_idx->e_leaf, newblock);
+ memmove(++fidx, path[i].p_idx++,
+ sizeof(struct ext3_extent_idx));
+ neh->e_num++;
++ EXT_ASSERT(neh->e_num <= neh->e_max);
+ m++;
+ }
-+
+ mark_buffer_uptodate(bh, 1);
+ unlock_buffer(bh);
+
+ struct ext3_ext_path *path,
+ struct ext3_extent *newext)
+{
-+ struct buffer_head *bh;
+ struct ext3_ext_path *curp = path;
+ struct ext3_extent_header *neh;
+ struct ext3_extent_idx *fidx;
-+ int len, err = 0;
++ struct buffer_head *bh;
+ unsigned long newblock;
++ int err = 0;
+
+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
+ if (newblock == 0)
+ }
+
+ /* move top-level index/leaf into new block */
-+ len = sizeof(struct ext3_extent_header) +
-+ sizeof(struct ext3_extent) * curp->p_hdr->e_max;
-+ EXT_ASSERT(len >= 0 && len < 4096);
-+ memmove(bh->b_data, curp->p_hdr, len);
++ memmove(bh->b_data, curp->p_hdr, tree->buffer_len);
+
+ /* set size of new block */
+ neh = EXT_BLOCK_HDR(bh);
-+ neh->e_max = ext3_ext_space_block(tree);
++ /* old root could have indexes or leaves
++ * so calculate e_max right way */
++ if (EXT_DEPTH(tree))
++ neh->e_max = ext3_ext_space_block_idx(tree);
++ else
++ neh->e_max = ext3_ext_space_block(tree);
++ neh->e_magic = EXT3_EXT_MAGIC;
+ mark_buffer_uptodate(bh, 1);
+ unlock_buffer(bh);
+
+ if ((err = ext3_ext_get_access(handle, tree, curp)))
+ goto out;
+
++ curp->p_hdr->e_magic = EXT3_EXT_MAGIC;
+ curp->p_hdr->e_max = ext3_ext_space_root_idx(tree);
+ curp->p_hdr->e_num = 1;
+ curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
++ /* FIXME: it works, but actually path[0] can be index */
+ curp->p_idx->e_block = EXT_FIRST_EXTENT(path[0].p_hdr)->e_block;
+ curp->p_idx->e_leaf = newblock;
+
+ path = ext3_ext_find_extent(tree, newext->e_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
+ struct ext3_ext_path *path,
+ struct ext3_extent *newext)
+{
-+ int depth, len;
+ struct ext3_extent_header * eh;
-+ struct ext3_extent *ex;
++ struct ext3_extent *ex, *fex;
+ struct ext3_extent *nearex; /* nearest extent */
+ struct ext3_ext_path *npath = NULL;
-+ int err;
++ int depth, len, err, next;
+
+ 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)) {
+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
+ return err;
+ ex->e_num += newext->e_num;
-+ err = ext3_ext_dirty(handle, tree, path + depth);
-+ return err;
++ eh = path[depth].p_hdr;
++ nearex = ex;
++ goto merge;
+ }
+
+repeat:
+ depth = EXT_DEPTH(tree);
+ eh = path[depth].p_hdr;
-+ if (eh->e_num == eh->e_max) {
-+ /* probably next leaf has space for us? */
-+ int next = ext3_ext_next_leaf_block(tree, path);
-+ if (next != 0xffffffff) {
-+ 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->e_num < eh->e_max) {
-+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->e_num);
-+ path = npath;
-+ goto repeat;
-+ }
-+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->e_num, eh->e_max);
++ if (eh->e_num < eh->e_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->e_block > fex->e_block && next != 0xffffffff) {
++ 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->e_num < eh->e_max) {
++ ext_debug(tree, "next leaf isnt full(%d)\n",
++ eh->e_num);
++ path = npath;
++ goto repeat;
+ }
-+ /*
-+ * 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;
-+ goto repeat;
++ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
++ eh->e_num, eh->e_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)))
+ "move %d from 0x%p to 0x%p\n",
+ newext->e_block, newext->e_start, newext->e_num,
+ nearex, len, nearex + 1, nearex + 2);
-+
+ memmove(nearex + 1, nearex, len);
+ path[depth].p_ext = nearex;
+ }
+
-+ if (!err) {
-+ eh->e_num++;
-+ nearex = path[depth].p_ext;
-+ nearex->e_block = newext->e_block;
-+ nearex->e_start = newext->e_start;
-+ nearex->e_num = newext->e_num;
-+
-+ /* time to correct all indexes above */
-+ err = ext3_ext_correct_indexes(handle, tree, path);
++ eh->e_num++;
++ nearex = path[depth].p_ext;
++ nearex->e_block = newext->e_block;
++ nearex->e_start = newext->e_start;
++ nearex->e_num = newext->e_num;
++
++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->e_num += nearex[1].e_num;
++ 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->e_num--;
++ EXT_ASSERT(eh->e_num > 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:
+ ext3_ext_drop_refs(npath);
+ kfree(npath);
+ }
-+
++ ext3_ext_tree_changed(tree);
+ return err;
+}
+
+ 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(tree->inode);
+ EXT_ASSERT(tree->root);
+
-+ while (num > 0 && block != 0xfffffffff) {
++ while (block < last && block != 0xfffffffff) {
++ 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);
+
+ /* there is no extent yet, so try to allocate
+ * all requested space */
+ start = block;
-+ end = block + num - 1;
++ end = block + num;
+ } else if (ex->e_block > block) {
+ /* need to allocate space before found extent */
+ start = block;
-+ end = ex->e_block - 1;
-+ if (block + num - 1 < end)
-+ end = block + num - 1;
++ end = ex->e_block;
++ if (block + num < end)
++ end = block + num;
+ } else if (block >= ex->e_block + ex->e_num) {
+ /* need to allocate space after found extent */
+ start = block;
-+ end = block + num - 1;
++ end = block + num;
+ if (end >= next)
-+ end = next - 1;
++ end = next;
+ } else if (block >= ex->e_block) {
+ /*
+ * some part of requested space is covered
+ * by found extent
+ */
+ start = block;
-+ end = ex->e_block + ex->e_num - 1;
-+ if (block + num - 1 < end)
-+ end = block + num - 1;
++ end = ex->e_block + ex->e_num;
++ if (block + num < end)
++ end = block + num;
+ exists = 1;
+ } else {
+ BUG();
+ }
++ EXT_ASSERT(end > start);
+
+ if (!exists) {
+ cbex.e_block = start;
-+ cbex.e_num = end - start + 1;
++ cbex.e_num = end - start;
+ cbex.e_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_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 */
-+ ext3_ext_drop_refs(path);
+ kfree(path);
+ path = NULL;
+ }
+
-+ block += cbex.e_num;
-+ num -= cbex.e_num;
++ block = cbex.e_block + cbex.e_num;
+ }
+
+ if (path) {
+ int depth = EXT_DEPTH(tree);
+ struct ext3_extent *ex, gex;
+
++ if (!tree->cex)
++ return;
++
+ ex = path[depth].p_ext;
+ if (ex == NULL) {
+ /* there is no extent yet, so gap is [0;-] */
+ ex->e_block = cex->e_block;
+ ex->e_start = cex->e_start;
+ ex->e_num = cex->e_num;
-+ ext_debug(tree, "%lu cached by %lu:%lu:%lu(gap)\n",
++ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
+ (unsigned long) block,
+ (unsigned long) ex->e_block,
+ (unsigned long) ex->e_num,
+ ext_debug(tree, "index is empty, remove it, free block %d\n",
+ path->p_idx->e_leaf);
+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->e_leaf);
-+ ext3_forget(handle, 0, tree->inode, bh, path->p_idx->e_leaf);
++ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->e_leaf);
+ ext3_free_blocks(handle, tree->inode, path->p_idx->e_leaf, 1);
+ return err;
+}
+ eh = path[depth].p_hdr;
+ EXT_ASSERT(eh);
+ EXT_ASSERT(eh->e_num <= eh->e_max);
++ EXT_ASSERT(eh->e_magic == EXT3_EXT_MAGIC);
+
+ /* find where to start removing */
+ le = ex = EXT_LAST_EXTENT(eh);
+ }
+
+ EXT_ASSERT(path[i].p_hdr->e_num <= path[i].p_hdr->e_max);
++ EXT_ASSERT(path[i].p_hdr->e_magic == EXT3_EXT_MAGIC);
+
+ if (!path[i].p_idx) {
+ /* this level hasn't touched yet */
+ err = ext3_ext_dirty(handle, tree, path);
+ }
+ }
++ ext3_ext_tree_changed(tree);
+
+ kfree(path);
+ ext3_journal_stop(handle, inode);
+ * possible initialization would be here
+ */
+
-+ if (test_opt(sb, EXTENTS))
-+ printk("EXT3-fs: file extents enabled\n");
++ 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");
++ }
+}
+
+/*
+static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer)
+{
+ struct inode *inode = buffer;
-+ ext3_mark_inode_dirty(handle, inode);
-+ return 0;
++ return ext3_mark_inode_dirty(handle, inode);
+}
+
+static int ext3_ext_mergable(struct ext3_extent *ex1,
+{
+ 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);
+ start = ex->e_start + ex->e_num - 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->e_block && to <= ex->e_block + ex->e_num - 1) {
+ printk("strange request: removal %lu-%lu from %u:%u\n",
+ return 0;
+}
+
-+static int ext3_ext_find_goal(struct inode *inode,
-+ struct ext3_ext_path *path)
++static 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;
+ int depth;
+
+ if (path) {
++ struct ext3_extent *ex;
+ depth = path->p_depth;
-+ /* try to find previous block */
-+ if (path[depth].p_ext)
-+ return path[depth].p_ext->e_start +
-+ path[depth].p_ext->e_num - 1;
+
++ /* try to predict block placement */
++ if ((ex = path[depth].p_ext))
++ return ex->e_start + (block - ex->e_block);
++
+ /* it looks index is empty
+ * try to find starting from index itself */
+ if (path[depth].p_bh)
+ 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;
++ return bg_start + colour + block;
+}
+
+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
+ if (ex->e_num == 0) {
+ ex->e_num = 1;
+ /* allocate new block for the extent */
-+ goal = ext3_ext_find_goal(inode, path);
++ goal = ext3_ext_find_goal(inode, path, ex->e_block);
+ ex->e_start = ext3_new_block(handle, inode, goal, 0, 0, err);
+ if (ex->e_start == 0) {
+ /* error occured: restore old extent */
+ tree->remove_extent_credits = ext3_remove_blocks_credits;
+ tree->buffer = (void *) inode;
+ tree->buffer_len = sizeof(EXT3_I(inode)->i_data);
-+ tree->cex = NULL; /* FIXME: add cache store later */
++ tree->cex = (struct ext3_extent *) &EXT3_I(inode)->i_cached_extent;
+}
+
-+#if 0
++#if EXT3_MULTIBLOCK_ALLOCATOR
+static int
+ext3_ext_new_extent_cb(struct ext3_extents_tree *tree,
+ struct ext3_ext_path *path,
+ struct ext3_extent *newex, int exist)
+{
+ struct inode *inode = tree->inode;
++ struct buffer_head *bh;
+ int count, err, goal;
++ unsigned long pblock;
++ unsigned long tgen;
+ loff_t new_i_size;
+ handle_t *handle;
-+ unsigned long pblock;
++ int i;
+
+ if (exist)
+ return EXT_CONTINUE;
+
++ tgen = EXT_GENERATION(tree);
+ count = ext3_ext_calc_credits_for_insert(tree, path);
++ up_write(&EXT3_I(inode)->truncate_sem);
++
+ handle = ext3_journal_start(inode, count + EXT3_ALLOC_NEEDED + 1);
-+ if (IS_ERR(handle))
++ if (IS_ERR(handle)) {
++ down_write(&EXT3_I(inode)->truncate_sem);
+ return PTR_ERR(handle);
++ }
+
-+ goal = ext3_ext_find_goal(inode, path);
++ if (tgen != EXT_GENERATION(tree)) {
++ /* the tree has changed. so path can be invalid at moment */
++ ext3_journal_stop(handle, inode);
++ down_write(&EXT3_I(inode)->truncate_sem);
++ return EXT_REPEAT;
++ }
++
++ down_write(&EXT3_I(inode)->truncate_sem);
++ goal = ext3_ext_find_goal(inode, path, newex->e_block);
+ count = newex->e_num;
-+#ifdef EXT3_MULTIBLOCK_ALLOCATOR
-+ pblock = ext3_new_block(handle, inode, goal, &count, NULL, &err);
-+ EXT_ASSERT(count <= num);
-+ /* FIXME: error handling here */
-+ EXT_ASSERT(err == 0);
-+#else
-+ pblock = 0;
-+#endif
++ pblock = ext3_new_blocks(handle, inode, &count, goal, &err);
++ if (!pblock)
++ goto out;
++ EXT_ASSERT(count <= newex->e_num);
+
+ /* insert new extent */
+ newex->e_start = pblock;
+ if (err)
+ goto out;
+
++ /* block have been allocated for data, so time to drop dirty
++ * in correspondend buffer_heads to prevent corruptions */
++ for (i = 0; i < newex->e_num; i++) {
++ bh = sb_get_hash_table(inode->i_sb, newex->e_start + i);
++ if (bh) {
++ mark_buffer_clean(bh);
++ wait_on_buffer(bh);
++ clear_bit(BH_Req, &bh->b_state);
++ __brelse(bh);
++ }
++ }
++
+ /* correct on-disk inode size */
+ if (newex->e_num > 0) {
+ new_i_size = (loff_t) newex->e_block + newex->e_num;
+ new_i_size = new_i_size << inode->i_blkbits;
-+ if (new_i_size > i_size_read(inode))
-+ new_i_size = i_size_read(inode);
+ if (new_i_size > EXT3_I(inode)->i_disksize) {
+ EXT3_I(inode)->i_disksize = new_i_size;
+ err = ext3_mark_inode_dirty(handle, inode);
+ struct ext3_extents_tree tree;
+ int err;
+
++ ext3_init_tree_desc(&tree, inode);
+ ext_debug(&tree, "blocks %lu-%lu requested for inode %u\n",
+ block, block + num,(unsigned) inode->i_ino);
-+
-+ ext3_init_tree_desc(&tree, inode);
-+ down(&EXT3_I(inode)->truncate_sem);
++ down_write(&EXT3_I(inode)->truncate_sem);
+ err = ext3_ext_walk_space(&tree, block, num, ext3_ext_new_extent_cb);
+ ext3_ext_invalidate_cache(&tree);
-+ up(&EXT3_I(inode)->truncate_sem);
++ up_write(&EXT3_I(inode)->truncate_sem);
+
+ return err;
+}
+ path = ext3_ext_find_extent(&tree, iblock, NULL);
+ if (IS_ERR(path)) {
+ err = PTR_ERR(path);
++ path = NULL;
+ goto out2;
+ }
+
+ }
+
+ /* allocate new block */
-+ goal = ext3_ext_find_goal(inode, path);
++ goal = ext3_ext_find_goal(inode, path, iblock);
+ newblock = ext3_new_block(handle, inode, goal, 0, 0, &err);
+ if (!newblock)
+ goto out2;
+{
+ 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;
+ 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, 0xffffffff,
+ 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_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, 0xffffffff,
+ 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;
+}
+
-Index: linux-2.4.20/fs/ext3/ialloc.c
++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.24/fs/ext3/ialloc.c
===================================================================
---- linux-2.4.20.orig/fs/ext3/ialloc.c 2004-01-23 19:00:25.000000000 +0300
-+++ linux-2.4.20/fs/ext3/ialloc.c 2004-01-24 00:45:20.000000000 +0300
-@@ -593,11 +593,13 @@
+--- linux-2.4.24.orig/fs/ext3/ialloc.c 2004-01-14 02:58:45.000000000 +0300
++++ linux-2.4.24/fs/ext3/ialloc.c 2004-01-26 23:17:19.000000000 +0300
+@@ -592,11 +592,13 @@
iloc.bh = NULL;
goto fail;
}
unlock_super (sb);
if(DQUOT_ALLOC_INODE(inode)) {
DQUOT_DROP(inode);
-Index: linux-2.4.20/fs/ext3/inode.c
+Index: linux-2.4.24/fs/ext3/inode.c
===================================================================
---- linux-2.4.20.orig/fs/ext3/inode.c 2004-01-23 19:00:25.000000000 +0300
-+++ linux-2.4.20/fs/ext3/inode.c 2004-01-24 04:34:04.000000000 +0300
+--- linux-2.4.24.orig/fs/ext3/inode.c 2004-01-14 02:58:45.000000000 +0300
++++ linux-2.4.24/fs/ext3/inode.c 2004-01-26 23:17:19.000000000 +0300
@@ -848,6 +848,15 @@
goto reread;
}
handle = start_transaction(inode);
if (IS_ERR(handle))
return; /* AKPM: return what? */
-@@ -2537,6 +2549,9 @@
+@@ -2536,6 +2548,9 @@
int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
int ret;
if (ext3_should_journal_data(inode))
ret = 3 * (bpp + indirects) + 2;
else
-@@ -2973,7 +2988,7 @@
+@@ -2972,7 +2987,7 @@
/* alloc blocks one by one */
for (i = 0; i < nblocks; i++) {
&bh_tmp, 1);
if (ret)
break;
-@@ -3049,7 +3064,7 @@
+@@ -3048,7 +3063,7 @@
if (blocks[i] != 0)
continue;
if (rc) {
printk(KERN_INFO "ext3_map_inode_page: error %d "
"allocating block %ld\n", rc, iblock);
-Index: linux-2.4.20/fs/ext3/Makefile
+Index: linux-2.4.24/fs/ext3/Makefile
===================================================================
---- linux-2.4.20.orig/fs/ext3/Makefile 2004-01-23 19:00:42.000000000 +0300
-+++ linux-2.4.20/fs/ext3/Makefile 2004-01-24 00:45:20.000000000 +0300
-@@ -13,7 +13,7 @@
+--- linux-2.4.24.orig/fs/ext3/Makefile 2004-01-14 02:58:45.000000000 +0300
++++ linux-2.4.24/fs/ext3/Makefile 2004-02-05 18:44:25.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/fs/ext3/super.c
+Index: linux-2.4.24/fs/ext3/super.c
===================================================================
---- linux-2.4.20.orig/fs/ext3/super.c 2004-01-23 19:00:25.000000000 +0300
-+++ linux-2.4.20/fs/ext3/super.c 2004-01-24 04:30:14.000000000 +0300
-@@ -623,6 +623,7 @@
+--- linux-2.4.24.orig/fs/ext3/super.c 2004-01-14 02:58:45.000000000 +0300
++++ linux-2.4.24/fs/ext3/super.c 2004-01-26 23:17:19.000000000 +0300
+@@ -530,6 +530,7 @@
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)) {
-@@ -796,6 +797,10 @@
+@@ -702,6 +703,10 @@
return 0;
}
}
else if (!strcmp (this_char, "grpid") ||
!strcmp (this_char, "bsdgroups"))
set_opt (*mount_options, GRPID);
-@@ -1485,6 +1490,8 @@
+@@ -1392,6 +1397,8 @@
test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
"writeback");
return sb;
failed_mount3:
-Index: linux-2.4.20/fs/ext3/ioctl.c
+Index: linux-2.4.24/fs/ext3/ioctl.c
===================================================================
---- linux-2.4.20.orig/fs/ext3/ioctl.c 2004-01-13 17:00:09.000000000 +0300
-+++ linux-2.4.20/fs/ext3/ioctl.c 2004-01-24 14:54:31.000000000 +0300
-@@ -189,6 +189,10 @@
+--- linux-2.4.24.orig/fs/ext3/ioctl.c 2004-01-14 02:58:42.000000000 +0300
++++ linux-2.4.24/fs/ext3/ioctl.c 2004-01-26 23:17:19.000000000 +0300
+@@ -174,6 +174,10 @@
return ret;
}
#endif
default:
return -ENOTTY;
}
-Index: linux-2.4.20/include/linux/ext3_fs.h
+Index: linux-2.4.24/include/linux/ext3_fs.h
===================================================================
---- linux-2.4.20.orig/include/linux/ext3_fs.h 2004-01-23 19:00:25.000000000 +0300
-+++ linux-2.4.20/include/linux/ext3_fs.h 2004-01-24 01:28:06.000000000 +0300
+--- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-01-14 02:58:45.000000000 +0300
++++ linux-2.4.24/include/linux/ext3_fs.h 2004-01-30 00:09:37.000000000 +0300
@@ -184,6 +184,7 @@
#define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H
-@@ -687,6 +693,7 @@
+@@ -688,6 +694,7 @@
extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
/* inode.c */
extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-@@ -767,6 +774,14 @@
+@@ -769,6 +776,14 @@
extern struct inode_operations ext3_symlink_inode_operations;
extern struct inode_operations ext3_fast_symlink_inode_operations;
#endif /* __KERNEL__ */
-Index: linux-2.4.20/include/linux/ext3_extents.h
+Index: linux-2.4.24/include/linux/ext3_extents.h
===================================================================
---- linux-2.4.20.orig/include/linux/ext3_extents.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.20/include/linux/ext3_extents.h 2004-01-24 15:15:11.000000000 +0300
-@@ -0,0 +1,207 @@
+--- 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-02-05 20:31:08.000000000 +0300
+@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2003 Alex Tomas <alex@clusterfs.com>
+ *
+ * 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
+#define EXT_STATS_
+
+
-+#define EXT3_ALLOC_NEEDED 2 /* block bitmap + group descriptor */
++#define EXT3_ALLOC_NEEDED 3 /* block bitmap + group desc. + sb */
+
+/*
+ * ext3_inode has i_block array (total 60 bytes)
+ __u16 e_num; /* number of valid entries */
+ __u16 e_max; /* capacity of store in entries */
+ __u16 e_depth; /* has tree real underlaying blocks? */
++ __u32 e_generation; /* generation of the tree */
+};
+
++#define EXT3_EXT_MAGIC 0xf301
++
+/*
+ * array of ext3_ext_path contains path to some extent
+ * creation/lookup routines use it for traversal/splitting/etc
+
+#define EXT_CONTINUE 0
+#define EXT_BREAK 1
++#define EXT_REPEAT 2
+
+
+#define EXT_FIRST_EXTENT(__hdr__) \
+ ((struct ext3_extent_header *) (bh)->b_data)
+#define EXT_DEPTH(_t_) \
+ (((struct ext3_extent_header *)((_t_)->root))->e_depth)
++#define EXT_GENERATION(_t_) \
++ (((struct ext3_extent_header *)((_t_)->root))->e_generation)
+
+
+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
+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 *);
+
++#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-01-24 19:30:22.000000000 +0300
++++ linux-2.4.24/include/linux/ext3_fs_i.h 2004-01-26 23:17:19.000000000 +0300
+@@ -76,6 +76,8 @@
+ * by other means, so we have truncate_sem.
+ */
+ struct rw_semaphore truncate_sem;
++
++ __u32 i_cached_extent[3];
+ };
+
+ #endif /* _LINUX_EXT3_FS_I */
+ void (*d_unpin)(struct dentry *, struct vfsmount *, int);
};
-+#define PIN(de,mnt,flag) if (de->d_op && de->d_op->d_pin) \
++#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->d_op && de->d_op->d_unpin) \
++#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \
+ de->d_op->d_unpin(de, mnt, flag);
+
+
+ void (*d_unpin)(struct dentry *, struct vfsmount *, int);
};
-+#define PIN(de,mnt,flag) if (de->d_op && de->d_op->d_pin) \
++#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->d_op && de->d_op->d_unpin) \
++#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \
+ de->d_op->d_unpin(de, mnt, flag);
+
+
+ void (*d_unpin)(struct dentry *, struct vfsmount *, int);
};
-+#define PIN(de,mnt,flag) if (de->d_op && de->d_op->d_pin) \
++#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->d_op && de->d_op->d_unpin) \
++#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \
+ de->d_op->d_unpin(de, mnt, flag);
+
+
-KERNEL=linux-2.4.20-20.9.tar.gz
+KERNEL=linux-2.4.20-28.9.tar.gz
SERIES=rh-2.4.20
VERSION=2.4.20
-EXTRA_VERSION=20.9
+EXTRA_VERSION=28.9_lustre
-BASE_ARCHS="i386"
+BASE_ARCHS="i586"
BIGMEM_ARCHS=""
BOOT_ARCHS=""
JENSEN_ARCHS=""
-SMP_ARCHS="i686"
+SMP_ARCHS="i586"
UP_ARCHS=""
+SRC_ARCHS="i586"
#include "lov_internal.h"
-#if 0
-static int lov_logop_cleanup(struct llog_ctxt *ctxt)
-{
- struct lov_obd *lov = &ctxt->loc_obd->u.lov;
- int i, rc = 0;
-
- ENTRY;
- for (i = 0; i < lov->desc.ld_tgt_count; i++) {
- struct obd_device *child = lov->tgts[i].ltd_exp->exp_obd;
- struct llog_ctxt *cctxt = llog_get_context(child, ctxt->loc_idx);
- rc = llog_cleanup(cctxt);
- if (rc) {
- CERROR("error lov_llog_open %d\n", i);
- break;
- }
- }
- RETURN(rc);
-}
-#endif
-
/* Add log records for each OSC that this object is striped over, and return
* cookies for each one. We _would_ have nice abstraction here, except that
* we need to keep cookies in stripe order, even if some are NULL, so that
lur->lur_oid = loi->loi_id;
lur->lur_ogen = loi->loi_gr;
- rc += llog_add(cctxt, &lur->lur_hdr, NULL, logcookies + rc, numcookies - rc);
+ rc += llog_add(cctxt, &lur->lur_hdr, NULL, logcookies + rc,
+ numcookies - rc);
}
OBD_FREE(lur, sizeof(*lur));
}
static int lov_llog_origin_connect(struct llog_ctxt *ctxt, int count,
- struct llog_logid *logid,
- struct llog_ctxt_gen *gen)
+ struct llog_logid *logid,
+ struct llog_gen *gen)
{
struct obd_device *obd = ctxt->loc_obd;
struct lov_obd *lov = &obd->u.lov;
#include <linux/obd.h>
#include <linux/lustre_lib.h>
+atomic_t obd_memory;
+int obd_memmax;
+
+
/* Debugging check only needed during development */
#ifdef OBD_CTXT_DEBUG
# define ASSERT_CTXT_MAGIC(magic) LASSERT((magic) == OBD_RUN_CTXT_MAGIC)
{
struct l_linux_dirent *dirent;
struct l_readdir_callback *buf = (struct l_readdir_callback *)__buf;
- int reclen = size_round(offsetof(struct l_linux_dirent, d_name) + namlen + 1);
- buf->error = -EINVAL;
- if (reclen > buf->count)
- return -EINVAL;
- dirent = buf->previous;
+ dirent = buf->lrc_dirent;
if (dirent)
- dirent->d_off = offset;
- dirent = buf->current_dir;
- buf->previous = dirent;
- dirent->d_ino = ino;
- dirent->d_reclen = reclen;
- memcpy(dirent->d_name, name, namlen);
- ((char *)dirent) += reclen;
- buf->current_dir = dirent;
- buf->count -= reclen;
+ dirent->lld_off = offset;
+
+ OBD_ALLOC(dirent, sizeof(*dirent));
+
+ list_add_tail(&dirent->lld_list, buf->lrc_list);
+
+ buf->lrc_dirent = dirent;
+ dirent->lld_ino = ino;
+ LASSERT(sizeof(dirent->lld_name) >= namlen + 1);
+ memcpy(dirent->lld_name, name, namlen);
+
return 0;
}
-long l_readdir(struct file * file, void * dirent, unsigned int count)
+long l_readdir(struct file *file, struct list_head *dentry_list)
{
- struct l_linux_dirent * lastdirent;
+ struct l_linux_dirent *lastdirent;
struct l_readdir_callback buf;
int error;
- buf.current_dir = (struct l_linux_dirent *)dirent;
- buf.previous = NULL;
- buf.count = count;
- buf.error = 0;
+ buf.lrc_dirent = NULL;
+ buf.lrc_list = dentry_list;
error = vfs_readdir(file, l_filldir, &buf);
if (error < 0)
return error;
- error = buf.error;
- lastdirent = buf.previous;
- if (lastdirent) {
- lastdirent->d_off = file->f_pos;
- error = count - buf.count;
- }
- return error;
+ lastdirent = buf.lrc_dirent;
+ if (lastdirent)
+ lastdirent->lld_off = file->f_pos;
+
+ return 0;
}
EXPORT_SYMBOL(l_readdir);
+EXPORT_SYMBOL(obd_memory);
+EXPORT_SYMBOL(obd_memmax);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
static void __exit lvfs_linux_exit(void)
{
+ int leaked;
+ ENTRY;
+
+ leaked = atomic_read(&obd_memory);
+ CDEBUG(leaked ? D_ERROR : D_INFO,
+ "obd mem max: %d leaked: %d\n", obd_memmax, leaked);
return;
}
static int mds_llog_origin_connect(struct llog_ctxt *ctxt, int count,
struct llog_logid *logid,
- struct llog_ctxt_gen *gen)
+ struct llog_gen *gen)
{
struct obd_device *obd = ctxt->loc_obd;
struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
{
struct mds_obd *mds = &obd->u.mds;
struct lov_stripe_md *lsm = NULL;
-#ifdef ENABLE_ORPHANS
struct llog_ctxt *ctxt;
-#endif
int rc;
ENTRY;
if (rc < 0)
RETURN(rc);
-#ifdef ENABLE_ORPHANS
ctxt = llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT);
rc = llog_add(ctxt, NULL, lsm, lustre_msg_buf(repmsg, offset + 1, 0),
repmsg->buflens[offset + 1] / sizeof(struct llog_cookie));
-#endif
obd_free_memmd(mds->mds_osc_exp, &lsm);
}
EXPORT_SYMBOL(llog_free_handle);
-/* returns negative on error; 0 if success; 1 if success & log destroyed */
+/* returns negative on error; 0 if success; 1 if success & log destroyed */
int llog_cancel_rec(struct llog_handle *loghandle, int index)
{
struct llog_log_hdr *llh = loghandle->lgh_hdr;
if ((le32_to_cpu(llh->llh_flags) & LLOG_F_ZAP_WHEN_EMPTY) &&
(le32_to_cpu(llh->llh_count) == 1) &&
- (loghandle->lgh_last_idx == (LLOG_BITMAP_BYTES * 8) - 1)) {
+ (loghandle->lgh_last_idx == (LLOG_BITMAP_BYTES * 8) - 1)) {
rc = llog_destroy(loghandle);
if (rc)
CERROR("failure destroying log after last cancel: %d\n",
}
rc = llog_write_rec(loghandle, &llh->llh_hdr, NULL, 0, NULL, 0);
- if (rc)
+ if (rc)
CERROR("failure re-writing header %d\n", rc);
LASSERT(rc == 0);
RETURN(rc);
GOTO(out, rc);
}
rc = 0;
-
+
handle->lgh_last_idx = 0; /* header is record with index 0 */
llh->llh_count = cpu_to_le32(1); /* for the header record */
llh->llh_hdr.lrh_type = cpu_to_le32(LLOG_HDR_MAGIC);
- llh->llh_hdr.lrh_len = llh->llh_tail.lrt_len = cpu_to_le32(LLOG_CHUNK_SIZE);
+ llh->llh_hdr.lrh_len = llh->llh_tail.lrt_len =
+ cpu_to_le32(LLOG_CHUNK_SIZE);
llh->llh_hdr.lrh_index = llh->llh_tail.lrt_index = 0;
llh->llh_timestamp = cpu_to_le64(LTIME_S(CURRENT_TIME));
if (uuid)
memcpy(&llh->llh_tgtuuid, uuid, sizeof(llh->llh_tgtuuid));
- llh->llh_bitmap_offset = cpu_to_le32(offsetof(typeof(*llh), llh_bitmap));
+ llh->llh_bitmap_offset = cpu_to_le32(offsetof(typeof(*llh),llh_bitmap));
ext2_set_bit(0, llh->llh_bitmap);
out:
INIT_LIST_HEAD(&handle->u.phd.phd_entry);
else
LBUG();
-
+
if (rc) {
OBD_FREE(llh, sizeof(*llh));
handle->lgh_hdr = NULL;
}
EXPORT_SYMBOL(llog_close);
-int llog_process(struct llog_handle *loghandle, llog_cb_t cb, void *data)
+int llog_process(struct llog_handle *loghandle, llog_cb_t cb,
+ void *data, void *catdata)
{
struct llog_log_hdr *llh = loghandle->lgh_hdr;
+ struct llog_process_cat_data *cd = catdata;
void *buf;
__u64 cur_offset = LLOG_CHUNK_SIZE;
- int rc = 0, index = 1;
+ int rc = 0, index = 1, last_index, idx;
int saved_index = 0;
ENTRY;
if (!buf)
RETURN(-ENOMEM);
+ if (cd != NULL)
+ index = cd->first_idx + 1;
+ if (cd != NULL && cd->last_idx)
+ last_index = cd->last_idx;
+ else
+ last_index = LLOG_BITMAP_BYTES * 8 - 1;
+
+
while (rc == 0) {
struct llog_rec_hdr *rec;
-
+
/* skip records not set in bitmap */
- while (index < (LLOG_BITMAP_BYTES * 8) &&
+ while (index <= last_index &&
!ext2_test_bit(index, llh->llh_bitmap))
++index;
- LASSERT(index <= LLOG_BITMAP_BYTES * 8);
- if (index == LLOG_BITMAP_BYTES * 8)
+ LASSERT(index <= last_index + 1);
+ if (index == last_index + 1)
break;
/* get the buf with our target record; avoid old garbage */
memset(buf, 0, LLOG_CHUNK_SIZE);
- rc = llog_next_block(loghandle, &saved_index, index,
+ rc = llog_next_block(loghandle, &saved_index, index,
&cur_offset, buf, LLOG_CHUNK_SIZE);
if (rc)
GOTO(out, rc);
rec = buf;
- index = le32_to_cpu(rec->lrh_index);
+ idx = le32_to_cpu(rec->lrh_index);
+ if (idx < index)
+ CDEBUG(D_HA, "index %u : idx %u\n", index, idx);
+ while (idx < index) {
+ rec = ((void *)rec + le32_to_cpu(rec->lrh_len));
+ idx ++;
+ }
/* process records in buffer, starting where we found one */
while ((void *)rec < buf + LLOG_CHUNK_SIZE) {
/* if set, process the callback on this record */
if (ext2_test_bit(index, llh->llh_bitmap)) {
rc = cb(loghandle, rec, data);
- if (rc)
+ if (rc == LLOG_PROC_BREAK) {
+ CWARN("recovery from log: "LPX64":%x"
+ " stopped\n",
+ loghandle->lgh_id.lgl_oid,
+ loghandle->lgh_id.lgl_ogen);
+ GOTO(out, rc);
+ }
+ if (rc)
GOTO(out, rc);
}
/* next record, still in buffer? */
++index;
- if (index > LLOG_BITMAP_BYTES * 8 - 1)
+ if (index > last_index)
GOTO(out, rc = 0);
rec = ((void *)rec + le32_to_cpu(rec->lrh_len));
}
struct llog_handle *loghandle;
struct llog_log_hdr *llh;
struct llog_logid_rec rec;
- int rc, index, bitmap_size, i;
+ int rc, index, bitmap_size;
ENTRY;
+ llh = cathandle->lgh_hdr;
+ bitmap_size = sizeof(llh->llh_bitmap) * 8;
+
+ index = (cathandle->lgh_last_idx + 1) % bitmap_size;
+
+ /* maximum number of available slots in catlog is bitmap_size - 2 */
+ if (llh->llh_cat_idx == cpu_to_le32(index)) {
+ CERROR("no free catalog slots for log...\n");
+ RETURN(ERR_PTR(-ENOSPC));
+ } else {
+ if (index == 0)
+ index = 1;
+ if (ext2_set_bit(index, llh->llh_bitmap)) {
+ CERROR("argh, index %u already set in log bitmap?\n",
+ index);
+ LBUG(); /* should never happen */
+ }
+ cathandle->lgh_last_idx = index;
+ llh->llh_count = cpu_to_le32(le32_to_cpu(llh->llh_count) + 1);
+ llh->llh_tail.lrt_index = cpu_to_le32(index);
+ }
+
rc = llog_create(cathandle->lgh_ctxt, &loghandle, NULL, NULL);
if (rc)
RETURN(ERR_PTR(rc));
- rc = llog_init_handle(loghandle,
- LLOG_F_IS_PLAIN | LLOG_F_ZAP_WHEN_EMPTY,
+ rc = llog_init_handle(loghandle,
+ LLOG_F_IS_PLAIN | LLOG_F_ZAP_WHEN_EMPTY,
&cathandle->lgh_hdr->llh_tgtuuid);
if (rc)
GOTO(out_destroy, rc);
- /* Find first free entry */
- llh = cathandle->lgh_hdr;
- bitmap_size = sizeof(llh->llh_bitmap) * 8;
- for (i = 0, index = le32_to_cpu(llh->llh_count); i < bitmap_size;
- i++, index++) {
- index %= bitmap_size;
- if (ext2_set_bit(index, llh->llh_bitmap)) {
- /* XXX This should trigger log clean up or similar */
- CERROR("catalog index %d is still in use\n", index);
- } else {
- cathandle->lgh_last_idx = index;
- llh->llh_count = cpu_to_le32(le32_to_cpu(llh->llh_count) + 1);
- break;
- }
- }
- if (i == bitmap_size) {
- CERROR("no free catalog slots for log...\n");
- GOTO(out_destroy, rc = -ENOSPC);
- }
- CWARN("new recovery log "LPX64":%x for index %u of catalog "LPX64"\n",
- loghandle->lgh_id.lgl_oid, loghandle->lgh_id.lgl_ogen, index,
- cathandle->lgh_id.lgl_oid);
+ CDEBUG(D_HA, "new recovery log "LPX64":%x for index %u of catalog "
+ LPX64"\n", loghandle->lgh_id.lgl_oid, loghandle->lgh_id.lgl_ogen,
+ index, cathandle->lgh_id.lgl_oid);
/* build the record for this log in the catalog */
rec.lid_hdr.lrh_len = cpu_to_le32(sizeof(rec));
rec.lid_hdr.lrh_index = cpu_to_le32(index);
rec.lid_tail.lrt_index = cpu_to_le32(index);
/* update the catalog: header and record */
- rc = llog_write_rec(cathandle, &rec.lid_hdr,
+ rc = llog_write_rec(cathandle, &rec.lid_hdr,
&loghandle->u.phd.phd_cookie, 1, NULL, index);
if (rc < 0) {
GOTO(out_destroy, rc);
}
EXPORT_SYMBOL(llog_cat_new_log);
-/* Assumes caller has already pushed us into the kernel context and is locking.
+/* Open an existent log handle and add it to the open list.
+ * This log handle will be closed when all of the records in it are removed.
+ *
+ * Assumes caller has already pushed us into the kernel context and is locking.
* We return a lock on the handle to ensure nobody yanks it from us.
*/
int llog_cat_id2handle(struct llog_handle *cathandle, struct llog_handle **res,
if (cathandle == NULL)
RETURN(-EBADF);
- list_for_each_entry(loghandle, &cathandle->u.chd.chd_head,
+ list_for_each_entry(loghandle, &cathandle->u.chd.chd_head,
u.phd.phd_entry) {
struct llog_logid *cgl = &loghandle->lgh_id;
if (cgl->lgl_oid == logid->lgl_oid) {
continue;
}
loghandle->u.phd.phd_cat_handle = cathandle;
- cathandle->u.chd.chd_current_log = loghandle;
GOTO(out, rc = 0);
}
}
} else {
rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
if (!rc) {
- list_add(&loghandle->u.phd.phd_entry,
+ list_add(&loghandle->u.phd.phd_entry,
&cathandle->u.chd.chd_head);
- cathandle->u.chd.chd_current_log = loghandle;
}
}
if (!rc) {
loghandle->u.phd.phd_cat_handle = cathandle;
loghandle->u.phd.phd_cookie.lgc_lgl = cathandle->lgh_id;
- loghandle->u.phd.phd_cookie.lgc_index =
+ loghandle->u.phd.phd_cookie.lgc_index =
le32_to_cpu(loghandle->lgh_hdr->llh_cat_idx);
}
int rc;
ENTRY;
- list_for_each_entry_safe(loghandle, n, &cathandle->u.chd.chd_head,
+ list_for_each_entry_safe(loghandle, n, &cathandle->u.chd.chd_head,
u.phd.phd_entry) {
int err = llog_close(loghandle);
if (err)
*
* NOTE: loghandle is write-locked upon successful return
*/
-static struct llog_handle *llog_cat_current_log(struct llog_handle *cathandle,
+static struct llog_handle *llog_cat_current_log(struct llog_handle *cathandle,
int create)
{
struct llog_handle *loghandle = NULL;
loghandle = cathandle->u.chd.chd_current_log;
if (loghandle) {
struct llog_log_hdr *llh = loghandle->lgh_hdr;
- if (loghandle->lgh_last_idx < (sizeof(llh->llh_bitmap) * 8) - 1) {
+ if (loghandle->lgh_last_idx < (sizeof(llh->llh_bitmap)*8) - 1) {
down_write(&loghandle->lgh_lock);
up_read(&cathandle->lgh_lock);
RETURN(loghandle);
loghandle = cathandle->u.chd.chd_current_log;
if (loghandle) {
struct llog_log_hdr *llh = loghandle->lgh_hdr;
- if (loghandle->lgh_last_idx < (sizeof(llh->llh_bitmap) * 8) - 1) {
+ if (loghandle->lgh_last_idx < (sizeof(llh->llh_bitmap)*8) - 1) {
down_write(&loghandle->lgh_lock);
up_write(&cathandle->lgh_lock);
RETURN(loghandle);
CDEBUG(D_INODE, "creating new log\n");
loghandle = llog_cat_new_log(cathandle);
- if (loghandle)
+ if (!IS_ERR(loghandle))
down_write(&loghandle->lgh_lock);
up_write(&cathandle->lgh_lock);
RETURN(loghandle);
* Assumes caller has already pushed us into the kernel context.
*/
int llog_cat_add_rec(struct llog_handle *cathandle, struct llog_rec_hdr *rec,
- struct llog_cookie *reccookie, void *buf)
+ struct llog_cookie *reccookie, void *buf)
{
struct llog_handle *loghandle;
int rc;
/* loghandle is already locked by llog_cat_current_log() for us */
rc = llog_write_rec(loghandle, rec, reccookie, 1, buf, -1);
up_write(&loghandle->lgh_lock);
+
RETURN(rc);
}
EXPORT_SYMBOL(llog_cat_add_rec);
down_write(&loghandle->lgh_lock);
rc = llog_cancel_rec(loghandle, cookies->lgc_index);
up_write(&loghandle->lgh_lock);
-
+
if (rc == 1) { /* log has been destroyed */
index = loghandle->u.phd.phd_cookie.lgc_index;
if (cathandle->u.chd.chd_current_log == loghandle)
cathandle->u.chd.chd_current_log = NULL;
llog_free_handle(loghandle);
-
+
LASSERT(index);
+ llog_cat_set_first_idx(cathandle, index);
rc = llog_cancel_rec(cathandle, index);
+ if (rc == 0)
+ CDEBUG(D_HA, "cancel plain log at index %u "
+ "of catalog "LPX64"\n",
+ index, cathandle->lgh_id.lgl_oid);
}
}
up_write(&cathandle->lgh_lock);
}
EXPORT_SYMBOL(llog_cat_cancel_records);
-int llog_cat_process_cb(struct llog_handle *cat_llh, struct llog_rec_hdr *rec, void *data)
+int llog_cat_process_cb(struct llog_handle *cat_llh, struct llog_rec_hdr *rec,
+ void *data)
{
struct llog_process_data *d = data;
struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
CERROR("invalid record in catalog\n");
RETURN(-EINVAL);
}
- CWARN("processing log "LPX64":%x at index %u of catalog "LPX64"\n",
+ CWARN("processing log "LPX64":%x at index %u of catalog "LPX64"\n",
lir->lid_id.lgl_oid, lir->lid_id.lgl_ogen,
le32_to_cpu(rec->lrh_index), cat_llh->lgh_id.lgl_oid);
rc = llog_cat_id2handle(cat_llh, &llh, &lir->lid_id);
if (rc) {
- CERROR("Cannot find handle for log "LPX64"\n", lir->lid_id.lgl_oid);
+ CERROR("Cannot find handle for log "LPX64"\n",
+ lir->lid_id.lgl_oid);
RETURN(rc);
- }
+ }
- rc = llog_process(llh, d->lpd_cb, d->lpd_data);
+ rc = llog_process(llh, d->lpd_cb, d->lpd_data, NULL);
RETURN(rc);
}
int llog_cat_process(struct llog_handle *cat_llh, llog_cb_t cb, void *data)
{
struct llog_process_data d;
+ struct llog_process_cat_data cd;
+ struct llog_log_hdr *llh = cat_llh->lgh_hdr;
int rc;
ENTRY;
+
+ LASSERT(llh->llh_flags &cpu_to_le32(LLOG_F_IS_CAT));
d.lpd_data = data;
d.lpd_cb = cb;
- rc = llog_process(cat_llh, llog_cat_process_cb, &d);
+ if (llh->llh_cat_idx > cat_llh->lgh_last_idx) {
+ CWARN("catlog "LPX64" crosses index zero\n",
+ cat_llh->lgh_id.lgl_oid);
+
+ cd.first_idx = le32_to_cpu(llh->llh_cat_idx);
+ cd.last_idx = 0;
+ rc = llog_process(cat_llh, llog_cat_process_cb, &d, &cd);
+ if (rc != 0)
+ RETURN(rc);
+
+ cd.first_idx = 0;
+ cd.last_idx = cat_llh->lgh_last_idx;
+ rc = llog_process(cat_llh, llog_cat_process_cb, &d, &cd);
+ } else {
+ rc = llog_process(cat_llh, llog_cat_process_cb, &d, NULL);
+ }
+
RETURN(rc);
}
EXPORT_SYMBOL(llog_cat_process);
+int llog_cat_set_first_idx(struct llog_handle *cathandle, int index)
+{
+ struct llog_log_hdr *llh = cathandle->lgh_hdr;
+ int i, bitmap_size, idx;
+ ENTRY;
+
+ bitmap_size = sizeof(llh->llh_bitmap) * 8;
+ if (llh->llh_cat_idx == cpu_to_le32(index - 1)) {
+ idx = le32_to_cpu(llh->llh_cat_idx) + 1;
+ llh->llh_cat_idx = cpu_to_le32(idx);
+ if (idx == cathandle->lgh_last_idx)
+ goto out;
+ for (i = (index + 1) % bitmap_size;
+ i != cathandle->lgh_last_idx;
+ i = (i + 1) % bitmap_size) {
+ if (!ext2_test_bit(i, llh->llh_bitmap)) {
+ idx = le32_to_cpu(llh->llh_cat_idx) + 1;
+ llh->llh_cat_idx = cpu_to_le32(idx);
+ } else if (i == 0) {
+ llh->llh_cat_idx = 0;
+ } else {
+ break;
+ }
+ }
+out:
+ CDEBUG(D_HA, "set catlog "LPX64" first idx %u\n",
+ cathandle->lgh_id.lgl_oid,le32_to_cpu(llh->llh_cat_idx));
+ }
+
+ RETURN(0);
+}
#if 0
/* Assumes caller has already pushed us into the kernel context. */
if (cathandle->lgh_file->f_dentry->d_inode->i_size == 0) {
llog_write_rec(cathandle, &llh->llh_hdr, NULL, 0, NULL, 0);
-write_hdr:
+write_hdr:
rc = lustre_fwrite(cathandle->lgh_file, llh, LLOG_CHUNK_SIZE,
&offset);
if (rc != LLOG_CHUNK_SIZE) {
/* helper functions for calling the llog obd methods */
-int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
+int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
int count, struct llog_logid *logid, struct llog_operations *op)
{
int rc = 0;
if (op->lop_setup)
rc = op->lop_setup(obd, index, disk_obd, count, logid);
- if (ctxt && rc)
+ if (ctxt && rc)
OBD_FREE(ctxt, sizeof(*ctxt));
RETURN(rc);
int rc = 0;
ENTRY;
- down(&ctxt->loc_sem);
LASSERT(ctxt);
if (CTXTP(ctxt, cleanup))
ctxt->loc_obd->obd_llog_ctxt[ctxt->loc_idx] = NULL;
class_export_put(ctxt->loc_exp);
ctxt->loc_exp = NULL;
- up(&ctxt->loc_sem);
OBD_FREE(ctxt, sizeof(*ctxt));
RETURN(rc);
if (!ctxt)
RETURN(0);
- down(&ctxt->loc_sem);
- if (ctxt->loc_llcd && CTXTP(ctxt, sync))
+
+ if (CTXTP(ctxt, sync))
rc = CTXTP(ctxt, sync)(ctxt, exp);
- else
- up(&ctxt->loc_sem);
RETURN(rc);
}
EXPORT_SYMBOL(llog_sync);
-int llog_add(struct llog_ctxt *ctxt,
- struct llog_rec_hdr *rec, struct lov_stripe_md *lsm,
- struct llog_cookie *logcookies, int numcookies)
+int llog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
+ struct lov_stripe_md *lsm, struct llog_cookie *logcookies,
+ int numcookies)
{
int rc;
ENTRY;
LASSERT(ctxt);
- down(&ctxt->loc_sem);
CTXT_CHECK_OP(ctxt, add, -EOPNOTSUPP);
rc = CTXTP(ctxt, add)(ctxt, rec, lsm, logcookies, numcookies);
- up(&ctxt->loc_sem);
RETURN(rc);
}
EXPORT_SYMBOL(llog_add);
EXPORT_SYMBOL(llog_cancel);
/* callback func for llog_process in llog_obd_origin_setup */
-static int cat_cancel_cb(struct llog_handle *cathandle,
+static int cat_cancel_cb(struct llog_handle *cathandle,
struct llog_rec_hdr *rec, void *data)
{
struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
CERROR("invalid record in catalog\n");
RETURN(-EINVAL);
}
- CWARN("processing log "LPX64":%x at index %u of catalog "LPX64"\n",
+ CWARN("processing log "LPX64":%x at index %u of catalog "LPX64"\n",
lir->lid_id.lgl_oid, lir->lid_id.lgl_ogen,
le32_to_cpu(rec->lrh_index), cathandle->lgh_id.lgl_oid);
rc = llog_cat_id2handle(cathandle, &loghandle, &lir->lid_id);
if (rc) {
- CERROR("Cannot find handle for log "LPX64"\n", lir->lid_id.lgl_oid);
+ CERROR("Cannot find handle for log "LPX64"\n",
+ lir->lid_id.lgl_oid);
RETURN(rc);
- }
-
+ }
+
llh = loghandle->lgh_hdr;
if ((le32_to_cpu(llh->llh_flags) & LLOG_F_ZAP_WHEN_EMPTY) &&
(le32_to_cpu(llh->llh_count) == 1)) {
rc = llog_destroy(loghandle);
if (rc)
- CERROR("failure destroying log during postsetup: %d\n", rc);
+ CERROR("failure destroying log in postsetup: %d\n", rc);
LASSERT(rc == 0);
index = loghandle->u.phd.phd_cookie.lgc_index;
- if (cathandle->u.chd.chd_current_log == loghandle)
- cathandle->u.chd.chd_current_log = NULL;
llog_free_handle(loghandle);
-
+
LASSERT(index);
+ llog_cat_set_first_idx(cathandle, index);
rc = llog_cancel_rec(cathandle, index);
if (rc == 0)
- CWARN("cancel log "LPX64":%x at index %u of catalog "LPX64"\n",
- lir->lid_id.lgl_oid, lir->lid_id.lgl_ogen,
- le32_to_cpu(rec->lrh_index), cathandle->lgh_id.lgl_oid);
+ CWARN("cancel log "LPX64":%x at index %u of catalog "
+ LPX64"\n", lir->lid_id.lgl_oid,
+ lir->lid_id.lgl_ogen, le32_to_cpu(rec->lrh_index),
+ cathandle->lgh_id.lgl_oid);
}
RETURN(rc);
/* lop_setup method for filter/osc */
// XXX how to set exports
-int llog_obd_origin_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
- int count, struct llog_logid *logid)
+int llog_obd_origin_setup(struct obd_device *obd, int index,
+ struct obd_device *disk_obd, int count,
+ struct llog_logid *logid)
{
struct llog_ctxt *ctxt;
struct llog_handle *handle;
RETURN(0);
LASSERT(count == 1);
-
+
ctxt = llog_get_context(obd, index);
LASSERT(ctxt);
- log_gen_init(ctxt);
+ llog_gen_init(ctxt);
- down(&ctxt->loc_sem);
if (logid->lgl_oid)
rc = llog_create(ctxt, &handle, logid, NULL);
else {
rc = llog_create(ctxt, &handle, NULL, NULL);
- if (!rc)
+ if (!rc)
*logid = handle->lgh_id;
}
- if (rc)
+ if (rc)
GOTO(out, rc);
ctxt->loc_handle = handle;
if (rc)
GOTO(out, rc);
- rc = llog_process(handle, (llog_cb_t)cat_cancel_cb, NULL);
- if (rc)
+ rc = llog_process(handle, (llog_cb_t)cat_cancel_cb, NULL, NULL);
+ if (rc)
CERROR("llog_process with cat_cancel_cb failed: %d\n", rc);
out:
- up(&ctxt->loc_sem);
if (ctxt && rc) {
obd->obd_llog_ctxt[index] = NULL;
OBD_FREE(ctxt, sizeof(*ctxt));
struct llog_log_hdr *llh;
int rc, index;
ENTRY;
-
+
if (!ctxt)
return 0;
cathandle = ctxt->loc_handle;
if (cathandle) {
- list_for_each_entry_safe(loghandle, n, &cathandle->u.chd.chd_head,
- u.phd.phd_entry) {
+ list_for_each_entry_safe(loghandle, n,
+ &cathandle->u.chd.chd_head,
+ u.phd.phd_entry) {
llh = loghandle->lgh_hdr;
- if ((le32_to_cpu(llh->llh_flags) & LLOG_F_ZAP_WHEN_EMPTY) &&
+ if ((le32_to_cpu(llh->llh_flags) &
+ LLOG_F_ZAP_WHEN_EMPTY) &&
(le32_to_cpu(llh->llh_count) == 1)) {
rc = llog_destroy(loghandle);
if (rc)
- CERROR("failure destroying log during cleanup: %d\n",
- rc);
+ CERROR("failure destroying log during "
+ "cleanup: %d\n", rc);
LASSERT(rc == 0);
index = loghandle->u.phd.phd_cookie.lgc_index;
- if (cathandle->u.chd.chd_current_log == loghandle)
- cathandle->u.chd.chd_current_log = NULL;
llog_free_handle(loghandle);
-
+
LASSERT(index);
+ llog_cat_set_first_idx(cathandle, index);
rc = llog_cancel_rec(cathandle, index);
if (rc == 0)
- CWARN("cancel plain log at index %u of catalog "LPX64"\n",
- index, cathandle->lgh_id.lgl_oid);
+ CDEBUG(D_HA, "cancel plain log at index"
+ " %u of catalog "LPX64"\n",
+ index,cathandle->lgh_id.lgl_oid);
}
}
llog_cat_put(ctxt->loc_handle);
}
EXPORT_SYMBOL(llog_obd_origin_cleanup);
-
/* add for obdfilter/sz and mds/unlink */
int llog_obd_origin_add(struct llog_ctxt *ctxt,
struct llog_rec_hdr *rec, struct lov_stripe_md *lsm,
CERROR("rc: %d\n", rc);
GOTO(out, rc);
}
-
+
out:
OBD_FREE(idarray, size);
RETURN(rc);
#include "ptlrpc_internal.h"
-/* should this take an imp_sem to ensure connect is single threaded? */
-int ptlrpc_connect_import(struct obd_import *imp)
+struct ptlrpc_connect_async_args {
+ __u64 pcaa_peer_committed;
+ int pcaa_initial_connect;
+ int pcaa_was_invalid;
+};
+
+/* A CLOSED import should remain so. */
+#define IMPORT_SET_STATE_NOLOCK(imp, state) \
+do { \
+ if (imp->imp_state != LUSTRE_IMP_CLOSED) { \
+ CDEBUG(D_HA, "%p %s: changing import state from %s to %s\n", \
+ imp, imp->imp_target_uuid.uuid, \
+ ptlrpc_import_state_name(imp->imp_state), \
+ ptlrpc_import_state_name(state)); \
+ imp->imp_state = state; \
+ } \
+} while(0)
+
+#define IMPORT_SET_STATE(imp, state) \
+do { \
+ unsigned long flags; \
+ \
+ spin_lock_irqsave(&imp->imp_lock, flags); \
+ IMPORT_SET_STATE_NOLOCK(imp, state); \
+ spin_unlock_irqrestore(&imp->imp_lock, flags); \
+} while(0)
+
+
+static int ptlrpc_connect_interpret(struct ptlrpc_request *request,
+ void * data, int rc);
+int ptlrpc_import_recovery_state_machine(struct obd_import *imp);
+
+/* Only this function is allowed to change the import state when it is
+ * CLOSED. I would rather refcount the import and free it after
+ * disconnection like we do with exports. To do that, the client_obd
+ * will need to save the peer info somewhere other than in the import,
+ * though. */
+int ptlrpc_init_import(struct obd_import *imp)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&imp->imp_lock, flags);
+
+ imp->imp_generation++;
+ imp->imp_state = LUSTRE_IMP_NEW;
+
+ spin_unlock_irqrestore(&imp->imp_lock, flags);
+
+ return 0;
+}
+
+/* Returns true if import was FULL, false if import was already not
+ * connected.
+ */
+int ptlrpc_set_import_discon(struct obd_import *imp)
+{
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&imp->imp_lock, flags);
+
+ if (imp->imp_state == LUSTRE_IMP_FULL) {
+ IMPORT_SET_STATE_NOLOCK(imp, LUSTRE_IMP_DISCON);
+ rc = 1;
+ } else {
+ CDEBUG(D_HA, "%p %s: import already not connected: %s\n",
+ imp,imp->imp_client->cli_name,
+ ptlrpc_import_state_name(imp->imp_state));
+ }
+ spin_unlock_irqrestore(&imp->imp_lock, flags);
+
+ return rc;
+}
+
+void ptlrpc_fail_import(struct obd_import *imp, int generation)
+{
+ ENTRY;
+
+ LASSERT (!imp->imp_dlm_fake);
+
+ if (ptlrpc_set_import_discon(imp))
+ ptlrpc_handle_failed_import(imp);
+
+ EXIT;
+}
+
+int ptlrpc_connect_import(struct obd_import *imp, char * new_uuid)
{
struct obd_device *obd = imp->imp_obd;
- int msg_flags;
int initial_connect = 0;
int rc;
__u64 committed_before_reconnect = 0;
+ int was_invalid = 0;
struct ptlrpc_request *request;
- struct lustre_handle old_hdl;
int size[] = {sizeof(imp->imp_target_uuid),
sizeof(obd->obd_uuid),
sizeof(imp->imp_dlm_handle)};
char *tmp[] = {imp->imp_target_uuid.uuid,
obd->obd_uuid.uuid,
(char *)&imp->imp_dlm_handle};
+ struct ptlrpc_connect_async_args *aa;
unsigned long flags;
spin_lock_irqsave(&imp->imp_lock, flags);
- if (imp->imp_state == LUSTRE_IMP_CONNECTING) {
+ if (imp->imp_state == LUSTRE_IMP_CLOSED) {
spin_unlock_irqrestore(&imp->imp_lock, flags);
+ CERROR("can't connect to a closed import\n");
+ RETURN(-EINVAL);
+ } else if (imp->imp_state == LUSTRE_IMP_FULL) {
+ spin_unlock_irqrestore(&imp->imp_lock, flags);
+ CERROR("already connected\n");
+ RETURN(0);
+ } else if (imp->imp_state == LUSTRE_IMP_CONNECTING) {
+ spin_unlock_irqrestore(&imp->imp_lock, flags);
+ CERROR("already connecting\n");
RETURN(-EALREADY);
- } else {
- LASSERT(imp->imp_state == LUSTRE_IMP_DISCON);
}
- CDEBUG(D_HA, "%s: new state: CONNECTING\n",
- imp->imp_client->cli_name);
- imp->imp_state = LUSTRE_IMP_CONNECTING;
+
+ IMPORT_SET_STATE_NOLOCK(imp, LUSTRE_IMP_CONNECTING);
+
imp->imp_conn_cnt++;
+ imp->imp_last_replay_transno = 0;
+
if (imp->imp_remote_handle.cookie == 0) {
initial_connect = 1;
} else {
- committed_before_reconnect = imp->imp_peer_committed_transno;
+ committed_before_reconnect = imp->imp_peer_committed_transno;;
+
+ }
+
+ if (imp->imp_invalid) {
+ imp->imp_invalid = 0;
+ was_invalid = 1;
}
+
spin_unlock_irqrestore(&imp->imp_lock, flags);
+ if (new_uuid) {
+ struct ptlrpc_connection *conn;
+ struct obd_uuid uuid;
+ struct obd_export *dlmexp;
+
+ obd_str2uuid(&uuid, new_uuid);
+
+ conn = ptlrpc_uuid_to_connection(&uuid);
+ if (!conn)
+ GOTO(out, rc = -ENOENT);
+
+ CDEBUG(D_HA, "switching import %s/%s from %s to %s\n",
+ imp->imp_target_uuid.uuid, imp->imp_obd->obd_name,
+ imp->imp_connection->c_remote_uuid.uuid,
+ conn->c_remote_uuid.uuid);
+
+ /* Switch the import's connection and the DLM export's
+ * connection (which are almost certainly the same, but we
+ * keep distinct refs just to make things clearer. I think. */
+ if (imp->imp_connection)
+ ptlrpc_put_connection(imp->imp_connection);
+ /* We hand off the ref from ptlrpc_get_connection. */
+ imp->imp_connection = conn;
+
+ dlmexp = class_conn2export(&imp->imp_dlm_handle);
+
+ LASSERT(dlmexp != NULL);
+
+ if (dlmexp->exp_connection)
+ ptlrpc_put_connection(dlmexp->exp_connection);
+ dlmexp->exp_connection = ptlrpc_connection_addref(conn);
+ class_export_put(dlmexp);
+
+ }
+
request = ptlrpc_prep_req(imp, imp->imp_connect_op, 3, size, tmp);
if (!request)
GOTO(out, rc = -ENOMEM);
request->rq_send_state = LUSTRE_IMP_CONNECTING;
request->rq_replen = lustre_msg_size(0, NULL);
+ request->rq_interpret_reply = ptlrpc_connect_interpret;
+
+ LASSERT (sizeof (*aa) <= sizeof (request->rq_async_args));
+ aa = (struct ptlrpc_connect_async_args *)&request->rq_async_args;
+ memset(aa, 0, sizeof *aa);
- // lustre_msg_add_op_flags(request->rq_reqmsg, MSG_CONNECT_PEER);
+ aa->pcaa_peer_committed = committed_before_reconnect;
+ aa->pcaa_initial_connect = initial_connect;
+ aa->pcaa_was_invalid = was_invalid;
- rc = ptlrpc_queue_wait(request);
- if (rc) {
- GOTO(free_req, rc);
+ if (aa->pcaa_initial_connect)
+ imp->imp_replayable = 1;
+ ptlrpcd_add_req(request);
+ rc = 0;
+out:
+ if (rc != 0) {
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_DISCON);
+ }
+
+ RETURN(rc);
+}
+
+static int ptlrpc_connect_interpret(struct ptlrpc_request *request,
+ void * data, int rc)
+{
+ struct ptlrpc_connect_async_args *aa = data;
+ struct obd_import *imp = request->rq_import;
+ struct lustre_handle old_hdl;
+ unsigned long flags;
+ int msg_flags;
+ ENTRY;
+
+ spin_lock_irqsave(&imp->imp_lock, flags);
+ if (imp->imp_state == LUSTRE_IMP_CLOSED) {
+ spin_unlock_irqrestore(&imp->imp_lock, flags);
+ RETURN(0);
}
+ spin_unlock_irqrestore(&imp->imp_lock, flags);
+
+ if (rc)
+ GOTO(out, rc);
msg_flags = lustre_msg_get_op_flags(request->rq_repmsg);
- if (initial_connect) {
- CDEBUG(D_HA, "%s: new state: FULL\n",
- imp->imp_client->cli_name);
- if (msg_flags & MSG_CONNECT_REPLAYABLE)
+ if (aa->pcaa_initial_connect) {
+ if (msg_flags & MSG_CONNECT_REPLAYABLE) {
+ CDEBUG(D_HA, "connected to replayable target: %s\n",
+ imp->imp_target_uuid.uuid);
imp->imp_replayable = 1;
+ ptlrpc_pinger_add_import(imp);
+ } else {
+ imp->imp_replayable = 0;
+ }
imp->imp_remote_handle = request->rq_repmsg->handle;
- imp->imp_state = LUSTRE_IMP_FULL;
- GOTO(free_req, rc = 0);
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_FULL);
+ GOTO(finish, rc = 0);
}
/* Determine what recovery state to move the import to. */
", failed\n", imp->imp_target_uuid.uuid,
imp->imp_connection->c_remote_uuid.uuid,
imp->imp_dlm_handle.cookie);
- GOTO(free_req, rc = -ENOTCONN);
+ GOTO(out, rc = -ENOTCONN);
}
if (memcmp(&imp->imp_remote_handle, &request->rq_repmsg->handle,
imp->imp_target_uuid.uuid,
imp->imp_connection->c_remote_uuid.uuid);
}
- CDEBUG(D_HA, "%s: new state: RECOVER\n",
- imp->imp_client->cli_name);
- imp->imp_state = LUSTRE_IMP_RECOVER;
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_RECOVER);
}
else if (MSG_CONNECT_RECOVERING & msg_flags) {
- CDEBUG(D_HA, "%s: new state: REPLAY\n",
- imp->imp_client->cli_name);
LASSERT(imp->imp_replayable);
imp->imp_state = LUSTRE_IMP_RECOVER;
imp->imp_remote_handle = request->rq_repmsg->handle;
- imp->imp_state = LUSTRE_IMP_REPLAY;
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_REPLAY);
}
else {
- CDEBUG(D_HA, "%s: new state: EVICTED\n",
- imp->imp_client->cli_name);
imp->imp_remote_handle = request->rq_repmsg->handle;
- imp->imp_state = LUSTRE_IMP_EVICTED;
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_EVICTED);
}
/* Sanity checks for a reconnected import. */
"after reconnect. We should LBUG right here.\n");
}
- if (request->rq_repmsg->last_committed < committed_before_reconnect) {
+ if (request->rq_repmsg->last_committed < aa->pcaa_peer_committed) {
CERROR("%s went back in time (transno "LPD64
" was previously committed, server now claims "LPD64
")! is shared storage not coherent?\n",
imp->imp_target_uuid.uuid,
- committed_before_reconnect,
+ aa->pcaa_peer_committed,
request->rq_repmsg->last_committed);
}
- free_req:
- ptlrpc_req_finished(request);
+finish:
+ rc = ptlrpc_import_recovery_state_machine(imp);
+ if (rc != 0) {
+ if (aa->pcaa_was_invalid) {
+ ptlrpc_set_import_active(imp, 0);
+ }
+ if (rc == -ENOTCONN) {
+ CDEBUG(D_HA, "evicted/aborted by %s@%s during recovery;"
+ "invalidating and reconnecting\n",
+ imp->imp_target_uuid.uuid,
+ imp->imp_connection->c_remote_uuid.uuid);
+ ptlrpc_connect_import(imp, NULL);
+ RETURN(0);
+ }
+ }
out:
- if (rc != 0)
- imp->imp_state = LUSTRE_IMP_DISCON;
+ if (rc != 0) {
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_DISCON);
+ if (aa->pcaa_initial_connect && !imp->imp_initial_recov)
+ GOTO(norecov, rc);
+ CDEBUG(D_ERROR,
+ "recovery of %s on %s failed (%d); restarting\n",
+ imp->imp_target_uuid.uuid,
+ (char *)imp->imp_connection->c_remote_uuid.uuid, rc);
+ ptlrpc_handle_failed_import(imp);
+ }
+
+norecov:
+ wake_up(&imp->imp_recovery_waitq);
RETURN(rc);
}
+static int completed_replay_interpret(struct ptlrpc_request *req,
+ void * data, int rc)
+{
+ atomic_dec(&req->rq_import->imp_replay_inflight);
+ ptlrpc_import_recovery_state_machine(req->rq_import);
+ RETURN(0);
+}
+
+static int signal_completed_replay(struct obd_import *imp)
+ {
+ struct ptlrpc_request *req;
+ ENTRY;
+
+ LASSERT(atomic_read(&imp->imp_replay_inflight) == 0);
+ atomic_inc(&imp->imp_replay_inflight);
+
+ req = ptlrpc_prep_req(imp, OBD_PING, 0, NULL, NULL);
+ if (!req)
+ RETURN(-ENOMEM);
+
+ req->rq_replen = lustre_msg_size(0, NULL);
+ req->rq_send_state = LUSTRE_IMP_REPLAY_WAIT;
+ req->rq_reqmsg->flags |= MSG_LAST_REPLAY;
+ req->rq_timeout *= 3;
+ req->rq_interpret_reply = completed_replay_interpret;
+
+ ptlrpcd_add_req(req);
+ RETURN(0);
+}
+
+
+int ptlrpc_import_recovery_state_machine(struct obd_import *imp)
+{
+ int rc = 0;
+
+ if (imp->imp_state == LUSTRE_IMP_EVICTED) {
+ CDEBUG(D_HA, "evicted from %s@%s; invalidating\n",
+ imp->imp_target_uuid.uuid,
+ imp->imp_connection->c_remote_uuid.uuid);
+ ptlrpc_set_import_active(imp, 0);
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_RECOVER);
+ }
+
+ if (imp->imp_state == LUSTRE_IMP_REPLAY) {
+ CDEBUG(D_HA, "replay requested by %s\n",
+ imp->imp_target_uuid.uuid);
+ rc = ptlrpc_replay_next(imp);
+ if (rc == 0 && atomic_read(&imp->imp_replay_inflight) == 0) {
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_REPLAY_LOCKS);
+ rc = ldlm_replay_locks(imp);
+ if (rc)
+ GOTO(out, rc);
+ }
+ rc = 0;
+ }
+
+ if (imp->imp_state == LUSTRE_IMP_REPLAY_LOCKS) {
+ if (atomic_read(&imp->imp_replay_inflight) == 0) {
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_REPLAY_WAIT);
+ rc = signal_completed_replay(imp);
+ if (rc)
+ GOTO(out, rc);
+ }
+ }
+
+ if (imp->imp_state == LUSTRE_IMP_REPLAY_WAIT) {
+ if (atomic_read(&imp->imp_replay_inflight) == 0) {
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_RECOVER);
+ }
+ }
+
+ if (imp->imp_state == LUSTRE_IMP_RECOVER) {
+ CDEBUG(D_HA, "reconnected to %s@%s\n",
+ imp->imp_target_uuid.uuid,
+ imp->imp_connection->c_remote_uuid.uuid);
+
+ ptlrpc_set_import_active(imp, 1);
+ ptlrpc_resend(imp);
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_FULL);
+ }
+
+ if (imp->imp_state == LUSTRE_IMP_FULL) {
+ wake_up(&imp->imp_recovery_waitq);
+ ptlrpc_wake_delayed(imp);
+ }
+
+ out:
+ RETURN(rc);
+}
+
+static int back_to_sleep(void *unused)
+{
+ return 0;
+}
int ptlrpc_disconnect_import(struct obd_import *imp)
{
struct ptlrpc_request *request;
int rq_opc;
int rc = 0;
+ unsigned long flags;
ENTRY;
switch (imp->imp_connect_op) {
RETURN(-EINVAL);
}
+
+ if (ptlrpc_import_in_recovery(imp)) {
+ struct l_wait_info lwi;
+ lwi = LWI_TIMEOUT_INTR(MAX(obd_timeout * HZ, 1), back_to_sleep,
+ NULL, NULL);
+ rc = l_wait_event(imp->imp_recovery_waitq,
+ !ptlrpc_import_in_recovery(imp), &lwi);
+
+ }
+
+ spin_lock_irqsave(&imp->imp_lock, flags);
+ if (imp->imp_state != LUSTRE_IMP_FULL) {
+ GOTO(out, 0);
+ }
+ spin_unlock_irqrestore(&imp->imp_lock, flags);
+
request = ptlrpc_prep_req(imp, rq_opc, 0, NULL, NULL);
if (request) {
/* For non-replayable connections, don't attempt
reconnect if this fails */
- if (!imp->imp_obd->obd_replayable) {
- imp->imp_state = LUSTRE_IMP_DISCON;
+ if (!imp->imp_replayable) {
+ IMPORT_SET_STATE(imp, LUSTRE_IMP_DISCON);
request->rq_send_state = LUSTRE_IMP_DISCON;
}
request->rq_replen = lustre_msg_size(0, NULL);
ptlrpc_req_finished(request);
}
- imp->imp_state = LUSTRE_IMP_DISCON;
+ spin_lock_irqsave(&imp->imp_lock, flags);
+out:
+ IMPORT_SET_STATE_NOLOCK(imp, LUSTRE_IMP_CLOSED);
memset(&imp->imp_remote_handle, 0, sizeof(imp->imp_remote_handle));
+ spin_unlock_irqrestore(&imp->imp_lock, flags);
+
RETURN(rc);
}
GOTO(out, rc =-EFAULT);
}
memcpy(handle->lgh_hdr, hdr, sizeof (*hdr));
+ handle->lgh_last_idx = le32_to_cpu(handle->lgh_hdr->llh_tail.lrt_index);
out:
if (req)
#ifdef __KERNEL__
int llog_origin_connect(struct llog_ctxt *ctxt, int count,
- struct llog_logid *logid,
- struct llog_ctxt_gen *gen)
+ struct llog_logid *logid, struct llog_gen *gen)
{
+ struct llog_gen_rec *lgr;
struct obd_import *imp;
struct ptlrpc_request *request;
struct llogd_conn_body *req_body;
int rc;
ENTRY;
+ if (list_empty(&ctxt->loc_handle->u.chd.chd_head)) {
+ CDEBUG(D_HA, "there is no record related to ctxt %p", ctxt);
+ RETURN(0);
+ }
+
+ /* FIXME what value for gen->conn_cnt */
+ LLOG_GEN_INC(ctxt->loc_gen);
+
+ /* first add llog_gen_rec */
+ OBD_ALLOC(lgr, sizeof(*lgr));
+ if (!lgr)
+ RETURN(-ENOMEM);
+ lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
+ lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
+ lgr->lgr_gen = ctxt->loc_gen;
+ rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1);
+ OBD_FREE(lgr, sizeof(*lgr));
+ if (rc != 1)
+ RETURN(rc);
+
LASSERT(ctxt->loc_imp);
imp = ctxt->loc_imp;
request = ptlrpc_prep_req(imp, LLOG_ORIGIN_CONNECT, 1, &size, NULL);
- if (!request)
+ if (!request)
RETURN(-ENOMEM);
req_body = lustre_msg_buf(request->rq_reqmsg, 0, sizeof(*req_body));
req_body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*req_body));
ctxt = llog_get_context(obd, req_body->lgdc_ctxt_idx);
- rc = llog_connect(ctxt, 1, &req_body->lgdc_logid,
+ rc = llog_connect(ctxt, 1, &req_body->lgdc_logid,
&req_body->lgdc_gen);
- if (rc != 0)
+ if (rc != 0)
CERROR("failed at llog_relp_connect\n");
RETURN(rc);
[ -d "$KERNELDIR" ] || \
usage 1 "$KERNELDIR is not a directory."
- if [ "$RELEASE" = "no" ] ; then
+ if ! (( $RELEASE )) ; then
[ "$TAG" ] || \
usage 1 "When building a snapshot, a tag name must be used."
fi
if [ "$EXTRA_VERSION_save" ] ; then
EXTRA_VERSION="$EXTRA_VERSION_save"
- else
- EXTRA_VERSION="${EXTRA_VERSION}_${TAG//_/}.${TIMESTAMP}"
+ elif ! (( $RELEASE )) ; then
+ EXTRA_VERSION="${EXTRA_VERSION}-${TAG//_/}.${TIMESTAMP}"
fi
- EXTRA_VERSION=${EXTRA_VERSION//-/_/}
+ # EXTRA_VERSION=${EXTRA_VERSION//-/_}
ALL_ARCHS="$BASE_ARCHS $BIGMEM_ARCHS $BOOT_ARCHS $JENSEN_ARCHS $SMP_ARCHS $UP_ARCHS"
patch_linux()
{
- FULL_PATCH="$PWD/lustre-kernel-${target}-${EXTRA_VERSION}.patch"
+ FULL_PATCH="$PWD/lustre-kernel-${TARGET}-${EXTRA_VERSION}.patch"
[ -f "$FULL_PATCH" ] && rm -f "$FULL_PATCH"
pushd linux >/dev/null
echo -n "Applying patches:"
prep_build()
{
# make .spec file
- sed -e s/@KERNEL_VERSION@/$VERSION/g \
- -e s/@KERNEL_RELEASE@/$EXTRA_VERSION/g \
- -e s/@KERNEL_SOURCE@/$KERNEL/g \
- -e s/@LUSTRE_SOURCE@/${LUSTRE##*/}/g \
- -e s/@LUSTRE_TARGET@/$TARGET/g \
- -e s/@CONFIGURE_FLAGS@/$CONFIGURE_FLAGS/g \
- -e s/@BASE_ARCHS@/$BASE_ARCHS/g \
- -e s/@BIGMEM_ARCHS@/$BIGMEM_ARCHS/g \
- -e s/@BOOT_ARCHS@/$BOOT_ARCHS/g \
- -e s/@JENSEN_ARCHS@/$BOOT_ARCHS/g \
- -e s/@SMP_ARCHS@/$SMP_ARCHS/g \
- -e s/@UP_ARCHS@/$UP_ARCHS/g \
+ sed -e "s/@KERNEL_VERSION@/$VERSION/g" \
+ -e "s/@KERNEL_EXTRA_VERSION@/$EXTRA_VERSION/g" \
+ -e "s^@KERNEL_RELEASE@^${EXTRA_VERSION//-/_}^g" \
+ -e "s/@KERNEL_SOURCE@/$KERNEL/g" \
+ -e "s/@LUSTRE_SOURCE@/${LUSTRE##*/}/g" \
+ -e "s/@LUSTRE_TARGET@/$TARGET/g" \
+ -e "s/@CONFIGURE_FLAGS@/$CONFIGURE_FLAGS/g" \
+ -e "s/@BASE_ARCHS@/$BASE_ARCHS/g" \
+ -e "s/@BIGMEM_ARCHS@/$BIGMEM_ARCHS/g" \
+ -e "s/@BOOT_ARCHS@/$BOOT_ARCHS/g" \
+ -e "s/@JENSEN_ARCHS@/$BOOT_ARCHS/g" \
+ -e "s/@SMP_ARCHS@/$SMP_ARCHS/g" \
+ -e "s/@UP_ARCHS@/$UP_ARCHS/g" \
< $TOPDIR/lustre/scripts/lustre-kernel-2.4.spec.in \
> lustre-kernel-2.4.spec
[ -d SRPMS ] || mkdir SRPMS
[ -d RPMS ] || mkdir RPMS
[ -d BUILD ] || mkdir BUILD
[ -d SOURCES ] || mkdir SOURCES
+ cp $TOPDIR/lustre/scripts/linux-rhconfig.h SOURCES
cp $TOPDIR/lustre/scripts/linux-merge-config.awk SOURCES
cp $TOPDIR/lustre/scripts/linux-merge-modules.awk SOURCES
cp "$LUSTRE" "$KERNEL_FILE" SOURCES
TARGET=
# Not sure what to put here
# TARGET_ARCH=$(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
-TARGET_ARCH="i386"
+TARGET_ARCH=
TARGET_CONFIG=
JOBS=1
CONFIGURE_FLAGS=
[ -r "$SERIES_FILE" ] || \
fatal 1 "Target $TARGET's series $SERIES missing from $TOPDIR/kernel_patches/series."
- CONFIG_TARGET="$TARGET${TARGET_ARCH:+-$TARGET_ARCH}${TARGET_CONFIG:+-$TARGET_CONFIG}"
+ TARGET_ARCH=${TARGET_ARCH:-$BASE_ARCHS}
+ CONFIG_TARGET="$TARGET-${TARGET_ARCH}${TARGET_CONFIG:+-$TARGET_CONFIG}"
CONFIG_FILE="$TOPDIR/kernel_patches/kernel_configs/kernel-$VERSION-$CONFIG_TARGET.config"
- [ -r "$CONFIG_FILE" ] || \
- fatal 1 "Target $TARGET's config file $CONFIG missing from $TOPDIR/kernel_patches/configs."
+ [ -r "$CONFIG_FILE" ] ||
+ fatal 1 "Target $TARGET's config file $CONFIG_FILE missing from $TOPDIR/kernel_patches/configs."
if [ "$EXTRA_VERSION_save" ] ; then
EXTRA_VERSION="$EXTRA_VERSION_save"
# adding some text to the end of the version number.
#
%define kversion @KERNEL_VERSION@
+%define kextraver @KERNEL_EXTRA_VERSION@
%define release @KERNEL_RELEASE@
# /usr/src/%{kslnk} -> /usr/src/linux-%{KVERREL}
%define kslnk linux-2.4
%define buildjensen 0
%define buildsmp 0
%define buildup 0
+%define buildsrc 0
%ifarch @BASE_ARCHS@
%define buildbase 1
Name: kernel
Version: %{kversion}
Release: %{release}%{?targetboard:%{targetboard}}%{?debuglevel_1:.dbg}
-%define KVERREL %{PACKAGE_VERSION}-%{PACKAGE_RELEASE}
+%define KVERREL %{PACKAGE_VERSION}-%{kextraver}%{?targetboard:%{targetboard}}%{?debuglevel_1:.dbg}
License: GPL
Group: System Environment/Kernel
ExclusiveArch: %{all_x86} x86_64
Source0: @LUSTRE_SOURCE@
Source1: @KERNEL_SOURCE@
+Source15: linux-rhconfig.h
Source16: linux-merge-config.awk
Source17: linux-merge-modules.awk
--target @LUSTRE_TARGET@ \
--target-arch %{_target_cpu} \
${target_config} \
- --extraversion %{release} \
+ --extraversion %{kextraver} \
-j $RPM_BUILD_NCPUS
}
--target @LUSTRE_TARGET@ \
--target-arch %{_target_cpu} \
${target_config} \
- --extraversion %{release} \
+ --extraversion %{kextraver} \
+ --kerneldir $RPM_SOURCE_DIR \
+ -j $RPM_BUILD_NCPUS \
+ --destdir $RPM_BUILD_ROOT \
+ -- @CONFIGURE_FLAGS@
+}
+
+BuildLustre()
+{
+ target_config=${1:+--target-config $1}
+ sh -x ./scripts/lmake \
+ --build-lustre \
+ --install-lustre \
+ --target @LUSTRE_TARGET@ \
+ --target-arch %{_target_cpu} \
+ ${target_config} \
+ --extraversion %{kextraver} \
--kerneldir $RPM_SOURCE_DIR \
-j $RPM_BUILD_NCPUS \
--destdir $RPM_BUILD_ROOT \
sh -x ./scripts/lmake \
--save-headers \
--target @LUSTRE_TARGET@ \
- --extraversion %{release} \
+ --extraversion %{kextraver} \
--destdir $RPM_BUILD_ROOT
}
%endif
# we want this one last, so that it is the one populating /usr/bin
-%if %{buildup} || %{buildbase}
+%if %{buildup} && %{buildbase}
BuildKernel
+%elseif %{buildbase}
+BuildLustre
%endif
%if %{buildbase}
mkdir -p $RPM_BUILD_ROOT/usr/src/linux-%{KVERREL}
rm -f drivers/net/hamradio/soundmodem/gentbl scripts/mkdep
tar cf - . | tar xf - -C $RPM_BUILD_ROOT/usr/src/linux-%{KVERREL}
-perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{release}custom/" $RPM_BUILD_ROOT/usr/src/linux-%{KVERREL}/Makefile
+perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{kextraver}custom/" $RPM_BUILD_ROOT/usr/src/linux-%{KVERREL}/Makefile
ln -sf linux-%{KVERREL} $RPM_BUILD_ROOT/usr/src/linux
# install -m 644 %{SOURCE10} $RPM_BUILD_ROOT/usr/src/linux-%{KVERREL}
done
echo '#endif' >> modversions.h
sed 's,$,autoconf.h,' ../../savedheaders/list | awk -f %{SOURCE16} >> autoconf.h
-# install -m 644 %{SOURCE15} rhconfig.h
+install -m 644 %{SOURCE15} rhconfig.h
echo "#include <linux/rhconfig.h>" >> version.h
keyword=if
for i in smp BOOT BOOTsmp bigmem up ; do
%files -n lustre-lite-utils
%defattr(-, root, root)
%doc lustre/COPYING lustre/BUGS lustre/ChangeLog lustre/README lustre/doc/lustre.pdf
+/sbin/*
%{_sbindir}/*
%{_bindir}/*
%{_libdir}/lustre/python
mdsfailover_HOST=${mdsfailover_HOST:-mdev5}
ost1_HOST=${ost1_HOST:-mdev2}
ost2_HOST=${ost2_HOST:-mdev3}
+EXTRA_OSTS=${EXTRA_OSTS:-mdev7}
client_HOST=client
LIVE_CLIENT=${LIVE_CLIENT:-mdev6}
# This should always be a list, not a regexp
-FAIL_CLIENTS=${FAIL_CLIENTS:-mdev7}
+#FAIL_CLIENTS=${FAIL_CLIENTS:-mdev7}
+FAIL_CLIENTS=${FAIL_CLIENTS:-""}
NETTYPE=${NETTYPE:-tcp}
TIMEOUT=${TIMEOUT:-30}
-#PTLDEBUG=${PTLDEBUG:-'"ha|info|ioctl|malloc"'}
PTLDEBUG=${PTLDEBUG:-0}
+SUBSYSTEM=${SUBSYSTEM:-0}
MOUNT=${MOUNT:-"/mnt/lustre"}
UPCALL=${CLIENT_UPCALL:-`pwd`/replay-single-upcall.sh}
MOUNT2=${MOUNT2:-"/mnt/lustre2"}
DIR=${DIR:-$MOUNT}
DIR2=${DIR2:-$MOUNT1}
-PTLDEBUG=${PTLDEBUG:-0}
+PTLDEBUG=${PTLDEBUG:-0x3f0400}
+SUBSYSTEM=${SUBSYSTEM:- 0xffb7e3ff}
PDSH=${PDSH:-pdsh -S -w}
MDSDEV=${MDSDEV:-/dev/sda1}
# requirement:
# add uml1 uml2 uml3 in your /etc/hosts
+# FIXME - there is no reason to use all of these different
+# return codes, espcially when most of them are mapped to something
+# else anyway. The combination of test number and return code
+# figure out what failed.
+
set -e
SRCDIR=`dirname $0`
FORCE=${FORCE:-" --force"}
+if [ "$VERBOSE" == "true" ]; then
+ CMDVERBOSE=""
+else
+ CMDVERBOSE=" > /dev/null"
+fi
+
gen_config() {
rm -f $XMLCONFIG
start_mds() {
echo "start mds service on `facet_active_host mds`"
- start mds --reformat $MDSLCONFARGS > /dev/null || return 94
+ start mds --reformat $MDSLCONFARGS $CMDVERBOSE || return 94
}
stop_mds() {
echo "stop mds service on `facet_active_host mds`"
- stop mds $@ > /dev/null || return 97
+ stop mds $@ $CMDVERBOSE || return 97
}
start_ost() {
echo "start ost service on `facet_active_host ost`"
- start ost --reformat $OSTLCONFARGS > /dev/null || return 95
+ start ost --reformat $OSTLCONFARGS $CMDVERBOSE || return 95
}
stop_ost() {
echo "stop ost service on `facet_active_host ost`"
- stop ost $@ > /dev/null || return 98
+ stop ost $@ $CMDVERBOSE || return 98
}
mount_client() {
local MOUNTPATH=$1
echo "mount lustre on ${MOUNTPATH}....."
- zconf_mount $MOUNTPATH > /dev/null || return 96
+ zconf_mount `hostname` $MOUNTPATH $CMDVERBOSE || return 96
}
umount_client() {
local MOUNTPATH=$1
echo "umount lustre on ${MOUNTPATH}....."
- zconf_umount $MOUNTPATH > /dev/null || return 97
+ zconf_umount $MOUNTPATH $CMDVERBOSE || return 97
}
manual_umount_client(){
}
cleanup() {
- umount_client $MOUNT || return -200
- stop_mds || return -201
- stop_ost || return -202
+ umount_client $MOUNT || return 200
+ stop_mds || return 201
+ stop_ost || return 202
+ # catch case where these return just fine, but modules are still not unloaded
+ /sbin/lsmod | grep -q portals
+ if [ 1 -ne $? ]; then
+ echo "modules still loaded..."
+ return 203
+ fi
}
check_mount() {
start_mds
mount_client $MOUNT
check_mount || return 41
- cleanup
+ cleanup || return $?
}
run_test 0 "single mount setup"
test_1() {
start_ost
echo "start ost second time..."
- start ost --reformat $OSTLCONFARGS > /dev/null
+ start ost --reformat $OSTLCONFARGS $CMDVERBOSE
start_mds
mount_client $MOUNT
check_mount || return 42
- cleanup
+ cleanup || return $?
}
run_test 1 "start up ost twice"
start_ost
start_mds
echo "start mds second time.."
- start mds --reformat $MDSLCONFARGS > /dev/null
+ start mds --reformat $MDSLCONFARGS $CMDVERBOSE
mount_client $MOUNT
check_mount || return 43
- cleanup
+ cleanup || return $?
}
run_test 2 "start up mds twice"
check_mount || return 44
umount_client $MOUNT
- cleanup
+ cleanup || return $?
}
run_test 3 "mount client twice"
setup
touch $DIR/$tfile || return 85
stop_ost ${FORCE}
-
- # cleanup may return an error from the failed
- # disconnects; for now I'll consider this successful
- # if all the modules have unloaded.
- if ! cleanup ; then
- lsmod | grep -q portals && return 1
- fi
+ cleanup
+ eno=$?
+ # ok for ost to fail shutdown
+ if [ 202 -ne $eno ]; then
+ return $eno;
+ fi
return 0
}
run_test 4 "force cleanup ost, then cleanup"
test_5() {
setup
- touch $DIR/$tfile || return 86
- stop_mds ${FORCE} || return 98
+ touch $DIR/$tfile || return 1
+ stop_mds ${FORCE} || return 2
# cleanup may return an error from the failed
# disconnects; for now I'll consider this successful
# if all the modules have unloaded.
- if ! cleanup ; then
- lsmod | grep -q portals && return 1
- fi
+ umount $MOUNT &
+ UMOUNT_PID=$!
+ sleep $TIMEOUT
+ echo "killing umount"
+ kill -TERM $UMOUNT_PID
+ wait $UMOUNT_PID
+
+ # cleanup client modules
+ $LCONF --cleanup --nosetup --node client_facet $XMLCONFIG > /dev/null
+
+ # stop_mds is a no-op here, and should not fail
+ stop_mds || return 4
+ stop_ost || return 5
+
+ lsmod | grep -q portals && return 6
return 0
}
run_test 5 "force cleanup mds, then cleanup"
manual_umount_client
mount_client ${MOUNT} || return 87
touch $DIR/a || return 86
- cleanup
+ cleanup || return $?
}
run_test 6 "manual umount, then mount again"
test_7() {
setup
manual_umount_client
- cleanup
+ cleanup || return $?
}
run_test 7 "manual umount, then cleanup"
start_ost
start_mds
mount_client $MOUNT
- [ "`cat /proc/sys/portals/debug`" = "1" ] && \
- echo "lmc --debug success" || return 1
- [ "`cat /proc/sys/portals/subsystem_debug`" = "16777216" ] && \
- echo "lmc --subsystem success" || return 1
+ CHECK_PTLDEBUG="`cat /proc/sys/portals/debug`"
+ if [ $CHECK_PTLDEBUG = "1" ]; then
+ echo "lmc --debug success"
+ else
+ echo "lmc --debug: want 1, have $CHECK_PTLDEBUG"
+ return 1
+ fi
+ CHECK_SUBSYSTEM="`cat /proc/sys/portals/subsystem_debug`"
+ if [ $CHECK_SUBSYSTEM = "2" ]; then
+ echo "lmc --subsystem success"
+ else
+ echo "lmc --subsystem: want 2, have $CHECK_SUBSYSTEM"
+ return 1
+ fi
check_mount || return 41
- cleanup
+ cleanup || return $?
# the new PTLDEBUG/SUBSYSTEM used for lconf --ptldebug/subsystem
- PTLDEBUG="inode"
- SUBSYSTEM="mds"
+ PTLDEBUG="inode+trace"
+ SUBSYSTEM="mds+ost"
# check lconf --ptldebug/subsystem overriding lmc --ptldebug/subsystem
start_ost
start_mds
+ CHECK_PTLDEBUG="`do_facet mds cat /proc/sys/portals/debug`"
+ if [ $CHECK_PTLDEBUG = "3" ]; then
+ echo "lconf --debug success"
+ else
+ echo "lconf --debug: want 3, have $CHECK_PTLDEBUG"
+ return 1
+ fi
+ CHECK_SUBSYSTEM="`do_facet mds cat /proc/sys/portals/subsystem_debug`"
+ if [ $CHECK_SUBSYSTEM = "20" ]; then
+ echo "lconf --subsystem success"
+ else
+ echo "lconf --subsystem: want 20, have $CHECK_SUBSYSTEM"
+ return 1
+ fi
mount_client $MOUNT
- [ "`cat /proc/sys/portals/debug`" = "2" ] && \
- echo "lconf --debug overriding success" || return 1
- [ "`cat /proc/sys/portals/subsystem_debug`" = "33554432" ] && \
- echo "lconf --subsystem overriding success" || return 1
check_mount || return 41
- cleanup
+ cleanup || return $?
# resume the old configuration
PTLDEBUG=$OLDPTLDEBUG
SUBSYSTEM=$OLDSUBSYSTEM
gen_config
}
-run_test 9 "test --ptldebug and --subsystem for lmc"
+
+run_test 9 "test --ptldebug and --subsystem for lmc and lconf"
test_10() {
OLDXMLCONFIG=$XMLCONFIG
}
run_test 11 "use default lov configuration (should return error)"
+test_12() {
+ OLDXMLCONFIG=$XMLCONFIG
+ XMLCONFIG="batch.xml"
+ BATCHFILE="batchfile"
+
+ # test double quote
+ [ -f "$XMLCONFIG" ] && rm -f $XMLCONFIG
+ [ -f "$BATCHFILE" ] && rm -f $BATCHFILE
+ echo "--add net --node localhost --nid localhost.localdomain --nettype tcp" > $BATCHFILE
+ echo "--add mds --node localhost --mds mds1 --mkfsoptions \"-I 128\"" >> $BATCHFILE
+ # --mkfsoptions "-I 128"
+ do_lmc -m $XMLCONFIG --batch $BATCHFILE || return $?
+ if [ `sed -n '/>-I 128</p' $XMLCONFIG | wc -l` -eq 1 ]; then
+ echo "matched double quote success"
+ else
+ echo "matched double quote fail"
+ return 1
+ fi
+ rm -f $XMLCONFIG
+ rm -f $BATCHFILE
+ echo "--add net --node localhost --nid localhost.localdomain --nettype tcp" > $BATCHFILE
+ echo "--add mds --node localhost --mds mds1 --mkfsoptions \"-I 128" >> $BATCHFILE
+ # --mkfsoptions "-I 128
+ do_lmc -m $XMLCONFIG --batch $BATCHFILE && return $?
+ echo "unmatched double quote should return error"
+
+ # test single quote
+ rm -f $BATCHFILE
+ echo "--add net --node localhost --nid localhost.localdomain --nettype tcp" > $BATCHFILE
+ echo "--add mds --node localhost --mds mds1 --mkfsoptions '-I 128'" >> $BATCHFILE
+ # --mkfsoptions '-I 128'
+ do_lmc -m $XMLCONFIG --batch $BATCHFILE || return $?
+ if [ `sed -n '/>-I 128</p' $XMLCONFIG | wc -l` -eq 1 ]; then
+ echo "matched single quote success"
+ else
+ echo "matched single quote fail"
+ return 1
+ fi
+ rm -f $XMLCONFIG
+ rm -f $BATCHFILE
+ echo "--add net --node localhost --nid localhost.localdomain --nettype tcp" > $BATCHFILE
+ echo "--add mds --node localhost --mds mds1 --mkfsoptions '-I 128" >> $BATCHFILE
+ # --mkfsoptions '-I 128
+ do_lmc -m $XMLCONFIG --batch $BATCHFILE && return $?
+ echo "unmatched single quote should return error"
+
+ # test backslash
+ rm -f $BATCHFILE
+ echo "--add net --node localhost --nid localhost.localdomain --nettype tcp" > $BATCHFILE
+ echo "--add mds --node localhost --mds mds1 --mkfsoptions \-\I\ \128" >> $BATCHFILE
+ # --mkfsoptions \-\I\ \128
+ do_lmc -m $XMLCONFIG --batch $BATCHFILE || return $?
+ if [ `sed -n '/>-I 128</p' $XMLCONFIG | wc -l` -eq 1 ]; then
+ echo "backslash followed by a whitespace/letter success"
+ else
+ echo "backslash followed by a whitespace/letter fail"
+ return 1
+ fi
+ rm -f $XMLCONFIG
+ rm -f $BATCHFILE
+ echo "--add net --node localhost --nid localhost.localdomain --nettype tcp" > $BATCHFILE
+ echo "--add mds --node localhost --mds mds1 --mkfsoptions -I\ 128\\" >> $BATCHFILE
+ # --mkfsoptions -I\ 128\
+ do_lmc -m $XMLCONFIG --batch $BATCHFILE && return $?
+ echo "backslash followed by nothing should return error"
+
+ rm -f $BATCHFILE
+ XMLCONFIG=$OLDXMLCONFIG
+}
+run_test 12 "lmc --batch, with single/double quote, backslash in batchfile"
+
+test_13() {
+ OLDXMLCONFIG=$XMLCONFIG
+ XMLCONFIG="conf13-1.xml"
+ SECONDXMLCONFIG="conf13-2.xml"
+
+ # check long uuid will be truncated properly and uniquely
+ echo "To generate XML configuration file(with long ost name): $XMLCONFIG"
+ [ -f "$XMLCONFIG" ] && rm -f $XMLCONFIG
+ do_lmc --add net --node localhost --nid localhost.localdomain --nettype tcp
+ do_lmc --add mds --node localhost --mds mds1_name_longer_than_31characters
+ do_lmc --add mds --node localhost --mds mds2_name_longer_than_31characters
+ if [ ! -f "$XMLCONFIG" ]; then
+ echo "Error:no file $XMLCONFIG created!"
+ return 1
+ fi
+ EXPECTEDMDS1UUID="e_longer_than_31characters_UUID"
+ EXPECTEDMDS2UUID="longer_than_31characters_UUID_2"
+ FOUNDMDS1UUID=`awk -F"'" '/<mds uuid=/{print $2}' $XMLCONFIG | sed -n '1p'`
+ FOUNDMDS2UUID=`awk -F"'" '/<mds uuid=/{print $2}' $XMLCONFIG | sed -n '2p'`
+ if [ $EXPECTEDMDS1UUID != $FOUNDMDS1UUID ]; then
+ echo "Error:expected uuid for mds1: $EXPECTEDMDS1UUID; found: $FOUNDMDS1UUID"
+ return 1
+ fi
+ if [ $EXPECTEDMDS2UUID != $FOUNDMDS2UUID ]; then
+ echo "Error:expected uuid for mds2: $EXPECTEDMDS2UUID; found: $FOUNDMDS2UUID"
+ return 1
+ fi
+ echo "Success:long uuid truncated successfully and being unique."
+
+ # check multiple invocations for lmc generate same XML configuration file
+ rm -f $XMLCONFIG
+ echo "Generate the first XML configuration file"
+ gen_config
+ echo "mv $XMLCONFIG to $SECONDXMLCONFIG"
+ mv $XMLCONFIG $SECONDXMLCONFIG || return $?
+ echo "Generate the second XML configuration file"
+ gen_config
+ if [ `diff $XMLCONFIG $SECONDXMLCONFIG | wc -l` -eq 0 ]; then
+ echo "Success:multiple invocations for lmc generate same XML file"
+ else
+ echo "Error: multiple invocations for lmc generate different XML file"
+ return 1
+ fi
+
+ rm -f $XMLCONFIG
+ rm -f $SECONDXMLCONFIG
+ XMLCONFIG=$OLDXMLCONFIG
+}
+run_test 13 "check new_uuid of lmc operating correctly"
+
+test_14() {
+ rm -f $XMLCONFIG
+
+ # create xml file with --mkfsoptions for ost
+ echo "create xml file with --mkfsoptions for ost"
+ add_mds mds --dev $MDSDEV --size $MDSSIZE
+ add_lov lov1 mds --stripe_sz $STRIPE_BYTES\
+ --stripe_cnt $STRIPES_PER_OBJ --stripe_pattern 0
+ add_ost ost --lov lov1 --dev $OSTDEV --size $OSTSIZE \
+ --mkfsoptions -V
+ add_client client mds --lov lov1 --path $MOUNT
+
+ FOUNDSTRING=`awk -F"<" '/<mkfsoptions>/{print $2}' $XMLCONFIG`
+ EXPECTEDSTRING="mkfsoptions>-V"
+ if [ $EXPECTEDSTRING != $FOUNDSTRING ]; then
+ echo "Error:expected string: $EXPECTEDSTRING; found: $FOUNDSTRING"
+ return 1
+ fi
+ echo "Success:mkfsoptions for ost written to xml file correctly."
+
+ # mount lustre to test lconf mkfsoptions-parsing
+ echo "mount lustre"
+ start_ost
+ start_mds
+ mount_client $MOUNT || return $?
+ cleanup
+ echo "lconf mkfsoptions-parsing for ost success"
+
+ gen_config
+}
+run_test 14 "test mkfsoptions of ost for lmc and lconf"
+
equals_msg "Done"
exec >> $TESTDIR/logs/recovery-`hostname`.log
exec 2>&1
+echo ==========================================
+echo "start upcall: `date`"
+echo "command line: $0 $*"
+
set -xv
failed_import() {
#!/bin/bash
PATH=`dirname $0`:`dirname $0`/../utils:$PATH
TMP=${TMP:-/tmp}
+
+MDS=`ls /proc/fs/lustre/mds | grep -v num_refs | head -1`
+[ -z "$MDS" ] && echo "no MDS available, skipping llog test" && exit 0
+
insmod ../obdclass/llog_test.o || exit 1
lctl modules > $TMP/ogdb-`hostname`
echo "NOW reload debugging syms.."
lctl <<EOT || RC=2
newdev
attach llog_test llt_name llt_uuid
-setup mds1
+setup $MDS
EOT
# Using ignore_errors will allow lctl to cleanup even if the test fails.