1 Index: linux-2.4.21-suse2/fs/ext3/extents-in-ea.c
2 ===================================================================
3 --- linux-2.4.21-suse2.orig/fs/ext3/extents-in-ea.c 2003-01-30 13:24:37.000000000 +0300
4 +++ linux-2.4.21-suse2/fs/ext3/extents-in-ea.c 2004-08-19 16:45:44.000000000 +0400
7 + * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
8 + * Written by Alex Tomas <alex@clusterfs.com>
10 + * This program is free software; you can redistribute it and/or modify
11 + * it under the terms of the GNU General Public License version 2 as
12 + * published by the Free Software Foundation.
14 + * This program is distributed in the hope that it will be useful,
15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 + * GNU General Public License for more details.
19 + * You should have received a copy of the GNU General Public Licens
20 + * along with this program; if not, write to the Free Software
21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
24 +#include <linux/module.h>
25 +#include <linux/fs.h>
26 +#include <linux/time.h>
27 +#include <linux/ext3_jbd.h>
28 +#include <linux/jbd.h>
29 +#include <linux/smp_lock.h>
30 +#include <linux/highuid.h>
31 +#include <linux/pagemap.h>
32 +#include <linux/quotaops.h>
33 +#include <linux/string.h>
34 +#include <linux/ext3_extents.h>
35 +#include <linux/ext3_xattr.h>
36 +#include <linux/slab.h>
37 +#include <asm/uaccess.h>
39 +static int ext3_get_ea_write_access(handle_t *handle, void *buffer)
41 + struct buffer_head *bh = (struct buffer_head *) buffer;
42 + return ext3_journal_get_write_access(handle, bh);
45 +static int ext3_mark_ea_buffer_dirty(handle_t *handle, void *buffer)
47 + struct buffer_head *bh = (struct buffer_head *) buffer;
48 + ext3_journal_dirty_metadata(handle, bh);
52 +static struct ext3_extents_helpers ext3_ea_helpers = {
53 + .get_write_access = ext3_get_ea_write_access,
54 + .mark_buffer_dirty = ext3_mark_ea_buffer_dirty,
57 + .remove_extent = NULL,
58 + .remove_extent_credits = NULL,
61 +int ext3_init_tree_in_ea_desc(struct ext3_extents_tree *tree,
62 + struct inode *inode, int name_index,
65 + struct buffer_head *bh;
66 + int offset, err, size;
68 + err = ext3_xattr_get_ea_loc(inode, name_index, eaname,
69 + &bh, &offset, &size);
74 + EXT_ASSERT(size >= sizeof(struct ext3_extent_header)
75 + + sizeof(struct ext3_extent));
76 + tree->inode = inode;
77 + tree->root = (void *) bh->b_data + offset;
78 + tree->buffer_len = size;
79 + tree->buffer = (void *) bh;
80 + tree->ops = &ext3_ea_helpers;
81 + tree->cex = NULL; /* FIXME: add cache store later */
85 +void ext3_release_tree_in_ea_desc(struct ext3_extents_tree *tree)
87 + struct buffer_head *bh;
89 + bh = (struct buffer_head *) tree->buffer;
94 +int ext3_init_tree_in_ea(struct inode *inode, int name_index,
95 + const char *eaname, int size)
97 + struct ext3_extents_tree tree;
102 + root = kmalloc(size, GFP_USER);
105 + memset(root, 0, size);
107 + /* first, create ea to store root of the tree */
108 + handle = ext3_journal_start(inode, EXT3_ALLOC_NEEDED + 3);
109 + if (IS_ERR(handle))
110 + return PTR_ERR(handle);
111 + if ((err = ext3_xattr_set(handle, inode, name_index,
112 + eaname, root, size, 0)))
114 + if ((err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname)))
116 + err = ext3_extent_tree_init(handle, &tree);
117 + ext3_release_tree_in_ea_desc(&tree);
119 + ext3_journal_stop(handle, inode);
125 +ext3_ext_in_ea_new_extent(struct ext3_extents_tree *tree,
126 + struct ext3_ext_path *path,
127 + struct ext3_extent *newex, int exist)
129 + struct inode *inode = tree->inode;
132 + unsigned long tgen;
135 + return EXT_CONTINUE;
137 + tgen = EXT_GENERATION(tree);
138 + needed = ext3_ext_calc_credits_for_insert(tree, path);
139 + up_write(&EXT3_I(inode)->truncate_sem);
140 + handle = ext3_journal_start(tree->inode, needed + 10);
141 + if (IS_ERR(handle)) {
142 + down_write(&EXT3_I(inode)->truncate_sem);
143 + return PTR_ERR(handle);
146 + if (tgen != EXT_GENERATION(tree)) {
147 + /* the tree has changed. so path can be invalid at moment */
148 + ext3_journal_stop(handle, inode);
149 + down_write(&EXT3_I(inode)->truncate_sem);
153 + down_write(&EXT3_I(inode)->truncate_sem);
155 + /* insert new extent */
156 + newex->ee_start = 0;
157 + err = ext3_ext_insert_extent(handle, tree, path, newex);
159 + ext3_journal_stop(handle, tree->inode);
164 +int ext3_ext_in_ea_alloc_space(struct inode *inode, int name_index,
165 + const char *eaname, unsigned long from,
168 + struct ext3_extents_tree tree;
171 + err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
173 + down_write(&EXT3_I(inode)->truncate_sem);
174 + err = ext3_ext_walk_space(&tree, from, num,
175 + ext3_ext_in_ea_new_extent);
176 + ext3_release_tree_in_ea_desc(&tree);
177 + up_write(&EXT3_I(inode)->truncate_sem);
182 +int ext3_ext_in_ea_remove_space(struct inode *inode, int name_index,
183 + const char *eaname, unsigned long from,
186 + struct ext3_extents_tree tree;
189 + err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
191 + err = ext3_ext_remove_space(&tree, from, num);
192 + ext3_release_tree_in_ea_desc(&tree);
197 +int ext3_ext_in_ea_presence(struct inode *inode, int name_index,
198 + const char *eaname, unsigned long block)
200 + struct ext3_extents_tree tree;
201 + struct ext3_ext_path *path;
202 + struct ext3_extent *ex;
205 + err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
209 + /* find extent for this block */
210 + path = ext3_ext_find_extent(&tree, block, NULL);
211 + if (IS_ERR(path)) {
212 + err = PTR_ERR(path);
216 + depth = EXT_DEPTH(&tree);
217 + ex = path[depth].p_ext;
219 + /* there is no extent yet */
223 + if (block >= ex->ee_block && block < ex->ee_block + ex->ee_len)
226 + ext3_release_tree_in_ea_desc(&tree);
230 Index: linux-2.4.21-suse2/fs/ext3/Makefile
231 ===================================================================
232 --- linux-2.4.21-suse2.orig/fs/ext3/Makefile 2004-08-19 13:51:49.000000000 +0400
233 +++ linux-2.4.21-suse2/fs/ext3/Makefile 2004-08-19 16:45:44.000000000 +0400
237 export-objs += xattr.o
238 -obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
239 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o extents-in-ea.o
240 obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
241 obj-$(CONFIG_EXT3_FS_XATTR_TRUSTED) += xattr_trusted.o
242 obj-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
243 Index: linux-2.4.21-suse2/fs/ext3/xattr.c
244 ===================================================================
245 --- linux-2.4.21-suse2.orig/fs/ext3/xattr.c 2004-08-19 13:51:48.000000000 +0400
246 +++ linux-2.4.21-suse2/fs/ext3/xattr.c 2004-08-19 17:12:21.000000000 +0400
250 /* try to find attribute in inode body */
251 - err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
252 + err = ext3_xattr_ibody_find(inode, name_index, name,
253 + &entry, &free1, NULL, NULL);
255 /* found EA in inode */
258 /* there is no such attribute in inode body */
259 /* try to find attribute in dedicated block */
260 err = ext3_xattr_block_find(inode, name_index, name,
262 + &entry, &free2, NULL, NULL);
263 if (err != 0 && err != -ENOENT) {
264 /* not found EA in block */
270 +int ext3_xattr_get_ea_loc(struct inode *inode, int name_index,
271 + const char *name, struct buffer_head **bh,
272 + int *offset, int *size)
274 + int free1 = -1, free2 = -1, err, name_len;
275 + struct ext3_xattr_entry entry;
277 + ea_idebug(inode, "name=%d.%s", name_index, name);
281 + name_len = strlen(name);
282 + if (name_len > 255)
285 + down_write(&EXT3_I(inode)->xattr_sem);
287 + /* try to find attribute in inode body */
288 + err = ext3_xattr_ibody_find(inode, name_index, name,
289 + &entry, &free1, bh, offset);
290 + if (err == -ENOENT) {
291 + /* there is no such attribute in inode body */
292 + /* try to find attribute in dedicated block */
293 + err = ext3_xattr_block_find(inode, name_index, name,
294 + &entry, &free2, bh, offset);
296 + if (err == 0 && size)
297 + *size = le32_to_cpu(entry.e_value_size);
298 + up_write(&EXT3_I(inode)->xattr_sem);
303 * ext3_xattr_block_set()
305 @@ -1183,7 +1216,8 @@
308 ext3_xattr_ibody_find(struct inode *inode, int name_index,
309 - const char *name, struct ext3_xattr_entry *rentry, int *free)
310 + const char *name, struct ext3_xattr_entry *rentry, int *free,
311 + struct buffer_head **bh, int *offset)
313 struct ext3_xattr_entry *last;
314 struct ext3_inode *raw_inode;
315 @@ -1230,6 +1264,15 @@
316 name_len == last->e_name_len &&
317 !memcmp(name, last->e_name, name_len)) {
318 memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
321 + voff = start + le16_to_cpu(last->e_value_offs);
322 + *offset = voff - (void *) iloc.bh->b_data;
330 *free -= EXT3_XATTR_LEN(last->e_name_len);
331 @@ -1250,7 +1293,8 @@
334 ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
335 - struct ext3_xattr_entry *rentry, int *free)
336 + struct ext3_xattr_entry *rentry, int *free,
337 + struct buffer_head **tbh, int *offset)
339 struct buffer_head *bh = NULL;
340 struct ext3_xattr_entry *entry;
341 @@ -1293,6 +1337,12 @@
342 memcmp(name, entry->e_name, name_len) == 0) {
343 memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
346 + *offset = le16_to_cpu(entry->e_value_offs);
352 *free -= EXT3_XATTR_LEN(entry->e_name_len);
353 *free -= le32_to_cpu(entry->e_value_size);
354 Index: linux-2.4.21-suse2/include/linux/ext3_xattr.h
355 ===================================================================
356 --- linux-2.4.21-suse2.orig/include/linux/ext3_xattr.h 2004-08-19 13:50:00.000000000 +0400
357 +++ linux-2.4.21-suse2/include/linux/ext3_xattr.h 2004-08-19 16:45:44.000000000 +0400
360 extern int ext3_xattr_set(handle_t *, struct inode *, int, const char *,
361 const void *, size_t, int);
362 +extern int ext3_xattr_get_ea_loc(struct inode *, int, const char *, struct buffer_head **, int *, int *);
364 extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
365 extern void ext3_xattr_put_super(struct super_block *);