ReactOS  0.4.13-dev-52-g0efcfec
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 
20 static 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 
45 static 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 {
55  PEXT2_VCB Vcb;
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++) {
71  hash = (hash << NAME_HASH_SHIFT) ^
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--) {
81  hash = (hash << VALUE_HASH_SHIFT) ^
82  (hash >> (8 * sizeof(hash) - VALUE_HASH_SHIFT)) ^
83  le32_to_cpu(*value++);
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
119 static __u32
121  ext4_fsblk_t blocknr,
122  struct ext4_xattr_header *header)
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 
152 static void
154  ext4_fsblk_t blocknr,
155  struct ext4_xattr_header *header)
156 {
157  /* TODO: Need METADATA_CSUM supports. */
158  header->h_checksum = 0;
159 }
160 
161 static 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 
193 static 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 
216 static 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 
224 static 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 
231 static 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 
309 static void *ext4_xattr_entry_data(struct ext4_xattr_ref *xattr_ref,
310  struct ext4_xattr_entry *entry,
311  BOOL in_inode)
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 
338 static 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 
381 Finish:
382  return ret;
383 }
384 
385 static 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 
432 Finish:
433  return ret;
434 }
435 
436 static __s32 ext4_xattr_inode_space(struct ext4_xattr_ref *xattr_ref)
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 
444 static __s32 ext4_xattr_block_space(struct ext4_xattr_ref *xattr_ref)
445 {
446  return xattr_ref->fs->BlockSize;
447 }
448 
449 static 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 
466 static struct ext4_xattr_item *
468  const char *name, size_t name_len)
469 {
470  struct ext4_xattr_item tmp = {
471  FALSE,
472  FALSE,
473  name_index,
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 
485 static 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 
541 static 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 
605 static 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 
646 static 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 
736 void ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref)
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)
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 
774 static 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 
804 Finish:
805  return ret;
806 }
807 
808 static 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 
821 static 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 
832 static 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 
858 static 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);
899  ext4_xattr_set_block_header(xattr_ref);
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);
931  ext4_xattr_set_inode_entry(item, ibody_header, entry,
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 
974 Finish:
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)
1003  list_node);
1004  else
1005  next_item = NULL;
1006  if (iter)
1007  ret = iter(ref, item, !next_item);
1008 
1009  if (ret != EXT4_XATTR_ITERATE_CONT) {
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  }
1051 Finish:
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);
1068 Finish:
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 
1098 Finish:
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 
1223 static 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 
1234 const 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;
1239  ASSERT(name_index);
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);
1284  if (prefix_tbl[i].name_index == name_index) {
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 }
static unsigned int block
Definition: xmlmemory.c:118
#define EXT4_XATTR_LEN(name_len)
Definition: ext4_xattr.h:94
__le16 i_extra_isize
Definition: ext2_fs.h:276
static __s32 ext4_xattr_inode_space(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:436
static ext4_fsblk_t ext4_inode_to_goal_block(struct inode *inode)
Definition: ext4_xattr.c:53
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
unsigned char __u8
Definition: compat.h:88
const char * prefix
Definition: ext4_xattr.c:1219
#define NAME_HASH_SHIFT
Definition: ext4_xattr.c:60
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:941
PEXT2_INODE Ext2AllocateInode(PEXT2_VCB Vcb)
Definition: memory.c:387
size_t data_size
Definition: ext4_xattr.h:134
#define TRUE
Definition: types.h:120
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
struct inode Inode
Definition: ext2fs.h:936
ULONG InodeSize
Definition: ext2fs.h:731
static struct ext4_xattr_item * ext4_xattr_item_alloc(__u8 name_index, const char *name, size_t name_len)
Definition: ext4_xattr.c:232
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
BOOLEAN Ext2SaveInodeXattr(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN struct inode *Inode, IN PEXT2_INODE InodeXattr)
Definition: generic.c:617
ULONG BlockSize
Definition: ext2fs.h:719
unsigned __int64 sector_t
Definition: types.h:78
static int ext4_xattr_fetch(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:449
__le16 e_value_offs
Definition: ext4_xattr.h:81
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define DbgPrint
Definition: loader.c:25
__u8 e_name_index
Definition: ext4_xattr.h:80
#define EXT4_XATTR_PAD_BITS
Definition: ext4_xattr.h:91
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
superblock * sb
Definition: btrfs.c:3876
static void ext4_free_blocks(void *icb, struct inode *inode, ext4_fsblk_t block, int count, int flags)
Definition: ext4_xattr.c:45
#define EXT4_XATTR_NEXT(entry)
Definition: ext4_xattr.h:97
Extended Attribute manipulation.
size_t block_size_rem
Definition: ext4_xattr.h:152
static int ext4_xattr_block_fetch(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:338
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define EXT4_XATTR_SIZE(size)
Definition: ext4_xattr.h:100
struct rb_node * rb_next(struct rb_node *)
Definition: rbtree.c:320
#define EXT4_XATTR_ENTRY(ptr)
Definition: ext4_xattr.h:115
uint8_t entry
Definition: isohybrid.c:63
#define INIT_LIST_HEAD(ptr)
Definition: list.h:24
#define le16_to_cpu
Definition: module.h:149
LONG NTSTATUS
Definition: precomp.h:26
#define ENODATA
Definition: errno.h:65
void rb_insert(struct rb_root *root, struct rb_node *node, int(*cmp)(struct rb_node *, struct rb_node *))
Definition: rbtree.c:392
#define GFP_NOFS
Definition: module.h:659
PEXT2_IRP_CONTEXT IrpContext
Definition: ext4_xattr.h:141
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
GLdouble n
Definition: glext.h:7729
static const struct xattr_prefix prefix_tbl[]
Definition: ext4_xattr.c:1223
__le32 e_value_size
Definition: ext4_xattr.h:83
__le32 e_value_block
Definition: ext4_xattr.h:82
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
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
Definition: fs.h:235
BOOL next_node(stream_t *stream, strbuf_t *buf)
Definition: stream.c:140
static void ext4_xattr_item_insert(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item)
Definition: ext4_xattr.c:216
Definition: send.c:47
struct rb_node * rb_first(struct rb_root *)
Definition: rbtree.c:294
Definition: arc.h:48
#define EEXIST
Definition: acclib.h:88
struct super_block sb
Definition: ext2fs.h:766
#define list_entry(ptr, type, member)
Definition: list.h:185
static int ext4_xattr_write_to_disk(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:858
static void ext4_xattr_item_remove(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item)
Definition: ext4_xattr.c:224
static DWORD block_size(DWORD block)
Definition: jsutils.c:64
struct ext4_xattr_item * iter_from
Definition: ext4_xattr.h:156
unsigned long long ext4_fsblk_t
Definition: ext3_fs_i.h:27
#define list_for_each_entry(pos, head, member)
Definition: list.h:221
Definition: fs.h:78
Definition: list.h:15
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
struct node node
#define EXT4_XATTR_BFIRST(block)
Definition: ext4_xattr.h:117
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
void rb_erase(struct rb_node *, struct rb_root *)
Definition: rbtree.c:223
static void ext4_xattr_try_free_block(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:808
unsigned int BOOL
Definition: ntddk_ex.h:94
#define EXT4_XATTR_INDEX_SECURITY
Definition: ext4_xattr.h:57
#define a
Definition: ke_i.h:78
#define EXT4_XATTR_INDEX_RICHACL
Definition: ext4_xattr.h:59
#define VALUE_HASH_SHIFT
Definition: ext4_xattr.c:61
size_t ea_size
Definition: ext4_xattr.h:150
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
__u8 e_name_len
Definition: ext4_xattr.h:79
#define EXT4_XATTR_INDEX_USER
Definition: ext4_xattr.h:52
PEXT2_VCB fs
Definition: ext4_xattr.h:153
#define le32_to_cpu
Definition: module.h:147
Definition: arc.h:49
void extents_brelse(struct buffer_head *bh)
Definition: ext4_bh.c:51
static void list_del_init(struct list_head *entry)
Definition: list.h:100
static __inline tree_data * last_item(tree *t)
Definition: treefuncs.c:676
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS Ext2FreeBlock(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN ULONG Block, IN ULONG Number)
Definition: generic.c:1150
void extents_mark_buffer_dirty(struct buffer_head *bh)
Definition: ext4_bh.c:39
struct buffer_head * block_bh
Definition: ext4_xattr.h:143
PEXT2_INODE OnDiskInode
Definition: ext4_xattr.h:146
BOOLEAN Ext2LoadInodeXattr(IN PEXT2_VCB Vcb, IN struct inode *Inode, IN PEXT2_INODE InodeXattr)
Definition: generic.c:586
static void ext4_xattr_compute_hash(struct ext4_xattr_header *header, struct ext4_xattr_entry *entry)
Definition: ext4_xattr.c:63
#define EXT4_XATTR_INDEX_SYSTEM
Definition: ext4_xattr.h:58
__u64 i_blocks
Definition: fs.h:85
#define b
Definition: ke_i.h:79
#define EXT4_XATTR_IS_LAST_ENTRY(entry)
Definition: ext4_xattr.h:119
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
INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *doMore)
Definition: replace.c:47
struct list_head list_node
Definition: ext4_xattr.h:137
BOOL IsOnDiskInodeDirty
Definition: ext4_xattr.h:147
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
#define EXT4_XATTR_INDEX_TRUSTED
Definition: ext4_xattr.h:55
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define EXT4_XATTR_IFIRST(hdr)
Definition: ext4_xattr.h:110
int ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref)
Definition: ext4_xattr.c:1176
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BLOCK_HASH_SHIFT
Definition: ext4_xattr.c:89
static __inline tree_data * next_item(tree *t, tree_data *td)
Definition: treefuncs.c:321
size_t inode_size_rem
Definition: ext4_xattr.h:151
#define Vcb
Definition: cdprocs.h:1425
#define ext4_xattr_block_checksum(...)
Definition: ext4_xattr.c:149
#define container_of(ptr, type, member)
Definition: glue.h:15
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_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref)
Definition: ext4_xattr.c:1019
static void ext4_xattr_item_free(struct ext4_xattr_item *item)
Definition: ext4_xattr.c:301
unsigned int __u32
Definition: compat.h:90
static void ext4_xattr_rehash(struct ext4_xattr_header *header, struct ext4_xattr_entry *entry)
Definition: ext4_xattr.c:96
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
__le32 e_hash
Definition: ext4_xattr.h:84
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
int ret
#define EXT4_XATTR_ITERATE_STOP
Definition: ext4_xattr.h:163
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
static void ext4_xattr_item_free_data(struct ext4_xattr_item *item)
Definition: ext4_xattr.c:275
#define err(...)
#define EXT4_XATTR_IHDR(raw_inode)
Definition: ext4_xattr.h:105
VOID Ext2DestroyInode(IN PEXT2_VCB Vcb, IN PEXT2_INODE inode)
Definition: memory.c:406
static int ext4_xattr_item_resize_data(struct ext4_xattr_item *item, size_t new_data_size)
Definition: ext4_xattr.c:283
__u32 i_ino
Definition: fs.h:79
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 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 int ext4_xattr_inode_fetch(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:385
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
signed __int32 __s32
Definition: types.h:23
__WINE_SERVER_LIST_INLINE int list_empty(const struct list *list)
Definition: list.h:143
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
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
static ATOM item
Definition: dde.c:856
#define EXT4_XATTR_ITERATE_CONT
Definition: ext4_xattr.h:162
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
void * kmalloc(size_t, int)
#define fs
Definition: i386-dis.c:435
BTRFS_UUID uuid
Definition: btrfs.h:204
static int ext4_xattr_item_cmp(struct rb_node *_a, struct rb_node *_b)
Definition: ext4_xattr.c:161
struct rb_root root
Definition: ext4_xattr.h:158
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
u64 __u64
Definition: btrfs.h:20
Definition: arc.h:46
static __s32 ext4_xattr_block_space(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:444
int Ext2LinuxError(NTSTATUS Status)
Definition: misc.c:304
#define EXT4_XATTR_ROUND
Definition: ext4_xattr.h:93
#define EXT4_XATTR_BHDR(block)
Definition: ext4_xattr.h:113
Definition: arc.h:40
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
Definition: name.c:36
unsigned int ULONG
Definition: retypes.h:1
static void le32_add_cpu(__le32 *var, u32 val)
Definition: module.h:189
const char * ext4_get_xattr_name_prefix(__u8 name_index, size_t *ret_prefix_len)
Definition: ext4_xattr.c:1277
#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS
Definition: ext4_xattr.h:53
Definition: rbtree.h:97
PEXT2_MCB inode_ref
Definition: ext4_xattr.h:144
struct super_block * i_sb
Definition: fs.h:96
#define EXT4_GOOD_OLD_INODE_SIZE
Definition: ext4_xattr.h:89
struct buffer_head * extents_bread(struct super_block *sb, sector_t block)
Definition: ext4_bh.c:15
#define EXT4_XATTR_MAGIC
Definition: ext4_xattr.h:46
static void ext4_xattr_set_block_header(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:821
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
#define cpu_to_le16
Definition: module.h:148
#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT
Definition: ext4_xattr.h:54
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
Definition: _hash_fun.h:40
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
#define EXT4_XATTR_NAME(entry)
Definition: ext4_xattr.h:102
static SERVICE_STATUS status
Definition: service.c:31
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
Definition: ext4_xattr.h:78
BOOLEAN Ext2SaveInode(IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN struct inode *Inode)
Definition: generic.c:548
static int ext4_xattr_try_alloc_block(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:774
#define BLOCKS_PER_GROUP
Definition: ext2fs.h:100
struct CFHEADER header
Definition: fdi.c:109
#define cpu_to_le32
Definition: module.h:146
void * kzalloc(int size, int flags)
Definition: linux.c:34
void ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref)
Definition: ext4_xattr.c:736
struct buffer_head * extents_bwrite(struct super_block *sb, sector_t block)
Definition: ext4_bh.c:27
void kfree(const void *)
struct list_head ordered_list
Definition: ext4_xattr.h:159
#define __le32
Definition: types.h:40
void extents_bforget(struct buffer_head *bh)
Definition: ext4_bh.c:64
Definition: dlist.c:348
Definition: ps.c:97