Whamcloud - gitweb
b=4336
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-extents-in-ea-2.4.21-suse2.patch
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
5 @@ -0,0 +1,224 @@
6 +/*
7 + * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
8 + * Written by Alex Tomas <alex@clusterfs.com>
9 + *
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.
13 + *
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.
18 + *
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-
22 + */
23 +
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>
38 +
39 +static int ext3_get_ea_write_access(handle_t *handle, void *buffer)
40 +{
41 +       struct buffer_head *bh = (struct buffer_head *) buffer;
42 +       return ext3_journal_get_write_access(handle, bh);
43 +}
44 +
45 +static int ext3_mark_ea_buffer_dirty(handle_t *handle, void *buffer)
46 +{
47 +       struct buffer_head *bh = (struct buffer_head *) buffer;
48 +       ext3_journal_dirty_metadata(handle, bh);
49 +       return 0;
50 +}
51 +
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,
55 +       .mergable               = NULL,
56 +       .new_block              = NULL,
57 +       .remove_extent          = NULL,
58 +       .remove_extent_credits  = NULL,
59 +};
60 +
61 +int ext3_init_tree_in_ea_desc(struct ext3_extents_tree *tree,
62 +                               struct inode *inode, int name_index,
63 +                               const char *eaname)
64 +{
65 +       struct buffer_head *bh;
66 +       int offset, err, size;
67 +
68 +       err = ext3_xattr_get_ea_loc(inode, name_index, eaname,
69 +                                       &bh, &offset, &size);
70 +       if (err)
71 +               return err;
72 +
73 +       EXT_ASSERT(bh);
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 */
82 +       return 0;
83 +}
84 +
85 +void ext3_release_tree_in_ea_desc(struct ext3_extents_tree *tree)
86 +{
87 +       struct buffer_head *bh;
88 +
89 +       bh = (struct buffer_head *) tree->buffer;
90 +       EXT_ASSERT(bh);
91 +       brelse(bh);
92 +}
93 +
94 +int ext3_init_tree_in_ea(struct inode *inode, int name_index,
95 +                               const char *eaname, int size)
96 +{
97 +       struct ext3_extents_tree tree;
98 +       handle_t *handle;
99 +       char *root;
100 +       int err;
101 +
102 +       root = kmalloc(size, GFP_USER);
103 +       if (!root)
104 +               return -ENOMEM;
105 +       memset(root, 0, size);
106 +
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)))
113 +               goto out;
114 +       if ((err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname)))
115 +               goto out;
116 +       err = ext3_extent_tree_init(handle, &tree);
117 +       ext3_release_tree_in_ea_desc(&tree);
118 +out:
119 +       ext3_journal_stop(handle, inode);
120 +       kfree(root);
121 +       return err;
122 +}
123 +
124 +static int
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)
128 +{
129 +       struct inode *inode = tree->inode;
130 +       handle_t *handle;
131 +       int needed, err;
132 +       unsigned long tgen;
133 +
134 +       if (exist)
135 +               return EXT_CONTINUE;
136 +
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);
144 +       }
145 +
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);
150 +               return EXT_REPEAT;
151 +       }
152 +
153 +       down_write(&EXT3_I(inode)->truncate_sem);
154 +
155 +       /* insert new extent */
156 +       newex->ee_start = 0;
157 +       err = ext3_ext_insert_extent(handle, tree, path, newex);
158 +       if (!err)
159 +               ext3_journal_stop(handle, tree->inode);
160 +
161 +       return err;
162 +}
163 +
164 +int ext3_ext_in_ea_alloc_space(struct inode *inode, int name_index,
165 +                               const char *eaname, unsigned long from,
166 +                               unsigned long num)
167 +{
168 +       struct ext3_extents_tree tree;
169 +       int err;
170 +
171 +       err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
172 +       if (err == 0) {
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);
178 +       }
179 +       return err;
180 +}
181 +
182 +int ext3_ext_in_ea_remove_space(struct inode *inode, int name_index,
183 +                               const char *eaname, unsigned long from,
184 +                               unsigned long num)
185 +{
186 +       struct ext3_extents_tree tree;
187 +       int err;
188 +
189 +       err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
190 +       if (err == 0) {
191 +               err = ext3_ext_remove_space(&tree, from, num);
192 +               ext3_release_tree_in_ea_desc(&tree);
193 +       }
194 +       return err;
195 +}
196 +
197 +int ext3_ext_in_ea_presence(struct inode *inode, int name_index,
198 +                               const char *eaname, unsigned long block)
199 +{
200 +       struct ext3_extents_tree tree;
201 +       struct ext3_ext_path *path;
202 +       struct ext3_extent *ex;
203 +       int err, depth;
204 +
205 +       err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
206 +       if (err)
207 +               return err;
208 +
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);
213 +               goto out;
214 +       }
215 +
216 +       depth = EXT_DEPTH(&tree);
217 +       ex = path[depth].p_ext;
218 +       if (!ex) {
219 +               /* there is no extent yet */
220 +               goto out;
221 +       }
222 +
223 +       if (block >= ex->ee_block && block < ex->ee_block + ex->ee_len)
224 +               err = 1;
225 +out:
226 +       ext3_release_tree_in_ea_desc(&tree);
227 +       return err;
228 +}
229 +
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
234 @@ -19,7 +19,7 @@
235  obj-m    := $(O_TARGET)
236  
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
247 @@ -715,7 +715,8 @@
248                 return -ERANGE;
249  
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);
254         if (err == 0) {
255                 /* found EA in inode */
256                 found = 1;
257 @@ -724,7 +725,7 @@
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,
261 -                                               &entry, &free2);
262 +                                               &entry, &free2, NULL, NULL);
263                 if (err != 0 && err != -ENOENT) {
264                         /* not found EA in block */
265                         goto finish;    
266 @@ -780,6 +781,38 @@
267         return err;
268  }
269  
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)
273 + {
274 +       int free1 = -1, free2 = -1, err, name_len;
275 +       struct ext3_xattr_entry entry;
276 +       
277 +       ea_idebug(inode, "name=%d.%s", name_index, name);
278
279 +       if (name == NULL)
280 +               return -EINVAL;
281 +       name_len = strlen(name);
282 +       if (name_len > 255)
283 +               return -ERANGE;
284
285 +       down_write(&EXT3_I(inode)->xattr_sem);
286
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);
295 +       }
296 +       if (err == 0 && size)
297 +               *size = le32_to_cpu(entry.e_value_size);
298 +       up_write(&EXT3_I(inode)->xattr_sem);
299 +       return err;
300 + }
301 +
302  /*
303   * ext3_xattr_block_set()
304   *
305 @@ -1183,7 +1216,8 @@
306   */
307  int
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)
312  {
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));
319 +                       if (offset) {
320 +                               void *voff;
321 +                               voff = start + le16_to_cpu(last->e_value_offs);
322 +                               *offset = voff - (void *) iloc.bh->b_data;
323 +                       }
324 +                       if (bh) {
325 +                               get_bh(iloc.bh);        
326 +                               *bh = iloc.bh;
327 +                       }
328                         ret = 0;
329                 } else {
330                         *free -= EXT3_XATTR_LEN(last->e_name_len);
331 @@ -1250,7 +1293,8 @@
332   */
333  int
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)
338  {
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));
344                         error = 0;
345 +                       if (offset)
346 +                               *offset = le16_to_cpu(entry->e_value_offs);
347 +                       if (tbh) {
348 +                               get_bh(bh);     
349 +                               *tbh = bh;
350 +                       }
351                 } else {
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
358 @@ -84,6 +84,7 @@
359                           size_t, int);
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 *);
363  
364  extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
365  extern void ext3_xattr_put_super(struct super_block *);