Whamcloud - gitweb
- landing of b_hd_cleanup_merge to HEAD.
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-ea-in-inode-2.4.24.patch
1  fs/ext3/ialloc.c          |    6 
2  fs/ext3/inode.c           |   12 
3  fs/ext3/super.c           |    6 
4  fs/ext3/xattr.c           |  597 +++++++++++++++++++++++++++++++++++++++++++++-
5  include/linux/ext3_fs.h   |    2 
6  include/linux/ext3_fs_i.h |    3 
7  6 files changed, 615 insertions(+), 11 deletions(-)
8
9 --- linux-2.4.22-ac1/fs/ext3/ialloc.c~ext3-ea-in-inode-2.4.22-rh        2003-10-08 13:57:56.000000000 +0400
10 +++ linux-2.4.22-ac1-alexey/fs/ext3/ialloc.c    2003-10-08 15:13:31.000000000 +0400
11 @@ -715,6 +715,12 @@ have_bit_and_group:
12         insert_inode_hash(inode);
13         inode->i_generation = sb->u.ext3_sb.s_next_generation++;
14  
15 +       if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
16 +               inode->u.ext3_i.i_extra_isize = sizeof(__u16)   /* i_extra_isize */
17 +                               + sizeof(__u16);        /* i_pad1 */
18 +       } else
19 +               inode->u.ext3_i.i_extra_isize = 0;
20 +
21         inode->u.ext3_i.i_state = EXT3_STATE_NEW;
22         err = ext3_get_inode_loc_new(inode, &iloc, 1);
23         if (err) goto fail;
24 --- linux-2.4.22-ac1/fs/ext3/inode.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:57.000000000 +0400
25 +++ linux-2.4.22-ac1-alexey/fs/ext3/inode.c     2003-10-08 15:14:57.000000000 +0400
26 @@ -2229,6 +2229,12 @@ void ext3_read_inode(struct inode * inod
27                 inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
28         INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
29  
30 +       if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
31 +               inode->u.ext3_i.i_extra_isize =
32 +                       le16_to_cpu(raw_inode->i_extra_isize);
33 +       else
34 +               inode->u.ext3_i.i_extra_isize = 0;
35 +
36         if (S_ISREG(inode->i_mode)) {
37                 inode->i_op = &ext3_file_inode_operations;
38                 inode->i_fop = &ext3_file_operations;
39 @@ -2277,6 +2283,8 @@ static int ext3_do_update_inode(handle_t
40                 if (err)
41                         goto out_brelse;
42         }
43 +       if (EXT3_I(inode)->i_state & EXT3_STATE_NEW)
44 +               memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb));
45         raw_inode->i_mode = cpu_to_le16(inode->i_mode);
46         if(!(test_opt(inode->i_sb, NO_UID32))) {
47                 raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
48 @@ -2360,6 +2368,10 @@ static int ext3_do_update_inode(handle_t
49         else for (block = 0; block < EXT3_N_BLOCKS; block++)
50                 raw_inode->i_block[block] = inode->u.ext3_i.i_data[block];
51  
52 +       if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
53 +               raw_inode->i_extra_isize =
54 +                       cpu_to_le16(EXT3_I(inode)->i_extra_isize);
55 +
56         BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
57         rc = ext3_journal_dirty_metadata(handle, bh);
58         if (!err)
59 --- linux-2.4.22-ac1/fs/ext3/super.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:57.000000000 +0400
60 +++ linux-2.4.22-ac1-alexey/fs/ext3/super.c     2003-10-08 15:13:31.000000000 +0400
61 @@ -1299,8 +1299,10 @@ struct super_block * ext3_read_super (st
62         } else {
63                 sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
64                 sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
65 -               if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) {
66 -                       printk (KERN_ERR
67 +               if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
68 +                               (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
69 +                               (sbi->s_inode_size > blocksize)) {
70 +                       printk (KERN_ERR
71                                 "EXT3-fs: unsupported inode size: %d\n",
72                                 sbi->s_inode_size);
73                         goto failed_mount;
74 --- linux-2.4.22-ac1/fs/ext3/xattr.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:56.000000000 +0400
75 +++ linux-2.4.22-ac1-alexey/fs/ext3/xattr.c     2003-10-12 16:36:07.000000000 +0400
76 @@ -100,6 +100,9 @@
77  static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
78                            struct ext3_xattr_header *);
79  
80 +int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,
81 +                       const void *, size_t, int);
82 +
83  #ifdef CONFIG_EXT3_FS_XATTR_SHARING
84  
85  static int ext3_xattr_cache_insert(struct buffer_head *);
86 @@ -348,17 +351,12 @@ ext3_removexattr(struct dentry *dentry, 
87  }
88  
89  /*
90 - * ext3_xattr_get()
91 - *
92 - * Copy an extended attribute into the buffer
93 - * provided, or compute the buffer size required.
94 - * Buffer is NULL to compute the size of the buffer required.
95 + * ext3_xattr_block_get()
96   *
97 - * Returns a negative error number on failure, or the number of bytes
98 - * used / required on success.
99 + * routine looks for attribute in EA block and returns it's value and size
100   */
101  int
102 -ext3_xattr_get(struct inode *inode, int name_index, const char *name,
103 +ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
104                void *buffer, size_t buffer_size)
105  {
106         struct buffer_head *bh = NULL;
107 @@ -447,6 +445,94 @@ cleanup:
108  }
109  
110  /*
111 + * ext3_xattr_ibode_get()
112 + *
113 + * routine looks for attribute in inode body and returns it's value and size
114 + */
115 +int
116 +ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
117 +              void *buffer, size_t buffer_size)
118 +{
119 +       int size, name_len = strlen(name), storage_size;
120 +       struct ext3_xattr_entry *last;
121 +       struct ext3_inode *raw_inode;
122 +       struct ext3_iloc iloc;
123 +       char *start, *end;
124 +       int ret = -ENOENT;
125 +       
126 +       if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
127 +               return -ENOENT;
128 +
129 +       ret = ext3_get_inode_loc(inode, &iloc);
130 +       if (ret)
131 +               return ret;
132 +       raw_inode = iloc.raw_inode;
133 +
134 +       storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
135 +                               EXT3_GOOD_OLD_INODE_SIZE -
136 +                               EXT3_I(inode)->i_extra_isize -
137 +                               sizeof(__u32);
138 +       start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
139 +                       EXT3_I(inode)->i_extra_isize;
140 +       if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
141 +               brelse(iloc.bh);
142 +               return -ENOENT;
143 +       }
144 +       start += sizeof(__u32);
145 +       end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
146 +
147 +       last = (struct ext3_xattr_entry *) start;
148 +       while (!IS_LAST_ENTRY(last)) {
149 +               struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
150 +               if (le32_to_cpu(last->e_value_size) > storage_size ||
151 +                               (char *) next >= end) {
152 +                       ext3_error(inode->i_sb, "ext3_xattr_ibody_get",
153 +                               "inode %ld", inode->i_ino);
154 +                       brelse(iloc.bh);
155 +                       return -EIO;
156 +               }
157 +               if (name_index == last->e_name_index &&
158 +                   name_len == last->e_name_len &&
159 +                   !memcmp(name, last->e_name, name_len))
160 +                       goto found;
161 +               last = next;
162 +       }
163 +
164 +       /* can't find EA */
165 +       brelse(iloc.bh);
166 +       return -ENOENT;
167 +       
168 +found:
169 +       size = le32_to_cpu(last->e_value_size);
170 +       if (buffer) {
171 +               ret = -ERANGE;
172 +               if (buffer_size >= size) {
173 +                       memcpy(buffer, start + le16_to_cpu(last->e_value_offs),
174 +                       size);
175 +                       ret = size;
176 +               }
177 +       } else
178 +               ret = size;
179 +       brelse(iloc.bh);
180 +       return ret;
181 +}
182 +
183 +int ext3_xattr_get(struct inode *inode, int name_index, const char *name,
184 +                       void *buffer, size_t buffer_size)
185 +{
186 +       int err;
187 +
188 +       /* try to find attribute in inode body */
189 +       err = ext3_xattr_ibody_get(inode, name_index, name,
190 +                                       buffer, buffer_size);
191 +       if (err < 0)
192 +               /* search was unsuccessful, try to find EA in dedicated block */
193 +               err = ext3_xattr_block_get(inode, name_index, name,
194 +                               buffer, buffer_size);
195 +       return err;
196 +}
197 +
198 +/*
199   * ext3_xattr_list()
200   *
201   * Copy a list of attribute names into the buffer
202 @@ -457,7 +543,7 @@ cleanup:
203   * used / required on success.
204   */
205  int
206 -ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
207 +ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
208  {
209         struct buffer_head *bh = NULL;
210         struct ext3_xattr_entry *entry;
211 @@ -530,6 +616,131 @@ cleanup:
212         return error;
213  }
214  
215 +/* ext3_xattr_ibody_list()
216 + *
217 + * generate list of attributes stored in inode body
218 + */
219 +int
220 +ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
221 +{
222 +       struct ext3_xattr_entry *last;
223 +       struct ext3_inode *raw_inode;
224 +       char *start, *end, *buf;
225 +       struct ext3_iloc iloc;
226 +       int storage_size;
227 +       int ret;
228 +       int size = 0;
229 +       
230 +       if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
231 +               return 0;
232 +
233 +       ret = ext3_get_inode_loc(inode, &iloc);
234 +       if (ret)
235 +               return ret;
236 +       raw_inode = iloc.raw_inode;
237 +
238 +       storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
239 +                               EXT3_GOOD_OLD_INODE_SIZE -
240 +                               EXT3_I(inode)->i_extra_isize -
241 +                               sizeof(__u32);
242 +       start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
243 +                       EXT3_I(inode)->i_extra_isize;
244 +       if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
245 +               brelse(iloc.bh);
246 +               return 0;
247 +       }
248 +       start += sizeof(__u32);
249 +       end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
250 +
251 +       last = (struct ext3_xattr_entry *) start;
252 +       while (!IS_LAST_ENTRY(last)) {
253 +               struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
254 +               struct ext3_xattr_handler *handler;
255 +               if (le32_to_cpu(last->e_value_size) > storage_size ||
256 +                               (char *) next >= end) {
257 +                       ext3_error(inode->i_sb, "ext3_xattr_ibody_list",
258 +                               "inode %ld", inode->i_ino);
259 +                       brelse(iloc.bh);
260 +                       return -EIO;
261 +               }
262 +               handler = ext3_xattr_handler(last->e_name_index);
263 +               if (handler)
264 +                       size += handler->list(NULL, inode, last->e_name,
265 +                                             last->e_name_len);
266 +               last = next;
267 +       }
268 +
269 +       if (!buffer) {
270 +               ret = size;
271 +               goto cleanup;
272 +       } else {
273 +               ret = -ERANGE;
274 +               if (size > buffer_size)
275 +                       goto cleanup;
276 +       }
277 +
278 +       last = (struct ext3_xattr_entry *) start;
279 +       buf = buffer;
280 +       while (!IS_LAST_ENTRY(last)) {
281 +               struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
282 +               struct ext3_xattr_handler *handler;
283 +               handler = ext3_xattr_handler(last->e_name_index);
284 +               if (handler)
285 +                       buf += handler->list(buf, inode, last->e_name,
286 +                                             last->e_name_len);
287 +               last = next;
288 +       }
289 +       ret = size;
290 +cleanup:
291 +       brelse(iloc.bh);
292 +       return ret;
293 +}
294 +
295 +/*
296 + * ext3_xattr_list()
297 + *
298 + * Copy a list of attribute names into the buffer
299 + * provided, or compute the buffer size required.
300 + * Buffer is NULL to compute the size of the buffer required.
301 + *
302 + * Returns a negative error number on failure, or the number of bytes
303 + * used / required on success.
304 + */
305 +int
306 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
307 +{
308 +       int error;
309 +       int size = buffer_size;
310 +
311 +       /* get list of attributes stored in inode body */
312 +       error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
313 +       if (error < 0) {
314 +               /* some error occured while collecting
315 +                * attributes in inode body */
316 +               size = 0;
317 +               goto cleanup;
318 +       }
319 +       size = error;
320 +
321 +       /* get list of attributes stored in dedicated block */
322 +       if (buffer) {
323 +               buffer_size -= error;
324 +               if (buffer_size <= 0) {
325 +                       buffer = NULL;
326 +                       buffer_size = 0;
327 +               } else
328 +                       buffer += error;
329 +       }
330 +
331 +       error = ext3_xattr_block_list(inode, buffer, buffer_size);
332 +       if (error < 0)
333 +               /* listing was successful, so we return len */
334 +               size = 0;
335 +
336 +cleanup:
337 +       return error + size;
338 +}
339 +
340  /*
341   * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
342   * not set, set it.
343 @@ -553,6 +764,279 @@ static void ext3_xattr_update_super_bloc
344  }
345  
346  /*
347 + * ext3_xattr_ibody_find()
348 + *
349 + * search attribute and calculate free space in inode body
350 + * NOTE: free space includes space our attribute hold
351 + */
352 +int
353 +ext3_xattr_ibody_find(struct inode *inode, int name_index,
354 +               const char *name, struct ext3_xattr_entry *rentry, int *free)
355 +{
356 +       struct ext3_xattr_entry *last;
357 +       struct ext3_inode *raw_inode;
358 +       int name_len = strlen(name);
359 +       int err, storage_size;
360 +       struct ext3_iloc iloc;
361 +       char *start, *end;
362 +       int ret = -ENOENT;
363 +       
364 +       if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
365 +               return ret;
366 +
367 +       err = ext3_get_inode_loc(inode, &iloc);
368 +       if (err)
369 +               return -EIO;
370 +       raw_inode = iloc.raw_inode;
371 +
372 +       storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
373 +                               EXT3_GOOD_OLD_INODE_SIZE -
374 +                               EXT3_I(inode)->i_extra_isize -
375 +                               sizeof(__u32);
376 +       *free = storage_size - sizeof(__u32);
377 +       start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
378 +                       EXT3_I(inode)->i_extra_isize;
379 +       if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
380 +               brelse(iloc.bh);
381 +               return -ENOENT;
382 +       }
383 +       start += sizeof(__u32);
384 +       end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
385 +
386 +       last = (struct ext3_xattr_entry *) start;
387 +       while (!IS_LAST_ENTRY(last)) {
388 +               struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
389 +               if (le32_to_cpu(last->e_value_size) > storage_size ||
390 +                               (char *) next >= end) {
391 +                       ext3_error(inode->i_sb, "ext3_xattr_ibody_find",
392 +                               "inode %ld", inode->i_ino);
393 +                       brelse(iloc.bh);
394 +                       return -EIO;
395 +               }
396 +
397 +               if (name_index == last->e_name_index &&
398 +                   name_len == last->e_name_len &&
399 +                   !memcmp(name, last->e_name, name_len)) {
400 +                       memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
401 +                       ret = 0;
402 +               } else {
403 +                       *free -= EXT3_XATTR_LEN(last->e_name_len);
404 +                       *free -= le32_to_cpu(last->e_value_size);
405 +               }
406 +               last = next;
407 +       }
408 +       
409 +       brelse(iloc.bh);
410 +       return ret;
411 +}
412 +
413 +/*
414 + * ext3_xattr_block_find()
415 + *
416 + * search attribute and calculate free space in EA block (if it allocated)
417 + * NOTE: free space includes space our attribute hold
418 + */
419 +int
420 +ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
421 +              struct ext3_xattr_entry *rentry, int *free)
422 +{
423 +       struct buffer_head *bh = NULL;
424 +       struct ext3_xattr_entry *entry;
425 +       char *end;
426 +       int name_len, error = -ENOENT;
427 +
428 +       if (!EXT3_I(inode)->i_file_acl) {
429 +               *free = inode->i_sb->s_blocksize -
430 +                       sizeof(struct ext3_xattr_header) -
431 +                       sizeof(__u32);
432 +               return -ENOENT;
433 +       }
434 +       ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
435 +       bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
436 +       if (!bh)
437 +               return -EIO;
438 +       ea_bdebug(bh, "b_count=%d, refcount=%d",
439 +               atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
440 +       end = bh->b_data + bh->b_size;
441 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
442 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
443 +bad_block:     ext3_error(inode->i_sb, "ext3_xattr_get",
444 +                       "inode %ld: bad block %d", inode->i_ino,
445 +                       EXT3_I(inode)->i_file_acl);
446 +               brelse(bh);
447 +               return -EIO;
448 +       }
449 +       /* find named attribute */
450 +       name_len = strlen(name);
451 +       *free = bh->b_size - sizeof(__u32);
452 +
453 +       entry = FIRST_ENTRY(bh);
454 +       while (!IS_LAST_ENTRY(entry)) {
455 +               struct ext3_xattr_entry *next =
456 +                       EXT3_XATTR_NEXT(entry);
457 +               if ((char *)next >= end)
458 +                       goto bad_block;
459 +               if (name_index == entry->e_name_index &&
460 +                   name_len == entry->e_name_len &&
461 +                   memcmp(name, entry->e_name, name_len) == 0) {
462 +                       memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
463 +                       error = 0;
464 +               } else {
465 +                       *free -= EXT3_XATTR_LEN(entry->e_name_len);
466 +                       *free -= le32_to_cpu(entry->e_value_size);
467 +               }
468 +               entry = next;
469 +       }
470 +       brelse(bh);
471 +
472 +       return error;
473 +}
474 +
475 +/*
476 + * ext3_xattr_inode_set()
477 + *
478 + * this routine add/remove/replace attribute in inode body
479 + */
480 +int
481 +ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index,
482 +                     const char *name, const void *value, size_t value_len,
483 +                     int flags)
484 +{
485 +       struct ext3_xattr_entry *last, *next, *here = NULL;
486 +       struct ext3_inode *raw_inode;
487 +       int name_len = strlen(name);
488 +       int esize = EXT3_XATTR_LEN(name_len);
489 +       struct buffer_head *bh;
490 +       int err, storage_size;
491 +       struct ext3_iloc iloc;
492 +       int free, min_offs;
493 +       char *start, *end;
494 +       
495 +       if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
496 +               return -ENOSPC;
497 +
498 +       err = ext3_get_inode_loc(inode, &iloc);
499 +       if (err)
500 +               return err;
501 +       raw_inode = iloc.raw_inode;
502 +       bh = iloc.bh;
503 +
504 +       storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
505 +                               EXT3_GOOD_OLD_INODE_SIZE -
506 +                               EXT3_I(inode)->i_extra_isize -
507 +                               sizeof(__u32);
508 +       start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
509 +                       EXT3_I(inode)->i_extra_isize;
510 +       if ((*(__u32*) start) != EXT3_XATTR_MAGIC) {
511 +               /* inode had no attributes before */
512 +               *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC);
513 +       }
514 +       start += sizeof(__u32);
515 +       end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
516 +       min_offs = storage_size;
517 +       free = storage_size - sizeof(__u32);
518 +
519 +       last = (struct ext3_xattr_entry *) start;       
520 +       while (!IS_LAST_ENTRY(last)) {
521 +               next = EXT3_XATTR_NEXT(last);
522 +               if (le32_to_cpu(last->e_value_size) > storage_size ||
523 +                               (char *) next >= end) {
524 +                       ext3_error(inode->i_sb, "ext3_xattr_ibody_set",
525 +                               "inode %ld", inode->i_ino);
526 +                       brelse(bh);
527 +                       return -EIO;
528 +               }
529 +               
530 +               if (last->e_value_size) {
531 +                       int offs = le16_to_cpu(last->e_value_offs);
532 +                       if (offs < min_offs)
533 +                               min_offs = offs;
534 +               }
535 +               if (name_index == last->e_name_index &&
536 +                       name_len == last->e_name_len &&
537 +                       !memcmp(name, last->e_name, name_len))
538 +                       here = last;
539 +               else {
540 +                       /* we calculate all but our attribute
541 +                        * because it will be removed before changing */
542 +                       free -= EXT3_XATTR_LEN(last->e_name_len);
543 +                       free -= le32_to_cpu(last->e_value_size);
544 +               }
545 +               last = next;
546 +       }
547 +
548 +       if (value && (esize + value_len > free)) {
549 +               brelse(bh);
550 +               return -ENOSPC;
551 +       }
552 +       
553 +       err = ext3_reserve_inode_write(handle, inode, &iloc);
554 +       if (err) {
555 +               brelse(bh);     
556 +               return err;
557 +       }
558 +
559 +       if (here) {
560 +               /* time to remove old value */
561 +               struct ext3_xattr_entry *e;
562 +               int size = le32_to_cpu(here->e_value_size);
563 +               int border = le16_to_cpu(here->e_value_offs);
564 +               char *src;
565 +
566 +               /* move tail */
567 +               memmove(start + min_offs + size, start + min_offs,
568 +                               border - min_offs);
569 +
570 +               /* recalculate offsets */
571 +               e = (struct ext3_xattr_entry *) start;
572 +               while (!IS_LAST_ENTRY(e)) {
573 +                       struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e);
574 +                       int offs = le16_to_cpu(e->e_value_offs);
575 +                       if (offs < border)
576 +                               e->e_value_offs =
577 +                                       cpu_to_le16(offs + size);
578 +                       e = next;
579 +               }
580 +               min_offs += size;
581 +
582 +               /* remove entry */
583 +               border = EXT3_XATTR_LEN(here->e_name_len);
584 +               src = (char *) here + EXT3_XATTR_LEN(here->e_name_len);
585 +               size = (char *) last - src;
586 +               if ((char *) here + size > end)
587 +                       printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n",
588 +                                       __FILE__, __LINE__, here, size, end);
589 +               memmove(here, src, size);
590 +               last = (struct ext3_xattr_entry *) ((char *) last - border);
591 +               *((__u32 *) last) = 0;
592 +       }
593 +       
594 +       if (value) {
595 +               int offs = min_offs - value_len;
596 +               /* use last to create new entry */
597 +               last->e_name_len = strlen(name);
598 +               last->e_name_index = name_index;
599 +               last->e_value_offs = cpu_to_le16(offs);
600 +               last->e_value_size = cpu_to_le32(value_len);
601 +               last->e_hash = last->e_value_block = 0;
602 +               memset(last->e_name, 0, esize);
603 +               memcpy(last->e_name, name, last->e_name_len);
604 +               if (start + offs + value_len > end)
605 +                       printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n",
606 +                                       __FILE__, __LINE__, start, offs,
607 +                                       value_len, end);
608 +               memcpy(start + offs, value, value_len);
609 +               last = EXT3_XATTR_NEXT(last);
610 +               *((__u32 *) last) = 0;
611 +       }
612 +       
613 +       ext3_mark_iloc_dirty(handle, inode, &iloc);
614 +       brelse(bh);
615 +
616 +       return 0;
617 +}
618 +
619 +/*
620   * ext3_xattr_set()
621   *
622   * Create, replace or remove an extended attribute for this inode. Buffer
623 @@ -566,6 +1050,101 @@ static void ext3_xattr_update_super_bloc
624   */
625  int
626  ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
627 +               const char *name, const void *value, size_t value_len, int flags)
628 +{
629 +       struct ext3_xattr_entry entry;
630 +       int err, where = 0, found = 0, total;
631 +       int free1 = -1, free2 = -1;
632 +       int name_len;
633 +       
634 +       ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
635 +                 name_index, name, value, (long)value_len);
636 +
637 +       if (IS_RDONLY(inode))
638 +               return -EROFS;
639 +       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
640 +               return -EPERM;
641 +       if (value == NULL)
642 +               value_len = 0;
643 +       if (name == NULL)
644 +               return -EINVAL;
645 +       name_len = strlen(name);
646 +       if (name_len > 255 || value_len > inode->i_sb->s_blocksize)
647 +               return -ERANGE;
648 +
649 +       /* try to find attribute in inode body */
650 +       err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
651 +       if (err == 0) {
652 +               /* found EA in inode */
653 +               found = 1;
654 +               where = 0;
655 +       } else if (err == -ENOENT) {
656 +               /* there is no such attribute in inode body */
657 +               /* try to find attribute in dedicated block */
658 +               err = ext3_xattr_block_find(inode, name_index, name,
659 +                                               &entry, &free2);
660 +               if (err != 0 && err != -ENOENT) {
661 +                       /* not found EA in block */
662 +                       goto finish;    
663 +               } else if (err == 0) {
664 +                       /* found EA in block */
665 +                       where = 1;
666 +                       found = 1;
667 +               }
668 +       } else
669 +               goto finish;
670 +
671 +       /* check flags: may replace? may create ? */
672 +       if (found && (flags & XATTR_CREATE)) {
673 +               err = -EEXIST;
674 +               goto finish;
675 +       } else if (!found && (flags & XATTR_REPLACE)) {
676 +               err = -ENODATA;
677 +               goto finish;
678 +       }
679 +
680 +       /* check if we have enough space to store attribute */
681 +       total = EXT3_XATTR_LEN(strlen(name)) + value_len;
682 +       if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) {
683 +               /* have no enough space */
684 +               err = -ENOSPC;
685 +               goto finish;
686 +       }
687 +       
688 +       /* time to remove attribute */
689 +       if (found) {
690 +               if (where == 0) {
691 +                       /* EA is stored in inode body */
692 +                       ext3_xattr_ibody_set(handle, inode, name_index, name,
693 +                                       NULL, 0, flags);
694 +               } else {
695 +                       /* EA is stored in separated block */
696 +                       ext3_xattr_block_set(handle, inode, name_index, name,
697 +                                       NULL, 0, flags);
698 +               }
699 +       }
700 +
701 +       /* try to store EA in inode body */
702 +       err = ext3_xattr_ibody_set(handle, inode, name_index, name,
703 +                               value, value_len, flags);
704 +       if (err) {
705 +               /* can't store EA in inode body */
706 +               /* try to store in block */
707 +               err = ext3_xattr_block_set(handle, inode, name_index,
708 +                                       name, value, value_len, flags); 
709 +       }
710 +
711 +finish:        
712 +       return err;
713 +}
714 +
715 +/*
716 + * ext3_xattr_block_set()
717 + *
718 + * this routine add/remove/replace attribute in EA block
719 + */
720 +int
721 +ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index,
722                const char *name, const void *value, size_t value_len, int flags)
723  {
724         struct super_block *sb = inode->i_sb;
725 @@ -603,6 +1181,7 @@ ext3_xattr_set(handle_t *handle, struct 
726         name_len = strlen(name);
727         if (name_len > 255 || value_len > sb->s_blocksize)
728                 return -ERANGE;
729 +
730         down(&ext3_xattr_sem);
731  
732         if (block) {
733 --- linux-2.4.22-ac1/include/linux/ext3_fs.h~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:57.000000000 +0400
734 +++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs.h     2003-10-08 15:13:31.000000000 +0400
735 @@ -265,6 +265,8 @@ struct ext3_inode {
736                         __u32   m_i_reserved2[2];
737                 } masix2;
738         } osd2;                         /* OS dependent 2 */
739 +       __u16   i_extra_isize;
740 +       __u16   i_pad1;
741  };
742  
743  #define i_size_high    i_dir_acl
744 --- linux-2.4.22-ac1/include/linux/ext3_fs_i.h~ext3-ea-in-inode-2.4.22-rh       2003-09-26 00:54:44.000000000 +0400
745 +++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs_i.h   2003-10-08 15:13:31.000000000 +0400
746 @@ -62,6 +62,9 @@ struct ext3_inode_info {
747          */
748         loff_t  i_disksize;
749  
750 +       /* on-disk additional length */
751 +       __u16 i_extra_isize;
752 +
753         /*
754          * truncate_sem is for serialising ext3_truncate() against
755          * ext3_getblock().  In the 2.4 ext2 design, great chunks of inode's
756
757 _