Index: linux-2.6.7/fs/ext3/extents-in-ea.c =================================================================== --- linux-2.6.7.orig/fs/ext3/extents-in-ea.c 2004-08-12 13:42:23.000000000 +0800 +++ linux-2.6.7/fs/ext3/extents-in-ea.c 2004-08-12 14:25:29.000000000 +0800 @@ -27,7 +27,7 @@ #include #include #include -#include +#include "xattr.h" #include #include @@ -111,7 +111,7 @@ err = ext3_extent_tree_init(handle, &tree); ext3_release_tree_in_ea_desc(&tree); out: - ext3_journal_stop(handle, inode); + ext3_journal_stop(handle); kfree(root); return err; } @@ -134,24 +134,24 @@ up_write(&EXT3_I(inode)->truncate_sem); handle = ext3_journal_start(tree->inode, needed + 10); if (IS_ERR(handle)) { - down_write(&EXT3_I(inode)->truncate_sem); + down(&EXT3_I(inode)->truncate_sem); return PTR_ERR(handle); } if (tgen != EXT_GENERATION(tree)) { /* the tree has changed. so path can be invalid at moment */ - ext3_journal_stop(handle, inode); - down_write(&EXT3_I(inode)->truncate_sem); + ext3_journal_stop(handle); + down(&EXT3_I(inode)->truncate_sem); return EXT_REPEAT; } - down_write(&EXT3_I(inode)->truncate_sem); + down(&EXT3_I(inode)->truncate_sem); /* insert new extent */ newex->ee_start = 0; err = ext3_ext_insert_extent(handle, tree, path, newex); if (!err) - ext3_journal_stop(handle, tree->inode); + ext3_journal_stop(handle); return err; } @@ -165,11 +165,11 @@ err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname); if (err == 0) { - down_write(&EXT3_I(inode)->truncate_sem); + down(&EXT3_I(inode)->truncate_sem); err = ext3_ext_walk_space(&tree, from, num, ext3_ext_in_ea_new_extent); ext3_release_tree_in_ea_desc(&tree); - up_write(&EXT3_I(inode)->truncate_sem); + up(&EXT3_I(inode)->truncate_sem); } return err; } @@ -222,3 +222,112 @@ return err; } +static int +ext3_ext_store_extent_cb(struct ext3_extents_tree *tree, + struct ext3_ext_path *path, + struct ext3_extent *newex, int exist) +{ + struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private; + + if (!exist) + return EXT_CONTINUE; + if (buf->err < 0) + return EXT_BREAK; + if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen) + return EXT_BREAK; + + if (!copy_to_user(buf->cur, newex, sizeof(*newex))) { + buf->err++; + buf->cur += sizeof(*newex); + } else { + buf->err = -EFAULT; + return EXT_BREAK; + } + return EXT_CONTINUE; +} + +static int +ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree, + struct ext3_ext_path *path, + struct ext3_extent *ex, int exist) +{ + struct ext3_extent_tree_stats *buf = + (struct ext3_extent_tree_stats *) tree->private; + int depth; + + if (!exist) + return EXT_CONTINUE; + + depth = EXT_DEPTH(tree); + buf->extents_num++; + if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr)) + buf->leaf_num++; + return EXT_CONTINUE; +} + +struct ea_tree_desc { + int name_index; + char eaname[256]; +}; + +int ext3_ext_in_ea_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int err = 0; + + if (cmd == EXT3_IOC_EA_TREE_INIT) { + struct ea_tree_desc desc; + + if (copy_from_user(&desc, (void *) arg, sizeof(desc))) + return -EFAULT; + err = ext3_init_tree_in_ea(inode, desc.name_index, + desc.eaname, 64); + } else if (cmd == EXT3_IOC_GET_EA_EXTENTS) { + struct ext3_extents_tree tree; + struct ext3_extent_buf buf; + struct ea_tree_desc desc; + + if (copy_from_user(&buf, (void *) arg, sizeof(buf))) + return -EFAULT; + if (copy_from_user(&desc, buf.cur, sizeof(desc))) + return -EFAULT; + err = ext3_init_tree_in_ea_desc(&tree, inode, + desc.name_index, desc.eaname); + if (err) + goto out; + buf.cur = buf.buffer; + buf.err = 0; + tree.private = &buf; + err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK, + ext3_ext_store_extent_cb); + if (err == 0) + err = buf.err; + ext3_release_tree_in_ea_desc(&tree); + } else if (cmd == EXT3_IOC_EA_TREE_ALLOCATE) { + struct ext3_extent_buf buf; + struct ea_tree_desc desc; + + if (copy_from_user(&buf, (void *) arg, sizeof(buf))) + return -EFAULT; + if (copy_from_user(&desc, buf.cur, sizeof(desc))) + return -EFAULT; + err = ext3_ext_in_ea_alloc_space(inode, desc.name_index, + desc.eaname, buf.start, + buf.err); + } else if (cmd == EXT3_IOC_EA_TREE_REMOVE) { + struct ext3_extent_buf buf; + struct ea_tree_desc desc; + + if (copy_from_user(&buf, (void *) arg, sizeof(buf))) + return -EFAULT; + if (copy_from_user(&desc, buf.cur, sizeof(desc))) + return -EFAULT; + err = ext3_ext_in_ea_remove_space(inode, desc.name_index, + desc.eaname, buf.start, + buf.err); + } + +out: + return err; +} + Index: linux-2.6.7/fs/ext3/ioctl.c =================================================================== --- linux-2.6.7.orig/fs/ext3/ioctl.c 2004-08-12 13:42:21.000000000 +0800 +++ linux-2.6.7/fs/ext3/ioctl.c 2004-08-12 13:43:19.000000000 +0800 @@ -155,6 +155,13 @@ case EXT3_IOC_GET_TREE_STATS: case EXT3_IOC_GET_TREE_DEPTH: return ext3_ext_ioctl(inode, filp, cmd, arg); + case EXT3_IOC_GET_EA_EXTENTS: + case EXT3_IOC_GET_EA_TREE_DEPTH: + case EXT3_IOC_GET_EA_TREE_STATS: + case EXT3_IOC_EA_TREE_INIT: + case EXT3_IOC_EA_TREE_ALLOCATE: + case EXT3_IOC_EA_TREE_REMOVE: + return ext3_ext_in_ea_ioctl(inode, filp, cmd, arg); default: return -ENOTTY; } Index: linux-2.6.7/include/linux/ext3_fs.h =================================================================== --- linux-2.6.7.orig/include/linux/ext3_fs.h 2004-08-12 13:42:21.000000000 +0800 +++ linux-2.6.7/include/linux/ext3_fs.h 2004-08-12 13:43:19.000000000 +0800 @@ -213,6 +213,14 @@ #define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long) #define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long) +#define EXT3_IOC_GET_EA_EXTENTS _IOR('f', 10, long) +#define EXT3_IOC_GET_EA_TREE_DEPTH _IOR('f', 11, long) +#define EXT3_IOC_GET_EA_TREE_STATS _IOR('f', 12, long) +#define EXT3_IOC_EA_TREE_INIT _IOW('f', 13, long) +#define EXT3_IOC_EA_TREE_ALLOCATE _IOW('f', 14, long) +#define EXT3_IOC_EA_TREE_REMOVE _IOW('f', 15, long) + + /* * Structure of an inode on the disk */ @@ -746,7 +754,10 @@ /* ioctl.c */ extern int ext3_ioctl (struct inode *, struct file *, unsigned int, unsigned long); - +extern int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg); +extern int ext3_ext_in_ea_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); /* namei.c */ extern int ext3_orphan_add(handle_t *, struct inode *); extern int ext3_orphan_del(handle_t *, struct inode *);