From: Andreas Gruenbacher Signed-off-by: Andrew Morton --- 25-akpm/fs/ext3/ialloc.c | 5 25-akpm/fs/ext3/inode.c | 10 25-akpm/fs/ext3/xattr.c | 639 ++------------------------------------ 25-akpm/fs/ext3/xattr.h | 3 25-akpm/include/linux/ext3_fs.h | 3 25-akpm/include/linux/ext3_fs_i.h | 3 6 files changed, 38 insertions(+), 625 deletions(-) diff -puN fs/ext3/ialloc.c~ext3-ea-revert-old-ea-in-inode fs/ext3/ialloc.c --- 25/fs/ext3/ialloc.c~ext3-ea-revert-old-ea-in-inode Tue Jan 11 14:39:45 2005 +++ 25-akpm/fs/ext3/ialloc.c Tue Jan 11 14:39:45 2005 @@ -596,11 +596,6 @@ got: spin_unlock(&sbi->s_next_gen_lock); ei->i_state = EXT3_STATE_NEW; - if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) { - ei->i_extra_isize = sizeof(__u16) /* i_extra_isize */ - + sizeof(__u16); /* i_pad1 */ - } else - ei->i_extra_isize = 0; ret = inode; if(DQUOT_ALLOC_INODE(inode)) { diff -puN fs/ext3/inode.c~ext3-ea-revert-old-ea-in-inode fs/ext3/inode.c --- 25/fs/ext3/inode.c~ext3-ea-revert-old-ea-in-inode Tue Jan 11 14:39:45 2005 +++ 25-akpm/fs/ext3/inode.c Tue Jan 11 14:39:45 2005 @@ -2277,7 +2277,7 @@ static unsigned long ext3_get_inode_bloc * trying to determine the inode's location on-disk and no read need be * performed. */ -int ext3_get_inode_loc(struct inode *inode, +static int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc, int in_mem) { unsigned long block; @@ -2485,11 +2485,6 @@ void ext3_read_inode(struct inode * inod ei->i_data[block] = raw_inode->i_block[block]; INIT_LIST_HEAD(&ei->i_orphan); - if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) - ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); - else - ei->i_extra_isize = 0; - if (S_ISREG(inode->i_mode)) { inode->i_op = &ext3_file_inode_operations; inode->i_fop = &ext3_file_operations; @@ -2625,9 +2620,6 @@ static int ext3_do_update_inode(handle_t } else for (block = 0; block < EXT3_N_BLOCKS; block++) raw_inode->i_block[block] = ei->i_data[block]; - if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) - raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); - BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); rc = ext3_journal_dirty_metadata(handle, bh); if (!err) diff -puN fs/ext3/xattr.c~ext3-ea-revert-old-ea-in-inode fs/ext3/xattr.c --- 25/fs/ext3/xattr.c~ext3-ea-revert-old-ea-in-inode Tue Jan 11 14:39:45 2005 +++ 25-akpm/fs/ext3/xattr.c Tue Jan 11 14:39:45 2005 @@ -9,7 +9,6 @@ * suggestion of Luka Renko . * xattr consolidation Copyright (c) 2004 James Morris , * Red Hat Inc. - * ea-in-inode support by Alex Tomas aka bzzz */ /* @@ -90,9 +89,10 @@ # define ea_bdebug(f...) #endif -static int ext3_xattr_set_handle2(handle_t *handle, struct inode *inode, - struct buffer_head *old_bh, - struct ext3_xattr_header *header); +static int ext3_xattr_set_handle2(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(handle_t *, struct inode *, struct ext3_xattr_header *, @@ -150,12 +150,17 @@ ext3_listxattr(struct dentry *dentry, ch } /* - * ext3_xattr_block_get() + * 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. * - * routine looks for attribute in EA block and returns it's value and size + * Returns a negative error number on failure, or the number of bytes + * used / required on success. */ int -ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, +ext3_xattr_get(struct inode *inode, int name_index, const char *name, void *buffer, size_t buffer_size) { struct buffer_head *bh = NULL; @@ -169,6 +174,7 @@ ext3_xattr_block_get(struct inode *inode if (name == NULL) return -EINVAL; + down_read(&EXT3_I(inode)->xattr_sem); error = -ENODATA; if (!EXT3_I(inode)->i_file_acl) goto cleanup; @@ -241,87 +247,15 @@ found: cleanup: brelse(bh); + up_read(&EXT3_I(inode)->xattr_sem); return error; } /* - * ext3_xattr_ibody_get() - * - * routine looks for attribute in inode body and returns it's value and size - */ -int -ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name, - void *buffer, size_t buffer_size) -{ - int size, name_len = strlen(name), storage_size; - struct ext3_xattr_entry *last; - struct ext3_inode *raw_inode; - struct ext3_iloc iloc; - char *start, *end; - int ret = -ENOENT; - - if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) - return -ENOENT; - - ret = ext3_get_inode_loc(inode, &iloc, 1); - if (ret) - return ret; - raw_inode = ext3_raw_inode(&iloc); - - 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; -} - -/* - * ext3_xattr_get() + * ext3_xattr_list() * - * Copy an extended attribute into the buffer + * 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. * @@ -329,31 +263,7 @@ found: * used / required on success. */ int -ext3_xattr_get(struct inode *inode, int name_index, const char *name, - void *buffer, size_t buffer_size) -{ - int err; - - down_read(&EXT3_I(inode)->xattr_sem); - - /* 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); - up_read(&EXT3_I(inode)->xattr_sem); - - return err; -} - -/* ext3_xattr_block_list() - * - * generate list of attributes stored in EA block - */ -int -ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) { struct buffer_head *bh = NULL; struct ext3_xattr_entry *entry; @@ -364,6 +274,7 @@ ext3_xattr_block_list(struct inode *inod ea_idebug(inode, "buffer=%p, buffer_size=%ld", buffer, (long)buffer_size); + down_read(&EXT3_I(inode)->xattr_sem); error = 0; if (!EXT3_I(inode)->i_file_acl) goto cleanup; @@ -373,7 +284,7 @@ ext3_xattr_block_list(struct inode *inod if (!bh) goto cleanup; ea_bdebug(bh, "b_count=%d, refcount=%d", - (int) atomic_read(&(bh->b_count)), (int) le32_to_cpu(HDR(bh)->h_refcount)); + 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)) { @@ -420,131 +331,11 @@ bad_block: ext3_error(inode->i_sb, "ext3 cleanup: brelse(bh); + up_read(&EXT3_I(inode)->xattr_sem); 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; - size_t rest = buffer_size; - struct ext3_iloc iloc; - char *start, *end; - int storage_size; - int size = 0; - int ret; - - if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) - return 0; - - ret = ext3_get_inode_loc(inode, &iloc, 1); - if (ret) - return ret; - raw_inode = ext3_raw_inode(&iloc); - - 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) - goto cleanup; - 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 ((char *) next >= end) { - ext3_error(inode->i_sb, "ext3_xattr_ibody_list", - "inode %ld", inode->i_ino); - ret = -EIO; - goto cleanup; - } - last = next; - } - - last = (struct ext3_xattr_entry *) start; - for (; !IS_LAST_ENTRY(last); last = EXT3_XATTR_NEXT(last)) { - struct xattr_handler *handler = - ext3_xattr_handler(last->e_name_index); - - if (!handler) - continue; - - size += handler->list(inode, buffer, rest, last->e_name, - last->e_name_len); - if (buffer) { - if (size > rest) { - ret = -ERANGE; - goto cleanup; - } - buffer += size; - } - rest -= size; - } - ret = buffer_size - rest; /* total 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 size = buffer_size; - int error; - - down_read(&EXT3_I(inode)->xattr_sem); - - /* 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); - /* listing was successful, so we return len */ - if (error < 0) - size = 0; - -cleanup: - up_read(&EXT3_I(inode)->xattr_sem); - return error + size; -} - /* * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is * not set, set it. @@ -566,286 +357,6 @@ 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, 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; - - *free = 0; - if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) - return ret; - - err = ext3_get_inode_loc(inode, &iloc, 1); - if (err) - return -EIO; - raw_inode = ext3_raw_inode(&iloc); - - 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)) { - 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, 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) { - 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_ibody_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, 1); - if (err) - return err; - raw_inode = ext3_raw_inode(&iloc); - 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; - } - - /* optimization: can we simple replace old value ? */ - if (here && value_len == le32_to_cpu(here->e_value_size)) { - int offs = le16_to_cpu(here->e_value_offs); - memcpy(start + offs, value, value_len); - goto done; - } - - 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 + %zd > 0x%p\n", - __FILE__, __LINE__, start, offs, - value_len, end); - memcpy(start + offs, value, value_len); - last = EXT3_XATTR_NEXT(last); - *((__u32 *) last) = 0; - } - -done: - ext3_mark_iloc_dirty(handle, inode, &iloc); - brelse(bh); - - return 0; -} - -/* * ext3_xattr_set_handle() * * Create, replace or remove an extended attribute for this inode. Buffer @@ -859,100 +370,6 @@ done: */ int ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, - const char *name, const void *value, size_t value_len, - int flags) -{ - int free1 = -1, free2 = -1; - int err, where = 0, total; - 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; - down_write(&EXT3_I(inode)->xattr_sem); - -#define EX_FOUND_IN_IBODY 1 -#define EX_FOUND_IN_BLOCK 2 - - /* try to find attribute in inode body */ - err = ext3_xattr_ibody_find(inode, name_index, name, &free1); - if (err == 0) { - /* found EA in inode */ - where = EX_FOUND_IN_IBODY; - } 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, &free2); - if (err != 0 && err != -ENOENT) { - /* not found EA in block */ - goto finish; - } else if (err == 0) { - /* found EA in block */ - where = EX_FOUND_IN_BLOCK; - } - } else - goto finish; - - /* check flags: may replace? may create ? */ - if (where && (flags & XATTR_CREATE)) { - err = -EEXIST; - goto finish; - } else if (!where && (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 (total > free1 && free2 > 0 && total > free2) { - /* have no enough space */ - err = -ENOSPC; - goto finish; - } - - /* there are two cases when we want to remove EA from original storage: - * a) EA is stored in the inode, but new value doesn't fit - * b) EA is stored in the block, but new value fit in inode - */ - if (where == EX_FOUND_IN_IBODY && total > free1) - ext3_xattr_ibody_set(handle, inode, name_index, name, - NULL, 0, flags); - else if (where == EX_FOUND_IN_BLOCK && total <= free1) - 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: - up_write(&EXT3_I(inode)->xattr_sem); - 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) { @@ -975,7 +392,22 @@ ext3_xattr_block_set(handle_t *handle, s * 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_write(&EXT3_I(inode)->xattr_sem); if (EXT3_I(inode)->i_file_acl) { /* The inode already has an extended attribute block. */ bh = sb_bread(sb, EXT3_I(inode)->i_file_acl); @@ -1201,6 +633,7 @@ cleanup: brelse(bh); if (!(bh && header == HDR(bh))) kfree(header); + up_write(&EXT3_I(inode)->xattr_sem); return error; } diff -puN fs/ext3/xattr.h~ext3-ea-revert-old-ea-in-inode fs/ext3/xattr.h --- 25/fs/ext3/xattr.h~ext3-ea-revert-old-ea-in-inode Tue Jan 11 14:39:45 2005 +++ 25-akpm/fs/ext3/xattr.h Tue Jan 11 14:39:45 2005 @@ -67,8 +67,7 @@ extern ssize_t ext3_listxattr(struct den 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(struct inode *, int, const char *, const void *, size_t, int); -extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *,const void *,size_t,int); -extern int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,const void *,size_t,int); +extern int ext3_xattr_set_handle(handle_t *, 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 *); diff -puN include/linux/ext3_fs.h~ext3-ea-revert-old-ea-in-inode include/linux/ext3_fs.h --- 25/include/linux/ext3_fs.h~ext3-ea-revert-old-ea-in-inode Tue Jan 11 14:39:45 2005 +++ 25-akpm/include/linux/ext3_fs.h Tue Jan 11 14:39:45 2005 @@ -293,8 +293,6 @@ 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 @@ -757,7 +755,6 @@ extern int ext3_forget(handle_t *, 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 *); -extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *, int); extern void ext3_read_inode (struct inode *); extern int ext3_write_inode (struct inode *, int); extern int ext3_setattr (struct dentry *, struct iattr *); diff -puN include/linux/ext3_fs_i.h~ext3-ea-revert-old-ea-in-inode include/linux/ext3_fs_i.h --- 25/include/linux/ext3_fs_i.h~ext3-ea-revert-old-ea-in-inode Tue Jan 11 14:39:45 2005 +++ 25-akpm/include/linux/ext3_fs_i.h Tue Jan 11 14:39:45 2005 @@ -113,9 +113,6 @@ 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 _