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 { 25 NTSTATUS status; 26 ULONG blockcnt = (count) ? *count : 1; 27 ULONG block = 0; 28 29 status = Ext2NewBlock((PEXT2_IRP_CONTEXT)icb, 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 { 48 Ext2FreeBlock((PEXT2_IRP_CONTEXT)icb, inode->i_sb->s_priv, (ULONG)block, count); 49 inode->i_blocks -= count * (inode->i_sb->s_blocksize >> 9); 50 return; 51 } 52 53 static inline ext4_fsblk_t ext4_inode_to_goal_block(struct inode *inode) 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 63 static inline void ext4_xattr_compute_hash(struct ext4_xattr_header *header, 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) >> 79 EXT4_XATTR_PAD_BITS; 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 */ 96 static void ext4_xattr_rehash(struct ext4_xattr_header *header, 97 struct ext4_xattr_entry *entry) 98 { 99 struct ext4_xattr_entry *here; 100 __u32 hash = 0; 101 102 ext4_xattr_compute_hash(header, entry); 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 120 ext4_xattr_block_checksum(PEXT2_MCB inode_ref, 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 153 ext4_xattr_set_block_checksum(PEXT2_MCB inode_ref, 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 * 194 ext4_xattr_item_search(struct ext4_xattr_ref *xattr_ref, 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, 220 ext4_xattr_item_cmp); 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 * 232 ext4_xattr_item_alloc(__u8 name_index, const char *name, size_t name_len) 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 248 if (name_index == EXT4_XATTR_INDEX_SYSTEM && 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 258 static int ext4_xattr_item_alloc_data(struct ext4_xattr_item *item, 259 const void *orig_data, size_t data_size) 260 { 261 void *data = NULL; 262 ASSERT(!item->data); 263 data = kmalloc(data_size, GFP_NOFS); 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 275 static void ext4_xattr_item_free_data(struct ext4_xattr_item *item) 276 { 277 ASSERT(item->data); 278 kfree(item->data); 279 item->data = NULL; 280 item->data_size = 0; 281 } 282 283 static int ext4_xattr_item_resize_data(struct ext4_xattr_item *item, 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 301 static void ext4_xattr_item_free(struct ext4_xattr_item *item) 302 { 303 if (item->data) 304 ext4_xattr_item_free_data(item); 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) { 316 struct ext4_xattr_ibody_header *header; 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); 350 entry = EXT4_XATTR_NEXT(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 } 367 if (ext4_xattr_item_alloc_data( 368 item, data, le32_to_cpu(entry->e_value_size)) != 0) { 369 ext4_xattr_item_free(item); 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; 390 struct ext4_xattr_ibody_header *header = NULL; 391 struct ext4_xattr_entry *entry = NULL; 392 int inode_size = xattr_ref->fs->InodeSize; 393 394 header = EXT4_XATTR_IHDR(xattr_ref->OnDiskInode); 395 entry = EXT4_XATTR_IFIRST(header); 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); 400 entry = EXT4_XATTR_NEXT(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 } 417 if (ext4_xattr_item_alloc_data( 418 item, data, le32_to_cpu(entry->e_value_size)) != 0) { 419 ext4_xattr_item_free(item); 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 * 467 ext4_xattr_lookup_item(struct ext4_xattr_ref *xattr_ref, __u8 name_index, 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 }; 477 if (name_index == EXT4_XATTR_INDEX_SYSTEM && 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 * 486 ext4_xattr_insert_item(struct ext4_xattr_ref *xattr_ref, __u8 name_index, 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; 492 item = ext4_xattr_item_alloc(name_index, name, name_len); 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 < 502 EXT4_XATTR_SIZE(data_size) + 503 EXT4_XATTR_LEN(item->name_len)) { 504 if (xattr_ref->block_size_rem < 505 EXT4_XATTR_SIZE(data_size) + 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 } 515 if (ext4_xattr_item_alloc_data(item, data, data_size) != 0) { 516 ext4_xattr_item_free(item); 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 * 542 ext4_xattr_insert_item_ordered(struct ext4_xattr_ref *xattr_ref, __u8 name_index, 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; 548 item = ext4_xattr_item_alloc(name_index, name, name_len); 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 < 563 EXT4_XATTR_SIZE(data_size) + 564 EXT4_XATTR_LEN(item->name_len)) 565 || 566 (last_item && !last_item->in_inode)) { 567 if (xattr_ref->block_size_rem < 568 EXT4_XATTR_SIZE(data_size) + 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 } 578 if (ext4_xattr_item_alloc_data(item, data, data_size) != 0) { 579 ext4_xattr_item_free(item); 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 = 611 ext4_xattr_lookup_item(xattr_ref, name_index, name, name_len); 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 = 618 container_of(next_node, 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); 639 ext4_xattr_item_free(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) 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); 756 ext4_xattr_item_free(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 = 782 ext4_inode_to_goal_block(&xattr_ref->inode_ref->Inode); 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 833 ext4_xattr_set_inode_entry(struct ext4_xattr_item *item, 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 845 static void ext4_xattr_set_block_entry(struct ext4_xattr_item *item, 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 903 extents_mark_buffer_dirty(xattr_ref->block_bh); 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; 922 extents_mark_buffer_dirty(xattr_ref->block_bh); 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); 933 memcpy(EXT4_XATTR_NAME(entry), item->name, 934 item->name_len); 935 memcpy(ibody_data, item->data, item->data_size); 936 entry = EXT4_XATTR_NEXT(entry); 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)); 968 ext4_xattr_set_block_checksum(xattr_ref->inode_ref, 969 xattr_ref->block_bh->b_blocknr, 970 block_header); 971 extents_mark_buffer_dirty(xattr_ref->block_bh); 972 } 973 974 Finish: 975 return ret; 976 } 977 978 void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref, 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; 999 int ret = EXT4_XATTR_ITERATE_CONT; 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 1009 if (ret != EXT4_XATTR_ITERATE_CONT) { 1010 if (ret == EXT4_XATTR_ITERATE_STOP) 1011 ref->iter_from = NULL; 1012 1013 break; 1014 } 1015 item = next_item; 1016 } 1017 } 1018 1019 void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref) 1020 { 1021 ref->iter_from = NULL; 1022 } 1023 1024 int ext4_fs_set_xattr(struct ext4_xattr_ref *ref, __u8 name_index, 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 = 1030 ext4_xattr_lookup_item(ref, name_index, name, name_len); 1031 if (replace) { 1032 if (!item) { 1033 ret = -ENODATA; 1034 goto Finish; 1035 } 1036 if (item->data_size != data_size) 1037 ret = ext4_xattr_resize_item(ref, item, 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 } 1048 item = ext4_xattr_insert_item(ref, name_index, name, name_len, 1049 data, data_size, &ret); 1050 } 1051 Finish: 1052 return ret; 1053 } 1054 1055 int ext4_fs_set_xattr_ordered(struct ext4_xattr_ref *ref, __u8 name_index, 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 = 1061 ext4_xattr_lookup_item(ref, name_index, name, name_len); 1062 if (item) { 1063 ret = -EEXIST; 1064 goto Finish; 1065 } 1066 item = ext4_xattr_insert_item_ordered(ref, name_index, name, name_len, 1067 data, data_size, &ret); 1068 Finish: 1069 return ret; 1070 } 1071 1072 int ext4_fs_remove_xattr(struct ext4_xattr_ref *ref, __u8 name_index, 1073 const char *name, size_t name_len) 1074 { 1075 return ext4_xattr_remove_item(ref, name_index, name, name_len); 1076 } 1077 1078 int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, __u8 name_index, 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 = 1085 ext4_xattr_lookup_item(ref, name_index, name, name_len); 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 1105 int ext4_fs_get_xattr_ref(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB fs, PEXT2_MCB inode_ref, 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 1146 if (ext4_xattr_inode_space(ref) < 1147 sizeof(struct ext4_xattr_ibody_header) + 1148 sizeof(__u32)) 1149 ref->inode_size_rem = 0; 1150 else { 1151 ref->inode_size_rem = 1152 ext4_xattr_inode_space(ref) - 1153 sizeof(struct ext4_xattr_ibody_header); 1154 } 1155 1156 ref->block_size_rem = 1157 ext4_xattr_block_space(ref) - 1158 sizeof(struct ext4_xattr_header) - 1159 sizeof(__u32); 1160 1161 rc = ext4_xattr_fetch(ref); 1162 if (rc != 0) { 1163 ext4_xattr_purge_items(ref); 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 1176 int ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref) 1177 { 1178 int ret; 1179 sector_t orig_file_acl = ref->inode_ref->Inode.i_file_acl; 1180 ret = ext4_xattr_write_to_disk(ref); 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 } 1210 ext4_xattr_purge_items(ref); 1211 Ext2DestroyInode(ref->fs, ref->OnDiskInode); 1212 ref->OnDiskInode = NULL; 1213 ref->inode_ref = NULL; 1214 ref->fs = NULL; 1215 return ret; 1216 } 1217 1218 struct xattr_prefix { 1219 const char *prefix; 1220 __u8 name_index; 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 1277 const char *ext4_get_xattr_name_prefix(__u8 name_index, 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 } 1296