Signed-off-by: Andrew Morton --- 25-akpm/fs/ext3/xattr.c | 242 ++++++++++++++++++++++++------------------------ 25-akpm/fs/ext3/xattr.h | 8 + 2 files changed, 129 insertions(+), 121 deletions(-) diff -puN fs/ext3/xattr.c~ext3-ea-revert-cleanup fs/ext3/xattr.c --- 25/fs/ext3/xattr.c~ext3-ea-revert-cleanup Wed Jan 12 16:55:13 2005 +++ 25-akpm/fs/ext3/xattr.c Wed Jan 12 16:55:13 2005 @@ -139,11 +139,22 @@ ext3_xattr_handler(int name_index) } /* + * Inode operation listxattr() + * + * dentry->d_inode->i_sem: don't care + */ +ssize_t +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + return ext3_xattr_list(dentry->d_inode, buffer, size); +} + +/* * ext3_xattr_block_get() * * routine looks for attribute in EA block and returns it's value and size */ -static int +int ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, void *buffer, size_t buffer_size) { @@ -239,7 +250,7 @@ cleanup: * * routine looks for attribute in inode body and returns it's value and size */ -static int +int ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name, void *buffer, size_t buffer_size) { @@ -341,7 +352,7 @@ ext3_xattr_get(struct inode *inode, int * * generate list of attributes stored in EA block */ -static int +int ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) { struct buffer_head *bh = NULL; @@ -417,7 +428,7 @@ cleanup: * * generate list of attributes stored in inode body */ -static int +int ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size) { struct ext3_xattr_entry *last; @@ -496,7 +507,7 @@ cleanup: * Returns a negative error number on failure, or the number of bytes * used / required on success. */ -static int +int ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) { int size = buffer_size; @@ -535,17 +546,6 @@ cleanup: } /* - * Inode operation listxattr() - * - * dentry->d_inode->i_sem: don't care - */ -ssize_t -ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) -{ - return ext3_xattr_list(dentry->d_inode, buffer, size); -} - -/* * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is * not set, set it. */ @@ -571,7 +571,7 @@ static void ext3_xattr_update_super_bloc * search attribute and calculate free space in inode body * NOTE: free space includes space our attribute hold */ -static int +int ext3_xattr_ibody_find(struct inode *inode, int name_index, const char *name, int *free) { @@ -638,7 +638,7 @@ ext3_xattr_ibody_find(struct inode *inod * search attribute and calculate free space in EA block (if it allocated) * NOTE: free space includes space our attribute hold */ -static int +int ext3_xattr_block_find(struct inode *inode, int name_index, const char *name, int *free) { @@ -698,7 +698,7 @@ bad_block: ext3_error(inode->i_sb, "ext3 * * this routine add/remove/replace attribute in inode body */ -static int +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) @@ -846,11 +846,112 @@ done: } /* + * ext3_xattr_set_handle() + * + * 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(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 */ -static int +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) @@ -1105,107 +1206,6 @@ cleanup: } /* - * ext3_xattr_set_handle() - * - * 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(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; -} - -/* * Second half of ext3_xattr_set_handle(): Update the file system. */ static int diff -puN fs/ext3/xattr.h~ext3-ea-revert-cleanup fs/ext3/xattr.h --- 25/fs/ext3/xattr.h~ext3-ea-revert-cleanup Wed Jan 12 16:55:13 2005 +++ 25-akpm/fs/ext3/xattr.h Wed Jan 12 16:55:13 2005 @@ -65,8 +65,10 @@ extern struct xattr_handler ext3_xattr_s extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); 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 void ext3_xattr_delete_inode(handle_t *, struct inode *); extern void ext3_xattr_put_super(struct super_block *); @@ -84,6 +86,12 @@ ext3_xattr_get(struct inode *inode, int { return -EOPNOTSUPP; } + +static inline int +ext3_xattr_list(struct inode *inode, void *buffer, size_t size) +{ + return -EOPNOTSUPP; +} static inline int ext3_xattr_set(struct inode *inode, int name_index, const char *name, _