1 Index: linux-2.4.29/fs/ext3/ialloc.c
2 ===================================================================
3 --- linux-2.4.29.orig/fs/ext3/ialloc.c 2005-05-03 15:56:43.831530296 +0300
4 +++ linux-2.4.29/fs/ext3/ialloc.c 2005-05-03 16:07:32.990843080 +0300
6 inode->i_generation = sb->u.ext3_sb.s_next_generation++;
8 inode->u.ext3_i.i_state = EXT3_STATE_NEW;
9 + inode->u.ext3_i.i_extra_isize =
10 + (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ?
11 + sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
13 err = ext3_get_inode_loc_new(inode, &iloc, 1);
15 BUFFER_TRACE(iloc->bh, "get_write_access");
16 Index: linux-2.4.29/fs/ext3/inode.c
17 ===================================================================
18 --- linux-2.4.29.orig/fs/ext3/inode.c 2005-05-03 15:58:30.758274960 +0300
19 +++ linux-2.4.29/fs/ext3/inode.c 2005-05-03 16:07:32.995842320 +0300
20 @@ -2240,6 +2240,12 @@
21 inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
22 INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
24 + if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
25 + inode->u.ext3_i.i_extra_isize =
26 + le16_to_cpu(raw_inode->i_extra_isize);
28 + inode->u.ext3_i.i_extra_isize = 0;
30 if (S_ISREG(inode->i_mode)) {
31 inode->i_op = &ext3_file_inode_operations;
32 inode->i_fop = &ext3_file_operations;
33 @@ -2367,6 +2373,10 @@
34 else for (block = 0; block < EXT3_N_BLOCKS; block++)
35 raw_inode->i_block[block] = inode->u.ext3_i.i_data[block];
37 + if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
38 + raw_inode->i_extra_isize =
39 + cpu_to_le16(EXT3_I(inode)->i_extra_isize);
41 BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
42 rc = ext3_journal_dirty_metadata(handle, bh);
44 Index: linux-2.4.29/fs/ext3/xattr.c
45 ===================================================================
46 --- linux-2.4.29.orig/fs/ext3/xattr.c 2005-04-07 19:31:00.000000000 +0300
47 +++ linux-2.4.29/fs/ext3/xattr.c 2005-05-03 16:07:33.007840496 +0300
49 static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
50 struct ext3_xattr_header *);
52 +int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,
53 + const void *, size_t, int);
55 #ifdef CONFIG_EXT3_FS_XATTR_SHARING
57 static int ext3_xattr_cache_insert(struct buffer_head *);
64 - * Copy an extended attribute into the buffer
65 - * provided, or compute the buffer size required.
66 - * Buffer is NULL to compute the size of the buffer required.
67 + * ext3_xattr_block_get()
69 - * Returns a negative error number on failure, or the number of bytes
70 - * used / required on success.
71 + * routine looks for attribute in EA block and returns it's value and size
74 -ext3_xattr_get(struct inode *inode, int name_index, const char *name,
75 +ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
76 void *buffer, size_t buffer_size)
78 struct buffer_head *bh = NULL;
83 + * ext3_xattr_ibody_get()
85 + * routine looks for attribute in inode body and returns it's value and size
88 +ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
89 + void *buffer, size_t buffer_size)
91 + int size, name_len = strlen(name), storage_size;
92 + struct ext3_xattr_entry *last;
93 + struct ext3_inode *raw_inode;
94 + struct ext3_iloc iloc;
98 + if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
101 + ret = ext3_get_inode_loc(inode, &iloc);
104 + raw_inode = iloc.raw_inode;
106 + storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
107 + EXT3_GOOD_OLD_INODE_SIZE -
108 + EXT3_I(inode)->i_extra_isize -
110 + start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
111 + EXT3_I(inode)->i_extra_isize;
112 + if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
116 + start += sizeof(__u32);
117 + end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
119 + last = (struct ext3_xattr_entry *) start;
120 + while (!IS_LAST_ENTRY(last)) {
121 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
122 + if (le32_to_cpu(last->e_value_size) > storage_size ||
123 + (char *) next >= end) {
124 + ext3_error(inode->i_sb, "ext3_xattr_ibody_get",
125 + "inode %ld", inode->i_ino);
129 + if (name_index == last->e_name_index &&
130 + name_len == last->e_name_len &&
131 + !memcmp(name, last->e_name, name_len))
136 + /* can't find EA */
141 + size = le32_to_cpu(last->e_value_size);
144 + if (buffer_size >= size) {
145 + memcpy(buffer, start + le16_to_cpu(last->e_value_offs),
155 +int ext3_xattr_get(struct inode *inode, int name_index, const char *name,
156 + void *buffer, size_t buffer_size)
160 + /* try to find attribute in inode body */
161 + err = ext3_xattr_ibody_get(inode, name_index, name,
162 + buffer, buffer_size);
164 + /* search was unsuccessful, try to find EA in dedicated block */
165 + err = ext3_xattr_block_get(inode, name_index, name,
166 + buffer, buffer_size);
173 * Copy a list of attribute names into the buffer
175 * used / required on success.
178 -ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
179 +ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
181 struct buffer_head *bh = NULL;
182 struct ext3_xattr_entry *entry;
183 @@ -530,6 +616,131 @@
187 +/* ext3_xattr_ibody_list()
189 + * generate list of attributes stored in inode body
192 +ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
194 + struct ext3_xattr_entry *last;
195 + struct ext3_inode *raw_inode;
196 + char *start, *end, *buf;
197 + struct ext3_iloc iloc;
202 + if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
205 + ret = ext3_get_inode_loc(inode, &iloc);
208 + raw_inode = iloc.raw_inode;
210 + storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
211 + EXT3_GOOD_OLD_INODE_SIZE -
212 + EXT3_I(inode)->i_extra_isize -
214 + start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
215 + EXT3_I(inode)->i_extra_isize;
216 + if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
220 + start += sizeof(__u32);
221 + end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
223 + last = (struct ext3_xattr_entry *) start;
224 + while (!IS_LAST_ENTRY(last)) {
225 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
226 + struct ext3_xattr_handler *handler;
227 + if (le32_to_cpu(last->e_value_size) > storage_size ||
228 + (char *) next >= end) {
229 + ext3_error(inode->i_sb, "ext3_xattr_ibody_list",
230 + "inode %ld", inode->i_ino);
234 + handler = ext3_xattr_handler(last->e_name_index);
236 + size += handler->list(NULL, inode, last->e_name,
246 + if (size > buffer_size)
250 + 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 + handler = ext3_xattr_handler(last->e_name_index);
257 + buf += handler->list(buf, inode, last->e_name,
268 + * ext3_xattr_list()
270 + * Copy a list of attribute names into the buffer
271 + * provided, or compute the buffer size required.
272 + * Buffer is NULL to compute the size of the buffer required.
274 + * Returns a negative error number on failure, or the number of bytes
275 + * used / required on success.
278 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
281 + int size = buffer_size;
283 + /* get list of attributes stored in inode body */
284 + error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
286 + /* some error occured while collecting
287 + * attributes in inode body */
293 + /* get list of attributes stored in dedicated block */
295 + buffer_size -= error;
296 + if (buffer_size <= 0) {
303 + error = ext3_xattr_block_list(inode, buffer, buffer_size);
305 + /* listing was successful, so we return len */
309 + return error + size;
313 * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
315 @@ -553,6 +764,279 @@
319 + * ext3_xattr_ibody_find()
321 + * search attribute and calculate free space in inode body
322 + * NOTE: free space includes space our attribute hold
325 +ext3_xattr_ibody_find(struct inode *inode, int name_index,
326 + const char *name, struct ext3_xattr_entry *rentry, int *free)
328 + struct ext3_xattr_entry *last;
329 + struct ext3_inode *raw_inode;
330 + int name_len = strlen(name);
331 + int err, storage_size;
332 + struct ext3_iloc iloc;
336 + if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
339 + err = ext3_get_inode_loc(inode, &iloc);
342 + raw_inode = iloc.raw_inode;
344 + storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
345 + EXT3_GOOD_OLD_INODE_SIZE -
346 + EXT3_I(inode)->i_extra_isize -
348 + *free = storage_size - sizeof(__u32);
349 + start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
350 + EXT3_I(inode)->i_extra_isize;
351 + if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
355 + start += sizeof(__u32);
356 + end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
358 + last = (struct ext3_xattr_entry *) start;
359 + while (!IS_LAST_ENTRY(last)) {
360 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
361 + if (le32_to_cpu(last->e_value_size) > storage_size ||
362 + (char *) next >= end) {
363 + ext3_error(inode->i_sb, "ext3_xattr_ibody_find",
364 + "inode %ld", inode->i_ino);
369 + if (name_index == last->e_name_index &&
370 + name_len == last->e_name_len &&
371 + !memcmp(name, last->e_name, name_len)) {
372 + memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
375 + *free -= EXT3_XATTR_LEN(last->e_name_len);
376 + *free -= le32_to_cpu(last->e_value_size);
386 + * ext3_xattr_block_find()
388 + * search attribute and calculate free space in EA block (if it allocated)
389 + * NOTE: free space includes space our attribute hold
392 +ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
393 + struct ext3_xattr_entry *rentry, int *free)
395 + struct buffer_head *bh = NULL;
396 + struct ext3_xattr_entry *entry;
398 + int name_len, error = -ENOENT;
400 + if (!EXT3_I(inode)->i_file_acl) {
401 + *free = inode->i_sb->s_blocksize -
402 + sizeof(struct ext3_xattr_header) -
406 + ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
407 + bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
410 + ea_bdebug(bh, "b_count=%d, refcount=%d",
411 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
412 + end = bh->b_data + bh->b_size;
413 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
414 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
415 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
416 + "inode %ld: bad block %d", inode->i_ino,
417 + EXT3_I(inode)->i_file_acl);
421 + /* find named attribute */
422 + name_len = strlen(name);
423 + *free = bh->b_size - sizeof(__u32);
425 + entry = FIRST_ENTRY(bh);
426 + while (!IS_LAST_ENTRY(entry)) {
427 + struct ext3_xattr_entry *next =
428 + EXT3_XATTR_NEXT(entry);
429 + if ((char *)next >= end)
431 + if (name_index == entry->e_name_index &&
432 + name_len == entry->e_name_len &&
433 + memcmp(name, entry->e_name, name_len) == 0) {
434 + memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
437 + *free -= EXT3_XATTR_LEN(entry->e_name_len);
438 + *free -= le32_to_cpu(entry->e_value_size);
448 + * ext3_xattr_inode_set()
450 + * this routine add/remove/replace attribute in inode body
453 +ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index,
454 + const char *name, const void *value, size_t value_len,
457 + struct ext3_xattr_entry *last, *next, *here = NULL;
458 + struct ext3_inode *raw_inode;
459 + int name_len = strlen(name);
460 + int esize = EXT3_XATTR_LEN(name_len);
461 + struct buffer_head *bh;
462 + int err, storage_size;
463 + struct ext3_iloc iloc;
464 + int free, min_offs;
467 + if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
470 + err = ext3_get_inode_loc(inode, &iloc);
473 + raw_inode = iloc.raw_inode;
476 + storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
477 + EXT3_GOOD_OLD_INODE_SIZE -
478 + EXT3_I(inode)->i_extra_isize -
480 + start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
481 + EXT3_I(inode)->i_extra_isize;
482 + if ((*(__u32*) start) != EXT3_XATTR_MAGIC) {
483 + /* inode had no attributes before */
484 + *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC);
486 + start += sizeof(__u32);
487 + end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
488 + min_offs = storage_size;
489 + free = storage_size - sizeof(__u32);
491 + last = (struct ext3_xattr_entry *) start;
492 + while (!IS_LAST_ENTRY(last)) {
493 + next = EXT3_XATTR_NEXT(last);
494 + if (le32_to_cpu(last->e_value_size) > storage_size ||
495 + (char *) next >= end) {
496 + ext3_error(inode->i_sb, "ext3_xattr_ibody_set",
497 + "inode %ld", inode->i_ino);
502 + if (last->e_value_size) {
503 + int offs = le16_to_cpu(last->e_value_offs);
504 + if (offs < min_offs)
507 + if (name_index == last->e_name_index &&
508 + name_len == last->e_name_len &&
509 + !memcmp(name, last->e_name, name_len))
512 + /* we calculate all but our attribute
513 + * because it will be removed before changing */
514 + free -= EXT3_XATTR_LEN(last->e_name_len);
515 + free -= le32_to_cpu(last->e_value_size);
520 + if (value && (esize + value_len > free)) {
525 + err = ext3_reserve_inode_write(handle, inode, &iloc);
532 + /* time to remove old value */
533 + struct ext3_xattr_entry *e;
534 + int size = le32_to_cpu(here->e_value_size);
535 + int border = le16_to_cpu(here->e_value_offs);
539 + memmove(start + min_offs + size, start + min_offs,
540 + border - min_offs);
542 + /* recalculate offsets */
543 + e = (struct ext3_xattr_entry *) start;
544 + while (!IS_LAST_ENTRY(e)) {
545 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e);
546 + int offs = le16_to_cpu(e->e_value_offs);
549 + cpu_to_le16(offs + size);
555 + border = EXT3_XATTR_LEN(here->e_name_len);
556 + src = (char *) here + EXT3_XATTR_LEN(here->e_name_len);
557 + size = (char *) last - src;
558 + if ((char *) here + size > end)
559 + printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n",
560 + __FILE__, __LINE__, here, size, end);
561 + memmove(here, src, size);
562 + last = (struct ext3_xattr_entry *) ((char *) last - border);
563 + *((__u32 *) last) = 0;
567 + int offs = min_offs - value_len;
568 + /* use last to create new entry */
569 + last->e_name_len = strlen(name);
570 + last->e_name_index = name_index;
571 + last->e_value_offs = cpu_to_le16(offs);
572 + last->e_value_size = cpu_to_le32(value_len);
573 + last->e_hash = last->e_value_block = 0;
574 + memset(last->e_name, 0, esize);
575 + memcpy(last->e_name, name, last->e_name_len);
576 + if (start + offs + value_len > end)
577 + printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n",
578 + __FILE__, __LINE__, start, offs,
580 + memcpy(start + offs, value, value_len);
581 + last = EXT3_XATTR_NEXT(last);
582 + *((__u32 *) last) = 0;
585 + ext3_mark_iloc_dirty(handle, inode, &iloc);
594 * Create, replace or remove an extended attribute for this inode. Buffer
595 @@ -566,6 +1050,101 @@
598 ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
599 + const char *name, const void *value, size_t value_len, int flags)
601 + struct ext3_xattr_entry entry;
602 + int err, where = 0, found = 0, total;
603 + int free1 = -1, free2 = -1;
606 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
607 + name_index, name, value, (long)value_len);
609 + if (IS_RDONLY(inode))
611 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
617 + name_len = strlen(name);
618 + if (name_len > 255 || value_len > inode->i_sb->s_blocksize)
621 + /* try to find attribute in inode body */
622 + err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
624 + /* found EA in inode */
627 + } else if (err == -ENOENT) {
628 + /* there is no such attribute in inode body */
629 + /* try to find attribute in dedicated block */
630 + err = ext3_xattr_block_find(inode, name_index, name,
632 + if (err != 0 && err != -ENOENT) {
633 + /* not found EA in block */
635 + } else if (err == 0) {
636 + /* found EA in block */
643 + /* check flags: may replace? may create ? */
644 + if (found && (flags & XATTR_CREATE)) {
647 + } else if (!found && (flags & XATTR_REPLACE)) {
652 + /* check if we have enough space to store attribute */
653 + total = EXT3_XATTR_LEN(strlen(name)) + value_len;
654 + if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) {
655 + /* have no enough space */
660 + /* time to remove attribute */
663 + /* EA is stored in inode body */
664 + ext3_xattr_ibody_set(handle, inode, name_index, name,
667 + /* EA is stored in separated block */
668 + ext3_xattr_block_set(handle, inode, name_index, name,
673 + /* try to store EA in inode body */
674 + err = ext3_xattr_ibody_set(handle, inode, name_index, name,
675 + value, value_len, flags);
677 + /* can't store EA in inode body */
678 + /* try to store in block */
679 + err = ext3_xattr_block_set(handle, inode, name_index,
680 + name, value, value_len, flags);
688 + * ext3_xattr_block_set()
690 + * this routine add/remove/replace attribute in EA block
693 +ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index,
694 const char *name, const void *value, size_t value_len, int flags)
696 struct super_block *sb = inode->i_sb;
698 name_len = strlen(name);
699 if (name_len > 255 || value_len > sb->s_blocksize)
702 down(&ext3_xattr_sem);
705 Index: linux-2.4.29/include/linux/ext3_fs.h
706 ===================================================================
707 --- linux-2.4.29.orig/include/linux/ext3_fs.h 2005-05-03 15:58:30.767273592 +0300
708 +++ linux-2.4.29/include/linux/ext3_fs.h 2005-05-03 16:07:33.009840192 +0300
710 __u32 m_i_reserved2[2];
712 } osd2; /* OS dependent 2 */
713 + __u16 i_extra_isize;
717 #define i_size_high i_dir_acl
718 Index: linux-2.4.29/include/linux/ext3_fs_i.h
719 ===================================================================
720 --- linux-2.4.29.orig/include/linux/ext3_fs_i.h 2005-04-07 18:52:18.000000000 +0300
721 +++ linux-2.4.29/include/linux/ext3_fs_i.h 2005-05-03 16:07:33.010840040 +0300
726 + /* on-disk additional length */
727 + __u16 i_extra_isize;
730 * truncate_sem is for serialising ext3_truncate() against
731 * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's