'unlabeled-1.1.4.2.6'.
+++ /dev/null
---- linux/fs/ext3/ialloc.c.orig Sat Oct 19 11:42:23 2002
-+++ linux/fs/ext3/ialloc.c Sat Jan 4 12:14:18 2003
-@@ -64,8 +64,8 @@ static int read_inode_bitmap (struct sup
- if (!bh) {
- ext3_error (sb, "read_inode_bitmap",
- "Cannot read inode bitmap - "
-- "block_group = %lu, inode_bitmap = %lu",
-- block_group, (unsigned long) gdp->bg_inode_bitmap);
-+ "block_group = %lu, inode_bitmap = %u",
-+ block_group, gdp->bg_inode_bitmap);
- retval = -EIO;
- }
- /*
-@@ -531,19 +532,19 @@ out:
- }
-
- /* Verify that we are loading a valid orphan from disk */
--struct inode *ext3_orphan_get (struct super_block * sb, ino_t ino)
-+struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino)
- {
-- ino_t max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count);
-+ unsigned long max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count);
- unsigned long block_group;
- int bit;
- int bitmap_nr;
- struct buffer_head *bh;
- struct inode *inode = NULL;
--
-+
- /* Error cases - e2fsck has already cleaned up for us */
- if (ino > max_ino) {
- ext3_warning(sb, __FUNCTION__,
-- "bad orphan ino %ld! e2fsck was run?\n", ino);
-+ "bad orphan ino %lu! e2fsck was run?\n", ino);
- return NULL;
- }
-
-@@ -552,7 +553,7 @@ struct inode *ext3_orphan_get (struct su
- if ((bitmap_nr = load_inode_bitmap(sb, block_group)) < 0 ||
- !(bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr])) {
- ext3_warning(sb, __FUNCTION__,
-- "inode bitmap error for orphan %ld\n", ino);
-+ "inode bitmap error for orphan %lu\n", ino);
- return NULL;
- }
-
-@@ -563,7 +564,7 @@ struct inode *ext3_orphan_get (struct su
- if (!ext3_test_bit(bit, bh->b_data) || !(inode = iget(sb, ino)) ||
- is_bad_inode(inode) || NEXT_ORPHAN(inode) > max_ino) {
- ext3_warning(sb, __FUNCTION__,
-- "bad orphan inode %ld! e2fsck was run?\n", ino);
-+ "bad orphan inode %lu! e2fsck was run?\n", ino);
- printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%ld) = %d\n",
- bit, bh->b_blocknr, ext3_test_bit(bit, bh->b_data));
- printk(KERN_NOTICE "inode=%p\n", inode);
-@@ -570,9 +571,9 @@ struct inode *ext3_orphan_get (struct su
- if (inode) {
- printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
- is_bad_inode(inode));
-- printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%d\n",
-+ printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
- NEXT_ORPHAN(inode));
-- printk(KERN_NOTICE "max_ino=%ld\n", max_ino);
-+ printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
- }
- /* Avoid freeing blocks if we got a bad deleted inode */
- if (inode && inode->i_nlink == 0)
---- linux/fs/ext3/namei.c.orig Sat Oct 19 11:42:45 2002
-+++ linux/fs/ext3/namei.c Sat Jan 4 12:13:27 2003
-@@ -716,10 +716,10 @@ int ext3_orphan_del(handle_t *handle, st
- {
- struct list_head *prev;
- struct ext3_sb_info *sbi;
-- ino_t ino_next;
-+ unsigned long ino_next;
- struct ext3_iloc iloc;
- int err = 0;
--
-+
- lock_super(inode->i_sb);
- if (list_empty(&inode->u.ext3_i.i_orphan)) {
- unlock_super(inode->i_sb);
-@@ -730,7 +730,7 @@ int ext3_orphan_del(handle_t *handle, st
- prev = inode->u.ext3_i.i_orphan.prev;
- sbi = EXT3_SB(inode->i_sb);
-
-- jbd_debug(4, "remove inode %ld from orphan list\n", inode->i_ino);
-+ jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
-
- list_del(&inode->u.ext3_i.i_orphan);
- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-@@ -741,13 +741,13 @@ int ext3_orphan_del(handle_t *handle, st
- * list in memory. */
- if (!handle)
- goto out;
--
-+
- err = ext3_reserve_inode_write(handle, inode, &iloc);
- if (err)
- goto out_err;
-
- if (prev == &sbi->s_orphan) {
-- jbd_debug(4, "superblock will point to %ld\n", ino_next);
-+ jbd_debug(4, "superblock will point to %lu\n", ino_next);
- BUFFER_TRACE(sbi->s_sbh, "get_write_access");
- err = ext3_journal_get_write_access(handle, sbi->s_sbh);
- if (err)
-@@ -758,8 +758,8 @@ int ext3_orphan_del(handle_t *handle, st
- struct ext3_iloc iloc2;
- struct inode *i_prev =
- list_entry(prev, struct inode, u.ext3_i.i_orphan);
--
-- jbd_debug(4, "orphan inode %ld will point to %ld\n",
-+
-+ jbd_debug(4, "orphan inode %lu will point to %lu\n",
- i_prev->i_ino, ino_next);
- err = ext3_reserve_inode_write(handle, i_prev, &iloc2);
- if (err)
-@@ -774,7 +774,7 @@ int ext3_orphan_del(handle_t *handle, st
- if (err)
- goto out_brelse;
-
--out_err:
-+out_err:
- ext3_std_error(inode->i_sb, err);
- out:
- unlock_super(inode->i_sb);
---- linux/include/linux/ext3_fs.h.orig Thu Jan 2 16:10:24 2003
-+++ linux/include/linux/ext3_fs.h Sat Jan 4 12:25:41 2003
-@@ -622,7 +622,7 @@ extern int ext3_sync_file (struct file *
- /* ialloc.c */
- extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int);
- extern void ext3_free_inode (handle_t *, struct inode *);
--extern struct inode * ext3_orphan_get (struct super_block *, ino_t);
-+extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);
- extern unsigned long ext3_count_free_inodes (struct super_block *);
- extern void ext3_check_inodes_bitmap (struct super_block *);
- extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
+++ /dev/null
-===== fs/ext3/ialloc.c 1.26 vs edited =====
---- 1.26/fs/ext3/ialloc.c Fri Feb 14 19:24:09 2003
-+++ edited/fs/ext3/ialloc.c Sat Mar 8 01:20:55 2003
-@@ -195,6 +195,36 @@
- }
-
- /*
-+ * @block_group: block group of inode
-+ * @offset: relative offset of inode within @block_group
-+ *
-+ * Check whether any of the inodes in this disk block are in use.
-+ *
-+ * Caller must be holding superblock lock (group/bitmap read lock in
-+ * future).
-+ */
-+int ext3_itable_block_used(struct super_block *sb, unsigned int block_group,
-+ int offset)
-+{
-+ struct buffer_head *ibitmap = read_inode_bitmap(sb, block_group);
-+ int inodes_per_block;
-+ unsigned long inum, iend;
-+
-+ if (!ibitmap)
-+ return 1;
-+
-+ inodes_per_block = sb->s_blocksize / EXT3_SB(sb)->s_inode_size;
-+ inum = offset & ~(inodes_per_block - 1);
-+ iend = inum + inodes_per_block;
-+ for (; inum < iend; inum++) {
-+ if (inum != offset && ext3_test_bit(inum, ibitmap->b_data))
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
- * There are two policies for allocating an inode. If the new inode is
- * a directory, then a forward search is made for a block group with both
- * free space and a low directory-to-inode ratio; if that fails, then of
-@@ -422,8 +452,9 @@
- struct ext3_group_desc * gdp;
- struct ext3_super_block * es;
- struct ext3_inode_info *ei;
-- int err = 0;
-+ struct ext3_iloc iloc;
- struct inode *ret;
-+ int err = 0;
-
- /* Cannot create files in a deleted directory */
- if (!dir || !dir->i_nlink)
-@@ -587,16 +618,23 @@
- goto fail2;
- }
- err = ext3_init_acl(handle, inode, dir);
-+ if (err)
-+ goto fail3;
-+
-+ err = ext3_get_inode_loc_new(inode, &iloc, 1);
-+ if (err)
-+ goto fail3;
-+
-+ BUFFER_TRACE(iloc->bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, iloc.bh);
- if (err) {
-- DQUOT_FREE_INODE(inode);
-- goto fail2;
-- }
-- err = ext3_mark_inode_dirty(handle, inode);
-- if (err) {
-- ext3_std_error(sb, err);
-- DQUOT_FREE_INODE(inode);
-- goto fail2;
-- }
-+ brelse(iloc.bh);
-+ iloc.bh = NULL;
-+ goto fail3;
-+ }
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err)
-+ goto fail3;
-
- ext3_debug("allocating inode %lu\n", inode->i_ino);
- goto really_out;
-@@ -610,6 +648,9 @@
- brelse(bitmap_bh);
- return ret;
-
-+fail3:
-+ ext3_std_error(sb, err);
-+ DQUOT_FREE_INODE(inode);
- fail2:
- inode->i_flags |= S_NOQUOTA;
- inode->i_nlink = 0;
-===== fs/ext3/inode.c 1.62 vs edited =====
---- 1.62/fs/ext3/inode.c Fri Feb 14 19:24:09 2003
-+++ edited/fs/ext3/inode.c Sat Mar 8 02:10:39 2003
-@@ -2144,69 +2144,118 @@
- unlock_kernel();
- }
-
--/*
-- * ext3_get_inode_loc returns with an extra refcount against the
-- * inode's underlying buffer_head on success.
-- */
-+#define NUM_INODE_PREREAD 16
-
--int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
-+/*
-+ * ext3_get_inode_loc returns with an extra refcount against the inode's
-+ * underlying buffer_head on success. If this is for a new inode allocation
-+ * (new is non-zero) then we may be able to optimize away the read if there
-+ * are no other in-use inodes in this inode table block. If we need to do
-+ * a read, then read in a whole chunk of blocks to avoid blocking again soon
-+ * if we are doing lots of creates/updates.
-+ */
-+int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new)
- {
-- struct buffer_head *bh = 0;
-+ struct buffer_head *bh[NUM_INODE_PREREAD];
-+ struct super_block *sb = inode->i_sb;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ unsigned long ino = inode->i_ino;
- unsigned long block;
- unsigned long block_group;
- unsigned long group_desc;
- unsigned long desc;
- unsigned long offset;
- struct ext3_group_desc * gdp;
--
-- if ((inode->i_ino != EXT3_ROOT_INO &&
-- inode->i_ino != EXT3_JOURNAL_INO &&
-- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
-- inode->i_ino > le32_to_cpu(
-- EXT3_SB(inode->i_sb)->s_es->s_inodes_count)) {
-- ext3_error (inode->i_sb, "ext3_get_inode_loc",
-- "bad inode number: %lu", inode->i_ino);
-+
-+ if ((ino != EXT3_ROOT_INO && ino != EXT3_JOURNAL_INO &&
-+ ino < EXT3_FIRST_INO(sb)) ||
-+ ino > le32_to_cpu(sbi->s_es->s_inodes_count)) {
-+ ext3_error(sb, "ext3_get_inode_loc", "bad inode number: %lu",
-+ ino);
- goto bad_inode;
- }
-- block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb);
-- if (block_group >= EXT3_SB(inode->i_sb)->s_groups_count) {
-- ext3_error (inode->i_sb, "ext3_get_inode_loc",
-- "group >= groups count");
-+ block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
-+ if (block_group >= EXT3_SB(sb)->s_groups_count) {
-+ ext3_error(sb, "ext3_get_inode_loc", "group >= groups count");
- goto bad_inode;
- }
-- group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb);
-- desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1);
-- bh = EXT3_SB(inode->i_sb)->s_group_desc[group_desc];
-- if (!bh) {
-- ext3_error (inode->i_sb, "ext3_get_inode_loc",
-- "Descriptor not loaded");
-+ group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb);
-+ desc = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
-+ if (!sbi->s_group_desc[group_desc]) {
-+ ext3_error(sb, "ext3_get_inode_loc", "Descriptor not loaded");
- goto bad_inode;
- }
-
-- gdp = (struct ext3_group_desc *) bh->b_data;
-+ gdp = (struct ext3_group_desc *)(sbi->s_group_desc[group_desc]->b_data);
- /*
- * Figure out the offset within the block group inode table
- */
-- offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) *
-- EXT3_INODE_SIZE(inode->i_sb);
-+ offset = ((ino - 1) % EXT3_INODES_PER_GROUP(sb));
- block = le32_to_cpu(gdp[desc].bg_inode_table) +
-- (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
-- if (!(bh = sb_bread(inode->i_sb, block))) {
-- ext3_error (inode->i_sb, "ext3_get_inode_loc",
-- "unable to read inode block - "
-- "inode=%lu, block=%lu", inode->i_ino, block);
-- goto bad_inode;
-+ (offset * sbi->s_inode_size >> EXT3_BLOCK_SIZE_BITS(sb));
-+ bh[0] = sb_getblk(sb, block);
-+ if (buffer_uptodate(bh[0]))
-+ goto done;
-+
-+ /* If we don't really need to read this block, and it isn't already
-+ * in memory, then we just zero it out. Otherwise, we keep the
-+ * current block contents (deleted inode data) for posterity.
-+ */
-+ if (new && !ext3_itable_block_used(sb, block_group, offset)) {
-+ lock_buffer(bh[0]);
-+ memset(bh[0]->b_data, 0, bh[0]->b_size);
-+ set_buffer_uptodate(bh[0]);
-+ unlock_buffer(bh[0]);
-+ } else {
-+ unsigned long block_end, itable_end;
-+ int count = 1;
-+
-+ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
-+ sbi->s_itb_per_group;
-+ block_end = block + NUM_INODE_PREREAD;
-+ if (block_end > itable_end)
-+ block_end = itable_end;
-+
-+ for (; block < block_end; block++) {
-+ bh[count] = sb_getblk(sb, block);
-+ if (count && (buffer_uptodate(bh[count]) ||
-+ buffer_locked(bh[count]))) {
-+ __brelse(bh[count]);
-+ } else
-+ count++;
-+ }
-+
-+ ll_rw_block(READ, count, bh);
-+
-+ /* Release all but the block we actually need (bh[0]) */
-+ while (--count > 0)
-+ __brelse(bh[count]);
-+
-+ wait_on_buffer(bh[0]);
-+ if (!buffer_uptodate(bh[0])) {
-+ ext3_error(sb, __FUNCTION__,
-+ "unable to read inode block - "
-+ "inode=%lu, block=%llu", ino,
-+ (unsigned long long)bh[0]->b_blocknr);
-+ goto bad_inode;
-+ }
- }
-- offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+done:
-+ offset = (offset * sbi->s_inode_size) & (EXT3_BLOCK_SIZE(sb) - 1);
-
-- iloc->bh = bh;
-- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-+ iloc->bh = bh[0];
-+ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
- iloc->block_group = block_group;
--
-+
- return 0;
--
-+
- bad_inode:
- return -EIO;
-+}
-+
-+int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc)
-+{
-+ return ext3_get_inode_loc_new(inode, iloc, 0);
- }
-
- void ext3_read_inode(struct inode * inode)
-===== include/linux/ext3_fs.h 1.22 vs edited =====
---- 1.22/include/linux/ext3_fs.h Tue Jan 14 00:56:29 2003
-+++ edited/include/linux/ext3_fs.h Sat Mar 8 01:56:28 2003
-@@ -719,6 +719,8 @@
- 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 *);
-
-+extern int ext3_itable_block_used(struct super_block *, unsigned int, int);
-+extern int ext3_get_inode_loc_new(struct inode *, struct ext3_iloc *, int);
- extern int ext3_get_inode_loc (struct inode *, struct ext3_iloc *);
- extern void ext3_read_inode (struct inode *);
- extern void ext3_write_inode (struct inode *, int);
+++ /dev/null
-Under rare conditions (filesystem corruption, really) it is possible
-for ext3_dirty_inode() to require _two_ blocks for the transaction: one
-for the inode and one to update the superblock - to set
-EXT3_FEATURE_RO_COMPAT_LARGE_FILE. This causes the filesystem to go
-BUG.
-
-So reserve an additional block for that eventuality.
-
-
- fs/ext3/inode.c | 2 +-
- 1 files changed, 1 insertion(+), 1 deletion(-)
-
---- 25/fs/ext3/inode.c~ext3-transaction-reserved-blocks Sat Dec 14 18:28:21 2002
-+++ 25-akpm/fs/ext3/inode.c Sat Dec 14 18:28:21 2002
-@@ -2698,7 +2698,7 @@ void ext3_dirty_inode(struct inode *inod
- handle_t *handle;
-
- lock_kernel();
-- handle = ext3_journal_start(inode, 1);
-+ handle = ext3_journal_start(inode, 2);
- if (IS_ERR(handle))
- goto out;
- if (current_handle &&
+++ /dev/null
---- linux/fs/ext3/namei.c.orig Fri Mar 14 14:11:58 2003
-+++ linux/fs/ext3/namei.c Fri Mar 14 14:39:48 2003
-@@ -1406,8 +1409,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;
-
-@@ -1455,7 +1458,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;
- }
-@@ -1468,20 +1471,19 @@
- {
- 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);
-
-@@ -1525,10 +1527,10 @@
- if (err)
- goto out_brelse;
-
--out_err:
-+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/fs/ext3/super.c.orig Fri Mar 14 14:11:58 2003
-+++ linux/fs/ext3/super.c Fri Mar 14 14:36:00 2003
-@@ -1134,6 +1314,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;
-
---- linux/include/linux/ext3_fs_sb.h.orig Tue Feb 11 16:34:33 2003
-+++ linux/include/linux/ext3_fs_sb.h Fri Mar 14 14:30:11 2003
-@@ -67,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/inode.c.orig Wed Mar 12 02:44:06 2003
-+++ ./fs/ext3/inode.c Wed Mar 12 11:55:20 2003
-@@ -99,7 +99,35 @@ int ext3_forget(handle_t *handle, int is
- return err;
- }
-
--/*
-+/*
-+ * Work out how many blocks we need to progress with the next chunk of a
-+ * truncate transaction.
-+ */
-+
-+static unsigned long blocks_for_truncate(struct inode *inode)
-+{
-+ unsigned long needed;
-+
-+ needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9);
-+
-+ /* Give ourselves just enough room to cope with inodes in which
-+ * i_blocks is corrupt: we've seen disk corruptions in the past
-+ * which resulted in random data in an inode which looked enough
-+ * like a regular file for ext3 to try to delete it. Things
-+ * will go a bit crazy if that happens, but at least we should
-+ * try not to panic the whole kernel. */
-+ if (needed < 2)
-+ needed = 2;
-+
-+ /* But we need to bound the transaction so we don't overflow the
-+ * journal. */
-+ if (needed > EXT3_MAX_TRANS_DATA)
-+ needed = EXT3_MAX_TRANS_DATA;
-+
-+ return EXT3_DATA_TRANS_BLOCKS + needed;
-+}
-+
-+/*
- * Truncate transactions can be complex and absolutely huge. So we need to
- * be able to restart the transaction at a conventient checkpoint to make
- * sure we don't overflow the journal.
-@@ -110,19 +138,14 @@ int ext3_forget(handle_t *handle, int is
- * transaction in the top-level truncate loop. --sct
- */
-
--static handle_t *start_transaction(struct inode *inode)
-+static handle_t *start_transaction(struct inode *inode)
- {
-- long needed;
- handle_t *result;
--
-- needed = inode->i_blocks;
-- if (needed > EXT3_MAX_TRANS_DATA)
-- needed = EXT3_MAX_TRANS_DATA;
--
-- result = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS + needed);
-+
-+ result = ext3_journal_start(inode, blocks_for_truncate(inode));
- if (!IS_ERR(result))
- return result;
--
-+
- ext3_std_error(inode->i_sb, PTR_ERR(result));
- return result;
- }
-@@ -135,14 +158,9 @@ static handle_t *start_transaction(struc
- */
- static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
- {
-- long needed;
--
- if (handle->h_buffer_credits > EXT3_RESERVE_TRANS_BLOCKS)
- return 0;
-- needed = inode->i_blocks;
-- if (needed > EXT3_MAX_TRANS_DATA)
-- needed = EXT3_MAX_TRANS_DATA;
-- if (!ext3_journal_extend(handle, EXT3_RESERVE_TRANS_BLOCKS + needed))
-+ if (!ext3_journal_extend(handle, blocks_for_truncate(inode)))
- return 0;
- return 1;
- }
-@@ -154,11 +172,8 @@ static int try_to_extend_transaction(han
- */
- static int ext3_journal_test_restart(handle_t *handle, struct inode *inode)
- {
-- long needed = inode->i_blocks;
-- if (needed > EXT3_MAX_TRANS_DATA)
-- needed = EXT3_MAX_TRANS_DATA;
- jbd_debug(2, "restarting handle %p\n", handle);
-- return ext3_journal_restart(handle, EXT3_DATA_TRANS_BLOCKS + needed);
-+ return ext3_journal_restart(handle, blocks_for_truncate(inode));
- }
-
- /*
+++ /dev/null
-From adilger@clusterfs.com Mon Dec 2 10:26:44 2002
-Date: Mon, 2 Dec 2002 10:26:44 -0700
-From: Andreas Dilger <adilger@clusterfs.com>
-To: Lustre LLNL Mailing list <lc-lustre@llnl.gov>,
- Lustre Development Mailing List <lustre-devel@lists.sourceforge.net>
-Subject: Re: data corrupting bug in 2.4.20 ext3, data=journal
-Message-ID: <20021202102644.H1422@schatzie.adilger.int>
-Mail-Followup-To: Lustre LLNL Mailing list <lc-lustre@llnl.gov>,
- Lustre Development Mailing List <lustre-devel@lists.sourceforge.net>
-Mime-Version: 1.0
-Content-Type: text/plain; charset=us-ascii
-Content-Disposition: inline
-User-Agent: Mutt/1.2.5.1i
-X-GPG-Key: 1024D/0D35BED6
-X-GPG-Fingerprint: 7A37 5D79 BF1B CECA D44F 8A29 A488 39F5 0D35 BED6
-Status: RO
-Content-Length: 1160
-Lines: 39
-
-Here is the new-improved fix for the ext3 discarding data at umount bug
-discovered late last week. To be used instead of the previous ext3 fix.
-
-Sadly, this is completely unrelated to the problems Mike is having with
-ext3 under UML, since it is an unmount-time problem.
-
------ Forwarded message from "Stephen C. Tweedie" <sct@redhat.com> -----
-The attached patch seems to fix things for me.
-
-Cheers,
- Stephen
-
-
---- linux-2.4-ext3merge/fs/ext3/super.c.=K0027=.orig 2002-12-02 15:35:13.000000000 +0000
-+++ linux-2.4-ext3merge/fs/ext3/super.c 2002-12-02 15:35:14.000000000 +0000
-@@ -1640,7 +1640,12 @@
- sb->s_dirt = 0;
- target = log_start_commit(EXT3_SB(sb)->s_journal, NULL);
-
-- if (do_sync_supers) {
-+ /*
-+ * Tricky --- if we are unmounting, the write really does need
-+ * to be synchronous. We can detect that by looking for NULL in
-+ * sb->s_root.
-+ */
-+ if (do_sync_supers || !sb->s_root) {
- unlock_super(sb);
- log_wait_commit(EXT3_SB(sb)->s_journal, target);
- lock_super(sb);
-
-
------ End forwarded message -----
-
-Cheers, Andreas
---
-Andreas Dilger
-http://sourceforge.net/projects/ext2resize/
-http://www-mddsp.enel.ucalgary.ca/People/adilger/
-
-
+++ /dev/null
-
-
-If ext3_add_nondir() fails it will do an iput() of the inode. But we
-continue to run ext3_mark_inode_dirty() against the potentially-freed
-inode. This oopses when slab poisoning is enabled.
-
-Fix it so that we only run ext3_mark_inode_dirty() if the inode was
-successfully instantiated.
-
-This bug was added in 2.4.20-pre9.
-
-
- fs/ext3/namei.c | 11 +++++------
- 1 files changed, 5 insertions(+), 6 deletions(-)
-
---- 24/fs/ext3/namei.c~ext3-use-after-free Sun Dec 15 11:27:50 2002
-+++ 24-akpm/fs/ext3/namei.c Sun Dec 15 11:27:50 2002
-@@ -429,8 +429,11 @@ static int ext3_add_nondir(handle_t *han
- {
- int err = ext3_add_entry(handle, dentry, inode);
- if (!err) {
-- d_instantiate(dentry, inode);
-- return 0;
-+ err = ext3_mark_inode_dirty(handle, inode);
-+ if (err == 0) {
-+ d_instantiate(dentry, inode);
-+ return 0;
-+ }
- }
- ext3_dec_count(handle, inode);
- iput(inode);
-@@ -465,7 +468,6 @@ static int ext3_create (struct inode * d
- inode->i_fop = &ext3_file_operations;
- inode->i_mapping->a_ops = &ext3_aops;
- err = ext3_add_nondir(handle, dentry, inode);
-- ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -490,7 +492,6 @@ static int ext3_mknod (struct inode * di
- if (!IS_ERR(inode)) {
- init_special_inode(inode, mode, rdev);
- err = ext3_add_nondir(handle, dentry, inode);
-- ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -934,7 +935,6 @@ static int ext3_symlink (struct inode *
- }
- inode->u.ext3_i.i_disksize = inode->i_size;
- err = ext3_add_nondir(handle, dentry, inode);
-- ext3_mark_inode_dirty(handle, inode);
- out_stop:
- ext3_journal_stop(handle, dir);
- return err;
-@@ -971,7 +971,6 @@ static int ext3_link (struct dentry * ol
- atomic_inc(&inode->i_count);
-
- err = ext3_add_nondir(handle, dentry, inode);
-- ext3_mark_inode_dirty(handle, inode);
- ext3_journal_stop(handle, dir);
- return err;
- }
-
-_
+++ /dev/null
---- linux/include/linux/extN_fs.h.orig Fri Mar 14 18:09:02 2003
-+++ linux/include/linux/extN_fs.h Fri Mar 14 18:10:20 2003
-@@ -190,6 +192,7 @@
- */
- #define EXTN_STATE_JDATA 0x00000001 /* journaled data exists */
- #define EXTN_STATE_NEW 0x00000002 /* inode is newly created */
-+#define EXTN_STATE_DELETE 0x00000010 /* deferred delete inode */
-
- /*
- * ioctl commands
---- linux/include/linux/extN_fs_sb.h.orig Tue Feb 11 16:34:33 2003
-+++ linux/include/linux/extN_fs_sb.h Mon Mar 10 14:42:07 2003
-@@ -29,6 +29,8 @@
-
- #define EXTN_MAX_GROUP_LOADED 32
-
-+#define EXTN_DELETE_THREAD
-+
- /*
- * third extended-fs super-block data in memory
- */
-@@ -73,6 +75,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 EXTN_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_EXTN_FS_SB */
---- linux/fs/extN/super.c.orig Wed Mar 12 14:05:30 2003
-+++ linux/fs/extN/super.c Thu Mar 13 19:05:26 2003
-@@ -396,6 +396,207 @@
- }
- }
-
-+#ifdef EXTN_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 extN_delete_thread(void *data)
-+{
-+ struct super_block *sb = data;
-+ struct extN_sb_info *sbi = EXTN_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, "kdelextN-%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);
-+ printk(KERN_INFO "EXTN-fs: delete thread on %s started\n",
-+ kdevname(sb->s_dev));
-+
-+ /* main loop */
-+ for (;;) {
-+ sleep_on(&sbi->s_delete_thread_queue);
-+ printk(KERN_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)) {
-+ memset(&sbi->s_delete_list, 0,
-+ sizeof(sbi->s_delete_list));
-+ spin_unlock(&sbi->s_delete_lock);
-+ printk(KERN_DEBUG "extN 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);
-+ printk(KERN_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)
-+ printk(KERN_WARNING
-+ "%lu blocks and %lu left 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 extN_start_delete_thread(struct super_block *sb)
-+{
-+ struct extN_sb_info *sbi = EXTN_SB(sb);
-+ int rc;
-+
-+ spin_lock_init(&sbi->s_delete_lock);
-+ memset(&sbi->s_delete_list, 0, sizeof(sbi->s_delete_list));
-+ init_waitqueue_head(&sbi->s_delete_thread_queue);
-+ init_waitqueue_head(&sbi->s_delete_waiter_queue);
-+ sbi->s_delete_blocks = 0;
-+ sbi->s_delete_inodes = 0;
-+ rc = kernel_thread(extN_delete_thread, sb, CLONE_VM | CLONE_FILES);
-+ if (rc < 0)
-+ printk(KERN_ERR "EXTN-fs: cannot start delete thread: rc %d\n",
-+ rc);
-+ else
-+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next);
-+}
-+
-+static void extN_stop_delete_thread(struct extN_sb_info *sbi)
-+{
-+ wake_up(&sbi->s_delete_thread_queue);
-+ wait_event(sbi->s_delete_waiter_queue, list_empty(&sbi->s_delete_list));
-+}
-+
-+/* Instead of playing games with the inode flags, destruction, etc we just
-+ * duplicate the inode data 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 copy the whole thing.
-+ *
-+ * 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
-+ * truncate thread when we run out of space.
-+ *
-+ * One shouldn't consider this duplicate an "inode", as it isn't really
-+ * visible to the VFS, but rather a data struct that holds truncate data.
-+ *
-+ * In 2.5 this can be done much more cleanly by just registering a "drop"
-+ * method in the super_operations struct.
-+ */
-+static void extN_delete_inode_thread(struct inode *old_inode)
-+{
-+ struct extN_sb_info *sbi = EXTN_SB(old_inode->i_sb);
-+ 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;
-+ }
-+
-+ /* We may want to delete the inode immediately and not defer it */
-+ if (IS_SYNC(old_inode) || blocks <= EXTN_NDIR_BLOCKS ||
-+ !sbi->s_delete_list.next) {
-+ extN_delete_inode(old_inode);
-+ return;
-+ }
-+
-+ if (EXTN_I(old_inode)->i_state & EXTN_STATE_DELETE) {
-+ extN_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+ old_inode->i_ino, blocks);
-+ extN_delete_inode(old_inode);
-+ return;
-+ }
-+
-+ /* 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);
-+
-+ EXTN_SB(old_inode->i_sb)->s_mount_state |= EXTN_ORPHAN_FS;
-+ new_inode = iget(old_inode->i_sb, old_inode->i_ino);
-+ EXTN_SB(old_inode->i_sb)->s_mount_state &= ~EXTN_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);
-+ extN_debug(KERN_DEBUG "delete inode %lu directly (bad read)\n",
-+ old_inode->i_ino);
-+ extN_delete_inode(old_inode);
-+ return;
-+ }
-+ J_ASSERT(new_inode != old_inode);
-+
-+ J_ASSERT(!list_empty(&EXTN_I(old_inode)->i_orphan));
-+ /* 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
-+ * the same as the on-disk orphan list.
-+ */
-+ EXTN_I(new_inode)->i_orphan = EXTN_I(old_inode)->i_orphan;
-+ EXTN_I(new_inode)->i_orphan.next->prev = &EXTN_I(new_inode)->i_orphan;
-+ EXTN_I(new_inode)->i_orphan.prev->next = &EXTN_I(new_inode)->i_orphan;
-+ EXTN_I(new_inode)->i_state |= EXTN_STATE_DELETE;
-+ up(&sbi->s_orphan_lock);
-+
-+ clear_inode(old_inode);
-+
-+ printk(KERN_DEBUG "delete inode %lu (%lu blocks) by thread\n",
-+ new_inode->i_ino, blocks);
-+ 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);
-+
-+ wake_up(&sbi->s_delete_thread_queue);
-+}
-+#else
-+#define extN_start_delete_thread(sbi) do {} while(0)
-+#define extN_stop_delete_thread(sbi) do {} while(0)
-+#endif /* EXTN_DELETE_THREAD */
-+
- void extN_put_super (struct super_block * sb)
- {
- struct extN_sb_info *sbi = EXTN_SB(sb);
-@@ -403,6 +578,7 @@
- kdev_t j_dev = sbi->s_journal->j_dev;
- int i;
-
-+ extN_stop_delete_thread(sbi);
- extN_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
-@@ -451,7 +627,11 @@
- write_inode: extN_write_inode, /* BKL not held. Don't need */
- dirty_inode: extN_dirty_inode, /* BKL not held. We take it */
- put_inode: extN_put_inode, /* BKL not held. Don't need */
-+#ifdef EXTN_DELETE_THREAD
-+ delete_inode: extN_delete_inode_thread,/* BKL not held. We take it */
-+#else
- delete_inode: extN_delete_inode, /* BKL not held. We take it */
-+#endif
- put_super: extN_put_super, /* BKL held */
- write_super: extN_write_super, /* BKL held */
- write_super_lockfs: extN_write_super_lockfs, /* BKL not held. Take it */
-@@ -1205,6 +1385,7 @@
- }
-
- extN_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-+ extN_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
+++ /dev/null
---- lustre/extN/inode.orig.c 2002-12-29 18:48:56.000000000 +0800
-+++ lustre/extN/inode.c 2002-12-29 19:17:24.000000000 +0800
-@@ -2728,3 +2728,85 @@
- * here, in extN_aops_journal_start() to ensure that the forthcoming "see if we
- * need to extend" test in extN_prepare_write() succeeds.
- */
-+
-+/* for each block: 1 ind + 1 dind + 1 tind
-+ * for each block: 3 bitmap blocks
-+ * for each block: 3 group descriptor blocks
-+ * i inode block
-+ * 1 superblock
-+ * 2 * EXTN_SINGLEDATA_TRANS_BLOCKS for the quote files
-+ * ((1+1+1) * 3 * nblocks) + 1 + 1 + 2 * EXTN_SINGLEDATA_TRANS_BLOCKS
-+ *
-+ * XXX assuming:
-+ * (1) fs logic block size == page size
-+ * (2) extN in writeback mode
-+ */
-+static inline int extN_san_write_trans_blocks(int nblocks)
-+{
-+ int ret;
-+
-+ ret = (1 + 1 + 1) * 3 * nblocks + 1 + 1;
-+
-+#ifdef CONFIG_QUOTA
-+ ret += 2 * EXTN_SINGLEDATA_TRANS_BLOCKS;
-+#endif
-+
-+ return ret;
-+}
-+
-+/* Alloc blocks for an inode, while don't create any buffer/page
-+ * for data I/O; set the inode size if file is extended.
-+ *
-+ * @inode: target inode
-+ * @blocks: array of logic block number
-+ * @nblocks: how many blocks need be alloced
-+ * @newsize: new filesize we should set
-+ *
-+ * return: 0 success, otherwise failed
-+ * (*blocks) contains physical block number alloced
-+ *
-+ * XXX this assume the fs block size == page size
-+ */
-+int extN_prep_san_write(struct inode *inode, long *blocks,
-+ int nblocks, loff_t newsize)
-+{
-+ handle_t *handle;
-+ struct buffer_head bh_tmp;
-+ int needed_blocks;
-+ int i, ret = 0, ret2;
-+
-+ needed_blocks = extN_san_write_trans_blocks(nblocks);
-+
-+ lock_kernel();
-+ handle = extN_journal_start(inode, needed_blocks);
-+ if (IS_ERR(handle)) {
-+ unlock_kernel();
-+ return PTR_ERR(handle);
-+ }
-+ unlock_kernel();
-+
-+ /* alloc blocks one by one */
-+ for (i = 0; i < nblocks; i++) {
-+ ret = extN_get_block_handle(handle, inode, blocks[i],
-+ &bh_tmp, 1);
-+ if (ret)
-+ break;
-+
-+ blocks[i] = bh_tmp.b_blocknr;
-+ }
-+
-+ /* set inode size if needed */
-+ if (!ret && (newsize > inode->i_size)) {
-+ inode->i_size = newsize;
-+ extN_mark_inode_dirty(handle, inode);
-+ }
-+
-+ lock_kernel();
-+ ret2 = extN_journal_stop(handle, inode);
-+ unlock_kernel();
-+
-+ if (!ret)
-+ ret = ret2;
-+ return ret;
-+}
-+EXPORT_SYMBOL(extN_prep_san_write);
+++ /dev/null
---- fs/extN/xattr.c Wed Mar 5 23:09:55 2003
-+++ fs/extN/xattr.c Tue Mar 11 17:57:24 2003
-@@ -1181,3 +1181,7 @@
- ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
- &ext3_xattr_user_handler);
- }
-+
-+EXPORT_SYMBOL(extN_xattr_get);
-+EXPORT_SYMBOL(extN_xattr_set);
-+
---- fs/extN/inode.c Wed Mar 5 23:09:55 2003
-+++ fs/extN/inode.c Tue Mar 11 18:24:42 2003
-@@ -1019,7 +1019,7 @@
- *err = -EIO;
- return NULL;
- }
--
-+EXPORT_SYMBOL(extN_bread);
- static int walk_page_buffers( handle_t *handle,
- struct buffer_head *head,
- unsigned from,
---- fs/extN/super.c Wed Mar 5 23:09:55 2003
-+++ fs/extN/super.c Tue Mar 11 18:28:01 2003
-@@ -1703,6 +1703,7 @@
- unlock_kernel();
- return ret;
- }
-+EXPORT_SYMBOL(extN_force_commit);
-
- /*
- * Ext3 always journals updates to the superblock itself, so we don't
---- fs/extN/xattr.h Tue Mar 11 21:37:48 2003
-+++ fs/extN/xattr.h Tue Mar 11 21:18:12 2003
-@@ -5,7 +5,7 @@
-
- (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
- */
--
-+#include <linux/module.h>
- #include <linux/config.h>
- #include <linux/xattr.h>
-
+++ /dev/null
-diff -ru lum-2.4.18-um30/fs/ext3/balloc.c uml-2.4.18-12.5/fs/ext3/balloc.c
---- lum-2.4.18-um30/fs/ext3/balloc.c Mon Feb 25 12:38:08 2002
-+++ uml-2.4.18-12.5/fs/ext3/balloc.c Thu Sep 19 13:40:11 2002
-@@ -276,7 +276,8 @@
- }
- lock_super (sb);
- es = sb->u.ext3_sb.s_es;
-- if (block < le32_to_cpu(es->s_first_data_block) ||
-+ 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 - "
-@@ -309,17 +310,6 @@
- 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),
-- sb->u.ext3_sb.s_itb_per_group) ||
-- in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
-- sb->u.ext3_sb.s_itb_per_group))
-- ext3_error (sb, "ext3_free_blocks",
-- "Freeing blocks in system zones - "
-- "Block = %lu, count = %lu",
-- block, count);
--
- /*
- * We are about to start releasing blocks in the bitmap,
- * so we need undo access.
-@@ -345,14 +335,24 @@
- if (err)
- goto error_return;
-
-- for (i = 0; i < count; i++) {
-+ for (i = 0; i < count; i++, 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),
-+ sb->u.ext2_sb.s_itb_per_group)) {
-+ ext3_error(sb, __FUNCTION__,
-+ "Freeing block in system zone - block = %lu",
-+ block);
-+ continue;
-+ }
-+
- /*
- * An HJ special. This is expensive...
- */
- #ifdef CONFIG_JBD_DEBUG
- {
- struct buffer_head *debug_bh;
-- debug_bh = sb_get_hash_table(sb, block + i);
-+ debug_bh = sb_get_hash_table(sb, block);
- if (debug_bh) {
- BUFFER_TRACE(debug_bh, "Deleted!");
- if (!bh2jh(bitmap_bh)->b_committed_data)
-@@ -365,9 +365,8 @@
- #endif
- BUFFER_TRACE(bitmap_bh, "clear bit");
- if (!ext3_clear_bit (bit + i, bitmap_bh->b_data)) {
-- ext3_error (sb, __FUNCTION__,
-- "bit already cleared for block %lu",
-- block + i);
-+ ext3_error(sb, __FUNCTION__,
-+ "bit already cleared for block %lu", block);
- BUFFER_TRACE(bitmap_bh, "bit already cleared");
- } else {
- dquot_freed_blocks++;
-@@ -415,7 +417,6 @@
- if (!err) err = ret;
-
- if (overflow && !err) {
-- block += count;
- count = overflow;
- goto do_more;
- }
-@@ -575,6 +577,7 @@
-
- ext3_debug ("goal=%lu.\n", goal);
-
-+repeat:
- /*
- * First, test whether the goal block is free.
- */
-@@ -684,10 +686,21 @@
- if (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||
- tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||
- in_range (tmp, le32_to_cpu(gdp->bg_inode_table),
-- sb->u.ext3_sb.s_itb_per_group))
-- ext3_error (sb, "ext3_new_block",
-- "Allocating block in system zone - "
-- "block = %u", tmp);
-+ EXT3_SB(sb)->s_itb_per_group)) {
-+ ext3_error(sb, __FUNCTION__,
-+ "Allocating block in system zone - block = %u", tmp);
-+
-+ /* Note: This will potentially use up one of the handle's
-+ * buffer credits. Normally we have way too many credits,
-+ * so that is OK. In _very_ rare cases it might not be OK.
-+ * We will trigger an assertion if we run out of credits,
-+ * and we will have to do a full fsck of the filesystem -
-+ * better than randomly corrupting filesystem metadata.
-+ */
-+ ext3_set_bit(j, bh->b_data);
-+ goto repeat;
-+ }
-+
-
- /* The superblock lock should guard against anybody else beating
- * us to this point! */
-diff -ru lum-2.4.18-um30/fs/ext3/namei.c uml-2.4.18-12.5/fs/ext3/namei.c
---- lum-2.4.18-um30/fs/ext3/namei.c Fri Nov 9 15:25:04 2001
-+++ uml-2.4.18-12.5/fs/ext3/namei.c Thu Sep 19 13:40:11 2002
-@@ -354,8 +355,8 @@
- */
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- ext3_mark_inode_dirty(handle, dir);
- dir->i_version = ++event;
-+ ext3_mark_inode_dirty(handle, dir);
- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, bh);
- brelse(bh);
-@@ -464,8 +465,8 @@
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
- inode->i_mapping->a_ops = &ext3_aops;
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -489,8 +490,8 @@
- err = PTR_ERR(inode);
- if (!IS_ERR(inode)) {
- init_special_inode(inode, mode, rdev);
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -933,8 +934,8 @@
- inode->i_size = l-1;
- }
- inode->u.ext3_i.i_disksize = inode->i_size;
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- out_stop:
- ext3_journal_stop(handle, dir);
- return err;
-@@ -970,8 +971,8 @@
- ext3_inc_count(handle, inode);
- atomic_inc(&inode->i_count);
-
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- ext3_journal_stop(handle, dir);
- return err;
- }
+++ /dev/null
-#ifndef _ASMI386_IOCTL_H
-#define _ASMI386_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT 0
-#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) (((dir) << _IOC_DIRSHIFT) | ((type) << _IOC_TYPESHIFT) | ((nr) << _IOC_NRSHIFT) | ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
-
-#endif /* _ASMI386_IOCTL_H */
+++ /dev/null
-#ifndef LIBLUSTRE_H__
-#define LIBLUSTRE_H__
-
-#include <sys/mman.h>
-#include <asm/page.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/vfs.h>
-
-#include <portals/list.h>
-#include <portals/p30.h>
-
-/* definitions for liblustre */
-
-/* always adopt 2.5 definitions */
-#define LINUX_VERSION_CODE 1
-#define KERNEL_VERSION(a,b,c) 0
-
-/* cheats for now */
-
-struct work_struct {
- void (*ws_task)(void *arg);
- void *ws_arg;
-};
-
-static inline void prepare_work(struct work_struct *q, void (*t)(void *),
- void *arg)
-{
- q->ws_task = t;
- q->ws_arg = arg;
- return;
-}
-
-static inline void schedule_work(struct work_struct *q)
-{
- q->ws_task(q->ws_arg);
-}
-
-
-#define strnlen(a,b) strlen(a)
-#define kmalloc(a,b) malloc(a)
-#define vmalloc malloc
-#define vfree free
-#define kfree(a) free(a)
-#define GFP_KERNEL 1
-#define GFP_HIGHUSER 1
-#define IS_ERR(a) (abs((int)(a)) < 500 ? 1 : 0)
-#define PTR_ERR(a) ((int)(a))
-
-#define capable(foo) 1
-#define CAP_SYS_ADMIN 1
-
-typedef struct {
- void *cwd;
-
-}mm_segment_t;
-
-typedef void *read_proc_t;
-typedef void *write_proc_t;
-
-
-/* modules */
-
-struct module {
- int count;
-};
-
-static inline void MODULE_AUTHOR(char *name)
-{
- printf("%s\n", name);
-}
-#define MODULE_DESCRIPTION(name) MODULE_AUTHOR(name)
-#define MODULE_LICENSE(name) MODULE_AUTHOR(name)
-
-#define THIS_MODULE NULL
-#define __init
-#define __exit
-
-/* devices */
-
-static inline int misc_register(void *foo)
-{
- return 0;
-}
-#define misc_deregister misc_register
-
-#define __MOD_INC_USE_COUNT(m) (m->count++)
-#define __MOD_DEC_USE_COUNT(m) (m->count--)
-#define MOD_INC_USE_COUNT do {int a = 1; a++; } while (0)
-#define MOD_DEC_USE_COUNT do {int a = 1; a++; } while (0)
-
-/* general stuff */
-
-#define EXPORT_SYMBOL(S)
-
-typedef int spinlock_t;
-typedef __u64 kdev_t;
-
-#define SPIN_LOCK_UNLOCKED 0
-#define spin_lock(l) do {int a = 1; a++; } while (0)
-#define spin_unlock(l) do {int a= 1; a++; } while (0)
-#define spin_lock_init(l) do {int a= 1; a++; } while (0)
-static inline void spin_lock_irqrestore(a,b)
-{
- return;
-}
-static inline void spin_unlock_irqrestore(a,b)
-{
- return;
-}
-static inline void spin_lock_irqsave(a,b)
-{
- return;
-}
-
-#define barrier() do {int a= 1; a++; } while (0)
-
-/* registering symbols */
-extern void *inter_module_get(char *name);
-extern void inter_module_put(char *name);
-
-#define ERESTARTSYS ERESTART
-#define HZ 1
-
-/* random */
-
-static inline void get_random_bytes(void *ptr, int size)
-{
- static int r;
- int *p = (int *)ptr;
- int *end = p + (size / sizeof(int));
- r = rand();
- while ( p + sizeof(int) < end ) {
- *p = r;
- p++;
- }
-}
-
-/* memory */
-
-static inline int copy_from_user(void *a,void *b, int c)
-{
- memcpy(a,b,c);
- return 0;
-}
-
-static inline int copy_to_user(void *a,void *b, int c)
-{
- memcpy(a,b,c);
- return 0;
-}
-
-
-/* slabs */
-typedef struct {
- int size;
-} kmem_cache_t;
-
-static inline kmem_cache_t *kmem_cache_create(name,objsize,c,d,e,f)
-{
- return malloc(objsize);
-};
-
-static inline int kmem_cache_destroy(kmem_cache_t *a)
-{
- free(a);
- return 0;
-}
-#define kmem_cache_validate(a,b) 1
-#define kmem_cache_alloc(cache, prio) malloc(cache->size)
-#define kmem_cache_free(cache, obj) OBD_FREE(obj, cache->size)
-#define PORTAL_SLAB_ALLOC(lock,cache,size) do { lock = kmem_cache_alloc(cache,prio); } while (0)
-#define PORTAL_SLAB_FREE(lock,cache,size) do { lock = kmem_cache_alloc(cache,prio); } while (0)
-
-struct page {
- void *addr;
- int index;
-};
-
-#define kmap(page) (page)->addr
-#define kunmap(a) do { int foo = 1; foo++; } while (0)
-
-static inline struct page *alloc_pages(mask,foo)
-{
- struct page *pg = malloc(sizeof(*pg));
-
- if (!pg)
- return NULL;
-#ifdef MAP_ANONYMOUS
- pg->addr = mmap(0, PAGE_SIZE, PROT_WRITE, MAP_ANONYMOUS, 0, 0);
-#else
- pg->addr = malloc(PAGE_SIZE);
-#endif
-
- if (!pg->addr) {
- free(pg);
- return NULL;
- }
- return pg;
-}
-
-static inline void __free_pages(struct page *pg, int what)
-{
-#ifdef MAP_ANONYMOUS
- munmap(pg->addr, PAGE_SIZE);
-#else
- free(pg->addr);
-#endif
- free(pg);
-}
-
-/* arithmetic */
-#define do_div(a,b) (a)/(b)
-
-/* dentries / intents */
-struct lookup_intent {
- void *it_iattr;
-};
-
-struct iattr {
- int mode;
-};
-
-struct dentry {
- int d_count;
-};
-struct file {
- struct dentry *f_dentry;
- void *private_data;
-} ;
-
-struct vfsmount {
- void *pwd;
-};
-#define cpu_to_le32(x) ((__u32)(x))
-
-/* semaphores */
-struct semaphore {
- int count;
-};
-
-#define down(a) do {(a)->count++;} while (0)
-#define up(a) do {(a)->count--;} while (0)
-#define sema_init(a,b) do { (a)->count = b; } while (0)
-
-typedef struct {
- struct list_head sleepers;
-} wait_queue_head_t;
-
-typedef struct {
- struct list_head sleeping;
- void *process;
-} wait_queue_t;
-
-struct signal {
- int signal;
-};
-
-struct task_struct {
- int state;
- struct signal pending;
- char comm[32];
- int pid;
-};
-
-extern struct task_struct *current;
-
-
-
-#define set_current_state(foo) do { current->state = foo; } while (0)
-
-#define init_waitqueue_entry(q,p) do { (q)->process = p; } while (0)
-#define add_wait_queue(q,p) do { list_add(&(q)->sleepers, &(p)->sleeping); } while (0)
-#define del_wait_queue(p) do { list_del(&(p)->sleeping); } while (0)
-#define remove_wait_queue(q,p) do { list_del(&(p)->sleeping); } while (0)
-
-#define init_waitqueue_head(l) INIT_LIST_HEAD(&(l)->sleepers)
-#define wake_up(l) do { int a; a++; } while (0)
-#define wait_event(l,m) do { int a; a++; } while (0)
-#define TASK_INTERRUPTIBLE 0
-#define TASK_UNINTERRUPTIBLE 1
-#define TASK_RUNNING 2
-
-
-#define schedule() do { int a; a++; } while (0)
-static inline int schedule_timeout(t)
-{
- return 0;
-}
-
-#define lock_kernel() do { int a; a++; } while (0)
-#define daemonize(l) do { int a; a++; } while (0)
-#define sigfillset(l) do { int a; a++; } while (0)
-#define recalc_sigpending(l) do { int a; a++; } while (0)
-#define kernel_thread(l,m,n)
-
-static inline int call_usermodehelper(char *prog, char **argv, char **evnp)
-{
- return 0;
-}
-
-
-
-#define KERN_INFO
-
-
-
-struct timer_list {
- struct list_head tl_list;
-};
-
-typedef struct { volatile int counter; } atomic_t;
-
-#define atomic_read(a) ((a)->counter)
-#define atomic_set(a,b) do {(a)->counter = b; } while (0)
-#define atomic_dec_and_test(a) ((--((a)->counter)) == 0)
-#define atomic_inc(a) (((a)->counter)++)
-#define atomic_dec(a) do { (a)->counter--; } while (0)
-#define atomic_add(b,a) do {(a)->counter += b;} while (0)
-#define atomic_sub(b,a) do {(a)->counter -= b;} while (0)
-
-#define LBUG() do { sleep(1000000); } while (0)
-
-#include <linux/obd_support.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_import.h>
-#include <linux/lustre_export.h>
-#include <linux/lustre_net.h>
-
-
-#endif
-
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
-extN_fs.h
-extN_fs_i.h
-extN_fs_sb.h
-extN_jbd.h
+++ /dev/null
-#ifndef __LINUX_HANDLES_H_
-#define __LINUX_HANDLES_H_
-
-#ifdef __KERNEL__
-#include <asm/types.h>
-#include <asm/atomic.h>
-#include <linux/list.h>
-#endif
-
-typedef void (*portals_handle_addref_cb)(void *object);
-
-/* These handles are most easily used by having them appear at the very top of
- * whatever object that you want to make handles for. ie:
- *
- * struct ldlm_lock {
- * struct portals_handle handle;
- * ...
- * };
- *
- * Now you're able to assign the results of cookie2handle directly to an
- * ldlm_lock. If it's not at the top, you'll want to hack up a macro that
- * uses some offsetof() magic. */
-
-struct portals_handle {
- struct list_head h_link;
- __u64 h_cookie;
- portals_handle_addref_cb h_addref;
-};
-
-/* handles.c */
-
-/* Add a handle to the hash table */
-void portals_handle_hash(struct portals_handle *, portals_handle_addref_cb);
-void portals_handle_unhash(struct portals_handle *);
-void *portals_handle2object(__u64 cookie);
-int portals_handle_init(void);
-void portals_handle_cleanup(void);
-
-#endif
+++ /dev/null
-
-Lustre requires changes to the core kernel before it can be compiled against
-hte core kernel source tree. We use Andrew Morton's 'patch-scripts' utilties
-to keep the complexity of managing changes across multiple kernel targets down.
-They handle the ordering metadata, application, refreshing, and removal of
-patches for us. Please read scripts/docco.txt for a more thorough explanation
-of what 'patch-scripts' do.
-
-We create a thin wrapper around patchscripts with our ./prepare_tree.sh. It
-exports two environment variables. PATCHSCRIPTS is a relative path from the
-kernel source tree to the checked-out patchscripts repository. It is requires
-for patchscripts to operate on data outside the kernel source tree. It also
-puts the absolute path to the scripts/ directory at the front of PATH.
-Finally, it creates a 'series' link from the kernel tree back to the proper
-series file for that kernel tree. More on that below.
-
-prepare_tree.sh and the patch-scripts commands are the only interface we should
-use on a daily basis. We should never have to manage the patches by hand.
-This will save us heart-ache once we're good with the tools. I promise.
-
-Data to be aware of:
-
-patches/
- contains all the patch files themselves. We should have a patch per
- functional change.
-
-series/
- the text files that patch-utils use to define the ordering of patches
- that are applied to a tree. We have a series file for each kernel
- tree variant that requires wildly different patches. (architecture
- differences, stock vs. redhat, etc)
-
-pc/
- control files for patch-utils. These are per tree and should never
- be in cvs.
-
-txt/
- text descriptions of the patches. Nice, but not functionally required.
-
-First, before anything happens, you need to prep a tree for use with
-patch-utils. This means putting a series link in the file and setting the
-environment variable:
-
- $ eval `./prepare_tree.sh -t /tmp/kernels/linux-2.4.18 -r stock-2.4`
-
-prepare-tree.sh is careful to output variable assignments to stdout and
-everything else to stderr so the eval won't go awry. It also is clever about
-resolving the series name, so tab-completed relative paths to the series files
-can be used with -r. (it assumes that series/ is under where prepare_tree.sh
-was executed from). The series link that is created from the tree back into
-the cvs repository is created by force. Don't re-run the command with a
-different role. (this should probably be fixed)
-
-With this in place, the shell that did the eval is ready to wield patch-utils.
-
-] To apply all the patches to a given tree:
-
- $ eval `./prepare_tree.sh -t /tmp/kernels/linux-2.4.18 -r stock-2.4`
- $ cd /tmp/kernels/linux-2.4.18
- $ pushpatch 100000
- ( the huge number just serves to iterate through the patches )
-
-] To refresh the patches against a newer kernel that the series applies to.
-
-Say the series file 'rh-8.0-dev' corresponds to a CFS policy of tracking the
-most recent red hat 8.0 distro kernel. It used to be 2.4.18-14, say, and RH
-has now released RH 2.4.18-17.8.0 and CFS has decided to move to it. We
-want to update the patches in cvs HEAD to be against 2.4.18-17.8.0
-
- $ eval `./prepare_tree.sh -t /tmp/linux-2.4.18-17.8.0 -r rh-8.0-dev`
- $ cd /tmp/linux-2.4.18-17.8.0
- $ for a in $NUM_PATCHES_HAVE ; do
- pushpatch;
- refpatch;
- done
-
-] To add a new series
-
-Simply add a new empty file to the series/ directory, choosing a descriptive
-name for the series.
-
-] To add a patch into a series
-
-Ideally a patch can be added to the end of the series. This is most easily
-done with patch-utils import_patch. After the patch is imported it still needs
-to be applied and refreshed with 'pushpatch' and 'refpatch'. ___remember to
-cvs add the patch with -ko___ so that tags in the context of the diff aren't
-change by CVS, rendering the patch unusable.
-
-It is considered valuable to have a common HEAD which can be checked out to
-patch a kernel and build lustre across lots of targets. This creates some
-friction in the desire to keep a single canonical set of patches in CVS. We
-solve this with the patch-utils scripts by having well-named patches that are
-bound to the different series. Say alpha and ia64 kernel trees both need a
-common lustre patch. Ideally they'd both have our-funcionality.patch in their
-series, but perhaps the code path we want to alter is different in the trees
-and not in the architecture-dependant part of the kernel. For this we'd want
-our-functionality-ia64.patch in the ia64 series file, and
-our-functionality-alpha.patch in the alpha. This split becomes irritating to
-manage as shared changes want to be pushed to all the patches. This will be a
-pain as long as the kernel's we're receiving don't share revision control
-somehow. At least the patch utils make it relatively painless to 'pushpatch'
-the source patch, clean up rejects, test, and 'refpatch' to generate the new
-patch for that series.
+++ /dev/null
-
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/drivers/block/blkpg.c~dev_read_only 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/drivers/block/blkpg.c 2002-12-06 14:52:29.000000000 -0800
-@@ -297,3 +297,38 @@ 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);
---- linux-2.4.18-17.8.0/drivers/block/loop.c~dev_read_only 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/drivers/block/loop.c 2002-12-06 14:52:29.000000000 -0800
-@@ -491,6 +491,11 @@ static int loop_make_request(request_que
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
-+#endif
-+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
---- linux-2.4.18-17.8.0/drivers/ide/ide-disk.c~dev_read_only 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/drivers/ide/ide-disk.c 2002-12-06 14:52:29.000000000 -0800
-@@ -557,6 +557,12 @@ 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)
- {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(1, HWGROUP(drive));
-+ return ide_stopped;
-+ }
-+#endif
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
-
-
-_
+++ /dev/null
- drivers/block/blkpg.c | 35 +++++++++++++++++++++++++++++++++++
- drivers/block/loop.c | 3 +++
- drivers/ide/ide-disk.c | 4 ++++
- 3 files changed, 42 insertions(+)
-
---- linux-rh-2.4.20-6/drivers/block/blkpg.c~dev_read_only_2.4.20 Mon Mar 31 23:41:44 2003
-+++ linux-rh-2.4.20-6-braam/drivers/block/blkpg.c Mon Mar 31 23:41:44 2003
-@@ -297,3 +297,38 @@ 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);
---- linux-rh-2.4.20-6/drivers/block/loop.c~dev_read_only_2.4.20 Mon Mar 31 23:41:44 2003
-+++ linux-rh-2.4.20-6-braam/drivers/block/loop.c Mon Mar 31 23:41:44 2003
-@@ -491,6 +491,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-rh-2.4.20-6/drivers/ide/ide-disk.c~dev_read_only_2.4.20 Mon Mar 31 23:41:44 2003
-+++ linux-rh-2.4.20-6-braam/drivers/ide/ide-disk.c Mon Mar 31 23:43:28 2003
-@@ -551,6 +551,10 @@ static ide_startstop_t lba_48_rw_disk(id
- */
- 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 (!blk_fs_request(rq)) {
- printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);
- idedisk_end_request(drive, 0);
-
-_
+++ /dev/null
---- linux/include/linux/mm.h.truncexport 2003-03-21 20:03:18.000000000 -0500
-+++ linux/include/linux/mm.h 2003-03-21 20:05:04.000000000 -0500
-@@ -650,6 +650,7 @@
- /* filemap.c */
- extern void remove_inode_page(struct page *);
- extern unsigned long page_unuse(struct page *);
-+extern void truncate_complete_page(struct page *);
- extern void truncate_inode_pages(struct address_space *, loff_t);
-
- /* generic vm_area_ops exported for stackable file systems */
---- linux/mm/filemap.c.truncexport 2003-03-21 20:01:19.000000000 -0500
-+++ linux/mm/filemap.c 2003-03-21 20:01:41.000000000 -0500
-@@ -245,7 +245,7 @@
- do_flushpage(page, partial);
- }
-
--static void truncate_complete_page(struct page *page)
-+void truncate_complete_page(struct page *page)
- {
- /*
- * Leave it on the LRU if it gets converted into anonymous buffers
-@@ -266,6 +266,7 @@
- remove_inode_page(page);
- page_cache_release(page);
- }
-+EXPORT_SYMBOL_GPL(truncate_complete_page);
-
- static int FASTCALL(truncate_list_pages(struct list_head *, unsigned long, unsigned *));
- static int truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial)
+++ /dev/null
-
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/fs/ext3/Makefile~exports 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/ext3/Makefile 2002-12-06 14:52:29.000000000 -0800
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o
-+
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
---- linux-2.4.18-17.8.0/fs/ext3/super.c~exports 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/ext3/super.c 2002-12-06 14:52:29.000000000 -0800
-@@ -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-17.8.0/include/linux/fs.h~exports 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/include/linux/fs.h 2002-12-06 14:52:29.000000000 -0800
-@@ -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-17.8.0/kernel/ksyms.c~exports 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/kernel/ksyms.c 2002-12-06 14:52:29.000000000 -0800
-@@ -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/Makefile | 2 ++
- fs/ext3/super.c | 2 +-
- include/linux/fs.h | 1 +
- kernel/ksyms.c | 4 ++++
- 4 files changed, 8 insertions(+), 1 deletion(-)
-
---- linux-2.4.20-hp4_pnnl1/fs/ext3/Makefile~exports_hp Tue Apr 1 20:36:07 2003
-+++ linux-2.4.20-hp4_pnnl1-braam/fs/ext3/Makefile Tue Apr 1 20:36:07 2003
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o
-+
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
---- linux-2.4.20-hp4_pnnl1/fs/ext3/super.c~exports_hp Tue Apr 1 20:36:07 2003
-+++ linux-2.4.20-hp4_pnnl1-braam/fs/ext3/super.c Tue Apr 1 20:36:07 2003
-@@ -1769,7 +1769,7 @@
- unregister_filesystem(&ext3_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- linux-2.4.20-hp4_pnnl1/include/linux/fs.h~exports_hp Tue Apr 1 20:36:07 2003
-+++ linux-2.4.20-hp4_pnnl1-braam/include/linux/fs.h Tue Apr 1 20:36:52 2003
-@@ -1020,6 +1020,7 @@
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
-
- #define kern_umount mntput
-
---- linux-2.4.20-hp4_pnnl1/kernel/ksyms.c~exports_hp Tue Apr 1 20:36:07 2003
-+++ linux-2.4.20-hp4_pnnl1-braam/kernel/ksyms.c Tue Apr 1 20:36:07 2003
-@@ -308,6 +308,11 @@
- EXPORT_SYMBOL(dcache_readdir);
- EXPORT_SYMBOL(dcache_dir_ops);
-
-+/* lustre */
-+EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(panic_notifier_list);
-+EXPORT_SYMBOL(do_kern_mount);
-+
- /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
- EXPORT_SYMBOL(default_llseek);
- EXPORT_SYMBOL(dentry_open);
-
-_
+++ /dev/null
---- lum/fs/inode.c Sat Oct 19 11:42:42 2002
-+++ linux-2.4.18-uml35-ext3online/fs/inode.c Mon Oct 14 00:41:20 2002
-@@ -606,7 +553,8 @@ static void dispose_list(struct list_hea
- /*
- * Invalidate all inodes for a device.
- */
--static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose)
-+static int invalidate_list(struct list_head *head, struct super_block * sb,
-+ struct list_head * dispose, int show)
- {
- struct list_head *next;
- int busy = 0, count = 0;
-@@ -631,6 +579,11 @@ static int invalidate_list(struct list_h
- count++;
- continue;
- }
-+ if (show)
-+ printk(KERN_ERR
-+ "inode busy: dev %s:%lu (%p) mode %o count %u\n",
-+ kdevname(sb->s_dev), inode->i_ino, inode,
-+ inode->i_mode, atomic_read(&inode->i_count));
- busy = 1;
- }
- /* only unused inodes may be cached with i_count zero */
-@@ -649,22 +601,23 @@ static int invalidate_list(struct list_h
- /**
- * invalidate_inodes - discard the inodes on a device
- * @sb: superblock
-+ * @show: whether we should display any busy inodes found
- *
- * Discard all of the inodes for a given superblock. If the discard
- * fails because there are busy inodes then a non zero value is returned.
- * If the discard is successful all the inodes have been discarded.
- */
-
--int invalidate_inodes(struct super_block * sb)
-+int invalidate_inodes(struct super_block * sb, int show)
- {
- int busy;
- LIST_HEAD(throw_away);
-
- spin_lock(&inode_lock);
-- busy = invalidate_list(&inode_in_use, sb, &throw_away);
-- busy |= invalidate_list(&inode_unused, sb, &throw_away);
-- busy |= invalidate_list(&sb->s_dirty, sb, &throw_away);
-- busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away);
-+ busy = invalidate_list(&inode_in_use, sb, &throw_away, show);
-+ busy |= invalidate_list(&inode_unused, sb, &throw_away, show);
-+ busy |= invalidate_list(&sb->s_dirty, sb, &throw_away, show);
-+ busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away, show);
- spin_unlock(&inode_lock);
-
- dispose_list(&throw_away);
-@@ -690,7 +643,7 @@ int invalidate_device(kdev_t dev, int do
- * hold).
- */
- shrink_dcache_sb(sb);
-- res = invalidate_inodes(sb);
-+ res = invalidate_inodes(sb, 0);
- drop_super(sb);
- }
- invalidate_buffers(dev);
---- lum/fs/super.c.orig Sat Oct 19 11:42:42 2002
-+++ lum/fs/super.c Wed Oct 30 17:16:55 2002
-@@ -936,7 +936,7 @@
- lock_super(sb);
- lock_kernel();
- sb->s_flags &= ~MS_ACTIVE;
-- invalidate_inodes(sb); /* bad name - it should be evict_inodes() */
-+ invalidate_inodes(sb, 0); /* bad name - it should be evict_inodes() */
- if (sop) {
- if (sop->write_super && sb->s_dirt)
- sop->write_super(sb);
-@@ -945,7 +945,7 @@
- }
-
- /* Forget any remaining inodes */
-- if (invalidate_inodes(sb)) {
-+ if (invalidate_inodes(sb, 1)) {
- printk(KERN_ERR "VFS: Busy inodes after unmount. "
- "Self-destruct in 5 seconds. Have a nice day...\n");
- }
---- lum/include/linux/fs.h Wed Oct 30 17:10:42 2002
-+++ lum/include/linux/fs.h.orig Tue Oct 22 23:15:00 2002
-@@ -1261,7 +1261,7 @@
- extern void set_buffer_flushtime(struct buffer_head *);
- extern void balance_dirty(void);
- extern int check_disk_change(kdev_t);
--extern int invalidate_inodes(struct super_block *);
-+extern int invalidate_inodes(struct super_block *, int);
- extern int invalidate_device(kdev_t, int);
- extern void invalidate_inode_pages(struct inode *);
- extern void invalidate_inode_pages2(struct address_space *);
---- lum/fs/smbfs/inode.c.orig Mon Feb 25 12:38:09 2002
-+++ lum/fs/smbfs/inode.c Thu Feb 6 21:34:26 2003
-@@ -166,7 +166,7 @@
- {
- VERBOSE("\n");
- shrink_dcache_sb(SB_of(server));
-- invalidate_inodes(SB_of(server));
-+ invalidate_inodes(SB_of(server), 0);
- }
-
- /*
+++ /dev/null
---- linux-chaos/fs/inode.c.b_io_export Wed Jan 29 16:56:15 2003
-+++ linux-chaos/fs/inode.c Wed Jan 29 16:56:27 2003
-@@ -66,7 +66,8 @@
- * 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-chaos/fs/Makefile.b_io_export Wed Jan 29 16:56:45 2003
-+++ linux-chaos/fs/Makefile Wed Jan 29 16:56: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-chaos/mm/filemap.c.b_io_export Wed Jan 29 16:50:39 2003
-+++ linux-chaos/mm/filemap.c Wed Jan 29 16:51:11 2003
-@@ -65,6 +65,7 @@
- * pagecache_lock
- */
- spinlock_cacheline_t pagemap_lru_lock_cacheline = {SPIN_LOCK_UNLOCKED};
-+EXPORT_SYMBOL(pagemap_lru_lock_cacheline);
-
- #define CLUSTER_PAGES (1 << page_cluster)
- #define CLUSTER_OFFSET(x) (((x) >> page_cluster) << page_cluster)
---- linux-chaos/mm/vmscan.c.b_io_export Wed Jan 29 16:51:58 2003
-+++ linux-chaos/mm/vmscan.c Wed Jan 29 16:55:16 2003
-@@ -839,6 +839,7 @@
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&kswapd_done, &wait);
- }
-+EXPORT_SYMBOL(wakeup_kswapd);
-
- static void wakeup_memwaiters(void)
- {
---- linux-chaos/mm/Makefile.b_io_export Wed Jan 29 16:52:46 2003
-+++ linux-chaos/mm/Makefile Wed Jan 29 16:54:23 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.c
-
- 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-chaos/mm/page_alloc.c.b_io_export Wed Jan 29 17:00:32 2003
-+++ linux-chaos/mm/page_alloc.c Wed Jan 29 17:01:31 2003
-@@ -31,6 +31,7 @@
- int nr_inactive_dirty_pages;
- int nr_inactive_clean_pages;
- pg_data_t *pgdat_list;
-+EXPORT_SYMBOL(pgdat_list);
-
- /*
- * The zone_table array is used to look up the address of the
+++ /dev/null
---- linux-2.4.19-hp2_pnnl4_Lv13/fs/inode.c.iod-export 2003-02-27 14:28:04.000000000 -0800
-+++ linux-2.4.19-hp2_pnnl4_Lv13/fs/inode.c 2003-03-03 13:54:59.000000000 -0800
-@@ -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 @@
- * 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.19-hp2_pnnl4_Lv13/fs/Makefile.iod-export 2003-02-27 14:28:01.000000000 -0800
-+++ linux-2.4.19-hp2_pnnl4_Lv13/fs/Makefile 2003-03-03 13:56:11.000000000 -0800
-@@ -7,7 +7,7 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o dquot.o
-+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o
- mod-subdirs := nls xfs
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
---- linux-2.4.19-hp2_pnnl4_Lv13/mm/page_alloc.c.iod-export 2003-02-27 14:28:01.000000000 -0800
-+++ linux-2.4.19-hp2_pnnl4_Lv13/mm/page_alloc.c 2003-03-03 13:54:59.000000000 -0800
-@@ -28,6 +28,7 @@
- LIST_HEAD(inactive_list);
- LIST_HEAD(active_list);
- pg_data_t *pgdat_list;
-+EXPORT_SYMBOL(pgdat_list);
-
- /* Used to look up the address of the struct zone encoded in page->zone */
- zone_t *zone_table[MAX_NR_ZONES*MAX_NR_NODES];
+++ /dev/null
-
-
-
- fs/jbd/commit.c | 27 +++++++++++++++++++++---
- fs/jbd/journal.c | 1
- fs/jbd/transaction.c | 56 ++++++++++++++++++++++++++++++++++++++++-----------
- include/linux/jbd.h | 20 ++++++++++++++++++
- 4 files changed, 90 insertions(+), 14 deletions(-)
-
---- linux-2.4.19/fs/jbd/commit.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
-+++ linux-2.4.19-root/fs/jbd/commit.c Sun Jan 19 19:46:42 2003
-@@ -475,7 +475,7 @@ start_journal_io:
- transaction's t_log_list queue, and metadata buffers are on
- the t_iobuf_list queue.
-
-- Wait for the transactions in reverse order. That way we are
-+ Wait for the buffers in reverse order. That way we are
- less likely to be woken up until all IOs have completed, and
- so we incur less scheduling load.
- */
-@@ -566,8 +566,10 @@ start_journal_io:
-
- jbd_debug(3, "JBD: commit phase 6\n");
-
-- if (is_journal_aborted(journal))
-+ if (is_journal_aborted(journal)) {
-+ unlock_journal(journal);
- goto skip_commit;
-+ }
-
- /* Done it all: now write the commit record. We should have
- * cleaned up our previous buffers by now, so if we are in abort
-@@ -577,6 +579,7 @@ start_journal_io:
- descriptor = journal_get_descriptor_buffer(journal);
- if (!descriptor) {
- __journal_abort_hard(journal);
-+ unlock_journal(journal);
- goto skip_commit;
- }
-
-@@ -600,7 +603,6 @@ start_journal_io:
- put_bh(bh); /* One for getblk() */
- journal_unlock_journal_head(descriptor);
- }
-- lock_journal(journal);
-
- /* End of a transaction! Finally, we can do checkpoint
- processing: any buffers committed as a result of this
-@@ -609,6 +611,25 @@ start_journal_io:
-
- skip_commit:
-
-+ /* Call any callbacks that had been registered for handles in this
-+ * transaction. It is up to the callback to free any allocated
-+ * memory.
-+ */
-+ if (!list_empty(&commit_transaction->t_jcb)) {
-+ struct list_head *p, *n;
-+ int error = is_journal_aborted(journal);
-+
-+ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+ struct journal_callback *jcb;
-+
-+ jcb = list_entry(p, struct journal_callback, jcb_list);
-+ list_del(p);
-+ jcb->jcb_func(jcb, error);
-+ }
-+ }
-+
-+ lock_journal(journal);
-+
- jbd_debug(3, "JBD: commit phase 7\n");
-
- J_ASSERT(commit_transaction->t_sync_datalist == NULL);
---- linux-2.4.19/fs/jbd/journal.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
-+++ linux-2.4.19-root/fs/jbd/journal.c Sun Jan 19 19:46:42 2003
-@@ -58,6 +58,7 @@ EXPORT_SYMBOL(journal_sync_buffer);
- #endif
- EXPORT_SYMBOL(journal_flush);
- EXPORT_SYMBOL(journal_revoke);
-+EXPORT_SYMBOL(journal_callback_set);
-
- EXPORT_SYMBOL(journal_init_dev);
- EXPORT_SYMBOL(journal_init_inode);
---- linux-2.4.19/fs/jbd/transaction.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
-+++ linux-2.4.19-root/fs/jbd/transaction.c Sun Jan 19 19:46:42 2003
-@@ -57,6 +57,7 @@ static transaction_t * get_transaction (
- transaction->t_state = T_RUNNING;
- transaction->t_tid = journal->j_transaction_sequence++;
- transaction->t_expires = jiffies + journal->j_commit_interval;
-+ INIT_LIST_HEAD(&transaction->t_jcb);
-
- /* Set up the commit timer for the new transaction. */
- J_ASSERT (!journal->j_commit_timer_active);
-@@ -201,6 +202,20 @@ repeat_locked:
- return 0;
- }
-
-+/* Allocate a new handle. This should probably be in a slab... */
-+static handle_t *new_handle(int nblocks)
-+{
-+ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+ if (!handle)
-+ return NULL;
-+ memset(handle, 0, sizeof (handle_t));
-+ handle->h_buffer_credits = nblocks;
-+ handle->h_ref = 1;
-+ INIT_LIST_HEAD(&handle->h_jcb);
-+
-+ return handle;
-+}
-+
- /*
- * Obtain a new handle.
- *
-@@ -227,14 +242,11 @@ handle_t *journal_start(journal_t *journ
- handle->h_ref++;
- return handle;
- }
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = start_this_handle(journal, handle);
-@@ -333,14 +345,11 @@ handle_t *journal_try_start(journal_t *j
-
- if (is_journal_aborted(journal))
- return ERR_PTR(-EIO);
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = try_start_this_handle(journal, handle);
-@@ -1328,6 +1337,28 @@ out:
- #endif
-
- /*
-+ * Register a callback function for this handle. The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters. There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations. The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void journal_callback_set(handle_t *handle,
-+ void (*func)(struct journal_callback *jcb, int error),
-+ struct journal_callback *jcb)
-+{
-+ list_add(&jcb->jcb_list, &handle->h_jcb);
-+ jcb->jcb_func = func;
-+}
-+
-+/*
- * All done for a particular handle.
- *
- * There is not much action needed here. We just return any remaining
-@@ -1393,7 +1424,10 @@ int journal_stop(handle_t *handle)
- wake_up(&journal->j_wait_transaction_locked);
- }
-
-- /*
-+ /* Move callbacks from the handle to the transaction. */
-+ list_splice(&handle->h_jcb, &transaction->t_jcb);
-+
-+ /*
- * If the handle is marked SYNC, we need to set another commit
- * going! We also want to force a commit if the current
- * transaction is occupying too much of the log, or if the
---- linux-2.4.19/include/linux/jbd.h~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
-+++ linux-2.4.19-root/include/linux/jbd.h Sun Jan 19 19:46:42 2003
-@@ -249,6 +249,13 @@ static inline struct journal_head *bh2jh
- return bh->b_private;
- }
-
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+struct journal_callback {
-+ struct list_head jcb_list;
-+ void (*jcb_func)(struct journal_callback *jcb, int error);
-+ /* user data goes here */
-+};
-+
- struct jbd_revoke_table_s;
-
- /* The handle_t type represents a single atomic update being performed
-@@ -279,6 +286,12 @@ struct handle_s
- operations */
- int h_err;
-
-+ /* List of application registered callbacks for this handle.
-+ * The function(s) will be called after the transaction that
-+ * this handle is part of has been committed to disk.
-+ */
-+ struct list_head h_jcb;
-+
- /* Flags */
- unsigned int h_sync: 1; /* sync-on-close */
- unsigned int h_jdata: 1; /* force data journaling */
-@@ -398,6 +411,10 @@ struct transaction_s
-
- /* How many handles used this transaction? */
- int t_handle_count;
-+
-+ /* List of registered callback functions for this transaction.
-+ * Called when the transaction is committed. */
-+ struct list_head t_jcb;
- };
-
-
-@@ -646,6 +663,9 @@ extern int journal_flushpage(journal_t
- extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
- extern int journal_stop(handle_t *);
- extern int journal_flush (journal_t *);
-+extern void journal_callback_set(handle_t *handle,
-+ void (*fn)(struct journal_callback *,int),
-+ struct journal_callback *jcb);
-
- extern void journal_lock_updates (journal_t *);
- extern void journal_unlock_updates (journal_t *);
+++ /dev/null
-
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/arch/i386/mm/init.c~kmem_cache_validate 2002-12-06 14:52:30.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/arch/i386/mm/init.c 2002-12-06 14:52:30.000000000 -0800
-@@ -43,6 +43,12 @@ unsigned long highstart_pfn, highend_pfn
- static unsigned long totalram_pages;
- static unsigned long totalhigh_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int do_check_pgt_cache(int low, int high)
- {
- int freed = 0;
---- linux-2.4.18-17.8.0/arch/ia64/mm/init.c~kmem_cache_validate 2002-12-06 14:52:30.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/arch/ia64/mm/init.c 2002-12-06 14:52:30.000000000 -0800
-@@ -37,6 +37,12 @@ unsigned long MAX_DMA_ADDRESS = PAGE_OFF
-
- static unsigned long totalram_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int
- do_check_pgt_cache (int low, int high)
- {
---- linux-2.4.18-17.8.0/include/linux/slab.h~kmem_cache_validate 2002-12-06 14:52:30.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/include/linux/slab.h 2002-12-06 14:52:30.000000000 -0800
-@@ -57,6 +57,7 @@ extern int kmem_cache_destroy(kmem_cache
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
-
- extern void *kmalloc(size_t, int);
- extern void kfree(const void *);
---- linux-2.4.18-17.8.0/kernel/ksyms.c~kmem_cache_validate 2002-12-06 14:52:30.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/kernel/ksyms.c 2002-12-06 14:52:30.000000000 -0800
-@@ -119,6 +119,7 @@ EXPORT_SYMBOL(kmem_cache_destroy);
- EXPORT_SYMBOL(kmem_cache_shrink);
- EXPORT_SYMBOL(kmem_cache_alloc);
- EXPORT_SYMBOL(kmem_cache_free);
-+EXPORT_SYMBOL(kmem_cache_validate);
- EXPORT_SYMBOL(kmalloc);
- EXPORT_SYMBOL(kfree);
- EXPORT_SYMBOL(vfree);
---- linux-2.4.18-17.8.0/mm/slab.c~kmem_cache_validate 2002-12-06 14:52:30.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/mm/slab.c 2002-12-06 14:52:30.000000000 -0800
-@@ -1208,6 +1208,59 @@ failed:
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!VALID_PAGE(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
-
-_
+++ /dev/null
-# This is a BitKeeper generated patch for the following project:
-# Project Name: Linux kernel tree
-# This patch format is intended for GNU patch command version 2.5 or higher.
-# This patch includes the following deltas:
-# ChangeSet 1.809 -> 1.814
-# kernel/ksyms.c 1.149 -> 1.152
-# fs/open.c 1.28 -> 1.29
-# fs/ext3/Makefile 1.4 -> 1.5
-# include/linux/ext3_jbd.h 1.5 -> 1.6
-# fs/driverfs/inode.c 1.52 -> 1.53
-# fs/dcache.c 1.33 -> 1.34
-# fs/stat.c 1.13 -> 1.14
-# include/linux/fs.h 1.175 -> 1.178
-# include/linux/namei.h 1.3 -> 1.4
-# fs/namei.c 1.56 -> 1.61
-# fs/nfsd/vfs.c 1.44 -> 1.45
-# arch/um/kernel/mem.c 1.5 -> 1.6
-# fs/ext3/ialloc.c 1.17 -> 1.18
-# fs/ext3/symlink.c 1.3 -> 1.4
-# fs/Makefile 1.42 -> 1.43
-# fs/ext3/namei.c 1.22 -> 1.23
-# include/linux/ext3_fs.h 1.11 -> 1.12
-# net/unix/af_unix.c 1.29 -> 1.30
-# fs/Config.in 1.39 -> 1.40
-# fs/ext3/inode.c 1.42 -> 1.43
-# fs/Config.help 1.21 -> 1.22
-# mm/slab.c 1.33 -> 1.34
-# fs/sysfs/inode.c 1.55 -> 1.56
-# fs/ext3/super.c 1.33 -> 1.34
-# fs/ext3/file.c 1.9 -> 1.10
-# include/linux/slab.h 1.13 -> 1.14
-# include/linux/dcache.h 1.19 -> 1.20
-# (new) -> 1.1 fs/ext3/xattr.h
-# (new) -> 1.1 include/linux/mbcache.h
-# (new) -> 1.1 include/linux/lustre_version.h
-# (new) -> 1.2 fs/ext3/xattr.c
-# (new) -> 1.1 fs/mbcache.c
-# (new) -> 1.1 fs/ext3/xattr_user.c
-#
-# The following is the BitKeeper ChangeSet Log
-# --------------------------------------------
-# 02/10/20 braam@clusterfs.com 1.810
-# xattrs for UML bk repository
-# --------------------------------------------
-# 02/10/20 braam@clusterfs.com 1.811
-# Changes for Lustre
-# --------------------------------------------
-# 02/12/17 root@kai.(none) 1.812
-# changed for lustre
-# --------------------------------------------
-# 03/01/01 root@kai.(none) 1.813
-# changes for intent of lustre
-# --------------------------------------------
-# 03/01/04 root@kai.(none) 1.814
-# fix error for intent
-# --------------------------------------------
-#
-diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
---- a/arch/um/kernel/mem.c Sat Jan 4 18:24:12 2003
-+++ b/arch/um/kernel/mem.c Sat Jan 4 18:24:12 2003
-@@ -656,6 +656,22 @@
- return(phys_mem_map(pte_val(pte)));
- }
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+ struct page *page;
-+ struct mem_region *mr;
-+ unsigned long phys = __pa(kaddr);
-+ unsigned int n = phys_region_index(phys);
-+
-+ if(regions[n] == NULL)
-+ return NULL;
-+
-+ mr = regions[n];
-+ page = (struct page *) mr->mem_map;
-+ return page + ((phys_addr(phys)) >> PAGE_SHIFT);
-+}
-+
-+
- struct mem_region *page_region(struct page *page, int *index_out)
- {
- int i;
-@@ -743,7 +759,7 @@
- (addr <= region->start + region->len))
- return(mk_phys(addr - region->start, i));
- }
-- panic("region_pa : no region for virtual address");
-+ //panic("region_pa : no region for virtual address");
- return(0);
- }
-
-diff -Nru a/fs/Config.help b/fs/Config.help
---- a/fs/Config.help Sat Jan 4 18:24:12 2003
-+++ b/fs/Config.help Sat Jan 4 18:24:12 2003
-@@ -154,6 +154,13 @@
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this may be dangerous.
-
-+CONFIG_EXT3_FS_XATTR
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
- CONFIG_JBD
- This is a generic journaling layer for block devices. It is
- currently used by the ext3 file system, but it could also be used to
-diff -Nru a/fs/Config.in b/fs/Config.in
---- a/fs/Config.in Sat Jan 4 18:24:12 2003
-+++ b/fs/Config.in Sat Jan 4 18:24:12 2003
-@@ -27,6 +27,7 @@
- dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
-
- tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
-+dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
- # CONFIG_JBD could be its own option (even modular), but until there are
- # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
- # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
-@@ -180,6 +181,17 @@
- define_tristate CONFIG_ZISOFS_FS $CONFIG_ISO9660_FS
- else
- define_tristate CONFIG_ZISOFS_FS n
-+fi
-+
-+# Meta block cache for Extended Attributes (ext2/ext3)
-+if [ "$CONFIG_EXT2_FS_XATTR" = "y" -o "$CONFIG_EXT3_FS_XATTR" = "y" ]; then
-+ if [ "$CONFIG_EXT2_FS" = "y" -o "$CONFIG_EXT3_FS" = "y" ]; then
-+ define_tristate CONFIG_FS_MBCACHE y
-+ else
-+ if [ "$CONFIG_EXT2_FS" = "m" -o "$CONFIG_EXT3_FS" = "m" ]; then
-+ define_tristate CONFIG_FS_MBCACHE m
-+ fi
-+ fi
- fi
-
- mainmenu_option next_comment
-diff -Nru a/fs/Makefile b/fs/Makefile
---- a/fs/Makefile Sat Jan 4 18:24:12 2003
-+++ b/fs/Makefile Sat Jan 4 18:24:12 2003
-@@ -6,7 +6,7 @@
- #
-
- export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o \
-- fcntl.o read_write.o dcookies.o
-+ fcntl.o read_write.o dcookies.o mbcache.o
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
- bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \
-@@ -29,6 +29,8 @@
- obj-y += binfmt_script.o
-
- obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
-+
-+obj-$(CONFIG_FS_MBCACHE) += mbcache.o
-
- obj-$(CONFIG_QUOTA) += dquot.o
- obj-$(CONFIG_QFMT_V1) += quota_v1.o
-diff -Nru a/fs/dcache.c b/fs/dcache.c
---- a/fs/dcache.c Sat Jan 4 18:24:12 2003
-+++ b/fs/dcache.c Sat Jan 4 18:24:12 2003
-@@ -638,6 +638,7 @@
- dentry->d_fsdata = NULL;
- dentry->d_mounted = 0;
- dentry->d_cookie = NULL;
-+ dentry->d_it = NULL;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
-diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c
---- a/fs/driverfs/inode.c Sat Jan 4 18:24:12 2003
-+++ b/fs/driverfs/inode.c Sat Jan 4 18:24:12 2003
-@@ -523,7 +523,7 @@
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-- return lookup_hash(&qstr,parent);
-+ return lookup_hash(&qstr,parent, NULL);
- }
-
- /**
-diff -Nru a/fs/ext3/Makefile b/fs/ext3/Makefile
---- a/fs/ext3/Makefile Sat Jan 4 18:24:12 2003
-+++ b/fs/ext3/Makefile Sat Jan 4 18:24:12 2003
-@@ -7,4 +7,10 @@
- ext3-objs := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o hash.o
-
-+export-objs += xattr.o
-+
-+ifeq ($(CONFIG_EXT3_FS_XATTR),y)
-+ext3-objs += xattr.o xattr_user.o
-+endif
-+
- include $(TOPDIR)/Rules.make
-diff -Nru a/fs/ext3/file.c b/fs/ext3/file.c
---- a/fs/ext3/file.c Sat Jan 4 18:24:12 2003
-+++ b/fs/ext3/file.c Sat Jan 4 18:24:12 2003
-@@ -23,7 +23,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
--#include <linux/smp_lock.h>
-+#include "xattr.h"
-
- /*
- * Called when an inode is released. Note that this is different
-@@ -98,5 +98,9 @@
- struct inode_operations ext3_file_inode_operations = {
- .truncate = ext3_truncate,
- .setattr = ext3_setattr,
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
- };
-
-diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
---- a/fs/ext3/ialloc.c Sat Jan 4 18:24:12 2003
-+++ b/fs/ext3/ialloc.c Sat Jan 4 18:24:12 2003
-@@ -25,6 +25,8 @@
- #include <asm/bitops.h>
- #include <asm/byteorder.h>
-
-+#include "xattr.h"
-+
- /*
- * ialloc.c contains the inodes allocation and deallocation routines
- */
-@@ -118,6 +120,7 @@
- * as writing the quota to disk may need the lock as well.
- */
- DQUOT_INIT(inode);
-+ ext3_xattr_delete_inode(handle, inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
-
-diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
---- a/fs/ext3/inode.c Sat Jan 4 18:24:12 2003
-+++ b/fs/ext3/inode.c Sat Jan 4 18:24:12 2003
-@@ -42,6 +42,18 @@
- */
- #undef SEARCH_FROM_ZERO
-
-+/*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext3_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = EXT3_I(inode)->i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
- /* The ext3 forget function must perform a revoke if we are freeing data
- * which has been journaled. Metadata (eg. indirect blocks) must be
- * revoked in all cases.
-@@ -51,7 +63,7 @@
- * still needs to be revoked.
- */
-
--static int ext3_forget(handle_t *handle, int is_metadata,
-+int ext3_forget(handle_t *handle, int is_metadata,
- struct inode *inode, struct buffer_head *bh,
- int blocknr)
- {
-@@ -167,9 +179,7 @@
- {
- handle_t *handle;
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
-
- lock_kernel();
-@@ -1979,6 +1989,8 @@
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext3_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -2130,8 +2142,6 @@
- struct ext3_group_desc * gdp;
-
- if ((inode->i_ino != EXT3_ROOT_INO &&
-- inode->i_ino != EXT3_ACL_IDX_INO &&
-- inode->i_ino != EXT3_ACL_DATA_INO &&
- inode->i_ino != EXT3_JOURNAL_INO &&
- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(
-@@ -2263,10 +2273,7 @@
-
- brelse (iloc.bh);
-
-- if (inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
- if (ext3_should_writeback_data(inode))
-@@ -2277,18 +2284,20 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext3_inode_is_fast_symlink(inode))
- inode->i_op = &ext3_fast_symlink_inode_operations;
- else {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext3_symlink_inode_operations;
- if (ext3_should_writeback_data(inode))
- inode->i_mapping->a_ops = &ext3_writeback_aops;
- else
- inode->i_mapping->a_ops = &ext3_aops;
- }
-- } else
-+ } else {
-+ inode->i_op = &ext3_special_inode_operations;
- init_special_inode(inode, inode->i_mode,
- le32_to_cpu(iloc.raw_inode->i_block[0]));
-+ }
- if (ei->i_flags & EXT3_SYNC_FL)
- inode->i_flags |= S_SYNC;
- if (ei->i_flags & EXT3_APPEND_FL)
-diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c
---- a/fs/ext3/namei.c Sat Jan 4 18:24:12 2003
-+++ b/fs/ext3/namei.c Sat Jan 4 18:24:12 2003
-@@ -36,6 +36,7 @@
- #include <linux/quotaops.h>
- #include <linux/buffer_head.h>
- #include <linux/smp_lock.h>
-+#include "xattr.h"
-
-
- /*
-@@ -1654,7 +1655,7 @@
- if (IS_DIRSYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFDIR);
-+ inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
-@@ -1662,7 +1663,6 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-- inode->i_blocks = 0;
- dir_block = ext3_bread (handle, inode, 0, 1, &err);
- if (!dir_block) {
- inode->i_nlink--; /* is this nlink == 0? */
-@@ -1689,9 +1689,6 @@
- BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, dir_block);
- brelse (dir_block);
-- inode->i_mode = S_IFDIR | mode;
-- if (dir->i_mode & S_ISGID)
-- inode->i_mode |= S_ISGID;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_entry (handle, dentry, inode);
- if (err) {
-@@ -2068,7 +2065,7 @@
- goto out_stop;
-
- if (l > sizeof (EXT3_I(inode)->i_data)) {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext3_symlink_inode_operations;
- if (ext3_should_writeback_data(inode))
- inode->i_mapping->a_ops = &ext3_writeback_aops;
- else
-@@ -2284,4 +2281,17 @@
- .rmdir = ext3_rmdir,
- .mknod = ext3_mknod,
- .rename = ext3_rename,
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
- };
-+
-+struct inode_operations ext3_special_inode_operations = {
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
-+};
-+
-+
-diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
---- a/fs/ext3/super.c Sat Jan 4 18:24:12 2003
-+++ b/fs/ext3/super.c Sat Jan 4 18:24:12 2003
-@@ -30,6 +30,7 @@
- #include <linux/smp_lock.h>
- #include <linux/buffer_head.h>
- #include <asm/uaccess.h>
-+#include "xattr.h"
-
- #ifdef CONFIG_JBD_DEBUG
- static int ext3_ro_after; /* Make fs read-only after this many jiffies */
-@@ -405,6 +406,7 @@
- struct ext3_super_block *es = sbi->s_es;
- int i;
-
-+ ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
- EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-@@ -554,6 +556,7 @@
- int is_remount)
- {
- unsigned long *mount_options = &sbi->s_mount_opt;
-+
- uid_t *resuid = &sbi->s_resuid;
- gid_t *resgid = &sbi->s_resgid;
- char * this_char;
-@@ -566,6 +569,13 @@
- continue;
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT3_FS_XATTR
-+ if (!strcmp (this_char, "user_xattr"))
-+ set_opt (*mount_options, XATTR_USER);
-+ else if (!strcmp (this_char, "nouser_xattr"))
-+ clear_opt (*mount_options, XATTR_USER);
-+ else
-+#endif
- if (!strcmp (this_char, "bsddf"))
- clear_opt (*mount_options, MINIX_DF);
- else if (!strcmp (this_char, "nouid32")) {
-@@ -982,6 +992,12 @@
- sbi->s_mount_opt = 0;
- sbi->s_resuid = EXT3_DEF_RESUID;
- sbi->s_resgid = EXT3_DEF_RESGID;
-+
-+ /* Default extended attribute flags */
-+#ifdef CONFIG_EXT3_FS_XATTR
-+ set_opt(sbi->s_mount_opt, XATTR_USER);
-+#endif
-+
- if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0))
- goto out_fail;
-
-@@ -1820,7 +1836,10 @@
-
- static int __init init_ext3_fs(void)
- {
-- int err = init_inodecache();
-+ int err = init_ext3_xattr();
-+ if (err)
-+ return err;
-+ err = init_inodecache();
- if (err)
- goto out1;
- err = register_filesystem(&ext3_fs_type);
-@@ -1830,6 +1849,7 @@
- out:
- destroy_inodecache();
- out1:
-+ exit_ext3_xattr();
- return err;
- }
-
-@@ -1837,6 +1857,7 @@
- {
- unregister_filesystem(&ext3_fs_type);
- destroy_inodecache();
-+ exit_ext3_xattr();
- }
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
-diff -Nru a/fs/ext3/symlink.c b/fs/ext3/symlink.c
---- a/fs/ext3/symlink.c Sat Jan 4 18:24:12 2003
-+++ b/fs/ext3/symlink.c Sat Jan 4 18:24:12 2003
-@@ -20,6 +20,7 @@
- #include <linux/fs.h>
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
-+#include "xattr.h"
-
- static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-@@ -33,7 +34,20 @@
- return vfs_follow_link(nd, (char*)ei->i_data);
- }
-
-+struct inode_operations ext3_symlink_inode_operations = {
-+ .readlink = page_readlink,
-+ .follow_link = page_follow_link,
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
-+};
-+
- struct inode_operations ext3_fast_symlink_inode_operations = {
-- .readlink = ext3_readlink, /* BKL not held. Don't need */
-+ .readlink = ext3_readlink, /* BKL not held. Don't need */
- .follow_link = ext3_follow_link, /* BKL not held. Don't need */
-+ .setxattr = ext3_setxattr,
-+ .getxattr = ext3_getxattr,
-+ .listxattr = ext3_listxattr,
-+ .removexattr = ext3_removexattr,
- };
-diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/ext3/xattr.c Sat Jan 4 18:24:12 2003
-@@ -0,0 +1,1131 @@
-+/*
-+ * linux/fs/ext3/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
-+ * Extended attributes for symlinks and special files added per
-+ * suggestion of Luka Renko <luka.renko@hermes.si>.
-+ */
-+
-+/*
-+ * Extended attributes are stored on disk blocks allocated outside of
-+ * any inode. The i_file_acl field is then made to point to this allocated
-+ * block. If all extended attributes of an inode are identical, these
-+ * inodes may share the same extended attribute block. Such situations
-+ * are automatically detected by keeping a cache of recent attribute block
-+ * numbers and hashes over the block's contents in memory.
-+ *
-+ *
-+ * Extended attribute block layout:
-+ *
-+ * +------------------+
-+ * | header |
-+ * ¦ entry 1 | |
-+ * | entry 2 | | growing downwards
-+ * | entry 3 | v
-+ * | four null bytes |
-+ * | . . . |
-+ * | value 1 | ^
-+ * | value 3 | | growing upwards
-+ * | value 2 | |
-+ * +------------------+
-+ *
-+ * The block header is followed by multiple entry descriptors. These entry
-+ * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
-+ * byte boundaries. The entry descriptors are sorted by attribute name,
-+ * so that two extended attribute blocks can be compared efficiently.
-+ *
-+ * Attribute values are aligned to the end of the block, stored in
-+ * no specific order. They are also padded to EXT3_XATTR_PAD byte
-+ * boundaries. No additional gaps are left between them.
-+ *
-+ * Locking strategy
-+ * ----------------
-+ * The VFS holdsinode->i_sem semaphore when any of the xattr inode
-+ * operations are called, so we are guaranteed that only one
-+ * processes accesses extended attributes of an inode at any time.
-+ *
-+ * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
-+ * only a single process is modifying an extended attribute block, even
-+ * if the block is shared among inodes.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/mbcache.h>
-+#include <linux/module.h>
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include "xattr.h"
-+
-+#define EXT3_EA_USER "user."
-+
-+#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT3_XATTR_DEBUG
-+# define ea_idebug(inode, f...) do { \
-+ printk(KERN_DEBUG "inode %s:%ld: ", \
-+ kdevname(inode->i_dev), inode->i_ino); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+# define ea_bdebug(bh, f...) do { \
-+ printk(KERN_DEBUG "block %s:%ld: ", \
-+ kdevname(bh->b_dev), bh->b_blocknr); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+#else
-+# define ea_idebug(f...)
-+# define ea_bdebug(f...)
-+#endif
-+
-+static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
-+ struct ext3_xattr_header *);
-+
-+static int ext3_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext3_xattr_cache_find(struct inode *,
-+ struct ext3_xattr_header *);
-+static void ext3_xattr_cache_remove(struct buffer_head *);
-+static void ext3_xattr_rehash(struct ext3_xattr_header *,
-+ struct ext3_xattr_entry *);
-+
-+static struct mb_cache *ext3_xattr_cache;
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext3_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+static DECLARE_MUTEX(ext3_xattr_sem);
-+static struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
-+static rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ if (!ext3_xattr_handlers[name_index-1]) {
-+ ext3_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext3_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ ext3_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext3_handler_lock);
-+ }
-+}
-+
-+static inline const char *
-+strcmp_prefix(const char *a, const char *a_prefix)
-+{
-+ while (*a_prefix && *a == *a_prefix) {
-+ a++;
-+ a_prefix++;
-+ }
-+ return *a_prefix ? NULL : a;
-+}
-+
-+/*
-+ * Decode the extended attribute name, and translate it into
-+ * the name_index and name suffix.
-+ */
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_resolve_name(const char **name)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext3_handler_lock);
-+ for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
-+ if (ext3_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext3_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext3_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext3_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_handler(int name_index)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ read_lock(&ext3_handler_lock);
-+ handler = ext3_xattr_handlers[name_index-1];
-+ read_unlock(&ext3_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+ssize_t
-+ext3_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -EOPNOTSUPP;
-+ return handler->get(inode, name, buffer, size);
-+}
-+
-+/*
-+ * Inode operation listxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+ssize_t
-+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext3_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+int
-+ext3_setxattr(struct dentry *dentry, const char *name,
-+ void *value, size_t size, int flags)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -EOPNOTSUPP;
-+ return handler->set(inode, name, value, size, flags);
-+}
-+
-+/*
-+ * Inode operation removexattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ */
-+int
-+ext3_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -EOPNOTSUPP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext3_xattr_get()
-+ *
-+ * Copy an extended attribute into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size;
-+ char *end;
-+ int name_len, error;
-+
-+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
-+ name_index, name, buffer, (long)buffer_size);
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return -ENODATA;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* find named attribute */
-+ name_len = strlen(name);
-+
-+ error = -ERANGE;
-+ if (name_len > 255)
-+ goto cleanup;
-+ entry = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0)
-+ goto found;
-+ entry = next;
-+ }
-+ /* Check the remaining name entries */
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ error = -ENODATA;
-+ goto cleanup;
-+found:
-+ /* check the buffer size */
-+ if (entry->e_value_block != 0)
-+ goto bad_block;
-+ size = le32_to_cpu(entry->e_value_size);
-+ if (size > inode->i_sb->s_blocksize ||
-+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
-+ goto bad_block;
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (buffer) {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ /* return value of attribute */
-+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
-+ size);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size = 0;
-+ char *buf, *end;
-+ int error;
-+
-+ ea_idebug(inode, "buffer=%p, buffer_size=%ld",
-+ buffer, (long)buffer_size);
-+
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* compute the size required for the list of attribute names */
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len) + 1;
-+ }
-+ }
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (!buffer) {
-+ error = size;
-+ goto cleanup;
-+ } else {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ }
-+
-+ /* list the attribute names */
-+ buf = buffer;
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ *buf++ = '\0';
-+ }
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext3_xattr_update_super_block(handle_t *handle,
-+ struct super_block *sb)
-+{
-+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+ ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-+ EXT3_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext3_xattr_set()
-+ *
-+ * Create, replace or remove an extended attribute for this inode. Buffer
-+ * is NULL to remove an existing extended attribute, and non-NULL to
-+ * either replace an existing extended attribute, or create a new extended
-+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
-+ * specify that an extended attribute must exist and must not exist
-+ * previous to the call, respectively.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t value_len, int flags)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_header *header = NULL;
-+ struct ext3_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int min_offs = sb->s_blocksize, not_found = 1, free, error;
-+ char *end;
-+
-+ /*
-+ * header -- Points either into bh, or to a temporarily
-+ * allocated buffer.
-+ * here -- The named entry found, or the place for inserting, within
-+ * the block pointed to by header.
-+ * last -- Points right after the last named entry within the block
-+ * pointed to by header.
-+ * min_offs -- The offset of the first value (values are aligned
-+ * towards the end of the block).
-+ * end -- Points right after the block pointed to by header.
-+ */
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+ return -EPERM;
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > sb->s_blocksize)
-+ return -ERANGE;
-+ down(&ext3_xattr_sem);
-+
-+ if (EXT3_I(inode)->i_file_acl) {
-+ /* The inode already has an extended attribute block. */
-+ int block = EXT3_I(inode)->i_file_acl;
-+
-+ bh = sb_bread(sb, block);
-+ error = -EIO;
-+ if (!bh)
-+ goto cleanup;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)),
-+ le32_to_cpu(HDR(bh)->h_refcount));
-+ header = HDR(bh);
-+ end = bh->b_data + bh->b_size;
-+ if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(sb, "ext3_xattr_set",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* Find the named attribute. */
-+ here = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(here)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!here->e_value_block && here->e_value_size) {
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ not_found = name_index - here->e_name_index;
-+ if (!not_found)
-+ not_found = name_len - here->e_name_len;
-+ if (!not_found)
-+ not_found = memcmp(name, here->e_name,name_len);
-+ if (not_found <= 0)
-+ break;
-+ here = next;
-+ }
-+ last = here;
-+ /* We still need to compute min_offs and last. */
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!last->e_value_block && last->e_value_size) {
-+ int offs = le16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ last = next;
-+ }
-+
-+ /* Check whether we have enough space left. */
-+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
-+ } else {
-+ /* We will use a new extended attribute block. */
-+ free = sb->s_blocksize -
-+ sizeof(struct ext3_xattr_header) - sizeof(__u32);
-+ here = last = NULL; /* avoid gcc uninitialized warning. */
-+ }
-+
-+ if (not_found) {
-+ /* Request to remove a nonexistent attribute? */
-+ error = -ENODATA;
-+ if (flags & XATTR_REPLACE)
-+ goto cleanup;
-+ error = 0;
-+ if (value == NULL)
-+ goto cleanup;
-+ else
-+ free -= EXT3_XATTR_LEN(name_len);
-+ } else {
-+ /* Request to create an existing attribute? */
-+ error = -EEXIST;
-+ if (flags & XATTR_CREATE)
-+ goto cleanup;
-+ if (!here->e_value_block && here->e_value_size) {
-+ unsigned int size = le32_to_cpu(here->e_value_size);
-+
-+ if (le16_to_cpu(here->e_value_offs) + size >
-+ sb->s_blocksize || size > sb->s_blocksize)
-+ goto bad_block;
-+ free += EXT3_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT3_XATTR_SIZE(value_len);
-+ error = -ENOSPC;
-+ if (free < 0)
-+ goto cleanup;
-+
-+ /* Here we know that we can set the new attribute. */
-+
-+ if (header) {
-+ if (header->h_refcount == cpu_to_le32(1)) {
-+ ea_bdebug(bh, "modifying in-place");
-+ ext3_xattr_cache_remove(bh);
-+ error = ext3_journal_get_write_access(handle, bh);
-+ if (error)
-+ goto cleanup;
-+ } else {
-+ int offset;
-+
-+ ea_bdebug(bh, "cloning");
-+ header = kmalloc(bh->b_size, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memcpy(header, HDR(bh), bh->b_size);
-+ header->h_refcount = cpu_to_le32(1);
-+ offset = (char *)header - bh->b_data;
-+ here = ENTRY((char *)here + offset);
-+ last = ENTRY((char *)last + offset);
-+ }
-+ } else {
-+ /* Allocate a buffer where we construct the new block. */
-+ header = kmalloc(sb->s_blocksize, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memset(header, 0, sb->s_blocksize);
-+ end = (char *)header + sb->s_blocksize;
-+ header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
-+ header->h_blocks = header->h_refcount = cpu_to_le32(1);
-+ last = here = ENTRY(header+1);
-+ }
-+
-+ if (not_found) {
-+ /* Insert the new name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ int rest = (char *)last - (char *)here;
-+ memmove((char *)here + size, here, rest);
-+ memset(here, 0, size);
-+ here->e_name_index = name_index;
-+ here->e_name_len = name_len;
-+ memcpy(here->e_name, name, name_len);
-+ } else {
-+ /* Remove the old value. */
-+ if (!here->e_value_block && here->e_value_size) {
-+ char *first_val = (char *)header + min_offs;
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ char *val = (char *)header + offs;
-+ size_t size = EXT3_XATTR_SIZE(
-+ le32_to_cpu(here->e_value_size));
-+ memmove(first_val + size, first_val, val - first_val);
-+ memset(first_val, 0, size);
-+ here->e_value_offs = 0;
-+ min_offs += size;
-+
-+ /* Adjust all value offsets. */
-+ last = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(last)) {
-+ int o = le16_to_cpu(last->e_value_offs);
-+ if (!last->e_value_block && o < offs)
-+ last->e_value_offs =
-+ cpu_to_le16(o + size);
-+ last = EXT3_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext3_xattr_set2(handle, inode, bh,NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ last = ENTRY((char *)last - size);
-+ memmove(here, (char*)here + size,
-+ (char*)last - (char*)here);
-+ memset(last, 0, size);
-+ }
-+ }
-+ }
-+
-+ if (value != NULL) {
-+ /* Insert the new value. */
-+ here->e_value_size = cpu_to_le32(value_len);
-+ if (value_len) {
-+ size_t size = EXT3_XATTR_SIZE(value_len);
-+ char *val = (char *)header + min_offs - size;
-+ here->e_value_offs =
-+ cpu_to_le16((char *)val - (char *)header);
-+ memset(val + size - EXT3_XATTR_PAD, 0,
-+ EXT3_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext3_xattr_rehash(header, here);
-+
-+ error = ext3_xattr_set2(handle, inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ up(&ext3_xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext3_xattr_set(): Update the file system.
-+ */
-+static int
-+ext3_xattr_set2(handle_t *handle, struct inode *inode,
-+ struct buffer_head *old_bh, struct ext3_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext3_xattr_cache_find(inode, header);
-+ if (new_bh) {
-+ /*
-+ * We found an identical block in the cache.
-+ * The old block will be released after updating
-+ * the inode.
-+ */
-+ ea_bdebug(old_bh, "reusing block %ld",
-+ new_bh->b_blocknr);
-+
-+ error = -EDQUOT;
-+ if (DQUOT_ALLOC_BLOCK(inode, 1))
-+ goto cleanup;
-+
-+ error = ext3_journal_get_write_access(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ HDR(new_bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
-+ ea_bdebug(new_bh, "refcount now=%d",
-+ le32_to_cpu(HDR(new_bh)->h_refcount));
-+ } else if (old_bh && header == HDR(old_bh)) {
-+ /* Keep this block. */
-+ new_bh = old_bh;
-+ ext3_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int block;
-+ int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-+ EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
-+
-+ block = ext3_new_block(handle, inode, goal, 0,
-+ 0, &error);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+getblk_failed:
-+ ext3_free_blocks(handle, inode, block, 1);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ error = ext3_journal_get_create_access(handle, new_bh);
-+ if (error) {
-+ unlock_buffer(new_bh);
-+ goto getblk_failed;
-+ }
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ set_buffer_uptodate(new_bh);
-+ unlock_buffer(new_bh);
-+ ext3_xattr_cache_insert(new_bh);
-+
-+ ext3_xattr_update_super_block(handle, sb);
-+ }
-+ error = ext3_journal_dirty_metadata(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ }
-+
-+ /* Update the inode. */
-+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ ext3_mark_inode_dirty(handle, inode);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+
-+ error = 0;
-+ if (old_bh && old_bh != new_bh) {
-+ /*
-+ * If there was an old block, and we are not still using it,
-+ * we now release the old block.
-+ */
-+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-+
-+ error = ext3_journal_get_write_access(handle, old_bh);
-+ if (error)
-+ goto cleanup;
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext3_free_blocks(handle, inode, old_bh->b_blocknr, 1);
-+
-+ /* ext3_forget() calls bforget() for us, but we
-+ let our caller release old_bh, so we need to
-+ duplicate the handle before. */
-+ get_bh(old_bh);
-+ ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ DQUOT_FREE_BLOCK(inode, 1);
-+ ext3_journal_dirty_metadata(handle, old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT3_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ down(&ext3_xattr_sem);
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
-+ "inode %ld: block %d read error", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ext3_journal_get_write_access(handle, bh);
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext3_xattr_cache_remove(bh);
-+ ext3_free_blocks(handle, inode, block, 1);
-+ ext3_forget(handle, 1, inode, bh, block);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ ext3_journal_dirty_metadata(handle, bh);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+ DQUOT_FREE_BLOCK(inode, 1);
-+ }
-+ EXT3_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ up(&ext3_xattr_sem);
-+}
-+
-+/*
-+ * ext3_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+ mb_cache_shrink(ext3_xattr_cache, sb->s_bdev);
-+}
-+
-+/*
-+ * ext3_xattr_cache_insert()
-+ *
-+ * Create a new entry in the extended attribute cache, and insert
-+ * it unless such an entry is already in the cache.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+static int
-+ext3_xattr_cache_insert(struct buffer_head *bh)
-+{
-+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
-+ struct mb_cache_entry *ce;
-+ int error;
-+
-+ ce = mb_cache_entry_alloc(ext3_xattr_cache);
-+ if (!ce)
-+ return -ENOMEM;
-+ error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, &hash);
-+ if (error) {
-+ mb_cache_entry_free(ce);
-+ if (error == -EBUSY) {
-+ ea_bdebug(bh, "already in cache (%d cache entries)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_cmp()
-+ *
-+ * Compare two extended attribute blocks for equality.
-+ *
-+ * Returns 0 if the blocks are equal, 1 if they differ, and
-+ * a negative error number on errors.
-+ */
-+static int
-+ext3_xattr_cmp(struct ext3_xattr_header *header1,
-+ struct ext3_xattr_header *header2)
-+{
-+ struct ext3_xattr_entry *entry1, *entry2;
-+
-+ entry1 = ENTRY(header1+1);
-+ entry2 = ENTRY(header2+1);
-+ while (!IS_LAST_ENTRY(entry1)) {
-+ if (IS_LAST_ENTRY(entry2))
-+ return 1;
-+ if (entry1->e_hash != entry2->e_hash ||
-+ entry1->e_name_len != entry2->e_name_len ||
-+ entry1->e_value_size != entry2->e_value_size ||
-+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
-+ return 1;
-+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
-+ return -EIO;
-+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
-+ (char *)header2 + le16_to_cpu(entry2->e_value_offs),
-+ le32_to_cpu(entry1->e_value_size)))
-+ return 1;
-+
-+ entry1 = EXT3_XATTR_NEXT(entry1);
-+ entry2 = EXT3_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext3_xattr_cache_find()
-+ *
-+ * Find an identical extended attribute block.
-+ *
-+ * Returns a pointer to the block found, or NULL if such a block was
-+ * not found or an error occurred.
-+ */
-+static struct buffer_head *
-+ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
-+{
-+ __u32 hash = le32_to_cpu(header->h_hash);
-+ struct mb_cache_entry *ce;
-+
-+ if (!header->h_hash)
-+ return NULL; /* never share */
-+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_bdev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, (unsigned long) ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT3_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",
-+ (unsigned long) ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT3_XATTR_REFCOUNT_MAX);
-+ } else if (!ext3_xattr_cmp(header, HDR(bh))) {
-+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
-+ mb_cache_entry_release(ce);
-+ return bh;
-+ }
-+ brelse(bh);
-+ ce = mb_cache_entry_find_next(ce, 0, inode->i_bdev, hash);
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * ext3_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext3_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_bdev,
-+ bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count)-1);
-+ mb_cache_entry_free(ce);
-+ } else
-+ ea_bdebug(bh, "no cache entry");
-+}
-+
-+#define NAME_HASH_SHIFT 5
-+#define VALUE_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ __u32 hash = 0;
-+ char *name = entry->e_name;
-+ int n;
-+
-+ for (n=0; n < entry->e_name_len; n++) {
-+ hash = (hash << NAME_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-+ *name++;
-+ }
-+
-+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-+ __u32 *value = (__u32 *)((char *)header +
-+ le16_to_cpu(entry->e_value_offs));
-+ for (n = (le32_to_cpu(entry->e_value_size) +
-+ EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
-+ hash = (hash << VALUE_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
-+ le32_to_cpu(*value++);
-+ }
-+ }
-+ entry->e_hash = cpu_to_le32(hash);
-+}
-+
-+#undef NAME_HASH_SHIFT
-+#undef VALUE_HASH_SHIFT
-+
-+#define BLOCK_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext3_xattr_rehash(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ struct ext3_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext3_xattr_hash_entry(header, entry);
-+ here = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(here)) {
-+ if (!here->e_hash) {
-+ /* Block is not shared if an entry's hash value == 0 */
-+ hash = 0;
-+ break;
-+ }
-+ hash = (hash << BLOCK_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
-+ le32_to_cpu(here->e_hash);
-+ here = EXT3_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+EXPORT_SYMBOL(ext3_xattr_get);
-+EXPORT_SYMBOL(ext3_xattr_set);
-+EXPORT_SYMBOL(ext3_bread);
-+
-+int __init
-+init_ext3_xattr(void)
-+{
-+ int err;
-+
-+ err = ext3_xattr_register(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
-+ if (err)
-+ return err;
-+ ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 6);
-+ if (!ext3_xattr_cache) {
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext3_xattr(void)
-+{
-+ if (ext3_xattr_cache)
-+ mb_cache_destroy(ext3_xattr_cache);
-+ ext3_xattr_cache = NULL;
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
-+}
-+
-diff -Nru a/fs/ext3/xattr.h b/fs/ext3/xattr.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/ext3/xattr.h Sat Jan 4 18:24:12 2003
-@@ -0,0 +1,133 @@
-+/*
-+ File: fs/ext3/xattr.h
-+
-+ On-disk format of extended attributes for the ext3 filesystem.
-+
-+ (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+#include <linux/config.h>
-+#include <linux/xattr.h>
-+
-+/* Magic value in attribute blocks */
-+#define EXT3_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT3_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT3_XATTR_INDEX_MAX 10
-+#define EXT3_XATTR_INDEX_USER 1
-+#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
-+#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+
-+struct ext3_xattr_header {
-+ __u32 h_magic; /* magic number for identification */
-+ __u32 h_refcount; /* reference count */
-+ __u32 h_blocks; /* number of disk blocks used */
-+ __u32 h_hash; /* hash value of all attributes */
-+ __u32 h_reserved[4]; /* zero right now */
-+};
-+
-+struct ext3_xattr_entry {
-+ __u8 e_name_len; /* length of name */
-+ __u8 e_name_index; /* attribute name index */
-+ __u16 e_value_offs; /* offset in disk block of value */
-+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */
-+ __u32 e_value_size; /* size of attribute value */
-+ __u32 e_hash; /* hash value of name and value */
-+ char e_name[0]; /* attribute name */
-+};
-+
-+#define EXT3_XATTR_PAD_BITS 2
-+#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
-+#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
-+#define EXT3_XATTR_LEN(name_len) \
-+ (((name_len) + EXT3_XATTR_ROUND + \
-+ sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
-+#define EXT3_XATTR_NEXT(entry) \
-+ ( (struct ext3_xattr_entry *)( \
-+ (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT3_XATTR_SIZE(size) \
-+ (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
-+
-+# ifdef CONFIG_EXT3_FS_XATTR
-+
-+struct ext3_xattr_handler {
-+ char *prefix;
-+ size_t (*list)(char *list, struct inode *inode, const char *name,
-+ int name_len);
-+ int (*get)(struct inode *inode, const char *name, void *buffer,
-+ size_t size);
-+ int (*set)(struct inode *inode, const char *name, const void *buffer,
-+ size_t size, int flags);
-+};
-+
-+extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
-+extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
-+
-+extern int ext3_setxattr(struct dentry *, const char *, void *, size_t, int);
-+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
-+extern int ext3_removexattr(struct dentry *, const char *);
-+
-+extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext3_xattr_list(struct inode *, char *, size_t);
-+extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
-+
-+extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
-+extern void ext3_xattr_put_super(struct super_block *);
-+
-+extern int init_ext3_xattr(void);
-+extern void exit_ext3_xattr(void);
-+
-+# else /* CONFIG_EXT3_FS_XATTR */
-+# define ext3_setxattr NULL
-+# define ext3_getxattr NULL
-+# define ext3_listxattr NULL
-+# define ext3_removexattr NULL
-+
-+static inline int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+ext3_xattr_list(struct inode *inode, void *buffer, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline void
-+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext3_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext3_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT3_FS_XATTR */
-+
-+extern struct ext3_xattr_handler ext3_xattr_user_handler;
-diff -Nru a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/ext3/xattr_user.c Sat Jan 4 18:24:12 2003
-@@ -0,0 +1,99 @@
-+/*
-+ * linux/fs/ext3/xattr_user.c
-+ * Handler for extended user attributes.
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/smp_lock.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include "xattr.h"
-+
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+# include <linux/ext3_acl.h>
-+#endif
-+
-+#define XATTR_USER_PREFIX "user."
-+
-+static size_t
-+ext3_xattr_user_list(char *list, struct inode *inode,
-+ const char *name, int name_len)
-+{
-+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
-+
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return 0;
-+
-+ if (list) {
-+ memcpy(list, XATTR_USER_PREFIX, prefix_len);
-+ memcpy(list+prefix_len, name, name_len);
-+ }
-+ return prefix_len + name_len;
-+}
-+
-+static int
-+ext3_xattr_user_get(struct inode *inode, const char *name,
-+ void *buffer, size_t size)
-+{
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -EOPNOTSUPP;
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+ error = ext3_permission_locked(inode, MAY_READ);
-+#else
-+ error = permission(inode, MAY_READ);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
-+ buffer, size);
-+}
-+
-+static int
-+ext3_xattr_user_set(struct inode *inode, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ handle_t *handle;
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -EOPNOTSUPP;
-+ if ( !S_ISREG(inode->i_mode) &&
-+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-+ return -EPERM;
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+ error = ext3_permission_locked(inode, MAY_WRITE);
-+#else
-+ error = permission(inode, MAY_WRITE);
-+#endif
-+ if (error)
-+ return error;
-+
-+ lock_kernel();
-+ handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+ error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
-+ value, size, flags);
-+ ext3_journal_stop(handle, inode);
-+ unlock_kernel();
-+
-+ return error;
-+}
-+
-+struct ext3_xattr_handler ext3_xattr_user_handler = {
-+ prefix: XATTR_USER_PREFIX,
-+ list: ext3_xattr_user_list,
-+ get: ext3_xattr_user_get,
-+ set: ext3_xattr_user_set,
-+};
-diff -Nru a/fs/mbcache.c b/fs/mbcache.c
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/fs/mbcache.c Sat Jan 4 18:24:12 2003
-@@ -0,0 +1,702 @@
-+/*
-+ * linux/fs/mbcache.c
-+ * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+/*
-+ * Filesystem Meta Information Block Cache (mbcache)
-+ *
-+ * The mbcache caches blocks of block devices that need to be located
-+ * by their device/block number, as well as by other criteria (such
-+ * as the block's contents).
-+ *
-+ * There can only be one cache entry in a cache per device and block number.
-+ * Additional indexes need not be unique in this sense. The number of
-+ * additional indexes (=other criteria) can be hardwired (at compile time)
-+ * or specified at cache create time.
-+ *
-+ * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
-+ * in the cache. A valid entry is in the main hash tables of the cache,
-+ * and may also be in the lru list. An invalid entry is not in any hashes
-+ * or lists.
-+ *
-+ * A valid cache entry is only in the lru list if no handles refer to it.
-+ * Invalid cache entries will be freed when the last handle to the cache
-+ * entry is released.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/hash.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <linux/mbcache.h>
-+
-+
-+#ifdef MB_CACHE_DEBUG
-+# define mb_debug(f...) do { \
-+ printk(KERN_DEBUG f); \
-+ printk("\n"); \
-+ } while (0)
-+#define mb_assert(c) do { if (!(c)) \
-+ printk(KERN_ERR "assertion " #c " failed\n"); \
-+ } while(0)
-+#else
-+# define mb_debug(f...) do { } while(0)
-+# define mb_assert(c) do { } while(0)
-+#endif
-+#define mb_error(f...) do { \
-+ printk(KERN_ERR f); \
-+ printk("\n"); \
-+ } while(0)
-+
-+MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
-+MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
-+MODULE_LICENSE("GPL");
-+
-+EXPORT_SYMBOL(mb_cache_create);
-+EXPORT_SYMBOL(mb_cache_shrink);
-+EXPORT_SYMBOL(mb_cache_destroy);
-+EXPORT_SYMBOL(mb_cache_entry_alloc);
-+EXPORT_SYMBOL(mb_cache_entry_insert);
-+EXPORT_SYMBOL(mb_cache_entry_release);
-+EXPORT_SYMBOL(mb_cache_entry_takeout);
-+EXPORT_SYMBOL(mb_cache_entry_free);
-+EXPORT_SYMBOL(mb_cache_entry_dup);
-+EXPORT_SYMBOL(mb_cache_entry_get);
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+EXPORT_SYMBOL(mb_cache_entry_find_first);
-+EXPORT_SYMBOL(mb_cache_entry_find_next);
-+#endif
-+
-+
-+/*
-+ * Global data: list of all mbcache's, lru list, and a spinlock for
-+ * accessing cache data structures on SMP machines. (The lru list is
-+ * global across all mbcaches.)
-+ */
-+
-+static LIST_HEAD(mb_cache_list);
-+static LIST_HEAD(mb_cache_lru_list);
-+static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
-+static struct shrinker *mb_shrinker;
-+
-+static inline int
-+mb_cache_indexes(struct mb_cache *cache)
-+{
-+#ifdef MB_CACHE_INDEXES_COUNT
-+ return MB_CACHE_INDEXES_COUNT;
-+#else
-+ return cache->c_indexes_count;
-+#endif
-+}
-+
-+/*
-+ * What the mbcache registers as to get shrunk dynamically.
-+ */
-+
-+static int mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask);
-+
-+static inline void
-+__mb_cache_entry_takeout_lru(struct mb_cache_entry *ce)
-+{
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_into_lru(struct mb_cache_entry *ce)
-+{
-+ list_add(&ce->e_lru_list, &mb_cache_lru_list);
-+}
-+
-+
-+static inline int
-+__mb_cache_entry_in_lru(struct mb_cache_entry *ce)
-+{
-+ return (!list_empty(&ce->e_lru_list));
-+}
-+
-+
-+/*
-+ * Insert the cache entry into all hashes.
-+ */
-+static inline void
-+__mb_cache_entry_link(struct mb_cache_entry *ce)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket;
-+ int n;
-+
-+ bucket = hash_long((unsigned long)ce->e_bdev +
-+ (ce->e_block & 0xffffff), cache->c_bucket_bits);
-+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
-+ for (n=0; n<mb_cache_indexes(cache); n++) {
-+ bucket = hash_long(ce->e_indexes[n].o_key,
-+ cache->c_bucket_bits);
-+ list_add(&ce->e_indexes[n].o_list,
-+ &cache->c_indexes_hash[n][bucket]);
-+ }
-+}
-+
-+
-+/*
-+ * Remove the cache entry from all hashes.
-+ */
-+static inline void
-+__mb_cache_entry_unlink(struct mb_cache_entry *ce)
-+{
-+ int n;
-+
-+ list_del_init(&ce->e_block_list);
-+ for (n = 0; n < mb_cache_indexes(ce->e_cache); n++)
-+ list_del(&ce->e_indexes[n].o_list);
-+}
-+
-+
-+static inline int
-+__mb_cache_entry_is_linked(struct mb_cache_entry *ce)
-+{
-+ return (!list_empty(&ce->e_block_list));
-+}
-+
-+
-+static inline struct mb_cache_entry *
-+__mb_cache_entry_read(struct mb_cache_entry *ce)
-+{
-+ __mb_cache_entry_takeout_lru(ce);
-+ atomic_inc(&ce->e_used);
-+ return ce;
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_forget(struct mb_cache_entry *ce)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+
-+ mb_assert(atomic_read(&ce->e_used) == 0);
-+ atomic_dec(&cache->c_entry_count);
-+ if (cache->c_op.free)
-+ cache->c_op.free(ce);
-+ kmem_cache_free(cache->c_entry_cache, ce);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
-+{
-+ if (atomic_dec_and_test(&ce->e_used)) {
-+ if (!__mb_cache_entry_is_linked(ce))
-+ goto forget;
-+ __mb_cache_entry_into_lru(ce);
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ return;
-+forget:
-+ spin_unlock(&mb_cache_spinlock);
-+ __mb_cache_entry_forget(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_shrink_fn() memory pressure callback
-+ *
-+ * This function is called by the kernel memory management when memory
-+ * gets low.
-+ *
-+ * @nr_to_scan: Number of objects to scan
-+ * @gfp_mask: (ignored)
-+ *
-+ * Returns the number of objects which are present in the cache.
-+ */
-+static int
-+mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l;
-+ int count = 0;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_prev(l, &mb_cache_list) {
-+ struct mb_cache *cache =
-+ list_entry(l, struct mb_cache, c_cache_list);
-+ mb_debug("cache %s (%d)", cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ count += atomic_read(&cache->c_entry_count);
-+ }
-+ mb_debug("trying to free %d entries", nr_to_scan);
-+ if (nr_to_scan == 0) {
-+ spin_unlock(&mb_cache_spinlock);
-+ goto out;
-+ }
-+ while (nr_to_scan && !list_empty(&mb_cache_lru_list)) {
-+ struct mb_cache_entry *ce =
-+ list_entry(mb_cache_lru_list.prev,
-+ struct mb_cache_entry, e_lru_list);
-+ list_move(&ce->e_lru_list, &free_list);
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ nr_to_scan--;
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ l = free_list.prev;
-+ while (l != &free_list) {
-+ struct mb_cache_entry *ce = list_entry(l,
-+ struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ __mb_cache_entry_forget(ce);
-+ count--;
-+ }
-+out:
-+ mb_debug("%d remaining entries ", count);
-+ return count;
-+}
-+
-+
-+/*
-+ * mb_cache_create() create a new cache
-+ *
-+ * All entries in one cache are equal size. Cache entries may be from
-+ * multiple devices. If this is the first mbcache created, registers
-+ * the cache with kernel memory management. Returns NULL if no more
-+ * memory was available.
-+ *
-+ * @name: name of the cache (informal)
-+ * @cache_op: contains the callback called when freeing a cache entry
-+ * @entry_size: The size of a cache entry, including
-+ * struct mb_cache_entry
-+ * @indexes_count: number of additional indexes in the cache. Must equal
-+ * MB_CACHE_INDEXES_COUNT if the number of indexes is
-+ * hardwired.
-+ * @bucket_bits: log2(number of hash buckets)
-+ */
-+struct mb_cache *
-+mb_cache_create(const char *name, struct mb_cache_op *cache_op,
-+ size_t entry_size, int indexes_count, int bucket_bits)
-+{
-+ int m=0, n, bucket_count = 1 << bucket_bits;
-+ struct mb_cache *cache = NULL;
-+
-+ if(entry_size < sizeof(struct mb_cache_entry) +
-+ indexes_count * sizeof(struct mb_cache_entry_index))
-+ return NULL;
-+
-+ cache = kmalloc(sizeof(struct mb_cache) +
-+ indexes_count * sizeof(struct list_head), GFP_KERNEL);
-+ if (!cache)
-+ goto fail;
-+ cache->c_name = name;
-+ if (cache_op)
-+ cache->c_op.free = cache_op->free;
-+ else
-+ cache->c_op.free = NULL;
-+ atomic_set(&cache->c_entry_count, 0);
-+ cache->c_bucket_bits = bucket_bits;
-+#ifdef MB_CACHE_INDEXES_COUNT
-+ mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
-+#else
-+ cache->c_indexes_count = indexes_count;
-+#endif
-+ cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
-+ GFP_KERNEL);
-+ if (!cache->c_block_hash)
-+ goto fail;
-+ for (n=0; n<bucket_count; n++)
-+ INIT_LIST_HEAD(&cache->c_block_hash[n]);
-+ for (m=0; m<indexes_count; m++) {
-+ cache->c_indexes_hash[m] = kmalloc(bucket_count *
-+ sizeof(struct list_head),
-+ GFP_KERNEL);
-+ if (!cache->c_indexes_hash[m])
-+ goto fail;
-+ for (n=0; n<bucket_count; n++)
-+ INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
-+ }
-+ cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
-+ 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
-+ if (!cache->c_entry_cache)
-+ goto fail;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ if (list_empty(&mb_cache_list)) {
-+ if (mb_shrinker) {
-+ printk(KERN_ERR "%s: already have a shrinker!\n",
-+ __FUNCTION__);
-+ remove_shrinker(mb_shrinker);
-+ }
-+ mb_shrinker = set_shrinker(DEFAULT_SEEKS, mb_cache_shrink_fn);
-+ }
-+ list_add(&cache->c_cache_list, &mb_cache_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ return cache;
-+
-+fail:
-+ if (cache) {
-+ while (--m >= 0)
-+ kfree(cache->c_indexes_hash[m]);
-+ if (cache->c_block_hash)
-+ kfree(cache->c_block_hash);
-+ kfree(cache);
-+ }
-+ return NULL;
-+}
-+
-+
-+/*
-+ * mb_cache_shrink()
-+ *
-+ * Removes all cache entires of a device from the cache. All cache entries
-+ * currently in use cannot be freed, and thus remain in the cache. All others
-+ * are freed.
-+ *
-+ * @cache: which cache to shrink
-+ * @bdev: which device's cache entries to shrink
-+ */
-+void
-+mb_cache_shrink(struct mb_cache *cache, struct block_device *bdev)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ l = mb_cache_lru_list.prev;
-+ while (l != &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ if (ce->e_bdev == bdev) {
-+ list_move(&ce->e_lru_list, &free_list);
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ l = free_list.prev;
-+ while (l != &free_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ __mb_cache_entry_forget(ce);
-+ }
-+}
-+
-+
-+/*
-+ * mb_cache_destroy()
-+ *
-+ * Shrinks the cache to its minimum possible size (hopefully 0 entries),
-+ * and then destroys it. If this was the last mbcache, un-registers the
-+ * mbcache from kernel memory management.
-+ */
-+void
-+mb_cache_destroy(struct mb_cache *cache)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l;
-+ int n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ l = mb_cache_lru_list.prev;
-+ while (l != &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ if (ce->e_cache == cache) {
-+ list_move(&ce->e_lru_list, &free_list);
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ }
-+ }
-+ list_del(&cache->c_cache_list);
-+ if (list_empty(&mb_cache_list) && mb_shrinker) {
-+ remove_shrinker(mb_shrinker);
-+ mb_shrinker = 0;
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+
-+ l = free_list.prev;
-+ while (l != &free_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ l = l->prev;
-+ __mb_cache_entry_forget(ce);
-+ }
-+
-+ if (atomic_read(&cache->c_entry_count) > 0) {
-+ mb_error("cache %s: %d orphaned entries",
-+ cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ }
-+
-+ kmem_cache_destroy(cache->c_entry_cache);
-+
-+ for (n=0; n < mb_cache_indexes(cache); n++)
-+ kfree(cache->c_indexes_hash[n]);
-+ kfree(cache->c_block_hash);
-+
-+ kfree(cache);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_alloc()
-+ *
-+ * Allocates a new cache entry. The new entry will not be valid initially,
-+ * and thus cannot be looked up yet. It should be filled with data, and
-+ * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
-+ * if no more memory was available.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_alloc(struct mb_cache *cache)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ atomic_inc(&cache->c_entry_count);
-+ ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
-+ if (ce) {
-+ INIT_LIST_HEAD(&ce->e_lru_list);
-+ INIT_LIST_HEAD(&ce->e_block_list);
-+ ce->e_cache = cache;
-+ atomic_set(&ce->e_used, 1);
-+ }
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_insert()
-+ *
-+ * Inserts an entry that was allocated using mb_cache_entry_alloc() into
-+ * the cache. After this, the cache entry can be looked up, but is not yet
-+ * in the lru list as the caller still holds a handle to it. Returns 0 on
-+ * success, or -EBUSY if a cache entry for that device + inode exists
-+ * already (this may happen after a failed lookup, but when another process
-+ * has inserted the same cache entry in the meantime).
-+ *
-+ * @bdev: device the cache entry belongs to
-+ * @block: block number
-+ * @keys: array of additional keys. There must be indexes_count entries
-+ * in the array (as specified when creating the cache).
-+ */
-+int
-+mb_cache_entry_insert(struct mb_cache_entry *ce, struct block_device *bdev,
-+ sector_t block, unsigned int keys[])
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket;
-+ struct list_head *l;
-+ int error = -EBUSY, n;
-+
-+ bucket = hash_long((unsigned long)bdev + (block & 0xffffffff),
-+ cache->c_bucket_bits);
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_prev(l, &cache->c_block_hash[bucket]) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_bdev == bdev && ce->e_block == block)
-+ goto out;
-+ }
-+ mb_assert(!__mb_cache_entry_is_linked(ce));
-+ ce->e_bdev = bdev;
-+ ce->e_block = block;
-+ for (n=0; n<mb_cache_indexes(cache); n++)
-+ ce->e_indexes[n].o_key = keys[n];
-+ __mb_cache_entry_link(ce);
-+out:
-+ spin_unlock(&mb_cache_spinlock);
-+ return error;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_release()
-+ *
-+ * Release a handle to a cache entry. When the last handle to a cache entry
-+ * is released it is either freed (if it is invalid) or otherwise inserted
-+ * in to the lru list.
-+ */
-+void
-+mb_cache_entry_release(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ __mb_cache_entry_release_unlock(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_takeout()
-+ *
-+ * Take a cache entry out of the cache, making it invalid. The entry can later
-+ * be re-inserted using mb_cache_entry_insert(), or released using
-+ * mb_cache_entry_release().
-+ */
-+void
-+mb_cache_entry_takeout(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ mb_assert(!__mb_cache_entry_in_lru(ce));
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ spin_unlock(&mb_cache_spinlock);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_free()
-+ *
-+ * This is equivalent to the sequence mb_cache_entry_takeout() --
-+ * mb_cache_entry_release().
-+ */
-+void
-+mb_cache_entry_free(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ mb_assert(!__mb_cache_entry_in_lru(ce));
-+ if (__mb_cache_entry_is_linked(ce))
-+ __mb_cache_entry_unlink(ce);
-+ __mb_cache_entry_release_unlock(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_dup()
-+ *
-+ * Duplicate a handle to a cache entry (does not duplicate the cache entry
-+ * itself). After the call, both the old and the new handle must be released.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_dup(struct mb_cache_entry *ce)
-+{
-+ atomic_inc(&ce->e_used);
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_get()
-+ *
-+ * Get a cache entry by device / block number. (There can only be one entry
-+ * in the cache per device and block.) Returns NULL if no such cache entry
-+ * exists.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_get(struct mb_cache *cache, struct block_device *bdev,
-+ sector_t block)
-+{
-+ unsigned int bucket;
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ bucket = hash_long((unsigned long)bdev + (block & 0xffffffff),
-+ cache->c_bucket_bits);
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(l, &cache->c_block_hash[bucket]) {
-+ ce = list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_bdev == bdev && ce->e_block == block) {
-+ ce = __mb_cache_entry_read(ce);
-+ goto cleanup;
-+ }
-+ }
-+ ce = NULL;
-+
-+cleanup:
-+ spin_unlock(&mb_cache_spinlock);
-+ return ce;
-+}
-+
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+
-+static struct mb_cache_entry *
-+__mb_cache_entry_find(struct list_head *l, struct list_head *head,
-+ int index, struct block_device *bdev, unsigned int key)
-+{
-+ while (l != head) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry,
-+ e_indexes[index].o_list);
-+ if (ce->e_bdev == bdev &&
-+ ce->e_indexes[index].o_key == key) {
-+ ce = __mb_cache_entry_read(ce);
-+ if (ce)
-+ return ce;
-+ }
-+ l = l->next;
-+ }
-+ return NULL;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_find_first()
-+ *
-+ * Find the first cache entry on a given device with a certain key in
-+ * an additional index. Additonal matches can be found with
-+ * mb_cache_entry_find_next(). Returns NULL if no match was found.
-+ *
-+ * @cache: the cache to search
-+ * @index: the number of the additonal index to search (0<=index<indexes_count)
-+ * @bdev: the device the cache entry should belong to
-+ * @key: the key in the index
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_find_first(struct mb_cache *cache, int index,
-+ struct block_device *bdev, unsigned int key)
-+{
-+ unsigned int bucket = hash_long(key, cache->c_bucket_bits);
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ mb_assert(index < mb_cache_indexes(cache));
-+ spin_lock(&mb_cache_spinlock);
-+ l = cache->c_indexes_hash[index][bucket].next;
-+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
-+ index, bdev, key);
-+ spin_unlock(&mb_cache_spinlock);
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_find_next()
-+ *
-+ * Find the next cache entry on a given device with a certain key in an
-+ * additional index. Returns NULL if no match could be found. The previous
-+ * entry is atomatically released, so that mb_cache_entry_find_next() can
-+ * be called like this:
-+ *
-+ * entry = mb_cache_entry_find_first();
-+ * while (entry) {
-+ * ...
-+ * entry = mb_cache_entry_find_next(entry, ...);
-+ * }
-+ *
-+ * @prev: The previous match
-+ * @index: the number of the additonal index to search (0<=index<indexes_count)
-+ * @bdev: the device the cache entry should belong to
-+ * @key: the key in the index
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_find_next(struct mb_cache_entry *prev, int index,
-+ struct block_device *bdev, unsigned int key)
-+{
-+ struct mb_cache *cache = prev->e_cache;
-+ unsigned int bucket = hash_long(key, cache->c_bucket_bits);
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ mb_assert(index < mb_cache_indexes(cache));
-+ spin_lock(&mb_cache_spinlock);
-+ l = prev->e_indexes[index].o_list.next;
-+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
-+ index, bdev, key);
-+ __mb_cache_entry_release_unlock(prev);
-+ return ce;
-+}
-+
-+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
-diff -Nru a/fs/namei.c b/fs/namei.c
---- a/fs/namei.c Sat Jan 4 18:24:12 2003
-+++ b/fs/namei.c Sat Jan 4 18:24:12 2003
-@@ -108,6 +108,14 @@
- * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
- * PATH_MAX includes the nul terminator --RR.
- */
-+
-+void intent_release(struct dentry *de, struct lookup_intent *it)
-+{
-+ if (it && de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de, it);
-+
-+}
-+
- static inline int do_getname(const char *filename, char *page)
- {
- int retval;
-@@ -265,6 +273,9 @@
-
- void path_release(struct nameidata *nd)
- {
-+ if (&nd->it && nd->dentry && nd->dentry->d_op &&
-+ nd->dentry->d_op->d_intent_release)
-+ nd->dentry->d_op->d_intent_release(nd->dentry, &nd->it);
- dput(nd->dentry);
- mntput(nd->mnt);
- }
-@@ -273,10 +284,18 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -351,7 +370,7 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -369,7 +388,10 @@
- struct dentry * dentry = d_alloc(parent, name);
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
-- result = dir->i_op->lookup(dir, dentry);
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
-+ result = dir->i_op->lookup(dir, dentry);
- if (result)
- dput(dentry);
- else {
-@@ -391,6 +413,12 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -402,7 +430,7 @@
- * 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)
- {
- int err = -ELOOP;
- if (current->link_count >= 5)
-@@ -419,10 +447,15 @@
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2) {
-+ err = dentry->d_inode->i_op->follow_link2(dentry, nd);
-+ }
-+ else
-+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-+ intent_release(dentry, &nd->it);
- path_release(nd);
- return err;
- }
-@@ -523,6 +556,8 @@
-
- if (!dentry)
- goto dcache_miss;
-+ if (dentry->d_op && dentry->d_op->d_revalidate2)
-+ goto need_revalidate2;
- if (dentry->d_op && dentry->d_op->d_revalidate)
- goto need_revalidate;
- done:
-@@ -534,7 +569,12 @@
- unlock_nd(nd);
-
- need_lookup:
-- dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
-+ if (nd->it.it_op == 0){
-+ dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE, NULL);
-+ }
-+ else{
-+ dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE, &nd->it);
-+ }
- if (IS_ERR(dentry))
- goto fail;
- mntget(mnt);
-@@ -546,6 +586,18 @@
- lock_nd(nd);
- goto done;
-
-+need_revalidate2:
-+ mntget(mnt);
-+ dget_locked(dentry);
-+ unlock_nd(nd);
-+ if (dentry->d_op->d_revalidate2(dentry, flags, &nd->it))
-+ goto relock;
-+ if (d_invalidate(dentry))
-+ goto relock;
-+ dput(dentry);
-+ mntput(mnt);
-+ goto need_lookup;
-+
- need_revalidate:
- mntget(mnt);
- dget_locked(dentry);
-@@ -577,6 +629,7 @@
- struct inode *inode;
- int err;
- unsigned int lookup_flags = nd->flags;
-+ int save_it_op = nd->it.it_op;
-
- while (*name=='/')
- name++;
-@@ -648,6 +701,7 @@
- break;
- }
- /* This does the actual lookups.. */
-+ nd->it.it_op = 0;
- err = do_lookup(nd, &this, &next, &pinned, LOOKUP_CONTINUE);
- if (err)
- break;
-@@ -662,7 +716,7 @@
- if (!inode->i_op)
- break;
-
-- if (inode->i_op->follow_link) {
-+ if (inode->i_op->follow_link || inode->i_op->follow_link2) {
- mntget(next.mnt);
- dget_locked(next.dentry);
- unlock_nd(nd);
-@@ -684,7 +738,7 @@
- nd->dentry = next.dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -692,6 +746,7 @@
- last_with_slashes:
- lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
- last_component:
-+ nd->it.it_op = save_it_op;
- if (lookup_flags & LOOKUP_PARENT)
- goto lookup_parent;
- if (this.name[0] == '.') switch (this.len) {
-@@ -717,7 +772,8 @@
- follow_mount(&next.mnt, &next.dentry);
- inode = next.dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
-- && inode && inode->i_op && inode->i_op->follow_link) {
-+ && inode && inode->i_op &&
-+ (inode->i_op->follow_link || inode->i_op->follow_link2)) {
- mntget(next.mnt);
- dget_locked(next.dentry);
- unlock_nd(nd);
-@@ -737,7 +793,8 @@
- break;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op ||
-+ (!inode->i_op->lookup && !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -886,7 +943,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -909,13 +967,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
-- dentry = inode->i_op->lookup(inode, new);
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
-+ dentry = inode->i_op->lookup(inode, new);
- if (!dentry) {
- dentry = new;
- security_ops->inode_post_lookup(inode, dentry);
-@@ -927,7 +988,7 @@
- }
-
- /* SMP-safe */
--struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, int len, struct lookup_intent *it)
- {
- unsigned long hash;
- struct qstr this;
-@@ -947,11 +1008,16 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash(&this, base, it);
- access:
- return ERR_PTR(-EACCES);
- }
-
-+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+{
-+ return lookup_one_len_it(name, base, len, NULL);
-+}
-+
- /*
- * namei()
- *
-@@ -1268,7 +1334,9 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ nd->it.it_op |= IT_CREAT;
-+ nd->it.it_mode = mode;
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1277,6 +1345,7 @@
- goto exit;
- }
-
-+ nd->it.it_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- error = vfs_create(dir->d_inode, dentry,
-@@ -1310,7 +1379,8 @@
- error = -ENOENT;
- if (!dentry->d_inode)
- goto exit_dput;
-- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
-+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
-+ dentry->d_inode->i_op->follow_link2))
- goto do_link;
-
- dput(nd->dentry);
-@@ -1325,8 +1395,10 @@
- return 0;
-
- exit_dput:
-+ intent_release(dentry, &nd->it);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry, &nd->it);
- path_release(nd);
- return error;
-
-@@ -1348,7 +1420,12 @@
- if (error)
- goto exit_dput;
- UPDATE_ATIME(dentry->d_inode);
-- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if(dentry->d_inode->i_op->follow_link2)
-+ error = dentry->d_inode->i_op->follow_link2(dentry, nd);
-+ else
-+ error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(dentry, &nd->it);
- dput(dentry);
- if (error)
- return error;
-@@ -1370,7 +1447,7 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
- putname(nd->last.name);
- goto do_last;
- }
-@@ -1384,7 +1461,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1429,6 +1506,7 @@
- char * tmp;
- struct dentry * dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1436,9 +1514,14 @@
- if (IS_ERR(tmp))
- return PTR_ERR(tmp);
-
-+ nd.it = it;
-+ nd.it.it_mode = 0;
-+ nd.it.it_op = IT_LOOKUP;
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-+
-+ nd.it = it;
- dentry = lookup_create(&nd, 0);
- error = PTR_ERR(dentry);
-
-@@ -1457,6 +1540,7 @@
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry, &nd.it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1495,6 +1579,7 @@
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1502,14 +1587,19 @@
- struct dentry *dentry;
- struct nameidata nd;
-
-+ nd.it = it;
-+ nd.it.it_mode = 0;
-+ nd.it.it_op = IT_LOOKUP;
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-+ nd.it = it;
- dentry = lookup_create(&nd, 1);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
- mode & ~current->fs->umask);
-+ intent_release(dentry, &nd.it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1593,11 +1683,14 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_RMDIR };
-
- name = getname(pathname);
- if(IS_ERR(name))
- return PTR_ERR(name);
--
-+
-+ nd.it = it;
-+ nd.it.it_op = IT_LOOKUP;
- error = path_lookup(name, LOOKUP_PARENT, &nd);
- if (error)
- goto exit;
-@@ -1614,10 +1707,12 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ nd.it = it;
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd.it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-+ intent_release(dentry, &nd.it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1663,11 +1758,14 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_UNLINK };
-
- name = getname(pathname);
- if(IS_ERR(name))
- return PTR_ERR(name);
-
-+ nd.it = it;
-+ nd.it.it_op = IT_LOOKUP;
- error = path_lookup(name, LOOKUP_PARENT, &nd);
- if (error)
- goto exit;
-@@ -1675,7 +1773,9 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+
-+ nd.it = it;
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd.it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1683,6 +1783,7 @@
- goto slashes;
- error = vfs_unlink(nd.dentry->d_inode, dentry);
- exit2:
-+ intent_release(dentry, &nd.it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1727,6 +1828,7 @@
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_SYMLINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1737,13 +1839,18 @@
- struct dentry *dentry;
- struct nameidata nd;
-
-+ nd.it = it;
-+ nd.it.it_op = IT_LOOKUP;
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-+ nd.it = it;
-+ nd.it.it_data = from;
- dentry = lookup_create(&nd, 0);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
-+ intent_release(dentry, &nd.it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1810,24 +1917,32 @@
- struct nameidata nd, old_nd;
- int error;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_LINK };
-+
-
- to = getname(newname);
- if (IS_ERR(to))
- return PTR_ERR(to);
-
-+ old_nd.it = it;
- error = __user_walk(oldname, 0, &old_nd);
- if (error)
- goto exit;
-+ nd.it = it;
-+ nd.it.it_op = IT_LOOKUP;
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-+ nd.it = old_nd.it;//if __user_walk() above didn't change old_nd.it, this step is not need.
-+ nd.it.it_op = IT_LINK2;
- new_dentry = lookup_create(&nd, 0);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-+ intent_release(new_dentry, &nd.it);
- dput(new_dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1874,7 +1989,8 @@
- * locking].
- */
- int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error = 0;
- struct inode *target;
-@@ -1902,6 +2018,7 @@
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1919,7 +2036,8 @@
- }
-
- int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- struct inode *target;
- int error;
-@@ -1944,12 +2062,14 @@
- }
- if (target)
- up(&target->i_sem);
-+ intent_release(new_dentry, it);
- dput(new_dentry);
- return error;
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
-@@ -1975,9 +2095,9 @@
- DQUOT_INIT(new_dir);
-
- if (is_dir)
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -1996,11 +2116,16 @@
- struct dentry * old_dentry, *new_dentry;
- struct dentry * trap;
- struct nameidata oldnd, newnd;
-+ struct lookup_intent it = { .it_op = IT_RENAME };
-
-+ oldnd.it = it;
-+ oldnd.it.it_op = IT_LOOKUP;
- error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
- if (error)
- goto exit;
-
-+ newnd.it = it;
-+ newnd.it.it_op = IT_LOOKUP;
- error = path_lookup(newname, LOOKUP_PARENT, &newnd);
- if (error)
- goto exit1;
-@@ -2020,7 +2145,8 @@
-
- trap = lock_rename(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ oldnd.it = it;
-+ old_dentry = lookup_hash(&oldnd.last, old_dir, &oldnd.it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -2040,7 +2166,9 @@
- error = -EINVAL;
- if (old_dentry == trap)
- goto exit4;
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ newnd.it = oldnd.it;
-+ newnd.it.it_op = IT_RENAME2;
-+ new_dentry = lookup_hash(&newnd.last, new_dir, &newnd.it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-@@ -2050,10 +2178,12 @@
- goto exit5;
-
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, NULL);
- exit5:
-+ intent_release(new_dentry, &newnd.it);
- dput(new_dentry);
- exit4:
-+ intent_release(old_dentry, &oldnd.it);
- dput(old_dentry);
- exit3:
- unlock_rename(new_dir, old_dir);
-@@ -2135,12 +2265,17 @@
- path_release(nd);
- return PTR_ERR(link);
- }
-+/* if call vfs_follow_link, then equal set nd->it.it_op = 0;then call __vfs_follow_link
-+ * if call vfs_follow_link_it, now equal call __vfs_follow_link directly
-+*/
-
- int vfs_follow_link(struct nameidata *nd, const char *link)
- {
-+ nd->it.it_op = 0;
- return __vfs_follow_link(nd, link);
- }
-
-+
- /* get the link contents into pagecache */
- static char *page_getlink(struct dentry * dentry, struct page **ppage)
- {
-@@ -2180,7 +2315,9 @@
- {
- struct page *page = NULL;
- char *s = page_getlink(dentry, &page);
-- int res = __vfs_follow_link(nd, s);
-+ int res;
-+ nd->it.it_op = 0;
-+ res = __vfs_follow_link(nd, s);
- if (page) {
- kunmap(page);
- page_cache_release(page);
-diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
---- a/fs/nfsd/vfs.c Sat Jan 4 18:24:12 2003
-+++ b/fs/nfsd/vfs.c Sat Jan 4 18:24:12 2003
-@@ -1292,7 +1292,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
-diff -Nru a/fs/open.c b/fs/open.c
---- a/fs/open.c Sat Jan 4 18:24:12 2003
-+++ b/fs/open.c Sat Jan 4 18:24:12 2003
-@@ -22,6 +22,8 @@
-
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
-
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
-+
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
- int retval = -ENODEV;
-@@ -96,7 +98,9 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-+ nd.it = it;
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-@@ -237,7 +241,9 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-+ nd.it = it;
- error = user_path_walk(filename, &nd);
- if (error)
- goto out;
-@@ -283,9 +289,10 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-+ nd.it = it;
- error = user_path_walk(filename, &nd);
--
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -329,7 +336,9 @@
- int old_fsuid, old_fsgid;
- kernel_cap_t old_cap;
- int res;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-+ nd.it = it;
- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
- return -EINVAL;
-
-@@ -374,7 +383,9 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-+ nd.it = it;
- error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
- if (error)
- goto out;
-@@ -425,7 +436,9 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-+ nd.it = it;
- error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
- if (error)
- goto out;
-@@ -488,7 +501,9 @@
- struct inode * inode;
- int error;
- struct iattr newattrs;
-+ struct lookup_intent it= { .it_op = IT_SETATTR };
-
-+ nd.it = it;
- error = user_path_walk(filename, &nd);
- if (error)
- goto out;
-@@ -555,7 +570,9 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-+ nd.it = it;
- error = user_path_walk(filename, &nd);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-@@ -568,7 +585,9 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-+ nd.it = it;
- error = user_path_walk_link(filename, &nd);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-@@ -605,11 +624,16 @@
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
-+
- struct file *filp_open(const char * filename, int flags, int mode)
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
-+ nd.it = it;
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
- namei_flags++;
-@@ -618,12 +642,13 @@
-
- error = open_namei(filename, namei_flags, mode, &nd);
- if (!error)
-- return dentry_open(nd.dentry, nd.mnt, flags);
-+ return dentry_open_it(nd.dentry, nd.mnt, flags, &nd.it);
-
- return ERR_PTR(error);
- }
-
--struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it)
- {
- struct file * f;
- struct inode *inode;
-@@ -666,6 +691,7 @@
- }
- }
-
-+ intent_release(dentry, it);
- return f;
-
- cleanup_all:
-@@ -678,10 +704,17 @@
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(dentry, it);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-+
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+}
-+
-
- /*
- * Find an empty file descriptor entry, and mark it busy.
-diff -Nru a/fs/stat.c b/fs/stat.c
---- a/fs/stat.c Sat Jan 4 18:24:12 2003
-+++ b/fs/stat.c Sat Jan 4 18:24:12 2003
-@@ -61,7 +61,9 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-+ nd.it = it;
- error = user_path_walk(name, &nd);
- if (!error) {
- error = vfs_getattr(nd.mnt, nd.dentry, stat);
-@@ -74,7 +76,9 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-+ nd.it = it;
- error = user_path_walk_link(name, &nd);
- if (!error) {
- error = vfs_getattr(nd.mnt, nd.dentry, stat);
-diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
---- a/fs/sysfs/inode.c Sat Jan 4 18:24:12 2003
-+++ b/fs/sysfs/inode.c Sat Jan 4 18:24:12 2003
-@@ -471,7 +471,7 @@
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-- return lookup_hash(&qstr,parent);
-+ return lookup_hash(&qstr,parent,NULL);
- }
-
- /**
-diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
---- a/include/linux/dcache.h Sat Jan 4 18:24:12 2003
-+++ b/include/linux/dcache.h Sat Jan 4 18:24:12 2003
-@@ -9,6 +9,24 @@
- #include <linux/spinlock.h>
- #include <asm/page.h> /* for BUG() */
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
-+
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -30,6 +48,8 @@
- unsigned int hash;
- };
-
-+#include <linux/namei.h>
-+
- struct dentry_stat_t {
- int nr_dentry;
- int nr_unused;
-@@ -79,6 +99,7 @@
- struct list_head d_subdirs; /* our children */
- struct list_head d_alias; /* inode alias list */
- int d_mounted;
-+ struct lookup_intent *d_it;
- struct qstr d_name;
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
-@@ -96,6 +117,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
-diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
---- a/include/linux/ext3_fs.h Sat Jan 4 18:24:12 2003
-+++ b/include/linux/ext3_fs.h Sat Jan 4 18:24:12 2003
-@@ -64,8 +64,6 @@
- */
- #define EXT3_BAD_INO 1 /* Bad blocks inode */
- #define EXT3_ROOT_INO 2 /* Root inode */
--#define EXT3_ACL_IDX_INO 3 /* ACL inode */
--#define EXT3_ACL_DATA_INO 4 /* ACL inode */
- #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
- #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
-@@ -95,7 +93,6 @@
- #else
- # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
- #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -130,28 +127,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext3_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext3_acl_entry /* Access Control List Entry */
--{
-- __u32 acle_size;
-- __u16 acle_perms; /* Access permissions */
-- __u16 acle_type; /* Type of entry */
-- __u16 acle_tag; /* User or group identity */
-- __u16 acle_pad1;
-- __u32 acle_next; /* Pointer on next entry for the */
-- /* same inode or on next free entry */
--};
--
--/*
- * Structure of a blocks group descriptor
- */
- struct ext3_group_desc
-@@ -347,6 +322,7 @@
- #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
- #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
-+#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -529,7 +505,7 @@
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-
--#define EXT3_FEATURE_COMPAT_SUPP 0
-+#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
-@@ -713,6 +689,7 @@
-
-
- /* inode.c */
-+extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
- extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
- extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-
-@@ -781,8 +758,10 @@
-
- /* namei.c */
- extern struct inode_operations ext3_dir_inode_operations;
-+extern struct inode_operations ext3_special_inode_operations;
-
- /* symlink.c */
-+extern struct inode_operations ext3_symlink_inode_operations;
- extern struct inode_operations ext3_fast_symlink_inode_operations;
-
-
-diff -Nru a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
---- a/include/linux/ext3_jbd.h Sat Jan 4 18:24:12 2003
-+++ b/include/linux/ext3_jbd.h Sat Jan 4 18:24:12 2003
-@@ -30,13 +30,19 @@
-
- #define EXT3_SINGLEDATA_TRANS_BLOCKS 8
-
-+/* Extended attributes may touch two data buffers, two bitmap buffers,
-+ * and two group and summaries. */
-+
-+#define EXT3_XATTR_TRANS_BLOCKS 8
-+
- /* Define the minimum size for a transaction which modifies data. This
- * needs to take into account the fact that we may end up modifying two
- * quota files too (one for the group, one for the user quota). The
- * superblock only gets updated once, of course, so don't bother
- * counting that again for the quota updates. */
-
--#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
-+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
-+ EXT3_XATTR_TRANS_BLOCKS - 2)
-
- extern int ext3_writepage_trans_blocks(struct inode *inode);
-
-diff -Nru a/include/linux/fs.h b/include/linux/fs.h
---- a/include/linux/fs.h Sat Jan 4 18:24:12 2003
-+++ b/include/linux/fs.h Sat Jan 4 18:24:12 2003
-@@ -700,7 +700,7 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct lookup_intent *it);
-
- /*
- * File types
-@@ -769,6 +769,8 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *,
-+ struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -779,6 +781,7 @@
- struct inode *, struct dentry *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*setattr) (struct dentry *, struct iattr *);
-@@ -995,6 +998,7 @@
- extern int unregister_filesystem(struct file_system_type *);
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-
- #define kern_umount mntput
-diff -Nru a/include/linux/lustre_version.h b/include/linux/lustre_version.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/include/linux/lustre_version.h Sat Jan 4 18:24:12 2003
-@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 4
-diff -Nru a/include/linux/mbcache.h b/include/linux/mbcache.h
---- /dev/null Wed Dec 31 16:00:00 1969
-+++ b/include/linux/mbcache.h Sat Jan 4 18:24:12 2003
-@@ -0,0 +1,72 @@
-+/*
-+ File: linux/mbcache.h
-+
-+ (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+/* Hardwire the number of additional indexes */
-+#define MB_CACHE_INDEXES_COUNT 1
-+
-+struct mb_cache_entry;
-+
-+struct mb_cache_op {
-+ void (*free)(struct mb_cache_entry *);
-+};
-+
-+struct mb_cache {
-+ struct list_head c_cache_list;
-+ const char *c_name;
-+ struct mb_cache_op c_op;
-+ atomic_t c_entry_count;
-+ int c_bucket_bits;
-+#ifndef MB_CACHE_INDEXES_COUNT
-+ int c_indexes_count;
-+#endif
-+ kmem_cache_t *c_entry_cache;
-+ struct list_head *c_block_hash;
-+ struct list_head *c_indexes_hash[0];
-+};
-+
-+struct mb_cache_entry_index {
-+ struct list_head o_list;
-+ unsigned int o_key;
-+};
-+
-+struct mb_cache_entry {
-+ struct list_head e_lru_list;
-+ struct mb_cache *e_cache;
-+ atomic_t e_used;
-+ struct block_device *e_bdev;
-+ sector_t e_block;
-+ struct list_head e_block_list;
-+ struct mb_cache_entry_index e_indexes[0];
-+};
-+
-+/* Functions on caches */
-+
-+struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
-+ int, int);
-+void mb_cache_shrink(struct mb_cache *, struct block_device *);
-+void mb_cache_destroy(struct mb_cache *);
-+
-+/* Functions on cache entries */
-+
-+struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
-+int mb_cache_entry_insert(struct mb_cache_entry *, struct block_device *,
-+ sector_t, unsigned int[]);
-+void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
-+void mb_cache_entry_release(struct mb_cache_entry *);
-+void mb_cache_entry_takeout(struct mb_cache_entry *);
-+void mb_cache_entry_free(struct mb_cache_entry *);
-+struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
-+struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *,
-+ struct block_device *,
-+ sector_t);
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
-+ struct block_device *,
-+ unsigned int);
-+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
-+ struct block_device *,
-+ unsigned int);
-+#endif
-diff -Nru a/include/linux/namei.h b/include/linux/namei.h
---- a/include/linux/namei.h Sat Jan 4 18:24:12 2003
-+++ b/include/linux/namei.h Sat Jan 4 18:24:12 2003
-@@ -5,6 +5,17 @@
-
- struct vfsmount;
-
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- struct nameidata {
- struct dentry *dentry;
- struct vfsmount *mnt;
-@@ -13,6 +24,7 @@
- int last_type;
- struct dentry *old_dentry;
- struct vfsmount *old_mnt;
-+ struct lookup_intent it;
- };
-
- /*
-@@ -46,7 +58,7 @@
- extern void path_release(struct nameidata *);
-
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
--extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
-+extern struct dentry * lookup_hash(struct qstr *, struct dentry *, struct lookup_intent *);
-
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
-diff -Nru a/include/linux/slab.h b/include/linux/slab.h
---- a/include/linux/slab.h Sat Jan 4 18:24:12 2003
-+++ b/include/linux/slab.h Sat Jan 4 18:24:12 2003
-@@ -56,6 +56,7 @@
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
- extern unsigned int kmem_cache_size(kmem_cache_t *);
-
- extern void *kmalloc(size_t, int);
-diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
---- a/kernel/ksyms.c Sat Jan 4 18:24:12 2003
-+++ b/kernel/ksyms.c Sat Jan 4 18:24:12 2003
-@@ -365,6 +365,13 @@
- EXPORT_SYMBOL(tty_get_baud_rate);
- EXPORT_SYMBOL(do_SAK);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+//EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(exit_files);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
- /* filesystem registration */
- EXPORT_SYMBOL(register_filesystem);
- EXPORT_SYMBOL(unregister_filesystem);
-@@ -529,6 +536,7 @@
- EXPORT_SYMBOL(seq_lseek);
- EXPORT_SYMBOL(single_open);
- EXPORT_SYMBOL(single_release);
-+EXPORT_SYMBOL(reparent_to_init);
-
- /* Program loader interfaces */
- EXPORT_SYMBOL(setup_arg_pages);
-diff -Nru a/mm/slab.c b/mm/slab.c
---- a/mm/slab.c Sat Jan 4 18:24:12 2003
-+++ b/mm/slab.c Sat Jan 4 18:24:12 2003
-@@ -1236,6 +1236,59 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!page_mem_map(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
-diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
---- a/net/unix/af_unix.c Sat Jan 4 18:24:12 2003
-+++ b/net/unix/af_unix.c Sat Jan 4 18:24:12 2003
-@@ -715,7 +715,7 @@
- /*
- * Do the final lookup.
- */
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- goto out_mknod_unlock;
+++ /dev/null
- arch/um/kernel/mem.c | 18 ++++++
- fs/dcache.c | 12 +++-
- fs/namei.c | 132 ++++++++++++++++++++++++++++++++++++++-----------
- fs/namespace.c | 1
- fs/nfsd/vfs.c | 2
- fs/open.c | 39 ++++++++++++--
- fs/stat.c | 2
- fs/sysfs/inode.c | 2
- include/linux/dcache.h | 28 ++++++++++
- include/linux/fs.h | 20 +++++++
- include/linux/namei.h | 3 -
- include/linux/slab.h | 1
- kernel/ksyms.c | 7 ++
- mm/slab.c | 5 +
- net/unix/af_unix.c | 2
- 15 files changed, 231 insertions(+), 43 deletions(-)
-
---- linux-2.5.63-nointent/arch/um/kernel/mem.c~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/arch/um/kernel/mem.c Tue Mar 18 15:02:10 2003
-@@ -660,6 +660,22 @@ struct page *pte_mem_map(pte_t pte)
- return(phys_mem_map(pte_val(pte)));
- }
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+ struct page *page;
-+ struct mem_region *mr;
-+ unsigned long phys = __pa(kaddr);
-+ unsigned int n = phys_region_index(phys);
-+
-+ if(regions[n] == NULL)
-+ return NULL;
-+
-+ mr = regions[n];
-+ page = (struct page *) mr->mem_map;
-+ return page + ((phys_addr(phys)) >> PAGE_SHIFT);
-+}
-+
-+
- struct mem_region *page_region(struct page *page, int *index_out)
- {
- int i;
-@@ -747,7 +763,7 @@ extern unsigned long region_pa(void *vir
- (addr <= region->start + region->len))
- return(mk_phys(addr - region->start, i));
- }
-- panic("region_pa : no region for virtual address");
-+ //panic("region_pa : no region for virtual address");
- return(0);
- }
-
---- linux-2.5.63-nointent/fs/namei.c~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/fs/namei.c Mon Mar 24 17:08:18 2003
-@@ -101,6 +101,14 @@
- * any extra contention...
- */
-
-+void intent_release(struct dentry *de, struct lookup_intent *it)
-+{
-+ if (it && de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de, it);
-+
-+}
-+
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -273,10 +281,18 @@ 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_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -330,7 +346,7 @@ ok:
- * 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;
-@@ -348,7 +364,10 @@ static struct dentry * real_lookup(struc
- struct dentry * dentry = d_alloc(parent, name);
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
-- result = dir->i_op->lookup(dir, dentry);
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
-+ result = dir->i_op->lookup(dir, dentry);
- if (result)
- dput(dentry);
- else {
-@@ -370,6 +389,12 @@ static struct dentry * real_lookup(struc
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -402,6 +427,7 @@ static inline int do_follow_link(struct
- current->link_count--;
- return err;
- loop:
-+ intent_release(dentry, &nd->it);
- path_release(nd);
- return err;
- }
-@@ -447,15 +473,26 @@ static int follow_mount(struct vfsmount
- return res;
- }
-
--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_mode;
-+ }
-+ intent_release(*dentry, it);
-+ if (it) {
-+ it->it_op = opc;
-+ it->it_mode = mode;
-+ }
- dput(*dentry);
- mntput(mounted->mnt_parent);
- *dentry = dget(mounted->mnt_root);
-@@ -467,7 +504,7 @@ static inline int __follow_down(struct v
-
- 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 vfsmount **mnt, struct dentry **dentry)
-@@ -531,7 +568,7 @@ done:
- return 0;
-
- need_lookup:
-- dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE, &nd->it);
- if (IS_ERR(dentry))
- goto fail;
- goto done;
-@@ -665,7 +702,7 @@ int link_path_walk(const char * name, st
- nd->dentry = next.dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -716,7 +753,8 @@ last_component:
- break;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op ||
-+ (!inode->i_op->lookup && !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -735,6 +773,7 @@ out_dput:
- dput(next.dentry);
- break;
- }
-+ intent_release(nd->dentry, &nd->it);
- path_release(nd);
- return_err:
- return err;
-@@ -857,7 +896,8 @@ int path_lookup(const char *name, unsign
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -880,13 +920,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;
-- dentry = inode->i_op->lookup(inode, new);
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
-+ dentry = inode->i_op->lookup(inode, new);
- if (!dentry) {
- dentry = new;
- security_inode_post_lookup(inode, dentry);
-@@ -898,7 +941,7 @@ out:
- }
-
- /* 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;
-@@ -918,11 +961,16 @@ struct dentry * lookup_one_len(const cha
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash(&this, base, it);
- access:
- return ERR_PTR(-EACCES);
- }
-
-+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+{
-+ return lookup_one_len_it(name, base, len, NULL);
-+}
-+
- /*
- * namei()
- *
-@@ -1224,6 +1272,9 @@ int open_namei(const char * pathname, in
- /*
- * Create - we need to know the parent.
- */
-+ nd->it.it_mode = mode;
-+ nd->it.it_op |= IT_CREAT;
-+
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1239,7 +1290,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(&nd->last, nd->dentry, &nd->it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1247,7 +1298,8 @@ do_last:
- up(&dir->d_inode->i_sem);
- goto exit;
- }
--
-+
-+ nd->it.it_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- if (!IS_POSIXACL(dir->d_inode))
-@@ -1277,7 +1329,7 @@ do_last:
- error = -ELOOP;
- if (flag & O_NOFOLLOW)
- goto exit_dput;
-- while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));
-+ while (__follow_down(&nd->mnt,&dentry,&nd->it) && d_mountpoint(dentry));
- }
- error = -ENOENT;
- if (!dentry->d_inode)
-@@ -1297,8 +1349,10 @@ ok:
- return 0;
-
- exit_dput:
-+ intent_release(dentry, &nd->it);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry, &nd->it);
- path_release(nd);
- return error;
-
-@@ -1320,7 +1374,12 @@ do_link:
- if (error)
- goto exit_dput;
- UPDATE_ATIME(dentry->d_inode);
-- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ error = dentry->d_inode->i_op->follow_link2(dentry, nd, &nd->it);
-+ else
-+ error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(dentry, &nd->it);
- dput(dentry);
- if (error)
- return error;
-@@ -1342,7 +1401,7 @@ do_link:
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash(&nd->last, nd->dentry, &nd->it);
- putname(nd->last.name);
- goto do_last;
- }
-@@ -1356,7 +1415,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(&nd->last, nd->dentry, &nd->it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1588,7 +1647,7 @@ asmlinkage long sys_rmdir(const char * p
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd.it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1654,8 +1713,18 @@ asmlinkage long sys_unlink(const char *
- error = -EISDIR;
- if (nd.last_type != LAST_NORM)
- goto exit1;
-+ if (nd.dentry->d_inode->i_op->unlink2) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->unlink2(nd.dentry->d_inode,
-+ nd.last.name,
-+ nd.last.len);
-+ /* 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(&nd.last, nd.dentry, &nd.it);
-+ dentry = lookup_hash(&nd.last, nd.dentry, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1859,7 +1928,8 @@ 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,
-+ struct lookup_intent *it)
- {
- int error = 0;
- struct inode *target;
-@@ -1887,6 +1957,7 @@ int vfs_rename_dir(struct inode *old_dir
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1904,7 +1975,8 @@ int vfs_rename_dir(struct inode *old_dir
- }
-
- int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- struct inode *target;
- int error;
-@@ -1921,6 +1993,7 @@ int vfs_rename_other(struct inode *old_d
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- if (!error) {
- /* The following d_move() should become unconditional */
- if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME))
-@@ -1934,7 +2007,8 @@ int vfs_rename_other(struct inode *old_d
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
-@@ -1960,9 +2034,9 @@ int vfs_rename(struct inode *old_dir, st
- DQUOT_INIT(new_dir);
-
- if (is_dir)
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry, it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry, it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -2005,7 +2079,7 @@ static inline int do_rename(const char *
-
- trap = lock_rename(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash(&oldnd.last, old_dir, &oldnd.it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -2025,7 +2099,7 @@ static inline int do_rename(const char *
- error = -EINVAL;
- if (old_dentry == trap)
- goto exit4;
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ new_dentry = lookup_hash(&newnd.last, new_dir, &newnd.it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-@@ -2035,7 +2109,7 @@ static inline int do_rename(const char *
- goto exit5;
-
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, NULL);
- exit5:
- dput(new_dentry);
- exit4:
---- linux-2.5.63-nointent/fs/nfsd/vfs.c~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/fs/nfsd/vfs.c Tue Mar 18 15:02:10 2003
-@@ -1337,7 +1337,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
---- linux-2.5.63-nointent/fs/sysfs/inode.c~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/fs/sysfs/inode.c Tue Mar 18 15:02:10 2003
-@@ -540,7 +540,7 @@ static struct dentry * get_dentry(struct
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-- return lookup_hash(&qstr,parent);
-+ return lookup_hash(&qstr,parent,NULL);
- }
-
-
---- linux-2.5.63-nointent/include/linux/dcache.h~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/include/linux/dcache.h Tue Mar 18 15:02:10 2003
-@@ -12,6 +12,27 @@
-
- struct vfsmount;
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_READDIR (1<<2)
-+#define IT_GETATTR (1<<3)
-+#define IT_LOOKUP (1<<4)
-+#define IT_UNLINK (1<<5)
-+
-+
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_flags;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -34,6 +55,8 @@ struct qstr {
- char name_str[0];
- };
-
-+#include <linux/namei.h>
-+
- struct dentry_stat_t {
- int nr_dentry;
- int nr_unused;
-@@ -87,6 +110,7 @@ struct dentry {
- struct list_head d_subdirs; /* our children */
- struct list_head d_alias; /* inode alias list */
- int d_mounted;
-+ struct lookup_intent *d_it;
- struct qstr d_name;
- struct qstr * d_qstr; /* quick str ptr used in lockless lookup and concurrent d_move */
- unsigned long d_time; /* used by d_revalidate */
-@@ -107,6 +131,8 @@ struct dentry_operations {
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
-@@ -147,6 +173,8 @@ d_iput: no no yes
-
- #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
- #define DCACHE_UNHASHED 0x0010
-+#define DCACHE_LUSTRE_INVALID 0x0011 /* Lustre invalidated */
-+
-
- extern spinlock_t dcache_lock;
- extern rwlock_t dparent_lock;
---- linux-2.5.63-nointent/include/linux/fs.h~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/include/linux/fs.h Tue Mar 18 15:02:10 2003
-@@ -234,6 +234,9 @@ typedef int (get_blocks_t)(struct inode
- #define ATTR_ATTR_FLAG 1024
- #define ATTR_KILL_SUID 2048
- #define ATTR_KILL_SGID 4096
-+#define ATTR_RAW 8192 /* file system, not vfs will massage attrs */
-+#define ATTR_FROM_OPEN 16384 /* called from open path, ie O_TRUNC */
-+
-
- /*
- * This is the Inode Attributes structure, used for notify_change(). It
-@@ -642,7 +645,7 @@ 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 *);
-+extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct lookup_intent *it);
-
- /*
- * File types
-@@ -728,19 +731,33 @@ struct file_operations {
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *,
-+ struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
-+ int (*link2) (struct inode *,struct inode *, const char *, int);
- int (*unlink) (struct inode *,struct dentry *);
-+ int (*unlink2) (struct inode *, const char *, int);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-+ int (*symlink2) (struct inode *, const char *, int, const char *);
- int (*mkdir) (struct inode *,struct dentry *,int);
-+ int (*mkdir2) (struct inode *, const char *, int,int);
- int (*rmdir) (struct inode *,struct dentry *);
-+ int (*rmdir2) (struct inode *, const char *, int);
- int (*mknod) (struct inode *,struct dentry *,int,dev_t);
-+ int (*mknod2) (struct inode *, const char *, int,int,int);
- int (*rename) (struct inode *, struct dentry *,
- struct inode *, struct dentry *);
-+ int (*rename2) (struct inode *, struct inode *,
-+ const char *oldname, int oldlen,
-+ const char *newname, int newlen);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *,
-+ struct lookup_intent *it);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*setattr) (struct dentry *, struct iattr *);
-+ int (*setattr_raw) (struct inode *, struct iattr *);
- int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
- int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,int);
-@@ -953,6 +970,7 @@ extern int register_filesystem(struct fi
- extern int unregister_filesystem(struct file_system_type *);
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-
- extern int vfs_statfs(struct super_block *, struct statfs *);
---- linux-2.5.63-nointent/include/linux/namei.h~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/include/linux/namei.h Tue Mar 18 15:02:10 2003
-@@ -11,6 +11,7 @@ struct nameidata {
- struct qstr last;
- unsigned int flags;
- int last_type;
-+ struct lookup_intent it;
- };
-
- /*
-@@ -44,7 +45,7 @@ extern int FASTCALL(link_path_walk(const
- extern void path_release(struct nameidata *);
-
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
--extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
-+extern struct dentry * lookup_hash(struct qstr *, struct dentry *, struct lookup_intent *);
-
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
---- linux-2.5.63-nointent/include/linux/slab.h~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/include/linux/slab.h Tue Mar 18 15:02:10 2003
-@@ -55,6 +55,7 @@ extern int kmem_cache_destroy(kmem_cache
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
- extern unsigned int kmem_cache_size(kmem_cache_t *);
-
- extern void *kmalloc(size_t, int);
---- linux-2.5.63-nointent/kernel/ksyms.c~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/kernel/ksyms.c Tue Mar 18 15:02:10 2003
-@@ -377,6 +377,7 @@ EXPORT_SYMBOL(unregister_filesystem);
- EXPORT_SYMBOL(kern_mount);
- EXPORT_SYMBOL(__mntput);
- EXPORT_SYMBOL(may_umount);
-+EXPORT_SYMBOL(reparent_to_init);
-
- /* executable format registration */
- EXPORT_SYMBOL(register_binfmt);
-@@ -407,6 +408,12 @@ EXPORT_SYMBOL(request_irq);
- EXPORT_SYMBOL(free_irq);
- EXPORT_SYMBOL(irq_stat);
-
-+/* lustre */
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(exit_files);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
-+
- /* waitqueue handling */
- EXPORT_SYMBOL(add_wait_queue);
- EXPORT_SYMBOL(add_wait_queue_exclusive);
---- linux-2.5.63-nointent/mm/slab.c~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/mm/slab.c Tue Mar 18 15:02:10 2003
-@@ -1792,6 +1792,11 @@ static inline void __cache_free (kmem_ca
- }
- }
-
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ return 1;
-+}
-+
- /**
- * kmem_cache_alloc - Allocate an object
- * @cachep: The cache to allocate from.
---- linux-2.5.63-nointent/net/unix/af_unix.c~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/net/unix/af_unix.c Tue Mar 18 15:02:10 2003
-@@ -720,7 +720,7 @@ static int unix_bind(struct socket *sock
- /*
- * Do the final lookup.
- */
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- goto out_mknod_unlock;
---- linux-2.5.63-nointent/fs/dcache.c~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/fs/dcache.c Tue Mar 18 15:02:10 2003
-@@ -1111,15 +1111,21 @@ 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);
-- spin_lock(&dcache_lock);
-+ if (lock) spin_lock(&dcache_lock);
- if (!list_empty(&entry->d_hash) && !d_unhashed(entry)) BUG();
- entry->d_vfs_flags &= ~DCACHE_UNHASHED;
- entry->d_bucket = list;
- list_add_rcu(&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.5.63-nointent/fs/namespace.c~lustre-2.5.63 Tue Mar 18 15:02:10 2003
-+++ linux-2.5.63-nointent-root/fs/namespace.c Tue Mar 18 15:02:10 2003
-@@ -925,6 +925,7 @@ void set_fs_pwd(struct fs_struct *fs, st
- mntput(old_pwdmnt);
- }
- }
-+EXPORT_SYMBOL(set_fs_pwd);
-
- static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd)
- {
---- linux-2.5.63-nointent/fs/open.c~lustre-2.5.63 Thu Mar 20 12:43:39 2003
-+++ linux-2.5.63-nointent-root/fs/open.c Mon Mar 24 16:25:47 2003
-@@ -97,7 +97,8 @@ static inline long do_sys_truncate(const
- struct nameidata nd;
- struct inode * inode;
- int error;
--
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-+ nd.it=it;
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-@@ -142,11 +143,13 @@ static inline long do_sys_truncate(const
- error = locks_verify_truncate(inode, NULL, length);
- if (!error) {
- DQUOT_INIT(inode);
-+ intent_release(nd.dentry, &nd.it);
- error = do_truncate(nd.dentry, length);
- }
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry, &nd.it);
- path_release(&nd);
- out:
- return error;
-@@ -340,6 +343,8 @@ 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 };
-+ nd.it=it;
-
- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
- return -EINVAL;
-@@ -371,6 +376,8 @@ asmlinkage long sys_access(const char *
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
- res = -EROFS;
-+
-+ intent_release(nd.dentry, &nd.it);
- path_release(&nd);
- }
-
-@@ -385,6 +392,8 @@ asmlinkage long sys_chdir(const char * f
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-+ nd.it=it;
-
- error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
- if (error)
-@@ -397,6 +406,7 @@ asmlinkage long sys_chdir(const char * f
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry, &nd.it);
- path_release(&nd);
- out:
- return error;
-@@ -436,6 +446,8 @@ asmlinkage long sys_chroot(const char *
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-+ nd.it=it;
-
- error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
- if (error)
-@@ -508,6 +520,18 @@ asmlinkage long sys_chmod(const char * f
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_mode = mode;
-+ newattrs.ia_valid = ATTR_MODE | 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)
-+ goto dput_and_out;
-+ }
-
- error = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-@@ -619,7 +643,10 @@ asmlinkage long sys_fchown(unsigned int
- struct file *filp_open(const char * filename, int flags, int mode)
- {
- int namei_flags, error;
-+ struct file * temp_filp;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = flags };
-+ nd.it=it;
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -628,9 +655,11 @@ struct file *filp_open(const char * file
- namei_flags |= 2;
-
- error = open_namei(filename, namei_flags, mode, &nd);
-- if (!error)
-- return dentry_open(nd.dentry, nd.mnt, flags);
--
-+ if (!error) {
-+ temp_filp = dentry_open(nd.dentry, nd.mnt, flags);
-+ intent_release(nd.dentry,&nd.it);
-+ return temp_filp;
-+ }
- return ERR_PTR(error);
- }
-
-@@ -675,7 +704,7 @@ struct file *dentry_open(struct dentry *
- goto cleanup_all;
- }
- }
--
-+
- return f;
-
- cleanup_all:
---- linux-2.5.63-nointent/fs/stat.c~lustre-2.5.63 Fri Mar 21 21:15:40 2003
-+++ linux-2.5.63-nointent-root/fs/stat.c Fri Mar 21 21:16:53 2003
-@@ -65,6 +65,7 @@ int vfs_stat(char *name, struct kstat *s
- error = user_path_walk(name, &nd);
- if (!error) {
- error = vfs_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry, &nd.it);
- path_release(&nd);
- }
- return error;
-@@ -80,6 +81,7 @@ int vfs_lstat(char *name, struct kstat *
- error = user_path_walk_link(name, &nd);
- if (!error) {
- error = vfs_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry, &nd.it);
- path_release(&nd);
- }
- return error;
-
-_
+++ /dev/null
-
-
-
- 0 files changed
-
---- /dev/null 2002-08-30 16:31:37.000000000 -0700
-+++ linux-2.4.18-17.8.0-zab/include/linux/lustre_version.h 2002-12-06 14:52:30.000000000 -0800
-@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 5
-
-_
+++ /dev/null
-
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/arch/um/kernel/mem.c~uml_check_get_page 2002-12-06 14:52:30.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/arch/um/kernel/mem.c 2002-12-06 14:52:30.000000000 -0800
-@@ -529,6 +529,21 @@ struct page *pte_mem_map(pte_t pte)
- return(phys_mem_map(pte_val(pte)));
- }
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+ struct page *page;
-+ struct mem_region *mr;
-+ unsigned long phys = __pa(kaddr);
-+ unsigned int n = phys_region_index(phys);
-+
-+ if (regions[n] == NULL)
-+ return NULL;
-+
-+ mr = regions[n];
-+ page = (struct page *) mr->mem_map;
-+ return page + ((phys_addr(phys)) >> PAGE_SHIFT);
-+}
-+
- struct mem_region *page_region(struct page *page, int *index_out)
- {
- int i;
-
-_
+++ /dev/null
-
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/include/asm-um/pgtable.h~uml_compile_fixes 2002-12-06 15:46:21.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/include/asm-um/pgtable.h 2002-12-06 15:46:21.000000000 -0800
-@@ -200,7 +200,7 @@ static inline void pgd_clear(pgd_t * pgd
- * called on a highmem page.
- */
-
--#define page_address(page) ({ if (!(page)->virtual) BUG(); (page)->virtual; })
-+//#define page_address(page) ({ if (!(page)->virtual) BUG(); (page)->virtual; })
- #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-
- extern struct page *pte_mem_map(pte_t pte);
-
-_
+++ /dev/null
-
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/arch/um/kernel/mem.c~uml_no_panic 2002-12-06 14:52:30.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/arch/um/kernel/mem.c 2002-12-06 14:52:30.000000000 -0800
-@@ -559,7 +559,9 @@ struct mem_region *page_region(struct pa
- return(region);
- }
- }
-- panic("No region found for page");
-+// panic("No region found for page");
-+ printk(KERN_ERR "no region foudn for page %p\n, returning NULL\n",
-+ page);
- return(NULL);
- }
-
-@@ -581,7 +583,9 @@ unsigned long region_pa(void *virt)
- (addr <= region->start + region->len))
- return(mk_phys(addr - region->start, i));
- }
-- panic("region_pa : no region for virtual address");
-+ //panic("region_pa : no region for virtual address");
-+ printk(KERN_ERR "no region for virtual address %lu, return pa 0\n",
-+ addr);
- return(0);
- }
-
-
-_
+++ /dev/null
- fs/dcache.c | 19 ++
- fs/exec.c | 14 +
- fs/namei.c | 364 +++++++++++++++++++++++++++++++++++++++++--------
- fs/nfsd/vfs.c | 2
- fs/open.c | 118 ++++++++++++++-
- fs/stat.c | 8 -
- include/linux/dcache.h | 28 +++
- include/linux/fs.h | 33 ++++
- kernel/ksyms.c | 1
- 9 files changed, 505 insertions(+), 82 deletions(-)
-
---- linux-rh-2.4.20-6/fs/dcache.c~vfs_intent-2.4.20 Tue Apr 1 01:03:23 2003
-+++ linux-rh-2.4.20-6-braam/fs/dcache.c Tue Apr 1 01:03:23 2003
-@@ -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.
-@@ -840,13 +847,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-rh-2.4.20-6/fs/namei.c~vfs_intent-2.4.20 Tue Apr 1 01:03:23 2003
-+++ linux-rh-2.4.20-6-braam/fs/namei.c Wed Apr 2 02:12:53 2003
-@@ -1,3 +1,4 @@
-+
- /*
- * linux/fs/namei.c
- *
-@@ -94,6 +95,13 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct dentry *de, struct lookup_intent *it)
-+{
-+ if (it && de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de, it);
-+
-+}
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -260,10 +268,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_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -281,11 +298,14 @@ 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;
-
-+again:
-+
- 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->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +344,12 @@ static struct dentry * real_lookup(struc
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ goto again;
-+ }
- }
- return result;
- }
-@@ -334,7 +363,8 @@ int max_recursive_link = 5;
- * 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 +378,14 @@ static inline int do_follow_link(struct
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-+ intent_release(dentry, it);
- path_release(nd);
- return -ELOOP;
- }
-@@ -381,15 +415,26 @@ int follow_up(struct vfsmount **mnt, str
- 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_mode;
-+ }
-+ intent_release(*dentry, it);
-+ if (it) {
-+ it->it_op = opc;
-+ it->it_mode = mode;
-+ }
- dput(*dentry);
- mntput(mounted->mnt_parent);
- *dentry = dget(mounted->mnt_root);
-@@ -401,7 +446,7 @@ static inline int __follow_down(struct v
-
- 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 +482,7 @@ static inline void follow_dotdot(struct
- 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 +494,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;
-@@ -526,18 +572,18 @@ 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;
- }
- /* Check mountpoints.. */
-- while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
-+ while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, NULL))
- ;
-
- err = -ENOENT;
-@@ -548,8 +594,8 @@ int link_path_walk(const char * name, st
- if (!inode->i_op)
- goto out_dput;
-
-- if (inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ if (inode->i_op->follow_link || inode->i_op->follow_link2) {
-+ err = do_follow_link(dentry, nd, NULL);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -565,7 +611,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->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -592,22 +638,23 @@ last_component:
- if (err < 0)
- break;
- }
-- dentry = cached_lookup(nd->dentry, &this, 0);
-+ dentry = cached_lookup(nd->dentry, &this, 0, NULL);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, 0);
-+ dentry = real_lookup(nd->dentry, &this, 0, NULL);
- 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, NULL))
- ;
- inode = dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
-- && inode && inode->i_op && inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ && inode && inode->i_op &&
-+ inode->i_op->follow_link || inode->i_op->follow_link2) {
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -621,7 +668,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->lookup2))
- break;
- }
- goto return_base;
-@@ -645,6 +693,30 @@ return_reval:
- * Check the cached dentry for staleness.
- */
- dentry = nd->dentry;
-+ revalidate_again:
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ err = -ESTALE;
-+ if (!dentry->d_op->d_revalidate2(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, NULL);
-+ d_invalidate(dentry);
-+ dput(dentry);
-+ dentry = new;
-+ goto revalidate_again;
-+ }
-+ } else
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ err = -ESTALE;
-+ if (!dentry->d_op->d_revalidate2(dentry, 0, it)) {
-+ d_invalidate(dentry);
-+ break;
-+ }
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- err = -ESTALE;
- if (!dentry->d_op->d_revalidate(dentry, 0)) {
-@@ -658,15 +730,28 @@ out_dput:
- dput(dentry);
- break;
- }
-+ if (err)
-+ intent_release(nd->dentry, 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 +836,14 @@ 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;
-+}
-+
- int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
- {
- int error = 0;
-@@ -779,7 +872,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;
-@@ -802,13 +896,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->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -820,6 +917,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)
- {
-@@ -841,7 +944,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);
- }
-@@ -872,6 +975,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.
-@@ -1010,7 +1130,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;
-@@ -1024,7 +1145,7 @@ int open_namei(const char * pathname, in
- * 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 +1155,10 @@ int open_namei(const char * pathname, in
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1049,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);
-@@ -1058,6 +1183,7 @@ do_last:
- goto exit;
- }
-
-+ it->it_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- error = vfs_create(dir->d_inode, dentry,
-@@ -1086,12 +1212,13 @@ do_last:
- 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)
- goto exit_dput;
-- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
-+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
-+ dentry->d_inode->i_op->follow_link2))
- goto do_link;
-
- dput(nd->dentry);
-@@ -1165,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)
-@@ -1177,8 +1304,10 @@ ok:
- return 0;
-
- exit_dput:
-+ intent_release(dentry, it);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry, it);
- path_release(nd);
- return error;
-
-@@ -1197,7 +1326,12 @@ do_link:
- * are done. Procfs-like symlinks just set LAST_BIND.
- */
- UPDATE_ATIME(dentry->d_inode);
-- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ error = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(dentry, it);
- dput(dentry);
- if (error)
- return error;
-@@ -1219,13 +1353,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;
-
-@@ -1233,7 +1374,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)
-@@ -1289,7 +1430,19 @@ 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.dentry->d_inode->i_op->mknod2) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mknod2(nd.dentry->d_inode,
-+ nd.last.name,
-+ nd.last.len,
-+ 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 +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,17 @@ 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.dentry->d_inode->i_op->mkdir2) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mkdir2(nd.dentry->d_inode,
-+ nd.last.name,
-+ nd.last.len,
-+ 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 +1529,8 @@ asmlinkage long sys_mkdir(const char * p
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+out2:
-+ path_release(&nd);
- path_release(&nd);
- out:
- putname(tmp);
-@@ -1465,8 +1631,33 @@ asmlinkage long sys_rmdir(const char * p
- error = -EBUSY;
- goto exit1;
- }
-+ if (nd.dentry->d_inode->i_op->rmdir2) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ struct dentry *last;
-+
-+ down(&nd.dentry->d_inode->i_sem);
-+ last = lookup_hash_it(&nd.last, nd.dentry, NULL);
-+ up(&nd.dentry->d_inode->i_sem);
-+ if (IS_ERR(last)) {
-+ error = PTR_ERR(last);
-+ goto exit1;
-+ }
-+ if (d_mountpoint(last)) {
-+ dput(last);
-+ error = -EBUSY;
-+ goto exit1;
-+ }
-+ dput(last);
-+
-+ error = op->rmdir2(nd.dentry->d_inode,
-+ nd.last.name,
-+ nd.last.len);
-+ /* 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);
-@@ -1518,14 +1709,23 @@ asmlinkage long sys_unlink(const char *
- if(IS_ERR(name))
- return PTR_ERR(name);
-
-- error = path_lookup(name, LOOKUP_PARENT, &nd);
-+ error = path_lookup_it(name, LOOKUP_PARENT, &nd, NULL);
- if (error)
- goto exit;
- error = -EISDIR;
- if (nd.last_type != LAST_NORM)
- goto exit1;
-+ if (nd.dentry->d_inode->i_op->unlink2) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->unlink2(nd.dentry->d_inode,
-+ nd.last.name,
-+ nd.last.len);
-+ /* 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 +1792,26 @@ asmlinkage long sys_symlink(const char *
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ if (nd.dentry->d_inode->i_op->symlink2) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->symlink2(nd.dentry->d_inode,
-+ nd.last.name,
-+ nd.last.len,
-+ 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 +1887,17 @@ 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.dentry->d_inode->i_op->link2) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->link2(old_nd.dentry->d_inode,
-+ nd.dentry->d_inode,
-+ nd.last.name,
-+ nd.last.len);
-+ /* 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 +1941,8 @@ 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,
-+ struct lookup_intent *it)
- {
- int error;
- struct inode *target;
-@@ -1778,6 +2000,7 @@ int vfs_rename_dir(struct inode *old_dir
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1799,7 +2022,8 @@ 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,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -1830,6 +2054,7 @@ int vfs_rename_other(struct inode *old_d
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- double_up(&old_dir->i_zombie, &new_dir->i_zombie);
- if (error)
- return error;
-@@ -1841,13 +2066,14 @@ int vfs_rename_other(struct inode *old_d
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- if (S_ISDIR(old_dentry->d_inode->i_mode))
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -1889,7 +2115,7 @@ static inline int do_rename(const char *
-
- 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 +2131,37 @@ 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;
-
-+ if (old_dir->d_inode->i_op->rename2) {
-+ lock_kernel();
-+ /* don't rename mount point. mds will take care of
-+ * the rest sanity checking */
-+ if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) {
-+ error = -EBUSY;
-+ goto exit5;
-+ }
-+
-+ error = old_dir->d_inode->i_op->rename2(old_dir->d_inode,
-+ new_dir->d_inode,
-+ oldnd.last.name,
-+ oldnd.last.len,
-+ newnd.last.name,
-+ newnd.last.len);
-+ unlock_kernel();
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit5;
-+ }
-+
- lock_kernel();
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, NULL);
- unlock_kernel();
--
-+exit5:
- dput(new_dentry);
- exit4:
- dput(old_dentry);
-@@ -1965,7 +2212,8 @@ 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;
-@@ -1978,7 +2226,7 @@ __vfs_follow_link(struct nameidata *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 +2250,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 */
-@@ -2044,7 +2298,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-rh-2.4.20-6/fs/nfsd/vfs.c~vfs_intent-2.4.20 Tue Apr 1 01:03:23 2003
-+++ linux-rh-2.4.20-6-braam/fs/nfsd/vfs.c Tue Apr 1 01:03:23 2003
-@@ -1293,7 +1293,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
---- linux-rh-2.4.20-6/fs/open.c~vfs_intent-2.4.20 Tue Apr 1 01:03:23 2003
-+++ linux-rh-2.4.20-6-braam/fs/open.c Tue Apr 1 01:03:23 2003
-@@ -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;
-
-@@ -108,7 +111,14 @@ 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;
-+ newattrs.ia_ctime = CURRENT_TIME;
-+ error = op->setattr_raw(inode, &newattrs);
-+ } else
-+ error = notify_change(dentry, &newattrs);
- up(&inode->i_sem);
- return error;
- }
-@@ -118,12 +128,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;
-@@ -163,11 +174,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(nd.dentry, &it);
-+ error = do_truncate(nd.dentry, length, 0);
- }
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -215,7 +228,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:
-@@ -260,11 +273,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;
-@@ -279,11 +294,29 @@ 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 = -EROFS;
-+ if (IS_RDONLY(inode))
-+ 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 +337,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;
-@@ -324,7 +359,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;
-@@ -347,6 +395,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;
-@@ -364,13 +413,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(nd.dentry, &it);
- path_release(&nd);
- }
-
-@@ -385,8 +435,11 @@ 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;
-
-@@ -397,6 +450,7 @@ asmlinkage long sys_chdir(const char * f
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -436,9 +490,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;
-
-@@ -454,6 +509,7 @@ asmlinkage long sys_chroot(const char *
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -508,6 +564,18 @@ asmlinkage long sys_chmod(const char * f
- if (IS_RDONLY(inode))
- goto dput_and_out;
-
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_mode = mode;
-+ newattrs.ia_valid = ATTR_MODE | 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)
-+ goto dput_and_out;
-+ }
-+
- error = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- goto dput_and_out;
-@@ -538,6 +606,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;
-+ 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;
-@@ -658,7 +740,8 @@ struct file *filp_open(const char * file
- return ERR_PTR(error);
- }
-
--struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it)
- {
- struct file * f;
- struct inode *inode;
-@@ -701,6 +784,7 @@ struct file *dentry_open(struct dentry *
- }
- f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-
-+ intent_release(dentry, it);
- return f;
-
- cleanup_all:
-@@ -715,11 +799,17 @@ cleanup_all:
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(dentry, it);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+}
-+
- /*
- * Find an empty file descriptor entry, and mark it busy.
- */
---- linux-rh-2.4.20-6/fs/stat.c~vfs_intent-2.4.20 Tue Apr 1 01:03:23 2003
-+++ linux-rh-2.4.20-6-braam/fs/stat.c Tue Apr 1 01:03:23 2003
-@@ -111,10 +111,12 @@ int vfs_stat(char *name, struct kstat *s
- {
- 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);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -124,10 +126,12 @@ int vfs_lstat(char *name, struct kstat *
- {
- 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);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
---- linux-rh-2.4.20-6/fs/exec.c~vfs_intent-2.4.20 Tue Apr 1 01:03:23 2003
-+++ linux-rh-2.4.20-6-braam/fs/exec.c Wed Apr 2 00:29:56 2003
-@@ -114,8 +114,9 @@ asmlinkage long sys_uselib(const char *
- struct file * file;
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = O_RDONLY };
-
-- error = user_path_walk(library, &nd);
-+ error = user_path_walk_it(library, &nd, &it);
- if (error)
- goto out;
-
-@@ -127,7 +128,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(nd.dentry, &it);
- error = PTR_ERR(file);
- if (IS_ERR(file))
- goto out;
-@@ -382,8 +384,9 @@ 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 = O_RDONLY };
-
-- 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 +398,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(nd.dentry, &it);
- if (!IS_ERR(file)) {
- err = deny_write_access(file);
- if (err) {
-@@ -1279,7 +1283,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-rh-2.4.20-6/include/linux/dcache.h~vfs_intent-2.4.20 Tue Apr 1 01:03:23 2003
-+++ linux-rh-2.4.20-6-braam/include/linux/dcache.h Tue Apr 1 01:03:23 2003
-@@ -7,6 +7,25 @@
- #include <linux/mount.h>
- #include <linux/kernel.h>
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_READDIR (1<<2)
-+#define IT_GETATTR (1<<3)
-+#define IT_LOOKUP (1<<4)
-+#define IT_UNLINK (1<<5)
-+
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_flags;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -82,6 +101,7 @@ struct dentry {
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
- struct super_block * d_sb; /* The root of the dentry tree */
-+ struct lookup_intent *d_it;
- unsigned long d_vfs_flags;
- void * d_fsdata; /* fs-specific data */
- void * d_extra_attributes; /* TUX-specific data */
-@@ -96,8 +116,15 @@ struct dentry_operations {
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
-+/* defined in fs/namei.c */
-+extern void intent_release(struct dentry *de, 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 +156,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-rh-2.4.20-6/include/linux/fs.h~vfs_intent-2.4.20 Tue Apr 1 01:03:23 2003
-+++ linux-rh-2.4.20-6-braam/include/linux/fs.h Wed Apr 2 02:13:01 2003
-@@ -1,3 +1,6 @@
-+
-+
-+
- #ifndef _LINUX_FS_H
- #define _LINUX_FS_H
-
-@@ -337,6 +340,8 @@ 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 2048 /* file system, not vfs will massage attrs */
-+#define ATTR_FROM_OPEN 4096 /* called from open path, ie O_TRUNC */
-
- /*
- * This is the Inode Attributes structure, used for notify_change(). It
-@@ -574,6 +579,7 @@ struct file {
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_intent;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -821,7 +827,9 @@ 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,
-+ struct lookup_intent *it);
-
- /*
- * File types
-@@ -882,20 +890,33 @@ struct file_operations {
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
-+ int (*link2) (struct inode *,struct inode *, const char *, int);
- int (*unlink) (struct inode *,struct dentry *);
-+ int (*unlink2) (struct inode *, const char *, int);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-+ int (*symlink2) (struct inode *, const char *, int, const char *);
- int (*mkdir) (struct inode *,struct dentry *,int);
-+ int (*mkdir2) (struct inode *, const char *, int,int);
- int (*rmdir) (struct inode *,struct dentry *);
-+ int (*rmdir2) (struct inode *, const char *, int);
- int (*mknod) (struct inode *,struct dentry *,int,int);
-+ int (*mknod2) (struct inode *, const char *, int,int,int);
- int (*rename) (struct inode *, struct dentry *,
- struct inode *, struct dentry *);
-+ int (*rename2) (struct inode *, struct inode *,
-+ const char *oldname, int oldlen,
-+ const char *newname, int newlen);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *,
-+ struct lookup_intent *it);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*revalidate) (struct dentry *);
- 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);
-@@ -1091,10 +1112,13 @@ 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 struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
-+extern int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, struct lookup_intent *it);
- extern int filp_close(struct file *, fl_owner_t id);
- extern char * getname(const char *);
-
-@@ -1385,6 +1409,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 *));
-@@ -1396,6 +1421,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 *);
-@@ -1495,6 +1522,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-rh-2.4.20-6/kernel/ksyms.c~vfs_intent-2.4.20 Tue Apr 1 01:03:23 2003
-+++ linux-rh-2.4.20-6-braam/kernel/ksyms.c Tue Apr 1 01:03:23 2003
-@@ -298,6 +298,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
-
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/fs/dcache.c~vfs_intent 2002-12-06 14:52:31.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/dcache.c 2002-12-06 14:52:31.000000000 -0800
-@@ -150,6 +150,8 @@ repeat:
- unhash_it:
- list_del_init(&dentry->d_hash);
-
-+
-+
- kill_it: {
- struct dentry *parent;
- list_del(&dentry->d_child);
-@@ -645,6 +647,7 @@ struct dentry * d_alloc(struct dentry *
- dentry->d_fsdata = NULL;
- dentry->d_extra_attributes = NULL;
- dentry->d_mounted = 0;
-+ dentry->d_it = NULL;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
---- linux-2.4.18-17.8.0/fs/namei.c~vfs_intent 2002-12-06 14:52:31.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/namei.c 2002-12-06 14:52:31.000000000 -0800
-@@ -1,3 +1,6 @@
-+
-+
-+
- /*
- * linux/fs/namei.c
- *
-@@ -94,6 +97,14 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct dentry *de, struct lookup_intent *it)
-+{
-+ if (it && de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de, it);
-+
-+}
-+
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -260,10 +271,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_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -281,7 +301,8 @@ 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;
-@@ -300,6 +321,9 @@ static struct dentry * real_lookup(struc
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +345,12 @@ static struct dentry * real_lookup(struc
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -334,7 +364,8 @@ int max_recursive_link = 5;
- * 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 +379,14 @@ static inline int do_follow_link(struct
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-+ intent_release(dentry, it);
- path_release(nd);
- return -ELOOP;
- }
-@@ -449,7 +484,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;
-@@ -526,12 +562,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;
-@@ -548,8 +584,8 @@ int link_path_walk(const char * name, st
- if (!inode->i_op)
- goto out_dput;
-
-- if (inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ if (inode->i_op->follow_link || inode->i_op->follow_link2) {
-+ err = do_follow_link(dentry, nd, NULL);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -565,7 +601,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->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -592,12 +628,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;
-@@ -606,8 +642,10 @@ 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);
-+ && inode && inode->i_op &&
-+ (inode->i_op->follow_link ||
-+ inode->i_op->follow_link2)) {
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -621,7 +659,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->lookup2))
- break;
- }
- goto return_base;
-@@ -663,10 +702,21 @@ 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 +801,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;
-@@ -779,7 +840,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;
-@@ -802,13 +864,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->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -820,6 +885,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)
- {
-@@ -841,7 +912,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);
- }
-@@ -872,6 +943,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.
-@@ -1010,7 +1098,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;
-@@ -1024,7 +1113,7 @@ int open_namei(const char * pathname, in
- * 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 +1123,10 @@ int open_namei(const char * pathname, in
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1049,7 +1142,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);
-@@ -1058,6 +1151,7 @@ do_last:
- goto exit;
- }
-
-+ it->it_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- error = vfs_create(dir->d_inode, dentry,
-@@ -1091,7 +1185,8 @@ do_last:
- error = -ENOENT;
- if (!dentry->d_inode)
- goto exit_dput;
-- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
-+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
-+ dentry->d_inode->i_op->follow_link2))
- goto do_link;
-
- dput(nd->dentry);
-@@ -1177,8 +1272,10 @@ ok:
- return 0;
-
- exit_dput:
-+ intent_release(dentry, it);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry, it);
- path_release(nd);
- return error;
-
-@@ -1197,7 +1294,12 @@ do_link:
- * are done. Procfs-like symlinks just set LAST_BIND.
- */
- UPDATE_ATIME(dentry->d_inode);
-- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ error = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(dentry, it);
- dput(dentry);
- if (error)
- return error;
-@@ -1219,13 +1321,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;
-
-@@ -1233,7 +1342,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)
-@@ -1279,6 +1388,7 @@ asmlinkage long sys_mknod(const char * f
- char * tmp;
- struct dentry * dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1289,7 +1399,7 @@ asmlinkage long sys_mknod(const char * f
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
-
- mode &= ~current->fs->umask;
-@@ -1307,6 +1417,7 @@ asmlinkage long sys_mknod(const char * f
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1347,6 +1458,7 @@ asmlinkage long sys_mkdir(const char * p
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1357,11 +1469,12 @@ asmlinkage long sys_mkdir(const char * p
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ dentry = lookup_create(&nd, 1, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
- mode & ~current->fs->umask);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1445,6 +1558,7 @@ asmlinkage long sys_rmdir(const char * p
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_RMDIR };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1466,10 +1580,11 @@ asmlinkage long sys_rmdir(const char * p
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1513,6 +1628,7 @@ asmlinkage long sys_unlink(const char *
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_UNLINK };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1525,7 +1641,7 @@ asmlinkage long sys_unlink(const char *
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1533,6 +1649,7 @@ asmlinkage long sys_unlink(const char *
- goto slashes;
- error = vfs_unlink(nd.dentry->d_inode, dentry);
- exit2:
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1579,6 +1696,7 @@ asmlinkage long sys_symlink(const char *
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_SYMLINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1592,10 +1710,12 @@ asmlinkage long sys_symlink(const char *
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ it.it_data = from;
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1660,6 +1780,7 @@ asmlinkage long sys_link(const char * ol
- {
- int error;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_LINK };
-
- to = getname(newname);
- error = PTR_ERR(to);
-@@ -1667,7 +1788,7 @@ asmlinkage long sys_link(const char * ol
- struct dentry *new_dentry;
- struct nameidata nd, old_nd;
-
-- error = __user_walk(oldname, LOOKUP_POSITIVE, &old_nd);
-+ error = __user_walk_it(oldname, LOOKUP_POSITIVE, &old_nd, &it);
- if (error)
- goto exit;
- error = path_lookup(to, LOOKUP_PARENT, &nd);
-@@ -1676,10 +1797,12 @@ asmlinkage long sys_link(const char * ol
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ it.it_op = IT_LINK2;
-+ new_dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1720,7 +1843,8 @@ 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,
-+ struct lookup_intent *it)
- {
- int error;
- struct inode *target;
-@@ -1778,6 +1902,7 @@ int vfs_rename_dir(struct inode *old_dir
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1799,7 +1924,8 @@ 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,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -1830,6 +1956,7 @@ int vfs_rename_other(struct inode *old_d
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- double_up(&old_dir->i_zombie, &new_dir->i_zombie);
- if (error)
- return error;
-@@ -1841,13 +1968,14 @@ int vfs_rename_other(struct inode *old_d
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- if (S_ISDIR(old_dentry->d_inode->i_mode))
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -1864,6 +1992,7 @@ static inline int do_rename(const char *
- int error = 0;
- struct dentry * old_dir, * new_dir;
- struct dentry * old_dentry, *new_dentry;
-+ struct lookup_intent it = { .it_op = IT_RENAME };
- struct nameidata oldnd, newnd;
-
- error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
-@@ -1889,7 +2018,7 @@ static inline int do_rename(const char *
-
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1905,18 +2034,21 @@ static inline int do_rename(const char *
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ it.it_op = IT_RENAME2;
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-
- lock_kernel();
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, &it);
- unlock_kernel();
-
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- exit4:
-+ intent_release(old_dentry, &it);
- dput(old_dentry);
- exit3:
- double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
-@@ -1965,7 +2097,8 @@ 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;
-@@ -1978,7 +2111,7 @@ __vfs_follow_link(struct nameidata *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;
-@@ -2000,7 +2133,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 */
-@@ -2042,7 +2181,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.18-17.8.0/fs/nfsd/vfs.c~vfs_intent 2002-12-06 14:52:31.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/nfsd/vfs.c 2002-12-06 14:52:31.000000000 -0800
-@@ -1298,7 +1298,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- unlock_kernel();
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
---- linux-2.4.18-17.8.0/fs/open.c~vfs_intent 2002-12-06 14:52:31.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/open.c 2002-12-06 14:52:31.000000000 -0800
-@@ -19,6 +19,9 @@
- #include <asm/uaccess.h>
-
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
-+extern int path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it);
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -118,12 +121,13 @@ static inline long do_sys_truncate(const
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-
-- error = user_path_walk(path, &nd);
-+ error = user_path_walk_it(path, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -168,6 +172,7 @@ static inline long do_sys_truncate(const
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -259,8 +264,9 @@ asmlinkage long sys_utime(char * filenam
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -286,6 +292,7 @@ asmlinkage long sys_utime(char * filenam
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -303,8 +310,9 @@ asmlinkage long sys_utimes(char * filena
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
-
- if (error)
- goto out;
-@@ -331,6 +339,7 @@ asmlinkage long sys_utimes(char * filena
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -347,6 +356,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;
-@@ -364,13 +374,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(nd.dentry, &it);
- path_release(&nd);
- }
-
-@@ -385,8 +396,11 @@ 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;
-
-@@ -397,6 +411,7 @@ asmlinkage long sys_chdir(const char * f
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -436,9 +451,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;
-
-@@ -454,6 +470,7 @@ asmlinkage long sys_chroot(const char *
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -498,8 +515,9 @@ asmlinkage long sys_chmod(const char * f
- struct inode * inode;
- int error;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -519,6 +537,7 @@ asmlinkage long sys_chmod(const char * f
- error = notify_change(nd.dentry, &newattrs);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -588,10 +607,12 @@ asmlinkage long sys_chown(const char * f
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -601,10 +622,12 @@ asmlinkage long sys_lchown(const char *
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -638,10 +661,16 @@ asmlinkage long sys_fchown(unsigned int
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
-+
- struct file *filp_open(const char * filename, int flags, int mode)
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -649,18 +678,19 @@ 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);
- }
-
- extern ssize_t do_readahead(struct file *file, unsigned long index, unsigned long nr);
- /* for files over a certains size it doesn't pay to do readahead on open */
- #define READAHEAD_CUTOFF 48000
-
--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;
-@@ -711,6 +741,7 @@ struct file *dentry_open(struct dentry *
- do_readahead(f, 0, (48 * 1024) >> PAGE_SHIFT);
-
-
-+ intent_release(dentry, it);
- return f;
-
- cleanup_all:
-@@ -725,11 +756,17 @@ cleanup_all:
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(dentry, it);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+}
-+
- /*
- * Find an empty file descriptor entry, and mark it busy.
- */
---- linux-2.4.18-17.8.0/fs/stat.c~vfs_intent 2002-12-06 14:52:31.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/stat.c 2002-12-06 14:52:31.000000000 -0800
-@@ -13,6 +13,7 @@
-
- #include <asm/uaccess.h>
-
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
- /*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
-@@ -104,10 +105,12 @@ int vfs_stat(char *name, struct kstat *s
- {
- 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);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -117,10 +120,12 @@ int vfs_lstat(char *name, struct kstat *
- {
- 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);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
---- linux-2.4.18-17.8.0/include/linux/dcache.h~vfs_intent 2002-12-06 14:52:31.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/include/linux/dcache.h 2002-12-06 14:52:31.000000000 -0800
-@@ -6,6 +6,34 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
-+
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -78,6 +106,7 @@ struct dentry {
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
- struct super_block * d_sb; /* The root of the dentry tree */
-+ struct lookup_intent *d_it;
- unsigned long d_vfs_flags;
- void * d_fsdata; /* fs-specific data */
- void * d_extra_attributes; /* TUX-specific data */
-@@ -91,6 +120,8 @@ struct dentry_operations {
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
---- linux-2.4.18-17.8.0/include/linux/fs.h~vfs_intent 2002-12-06 14:52:31.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/include/linux/fs.h 2002-12-06 14:52:31.000000000 -0800
-@@ -576,6 +576,7 @@ struct file {
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_intent;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -836,7 +837,9 @@ 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,
-+ struct lookup_intent *it);
-
- /*
- * File types
-@@ -897,6 +900,7 @@ struct file_operations {
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -907,6 +911,8 @@ struct inode_operations {
- struct inode *, struct dentry *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *,
-+ struct lookup_intent *it);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*revalidate) (struct dentry *);
-@@ -1381,6 +1387,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 *));
-@@ -1392,6 +1399,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 *);
-@@ -1492,6 +1501,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.18-17.8.0/kernel/ksyms.c~vfs_intent 2002-12-06 14:52:31.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/kernel/ksyms.c 2002-12-06 14:52:31.000000000 -0800
-@@ -293,6 +293,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
-drivers/block/blkpg.c
-drivers/block/loop.c
-drivers/ide/ide-disk.c
+++ /dev/null
-drivers/block/blkpg.c
-drivers/block/loop.c
-drivers/ide/ide-disk.c
+++ /dev/null
-include/linux/mm.h
-mm/filemap.c
+++ /dev/null
-fs/ext3/Makefile
-fs/ext3/super.c
-include/linux/fs.h
-kernel/ksyms.c
+++ /dev/null
-fs/ext3/Makefile
-fs/ext3/super.c
-include/linux/fs.h
-kernel/ksyms.c
+++ /dev/null
-fs/inode.c
-fs/Makefile
-mm/filemap.c
-mm/vmscan.c
-mm/Makefile
-mm/page_alloc.c
+++ /dev/null
-fs/inode.c
-fs/Makefile
-mm/page_alloc.c
+++ /dev/null
-fs/jbd/commit.c
-fs/jbd/journal.c
-fs/jbd/transaction.c
-include/linux/jbd.h
+++ /dev/null
-arch/i386/mm/init.c
-arch/ia64/mm/init.c
-include/linux/slab.h
-kernel/ksyms.c
-kernel/ksyms.c.validate
-mm/slab.c
+++ /dev/null
-arch/um/kernel/mem.c
-fs/Config.help
-fs/Config.in
-fs/dcache.c
-fs/driverfs/inode.c
-fs/ext3/file.c
-fs/ext3/ialloc.c
-fs/ext3/inode.c
-fs/ext3/Makefile
-fs/ext3/namei.c
-fs/ext3/super.c
-fs/ext3/symlink.c
-fs/ext3/xattr.c
-fs/ext3/xattr.h
-fs/ext3/xattr_user.c
-fs/Makefile
-fs/mbcache.c
-fs/namei.c
-fs/nfsd/vfs.c
-fs/open.c
-fs/stat.c
-fs/sysfs/inode.c
-include/linux/dcache.h
-include/linux/ext3_fs.h
-include/linux/ext3_jbd.h
-include/linux/fs.h
-include/linux/lustre_version.h
-include/linux/mbcache.h
-include/linux/namei.h
-include/linux/slab.h
-kernel/ksyms.c
-mm/slab.c
-net/unix/af_unix.c
+++ /dev/null
-arch/um/kernel/mem.c
-fs/namei.c
-fs/nfsd/vfs.c
-fs/sysfs/inode.c
-include/linux/dcache.h
-include/linux/fs.h
-include/linux/namei.h
-include/linux/slab.h
-kernel/ksyms.c
-mm/slab.c
-net/unix/af_unix.c
-fs/dcache.c
+++ /dev/null
-arch/um/kernel/mem.c
-fs/namei.c
-fs/nfsd/vfs.c
-fs/sysfs/inode.c
-include/linux/dcache.h
-include/linux/fs.h
-include/linux/namei.h
-include/linux/slab.h
-kernel/ksyms.c
-mm/slab.c
-net/unix/af_unix.c
+++ /dev/null
-include/linux/lustre_version.h
+++ /dev/null
-./include/linux/lustre_version.h
-./arch/ia64/mm/init.c
-./arch/i386/mm/init.c
-./drivers/block/blkpg.c
-./drivers/block/loop.c
-./drivers/ide/ide-disk.c
-./fs/ext3/Makefile
-./fs/ext3/super.c
-./fs/jbd/commit.c
-./fs/jbd/journal.c
-./fs/jbd/transaction.c
-./include/linux/blkdev.h
-./include/linux/slab.h
-./include/linux/jbd.h
-./kernel/ksyms.c
-./include/linux/dcache.h
-./include/linux/fs.h
-./fs/dcache.c
-./fs/nfsd/vfs.c
-./fs/namei.c
-./fs/open.c
-./fs/stat.c
-./mm/slab.c
+++ /dev/null
-arch/um/kernel/mem.c
-arch/um/kernel/mem.c.uml-fixes
+++ /dev/null
-include/asm-um/pgtable.h
-include/asm-um/pgtable.h.orig
+++ /dev/null
-arch/um/kernel/mem.c
-arch/um/kernel/mem.c.uml-fixes
+++ /dev/null
-include/linux/lustre_version.h
-arch/ia64/mm/init.c
-arch/i386/mm/init.c
-drivers/block/blkpg.c
-drivers/block/loop.c
-drivers/ide/ide-disk.c
-fs/ext3/Makefile
-fs/ext3/super.c
-fs/jbd/commit.c
-fs/jbd/journal.c
-fs/jbd/transaction.c
-include/linux/blkdev.h
-include/linux/slab.h
-include/linux/jbd.h
-kernel/ksyms.c
-include/linux/dcache.h
-include/linux/fs.h
-fs/dcache.c
-fs/nfsd/vfs.c
-fs/namei.c
-fs/open.c
-fs/stat.c
-mm/slab.c
+++ /dev/null
-include/linux/lustre_version.h
-arch/ia64/mm/init.c
-arch/i386/mm/init.c
-drivers/block/blkpg.c
-drivers/block/loop.c
-drivers/ide/ide-disk.c
-fs/ext3/Makefile
-fs/ext3/super.c
-include/linux/blkdev.h
-include/linux/slab.h
-kernel/ksyms.c
-include/linux/dcache.h
-include/linux/fs.h
-fs/dcache.c
-fs/nfsd/vfs.c
-fs/namei.c
-fs/open.c
-fs/stat.c
-mm/slab.c
+++ /dev/null
-fs/dcache.c
-fs/namei.c
-fs/nfsd/vfs.c
-fs/open.c
-fs/stat.c
-include/linux/dcache.h
-include/linux/fs.h
-kernel/ksyms.c
+++ /dev/null
-fs/dcache.c
-fs/namei.c
-fs/nfsd/vfs.c
-fs/open.c
-fs/stat.c
-fs/exec.c
-include/linux/dcache.h
-include/linux/fs.h
-kernel/ksyms.c
+++ /dev/null
-fs/dcache.c
-fs/namei.c
-fs/nfsd/vfs.c
-fs/open.c
-fs/stat.c
-include/linux/dcache.h
-include/linux/fs.h
-kernel/ksyms.c
+++ /dev/null
-#!/bin/bash
-
-die() {
- echo -e $* >&2
- echo aborting.. >&2
- exit 1
-}
-
-canon() {
- cd $1
- CANON=$PWD
- cd -
-}
-
-canon $(dirname $0)
-MYDIR=$CANON
-
-while [ ${#*} -gt 1 ]; do
- case "$1" in
- -t)
- shift;
- TREE=$1
- ;;
- -s)
- shift;
- SERIES=$1
- ;;
- *)
- die "unknown argument $1"
- break;
- ;;
- esac
- shift;
-done
-
-[ -z "$TREE" -o -z "$SERIES" ] && die "I need a tree and series:\n\t$0 -t kernel_dir -s series_name"
-[ ! -d $TREE ] && die "kernel tree '$TREE' isn't a directory"
-SERIES=$(basename $SERIES)
-[ ! -f $MYDIR/series/$SERIES ] && die "no series file '$SERIES'"
-
-canon $TREE
-TREE=$CANON
-
-# patch scripts wants a relative path from the linux tree to
-# its patch pile :(
-
-MY=$(echo $MYDIR | sed -e 's_^/__')
-TR=$(echo $TREE | sed -e 's_^/__')
-
-while true ; do
- M=$(echo $MY | cut -d/ -f 1)
- T=$(echo $TR | cut -d/ -f 1)
-
- if [ $M != $T ]; then
- break;
- fi
-
- MY=$(echo $MY | cut -d/ -f 2-)
- TR=$(echo $TR | cut -d/ -f 2-)
-done
-
-[ $MY == $MYDIR ] && die "bad! $MY == $MYDIR"
-
-REVERSE=$(revpath $TR)${MY}
-ABSINO=$(stat $MYDIR | awk '($3 == "Inode:") {print $4}')
-REVINO=`(cd $TREE ; stat $REVERSE | awk '($3 == "Inode:") {print $4}')`
-
-[ $ABSINO != $REVINO ] && die "inodes differ, my reverse path is bad?"
-
-echo export PATCHSCRIPTS=$REVERSE
-
-cd $TREE
-ln -sf $REVERSE/series/$SERIES series
-
-PATH_ELEMENTS=$(echo $PATH | sed -e 's/:/ /g')
-
-NEW_PATH=$MYDIR/scripts
-
-for p in $PATH_ELEMENTS; do
- if echo $p | grep kernel_patches/scripts > /dev/null 2>&1 ; then
- continue;
- fi
- NEW_PATH="$NEW_PATH:$p"
-done
-
-echo export PATH=$NEW_PATH
-
-echo "'$TREE' successfully setup" >&2
+++ /dev/null
-#!/bin/sh
-# Extract names of new files from a patch, print them out
-
-PATCHFILE=$1
-case "$PATCHFILE" in
-*.gz) CMD="gzip -d < $PATCHFILE";;
-*) CMD="cat $PATCHFILE";;
-esac
-
-TMP=$(mktemp /tmp/abp.XXXXXX)
-
-eval $CMD | egrep '^--- .*1969|^--- .*1970' > $TMP
-sed -e 's@[^/]*/\([^ ]*\).*@\1@' < $TMP | sed -e 's@^linux/@@' | sort
-rm -f $TMP
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-
-do_apply()
-{
- FILES=$(cat $P/pc/$PATCH_NAME.pc)
- for file in $FILES
- do
- copy_file_to_bup $file $PATCH_NAME
- done
-
- silent=-s
- if [ $opt_force != 0 ]
- then
- silent=
- fi
-
- if patch -p1 $silent -i "$1" || [ $opt_force != 0 ]
- then
- true
- else
- echo SOMETHING WENT WRONG
- exit 1
- fi
-}
-
-add_to_db()
-{
- basename "$1" >> "$DB"
-}
-
-usage()
-{
- echo "Usage: apatch patchname"
- exit 1
-}
-
-opt_force=0
-PATCH_NAMES=""
-
-for i in $*
-do
- case "$i" in
- -f)
- opt_force=1;;
- *)
- PATCH_NAMES="$PATCH_NAMES $i"
- esac
-done
-
-if [ x"$PATCH_NAMES" == x ]
-then
- usage
-fi
-
-apatch()
-{
- PATCH_NAME=$(stripit $1)
-
- need_file_there $P/pc/$PATCH_NAME.pc
-
- if is_applied "$PATCH_NAME"
- then
- echo "$PATCH_NAME" is already applied
- exit 1
- fi
-
- if [ $opt_force != 0 ]
- then
- echo FORCING PATCH
- fi
-
- if [ $opt_force != 0 ] || can_apply $P/patches/"$PATCH_NAME".patch
- then
- do_apply $P/patches/"$PATCH_NAME".patch
- add_to_db "$PATCH_NAME"
- echo applied $PATCH_NAME
- echo
- else
- echo "$PATCH_NAME" does not apply
- exit 1
- fi
-}
-
-for i in $PATCH_NAMES
-do
- if ! apatch $i
- then
- exit 1
- fi
-done
-
+++ /dev/null
-#!/bin/sh
-
-#
-# Make superpatch from currently applied patches using combinediff.
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: combine-applied output-file"
- exit 1
-}
-
-if [ $# -ne 1 ]
-then
- usage
-fi
-
-need_file_there applied-patches
-CURRENT=$(mktemp /tmp/cmbd-XXXXXXXX)
-for FILE in `cat applied-patches`
-do
- NEXT=$(mktemp /tmp/cmbd-XXXXXXXX)
- if [ -f $P/patches/$FILE ]
- then
- combinediff $CURRENT $P/patches/$FILE > $NEXT
- elif [ -f $P/patches/$FILE.patch ]
- then
- combinediff $CURRENT $P/patches/$FILE.patch > $NEXT
- elif [ -f $FILE ]
- then
- combinediff $CURRENT $FILE > $NEXT
- fi
- rm $CURRENT
- CURRENT=$NEXT
-done
-
-mv $NEXT "$1"
+++ /dev/null
-#!/bin/sh
-
-#
-# Make superpatch from current series using combinediff.
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: combine-series output-file"
- exit 1
-}
-
-if [ $# -ne 1 ]
-then
- usage
-fi
-
-need_file_there series
-CURRENT=$(mktemp /tmp/cmbd-XXXXXXXX)
-for FILE in $(cat series)
-do
- NEXT=$(mktemp /tmp/cmbd-XXXXXXXX)
- if [ -f $P/patches/$FILE ]
- then
- combinediff $CURRENT $P/patches/$FILE > $NEXT
- elif [ -f $P/patches/$FILE.patch ]
- then
- combinediff $CURRENT $P/patches/$FILE.patch > $NEXT
- elif [ -f $FILE ]
- then
- combinediff $CURRENT $FILE > $NEXT
- fi
- rm $CURRENT
- CURRENT=$NEXT
-done
-
-mv $NEXT "$1"
+++ /dev/null
-#!/bin/sh
-
-doit()
-{
- echo $*
- $*
-}
-
-usage()
-{
- echo "Usage: cvs-take-patch patch_file_name"
- exit 1
-}
-
-#
-# Find the highest level directory in $1 which does not
-# contain the directory $2. Return it in $MISSING
-#
-highest_missing()
-{
- START_DIR="$1"
- NAME="$2"
- MISSING=""
- WHERE=$(dirname "$START_DIR")
- PREV_WHERE=$START_DIR
- while [ x"$WHERE" != x"$PREV_WHERE" ]
- do
- WHERE="$PREV_WHERE"
- if [ ! -d "$WHERE"/"$NAME" ]
- then
- MISSING="$WHERE"
- fi
- PREV_WHERE=$(dirname "$WHERE")
- done
- echo highest_missing returns $MISSING
-}
-
-#
-# Add all new directries to CVS, top-down
-# $1: name of a directory
-# $2: name of the CVS directory
-#
-add_cvs_dirs()
-{
- MISSING=foo
- while [ "$MISSING" != "" ]
- do
- highest_missing $1 $2
- if [ x"$MISSING" != "x" ]
- then
- if [ ! -d "$MISSING"/"$2" ]
- then
- doit cvs add $MISSING
- fi
- fi
- done
-}
-
-PATCHFILE=$1
-
-REMOVEDFILES=$(removed-by-patch $PATCHFILE)
-if [ "$REMOVEDFILES" != "" ]
-then
- doit cvs remove $REMOVEDFILES
-fi
-
-NEWFILES=$(added-by-patch $PATCHFILE)
-for i in $NEWFILES
-do
- DIRNAME=$(dirname $i)
- echo "Looking at $DIRNAME"
- add_cvs_dirs $DIRNAME CVS
-done
-
-if [ "$NEWFILES" != "" ]
-then
- doit cvs add $NEWFILES
-fi
+++ /dev/null
-Patch management scripts
-Andrew Morton <akpm@digeo.com>
-18 October 2002
-
-This is a description of a bunch of shell scripts which I use for
-managing kernel patches. They are quite powerful. They can be used on
-projects other than the linux kernel. They are easy to use, and fast.
-
-You end up doing a ton of recompiling with these scripts, because
-you're pushing and popping all the time. ccache takes away the pain of
-all that. http://ccache.samba.org/ - be sure to put the cache
-directory on the same fs as where you're working so that ccache can use
-hardlinks.
-
-The key philosophical concept is that your primary output is patches.
-Not ".c" files, not ".h" files. But patches. So patches are the
-first-class object here.
-
-Installation
-============
-
-You place all the scripts somewhere in your path, or in
-/usr/lib/patch-scripts.
-
-Terminology
-===========
-
-The patch scripts require three special directories called "pc",
-"patches" and "txt".
-
-If the environment variable PATCHSCRIPTS is set, it is taken to to be
-the directory in which those three directories reside. Typically, it
-would be a relative pathname. So
-
- setenv PATCHSCRIPTS ./i-put-them-here
-
-would tell the patch scripts to look in ./i-put-them-here/pc, etc.
-
-If PATCHSCRIPTS is not set, and the directory ./patch-scripts is
-present then the patch scripts will us ./patch-scripts/pc/,
-./patch-scripts/patches/ and ./patch-scripts/txt/.
-
-Otherwise, the patch scripts use ./pc, ./patches and ./txt.
-
-In this document, the symbol $P is used to describe the directory which
-holds the pc/, patches/ and txt/ directories, as determined by the
-above search.
-
-It is expected that $P will always expand to a relative path.
-
-Concepts
-========
-
-All work occurs with a single directory tree. All commands are invoked
-within the root of that tree. The scripts manage a "stack" of patches.
-
-Each patch is a changeset against the base tree plus the preceding patches.
-
-All patches are listed, in order, in the file ./series. You manage the
-series file.
-
-Any currently-applied patches are described in the file
-./applied-patches. The patch scripts manage this file.
-
-Each patch affects a number of files in the tree. These files are
-listed in a "patch control" file. These .pc files live in the
-directory $P/pc/
-
-Patches are placed in the directory $P/patches/
-
-Documentation for the patches is placed in $P/txt/
-
-So for a particular patch "my-first-patch" the following will exist:
-
-- An entry "my-first-patch.patch" in ./series
-
-- An entry "my-first-patch" in ./applied-patches (if it's currently applied)
-
-- A file $P/pc/my-first-patch.pc which contains the names of the
- files which my-first-patch modifies, adds or removes
-
-- A file $P/txt/my-first-patch.txt which contains the patch's
- changelog.
-
-- A file $P/patches/my-first-patch.patch, which is the output of the
- patch scripts.
-
-Operation
-=========
-
-When a patch "my-patch" is applied with apatch, or with pushpatch
-(which calls apatch), all the affected files (from $P/pc/my-patch.pc)
-are copied to files with ~my-patch appended. So if $P/pc/my-patch.pc
-contained
-
- kernel/sched.c
- fs/inode.c
-
-then apatch will copy those files into kernel/sched.c~my-patch and
-fs/inode.c~my-patch. It will then apply the patch to kernel/sched.c
-and fs/inode.c
-
-When a diff is regenerated by refpatch (which calls mpatch), the diff
-is made between kernel/sched.c and kernel/sched.c~my-patch. How do the
-scripts know to use "~my-patch"? Because my-patch is the current
-topmost patch. It's the last line in ./applied-patches.
-
-In this way, the whole thing is stackable. If you have four patches
-applied, say "patch-1", "patch-2", "patch-3" and "patch-4", and if
-patch-2 and patch-4 both touch kernel/sched.c then you will have:
-
- kernel/sched.c~patch-2 Original copy, before patch-2
- kernel/sched.c~patch-4 Copy before patch-4. Contains changes
- from patch-2
- kernel/sched.c Current working copy. Contains changes
- from patch-4.
-
-This means that your diff headers contain "~patch-name" in them, which
-is convenient documentation.
-
-Walkthrough
-===========
-
-Let's start.
-
-Go into /usr/src/linux (or wherever)
-
- mkdir pc patches txt
-
-Now let's generate a patch
-
- fpatch my-patch kernel/sched.c
-
-OK, we've copied kernel/sched.c to kernel/sched.c~my-patch. We've
-appended "my-patch" to ./applied-patches and we've put "kernel/sched.c"
-into the patch control file, pc/my-patch.pc.
-
- Now edit kernel/sched.c a bit.
-
-Now we're ready to document the patch
-
- Now write txt/my-patch.txt
-
-Now generate the patch
-
- refpatch
-
-This will generate patches/my-patch.patch. Take a look.
-
-Now remove the patch
-
- poppatch
-
-applied-patches is now empty, and the patch is removed.
-
-Now let's add a file to my-patch and then generate my-second-patch:
-
- Add "my-patch.patch" to ./series (no blank lines in that file please)
-
- pushpatch
-
-OK, the patch is applied again. Let's add another file
-
- fpatch kernel/printk.c
-
-Note that here we gave fpatch a single argument. So rather than
-opening a new patch, it adds kernel/printk.c to the existing topmost
-patch. That's my-patch.
-
- Edit kernel/printk.c
-
-Refresh my-patch (you end up running refpatch a lot)
-
- refpatch
-
-Now start a second patch:
-
- fpatch my-second-patch kernel/sched.c
-
-Now take a look at applied-patches. Also do an `ls kernel/sched*'.
-
- Edit kernel/sched.c, to make some changes for my-second-patch
-
-Generate my-second-patch:
-
- refpatch
-
-Take a look in patches/my-second-patch.patch
-
-Don't forget to add "my-second-patch.patch" to the series file.
-
-And remove both patches:
-
- poppatch
- poppatch
-
-
-That's pretty much it, really.
-
-
-Command reference
-=================
-
-Generally, where any of these commands take a "patch-name", that can be
-of the form txt/patch-name.txt, patch-name.pc, just patch-name or
-whatever. The scripts will strip off a leading "txt/", "patches/" or
-"pc/" and any trailing extension. This is so you can do
-
- apatch patches/a<tab>
-
-to conveniently use shell tabbing to select patch names.
-
-
-
-added-by-patch
-
- Some internal thing.
-
-apatch [-f] patch-name
-
- This is the low-level function which adds patches. It does the
- copying into ~-files and updates the applied-patches file. It
- applies the actual patch.
-
- apatch will do a patch --dry-run first and will refuse to apply the
- patch if the dryrun fails.
-
- So when you are getting rejects you do this:
-
- pushpatch # This fails, due to rejects. Drat.
- apatch -f patch-name # Force the patch
- (or) pushpatch -f # Force the patch
-
- OK, you've now applied patch-name, but you have rejects. Go fix
- those up and do
-
- refpatch
-
- And you're ready to move on.
-
-combine-series output-file
-
- It incrementally combinediffs all the patches in series to make a
- complete patch for the series. Requires combinediff frmo patchutils.
-
- See http://cyberelk.net/tim/patchutils/ (Don't download the
- "experimental" patchutils - it seems to only have half of the
- commands in it. Go for "stable")
-
-cvs-take-patch
-
- I forget.
-
-export_patch
-
- export the patches listed in ./series to a set of files which
- are named in such a way that the sort order is the same as the
- order of the series file.
-
- Usage: export_patch directory [prefix]
-
- Example:
-
- Suppose ./series contains
-
- mango.patch
- orange.patch
- banana.patch
- apple.patch
- pear.patch
-
- export_patch ../mypatches fruit
-
- The patches would be copied to
-
- ../mypatches/p00001_fruit_mango.patch
- ../mypatches/p00002_fruit_orange.patch
- ../mypatches/p00003_fruit_banana.patch
- ../mypatches/p00003_fruit_banana.patch
- ../mypatches/p00003_fruit_banana.patch
-
- Named in this way, someone may easily apply them:
-
- cat mypatches/p*fruit* | patch -p1
-
- If prefix is omitted, the patchnames will be transformed
- such that "original.patch" becomes "pXXXXX_original.patch".
-
-fpatch [patch-name] foo.c
-
- If patch-name is given, fpatch will start a new patch which
- modifies (or adds, or removes) the single file foo.c. It updates
- ./applied-patches and creates pc/patch-name.pc. fpatch will copy
- foo.c to foo.c~patch-name in preparation for edits of foo.c.
-
- If patch-name is not given then fpatch will add foo.c to the
- current topmost patch. It will add "foo.c" to $P/pc/$(toppatch).pc.
- It will copy foo.c to foo.c~$(toppatch).
-
-import_patch
-
- Imports a set of patch files, creating $P/pc, $P/txt, $P/patches and
- ./series as necessary. It also creates $P/txt/*.txt by stripping
- off the top of the patches (and removes any diffstat output it finds,
- so that it can eat refpatch output and export_patch output.) The
- imported patch names are appended to the series file.
-
- In creating the $P/txt/*.txt files, mail headers are stripped with
- formail, preserving the "From:" and "Subject:" lines. "DESC" and
- "EDESC" markers are added if they are not already present, using the
- "From:" and "Subject:" lines for the DESC portion, if they are present.
- (See "patchdesc" command, below, for more on these markers.)
-
- Also, it can rename the patch file as it is imported by stripping out
- a pattern. This is useful if, as often is the case, you have patch
- sets with filenames designed to help sort the patches into the correct
- order, such as "p001_xxx_funky_stuff.patch" you can have it automatically
- renamed to funky_stuff.patch on import, and let the series file manage
- the ordering.
-
- Import_patch will uncompress patches (*.Z, *.bz2, *.gz) as necessary.
-
- Usage:
-
- import_patch [-p pattern] patchfile ...
-
- Example:
-
- % ls ../fruit/p*patch
- ../fruit/p00001_northern_apple.patch
- ../fruit/p00001_tropical_mango.patch
- ../fruit/p00002_northern_pear.patch
- ../fruit/p00002_tropical_orange.patch
- ../fruit/p00003_tropical_banana.patch
- % import_patch -p 'p[0-9]*_tropical_' ../fruit/p*tropical*
- Recreated pc/mango.pc
- Recreated pc/orange.pc
- Recreated pc/banana.pc
- % import_patch -p 'p[0-9]*_northern_' ../fruit/p*northern*
- Recreated pc/apple.pc
- Recreated pc/pear.pc
-
- Then you can "pushpatch; refpatch" 5 times.
-
-inpatch
-
- List the names of ths files which are affected by the current
- topmost patch.
-
- This is basically
-
- cat pc/$(toppatch).pc
-
-mpatch
-
- A low-level thing to generate patches
-
-new-kernel
-
- Some thing I use for importing a new kernel from kernel.org
-
-p0-2-p1
-
- Internal thing to convert patch -p0 form into patch -p1
-
-patchdesc
-
- Generates a single-line description of a patch.
-
- The txt/my-patch.txt files have the following format:
-
- <start of file>
- DESC
- some short description
- EDESC
-
- The long description
- <end of file>
-
- I use
-
- patchdesc $(cat series)
-
- to generate short-form summaries of the patch series.
-
-patchfns
-
- Internal utilities
-
-pcpatch
-
- Standalone tool to generate a .pc file from a patch.
-
- Say someone sends you "his-patch.diff". What you do is:
-
- cp ~/his-patch.diff patches/his-patch.patch
- pcpatch his-patch
-
- This generates $P/pc/his-patch.pc and you're all set. Add
- "his-patch.patch" to ./series in the right place and start pushing.
-
-p_diff
-
- I forget
-
-poppatch
-
- Remove one or more patches from the current stack. This command
- does *not* use the series file. It works purely against
- applied-patches.
-
- Usage:
-
- poppatch
- Remove the topmost patch
- poppatch 10
- Remove ten patches
- poppatch some-patch-name[.patch]
- Remove patches until "some-patch-name" is top patch
-
-pstatus
-
- Shows status of patches
-
- Usage:
- pstatus [patchfile ...]
-
- One line per patch is output showing:
- 1: Patch number in the series file
- 2: Whether the patch is currently applied
- 3: Name of patch
- 4: Status of the patch (needs pcpatch, changelog, refpatch)
-
- If no patchfiles are specified, $P/patches/*.patch
- are assumed.
-
- Caveats:
- A patch set which contains separate patches to add a file
- and modify that same file may give spurious "Needs refpatch"
- status for the patch which adds the file or the topmost patch.
-
-ptkdiff
-
- Two modes:
-
- ptkdiff -
-
- Run tkdiff against all the file affected
- by $(toppatch). The diff is only for the changes made
- by the top patch! ie: it's between "filename" and
- "filename~toppatch-name".
-
- ptkdiff filename
-
- Just run tkdiff against that file,
- showing the changes which are due to toppatch.
-
-pushpatch [-f]
-
- Apply the next patch, from the series file.
-
- This consults ./applied-patches to find out the top patch, then
- consults ./series to find the next patch. And pushes it.
-
- pushpatch
-
- Apply the next patch
-
- pushpatch 10
-
- Apply the next ten patches
-
- pushpatch some-patch-name
-
- Keep pushing patches until "some-patch-name" is toppatch
-
- pushpatch -f
-
- Push the next patch, ignoring rejects.
-
-refpatch
-
- regnerates the topmost patch. Reads all the affected files
- from pc/$(toppatch).pc and diffs them against their tilde-files.
-
- Also pastes into the patch your patch documentation and
- generates a diffstat summary.
-
-removed-by-patch
-
- Some thing.
-
-rename-patch
-
- CVS rename for patches.
-
-rolled-up-patch
-
- Bit of a hack. Is designed to generate a rolled-up diff of all
- currently-applied patches. But it requires a ../linux-2.x.y tree to
- diff against. Needs to be redone.
-
-rpatch
-
- Internal command
-
-split-patch
-
- Some thing someone write to split patches up. I don't use it.
-
-tag-series
-
- Assuming you keep pc/*, patches/* and txt/* under CVS revision
- control, tag-series allows you to tag a patchset's individual
- components. I use
-
- tag-series s2_5_44-mm3 pc/2.5.44-mm3-series
-
- which will attach the cvs tag "s2_5_44-mm3" to every .pc, .patch
- and .txt file which is mentioned in the series file
- "pc/2.5.44-mm3-series".
-
- It will also tag pc/2.5.44-mm3-series, which is a bit redundant
- given that I use a different series file for each patchset release..
-
-
-toppatch
-
- Print the name of the topmost patch. From ./applied-patches
-
-touched-by-patch patch-filename
-
- List the names of files which are affected by a diff.
-
-unitdiff.py
-
- Rasmus Andersen's script to convert a diff into minimum-context
- form. This form has a better chance of applying if you're getting
- nasty rejects. But patch can and will make mistakes when fed
- small-context input.
-
-
-Work Practices
-==============
-
-I keep the kernel tree, the $P/pc/, $P/patches/ and $P/txt/ contents under
-CVS control. This is important...
-
-I have several "series" files. I keep these in $P/pc/foo-series and use
-
- ln -s pc/foo-series series
-
-when I'm working on foo.
-
-If someone sends me a patch I'll do:
-
- cp ~/whatever patches/his-patch.patch
- pcpatch his-patch
- apatch his-patch
-
- If apatch fails then run `apatch -f his-patch' and fix the rejects.
-
- refpatch
-
- to clean up any fuzz.
-
- poppatch
- cvs add pc/his-patch.pc patches/his-patch.patch
- cvs commit pc patches
-
- Now edit ./series and place "his-patch.patch" in the appropriate place.
-
-
-If you're working on a particular patch (say, "dud-patch") and you
-balls something up, just run:
-
- refpatch # Generate the crap patch
- poppatch # Remove it all
- rm patches/dud-patch.patch
- cvs up patches/dud-patch.patch
-
-and all is well.
-
-
-Getting updates from Linus
-==========================
-
-What I do is to grab the latest -bk diff from
-http://www.kernel.org/pub/linux/kernel/people/dwmw2/bk-2.5/
-and do:
-
- gzip -d < cs<tab> > patches/linus.patch
- pcpatch linus
- apatch linus | grep diff
-
- Now fix up all the files which got deleted,
- because there's something wrong with bitkeeper diffs:
-
- cvs up -ko <missing files from the above diff>
-
- apatch linus
- $EDITOR linus/linus.txt
-
- Add the changeset number to txt/linus.txt
-
- refpatch
- poppatch
-
- Now add "linus.patch" as the first entry in your ./series file and
- start pushing your other patches on top of that.
-
-BUGS
-====
-
-Tons and tons. The scripts are fragile, the error handling is ungraceful and
-if you do something silly you can end up in a pickle.
-
-Generally the scripts are very careful to not wreck your files or your
-patches. But they can get the ./applied-patches and ~-files into an
-awkward state.
-
-Usually you can sort it out by copying the ~-files back onto the originals
-and removing the last line from ./applied-patches. Or do a "refpatch ;
-poppatch ; rm patches/troublesome-patch.patch ; cvs up patches".
-
-If it's really bad, just blow away the entire tree and do a new CVS checkout.
-
-
-Working on non-kernel projects
-==============================
-
-Well it's the same thing. Say you've downloaded a copy of util-linux
-and you want to make a change:
-
- cd /usr/src
- tar xvfz ~/util-linux.tar.gz
- cd util-linux
- mkdir pc patches txt
- fpatch my-patch sys-utils/rdev.c
- fpatch sys-utils/ipcs.8
- <edit, edit>
- refpatch
- <ship patches/my-patch.patch>
-
-How to balls things up
-======================
-
-Well here's one way. Suppose you have 20 patches applied, and three of
-them (say, "p1", "p6" and "p11") all modify "foo.c".
-
-Now you go and change foo.c.
-
-Well, to which patch does that change belong? You need to decide.
-Let's say you decide "p6".
-
-If you run `refpatch' when "p11" is toppatch then you lose. The diff
-went into p11.
-
-What you can do is:
-
-1:
- poppatch p6
- <edit>
- refpatch
- pushpatch p11
- <test>
-
- (See why ccache is looking good?)
-
-or
-
-2:
- <edit>
- <test>
- poppatch p6 <hope like hell that the other patches remove cleanly>
- refpatch
-
-
-Another good way of ballsing up is to cheat. Say "oh I just want to make
-this one-line change". And "oh, and this one".
-
-Now you're getting in a mess. It's much, much better to just use the system:
-
- fpatch junk file1
- fpatch file2
- <edit>
- <play>
- refpatch
- poppatch
- rm pc/junk.pc patches/junk.patch
-
-Merging with -mm kernels
-========================
-
-Haven't tried this, but it should work:
-
-- Grab all the patches from broken-out/, place them in your $P/patches/
-
-- Copy my series file into ./series (or $P/pc/akpm-series and symlink it)
-
-- pushpatch 99
-
-And you're off and running. The nice thing about this is that you can
-send me incremental diffs to diffs which I already have.
-
-Or whatever. I'm fairly handy with diffs nowadays. Rejects are
-expected. I just prefer to have "one concept per diff".
-
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "export_patch: export the patches listed in ./series" 1>&2
- echo "usage: export_patch destination-directory [prefix] " 1>&2
- exit 1
-}
-
-DIR="$1"
-PREFIX="$2""_"
-
-if [ "$DIR" = "" ]
-then
- usage
-fi
-
-if [ -e "$DIR" -a ! -d "$DIR" ]
-then
- echo "$DIR exists already, but is not a directory." 1>&2
- exit 1
-fi
-
-if [ ! -r ./series ]
-then
- echo "./series is not readable." 1>&2
- exit 1
-fi
-
-mkdir -p "$DIR" || exit 1
-
-count=1
-for x in `cat ./series`
-do
- fname=`echo "$count" "$PREFIX" "$x" |\
- awk '{ if ( $2 != "_" )
- printf("p%05d_%s%s\n", $1, $2, $3);
- else
- printf("p%05d_%s\n", $1, $3);
- }'`
- if [ ! -r $P/patches/"$x" ]
- then
- echo "$P/patches/"$x" is not readable. skipping." 1>&2
- continue;
- fi
- cp -f $P/patches/"$x" "$DIR"/"$fname" || continue;
- count=`expr $count + 1`
-done
-
+++ /dev/null
-#!/bin/sh
-
-insert_line()
-{
- PATTERN="$1"
- LINE="$2"
- FILE="$3"
- awk ' BEGIN { found=0; }
- /'"$PATTERN"'/ {
- print;
- if (!found)
- printf("%s\n", "'$LINE'");
- found=1;
- next;
- }
- { print; }
- ' < "$FILE"
-}
-
-# extract the description from the top of a patch
-# filter stdin
-# collapse adjacent blank lines to a single blank line
-# remove any lines that look like diffstat output
-# stop output on encountering a line beginning with '---' (beginning of patch)
-
- TMPFILE=`mktemp /tmp/xdtmp.XXXXXX` || exit 1
- formail -kfcb -X 'From:' -X 'Subject:' |\
- awk '
- BEGIN { found_end=0; lastone="x"; }
- /^ .* [|] +[0-9]+ [+-]+$/ {
- #/* we found something like diffstat output... */
- if (found_end == 1) {
- /* we are past end of diffstat, let it pass */
- print;
- }
- next;
- }
- /^ [1-9][0-9]* files changed/ {
- #/* end of diffstat output, stop filtering diffstat */
- found_end=1;
- next;
- }
- /^--- / { exit; }
- {
- #/* collapse adjacent blank lines to 1 blank line */
- if ( $0 == "" && lastone == "" )
- next;
- else
- print;
- lastone=$0;
- }
- ' | awk '{ if ($0 == "" && FNR == 1) next; print; }' > "$TMPFILE"
-
- descs=`head -10 $TMPFILE | grep -c '^[ ]*DESC[ ]*$'`
- if [ "$descs" = "0" ]
- then
- # DESC is not 1st non blank line in the file
- echo "DESC"
- descs=0
- fi
- edescs=`grep -c '^EDESC$' "$TMPFILE"`
- subjects=`grep -c '^[ ]*Subject[:]' "$TMPFILE"`
- froms=`grep -c '^[ ]*From[:]' "$TMPFILE"`
- if [ "$edescs" = "0" ]
- then
- if [ "$subjects" != "0" ]
- then
- insert_line '^Subject[:]' 'EDESC' "$TMPFILE"
- else
- if [ "$froms" != "0" ]
- then
- insert_line '^From[:]' 'EDESC' "$TMPFILE"
- else
- if [ "$descs" = "0" ]
- then
- # blank DESC line...
- echo '(undescribed patch)'
- echo EDESC
- cat "$TMPFILE"
- else
- insert_line '^DESC$' "EDESC" "$TMPFILE"
- fi
- fi
- fi
- else
- cat $TMPFILE
- fi
+++ /dev/null
-#!/bin/sh
-
-#
-# Add a file to a patch.
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: fpatch patchname filename"
- echo " fpatch filename"
- exit 1
-}
-
-if [ $# == 1 ]
-then
- PATCH_NAME=$(top_patch)
- FILENAME=$1
-elif [ $# == 2 ]
-then
- PATCH_NAME=$(stripit $1)
- FILENAME=$2
-else
- usage
-fi
-
-
-if is_applied_last $PATCH_NAME
-then
- true
-else
- if is_applied $PATCH_NAME
- then
- echo $PATCH_NAME is not the last-applied patch
- exit 1
- else
- echo $PATCH_NAME >> $DB
- fi
-fi
-
-if file_in_patch $FILENAME $PATCH_NAME
-then
- echo File $FILENAME is already in patch $PATCH_NAME
- exit 1
-fi
-
-install_file_in_patch $FILENAME $PATCH_NAME
-
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "usage: import_patch [ -p prefix-pattern ] patchfile [...]" 1>&2
- exit 1
-}
-
-XPATTERN=""
-if [ "$1" = "-p" ]
-then
- XPATTERN="$2"
- shift;
- shift;
-fi
-
-if [ "$1" = "" ]
-then
- usage
-fi
-
-if [ ! -e applied-patches ]
-then
- touch applied-patches
-fi
-
-mkdir -p patches || exit 1
-mkdir -p txt || exit 1
-mkdir -p pc || exit 1
-
-if [ ! -e ./series ]
-then
- touch ./series
- if [ "$?" != "0" ]
- then
- echo "Cannot create ./series" 1>&2
- exit 1
- fi
-fi
-
-if [ ! -w ./series ]
-then
- echo "./series is not writable." 1>&2
- exit 1
-fi
-
-PATTERN='s/^'"$XPATTERN"'//'
-for x in $*
-do
- if [ ! -r "$x" ]
- then
- echo "$x does not exist, skipping." 1>&2
- continue
- fi
- patchname=`basename $x .bz2`
- patchname=`basename $patchname .gz`
- patchname=`basename $patchname .Z`
- patchname=`basename $patchname .patch`
- if is_applied $patchname
- then
- echo $patchname is currently applied
- exit 1
- fi
- if [ "$XPATTERN" != "" ]
- then
- patchname=`echo $patchname | sed -e "$PATTERN"`
- fi
- pname=$P/patches/"$patchname".patch
- if [ -r "$pname" ]
- then
- echo "$pname exists already, skipping." 1>&2
- continue
- fi
- case "$x" in
- *.bz2)
- bunzip2 < "$x" > "$pname"
- ;;
- *.gz)
- gunzip < "$x" > "$pname"
- ;;
- *.Z) zcat < "$z" > "$pname"
- ;;
- *)
- cat "$x" > "$pname" || continue
- ;;
- esac
- echo "$patchname".patch >> series
- pcpatch "$pname"
- extract_description < "$pname" >$P/txt/"$patchname".txt
- grep '^[(]undescribed patch[)]$' < $P/txt/"$patchname".txt > /dev/null
- if [ "$?" = "0" ]
- then
- echo "Warning: $patchname has no description." 1>&2
- fi
-done
-
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: inpatch"
- exit 1
-}
-
-if [ $# != 0 ]
-then
- usage
-fi
-
-if [ -e $DB ]
-then
- TOP_PATCH=$(top_patch)
- if [ x$TOP_PATCH != x ]
- then
- cat $P/pc/$TOP_PATCH.pc
- fi
-fi
+++ /dev/null
-#!/bin/sh
-#
-# Grab a patch frmo kernel.org, install it.
-#
-# Usage: linus-patch http://www.kernel.org/pub/linux/kernel/people/dwmw2/bk-2.5/cset-1.786.152.7-to-1.798.txt.gz
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-poppatch 999 || die poppatch
-wget $1 || die wget
-FILE=$(basename $1)
-gzip -d < $FILE > $P/patches/linus.patch
-pcpatch linus || die pcpatch
-(
- echo DESC
- echo $FILE
- echo EDESC
- echo
- echo $FILE
-) > $P/txt/linus.txt
-rm $FILE
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: mpatch patchname [output_dir]"
- exit 1
-}
-
-doit()
-{
- echo $* 1>&2
- $* || {
- echo oops
- exit 1
- }
-}
-
-epoch()
-{
-# doit touch -t 7001011000.00 $1
- doit touch -t 7001010000.00 $1
-}
-
-dirfor()
-{
- dir=$(dirname $1)
- if [ ! -d $dir ]
- then
- doit mkdir -p $dir
- RMDIRS="$RMDIRS $dir"
- fi
-}
-
-if [ $# == 0 ]
-then
- usage
-fi
-
-PATCH_NAME=$(stripit $1)
-OUTPUT_DIR=$2
-
-FILES=$(cat $P/pc/$PATCH_NAME.pc)
-OUT=$P/patches/$PATCH_NAME.patch
-TMPOUT=$(mktemp /tmp/patch-$PATCH_NAME-XXXXXX)
-TXT=$P/txt/$PATCH_NAME.txt
-OLDDIR=$(basename $(/bin/pwd))
-NEWDIR=$OLDDIR-$LOGNAME
-
-if is_applied_last $PATCH_NAME
-then
- true
-else
- echo $PATCH_NAME is not the last-applied patch
- exit 1
-fi
-
-doit rm -f $OUT
-echo "Placing patch in " $OUT
-
-if [ -e $TXT -a -s $TXT ]
-then
- echo >> $OUT
- body $TXT >> $OUT
- echo >> $OUT
- echo >> $OUT
-else
- echo "**** No patch description for $PATCH_NAME ****"
-fi
-
-rm -f $TMPOUT
-
-for file in $FILES
-do
- OLD_FILE="$file"~"$PATCH_NAME"
- if [ ! -e $OLD_FILE ]
- then
- OLD_FILE=/dev/null
- fi
- NEW_FILE=$file
- XDIFF_OPTS=""
- if [ ! -e $NEW_FILE ]
- then
- NEW_FILE=/dev/null
- XDIFF_OPTS="-L $file"
- fi
-
- echo diff -puN $XDIFF_OPTS $DIFF_OPTS $OLD_FILE $NEW_FILE
- diff -puN $XDIFF_OPTS $DIFF_OPTS $OLD_FILE $NEW_FILE | p0-2-p1 $OLDDIR $NEWDIR >> $TMPOUT
-done
-diffstat -p1 $TMPOUT >> $OUT 2>/dev/null
-echo >> $OUT
-cat $TMPOUT >> $OUT
-echo >> $OUT
-echo "_" >> $OUT
-rm -f $TMPOUT
+++ /dev/null
-#!/bin/sh
-
-usage()
-{
- echo "Usage: new-kernel linux-2.4.2-pre2 linux-2.4.3-pre3 linux-2.4.3 patch.gz cvs-dir"
- exit 1
-}
-
-wantdir()
-{
- if [ x$1 = x ]
- then
- usage
- fi
- if [ ! -d $1 ]
- then
- echo "directory $1 does not exist"
- usage
- fi
-}
-
-wantfile()
-{
- if [ x$1 = x ]
- then
- usage
- fi
- if [ ! -f $1 ]
- then
- echo "file $1 does not exist"
- usage
- fi
-}
-
-doit()
-{
- echo $* 1>&2
- $* || {
- echo oops
- exit 1
- }
-}
-
-
-CURRENT_KERNEL=$1
-NEXT_KERNEL=$2
-BASE_KERNEL=$3
-PATCH_FILE=$4
-CVS_DIR=$5
-
-TEMP_PATCH=$(mktemp /tmp/patch-XXXXXX)
-MY_DIFF="$CURRENT_KERNEL"--"$NEXT_KERNEL"
-
-wantdir $CURRENT_KERNEL
-wantdir $BASE_KERNEL
-wantdir $CVS_DIR
-wantfile $PATCH_FILE
-
-doit rm -rf $NEXT_KERNEL
-doit cp -a $BASE_KERNEL $NEXT_KERNEL
-doit rm -f $TEMP_PATCH
-doit gunzip < $PATCH_FILE > $TEMP_PATCH
-cd $NEXT_KERNEL
-doit patch -p1 --dry-run -i $TEMP_PATCH
-doit patch -p1 -s -i $TEMP_PATCH
-echo cd ..
-cd ..
-
-echo diff -uNrp $CURRENT_KERNEL $NEXT_KERNEL
-diff -uNrp $CURRENT_KERNEL $NEXT_KERNEL > $MY_DIFF
-
-echo cd $CVS_DIR
-cd $CVS_DIR
-doit patch -p1 --dry-run -s -i ../$MY_DIFF
-doit patch -p1 -s -i ../$MY_DIFF
-cvs-take-patch ../$MY_DIFF
-cvs commit -m "'doing $NEXT_KERNEL'"
-cvs update -ko -d -P
-
-TAG=$(echo $NEXT_KERNEL | sed -e 's@\.@_@g')
-cvs tag $TAG
-rm -f $TEMP_PATCH
+++ /dev/null
-#!/bin/sh
-#
-# Usage: p0-2-p1 olddir newdir
-#
-OLDDIR=$1
-NEWDIR=$2
-
-sed -e "s/^--- \([^\/].*\)/--- $OLDDIR\/\1/" |
-sed -e "s/^+++ \([^\/].*\)/+++ $NEWDIR\/\1/"
-
+++ /dev/null
-#!/bin/sh
-
-#
-# Bring up a patched file in diff. We show the diffs
-# in the topmost patch, unless it was specified
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: pdiff [patchname] filename"
- echo " pdiff [patchname] -"
- exit 1
-}
-
-if [ $# == 1 ]
-then
- PATCH_NAME=$(top_patch)
- FILENAME=$1
-elif [ $# == 2 ]
-then
- PATCH_NAME=$(stripit $1)
- FILENAME=$2
-else
- usage
-fi
-
-if ! is_applied $PATCH_NAME
-then
- echo $PATCH_NAME is not applied
- exit 1
-fi
-
-doit()
-{
- filename=$1
- unpatched_file=$filename"~"$PATCH_NAME
- need_file_there $filename
- if [ -e $unpatched_file ]
- then
- diff -u $unpatched_file $filename
- else
- echo pdiff: $filename appears to not be in $PATCH_NAME
- fi
-}
-
-if [ x"$FILENAME" = "x-" ]
-then
- FILENAME=$(cat $P/pc/$PATCH_NAME.pc)
-fi
-
-for i in $FILENAME
-do
- doit $i
-done
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-desc1()
-{
- PATCH=$(stripit $1)
- TXT=$P/txt/$PATCH.txt
- echo $PATCH.patch
- desc < $TXT
- echo
-}
-
-for i in $*
-do
- desc1 $i
-done
+++ /dev/null
-DB=applied-patches
-
-#
-# Work out where the user's pc/, patch/ and txt/ directories live.
-#
-# If the user specified PATCHSCRIPTS in environment then use that (it's
-# probably a relative path)
-#
-# If there is a directory ./patch-scripts then use that
-#
-# Otherwise use "."
-#
-
-if [ x$PATCHSCRIPTS != x ]
-then
- P=$PATCHSCRIPTS
-elif [ -d ./patch-scripts ]
-then
- P=./patch-scripts
-elif [ -d ./patches ]
-then
- P=.
-else
- echo "could not locate your pc/ and patches/ directories"
- exit 1
-fi
-
-top_patch()
-{
- tail -1 $DB
-}
-
-die()
-{
- echo error: $*
- exit 1
-}
-
-is_numeric()
-{
- if echo $1 | egrep '^[0-9]*$' > /dev/null
- then
- return 0
- fi
- return 1
-}
-
-is_applied_last()
-{
- name="$(stripit $1)"
- top_patch >$DB.1
- if grep "^$name$" "$DB.1" > /dev/null 2>&1
- then
- rm $DB.1
- return 0
- else
- rm $DB.1
- return 1
- fi
-}
-
-is_applied()
-{
- name=$(stripit "$1")
- if grep "^$name$" "$DB" > /dev/null 2>&1
- then
- return 0
- else
- return 1
- fi
-}
-
-can_apply()
-{
- if patch -p1 --dry-run -i "$1" -f
- then
- return 0
- else
- return 1
- fi
-}
-
-can_remove()
-{
- if patch -R -p1 --dry-run -i $P/patches/"$1".patch -f
- then
- return 0
- else
- return 1
- fi
-}
-
-remove_from_db()
-{
- tmpfile=$(mktemp /tmp/p_XXXXXX)
- name="$1"
- sed -e "/^$name$/d" < "$DB" > $tmpfile
- mv $tmpfile "$DB"
-}
-
-stripit()
-{
- ret=$(basename $1)
- ret=$(echo $ret | sed -e 's/\.patch$//')
- ret=$(echo $ret | sed -e 's/\.pc$//')
- ret=$(echo $ret | sed -e 's/\.txt$//')
- echo $ret
-}
-
-top_is_current()
-{
- patch_name=$(top_patch)
- if [ x$patch_name == x ]
- then
- return 1
- else
- patch_file=$P/patches/"$patch_name".patch
- files=$(cat $P/pc/$patch_name.pc)
- for file in $files
- do
- if [ $file -nt $patch_file ]
- then
- echo $file newer than $patch_file
- return 0
- fi
- done
- fi
- return 1
-}
-
-need_top_current()
-{
- if top_is_current
- then
- echo "Error: Top patch is not up-to-date"
- exit 1
- fi
-}
-
-warn_top_current()
-{
- if top_is_current
- then
- echo "Warning: Top patch is not up-to-date"
- fi
-}
-
-file_in_patch()
-{
- file=$1
- patch=$2
-
- if [ -e $P/pc/$patch.pc ]
- then
- if grep "^"$file"$" $P/pc/$patch.pc > /dev/null
- then
- return 0
- fi
- fi
- return 1
-}
-
-# copy_file_to_bup filename patchname
-copy_file_to_bup()
-{
- file=$1
- patch=$2
- bup="$file"~"$patch"
-
- if [ -e $bup ]
- then
- echo "Cannot install file $file in patch $patch: backup $bup exists"
- exit 1
- fi
-
- if [ -e $file ]
- then
- cp $file "$file"~"$patch"
- else
- echo "file $file appears to be newly added"
- fi
-}
-
-install_file_in_patch()
-{
- file=$1
- patch=$2
-
- copy_file_to_bup $file $patch
- echo $file >> $P/pc/$patch.pc
-# touch $P/txt/$patch.txt
-}
-
-need_file_there()
-{
- if [ ! -e $1 ]
- then
- echo "File $1 does not exist"
- exit 1
- fi
-}
-
-desc()
-{
- state=0
- while read x
- do
- if [ x"$x" = xDESC ]
- then
- state=1
- elif [ x"$x" = xEDESC ]
- then
- state=0
- elif [ $state = 1 ]
- then
- echo " $x"
- fi
- done
-}
-
-body()
-{
- file=$1
-
- did_stuff=0
- while read x
- do
- if [ x"$x" = xEDESC ]
- then
- cat
- did_stuff=1
- fi
- done < $file
-
- if [ $did_stuff = 0 ]
- then
- cat $file
- fi
-}
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "pcpatch: recreate the pc file from patches/{patchname}.patch"
- exit 1
-}
-
-doit()
-{
- echo $* 1>&2
- $* || {
- echo oops
- exit 1
- }
-}
-
-if [ $# != 1 -o "$1" = "help" ]
-then
- usage
-fi
-PATCH=$1
-PATCH_NAME=$(stripit $PATCH)
-PC=$P/pc/$PATCH_NAME.pc
-
-if [ ! -e $P/patches/$PATCH_NAME.patch ]
-then
- echo "$P/patches/$PATCH_NAME.patch does not exist"
- exit 1
-fi
-
-if is_applied "$PATCH"
-then
- echo $PATCH is applied!
- exit 1
-fi
-
-touched-by-patch $P/patches/$PATCH_NAME.patch > $PC
-echo Recreated $PC
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: poppatch [npatches]"
- exit 1
-}
-
-doit()
-{
- echo $* 1>&2
- $* || {
- echo oops
- exit 1
- }
-}
-
-if [ $# -gt 1 ]
-then
- usage
-fi
-
-NR=1
-STOP_AT=""
-if [ $# -eq 1 ]
-then
- if is_numeric $1
- then
- NR=$1
- else
- NR=1000
- STOP_AT=$(stripit $1)
- fi
-fi
-
-pop_one()
-{
- TOP_PATCH=$(top_patch)
- if [ x$TOP_PATCH == x ]
- then
- echo "no patches applied"
- exit 0
- else
- popped_patch="$(top_patch)"
- if ! rpatch $(top_patch)
- then
- echo still at $(top_patch)
- exit 1
- fi
- echo
- fi
-}
-
-for i in $(seq 1 $NR)
-do
- pop_one
- if [ x$STOP_AT != "x" ]
- then
- if [ $STOP_AT == $(toppatch) ]
- then
- exit 0
- fi
- fi
-done
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-if [ $# -ne 1 ]
-then
- echo "Usage prep-patch patchname"
- exit 1
-fi
-
-PATCHNAME=$(stripit $1)
-
-xcb -s 2 < $P/patches/$PATCHNAME.patch
-head -2 $P/txt/$PATCHNAME.txt | tail -1 | tr -d '\n' | xcb -s 1
+++ /dev/null
-#!/bin/sh
-
-# print out patch status. Usage: pstatus [ patchfile ... ]
-#
-# Stephen Cameron <steve.cameron@hp.com>
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-if [ ! -f ./series ]
-then
- echo "./series does not exist." 1>&2
- exit 1
-fi
-
-if [ ! -d ./patches ]
-then
- echo "Directory ./patches does not exist." 1>&2
- exit 1
-fi
-
-
-PATCHLIST="$*"
-if [ "$PATCHLIST" = "" ]
-then
- series_optimize=yes
- PATCHLIST=`cat series | sed -e 's/[.]patch[ ]*$//'`
- SORTSERIES=`mktemp /tmp/ser.XXXXXX` || exit 1
- SORTPATCHES=`mktemp /tmp/pat.XXXXXX` || exit 1
- sed -e 's/^[ ]//' -e 's/[.]patch[ ]*$//' < series | \
- sort > $SORTSERIES
- exists="`echo $P/patches/*.patch 2>/dev/null`"
- if [ "$exists" != "$P/patches/*.patch" ]
- then
- ls -1 $P/patches/*.patch | sed -e 's/^.*\/patches\///' \
- -e 's/[.]patch[ ]*$//' | sort > $SORTPATCHES
- PATCHLIST="$PATCHLIST"" `comm -1 -3 $SORTSERIES $SORTPATCHES`"
- fi
- rm -f $SORTPATCHES $SORTSERIES
-else
- series_optimize=no
-fi
-
-NSERIES=`wc -l series | awk '{ print $1; }'`
-series=1
-for PATCH_NAME in $PATCHLIST
-do
- PATCH_NAME=$(stripit $PATCH_NAME)
- # see if this patch even exists
- if [ ! -f $P/patches/"$PATCH_NAME".patch ]
- then
- echo "$PATCH_NAME does not exist."
- continue
- fi
- # see if this patch is applied
- applied="-"
- if [ -f applied-patches ]
- then
- grep '^'"$PATCH_NAME"'$' applied-patches > /dev/null
- if [ "$?" = "0" ]
- then
- applied="a"
- fi
- fi
-
- # figure the status of this patch, that is,
- # if it needs changelog, pcpatch, refpatch
-
- stat=""
- if [ ! -f $P/txt/"$PATCH_NAME".txt ]
- then
- stat="changelog "
- fi
- if [ ! -f $P/pc/"$PATCH_NAME".pc ]
- then
- stat="$stat""pcpatch "
- elif [ "$applied" != '-' ]
- then
- rpatch=n
-
- # for each file this patch touches
- for y in `cat $P/pc/"$PATCH_NAME".pc`
- do
- # is the patch adding the file?
- if [ ! -e "$y"'~'"$PATCH_NAME" -a -f "$y" ]
- then
- # file is newer than the patch?
- if [ "$y" -nt $P/patches/"$PATCH_NAME".patch ]
- then
- rpatch=y
- stat="$stat""refpatch "
- break
- fi
- else
- # modified file is newer than the patch?
- if [ "$y"'~'"$PATCH_NAME" -nt \
- $P/patches/"$PATCH_NAME".patch ]
- then
- rpatch=y
- stat="$stat""refpatch "
- break
- fi
- if [ "`toppatch`" = "$PATCH_NAME" -a \
- "$y" -nt $P/patches/"$PATCH_NAME".patch ]
- then
- # toppatch, so check if the file
- # is newer than the patch?
- rpatch=y
- stat="$stat""refpatch "
- break
- fi
- fi
- done
- fi
- # check if they changed the changelog recently
- if [ "$rpatch" = "n" -a -f $P/txt/"$PATCH_NAME".txt \
- -a $P/txt/"$PATCH_NAME".txt -nt \
- $P/patches/"$PATCH_NAME".patch ]
- then
- rpatch=y
- stat="$stat""refpatch "
- fi
- if [ "$stat" != "" ]
- then
- stat="Needs ""$stat"
- fi
-
- if [ "$series_optimize" != "yes" ]
- then
- # have to find the series number the hard way.
- series=`grep -n '^'"$PATCH_NAME"'\.patch$' series |\
- awk -F: '{ printf "%d", $1}' `
- if [ "$series" = "" ]
- then
- series="?"
- fi
- fi
-
- echo "$series":"$applied":"$PATCH_NAME $stat"
-
- if [ "$series_optimize" = "yes" ]
- then
- if [ "$series" != "?" ]
- then
- series=`expr $series + 1`
- if [ $series -gt $NSERIES ]
- then
- series="?"
- fi
- fi
- fi
-done
+++ /dev/null
-#!/bin/sh
-
-#
-# Bring up a patched file in tkdiff. We show the diffs
-# in the topmost patch, unless it was specified
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: ptkdiff filename ..."
- echo " ptkdiff -"
- exit 1
-}
-
-PATCH_NAME=$(top_patch)
-
-doit()
-{
- filename=$1
- unpatched_file=$filename"~"$PATCH_NAME
- need_file_there $filename
- if [ -e $unpatched_file ]
- then
- tkdiff $unpatched_file $filename
- else
- echo ptkdiff: $filename appears to not be in $PATCH_NAME
- fi
-}
-
-if [ x"$1" = "x-" ]
-then
- FILENAME=$(cat $P/pc/$PATCH_NAME.pc)
-else
- FILENAME="$*"
-fi
-
-for i in $FILENAME
-do
- doit $i &
-done
+++ /dev/null
-#!/bin/sh
-
-#
-# Add next patch in series
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: pushpatch [npatches]"
- exit 1
-}
-
-opt_force=0
-
-for i in $*
-do
- case "$i" in
- -f)
- opt_force=1;;
- *)
- if [ -n "$NR" -o -n "$STOP_AT" ]
- then
- usage
- fi
- if is_numeric $i
- then
- NR=$i
- else
- NR=1000
- STOP_AT=$(stripit $i)
- fi;;
- esac
-done
-
-[ $opt_force = 1 ] && force="-f"
-
-SERIES=series
-
-if [ ! -e $SERIES ]
-then
- echo 'File "series" not found'
- exit 1
-fi
-
-push_one()
-{
- top=$(toppatch)
- if [ x"$top" == x ]
- then
- todo=$(head -1 $SERIES)
- else
- last_in_series=$(stripit $(tail -1 $SERIES))
- if [ $last_in_series == $top ]
- then
- echo "Series fully applied. Ends at $top"
- exit 0
- fi
- todo=$(grep -C1 "^$top\.patch" $SERIES | tail -1)
- if [ x$todo = x ]
- then
- todo=$(head -1 $SERIES)
- fi
- fi
-
- apatch $force $todo
-}
-
-for i in $(seq 1 $NR)
-do
- push_one
- if [ x$STOP_AT != "x" ]
- then
- if [ $STOP_AT == $(toppatch) ]
- then
- exit 0
- fi
- fi
-done
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: refpatch"
- exit 1
-}
-
-doit()
-{
- echo $* 1>&2
- $* || {
- echo oops
- exit 1
- }
-}
-
-if [ $# != 0 ]
-then
- usage
-fi
-
-TOP_PATCH=$(top_patch)
-mpatch $* $(top_patch)
-echo "Refreshed $TOP_PATCH"
+++ /dev/null
-#!/bin/sh
-# Extract names of new files from a patch, print them out
-
-PATCHFILE=$1
-case "$PATCHFILE" in
-*.gz) CMD="gzip -d < $PATCHFILE";;
-*) CMD="cat $PATCHFILE";;
-esac
-
-TMP=$(mktemp /tmp/rbp-XXXXXX)
-
-eval $CMD | egrep '^\+\+\+.*1970|\+\+\+.*1969' > $TMP
-sed -e 's@[^/]*/\([^ ]*\).*@\1@' < $TMP | sed -e 's@^linux/@@' | sort
-rm -f $TMP
+++ /dev/null
-#!/bin/sh
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-OLD=$(stripit $1)
-NEW=$(stripit $2)
-
-mv $P/pc/$OLD.pc $P/pc/$NEW.pc
-mv $P/patches/$OLD.patch $P/patches/$NEW.patch
-mv $P/txt/$OLD.txt $P/txt/$NEW.txt
-
-cvs remove $P/pc/$OLD.pc
-cvs remove $P/patches/$OLD.patch
-cvs remove $P/txt/$OLD.txt
-
-cvs add $P/pc/$NEW.pc
-cvs add $P/patches/$NEW.patch
-cvs add $P/txt/$NEW.txt
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: rolled-up-patch"
- exit 1
-}
-
-if [ $# != 0 ]
-then
- usage
-fi
-
-RUP=$(mktemp /tmp/rup-XXXXXX)
-rm -f $RUP
-
-for i in $(cat applied-patches)
-do
- patch_name=$(stripit $i)
- cat $P/pc/$patch_name.pc
-done | sort | uniq > $RUP
-
-kdiff $(cat $RUP)
-rm -f $RUP
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-do_remove()
-{
- if patch -R -p1 -s -i $P/patches/"$1".patch
- then
- true
- else
- echo SOMETHING WENT WRONG
- exit 1
- fi
-}
-
-kill_old_ones()
-{
- FILES=$(cat $P/pc/$1.pc)
- for file in $FILES
- do
- rm -f "$file"~"$1"
- done
-}
-
-usage()
-{
- echo "Usage: rpatch patchname"
- exit 1
-}
-
-if [ $# == 0 ]
-then
- usage
-fi
-
-PATCH_NAME=$(stripit $1)
-
-warn_top_current
-
-if is_applied "$PATCH_NAME"
-then
- if can_remove "$PATCH_NAME"
- then
- do_remove "$PATCH_NAME"
- kill_old_ones "$PATCH_NAME"
- remove_from_db "$PATCH_NAME"
- else
- echo "$PATCH_NAME" does not remove cleanly
- exit 1
- fi
-else
- echo "$PATCH_NAME" is not applied
- exit 1
-fi
-
-top=$(top_patch)
-if [ x"$top" == x ]
-then
- msg="no patches applied"
-else
- msg="now at $top"
-fi
-
-echo Removed $PATCH_NAME, $msg
-
+++ /dev/null
-#!/usr/bin/perl -w
-$out = "";
-while (<>) {
- next if (/^Only/);
- next if (/^Binary/);
- if (/^diff/ || /^Index/) {
- if ($out) {
- close OUT;
- }
- (@out) = split(' ', $_);
- shift(@out) if (/^diff/);
- $out = pop(@out);
- $out =~ s:/*usr/:/:;
- $out =~ s:/*src/:/:;
- $out =~ s:^/*linux[^/]*::;
- $out =~ s:\(w\)::;
- next if ($out eq "");
- $out = "/var/tmp/patches/$out";
- $dir = $out;
- $dir =~ s:/[^/]*$::;
- print STDERR "$out\n";
- system("mkdir -p $dir");
- open(OUT, ">$out") || die("cannot open $out");
- }
- if ($out) {
- print OUT $_;
- }
-}
-
+++ /dev/null
-#!/bin/sh
-
-# tag-series tagname series-file-name
-#
-# Does a `cvs tag tagname' of all the .pc, .txt and .patch files mentioned
-# in series-file-name. Also tags series-file-name.
-#
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-# tag_one tag patchname
-#
-tag_one()
-{
- PN=$(stripit $2)
- if [ -r $P/txt/$PN.txt ]
- then
- cvs tag $1 $P/pc/$PN.pc $P/patches/$PN.patch $P/txt/$PN.txt
- else
- cvs tag $1 $P/pc/$PN.pc $P/patches/$PN.patch
- fi
-}
-
-if [ $# -ne 2 ]
-then
- echo Usage: tag-series tagname series-file-name
- exit 1
-fi
-
-TAG=$1
-SERIES=$2
-
-for p in $(cat $SERIES)
-do
- tag_one $TAG $p
-done
-cvs tag $TAG $SERIES
+++ /dev/null
-#!/bin/sh
-
-. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
- echo "Impossible to find my library 'patchfns'."
- echo "Check your install, or go to the right directory"
- exit 1
-}
-
-usage()
-{
- echo "Usage: toppatch"
- exit 1
-}
-
-if [ $# != 0 ]
-then
- usage
-fi
-
-if [ -e $DB ]
-then
- TOP_PATCH=$(top_patch)
- if [ x$TOP_PATCH != x ]
- then
- echo $TOP_PATCH
- fi
-fi
+++ /dev/null
-#!/bin/sh
-# Extract names of new files from a patch, print them out
-
-PATCHFILE=$1
-case "$PATCHFILE" in
-*.gz) CMD="gzip -d < $PATCHFILE";;
-*) CMD="cat $PATCHFILE";;
-esac
-
-TMP=$(mktemp /tmp/tbp-XXXXXX) || exit 1
-TMP2=$(mktemp /tmp/tbp2-XXXXXX) || exit 1
-
-eval $CMD | egrep '^\+\+\+ |^\-\-\- ' > $TMP
-
-cat $TMP | sed -e 's@[^/]*/\([^ ]*\).*@\1@' \
- | grep -v '^dev\/null$' \
- | sort \
- | uniq \
- > $TMP2
-
-rm -f $TMP
-grep < $TMP2 '^[+][+][+]' > /dev/null
-if [ "$?" = "0" ]
-then
- echo "WARNING: $PATCHFILE appears to be -p0 form rather than -p1." 1>&2
- echo " Use "\'"p0-2-p1 . . < $PATCHFILE"\'" to fix" 1>&2
- awk '{ print $2 }' < $TMP2
-else
- cat $TMP2
-fi | grep -v '~'
-
-rm -f $TMP2
+++ /dev/null
-#!/usr/bin/python
-
-import sys
-import re
-import string
-
-#TODO
-# clean up rest/file
-# clean up +6 and like (assumptions). should be turned into 'find'
-# make regession tests for all cases (Only in, etc)
-
-try:
- filename = sys.argv[1]
-except:
- print 'requires a file name'
- sys.exit(1)
-
-filefd = open(filename)
-file = filefd.read()
-filefd.close()
-
-rest = file
-pat = "(^(?:diff .*\n)?--- .*\n\+\+\+ .*)?\n@@ -(\d+),?(\d+)? \+(\d+),?(\d+)? @@|^(Only in .*)"
-startpat = re.compile(pat, re.M)
-
-pos = 0
-oldpos = 0
-filelen = len(rest)
-oldrest = ""
-while(1):
- rexp = startpat.search(rest)
- if not rexp:
- break
-
- if rexp.group(6):
- print rexp.group(6)
- rest = rest[rexp.end(6)+1:]
- continue
-
- header = rexp.group(1)
- orgfile_start = string.atoi(rexp.group(2))
- if rexp.group(3):
- orgfile_len = string.atoi(rexp.group(3))
- else:
- orgfile_len = -1
- newfile_start = string.atoi(rexp.group(4))
- if rexp.group(5):
- newfile_len = string.atoi(rexp.group(5))
- else:
- newfile_len = -1
- rest = rest[rexp.start(2):]
- rest = rest[string.find(rest, "\n")+1:]
-
- rexp2 = startpat.search(rest)
- if rexp2:
- if rexp2.start(6) != -1:
- oldrest = rest[rexp2.start(6)-1:]
- rest = rest[:rexp2.start(6)]
- elif rexp2.start(1) == -1:
- oldrest = rest[rexp2.start(2)-5:]
- rest = rest[:rexp2.start(2)-4]
- else:
- oldrest = rest[rexp2.start(1)-1:]
- rest = rest[:rexp2.start(1)]
- else:
- oldrest = rest
-
-# pos = filelen - len(oldrest)
-# if pos - oldpos > 100:
-# sys.stderr.write(`pos`+'/'+`filelen`+'\n')
-# oldpos = pos
-
- first = 1
- oldminuses = 0
- oldplusses = 0
- oldoffset = 0
- while(1):
- #erstat early line stuff med lookbehind paa {1,2}-dims
- #nedenfor RAA
- linepat = "^([^-+\n]*)\n?(((^[-+].*\n)|^(.*\n){1,2}(?=^[-+].*\n))+)(.*)\n?"
- compat = re.compile(linepat, re.M)
- rexp = compat.search(rest)
- if not rexp:
- break
-
- prematch = rexp.group(1)
- match = rexp.group(2)
- muddle = len(match)
-
-# print rest
-# print 'prematch ', rexp.start(1), rexp.end(1), prematch
-# print 'match ---------'
-# print match
-# print 'match --------'
-
- # dump unwanted early lines...
- if match[0] != "+" and match[0] != "-":
- while(1):
- next = string.find(match, '\n')
- if next == -1:
- break
- if match[next+1] == "+" or match[next+1] == "-":
- prematch = match[:next]
- match = match[next+1:]
- break
- match = match[next+1:]
-
-
-# print 'prematch ', rexp.start(1), rexp.end(1), len(prematch)
-# print '('+prematch+')'
-# if prematch == ' ':
-# print 'space'
- muddle = muddle - len(match)
-
- lines = string.count(match, "\n")
- compat = re.compile("^-", re.M)
- minuses = len(compat.findall(match))
- compat = re.compile("^\+", re.M)
- plusses = len(compat.findall(match))
- orgsize = minuses + 2 + (lines - minuses - plusses)
- newsize = plusses + 2 + (lines - minuses - plusses)
-
- noeol = "^(\\\ No newline at end of file)$"
- compnoeol = re.compile(noeol, re.M)
- if compnoeol.search(match) or compnoeol.search(rexp.group(6)):
- orgsize = orgsize - 1
- newsize = newsize - 1
-
- coherent = 0
- if lines - plusses == 0:
- coherent = 1
- elif lines - minuses == 0:
- coherent = 1
-
- # RAA FIXME
- if not len(prematch):#or len(prematch) == 1 and prematch == ' ':
- orgsize = orgsize -1
- newsize = newsize -1
- if rexp.start(6) == rexp.end(6):
- orgsize = orgsize -1
- newsize = newsize -1
-
-# print "lines in match: ", lines
-# print "number of minuses: ", minuses
-# print "number of plusses: ", plusses
-
- matchpos = rexp.start(2) + muddle
- offset = string.count(rest[:matchpos], "\n")
-
-# print 'offset/oldoffset: ', offset,oldoffset
-# print 'oldplusses/oldminuses: ', oldplusses, oldminuses
-# print 'orgfile_start/newfile_start: ', orgfile_start, newfile_start
-
- orgstart = orgfile_start + offset + oldoffset - oldplusses
- newstart = newfile_start + offset - oldminuses + oldoffset
-
- # RAA: Bwadr. Fix antagelse om prematch paa en anden
- # maade
- orgstartmod = 0
- newstartmod = 0
- if orgfile_start == 1 and not len(prematch):
- orgstartmod = 1
- if newfile_start == 1 and not len(prematch):
- newstartmod = 1
- if orgfile_start == 0 and orgfile_len == 0:
- orgstartmod = 1
- # RAA Hack!
- plusses = plusses + 1
- minuses = minuses +1
- if newfile_start == 0 and newfile_len == 0:
- newstartmod = 1
- # RAA Hack!
- plusses = plusses + 1
- minuses = minuses +1
-
- if header and first:
- print header
- first = 0
-
- # should the start(1) == 0 be orgstart == 1? RAA
- if orgstart == 1 and newstart == 1 and plusses == 0 and coherent:
- print "@@ -"+`orgstart`+","+`orgsize`+" +"+`newstart`+" @@"
- print match[:string.rfind(match, "\n")]
- print rexp.group(6)
- elif rexp.start(6) == rexp.end(6) and plusses == 0 and coherent:
- if orgstartmod:
- orgstart = orgstart + 1
- if newstartmod:
- newstart = newstart + 1
- print "@@ -"+`orgstart-1`+","+`orgsize`+" +"+`newstart-1`+" @@"
- print prematch
- print match[:string.rfind(match, "\n")]
- elif orgstart == 1 and orgstart == 1 and minuses == 0 and coherent:
- print "@@ -"+`orgstart`+" +"+`newstart`+","+`newsize`+" @@"
- print match[:string.rfind(match, "\n")]
- print rexp.group(6)
- elif rexp.start(6) == rexp.end(6) and minuses == 0 and coherent:
- if orgstartmod:
- orgstart = orgstart + 1
- if newstartmod:
- newstart = newstart + 1
- print "@@ -"+`orgstart-1`+" +"+`newstart-1`+","+`newsize`+" @@"
- print prematch
- print match[:string.rfind(match, "\n")]
- else:
- if orgstartmod:
- orgstart = orgstart + 1
- if newstartmod:
- newstart = newstart + 1
- print "@@ -"+`orgstart-1`+","+`orgsize`+" +"+`newstart-1`+","+`newsize`+" @@"
- if len(prematch):
- print prematch
- print match[:string.rfind(match, "\n")]
- if rexp.start(6) != rexp.end(6):
- print rexp.group(6)
-
- rest = rest[rexp.end(6):]
- oldminuses = minuses + oldminuses
- oldplusses = plusses + oldplusses
- oldoffset = oldoffset + offset + lines #include match()-lines
-
-
- rest = oldrest
+++ /dev/null
-dev_read_only.patch
-exports.patch
-kmem_cache_validate.patch
-lustre_version.patch
-vfs_intent-2.4.18-18.patch
-invalidate_show.patch
-iod-rmap-exports.patch
+++ /dev/null
-dev_read_only_hp.patch
-exports_hp.patch
-kmem_cache_validate_hp.patch
-jbd-transno-cb.patch
-lustre_version.patch
-vfs_intent_hp.patch
-invalidate_show.patch
+++ /dev/null
-dev_read_only_hp.patch
-exports_hp.patch
-kmem_cache_validate_hp.patch
-lustre_version.patch
-vfs_intent_hp.patch
-invalidate_show.patch
-export-truncate.patch
-iod-stock-24-exports_hp.patch
+++ /dev/null
-dev_read_only_hp.patch
-exports_hp.patch
-kmem_cache_validate_hp.patch
-jbd-transno-cb.patch
-lustre_version.patch
-vfs_intent_hp.patch
-invalidate_show.patch
-iod-stock-24-exports_hp.patch
+++ /dev/null
-lin-2.5.44.patch
+++ /dev/null
-dev_read_only.patch
-exports.patch
-kmem_cache_validate.patch
-lustre_version.patch
-uml_check_get_page.patch
-uml_no_panic.patch
-vfs_intent-2.4.18-18.patch
-uml_compile_fixes.patch
+++ /dev/null
-dev_read_only_2.4.20.patch
-exports_2.4.20.patch
-kmem_cache_validate_hp.patch
-lustre_version.patch
-vfs_intent-2.4.20.patch
-invalidate_show.patch
-iod-rmap-exports-2.4.20.patch
-export-truncate.patch
-uml_check_get_page.patch
-uml_no_panic.patch
+++ /dev/null
-dev_read_only.patch
-exports.patch
-kmem_cache_validate.patch
-lustre_version.patch
-uml_check_get_page.patch
-uml_no_panic.patch
-vfs_intent.patch
-uml_compile_fixes.patch
+++ /dev/null
-vanilla-2.4.18
-invalidate_show.patch
+++ /dev/null
-vanilla-2.4.19.patch
-jbd-transno-cb.patch
-invalidate_show.patch
+++ /dev/null
-lustre-2.5.patch
+++ /dev/null
-lustre_version.patch
-lustre-2.5.63.patch
+++ /dev/null
-DESC
-(undescribed patch)
-EDESC
+++ /dev/null
-DESC
-(undescribed patch)
-EDESC
+++ /dev/null
-DESC
-(undescribed patch)
-EDESC
+++ /dev/null
-DESC
-patches for making kernel 2.5.44 ready for mounting Lustre, and some basic
-sys_call.
-EDESC
+++ /dev/null
-DESC
-(undescribed patch)
-EDESC
+++ /dev/null
-DESC
-(undescribed patch)
-EDESC
+++ /dev/null
-DESC
-(undescribed patch)
-EDESC
+++ /dev/null
-DESC
-(undescribed patch)
-EDESC
+++ /dev/null
-DESC
-(undescribed patch)
-EDESC
+++ /dev/null
-series/rh-8.0:
- redhat 2.4.18-14
- redhat 2.4.18-17
-series/rh-2.4.18-18
- redhat 2.4.18-18
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
-libtest
+++ /dev/null
-# Administration utilities Makefile
-DEFS=
-
-CFLAGS:=-g -O2 -I$(top_srcdir)/utils -I$(PORTALS)/include -I$(srcdir)/../include -Wall -L$(PORTALSLIB)
-
-KFLAGS:=
-CPPFLAGS = $(HAVE_LIBREADLINE)
-LIBS=
-LLIBS= ../lov/liblov.a ../obdecho/libobdecho.a ../osc/libosc.a ../ldlm/libldlm.a ../ptlrpc/libptlrpc.a ../obdclass/liblustreclass.a
-
-libtest_LDADD := $(LIBREADLINE) $(LLIBS) \
- $(PORTALS)/user/procbridge/libprocbridge.a $(PORTALS)/user/tcpnal/libtcpnal.a \
- $(PORTALS)/user/util/libtcpnalutil.a $(PORTALS)/user/$(PORTALS)/api/libptlapi.a \
- $(PORTALS)/lib/libptllib.a -lptlctl -lpthread -lefence
-bin_PROGRAMS = libtest
-libtest_SOURCES = libtest.c
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Light Super operations
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <stdlib.h>
-#include <string.h>
-#include <error.h>
-#include <assert.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <sysio.h>
-#include <fs.h>
-#include <mount.h>
-#include <inode.h>
-#include <file.h>
-
-#include "llite_lib.h"
-
-void llu_prepare_mdc_op_data(struct mdc_op_data *data,
- struct inode *i1,
- struct inode *i2,
- const char *name,
- int namelen,
- int mode)
-{
- struct llu_inode_info *lli1, *lli2;
-
- LASSERT(i1);
-
- lli1 = llu_i2info(i1);
- data->ino1 = lli1->lli_st_ino;
- data->gen1 = lli1->lli_st_generation;
- data->typ1 = lli1->lli_st_mode & S_IFMT;
- data->gid1 = lli1->lli_st_gid;
-
- if (i2) {
- lli2 = llu_i2info(i2);
- data->ino2 = lli2->lli_st_ino;
- data->gen2 = lli2->lli_st_generation;
- data->typ2 = lli2->lli_st_mode & S_IFMT;
- data->gid2 = lli2->lli_st_gid;
- } else
- data->ino2 = 0;
-
- data->name = name;
- data->namelen = namelen;
- data->mode = mode;
-}
-
-static struct inode *llu_create_node(struct inode *dir, const char *name,
- int namelen, const void *data, int datalen,
- int mode, __u64 extra,
- struct lookup_intent *it)
-{
- struct inode *inode;
- struct ptlrpc_request *request = NULL;
- struct mds_body *body;
- time_t time = 123456;//time(NULL);
- struct llu_sb_info *sbi = llu_i2sbi(dir);
-
- if (it && it->it_disposition) {
- LBUG();
-#if 0
- ll_invalidate_inode_pages(dir);
-#endif
- request = it->it_data;
- body = lustre_msg_buf(request->rq_repmsg, 1, sizeof(*body));
- } else {
- struct mdc_op_data op_data;
- struct llu_inode_info *lli_dir = llu_i2info(dir);
- int gid = current->fsgid;
- int rc;
-
- if (lli_dir->lli_st_mode & S_ISGID) {
- gid = lli_dir->lli_st_gid;
- if (S_ISDIR(mode))
- mode |= S_ISGID;
- }
-
- llu_prepare_mdc_op_data(&op_data, dir, NULL, name, namelen, 0);
- rc = mdc_create(&sbi->ll_mdc_conn, &op_data,
- data, datalen, mode, current->fsuid, gid,
- time, extra, &request);
- if (rc) {
- inode = (struct inode*)rc;
- goto out;
- }
- body = lustre_msg_buf(request->rq_repmsg, 0, sizeof(*body));
- }
-
- inode = llu_new_inode(dir->i_fs, body->ino, body->mode);
- if (!inode) {
- /* FIXME more cleanup needed? */
- goto out;
- }
-
- llu_update_inode(inode, body, NULL);
-
- if (it && it->it_disposition) {
- /* We asked for a lock on the directory, but were
- * granted a lock on the inode. Since we finally have
- * an inode pointer, stuff it in the lock. */
-#if 0
- ll_mdc_lock_set_inode((struct lustre_handle *)it->it_lock_handle,
- inode);
-#endif
- }
-
- out:
- ptlrpc_req_finished(request);
- return inode;
-}
-
-int llu_create(struct inode *dir, struct pnode_base *pnode, int mode)
-{
- struct inode *inode;
-#if 0
- int rc = 0;
-
- CDEBUG(D_VFSTRACE, "VFS Op:name=%s,dir=%lu,intent=%s\n",
- dentry->d_name.name, dir->i_ino, LL_IT2STR(dentry->d_it));
-
- it = dentry->d_it;
-
- rc = ll_it_open_error(IT_OPEN_CREATE, it);
- if (rc) {
- LL_GET_INTENT(dentry, it);
- ptlrpc_req_finished(it->it_data);
- RETURN(rc);
- }
-#endif
- inode = llu_create_node(dir, pnode->pb_name.name, pnode->pb_name.len,
- NULL, 0, mode, 0, NULL);
-
- if (IS_ERR(inode))
- RETURN(PTR_ERR(inode));
-
- pnode->pb_ino = inode;
-
- return 0;
-}
-
-static int llu_create_obj(struct lustre_handle *conn, struct inode *inode,
- struct lov_stripe_md *lsm)
-{
- struct ptlrpc_request *req = NULL;
- struct llu_inode_info *lli = llu_i2info(inode);
- struct lov_mds_md *lmm = NULL;
- struct obdo *oa;
- struct iattr iattr;
- struct mdc_op_data op_data;
- int rc, err, lmm_size = 0;;
- ENTRY;
-
- oa = obdo_alloc();
- if (!oa)
- RETURN(-ENOMEM);
-
- oa->o_mode = S_IFREG | 0600;
- oa->o_id = lli->lli_st_ino;
- /* Keep these 0 for now, because chown/chgrp does not change the
- * ownership on the OST, and we don't want to allow BA OST NFS
- * users to access these objects by mistake.
- */
- oa->o_uid = 0;
- oa->o_gid = 0;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE |
- OBD_MD_FLUID | OBD_MD_FLGID;
-
- rc = obd_create(conn, oa, &lsm, NULL);
- if (rc) {
- CERROR("error creating objects for inode %lu: rc = %d\n",
- lli->lli_st_ino, rc);
- if (rc > 0) {
- CERROR("obd_create returned invalid rc %d\n", rc);
- rc = -EIO;
- }
- GOTO(out_oa, rc);
- }
-
- LASSERT(lsm && lsm->lsm_object_id);
- rc = obd_packmd(conn, &lmm, lsm);
- if (rc < 0)
- GOTO(out_destroy, rc);
-
- lmm_size = rc;
-
- /* Save the stripe MD with this file on the MDS */
- memset(&iattr, 0, sizeof(iattr));
- iattr.ia_valid = ATTR_FROM_OPEN;
-
- llu_prepare_mdc_op_data(&op_data, inode, NULL, NULL, 0, 0);
-
- rc = mdc_setattr(&llu_i2sbi(inode)->ll_mdc_conn, &op_data,
- &iattr, lmm, lmm_size, &req);
- ptlrpc_req_finished(req);
-
- obd_free_diskmd(conn, &lmm);
-
- /* If we couldn't complete mdc_open() and store the stripe MD on the
- * MDS, we need to destroy the objects now or they will be leaked.
- */
- if (rc) {
- CERROR("error: storing stripe MD for %lu: rc %d\n",
- lli->lli_st_ino, rc);
- GOTO(out_destroy, rc);
- }
- lli->lli_smd = lsm;
-
- EXIT;
-out_oa:
- obdo_free(oa);
- return rc;
-
-out_destroy:
- obdo_from_inode(oa, inode, OBD_MD_FLTYPE);
- oa->o_id = lsm->lsm_object_id;
- oa->o_valid |= OBD_MD_FLID;
- err = obd_destroy(conn, oa, lsm, NULL);
- obd_free_memmd(conn, &lsm);
- if (err) {
- CERROR("error uncreating inode %lu objects: rc %d\n",
- lli->lli_st_ino, err);
- }
- goto out_oa;
-}
-
-/* FIXME currently no "it" passed in */
-static int llu_local_open(struct llu_inode_info *lli, struct lookup_intent *it)
-{
- struct ll_file_data *fd;
-#if 0
- struct ptlrpc_request *req = it->it_data;
- struct mds_body *body = lustre_msg_buf(req->rq_repmsg, 1);
- ENTRY;
-#endif
- LASSERT(!lli->lli_file_data);
-
- fd = malloc(sizeof(struct ll_file_data));
- /* We can't handle this well without reorganizing ll_file_open and
- * ll_mdc_close, so don't even try right now. */
- LASSERT(fd != NULL);
-
- memset(fd, 0, sizeof(*fd));
-#if 0
- memcpy(&fd->fd_mds_och.och_fh, &body->handle, sizeof(body->handle));
- fd->fd_mds_och.och_req = it->it_data;
-#endif
- lli->lli_file_data = fd;
-
- RETURN(0);
-}
-
-static int llu_osc_open(struct lustre_handle *conn, struct inode *inode,
- struct lov_stripe_md *lsm)
-{
- struct ll_file_data *fd = llu_i2info(inode)->lli_file_data;
- struct obdo *oa;
- int rc;
- ENTRY;
-
- oa = obdo_alloc();
- if (!oa)
- RETURN(-ENOMEM);
- oa->o_id = lsm->lsm_object_id;
- oa->o_mode = S_IFREG;
- oa->o_valid = (OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLBLOCKS |
- OBD_MD_FLMTIME | OBD_MD_FLCTIME);
- rc = obd_open(conn, oa, lsm, NULL, &fd->fd_ost_och);
- if (rc)
- GOTO(out, rc);
-
-// file->f_flags &= ~O_LOV_DELAY_CREATE;
- obdo_to_inode(inode, oa, OBD_MD_FLBLOCKS | OBD_MD_FLMTIME |
- OBD_MD_FLCTIME);
-
- EXIT;
-out:
- obdo_free(oa);
- return rc;
-}
-
-static int llu_file_open(struct inode *inode)
-{
-#if 0
- struct llu_sb_info *sbi = llu_i2sbi(inode);
-#endif
- struct llu_inode_info *lli = llu_i2info(inode);
- struct lustre_handle *conn = llu_i2obdconn(inode);
- struct lookup_intent *it;
- struct lov_stripe_md *lsm;
- int rc = 0;
-
-#if 0
- CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu\n", inode->i_ino);
- LL_GET_INTENT(file->f_dentry, it);
- rc = ll_it_open_error(IT_OPEN_OPEN, it);
- if (rc)
- RETURN(rc);
-#endif
- rc = llu_local_open(lli, it);
- if (rc)
- LBUG();
-#if 0
- mdc_set_open_replay_data(&((struct ll_file_data *)
- file->private_data)->fd_mds_och);
-#endif
- lsm = lli->lli_smd;
- if (lsm == NULL) {
-#if 0
- if (file->f_flags & O_LOV_DELAY_CREATE) {
- CDEBUG(D_INODE, "delaying object creation\n");
- RETURN(0);
- }
-#endif
- if (!lli->lli_smd) {
- rc = llu_create_obj(conn, inode, NULL);
- if (rc)
- GOTO(out_close, rc);
- } else {
- CERROR("warning: stripe already set on ino %lu\n",
- lli->lli_st_ino);
- }
- lsm = lli->lli_smd;
- }
-
- rc = llu_osc_open(conn, inode, lsm);
- if (rc)
- GOTO(out_close, rc);
- RETURN(0);
-
- out_close:
-// ll_mdc_close(&sbi->ll_mdc_conn, inode, file);
- return rc;
-}
-
-int llu_iop_open(struct pnode *pnode, int flags, mode_t mode)
-{
- struct inode *dir = pnode->p_parent->p_base->pb_ino;
- int rc;
- /* FIXME later we must add the ldlm here */
-
- LASSERT(dir);
-
- /* libsysio forgot to guarentee mode is valid XXX */
- mode |= S_IFREG;
-
- if (!pnode->p_base->pb_ino) {
- rc = llu_create(dir, pnode->p_base, mode);
- if (rc)
- return rc;
- }
-
- LASSERT(pnode->p_base->pb_ino);
- return llu_file_open(pnode->p_base->pb_ino);
-}
-
-
-static int llu_mdc_close(struct lustre_handle *mdc_conn, struct inode *inode)
-{
- struct llu_inode_info *lli = llu_i2info(inode);
- struct ll_file_data *fd = lli->lli_file_data;
- struct ptlrpc_request *req = NULL;
- unsigned long flags;
- struct obd_import *imp;
- int rc;
-
- /* FIXME add following code later FIXME */
-#if 0
- /* Complete the open request and remove it from replay list */
- rc = mdc_close(&ll_i2sbi(inode)->ll_mdc_conn, lli->lli_st_ino,
- inode->i_mode, &fd->fd_mds_och.och_fh, &req);
- if (rc)
- CERROR("inode %lu close failed: rc = %d\n",
- lli->lli_st_ino, rc);
-
- imp = fd->fd_mds_och.och_req->rq_import;
- LASSERT(imp != NULL);
- spin_lock_irqsave(&imp->imp_lock, flags);
-
- DEBUG_REQ(D_HA, fd->fd_mds_och.och_req, "matched open req %p",
- fd->fd_mds_och.och_req);
-
- /* We held on to the request for replay until we saw a close for that
- * file. Now that we've closed it, it gets replayed on the basis of
- * its transno only. */
- fd->fd_mds_och.och_req->rq_replay = 0;
-
- if (fd->fd_mds_och.och_req->rq_transno) {
- /* This open created a file, so it needs replay as a
- * normal transaction now. Our reference to it now
- * effectively owned by the imp_replay_list, and it'll
- * be committed just like other transno-having
- * requests from here on out. */
-
- /* We now retain this close request, so that it is
- * replayed if the open is replayed. We duplicate the
- * transno, so that we get freed at the right time,
- * and rely on the difference in xid to keep
- * everything ordered correctly.
- *
- * But! If this close was already given a transno
- * (because it caused real unlinking of an
- * open-unlinked file, f.e.), then we'll be ordered on
- * the basis of that and we don't need to do anything
- * magical here. */
- if (!req->rq_transno) {
- req->rq_transno = fd->fd_mds_och.och_req->rq_transno;
- ptlrpc_retain_replayable_request(req, imp);
- }
- spin_unlock_irqrestore(&imp->imp_lock, flags);
-
- /* Should we free_committed now? we always free before
- * replay, so it's probably a wash. We could check to
- * see if the fd_req should already be committed, in
- * which case we can avoid the whole retain_replayable
- * dance. */
- } else {
- /* No transno means that we can just drop our ref. */
- spin_unlock_irqrestore(&imp->imp_lock, flags);
- }
- ptlrpc_req_finished(fd->fd_mds_och.och_req);
-
- /* Do this after the fd_req->rq_transno check, because we don't want
- * to bounce off zero references. */
- ptlrpc_req_finished(req);
- fd->fd_mds_och.och_fh.cookie = DEAD_HANDLE_MAGIC;
-#endif
- lli->lli_file_data = NULL;
- free(fd);
-
- RETURN(-abs(rc));
-}
-
-static int llu_file_release(struct inode *inode)
-{
- struct llu_sb_info *sbi = llu_i2sbi(inode);
- struct llu_inode_info *lli = llu_i2info(inode);
- struct lov_stripe_md *lsm = lli->lli_smd;
- struct ll_file_data *fd;
- struct obdo oa;
- int rc = 0, rc2;
-
- fd = lli->lli_file_data;
- if (!fd) /* no process opened the file after an mcreate */
- RETURN(rc = 0);
-
- /* we might not be able to get a valid handle on this file
- * again so we really want to flush our write cache.. */
- if (S_ISREG(inode->i_mode) && lsm) {
- memset(&oa, 0, sizeof(oa));
- oa.o_id = lsm->lsm_object_id;
- oa.o_mode = S_IFREG;
- oa.o_valid = OBD_MD_FLTYPE | OBD_MD_FLID;
-
- memcpy(&oa.o_inline, &fd->fd_ost_och, FD_OSTDATA_SIZE);
- oa.o_valid |= OBD_MD_FLHANDLE;
-
- rc = obd_close(&sbi->ll_osc_conn, &oa, lsm, NULL);
- if (rc)
- CERROR("inode %lu object close failed: rc = "
- "%d\n", lli->lli_st_ino, rc);
- }
-
- rc2 = llu_mdc_close(&sbi->ll_mdc_conn, inode);
- if (rc2 && !rc)
- rc = rc2;
-
- RETURN(rc);
-}
-
-int llu_iop_close(struct inode *inode)
-{
- return llu_file_release(inode);
-}
-
-int llu_iop_ipreadv(struct inode *ino,
- struct io_arguments *ioargs,
- struct ioctx **ioctxp)
-{
- struct ioctx *ioctx;
-
- if (!ioargs->ioarg_iovlen)
- return 0;
- if (ioargs->ioarg_iovlen < 0)
- return -EINVAL;
-
- ioctx = _sysio_ioctx_new(ino, ioargs);
- if (!ioctx)
- return -ENOMEM;
-
- ioctx->ioctx_cc = llu_file_read(ino,
- ioctx->ioctx_iovec,
- ioctx->ioctx_iovlen,
- ioctx->ioctx_offset);
- if (ioctx->ioctx_cc < 0)
- ioctx->ioctx_errno = ioctx->ioctx_cc;
-
- *ioctxp = ioctx;
- return 0;
-}
-
-int llu_iop_ipwritev(struct inode *ino,
- struct io_arguments *ioargs,
- struct ioctx **ioctxp)
-{
- struct ioctx *ioctx;
-
- if (!ioargs->ioarg_iovlen)
- return 0;
- if (ioargs->ioarg_iovlen < 0)
- return -EINVAL;
-
- ioctx = _sysio_ioctx_new(ino, ioargs);
- if (!ioctx)
- return -ENOMEM;
-
- ioctx->ioctx_cc = llu_file_write(ino,
- ioctx->ioctx_iovec,
- ioctx->ioctx_iovlen,
- ioctx->ioctx_offset);
- if (ioctx->ioctx_cc < 0)
- ioctx->ioctx_errno = ioctx->ioctx_cc;
-
- *ioctxp = ioctx;
- return 0;
-}
-
+++ /dev/null
-#include <stdio.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include <portals/api-support.h> /* needed for ptpctl.h */
-#include <portals/ptlctl.h> /* needed for parse_dump */
-
-
-#include <liblustre.h>
-#include <linux/obd.h>
-#include <linux/obd_class.h>
-#include <../user/procbridge/procbridge.h>
-
-ptl_handle_ni_t tcpnal_ni;
-
-struct pingcli_args {
- ptl_nid_t mynid;
- ptl_nid_t nid;
- ptl_pid_t port;
- int count;
- int size;
-};
-
-struct task_struct *current;
-
-struct obd_class_user_state ocus;
-
-/* portals interfaces */
-inline const ptl_handle_ni_t *
-kportal_get_ni (int nal)
-{
- return &tcpnal_ni;
-}
-
-inline void
-kportal_put_ni (int nal)
-{
- return;
-}
-
-void init_current(int argc, char **argv)
-{
- current = malloc(sizeof(*current));
- strncpy(current->comm, argv[0], sizeof(current->comm));
- current->pid = getpid();
-
-}
-
-extern ptl_nid_t tcpnal_mynid;
-
-int init_lib_portals(struct pingcli_args *args)
-{
- int rc;
-
- PtlInit();
- tcpnal_mynid = args->mynid;
- rc = PtlNIInit(procbridge_interface, 0, 0, 0, &tcpnal_ni);
- if (rc != 0) {
- CERROR("ksocknal: PtlNIInit failed: error %d\n", rc);
- PtlFini();
- RETURN (rc);
- }
- PtlNIDebug(tcpnal_ni, ~0);
- return rc;
-}
-
-extern int class_handle_ioctl(struct obd_class_user_state *ocus, unsigned int cmd, unsigned long arg);
-
-
-int lib_ioctl(int dev_id, int opc, void * ptr)
-{
-
- if (dev_id == OBD_DEV_ID) {
- struct obd_ioctl_data *ioc = ptr;
- class_handle_ioctl(&ocus, opc, (unsigned long)ptr);
-
- /* you _may_ need to call obd_ioctl_unpack or some
- other verification function if you want to use ioc
- directly here */
- printf ("processing ioctl cmd: %x buf len: %d\n",
- opc, ioc->ioc_len);
- }
- return (0);
-}
-
-int main(int argc, char **argv)
-{
- struct pingcli_args *args;
- args= malloc(sizeof(*args));
- if (!args) {
- printf("Malloc error\n");
- exit(1);
- }
-
- args->mynid = ntohl (inet_addr (argv[1]));
- INIT_LIST_HEAD(&ocus.ocus_conns);
-
- init_current(argc, argv);
- init_obdclass();
- init_lib_portals(args);
- ptlrpc_init();
- ldlm_init();
- osc_init();
- echo_client_init();
- /* XXX need mdc_getlovinfo before lov_init can work.. */
- // lov_init();
-
- parse_dump("/tmp/DUMP_FILE", lib_ioctl);
-
- printf("Hello\n");
- return 0;
-}
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Light Super operations
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <stdlib.h>
-#include <string.h>
-#include <error.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <sysio.h>
-#include <fs.h>
-#include <mount.h>
-#include <inode.h>
-#include <file.h>
-
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include <portals/api-support.h> /* needed for ptpctl.h */
-#include <portals/ptlctl.h> /* needed for parse_dump */
-
-#include "llite_lib.h"
-
-
-ptl_handle_ni_t tcpnal_ni;
-struct task_struct *current;
-struct obd_class_user_state ocus;
-
-/* portals interfaces */
-ptl_handle_ni_t *
-kportal_get_ni (int nal)
-{
- return &tcpnal_ni;
-}
-
-inline void
-kportal_put_ni (int nal)
-{
- return;
-}
-
-struct ldlm_namespace;
-struct ldlm_res_id;
-struct obd_import;
-
-extern int ldlm_cli_cancel_unused(struct ldlm_namespace *ns, struct ldlm_res_id *res_id, int flags);
-extern int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int local_only);
-extern int ldlm_replay_locks(struct obd_import *imp);
-
-void *inter_module_get(char *arg)
-{
- if (!strcmp(arg, "tcpnal_ni"))
- return &tcpnal_ni;
- else if (!strcmp(arg, "ldlm_cli_cancel_unused"))
- return ldlm_cli_cancel_unused;
- else if (!strcmp(arg, "ldlm_namespace_cleanup"))
- return ldlm_namespace_cleanup;
- else if (!strcmp(arg, "ldlm_replay_locks"))
- return ldlm_replay_locks;
- else
- return NULL;
-}
-
-void init_current(char *comm)
-{
- current = malloc(sizeof(*current));
- current->fs = malloc(sizeof(*current->fs));
- current->fs->umask = umask(0777);
- umask(current->fs->umask);
- strncpy(current->comm, comm, sizeof(current->comm));
- current->pid = getpid();
- current->fsuid = 0;
- current->fsgid = 0;
- current->cap_effective = 0;
- memset(¤t->pending, 0, sizeof(current->pending));
-}
-
-ptl_nid_t tcpnal_mynid;
-
-int init_lib_portals()
-{
- int rc;
-
- PtlInit();
- rc = PtlNIInit(procbridge_interface, 0, 0, 0, &tcpnal_ni);
- if (rc != 0) {
- CERROR("ksocknal: PtlNIInit failed: error %d\n", rc);
- PtlFini();
- RETURN (rc);
- }
- PtlNIDebug(tcpnal_ni, ~0);
- return rc;
-}
-
-extern int class_handle_ioctl(struct obd_class_user_state *ocus, unsigned int cmd, unsigned long arg);
-
-struct mount_option_s mount_option = {NULL, NULL};
-
-/* FIXME simple arg parser FIXME */
-void parse_mount_options(void *arg)
-{
- char *buf = NULL;
- struct obd_ioctl_data *data;
- char *ptr, *comma, *eq, **tgt, *v;
- int len;
-
- if (obd_ioctl_getdata(&buf, &len, arg)) {
- CERROR("OBD ioctl: data error\n");
- return;
- }
- data = (struct obd_ioctl_data *)buf;
- ptr = data->ioc_inlbuf1;
- printf("mount option: %s\n", ptr);
-
- while (ptr) {
- eq = strchr(ptr, '=');
- if (!eq)
- return;
-
- *eq = 0;
- if (!strcmp("osc", ptr))
- tgt = &mount_option.osc_uuid;
- else if (!strcmp("mdc", ptr))
- tgt = &mount_option.mdc_uuid;
- else {
- printf("Unknown mount option %s\n", ptr);
- return;
- }
-
- v = eq + 1;
- comma = strchr(v, ',');
- if (comma) {
- *comma = 0;
- ptr = comma + 1;
- } else
- ptr = NULL;
-
- *tgt = malloc(strlen(v)+1);
- strcpy(*tgt, v);
- }
-
- if (buf)
- obd_ioctl_freedata(buf, len);
-}
-
-int lib_ioctl(int dev_id, int opc, void * ptr)
-{
- int rc;
-
- if (dev_id == OBD_DEV_ID) {
- struct obd_ioctl_data *ioc = ptr;
-
- if (opc == OBD_IOC_MOUNTOPT) {
- parse_mount_options(ptr);
- return 0;
- }
-
- rc = class_handle_ioctl(&ocus, opc, (unsigned long)ptr);
-
- /* you _may_ need to call obd_ioctl_unpack or some
- other verification function if you want to use ioc
- directly here */
- printf ("processing ioctl cmd: %x buf len: %d, rc %d\n",
- opc, ioc->ioc_len, rc);
-
- if (rc)
- return rc;
- }
- return (0);
-}
-
-int lllib_init(char *arg)
-{
- tcpnal_mynid = ntohl(inet_addr(arg));
- INIT_LIST_HEAD(&ocus.ocus_conns);
-
- init_current("dummy");
- if (init_obdclass() ||
- init_lib_portals() ||
- ptlrpc_init() ||
- ldlm_init() ||
- mdc_init() ||
- lov_init() ||
- osc_init())
- return -1;
-
- if (parse_dump("/tmp/DUMP_FILE", lib_ioctl))
- return -1;
-
- return _sysio_fssw_register("llite", &llu_fssw_ops);
-}
-
-/* FIXME */
-void generate_random_uuid(unsigned char uuid_out[16])
-{
- int *arr = (int*)uuid_out;
- int i;
-
- for (i = 0; i < sizeof(uuid_out)/sizeof(int); i++)
- arr[i] = rand();
-}
-
+++ /dev/null
-#ifndef __LLU_H_
-#define __LLU_H_
-
-#include <liblustre.h>
-#include <linux/obd.h>
-#include <linux/obd_class.h>
-#include <portals/procbridge.h>
-#include <linux/lustre_lite.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-struct ll_file_data {
- struct obd_client_handle fd_mds_och;
- struct obd_client_handle fd_ost_och;
- __u32 fd_flags;
-};
-
-struct llu_sb_info
-{
- struct obd_uuid ll_sb_uuid;
- struct lustre_handle ll_mdc_conn;
- struct lustre_handle ll_osc_conn;
- obd_id ll_rootino;
- int ll_flags;
- struct list_head ll_conn_chain;
-};
-
-struct llu_inode_info {
- struct llu_sb_info *lli_sbi;
- struct ll_fid lli_fid;
- struct lov_stripe_md *lli_smd;
- char *lli_symlink_name;
- /*struct semaphore lli_open_sem;*/
- unsigned long lli_flags;
- struct list_head lli_read_extents;
-
- /* in libsysio we have no chance to store data in file,
- * so place it here */
- struct ll_file_data *lli_file_data;
-
- /* stat FIXME not 64 bit clean */
- dev_t lli_st_dev;
- ino_t lli_st_ino;
- mode_t lli_st_mode;
- nlink_t lli_st_nlink;
- uid_t lli_st_uid;
- gid_t lli_st_gid;
- dev_t lli_st_rdev;
- loff_t lli_st_size;
- unsigned int lli_st_blksize;
- unsigned int lli_st_blocks;
- time_t lli_st_atime;
- time_t lli_st_mtime;
- time_t lli_st_ctime;
-
- /* not for stat, change it later */
- int lli_st_flags;
- unsigned long lli_st_generation;
-};
-
-static inline struct llu_sb_info *llu_fs2sbi(struct filesys *fs)
-{
- return (struct llu_sb_info*)(fs->fs_private);
-}
-
-static inline struct llu_inode_info *llu_i2info(struct inode *inode)
-{
- return (struct llu_inode_info*)(inode->i_private);
-}
-
-static inline struct llu_sb_info *llu_i2sbi(struct inode *inode)
-{
- return llu_i2info(inode)->lli_sbi;
-}
-
-static inline struct client_obd *sbi2mdc(struct llu_sb_info *sbi)
-{
- struct obd_device *obd = class_conn2obd(&sbi->ll_mdc_conn);
- if (obd == NULL)
- LBUG();
- return &obd->u.cli;
-}
-
-static inline struct lustre_handle *llu_i2obdconn(struct inode *inode)
-{
- return &(llu_i2info(inode)->lli_sbi->ll_osc_conn);
-}
-
-
-struct mount_option_s
-{
- char *mdc_uuid;
- char *osc_uuid;
-};
-
-/* llite_lib.c */
-void generate_random_uuid(unsigned char uuid_out[16]);
-
-extern struct mount_option_s mount_option;
-
-/* super.c */
-void llu_update_inode(struct inode *inode, struct mds_body *body,
- struct lov_stripe_md *lmm);
-void obdo_to_inode(struct inode *dst, struct obdo *src, obd_flag valid);
-void obdo_from_inode(struct obdo *dst, struct inode *src, obd_flag valid);
-struct inode* llu_new_inode(struct filesys *fs, ino_t ino, mode_t mode);
-
-extern struct fssw_ops llu_fssw_ops;
-
-/* file.c */
-void llu_prepare_mdc_op_data(struct mdc_op_data *data,
- struct inode *i1,
- struct inode *i2,
- const char *name,
- int namelen,
- int mode);
-int llu_create(struct inode *dir, struct pnode_base *pnode, int mode);
-int llu_iop_open(struct pnode *pnode, int flags, mode_t mode);
-int llu_iop_close(struct inode *inode);
-int llu_iop_ipreadv(struct inode *ino,
- struct io_arguments *ioargs,
- struct ioctx **ioctxp);
-int llu_iop_ipwritev(struct inode *ino,
- struct io_arguments *ioargs,
- struct ioctx **ioctxp);
-
-/* rw.c */
-int llu_iop_iodone(struct ioctx *ioctxp __IS_UNUSED);
-ssize_t llu_file_write(struct inode *inode, const struct iovec *iovec,
- size_t iovlen, loff_t pos);
-ssize_t llu_file_read(struct inode *inode, const struct iovec *iovec,
- size_t iovlen, loff_t pos);
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Light user test program
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define _BSD_SOURCE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/queue.h>
-#include <sys/statvfs.h>
-
-#include <sysio.h>
-#include <mount.h>
-
-
-int do_stat(const char *name)
-{
- struct stat stat;
-
- if (lstat(name, &stat)) {
- perror("failed to stat: ");
- return -1;
- }
- printf("******* stat '%s' ********\n", name);
- printf("ino:\t\t%lu\n",stat.st_ino);
- printf("mode:\t\t%o\n",stat.st_mode);
- printf("nlink:\t\t%d\n",stat.st_nlink);
- printf("uid/gid:\t%d/%d\n", stat.st_uid, stat.st_gid);
- printf("size:\t\t%ld\n", stat.st_size);
- printf("blksize:\t%ld\n", stat.st_blksize);
- printf("block count:\t%ld\n", stat.st_blocks);
- printf("atime:\t\t%lu\n",stat.st_atime);
- printf("mtime:\t\t%lu\n",stat.st_mtime);
- printf("ctime:\t\t%lu\n",stat.st_ctime);
- printf("******* end stat ********\n");
-
- return 0;
-}
-/*
- * Get stats of file and file system.
- *
- * Usage: test_stats [-a] [-r <root-path>] [-m <root-driver>] [<path> ...]
- */
-
-extern int lllib_init(char *arg);
-
-char *root_driver = "llite";
-char *root_path = "/";
-unsigned mntflgs = 0;
-struct mount root_mount;
-
-extern int portal_debug;
-extern int portal_subsystem_debug;
-
-char* files[] = {"/dir1", "/dir1/file1", "/dir1/file2", "/dir1/dir2", "/dir1/dir2/file3"};
-
-int
-main(int argc, char * const argv[])
-{
- struct stat statbuf;
- int rc, err, i, fd, written, readed;
- char pgbuf[4096], readbuf[4096];
- int npages;
-
- if (_sysio_init() != 0) {
- perror("init sysio");
- exit(1);
- }
- err = lllib_init(argv[1]);
- if (err) {
- perror("init llite driver");
- exit(1);
- }
-
- err = _sysio_mount_root(root_path, root_driver, mntflgs, NULL);
- if (err) {
- errno = -err;
- perror(root_driver);
- exit(1);
- }
-#if 0
- for (i=0; i< sizeof(files)/sizeof(char*); i++) {
- printf("******** stat %s *********\n", files[i]);
- /* XXX ugly, only for testing */
- err = fixme_lstat(files[i], &statbuf);
- if (err)
- perror(root_driver);
- printf("******** end stat %s: %d*********\n", files[i], err);
- }
-#endif
-#if 0
- portal_debug = 0;
- portal_subsystem_debug = 0;
- npages = 10;
-
- fd = open("/newfile01", O_RDWR|O_CREAT|O_TRUNC, 00664);
- printf("***************** open return %d ****************\n", fd);
-
- printf("***************** begin write pages ****************\n");
- for (i = 0; i < npages; i++ ) {
- memset(pgbuf, ('A'+ i%10), 4096);
- written = write(fd, pgbuf, 4096);
- printf(">>> page %d: %d bytes written\n", i, written);
- }
-
- printf("***************** begin read pages ****************\n");
- lseek(fd, 0, SEEK_SET);
-
- for (i = 0; i < npages; i++ ) {
- memset(readbuf, '8', 4096);
- readed = read(fd, readbuf, 4096);
- readbuf[10] = 0;
- printf("<<< page %d: %d bytes (%s)\n", i, readed, readbuf);
- }
- close(fd);
-#endif
-
-#if 1
- //rc = chown("/newfile01", 10, 20);
- rc = chmod("/newfile01", 0777);
- printf("-------------- chmod return %d -----------\n", rc);
- do_stat("/newfile01");
-#endif
-
- printf("sysio is about shutdown\n");
- /*
- * Clean up.
- */
- _sysio_shutdown();
-
- printf("complete successfully\n");
- return 0;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Light Super operations
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <stdlib.h>
-#include <string.h>
-#include <error.h>
-#include <assert.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <sysio.h>
-#include <fs.h>
-#include <mount.h>
-#include <inode.h>
-#include <file.h>
-
-#include "llite_lib.h"
-
-int llu_iop_iodone(struct ioctx *ioctxp __IS_UNUSED)
-{
- return 1;
-}
-
-/*
- * this grabs a lock and manually implements behaviour that makes it look
- * like the OST is returning the file size with each lock acquisition
- */
-int llu_extent_lock(struct ll_file_data *fd, struct inode *inode,
- struct lov_stripe_md *lsm,
- int mode, struct ldlm_extent *extent,
- struct lustre_handle *lockh)
-{
-#if 0
- struct ll_inode_info *lli = ll_i2info(inode);
- int rc;
- ENTRY;
-
- rc = ll_extent_lock_no_validate(fd, inode, lsm, mode, extent, lockh);
- if (rc != ELDLM_OK)
- RETURN(rc);
-
- /* always do a getattr for the first person to pop out of lock
- * acquisition.. the DID_GETATTR flag and semaphore serialize
- * this initial race. we used to make a decision based on whether
- * the lock was matched or acquired, but the matcher could win the
- * waking race with the first issuer so that was no good..
- */
- if (test_bit(LLI_F_DID_GETATTR, &lli->lli_flags))
- RETURN(ELDLM_OK);
-
- down(&lli->lli_getattr_sem);
-
- if (!test_bit(LLI_F_DID_GETATTR, &lli->lli_flags)) {
- rc = ll_inode_getattr(inode, lsm, fd ? &fd->fd_ost_och : NULL);
- if (rc == 0) {
- set_bit(LLI_F_DID_GETATTR, &lli->lli_flags);
- } else {
- /* XXX can this fail? */
- ll_extent_unlock(fd, inode, lsm, mode, lockh);
- }
- }
-
- up(&lli->lli_getattr_sem);
- RETURN(rc);
-#else
- return ELDLM_OK;
-#endif
-}
-
-int ll_extent_unlock(struct ll_file_data *fd, struct inode *inode,
- struct lov_stripe_md *lsm, int mode,
- struct lustre_handle *lockh)
-{
-#if 0
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- int rc;
- ENTRY;
-
- /* XXX phil: can we do this? won't it screw the file size up? */
- if ((fd && (fd->fd_flags & LL_FILE_IGNORE_LOCK)) ||
- (sbi->ll_flags & LL_SBI_NOLCK))
- RETURN(0);
-
- rc = obd_cancel(&sbi->ll_osc_conn, lsm, mode, lockh);
-
- RETURN(rc);
-#else
- return 0;
-#endif
-}
-
-static int llu_brw(int cmd, struct inode *inode, struct page *page, int flags)
-{
- struct llu_inode_info *lli = llu_i2info(inode);
- struct lov_stripe_md *lsm = lli->lli_smd;
- struct obd_brw_set *set;
- struct brw_page pg;
- int rc;
- ENTRY;
-
- set = obd_brw_set_new();
- if (set == NULL)
- RETURN(-ENOMEM);
-
- pg.pg = page;
- pg.off = ((obd_off)page->index) << PAGE_SHIFT;
-
- /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
-#if 0
- if (cmd == OBD_BRW_WRITE && (pg.off + PAGE_SIZE > lli->lli_st_size))
- pg.count = lli->lli_st_size % PAGE_SIZE;
- else
-#endif
- pg.count = PAGE_SIZE;
-
- CDEBUG(D_PAGE, "%s %d bytes ino %lu at "LPU64"/"LPX64"\n",
- cmd & OBD_BRW_WRITE ? "write" : "read", pg.count, lli->lli_st_ino,
- pg.off, pg.off);
- if (pg.count == 0) {
- LBUG();
- }
-
- pg.flag = flags;
-
- set->brw_callback = ll_brw_sync_wait;
- rc = obd_brw(cmd, llu_i2obdconn(inode), lsm, 1, &pg, set, NULL);
- if (rc) {
- if (rc != -EIO)
- CERROR("error from obd_brw: rc = %d\n", rc);
- } else {
- rc = ll_brw_sync_wait(set, CB_PHASE_START);
- if (rc)
- CERROR("error from callback: rc = %d\n", rc);
- }
- obd_brw_set_decref(set);
-
- RETURN(rc);
-}
-
-static int llu_prepare_write(struct inode *inode, struct page *page,
- unsigned from, unsigned to)
-{
- struct llu_inode_info *lli = llu_i2info(inode);
- obd_off offset = ((obd_off)page->index) << PAGE_SHIFT;
- int rc = 0;
- ENTRY;
-
-#if 0
- if (!PageLocked(page))
- LBUG();
-
- if (PageUptodate(page))
- RETURN(0);
-
- //POISON(addr + from, 0xca, to - from);
-#endif
- /* We're completely overwriting an existing page, so _don't_ set it up
- * to date until commit_write */
- if (from == 0 && to == PAGE_SIZE)
- RETURN(0);
-
- /* If are writing to a new page, no need to read old data.
- * the extent locking and getattr procedures in ll_file_write have
- * guaranteed that i_size is stable enough for our zeroing needs */
- if (lli->lli_st_size <= offset) {
- memset(kmap(page), 0, PAGE_SIZE);
- kunmap(page);
- GOTO(prepare_done, rc = 0);
- }
-
- rc = llu_brw(OBD_BRW_READ, inode, page, 0);
-
- EXIT;
-
- prepare_done:
- return rc;
-}
-
-static int llu_commit_write(struct inode *inode, struct page *page,
- unsigned from, unsigned to)
-{
- struct llu_inode_info *lli = llu_i2info(inode);
- loff_t size;
- int rc;
- ENTRY;
-#if 0
- LASSERT(inode == file->f_dentry->d_inode);
- LASSERT(PageLocked(page));
-
- CDEBUG(D_INODE, "inode %p is writing page %p from %d to %d at %lu\n",
- inode, page, from, to, page->index);
- CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu,from=%d,to=%d\n",
- inode->i_ino, from, to);
- /* to match full page case in prepare_write */
- SetPageUptodate(page);
- /* mark the page dirty, put it on mapping->dirty,
- * mark the inode PAGES_DIRTY, put it on sb->dirty */
- set_page_dirty(page);
-#endif
- rc = llu_brw(OBD_BRW_WRITE, inode, page, 0);
- if (rc)
- return rc;
-
- /* this is matched by a hack in obdo_to_inode at the moment */
- size = (((obd_off)page->index) << PAGE_SHIFT) + to;
- if (size > lli->lli_st_size)
- lli->lli_st_size = size;
-
- RETURN(0);
-} /* ll_commit_write */
-
-ssize_t
-llu_generic_file_write(struct inode *inode, const char *buf,
- size_t count, loff_t pos)
-{
- struct page *page;
- ssize_t written;
- long status = 0;
- int err;
- unsigned bytes;
-
- if ((ssize_t) count < 0)
- return -EINVAL;
-#if 0
- down(&inode->i_sem);
-#endif
- if (pos < 0)
- return -EINVAL;
-
- written = 0;
-
-#if 0
- remove_suid(inode);
- update_inode_times(inode);
-#endif
- do {
- unsigned long index, offset;
- char *kaddr;
-
- /*
- * Try to find the page in the cache. If it isn't there,
- * allocate a free page.
- */
- offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
- index = pos >> PAGE_CACHE_SHIFT;
- bytes = PAGE_CACHE_SIZE - offset;
- if (bytes > count) {
- bytes = count;
- }
-
- status = -ENOMEM; /* we'll assign it later anyway */
- page = __grab_cache_page(index);
- if (!page)
- break;
-
- kaddr = kmap(page);
- status = llu_prepare_write(inode, page, offset, offset+bytes);
- if (status)
- goto sync_failure;
-
- memcpy(kaddr+offset, buf, bytes);
-
- status = llu_commit_write(inode, page, offset, offset+bytes);
- if (!status)
- status = bytes;
-
- if (status >= 0) {
- written += status;
- count -= status;
- pos += status;
- buf += status;
- }
-unlock:
- kunmap(page);
- page_cache_release(page);
-
- if (status < 0)
- break;
- } while (count);
-done:
- err = written ? written : status;
-
-#if 0
- up(&inode->i_sem);
-#endif
- return err;
-
- status = -EFAULT;
- goto unlock;
-
-sync_failure:
- /*
- * If blocksize < pagesize, prepare_write() may have instantiated a
- * few blocks outside i_size. Trim these off again.
- */
- kunmap(page);
- page_cache_release(page);
- goto done;
-}
-
-ssize_t llu_file_write(struct inode *inode, const struct iovec *iovec,
- size_t iovlen, loff_t pos)
-{
- struct llu_inode_info *lli = llu_i2info(inode);
- struct ll_file_data *fd = lli->lli_file_data; /* XXX not ready don't use it now */
- struct lustre_handle lockh = { 0, 0 };
- struct lov_stripe_md *lsm = lli->lli_smd;
- struct ldlm_extent extent;
- ldlm_error_t err;
- ssize_t retval = 0;
- ENTRY;
-
- /* XXX consider other types later */
- if (!S_ISREG(lli->lli_st_mode))
- LBUG();
-#if 0
- CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu,size="LPSZ",offset=%Ld\n",
- inode->i_ino, count, *ppos);
-
- /*
- * sleep doing some writeback work of this mount's dirty data
- * if the VM thinks we're low on memory.. other dirtying code
- * paths should think about doing this, too, but they should be
- * careful not to hold locked pages while they do so. like
- * ll_prepare_write. *cough*
- */
- ll_check_dirty(inode->i_sb);
-#endif
- while (iovlen--) {
- const char *buf = iovec[iovlen].iov_base;
- size_t count = iovec[iovlen].iov_len;
-
- /* POSIX, but surprised the VFS doesn't check this already */
- if (count == 0)
- continue;
-
-#if 0
- if (!S_ISBLK(lli->lli_st_mode) && file->f_flags & O_APPEND) {
- extent.start = 0;
- extent.end = OBD_OBJECT_EOF;
- } else {
- extent.start = *ppos;
- extent.end = *ppos + count - 1;
- }
-#else
- extent.start = pos;
- extent.end = pos + count - 1;
-#endif
-
- err = llu_extent_lock(fd, inode, lsm, LCK_PW, &extent, &lockh);
- if (err != ELDLM_OK)
- RETURN(-ENOLCK);
-
-#if 0
- if (!S_ISBLK(inode->i_mode) && file->f_flags & O_APPEND)
- *ppos = inode->i_size;
-
- CDEBUG(D_INFO, "Writing inode %lu, "LPSZ" bytes, offset %Lu\n",
- inode->i_ino, count, *ppos);
-#endif
- retval += llu_generic_file_write(inode, buf, count, pos);
- }
-
- /* XXX errors? */
- ll_extent_unlock(fd, inode, lsm, LCK_PW, &lockh);
- return(retval);
-}
-
-static void llu_update_atime(struct inode *inode)
-{
-#if 0
- struct llu_inode_info *lli = llu_i2info(inode);
-
-#ifdef USE_ATIME
- struct iattr attr;
-
- attr.ia_atime = LTIME_S(CURRENT_TIME);
- attr.ia_valid = ATTR_ATIME;
-
- if (lli->lli_st_atime == attr.ia_atime) return;
- if (IS_RDONLY(inode)) return;
- if (IS_NOATIME(inode)) return;
-
- /* ll_inode_setattr() sets inode->i_atime from attr.ia_atime */
- llu_inode_setattr(inode, &attr, 0);
-#else
- /* update atime, but don't explicitly write it out just this change */
- inode->i_atime = CURRENT_TIME;
-#endif
-#endif
-}
-
-static size_t llu_generic_file_read(struct inode *inode, char *buf,
- size_t count, loff_t pos)
-{
- struct llu_inode_info *lli = llu_i2info(inode);
- unsigned long index, offset;
- int error = 0;
- size_t readed = 0;
-
- index = pos >> PAGE_CACHE_SHIFT;
- offset = pos & ~PAGE_CACHE_MASK;
-
- do {
- struct page *page;
- unsigned long end_index, nr;
-
- end_index = lli->lli_st_size >> PAGE_CACHE_SHIFT;
-
- if (index > end_index)
- break;
- nr = PAGE_CACHE_SIZE;
- if (index == end_index) {
- nr = lli->lli_st_size & ~PAGE_CACHE_MASK;
- if (nr <= offset)
- break;
- }
-
- nr = nr - offset;
- if (nr > count)
- nr = count;
-
- page = grab_cache_page(index);
- if (!page) {
- error = -ENOMEM;
- break;
- }
-
- error = llu_brw(OBD_BRW_READ, inode, page, 0);
- if (error) {
- page_cache_release(page);
- break;
- }
-
- memcpy(buf, kmap(page)+offset, nr);
- offset += nr;
- index += offset >> PAGE_CACHE_SHIFT;
- offset &= ~PAGE_CACHE_MASK;
- readed += nr;
- count -= nr;
-
- page_cache_release(page);
- } while (count);
-
- if (error)
- return error;
- return readed;
-}
-
-ssize_t llu_file_read(struct inode *inode, const struct iovec *iovec,
- size_t iovlen, loff_t pos)
-{
- struct llu_inode_info *lli = llu_i2info(inode);
- struct ll_file_data *fd = lli->lli_file_data;
- struct lov_stripe_md *lsm = lli->lli_smd;
- struct lustre_handle lockh = { 0, 0 };
-#if 0
- struct ll_read_extent rextent;
-#else
- struct ldlm_extent extent;
-#endif
- ldlm_error_t err;
- ssize_t retval = 0;
- ENTRY;
-
- while (iovlen--) {
- char *buf = iovec[iovlen].iov_base;
- size_t count = iovec[iovlen].iov_len;
-
- /* "If nbyte is 0, read() will return 0 and have no other results."
- * -- Single Unix Spec */
- if (count == 0)
- RETURN(0);
-
-#if 0
- rextent.re_extent.start = pos;
- rextent.re_extent.end = pos + count - 1;
-#else
- extent.start = pos;
- extent.end = pos + count - 1;
-#endif
- err = llu_extent_lock(fd, inode, lsm, LCK_PR, &extent, &lockh);
- if (err != ELDLM_OK)
- RETURN(-ENOLCK);
-#if 0
- rextent.re_task = current;
- spin_lock(&lli->lli_read_extent_lock);
- list_add(&rextent.re_lli_item, &lli->lli_read_extents);
- spin_unlock(&lli->lli_read_extent_lock);
-#endif
- CDEBUG(D_INFO, "Reading inode %lu, "LPSZ" bytes, offset %Ld\n",
- lli->lli_st_ino, count, pos);
- retval = llu_generic_file_read(inode, buf, count, pos);
-#if 0
- spin_lock(&lli->lli_read_extent_lock);
- list_del(&rextent.re_lli_item);
- spin_unlock(&lli->lli_read_extent_lock);
-#endif
- }
-
- if (retval > 0)
- llu_update_atime(inode);
-
- /* XXX errors? */
- ll_extent_unlock(fd, inode, lsm, LCK_PR, &lockh);
- RETURN(retval);
-}
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Light Super operations
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <stdlib.h>
-#include <string.h>
-#include <error.h>
-#include <assert.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <sysio.h>
-#include <fs.h>
-#include <mount.h>
-#include <inode.h>
-#include <file.h>
-
-#include "llite_lib.h"
-
-static void llu_fsop_gone(struct filesys *fs)
-{
- /* FIXME */
-}
-
-static struct inode_ops llu_inode_ops;
-
-void llu_update_inode(struct inode *inode, struct mds_body *body,
- struct lov_stripe_md *lsm)
-{
- struct llu_inode_info *lli = llu_i2info(inode);
-
- LASSERT ((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0));
- if (lsm != NULL) {
- if (lli->lli_smd == NULL)
- lli->lli_smd = lsm;
- else
- LASSERT (!memcmp (lli->lli_smd, lsm,
- sizeof (*lsm)));
- }
-
- if (body->valid & OBD_MD_FLID)
- lli->lli_st_ino = body->ino;
- if (body->valid & OBD_MD_FLATIME)
- LTIME_S(lli->lli_st_atime) = body->atime;
- if (body->valid & OBD_MD_FLMTIME)
- LTIME_S(lli->lli_st_mtime) = body->mtime;
- if (body->valid & OBD_MD_FLCTIME)
- LTIME_S(lli->lli_st_ctime) = body->ctime;
- if (body->valid & OBD_MD_FLMODE)
- lli->lli_st_mode = (lli->lli_st_mode & S_IFMT)|(body->mode & ~S_IFMT);
- if (body->valid & OBD_MD_FLTYPE)
- lli->lli_st_mode = (lli->lli_st_mode & ~S_IFMT)|(body->mode & S_IFMT);
- if (body->valid & OBD_MD_FLUID)
- lli->lli_st_uid = body->uid;
- if (body->valid & OBD_MD_FLGID)
- lli->lli_st_gid = body->gid;
- if (body->valid & OBD_MD_FLFLAGS)
- lli->lli_st_flags = body->flags;
- if (body->valid & OBD_MD_FLNLINK)
- lli->lli_st_nlink = body->nlink;
- if (body->valid & OBD_MD_FLGENER)
- lli->lli_st_generation = body->generation;
- if (body->valid & OBD_MD_FLRDEV)
- lli->lli_st_rdev = body->rdev;
- if (body->valid & OBD_MD_FLSIZE)
- lli->lli_st_size = body->size;
- if (body->valid & OBD_MD_FLBLOCKS)
- lli->lli_st_blocks = body->blocks;
-
- /* fillin fid */
- if (body->valid & OBD_MD_FLID)
- lli->lli_fid.id = body->ino;
- if (body->valid & OBD_MD_FLGENER)
- lli->lli_fid.generation = body->generation;
- if (body->valid & OBD_MD_FLTYPE)
- lli->lli_fid.f_type = body->mode & S_IFMT;
-}
-
-void obdo_to_inode(struct inode *dst, struct obdo *src, obd_flag valid)
-{
- struct llu_inode_info *lli = llu_i2info(dst);
-
- valid &= src->o_valid;
-
- if (valid & OBD_MD_FLATIME)
- LTIME_S(lli->lli_st_atime) = src->o_atime;
- if (valid & OBD_MD_FLMTIME)
- LTIME_S(lli->lli_st_mtime) = src->o_mtime;
- if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(lli->lli_st_ctime))
- LTIME_S(lli->lli_st_ctime) = src->o_ctime;
- if (valid & OBD_MD_FLSIZE)
- lli->lli_st_size = src->o_size;
- if (valid & OBD_MD_FLBLOCKS) /* allocation of space */
- lli->lli_st_blocks = src->o_blocks;
- if (valid & OBD_MD_FLBLKSZ)
- lli->lli_st_blksize = src->o_blksize;
- if (valid & OBD_MD_FLTYPE)
- lli->lli_st_mode = (lli->lli_st_mode & ~S_IFMT) | (src->o_mode & S_IFMT);
- if (valid & OBD_MD_FLMODE)
- lli->lli_st_mode = (lli->lli_st_mode & S_IFMT) | (src->o_mode & ~S_IFMT);
- if (valid & OBD_MD_FLUID)
- lli->lli_st_uid = src->o_uid;
- if (valid & OBD_MD_FLGID)
- lli->lli_st_gid = src->o_gid;
- if (valid & OBD_MD_FLFLAGS)
- lli->lli_st_flags = src->o_flags;
- if (valid & OBD_MD_FLNLINK)
- lli->lli_st_nlink = src->o_nlink;
- if (valid & OBD_MD_FLGENER)
- lli->lli_st_generation = src->o_generation;
- if (valid & OBD_MD_FLRDEV)
- lli->lli_st_rdev = src->o_rdev;
-}
-
-void obdo_from_inode(struct obdo *dst, struct inode *src, obd_flag valid)
-{
- struct llu_inode_info *lli = llu_i2info(src);
-
- if (valid & OBD_MD_FLATIME)
- dst->o_atime = LTIME_S(lli->lli_st_atime);
- if (valid & OBD_MD_FLMTIME)
- dst->o_mtime = LTIME_S(lli->lli_st_mtime);
- if (valid & OBD_MD_FLCTIME)
- dst->o_ctime = LTIME_S(lli->lli_st_ctime);
- if (valid & OBD_MD_FLSIZE)
- dst->o_size = lli->lli_st_size;
- if (valid & OBD_MD_FLBLOCKS) /* allocation of space */
- dst->o_blocks = lli->lli_st_blocks;
- if (valid & OBD_MD_FLBLKSZ)
- dst->o_blksize = lli->lli_st_blksize;
- if (valid & OBD_MD_FLTYPE)
- dst->o_mode = (dst->o_mode & ~S_IFMT) | (lli->lli_st_mode & S_IFMT);
- if (valid & OBD_MD_FLMODE)
- dst->o_mode = (dst->o_mode & S_IFMT) | (lli->lli_st_mode & ~S_IFMT);
- if (valid & OBD_MD_FLUID)
- dst->o_uid = lli->lli_st_uid;
- if (valid & OBD_MD_FLGID)
- dst->o_gid = lli->lli_st_gid;
- if (valid & OBD_MD_FLFLAGS)
- dst->o_flags = lli->lli_st_flags;
- if (valid & OBD_MD_FLNLINK)
- dst->o_nlink = lli->lli_st_nlink;
- if (valid & OBD_MD_FLGENER)
- dst->o_generation = lli->lli_st_generation;
- if (valid & OBD_MD_FLRDEV)
- dst->o_rdev = (__u32)(lli->lli_st_rdev);
-
- dst->o_valid |= (valid & ~OBD_MD_FLID);
-}
-
-int llu_inode_getattr(struct inode *inode, struct lov_stripe_md *lsm,
- char *ostdata)
-{
- struct llu_sb_info *sbi = llu_i2sbi(inode);
- struct obdo oa;
- int rc;
- ENTRY;
-
- LASSERT(lsm);
- LASSERT(sbi);
-
- memset(&oa, 0, sizeof oa);
- oa.o_id = lsm->lsm_object_id;
- oa.o_mode = S_IFREG;
- oa.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLSIZE |
- OBD_MD_FLBLOCKS | OBD_MD_FLMTIME | OBD_MD_FLCTIME;
-
- if (ostdata != NULL) {
- memcpy(&oa.o_inline, ostdata, FD_OSTDATA_SIZE);
- oa.o_valid |= OBD_MD_FLHANDLE;
- }
-
- rc = obd_getattr(&sbi->ll_osc_conn, &oa, lsm);
- if (rc)
- RETURN(rc);
-
- obdo_to_inode(inode, &oa, OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
- OBD_MD_FLMTIME | OBD_MD_FLCTIME);
-
- RETURN(0);
-}
-
-struct inode* llu_new_inode(struct filesys *fs, ino_t ino, mode_t mode)
-{
- struct inode *inode;
- struct llu_inode_info *lli;
-
- OBD_ALLOC(lli, sizeof(*lli));
- if (!lli)
- return NULL;
-
- /* initialize lli here */
- lli->lli_sbi = llu_fs2sbi(fs);
- lli->lli_smd = NULL;
- lli->lli_symlink_name = NULL;
- lli->lli_flags = 0;
- INIT_LIST_HEAD(&lli->lli_read_extents);
- lli->lli_file_data = NULL;
-
- /* could file_identifier be 0 ? FIXME */
- inode = _sysio_i_new(fs, ino, NULL,
-#ifndef AUTOMOUNT_FILE_NAME
- mode & S_IFMT,
-#else
- mode, /* all of the bits! */
-#endif
- 0,
- &llu_inode_ops, lli);
-
- if (!inode)
- OBD_FREE(lli, sizeof(*lli));
-
- return inode;
-}
-
-static int llu_iop_lookup(struct pnode *pnode,
- struct inode **inop,
- struct intent *intnt __IS_UNUSED,
- const char *path __IS_UNUSED)
-{
- struct pnode_base *pb_dir = pnode->p_parent->p_base;
- struct ptlrpc_request *request = NULL;
- struct llu_sb_info *sbi = llu_i2sbi(pb_dir->pb_ino);
- struct ll_fid *fid = &llu_i2info(pb_dir->pb_ino)->lli_fid;
- struct qstr *name = &pnode->p_base->pb_name;
- struct mds_body *body;
- unsigned long valid;
- char *pname;
- int rc, easize;
- struct ll_read_inode2_cookie lic = {.lic_body = NULL, .lic_lsm = NULL};
-
- /* the mount root inode have no name, so don't call
- * remote in this case. but probably we need revalidate
- * it here? FIXME */
- if (pnode->p_mount->mnt_root == pnode) {
- struct inode *i = pnode->p_base->pb_ino;
- I_REF(i);
- *inop = i;
- return 0;
- }
-
- if (!name->len)
- return -EINVAL;
-
- /* mdc_getattr_name require NULL-terminated name */
- OBD_ALLOC(pname, name->len + 1);
- if (!pname)
- return -ENOMEM;
- memcpy(pname, name->name, name->len);
- pname[name->len] = 0;
-
- valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLSIZE;
-
- /* FIXME before getattr_name, we don't know whether
- * the inode we are finding is regular or not, so here
- * we blindly require server feed in EA data */
- easize = obd_size_diskmd(&sbi->ll_osc_conn, NULL);
- valid |= OBD_MD_FLEASIZE;
-
- rc = mdc_getattr_name(&sbi->ll_mdc_conn, fid,
- pname, name->len + 1,
- valid, easize, &request);
- if (rc < 0) {
- CERROR("mdc_getattr_name: %d\n", rc);
- rc = -ENOENT;
- goto out;
- }
- body = lustre_msg_buf(request->rq_repmsg, 0, sizeof(*body));
-
- *inop = llu_new_inode(pnode->p_mount->mnt_fs, body->ino, body->mode);
- if (!inop)
- goto out;
-
- lic.lic_body = lustre_msg_buf(request->rq_repmsg, 0, sizeof(*lic.lic_body));
- LASSERT (lic.lic_body != NULL);
- LASSERT_REPSWABBED (request, 0);
-
- if (S_ISREG(lic.lic_body->mode) &&
- lic.lic_body->valid & OBD_MD_FLEASIZE) {
- struct lov_mds_md *lmm;
- int lmm_size;
- int rc;
-
- lmm_size = lic.lic_body->eadatasize;
- if (lmm_size == 0) {
- CERROR ("OBD_MD_FLEASIZE set but eadatasize 0\n");
- RETURN (-EPROTO);
- }
- lmm = lustre_msg_buf(request->rq_repmsg, 0 + 1, lmm_size);
- LASSERT(lmm != NULL);
- LASSERT_REPSWABBED (request, 0 + 1);
-
- rc = obd_unpackmd (&sbi->ll_osc_conn,
- &lic.lic_lsm, lmm, lmm_size);
- if (rc < 0) {
- CERROR ("Error %d unpacking eadata\n", rc);
- RETURN (rc);
- }
- LASSERT (rc >= sizeof (*lic.lic_lsm));
-
- } else {
- lic.lic_lsm = NULL;
- }
-
- llu_update_inode(*inop, body, lic.lic_lsm);
-
- if (llu_i2info(*inop)->lli_smd) {
- rc = llu_inode_getattr(*inop, llu_i2info(*inop)->lli_smd, NULL);
- if (rc)
- _sysio_i_gone(*inop);
- }
-
-out:
- ptlrpc_req_finished(request);
- OBD_FREE(pname, name->len + 1);
-
- return rc;
-}
-
-static int llu_iop_getattr(struct pnode *pno,
- struct inode *ino,
- struct intnl_stat *b)
-{
- struct llu_inode_info *lli = llu_i2info(ino);
-
- b->st_dev = lli->lli_st_dev;
- b->st_ino = lli->lli_st_ino;
- b->st_mode = lli->lli_st_mode;
- b->st_nlink = lli->lli_st_nlink;
- b->st_uid = lli->lli_st_uid;
- b->st_gid = lli->lli_st_gid;
- b->st_rdev = lli->lli_st_rdev;
- b->st_size = lli->lli_st_size;
- b->st_blksize = lli->lli_st_blksize;
- b->st_blocks = lli->lli_st_blocks;
- b->st_atime = lli->lli_st_atime;
- b->st_mtime = lli->lli_st_mtime;
- b->st_ctime = lli->lli_st_ctime;
-
- return 0;
-}
-
-int llu_mdc_cancel_unused(struct lustre_handle *conn,
- struct llu_inode_info *lli,
- int flags)
-{
- struct ldlm_res_id res_id =
- { .name = {lli->lli_st_ino, lli->lli_st_generation} };
- struct obd_device *obddev = class_conn2obd(conn);
- ENTRY;
- RETURN(ldlm_cli_cancel_unused(obddev->obd_namespace, &res_id, flags));
-}
-
-static void llu_clear_inode(struct inode *inode)
-{
- struct llu_sb_info *sbi = llu_i2sbi(inode);
- struct llu_inode_info *lli = llu_i2info(inode);
- int rc;
- ENTRY;
-
- CDEBUG(D_INODE, "clear inode: %lu\n", lli->lli_st_ino);
- rc = llu_mdc_cancel_unused(&sbi->ll_mdc_conn, lli,
- LDLM_FL_NO_CALLBACK);
- if (rc < 0) {
- CERROR("ll_mdc_cancel_unused: %d\n", rc);
- /* XXX FIXME do something dramatic */
- }
-
- if (lli->lli_smd) {
- rc = obd_cancel_unused(&sbi->ll_osc_conn, lli->lli_smd, 0);
- if (rc < 0) {
- CERROR("obd_cancel_unused: %d\n", rc);
- /* XXX FIXME do something dramatic */
- }
- }
-
- if (lli->lli_smd)
- obd_free_memmd(&sbi->ll_osc_conn, &lli->lli_smd);
-
- if (lli->lli_symlink_name) {
- OBD_FREE(lli->lli_symlink_name,
- strlen(lli->lli_symlink_name) + 1);
- lli->lli_symlink_name = NULL;
- }
-
- EXIT;
-}
-
-void llu_iop_gone(struct inode *inode)
-{
- struct llu_inode_info *lli = llu_i2info(inode);
-
- llu_clear_inode(inode);
-
- OBD_FREE(lli, sizeof(*lli));
-}
-
-static int llu_setattr_raw(struct inode *inode, struct iattr *attr)
-{
- struct ptlrpc_request *request = NULL;
- struct llu_sb_info *sbi = llu_i2sbi(inode);
- struct llu_inode_info *lli = llu_i2info(inode);
- struct mdc_op_data op_data;
- int err = 0;
- ENTRY;
- CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu\n", lli->lli_st_ino);
-
- /* if need truncate, do it at first */
- if (attr->ia_valid & ATTR_SIZE) {
- printf("************* don't support truncate now !!!!!!!!\n");
- LBUG();
- }
-
- /* Don't send size changes to MDS to avoid "fast EA" problems, and
- * also avoid a pointless RPC (we get file size from OST anyways).
- */
- attr->ia_valid &= ~ATTR_SIZE;
- if (!attr->ia_valid)
- RETURN(0);
-
- llu_prepare_mdc_op_data(&op_data, inode, NULL, NULL, 0, 0);
-
- err = mdc_setattr(&sbi->ll_mdc_conn, &op_data,
- attr, NULL, 0, &request);
- if (err)
- CERROR("mdc_setattr fails: err = %d\n", err);
-
- ptlrpc_req_finished(request);
-
- if (S_ISREG(inode->i_mode) && attr->ia_valid & ATTR_MTIME_SET) {
- struct lov_stripe_md *lsm = lli->lli_smd;
- struct obdo oa;
- int err2;
-
- CDEBUG(D_INODE, "set mtime on OST inode %lu to %lu\n",
- lli->lli_st_ino, attr->ia_mtime);
- oa.o_id = lsm->lsm_object_id;
- oa.o_mode = S_IFREG;
- oa.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMTIME;
- oa.o_mtime = attr->ia_mtime;
- err2 = obd_setattr(&sbi->ll_osc_conn, &oa, lsm, NULL);
- if (err2) {
- CERROR("obd_setattr fails: rc=%d\n", err);
- if (!err)
- err = err2;
- }
- }
- RETURN(err);
-}
-
-/* FIXME here we simply act as a thin layer to glue it with
- * llu_setattr_raw(), which is copy from kernel
- */
-static int llu_iop_setattr(struct pnode *pno,
- struct inode *ino,
- unsigned mask,
- struct intnl_stat *stbuf)
-{
- struct iattr iattr;
-
- memset(&iattr, 0, sizeof(iattr));
-
- if (mask & SETATTR_MODE) {
- iattr.ia_mode = stbuf->st_mode;
- iattr.ia_valid |= ATTR_MODE;
- }
- if (mask & SETATTR_MTIME) {
- iattr.ia_mtime = stbuf->st_mtime;
- iattr.ia_valid |= ATTR_MTIME;
- }
- if (mask & SETATTR_ATIME) {
- iattr.ia_atime = stbuf->st_atime;
- iattr.ia_valid |= ATTR_ATIME;
- }
- if (mask & SETATTR_UID) {
- iattr.ia_uid = stbuf->st_uid;
- iattr.ia_valid |= ATTR_UID;
- }
- if (mask & SETATTR_GID) {
- iattr.ia_gid = stbuf->st_gid;
- iattr.ia_valid |= ATTR_GID;
- }
- if (mask & SETATTR_LEN) {
- iattr.ia_size = stbuf->st_size; /* FIXME signed expansion problem */
- iattr.ia_valid |= ATTR_SIZE;
- }
-
- iattr.ia_valid |= ATTR_RAW;
- /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME
- * without ATTR_FROM_OPEN, mds_reint_setattr will call
- * mds_fid2locked_dentry() and deadlocked at completion_ast call.
- * Here we workaround it and avoid any locking.
- * FIXME FIXME FIXME FIXME FIXME FIXME FIXME
- */
- iattr.ia_valid |= ATTR_FROM_OPEN;
-
- return llu_setattr_raw(ino, &iattr);
-}
-
-
-static int llu_mkdir2(struct inode *dir, const char *name, int len, int mode)
-{
- struct ptlrpc_request *request = NULL;
- time_t curtime = CURRENT_TIME;
- struct llu_sb_info *sbi = llu_i2sbi(dir);
- struct llu_inode_info *lli = llu_i2info(dir);
- struct mdc_op_data op_data;
- int err = -EMLINK;
- ENTRY;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%s,dir=%lu\n",
- name, lli->lli_st_ino);
-
- /* FIXME check this later */
-#if 0
- if (dir->i_nlink >= EXT2_LINK_MAX)
- RETURN(err);
- mode = (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask) | S_IFDIR;
-#endif
- mode |= S_IFDIR;
- llu_prepare_mdc_op_data(&op_data, dir, NULL, name, len, 0);
- err = mdc_create(&sbi->ll_mdc_conn, &op_data, NULL, 0, mode,
- current->fsuid, current->fsgid,
- curtime, 0, &request);
- ptlrpc_req_finished(request);
- RETURN(err);
-}
-
-static int llu_iop_mkdir(struct pnode *pno, mode_t mode)
-{
- struct inode *dir = pno->p_base->pb_parent->pb_ino;
- struct qstr *qstr = &pno->p_base->pb_name;
- int rc;
-
- LASSERT(dir);
-
- rc = llu_mkdir2(dir, qstr->name, qstr->len, mode);
-
- return rc;
-}
-
-#ifndef S_IRWXUGO
-#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
-#endif
-
-static int llu_symlink2(struct inode *dir, const char *name, int len,
- const char *tgt)
-{
- struct ptlrpc_request *request = NULL;
- time_t curtime = CURRENT_TIME;
- struct llu_sb_info *sbi = llu_i2sbi(dir);
- struct llu_inode_info *lli = llu_i2info(dir);
- struct mdc_op_data op_data;
- int err = -EMLINK;
- ENTRY;
-
- CDEBUG(D_VFSTRACE, "VFS Op:name=%s,dir=%lu,target=%s\n",
- name, lli->lli_st_ino, tgt);
-
-#if 0
- if (dir->i_nlink >= EXT2_LINK_MAX)
- RETURN(err);
-#endif
- llu_prepare_mdc_op_data(&op_data, dir, NULL, name, len, 0);
- err = mdc_create(&sbi->ll_mdc_conn, &op_data,
- tgt, strlen(tgt) + 1, S_IFLNK | S_IRWXUGO,
- current->fsuid, current->fsgid, curtime, 0, &request);
- ptlrpc_req_finished(request);
- RETURN(err);
-}
-
-static int llu_iop_symlink(struct pnode *pno, const char *data)
-{
- struct inode *dir = pno->p_base->pb_parent->pb_ino;
- struct qstr *qstr = &pno->p_base->pb_name;
- int rc;
-
- LASSERT(dir);
-
- rc = llu_symlink2(dir, qstr->name, qstr->len, data);
-
- return rc;
-}
-
-struct filesys_ops llu_filesys_ops =
-{
- fsop_gone: llu_fsop_gone,
-};
-
-
-static struct inode_ops llu_inode_ops = {
- inop_lookup: llu_iop_lookup,
- inop_getattr: llu_iop_getattr,
- inop_setattr: llu_iop_setattr,
- inop_getdirentries: NULL,
- inop_mkdir: llu_iop_mkdir,
- inop_rmdir: NULL,
- inop_symlink: llu_iop_symlink,
- inop_readlink: NULL,
- inop_open: llu_iop_open,
- inop_close: llu_iop_close,
- inop_unlink: NULL,
- inop_ipreadv: llu_iop_ipreadv,
- inop_ipwritev: llu_iop_ipwritev,
- inop_iodone: llu_iop_iodone,
- inop_fcntl: NULL,
- inop_sync: NULL,
- inop_datasync: NULL,
- inop_ioctl: NULL,
- inop_mknod: NULL,
- inop_statvfs: NULL,
- inop_gone: llu_iop_gone,
-};
-
-
-static int
-llu_fsswop_mount(const char *source,
- unsigned flags,
- const void *data __IS_UNUSED,
- struct pnode *tocover,
- struct mount **mntp)
-{
- struct filesys *fs;
- struct inode *root;
- struct pnode_base *rootpb;
- static struct qstr noname = { NULL, 0, 0 };
- struct ll_fid rootfid;
-
- struct llu_sb_info *sbi;
- struct ptlrpc_connection *mdc_conn;
- struct ptlrpc_request *request = NULL;
- struct mds_body *root_body;
- struct obd_uuid param_uuid;
- class_uuid_t uuid;
- struct obd_device *obd;
- char *osc=mount_option.osc_uuid;
- char *mdc=mount_option.mdc_uuid;
- int err = -EINVAL;
-
- ENTRY;
-
- OBD_ALLOC(sbi, sizeof(*sbi));
- if (!sbi)
- RETURN(-ENOMEM);
-
- INIT_LIST_HEAD(&sbi->ll_conn_chain);
- generate_random_uuid(uuid);
- class_uuid_unparse(uuid, &sbi->ll_sb_uuid);
-
- fs = _sysio_fs_new(&llu_filesys_ops, flags, sbi);
- if (!fs) {
- err = -ENOMEM;
- goto out_free;
- }
-
- strncpy(param_uuid.uuid, mdc, sizeof(param_uuid.uuid));
- obd = class_uuid2obd(¶m_uuid);
- if (!obd) {
- CERROR("MDC %s: not setup or attached\n", mdc);
- err = -EINVAL;
- goto out_free;
- }
-
- /* setup mdc */
- /* FIXME need recover stuff */
- err = obd_connect(&sbi->ll_mdc_conn, obd, &sbi->ll_sb_uuid);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", mdc, err);
- goto out_free;
- }
-
- mdc_conn = sbi2mdc(sbi)->cl_import->imp_connection;
-
- /* setup osc */
- strncpy(param_uuid.uuid, osc, sizeof(param_uuid.uuid));
- obd = class_uuid2obd(¶m_uuid);
- if (!obd) {
- CERROR("OSC %s: not setup or attached\n", osc);
- err = -EINVAL;
- goto out_mdc;
- }
-
- err = obd_connect(&sbi->ll_osc_conn, obd, &sbi->ll_sb_uuid);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", osc, err);
- goto out_mdc;
- }
-
- err = mdc_getstatus(&sbi->ll_mdc_conn, &rootfid);
- if (err) {
- CERROR("cannot mds_connect: rc = %d\n", err);
- goto out_osc;
- }
- CDEBUG(D_SUPER, "rootfid "LPU64"\n", rootfid.id);
- sbi->ll_rootino = rootfid.id;
-
-/* XXX do we need this??
- memset(&osfs, 0, sizeof(osfs));
- rc = obd_statfs(&sbi->ll_mdc_conn, &osfs);
-*/
- /* fetch attr of root inode */
- err = mdc_getattr(&sbi->ll_mdc_conn, &rootfid,
- OBD_MD_FLNOTOBD|OBD_MD_FLBLOCKS, 0, &request);
- if (err) {
- CERROR("mdc_getattr failed for root: rc = %d\n", err);
- goto out_request;
- }
-
- root_body = lustre_msg_buf(request->rq_repmsg, 0, sizeof(*root_body));
- LASSERT(sbi->ll_rootino != 0);
-
- root = llu_new_inode(fs, root_body->ino, root_body->mode);
- if (!root) {
- err = -ENOMEM;
- goto out_request;
- }
-
- llu_update_inode(root, root_body, NULL);
-
- /*
- * Generate base path-node for root.
- */
- rootpb = _sysio_pb_new(&noname, NULL, root);
- if (!rootpb) {
- err = -ENOMEM;
- goto out_inode;
- }
-
- err = _sysio_do_mount(fs, rootpb, flags, NULL, mntp);
- if (err) {
- _sysio_pb_gone(rootpb);
- goto out_inode;
- }
-
- ptlrpc_req_finished(request);
- request = NULL;
-
- printf("************************************************\n");
- printf("* Mount successfully!!!!!!! *\n");
- printf("************************************************\n");
-
- return 0;
-
-out_inode:
- _sysio_i_gone(root);
-out_request:
- ptlrpc_req_finished(request);
-out_osc:
- obd_disconnect(&sbi->ll_osc_conn);
-out_mdc:
- obd_disconnect(&sbi->ll_mdc_conn);
-out_free:
- OBD_FREE(sbi, sizeof(*sbi));
- return err;
-}
-
-struct fssw_ops llu_fssw_ops = {
- llu_fsswop_mount
-};
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Copyright (C) 2002, 2003 Cluster File Systems, Inc
- *
- * this started as an implementation of an io daemon that woke regularly
- * to force writeback.. the throttling in prepare_write and kupdate's usual
- * writeback pressure got rid of our thread, but the file name remains.
- */
-#include <linux/version.h>
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/kmod.h>
-#include <linux/pagemap.h>
-#include <linux/mm.h>
-
-/* PG_inactive_clean is shorthand for rmap, we want free_high/low here.. */
-#ifdef PG_inactive_clean
-#include <linux/mm_inline.h>
-#endif
-
-#define DEBUG_SUBSYSTEM S_LLITE
-#include <linux/lustre_lite.h>
-
-#ifndef list_for_each_prev_safe
-#define list_for_each_prev_safe(pos, n, head) \
- for (pos = (head)->prev, n = pos->prev; pos != (head); \
- pos = n, n = pos->prev )
-#endif
-
-extern spinlock_t inode_lock;
-
-#define LLWP_MAX_PAGES (PTL_MD_MAX_IOV)
-struct ll_writeback_pages {
- unsigned has_whole_pages:1,
- num_frags:2,
- num_pages:29;
- struct brw_page pgs[LLWP_MAX_PAGES];
-};
-
-
-/*
- * ugh, we want disk allocation on the target to happen in offset order. we'll
- * follow sedgewicks advice and stick to the dead simple shellsort -- it'll do
- * fine for our small page arrays and doesn't require allocation. its an
- * insertion sort that swaps elements that are strides apart, shrinking the
- * stride down until its '1' and the array is sorted.
- */
-void sort_brw_pages(struct brw_page *array, int num)
-{
- int stride, i, j;
- struct brw_page tmp;
-
- if ( num == 1 )
- return;
-
- for( stride = 1; stride < num ; stride = (stride*3) +1 )
- ;
-
- do {
- stride /= 3;
- for ( i = stride ; i < num ; i++ ) {
- tmp = array[i];
- j = i;
- while ( j >= stride &&
- array[j - stride].off > tmp.off ) {
- array[j] = array[j - stride];
- j -= stride;
- }
- array[j] = tmp;
- }
- } while ( stride > 1 );
-}
-
-/*
- * returns 0 if the page was inserted in the array because it was
- * within i_size. if we raced with truncate and i_size was less
- * than the page we can unlock the page because truncate_inode_pages will
- * be waiting to cleanup the page
- */
-static int llwp_consume_page(struct ll_writeback_pages *llwp,
- struct inode *inode, struct page *page)
-{
- obd_off off = ((obd_off)page->index) << PAGE_SHIFT;
- struct brw_page *pg;
-
- /* we raced with truncate? */
- if ( off >= inode->i_size ) {
- unlock_page(page);
- goto out;
- }
-
- page_cache_get(page);
- pg = &llwp->pgs[llwp->num_pages];
- llwp->num_pages++;
-
- pg->pg = page;
- pg->off = off;
- pg->flag = OBD_BRW_CREATE;
- pg->count = PAGE_SIZE;
-
- /* catch partial writes for files that end mid-page */
- if ( pg->off + pg->count > inode->i_size )
- pg->count = inode->i_size & ~PAGE_MASK;
-
- if ( pg->count == PAGE_SIZE ) {
- if ( ! llwp->has_whole_pages ) {
- llwp->has_whole_pages = 1;
- llwp->num_frags++;
- }
- } else {
- llwp->num_frags++;
- }
-
- /*
- * matches ptlrpc_bulk_get assert that trickles down
- * from a 0 page length going through niobuf and into
- * the buffer regions being posted
- */
- LASSERT(pg->count >= 0);
-
- CDEBUG(D_CACHE, "brw_page %p: off "LPU64" cnt %d, page %p: ind %ld"
- " i_size: "LPU64"\n", pg, pg->off, pg->count, page,
- page->index, inode->i_size);
-
- if ( llwp->num_frags == 3 || llwp->num_pages == LLWP_MAX_PAGES )
- return -1;
-
-out:
- return 0;
-}
-
-/*
- * returns the number of pages that it added to the pgs array
- *
- * this duplicates filemap_fdatasync and gives us an opportunity to grab lots
- * of dirty pages..
- */
-static void ll_get_dirty_pages(struct inode *inode,
- struct ll_writeback_pages *llwp)
-{
- struct address_space *mapping = inode->i_mapping;
- struct page *page;
- struct list_head *pos, *n;
- ENTRY;
-
- spin_lock(&pagecache_lock);
-
- list_for_each_prev_safe(pos, n, &mapping->dirty_pages) {
- page = list_entry(pos, struct page, list);
-
- if (TryLockPage(page))
- continue;
-
- list_del(&page->list);
- list_add(&page->list, &mapping->locked_pages);
-
- if ( ! PageDirty(page) ) {
- unlock_page(page);
- continue;
- }
- ClearPageDirty(page);
-
- if ( llwp_consume_page(llwp, inode, page) != 0)
- break;
- }
-
- spin_unlock(&pagecache_lock);
- EXIT;
-}
-
-static void ll_brw_pages_unlock( struct inode *inode,
- struct ll_writeback_pages *llwp)
-{
- int rc, i;
- struct obd_brw_set *set;
- ENTRY;
-
- sort_brw_pages(llwp->pgs, llwp->num_pages);
-
- set = obd_brw_set_new();
- if (set == NULL) {
- EXIT;
- return;
- }
- set->brw_callback = ll_brw_sync_wait;
-
- rc = obd_brw(OBD_BRW_WRITE, ll_i2obdconn(inode),
- ll_i2info(inode)->lli_smd, llwp->num_pages, llwp->pgs,
- set, NULL);
- if (rc) {
- CERROR("error from obd_brw: rc = %d\n", rc);
- } else {
- rc = ll_brw_sync_wait(set, CB_PHASE_START);
- if (rc)
- CERROR("error from callback: rc = %d\n", rc);
- }
- obd_brw_set_decref(set);
-
- /* XXX this doesn't make sense to me */
- rc = 0;
-
- for ( i = 0 ; i < llwp->num_pages ; i++) {
- struct page *page = llwp->pgs[i].pg;
-
- CDEBUG(D_CACHE, "cleaning page %p\n", page);
- LASSERT(PageLocked(page));
- unlock_page(page);
- page_cache_release(page);
- }
-
- EXIT;
-}
-
-#ifndef PG_inactive_clean
-#ifdef CONFIG_DISCONTIGMEM
-#error "sorry, we don't support DISCONTIGMEM yet"
-#endif
-/*
- * __alloc_pages marks a zone as needing balancing if an allocation is
- * performed when the zone has fewer free pages than its 'low' water
- * mark. its cleared when try_to_free_pages makes progress.
- */
-static int zones_need_balancing(void)
-{
- pg_data_t * pgdat;
- zone_t *zone;
- int i;
-
- for ( pgdat = pgdat_list ; pgdat != NULL ; pgdat = pgdat->node_next ) {
- for ( i = pgdat->nr_zones-1 ; i >= 0 ; i-- ) {
- zone = &pgdat->node_zones[i];
-
- if ( zone->need_balance )
- return 1;
- }
- }
- return 0;
-}
-#endif
-/* 2.4 doesn't give us a way to find out how many pages we have
- * cached 'cause we're not using buffer_heads. we are very
- * conservative here and flush the superblock of all dirty data
- * when the vm (rmap or stock) thinks that it is running low
- * and kswapd would have done work. kupdated isn't good enough
- * because writers (dbench) can dirty _very quickly_, and we
- * allocate under writepage..
- *
- * 2.5 gets this right, see the {inc,dec}_page_state(nr_dirty, )
- */
-static int should_writeback(void)
-{
-#ifdef PG_inactive_clean
- if (free_high(ALL_ZONES) > 0 || free_low(ANY_ZONE) > 0)
-#else
- if (zones_need_balancing())
-#endif
- return 1;
- return 0;
-}
-
-int ll_check_dirty( struct super_block *sb)
-{
- unsigned long old_flags; /* hack? */
- int making_progress;
- struct ll_writeback_pages *llwp;
- struct inode *inode;
- int rc = 0;
- ENTRY;
-
- if ( ! should_writeback() )
- return 0;
-
- old_flags = current->flags;
- current->flags |= PF_MEMALLOC;
- llwp = kmalloc(sizeof(struct ll_writeback_pages), GFP_ATOMIC);
- if ( llwp == NULL )
- GOTO(cleanup, rc = -ENOMEM);
- memset(llwp, 0, offsetof(struct ll_writeback_pages, pgs));
-
- spin_lock(&inode_lock);
-
- /*
- * first we try and write back dirty pages from dirty inodes
- * until the VM thinkgs we're ok again..
- */
- do {
- struct list_head *pos;
- inode = NULL;
- making_progress = 0;
-
- list_for_each_prev(pos, &sb->s_dirty) {
- inode = list_entry(pos, struct inode, i_list);
-
- if ( ! (inode->i_state & I_DIRTY_PAGES) ) {
- inode = NULL;
- continue;
- }
- break;
- }
-
- if ( inode == NULL )
- break;
-
- /* duplicate __sync_one, *sigh* */
- list_del(&inode->i_list);
- list_add(&inode->i_list, &inode->i_sb->s_locked_inodes);
- inode->i_state |= I_LOCK;
- inode->i_state &= ~I_DIRTY_PAGES;
-
- spin_unlock(&inode_lock);
-
- do {
- memset(llwp, 0, sizeof(*llwp));
- ll_get_dirty_pages(inode, llwp);
- if ( llwp->num_pages ) {
- ll_brw_pages_unlock(inode, llwp);
- rc += llwp->num_pages;
- making_progress = 1;
- }
- } while (llwp->num_pages && should_writeback() );
-
- spin_lock(&inode_lock);
-
- if ( ! list_empty(&inode->i_mapping->dirty_pages) )
- inode->i_state |= I_DIRTY_PAGES;
-
- inode->i_state &= ~I_LOCK;
- /*
- * we are sneaky and leave the inode on the dirty list,
- * even though it might not still be..
- */
- if (!(inode->i_state & I_FREEING)) {
- list_del(&inode->i_list);
- list_add(&inode->i_list, &inode->i_sb->s_dirty);
- }
- wake_up(&inode->i_wait);
-
- } while ( making_progress && should_writeback() );
-
- /*
- * and if that didn't work, we sleep on any data that might
- * be under writeback..
- */
- while ( should_writeback() ) {
- if ( list_empty(&sb->s_locked_inodes) )
- break;
-
- inode = list_entry(sb->s_locked_inodes.next, struct inode,
- i_list);
-
- atomic_inc(&inode->i_count); /* XXX hack? */
- spin_unlock(&inode_lock);
- wait_event(inode->i_wait, !(inode->i_state & I_LOCK));
- iput(inode);
- spin_lock(&inode_lock);
- }
-
- spin_unlock(&inode_lock);
-
-cleanup:
- if ( llwp != NULL )
- kfree(llwp);
- current->flags = old_flags;
-
- RETURN(rc);
-}
-
-int ll_batch_writepage( struct inode *inode, struct page *page )
-{
- unsigned long old_flags; /* hack? */
- struct ll_writeback_pages *llwp;
- int rc = 0;
- ENTRY;
-
- old_flags = current->flags;
- current->flags |= PF_MEMALLOC;
- llwp = kmalloc(sizeof(struct ll_writeback_pages), GFP_ATOMIC);
- if ( llwp == NULL )
- GOTO(cleanup, rc = -ENOMEM);
- memset(llwp, 0, offsetof(struct ll_writeback_pages, pgs));
-
- llwp_consume_page(llwp, inode, page);
-
- ll_get_dirty_pages(inode, llwp);
- if ( llwp->num_pages )
- ll_brw_pages_unlock(inode, llwp);
-
-cleanup:
- if ( llwp != NULL )
- kfree(llwp);
- current->flags = old_flags;
- RETURN(rc);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc. <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (Un)packing of OST/MDS requests
- *
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_net.h>
-#include <linux/obd.h>
-#include <linux/obd_lov.h>
-#include <linux/obd_support.h>
-
-/* lov_packdesc() is in mds/mds_lov.c */
-
-void lov_unpackdesc(struct lov_desc *ld)
-{
- ld->ld_tgt_count = NTOH__u32(ld->ld_tgt_count);
- ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
- ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
- ld->ld_pattern = HTON__u32(ld->ld_pattern);
-}
-
-/* Pack LOV object metadata for shipment to the MDS.
- *
- * XXX In the future, this will be enhanced to get the EA size from the
- * underlying OSC device(s) to get their EA sizes so we can stack
- * LOVs properly. For now lov_mds_md_size() just assumes one obd_id
- * per stripe.
- */
-int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp,
- struct lov_stripe_md *lsm)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct lov_obd *lov = &obd->u.lov;
- struct lov_oinfo *loi;
- struct lov_mds_md *lmm;
- int ost_count = lov->desc.ld_tgt_count;
- int stripe_count = ost_count;
- int lmm_size;
- int i;
- ENTRY;
-
- if (lsm)
- stripe_count = lsm->lsm_stripe_count;
-
- /* XXX LOV STACKING call into osc for sizes */
- lmm_size = lov_mds_md_size(ost_count);
-
- if (!lmmp)
- RETURN(lmm_size);
-
- if (*lmmp && !lsm) {
- /* endianness */
- ost_count = ((*lmmp)->lmm_ost_count);
- OBD_FREE(*lmmp, lov_mds_md_size(ost_count));
- *lmmp = NULL;
- RETURN(0);
- }
-
- if (!*lmmp) {
- OBD_ALLOC(*lmmp, lmm_size);
- if (!*lmmp)
- RETURN(-ENOMEM);
- }
-
- lmm = *lmmp;
-
- lmm->lmm_stripe_count = (stripe_count);
- if (!lsm)
- RETURN(lmm_size);
- /* XXX endianness */
- lmm->lmm_magic = (lsm->lsm_magic);
- lmm->lmm_object_id = (lsm->lsm_object_id);
- lmm->lmm_stripe_size = (lsm->lsm_stripe_size);
- lmm->lmm_stripe_pattern = (lsm->lsm_stripe_pattern);
- lmm->lmm_stripe_offset = (lsm->lsm_stripe_offset);
- lmm->lmm_ost_count = (lov->desc.ld_tgt_count);
-
- /* Only fill in the object ids which we are actually using.
- * Assumes lmm_objects is otherwise zero-filled. */
- for (i = 0, loi = lsm->lsm_oinfo; i < stripe_count; i++, loi++)
- /* XXX call down to osc_packmd() to do the packing */
- lmm->lmm_objects[loi->loi_ost_idx].l_object_id = (loi->loi_id);
-
- RETURN(lmm_size);
-}
-
-int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
- struct lov_mds_md *lmm)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct lov_obd *lov = &obd->u.lov;
- struct lov_stripe_md *lsm;
- struct lov_oinfo *loi;
- int ost_count = lov->desc.ld_active_tgt_count;
- int ost_offset = 0;
- int stripe_count = 0;
- int lsm_size;
- int i;
- ENTRY;
-
- if (lmm)
- /* endianness */
- stripe_count = (lmm->lmm_stripe_count);
-
- if (!stripe_count)
- stripe_count = lov->desc.ld_default_stripe_count;
- if (!stripe_count || stripe_count > ost_count)
- stripe_count = ost_count;
-
- /* XXX LOV STACKING call into osc for sizes */
- lsm_size = lov_stripe_md_size(stripe_count);
-
- if (!lsmp)
- RETURN(lsm_size);
-
- if (*lsmp && !lmm) {
- stripe_count = (*lsmp)->lsm_stripe_count;
- OBD_FREE(*lsmp, lov_stripe_md_size(stripe_count));
- *lsmp = NULL;
- RETURN(0);
- }
-
- if (!*lsmp) {
- OBD_ALLOC(*lsmp, lsm_size);
- if (!*lsmp)
- RETURN(-ENOMEM);
- }
-
- lsm = *lsmp;
-
- lsm->lsm_stripe_count = stripe_count;
- if (!lmm)
- RETURN(lsm_size);
-
- /* XXX endianness */
- ost_offset = lsm->lsm_stripe_offset = (lmm->lmm_stripe_offset);
- lsm->lsm_magic = (lmm->lmm_magic);
- lsm->lsm_object_id = (lmm->lmm_object_id);
- lsm->lsm_stripe_size = (lmm->lmm_stripe_size);
- lsm->lsm_stripe_pattern = (lmm->lmm_stripe_pattern);
-
- for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) {
- ost_offset %= ost_count;
-
- if (!lmm->lmm_objects[ost_offset].l_object_id)
- continue;
-
- LASSERT(loi - lsm->lsm_oinfo < stripe_count);
- /* XXX LOV STACKING call down to osc_unpackmd() */
- loi->loi_id = (lmm->lmm_objects[ost_offset].l_object_id);
- loi->loi_ost_idx = ost_offset;
- loi++;
- }
-
- RETURN(lsm_size);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lustre/mds/handler.c
- * Lustre Metadata Server (mds) request handler
- *
- * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
- * Author: Peter Braam <braam@clusterfs.com>
- * Author: Andreas Dilger <adilger@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- * Author: Mike Shaver <shaver@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/module.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_dlm.h>
-#include <linux/init.h>
-#include <linux/obd_class.h>
-#include <linux/random.h>
-#include <linux/locks.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
-#include <linux/buffer_head.h>
-#include <linux/workqueue.h>
-#endif
-#include <linux/obd_lov.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_fsfilt.h>
-#include <linux/lprocfs_status.h>
-
-extern kmem_cache_t *mds_file_cache;
-extern inline struct mds_obd *mds_req2mds(struct ptlrpc_request *req);
-extern void mds_start_transno(struct mds_obd *mds);
-extern int mds_finish_transno(struct mds_obd *mds, void *handle,
- struct ptlrpc_request *req, int rc);
-extern int enqueue_ordered_locks(int lock_mode, struct obd_device *obd,
- struct ldlm_res_id *p1_res_id,
- struct ldlm_res_id *p2_res_id,
- struct ldlm_res_id *c1_res_id,
- struct ldlm_res_id *c2_res_id,
- struct lustre_handle *p1_lockh,
- struct lustre_handle *p2_lockh,
- struct lustre_handle *c1_lockh,
- struct lustre_handle *c2_lockh);
-
-int mds_open(struct mds_update_record *rec, int offset,
- struct ptlrpc_request *req, struct lustre_handle *child_lockh)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct obd_device *obd = req->rq_export->exp_obd;
- struct ldlm_reply *rep = lustre_msg_buf(req->rq_repmsg, 0);
- struct file *file;
- struct mds_body *body = lustre_msg_buf(req->rq_repmsg, 1);
- struct dentry *dchild, *parent;
- struct mds_export_data *med;
- struct mds_file_data *mfd = NULL;
- struct ldlm_res_id child_res_id = { .name = {0} };
- struct lustre_handle parent_lockh;
- int rc = 0, parent_mode, child_mode = LCK_PR, lock_flags, created = 0;
- ENTRY;
-
-#warning replay of open needs to be redone
- /* was this animal open already and the client lost the reply? */
- /* XXX need some way to detect a reopen, to avoid locked list walks */
- med = &req->rq_export->exp_mds_data;
-#if 0
- spin_lock(&med->med_open_lock);
- list_for_each(tmp, &med->med_open_head) {
- mfd = list_entry(tmp, typeof(*mfd), mfd_list);
- if (!memcmp(&mfd->mfd_clienthandle, &body->handle,
- sizeof(mfd->mfd_clienthandle)) &&
- body->fid1.id == mfd->mfd_file->f_dentry->d_inode->i_ino) {
- dchild = mfd->mfd_file->f_dentry;
- spin_unlock(&med->med_open_lock);
- CERROR("Re opening "LPD64"\n", body->fid1.id);
- GOTO(out_pack, rc = 0);
- }
- }
- spin_unlock(&med->med_open_lock);
-#endif
- rep->lock_policy_res1 |= IT_OPEN_LOOKUP;
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OPEN_PACK)) {
- CERROR("test case OBD_FAIL_MDS_OPEN_PACK\n");
- req->rq_status = -ENOMEM;
- RETURN(-ENOMEM);
- }
-
- /* Step 1: Find and lock the parent */
- parent_mode = (rec->ur_flags & O_CREAT) ? LCK_PW : LCK_PR;
- parent = mds_fid2locked_dentry(obd, rec->ur_fid1, NULL, parent_mode,
- &parent_lockh);
- if (IS_ERR(parent)) {
- rc = PTR_ERR(parent);
- CERROR("parent lookup error %d\n", rc);
- LBUG();
- RETURN(rc);
- }
- LASSERT(parent->d_inode);
-
- /* Step 2: Lookup the child */
- dchild = lookup_one_len(lustre_msg_buf(req->rq_reqmsg, 3),
- parent, req->rq_reqmsg->buflens[3] - 1);
- if (IS_ERR(dchild))
- GOTO(out_step_2, rc = PTR_ERR(dchild));
-
- if (dchild->d_inode)
- rep->lock_policy_res1 |= IT_OPEN_POS;
- else
- rep->lock_policy_res1 |= IT_OPEN_NEG;
-
- /* Step 3: If the child was negative, and we're supposed to,
- * create it. */
- if ((rec->ur_flags & O_CREAT) && !dchild->d_inode) {
- int err;
- void *handle;
- mds_start_transno(mds);
- rep->lock_policy_res1 |= IT_OPEN_CREATE;
- handle = fsfilt_start(obd, parent->d_inode, FSFILT_OP_CREATE);
- if (IS_ERR(handle)) {
- rc = PTR_ERR(handle);
- mds_finish_transno(mds, handle, req, rc);
- GOTO(out_step_3, rc);
- }
- rc = vfs_create(parent->d_inode, dchild, rec->ur_mode);
- rc = mds_finish_transno(mds, handle, req, rc);
- err = fsfilt_commit(obd, parent->d_inode, handle);
- if (rc || err) {
- CERROR("error on commit: err = %d\n", err);
- if (!rc)
- rc = err;
- GOTO(out_step_3, rc);
- }
- created = 1;
- child_mode = LCK_PW;
- } else if (!dchild->d_inode) {
- /* It's negative and we weren't supposed to create it */
- GOTO(out_step_3, rc = -ENOENT);
- }
-
- /* Step 4: It's positive, so lock the child */
- child_res_id.name[0] = dchild->d_inode->i_ino;
- child_res_id.name[1] = dchild->d_inode->i_generation;
- reacquire:
- lock_flags = 0;
- rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, NULL,
- child_res_id, LDLM_PLAIN, NULL, 0, child_mode,
- &lock_flags, ldlm_completion_ast,
- mds_blocking_ast, NULL, NULL, child_lockh);
- if (rc != ELDLM_OK) {
- CERROR("ldlm_cli_enqueue: %d\n", rc);
- GOTO(out_step_3, rc = -EIO);
- }
-
- mds_pack_inode2fid(&body->fid1, dchild->d_inode);
- mds_pack_inode2body(body, dchild->d_inode);
- if (S_ISREG(dchild->d_inode->i_mode)) {
- rc = mds_pack_md(obd, req->rq_repmsg, 2, body, dchild->d_inode);
- if (rc)
- GOTO(out_step_4, rc);
- } else {
- /* If this isn't a regular file, we can't open it. */
- GOTO(out_step_3, rc = 0); /* returns the lock to the client */
- }
-
- if (!created && (rec->ur_flags & O_CREAT) && (rec->ur_flags & O_EXCL)) {
- /* File already exists, we didn't just create it, and we
- * were passed O_EXCL; err-or. */
- GOTO(out_step_3, rc = -EEXIST); // returns a lock to the client
- }
-
- /* If we're opening a file without an EA, the client needs a write
- * lock. */
- if (child_mode != LCK_PW && S_ISREG(dchild->d_inode->i_mode) &&
- !(body->valid & OBD_MD_FLEASIZE)) {
- ldlm_lock_decref(child_lockh, child_mode);
- child_mode = LCK_PW;
- goto reacquire;
- }
-
- /* Step 5: Open it */
- rep->lock_policy_res1 |= IT_OPEN_OPEN;
- mfd = kmem_cache_alloc(mds_file_cache, GFP_KERNEL);
- if (!mfd) {
- CERROR("mds: out of memory\n");
- GOTO(out_step_4, req->rq_status = -ENOMEM);
- }
-
- /* dentry_open does a dput(de) and mntput(mds->mds_vfsmnt) on error */
- mntget(mds->mds_vfsmnt);
- file = dentry_open(dchild,mds->mds_vfsmnt,
- rec->ur_flags & ~(O_DIRECT | O_TRUNC));
- if (IS_ERR(file))
- GOTO(out_step_5, rc = PTR_ERR(file));
-
- file->private_data = mfd;
- mfd->mfd_file = file;
- get_random_bytes(&mfd->mfd_servercookie, sizeof(mfd->mfd_servercookie));
- spin_lock(&med->med_open_lock);
- list_add(&mfd->mfd_list, &med->med_open_head);
- spin_unlock(&med->med_open_lock);
-
- body->handle.addr = (__u64)(unsigned long)mfd;
- body->handle.cookie = mfd->mfd_servercookie;
- CDEBUG(D_INODE, "file %p: mfd %p, cookie "LPX64"\n",
- mfd->mfd_file, mfd, mfd->mfd_servercookie);
- GOTO(out_step_2, rc = 0); /* returns a lock to the client */
-
- out_step_5:
- if (mfd != NULL) {
- kmem_cache_free(mds_file_cache, mfd);
- mfd = NULL;
- }
- out_step_4:
- ldlm_lock_decref(child_lockh, child_mode);
- out_step_3:
- l_dput(dchild);
- out_step_2:
- l_dput(parent);
- ldlm_lock_decref(&parent_lockh, parent_mode);
- RETURN(rc);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Phil Schwan <phil@clusterfs.com>
- *
- * This file is part of Portals, http://www.sf.net/projects/sandiaportals/
- *
- * Portals is free software; you can redistribute it and/or
- * modify it under the terms of version 2.1 of the GNU Lesser General
- * Public License as published by the Free Software Foundation.
- *
- * Portals 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Portals; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-#include <linux/random.h>
-
-#define DEBUG_SUBSYSTEM S_PORTALS
-
-#include <linux/kp30.h>
-#include <linux/lustre_handles.h>
-
-static spinlock_t handle_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t random_lock = SPIN_LOCK_UNLOCKED;
-static struct list_head *handle_hash = NULL;
-static int handle_count = 0;
-
-#define HANDLE_HASH_SIZE (1 << 14)
-#define HANDLE_HASH_MASK (HANDLE_HASH_SIZE - 1)
-
-void class_handle_hash(struct portals_handle *h, portals_handle_addref_cb cb)
-{
- struct list_head *bucket;
- ENTRY;
-
- LASSERT(h != NULL);
- LASSERT(list_empty(&h->h_link));
-
- /* My hypothesis is that get_random_bytes, if called from two threads at
- * the same time, will return the same bytes. -phil */
- spin_lock(&random_lock);
- get_random_bytes(&h->h_cookie, sizeof(h->h_cookie));
- spin_unlock(&random_lock);
-
- h->h_addref = cb;
-
- bucket = handle_hash + (h->h_cookie & HANDLE_HASH_MASK);
-
- CDEBUG(D_INFO, "adding object %p with handle "LPX64" to hash\n",
- h, h->h_cookie);
-
- spin_lock(&handle_lock);
- list_add(&h->h_link, bucket);
- handle_count++;
- spin_unlock(&handle_lock);
- EXIT;
-}
-
-static void class_handle_unhash_nolock(struct portals_handle *h)
-{
- LASSERT(!list_empty(&h->h_link));
-
- CDEBUG(D_INFO, "removing object %p with handle "LPX64" from hash\n",
- h, h->h_cookie);
-
- handle_count--;
- list_del_init(&h->h_link);
-}
-
-void class_handle_unhash(struct portals_handle *h)
-{
- spin_lock(&handle_lock);
- class_handle_unhash_nolock(h);
- spin_unlock(&handle_lock);
-}
-
-void *class_handle2object(__u64 cookie)
-{
- struct list_head *bucket, *tmp;
- void *retval = NULL;
- ENTRY;
-
- LASSERT(handle_hash != NULL);
-
- spin_lock(&handle_lock);
- bucket = handle_hash + (cookie & HANDLE_HASH_MASK);
-
- list_for_each(tmp, bucket) {
- struct portals_handle *h;
- h = list_entry(tmp, struct portals_handle, h_link);
-
- if (h->h_cookie == cookie) {
- h->h_addref(h);
- retval = h;
- break;
- }
- }
- spin_unlock(&handle_lock);
-
- RETURN(retval);
-}
-
-int class_handle_init(void)
-{
- struct list_head *bucket;
-
- LASSERT(handle_hash == NULL);
-
- PORTAL_ALLOC(handle_hash, sizeof(*handle_hash) * HANDLE_HASH_SIZE);
- if (handle_hash == NULL)
- return -ENOMEM;
-
- for (bucket = handle_hash + HANDLE_HASH_SIZE - 1; bucket >= handle_hash;
- bucket--)
- INIT_LIST_HEAD(bucket);
-
- return 0;
-}
-
-static void cleanup_all_handles(void)
-{
- int i;
-
- spin_lock(&handle_lock);
- for (i = 0; i < HANDLE_HASH_SIZE; i++) {
- struct list_head *tmp, *pos;
- list_for_each_safe(tmp, pos, &(handle_hash[i])) {
- struct portals_handle *h;
- h = list_entry(tmp, struct portals_handle, h_link);
-
- CERROR("forcing cleanup for handle "LPX64"\n",
- h->h_cookie);
-
- class_handle_unhash_nolock(h);
- }
- }
- spin_lock(&handle_lock);
-}
-
-void class_handle_cleanup(void)
-{
- LASSERT(handle_hash != NULL);
-
- if (handle_count != 0) {
- CERROR("handle_count at cleanup: %d\n", handle_count);
- cleanup_all_handles();
- }
-
- PORTAL_FREE(handle_hash, sizeof(*handle_hash) * HANDLE_HASH_SIZE);
- handle_hash = NULL;
-
- if (handle_count)
- CERROR("leaked %d handles\n", handle_count);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#ifdef __KERNEL__
-# include <linux/module.h>
-# include <linux/init.h>
-# include <linux/list.h>
-#else
-# include <liblustre.h>
-#endif
-#include <linux/obd.h>
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_ha.h>
-#include <linux/lustre_net.h>
-#include <linux/lprocfs_status.h>
-
-struct uuid_nid_data {
- struct list_head head;
- ptl_nid_t nid;
- char *uuid;
- __u32 nal;
- ptl_handle_ni_t ni;
-};
-
-/* FIXME: This should probably become more elegant than a global linked list */
-static struct list_head g_uuid_list;
-static spinlock_t g_uuid_lock;
-
-void class_init_uuidlist(void)
-{
- INIT_LIST_HEAD(&g_uuid_list);
- spin_lock_init(&g_uuid_lock);
-}
-
-void class_exit_uuidlist(void)
-{
- struct list_head *tmp, *n;
-
- /* Module going => sole user => don't need to lock g_uuid_list */
- list_for_each_safe(tmp, n, &g_uuid_list) {
- struct uuid_nid_data *data =
- list_entry(tmp, struct uuid_nid_data, head);
-
- PORTAL_FREE(data->uuid, strlen(data->uuid) + 1);
- PORTAL_FREE(data, sizeof(*data));
- }
-}
-
-int lustre_uuid_to_peer(char *uuid, struct lustre_peer *peer)
-{
- struct list_head *tmp;
-
- spin_lock (&g_uuid_lock);
-
- list_for_each(tmp, &g_uuid_list) {
- struct uuid_nid_data *data =
- list_entry(tmp, struct uuid_nid_data, head);
-
- if (strcmp(data->uuid, uuid) == 0) {
- peer->peer_nid = data->nid;
- peer->peer_ni = data->ni;
-
- spin_unlock (&g_uuid_lock);
- return 0;
- }
- }
-
- spin_unlock (&g_uuid_lock);
- return -1;
-}
-
-int class_add_uuid(char *uuid, __u64 nid, __u32 nal)
-{
- const ptl_handle_ni_t *nip;
- struct uuid_nid_data *data;
- int rc;
- int nob = strnlen (uuid, PAGE_SIZE) + 1;
-
- if (nob > PAGE_SIZE)
- return -EINVAL;
-
- nip = kportal_get_ni (nal);
- if (nip == NULL) {
- CERROR("get_ni failed: is the NAL module loaded?\n");
- return -EIO;
- }
-
- rc = -ENOMEM;
- PORTAL_ALLOC(data, sizeof(*data));
- if (data == NULL)
- goto fail_0;
-
- PORTAL_ALLOC(data->uuid, nob);
- if (data == NULL)
- goto fail_1;
-
- memcpy(data->uuid, uuid, nob);
- data->nid = nid;
- data->nal = nal;
- data->ni = *nip;
-
- spin_lock (&g_uuid_lock);
-
- list_add(&data->head, &g_uuid_list);
-
- spin_unlock (&g_uuid_lock);
-
- return 0;
-
- fail_1:
- PORTAL_FREE (data, sizeof (*data));
- fail_0:
- kportal_put_ni (nal);
- return (rc);
-}
-
-/* delete only one entry if uuid is specified, otherwise delete all */
-int class_del_uuid (char *uuid)
-{
- struct list_head deathrow;
- struct list_head *tmp;
- struct list_head *n;
- struct uuid_nid_data *data;
-
- INIT_LIST_HEAD (&deathrow);
-
- spin_lock (&g_uuid_lock);
-
- list_for_each_safe(tmp, n, &g_uuid_list) {
- data = list_entry(tmp, struct uuid_nid_data, head);
-
- if (uuid == NULL || strcmp(data->uuid, uuid) == 0) {
- list_del (&data->head);
- list_add (&data->head, &deathrow);
- if (uuid)
- break;
- }
- }
-
- spin_unlock (&g_uuid_lock);
-
- if (list_empty (&deathrow))
- return -EINVAL;
-
- do {
- data = list_entry(deathrow.next, struct uuid_nid_data, head);
-
- list_del (&data->head);
-
- kportal_put_ni (data->nal);
- PORTAL_FREE(data->uuid, strlen(data->uuid) + 1);
- PORTAL_FREE(data, sizeof(*data));
- } while (!list_empty (&deathrow));
-
- return 0;
-}
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS:=
-
-MODULE = ptlrpc
-modulefs_DATA = ptlrpc.o
-EXTRA_PROGRAMS = ptlrpc
-
-ptlrpc_SOURCES = rpc.c events.c service.c client.c niobuf.c
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define EXPORT_SYMTAB
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-
-int ptlrpc_enqueue(struct ptlrpc_client *peer, struct ptlrpc_request *req)
-{
- struct ptlrpc_request *srv_req;
-
- if (!peer->cli_obd) {
- EXIT;
- return -1;
- }
-
- OBD_ALLOC(srv_req, sizeof(*srv_req));
- if (!srv_req) {
- EXIT;
- return -ENOMEM;
- }
-
- CDEBUG(0, "peer obd minor %d, incoming req %p, srv_req %p\n",
- peer->cli_obd->obd_minor, req, srv_req);
-
- memset(srv_req, 0, sizeof(*req));
-
- /* move the request buffer */
- srv_req->rq_reqbuf = req->rq_reqbuf;
- srv_req->rq_reqlen = req->rq_reqlen;
- srv_req->rq_obd = peer->cli_obd;
-
- /* remember where it came from */
- srv_req->rq_reply_handle = req;
-
- list_add(&srv_req->rq_list, &peer->cli_obd->obd_req_list);
- wake_up(&peer->cli_obd->obd_req_waitq);
- return 0;
-}
-
-int ptlrpc_connect_client(int dev, char *uuid, int req_portal, int rep_portal,
- req_pack_t req_pack, rep_unpack_t rep_unpack,
- struct ptlrpc_client *cl)
-{
- int err;
-
- memset(cl, 0, sizeof(*cl));
- spin_lock_init(&cl->cli_lock);
- cl->cli_xid = 1;
- cl->cli_obd = NULL;
- cl->cli_request_portal = req_portal;
- cl->cli_reply_portal = rep_portal;
- cl->cli_rep_unpack = rep_unpack;
- cl->cli_req_pack = req_pack;
-
- /* non networked client */
- if (dev >= 0 && dev < MAX_OBD_DEVICES) {
- struct obd_device *obd = &obd_dev[dev];
-
- if ((!obd->obd_flags & OBD_ATTACHED) ||
- (!obd->obd_flags & OBD_SET_UP)) {
- CERROR("target device %d not att or setup\n", dev);
- return -EINVAL;
- }
- if (strcmp(obd->obd_type->typ_name, "ost") &&
- strcmp(obd->obd_type->typ_name, "mds")) {
- return -EINVAL;
- }
-
- cl->cli_obd = &obd_dev[dev];
- return 0;
- }
-
- /* networked */
- err = kportal_uuid_to_peer(uuid, &cl->cli_server);
- if (err != 0) {
- CERROR("cannot find peer %s!", uuid);
- }
-
- return err;
-}
-
-struct ptlrpc_bulk_desc *ptlrpc_prep_bulk(struct lustre_peer *peer)
-{
- struct ptlrpc_bulk_desc *bulk;
-
- OBD_ALLOC(bulk, sizeof(*bulk));
- if (bulk != NULL) {
- memset(bulk, 0, sizeof(*bulk));
- memcpy(&bulk->b_peer, peer, sizeof(*peer));
- init_waitqueue_head(&bulk->b_waitq);
- }
-
- return bulk;
-}
-
-struct ptlrpc_request *ptlrpc_prep_req(struct ptlrpc_client *cl,
- int opcode, int namelen, char *name,
- int tgtlen, char *tgt)
-{
- struct ptlrpc_request *request;
- int rc;
- ENTRY;
-
- OBD_ALLOC(request, sizeof(*request));
- if (!request) {
- CERROR("request allocation out of memory\n");
- return NULL;
- }
-
- memset(request, 0, sizeof(*request));
-
- spin_lock(&cl->cli_lock);
- request->rq_xid = cl->cli_xid++;
- spin_unlock(&cl->cli_lock);
-
- rc = cl->cli_req_pack(name, namelen, tgt, tgtlen,
- &request->rq_reqhdr, &request->rq_req,
- &request->rq_reqlen, &request->rq_reqbuf);
- if (rc) {
- CERROR("cannot pack request %d\n", rc);
- return NULL;
- }
- request->rq_reqhdr->opc = opcode;
- request->rq_reqhdr->xid = request->rq_xid;
-
- EXIT;
- return request;
-}
-
-void ptlrpc_free_req(struct ptlrpc_request *request)
-{
- OBD_FREE(request, sizeof(*request));
-}
-
-static int ptlrpc_check_reply(struct ptlrpc_request *req)
-{
- if (req->rq_repbuf != NULL) {
- req->rq_flags = PTL_RPC_REPLY;
- EXIT;
- return 1;
- }
-
- if (sigismember(&(current->pending.signal), SIGKILL) ||
- sigismember(&(current->pending.signal), SIGINT)) {
- req->rq_flags = PTL_RPC_INTR;
- EXIT;
- return 1;
- }
-
- return 0;
-}
-
-/* Abort this request and cleanup any resources associated with it. */
-int ptlrpc_abort(struct ptlrpc_request *request)
-{
- /* First remove the MD for the reply; in theory, this means
- * that we can tear down the buffer safely. */
- PtlMEUnlink(request->rq_reply_me_h);
- PtlMDUnlink(request->rq_reply_md_h);
- OBD_FREE(request->rq_repbuf, request->rq_replen);
- request->rq_repbuf = NULL;
- request->rq_replen = 0;
-
- return 0;
-}
-
-int ptlrpc_queue_wait(struct ptlrpc_client *cl, struct ptlrpc_request *req)
-
-{
- int rc;
- ENTRY;
-
- init_waitqueue_head(&req->rq_wait_for_rep);
-
- if (cl->cli_obd) {
- /* Local delivery */
- ENTRY;
- rc = ptlrpc_enqueue(cl, req);
- } else {
- /* Remote delivery via portals. */
- req->rq_req_portal = cl->cli_request_portal;
- req->rq_reply_portal = cl->cli_reply_portal;
- rc = ptl_send_rpc(req, &cl->cli_server);
- }
- if (rc) {
- CERROR("error %d, opcode %d\n", rc, req->rq_reqhdr->opc);
- return -rc;
- }
-
- CDEBUG(0, "-- sleeping\n");
- wait_event_interruptible(req->rq_wait_for_rep, ptlrpc_check_reply(req));
- CDEBUG(0, "-- done\n");
-
- if (req->rq_flags == PTL_RPC_INTR) {
- /* Clean up the dangling reply buffers */
- ptlrpc_abort(req);
- EXIT;
- return -EINTR;
- }
-
- if (req->rq_flags != PTL_RPC_REPLY) {
- CERROR("Unknown reason for wakeup\n");
- EXIT;
- return -EINTR;
- }
-
- rc = cl->cli_rep_unpack(req->rq_repbuf, req->rq_replen,
- &req->rq_rephdr, &req->rq_rep);
- if (rc) {
- CERROR("unpack_rep failed: %d\n", rc);
- return rc;
- }
- CERROR("got rep %d\n", req->rq_rephdr->xid);
-
- if ( req->rq_rephdr->status == 0 )
- CDEBUG(0, "--> buf %p len %d status %d\n", req->rq_repbuf,
- req->rq_replen, req->rq_rephdr->status);
-
- EXIT;
- return 0;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define EXPORT_SYMTAB
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-
-ptl_handle_eq_t sent_pkt_eq, rcvd_rep_eq, bulk_source_eq, bulk_sink_eq;
-static const ptl_handle_ni_t *socknal_nip = NULL, *qswnal_nip = NULL;
-
-/*
- * Free the packet when it has gone out
- */
-static int sent_packet_callback(ptl_event_t *ev, void *data)
-{
- ENTRY;
-
- if (ev->type == PTL_EVENT_SENT) {
- OBD_FREE(ev->mem_desc.start, ev->mem_desc.length);
- } else {
- // XXX make sure we understand all events, including ACK's
- CERROR("Unknown event %d\n", ev->type);
- BUG();
- }
-
- EXIT;
- return 1;
-}
-
-/*
- * Wake up the thread waiting for the reply once it comes in.
- */
-static int rcvd_reply_callback(ptl_event_t *ev, void *data)
-{
- struct ptlrpc_request *rpc = ev->mem_desc.user_ptr;
- ENTRY;
-
- if (ev->type == PTL_EVENT_PUT) {
- rpc->rq_repbuf = ev->mem_desc.start + ev->offset;
- barrier();
- wake_up_interruptible(&rpc->rq_wait_for_rep);
- } else {
- // XXX make sure we understand all events, including ACK's
- CERROR("Unknown event %d\n", ev->type);
- BUG();
- }
-
- EXIT;
- return 1;
-}
-
-int server_request_callback(ptl_event_t *ev, void *data)
-{
- struct ptlrpc_service *service = data;
- int rc;
-
- if (ev->rlength != ev->mlength)
- CERROR("Warning: Possibly truncated rpc (%d/%d)\n",
- ev->mlength, ev->rlength);
-
- /* The ME is unlinked when there is less than 1024 bytes free
- * on its MD. This ensures we are always able to handle the rpc,
- * although the 1024 value is a guess as to the size of a
- * large rpc (the known safe margin should be determined).
- *
- * NOTE: The portals API by default unlinks all MD's associated
- * with an ME when it's unlinked. For now, this behavior
- * has been commented out of the portals library so the
- * MD can be unlinked when its ref count drops to zero.
- * A new MD and ME will then be created that use the same
- * kmalloc()'ed memory and inserted at the ring tail.
- */
-
- service->srv_ref_count[service->srv_md_active]++;
-
- if (ev->offset >= (service->srv_buf_size - 1024)) {
- CDEBUG(D_INODE, "Unlinking ME %d\n", service->srv_me_active);
-
- rc = PtlMEUnlink(service->srv_me_h[service->srv_me_active]);
- service->srv_me_h[service->srv_me_active] = 0;
-
- if (rc != PTL_OK) {
- CERROR("PtlMEUnlink failed - DROPPING soon: %d\n", rc);
- BUG();
- return rc;
- }
-
- service->srv_me_active = NEXT_INDEX(service->srv_me_active,
- service->srv_ring_length);
-
- if (service->srv_me_h[service->srv_me_active] == 0)
- CERROR("All %d ring ME's are unlinked!\n",
- service->srv_ring_length);
- }
-
- if (ev->type == PTL_EVENT_PUT) {
- wake_up(&service->srv_waitq);
- } else {
- CERROR("Unexpected event type: %d\n", ev->type);
- }
-
- return 0;
-}
-
-
-static int bulk_source_callback(ptl_event_t *ev, void *data)
-{
- struct ptlrpc_bulk_desc *bulk = ev->mem_desc.user_ptr;
-
- ENTRY;
-
- if (ev->type == PTL_EVENT_SENT) {
- CDEBUG(D_NET, "got SENT event\n");
- } else if (ev->type == PTL_EVENT_ACK) {
- CDEBUG(D_NET, "got ACK event\n");
- bulk->b_flags = PTL_BULK_SENT;
- wake_up_interruptible(&bulk->b_waitq);
- } else {
- CERROR("Unexpected event type!\n");
- BUG();
- }
-
- EXIT;
- return 1;
-}
-
-static int bulk_sink_callback(ptl_event_t *ev, void *data)
-{
- struct ptlrpc_bulk_desc *bulk = ev->mem_desc.user_ptr;
-
- ENTRY;
-
- if (ev->type == PTL_EVENT_PUT) {
- if (bulk->b_buf != ev->mem_desc.start + ev->offset)
- CERROR("bulkbuf != mem_desc -- why?\n");
- bulk->b_flags = PTL_BULK_RCVD;
- wake_up_interruptible(&bulk->b_waitq);
- } else {
- CERROR("Unexpected event type!\n");
- BUG();
- }
-
- EXIT;
- return 1;
-}
-
-int ptlrpc_init_portals(void)
-{
- int rc;
- ptl_handle_ni_t ni;
-
- socknal_nip = inter_module_get_request("ksocknal_ni", "ksocknal");
- qswnal_nip = inter_module_get_request("kqswnal_ni", "kqswnal");
- if (socknal_nip == NULL && qswnal_nip == NULL) {
- CERROR("get_ni failed: is a NAL module loaded?\n");
- return -EIO;
- }
-
- /* Use the qswnal if it's there */
- if (qswnal_nip != NULL)
- ni = *qswnal_nip;
- else
- ni = *socknal_nip;
-
- rc = PtlEQAlloc(ni, 128, sent_packet_callback, NULL, &sent_pkt_eq);
- if (rc != PTL_OK)
- CERROR("PtlEQAlloc failed: %d\n", rc);
-
- rc = PtlEQAlloc(ni, 128, rcvd_reply_callback, NULL, &rcvd_rep_eq);
- if (rc != PTL_OK)
- CERROR("PtlEQAlloc failed: %d\n", rc);
-
- rc = PtlEQAlloc(ni, 128, bulk_source_callback, NULL, &bulk_source_eq);
- if (rc != PTL_OK)
- CERROR("PtlEQAlloc failed: %d\n", rc);
-
- rc = PtlEQAlloc(ni, 128, bulk_sink_callback, NULL, &bulk_sink_eq);
- if (rc != PTL_OK)
- CERROR("PtlEQAlloc failed: %d\n", rc);
-
- return rc;
-}
-
-void ptlrpc_exit_portals(void)
-{
- PtlEQFree(sent_pkt_eq);
- PtlEQFree(rcvd_rep_eq);
- PtlEQFree(bulk_source_eq);
- PtlEQFree(bulk_sink_eq);
-
- if (qswnal_nip != NULL)
- inter_module_put("kqswnal_ni");
- if (socknal_nip != NULL)
- inter_module_put("ksocknal_ni");
-}
+++ /dev/null
-
-
-
-struct uuid_nid_data {
- struct list_head head;
- char *uuid;
- __u32 nid;
- __u32 nal;
- ptl_handle_ni_t ni;
-};
-
-
-/* FIXME: This should probably become more elegant than a global linked list */
-static struct list_head g_uuid_list;
-static spinlock_t g_uuid_lock;
-
-
-int lustre_uuid_to_peer(char *uuid, struct lustre_peer *peer)
-{
- struct list_head *tmp;
-
- spin_lock (&g_uuid_lock);
-
- list_for_each(tmp, &g_uuid_list) {
- struct uuid_nid_data *data =
- list_entry(tmp, struct uuid_nid_data, head);
-
- if (strcmp(data->uuid, uuid) == 0) {
- peer->peer_nid = data->nid;
- peer->peer_ni = data->ni;
-
- spin_unlock (&g_uuid_lock);
- return 0;
- }
- }
-
- spin_unlock (&g_uuid_lock);
- return -1;
-}
-
-/* delete only one entry if uuid is specified, otherwise delete all */
-static int lustre_add_uuid(char *uuid, __u64 nid, __u32 nal)
-{
- const ptl_handle_ni_t *nip;
- struct uuid_nid_data *data;
- int rc;
- int nob = strnlen (uuid, PAGE_SIZE) + 1;
-
- if (nob > PAGE_SIZE)
- return -EINVAL;
-
- nip = lustre_get_ni (nal);
- if (nip == NULL) {
- CERROR("get_ni failed: is the NAL module loaded?\n");
- return -EIO;
- }
-
- rc = -ENOMEM;
- PORTAL_ALLOC(data, sizeof(*data));
- if (data == NULL)
- goto fail_0;
-
- PORTAL_ALLOC(data->uuid, nob);
- if (data == NULL)
- goto fail_1;
-
- memcpy(data->uuid, uuid, nob);
- data->nid = nid;
- data->nal = nal;
- data->ni = *nip;
-
- spin_lock (&g_uuid_lock);
-
- list_add(&data->head, &g_uuid_list);
-
- spin_unlock (&g_uuid_lock);
-
- return 0;
-
- fail_1:
- PORTAL_FREE (data, sizeof (*data));
- fail_0:
- lustre_put_ni (nal);
- return (rc);
-}
-
-static int lustre_del_uuid (char *uuid)
-{
- struct list_head deathrow;
- struct list_head *tmp;
- struct list_head *n;
- struct uuid_nid_data *data;
-
- INIT_LIST_HEAD (&deathrow);
-
- spin_lock (&g_uuid_lock);
-
- list_for_each_safe(tmp, n, &g_uuid_list) {
- data = list_entry(tmp, struct uuid_nid_data, head);
-
- if (uuid == NULL || strcmp(data->uuid, uuid) == 0) {
- list_del (&data->head);
- list_add (&data->head, &deathrow);
- if (uuid)
- break;
- }
- }
-
- spin_unlock (&g_uuid_lock);
-
- if (list_empty (&deathrow))
- return -EINVAL;
-
- do {
- data = list_entry(deathrow.next, struct uuid_nid_data, head);
-
- list_del (&data->head);
-
- lustre_put_ni (data->nal);
- PORTAL_FREE(data->uuid, strlen(data->uuid) + 1);
- PORTAL_FREE(data, sizeof(*data));
- } while (!list_empty (&deathrow));
-
- return 0;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define EXPORT_SYMTAB
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-
-extern ptl_handle_eq_t bulk_source_eq, sent_pkt_eq, rcvd_rep_eq, bulk_sink_eq;
-static ptl_process_id_t local_id = {PTL_ADDR_GID, PTL_ID_ANY, PTL_ID_ANY};
-
-
-int ptlrpc_check_bulk_sent(struct ptlrpc_bulk_desc *bulk)
-{
- if (bulk->b_flags == PTL_BULK_SENT) {
- EXIT;
- return 1;
- }
-
- if (sigismember(&(current->pending.signal), SIGKILL) ||
- sigismember(&(current->pending.signal), SIGINT)) {
- bulk->b_flags = PTL_RPC_INTR;
- EXIT;
- return 1;
- }
-
- CERROR("no event yet\n");
- return 0;
-}
-
-int ptl_send_buf(struct ptlrpc_request *request, struct lustre_peer *peer,
- int portal)
-{
- int rc;
- ptl_process_id_t remote_id;
- ptl_handle_md_t md_h;
- ptl_ack_req_t ack;
-
- switch (request->rq_type) {
- case PTL_RPC_BULK:
- request->rq_req_md.start = request->rq_bulkbuf;
- request->rq_req_md.length = request->rq_bulklen;
- request->rq_req_md.eventq = bulk_source_eq;
- request->rq_req_md.threshold = 2; /* SENT and ACK events */
- ack = PTL_ACK_REQ;
- break;
- case PTL_RPC_REQUEST:
- request->rq_req_md.start = request->rq_reqbuf;
- request->rq_req_md.length = request->rq_reqlen;
- request->rq_req_md.eventq = sent_pkt_eq;
- request->rq_req_md.threshold = 1;
- ack = PTL_NOACK_REQ;
- break;
- case PTL_RPC_REPLY:
- request->rq_req_md.start = request->rq_repbuf;
- request->rq_req_md.length = request->rq_replen;
- request->rq_req_md.eventq = sent_pkt_eq;
- request->rq_req_md.threshold = 1;
- ack = PTL_NOACK_REQ;
- break;
- default:
- BUG();
- return -1; /* notreached */
- }
- request->rq_req_md.options = PTL_MD_OP_PUT;
- request->rq_req_md.user_ptr = request;
-
- rc = PtlMDBind(peer->peer_ni, request->rq_req_md, &md_h);
- if (rc != 0) {
- BUG();
- CERROR("PtlMDBind failed: %d\n", rc);
- return rc;
- }
-
- remote_id.addr_kind = PTL_ADDR_NID;
- remote_id.nid = peer->peer_nid;
- remote_id.pid = 0;
-
- CERROR("Sending %d bytes to portal %d, xid %d\n",
- request->rq_req_md.length, portal, request->rq_xid);
-
- rc = PtlPut(md_h, ack, remote_id, portal, 0, request->rq_xid, 0, 0);
- if (rc != PTL_OK) {
- BUG();
- CERROR("PtlPut(%d, %d, %d) failed: %d\n", remote_id.nid,
- portal, request->rq_xid, rc);
- /* FIXME: tear down md */
- }
-
- return rc;
-}
-
-int ptlrpc_send_bulk(struct ptlrpc_bulk_desc *bulk, int portal)
-{
- int rc;
- ptl_process_id_t remote_id;
- ptl_handle_md_t md_h;
-
- bulk->b_md.start = bulk->b_buf;
- bulk->b_md.length = bulk->b_buflen;
- bulk->b_md.eventq = bulk_source_eq;
- bulk->b_md.threshold = 2; /* SENT and ACK events */
- bulk->b_md.options = PTL_MD_OP_PUT;
- bulk->b_md.user_ptr = bulk;
-
- rc = PtlMDBind(bulk->b_peer.peer_ni, bulk->b_md, &md_h);
- if (rc != 0) {
- BUG();
- CERROR("PtlMDBind failed: %d\n", rc);
- return rc;
- }
-
- remote_id.addr_kind = PTL_ADDR_NID;
- remote_id.nid = bulk->b_peer.peer_nid;
- remote_id.pid = 0;
-
- CERROR("Sending %d bytes to portal %d, xid %d\n",
- bulk->b_md.length, portal, bulk->b_xid);
-
- rc = PtlPut(md_h, PTL_ACK_REQ, remote_id, portal, 0, bulk->b_xid, 0, 0);
- if (rc != PTL_OK) {
- BUG();
- CERROR("PtlPut(%d, %d, %d) failed: %d\n", remote_id.nid,
- portal, bulk->b_xid, rc);
- /* FIXME: tear down md */
- }
-
- return rc;
-}
-
-int ptlrpc_wait_bulk(struct ptlrpc_bulk_desc *bulk)
-{
- int rc;
-
- ENTRY;
-
- rc = PtlMEPrepend(bulk->b_peer.peer_ni, bulk->b_portal, local_id,
- bulk->b_xid, 0, PTL_UNLINK, &bulk->b_me_h);
- if (rc != PTL_OK) {
- CERROR("PtlMEAttach failed: %d\n", rc);
- BUG();
- EXIT;
- goto cleanup1;
- }
-
- bulk->b_md.start = bulk->b_buf;
- bulk->b_md.length = bulk->b_buflen;
- bulk->b_md.threshold = 1;
- bulk->b_md.options = PTL_MD_OP_PUT;
- bulk->b_md.user_ptr = bulk;
- bulk->b_md.eventq = bulk_sink_eq;
-
- rc = PtlMDAttach(bulk->b_me_h, bulk->b_md, PTL_UNLINK, &bulk->b_md_h);
- if (rc != PTL_OK) {
- CERROR("PtlMDAttach failed: %d\n", rc);
- BUG();
- EXIT;
- goto cleanup2;
- }
-
- CDEBUG(D_NET, "Setup bulk sink buffer: %u bytes, xid %u, portal %u\n",
- bulk->b_buflen, bulk->b_xid, bulk->b_portal);
-
- cleanup2:
- PtlMEUnlink(bulk->b_me_h);
- cleanup1:
- PtlMDUnlink(bulk->b_md_h);
-
- return rc;
-}
-
-int ptlrpc_reply(struct obd_device *obddev, struct ptlrpc_service *svc,
- struct ptlrpc_request *req)
-{
- struct ptlrpc_request *clnt_req = req->rq_reply_handle;
- ENTRY;
-
- if (req->rq_reply_handle == NULL) {
- /* This is a request that came from the network via portals. */
-
- /* FIXME: we need to increment the count of handled events */
- req->rq_type = PTL_RPC_REPLY;
- req->rq_reqhdr->xid = req->rq_reqhdr->xid;
- ptl_send_buf(req, &req->rq_peer, svc->srv_rep_portal);
- } else {
- /* This is a local request that came from another thread. */
-
- /* move the reply to the client */
- clnt_req->rq_replen = req->rq_replen;
- clnt_req->rq_repbuf = req->rq_repbuf;
- req->rq_repbuf = NULL;
- req->rq_replen = 0;
-
- /* free the request buffer */
- OBD_FREE(req->rq_reqbuf, req->rq_reqlen);
- req->rq_reqbuf = NULL;
-
- /* wake up the client */
- wake_up_interruptible(&clnt_req->rq_wait_for_rep);
- }
-
- EXIT;
- return 0;
-}
-
-int ptlrpc_error(struct obd_device *obddev, struct ptlrpc_service *svc,
- struct ptlrpc_request *req)
-{
- struct ptlrep_hdr *hdr;
-
- ENTRY;
-
- OBD_ALLOC(hdr, sizeof(*hdr));
- if (!hdr) {
- EXIT;
- return -ENOMEM;
- }
-
- memset(hdr, 0, sizeof(*hdr));
-
- hdr->xid = req->rq_reqhdr->xid;
- hdr->status = req->rq_status;
- hdr->type = OST_TYPE_ERR;
-
- if (req->rq_repbuf) {
- CERROR("req has repbuf\n");
- BUG();
- }
-
- req->rq_repbuf = (char *)hdr;
- req->rq_replen = sizeof(*hdr);
-
- EXIT;
- return ptlrpc_reply(obddev, svc, req);
-}
-
-int ptl_send_rpc(struct ptlrpc_request *request, struct lustre_peer *peer)
-{
- ptl_process_id_t local_id;
- int rc;
- char *repbuf;
-
- ENTRY;
-
- if (request->rq_replen == 0) {
- CERROR("request->rq_replen is 0!\n");
- EXIT;
- return -EINVAL;
- }
-
- /* request->rq_repbuf is set only when the reply comes in, in
- * client_packet_callback() */
- OBD_ALLOC(repbuf, request->rq_replen);
- if (!repbuf) {
- EXIT;
- return -ENOMEM;
- }
-
- local_id.addr_kind = PTL_ADDR_GID;
- local_id.gid = PTL_ID_ANY;
- local_id.rid = PTL_ID_ANY;
-
- //CERROR("sending req %d\n", request->rq_xid);
- rc = PtlMEPrepend(peer->peer_ni, request->rq_reply_portal, local_id,
- request->rq_xid, 0, PTL_UNLINK,
- &request->rq_reply_me_h);
- if (rc != PTL_OK) {
- CERROR("PtlMEAttach failed: %d\n", rc);
- BUG();
- EXIT;
- goto cleanup;
- }
-
- request->rq_type = PTL_RPC_REQUEST;
- request->rq_reply_md.start = repbuf;
- request->rq_reply_md.length = request->rq_replen;
- request->rq_reply_md.threshold = 1;
- request->rq_reply_md.options = PTL_MD_OP_PUT;
- request->rq_reply_md.user_ptr = request;
- request->rq_reply_md.eventq = rcvd_rep_eq;
-
- rc = PtlMDAttach(request->rq_reply_me_h, request->rq_reply_md,
- PTL_UNLINK, &request->rq_reply_md_h);
- if (rc != PTL_OK) {
- CERROR("PtlMDAttach failed: %d\n", rc);
- BUG();
- EXIT;
- goto cleanup2;
- }
-
- CDEBUG(D_NET, "Setup reply buffer: %u bytes, xid %u, portal %u\n",
- request->rq_replen, request->rq_xid, request->rq_reply_portal);
-
- return ptl_send_buf(request, peer, request->rq_req_portal);
-
- cleanup2:
- PtlMEUnlink(request->rq_reply_me_h);
- cleanup:
- OBD_FREE(repbuf, request->rq_replen);
-
- return rc;
-}
-
-/* ptl_received_rpc() should be called by the sleeping process once
- * it finishes processing an event. This ensures the ref count is
- * decremented and that the rpc ring buffer cycles properly.
- */
-int ptl_received_rpc(struct ptlrpc_service *service) {
- int rc, index;
-
- index = service->srv_md_active;
- CDEBUG(D_INFO, "MD index=%d Ref Count=%d\n", index,
- service->srv_ref_count[index]);
- service->srv_ref_count[index]--;
-
- if ((service->srv_ref_count[index] <= 0) &&
- (service->srv_me_h[index] == 0)) {
-
- /* Replace the unlinked ME and MD */
- rc = PtlMEInsert(service->srv_me_h[service->srv_me_tail],
- service->srv_id, 0, ~0, PTL_RETAIN,
- PTL_INS_AFTER, &(service->srv_me_h[index]));
- CERROR("Inserting new ME and MD in ring, rc %d\n", rc);
- service->srv_me_tail = index;
- service->srv_ref_count[index] = 0;
-
- if (rc != PTL_OK) {
- CERROR("PtlMEInsert failed: %d\n", rc);
- BUG();
- return rc;
- }
-
- service->srv_md[index].start = service->srv_buf[index];
- service->srv_md[index].length = service->srv_buf_size;
- service->srv_md[index].threshold = PTL_MD_THRESH_INF;
- service->srv_md[index].options = PTL_MD_OP_PUT;
- service->srv_md[index].user_ptr = service;
- service->srv_md[index].eventq = service->srv_eq_h;
-
- rc = PtlMDAttach(service->srv_me_h[index],
- service->srv_md[index],
- PTL_RETAIN, &(service->srv_md_h[index]));
-
- CDEBUG(D_INFO, "Attach MD in ring, rc %d\n", rc);
- if (rc != PTL_OK) {
- /* XXX cleanup */
- BUG();
- CERROR("PtlMDAttach failed: %d\n", rc);
- return rc;
- }
-
- service->srv_md_active =
- NEXT_INDEX(index, service->srv_ring_length);
- }
-
- return 0;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Portal-RPC reconnection and replay operations, for use in recovery.
- *
- * Copyright (c) 2003 Cluster File Systems, Inc.
- * Author: Phil Schwan <phil@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/version.h>
-
-#define DEBUG_SUBSYSTEM S_RPC
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include "ptlrpc_internal.h"
-
-static struct ptlrpc_thread *pinger_thread = NULL;
-static spinlock_t pinger_lock = SPIN_LOCK_UNLOCKED;
-static struct list_head pinger_imports = LIST_HEAD_INIT(pinger_imports);
-
-int ptlrpc_pinger_add_import(struct obd_import *imp)
-{
- ENTRY;
- if (!list_empty(&imp->imp_pinger_chain))
- RETURN(-EALREADY);
-
- spin_lock(&pinger_lock);
- list_add(&imp->imp_pinger_chain, &pinger_imports);
- spin_unlock(&pinger_lock);
- RETURN(0);
-}
-
-int ptlrpc_pinger_del_import(struct obd_import *imp)
-{
- ENTRY;
- if (list_empty(&imp->imp_pinger_chain))
- RETURN(-EALREADY);
-
- spin_lock(&pinger_lock);
- list_del_init(&imp->imp_pinger_chain);
- spin_unlock(&pinger_lock);
- RETURN(0);
-}
-
-static void ptlrpc_pinger_do_stuff(void)
-{
-
-
-
-}
-
-static int ptlrpc_pinger_main(void *arg)
-{
- struct ptlrpc_svc_data *data = (struct ptlrpc_svc_data *)arg;
- struct ptlrpc_thread *thread = data->thread;
- unsigned long flags;
- int rc = 0;
- ENTRY;
-
- lock_kernel();
- ptlrpc_daemonize();
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- sigfillset(¤t->blocked);
- recalc_sigpending();
-#else
- spin_lock_irqsave(¤t->sigmask_lock, flags);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irqrestore(¤t->sigmask_lock, flags);
-#endif
-
-#ifdef __arch_um__
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- sprintf(current->comm, "%s|%d", data->name, current->thread.extern_pid);
-#endif
-#else
- strcpy(current->comm, data->name);
-#endif
- unlock_kernel();
-
- /* Record that the thread is running */
- thread->t_flags = SVC_RUNNING;
- wake_up(&thread->t_ctl_waitq);
-
- /* And now, loop forever on requests */
- while (1) {
- struct l_wait_info lwi = LWI_TIMEOUT(5 * HZ, NULL, NULL);
- l_wait_event(thread->t_ctl_waitq,
- thread->t_flags & SVC_STOPPING, &lwi);
-
- if (thread->t_flags & SVC_STOPPING) {
- thread->t_flags &= ~SVC_STOPPING;
- EXIT;
- break;
- }
- ptlrpc_pinger_do_stuff();
- }
-
- thread->t_flags = SVC_STOPPED;
- wake_up(&thread->t_ctl_waitq);
-
- CDEBUG(D_NET, "pinger thread exiting, process %d: rc = %d\n",
- current->pid, rc);
- return rc;
-}
-
-int ptlrpc_pinger_start(void)
-{
- struct l_wait_info lwi = { 0 };
- struct ptlrpc_svc_data d;
- int rc;
- ENTRY;
-
- spin_lock(&pinger_lock);
- if (pinger_thread != NULL)
- GOTO(out, rc = -EALREADY);
-
- OBD_ALLOC(pinger_thread, sizeof(*pinger_thread));
- if (pinger_thread == NULL)
- GOTO(out, rc = -ENOMEM);
- init_waitqueue_head(&pinger_thread->t_ctl_waitq);
-
- d.name = "Lustre pinger";
- d.thread = pinger_thread;
-
- /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
- * just drop the VM and FILES in ptlrpc_daemonize() right away. */
- rc = kernel_thread(ptlrpc_pinger_main, &d, CLONE_VM | CLONE_FILES);
- if (rc < 0) {
- CERROR("cannot start thread: %d\n", rc);
- OBD_FREE(pinger_thread, sizeof(*pinger_thread));
- GOTO(out, rc);
- }
- l_wait_event(pinger_thread->t_ctl_waitq,
- pinger_thread->t_flags & SVC_RUNNING, &lwi);
-
- out:
- spin_unlock(&pinger_lock);
- RETURN(rc);
-}
-
-int ptlrpc_stop_pinger(void)
-{
- struct l_wait_info lwi = { 0 };
- int rc = 0;
- ENTRY;
-
- spin_lock(&pinger_lock);
- if (pinger_thread == NULL)
- GOTO(out, rc = -EALREADY);
-
- pinger_thread->t_flags = SVC_STOPPING;
- wake_up(&pinger_thread->t_ctl_waitq);
- l_wait_event(pinger_thread->t_ctl_waitq,
- (pinger_thread->t_flags & SVC_STOPPED), &lwi);
-
- OBD_FREE(pinger_thread, sizeof(*pinger_thread));
-
- out:
- spin_unlock(&pinger_lock);
- RETURN(rc);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2003 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/* Intramodule declarations for ptlrpc. */
-
-#ifndef PTLRPC_INTERNAL_H
-#define PTLRPC_INTERNAL_H
-
-struct ldlm_namespace;
-struct obd_import;
-struct ldlm_res_id;
-
-/* ldlm hooks that we need, managed via inter_module_{get,put} */
-extern int (*ptlrpc_ldlm_namespace_cleanup)(struct ldlm_namespace *, int);
-extern int (*ptlrpc_ldlm_cli_cancel_unused)(struct ldlm_namespace *,
- struct ldlm_res_id *, int);
-extern int (*ptlrpc_ldlm_replay_locks)(struct obd_import *);
-
-int ptlrpc_get_ldlm_hooks(void);
-void ptlrpc_daemonize(void);
-
-int ptlrpc_import_handle_eviction(struct obd_import *);
-
-#endif /* PTLRPC_INTERNAL_H */
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_RPC
-
-#ifdef __KERNEL__
-# include <linux/module.h>
-# include <linux/init.h>
-#else
-# include <liblustre.h>
-#endif
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-
-#include "ptlrpc_internal.h"
-
-extern int ptlrpc_init_portals(void);
-extern void ptlrpc_exit_portals(void);
-
-int (*ptlrpc_ldlm_namespace_cleanup)(struct ldlm_namespace *, int);
-int (*ptlrpc_ldlm_replay_locks)(struct obd_import *);
-
-#define GET_HOOK(name) \
-if (!ptlrpc_##name) { \
- if (!(ptlrpc_##name = inter_module_get(#name))) { \
- CERROR("can't i_m_g(\"" #name "\")\n"); \
- return 0; \
- } \
-}
-
-/* This is called from ptlrpc_get_connection, which runs after all the modules
- * are loaded, but before anything else interesting happens.
- */
-int ptlrpc_get_ldlm_hooks(void)
-{
- static int ensured = 0;
-
- if (ensured)
- return 1;
-
- GET_HOOK(ldlm_namespace_cleanup);
- GET_HOOK(ldlm_replay_locks);
-
- ensured = 1;
- RETURN(1);
-}
-
-#undef GET_HOOK
-
-#define PUT_HOOK(hook) \
-if (ptlrpc_##hook) { \
- inter_module_put(#hook); \
- ptlrpc_##hook = NULL; \
-}
-
-void ptlrpc_put_ldlm_hooks(void)
-{
- ENTRY;
- PUT_HOOK(ldlm_namespace_cleanup);
- PUT_HOOK(ldlm_replay_locks);
- EXIT;
-}
-
-#undef PUT_HOOK
-
-__init int ptlrpc_init(void)
-{
- int rc;
- ENTRY;
-
- rc = ptlrpc_init_portals();
- if (rc)
- RETURN(rc);
-
- ptlrpc_init_connection();
-
- ptlrpc_put_connection_superhack = ptlrpc_put_connection;
- ptlrpc_abort_inflight_superhack = ptlrpc_abort_inflight;
- RETURN(0);
-}
-
-static void __exit ptlrpc_exit(void)
-{
- ptlrpc_exit_portals();
- ptlrpc_cleanup_connection();
-}
-
-/* connection.c */
-EXPORT_SYMBOL(ptlrpc_readdress_connection);
-EXPORT_SYMBOL(ptlrpc_get_connection);
-EXPORT_SYMBOL(ptlrpc_put_connection);
-EXPORT_SYMBOL(ptlrpc_connection_addref);
-EXPORT_SYMBOL(ptlrpc_init_connection);
-EXPORT_SYMBOL(ptlrpc_cleanup_connection);
-
-/* niobuf.c */
-EXPORT_SYMBOL(ptlrpc_bulk_put);
-EXPORT_SYMBOL(ptlrpc_bulk_get);
-EXPORT_SYMBOL(ptlrpc_register_bulk_put);
-EXPORT_SYMBOL(ptlrpc_register_bulk_get);
-EXPORT_SYMBOL(ptlrpc_abort_bulk);
-EXPORT_SYMBOL(ptlrpc_reply);
-EXPORT_SYMBOL(ptlrpc_error);
-EXPORT_SYMBOL(ptlrpc_resend_req);
-EXPORT_SYMBOL(ptl_send_rpc);
-EXPORT_SYMBOL(ptlrpc_link_svc_me);
-EXPORT_SYMBOL(obd_brw_set_new);
-EXPORT_SYMBOL(obd_brw_set_add);
-EXPORT_SYMBOL(obd_brw_set_del);
-EXPORT_SYMBOL(obd_brw_set_decref);
-EXPORT_SYMBOL(obd_brw_set_addref);
-
-/* client.c */
-EXPORT_SYMBOL(ptlrpc_init_client);
-EXPORT_SYMBOL(ptlrpc_cleanup_client);
-EXPORT_SYMBOL(ptlrpc_req_to_uuid);
-EXPORT_SYMBOL(ptlrpc_uuid_to_connection);
-EXPORT_SYMBOL(ptlrpc_queue_wait);
-EXPORT_SYMBOL(ptlrpc_continue_req);
-EXPORT_SYMBOL(ptlrpc_replay_req);
-EXPORT_SYMBOL(ptlrpc_restart_req);
-EXPORT_SYMBOL(ptlrpc_prep_req);
-EXPORT_SYMBOL(ptlrpc_free_req);
-EXPORT_SYMBOL(ptlrpc_abort);
-EXPORT_SYMBOL(ptlrpc_req_finished);
-EXPORT_SYMBOL(ptlrpc_request_addref);
-EXPORT_SYMBOL(ptlrpc_prep_bulk_imp);
-EXPORT_SYMBOL(ptlrpc_prep_bulk_exp);
-EXPORT_SYMBOL(ptlrpc_free_bulk);
-EXPORT_SYMBOL(ptlrpc_prep_bulk_page);
-EXPORT_SYMBOL(ptlrpc_free_bulk_page);
-EXPORT_SYMBOL(ll_brw_sync_wait);
-EXPORT_SYMBOL(ptlrpc_abort_inflight);
-EXPORT_SYMBOL(ptlrpc_retain_replayable_request);
-EXPORT_SYMBOL(ptlrpc_next_xid);
-
-EXPORT_SYMBOL(ptlrpc_prep_set);
-EXPORT_SYMBOL(ptlrpc_drop_set);
-EXPORT_SYMBOL(ptlrpc_set_add_req);
-EXPORT_SYMBOL(ptlrpc_req_completed);
-EXPORT_SYMBOL(ptlrpc_req_result);
-
-/* service.c */
-EXPORT_SYMBOL(ptlrpc_init_svc);
-EXPORT_SYMBOL(ptlrpc_stop_all_threads);
-EXPORT_SYMBOL(ptlrpc_start_thread);
-EXPORT_SYMBOL(ptlrpc_unregister_service);
-
-/* pack_generic.c */
-EXPORT_SYMBOL(lustre_pack_msg);
-EXPORT_SYMBOL(lustre_msg_size);
-EXPORT_SYMBOL(lustre_unpack_msg);
-EXPORT_SYMBOL(lustre_msg_buf);
-EXPORT_SYMBOL(lustre_msg_string);
-EXPORT_SYMBOL(lustre_swab_reqbuf);
-EXPORT_SYMBOL(lustre_swab_repbuf);
-EXPORT_SYMBOL(lustre_swab_obdo);
-EXPORT_SYMBOL(lustre_swab_obd_statfs);
-EXPORT_SYMBOL(lustre_swab_obd_ioobj);
-EXPORT_SYMBOL(lustre_swab_niobuf_remote);
-EXPORT_SYMBOL(lustre_swab_ost_body);
-EXPORT_SYMBOL(lustre_swab_ll_fid);
-EXPORT_SYMBOL(lustre_swab_mds_status_req);
-EXPORT_SYMBOL(lustre_swab_mds_fileh_body);
-EXPORT_SYMBOL(lustre_swab_mds_body);
-EXPORT_SYMBOL(lustre_swab_mds_rec_setattr);
-EXPORT_SYMBOL(lustre_swab_mds_rec_create);
-EXPORT_SYMBOL(lustre_swab_mds_rec_link);
-EXPORT_SYMBOL(lustre_swab_mds_rec_unlink);
-EXPORT_SYMBOL(lustre_swab_mdx_rec_rename);
-EXPORT_SYMBOL(lustre_swab_lov_desc);
-EXPORT_SYMBOL(lustre_swab_ldlm_res_id);
-EXPORT_SYMBOL(lustre_swab_ldlm_extent);
-EXPORT_SYMBOL(lustre_swab_ldlm_intent);
-EXPORT_SYMBOL(lustre_swab_ldlm_resource_desc);
-EXPORT_SYMBOL(lustre_swab_ldlm_lock_desc);
-EXPORT_SYMBOL(lustre_swab_ldlm_request);
-EXPORT_SYMBOL(lustre_swab_ldlm_reply);
-EXPORT_SYMBOL(lustre_swab_ptlbd_op);
-EXPORT_SYMBOL(lustre_swab_ptlbd_niob);
-EXPORT_SYMBOL(lustre_swab_ptlbd_rsp);
-
-/* ptlrpc_module.c */
-EXPORT_SYMBOL(ptlrpc_put_ldlm_hooks);
-
-/* recover.c */
-EXPORT_SYMBOL(ptlrpc_run_recovery_upcall);
-EXPORT_SYMBOL(ptlrpc_reconnect_import);
-EXPORT_SYMBOL(ptlrpc_replay);
-EXPORT_SYMBOL(ptlrpc_resend);
-EXPORT_SYMBOL(ptlrpc_wake_delayed);
-EXPORT_SYMBOL(ptlrpc_set_import_active);
-EXPORT_SYMBOL(ptlrpc_fail_import);
-EXPORT_SYMBOL(ptlrpc_fail_export);
-EXPORT_SYMBOL(ptlrpc_recover_import);
-
-#ifdef __KERNEL__
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Request Processor");
-MODULE_LICENSE("GPL");
-
-module_init(ptlrpc_init);
-module_exit(ptlrpc_exit);
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define EXPORT_SYMTAB
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-
-extern int server_request_callback(ptl_event_t *ev, void *data);
-
-static int ptlrpc_check_event(struct ptlrpc_service *svc)
-{
-
- if (sigismember(&(current->pending.signal), SIGKILL) ||
- sigismember(&(current->pending.signal), SIGINT)) {
- svc->srv_flags |= SVC_KILLED;
- EXIT;
- return 1;
- }
-
- if ( svc->srv_flags & SVC_STOPPING ) {
- EXIT;
- return 1;
- }
-
- if ( svc->srv_eq_h ) {
- int rc;
- rc = PtlEQGet(svc->srv_eq_h, &svc->srv_ev);
-
- if (rc == PTL_OK) {
- svc->srv_flags |= SVC_EVENT;
- EXIT;
- return 1;
- }
-
- if (rc == PTL_EQ_DROPPED) {
- CERROR("dropped event!\n");
- BUG();
- }
- CERROR("PtlEQGet returns %d\n", rc);
- EXIT;
- return 0;
- }
-
- if (!list_empty(&svc->srv_reqs)) {
- svc->srv_flags |= SVC_LIST;
- EXIT;
- return 1;
- }
-
- EXIT;
- return 0;
-}
-
-struct ptlrpc_service *
-ptlrpc_init_svc(__u32 bufsize, int req_portal, int rep_portal, char *uuid,
- req_unpack_t unpack, rep_pack_t pack, svc_handler_t handler)
-{
- int err;
- struct ptlrpc_service *svc;
-
- OBD_ALLOC(svc, sizeof(*svc));
- if ( !svc ) {
- CERROR("no memory\n");
- return NULL;
- }
-
- memset(svc, 0, sizeof(*svc));
-
- spin_lock_init(&svc->srv_lock);
- INIT_LIST_HEAD(&svc->srv_reqs);
- init_waitqueue_head(&svc->srv_ctl_waitq);
- init_waitqueue_head(&svc->srv_waitq);
-
- svc->srv_thread = NULL;
- svc->srv_flags = 0;
-
- svc->srv_buf_size = bufsize;
- svc->srv_rep_portal = rep_portal;
- svc->srv_req_portal = req_portal;
- svc->srv_req_unpack = unpack;
- svc->srv_rep_pack = pack;
- svc->srv_handler = handler;
- err = kportal_uuid_to_peer(uuid, &svc->srv_self);
- if (err) {
- CERROR("cannot get peer for uuid %s", uuid);
- OBD_FREE(svc, sizeof(*svc));
- return NULL;
- }
- return svc;
-}
-
-static int ptlrpc_main(void *arg)
-{
- int rc;
- struct ptlrpc_svc_data *data = (struct ptlrpc_svc_data *)arg;
- struct obd_device *obddev = data->dev;
- struct ptlrpc_service *svc = data->svc;
-
- ENTRY;
-
- lock_kernel();
- daemonize();
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-
- sprintf(current->comm, data->name);
-
- /* Record that the thread is running */
- svc->srv_thread = current;
- svc->srv_flags = SVC_RUNNING;
- wake_up(&svc->srv_ctl_waitq);
-
- /* XXX maintain a list of all managed devices: insert here */
-
- /* And now, loop forever on requests */
- while (1) {
-
- wait_event(svc->srv_waitq, ptlrpc_check_event(svc));
-
- if (svc->srv_flags & SVC_SIGNAL) {
- EXIT;
- break;
- }
-
- if (svc->srv_flags & SVC_STOPPING) {
- EXIT;
- break;
- }
-
- if (svc->srv_flags & SVC_EVENT) {
- struct ptlrpc_request request;
- svc->srv_flags = SVC_RUNNING;
-
- /* FIXME: If we move to an event-driven model,
- * we should put the request on the stack of
- * mds_handle instead. */
- memset(&request, 0, sizeof(request));
- request.rq_obd = obddev;
- request.rq_reqbuf = svc->srv_ev.mem_desc.start + svc->srv_ev.offset;
- request.rq_reqlen = svc->srv_ev.mem_desc.length;
- request.rq_xid = svc->srv_ev.match_bits;
- CERROR("got req %d\n", request.rq_xid);
-
- request.rq_peer.peer_nid = svc->srv_ev.initiator.nid;
- /* FIXME: this NI should be the incoming NI.
- * We don't know how to find that from here. */
- request.rq_peer.peer_ni = svc->srv_self.peer_ni;
- rc = svc->srv_handler(obddev, svc, &request);
- ptl_received_rpc(svc);
- continue;
- }
-
- if (svc->srv_flags & SVC_LIST) {
- struct ptlrpc_request *request;
- svc->srv_flags = SVC_RUNNING;
-
- spin_lock(&svc->srv_lock);
- request = list_entry(svc->srv_reqs.next,
- struct ptlrpc_request,
- rq_list);
- list_del(&request->rq_list);
- spin_unlock(&svc->srv_lock);
- rc = svc->srv_handler(obddev, svc, request);
- continue;
- }
- CERROR("unknown break in service");
- break;
- }
-
- svc->srv_thread = NULL;
- svc->srv_flags = SVC_STOPPED;
- wake_up(&svc->srv_ctl_waitq);
- CERROR("svc exiting process %d\n", current->pid);
- return 0;
-}
-
-void ptlrpc_stop_thread(struct ptlrpc_service *svc)
-{
- svc->srv_flags = SVC_STOPPING;
-
- wake_up(&svc->srv_waitq);
- wait_event_interruptible(svc->srv_ctl_waitq,
- (svc->srv_flags & SVC_STOPPED));
-}
-
-int ptlrpc_start_thread(struct obd_device *dev, struct ptlrpc_service *svc,
- char *name)
-{
- struct ptlrpc_svc_data d;
- int rc;
- ENTRY;
-
- d.dev = dev;
- d.svc = svc;
- d.name = name;
-
- init_waitqueue_head(&svc->srv_waitq);
-
- init_waitqueue_head(&svc->srv_ctl_waitq);
- rc = kernel_thread(ptlrpc_main, (void *) &d,
- CLONE_VM | CLONE_FS | CLONE_FILES);
- if (rc < 0) {
- CERROR("cannot start thread\n");
- return -EINVAL;
- }
- wait_event(svc->srv_ctl_waitq, svc->srv_flags & SVC_RUNNING);
-
- EXIT;
- return 0;
-}
-
-
-int rpc_register_service(struct ptlrpc_service *service, char *uuid)
-{
- struct lustre_peer peer;
- int rc, i;
-
- rc = kportal_uuid_to_peer(uuid, &peer);
- if (rc != 0) {
- CERROR("Invalid uuid \"%s\"\n", uuid);
- return -EINVAL;
- }
-
- service->srv_ring_length = RPC_RING_LENGTH;
- service->srv_me_active = 0;
- service->srv_md_active = 0;
-
- service->srv_id.addr_kind = PTL_ADDR_GID;
- service->srv_id.gid = PTL_ID_ANY;
- service->srv_id.rid = PTL_ID_ANY;
-
- rc = PtlEQAlloc(peer.peer_ni, 128, server_request_callback,
- service, &(service->srv_eq_h));
-
- if (rc != PTL_OK) {
- CERROR("PtlEQAlloc failed: %d\n", rc);
- return rc;
- }
-
- /* Attach the leading ME on which we build the ring */
- rc = PtlMEAttach(peer.peer_ni, service->srv_req_portal,
- service->srv_id, 0, ~0, PTL_RETAIN,
- &(service->srv_me_h[0]));
-
- if (rc != PTL_OK) {
- CERROR("PtlMEAttach failed: %d\n", rc);
- return rc;
- }
-
- for (i = 0; i < service->srv_ring_length; i++) {
- OBD_ALLOC(service->srv_buf[i], service->srv_buf_size);
-
- if (service->srv_buf[i] == NULL) {
- CERROR("no memory\n");
- return -ENOMEM;
- }
-
- /* Insert additional ME's to the ring */
- if (i > 0) {
- rc = PtlMEInsert(service->srv_me_h[i-1],
- service->srv_id, 0, ~0, PTL_RETAIN,
- PTL_INS_AFTER,&(service->srv_me_h[i]));
- service->srv_me_tail = i;
-
- if (rc != PTL_OK) {
- CERROR("PtlMEInsert failed: %d\n", rc);
- return rc;
- }
- }
-
- service->srv_ref_count[i] = 0;
- service->srv_md[i].start = service->srv_buf[i];
- service->srv_md[i].length = service->srv_buf_size;
- service->srv_md[i].threshold = PTL_MD_THRESH_INF;
- service->srv_md[i].options = PTL_MD_OP_PUT;
- service->srv_md[i].user_ptr = service;
- service->srv_md[i].eventq = service->srv_eq_h;
-
- rc = PtlMDAttach(service->srv_me_h[i], service->srv_md[i],
- PTL_RETAIN, &(service->srv_md_h[i]));
-
- if (rc != PTL_OK) {
- /* cleanup */
- CERROR("PtlMDAttach failed: %d\n", rc);
- return rc;
- }
- }
-
- return 0;
-}
-
-int rpc_unregister_service(struct ptlrpc_service *service)
-{
- int rc, i;
-
- for (i = 0; i < service->srv_ring_length; i++) {
- rc = PtlMDUnlink(service->srv_md_h[i]);
- if (rc)
- CERROR("PtlMDUnlink failed: %d\n", rc);
-
- rc = PtlMEUnlink(service->srv_me_h[i]);
- if (rc)
- CERROR("PtlMEUnlink failed: %d\n", rc);
-
- if (service->srv_buf[i] != NULL)
- OBD_FREE(service->srv_buf[i], service->srv_buf_size);
- service->srv_buf[i] = NULL;
- }
-
- rc = PtlEQFree(service->srv_eq_h);
- if (rc)
- CERROR("PtlEQFree failed: %d\n", rc);
-
- return 0;
-}
-
+++ /dev/null
-#!/bin/sh
-#
-# llite-group.sh : Cluster Manager service script for Lustre
-#
-# This must be named llite-<group>.sh, where group is the device
-# group that is being managed by the cluster manager service.
-#
-
-set -e
-set -vx
-
-[ -f ${LUSTRE_CFG:=/etc/lustre/lustre.cfg} ] && . ${LUSTRE_CFG}
-
-LDAPURL=${LDAPURL:-ldap://localhost}
-CONFIG=${CONFIG:-test23}
-
-LACTIVE=${LACTIVE:-/usr/sbin/lactive}
-LCONF=${LCONF:-/usr/sbin/lconf}
-
-group=`basename $0 .sh| cut -d- -f2`
-confopt="--ldapurl $LDAPURL --config $CONFIG"
-
-[ -z "$group" ] && exit 0
-
-node=`hostname -s`
-
-[ -d ${STATUS_DIR:=/var/lustre} ] || mkdir -p $STATUS_DIR
-
-start() {
- echo -n "Starting $SERVICE: "
- python2 $LACTIVE $confopt --group $group --active $node
- python2 $LCONF -v $confopt
- RETVAL=$?
- echo done
-}
-
-stop() {
- echo -n "Shutting down $SERVICE: "
- python2 $LCONF -dv $confopt
- RETVAL=$?
- echo done
-}
-
-status() {
- RETVAL=0
-}
-
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- restart
- ;;
- status)
- status $SERVICE
- ;;
- *)
- echo "Usage: $0 {start|stop|status}"
- exit 1
-esac
-
-exit $RETVAL
+++ /dev/null
-#! /bin/sh
-# nodelustre - Start and stop Lustre on MCR nodes
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Gord Eagle <gord@clusterfs.com>, 2002-09-10
-
-# Set this to the shared config file.
-MASTER_CONFIG=http://emcri/lustre.xml
-CONFIG=/etc/lustre/lustre.xml
-COMPUTE_NODE=client
-
-LCONF=/usr/local/cfs/lustre/utils/lconf
-WGET=wget
-
-case "$1" in
-start | stop)
- # Fetch the config file. We can't use --output-document because it
- # makes Wget ignore timestamping.
- if test -n "$MASTER_CONFIG"; then
- (cd `echo "$CONFIG" | sed 's%/[^/]*$%%'` && \
- $WGET --timestamping "$MASTER_CONFIG") || exit $?
- fi
-
- # Map all client nodes to the COMPUTE_NODE virtual node.
- if test -n "$COMPUTE_NODE" && nodeattr compute; then
- node=" --node $COMPUTE_NODE"
- else
- node=
- fi
-
- # If we're stopping, do the lconf cleanup.
- if test "$1" = stop; then
- cleanup=' --cleanup'
- else
- cleanup=
- fi
-
- $LCONF$cleanup$node "$CONFIG"
- ;;
-
-*)
- echo "$0 {start|stop}" 1>&2
- exit 1
- ;;
-esac
-
-exit 0
+++ /dev/null
-#!/usr/bin/perl
-# -*- Mode: perl; indent-tabs-mode: nil; cperl-indent-level: 4 -*-
-
-use strict;
-use diagnostics;
-use IO::File;
-use Time::Local;
-
-my $pristine = 1;
-my $kernver;
-
-sub get_tag()
-{
- my $tag;
-
- my $tagfile = new IO::File;
- if (!$tagfile->open("CVS/Tag")) {
- return "HEAD";
- } else {
- my $tmp = <$tagfile>;
- $tagfile->close();
-
- $tmp =~ m/T(.*)/;
- return $1;
- }
-}
-
-sub get_latest_mtime()
-{
- my %months=("Jan" => 0, "Feb" => 1, "Mar" => 2, "Apr" => 3, "May" => 4,
- "Jun" => 5, "Jul" => 6, "Aug" => 7, "Sep" => 8, "Oct" => 9,
- "Nov" => 10, "Dec" => 11);
-
- my $last_mtime = 0;
- my @entries = `find . -name Entries`;
- my $entry_file;
- foreach $entry_file (@entries) {
- chomp($entry_file);
- my $entry = new IO::File;
- if (!$entry->open($entry_file)) {
- die "unable to open $entry_file: $!\n";
- }
- my $line;
- while (defined($line = <$entry>)) {
- chomp($line);
- #print "line: $line\n";
- my ($junk, $file, $version, $date) = split(/\//, $line);
-
- #print "junk: $junk\nfile: $file\nver: $version\ndate: $date\n";
- #print "last_mtime: " . localtime($last_mtime) . "\n";
-
- if ($junk eq "D" ||
- $file eq "lustre.spec.in" ||
- $file !~ m/\.(c|h|am|in)$/) {
- next;
- }
-
- my $cur_dir = $entry_file;
- $cur_dir =~ s/\/CVS\/Entries$//;
- my @statbuf = stat("$cur_dir/$file");
- my $mtime = $statbuf[9];
- my $local_date = gmtime($mtime);
- if ($local_date ne $date &&
- $file ne "lustre.spec.in") {
- #print "$file : " . localtime($mtime) . "\n";
- $pristine = 0;
- }
-
- if ($mtime > $last_mtime) {
- $last_mtime = $mtime;
- }
-
- if ($date) {
- my @t = split(/ +/, $date);
- if (int(@t) != 5) {
- #print "skipping: $date\n";
- next;
- }
- my ($hours, $min, $sec) = split(/:/, $t[3]);
- my ($mon, $mday, $year) = ($t[1], $t[2], $t[4]);
- my $secs = 0;
- $mon = $months{$mon};
- $secs = timelocal($sec, $min, $hours, $mday, $mon, $year);
- if ($secs > $last_mtime) {
- $last_mtime = $secs;
- }
- }
- }
- $entry->close();
- }
- return $last_mtime;
-}
-
-sub get_linuxdir()
-{
- my $config = new IO::File;
- my ($line, $dir);
- if (!$config->open("Makefile")) {
- die "Run ./configure first\n";
- }
- while (defined($line = <$config>)) {
- chomp($line);
- if ($line =~ /LINUX = (.*)/) {
- $dir = $1;
- last;
- }
- }
- $config->close();
- my $ver = new IO::File;
- if (!$ver->open("$dir/include/linux/version.h")) {
- die "Run make dep on $dir\n";
- }
- while(defined($line = <$ver>)) {
- $line =~ /\#define UTS_RELEASE "(.*)"/;
- if ($1) {
- $kernver = $1;
- last;
- }
- }
- $ver->close();
- chomp($kernver);
- $dir =~ s/\//\./g;
- return $dir;
-}
-
-sub generate_ver($$$)
-{
- my $tag = shift;
- my $mtime = shift;
- my $linuxdir = shift;
-
- #print "localtime: " . localtime($mtime) . "\n";
-
- my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
- localtime($mtime);
- $year += 1900;
- $mon++;
- my $show_last = sprintf("%04d%02d%02d%02d%02d%02d", $year, $mon, $mday,
- $hour, $min, $sec);
-
- print "#define BUILD_VERSION \"";
- if ($pristine) {
- print "$tag-$show_last-PRISTINE-$linuxdir-$kernver\"\n";
- } else {
- print "$tag-$show_last-CHANGED-$linuxdir-$kernver\"\n";
- }
-}
-
-if ($ARGV[0]) {
- chdir($ARGV[0]);
-}
-my $linuxdir = get_linuxdir();
-my $tag = get_tag();
-my $mtime = get_latest_mtime();
-generate_ver($tag, $mtime, $linuxdir);
-
-exit(0);
+++ /dev/null
-#!/bin/sh
-set -e
-
-#
-# Runs create.pl and rename.pl on two mountpoints with increasing load, varying
-# debug levels. Assumes that the node is already setup with llmount2.sh
-#
-
-SRCDIR="`dirname $0`"
-CREATE=$SRCDIR/create.pl
-
-debug_client_on()
-{
- echo -1 > /proc/sys/portals/debug
-}
-
-debug_client_off()
-{
- echo 0 > /proc/sys/portals/debug
-}
-
-MNT=${MNT:-/mnt/lustre}
-
-debug_client_on
-echo "create.pl, 2 mounts, 1 thread, 10 ops, debug on"
-perl $CREATE -- $MNT 2 10
-echo "create.pl, 2 mounts, 1 thread, 100 ops, debug on"
-perl $CREATE --silent -- $MNT 2 100
-echo "create.pl --mcreate=0, 2 mounts, 1 thread, 10 ops, debug on"
-perl $CREATE --mcreate=0 -- $MNT 2 10
-echo "create.pl --mcreate=0, 2 mounts, 1 thread, 100 ops, debug on"
-perl $CREATE --mcreate=0 --silent -- $MNT 2 100
-echo "rename.pl, 2 mounts, 1 thread, 10 ops, debug on"
-perl rename.pl --count=2 $MNT 10
-echo "rename.pl, 2 mounts, 1 thread, 100 ops, debug on"
-perl rename.pl --count=2 --silent $MNT 100
-
-debug_client_off
-echo "create.pl, 2 mounts, 1 thread, 1000 ops, debug off"
-perl $CREATE --silent -- $MNT 2 1000
-echo "create.pl --mcreate=0, 2 mounts, 1 thread, 1000 ops, debug off"
-perl $CREATE --silent --mcreate=0 -- $MNT 2 1000
-echo "rename.pl, 2 mounts, 1 thread, 1000 ops, debug off"
-perl rename.pl --count=2 --silent $MNT 1000
-
-debug_client_on
-echo "create.pl, 2 mounts, 2 threads, 100 ops, debug on"
-perl $CREATE --silent -- $MNT 2 100 &
-perl $CREATE --silent -- $MNT 2 100 &
-wait
-echo "create.pl --mcreate=0, 2 mounts, 2 threads, 100 ops, debug on"
-perl $CREATE --silent --mcreate=0 -- $MNT 2 100 &
-perl $CREATE --silent --mcreate=0 -- $MNT 2 100 &
-wait
-echo "rename.pl, 2 mounts, 2 thread, 1000 ops, debug on"
-perl rename.pl --count=2 --silent $MNT 1000 &
-perl rename.pl --count=2 --silent $MNT 1000 &
-wait
-
-debug_client_off
-echo "create.pl, 2 mounts, 2 threads, 2000 ops, debug off"
-perl $CREATE --silent -- $MNT 2 2000 &
-perl $CREATE --silent -- $MNT 2 2000 &
-wait
-echo "create.pl --mcreate=0, 2 mounts, 2 threads, 2000 ops, debug off"
-perl $CREATE --silent --mcreate=0 -- $MNT 2 2000 &
-perl $CREATE --silent --mcreate=0 -- $MNT 2 2000 &
-wait
-echo "rename.pl, 2 mounts, 2 threads, 2000 ops, debug off"
-perl rename.pl --count=2 --silent $MNT 2000 &
-perl rename.pl --count=2 --silent $MNT 2000 &
-wait
-
-debug_client_on
-echo "create.pl, 2 mounts, 4 threads, 100 ops, debug on"
-for i in `seq 1 4`; do
- perl $CREATE --silent -- $MNT 2 100 &
-done
-wait
-echo "create.pl --mcreate=0, 2 mounts, 4 threads, 100 ops, debug on"
-for i in `seq 1 4`; do
- perl $CREATE --silent --mcreate=0 -- $MNT 2 100 &
-done
-wait
-echo "rename.pl, 2 mounts, 4 threads, 2000 ops, debug on"
-for i in `seq 1 4`; do
- perl rename.pl --count=2 --silent $MNT 2000 &
-done
-wait
-
-debug_client_off
-echo "create.pl, 2 mounts, 4 threads, 2000 ops, debug off"
-for i in `seq 1 4`; do
- perl $CREATE --silent -- $MNT 2 2000 &
-done
-wait
-echo "create.pl --mcreate=0, 2 mounts, 4 threads, 2000 ops, debug off"
-for i in `seq 1 4`; do
- perl $CREATE --silent --mcreate=0 -- $MNT 2 2000 &
-done
-wait
-echo "rename.pl, 2 mounts, 4 threads, 2000 ops, debug off"
-for i in `seq 1 4`; do
- perl rename.pl --count=2 --silent $MNT 2000 &
-done
-wait
-
-debug_client_on
-echo "create.pl, 2 mounts, 8 threads, 500 ops, debug on"
-for i in `seq 1 8`; do
- perl $CREATE --silent -- $MNT 2 500 &
-done
-wait
-echo "create.pl --mcreate=0, 2 mounts, 8 threads, 500 ops, debug on"
-for i in `seq 1 8`; do
- perl $CREATE --silent --mcreate=0 -- $MNT 2 500 &
-done
-wait
-echo "rename.pl, 2 mounts, 8 threads, 2000 ops, debug on"
-for i in `seq 1 8`; do
- perl rename.pl --count=2 --silent $MNT 2000 &
-done
-wait
-
-debug_client_off
-echo "create.pl, 2 mounts, 8 threads, 2000 ops, debug off"
-for i in `seq 1 8`; do
- perl $CREATE --silent -- $MNT 2 2000 &
-done
-wait
-echo "create.pl --mcreate=0, 2 mounts, 8 threads, 2000 ops, debug off"
-for i in `seq 1 8`; do
- perl $CREATE --silent --mcreate=0 -- $MNT 2 2000 &
-done
-wait
-echo "rename.pl, 2 mounts, 8 threads, 2000 ops, debug off"
-for i in `seq 1 8`; do
- perl rename.pl --count=2 --silent $MNT 2000 &
-done
-wait
+++ /dev/null
-#!/bin/sh
-set -e
-
-#
-# Runs create.pl and rename.pl on a single mountpoint with increasing
-# load, varying debug levels
-#
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-MNT=${MNT:-/mnt/lustre}
-
-debug_client_on
-echo "create.pl, 1 mount, 1 thread, 10 ops, debug on"
-perl create.pl -- $MNT -1 10
-echo "create.pl, 1 mount, 1 thread, 100 ops, debug on"
-perl create.pl --silent -- $MNT -1 100
-echo "create.pl --mcreate=0, 1 mount, 1 thread, 10 ops, debug on"
-perl create.pl --mcreate=0 -- $MNT -1 10
-echo "create.pl --mcreate=0, 1 mount, 1 thread, 100 ops, debug on"
-perl create.pl --mcreate=0 --silent -- $MNT -1 100
-echo "rename.pl, 1 mount, 1 thread, 10 ops, debug on"
-perl rename.pl $MNT 10
-echo "rename.pl, 1 mount, 1 thread, 100 ops, debug on"
-perl rename.pl --silent $MNT 100
-
-debug_client_off
-echo "create.pl, 1 mount, 1 thread, 1000 ops, debug off"
-perl create.pl --silent -- $MNT -1 1000
-echo "create.pl --mcreate=0, 1 mount, 1 thread, 1000 ops, debug off"
-perl create.pl --silent --mcreate=0 -- $MNT -1 1000
-echo "rename.pl, 1 mount, 1 thread, 1000 ops, debug off"
-perl rename.pl --silent $MNT 1000
-
-debug_client_on
-echo "create.pl, 1 mount, 2 threads, 100 ops, debug on"
-perl create.pl --silent -- $MNT -1 100 &
-perl create.pl --silent -- $MNT -1 100 &
-wait
-echo "create.pl --mcreate=0, 1 mount, 2 threads, 100 ops, debug on"
-perl create.pl --silent --mcreate=0 -- $MNT -1 100 &
-perl create.pl --silent --mcreate=0 -- $MNT -1 100 &
-wait
-echo "rename.pl, 1 mount, 2 thread, 1000 ops, debug on"
-perl rename.pl --silent $MNT 1000 &
-perl rename.pl --silent $MNT 1000 &
-wait
-
-debug_client_off
-echo "create.pl, 1 mount, 2 threads, 2000 ops, debug off"
-perl create.pl --silent -- $MNT -1 2000 &
-perl create.pl --silent -- $MNT -1 2000 &
-wait
-echo "create.pl --mcreate=0, 1 mount, 2 threads, 2000 ops, debug off"
-perl create.pl --silent --mcreate=0 -- $MNT -1 2000 &
-perl create.pl --silent --mcreate=0 -- $MNT -1 2000 &
-wait
-echo "rename.pl, 1 mount, 2 threads, 2000 ops, debug off"
-perl rename.pl --silent $MNT 2000 &
-perl rename.pl --silent $MNT 2000 &
-wait
-
-debug_client_on
-echo "create.pl, 1 mount, 4 threads, 100 ops, debug on"
-for i in `seq 1 4`; do
- perl create.pl --silent -- $MNT -1 100 &
-done
-wait
-echo "create.pl --mcreate=0, 1 mount, 4 threads, 100 ops, debug on"
-for i in `seq 1 4`; do
- perl create.pl --silent --mcreate=0 -- $MNT -1 100 &
-done
-wait
-echo "rename.pl, 1 mount, 4 threads, 2000 ops, debug on"
-for i in `seq 1 4`; do
- perl rename.pl --silent $MNT 2000 &
-done
-wait
-
-debug_client_off
-echo "create.pl, 1 mount, 4 threads, 2000 ops, debug off"
-for i in `seq 1 4`; do
- perl create.pl --silent -- $MNT -1 2000 &
-done
-wait
-echo "create.pl --mcreate=0, 1 mount, 4 threads, 2000 ops, debug off"
-for i in `seq 1 4`; do
- perl create.pl --silent --mcreate=0 -- $MNT -1 2000 &
-done
-wait
-echo "rename.pl, 1 mount, 4 threads, 2000 ops, debug off"
-for i in `seq 1 4`; do
- perl rename.pl --silent $MNT 2000 &
-done
-wait
-
-debug_client_on
-echo "create.pl, 1 mount, 8 threads, 500 ops, debug on"
-for i in `seq 1 8`; do
- perl create.pl --silent -- $MNT -1 500 &
-done
-wait
-echo "create.pl --mcreate=0, 1 mount, 8 threads, 500 ops, debug on"
-for i in `seq 1 8`; do
- perl create.pl --silent --mcreate=0 -- $MNT -1 500 &
-done
-wait
-echo "rename.pl, 1 mount, 8 threads, 2000 ops, debug on"
-for i in `seq 1 8`; do
- perl rename.pl --silent $MNT 2000 &
-done
-wait
-
-debug_client_off
-echo "create.pl, 1 mount, 8 threads, 2000 ops, debug off"
-for i in `seq 1 8`; do
- perl create.pl --silent -- $MNT -1 2000 &
-done
-wait
-echo "create.pl --mcreate=0, 1 mount, 8 threads, 2000 ops, debug off"
-for i in `seq 1 8`; do
- perl create.pl --silent --mcreate=0 -- $MNT -1 2000 &
-done
-wait
-echo "rename.pl, 1 mount, 8 threads, 2000 ops, debug off"
-for i in `seq 1 8`; do
- perl rename.pl --silent $MNT 2000 &
-done
-wait
+++ /dev/null
-#!/bin/bash
-
-config=${1:-ba-echo.xml}
-
-LMC="save_cmd"
-LMC_REAL="../../lustre/utils/lmc -m $config"
-
-PORT=988
-TCPBUF=1048576
-OST=ba-ost-1
-CLIENT=client
-
-UUIDLIST=${UUIDLIST:-/usr/local/admin/ba-ost/UUID.txt}
-
-h2ip () {
- echo "${1}"
-}
-BATCH=/tmp/lmc-batch.$$
-save_cmd() {
- echo "$@" >> $BATCH
-}
-
-[ -f $config ] && rm $config
-
-# Client node
-${LMC} --node $CLIENT --tcpbuf $TCPBUF --net '*' tcp $PORT
-
-OBD_UUID=`awk "/$OST / { print \\$3 }" $UUIDLIST`
-[ "$OBD_UUID" ] && OBD_UUID="--obduuid=$OBD_UUID" || echo "$OST: no UUID"
-
-# server node
-${LMC} --node $OST --tcpbuf $TCPBUF --net $OST tcp $PORT
-${LMC} --node $OST --obdtype=obdecho $OBD_UUID --ost
-
-# osc on client
-${LMC} --node $CLIENT --osc OSC_$OST
-
-$LMC_REAL --batch $BATCH
-rm -f $BATCH
+++ /dev/null
-#!/bin/bash
-
-# There are configurations for three machines in this config file: the OST,
-# the MDS/client, other clients
-#
-# To start your cluster using the ba-mount.xml file that this produces, first
-# run:
-# > lconf ba-mount.xml
-# on the MDS/client, and then run:
-# > lconf --node client ba-mount.xml
-# on any other clients.
-
-config=${1:-ba-mount.xml}
-
-LMC_REAL="${LMC:-../utils/lmc} -m config"
-LMC="save_cmd"
-
-PORT=988
-TCPBUF=1048576
-OST=ba-ost-1
-MDS=mds-hostname
-
-UUIDLIST=${UUIDLIST:-/usr/local/admin/ba-ost/UUID.txt}
-
-h2ip () {
- echo "${1}"
-}
-BATCH=/tmp/lmc-batch.$$
-save_cmd() {
- echo "$@" >> $BATCH
-}
-
-[ -f $config ] && rm $config
-
-# MDS/client node
-${LMC} --node $MDS --tcpbuf $TCPBUF --net '*' tcp $PORT
-${LMC} --node $MDS --mds mds1 /tmp/mds1 50000
-
-OBD_UUID=`awk "/$OST / { print \\$3 }" $UUIDLIST`
-[ "$OBD_UUID" ] && OBD_UUID="--obduuid=$OBD_UUID" || echo "$OST: no UUID"
-
-# server node
-${LMC} --node $OST --tcpbuf $TCPBUF --net $OST tcp $PORT
-${LMC} --node $OST $OBD_UUID --ost bluearc
-
-# mount point on the MDS/client
-${LMC} --node $MDS --mtpt /mnt/lustre mds1 OSC_$OST
-
-# other clients
-${LMC} --node client --tcpbuf $TCPBUF --net '*' tcp $PORT
-${LMC} --node client --mtpt /mnt/lustre mds1 OSC_$OST
-
-$LMC_REAL --batch $BATCH
-rm -f $BATCH
+++ /dev/null
-#!/bin/sh
-set -evx
-
-MNT=${MNT:-/mnt/lustre}
-DIR=${DIR:-$MNT}
-SRC=${SRC:-`dirname $0`/../..}
-while date; do
- for i in portals lustre; do
- TGT=$DIR/$i
- [ -d $TGT ] || cp -av $SRC/$i/ $TGT
- make -C $TGT clean
- make -C $TGT -j2
- make -C $TGT clean
- done
-done
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Compile with:
- * cc -I../../portals/include -o mkdirdeep mkdirdeep.c
- * -L../../portals/linux/utils -lptlctl
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <linux/limits.h>
-#include <portals/lltrace.h>
-
-static int opt_depth = 1;
-static int opt_mknod = 0;
-static int opt_verbose = 0;
-static int opt_trace = 1;
-static char* basepathname = 0;
-static char mycwd[PATH_MAX];
-static char* pname = 0;
-static char* outputfilename = 0;
-
-void usage()
-{
- fprintf(stderr, "Usage: %s --depth <d> --output <outputtracefilename>"
- "[--mknod] [--verbose] [--notrace] <basepath>\n", pname);
- exit(1);
-}
-
-int do_mkdir(char* path)
-{
- int rc = mkdir(path, 0755);
- if (rc!=0)
- fprintf(stderr, "mkdir(%s) failed: %s\n",
- path, strerror(errno));
- if (opt_verbose)
- printf("mkdir %s\n", path);
- return rc;
-}
-
-
-int do_mknod(char* path)
-{
- int rc = mknod(path, 0755, S_IFIFO);
- if (rc!=0)
- fprintf(stderr, "mkdir(%s) failed: %s\n",
- path, strerror(errno));
- if (opt_verbose)
- printf("mknod %s\n", path);
- return rc;
-}
-
-int do_chdir(char* path)
-{
- int rc = chdir(path);
- if (rc!=0)
- fprintf(stderr, "chdir(%s) failed: %s\n",
- path, strerror(errno));
- if (opt_verbose)
- printf("chdir %s\n", path);
-
- return rc;
-}
-
-
-int do_stat(char* path)
-{
- char mark_buf[PATH_MAX];
- struct stat mystat;
- int rc = stat(path, &mystat);
- if (rc!=0)
- fprintf(stderr, "stat(%s) failed: %s\n",
- path, strerror(errno));
- if (opt_verbose)
- printf("stat %s = inode %lu\n", path, mystat.st_ino);
-
- if (opt_trace) {
- snprintf(mark_buf, PATH_MAX, "stat %s = inode %lu",
- path, mystat.st_ino);
- ltrace_mark(0, mark_buf);
- }
-
- return rc;
-}
-
-int main(int argc, char** argv)
-{
- int c, opt_index, i, mypid;
-
- static struct option long_options[] = {
- {"depth", 1, 0, 0 },
- {"help", 0, 0, 0 },
- {"mknod", 0, 0, 0 },
- {"verbose", 0, 0, 0 },
- {"notrace", 0, 0, 0 },
- {"output", 1, 0, 0 },
- {0,0,0,0}
- };
-
- char full_pathname[PATH_MAX];
- char rel_pathname[PATH_MAX];
- char mark_buf[PATH_MAX];
-
- pname = strdup(argv[0]);
-
- while (1) {
- c = getopt_long(argc, argv, "d:mhv", long_options, &opt_index);
- if (c == -1)
- break;
- if (c==0) {
- if (!strcmp(long_options[opt_index].name, "notrace")) {
- opt_trace = 0;
- continue;
- }
- c = long_options[opt_index].name[0];
- }
- switch (c) {
- case 'd':
- opt_depth = atoi(optarg);
- if ((opt_depth == 0) || (opt_depth > 100))
- usage();
- break;
- case 'm':
- opt_mknod = 1;
- break;
- case 'v':
- opt_verbose = 1;
- break;
- case 'o':
- outputfilename = optarg;
- break;
- case 'h':
- case '?':
- case ':':
- default:
- usage();
- break;
- }
- }
-
- if (optind != (argc-1))
- usage();
-
- if (outputfilename == NULL)
- usage();
-
- basepathname = argv[optind];
- mypid = getpid();
-
- printf("%s(pid=%d) depth=%d mknod=%d, basepathname=%s, "
- "trace=%d, outputfilename=%s\n",
- pname, mypid, opt_depth, opt_mknod, basepathname, opt_trace,
- outputfilename);
-
- if (!getcwd(&mycwd[0], sizeof(mycwd))) {
- fprintf(stderr, "%s: unable to getcwd()\n", pname);
- exit(1);
- }
-
- if (opt_trace) {
- ltrace_start();
- ltrace_clear();
- snprintf(mark_buf, PATH_MAX,
- "Initialize - mkdir %s; chdir %s",
- basepathname, basepathname);
- ltrace_mark(2, mark_buf);
- }
-
- if (do_mkdir(basepathname)!=0)
- exit(1);
- if (do_chdir(basepathname)!=0)
- exit(1);
-
- /* Create directory tree with depth level of subdirectories */
-
- if (opt_trace) {
- snprintf(mark_buf, PATH_MAX,
- "Create Directory Tree (depth %d)", opt_depth);
- ltrace_mark(2, mark_buf);
- }
-
- for (i=0; i<opt_depth; i++) {
-
- snprintf(rel_pathname, sizeof(rel_pathname),"%d", i+1);
-
- if (i == (opt_depth-1)) {
- /* Last Iteration */
-
- if (opt_trace) {
- snprintf(mark_buf, PATH_MAX,
- "Tree Leaf (%d) %s/stat", i,
- (opt_mknod ? "mknod" : "mkdir"));
- ltrace_mark(3, mark_buf);
- }
-
- if (opt_mknod)
- do_mknod(rel_pathname);
- else
- do_mkdir(rel_pathname);
- /* Now stat it */
- do_stat(rel_pathname);
- }
- else {
- /* Not Leaf */
-
- if (opt_trace) {
- snprintf(mark_buf, PATH_MAX,
- "Tree Level (%d) mkdir/stat/chdir",
- i);
- ltrace_mark(3, mark_buf);
- }
-
- do_mkdir(rel_pathname);
- do_stat(rel_pathname);
- do_chdir(rel_pathname);
- }
- }
-
- /* Stat through directory tree with fullpaths */
-
- if (opt_trace) {
- snprintf(mark_buf, PATH_MAX, "Walk Directory Tree");
- ltrace_mark(2, mark_buf);
- }
-
- do_chdir(basepathname);
-
- strncpy(full_pathname, basepathname, sizeof(full_pathname));
-
- for (i=0; i<opt_depth; i++) {
- snprintf(rel_pathname, sizeof(rel_pathname),"%d", i+1);
- strcat(full_pathname, "/");
- strcat(full_pathname, rel_pathname);
-
- if (opt_trace) {
- snprintf(mark_buf, PATH_MAX, "stat %s",
- full_pathname);
- ltrace_mark(2, mark_buf);
- }
-
- do_stat(full_pathname);
- }
-
- /* Cleanup */
-
- if (opt_trace) {
- snprintf(mark_buf, PATH_MAX, "Cleanup");
- ltrace_mark(2, mark_buf);
- }
-
- if (opt_trace) {
- ltrace_write_file(outputfilename);
- ltrace_add_processnames(outputfilename);
- ltrace_stop();
- }
-
- do_chdir(basepathname);
-
- snprintf(full_pathname, sizeof(full_pathname),
- "rm -rf %s\n", basepathname);
- if (opt_verbose)
- printf("Cleanup: %s", full_pathname);
-
- system(full_pathname);
-
- printf("%s (pid=%d) done.\n", pname, mypid);
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-int main(int argc, char ** argv)
-{
- int i, rc, count;
- char dirname[4096];
-
- if (argc < 3) {
- printf("Usage %s dirnamebase count\n", argv[0]);
- return 1;
- }
-
- if (strlen(argv[1]) > 4080) {
- printf("name too long\n");
- return 1;
- }
-
- count = strtoul(argv[2], NULL, 0);
-
- for (i=0 ; i < count ; i++) {
- sprintf(dirname, "%s-%d", argv[1], i);
- rc = mkdir(dirname, S_IFREG| 0444);
- if (rc) {
- printf("mkdir(%s) error: %s\n",
- dirname, strerror(errno));
- break;
- }
- if ((i % 10000) == 0)
- printf(" - created %d (time %ld)\n", i, time(0));
- }
- return rc;
-}
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-int main(int argc, char ** argv)
-{
- int rc;
-
- if (argc < 3) {
- printf("Usage: %s file link\n", argv[0]);
- return 1;
- }
-
- rc = link(argv[1], argv[2]);
- if (rc) {
- printf("link(%s, %s) error: %s\n", argv[1], argv[2],
- strerror(errno));
- return errno;
- }
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-int main(int argc, char ** argv)
-{
- int rc;
-
- if (argc < 2) {
- printf("Usage %s filename\n", argv[0]);
- return 1;
- }
-
- rc = unlink(argv[1]);
- if (rc) {
- printf("unlink(%s) error: %s\n", argv[1], strerror(errno));
- }
- return rc;
-}
+++ /dev/null
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_lite.h>
-#include <linux/obd_lov.h>
-
-int main(int argc, char **argv)
-{
- int fd;
-
- if (argc != 2) {
- printf("Usage %s <filename>\n", argv[0]);
- exit(1);
- }
-
- fd = open(argv[1], O_RDONLY | O_LOV_DELAY_CREATE);
- if (fd == -1) {
- printf("Error opening %s\n", argv[1]);
- exit(1);
- }
-
- return 0;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
- char *dname1, *dname2;
- int fddev1, fddev2, rc;
- //DIR *dp;
- struct stat st1, st2;
-
- if (argc < 2 || argc > 3) {
- fprintf(stderr, "usage: %s filename1 [filename2]\n", argv[0]);
- exit(1);
- }
-
- dname1 = argv[1];
- if (argc == 3)
- dname2 = argv[2];
- else
- dname2 = argv[1];
-
- //create the special file (right now only test on pipe)
- fprintf(stderr, "creating special file %s\n", dname1);
- rc = mknod(dname1, 0777|S_IFIFO, 0);
- if (rc == -1) {
- fprintf(stderr, "creating %s fails: %s\n",
- dname1, strerror(errno));
- exit(1);
- }
-
- // open the special file again
- fprintf(stderr, "opening file\n");
- fddev1 = open(dname1, O_RDONLY | O_NONBLOCK);
- if (fddev1 == -1) {
- fprintf(stderr, "open %s fails: %s\n",
- dname1, strerror(errno));
- exit(1);
- }
-
- // doesn't matter if the two dirs are the same??
- fddev2 = open(dname2, O_RDONLY | O_NONBLOCK);
- if (fddev2 == -1) {
- fprintf(stderr, "open %s fails: %s\n",
- dname2, strerror(errno));
- exit(1);
- }
-
- // delete the special file
- fprintf (stderr, "unlinking %s\n", dname1);
- rc = unlink(dname1);
- if (rc) {
- fprintf(stderr, "unlink %s error: %s\n",
- dname1, strerror(errno));
- exit(1);
- }
-
- if (access(dname2, F_OK) == 0){
- fprintf(stderr, "%s still exists\n", dname2);
- exit(1);
- }
-
- if (access(dname1, F_OK) == 0){
- fprintf(stderr, "%s still exists\n", dname1);
- exit(1);
- }
-
- // fchmod one special file
- rc = fchmod (fddev1, 0777);
- if(rc == -1)
- {
- fprintf(stderr, "fchmod unlinked special file %s fails: %s\n",
- dname1, strerror(errno));
- exit(1);
- }
-
- // fstat two files to check if they are the same
- rc = fstat(fddev1, &st1);
- if(rc == -1)
- {
- fprintf(stderr, "fstat unlinked special file %s fails: %s\n",
- dname1, strerror(errno));
- exit(1);
- }
-
- rc = fstat(fddev2, &st2);
- if (rc == -1) {
- fprintf(stderr, "fstat file %s fails: %s\n",
- dname2, strerror(errno));
- exit(1);
- }
-
- if (st1.st_mode != st2.st_mode) { // can we do this?
- fprintf(stderr, "fstat different value on %s and %s\n", dname1, dname2);
- exit(1);
- }
-
- fprintf(stderr, "Ok, everything goes well.\n");
- return 0;
-}
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
- char *dname1, *dname2;
- int fddir1, fddir2, rc;
- //DIR *dp;
- struct stat st1, st2;
-
- if (argc < 2 || argc > 3) {
- fprintf(stderr, "usage: %s dirname1 [dirname2]\n", argv[0]);
- exit(1);
- }
-
- dname1 = argv[1];
- if (argc == 3)
- dname2 = argv[2];
- else
- dname2 = argv[1];
-
- //create the directory
- fprintf(stderr, "creating directory %s\n", dname1);
- rc = mkdir(dname1, 0744);
- if (rc == -1) {
- fprintf(stderr, "creating %s fails: %s\n",
- dname1, strerror(errno));
- exit(1);
- }
-
- // open the dir again
- fprintf(stderr, "opening directory\n");
- fddir1 = open(dname1, O_RDONLY | O_DIRECTORY);
- if (fddir1 == -1) {
- fprintf(stderr, "open %s fails: %s\n",
- dname1, strerror(errno));
- exit(1);
- }
-
- // doesn't matter if the two dirs are the same??
- fddir2 = open(dname2, O_RDONLY | O_DIRECTORY);
- if (fddir2 == -1) {
- fprintf(stderr, "open %s fails: %s\n",
- dname2, strerror(errno));
- exit(1);
- }
-
- // another method
-/*
- if ( (dp = opendir(dname2)) == NULL) {
- fprintf(stderr, "opendir() %s\n", strerror(errno));
- exit(1);
- }
- fddir = dirfd(dp);
-*/
-
- // delete the dir
- fprintf (stderr, "unlinking %s\n", dname1);
- rc = rmdir(dname1);
- if (rc) {
- fprintf(stderr, "unlink %s error: %s\n",
- dname1, strerror(errno));
- exit(1);
- }
-
- if (access(dname2, F_OK) == 0){
- fprintf(stderr, "%s still exists\n", dname2);
- exit(1);
- }
-
- if (access(dname1, F_OK) == 0){
- fprintf(stderr, "%s still exists\n", dname1);
- exit(1);
- }
-
- // fchmod the dir
- rc = fchmod (fddir1, 0777);
- if(rc == -1)
- {
- fprintf(stderr, "fchmod unlinked dir fails %s\n",
- strerror(errno));
- exit(1);
- }
-
- // fstat two dirs to check if they are the same
- rc = fstat(fddir1, &st1);
- if(rc == -1)
- {
- fprintf(stderr, "fstat unlinked dir %s fails %s\n",
- dname1, strerror(errno));
- exit(1);
- }
-
- rc = fstat(fddir2, &st2);
- if (rc == -1) {
- fprintf(stderr, "fstat dir %s fails %s\n",
- dname2, strerror(errno));
- exit(1);
- }
-
- if (st1.st_mode != st2.st_mode) { // can we do this?
- fprintf(stderr, "fstat different value on %s and %s\n", dname1, dname2);
- exit(1);
- }
-
- fprintf(stderr, "Ok, everything goes well.\n");
- return 0;
-}
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#if 0
-#define DEBUG
-#endif
-
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-typedef struct flag_mapping {
- char string[20];
- int flag;
-} FLAG_MAPPING;
-
-FLAG_MAPPING flag_table[] = {
- {"O_RDONLY", O_RDONLY},
- {"O_WRONLY", O_WRONLY},
- {"O_RDWR", O_RDWR},
- {"O_CREAT", O_CREAT},
- {"O_EXCL", O_EXCL},
- {"O_NOCTTY", O_NOCTTY},
- {"O_TRUNC", O_TRUNC},
- {"O_APPEND", O_APPEND},
- {"O_NONBLOCK", O_NONBLOCK},
- {"O_NDELAY", O_NDELAY},
- {"O_SYNC", O_SYNC},
- {"O_NOFOLLOW", O_NOFOLLOW},
- {"O_DIRECTORY", O_DIRECTORY},
- {"O_LARGEFILE", O_LARGEFILE},
- {"", -1}
-};
-
-void Usage_and_abort(void)
-{
- fprintf(stderr, "Usage: openfile -f flags [ -m mode ] filename \n");
- fprintf(stderr, "e.g. openfile -f O_RDWR:O_CREAT -m 0755 /etc/passwd\n");
- exit(-1);
-}
-
-int main(int argc, char** argv)
-{
- int i;
- int flags=0;
- mode_t mode=0;
- char* fname=NULL;
- int mode_set=0;
- int flag_set=0;
- int file_set=0;
- char c;
- char* cloned_flags;
-
- if(argc == 1) {
- Usage_and_abort();
- }
-
- while ((c = getopt (argc, argv, "f:m:")) != -1) {
- switch (c) {
- case 'f': {
- char *tmp;
-
- cloned_flags = (char*)malloc(strlen(optarg));
- if (cloned_flags==NULL) {
- fprintf(stderr, "Insufficient memory.\n");
- exit(-1);
- }
-
- strncpy(cloned_flags, optarg, strlen(optarg));
- tmp = strtok(optarg, ":");
- while (tmp) {
- int i = 0;
-#ifdef DEBUG
- printf("flags = %s\n",tmp);
-#endif
- flag_set = 1;
- while (flag_table[i].flag != -1) {
- int r;
- r = strncasecmp(tmp, (flag_table[i].string),
- strlen((flag_table[i].string)) );
-
- if (r == 0)
- break;
- i++;
- }
-
- if (flag_table[i].flag != -1) {
- flags |= flag_table[i].flag;
- } else {
- fprintf(stderr, "No such flag: %s\n",
- tmp);
- exit(-1);
- }
-
- tmp = strtok(NULL, ":");
-
- }
-#ifdef DEBUG
- printf("flags = %x\n", flags);
-#endif
- break;
- }
- case 'm':
-#ifdef DEBUG
- printf("mode = %s\n", optarg);
-#endif
- mode = strtol (optarg, NULL, 8);
- mode_set = 1;
-#ifdef DEBUG
- printf("mode = %o\n", mode);
-#endif
- break;
- default:
- fprintf(stderr, "Bad parameters.\n");
- Usage_and_abort();
- }
- }
-
- if (optind == argc) {
- fprintf(stderr, "Bad parameters.\n");
- Usage_and_abort();
- }
-
- fname = argv[optind];
- file_set = 1;
-
- if (!flag_set || !file_set) {
- fprintf(stderr, "Missing flag or file-name\n");
- exit(-1);
- }
-
-
- if (mode_set)
- i = open(fname, flags, mode);
- else
- i = open(fname, flags);
-
- if (i != -1) {
- fprintf(stderr, "Succeed in opening file \"%s\"(flags=%s",
- fname, cloned_flags);
-
- if (mode_set)
- fprintf(stderr, ", mode=%o", mode);
- fprintf(stderr, ")\n");
- close (i);
- } else {
- fprintf(stderr, "Error in opening file \"%s\"(flags=%s",
- fname, cloned_flags);
- if (mode_set)
- fprintf(stderr, ", mode=%o", mode);
- fprintf(stderr, ") %s\n", strerror(errno));
- }
- return(i);
-}
+++ /dev/null
-#!/bin/sh
-
-set -ex
-
-LUSTRE=${LUSTRE:-`dirname $0`/..}
-PATH=$PATH:$LUSTRE/utils:$LUSTRE/tests
-
-. $LUSTRE/../ltest/functional/llite/common/common.sh
-
-PDSH='pdsh -S -w'
-
-# XXX I wish all this stuff was in some default-config.sh somewhere
-MDSNODE=${MDSNODE:-mdev6}
-OSTNODE=${OSTNODE:-mdev7}
-CLIENT=${CLIENTNODE:-mdev8}
-NETWORKTYPE=${NETWORKTYPE:-tcp}
-MOUNTPT=${MOUNTPT:-/mnt/lustre}
-CONFIG=recovery-small.xml
-MDSDEV=/tmp/mds
-OSTDEV=/tmp/ost
-MDSSIZE=100000
-OSTSIZE=100000
-
-do_mds() {
- $PDSH $MDSNODE "PATH=\$PATH:$LUSTRE/utils:$LUSTRE/tests; cd $PWD; $@"
-}
-
-do_client() {
- $PDSH $CLIENT "PATH=\$PATH:$LUSTRE/utils:$LUSTRE/tests; cd $PWD; $@"
-}
-
-do_ost() {
- $PDSH $OSTNODE "PATH=\$PATH:$LUSTRE/utils:$LUSTRE/tests; cd $PWD; $@"
-}
-
-drop_request() {
- do_mds "echo 0x121 > /proc/sys/lustre/fail_loc"
- do_client "$1 & sleep ${TIMEOUT:-5}; sleep 2; kill \$!"
- do_mds "echo 0 > /proc/sys/lustre/fail_loc"
-}
-
-make_config() {
- rm -f $CONFIG
- for NODE in $CLIENT $MDSNODE $OSTNODE; do
- lmc -m $CONFIG --add net --node $NODE --nid `h2$NETWORKTYPE $NODE` \
- --nettype $NETWORKTYPE || exit 4
- done
- lmc -m $CONFIG --add mds --node $MDSNODE --mds mds1 --dev $MDSDEV \
- --size $MDSSIZE || exit 5
- lmc -m $CONFIG --add ost --node $OSTNODE --ost ost1 --dev $OSTDEV \
- --size $OSTSIZE || exit 6
- lmc -m $CONFIG --add mtpt --node $CLIENT --path $MOUNTPT --mds mds1 \
- --ost ost1 || exit 7
-}
-
-start_mds() {
- do_mds "lconf $@ $CONFIG"
-}
-
-shutdown_mds() {
- do_mds "lconf $@ --cleanup $CONFIG"
-}
-
-start_ost() {
- do_ost "lconf $@ $CONFIG"
-}
-
-shutdown_ost() {
- do_ost "lconf $@ --cleanup $CONFIG"
-}
-
-mount_client() {
- do_client "lconf $@ $CONFIG"
-}
-
-unmount_client() {
- do_client "lconf $@ --cleanup $CONFIG"
-}
-
-setup() {
- make_config
- start_mds ${REFORMAT:---reformat}
- start_ost ${REFORMAT:---reformat}
- mount_client --timeout=${TIMEOUT:-5} --recovery_upcall=/bin/true
-}
-
-cleanup() {
- do_mds "echo 0 > /proc/sys/lustre/fail_loc"
- unmount_client $@ || true
- shutdown_mds $@ || true
- shutdown_ost $@ || true
-}
-
-wait_for_timeout() {
- # wait to make sure we enter recovery
- # it'd be better if the upcall notified us somehow, I think
- sleep $(( ${TIMEOUT:-5} + 2 ))
-}
-
-try_to_cleanup() {
- kill -INT $!
- unmount_client --force
- mount_client --timeout=${TIMEOUT:-5} --recovery_upcall=/bin/true
-}
-
-if [ ! -z "$ONLY" ]; then
- eval "$ONLY"
- exit $?
-fi
-
-setup
-drop_request "mcreate /mnt/lustre/1" & wait_for_timeout
-try_to_cleanup
-
-drop_request "tchmod 111 /mnt/lustre/2" & wait_for_timeout
-try_to_cleanup
-
-drop_request "statone /mnt/lustre/2" & wait_for_timeout
-try_to_cleanup
-
-do_client "cp /etc/resolv.conf /mnt/lustre/resolv.conf"
-drop_request "cat /mnt/lustre/resolv.conf > /dev/null" & wait_for_timeout
-try_to_cleanup
-
-drop_request "mv /mnt/lustre/resolv.conf /mnt/lustre/renamed" & wait_for_timeout
-try_to_cleanup
-
-drop_request "mlink /mnt/lustre/renamed-again /mnt/lustre/link1" & wait_for_timeout
-try_to_cleanup
-
-drop_request "munlink /mnt/lustre/link1" & wait_for_timeout
-try_to_cleanup
-
-cleanup
+++ /dev/null
-#!/bin/sh
-
-set -ex
-
-LUSTRE=${LUSTRE:-`dirname $0`/..}
-PATH=$PATH:$LUSTRE/utils:$LUSTRE/tests
-
-. $LUSTRE/../ltest/functional/llite/common/common.sh
-
-PDSH='pdsh -S -w'
-
-# XXX I wish all this stuff was in some default-config.sh somewhere
-MDSNODE=${MDSNODE:-dev2}
-OSTNODE=${OSTNODE:-dev3}
-CLIENT=${CLIENTNODE:-dev4}
-NETWORKTYPE=${NETWORKTYPE:-tcp}
-MOUNTPT=${MOUNTPT:-/mnt/lustre}
-CONFIG=recovery-small.xml
-MDSDEV=/tmp/mds
-OSTDEV=/tmp/ost
-MDSSIZE=100000
-OSTSIZE=100000
-
-do_mds() {
- $PDSH $MDSNODE "PATH=\$PATH:$LUSTRE/utils:$LUSTRE/tests; cd $PWD; $@"
-}
-
-do_client() {
- $PDSH $CLIENT "PATH=\$PATH:$LUSTRE/utils:$LUSTRE/tests; cd $PWD; $@"
-}
-
-do_ost() {
- $PDSH $OSTNODE "PATH=\$PATH:$LUSTRE/utils:$LUSTRE/tests; cd $PWD; $@"
-}
-
-drop_request() {
- do_mds "echo 0x121 > /proc/sys/lustre/fail_loc"
- do_client "$1"
- do_mds "echo 0 > /proc/sys/lustre/fail_loc"
-}
-
-drop_reply() {
- do_mds "echo 0x120 > /proc/sys/lustre/fail_loc"
- do_client "$@"
- do_mds "echo 0 > /proc/sys/lustre/fail_loc"
-}
-
-make_config() {
- rm -f $CONFIG
- for NODE in $CLIENT $MDSNODE $OSTNODE; do
- lmc -m $CONFIG --add net --node $NODE --nid `h2$NETWORKTYPE $NODE` \
- --nettype $NETWORKTYPE || exit 4
- done
- lmc -m $CONFIG --add mds --node $MDSNODE --mds mds1 --dev $MDSDEV \
- --size $MDSSIZE || exit 5
- lmc -m $CONFIG --add ost --node $OSTNODE --obd obd1 --dev $OSTDEV \
- --size $OSTSIZE || exit 6
- lmc -m $CONFIG --add mtpt --node $CLIENT --path $MOUNTPT --mds mds1 \
- --obd obd1 || exit 7
-}
-
-start_mds() {
- do_mds "lconf $@ $CONFIG"
-}
-
-shutdown_mds() {
- do_mds "lconf $@ --cleanup $CONFIG"
-}
-
-start_ost() {
- do_ost "lconf $@ $CONFIG"
-}
-
-shutdown_ost() {
- do_ost "lconf $@ --cleanup $CONFIG"
-}
-
-mount_client() {
- do_client "lconf $@ $CONFIG"
-}
-
-unmount_client() {
- do_client "lconf $@ --cleanup $CONFIG"
-}
-
-setup() {
- make_config
- start_mds --reformat
- start_ost --reformat
- # XXX we should write our own upcall, when we move this somewhere better.
- mount_client --timeout=10 \
- --recovery_upcall=$PWD/../../ltest/functional/llite/09/client-upcall.sh
-}
-
-cleanup() {
- unmount_client || true
- shutdown_mds || true
- shutdown_ost || true
-}
-
-replay() {
- if [ $# -gt 1 ]; then
- do_client "$1"
- shift
- fi
- do_mds "sync"
- do_mds 'echo -e "device \$mds1\\nprobe\\nnotransno\\nreadonly" | lctl'
- do_client "$1" &
- shutdown_mds -f
- start_mds
- wait
-}
-
-if [ ! -z "$ONLY" ]; then
- eval "$ONLY"
- exit $?
-fi
-
-setup
-drop_request "mcreate /mnt/lustre/1"
-drop_reply "mcreate /mnt/lustre/2"
-replay "mcreate /mnt/lustre/3"
-cleanup
+++ /dev/null
-#!/usr/bin/perl
-use strict;
-use diagnostics;
-use Getopt::Long;
-
-sub usage () {
- print "Usage: $0 <mount point prefix> <iterations>\n";
- print "example: $0 --count=2 /mnt/lustre 50\n";
- print " will test in /mnt/lustre1 and /mnt/lustre2\n";
- print " $0 --count=0 /mnt/lustre 50\n";
- print " will test in /mnt/lustre only\n";
- exit;
-}
-my ($j, $k, $d, $f1, $f2, $path, $silent);
-my $count = 0;
-my $create = 10;
-
-GetOptions("silent!"=> \$silent,
- "count=i" => \$count,
- "create=i" => \$create);
-
-my $mtpt = shift || usage();
-my $i = shift || usage();
-my $total = $i;
-my $files = 6;
-my $dirs = 3;
-my $mcreate = 0; # should we use mcreate or open?
-
-my $which = "";
-if ($count > 0) {
- $which = int(rand() * $count) + 1;
-}
-
-$k = $dirs;
-if ($create == 0) {
- $k = 0;
-}
-while ($k--) {
- $path = "$mtpt$which/$k";
- my $rc = mkdir $path, 0755;
- print "mkdir $path failed: $!\n" if !$rc;
- $j = $files;
- while ($j--) {
- `./mcreate $path/$j`;
- }
-}
-
-while ($i--) {
- my $which = "";
- if ($count > 0) {
- $which = int(rand() * $count) + 1;
- }
- $d = int(rand() * $dirs);
- $f1 = int(rand() * $files);
- $f2 = int(rand() * $files);
- print "[$$] $mtpt$which/$d/$f1 $mtpt$which/$d/$f2 ...\n" if !$silent;
- my $rc = rename "$mtpt$which/$d/$f1", "$mtpt$which/$d/$f2";
- print "[$$] done: $rc\n" if !$silent;
- if (($total - $i) % 100 == 0) {
- print STDERR "[" . $$ . "]" . ($total - $i) . " operations\n";
- }
-}
-
-$k = $dirs;
-if ($create == 0) {
- $k = 0;
-}
-while ($k--) {
- $path = "$mtpt$which/$k";
- $j = $files;
- while ($j--) {
- unlink "$path/$j";
- }
- my $rc = rmdir $path;
- print "rmdir $path failed: $!\n" if !$rc;
-}
-
-print "Done.\n";
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#define DEBUG 0
-
-void
-Usage_and_abort()
-{
- fprintf(stderr, "Usage: runas -u user_id [ -g grp_id ]" \
- " command_to_be_run \n");
- exit(-1);
-}
-
-// Usage: runas -u user_id [ -g grp_id ] "command_to_be_run"
-// return: the return value of "command_to_be_run"
-// NOTE: returning -1 might be the return code of this program itself or
-// the "command_to_be_run"
-
-// ROOT runs "runas" for free
-// Other users run "runas" requires chmod 6755 "command_to_be_run"
-
-int
-main(int argc, char**argv)
-{
- char command[1024];
- char *cmd_ptr;
- int status;
- int c,i;
- int gid_is_set = 0;
- int uid_is_set = 0;
- uid_t user_id;
- gid_t grp_id;
-
- if(argc == 1) {
- Usage_and_abort();
- }
-
- // get UID and GID
- while ((c = getopt (argc, argv, "u:g:h")) != -1) {
- switch (c) {
- case 'u':
- user_id = (uid_t)atoi(optarg);
- uid_is_set = 1;
- if(!gid_is_set) {
- grp_id = user_id;
- }
- break;
-
- case 'g':
- grp_id = (gid_t)atoi(optarg);
- gid_is_set = 1;
- break;
-
- case 'h':
- Usage_and_abort ();
- break;
-
- default:
- // fprintf(stderr, "Bad parameters.\n");
- // Usage_and_abort ();
- }
- }
-
- if (!uid_is_set){
- Usage_and_abort ();
- }
-
-
- if(optind == argc) {
- fprintf(stderr, "Bad parameters.\n");
- Usage_and_abort();
- }
-
-
- // assemble the command
- cmd_ptr = command ;
- for (i = optind; i < argc; i++)
- cmd_ptr += sprintf(cmd_ptr, "%s ", argv[i]);
-
-
-#if DEBUG
- system("whoami");
-#endif
-
- // set GID
- status = setregid(grp_id, grp_id );
- if( status == -1) {
- fprintf(stderr, "Cannot change grp_ID to %d, errno=%d (%s)\n",
- grp_id, errno, strerror(errno) );
- exit(-1);
- }
-
- // set UID
- status = setreuid(user_id, user_id );
- if(status == -1) {
- fprintf(stderr,"Cannot change user_ID to %d, errno=%d (%s)\n",
- user_id, errno, strerror(errno) );
- exit(-1);
- }
-
-#if DEBUG
- system("whoami");
-#endif
-
- fprintf(stdout, "running as USER(%d), Grp (%d): \"%s\" \n",
- user_id, grp_id, command );
-
- // run the command
- status = system(command);
-
- // pass the return code of command_to_be_run out of this wrapper
- if (status == -1) {
- fprintf(stderr, "%s: system() command failed to run\n",
- argv[0]);
- }
- else{
- status = WEXITSTATUS(status);
- fprintf(stderr, "[%s #%d] \"%s\" returns %d (%s).\n", argv[0],
- user_id, argv[optind], status, strerror(status));
-
- }
-
- return(status);
-}
-
+++ /dev/null
-#!/bin/sh
-while sleep 1 ; do
- egrep "ll_|ldlm|filp|dentry|inode|portals|size-[0-9]* " /proc/slabinfo
- echo '-----------------------'
-done
+++ /dev/null
-#!/bin/sh
-vmstat 1 | while read LINE ; do echo "`date +%H:%M:%S`: $LINE" ; done
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <liblustre.h>
-#include <linux/lustre_lib.h>
-#include <linux/obd.h>
-
-int main(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- char rawbuf[8192], parent[4096], *buf = rawbuf, *base, *t;
- int max = sizeof(rawbuf), fd, offset, rc;
-
- if (argc != 2) {
- printf("usage: %s filename\n", argv[0]);
- return 1;
- }
-
- base = argv[1];
- t = strrchr(base, '/');
- if (!t) {
- strcpy(parent, ".");
- offset = -1;
- } else {
- strncpy(parent, base, t - base);
- offset = t - base - 1;
- }
-
- fd = open(parent, O_RDONLY);
- if (fd < 0) {
- printf("open(%s) error: %s\n", parent, strerror(errno));
- exit(errno);
- }
-
- memset(&data, 0, sizeof(data));
- data.ioc_version = OBD_IOCTL_VERSION;
- data.ioc_len = sizeof(data);
- if (offset >= 0)
- data.ioc_inlbuf1 = base + offset + 2;
- else
- data.ioc_inlbuf1 = base;
- data.ioc_inllen1 = strlen(data.ioc_inlbuf1) + 1;
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- printf("ioctl_pack failed.\n");
- exit(1);
- }
-
- rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
- if (rc < 0) {
- printf("ioctl(%s/%s) error: %s\n", parent,
- data.ioc_inlbuf1, strerror(errno));
- exit(errno);
- }
-
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-void usage(char *prog)
-{
- printf("usage: %s filenamefmt count\n", prog);
- printf(" %s filenamefmt start count\n", prog);
-}
-
-int main(int argc, char ** argv)
-{
- int i, rc = 0;
- char format[4096], *fmt;
- char filename[4096];
- long start, last;
- long begin = 0, count;
-
- if (argc < 3 || argc > 4) {
- usage(argv[0]);
- return 1;
- }
-
- if (strlen(argv[1]) > 4080) {
- printf("name too long\n");
- return 1;
- }
-
- start = last = time(0);
-
- if (argc == 3) {
- count = strtol(argv[2], NULL, 0);
- if (count < 1) {
- printf("count must be at least one\n");
- return 1;
- }
- } else {
- begin = strtol(argv[2], NULL, 0);
- count = strtol(argv[3], NULL, 0);
- }
-
- if (strchr(argv[1], '%')) {
- fmt = argv[1];
- } else {
- sprintf(format, "%s%%d", argv[1]);
- fmt = format;
- }
- for (i = 0; i < count; i++, begin++) {
- sprintf(filename, fmt, begin);
- rc = unlink(filename);
- if (rc) {
- printf("unlink(%s) error: %s\n",
- filename, strerror(errno));
- rc = errno;
- break;
- }
- if ((i % 10000) == 0) {
- printf(" - unlinked %d (time %ld ; total %ld ; last "
- "%ld)\n", i, time(0), time(0) - start,
- time(0) - last);
- last = time(0);
- }
- }
- printf("total: %d unlinks in %ld seconds: %f unlinks/second\n", i,
- time(0) - start, ((float)i / (time(0) - start)));
-
- return rc;
-}
+++ /dev/null
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
- int fd, rc;
- int i = 0;
- char buf[4096];
-
- memset(buf, 0, 4096);
-
- if (argc != 2) {
- printf("Usage openme <filename>\n");
- exit(1);
- }
-
- fd = open(argv[1], O_RDWR | O_CREAT, 0600);
- if (fd == -1) {
- printf("Error opening %s\n", argv[1]);
- exit(1);
- }
-
- while (1) {
- sprintf(buf, "write %d\n", i);
- rc = write(fd, buf, sizeof(buf));
- sleep(1);
- }
- return 0;
-}
+++ /dev/null
-Makefile
-Makefile.in
-.deps
-*.pyc
+++ /dev/null
-pymod_SCRIPTS = __init__.py lustredb.py error.py cmdline.py
-EXTRA_DIST = $(pymod_SCRIPTS)
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Author: Robert Read <rread@clusterfs.com>
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free software; you can redistribute it and/or
-# modify it under the terms of version 2 of the GNU General Public
-# License as published by the Free Software Foundation.
-#
-# Lustre is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-# Standard the comand line handling for all the python tools.
-
-import sys, getopt, types
-import string
-import error
-
-class Options:
- FLAG = 1
- PARAM = 2
- INTPARAM = 3
- def __init__(self, cmd, remain_help, options):
- self.options = options
- shorts = ""
- longs = []
- options.append(('help,h', "Print this help"))
- for opt in options:
- long = self.long(opt)
- short = self.short(opt)
- if self.type(opt) in (Options.PARAM, Options.INTPARAM):
- if short: short = short + ':'
- if long: long = long + '='
- shorts = shorts + short
- longs.append(long)
- self.short_opts = shorts
- self.long_opts = longs
- self.cmd = cmd
- self.remain_help = remain_help
-
- def init_values(self):
- values = {}
- for opt in self.options:
- values[self.long(opt)] = self.default(opt)
- return values
-
- def long(self, option):
- n = string.find(option[0], ',')
- if n < 0: return option[0]
- else: return option[0][0:n]
-
- def short(self, option):
- n = string.find(option[0], ',')
- if n < 0: return ''
- else: return option[0][n+1:]
-
- def help(self, option):
- return option[1]
-
- def type(self, option):
- if len(option) >= 3:
- return option[2]
- return Options.FLAG
-
- def default(self, option):
- if len(option) >= 4:
- return option[3]
- return None
-
- def lookup_option(self, key, key_func):
- for opt in self.options:
- if key_func(opt) == key:
- return opt
-
- def lookup_short(self, key):
- return self.lookup_option(key, self.short)
-
- def lookup_long(self, key):
- return self.lookup_option(key, self.long)
-
- def handle_opts(self, opts):
- values = self.init_values()
- for o, a in opts:
- if o[0:2] != '--':
- option = self.lookup_short(o[1:])
- else:
- option = self.lookup_long(o[2:])
- if self.type(option) == Options.PARAM:
- val = a
- elif self.type(option) == Options.INTPARAM:
- try:
- val = int(a)
- except ValueError, e:
- raise error.OptionError("option: '%s' expects integer value, got '%s' " % (o,a))
- else:
- val = 1
- values[self.long(option)] = val
- return values
-
- class option_wrapper:
- def __init__(self, values):
- self.__dict__['values'] = values
- def __getattr__(self, name):
- if self.values.has_key(name):
- return self.values[name]
- else:
- raise error.OptionError("bad option name: " + name)
- def __setattr__(self, name, value):
- self.values[name] = value
-
- def parse(self, argv):
- try:
- opts, args = getopt.getopt(argv, self.short_opts, self.long_opts)
- values = self.handle_opts(opts)
- if values["help"]:
- self.usage()
- sys.exit(0)
- return self.option_wrapper(values), args
- except getopt.error, e:
- raise error.OptionError(str(e))
-
- def usage(self):
- ret = 'usage: %s [options] %s\n' % (self.cmd, self.remain_help)
- for opt in self.options:
- s = self.short(opt)
- if s: str = "-%s|--%s" % (s,self.long(opt))
- else: str = "--%s" % (self.long(opt),)
- if self.type(opt) in (Options.PARAM, Options.INTPARAM):
- str = "%s <arg>" % (str,)
- help = self.help(opt)
- n = string.find(help, '\n')
- if self.default(opt) != None:
- if n < 0:
- str = "%-15s %s (default=%s)" %(str, help,
- self.default(opt))
- else:
- str = "%-15s %s (default=%s)%s" %(str, help[0:n],
- self.default(opt),
- help[n:])
- else:
- str = "%-15s %s" %(str, help)
- ret = ret + str + "\n"
- print ret
-
-# Test driver
-if __name__ == "__main__":
- cl = Options("test", "xml_file", [
- ('verbose,v', "verbose ", Options.FLAG, 0),
- ('cleanup,d', "shutdown"),
- ('gdb', "Display gdb module file ", Options.FLAG, 0),
- ('device', "device path ", Options.PARAM),
- ('ldapurl', "LDAP server URL ", Options.PARAM),
- ('lustre', "Lustre source dir ", Options.PARAM),
- ('portals', "Portals source dir ", Options.PARAM),
- ('maxlevel', """Specify the maximum level
- Levels are aproximatly like:
- 70 - mountpoint, echo_client, osc, mdc, lov""",
- Options.INTPARAM, 100),
-
- ])
-
- conf, args = cl.parse(sys.argv[1:])
-
- for key in conf.values.keys():
- print "%-10s = %s" % (key, conf.values[key])
+++ /dev/null
-import exceptions
-
-class LconfError (exceptions.Exception):
- def __init__(self, args):
- self.args = args
-
-class OptionError (exceptions.Exception):
- def __init__(self, args):
- self.args = args
-
+++ /dev/null
-import sys, types, string, os
-import re, exceptions
-import xml.dom.minidom
-import Lustre
-
-# ============================================================
-# XML processing and query
-
-class LustreDB:
- def lookup(self, uuid):
- """ lookup returns a new LustreDB instance"""
- return self._lookup_by_uuid(uuid)
-
- def lookup_name(self, name, class_name = ""):
- """ lookup returns a new LustreDB instance"""
- return self._lookup_by_name(name, class_name)
-
- def lookup_class(self, class_name):
- """ lookup returns a new LustreDB instance"""
- return self._lookup_by_class(class_name)
-
- def get_val(self, tag, default=None):
- v = self._get_val(tag)
- if v:
- return v
- if default != None:
- return default
- return None
-
- def get_class(self):
- return self._get_class()
-
- def get_val_int(self, tag, default=0):
- str = self._get_val(tag)
- try:
- if str:
- return int(str)
- return default
- except ValueError:
- raise LconfError("text value is not integer:", str)
-
- def get_first_ref(self, tag):
- """ Get the first uuidref of the type TAG. Only
- one is expected. Returns the uuid."""
- uuids = self._get_refs(tag)
- if len(uuids) > 0:
- return uuids[0]
- return None
-
- def get_refs(self, tag):
- """ Get all the refs of type TAG. Returns list of uuids. """
- uuids = self._get_refs(tag)
- return uuids
-
- def get_all_refs(self):
- """ Get all the refs. Returns list of uuids. """
- uuids = self._get_all_refs()
- return uuids
-
- def nid2server(self, nid, net_type):
- netlist = self.lookup_class('network')
- for net_db in netlist:
- if net_db.get_val('nid') == nid and net_db.get_val('nettype') == net_type:
- return net_db
- return None
-
- # Find the target_device for target on a node
- # node->profiles->device_refs->target
- def get_node_tgt_dev(self, node_name, target_uuid):
- node_db = self.lookup_name(node_name)
- if not node_db:
- return None
- return self.get_tgt_dev(target_uuid)
-
- # get all network uuids for this node
- def get_networks(self):
- ret = []
- prof_list = self.get_refs('profile')
- for prof_uuid in prof_list:
- prof_db = self.lookup(prof_uuid)
- net_list = prof_db.get_refs('network')
- for net_uuid in net_list:
- ret.append(net_uuid)
- return ret
-
- def get_active_dev(self, tgtuuid):
- tgt = self.lookup(tgtuuid)
- tgt_dev_uuid =tgt.get_first_ref('active')
- return tgt_dev_uuid
-
- def get_tgt_dev(self, tgtuuid):
- prof_list = self.get_refs('profile')
- for prof_uuid in prof_list:
- prof_db = self.lookup(prof_uuid)
- if not prof_db:
- panic("profile:", profile, "not found.")
- for ref_class, ref_uuid in prof_db.get_all_refs():
- if ref_class in ('osd', 'mdsdev'):
- devdb = self.lookup(ref_uuid)
- uuid = devdb.get_first_ref('target')
- if tgtuuid == uuid:
- return ref_uuid
- return None
-
- def get_group(self, group):
- ret = []
- devs = self.lookup_class('mds')
- for tgt in devs:
- if tgt.get_val('group', "") == group:
- ret.append(tgt.getUUID())
- devs = self.lookup_class('ost')
- for tgt in devs:
- if tgt.get_val('group', "") == group:
- ret.append(tgt.getUUID())
- return ret
-
- # Change the current active device for a target
- def update_active(self, tgtuuid, new_uuid):
- self._update_active(tgtuuid, new_uuid)
-
-class LustreDB_XML(LustreDB):
- def __init__(self, dom, root_node):
- # init xmlfile
- self.dom_node = dom
- self.root_node = root_node
-
- def xmltext(self, dom_node, tag):
- list = dom_node.getElementsByTagName(tag)
- if len(list) > 0:
- dom_node = list[0]
- dom_node.normalize()
- if dom_node.firstChild:
- txt = string.strip(dom_node.firstChild.data)
- if txt:
- return txt
-
- def xmlattr(self, dom_node, attr):
- return dom_node.getAttribute(attr)
-
- def _get_val(self, tag):
- """a value could be an attribute of the current node
- or the text value in a child node"""
- ret = self.xmlattr(self.dom_node, tag)
- if not ret:
- ret = self.xmltext(self.dom_node, tag)
- return ret
-
- def _get_class(self):
- return self.dom_node.nodeName
-
- def get_ref_type(self, ref_tag):
- res = string.split(ref_tag, '_')
- return res[0]
-
- #
- # [(ref_class, ref_uuid),]
- def _get_all_refs(self):
- list = []
- for n in self.dom_node.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- ref_uuid = self.xml_get_ref(n)
- ref_class = self.get_ref_type(n.nodeName)
- list.append((ref_class, ref_uuid))
-
- list.sort()
- return list
-
- def _get_refs(self, tag):
- """ Get all the refs of type TAG. Returns list of uuids. """
- uuids = []
- refname = '%s_ref' % tag
- reflist = self.dom_node.getElementsByTagName(refname)
- for r in reflist:
- uuids.append(self.xml_get_ref(r))
- return uuids
-
- def xmllookup_by_uuid(self, dom_node, uuid):
- for n in dom_node.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- if self.xml_get_uuid(n) == uuid:
- return n
- else:
- n = self.xmllookup_by_uuid(n, uuid)
- if n: return n
- return None
-
- def _lookup_by_uuid(self, uuid):
- dom = self. xmllookup_by_uuid(self.root_node, uuid)
- if dom:
- return LustreDB_XML(dom, self.root_node)
-
- def xmllookup_by_name(self, dom_node, name):
- for n in dom_node.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- if self.xml_get_name(n) == name:
- return n
- else:
- n = self.xmllookup_by_name(n, name)
- if n: return n
- return None
-
- def _lookup_by_name(self, name, class_name):
- dom = self.xmllookup_by_name(self.root_node, name)
- if dom:
- return LustreDB_XML(dom, self.root_node)
-
- def xmllookup_by_class(self, dom_node, class_name):
- return dom_node.getElementsByTagName(class_name)
-
- def _lookup_by_class(self, class_name):
- ret = []
- domlist = self.xmllookup_by_class(self.root_node, class_name)
- for node in domlist:
- ret.append(LustreDB_XML(node, self.root_node))
- return ret
-
- def xml_get_name(self, n):
- return n.getAttribute('name')
-
- def getName(self):
- return self.xml_get_name(self.dom_node)
-
- def xml_get_ref(self, n):
- return n.getAttribute('uuidref')
-
- def xml_get_uuid(self, dom_node):
- return dom_node.getAttribute('uuid')
-
- def getUUID(self):
- return self.xml_get_uuid(self.dom_node)
-
- def get_routes(self, type, gw):
- """ Return the routes as a list of tuples of the form:
- [(type, gw, lo, hi),]"""
- res = []
- tbl = self.dom_node.getElementsByTagName('routetbl')
- for t in tbl:
- routes = t.getElementsByTagName('route')
- for r in routes:
- net_type = self.xmlattr(r, 'type')
- if type != net_type:
- lo = self.xmlattr(r, 'lo')
- hi = self.xmlattr(r, 'hi')
- res.append((type, gw, lo, hi))
- return res
-
- def get_route_tbl(self):
- ret = []
- for r in self.dom_node.getElementsByTagName('route'):
- net_type = self.xmlattr(r, 'type')
- gw = self.xmlattr(r, 'gw')
- lo = self.xmlattr(r, 'lo')
- hi = self.xmlattr(r, 'hi')
- ret.append((net_type, gw, lo, hi))
- return ret
-
- def _update_active(self, tgt, new):
- raise LconfError("updates not implemented for XML")
-
-# ================================================================
-# LDAP Support
-class LustreDB_LDAP(LustreDB):
- def __init__(self, name, attrs,
- base = "fs=lustre",
- parent = None,
- url = "ldap://localhost",
- user = "cn=Manager, fs=lustre",
- pw = "secret"
- ):
- self._name = name
- self._attrs = attrs
- self._base = base
- self._parent = parent
- self._url = url
- self._user = user
- self._pw = pw
- if parent:
- self.l = parent.l
- self._base = parent._base
- else:
- self.open()
-
- def open(self):
- import ldap
- try:
- self.l = ldap.initialize(self._url)
- # Set LDAP protocol version used
- self.l.protocol_version=ldap.VERSION3
- # user and pw only needed if modifying db
- self.l.bind_s(self._user, self._pw, ldap.AUTH_SIMPLE);
- except ldap.LDAPError, e:
- raise LconfError(e)
- # FIXME, do something useful here
-
- def close(self):
- self.l.unbind_s()
-
- def ldap_search(self, filter):
- """Return list of uuids matching the filter."""
- import ldap
- dn = self._base
- ret = []
- uuids = []
- try:
- for name, attrs in self.l.search_s(dn, ldap.SCOPE_ONELEVEL,
- filter, ["uuid"]):
- for v in attrs['uuid']:
- uuids.append(v)
- except ldap.NO_SUCH_OBJECT, e:
- pass
- except ldap.LDAPError, e:
- print e # FIXME: die here?
- if len(uuids) > 0:
- for uuid in uuids:
- ret.append(self._lookup_by_uuid(uuid))
- return ret
-
- def _lookup_by_name(self, name, class_name):
- list = self.ldap_search("lustreName=%s" %(name))
- if len(list) == 1:
- return list[0]
- return None
-
- def _lookup_by_class(self, class_name):
- return self.ldap_search("objectclass=%s" %(string.upper(class_name)))
-
- def _lookup_by_uuid(self, uuid):
- import ldap
- dn = "uuid=%s,%s" % (uuid, self._base)
- ret = None
- try:
- for name, attrs in self.l.search_s(dn, ldap.SCOPE_BASE,
- "objectclass=*"):
- ret = LustreDB_LDAP(name, attrs, parent = self)
-
- except ldap.NO_SUCH_OBJECT, e:
- pass # just return empty list
- except ldap.LDAPError, e:
- print e # FIXME: die here?
- return ret
-
-
- def _get_val(self, k):
- ret = None
- if self._attrs.has_key(k):
- v = self._attrs[k]
- if type(v) == types.ListType:
- ret = str(v[0])
- else:
- ret = str(v)
- return ret
-
- def _get_class(self):
- return string.lower(self._attrs['objectClass'][0])
-
- def get_ref_type(self, ref_tag):
- return ref_tag[:-3]
-
- #
- # [(ref_class, ref_uuid),]
- def _get_all_refs(self):
- list = []
- for k in self._attrs.keys():
- if re.search('.*Ref', k):
- for uuid in self._attrs[k]:
- ref_class = self.get_ref_type(k)
- list.append((ref_class, uuid))
- return list
-
- def _get_refs(self, tag):
- """ Get all the refs of type TAG. Returns list of uuids. """
- uuids = []
- refname = '%sRef' % tag
- if self._attrs.has_key(refname):
- return self._attrs[refname]
- return []
-
- def getName(self):
- return self._get_val('lustreName')
-
- def getUUID(self):
- return self._get_val('uuid')
-
- def get_route_tbl(self):
- return []
-
- def _update_active(self, tgtuuid, newuuid):
- """Return list of uuids matching the filter."""
- import ldap
- dn = "uuid=%s,%s" %(tgtuuid, self._base)
- ret = []
- uuids = []
- try:
- self.l.modify_s(dn, [(ldap.MOD_REPLACE, "activeRef", newuuid)])
- except ldap.NO_SUCH_OBJECT, e:
- print e
- except ldap.LDAPError, e:
- print e # FIXME: die here?
- return
-
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Author: Robert Read <rread@clusterfs.com>
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free software; you can redistribute it and/or
-# modify it under the terms of version 2 of the GNU General Public
-# License as published by the Free Software Foundation.
-#
-# Lustre is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-# For all the OST/MDSs that are primary on the --primary node, set
-# them to be active on --active if that OST is available on --active.
-#
-# Make the active node the active node for all devices it shares with the
-# old. The bulk of this code is for figuring out which devices to
-# change, and what to change them to.
-
-# XXX add error checking
-# XXX make this code less ugly
-
-import sys, getopt, types
-import string, os
-import ldap
-import Lustre
-
-lactive_options = [
- ('ldapurl',"LDAP server URL", Lustre.Options.PARAM,
- "ldap://localhost"),
- ('config', "Cluster config name used for LDAP query", Lustre.Options.PARAM),
- ('group', "The group of devices to update", Lustre.Options.PARAM),
- ('active', "The active node name", Lustre.Options.PARAM),
- ]
-
-def fatal(*args):
- msg = string.join(map(str,args))
- print "! " + msg
- sys.exit(1)
-
-
-cl = Lustre.Options("lactive","", lactive_options)
-config, args = cl.parse(sys.argv[1:])
-
-if not (config.group or config.active):
- fatal("Must specify both group and active node.")
-
-if not config.config:
- fatal("Missing config")
-
-base = "config=%s,fs=lustre" % (config.config,)
-db = Lustre.LustreDB_LDAP('', {}, base=base, url = config.ldapurl)
-
-active_node = db.lookup_name(config.active)
-if not active_node:
- fatal(config.active, "node not found in database.")
-
-devices = db.get_group(config.group)
-if len(devices) < 0:
- fatal("no devices found for group", config.group)
-
-# for all devices in group
- # lookup device in active node
- # update the active device
-for tgtuuid in devices:
- active_uuid = db.get_active_dev(tgtuuid)
- new_active_uuid = active_node.get_tgt_dev(tgtuuid)
- if active_uuid != new_active_uuid:
- print ("%s: changing active %s to %s:%s"
- % (tgtuuid, active_uuid,
- config.active, new_active_uuid))
- db.update_active(tgtuuid, new_active_uuid)
-
-
-
-
-
+++ /dev/null
-#define _XOPEN_SOURCE 500
-
-#include <stdio.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <libgen.h>
-#include <ftw.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#define printk printf
-#include <linux/lustre_lib.h>
-#include <linux/lustre_lite.h>
-
-#warning Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c
-#define MAX_LOV_UUID_COUNT 1000
-#define OBD_NOT_FOUND ((__u32)-1)
-#define debugMsg if (debug) printf
-
-char * cmd;
-int debug;
-struct option longOpts[] = {
- {"debug", 0, 0, 'd'},
- {"help", 0, 0, 'h'},
- {"obd", 1, 0, 'o'},
- {"query", 0, 0, 'o'},
- {0, 0, 0, 0}
- };
-int query;
-char * shortOpts = "dho:qv";
-char * usageMsg = "[ --obd <obd uuid> | --query ] <dir|file> ...";
-
-int max_stripe_count = MAX_LOV_UUID_COUNT;
-obd_uuid_t * obduuid;
-__u32 obdcount;
-__u32 obdindex;
-char * buf;
-int buflen;
-struct obd_ioctl_data data;
-struct lov_desc desc;
-obd_uuid_t * uuids;
-int uuidslen;
-int cfglen;
-struct lov_user_md *lum;
-int lumlen;
-
-void init();
-void usage(FILE *stream);
-void errMsg(char *fmt, ...);
-void processPath(char *path);
-int processFile(
- const char *path,
- const struct stat *sp,
- int flag,
- struct FTW *ftwp
- );
-__u32 getobdindex(const char *path);
-
-int
-main (int argc, char **argv) {
- int c;
-
- cmd = basename(argv[0]);
-
- while ((c = getopt_long(argc, argv, shortOpts, longOpts, NULL)) != -1) {
- switch (c) {
- case 'd':
- debug++;
- break;
- case 'o':
- if (obduuid) {
- errMsg("obd '%s' already specified: '%s'.",
- obduuid, optarg);
- exit(1);
- }
-
- obduuid = (obd_uuid_t *)optarg;
- break;
- case 'h':
- usage(stdout);
- exit(0);
- case 'q':
- query++;
- break;
- case '?':
- usage(stderr);
- exit(1);
- default:
- errMsg("Internal error. Valid '%s' unrecognized.",
- argv[optind - 1]);
- usage(stderr);
- exit(1);
- }
- }
-
- if (optind >= argc) {
- usage(stderr);
- exit(1);
- }
-
- if (obduuid == NULL)
- query++;
-
- init();
-
- do {
- processPath(argv[optind]);
- } while (++optind < argc);
-
- exit (0);
-}
-
-void
-init()
-{
- int datalen, desclen;
-
- datalen = size_round(sizeof(data));
- desclen = size_round(sizeof(desc));
- uuidslen = size_round(max_stripe_count * sizeof(*uuids));
- cfglen = datalen + desclen + uuidslen;
- lumlen = sizeof(*lum) + max_stripe_count * sizeof(*lum->lum_luoinfo);
- if (cfglen > lumlen)
- buflen = cfglen;
- else
- buflen = lumlen;
-
-#warning max ioctl buffer size currently hardcoded to 8192
- if (buflen > 8192) {
- int nuuids, remaining, nluoinfos;
-
- buflen = 8192;
- nuuids = (buflen - datalen - desclen) / sizeof(*uuids);
- uuidslen = size_round(nuuids * sizeof(*uuids));
- remaining = nuuids * sizeof(*uuids);
- if (uuidslen > remaining)
- nuuids--;
- nluoinfos = (buflen - sizeof(*lum)) / sizeof(*lum->lum_luoinfo);
- if (nuuids > nluoinfos)
- max_stripe_count = nluoinfos;
- else
- max_stripe_count = nuuids;
-
- cfglen = datalen + desclen + uuidslen;
- lumlen = sizeof(*lum) + max_stripe_count *
- sizeof(*lum->lum_luoinfo);
- }
-
- if ((buf = malloc(buflen)) == NULL) {
- errMsg("Unable to allocate %d bytes of memory for ioctl's.",
- buflen);
- exit(1);
- }
-
- lum = (struct lov_user_md *)buf;
- uuids = (obd_uuid_t *)buf;
-}
-
-void
-usage(FILE *stream)
-{
- fprintf(stream, "usage: %s %s\n", cmd, usageMsg);
-}
-
-void
-errMsg(char *fmt, ...)
-{
- va_list args;
-
- fprintf(stderr, "%s: ", cmd);
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- fprintf(stderr, "\n");
-}
-
-void
-processPath(char *path)
-{
- obdindex = OBD_NOT_FOUND;
- nftw((const char *)path, processFile, 128, FTW_PHYS|FTW_MOUNT);
-}
-
-int
-processFile(const char *path,
- const struct stat *sp,
- int flag,
- struct FTW *ftwp
-) {
- struct lov_user_oinfo *luoinfo;
- int fd;
- int count;
- int rc;
- int i;
-
- if (flag != FTW_F)
- return 0;
-
- if ((obdcount == 0) && (getobdindex(path) == OBD_NOT_FOUND)) {
- /* terminate nftw walking this tree */
- return(1);
- }
-
- if ((fd = open(path, O_RDONLY)) < 0) {
- errMsg("open \"%.20s\" failed.", path);
- perror("open");
- exit(1);
- }
-
- memset((void *)buf, 0, buflen);
- lum->lum_stripe_count = max_stripe_count;
-
- if ((rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, (void *)lum)) < 0) {
- errMsg("LL_IOC_LOV_GETSTRIPE ioctl failed.");
- perror("ioctl");
- exit(1);
- }
-
- close(fd);
-
- count = lum->lum_stripe_count;
- luoinfo = lum->lum_luoinfo;
-
- if (query) {
- printf("%s\n", path);
- for (i = 0; i < count; i++, luoinfo++) {
- printf("%4d: obdindex: %-4d objid: %lld\n",
- i, luoinfo->luo_idx, luoinfo->luo_id);
- }
- return(0);
- }
-
- debugMsg("LL_IOC_LOV_GETSTRIPE:%s: obdindex: %d count: %d\n",
- path, obdindex, count);
-
- for (i = 0; i < count; i++, luoinfo++) {
- debugMsg("%-4d: obdidx: %-4d objid: %lld\n",
- i, luoinfo->luo_idx, luoinfo->luo_id);
- if (luoinfo->luo_idx == obdindex) {
- printf("%s\n", path);
- return 0;
- }
- }
-
- return(0);
-}
-
-__u32
-getobdindex(const char *path)
-{
- obd_uuid_t *uuidp;
- int fd;
- int rc;
- int i;
-
- if ((fd = open(path, O_RDONLY)) < 0) {
- errMsg("open \"%.20s\" failed.", path);
- perror("open");
- exit(1);
- }
-
- data.ioc_inllen1 = sizeof(desc);
- data.ioc_inlbuf1 = (char *)&desc;
- data.ioc_inllen2 = uuidslen;
- data.ioc_inlbuf2 = (char *)uuids;
- data.ioc_inllen3 = 0;
-
- memset(&desc, 0, sizeof(desc));
- desc.ld_tgt_count = max_stripe_count;
-
- if (obd_ioctl_pack(&data, &buf, buflen)) {
- errMsg("internal buffering error.");
- exit(1);
- }
-
- rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
- if (rc) {
- errMsg("OBD_IOC_LOV_GET_CONFIG ioctl failed: %d.", errno);
- perror("ioctl");
- exit(1);
- }
-
- if (obd_ioctl_unpack(&data, buf, buflen)) {
- errMsg("Invalid reply from ioctl.");
- exit(1);
- }
-
- close(fd);
-
- obdcount = desc.ld_tgt_count;
-
- if (query) {
- printf("OBDS:\n");
- for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++)
- printf("%4d: %s\n", i, (char *)uuidp);
-
- return(0);
- }
-
- for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
- rc = strncmp((const char *)obduuid, (const char *)uuidp,
- sizeof(*uuidp));
- if (rc == 0) {
- obdindex = i;
- break;
- }
- }
-
- if (obdindex == OBD_NOT_FOUND) {
- errMsg("obd UUID '%s' not found.", obduuid);
- return(OBD_NOT_FOUND);
- }
-
- return(0);
-}
+++ /dev/null
-#!/usr/bin/perl
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Author: Hariharan Thantry <thantry@users.sourceforge.net>
-
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free software; you can redistribute it and/or
-# modify it under the terms of version 2 of the GNU General Public
-# License as published by the Free Software Foundation.
-#
-# Lustre is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-
-package llparser;
-require Exporter;
-@ISA = qw(Exporter);
-@EXPORT = qw(parse_file print_rpcrelations parse_foptions %ll_subsystems
- %subsysnum %trace_masks $e_subsys $e_mask $e_processor $e_time
- $e_file $e_line $e_function $e_pid $e_stack $e_fmtstr $e_backref
- $e_treeparent $e_numchildren $e_youngestchild $e_next $e_pidhead
- $e_rpcsndrcv $e_rpcpid $e_rpcxid $e_rpcnid $e_rpcopc $e_rpcnext
- $e_curlineref $SEND $RCV);
-
-($e_subsys,
- $e_mask,
- $e_processor,
- $e_time,
- $e_file,
- $e_line,
- $e_function,
- $e_pid,
- $e_stack,
- $e_fmtstr,
- $e_treeparent,
- $e_numchildren,
- $e_youngestchild,
- $e_pidhead,
- $e_next,
- $e_backref) = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
-
-($e_rpcpid,
- $e_rpcxid,
- $e_rpcnid,
- $e_rpcopc,
- $e_rpcnext,
- $e_rpcsndrcv,
- $e_curlineref) = (0, 1, 2, 3, 4, 5, 6);
-
-$SEND = 0;
-$RCV = 1;
-
-$REGEX=qr/^\s*(\w+)\s*:\s*(\d+)\s*:\s*(\d+)\s*:\s*(\d+\.(?:\d+))\s*\(\s*([^:]+)\s*:\s*(\d+)\s*:\s*([^()]+)\s*\(\)\s*(?:(?:\d+)\s*\|\s*)?(\d+)\s*\+\s*(\d+)\s*(?:.*)\):(.*)$/;
-
-$RPCREGEX = qr/^\s*(?:Sending|Handling)\s*RPC\s*pid:xid:nid:opc\s*(\d+):(?:0x)?(\w+):(?:0x)?(\w+):(\d+)\s*$/;
-$FILEOPTIONREGEX = qr/(--server)|(-s)/;
-$SENDING = qr/Sending/;
-
-
-# Needs to match definition in portals/include/linux/kp30.h
-%ll_subsystems = ("00" => "UNDEFINED", "01" => "MDC", "02" => "MDS",
- "03" => "OSC", "04" => "OST", "05" => "CLASS",
- "06" => "OBDFS","07" => "LLITE","08" => "RPC",
- "09" => "EXT2OBD","0a" => "PORTALS","0b" => "SOCKNAL",
- "0c" => "QSWNAL","0d" => "PINGER","0e" => "FILTER",
- "0f" => "TRACE","10" => "ECHO","11" => "LDLM",
- "12" => "LOV", "13" => "GMNAL","14" => "PTLROUTER" );
-
-%subsysnum;
-$subsysnum->{UNDEFINED} = 0;
-$subsysnum->{MDC} = 1;
-$subsysnum->{MDS} = 2;
-$subsysnum->{OSC} = 3;
-$subsysnum->{OST} = 4;
-$subsysnum->{CLASS} = 5;
-$subsysnum->{OBDFS} = 6;
-$subsysnum->{LLITE} = 7;
-$subsysnum->{RPC} = 8;
-$subsysnum->{EXT2OBD} = 9;
-$subsysnum->{PORTALS} = 10;
-$subsysnum->{SOCKNAL} = 11;
-$subsysnum->{QSWNAL} = 12;
-$subsysnum->{PINGER} = 13;
-$subsysnum->{FILTER} = 14;
-$subsysnum->{TRACE} = 15; # obdtrace, not to be confused with D_TRACE */
-$subsysnum->{ECHO} = 16;
-$subsysnum->{LDLM} = 17;
-$subsysnum->{LOV} = 18;
-$subsysnum->{GMNAL} = 19;
-$subsysnum->{PTLROUTER} = 20;
-
-%tracemasks;
-$tracemasks->{TRACE} = 1 << 0; # /* ENTRY/EXIT markers */
-$tracemasks->{INODE} = 1 << 1; #
-$tracemasks->{SUPER} = 1 << 2; #
-$tracemasks->{EXT2} = 1 << 3; # /* anything from ext2_debug */
-$tracemasks->{MALLOC} = 1 << 4; # /* print malloc, free information */
-$tracemasks->{CACHE} = 1 << 5; # /* cache-related items */
-$tracemasks->{INFO} = 1 << 6; # /* general information */
-$tracemasks->{IOCTL} = 1 << 7; # /* ioctl related information */
-$tracemasks->{BLOCKS} = 1 << 8; # /* ext2 block allocation */
-$tracemasks->{NET} = 1 << 9; # /* network communications */
-$tracemasks->{WARNING} = 1 << 10; #
-$tracemasks->{BUFFS} = 1 << 11; #
-$tracemasks->{OTHER} = 1 << 12; #
-$tracemasks->{DENTRY} = 1 << 13; #
-$tracemasks->{PORTALS} = 1 << 14; # /* ENTRY/EXIT markers */
-$tracemasks->{PAGE} = 1 << 15; # /* bulk page handling */
-$tracemasks->{DLMTRACE} = 1 << 16; #
-$tracemasks->{ERROR} = 1 << 17; # /* CERROR} = ...) == CDEBUG} = D_ERROR, ...) */
-$tracemasks->{EMERG} = 1 << 18; # /* CEMERG} = ...) == CDEBUG} = D_EMERG, ...) */
-$tracemasks->{HA} = 1 << 19; # /* recovery and failover */
-$tracemasks->{RPCTRACE} = 1 << 19; # /* recovery and failover */
-
-# Contains all the file names, the first filename is the
-# client. After that are all servers.
-my @filearray = ();
-
-
-# Create backlinks between array entries based on the calling sequence
-# For each new PID encountered, the first entry will be present in the
-# PID hash.
-
-sub create_links {
- my $arrayref = shift @_;
- my $pidhashref = shift @_;
- my $stitchref = shift @_;
- my %local_hash;
- my $hash_lineref;
- my $tmpfmtref;
- my $tmpref;
- my $firstlineaftermarker = 0;
-
- foreach $lineref (@$arrayref) {
- next if ($lineref->[$e_time] == 0); # Skip the client marker line
- my $pidprevious = $pidhashref->{$lineref->[$e_pid]};
- if ($pidprevious->[$e_next] == 0) {
- $pidprevious->[$e_next] = $lineref;
- if (exists $local_hash{$lineref->[$e_pid]}
- && $firstlineaftermarker) {
- $hash_lineref=$local_hash{$lineref->[$e_pid]};
- $hash_lineref->[$e_next] =$lineref;
- $firstlineaftermarker = 0;
- }
- } elsif ($local_hash{$lineref->[$e_pid]} == 0) {
- # True only for the first line, the marker line.
- $local_hash{$lineref->[$e_pid]}=$lineref;
- #print "LINE ADDED TO HASH: @$lineref\n";
- $firstlineaftermarker = 1;
- }
- # Stack grows upward (assumes x86 kernel)
- if ($lineref->[$e_stack] < $pidprevious->[$e_stack]) {
- # lineref is not a child of pidprevious, find its parent
- LINE: while(($lineref->[$e_stack] < $pidprevious->[$e_stack]) &&
- ($lineref->[$e_function] == $pidprevious->[$e_function])
- ) {
- #This second part of the comparision is a HACK
- last LINE if ($pidprevious->[$e_backref] == 0);
- $pidprevious = $pidprevious->[$e_backref];
- }
- }
- if ($lineref->[$e_stack] > $pidprevious->[$e_stack]) {
- # lineref is child of pidprevious, with the caveat that they must
- # belong to different functions. This is a HACK
- # until CDEBUG is modified
- while($lineref->[$e_function] eq $pidprevious->[$e_function]) {
- last if ($pidprevious->[$e_backref] == 0);
- $pidprevious = $pidprevious->[$e_backref];
- }
-
- $lineref->[$e_backref] = $pidprevious;
- $pidprevious->[$e_numchildren]++;
- } else {
- # lineref is sibling of pidprevious
- $lineref->[$e_numchildren] = 0;
- $lineref->[$e_backref] = $pidprevious->[$e_backref];
- ($lineref->[$e_backref])->[$e_numchildren]++;
- }
-
- $pidhashref->{$lineref->[$e_pid]} = $lineref;
- $lineref->[$e_youngestchild] = $lineref;
- while ($pidprevious->[$e_backref] != 0) {
- $pidprevious->[$e_youngestchild] = $lineref;
- $pidprevious = $pidprevious->[$e_backref];
- }
- $pidprevious->[$e_youngestchild] = $lineref;
- $lineref->[$e_pidhead]=$pidprevious;
-
- # Stitch together rpc's
- if($lineref->[$e_fmtstr] =~ $RPCREGEX) {
- #print "RPC LINE: @$lineref\n";
- $tmpfmtref = [$1, $2, $3, $4, 0, 0, 0];
- if ($lineref->[$e_fmtstr] =~ $SENDING) {
- $tmpfmtref->[$e_rpcsndrcv] = $SEND;
- } else { $tmpfmtref->[$e_rpcsndrcv] = $RCV; }
- $tmpfmtref->[$e_curlineref] = $lineref;
- $stitchref->{$lineref->[$e_time]} = $tmpfmtref;
-
- }
-
- }
-match_rpcs($stitchref);
-return $arrayref;
-}
-
-
-
-
-# Main loop, parses the debug log
-
-sub parse_file {
- my %hasharray;
- my $input_files = shift;
-
- my $stitch_ref = shift;
- my $pid = shift;
- my $rpctrace = shift;
- my $trace = shift;
- my $nodlm = shift;
- my $noclass = shift;
- my $nonet = shift;
-
- print "$pid, $rpctrace, $nodlm, $noclass, $nonet\n";
- $backref = 0;
- $treeparent = 0;
- $numchildren = 0;
- $youngestchild = 0;
- $next = 0;
- $pidhead = 0;
- $iter = 0;
-
- foreach $file (@$input_files) {
-
- open(FILEHANDLE, $file) or die "Can't open file: $file\n";
- while(<FILEHANDLE>) {
- if (/$REGEX/) {
- @parsed_line=($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,
- $treeparent, $numchildren, $youngestchild,
- $pidhead, $next, $backref);
- next if (($parsed_line[$e_pid] != $pid) &&
- ($pid) && ($iter == 0));
- next if (($parsed_line[$e_mask] != $tracemasks->{RPCTRACE})
- && ($rpctrace));
- next if ($trace && $parsed_line[$e_mask] !=
- $tracemasks->{TRACE});
- next if ($nodlm && hex($parsed_line[$e_subsys]) ==
- $subsysnum->{LDLM});
- next if ($noclass && hex($parsed_line[$e_subsys]) ==
- $subsysnum->{CLASS});
- next if ($nonet && (hex($parsed_line[$e_subsys]) ==
- $subsysnum->{RPC} ||
- hex($parsed_line[$e_subsys]) ==
- $subsysnum->{NET} ||
- hex($parsed_line[$e_subsys]) ==
- $subsysnum->{PORTALS} ||
- hex($parsed_line[$e_subsys]) ==
- $subsysnum->{SOCKNAL} ||
- hex($parsed_line[$e_subsys]) ==
- $subsysnum->{QSWNAL} ||
- hex($parsed_line[$e_subsys]) ==
- $subsysnum->{GMNAL}));
-
-
- if (!exists($hasharray{$parsed_line[$e_pid]})) {
- # Push a marker for the beginning of this PID
- my @marker_line;
- $marker_line[$e_subsys] = 0;
- $marker_line[$e_mask] = 0;
- $marker_line[$e_processor] = 0;
- $marker_line[$e_time] = $parsed_line[$e_time];
- $marker_line[$e_file] = 0;
- $marker_line[$e_line] = 0;
- $marker_line[$e_function] = 0;
- $marker_line[$e_pid] = $parsed_line[$e_pid];
- # marker lines are everyone's parent, so stack value zero
- $marker_line[$e_stack] = 0;
- $marker_line[$e_fmtstr] = "";
- $marker_line[$e_treeparent] = 0;
- $marker_line[$e_numchildren] = 0;
- $marker_line[$e_youngestchild] = 0;
- $marker_line[$e_pidhead] = 0;
- $marker_line[$e_next]= \@parsed_line;
- $marker_line[$e_backref] = 0;
- $hasharray{$parsed_line[$e_pid]} = \@marker_line;
- push @$array_parsed, [ @marker_line ];
-
- }
- push @$array_parsed, [ @parsed_line ];
- }
-
- }
- close(FILEHANDLE);
- if ($iter == 0) {
- # Insert end of client line marker, an all zero pattern;
- @marker_line = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- push @$array_parsed, [ @marker_line ];
-
- }
- $iter ++;
- }
-
- $array_parsed=create_links($array_parsed, \%hasharray, $stitch_ref);
- #print_array($array_parsed);
- return $array_parsed;
-}
-
-sub print_array {
-
- my $arrayref = shift;
- foreach $lineref(@$arrayref){
- if ($lineref->[$e_backref]==0){
- print "MARKER LINE(addr): $lineref contents: [@$lineref]\n";
- } else {
-
- print "REGULAR LINE (addr) :$lineref contents:[@$lineref]\n";
- }
- }
-
-}
-
-sub print_rpcrelations {
-
- my $rpchashref = shift;
- foreach $rpckeys (sort keys %$rpchashref) {
- $tmpref = $rpchashref->{$rpckeys};
- #print "Key: $rpckeys, Contents: @$tmpref\n";
-
- }
-
-}
-sub match_rpcs {
- my $rpchashref = shift;
- foreach $rpckeys (sort keys %$rpchashref) {
- $tmpref = $rpchashref->{$rpckeys};
- #print "MATCHING: $@tmpref...\n";
- foreach $cmpkeys (sort keys %$rpchashref) {
- next if($cmpkeys == $rpckeys);
- $cmpref = $rpchashref->{$cmpkeys};
- # print "Line compared: @$cmpref\n";
- next if ($tmpref->[$e_rpcsndrcv] == $cmpref->[$e_rpcsndrcv]);
- next if ($tmpref->[$e_rpcpid] != $cmpref->[$e_rpcpid]);
- next if ($tmpref->[$e_rpcxid] != $cmpref->[$e_rpcxid]);
- if ($tmpref->[$e_rpcsndrcv] == $SEND) {
- $tmpref->[$e_rpcnext] = $cmpkeys;
- #print "MACTHED: KEY 1: $rpckeys CONTENTS: @$tmpref",
- #"KEY2: $cmpkeys CONTENTS: @$cmpref\n"
-
- }
-
- }
-
- }
-
-}
-
-sub getnextchild {
- my $rootline = shift;
- my $lineref = shift;
- my $tempref = $lineref->[$e_next];
- if ($tempref == 0) {
- return 0;
- }
-
- if (($tempref->[$e_stack] > $rootline->[$e_stack]) ||
- (($tempref->[$e_stack] <= $rootline->[$e_stack]) &&
- ($tempref->[$e_function] == $rootline->[$e_function])
- )){
- # Child
- return $tempref;
-
- }
- return 0;
-
-
-}
-
-
-sub parse_foptions {
-
- my $inarg = shift;
- my $idx = 0;
- foreach $elem(@$inarg) {
- next if ($elem =~ /$FILEOPTIONREGEX/);
- $filearray[$idx] = $elem;
- $idx++;
- }
- return \@filearray;
-}
-
-1;
-#$array_parsed=parse_file();
-#print_array($array_parsed);
+++ /dev/null
-#!/bin/bash
-#
-# Load a lustre config xml into an openldap database.
-# See https://projects.clusterfs.com/lustre/LustreLDAP
-# for more details.
-#
-# Usage: load_ldap.sh <xml_file>
-set -e
-
-LDAP_BASE=${LDAP_BASE:-fs=lustre}
-LDAP_ROOTDN=${LDAP_ROOTDN:-cn=Manager,fs=lustre}
-LDAP_PW=${LDAP_PW:-secret}
-LDAP_AUTH="-x -D $LDAP_ROOTDN -w $LDAP_PW"
-LUSTRE=${LUSTRE:-`dirname $0`/..}
-
-[ ! -z $LDAPURL ] && LDAP_AUTH="$LDAP_AUTH -H $LDAPURL"
-
-XML=${XML:-$1}
-
-if [ -z "$XML" ] || [ ! -r $XML ]; then
- echo "usage: $0 xmlfile"
- exit 1
-fi
-
-NAME=`basename $XML .xml`
-LDIF=/tmp/$NAME.ldif
-
-# add the top level record, if needed
-ldapsearch $LDAP_AUTH -b $LDAP_BASE > /dev/null 2>&1 ||
- ldapadd $LDAP_AUTH -f $LUSTRE/conf/top.ldif
-
-# If this config already exists, then delete it
-ldapsearch $LDAP_AUTH -b config=$NAME,$LDAP_BASE > /dev/null 2>&1 &&
- ldapdelete $LDAP_AUTH -r config=$NAME,$LDAP_BASE
-
-4xslt -D config=$NAME $XML $LUSTRE/conf/lustre2ldif.xsl > $LDIF
-
-echo "Loading config to 'config=$NAME,$LDAP_BASE' ..."
-ldapadd $LDAP_AUTH -f $LDIF
-
-rm -f $LDIF
+++ /dev/null
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-
-/****************** Custom includes ********************/
-#include <linux/lustre_lite.h>
-#include <linux/lustre_idl.h>
-
-
-/****************** Functions ******************/
-
-void usage(char *pgm)
-{
- fprintf(stderr, "\nIncorrect parameters! Correct usage:\n\n" );
- fprintf(stderr, "%s <output filename> <stripe size> <OST #> <stripe #>\n", pgm);
-
- fprintf(stderr, "\n\nArgument explanations:\n---------------------\n\n");
- fprintf(stderr, "<output filename> = the full name and path of the output file to create\n");
- fprintf(stderr, "<stripe size> = the number of bytes to have in each stripe.\n");
- fprintf(stderr, "<OST #> = the OST number to start the striping on.\n");
- fprintf(stderr, "<stripe #> = the number of stripes to use.\n");
-
- fprintf(stderr, "\n\nExamples:\n---------\n\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost1 131072 0 1\n", pgm);
- fprintf(stderr, "\t\tcreates a file only on ost1.\n\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost2 131072 1 1\n", pgm);
- fprintf(stderr, "\t\tcreates a file only on ost2.\n\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost1and2 131072 0 2\n", pgm);
- fprintf(stderr, "\t\tcreates a 128k file with 2 stripes, on ost1 and ost2.\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost1and2 131072 1 2\n", pgm);
- fprintf(stderr, "\t\tcreates a 128k file with 2 stripes, on ost2 and ost1.\n");
-}
-
-int create_file(char *name, long stripe_size, int stripe_offset,
- int stripe_count)
-{
- struct lov_mds_md a_striping;
- int fd, result = 0;
-
- /* Initialize IOCTL striping pattern structure */
- a_striping.lmm_magic = LOV_MAGIC;
- a_striping.lmm_stripe_pattern = 0;
- a_striping.lmm_stripe_size = stripe_size;
- a_striping.lmm_stripe_offset = stripe_offset;
- a_striping.lmm_stripe_count = stripe_count;
-
- fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
- if (fd < 0) {
- fprintf(stderr, "\nUnable to open '%s': %s\n",
- name, strerror(errno));
- result = -errno;
- } else if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &a_striping)) {
- fprintf(stderr, "\nError on ioctl for '%s' (%d): %s\n",
- name, fd, strerror(errno));
- result = -errno;
- } else if (close(fd) < 0) {
- fprintf(stderr, "\nError on close for '%s' (%d): %s\n",
- name, fd, strerror(errno));
- result = -errno;
- }
-
- return result;
-}
-
-int main(int argc, char *argv[])
-{
- int result;
- long st_size;
- int st_offset,
- st_count;
-
- /* Check to make sure we have enough parameters */
- if (argc != 5) {
- usage(argv[0]);
- return(-1);
- }
-
- /* Get the stripe size */
- st_size = atol(argv[2]);
-
- /* Get the stripe offset*/
- st_offset = atoi(argv[3]);
-
- /* Get the stripe count */
- st_count = atoi(argv[4]);
-
- /* Create the file, as specified. Return and display any errors. */
- result = create_file(argv[1], st_size, st_offset, st_count);
-
- return result;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Eric Barton <eeb@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <signal.h>
-
-#include <linux/lustre_lib.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_dlm.h>
-#include <linux/obd_lov.h> /* for IOC_LOV_SET_OSC_ACTIVE */
-#include <linux/obd.h> /* for struct lov_stripe_md */
-#include <linux/obd_class.h>
-#include <linux/lustre_build_version.h>
-
-#include <unistd.h>
-#include <sys/un.h>
-#include <time.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <errno.h>
-#include <string.h>
-
-#include <asm/page.h> /* needed for PAGE_SIZE - rread */
-
-#define __KERNEL__
-#include <linux/list.h>
-#undef __KERNEL__
-
-#include "obdctl.h"
-
-struct obdio_conn {
- int oc_fd;
- uint64_t oc_conn_addr;
- uint64_t oc_conn_cookie;
- struct obd_ioctl_data oc_data;
- char oc_buffer[8192];
-};
-
-char *
-obdio_alloc_aligned_buffer (char **spacep, int size)
-{
- int pagesize = getpagesize();
- char *space = malloc (size + pagesize - 1);
-
- *spacep = space;
- if (space == NULL)
- return (NULL);
-
- return ((char *)(((unsigned long)space + pagesize - 1) & ~(pagesize - 1)));
-}
-
-void
-obdio_iocinit (struct obdio_conn *conn)
-{
- memset (&conn->oc_data, 0, sizeof (conn->oc_data));
- conn->oc_data.ioc_version = OBD_IOCTL_VERSION;
- conn->oc_data.ioc_addr = conn->oc_conn_addr;
- conn->oc_data.ioc_cookie = conn->oc_conn_cookie;
- conn->oc_data.ioc_len = sizeof (conn->oc_data);
-}
-
-int
-obdio_ioctl (struct obdio_conn *conn, int cmd)
-{
- char *buf = conn->oc_buffer;
- int rc;
- int rc2;
-
- rc = obd_ioctl_pack (&conn->oc_data, &buf, sizeof (conn->oc_buffer));
- if (rc != 0) {
- fprintf (stderr, "obd_ioctl_pack: %d (%s)\n",
- rc, strerror (errno));
- abort ();
- }
-
- rc = ioctl (conn->oc_fd, cmd, buf);
- if (rc != 0)
- return (rc);
-
- rc2 = obd_ioctl_unpack (&conn->oc_data, buf, sizeof (conn->oc_buffer));
- if (rc2 != 0) {
- fprintf (stderr, "obd_ioctl_unpack: %d (%s)\n",
- rc2, strerror (errno));
- abort ();
- }
-
- return (rc);
-}
-
-struct obdio_conn *
-obdio_connect (int device)
-{
- struct obdio_conn *conn;
- int rc;
-
- conn = malloc (sizeof (*conn));
- if (conn == NULL) {
- fprintf (stderr, "obdio_connect: no memory\n");
- return (NULL);
- }
- memset (conn, 0, sizeof (*conn));
-
- conn->oc_fd = open ("/dev/obd", O_RDWR);
- if (conn->oc_fd < 0) {
- fprintf (stderr, "Can't open /dev/obd: %s\n",
- strerror (errno));
- goto failed;
- }
-
- obdio_iocinit (conn);
- conn->oc_data.ioc_dev = device;
- rc = obdio_ioctl (conn, OBD_IOC_DEVICE);
- if (rc != 0) {
- fprintf (stderr, "Can't set device %d: %s\n",
- device, strerror (errno));
- goto failed;
- }
-
- obdio_iocinit (conn);
- rc = obdio_ioctl (conn, OBD_IOC_CONNECT);
- if (rc != 0) {
- fprintf (stderr, "Can't connect to device %d: %s\n",
- device, strerror (errno));
- goto failed;
- }
-
- conn->oc_conn_addr = conn->oc_data.ioc_addr;
- conn->oc_conn_cookie = conn->oc_data.ioc_cookie;
- return (conn);
-
- failed:
- free (conn);
- return (NULL);
-}
-
-void
-obdio_disconnect (struct obdio_conn *conn)
-{
- close (conn->oc_fd);
- /* obdclass will automatically close on last ref */
- free (conn);
-}
-
-int
-obdio_open (struct obdio_conn *conn, uint64_t oid, struct lustre_handle *fh)
-{
- int rc;
-
- obdio_iocinit (conn);
-
- conn->oc_data.ioc_obdo1.o_id = oid;
- conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
- conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
-
- rc = obdio_ioctl (conn, OBD_IOC_OPEN);
-
- if (rc == 0)
- obd_oa2handle (fh, &conn->oc_data.ioc_obdo1);
-
- return (rc);
-}
-
-int
-obdio_close (struct obdio_conn *conn, uint64_t oid, struct lustre_handle *fh)
-{
- obdio_iocinit (conn);
-
-
- conn->oc_data.ioc_obdo1.o_id = oid;
- conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
- obd_handle2oa (&conn->oc_data.ioc_obdo1, fh);
- conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE |
- OBD_MD_FLMODE | OBD_MD_FLHANDLE;
-
- return (obdio_ioctl (conn, OBD_IOC_CLOSE));
-}
-
-int
-obdio_pread (struct obdio_conn *conn, uint64_t oid,
- char *buffer, uint32_t count, uint64_t offset)
-{
- obdio_iocinit (conn);
-
- conn->oc_data.ioc_obdo1.o_id = oid;
- conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
- conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
-
- conn->oc_data.ioc_pbuf2 = buffer;
- conn->oc_data.ioc_plen2 = count;
- conn->oc_data.ioc_count = count;
- conn->oc_data.ioc_offset = offset;
-
- return (obdio_ioctl (conn, OBD_IOC_BRW_READ));
-}
-
-int
-obdio_pwrite (struct obdio_conn *conn, uint64_t oid,
- char *buffer, uint32_t count, uint64_t offset)
-{
- obdio_iocinit (conn);
-
- conn->oc_data.ioc_obdo1.o_id = oid;
- conn->oc_data.ioc_obdo1.o_mode = S_IFREG;
- conn->oc_data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
-
- conn->oc_data.ioc_pbuf2 = buffer;
- conn->oc_data.ioc_plen2 = count;
- conn->oc_data.ioc_count = count;
- conn->oc_data.ioc_offset = offset;
-
- return (obdio_ioctl (conn, OBD_IOC_BRW_WRITE));
-}
-
-void
-obdio_test_extent (struct obdio_conn *conn, uint32_t myid, int reps,
- uint64_t oid, uint64_t offset, uint32_t size)
-{
- char *space;
- char *buffer = obdio_alloc_aligned_buffer (&space, size);
- uint32_t *ibuf;
- int i;
- int j;
- int rc;
-
- if (buffer == NULL) {
- fprintf (stderr, "Can't allocate buffer size %d\n", size);
- abort ();
- }
-
- for (i = 0; i < reps; i++) {
- ibuf = (uint32_t *) buffer;
- for (j = 0; j < size / (4 * sizeof (*ibuf)); j++) {
- ibuf[0] = myid;
- ibuf[1] = i;
- ibuf[2] = j;
- ibuf[3] = myid;
- ibuf += 4;
- }
-
- rc = obdio_pwrite (conn, oid, buffer, size, offset);
- if (rc != 0) {
- fprintf (stderr, "Error writing "LPX64" @ "LPU64" for %u: %s\n",
- oid, offset, size, strerror (errno));
- abort ();
- }
-
- memset (buffer, 0xbb, size);
-
- rc = obdio_pread (conn, oid, buffer, size, offset);
- if (rc != 0) {
- fprintf (stderr, "Error reading "LPX64" @ "LPU64" for %u: %s\n",
- oid, offset, size, strerror (errno));
- abort ();
- }
-
- ibuf = (uint32_t *) buffer;
- for (j = 0; j < size / (4 * sizeof (*ibuf)); j++) {
- if (ibuf[0] != myid ||
- ibuf[1] != i ||
- ibuf[2] != j ||
- ibuf[3] != myid) {
- fprintf (stderr, "Error checking "LPX64" @ "LPU64" for %u, chunk %d: %s\n",
- oid, offset, size, j, strerror (errno));
- fprintf (stderr, "Expected [%x,%x,%x,%x], got [%x,%x,%x,%x]\n",
- myid, i, j, myid, ibuf[0], ibuf[1], ibuf[2], ibuf[3]);
- abort ();
- }
- ibuf += 4;
- }
- }
-}
-
-int
-parse_kmg (uint64_t *valp, char *str)
-{
- uint64_t val;
- char mod[32];
-
- switch (sscanf (str, LPU64"%1[gGmMkK]", &val, mod))
- {
- default:
- return (-1);
-
- case 1:
- *valp = val;
- return (0);
-
- case 2:
- switch (*mod)
- {
- case 'g':
- case 'G':
- *valp = val << 30;
- return (0);
-
- case 'm':
- case 'M':
- *valp = val << 20;
- return (0);
-
- case 'k':
- case 'K':
- *valp = val << 10;
- return (0);
-
- default:
- *valp = val;
- return (0);
- }
- }
-}
-
-void
-usage (char *cmdname, int help)
-{
- char *name = strrchr (cmdname, '/');
-
- if (name == NULL)
- name = cmdname;
-
- fprintf (help ? stdout : stderr,
- "usage: %s -d device -s size -o offset [-i id][-n reps] oid\n",
- name);
-}
-
-int
-main (int argc, char **argv)
-{
- struct lustre_handle fh;
- uint32_t myid = getpid ();
- uint64_t oid;
- uint64_t base_offset = 0;
- int set_base = 0;
- uint32_t size = 0;
- int set_size = 0;
- int device = 0;
- int set_device = 0;
- int reps = 1;
- char *end;
- struct obdio_conn *conn;
- uint64_t val;
- int rc;
- int c;
-
- while ((c = getopt (argc, argv, "hi:s:b:d:n:")) != -1)
- switch (c) {
- case 'h':
- usage (argv[0], 1);
- return (0);
-
- case 'i':
- myid = strtol (optarg, &end, 0);
- if (end == optarg || *end != 0) {
- fprintf (stderr, "Can't parse id %s\n",
- optarg);
- return (1);
- }
- myid = (uint32_t)val;
- break;
-
- case 's':
- if (parse_kmg (&val, optarg) != 0) {
- fprintf (stderr, "Can't parse size %s\n",
- optarg);
- return (1);
- }
- size = (uint32_t)val;
- set_size++;
- break;
-
- case 'b':
- if (parse_kmg (&val, optarg) != 0) {
- fprintf (stderr, "Can't parse base offset %s\n",
- optarg);
- return (1);
- }
- base_offset = val;
- set_base++;
- break;
-
- case 'd':
- device = strtol (optarg, &end, 0);
- if (end == optarg || *end != 0) {
- fprintf (stderr, "Can't parse device %s\n",
- optarg);
- return (1);
- }
- set_device++;
- break;
- case 'n':
- if (parse_kmg (&val, optarg) != 0) {
- fprintf (stderr, "Can't parse reps %s\n",
- optarg);
- return (1);
- }
- reps = (int)val;
- break;
-
- default:
- usage (argv[0], 0);
- return (1);
- }
-
- if (!set_size ||
- !set_base ||
- !set_device ||
- optind == argc) {
- fprintf (stderr, "No %s specified\n",
- !set_size ? "size" :
- !set_base ? "base offset" :
- !set_device ? "device" : "object id");
- return (1);
- }
-
- oid = strtoull (argv[optind], &end, 0);
- if (end == argv[optind] || *end != 0) {
- fprintf (stderr, "Can't parse object id %s\n",
- argv[optind]);
- return (1);
- }
-
- conn = obdio_connect (device);
- if (conn == NULL)
- return (1);
-
- rc = obdio_open (conn, oid, &fh);
- if (rc != 0) {
- fprintf (stderr, "Failed to open object "LPX64": %s\n",
- oid, strerror (errno));
- return (1);
- }
-
- obdio_test_extent (conn, myid, reps, oid, base_offset, size);
-
- rc = obdio_close (conn, oid, &fh);
- if (rc != 0) {
- fprintf (stderr, "Error closing object "LPX64": %s\n",
- oid, strerror (errno));
- return (1);
- }
-
- obdio_disconnect (conn);
- return (0);
-}
-
-
+++ /dev/null
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/time.h>
-
-struct one_stat {
- char *name;
- int fd;
- long long current;
- long long delta;
-};
-
-struct one_stat *read_bytes;
-struct one_stat *read_reqs;
-struct one_stat *write_bytes;
-struct one_stat *write_reqs;
-struct one_stat *getattr_reqs;
-struct one_stat *setattr_reqs;
-struct one_stat *create_reqs;
-struct one_stat *destroy_reqs;
-struct one_stat *statfs_reqs;
-struct one_stat *open_reqs;
-struct one_stat *close_reqs;
-struct one_stat *punch_reqs;
-
-struct one_stat *
-init_one_stat (char *basename, char *name)
-{
- char fname[1024];
- struct one_stat *stat = (struct one_stat *)malloc (sizeof (*stat));
-
- if (stat == NULL) {
- fprintf (stderr, "Can't allocate stat %s: %s\n",
- name, strerror (errno));
- abort ();
- }
-
- snprintf (fname, sizeof (fname), "%s/%s", basename, name);
-
- memset (stat, 0, sizeof (*stat));
- stat->name = name;
-
- stat->fd = open (fname, O_RDONLY);
- if (stat->fd < 0 ) {
- fprintf (stderr, "Can't open stat %s: %s\n",
- fname, strerror (errno));
- abort ();
- }
-
- return (stat);
-}
-
-void
-update_one_stat (struct one_stat *stat)
-{
- static char buffer[1024];
- long long prev = stat->current;
- int nob;
-
- lseek (stat->fd, 0, SEEK_SET);
- nob = read (stat->fd, buffer, sizeof (buffer) - 1);
- if (nob < 0) {
- fprintf (stderr, "Can't read stat %s: %s\n",
- stat->name, strerror (errno));
- abort ();
- }
-
- buffer[nob] = 0;
- if (sscanf (buffer, "%Ld", &stat->current) != 1) {
- fprintf (stderr, "Can't parse stat %s: %s\n",
- stat->name, strerror (errno));
- abort ();
- }
-
- stat->delta = stat->current - prev;
-}
-
-double
-timenow ()
-{
- struct timeval tv;
-
- gettimeofday (&tv, NULL);
- return (tv.tv_sec + tv.tv_usec / 1000000.0);
-}
-
-void
-do_stat (void)
-{
- static double last = 0.0;
- double now;
- double t;
-
- now = timenow();
-
- update_one_stat (read_bytes);
- update_one_stat (read_reqs);
- update_one_stat (write_bytes);
- update_one_stat (write_reqs);
- update_one_stat (getattr_reqs);
- update_one_stat (setattr_reqs);
- update_one_stat (open_reqs);
- update_one_stat (close_reqs);
- update_one_stat (create_reqs);
- update_one_stat (destroy_reqs);
- update_one_stat (statfs_reqs);
- update_one_stat (punch_reqs);
-
- if (last == 0.0) {
- printf ("R %Ld/%Ld W %Ld/%Ld attr %Ld/%Ld open %Ld/%Ld create %Ld/%Ld stat %Ld punch %Ld\n",
- read_bytes->current, read_reqs->current,
- write_bytes->current, write_reqs->current,
- getattr_reqs->current, setattr_reqs->current,
- open_reqs->current, close_reqs->current,
- create_reqs->current, destroy_reqs->current,
- statfs_reqs->current, punch_reqs->current);
- } else {
- t = now - last;
-
- printf ("R %7Ld (%6d/s %7.2fMb/s) W %7Ld (%6d/s %7.2fMb/s)",
- read_reqs->delta, (int)(read_reqs->delta / t),
- read_bytes->delta / ((1<<20) * t),
- write_reqs->delta, (int)(write_reqs->delta / t),
- write_bytes->delta / ((1<<20) * t));
-
- if (getattr_reqs->delta != 0)
- printf (" ga:%Ld", getattr_reqs->delta);
-
- if (setattr_reqs->delta != 0)
- printf (" sa:%Ld", setattr_reqs->delta);
-
- if (open_reqs->delta != 0)
- printf (" op:%Ld", open_reqs->delta);
-
- if (close_reqs->delta != 0)
- printf (" cl:%Ld", close_reqs->delta);
-
- if (create_reqs->delta != 0)
- printf (" cx:%Ld", create_reqs->delta);
-
- if (destroy_reqs->delta != 0)
- printf (" dx:%Ld", destroy_reqs->delta);
-
- if (statfs_reqs->delta != 0)
- printf (" st:%Ld", statfs_reqs->delta);
-
- if (punch_reqs->delta != 0)
- printf (" pu:%Ld", punch_reqs->delta);
-
- printf ("\n");
- }
-
- last = timenow();
-}
-
-int main (int argc, char **argv)
-{
- char *basedir = "/proc/sys/obdfilter";
- int interval = 0;
-
- if (argc > 1)
- interval = atoi (argv[1]);
-
- read_bytes = init_one_stat (basedir, "read_bytes");
- read_reqs = init_one_stat (basedir, "read_reqs");
- write_bytes = init_one_stat (basedir, "write_bytes");
- write_reqs = init_one_stat (basedir, "write_reqs");
- getattr_reqs = init_one_stat (basedir, "getattr_reqs");
- setattr_reqs = init_one_stat (basedir, "setattr_reqs");
- create_reqs = init_one_stat (basedir, "create_reqs");
- destroy_reqs = init_one_stat (basedir, "destroy_reqs");
- statfs_reqs = init_one_stat (basedir, "statfs_reqs");
- open_reqs = init_one_stat (basedir, "open_reqs");
- close_reqs = init_one_stat (basedir, "close_reqs");
- punch_reqs = init_one_stat (basedir, "punch_reqs");
-
- do_stat ();
-
- if (interval == 0)
- return (0);
-
- for (;;) {
- sleep (interval);
- do_stat ();
- }
-}