+++ /dev/null
- fs/ext3/ialloc.c | 6
- fs/ext3/inode.c | 12
- fs/ext3/super.c | 6
- fs/ext3/xattr.c | 597 +++++++++++++++++++++++++++++++++++++++++++++-
- include/linux/ext3_fs.h | 2
- include/linux/ext3_fs_i.h | 3
- 6 files changed, 615 insertions(+), 11 deletions(-)
-
---- linux-2.4.20/fs/ext3/ialloc.c~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:08.000000000 +0400
-+++ linux-2.4.20-alexey/fs/ext3/ialloc.c 2003-10-12 16:25:21.000000000 +0400
-@@ -577,6 +577,12 @@ repeat:
- insert_inode_hash(inode);
- inode->i_generation = sb->u.ext3_sb.s_next_generation++;
-
-+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+ inode->u.ext3_i.i_extra_isize = sizeof(__u16) /* i_extra_isize */
-+ + sizeof(__u16); /* i_pad1 */
-+ } else
-+ inode->u.ext3_i.i_extra_isize = 0;
-+
- inode->u.ext3_i.i_state = EXT3_STATE_NEW;
- err = ext3_get_inode_loc_new(inode, &iloc, 1);
- if (err) goto fail;
---- linux-2.4.20/fs/ext3/inode.c~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:08.000000000 +0400
-+++ linux-2.4.20-alexey/fs/ext3/inode.c 2003-10-12 16:25:21.000000000 +0400
-@@ -2209,6 +2209,12 @@ void ext3_read_inode(struct inode * inod
- inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-
-+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
-+ inode->u.ext3_i.i_extra_isize =
-+ le16_to_cpu(raw_inode->i_extra_isize);
-+ else
-+ inode->u.ext3_i.i_extra_isize = 0;
-+
- brelse (iloc.bh);
-
- if (S_ISREG(inode->i_mode)) {
-@@ -2274,6 +2280,8 @@ static int ext3_do_update_inode(handle_t
- if (err)
- goto out_brelse;
- }
-+ if (EXT3_I(inode)->i_state & EXT3_STATE_NEW)
-+ memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb));
- raw_inode->i_mode = cpu_to_le16(inode->i_mode);
- if(!(test_opt(inode->i_sb, NO_UID32))) {
- raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
-@@ -2357,6 +2365,10 @@ static int ext3_do_update_inode(handle_t
- else for (block = 0; block < EXT3_N_BLOCKS; block++)
- raw_inode->i_block[block] = inode->u.ext3_i.i_data[block];
-
-+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
-+ raw_inode->i_extra_isize =
-+ cpu_to_le16(EXT3_I(inode)->i_extra_isize);
-+
- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
- rc = ext3_journal_dirty_metadata(handle, bh);
- if (!err)
---- linux-2.4.20/fs/ext3/xattr.c~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:06.000000000 +0400
-+++ linux-2.4.20-alexey/fs/ext3/xattr.c 2003-10-12 16:26:31.000000000 +0400
-@@ -100,6 +100,9 @@
- static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
- struct ext3_xattr_header *);
-
-+int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,
-+ const void *, size_t, int);
-+
- #ifdef CONFIG_EXT3_FS_XATTR_SHARING
-
- static int ext3_xattr_cache_insert(struct buffer_head *);
-@@ -348,17 +351,12 @@ ext3_removexattr(struct dentry *dentry,
- }
-
- /*
-- * ext3_xattr_get()
-- *
-- * Copy an extended attribute into the buffer
-- * provided, or compute the buffer size required.
-- * Buffer is NULL to compute the size of the buffer required.
-+ * ext3_xattr_block_get()
- *
-- * Returns a negative error number on failure, or the number of bytes
-- * used / required on success.
-+ * routine looks for attribute in EA block and returns it's value and size
- */
- int
--ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
- void *buffer, size_t buffer_size)
- {
- struct buffer_head *bh = NULL;
-@@ -447,6 +445,94 @@ cleanup:
- }
-
- /*
-+ * ext3_xattr_ibode_get()
-+ *
-+ * routine looks for attribute in inode body and returns it's value and size
-+ */
-+int
-+ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ int size, name_len = strlen(name), storage_size;
-+ struct ext3_xattr_entry *last;
-+ struct ext3_inode *raw_inode;
-+ struct ext3_iloc iloc;
-+ char *start, *end;
-+ int ret = -ENOENT;
-+
-+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+ return -ENOENT;
-+
-+ ret = ext3_get_inode_loc(inode, &iloc);
-+ if (ret)
-+ return ret;
-+ raw_inode = iloc.raw_inode;
-+
-+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+ EXT3_GOOD_OLD_INODE_SIZE -
-+ EXT3_I(inode)->i_extra_isize -
-+ sizeof(__u32);
-+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+ EXT3_I(inode)->i_extra_isize;
-+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
-+ brelse(iloc.bh);
-+ return -ENOENT;
-+ }
-+ start += sizeof(__u32);
-+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if (le32_to_cpu(last->e_value_size) > storage_size ||
-+ (char *) next >= end) {
-+ ext3_error(inode->i_sb, "ext3_xattr_ibody_get",
-+ "inode %ld", inode->i_ino);
-+ brelse(iloc.bh);
-+ return -EIO;
-+ }
-+ if (name_index == last->e_name_index &&
-+ name_len == last->e_name_len &&
-+ !memcmp(name, last->e_name, name_len))
-+ goto found;
-+ last = next;
-+ }
-+
-+ /* can't find EA */
-+ brelse(iloc.bh);
-+ return -ENOENT;
-+
-+found:
-+ size = le32_to_cpu(last->e_value_size);
-+ if (buffer) {
-+ ret = -ERANGE;
-+ if (buffer_size >= size) {
-+ memcpy(buffer, start + le16_to_cpu(last->e_value_offs),
-+ size);
-+ ret = size;
-+ }
-+ } else
-+ ret = size;
-+ brelse(iloc.bh);
-+ return ret;
-+}
-+
-+int ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ int err;
-+
-+ /* try to find attribute in inode body */
-+ err = ext3_xattr_ibody_get(inode, name_index, name,
-+ buffer, buffer_size);
-+ if (err < 0)
-+ /* search was unsuccessful, try to find EA in dedicated block */
-+ err = ext3_xattr_block_get(inode, name_index, name,
-+ buffer, buffer_size);
-+ return err;
-+}
-+
-+/*
- * ext3_xattr_list()
- *
- * Copy a list of attribute names into the buffer
-@@ -457,7 +543,7 @@ cleanup:
- * used / required on success.
- */
- int
--ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
- {
- struct buffer_head *bh = NULL;
- struct ext3_xattr_entry *entry;
-@@ -530,6 +616,131 @@ cleanup:
- return error;
- }
-
-+/* ext3_xattr_ibody_list()
-+ *
-+ * generate list of attributes stored in inode body
-+ */
-+int
-+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct ext3_xattr_entry *last;
-+ struct ext3_inode *raw_inode;
-+ char *start, *end, *buf;
-+ struct ext3_iloc iloc;
-+ int storage_size;
-+ int ret;
-+ int size = 0;
-+
-+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+ return 0;
-+
-+ ret = ext3_get_inode_loc(inode, &iloc);
-+ if (ret)
-+ return ret;
-+ raw_inode = iloc.raw_inode;
-+
-+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+ EXT3_GOOD_OLD_INODE_SIZE -
-+ EXT3_I(inode)->i_extra_isize -
-+ sizeof(__u32);
-+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+ EXT3_I(inode)->i_extra_isize;
-+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
-+ brelse(iloc.bh);
-+ return 0;
-+ }
-+ start += sizeof(__u32);
-+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ struct ext3_xattr_handler *handler;
-+ if (le32_to_cpu(last->e_value_size) > storage_size ||
-+ (char *) next >= end) {
-+ ext3_error(inode->i_sb, "ext3_xattr_ibody_list",
-+ "inode %ld", inode->i_ino);
-+ brelse(iloc.bh);
-+ return -EIO;
-+ }
-+ handler = ext3_xattr_handler(last->e_name_index);
-+ if (handler)
-+ size += handler->list(NULL, inode, last->e_name,
-+ last->e_name_len);
-+ last = next;
-+ }
-+
-+ if (!buffer) {
-+ ret = size;
-+ goto cleanup;
-+ } else {
-+ ret = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ }
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ buf = buffer;
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ struct ext3_xattr_handler *handler;
-+ handler = ext3_xattr_handler(last->e_name_index);
-+ if (handler)
-+ buf += handler->list(buf, inode, last->e_name,
-+ last->e_name_len);
-+ last = next;
-+ }
-+ ret = size;
-+cleanup:
-+ brelse(iloc.bh);
-+ return ret;
-+}
-+
-+/*
-+ * ext3_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ int error;
-+ int size = buffer_size;
-+
-+ /* get list of attributes stored in inode body */
-+ error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
-+ if (error < 0) {
-+ /* some error occured while collecting
-+ * attributes in inode body */
-+ size = 0;
-+ goto cleanup;
-+ }
-+ size = error;
-+
-+ /* get list of attributes stored in dedicated block */
-+ if (buffer) {
-+ buffer_size -= error;
-+ if (buffer_size <= 0) {
-+ buffer = NULL;
-+ buffer_size = 0;
-+ } else
-+ buffer += error;
-+ }
-+
-+ error = ext3_xattr_block_list(inode, buffer, buffer_size);
-+ if (error < 0)
-+ /* listing was successful, so we return len */
-+ size = 0;
-+
-+cleanup:
-+ return error + size;
-+}
-+
- /*
- * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
- * not set, set it.
-@@ -553,6 +764,279 @@ static void ext3_xattr_update_super_bloc
- }
-
- /*
-+ * ext3_xattr_ibody_find()
-+ *
-+ * search attribute and calculate free space in inode body
-+ * NOTE: free space includes space our attribute hold
-+ */
-+int
-+ext3_xattr_ibody_find(struct inode *inode, int name_index,
-+ const char *name, struct ext3_xattr_entry *rentry, int *free)
-+{
-+ struct ext3_xattr_entry *last;
-+ struct ext3_inode *raw_inode;
-+ int name_len = strlen(name);
-+ int err, storage_size;
-+ struct ext3_iloc iloc;
-+ char *start, *end;
-+ int ret = -ENOENT;
-+
-+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+ return ret;
-+
-+ err = ext3_get_inode_loc(inode, &iloc);
-+ if (err)
-+ return -EIO;
-+ raw_inode = iloc.raw_inode;
-+
-+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+ EXT3_GOOD_OLD_INODE_SIZE -
-+ EXT3_I(inode)->i_extra_isize -
-+ sizeof(__u32);
-+ *free = storage_size - sizeof(__u32);
-+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+ EXT3_I(inode)->i_extra_isize;
-+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
-+ brelse(iloc.bh);
-+ return -ENOENT;
-+ }
-+ start += sizeof(__u32);
-+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if (le32_to_cpu(last->e_value_size) > storage_size ||
-+ (char *) next >= end) {
-+ ext3_error(inode->i_sb, "ext3_xattr_ibody_find",
-+ "inode %ld", inode->i_ino);
-+ brelse(iloc.bh);
-+ return -EIO;
-+ }
-+
-+ if (name_index == last->e_name_index &&
-+ name_len == last->e_name_len &&
-+ !memcmp(name, last->e_name, name_len)) {
-+ memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
-+ ret = 0;
-+ } else {
-+ *free -= EXT3_XATTR_LEN(last->e_name_len);
-+ *free -= le32_to_cpu(last->e_value_size);
-+ }
-+ last = next;
-+ }
-+
-+ brelse(iloc.bh);
-+ return ret;
-+}
-+
-+/*
-+ * ext3_xattr_block_find()
-+ *
-+ * search attribute and calculate free space in EA block (if it allocated)
-+ * NOTE: free space includes space our attribute hold
-+ */
-+int
-+ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
-+ struct ext3_xattr_entry *rentry, int *free)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ char *end;
-+ int name_len, error = -ENOENT;
-+
-+ if (!EXT3_I(inode)->i_file_acl) {
-+ *free = inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_xattr_header) -
-+ sizeof(__u32);
-+ return -ENOENT;
-+ }
-+ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
-+ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
-+ "inode %ld: bad block %d", inode->i_ino,
-+ EXT3_I(inode)->i_file_acl);
-+ brelse(bh);
-+ return -EIO;
-+ }
-+ /* find named attribute */
-+ name_len = strlen(name);
-+ *free = bh->b_size - sizeof(__u32);
-+
-+ entry = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0) {
-+ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
-+ error = 0;
-+ } else {
-+ *free -= EXT3_XATTR_LEN(entry->e_name_len);
-+ *free -= le32_to_cpu(entry->e_value_size);
-+ }
-+ entry = next;
-+ }
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_inode_set()
-+ *
-+ * this routine add/remove/replace attribute in inode body
-+ */
-+int
-+ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t value_len,
-+ int flags)
-+{
-+ struct ext3_xattr_entry *last, *next, *here = NULL;
-+ struct ext3_inode *raw_inode;
-+ int name_len = strlen(name);
-+ int esize = EXT3_XATTR_LEN(name_len);
-+ struct buffer_head *bh;
-+ int err, storage_size;
-+ struct ext3_iloc iloc;
-+ int free, min_offs;
-+ char *start, *end;
-+
-+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+ return -ENOSPC;
-+
-+ err = ext3_get_inode_loc(inode, &iloc);
-+ if (err)
-+ return err;
-+ raw_inode = iloc.raw_inode;
-+ bh = iloc.bh;
-+
-+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+ EXT3_GOOD_OLD_INODE_SIZE -
-+ EXT3_I(inode)->i_extra_isize -
-+ sizeof(__u32);
-+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+ EXT3_I(inode)->i_extra_isize;
-+ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) {
-+ /* inode had no attributes before */
-+ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC);
-+ }
-+ start += sizeof(__u32);
-+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+ min_offs = storage_size;
-+ free = storage_size - sizeof(__u32);
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(last)) {
-+ next = EXT3_XATTR_NEXT(last);
-+ if (le32_to_cpu(last->e_value_size) > storage_size ||
-+ (char *) next >= end) {
-+ ext3_error(inode->i_sb, "ext3_xattr_ibody_set",
-+ "inode %ld", inode->i_ino);
-+ brelse(bh);
-+ return -EIO;
-+ }
-+
-+ if (last->e_value_size) {
-+ int offs = le16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ if (name_index == last->e_name_index &&
-+ name_len == last->e_name_len &&
-+ !memcmp(name, last->e_name, name_len))
-+ here = last;
-+ else {
-+ /* we calculate all but our attribute
-+ * because it will be removed before changing */
-+ free -= EXT3_XATTR_LEN(last->e_name_len);
-+ free -= le32_to_cpu(last->e_value_size);
-+ }
-+ last = next;
-+ }
-+
-+ if (value && (esize + value_len > free)) {
-+ brelse(bh);
-+ return -ENOSPC;
-+ }
-+
-+ err = ext3_reserve_inode_write(handle, inode, &iloc);
-+ if (err) {
-+ brelse(bh);
-+ return err;
-+ }
-+
-+ if (here) {
-+ /* time to remove old value */
-+ struct ext3_xattr_entry *e;
-+ int size = le32_to_cpu(here->e_value_size);
-+ int border = le16_to_cpu(here->e_value_offs);
-+ char *src;
-+
-+ /* move tail */
-+ memmove(start + min_offs + size, start + min_offs,
-+ border - min_offs);
-+
-+ /* recalculate offsets */
-+ e = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(e)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e);
-+ int offs = le16_to_cpu(e->e_value_offs);
-+ if (offs < border)
-+ e->e_value_offs =
-+ cpu_to_le16(offs + size);
-+ e = next;
-+ }
-+ min_offs += size;
-+
-+ /* remove entry */
-+ border = EXT3_XATTR_LEN(here->e_name_len);
-+ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len);
-+ size = (char *) last - src;
-+ if ((char *) here + size > end)
-+ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n",
-+ __FILE__, __LINE__, here, size, end);
-+ memmove(here, src, size);
-+ last = (struct ext3_xattr_entry *) ((char *) last - border);
-+ *((__u32 *) last) = 0;
-+ }
-+
-+ if (value) {
-+ int offs = min_offs - value_len;
-+ /* use last to create new entry */
-+ last->e_name_len = strlen(name);
-+ last->e_name_index = name_index;
-+ last->e_value_offs = cpu_to_le16(offs);
-+ last->e_value_size = cpu_to_le32(value_len);
-+ last->e_hash = last->e_value_block = 0;
-+ memset(last->e_name, 0, esize);
-+ memcpy(last->e_name, name, last->e_name_len);
-+ if (start + offs + value_len > end)
-+ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n",
-+ __FILE__, __LINE__, start, offs,
-+ value_len, end);
-+ memcpy(start + offs, value, value_len);
-+ last = EXT3_XATTR_NEXT(last);
-+ *((__u32 *) last) = 0;
-+ }
-+
-+ ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ brelse(bh);
-+
-+ return 0;
-+}
-+
-+/*
- * ext3_xattr_set()
- *
- * Create, replace or remove an extended attribute for this inode. Buffer
-@@ -566,6 +1050,101 @@ static void ext3_xattr_update_super_bloc
- */
- 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 ext3_xattr_entry entry;
-+ int err, where = 0, found = 0, total;
-+ int free1 = -1, free2 = -1;
-+ int name_len;
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+ return -EPERM;
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > inode->i_sb->s_blocksize)
-+ return -ERANGE;
-+
-+ /* try to find attribute in inode body */
-+ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
-+ if (err == 0) {
-+ /* found EA in inode */
-+ found = 1;
-+ where = 0;
-+ } else if (err == -ENOENT) {
-+ /* there is no such attribute in inode body */
-+ /* try to find attribute in dedicated block */
-+ err = ext3_xattr_block_find(inode, name_index, name,
-+ &entry, &free2);
-+ if (err != 0 && err != -ENOENT) {
-+ /* not found EA in block */
-+ goto finish;
-+ } else if (err == 0) {
-+ /* found EA in block */
-+ where = 1;
-+ found = 1;
-+ }
-+ } else
-+ goto finish;
-+
-+ /* check flags: may replace? may create ? */
-+ if (found && (flags & XATTR_CREATE)) {
-+ err = -EEXIST;
-+ goto finish;
-+ } else if (!found && (flags & XATTR_REPLACE)) {
-+ err = -ENODATA;
-+ goto finish;
-+ }
-+
-+ /* check if we have enough space to store attribute */
-+ total = EXT3_XATTR_LEN(strlen(name)) + value_len;
-+ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) {
-+ /* have no enough space */
-+ err = -ENOSPC;
-+ goto finish;
-+ }
-+
-+ /* time to remove attribute */
-+ if (found) {
-+ if (where == 0) {
-+ /* EA is stored in inode body */
-+ ext3_xattr_ibody_set(handle, inode, name_index, name,
-+ NULL, 0, flags);
-+ } else {
-+ /* EA is stored in separated block */
-+ ext3_xattr_block_set(handle, inode, name_index, name,
-+ NULL, 0, flags);
-+ }
-+ }
-+
-+ /* try to store EA in inode body */
-+ err = ext3_xattr_ibody_set(handle, inode, name_index, name,
-+ value, value_len, flags);
-+ if (err) {
-+ /* can't store EA in inode body */
-+ /* try to store in block */
-+ err = ext3_xattr_block_set(handle, inode, name_index,
-+ name, value, value_len, flags);
-+ }
-+
-+finish:
-+ return err;
-+}
-+
-+/*
-+ * ext3_xattr_block_set()
-+ *
-+ * this routine add/remove/replace attribute in EA block
-+ */
-+int
-+ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index,
- const char *name, const void *value, size_t value_len, int flags)
- {
- struct super_block *sb = inode->i_sb;
---- linux-2.4.20/include/linux/ext3_fs.h~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:08.000000000 +0400
-+++ linux-2.4.20-alexey/include/linux/ext3_fs.h 2003-10-12 16:35:46.000000000 +0400
-@@ -264,6 +264,8 @@ struct ext3_inode {
- __u32 m_i_reserved2[2];
- } masix2;
- } osd2; /* OS dependent 2 */
-+ __u16 i_extra_isize;
-+ __u16 i_pad1;
- };
-
- #define i_size_high i_dir_acl
---- linux-2.4.20/include/linux/ext3_fs_i.h~ext3-ea-in-inode-2.4.20 2001-11-22 22:46:19.000000000 +0300
-+++ linux-2.4.20-alexey/include/linux/ext3_fs_i.h 2003-10-12 16:34:14.000000000 +0400
-@@ -62,6 +62,9 @@ struct ext3_inode_info {
- */
- loff_t i_disksize;
-
-+ /* on-disk additional length */
-+ __u16 i_extra_isize;
-+
- /*
- * truncate_sem is for serialising ext3_truncate() against
- * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's
---- linux-2.4.20/fs/ext3/super.c~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:09.000000000 +0400
-+++ linux-2.4.20-alexey/fs/ext3/super.c 2003-10-12 16:25:21.000000000 +0400
-@@ -1292,8 +1292,10 @@ struct super_block * ext3_read_super (st
- } else {
- sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
- sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
-- if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) {
-- printk (KERN_ERR
-+ if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
-+ (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
-+ (sbi->s_inode_size > blocksize)) {
-+ printk (KERN_ERR
- "EXT3-fs: unsupported inode size: %d\n",
- sbi->s_inode_size);
- goto failed_mount;
-
-_