Commit 574dd596 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] xattr: cleanups

From: From: Andreas Gruenbacher <agruen@suse.de>

* Various minor cleanups and simplifications in the extended attributes
  and acl code.

* Use a smarter shortcut rule in ext[23]_permission(): If the mask
  contains permissions that are not also contained in the group
  file mode permission bits, those permissions can never be granted by
  an acl. (The previous shortcut rule was more coarse.)
parent c3087712
/*
* linux/fs/ext2/acl.c
*
* Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
* Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
*/
#include <linux/init.h>
......@@ -19,7 +19,7 @@ static struct posix_acl *
ext2_acl_from_disk(const void *value, size_t size)
{
const char *end = (char *)value + size;
int n, count;
size_t n, count;
struct posix_acl *acl;
if (!value)
......@@ -85,7 +85,7 @@ ext2_acl_to_disk(const struct posix_acl *acl, size_t *size)
{
ext2_acl_header *ext_acl;
char *e;
int n;
size_t n;
*size = ext2_acl_size(acl->a_count);
ext_acl = (ext2_acl_header *)kmalloc(sizeof(ext2_acl_header) +
......@@ -130,10 +130,11 @@ ext2_acl_to_disk(const struct posix_acl *acl, size_t *size)
static struct posix_acl *
ext2_get_acl(struct inode *inode, int type)
{
const size_t max_size = ext2_acl_size(EXT2_ACL_MAX_ENTRIES);
struct ext2_inode_inode *ei = EXT2_I(inode);
int name_index;
char *value;
struct posix_acl *acl, **p_acl;
const size_t size = ext2_acl_size(EXT2_ACL_MAX_ENTRIES);
struct posix_acl *acl;
int retval;
if (!test_opt(inode->i_sb, POSIX_ACL))
......@@ -141,36 +142,43 @@ ext2_get_acl(struct inode *inode, int type)
switch(type) {
case ACL_TYPE_ACCESS:
p_acl = &EXT2_I(inode)->i_acl;
if (ei->i_acl != EXT2_ACL_NOT_CACHED)
return posix_acl_dup(ei->i_acl);
name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
break;
case ACL_TYPE_DEFAULT:
p_acl = &EXT2_I(inode)->i_default_acl;
if (ei->i_default_acl != EXT2_ACL_NOT_CACHED)
return posix_acl_dup(ei->i_default_acl);
name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
break;
default:
return ERR_PTR(-EINVAL);
}
if (*p_acl != EXT2_ACL_NOT_CACHED)
return posix_acl_dup(*p_acl);
value = kmalloc(size, GFP_KERNEL);
value = kmalloc(max_size, GFP_KERNEL);
if (!value)
return ERR_PTR(-ENOMEM);
retval = ext2_xattr_get(inode, name_index, "", value, size);
if (retval == -ENODATA || retval == -ENOSYS)
*p_acl = acl = NULL;
else if (retval < 0)
retval = ext2_xattr_get(inode, name_index, "", value, max_size);
acl = ERR_PTR(retval);
else {
if (retval >= 0)
acl = ext2_acl_from_disk(value, retval);
if (!IS_ERR(acl))
*p_acl = posix_acl_dup(acl);
}
else if (retval == -ENODATA || retval == -ENOSYS)
acl = NULL;
kfree(value);
if (!IS_ERR(acl)) {
switch(type) {
case ACL_TYPE_ACCESS:
ei->i_acl = posix_acl_dup(acl);
break;
case ACL_TYPE_DEFAULT:
ei->i_default_acl = posix_acl_dup(acl);
break;
}
}
return acl;
}
......@@ -180,9 +188,9 @@ ext2_get_acl(struct inode *inode, int type)
static int
ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
{
struct ext2_inode_info *ei = EXT2_I(inode);
int name_index;
void *value = NULL;
struct posix_acl **p_acl;
size_t size;
int error;
......@@ -194,7 +202,6 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
switch(type) {
case ACL_TYPE_ACCESS:
name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
p_acl = &EXT2_I(inode)->i_acl;
if (acl) {
mode_t mode = inode->i_mode;
error = posix_acl_equiv_mode(acl, &mode);
......@@ -211,7 +218,6 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
case ACL_TYPE_DEFAULT:
name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
p_acl = &EXT2_I(inode)->i_default_acl;
if (!S_ISDIR(inode->i_mode))
return acl ? -EACCES : 0;
break;
......@@ -232,9 +238,19 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
if (value)
kfree(value);
if (!error) {
if (*p_acl && *p_acl != EXT2_ACL_NOT_CACHED)
posix_acl_release(*p_acl);
*p_acl = posix_acl_dup(acl);
switch(type) {
case ACL_TYPE_ACCESS:
if (ei->i_acl != EXT2_ACL_NOT_CACHED)
posix_acl_release(ei->i_acl);
ei->i_acl = posix_acl_dup(acl);
break;
case ACL_TYPE_DEFAULT:
if (ei->i_default_acl != EXT2_ACL_NOT_CACHED)
posix_acl_release(ei->i_default_acl);
ei->i_default_acl = posix_acl_dup(acl);
break;
}
}
return error;
}
......@@ -254,11 +270,13 @@ __ext2_permission(struct inode *inode, int mask, int lock)
if (current->fsuid == inode->i_uid) {
mode >>= 6;
} else if (test_opt(inode->i_sb, POSIX_ACL)) {
/* ACL can't contain additional permissions if
the ACL_MASK entry is 0 */
if (!(mode & S_IRWXG))
struct ext2_inode_info *ei = EXT2_I(inode);
/* The access ACL cannot grant access if the group class
permission bits don't contain all requested permissions. */
if (((mode >> 3) & mask & S_IRWXO) != mask)
goto check_groups;
if (EXT2_I(inode)->i_acl == EXT2_ACL_NOT_CACHED) {
if (ei->i_acl == EXT2_ACL_NOT_CACHED) {
struct posix_acl *acl;
if (lock) {
......@@ -271,12 +289,11 @@ __ext2_permission(struct inode *inode, int mask, int lock)
if (IS_ERR(acl))
return PTR_ERR(acl);
posix_acl_release(acl);
if (EXT2_I(inode)->i_acl == EXT2_ACL_NOT_CACHED)
if (ei->i_acl == EXT2_ACL_NOT_CACHED)
return -EIO;
}
if (EXT2_I(inode)->i_acl) {
int error = posix_acl_permission(inode,
EXT2_I(inode)->i_acl, mask);
if (ei->i_acl) {
int error = posix_acl_permission(inode, ei->i_acl,mask);
if (error == -EACCES)
goto check_capabilities;
return error;
......
/*
* linux/fs/ext2/xattr.c
*
* Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
* Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
*
* Fix by Harrison Xing <harrison@mountainviewdata.com>.
* Extended attributes for symlinks and special files added per
......@@ -83,8 +83,9 @@ EXPORT_SYMBOL(ext2_xattr_set);
} while (0)
# define ea_bdebug(bh, f...) do { \
char b[BDEVNAME_SIZE]; \
printk(KERN_DEBUG "block %s:%ld: ", \
bdevname(bh->b_bdev, b), bh->b_blocknr); \
printk(KERN_DEBUG "block %s:%lu: ", \
bdevname(bh->b_bdev, b), \
(unsigned long) bh->b_blocknr); \
printk(f); \
printk("\n"); \
} while (0)
......@@ -196,7 +197,6 @@ ext2_xattr_handler(int name_index)
* Inode operation getxattr()
*
* dentry->d_inode->i_sem down
* BKL held [before 2.5.x]
*/
ssize_t
ext2_getxattr(struct dentry *dentry, const char *name,
......@@ -215,7 +215,6 @@ ext2_getxattr(struct dentry *dentry, const char *name,
* Inode operation listxattr()
*
* dentry->d_inode->i_sem down
* BKL held [before 2.5.x]
*/
ssize_t
ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
......@@ -227,7 +226,6 @@ ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
* Inode operation setxattr()
*
* dentry->d_inode->i_sem down
* BKL held [before 2.5.x]
*/
int
ext2_setxattr(struct dentry *dentry, const char *name,
......@@ -248,7 +246,6 @@ ext2_setxattr(struct dentry *dentry, const char *name,
* Inode operation removexattr()
*
* dentry->d_inode->i_sem down
* BKL held [before 2.5.x]
*/
int
ext2_removexattr(struct dentry *dentry, const char *name)
......@@ -278,9 +275,9 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
{
struct buffer_head *bh = NULL;
struct ext2_xattr_entry *entry;
unsigned int size;
size_t name_len, size;
char *end;
int name_len, error;
int error;
ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
name_index, name, buffer, (long)buffer_size);
......@@ -376,7 +373,7 @@ ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
{
struct buffer_head *bh = NULL;
struct ext2_xattr_entry *entry;
unsigned int size = 0;
size_t size = 0;
char *buf, *end;
int error;
......@@ -482,8 +479,8 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
struct buffer_head *bh = NULL;
struct ext2_xattr_header *header = NULL;
struct ext2_xattr_entry *here, *last;
unsigned int name_len;
int min_offs = sb->s_blocksize, not_found = 1, free, error;
size_t name_len, free, min_offs = sb->s_blocksize;
int not_found = 1, error;
char *end;
/*
......@@ -540,7 +537,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
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);
size_t offs = le16_to_cpu(here->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
......@@ -560,7 +557,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
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);
size_t offs = le16_to_cpu(last->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
......@@ -584,25 +581,23 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
error = 0;
if (value == NULL)
goto cleanup;
else
free -= EXT2_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);
size_t 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 += EXT2_XATTR_SIZE(size);
}
free += EXT2_XATTR_LEN(name_len);
}
free -= EXT2_XATTR_SIZE(value_len);
error = -ENOSPC;
if (free < 0)
if (free < EXT2_XATTR_LEN(name_len) + EXT2_XATTR_SIZE(value_len))
goto cleanup;
/* Here we know that we can set the new attribute. */
......@@ -640,8 +635,8 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
if (not_found) {
/* Insert the new name. */
int size = EXT2_XATTR_LEN(name_len);
int rest = (char *)last - (char *)here;
size_t size = EXT2_XATTR_LEN(name_len);
size_t rest = (char *)last - (char *)here;
memmove((char *)here + size, here, rest);
memset(here, 0, size);
here->e_name_index = name_index;
......@@ -651,7 +646,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
/* 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);
size_t offs = le16_to_cpu(here->e_value_offs);
char *val = (char *)header + offs;
size_t size = EXT2_XATTR_SIZE(
le32_to_cpu(here->e_value_size));
......@@ -663,7 +658,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
/* Adjust all value offsets. */
last = ENTRY(header+1);
while (!IS_LAST_ENTRY(last)) {
int o = le16_to_cpu(last->e_value_offs);
size_t o = le16_to_cpu(last->e_value_offs);
if (!last->e_value_block && o < offs)
last->e_value_offs =
cpu_to_le16(o + size);
......@@ -678,7 +673,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
goto cleanup;
} else {
/* Remove the old name. */
int size = EXT2_XATTR_LEN(name_len);
size_t size = EXT2_XATTR_LEN(name_len);
last = ENTRY((char *)last - size);
memmove(here, (char*)here + size,
(char*)last - (char*)here);
......@@ -732,9 +727,9 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
* The old block will be released after updating
* the inode.
*/
ea_bdebug(new_bh, "%s block %ld",
ea_bdebug(new_bh, "%s block %lu",
(old_bh == new_bh) ? "keeping" : "reusing",
new_bh->b_blocknr);
(unsigned long) new_bh->b_blocknr);
error = -EDQUOT;
if (DQUOT_ALLOC_BLOCK(inode, 1))
......@@ -751,8 +746,10 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
ext2_xattr_cache_insert(new_bh);
} else {
/* We need to allocate a new block */
int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
int goal = le32_to_cpu(EXT2_SB(sb)->s_es->
s_first_data_block) +
EXT2_I(inode)->i_block_group *
EXT2_BLOCKS_PER_GROUP(sb);
int block = ext2_new_block(inode, goal, 0, 0, &error);
if (error)
goto cleanup;
......@@ -857,8 +854,8 @@ ext2_xattr_delete_inode(struct inode *inode)
if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
ext2_xattr_cache_remove(bh);
ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
get_bh(bh);
bforget(bh);
bh = NULL;
} else {
HDR(bh)->h_refcount = cpu_to_le32(
le32_to_cpu(HDR(bh)->h_refcount) - 1);
......
/*
* linux/fs/ext3/acl.c
*
* Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
* Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
*/
#include <linux/init.h>
......@@ -20,7 +20,7 @@ static struct posix_acl *
ext3_acl_from_disk(const void *value, size_t size)
{
const char *end = (char *)value + size;
int n, count;
size_t n, count;
struct posix_acl *acl;
if (!value)
......@@ -86,7 +86,7 @@ ext3_acl_to_disk(const struct posix_acl *acl, size_t *size)
{
ext3_acl_header *ext_acl;
char *e;
int n;
size_t n;
*size = ext3_acl_size(acl->a_count);
ext_acl = (ext3_acl_header *)kmalloc(sizeof(ext3_acl_header) +
......@@ -133,10 +133,11 @@ ext3_acl_to_disk(const struct posix_acl *acl, size_t *size)
static struct posix_acl *
ext3_get_acl(struct inode *inode, int type)
{
const size_t max_size = ext3_acl_size(EXT3_ACL_MAX_ENTRIES);
struct ext3_inode_info *ei = EXT3_I(inode);
int name_index;
char *value;
struct posix_acl *acl, **p_acl;
const size_t size = ext3_acl_size(EXT3_ACL_MAX_ENTRIES);
struct posix_acl *acl;
int retval;
if (!test_opt(inode->i_sb, POSIX_ACL))
......@@ -144,36 +145,43 @@ ext3_get_acl(struct inode *inode, int type)
switch(type) {
case ACL_TYPE_ACCESS:
p_acl = &EXT3_I(inode)->i_acl;
if (ei->i_acl != EXT3_ACL_NOT_CACHED)
return posix_acl_dup(ei->i_acl);
name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
break;
case ACL_TYPE_DEFAULT:
p_acl = &EXT3_I(inode)->i_default_acl;
if (ei->i_default_acl != EXT3_ACL_NOT_CACHED)
return posix_acl_dup(ei->i_default_acl);
name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
break;
default:
return ERR_PTR(-EINVAL);
}
if (*p_acl != EXT3_ACL_NOT_CACHED)
return posix_acl_dup(*p_acl);
value = kmalloc(size, GFP_KERNEL);
value = kmalloc(max_size, GFP_KERNEL);
if (!value)
return ERR_PTR(-ENOMEM);
retval = ext3_xattr_get(inode, name_index, "", value, size);
if (retval == -ENODATA || retval == -ENOSYS)
*p_acl = acl = NULL;
else if (retval < 0)
retval = ext3_xattr_get(inode, name_index, "", value, max_size);
acl = ERR_PTR(retval);
else {
if (retval > 0)
acl = ext3_acl_from_disk(value, retval);
if (!IS_ERR(acl))
*p_acl = posix_acl_dup(acl);
}
else if (retval == -ENODATA || retval == -ENOSYS)
acl = NULL;
kfree(value);
if (!IS_ERR(acl)) {
switch(type) {
case ACL_TYPE_ACCESS:
ei->i_acl = posix_acl_dup(acl);
break;
case ACL_TYPE_DEFAULT:
ei->i_default_acl = posix_acl_dup(acl);
break;
}
}
return acl;
}
......@@ -186,9 +194,9 @@ static int
ext3_set_acl(handle_t *handle, struct inode *inode, int type,
struct posix_acl *acl)
{
struct ext3_inode_info *ei = EXT3_I(inode);
int name_index;
void *value = NULL;
struct posix_acl **p_acl;
size_t size;
int error;
......@@ -198,7 +206,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
switch(type) {
case ACL_TYPE_ACCESS:
name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
p_acl = &EXT3_I(inode)->i_acl;
if (acl) {
mode_t mode = inode->i_mode;
error = posix_acl_equiv_mode(acl, &mode);
......@@ -215,7 +222,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
case ACL_TYPE_DEFAULT:
name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
p_acl = &EXT3_I(inode)->i_default_acl;
if (!S_ISDIR(inode->i_mode))
return acl ? -EACCES : 0;
break;
......@@ -231,14 +237,25 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
return (int)PTR_ERR(value);
}
error = ext3_xattr_set_handle(handle, inode, name_index, "", value, size, 0);
error = ext3_xattr_set_handle(handle, inode, name_index, "",
value, size, 0);
if (value)
kfree(value);
if (!error) {
if (*p_acl && *p_acl != EXT3_ACL_NOT_CACHED)
posix_acl_release(*p_acl);
*p_acl = posix_acl_dup(acl);
switch(type) {
case ACL_TYPE_ACCESS:
if (ei->i_acl != EXT3_ACL_NOT_CACHED)
posix_acl_release(ei->i_acl);
ei->i_acl = posix_acl_dup(acl);
break;
case ACL_TYPE_DEFAULT:
if (ei->i_default_acl != EXT3_ACL_NOT_CACHED)
posix_acl_release(ei->i_default_acl);
ei->i_default_acl = posix_acl_dup(acl);
break;
}
}
return error;
}
......@@ -258,11 +275,13 @@ __ext3_permission(struct inode *inode, int mask, int lock)
if (current->fsuid == inode->i_uid) {
mode >>= 6;
} else if (test_opt(inode->i_sb, POSIX_ACL)) {
/* ACL can't contain additional permissions if
the ACL_MASK entry is 0 */
if (!(mode & S_IRWXG))
struct ext3_inode_info *ei = EXT3_I(inode);
/* The access ACL cannot grant access if the group class
permission bits don't contain all requested permissions. */
if (((mode >> 3) & mask & S_IRWXO) != mask)
goto check_groups;
if (EXT3_I(inode)->i_acl == EXT3_ACL_NOT_CACHED) {
if (ei->i_acl == EXT3_ACL_NOT_CACHED) {
struct posix_acl *acl;
if (lock) {
......@@ -275,12 +294,11 @@ __ext3_permission(struct inode *inode, int mask, int lock)
if (IS_ERR(acl))
return PTR_ERR(acl);
posix_acl_release(acl);
if (EXT3_I(inode)->i_acl == EXT3_ACL_NOT_CACHED)
if (ei->i_acl == EXT3_ACL_NOT_CACHED)
return -EIO;
}
if (EXT3_I(inode)->i_acl) {
int error = posix_acl_permission(inode,
EXT3_I(inode)->i_acl, mask);
if (ei->i_acl) {
int error = posix_acl_permission(inode, ei->i_acl,mask);
if (error == -EACCES)
goto check_capabilities;
return error;
......
/*
* linux/fs/ext3/xattr.c
*
* Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
* Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
*
* Fix by Harrison Xing <harrison@mountainviewdata.com>.
* Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
......@@ -63,8 +63,6 @@
#include "xattr.h"
#include "acl.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)
......@@ -79,8 +77,9 @@
} while (0)
# define ea_bdebug(bh, f...) do { \
char b[BDEVNAME_SIZE]; \
printk(KERN_DEBUG "block %s:%ld: ", \
bdevname(bh->b_bdev, b), bh->b_blocknr); \
printk(KERN_DEBUG "block %s:%lu: ", \
bdevname(bh->b_bdev, b), \
(unsigned long) bh->b_blocknr); \
printk(f); \
printk("\n"); \
} while (0)
......@@ -271,9 +270,9 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name,
{
struct buffer_head *bh = NULL;
struct ext3_xattr_entry *entry;
unsigned int size;
size_t name_len, size;
char *end;
int name_len, error;
int error;
ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
name_index, name, buffer, (long)buffer_size);
......@@ -369,7 +368,7 @@ ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
{
struct buffer_head *bh = NULL;
struct ext3_xattr_entry *entry;
unsigned int size = 0;
size_t size = 0;
char *buf, *end;
int error;
......@@ -478,8 +477,8 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
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;
size_t name_len, free, min_offs = sb->s_blocksize;
int not_found = 1, error;
char *end;
/*
......@@ -536,7 +535,7 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
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);
size_t offs = le16_to_cpu(here->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
......@@ -556,7 +555,7 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
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);
size_t offs = le16_to_cpu(last->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
......@@ -580,25 +579,23 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
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);
size_t 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_LEN(name_len);
}
free -= EXT3_XATTR_SIZE(value_len);
error = -ENOSPC;
if (free < 0)
if (free < EXT3_XATTR_LEN(name_len) + EXT3_XATTR_SIZE(value_len))
goto cleanup;
/* Here we know that we can set the new attribute. */
......@@ -639,8 +636,8 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
if (not_found) {
/* Insert the new name. */
int size = EXT3_XATTR_LEN(name_len);
int rest = (char *)last - (char *)here;
size_t size = EXT3_XATTR_LEN(name_len);
size_t rest = (char *)last - (char *)here;
memmove((char *)here + size, here, rest);
memset(here, 0, size);
here->e_name_index = name_index;
......@@ -650,7 +647,7 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
/* 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);
size_t 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));
......@@ -662,7 +659,7 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
/* Adjust all value offsets. */
last = ENTRY(header+1);
while (!IS_LAST_ENTRY(last)) {
int o = le16_to_cpu(last->e_value_offs);
size_t o = le16_to_cpu(last->e_value_offs);
if (!last->e_value_block && o < offs)
last->e_value_offs =
cpu_to_le16(o + size);
......@@ -678,7 +675,7 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
goto cleanup;
} else {
/* Remove the old name. */
int size = EXT3_XATTR_LEN(name_len);
size_t size = EXT3_XATTR_LEN(name_len);
last = ENTRY((char *)last - size);
memmove(here, (char*)here + size,
(char*)last - (char*)here);
......@@ -733,9 +730,9 @@ ext3_xattr_set_handle2(handle_t *handle, struct inode *inode,
* The old block will be released after updating
* the inode.
*/
ea_bdebug(new_bh, "%s block %ld",
ea_bdebug(new_bh, "%s block %lu",
(old_bh == new_bh) ? "keeping" : "reusing",
new_bh->b_blocknr);
(unsigned long) new_bh->b_blocknr);
error = -EDQUOT;
if (DQUOT_ALLOC_BLOCK(inode, 1))
......@@ -895,8 +892,8 @@ ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
ext3_xattr_cache_remove(bh);
ext3_free_blocks(handle, inode, EXT3_I(inode)->i_file_acl, 1);
get_bh(bh);
ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
bh = NULL;
} else {
HDR(bh)->h_refcount = cpu_to_le32(
le32_to_cpu(HDR(bh)->h_refcount) - 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment