📄 ext3-ea-in-inode-2.6-suse.patch
字号:
+ !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, 0);+ 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;+ }++ 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;+ }+ + 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@@ -470,6 +959,104 @@ */ 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)+{+ 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;+ down_write(&EXT3_I(inode)->xattr_sem);++ /* 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: + 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) {@@ -492,22 +1078,7 @@ * 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);@@ -733,7 +1304,6 @@ brelse(bh); if (!(bh && header == HDR(bh))) kfree(header);- up_write(&EXT3_I(inode)->xattr_sem); return error; }Index: linux-2.6.0/fs/ext3/xattr.h===================================================================--- linux-2.6.0.orig/fs/ext3/xattr.h 2003-06-24 18:04:43.000000000 +0400+++ linux-2.6.0/fs/ext3/xattr.h 2004-01-14 18:54:12.000000000 +0300@@ -77,7 +77,8 @@ 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_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 *);Index: linux-2.6.0/include/linux/ext3_fs.h===================================================================--- linux-2.6.0.orig/include/linux/ext3_fs.h 2004-01-14 18:54:11.000000000 +0300+++ linux-2.6.0/include/linux/ext3_fs.h 2004-01-14 18:54:12.000000000 +0300@@ -265,6 +265,8 @@ __u32 m_i_reserved2[2]; } masix2; } osd2; /* OS dependent 2 */+ __u16 i_extra_isize;+ __u16 i_pad1; }; #define i_size_high i_dir_acl@@ -721,6 +723,7 @@ extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, 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 *);+int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc, int in_mem); extern void ext3_read_inode (struct inode *); extern void ext3_write_inode (struct inode *, int);Index: linux-2.6.0/include/linux/ext3_fs_i.h===================================================================--- linux-2.6.0.orig/include/linux/ext3_fs_i.h 2003-12-30 08:32:44.000000000 +0300+++ linux-2.6.0/include/linux/ext3_fs_i.h 2004-01-14 18:54:12.000000000 +0300@@ -96,6 +96,9 @@ */ 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%diffstat fs/ext3/ialloc.c | 5 fs/ext3/inode.c | 10 fs/ext3/xattr.c | 634 +++++++++++++++++++++++++++++++++++++++++++--- fs/ext3/xattr.h | 3 include/linux/ext3_fs.h | 2 include/linux/ext3_fs_i.h | 3 6 files changed, 623 insertions(+), 34 deletions(-)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -