ReactOS 0.4.15-dev-7788-g1ad9096
ext4_xattr.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public Licens
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
14 */
15
16#include <ext2fs.h>
17#include <linux/module.h>
18#include <linux/ext4_xattr.h>
19
20static ext4_fsblk_t ext4_new_meta_blocks(void *icb, struct inode *inode,
21 ext4_fsblk_t goal,
22 unsigned int flags,
23 unsigned long *count, int *errp)
24{
26 ULONG blockcnt = (count) ? *count : 1;
27 ULONG block = 0;
28
30 inode->i_sb->s_priv,
31 0, (ULONG)goal,
32 &block,
33 &blockcnt);
34 if (count)
35 *count = blockcnt;
36
37 if (!NT_SUCCESS(status)) {
38 *errp = Ext2LinuxError(status);
39 return 0;
40 }
41 inode->i_blocks += (blockcnt * (inode->i_sb->s_blocksize >> 9));
42 return block;
43}
44
45static void ext4_free_blocks(void *icb, struct inode *inode,
46 ext4_fsblk_t block, int count, int flags)
47{
49 inode->i_blocks -= count * (inode->i_sb->s_blocksize >> 9);
50 return;
51}
52
54{
56 Vcb = inode->i_sb->s_priv;
57 return (inode->i_ino - 1) / BLOCKS_PER_GROUP;
58}
59
60#define NAME_HASH_SHIFT 5
61#define VALUE_HASH_SHIFT 16
62
64 struct ext4_xattr_entry *entry)
65{
66 __u32 hash = 0;
67 char *name = EXT4_XATTR_NAME(entry);
68 int n;
69
70 for (n = 0; n < entry->e_name_len; n++) {
72 (hash >> (8 * sizeof(hash) - NAME_HASH_SHIFT)) ^ *name++;
73 }
74
75 if (entry->e_value_block == 0 && entry->e_value_size != 0) {
76 __le32 *value =
77 (__le32 *)((char *)header + le16_to_cpu(entry->e_value_offs));
78 for (n = (le32_to_cpu(entry->e_value_size) + EXT4_XATTR_ROUND) >>
80 n; n--) {
82 (hash >> (8 * sizeof(hash) - VALUE_HASH_SHIFT)) ^
84 }
85 }
86 entry->e_hash = cpu_to_le32(hash);
87}
88
89#define BLOCK_HASH_SHIFT 16
90
91/*
92 * ext4_xattr_rehash()
93 *
94 * Re-compute the extended attribute hash value after an entry has changed.
95 */
97 struct ext4_xattr_entry *entry)
98{
99 struct ext4_xattr_entry *here;
100 __u32 hash = 0;
101
103 here = EXT4_XATTR_ENTRY(header + 1);
104 while (!EXT4_XATTR_IS_LAST_ENTRY(here)) {
105 if (!here->e_hash) {
106 /* Block is not shared if an entry's hash value == 0 */
107 hash = 0;
108 break;
109 }
110 hash = (hash << BLOCK_HASH_SHIFT) ^
111 (hash >> (8 * sizeof(hash) - BLOCK_HASH_SHIFT)) ^
112 le32_to_cpu(here->e_hash);
113 here = EXT4_XATTR_NEXT(here);
114 }
115 header->h_hash = cpu_to_le32(hash);
116}
117
118#if CONFIG_META_CSUM_ENABLE
119static __u32
121 ext4_fsblk_t blocknr,
123{
124 __u32 checksum = 0;
125 __u64 le64_blocknr = blocknr;
126 struct ext4_sblock *sb = &inode_ref->fs->sb;
127
128 if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
129 __u32 orig_checksum;
130
131 /* Preparation: temporarily set bg checksum to 0 */
132 orig_checksum = header->h_checksum;
133 header->h_checksum = 0;
134 /* First calculate crc32 checksum against fs uuid */
135 checksum = ext4_crc32c(EXT4_CRC32_INIT, sb->uuid,
136 sizeof(sb->uuid));
137 /* Then calculate crc32 checksum block number */
138 checksum = ext4_crc32c(checksum, &le64_blocknr,
139 sizeof(le64_blocknr));
140 /* Finally calculate crc32 checksum against
141 * the entire xattr block */
142 checksum = ext4_crc32c(checksum, header,
143 ext4_sb_get_block_size(sb));
144 header->h_checksum = orig_checksum;
145 }
146 return checksum;
147}
148#else
149#define ext4_xattr_block_checksum(...) 0
150#endif
151
152static void
154 ext4_fsblk_t blocknr,
156{
157 /* TODO: Need METADATA_CSUM supports. */
158 header->h_checksum = 0;
159}
160
161static int ext4_xattr_item_cmp(struct rb_node *_a,
162 struct rb_node *_b)
163{
164 int result;
165 struct ext4_xattr_item *a, *b;
166 a = container_of(_a, struct ext4_xattr_item, node);
167 a = container_of(_a, struct ext4_xattr_item, node);
168 b = container_of(_b, struct ext4_xattr_item, node);
169
170 if (a->is_data && !b->is_data)
171 return -1;
172
173 if (!a->is_data && b->is_data)
174 return 1;
175
176 result = a->name_index - b->name_index;
177 if (result)
178 return result;
179
180 if (a->name_len < b->name_len)
181 return -1;
182
183 if (a->name_len > b->name_len)
184 return 1;
185
186 return memcmp(a->name, b->name, a->name_len);
187}
188
189//
190// Red-black tree insert routine.
191//
192
193static struct ext4_xattr_item *
195 struct ext4_xattr_item *name)
196{
197 struct rb_node *new = xattr_ref->root.rb_node;
198
199 while (new) {
200 struct ext4_xattr_item *node =
201 container_of(new, struct ext4_xattr_item, node);
202 int result = ext4_xattr_item_cmp(&name->node, new);
203
204 if (result < 0)
205 new = new->rb_left;
206 else if (result > 0)
207 new = new->rb_right;
208 else
209 return node;
210
211 }
212
213 return NULL;
214}
215
216static void ext4_xattr_item_insert(struct ext4_xattr_ref *xattr_ref,
217 struct ext4_xattr_item *item)
218{
219 rb_insert(&xattr_ref->root, &item->node,
221 list_add_tail(&item->list_node, &xattr_ref->ordered_list);
222}
223
224static void ext4_xattr_item_remove(struct ext4_xattr_ref *xattr_ref,
225 struct ext4_xattr_item *item)
226{
227 rb_erase(&item->node, &xattr_ref->root);
228 list_del_init(&item->list_node);
229}
230
231static struct ext4_xattr_item *
233{
234 struct ext4_xattr_item *item;
235 item = kzalloc(sizeof(struct ext4_xattr_item) + name_len, GFP_NOFS);
236 if (!item)
237 return NULL;
238
239 item->name_index = name_index;
240 item->name = (char *)(item + 1);
241 item->name_len = name_len;
242 item->data = NULL;
243 item->data_size = 0;
244 INIT_LIST_HEAD(&item->list_node);
245
246 memcpy(item->name, name, name_len);
247
249 name_len == 4 &&
250 !memcmp(name, "data", 4))
251 item->is_data = TRUE;
252 else
253 item->is_data = FALSE;
254
255 return item;
256}
257
259 const void *orig_data, size_t data_size)
260{
261 void *data = NULL;
262 ASSERT(!item->data);
264 if (!data)
265 return -ENOMEM;
266
267 if (orig_data)
268 memcpy(data, orig_data, data_size);
269
270 item->data = data;
271 item->data_size = data_size;
272 return 0;
273}
274
276{
277 ASSERT(item->data);
278 kfree(item->data);
279 item->data = NULL;
280 item->data_size = 0;
281}
282
284 size_t new_data_size)
285{
286 if (new_data_size != item->data_size) {
287 void *new_data;
288 new_data = kmalloc(new_data_size, GFP_NOFS);
289 if (!new_data)
290 return -ENOMEM;
291
292 memcpy(new_data, item->data, item->data_size);
293 kfree(item->data);
294
295 item->data = new_data;
296 item->data_size = new_data_size;
297 }
298 return 0;
299}
300
302{
303 if (item->data)
305
306 kfree(item);
307}
308
309static void *ext4_xattr_entry_data(struct ext4_xattr_ref *xattr_ref,
310 struct ext4_xattr_entry *entry,
312{
313 char *ret;
314 int block_size;
315 if (in_inode) {
317 struct ext4_xattr_entry *first_entry;
318 int inode_size = xattr_ref->fs->InodeSize;
319 header = EXT4_XATTR_IHDR(xattr_ref->OnDiskInode);
320 first_entry = EXT4_XATTR_IFIRST(header);
321
322 ret = ((char *)first_entry + le16_to_cpu(entry->e_value_offs));
323 if (ret + EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) -
324 (char *)xattr_ref->OnDiskInode > inode_size)
325 ret = NULL;
326
327 return ret;
328
329 }
330 block_size = xattr_ref->fs->BlockSize;
331 ret = ((char *)xattr_ref->block_bh->b_data + le16_to_cpu(entry->e_value_offs));
332 if (ret + EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) -
333 (char *)xattr_ref->block_bh->b_data > block_size)
334 ret = NULL;
335 return ret;
336}
337
338static int ext4_xattr_block_fetch(struct ext4_xattr_ref *xattr_ref)
339{
340 int ret = 0;
341 size_t size_rem;
342 void *data;
343 struct ext4_xattr_entry *entry = NULL;
344
345 ASSERT(xattr_ref->block_bh->b_data);
346 entry = EXT4_XATTR_BFIRST(xattr_ref->block_bh);
347
348 size_rem = xattr_ref->fs->BlockSize;
349 for (; size_rem > 0 && !EXT4_XATTR_IS_LAST_ENTRY(entry);
351 size_rem -= EXT4_XATTR_LEN(entry->e_name_len)) {
352 struct ext4_xattr_item *item;
353 char *e_name = EXT4_XATTR_NAME(entry);
354
355 data = ext4_xattr_entry_data(xattr_ref, entry, FALSE);
356 if (!data) {
357 ret = -EIO;
358 goto Finish;
359 }
360
361 item = ext4_xattr_item_alloc(entry->e_name_index, e_name,
362 (size_t)entry->e_name_len);
363 if (!item) {
364 ret = -ENOMEM;
365 goto Finish;
366 }
368 item, data, le32_to_cpu(entry->e_value_size)) != 0) {
370 ret = -ENOMEM;
371 goto Finish;
372 }
373 ext4_xattr_item_insert(xattr_ref, item);
374 xattr_ref->block_size_rem -=
375 EXT4_XATTR_SIZE(item->data_size) +
376 EXT4_XATTR_LEN(item->name_len);
377 xattr_ref->ea_size += EXT4_XATTR_SIZE(item->data_size) +
378 EXT4_XATTR_LEN(item->name_len);
379 }
380
381Finish:
382 return ret;
383}
384
385static int ext4_xattr_inode_fetch(struct ext4_xattr_ref *xattr_ref)
386{
387 void *data;
388 size_t size_rem;
389 int ret = 0;
391 struct ext4_xattr_entry *entry = NULL;
392 int inode_size = xattr_ref->fs->InodeSize;
393
394 header = EXT4_XATTR_IHDR(xattr_ref->OnDiskInode);
396
397 size_rem = inode_size - EXT4_GOOD_OLD_INODE_SIZE -
398 xattr_ref->OnDiskInode->i_extra_isize;
399 for (; size_rem > 0 && !EXT4_XATTR_IS_LAST_ENTRY(entry);
401 size_rem -= EXT4_XATTR_LEN(entry->e_name_len)) {
402 struct ext4_xattr_item *item;
403 char *e_name = EXT4_XATTR_NAME(entry);
404
405 data = ext4_xattr_entry_data(xattr_ref, entry, TRUE);
406 if (!data) {
407 ret = -EIO;
408 goto Finish;
409 }
410
411 item = ext4_xattr_item_alloc(entry->e_name_index, e_name,
412 (size_t)entry->e_name_len);
413 if (!item) {
414 ret = -ENOMEM;
415 goto Finish;
416 }
418 item, data, le32_to_cpu(entry->e_value_size)) != 0) {
420 ret = -ENOMEM;
421 goto Finish;
422 }
423 item->in_inode = TRUE;
424 ext4_xattr_item_insert(xattr_ref, item);
425 xattr_ref->inode_size_rem -=
426 EXT4_XATTR_SIZE(item->data_size) +
427 EXT4_XATTR_LEN(item->name_len);
428 xattr_ref->ea_size += EXT4_XATTR_SIZE(item->data_size) +
429 EXT4_XATTR_LEN(item->name_len);
430 }
431
432Finish:
433 return ret;
434}
435
437{
438 int inode_size = xattr_ref->fs->InodeSize;
439 int size_rem = inode_size - EXT4_GOOD_OLD_INODE_SIZE -
440 xattr_ref->OnDiskInode->i_extra_isize;
441 return size_rem;
442}
443
445{
446 return xattr_ref->fs->BlockSize;
447}
448
449static int ext4_xattr_fetch(struct ext4_xattr_ref *xattr_ref)
450{
451 int ret = 0;
452 int inode_size = xattr_ref->fs->InodeSize;
453 if (inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
454 ret = ext4_xattr_inode_fetch(xattr_ref);
455 if (ret != 0)
456 return ret;
457 }
458
459 if (xattr_ref->block_loaded)
460 ret = ext4_xattr_block_fetch(xattr_ref);
461
462 xattr_ref->dirty = FALSE;
463 return ret;
464}
465
466static struct ext4_xattr_item *
468 const char *name, size_t name_len)
469{
470 struct ext4_xattr_item tmp = {
471 FALSE,
472 FALSE,
474 (char *)name, /*won't touch this string*/
475 name_len,
476 };
478 name_len == 4 &&
479 !memcmp(name, "data", 4))
480 tmp.is_data = TRUE;
481
482 return ext4_xattr_item_search(xattr_ref, &tmp);
483}
484
485static struct ext4_xattr_item *
487 const char *name, size_t name_len, const void *data,
488 size_t data_size,
489 int *err)
490{
491 struct ext4_xattr_item *item;
493 if (!item) {
494 if (err)
495 *err = -ENOMEM;
496
497 return NULL;
498 }
499
500 item->in_inode = TRUE;
501 if (xattr_ref->inode_size_rem <
503 EXT4_XATTR_LEN(item->name_len)) {
504 if (xattr_ref->block_size_rem <
506 EXT4_XATTR_LEN(item->name_len)) {
507 if (err)
508 *err = -ENOSPC;
509
510 return NULL;
511 }
512
513 item->in_inode = FALSE;
514 }
517 if (err)
518 *err = -ENOMEM;
519
520 return NULL;
521 }
522 ext4_xattr_item_insert(xattr_ref, item);
523 xattr_ref->ea_size +=
524 EXT4_XATTR_SIZE(item->data_size) + EXT4_XATTR_LEN(item->name_len);
525 if (item->in_inode) {
526 xattr_ref->inode_size_rem -=
527 EXT4_XATTR_SIZE(item->data_size) +
528 EXT4_XATTR_LEN(item->name_len);
529 } else {
530 xattr_ref->block_size_rem -=
531 EXT4_XATTR_SIZE(item->data_size) +
532 EXT4_XATTR_LEN(item->name_len);
533 }
534 xattr_ref->dirty = TRUE;
535 if (err)
536 *err = 0;
537
538 return item;
539}
540
541static struct ext4_xattr_item *
543 const char *name, size_t name_len, const void *data,
544 size_t data_size,
545 int *err)
546{
547 struct ext4_xattr_item *item, *last_item = NULL;
549 if (!item) {
550 if (err)
551 *err = -ENOMEM;
552
553 return NULL;
554 }
555
556 if (!list_empty(&xattr_ref->ordered_list))
557 last_item = list_entry(xattr_ref->ordered_list.prev,
558 struct ext4_xattr_item,
559 list_node);
560
561 item->in_inode = TRUE;
562 if ((xattr_ref->inode_size_rem <
564 EXT4_XATTR_LEN(item->name_len))
565 ||
566 (last_item && !last_item->in_inode)) {
567 if (xattr_ref->block_size_rem <
569 EXT4_XATTR_LEN(item->name_len)) {
570 if (err)
571 *err = -ENOSPC;
572
573 return NULL;
574 }
575
576 item->in_inode = FALSE;
577 }
580 if (err)
581 *err = -ENOMEM;
582
583 return NULL;
584 }
585 ext4_xattr_item_insert(xattr_ref, item);
586 xattr_ref->ea_size +=
587 EXT4_XATTR_SIZE(item->data_size) + EXT4_XATTR_LEN(item->name_len);
588 if (item->in_inode) {
589 xattr_ref->inode_size_rem -=
590 EXT4_XATTR_SIZE(item->data_size) +
591 EXT4_XATTR_LEN(item->name_len);
592 }
593 else {
594 xattr_ref->block_size_rem -=
595 EXT4_XATTR_SIZE(item->data_size) +
596 EXT4_XATTR_LEN(item->name_len);
597 }
598 xattr_ref->dirty = TRUE;
599 if (err)
600 *err = 0;
601
602 return item;
603}
604
605static int ext4_xattr_remove_item(struct ext4_xattr_ref *xattr_ref,
606 __u8 name_index, const char *name,
607 size_t name_len)
608{
609 int ret = -ENOENT;
610 struct ext4_xattr_item *item =
612 if (item) {
613 if (item == xattr_ref->iter_from) {
614 struct rb_node *next_node;
615 next_node = rb_next(&item->node);
616 if (next_node)
617 xattr_ref->iter_from =
619 struct ext4_xattr_item,
620 node);
621 else
622 xattr_ref->iter_from = NULL;
623 }
624
625 xattr_ref->ea_size -= EXT4_XATTR_SIZE(item->data_size) +
626 EXT4_XATTR_LEN(item->name_len);
627
628 if (item->in_inode) {
629 xattr_ref->inode_size_rem +=
630 EXT4_XATTR_SIZE(item->data_size) +
631 EXT4_XATTR_LEN(item->name_len);
632 } else {
633 xattr_ref->block_size_rem +=
634 EXT4_XATTR_SIZE(item->data_size) +
635 EXT4_XATTR_LEN(item->name_len);
636 }
637
638 ext4_xattr_item_remove(xattr_ref, item);
640 xattr_ref->dirty = TRUE;
641 ret = 0;
642 }
643 return ret;
644}
645
646static int ext4_xattr_resize_item(struct ext4_xattr_ref *xattr_ref,
647 struct ext4_xattr_item *item,
648 size_t new_data_size)
649{
650 int ret = 0;
651 BOOL to_inode = FALSE, to_block = FALSE;
652 size_t old_data_size = item->data_size;
653 size_t orig_room_size = item->in_inode ?
654 xattr_ref->inode_size_rem :
655 xattr_ref->block_size_rem;
656
657 /*
658 * Check if we can hold this entry in both in-inode and
659 * on-block form
660 *
661 * More complicated case: we do not allow entries stucking in
662 * the middle between in-inode space and on-block space, so
663 * the entry has to stay in either inode space or block space.
664 */
665 if (item->in_inode) {
666 if (xattr_ref->inode_size_rem +
667 EXT4_XATTR_SIZE(old_data_size) <
668 EXT4_XATTR_SIZE(new_data_size)) {
669 if (xattr_ref->block_size_rem <
670 EXT4_XATTR_SIZE(new_data_size) +
671 EXT4_XATTR_LEN(item->name_len))
672 return -ENOSPC;
673
674 to_block = TRUE;
675 }
676 } else {
677 if (xattr_ref->block_size_rem +
678 EXT4_XATTR_SIZE(old_data_size) <
679 EXT4_XATTR_SIZE(new_data_size)) {
680 if (xattr_ref->inode_size_rem <
681 EXT4_XATTR_SIZE(new_data_size) +
682 EXT4_XATTR_LEN(item->name_len))
683 return -ENOSPC;
684
685 to_inode = TRUE;
686 }
687 }
688 ret = ext4_xattr_item_resize_data(item, new_data_size);
689 if (ret)
690 return ret;
691
692 xattr_ref->ea_size =
693 xattr_ref->ea_size -
694 EXT4_XATTR_SIZE(old_data_size) +
695 EXT4_XATTR_SIZE(new_data_size);
696
697 /*
698 * This entry may originally lie in inode space or block space,
699 * and it is going to be transferred to another place.
700 */
701 if (to_block) {
702 xattr_ref->inode_size_rem +=
703 EXT4_XATTR_SIZE(old_data_size) +
704 EXT4_XATTR_LEN(item->name_len);
705 xattr_ref->block_size_rem -=
706 EXT4_XATTR_SIZE(new_data_size) +
707 EXT4_XATTR_LEN(item->name_len);
708 item->in_inode = FALSE;
709 } else if (to_inode) {
710 xattr_ref->block_size_rem +=
711 EXT4_XATTR_SIZE(old_data_size) +
712 EXT4_XATTR_LEN(item->name_len);
713 xattr_ref->inode_size_rem -=
714 EXT4_XATTR_SIZE(new_data_size) +
715 EXT4_XATTR_LEN(item->name_len);
716 item->in_inode = TRUE;
717 } else {
718 /*
719 * No need to transfer as there is enough space for the entry
720 * to stay in inode space or block space it used to be.
721 */
722 orig_room_size +=
723 EXT4_XATTR_SIZE(old_data_size);
724 orig_room_size -=
725 EXT4_XATTR_SIZE(new_data_size);
726 if (item->in_inode)
727 xattr_ref->inode_size_rem = orig_room_size;
728 else
729 xattr_ref->block_size_rem = orig_room_size;
730
731 }
732 xattr_ref->dirty = TRUE;
733 return ret;
734}
735
737{
738 struct rb_node *first_node;
739 struct ext4_xattr_item *item = NULL;
740 first_node = rb_first(&xattr_ref->root);
741 if (first_node)
742 item = container_of(first_node, struct ext4_xattr_item,
743 node);
744
745 while (item) {
746 struct rb_node *next_node;
747 struct ext4_xattr_item *next_item = NULL;
748 next_node = rb_next(&item->node);
749 if (next_node)
750 next_item = container_of(next_node, struct ext4_xattr_item,
751 node);
752 else
753 next_item = NULL;
754
755 ext4_xattr_item_remove(xattr_ref, item);
757
758 item = next_item;
759 }
760 xattr_ref->ea_size = 0;
761 if (ext4_xattr_inode_space(xattr_ref) <
762 sizeof(struct ext4_xattr_ibody_header))
763 xattr_ref->inode_size_rem = 0;
764 else
765 xattr_ref->inode_size_rem =
766 ext4_xattr_inode_space(xattr_ref) -
767 sizeof(struct ext4_xattr_ibody_header);
768
769 xattr_ref->block_size_rem =
770 ext4_xattr_block_space(xattr_ref) -
771 sizeof(struct ext4_xattr_header);
772}
773
774static int ext4_xattr_try_alloc_block(struct ext4_xattr_ref *xattr_ref)
775{
776 int ret = 0;
777
778 ext4_fsblk_t xattr_block = 0;
779 xattr_block = xattr_ref->inode_ref->Inode.i_file_acl;
780 if (!xattr_block) {
781 ext4_fsblk_t goal =
783
784 xattr_block = ext4_new_meta_blocks(xattr_ref->IrpContext,
785 &xattr_ref->inode_ref->Inode,
786 goal, 0, NULL,
787 &ret);
788 if (ret != 0)
789 goto Finish;
790
791 xattr_ref->block_bh = extents_bwrite(&xattr_ref->fs->sb, xattr_block);
792 if (!xattr_ref->block_bh) {
793 ext4_free_blocks(xattr_ref->IrpContext, &xattr_ref->inode_ref->Inode,
794 xattr_block, 1, 0);
795 ret = -ENOMEM;
796 goto Finish;
797 }
798
799 xattr_ref->inode_ref->Inode.i_file_acl = xattr_block;
800 xattr_ref->IsOnDiskInodeDirty = TRUE;
801 xattr_ref->block_loaded = TRUE;
802 }
803
804Finish:
805 return ret;
806}
807
808static void ext4_xattr_try_free_block(struct ext4_xattr_ref *xattr_ref)
809{
810 ext4_fsblk_t xattr_block;
811 xattr_block = xattr_ref->inode_ref->Inode.i_file_acl;
812 xattr_ref->inode_ref->Inode.i_file_acl = 0;
813 extents_brelse(xattr_ref->block_bh);
814 xattr_ref->block_bh = NULL;
815 ext4_free_blocks(xattr_ref->IrpContext, &xattr_ref->inode_ref->Inode,
816 xattr_block, 1, 0);
817 xattr_ref->IsOnDiskInodeDirty = TRUE;
818 xattr_ref->block_loaded = FALSE;
819}
820
821static void ext4_xattr_set_block_header(struct ext4_xattr_ref *xattr_ref)
822{
823 struct ext4_xattr_header *block_header = NULL;
824 block_header = EXT4_XATTR_BHDR(xattr_ref->block_bh);
825
826 memset(block_header, 0, sizeof(struct ext4_xattr_header));
827 block_header->h_magic = EXT4_XATTR_MAGIC;
828 block_header->h_refcount = cpu_to_le32(1);
829 block_header->h_blocks = cpu_to_le32(1);
830}
831
832static void
834 struct ext4_xattr_ibody_header *ibody_header,
835 struct ext4_xattr_entry *entry, void *ibody_data_ptr)
836{
837 entry->e_name_len = (__u8)item->name_len;
838 entry->e_name_index = item->name_index;
839 entry->e_value_offs =
840 cpu_to_le16((char *)ibody_data_ptr - (char *)EXT4_XATTR_IFIRST(ibody_header));
841 entry->e_value_block = 0;
842 entry->e_value_size = cpu_to_le32(item->data_size);
843}
844
846 struct ext4_xattr_header *block_header,
847 struct ext4_xattr_entry *block_entry,
848 void *block_data_ptr)
849{
850 block_entry->e_name_len = (__u8)item->name_len;
851 block_entry->e_name_index = item->name_index;
852 block_entry->e_value_offs =
853 cpu_to_le16((char *)block_data_ptr - (char *)block_header);
854 block_entry->e_value_block = 0;
855 block_entry->e_value_size = cpu_to_le32(item->data_size);
856}
857
858static int ext4_xattr_write_to_disk(struct ext4_xattr_ref *xattr_ref)
859{
860 int ret = 0;
861 BOOL block_modified = FALSE;
862 void *ibody_data = NULL;
863 void *block_data = NULL;
864 size_t inode_size_rem, block_size_rem;
865 struct ext4_xattr_ibody_header *ibody_header = NULL;
866 struct ext4_xattr_header *block_header = NULL;
867 struct ext4_xattr_entry *entry = NULL;
868 struct ext4_xattr_entry *block_entry = NULL;
869 struct ext4_xattr_item *item = NULL;
870
871 inode_size_rem = ext4_xattr_inode_space(xattr_ref);
872 block_size_rem = ext4_xattr_block_space(xattr_ref);
873 if (inode_size_rem > sizeof(struct ext4_xattr_ibody_header)) {
874 ibody_header = EXT4_XATTR_IHDR(xattr_ref->OnDiskInode);
875 entry = EXT4_XATTR_IFIRST(ibody_header);
876 }
877
878 if (!xattr_ref->dirty)
879 goto Finish;
880 /* If there are enough spaces in the ibody EA table.*/
881 if (inode_size_rem > sizeof(struct ext4_xattr_ibody_header)) {
882 memset(ibody_header, 0, inode_size_rem);
883 ibody_header->h_magic = EXT4_XATTR_MAGIC;
884 ibody_data = (char *)ibody_header + inode_size_rem;
885 inode_size_rem -= sizeof(struct ext4_xattr_ibody_header);
886
887 xattr_ref->IsOnDiskInodeDirty = TRUE;
888 }
889 /* If we need an extra block to hold the EA entries*/
890 if (xattr_ref->ea_size > inode_size_rem) {
891 if (!xattr_ref->block_loaded) {
892 ret = ext4_xattr_try_alloc_block(xattr_ref);
893 if (ret != 0)
894 goto Finish;
895 }
896 memset(xattr_ref->block_bh->b_data, 0, xattr_ref->fs->BlockSize);
897 block_header = EXT4_XATTR_BHDR(xattr_ref->block_bh);
898 block_entry = EXT4_XATTR_BFIRST(xattr_ref->block_bh);
900 block_data = (char *)block_header + block_size_rem;
901 block_size_rem -= sizeof(struct ext4_xattr_header);
902
904 } else {
905 /* We don't need an extra block.*/
906 if (xattr_ref->block_loaded) {
907 block_header = EXT4_XATTR_BHDR(xattr_ref->block_bh);
908 le32_add_cpu(&block_header->h_refcount, -1);
909 if (!block_header->h_refcount) {
910 ext4_xattr_try_free_block(xattr_ref);
911 block_header = NULL;
912 } else {
913 block_entry =
914 EXT4_XATTR_BFIRST(xattr_ref->block_bh);
915 block_data =
916 (char *)block_header + block_size_rem;
917 block_size_rem -=
918 sizeof(struct ext4_xattr_header);
919 xattr_ref->inode_ref->Inode.i_file_acl = 0;
920
921 xattr_ref->IsOnDiskInodeDirty = TRUE;
923 }
924 }
925 }
926
927 list_for_each_entry(item, &xattr_ref->ordered_list, struct ext4_xattr_item, list_node) {
928 if (item->in_inode) {
929 ibody_data = (char *)ibody_data -
930 EXT4_XATTR_SIZE(item->data_size);
932 ibody_data);
934 item->name_len);
935 memcpy(ibody_data, item->data, item->data_size);
937 inode_size_rem -= EXT4_XATTR_SIZE(item->data_size) +
938 EXT4_XATTR_LEN(item->name_len);
939
940 xattr_ref->IsOnDiskInodeDirty = TRUE;
941 continue;
942 }
943 if (EXT4_XATTR_SIZE(item->data_size) +
944 EXT4_XATTR_LEN(item->name_len) >
945 block_size_rem) {
946 ret = -ENOSPC;
947 DbgPrint("ext4_xattr.c: IMPOSSIBLE -ENOSPC AS WE DID INSPECTION!\n");
948 ASSERT(0);
949 }
950 block_data =
951 (char *)block_data - EXT4_XATTR_SIZE(item->data_size);
952 ext4_xattr_set_block_entry(item, block_header, block_entry,
953 block_data);
954 memcpy(EXT4_XATTR_NAME(block_entry), item->name,
955 item->name_len);
956 memcpy(block_data, item->data, item->data_size);
957 ext4_xattr_compute_hash(block_header, block_entry);
958 block_entry = EXT4_XATTR_NEXT(block_entry);
959 block_size_rem -= EXT4_XATTR_SIZE(item->data_size) +
960 EXT4_XATTR_LEN(item->name_len);
961
962 block_modified = TRUE;
963 }
964 xattr_ref->dirty = FALSE;
965 if (block_modified) {
966 ext4_xattr_rehash(block_header,
967 EXT4_XATTR_BFIRST(xattr_ref->block_bh));
969 xattr_ref->block_bh->b_blocknr,
970 block_header);
972 }
973
974Finish:
975 return ret;
976}
977
979 int (*iter)(struct ext4_xattr_ref *ref,
980 struct ext4_xattr_item *item,
981 BOOL is_last))
982{
983 struct ext4_xattr_item *item;
984 if (!ref->iter_from) {
985 struct list_head *first_node;
986 first_node = ref->ordered_list.next;
987 if (first_node && first_node != &ref->ordered_list) {
988 ref->iter_from =
989 list_entry(first_node,
990 struct ext4_xattr_item,
991 list_node);
992 }
993 }
994
995 item = ref->iter_from;
996 while (item) {
997 struct list_head *next_node;
998 struct ext4_xattr_item *next_item;
1000 next_node = item->list_node.next;
1001 if (next_node && next_node != &ref->ordered_list)
1002 next_item = list_entry(next_node, struct ext4_xattr_item,
1003 list_node);
1004 else
1005 next_item = NULL;
1006 if (iter)
1007 ret = iter(ref, item, !next_item);
1008
1011 ref->iter_from = NULL;
1012
1013 break;
1014 }
1015 item = next_item;
1016 }
1017}
1018
1020{
1021 ref->iter_from = NULL;
1022}
1023
1025 const char *name, size_t name_len, const void *data,
1026 size_t data_size, BOOL replace)
1027{
1028 int ret = 0;
1029 struct ext4_xattr_item *item =
1031 if (replace) {
1032 if (!item) {
1033 ret = -ENODATA;
1034 goto Finish;
1035 }
1036 if (item->data_size != data_size)
1038
1039 if (ret != 0) {
1040 goto Finish;
1041 }
1042 memcpy(item->data, data, data_size);
1043 } else {
1044 if (item) {
1045 ret = -EEXIST;
1046 goto Finish;
1047 }
1049 data, data_size, &ret);
1050 }
1051Finish:
1052 return ret;
1053}
1054
1056 const char *name, size_t name_len, const void *data,
1057 size_t data_size)
1058{
1059 int ret = 0;
1060 struct ext4_xattr_item *item =
1062 if (item) {
1063 ret = -EEXIST;
1064 goto Finish;
1065 }
1067 data, data_size, &ret);
1068Finish:
1069 return ret;
1070}
1071
1073 const char *name, size_t name_len)
1074{
1076}
1077
1079 const char *name, size_t name_len, void *buf,
1080 size_t buf_size, size_t *data_size)
1081{
1082 int ret = 0;
1083 size_t item_size = 0;
1084 struct ext4_xattr_item *item =
1086
1087 if (!item) {
1088 ret = -ENODATA;
1089 goto Finish;
1090 }
1091 item_size = item->data_size;
1092 if (buf_size > item_size)
1093 buf_size = item_size;
1094
1095 if (buf)
1096 memcpy(buf, item->data, buf_size);
1097
1098Finish:
1099 if (data_size)
1100 *data_size = item_size;
1101
1102 return ret;
1103}
1104
1106 struct ext4_xattr_ref *ref)
1107{
1108 int rc;
1109 ext4_fsblk_t xattr_block;
1110 xattr_block = inode_ref->Inode.i_file_acl;
1111 memset(&ref->root, 0, sizeof(struct rb_root));
1112 ref->ea_size = 0;
1113 ref->iter_from = NULL;
1114 if (xattr_block) {
1115 ref->block_bh = extents_bread(&fs->sb, xattr_block);
1116 if (!ref->block_bh)
1117 return -EIO;
1118
1119 ref->block_loaded = TRUE;
1120 } else
1121 ref->block_loaded = FALSE;
1122
1123 ref->inode_ref = inode_ref;
1124 ref->fs = fs;
1125 INIT_LIST_HEAD(&ref->ordered_list);
1126
1127 ref->OnDiskInode = Ext2AllocateInode(fs);
1128 if (!ref->OnDiskInode) {
1129 if (xattr_block) {
1130 extents_brelse(ref->block_bh);
1131 ref->block_bh = NULL;
1132 }
1133 return -ENOMEM;
1134 }
1135 if (!Ext2LoadInodeXattr(fs, &inode_ref->Inode, ref->OnDiskInode)) {
1136 if (xattr_block) {
1137 extents_brelse(ref->block_bh);
1138 ref->block_bh = NULL;
1139 }
1140
1141 Ext2DestroyInode(fs, ref->OnDiskInode);
1142 return -EIO;
1143 }
1144 ref->IsOnDiskInodeDirty = FALSE;
1145
1147 sizeof(struct ext4_xattr_ibody_header) +
1148 sizeof(__u32))
1149 ref->inode_size_rem = 0;
1150 else {
1151 ref->inode_size_rem =
1153 sizeof(struct ext4_xattr_ibody_header);
1154 }
1155
1156 ref->block_size_rem =
1158 sizeof(struct ext4_xattr_header) -
1159 sizeof(__u32);
1160
1161 rc = ext4_xattr_fetch(ref);
1162 if (rc != 0) {
1164 if (xattr_block) {
1165 extents_brelse(ref->block_bh);
1166 ref->block_bh = NULL;
1167 }
1168
1169 Ext2DestroyInode(fs, ref->OnDiskInode);
1170 return rc;
1171 }
1172 ref->IrpContext = IrpContext;
1173 return 0;
1174}
1175
1177{
1178 int ret;
1179 sector_t orig_file_acl = ref->inode_ref->Inode.i_file_acl;
1181 if (ref->IsOnDiskInodeDirty) {
1182 ASSERT(ref->fs->InodeSize > EXT4_GOOD_OLD_INODE_SIZE);
1183
1184 /* As we may do block allocation in ext4_xattr_write_to_disk */
1185 if (ret)
1186 ref->inode_ref->Inode.i_file_acl = orig_file_acl;
1187
1188 if (!ret) {
1189 ret = Ext2SaveInode(ref->IrpContext, ref->fs, &ref->inode_ref->Inode)
1190 ? 0 : -EIO;
1191 if (!ret) {
1192 ret = Ext2SaveInodeXattr(ref->IrpContext,
1193 ref->fs,
1194 &ref->inode_ref->Inode,
1195 ref->OnDiskInode)
1196 ? 0 : -EIO;
1197 }
1198 }
1199 ref->IsOnDiskInodeDirty = FALSE;
1200 }
1201 if (ref->block_loaded) {
1202 if (!ret)
1203 extents_brelse(ref->block_bh);
1204 else
1205 extents_bforget(ref->block_bh);
1206
1207 ref->block_bh = NULL;
1208 ref->block_loaded = FALSE;
1209 }
1211 Ext2DestroyInode(ref->fs, ref->OnDiskInode);
1212 ref->OnDiskInode = NULL;
1213 ref->inode_ref = NULL;
1214 ref->fs = NULL;
1215 return ret;
1216}
1217
1219 const char *prefix;
1221};
1222
1223static const struct xattr_prefix prefix_tbl[] = {
1224 {"user.", EXT4_XATTR_INDEX_USER},
1225 {"system.posix_acl_access", EXT4_XATTR_INDEX_POSIX_ACL_ACCESS},
1226 {"system.posix_acl_default", EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT},
1227 {"trusted.", EXT4_XATTR_INDEX_TRUSTED},
1228 {"security.", EXT4_XATTR_INDEX_SECURITY},
1229 {"system.", EXT4_XATTR_INDEX_SYSTEM},
1230 {"system.richacl", EXT4_XATTR_INDEX_RICHACL},
1231 {NULL, 0},
1232};
1233
1234const char *ext4_extract_xattr_name(const char *full_name, size_t full_name_len,
1235 __u8 *name_index, size_t *name_len,
1236 BOOL *found)
1237{
1238 int i;
1240 ASSERT(found);
1241
1242 *found = FALSE;
1243
1244 if (!full_name_len) {
1245 if (name_len)
1246 *name_len = 0;
1247
1248 return NULL;
1249 }
1250
1251 for (i = 0; prefix_tbl[i].prefix; i++) {
1252 size_t prefix_len = strlen(prefix_tbl[i].prefix);
1253 if (full_name_len >= prefix_len &&
1254 !memcmp(full_name, prefix_tbl[i].prefix, prefix_len)) {
1255 BOOL require_name =
1256 prefix_tbl[i].prefix[prefix_len - 1] == '.';
1257 *name_index = prefix_tbl[i].name_index;
1258 if (name_len)
1259 *name_len = full_name_len - prefix_len;
1260
1261 if (!(full_name_len - prefix_len) && require_name)
1262 return NULL;
1263
1264 *found = TRUE;
1265 if (require_name)
1266 return full_name + prefix_len;
1267
1268 return NULL;
1269 }
1270 }
1271 if (name_len)
1272 *name_len = 0;
1273
1274 return NULL;
1275}
1276
1278 size_t *ret_prefix_len)
1279{
1280 int i;
1281
1282 for (i = 0; prefix_tbl[i].prefix; i++) {
1283 size_t prefix_len = strlen(prefix_tbl[i].prefix);
1285 if (ret_prefix_len)
1286 *ret_prefix_len = prefix_len;
1287
1288 return prefix_tbl[i].prefix;
1289 }
1290 }
1291 if (ret_prefix_len)
1292 *ret_prefix_len = 0;
1293
1294 return NULL;
1295}
#define ENOENT
Definition: acclib.h:79
#define EEXIST
Definition: acclib.h:88
#define ENOMEM
Definition: acclib.h:84
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define EIO
Definition: acclib.h:81
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
LONG NTSTATUS
Definition: precomp.h:26
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
u8 __u8
Definition: btrfs.h:17
u32 __u32
Definition: btrfs.h:19
u64 __u64
Definition: btrfs.h:20
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
BOOL next_node(stream_t *stream, strbuf_t *buf)
Definition: stream.c:140
#define INIT_LIST_HEAD(ptr)
Definition: list.h:24
#define list_entry(ptr, type, member)
Definition: list.h:185
#define list_for_each_entry(pos, head, member)
Definition: list.h:221
static void list_del_init(struct list_head *entry)
Definition: list.h:100
superblock * sb
Definition: btrfs.c:4261
#define ENODATA
Definition: errno.h:65
#define ENOSPC
Definition: errno.h:34
struct rb_node * rb_first(struct rb_root *)
Definition: rbtree.c:294
struct rb_node * rb_next(struct rb_node *)
Definition: rbtree.c:320
void rb_erase(struct rb_node *, struct rb_root *)
Definition: rbtree.c:223
void rb_insert(struct rb_root *root, struct rb_node *node, int(*cmp)(struct rb_node *, struct rb_node *))
Definition: rbtree.c:392
unsigned __int64 sector_t
Definition: types.h:82
#define __le32
Definition: types.h:44
signed __int32 __s32
Definition: types.h:23
BOOLEAN Ext2SaveInodeXattr(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN struct inode *Inode, IN PEXT2_INODE InodeXattr)
Definition: generic.c:621
VOID Ext2DestroyInode(IN PEXT2_VCB Vcb, IN PEXT2_INODE inode)
Definition: memory.c:406
NTSTATUS Ext2NewBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN ULONG GroupHint, IN ULONG BlockHint, OUT PULONG Block, IN OUT PULONG Number)
Definition: generic.c:1008
NTSTATUS Ext2FreeBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN ULONG Block, IN ULONG Number)
Definition: generic.c:1217
BOOLEAN Ext2LoadInodeXattr(IN PEXT2_VCB Vcb, IN struct inode *Inode, IN PEXT2_INODE InodeXattr)
Definition: generic.c:590
BOOLEAN Ext2SaveInode(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN struct inode *Inode)
Definition: generic.c:552
#define BLOCKS_PER_GROUP
Definition: ext2fs.h:100
PEXT2_INODE Ext2AllocateInode(PEXT2_VCB Vcb)
Definition: memory.c:387
int Ext2LinuxError(NTSTATUS Status)
Definition: misc.c:304
unsigned long long ext4_fsblk_t
Definition: ext3_fs_i.h:27
static struct ext4_xattr_item * ext4_xattr_item_alloc(__u8 name_index, const char *name, size_t name_len)
Definition: ext4_xattr.c:232
static int ext4_xattr_block_fetch(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:338
static void * ext4_xattr_entry_data(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_entry *entry, BOOL in_inode)
Definition: ext4_xattr.c:309
#define ext4_xattr_block_checksum(...)
Definition: ext4_xattr.c:149
static int ext4_xattr_try_alloc_block(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:774
#define BLOCK_HASH_SHIFT
Definition: ext4_xattr.c:89
#define NAME_HASH_SHIFT
Definition: ext4_xattr.c:60
static int ext4_xattr_write_to_disk(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:858
static void ext4_xattr_set_inode_entry(struct ext4_xattr_item *item, struct ext4_xattr_ibody_header *ibody_header, struct ext4_xattr_entry *entry, void *ibody_data_ptr)
Definition: ext4_xattr.c:833
static void ext4_xattr_compute_hash(struct ext4_xattr_header *header, struct ext4_xattr_entry *entry)
Definition: ext4_xattr.c:63
static ext4_fsblk_t ext4_inode_to_goal_block(struct inode *inode)
Definition: ext4_xattr.c:53
static const struct xattr_prefix prefix_tbl[]
Definition: ext4_xattr.c:1223
static int ext4_xattr_item_cmp(struct rb_node *_a, struct rb_node *_b)
Definition: ext4_xattr.c:161
#define VALUE_HASH_SHIFT
Definition: ext4_xattr.c:61
static void ext4_xattr_try_free_block(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:808
static void ext4_xattr_item_free_data(struct ext4_xattr_item *item)
Definition: ext4_xattr.c:275
static void ext4_xattr_set_block_entry(struct ext4_xattr_item *item, struct ext4_xattr_header *block_header, struct ext4_xattr_entry *block_entry, void *block_data_ptr)
Definition: ext4_xattr.c:845
static void ext4_xattr_item_free(struct ext4_xattr_item *item)
Definition: ext4_xattr.c:301
static int ext4_xattr_item_alloc_data(struct ext4_xattr_item *item, const void *orig_data, size_t data_size)
Definition: ext4_xattr.c:258
static int ext4_xattr_remove_item(struct ext4_xattr_ref *xattr_ref, __u8 name_index, const char *name, size_t name_len)
Definition: ext4_xattr.c:605
static void ext4_free_blocks(void *icb, struct inode *inode, ext4_fsblk_t block, int count, int flags)
Definition: ext4_xattr.c:45
static struct ext4_xattr_item * ext4_xattr_item_search(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *name)
Definition: ext4_xattr.c:194
static struct ext4_xattr_item * ext4_xattr_lookup_item(struct ext4_xattr_ref *xattr_ref, __u8 name_index, const char *name, size_t name_len)
Definition: ext4_xattr.c:467
static int ext4_xattr_fetch(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:449
static __s32 ext4_xattr_inode_space(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:436
static ext4_fsblk_t ext4_new_meta_blocks(void *icb, struct inode *inode, ext4_fsblk_t goal, unsigned int flags, unsigned long *count, int *errp)
Definition: ext4_xattr.c:20
static void ext4_xattr_item_insert(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item)
Definition: ext4_xattr.c:216
static int ext4_xattr_item_resize_data(struct ext4_xattr_item *item, size_t new_data_size)
Definition: ext4_xattr.c:283
static void ext4_xattr_item_remove(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item)
Definition: ext4_xattr.c:224
static struct ext4_xattr_item * ext4_xattr_insert_item_ordered(struct ext4_xattr_ref *xattr_ref, __u8 name_index, const char *name, size_t name_len, const void *data, size_t data_size, int *err)
Definition: ext4_xattr.c:542
static void ext4_xattr_set_block_header(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:821
static struct ext4_xattr_item * ext4_xattr_insert_item(struct ext4_xattr_ref *xattr_ref, __u8 name_index, const char *name, size_t name_len, const void *data, size_t data_size, int *err)
Definition: ext4_xattr.c:486
static void ext4_xattr_set_block_checksum(PEXT2_MCB inode_ref, ext4_fsblk_t blocknr, struct ext4_xattr_header *header)
Definition: ext4_xattr.c:153
static int ext4_xattr_inode_fetch(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:385
static __s32 ext4_xattr_block_space(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:444
static void ext4_xattr_rehash(struct ext4_xattr_header *header, struct ext4_xattr_entry *entry)
Definition: ext4_xattr.c:96
static int ext4_xattr_resize_item(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item, size_t new_data_size)
Definition: ext4_xattr.c:646
Extended Attribute manipulation.
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble n
Definition: glext.h:7729
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define container_of(ptr, type, member)
Definition: glue.h:15
#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS
Definition: ext4_xattr.h:53
#define EXT4_XATTR_ITERATE_STOP
Definition: ext4_xattr.h:163
#define EXT4_XATTR_IFIRST(hdr)
Definition: ext4_xattr.h:110
int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, __u8 name_index, const char *name, size_t name_len, void *buf, size_t buf_size, size_t *data_size)
Definition: ext4_xattr.c:1078
#define EXT4_GOOD_OLD_INODE_SIZE
Definition: ext4_xattr.h:89
int ext4_fs_set_xattr(struct ext4_xattr_ref *ref, __u8 name_index, const char *name, size_t name_len, const void *data, size_t data_size, BOOL replace)
Definition: ext4_xattr.c:1024
#define EXT4_XATTR_INDEX_SYSTEM
Definition: ext4_xattr.h:58
#define EXT4_XATTR_IS_LAST_ENTRY(entry)
Definition: ext4_xattr.h:119
#define EXT4_XATTR_IHDR(raw_inode)
Definition: ext4_xattr.h:105
#define EXT4_XATTR_NAME(entry)
Definition: ext4_xattr.h:102
#define EXT4_XATTR_MAGIC
Definition: ext4_xattr.h:46
int ext4_fs_set_xattr_ordered(struct ext4_xattr_ref *ref, __u8 name_index, const char *name, size_t name_len, const void *data, size_t data_size)
Definition: ext4_xattr.c:1055
#define EXT4_XATTR_ITERATE_CONT
Definition: ext4_xattr.h:162
#define EXT4_XATTR_INDEX_SECURITY
Definition: ext4_xattr.h:57
#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT
Definition: ext4_xattr.h:54
#define EXT4_XATTR_ENTRY(ptr)
Definition: ext4_xattr.h:115
#define EXT4_XATTR_INDEX_TRUSTED
Definition: ext4_xattr.h:55
const char * ext4_extract_xattr_name(const char *full_name, size_t full_name_len, __u8 *name_index, size_t *name_len, BOOL *found)
Definition: ext4_xattr.c:1234
#define EXT4_XATTR_SIZE(size)
Definition: ext4_xattr.h:100
#define EXT4_XATTR_BFIRST(block)
Definition: ext4_xattr.h:117
#define EXT4_XATTR_LEN(name_len)
Definition: ext4_xattr.h:94
void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref)
Definition: ext4_xattr.c:1019
void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref, int(*iter)(struct ext4_xattr_ref *ref, struct ext4_xattr_item *item, BOOL is_last))
Definition: ext4_xattr.c:978
void ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:736
const char * ext4_get_xattr_name_prefix(__u8 name_index, size_t *ret_prefix_len)
Definition: ext4_xattr.c:1277
int ext4_fs_remove_xattr(struct ext4_xattr_ref *ref, __u8 name_index, const char *name, size_t name_len)
Definition: ext4_xattr.c:1072
#define EXT4_XATTR_INDEX_USER
Definition: ext4_xattr.h:52
int ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref)
Definition: ext4_xattr.c:1176
#define EXT4_XATTR_INDEX_RICHACL
Definition: ext4_xattr.h:59
#define EXT4_XATTR_PAD_BITS
Definition: ext4_xattr.h:91
#define EXT4_XATTR_BHDR(block)
Definition: ext4_xattr.h:113
int ext4_fs_get_xattr_ref(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB fs, PEXT2_MCB inode_ref, struct ext4_xattr_ref *ref)
Definition: ext4_xattr.c:1105
#define EXT4_XATTR_NEXT(entry)
Definition: ext4_xattr.h:97
#define EXT4_XATTR_ROUND
Definition: ext4_xattr.h:93
#define DbgPrint
Definition: hal.h:12
#define fs
Definition: i386-dis.c:444
uint32_t entry
Definition: isohybrid.c:63
static DWORD block_size(DWORD block)
Definition: jsutils.c:66
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
struct buffer_head * extents_bread(struct super_block *sb, sector_t block)
Definition: ext4_bh.c:15
#define kmalloc(size, gfp)
Definition: module.h:1125
#define GFP_NOFS
Definition: module.h:669
void extents_brelse(struct buffer_head *bh)
Definition: ext4_bh.c:51
#define le16_to_cpu
Definition: module.h:151
#define cpu_to_le32
Definition: module.h:148
void * kzalloc(int size, int flags)
Definition: linux.c:34
#define kfree(p)
Definition: module.h:1126
struct buffer_head * extents_bwrite(struct super_block *sb, sector_t block)
Definition: ext4_bh.c:27
#define le32_to_cpu
Definition: module.h:149
static void le32_add_cpu(__le32 *var, u32 val)
Definition: module.h:191
void extents_bforget(struct buffer_head *bh)
Definition: ext4_bh.c:64
void extents_mark_buffer_dirty(struct buffer_head *bh)
Definition: ext4_bh.c:39
#define cpu_to_le16
Definition: module.h:150
static ATOM item
Definition: dde.c:856
#define Vcb
Definition: cdprocs.h:1415
#define err(...)
INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *doMore)
Definition: replace.c:47
#define __u8
Definition: types.h:12
#define memset(x, y, z)
Definition: compat.h:39
struct inode Inode
Definition: ext2fs.h:945
ULONG BlockSize
Definition: ext2fs.h:728
ULONG InodeSize
Definition: ext2fs.h:740
struct super_block sb
Definition: ext2fs.h:775
__le16 i_extra_isize
Definition: ext2_fs.h:276
Definition: ext4_xattr.h:78
__le32 e_value_block
Definition: ext4_xattr.h:82
__le32 e_hash
Definition: ext4_xattr.h:84
__le32 e_value_size
Definition: ext4_xattr.h:83
__le16 e_value_offs
Definition: ext4_xattr.h:81
__u8 e_name_len
Definition: ext4_xattr.h:79
__u8 e_name_index
Definition: ext4_xattr.h:80
struct list_head list_node
Definition: ext4_xattr.h:137
size_t data_size
Definition: ext4_xattr.h:134
struct rb_node node
Definition: ext4_xattr.h:136
size_t block_size_rem
Definition: ext4_xattr.h:152
size_t ea_size
Definition: ext4_xattr.h:150
PEXT2_VCB fs
Definition: ext4_xattr.h:153
struct rb_root root
Definition: ext4_xattr.h:158
struct ext4_xattr_item * iter_from
Definition: ext4_xattr.h:156
BOOL IsOnDiskInodeDirty
Definition: ext4_xattr.h:147
PEXT2_IRP_CONTEXT IrpContext
Definition: ext4_xattr.h:141
struct buffer_head * block_bh
Definition: ext4_xattr.h:143
size_t inode_size_rem
Definition: ext4_xattr.h:151
PEXT2_INODE OnDiskInode
Definition: ext4_xattr.h:146
PEXT2_MCB inode_ref
Definition: ext4_xattr.h:144
struct list_head ordered_list
Definition: ext4_xattr.h:159
Definition: ffs.h:70
Definition: _hash_fun.h:40
Definition: fs.h:78
__u64 i_blocks
Definition: fs.h:85
__u32 i_ino
Definition: fs.h:79
struct super_block * i_sb
Definition: fs.h:96
Definition: list.h:15
Definition: name.c:39
Definition: rbtree.h:98
Definition: send.c:48
Definition: ps.c:97
BTRFS_UUID uuid
Definition: btrfs.h:225
const char * prefix
Definition: ext4_xattr.c:1219
uint32_t ULONG
Definition: typedefs.h:59
Definition: dlist.c:348
Definition: pdh_main.c:94
int ret
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
static unsigned int block
Definition: xmlmemory.c:101