Whamcloud - gitweb
landing b_cmobd_merge on HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-extents-in-ea-2.4.20.patch
1 Index: linux-2.4.20/fs/ext3/extents-in-ea.c
2 ===================================================================
3 --- linux-2.4.20.orig/fs/ext3/extents-in-ea.c   2004-05-06 23:03:39.000000000 -0700
4 +++ linux-2.4.20/fs/ext3/extents-in-ea.c        2004-05-06 23:03:39.000000000 -0700
5 @@ -0,0 +1,202 @@
6 +/*
7 + * Copyright (C) 2003 Alex Tomas <alex@clusterfs.com>
8 + *
9 + * This program is free software; you can redistribute it and/or modify
10 + * it under the terms of the GNU General Public License version 2 as
11 + * published by the Free Software Foundation.
12 + *
13 + * This program is distributed in the hope that it will be useful,
14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 + * GNU General Public License for more details.
17 + *
18 + * You should have received a copy of the GNU General Public Licens
19 + * along with this program; if not, write to the Free Software
20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
21 + */
22 +
23 +#include <linux/module.h>
24 +#include <linux/fs.h>
25 +#include <linux/time.h>
26 +#include <linux/ext3_jbd.h>
27 +#include <linux/jbd.h>
28 +#include <linux/smp_lock.h>
29 +#include <linux/highuid.h>
30 +#include <linux/pagemap.h>
31 +#include <linux/quotaops.h>
32 +#include <linux/string.h>
33 +#include <linux/ext3_extents.h>
34 +#include <linux/ext3_xattr.h>
35 +#include <linux/slab.h>
36 +#include <asm/uaccess.h>
37 +
38 +static int ext3_get_ea_write_access(handle_t *handle, void *buffer)
39 +{
40 +       struct buffer_head *bh = (struct buffer_head *) buffer;
41 +       return ext3_journal_get_write_access(handle, bh);
42 +}
43 +
44 +static int ext3_mark_ea_buffer_dirty(handle_t *handle, void *buffer)
45 +{
46 +       struct buffer_head *bh = (struct buffer_head *) buffer;
47 +       ext3_journal_dirty_metadata(handle, bh);
48 +       return 0;
49 +}
50 +
51 +int ext3_init_tree_in_ea_desc(struct ext3_extents_tree *tree,
52 +                               struct inode *inode, int name_index,
53 +                               const char *eaname)
54 +{
55 +       struct buffer_head *bh;
56 +       int offset, err, size;
57 +
58 +       err = ext3_xattr_get_ea_loc(inode, name_index, eaname,
59 +                                       &bh, &offset, &size);
60 +       if (err)
61 +               return err;
62 +
63 +       EXT_ASSERT(bh);
64 +       EXT_ASSERT(size >= sizeof(struct ext3_extent_header)
65 +                               + sizeof(struct ext3_extent));
66 +       tree->inode = inode;
67 +       tree->root = (void *) bh->b_data + offset;
68 +       tree->buffer_len = size;
69 +       tree->buffer = (void *) bh;
70 +       tree->get_write_access = ext3_get_ea_write_access;
71 +       tree->mark_buffer_dirty = ext3_mark_ea_buffer_dirty;
72 +       tree->mergable = NULL;
73 +       tree->remove_extent = NULL;
74 +       tree->remove_extent_credits = NULL;
75 +       tree->new_block = NULL;
76 +       tree->cex = NULL;       /* FIXME: add cache store later */
77 +       return 0;
78 +}
79 +
80 +void ext3_release_tree_in_ea_desc(struct ext3_extents_tree *tree)
81 +{
82 +       struct buffer_head *bh;
83 +
84 +       bh = (struct buffer_head *) tree->buffer;
85 +       EXT_ASSERT(bh);
86 +       brelse(bh);
87 +}
88 +
89 +int ext3_init_tree_in_ea(struct inode *inode, int name_index,
90 +                               const char *eaname, int size)
91 +{
92 +       struct ext3_extents_tree tree;
93 +       handle_t *handle;
94 +       char *root;
95 +       int err;
96 +
97 +       root = kmalloc(size, GFP_USER);
98 +       if (!root)
99 +               return -ENOMEM;
100 +       memset(root, 0, size);
101 +
102 +       /* first, create ea to store root of the tree */
103 +       handle = ext3_journal_start(inode, EXT3_ALLOC_NEEDED + 2);
104 +       if (IS_ERR(handle))
105 +               return PTR_ERR(handle);
106 +       if ((err = ext3_xattr_set(handle, inode, name_index,
107 +                                       eaname, root, size, 0)))
108 +               goto out;
109 +       if ((err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname)))
110 +               goto out;
111 +       err = ext3_extent_tree_init(handle, &tree);
112 +       ext3_release_tree_in_ea_desc(&tree);
113 +out:
114 +       ext3_journal_stop(handle, inode);
115 +       kfree(root);
116 +       return err;
117 +}
118 +
119 +static int
120 +ext3_ext_in_ea_new_extent(struct ext3_extents_tree *tree,
121 +                       struct ext3_ext_path *path,
122 +                       struct ext3_extent *newex, int exist)
123 +{
124 +       handle_t *handle;
125 +       int needed, err;
126 +
127 +       if (exist)
128 +               return EXT_CONTINUE;
129 +
130 +       needed = ext3_ext_calc_credits_for_insert(tree, path);
131 +       handle = ext3_journal_start(tree->inode, needed);
132 +       if (IS_ERR(handle))
133 +               return PTR_ERR(handle);
134 +
135 +       /* insert new extent */
136 +       newex->e_start = 0;
137 +       err = ext3_ext_insert_extent(handle, tree, path, newex);
138 +       if (!err)
139 +               ext3_journal_stop(handle, tree->inode);
140 +
141 +       return err;
142 +}
143 +
144 +int ext3_ext_in_ea_alloc_space(struct inode *inode, int name_index,
145 +                               const char *eaname, unsigned long from,
146 +                               unsigned long num)
147 +{
148 +       struct ext3_extents_tree tree;
149 +       int err;
150 +
151 +       err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
152 +       if (err == 0) {
153 +               err = ext3_ext_walk_space(&tree, from, num,
154 +                                               ext3_ext_in_ea_new_extent);
155 +               ext3_release_tree_in_ea_desc(&tree);
156 +       }
157 +       return err;
158 +}
159 +
160 +int ext3_ext_in_ea_remove_space(struct inode *inode, int name_index,
161 +                               const char *eaname, unsigned long from,
162 +                               unsigned long num)
163 +{
164 +       struct ext3_extents_tree tree;
165 +       int err;
166 +
167 +       err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
168 +       if (err == 0) {
169 +               err = ext3_ext_remove_space(&tree, from, num);
170 +               ext3_release_tree_in_ea_desc(&tree);
171 +       }
172 +       return err;
173 +}
174 +
175 +int ext3_ext_in_ea_presence(struct inode *inode, int name_index,
176 +                               const char *eaname, unsigned long block)
177 +{
178 +       struct ext3_extents_tree tree;
179 +       struct ext3_ext_path *path;
180 +       struct ext3_extent *ex;
181 +       int err, depth;
182 +
183 +       err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
184 +       if (err)
185 +               return err;
186 +
187 +       /* find extent for this block */
188 +       path = ext3_ext_find_extent(&tree, block, NULL);
189 +       if (IS_ERR(path)) {
190 +               err = PTR_ERR(path);
191 +               goto out;
192 +       }
193 +
194 +       depth = EXT_DEPTH(&tree);
195 +       ex = path[depth].p_ext;
196 +       if (!ex) {
197 +               /* there is no extent yet */
198 +               goto out;
199 +       }
200 +
201 +       if (block >= ex->e_block && block < ex->e_block + ex->e_num)
202 +               err = 1;
203 +out:
204 +       ext3_release_tree_in_ea_desc(&tree);
205 +       return err;
206 +}
207 +
208 Index: linux-2.4.20/fs/ext3/Makefile
209 ===================================================================
210 --- linux-2.4.20.orig/fs/ext3/Makefile  2004-05-06 23:02:11.000000000 -0700
211 +++ linux-2.4.20/fs/ext3/Makefile       2004-05-06 23:03:39.000000000 -0700
212 @@ -19,7 +19,7 @@
213  obj-m    := $(O_TARGET)
214  
215  export-objs += xattr.o
216 -obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
217 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o extents-in-ea.o
218  obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
219  
220  include $(TOPDIR)/Rules.make
221 Index: linux-2.4.20/fs/ext3/xattr.c
222 ===================================================================
223 --- linux-2.4.20.orig/fs/ext3/xattr.c   2004-05-06 23:02:11.000000000 -0700
224 +++ linux-2.4.20/fs/ext3/xattr.c        2004-05-06 23:05:20.000000000 -0700
225 @@ -771,7 +771,8 @@
226   */
227  int
228  ext3_xattr_ibody_find(struct inode *inode, int name_index,
229 -               const char *name, struct ext3_xattr_entry *rentry, int *free)
230 +               const char *name, struct ext3_xattr_entry *rentry, int *free,
231 +               struct buffer_head **bh, int *offset)
232  {
233         struct ext3_xattr_entry *last;
234         struct ext3_inode *raw_inode;
235 @@ -818,6 +819,15 @@
236                     name_len == last->e_name_len &&
237                     !memcmp(name, last->e_name, name_len)) {
238                         memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
239 +                       if (offset) {
240 +                               void *voff;
241 +                               voff = start + le16_to_cpu(last->e_value_offs);
242 +                               *offset = voff - (void *) iloc.bh->b_data;
243 +                       }
244 +                       if (bh) {
245 +                               get_bh(iloc.bh);        
246 +                               *bh = iloc.bh;
247 +                       }
248                         ret = 0;
249                 } else {
250                         *free -= EXT3_XATTR_LEN(last->e_name_len);
251 @@ -838,7 +848,8 @@
252   */
253  int
254  ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
255 -              struct ext3_xattr_entry *rentry, int *free)
256 +              struct ext3_xattr_entry *rentry, int *free,
257 +              struct buffer_head **tbh, int *offset)
258  {
259         struct buffer_head *bh = NULL;
260         struct ext3_xattr_entry *entry;
261 @@ -881,6 +892,12 @@
262                     memcmp(name, entry->e_name, name_len) == 0) {
263                         memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
264                         error = 0;
265 +                       if (offset)
266 +                               *offset = le16_to_cpu(entry->e_value_offs);
267 +                       if (tbh) {
268 +                               get_bh(bh);     
269 +                               *tbh = bh;
270 +                       }
271                 } else {
272                         *free -= EXT3_XATTR_LEN(entry->e_name_len);
273                         *free -= le32_to_cpu(entry->e_value_size);
274 @@ -1073,7 +1090,8 @@
275                 return -ERANGE;
276  
277         /* try to find attribute in inode body */
278 -       err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
279 +       err = ext3_xattr_ibody_find(inode, name_index, name,
280 +                                       &entry, &free1, NULL, NULL);
281         if (err == 0) {
282                 /* found EA in inode */
283                 found = 1;
284 @@ -1082,7 +1100,7 @@
285                 /* there is no such attribute in inode body */
286                 /* try to find attribute in dedicated block */
287                 err = ext3_xattr_block_find(inode, name_index, name,
288 -                                               &entry, &free2);
289 +                                               &entry, &free2, NULL, NULL);
290                 if (err != 0 && err != -ENOENT) {
291                         /* not found EA in block */
292                         goto finish;    
293 @@ -1138,6 +1156,38 @@
294         return err;
295  }
296  
297 +int ext3_xattr_get_ea_loc(struct inode *inode, int name_index,
298 +                               const char *name, struct buffer_head **bh,
299 +                               int *offset, int *size)
300 +{
301 +       int free1 = -1, free2 = -1, err, name_len;
302 +       struct ext3_xattr_entry entry;
303 +       
304 +       ea_idebug(inode, "name=%d.%s", name_index, name);
305 +
306 +       if (name == NULL)
307 +               return -EINVAL;
308 +       name_len = strlen(name);
309 +       if (name_len > 255)
310 +               return -ERANGE;
311 +
312 +       down(&ext3_xattr_sem);
313 +
314 +       /* try to find attribute in inode body */
315 +       err = ext3_xattr_ibody_find(inode, name_index, name,
316 +                                       &entry, &free1, bh, offset);
317 +       if (err == -ENOENT) {
318 +               /* there is no such attribute in inode body */
319 +               /* try to find attribute in dedicated block */
320 +               err = ext3_xattr_block_find(inode, name_index, name,
321 +                                               &entry, &free2, bh, offset);
322 +       }
323 +       if (err == 0 && size)
324 +               *size = le32_to_cpu(entry.e_value_size);
325 +       up(&ext3_xattr_sem);
326 +       return err;
327 +}
328 +
329  /*
330   * ext3_xattr_block_set()
331   *
332 Index: linux-2.4.20/include/linux/ext3_xattr.h
333 ===================================================================
334 --- linux-2.4.20.orig/include/linux/ext3_xattr.h        2004-05-06 23:02:11.000000000 -0700
335 +++ linux-2.4.20/include/linux/ext3_xattr.h     2004-05-06 23:03:39.000000000 -0700
336 @@ -80,6 +80,7 @@
337  extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
338  extern int ext3_xattr_list(struct inode *, char *, size_t);
339  extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
340 +extern int ext3_xattr_get_ea_loc(struct inode *, int, const char *, struct buffer_head **, int *, int *);
341  
342  extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
343  extern void ext3_xattr_put_super(struct super_block *);