.. | .. |
---|
10 | 10 | #include "xfs_format.h" |
---|
11 | 11 | #include "xfs_log_format.h" |
---|
12 | 12 | #include "xfs_trans_resv.h" |
---|
13 | | -#include "xfs_bit.h" |
---|
14 | 13 | #include "xfs_sb.h" |
---|
15 | 14 | #include "xfs_mount.h" |
---|
16 | 15 | #include "xfs_da_format.h" |
---|
17 | 16 | #include "xfs_da_btree.h" |
---|
18 | 17 | #include "xfs_inode.h" |
---|
19 | 18 | #include "xfs_trans.h" |
---|
20 | | -#include "xfs_inode_item.h" |
---|
21 | 19 | #include "xfs_bmap_btree.h" |
---|
22 | 20 | #include "xfs_bmap.h" |
---|
23 | 21 | #include "xfs_attr_sf.h" |
---|
.. | .. |
---|
27 | 25 | #include "xfs_error.h" |
---|
28 | 26 | #include "xfs_trace.h" |
---|
29 | 27 | #include "xfs_buf_item.h" |
---|
30 | | -#include "xfs_cksum.h" |
---|
31 | 28 | #include "xfs_dir2.h" |
---|
32 | 29 | #include "xfs_log.h" |
---|
33 | 30 | |
---|
.. | .. |
---|
236 | 233 | } |
---|
237 | 234 | |
---|
238 | 235 | static xfs_failaddr_t |
---|
| 236 | +xfs_attr3_leaf_verify_entry( |
---|
| 237 | + struct xfs_mount *mp, |
---|
| 238 | + char *buf_end, |
---|
| 239 | + struct xfs_attr_leafblock *leaf, |
---|
| 240 | + struct xfs_attr3_icleaf_hdr *leafhdr, |
---|
| 241 | + struct xfs_attr_leaf_entry *ent, |
---|
| 242 | + int idx, |
---|
| 243 | + __u32 *last_hashval) |
---|
| 244 | +{ |
---|
| 245 | + struct xfs_attr_leaf_name_local *lentry; |
---|
| 246 | + struct xfs_attr_leaf_name_remote *rentry; |
---|
| 247 | + char *name_end; |
---|
| 248 | + unsigned int nameidx; |
---|
| 249 | + unsigned int namesize; |
---|
| 250 | + __u32 hashval; |
---|
| 251 | + |
---|
| 252 | + /* hash order check */ |
---|
| 253 | + hashval = be32_to_cpu(ent->hashval); |
---|
| 254 | + if (hashval < *last_hashval) |
---|
| 255 | + return __this_address; |
---|
| 256 | + *last_hashval = hashval; |
---|
| 257 | + |
---|
| 258 | + nameidx = be16_to_cpu(ent->nameidx); |
---|
| 259 | + if (nameidx < leafhdr->firstused || nameidx >= mp->m_attr_geo->blksize) |
---|
| 260 | + return __this_address; |
---|
| 261 | + |
---|
| 262 | + /* |
---|
| 263 | + * Check the name information. The namelen fields are u8 so we can't |
---|
| 264 | + * possibly exceed the maximum name length of 255 bytes. |
---|
| 265 | + */ |
---|
| 266 | + if (ent->flags & XFS_ATTR_LOCAL) { |
---|
| 267 | + lentry = xfs_attr3_leaf_name_local(leaf, idx); |
---|
| 268 | + namesize = xfs_attr_leaf_entsize_local(lentry->namelen, |
---|
| 269 | + be16_to_cpu(lentry->valuelen)); |
---|
| 270 | + name_end = (char *)lentry + namesize; |
---|
| 271 | + if (lentry->namelen == 0) |
---|
| 272 | + return __this_address; |
---|
| 273 | + } else { |
---|
| 274 | + rentry = xfs_attr3_leaf_name_remote(leaf, idx); |
---|
| 275 | + namesize = xfs_attr_leaf_entsize_remote(rentry->namelen); |
---|
| 276 | + name_end = (char *)rentry + namesize; |
---|
| 277 | + if (rentry->namelen == 0) |
---|
| 278 | + return __this_address; |
---|
| 279 | + if (!(ent->flags & XFS_ATTR_INCOMPLETE) && |
---|
| 280 | + rentry->valueblk == 0) |
---|
| 281 | + return __this_address; |
---|
| 282 | + } |
---|
| 283 | + |
---|
| 284 | + if (name_end > buf_end) |
---|
| 285 | + return __this_address; |
---|
| 286 | + |
---|
| 287 | + return NULL; |
---|
| 288 | +} |
---|
| 289 | + |
---|
| 290 | +static xfs_failaddr_t |
---|
239 | 291 | xfs_attr3_leaf_verify( |
---|
240 | 292 | struct xfs_buf *bp) |
---|
241 | 293 | { |
---|
242 | 294 | struct xfs_attr3_icleaf_hdr ichdr; |
---|
243 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 295 | + struct xfs_mount *mp = bp->b_mount; |
---|
244 | 296 | struct xfs_attr_leafblock *leaf = bp->b_addr; |
---|
245 | 297 | struct xfs_attr_leaf_entry *entries; |
---|
| 298 | + struct xfs_attr_leaf_entry *ent; |
---|
| 299 | + char *buf_end; |
---|
246 | 300 | uint32_t end; /* must be 32bit - see below */ |
---|
| 301 | + __u32 last_hashval = 0; |
---|
247 | 302 | int i; |
---|
| 303 | + xfs_failaddr_t fa; |
---|
248 | 304 | |
---|
249 | 305 | xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf); |
---|
250 | 306 | |
---|
251 | | - if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
252 | | - struct xfs_da3_node_hdr *hdr3 = bp->b_addr; |
---|
253 | | - |
---|
254 | | - if (ichdr.magic != XFS_ATTR3_LEAF_MAGIC) |
---|
255 | | - return __this_address; |
---|
256 | | - |
---|
257 | | - if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid)) |
---|
258 | | - return __this_address; |
---|
259 | | - if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) |
---|
260 | | - return __this_address; |
---|
261 | | - if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->info.lsn))) |
---|
262 | | - return __this_address; |
---|
263 | | - } else { |
---|
264 | | - if (ichdr.magic != XFS_ATTR_LEAF_MAGIC) |
---|
265 | | - return __this_address; |
---|
266 | | - } |
---|
267 | | - /* |
---|
268 | | - * In recovery there is a transient state where count == 0 is valid |
---|
269 | | - * because we may have transitioned an empty shortform attr to a leaf |
---|
270 | | - * if the attr didn't fit in shortform. |
---|
271 | | - */ |
---|
272 | | - if (!xfs_log_in_recovery(mp) && ichdr.count == 0) |
---|
273 | | - return __this_address; |
---|
| 307 | + fa = xfs_da3_blkinfo_verify(bp, bp->b_addr); |
---|
| 308 | + if (fa) |
---|
| 309 | + return fa; |
---|
274 | 310 | |
---|
275 | 311 | /* |
---|
276 | 312 | * firstused is the block offset of the first name info structure. |
---|
.. | .. |
---|
287 | 323 | (char *)bp->b_addr + ichdr.firstused) |
---|
288 | 324 | return __this_address; |
---|
289 | 325 | |
---|
290 | | - /* XXX: need to range check rest of attr header values */ |
---|
291 | | - /* XXX: hash order check? */ |
---|
| 326 | + /* |
---|
| 327 | + * NOTE: This verifier historically failed empty leaf buffers because |
---|
| 328 | + * we expect the fork to be in another format. Empty attr fork format |
---|
| 329 | + * conversions are possible during xattr set, however, and format |
---|
| 330 | + * conversion is not atomic with the xattr set that triggers it. We |
---|
| 331 | + * cannot assume leaf blocks are non-empty until that is addressed. |
---|
| 332 | + */ |
---|
| 333 | + buf_end = (char *)bp->b_addr + mp->m_attr_geo->blksize; |
---|
| 334 | + for (i = 0, ent = entries; i < ichdr.count; ent++, i++) { |
---|
| 335 | + fa = xfs_attr3_leaf_verify_entry(mp, buf_end, leaf, &ichdr, |
---|
| 336 | + ent, i, &last_hashval); |
---|
| 337 | + if (fa) |
---|
| 338 | + return fa; |
---|
| 339 | + } |
---|
292 | 340 | |
---|
293 | 341 | /* |
---|
294 | 342 | * Quickly check the freemap information. Attribute data has to be |
---|
.. | .. |
---|
324 | 372 | xfs_attr3_leaf_write_verify( |
---|
325 | 373 | struct xfs_buf *bp) |
---|
326 | 374 | { |
---|
327 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 375 | + struct xfs_mount *mp = bp->b_mount; |
---|
328 | 376 | struct xfs_buf_log_item *bip = bp->b_log_item; |
---|
329 | 377 | struct xfs_attr3_leaf_hdr *hdr3 = bp->b_addr; |
---|
330 | 378 | xfs_failaddr_t fa; |
---|
.. | .. |
---|
354 | 402 | xfs_attr3_leaf_read_verify( |
---|
355 | 403 | struct xfs_buf *bp) |
---|
356 | 404 | { |
---|
357 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 405 | + struct xfs_mount *mp = bp->b_mount; |
---|
358 | 406 | xfs_failaddr_t fa; |
---|
359 | 407 | |
---|
360 | 408 | if (xfs_sb_version_hascrc(&mp->m_sb) && |
---|
.. | .. |
---|
369 | 417 | |
---|
370 | 418 | const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = { |
---|
371 | 419 | .name = "xfs_attr3_leaf", |
---|
| 420 | + .magic16 = { cpu_to_be16(XFS_ATTR_LEAF_MAGIC), |
---|
| 421 | + cpu_to_be16(XFS_ATTR3_LEAF_MAGIC) }, |
---|
372 | 422 | .verify_read = xfs_attr3_leaf_read_verify, |
---|
373 | 423 | .verify_write = xfs_attr3_leaf_write_verify, |
---|
374 | 424 | .verify_struct = xfs_attr3_leaf_verify, |
---|
.. | .. |
---|
379 | 429 | struct xfs_trans *tp, |
---|
380 | 430 | struct xfs_inode *dp, |
---|
381 | 431 | xfs_dablk_t bno, |
---|
382 | | - xfs_daddr_t mappedbno, |
---|
383 | 432 | struct xfs_buf **bpp) |
---|
384 | 433 | { |
---|
385 | 434 | int err; |
---|
386 | 435 | |
---|
387 | | - err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, |
---|
388 | | - XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops); |
---|
| 436 | + err = xfs_da_read_buf(tp, dp, bno, 0, bpp, XFS_ATTR_FORK, |
---|
| 437 | + &xfs_attr3_leaf_buf_ops); |
---|
389 | 438 | if (!err && tp && *bpp) |
---|
390 | 439 | xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_ATTR_LEAF_BUF); |
---|
391 | 440 | return err; |
---|
.. | .. |
---|
395 | 444 | * Namespace helper routines |
---|
396 | 445 | *========================================================================*/ |
---|
397 | 446 | |
---|
398 | | -/* |
---|
399 | | - * If namespace bits don't match return 0. |
---|
400 | | - * If all match then return 1. |
---|
401 | | - */ |
---|
402 | | -STATIC int |
---|
403 | | -xfs_attr_namesp_match(int arg_flags, int ondisk_flags) |
---|
| 447 | +static bool |
---|
| 448 | +xfs_attr_match( |
---|
| 449 | + struct xfs_da_args *args, |
---|
| 450 | + uint8_t namelen, |
---|
| 451 | + unsigned char *name, |
---|
| 452 | + int flags) |
---|
404 | 453 | { |
---|
405 | | - return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags); |
---|
| 454 | + if (args->namelen != namelen) |
---|
| 455 | + return false; |
---|
| 456 | + if (memcmp(args->name, name, namelen) != 0) |
---|
| 457 | + return false; |
---|
| 458 | + /* |
---|
| 459 | + * If we are looking for incomplete entries, show only those, else only |
---|
| 460 | + * show complete entries. |
---|
| 461 | + */ |
---|
| 462 | + if (args->attr_filter != |
---|
| 463 | + (flags & (XFS_ATTR_NSP_ONDISK_MASK | XFS_ATTR_INCOMPLETE))) |
---|
| 464 | + return false; |
---|
| 465 | + return true; |
---|
406 | 466 | } |
---|
407 | 467 | |
---|
| 468 | +static int |
---|
| 469 | +xfs_attr_copy_value( |
---|
| 470 | + struct xfs_da_args *args, |
---|
| 471 | + unsigned char *value, |
---|
| 472 | + int valuelen) |
---|
| 473 | +{ |
---|
| 474 | + /* |
---|
| 475 | + * No copy if all we have to do is get the length |
---|
| 476 | + */ |
---|
| 477 | + if (!args->valuelen) { |
---|
| 478 | + args->valuelen = valuelen; |
---|
| 479 | + return 0; |
---|
| 480 | + } |
---|
| 481 | + |
---|
| 482 | + /* |
---|
| 483 | + * No copy if the length of the existing buffer is too small |
---|
| 484 | + */ |
---|
| 485 | + if (args->valuelen < valuelen) { |
---|
| 486 | + args->valuelen = valuelen; |
---|
| 487 | + return -ERANGE; |
---|
| 488 | + } |
---|
| 489 | + |
---|
| 490 | + if (!args->value) { |
---|
| 491 | + args->value = kmem_alloc_large(valuelen, KM_NOLOCKDEP); |
---|
| 492 | + if (!args->value) |
---|
| 493 | + return -ENOMEM; |
---|
| 494 | + } |
---|
| 495 | + args->valuelen = valuelen; |
---|
| 496 | + |
---|
| 497 | + /* remote block xattr requires IO for copy-in */ |
---|
| 498 | + if (args->rmtblkno) |
---|
| 499 | + return xfs_attr_rmtval_get(args); |
---|
| 500 | + |
---|
| 501 | + /* |
---|
| 502 | + * This is to prevent a GCC warning because the remote xattr case |
---|
| 503 | + * doesn't have a value to pass in. In that case, we never reach here, |
---|
| 504 | + * but GCC can't work that out and so throws a "passing NULL to |
---|
| 505 | + * memcpy" warning. |
---|
| 506 | + */ |
---|
| 507 | + if (!value) |
---|
| 508 | + return -EINVAL; |
---|
| 509 | + memcpy(args->value, value, valuelen); |
---|
| 510 | + return 0; |
---|
| 511 | +} |
---|
408 | 512 | |
---|
409 | 513 | /*======================================================================== |
---|
410 | 514 | * External routines when attribute fork size < XFS_LITINO(mp). |
---|
411 | 515 | *========================================================================*/ |
---|
412 | 516 | |
---|
413 | 517 | /* |
---|
414 | | - * Query whether the requested number of additional bytes of extended |
---|
| 518 | + * Query whether the total requested number of attr fork bytes of extended |
---|
415 | 519 | * attribute space will be able to fit inline. |
---|
416 | 520 | * |
---|
417 | 521 | * Returns zero if not, else the di_forkoff fork offset to be used in the |
---|
.. | .. |
---|
421 | 525 | * special case for dev/uuid inodes, they have fixed size data forks. |
---|
422 | 526 | */ |
---|
423 | 527 | int |
---|
424 | | -xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) |
---|
| 528 | +xfs_attr_shortform_bytesfit( |
---|
| 529 | + struct xfs_inode *dp, |
---|
| 530 | + int bytes) |
---|
425 | 531 | { |
---|
426 | | - int offset; |
---|
427 | | - int minforkoff; /* lower limit on valid forkoff locations */ |
---|
428 | | - int maxforkoff; /* upper limit on valid forkoff locations */ |
---|
429 | | - int dsize; |
---|
430 | | - xfs_mount_t *mp = dp->i_mount; |
---|
| 532 | + struct xfs_mount *mp = dp->i_mount; |
---|
| 533 | + int64_t dsize; |
---|
| 534 | + int minforkoff; |
---|
| 535 | + int maxforkoff; |
---|
| 536 | + int offset; |
---|
| 537 | + |
---|
| 538 | + /* |
---|
| 539 | + * Check if the new size could fit at all first: |
---|
| 540 | + */ |
---|
| 541 | + if (bytes > XFS_LITINO(mp)) |
---|
| 542 | + return 0; |
---|
431 | 543 | |
---|
432 | 544 | /* rounded down */ |
---|
433 | | - offset = (XFS_LITINO(mp, dp->i_d.di_version) - bytes) >> 3; |
---|
| 545 | + offset = (XFS_LITINO(mp) - bytes) >> 3; |
---|
434 | 546 | |
---|
435 | | - if (dp->i_d.di_format == XFS_DINODE_FMT_DEV) { |
---|
| 547 | + if (dp->i_df.if_format == XFS_DINODE_FMT_DEV) { |
---|
436 | 548 | minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3; |
---|
437 | 549 | return (offset >= minforkoff) ? minforkoff : 0; |
---|
438 | 550 | } |
---|
.. | .. |
---|
460 | 572 | |
---|
461 | 573 | dsize = dp->i_df.if_bytes; |
---|
462 | 574 | |
---|
463 | | - switch (dp->i_d.di_format) { |
---|
| 575 | + switch (dp->i_df.if_format) { |
---|
464 | 576 | case XFS_DINODE_FMT_EXTENTS: |
---|
465 | 577 | /* |
---|
466 | 578 | * If there is no attr fork and the data fork is extents, |
---|
.. | .. |
---|
493 | 605 | * A data fork btree root must have space for at least |
---|
494 | 606 | * MINDBTPTRS key/ptr pairs if the data fork is small or empty. |
---|
495 | 607 | */ |
---|
496 | | - minforkoff = max(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); |
---|
| 608 | + minforkoff = max_t(int64_t, dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); |
---|
497 | 609 | minforkoff = roundup(minforkoff, 8) >> 3; |
---|
498 | 610 | |
---|
499 | 611 | /* attr fork btree root can have at least this many key/ptr pairs */ |
---|
500 | | - maxforkoff = XFS_LITINO(mp, dp->i_d.di_version) - |
---|
501 | | - XFS_BMDR_SPACE_CALC(MINABTPTRS); |
---|
| 612 | + maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); |
---|
502 | 613 | maxforkoff = maxforkoff >> 3; /* rounded down */ |
---|
503 | 614 | |
---|
504 | 615 | if (offset >= maxforkoff) |
---|
.. | .. |
---|
530 | 641 | * Create the initial contents of a shortform attribute list. |
---|
531 | 642 | */ |
---|
532 | 643 | void |
---|
533 | | -xfs_attr_shortform_create(xfs_da_args_t *args) |
---|
| 644 | +xfs_attr_shortform_create( |
---|
| 645 | + struct xfs_da_args *args) |
---|
534 | 646 | { |
---|
535 | | - xfs_attr_sf_hdr_t *hdr; |
---|
536 | | - xfs_inode_t *dp; |
---|
537 | | - struct xfs_ifork *ifp; |
---|
| 647 | + struct xfs_inode *dp = args->dp; |
---|
| 648 | + struct xfs_ifork *ifp = dp->i_afp; |
---|
| 649 | + struct xfs_attr_sf_hdr *hdr; |
---|
538 | 650 | |
---|
539 | 651 | trace_xfs_attr_sf_create(args); |
---|
540 | 652 | |
---|
541 | | - dp = args->dp; |
---|
542 | | - ASSERT(dp != NULL); |
---|
543 | | - ifp = dp->i_afp; |
---|
544 | | - ASSERT(ifp != NULL); |
---|
545 | 653 | ASSERT(ifp->if_bytes == 0); |
---|
546 | | - if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) { |
---|
| 654 | + if (ifp->if_format == XFS_DINODE_FMT_EXTENTS) { |
---|
547 | 655 | ifp->if_flags &= ~XFS_IFEXTENTS; /* just in case */ |
---|
548 | | - dp->i_d.di_aformat = XFS_DINODE_FMT_LOCAL; |
---|
| 656 | + ifp->if_format = XFS_DINODE_FMT_LOCAL; |
---|
549 | 657 | ifp->if_flags |= XFS_IFINLINE; |
---|
550 | 658 | } else { |
---|
551 | 659 | ASSERT(ifp->if_flags & XFS_IFINLINE); |
---|
.. | .. |
---|
558 | 666 | } |
---|
559 | 667 | |
---|
560 | 668 | /* |
---|
| 669 | + * Return -EEXIST if attr is found, or -ENOATTR if not |
---|
| 670 | + * args: args containing attribute name and namelen |
---|
| 671 | + * sfep: If not null, pointer will be set to the last attr entry found on |
---|
| 672 | + -EEXIST. On -ENOATTR pointer is left at the last entry in the list |
---|
| 673 | + * basep: If not null, pointer is set to the byte offset of the entry in the |
---|
| 674 | + * list on -EEXIST. On -ENOATTR, pointer is left at the byte offset of |
---|
| 675 | + * the last entry in the list |
---|
| 676 | + */ |
---|
| 677 | +int |
---|
| 678 | +xfs_attr_sf_findname( |
---|
| 679 | + struct xfs_da_args *args, |
---|
| 680 | + struct xfs_attr_sf_entry **sfep, |
---|
| 681 | + unsigned int *basep) |
---|
| 682 | +{ |
---|
| 683 | + struct xfs_attr_shortform *sf; |
---|
| 684 | + struct xfs_attr_sf_entry *sfe; |
---|
| 685 | + unsigned int base = sizeof(struct xfs_attr_sf_hdr); |
---|
| 686 | + int size = 0; |
---|
| 687 | + int end; |
---|
| 688 | + int i; |
---|
| 689 | + |
---|
| 690 | + sf = (struct xfs_attr_shortform *)args->dp->i_afp->if_u1.if_data; |
---|
| 691 | + sfe = &sf->list[0]; |
---|
| 692 | + end = sf->hdr.count; |
---|
| 693 | + for (i = 0; i < end; sfe = xfs_attr_sf_nextentry(sfe), |
---|
| 694 | + base += size, i++) { |
---|
| 695 | + size = xfs_attr_sf_entsize(sfe); |
---|
| 696 | + if (!xfs_attr_match(args, sfe->namelen, sfe->nameval, |
---|
| 697 | + sfe->flags)) |
---|
| 698 | + continue; |
---|
| 699 | + break; |
---|
| 700 | + } |
---|
| 701 | + |
---|
| 702 | + if (sfep != NULL) |
---|
| 703 | + *sfep = sfe; |
---|
| 704 | + |
---|
| 705 | + if (basep != NULL) |
---|
| 706 | + *basep = base; |
---|
| 707 | + |
---|
| 708 | + if (i == end) |
---|
| 709 | + return -ENOATTR; |
---|
| 710 | + return -EEXIST; |
---|
| 711 | +} |
---|
| 712 | + |
---|
| 713 | +/* |
---|
561 | 714 | * Add a name/value pair to the shortform attribute list. |
---|
562 | 715 | * Overflow from the inode has already been checked for. |
---|
563 | 716 | */ |
---|
564 | 717 | void |
---|
565 | | -xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) |
---|
| 718 | +xfs_attr_shortform_add( |
---|
| 719 | + struct xfs_da_args *args, |
---|
| 720 | + int forkoff) |
---|
566 | 721 | { |
---|
567 | | - xfs_attr_shortform_t *sf; |
---|
568 | | - xfs_attr_sf_entry_t *sfe; |
---|
569 | | - int i, offset, size; |
---|
570 | | - xfs_mount_t *mp; |
---|
571 | | - xfs_inode_t *dp; |
---|
572 | | - struct xfs_ifork *ifp; |
---|
| 722 | + struct xfs_attr_shortform *sf; |
---|
| 723 | + struct xfs_attr_sf_entry *sfe; |
---|
| 724 | + int offset, size; |
---|
| 725 | + struct xfs_mount *mp; |
---|
| 726 | + struct xfs_inode *dp; |
---|
| 727 | + struct xfs_ifork *ifp; |
---|
573 | 728 | |
---|
574 | 729 | trace_xfs_attr_sf_add(args); |
---|
575 | 730 | |
---|
.. | .. |
---|
579 | 734 | |
---|
580 | 735 | ifp = dp->i_afp; |
---|
581 | 736 | ASSERT(ifp->if_flags & XFS_IFINLINE); |
---|
582 | | - sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; |
---|
583 | | - sfe = &sf->list[0]; |
---|
584 | | - for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { |
---|
585 | | -#ifdef DEBUG |
---|
586 | | - if (sfe->namelen != args->namelen) |
---|
587 | | - continue; |
---|
588 | | - if (memcmp(args->name, sfe->nameval, args->namelen) != 0) |
---|
589 | | - continue; |
---|
590 | | - if (!xfs_attr_namesp_match(args->flags, sfe->flags)) |
---|
591 | | - continue; |
---|
| 737 | + sf = (struct xfs_attr_shortform *)ifp->if_u1.if_data; |
---|
| 738 | + if (xfs_attr_sf_findname(args, &sfe, NULL) == -EEXIST) |
---|
592 | 739 | ASSERT(0); |
---|
593 | | -#endif |
---|
594 | | - } |
---|
595 | 740 | |
---|
596 | 741 | offset = (char *)sfe - (char *)sf; |
---|
597 | | - size = XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); |
---|
| 742 | + size = xfs_attr_sf_entsize_byname(args->namelen, args->valuelen); |
---|
598 | 743 | xfs_idata_realloc(dp, size, XFS_ATTR_FORK); |
---|
599 | | - sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; |
---|
600 | | - sfe = (xfs_attr_sf_entry_t *)((char *)sf + offset); |
---|
| 744 | + sf = (struct xfs_attr_shortform *)ifp->if_u1.if_data; |
---|
| 745 | + sfe = (struct xfs_attr_sf_entry *)((char *)sf + offset); |
---|
601 | 746 | |
---|
602 | 747 | sfe->namelen = args->namelen; |
---|
603 | 748 | sfe->valuelen = args->valuelen; |
---|
604 | | - sfe->flags = XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); |
---|
| 749 | + sfe->flags = args->attr_filter; |
---|
605 | 750 | memcpy(sfe->nameval, args->name, args->namelen); |
---|
606 | 751 | memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); |
---|
607 | 752 | sf->hdr.count++; |
---|
.. | .. |
---|
620 | 765 | struct xfs_inode *ip, |
---|
621 | 766 | struct xfs_trans *tp) |
---|
622 | 767 | { |
---|
623 | | - xfs_idestroy_fork(ip, XFS_ATTR_FORK); |
---|
| 768 | + ASSERT(ip->i_afp->if_nextents == 0); |
---|
| 769 | + |
---|
| 770 | + xfs_idestroy_fork(ip->i_afp); |
---|
| 771 | + kmem_cache_free(xfs_ifork_zone, ip->i_afp); |
---|
| 772 | + ip->i_afp = NULL; |
---|
624 | 773 | ip->i_d.di_forkoff = 0; |
---|
625 | | - ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; |
---|
626 | | - |
---|
627 | | - ASSERT(ip->i_d.di_anextents == 0); |
---|
628 | | - ASSERT(ip->i_afp == NULL); |
---|
629 | | - |
---|
630 | 774 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
---|
631 | 775 | } |
---|
632 | 776 | |
---|
.. | .. |
---|
634 | 778 | * Remove an attribute from the shortform attribute list structure. |
---|
635 | 779 | */ |
---|
636 | 780 | int |
---|
637 | | -xfs_attr_shortform_remove(xfs_da_args_t *args) |
---|
| 781 | +xfs_attr_shortform_remove( |
---|
| 782 | + struct xfs_da_args *args) |
---|
638 | 783 | { |
---|
639 | | - xfs_attr_shortform_t *sf; |
---|
640 | | - xfs_attr_sf_entry_t *sfe; |
---|
641 | | - int base, size=0, end, totsize, i; |
---|
642 | | - xfs_mount_t *mp; |
---|
643 | | - xfs_inode_t *dp; |
---|
| 784 | + struct xfs_attr_shortform *sf; |
---|
| 785 | + struct xfs_attr_sf_entry *sfe; |
---|
| 786 | + int size = 0, end, totsize; |
---|
| 787 | + unsigned int base; |
---|
| 788 | + struct xfs_mount *mp; |
---|
| 789 | + struct xfs_inode *dp; |
---|
| 790 | + int error; |
---|
644 | 791 | |
---|
645 | 792 | trace_xfs_attr_sf_remove(args); |
---|
646 | 793 | |
---|
647 | 794 | dp = args->dp; |
---|
648 | 795 | mp = dp->i_mount; |
---|
649 | | - base = sizeof(xfs_attr_sf_hdr_t); |
---|
650 | | - sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; |
---|
651 | | - sfe = &sf->list[0]; |
---|
652 | | - end = sf->hdr.count; |
---|
653 | | - for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), |
---|
654 | | - base += size, i++) { |
---|
655 | | - size = XFS_ATTR_SF_ENTSIZE(sfe); |
---|
656 | | - if (sfe->namelen != args->namelen) |
---|
657 | | - continue; |
---|
658 | | - if (memcmp(sfe->nameval, args->name, args->namelen) != 0) |
---|
659 | | - continue; |
---|
660 | | - if (!xfs_attr_namesp_match(args->flags, sfe->flags)) |
---|
661 | | - continue; |
---|
662 | | - break; |
---|
663 | | - } |
---|
664 | | - if (i == end) |
---|
665 | | - return -ENOATTR; |
---|
| 796 | + sf = (struct xfs_attr_shortform *)dp->i_afp->if_u1.if_data; |
---|
| 797 | + |
---|
| 798 | + error = xfs_attr_sf_findname(args, &sfe, &base); |
---|
| 799 | + if (error != -EEXIST) |
---|
| 800 | + return error; |
---|
| 801 | + size = xfs_attr_sf_entsize(sfe); |
---|
666 | 802 | |
---|
667 | 803 | /* |
---|
668 | 804 | * Fix up the attribute fork data, covering the hole |
---|
.. | .. |
---|
680 | 816 | totsize -= size; |
---|
681 | 817 | if (totsize == sizeof(xfs_attr_sf_hdr_t) && |
---|
682 | 818 | (mp->m_flags & XFS_MOUNT_ATTR2) && |
---|
683 | | - (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && |
---|
| 819 | + (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) && |
---|
684 | 820 | !(args->op_flags & XFS_DA_OP_ADDNAME)) { |
---|
685 | 821 | xfs_attr_fork_remove(dp, args->trans); |
---|
686 | 822 | } else { |
---|
.. | .. |
---|
690 | 826 | ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || |
---|
691 | 827 | (args->op_flags & XFS_DA_OP_ADDNAME) || |
---|
692 | 828 | !(mp->m_flags & XFS_MOUNT_ATTR2) || |
---|
693 | | - dp->i_d.di_format == XFS_DINODE_FMT_BTREE); |
---|
| 829 | + dp->i_df.if_format == XFS_DINODE_FMT_BTREE); |
---|
694 | 830 | xfs_trans_log_inode(args->trans, dp, |
---|
695 | 831 | XFS_ILOG_CORE | XFS_ILOG_ADATA); |
---|
696 | 832 | } |
---|
.. | .. |
---|
707 | 843 | int |
---|
708 | 844 | xfs_attr_shortform_lookup(xfs_da_args_t *args) |
---|
709 | 845 | { |
---|
710 | | - xfs_attr_shortform_t *sf; |
---|
711 | | - xfs_attr_sf_entry_t *sfe; |
---|
| 846 | + struct xfs_attr_shortform *sf; |
---|
| 847 | + struct xfs_attr_sf_entry *sfe; |
---|
712 | 848 | int i; |
---|
713 | 849 | struct xfs_ifork *ifp; |
---|
714 | 850 | |
---|
.. | .. |
---|
716 | 852 | |
---|
717 | 853 | ifp = args->dp->i_afp; |
---|
718 | 854 | ASSERT(ifp->if_flags & XFS_IFINLINE); |
---|
719 | | - sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; |
---|
| 855 | + sf = (struct xfs_attr_shortform *)ifp->if_u1.if_data; |
---|
720 | 856 | sfe = &sf->list[0]; |
---|
721 | 857 | for (i = 0; i < sf->hdr.count; |
---|
722 | | - sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { |
---|
723 | | - if (sfe->namelen != args->namelen) |
---|
724 | | - continue; |
---|
725 | | - if (memcmp(args->name, sfe->nameval, args->namelen) != 0) |
---|
726 | | - continue; |
---|
727 | | - if (!xfs_attr_namesp_match(args->flags, sfe->flags)) |
---|
728 | | - continue; |
---|
729 | | - return -EEXIST; |
---|
| 858 | + sfe = xfs_attr_sf_nextentry(sfe), i++) { |
---|
| 859 | + if (xfs_attr_match(args, sfe->namelen, sfe->nameval, |
---|
| 860 | + sfe->flags)) |
---|
| 861 | + return -EEXIST; |
---|
730 | 862 | } |
---|
731 | 863 | return -ENOATTR; |
---|
732 | 864 | } |
---|
733 | 865 | |
---|
734 | 866 | /* |
---|
735 | | - * Look up a name in a shortform attribute list structure. |
---|
| 867 | + * Retrieve the attribute value and length. |
---|
| 868 | + * |
---|
| 869 | + * If args->valuelen is zero, only the length needs to be returned. Unlike a |
---|
| 870 | + * lookup, we only return an error if the attribute does not exist or we can't |
---|
| 871 | + * retrieve the value. |
---|
736 | 872 | */ |
---|
737 | | -/*ARGSUSED*/ |
---|
738 | 873 | int |
---|
739 | | -xfs_attr_shortform_getvalue(xfs_da_args_t *args) |
---|
| 874 | +xfs_attr_shortform_getvalue( |
---|
| 875 | + struct xfs_da_args *args) |
---|
740 | 876 | { |
---|
741 | | - xfs_attr_shortform_t *sf; |
---|
742 | | - xfs_attr_sf_entry_t *sfe; |
---|
743 | | - int i; |
---|
| 877 | + struct xfs_attr_shortform *sf; |
---|
| 878 | + struct xfs_attr_sf_entry *sfe; |
---|
| 879 | + int i; |
---|
744 | 880 | |
---|
745 | 881 | ASSERT(args->dp->i_afp->if_flags == XFS_IFINLINE); |
---|
746 | | - sf = (xfs_attr_shortform_t *)args->dp->i_afp->if_u1.if_data; |
---|
| 882 | + sf = (struct xfs_attr_shortform *)args->dp->i_afp->if_u1.if_data; |
---|
747 | 883 | sfe = &sf->list[0]; |
---|
748 | 884 | for (i = 0; i < sf->hdr.count; |
---|
749 | | - sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { |
---|
750 | | - if (sfe->namelen != args->namelen) |
---|
751 | | - continue; |
---|
752 | | - if (memcmp(args->name, sfe->nameval, args->namelen) != 0) |
---|
753 | | - continue; |
---|
754 | | - if (!xfs_attr_namesp_match(args->flags, sfe->flags)) |
---|
755 | | - continue; |
---|
756 | | - if (args->flags & ATTR_KERNOVAL) { |
---|
757 | | - args->valuelen = sfe->valuelen; |
---|
758 | | - return -EEXIST; |
---|
759 | | - } |
---|
760 | | - if (args->valuelen < sfe->valuelen) { |
---|
761 | | - args->valuelen = sfe->valuelen; |
---|
762 | | - return -ERANGE; |
---|
763 | | - } |
---|
764 | | - args->valuelen = sfe->valuelen; |
---|
765 | | - memcpy(args->value, &sfe->nameval[args->namelen], |
---|
766 | | - args->valuelen); |
---|
767 | | - return -EEXIST; |
---|
| 885 | + sfe = xfs_attr_sf_nextentry(sfe), i++) { |
---|
| 886 | + if (xfs_attr_match(args, sfe->namelen, sfe->nameval, |
---|
| 887 | + sfe->flags)) |
---|
| 888 | + return xfs_attr_copy_value(args, |
---|
| 889 | + &sfe->nameval[args->namelen], sfe->valuelen); |
---|
768 | 890 | } |
---|
769 | 891 | return -ENOATTR; |
---|
770 | 892 | } |
---|
.. | .. |
---|
792 | 914 | |
---|
793 | 915 | dp = args->dp; |
---|
794 | 916 | ifp = dp->i_afp; |
---|
795 | | - sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; |
---|
| 917 | + sf = (struct xfs_attr_shortform *)ifp->if_u1.if_data; |
---|
796 | 918 | size = be16_to_cpu(sf->hdr.totsize); |
---|
797 | | - tmpbuffer = kmem_alloc(size, KM_SLEEP); |
---|
| 919 | + tmpbuffer = kmem_alloc(size, 0); |
---|
798 | 920 | ASSERT(tmpbuffer != NULL); |
---|
799 | 921 | memcpy(tmpbuffer, ifp->if_u1.if_data, size); |
---|
800 | | - sf = (xfs_attr_shortform_t *)tmpbuffer; |
---|
| 922 | + sf = (struct xfs_attr_shortform *)tmpbuffer; |
---|
801 | 923 | |
---|
802 | 924 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); |
---|
803 | | - xfs_bmap_local_to_extents_empty(dp, XFS_ATTR_FORK); |
---|
| 925 | + xfs_bmap_local_to_extents_empty(args->trans, dp, XFS_ATTR_FORK); |
---|
804 | 926 | |
---|
805 | 927 | bp = NULL; |
---|
806 | 928 | error = xfs_da_grow_inode(args, &blkno); |
---|
807 | | - if (error) { |
---|
808 | | - /* |
---|
809 | | - * If we hit an IO error middle of the transaction inside |
---|
810 | | - * grow_inode(), we may have inconsistent data. Bail out. |
---|
811 | | - */ |
---|
812 | | - if (error == -EIO) |
---|
813 | | - goto out; |
---|
814 | | - xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */ |
---|
815 | | - memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */ |
---|
| 929 | + if (error) |
---|
816 | 930 | goto out; |
---|
817 | | - } |
---|
818 | 931 | |
---|
819 | 932 | ASSERT(blkno == 0); |
---|
820 | 933 | error = xfs_attr3_leaf_create(args, blkno, &bp); |
---|
821 | | - if (error) { |
---|
822 | | - /* xfs_attr3_leaf_create may not have instantiated a block */ |
---|
823 | | - if (bp && (xfs_da_shrink_inode(args, 0, bp) != 0)) |
---|
824 | | - goto out; |
---|
825 | | - xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */ |
---|
826 | | - memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */ |
---|
| 934 | + if (error) |
---|
827 | 935 | goto out; |
---|
828 | | - } |
---|
829 | 936 | |
---|
830 | 937 | memset((char *)&nargs, 0, sizeof(nargs)); |
---|
831 | 938 | nargs.dp = dp; |
---|
.. | .. |
---|
843 | 950 | nargs.valuelen = sfe->valuelen; |
---|
844 | 951 | nargs.hashval = xfs_da_hashname(sfe->nameval, |
---|
845 | 952 | sfe->namelen); |
---|
846 | | - nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags); |
---|
| 953 | + nargs.attr_filter = sfe->flags & XFS_ATTR_NSP_ONDISK_MASK; |
---|
847 | 954 | error = xfs_attr3_leaf_lookup_int(bp, &nargs); /* set a->index */ |
---|
848 | 955 | ASSERT(error == -ENOATTR); |
---|
849 | 956 | error = xfs_attr3_leaf_add(bp, &nargs); |
---|
850 | 957 | ASSERT(error != -ENOSPC); |
---|
851 | 958 | if (error) |
---|
852 | 959 | goto out; |
---|
853 | | - sfe = XFS_ATTR_SF_NEXTENTRY(sfe); |
---|
| 960 | + sfe = xfs_attr_sf_nextentry(sfe); |
---|
854 | 961 | } |
---|
855 | 962 | error = 0; |
---|
856 | 963 | *leaf_bp = bp; |
---|
.. | .. |
---|
874 | 981 | struct xfs_attr3_icleaf_hdr leafhdr; |
---|
875 | 982 | int bytes; |
---|
876 | 983 | int i; |
---|
877 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 984 | + struct xfs_mount *mp = bp->b_mount; |
---|
878 | 985 | |
---|
879 | 986 | leaf = bp->b_addr; |
---|
880 | 987 | xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); |
---|
.. | .. |
---|
891 | 998 | return 0; |
---|
892 | 999 | if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX) |
---|
893 | 1000 | return 0; |
---|
894 | | - bytes += sizeof(struct xfs_attr_sf_entry) - 1 |
---|
895 | | - + name_loc->namelen |
---|
896 | | - + be16_to_cpu(name_loc->valuelen); |
---|
| 1001 | + bytes += xfs_attr_sf_entsize_byname(name_loc->namelen, |
---|
| 1002 | + be16_to_cpu(name_loc->valuelen)); |
---|
897 | 1003 | } |
---|
898 | 1004 | if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && |
---|
899 | | - (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && |
---|
| 1005 | + (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) && |
---|
900 | 1006 | (bytes == sizeof(struct xfs_attr_sf_hdr))) |
---|
901 | 1007 | return -1; |
---|
902 | 1008 | return xfs_attr_shortform_bytesfit(dp, bytes); |
---|
.. | .. |
---|
913 | 1019 | char *endp; |
---|
914 | 1020 | struct xfs_ifork *ifp; |
---|
915 | 1021 | int i; |
---|
916 | | - int size; |
---|
| 1022 | + int64_t size; |
---|
917 | 1023 | |
---|
918 | | - ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL); |
---|
| 1024 | + ASSERT(ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL); |
---|
919 | 1025 | ifp = XFS_IFORK_PTR(ip, XFS_ATTR_FORK); |
---|
920 | 1026 | sfp = (struct xfs_attr_shortform *)ifp->if_u1.if_data; |
---|
921 | 1027 | size = ifp->if_bytes; |
---|
.. | .. |
---|
938 | 1044 | * xfs_attr_sf_entry is defined with a 1-byte variable |
---|
939 | 1045 | * array at the end, so we must subtract that off. |
---|
940 | 1046 | */ |
---|
941 | | - if (((char *)sfep + sizeof(*sfep) - 1) >= endp) |
---|
| 1047 | + if (((char *)sfep + sizeof(*sfep)) >= endp) |
---|
942 | 1048 | return __this_address; |
---|
943 | 1049 | |
---|
944 | 1050 | /* Don't allow names with known bad length. */ |
---|
.. | .. |
---|
950 | 1056 | * within the data buffer. The next entry starts after the |
---|
951 | 1057 | * name component, so nextentry is an acceptable test. |
---|
952 | 1058 | */ |
---|
953 | | - next_sfep = XFS_ATTR_SF_NEXTENTRY(sfep); |
---|
| 1059 | + next_sfep = xfs_attr_sf_nextentry(sfep); |
---|
954 | 1060 | if ((char *)next_sfep > endp) |
---|
955 | 1061 | return __this_address; |
---|
956 | 1062 | |
---|
.. | .. |
---|
999 | 1105 | |
---|
1000 | 1106 | trace_xfs_attr_leaf_to_sf(args); |
---|
1001 | 1107 | |
---|
1002 | | - tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP); |
---|
| 1108 | + tmpbuffer = kmem_alloc(args->geo->blksize, 0); |
---|
1003 | 1109 | if (!tmpbuffer) |
---|
1004 | 1110 | return -ENOMEM; |
---|
1005 | 1111 | |
---|
.. | .. |
---|
1021 | 1127 | |
---|
1022 | 1128 | if (forkoff == -1) { |
---|
1023 | 1129 | ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); |
---|
1024 | | - ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); |
---|
| 1130 | + ASSERT(dp->i_df.if_format != XFS_DINODE_FMT_BTREE); |
---|
1025 | 1131 | xfs_attr_fork_remove(dp, args->trans); |
---|
1026 | 1132 | goto out; |
---|
1027 | 1133 | } |
---|
.. | .. |
---|
1051 | 1157 | nargs.value = &name_loc->nameval[nargs.namelen]; |
---|
1052 | 1158 | nargs.valuelen = be16_to_cpu(name_loc->valuelen); |
---|
1053 | 1159 | nargs.hashval = be32_to_cpu(entry->hashval); |
---|
1054 | | - nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags); |
---|
| 1160 | + nargs.attr_filter = entry->flags & XFS_ATTR_NSP_ONDISK_MASK; |
---|
1055 | 1161 | xfs_attr_shortform_add(&nargs, forkoff); |
---|
1056 | 1162 | } |
---|
1057 | 1163 | error = 0; |
---|
.. | .. |
---|
1071 | 1177 | struct xfs_attr_leafblock *leaf; |
---|
1072 | 1178 | struct xfs_attr3_icleaf_hdr icleafhdr; |
---|
1073 | 1179 | struct xfs_attr_leaf_entry *entries; |
---|
1074 | | - struct xfs_da_node_entry *btree; |
---|
1075 | 1180 | struct xfs_da3_icnode_hdr icnodehdr; |
---|
1076 | 1181 | struct xfs_da_intnode *node; |
---|
1077 | 1182 | struct xfs_inode *dp = args->dp; |
---|
.. | .. |
---|
1086 | 1191 | error = xfs_da_grow_inode(args, &blkno); |
---|
1087 | 1192 | if (error) |
---|
1088 | 1193 | goto out; |
---|
1089 | | - error = xfs_attr3_leaf_read(args->trans, dp, 0, -1, &bp1); |
---|
| 1194 | + error = xfs_attr3_leaf_read(args->trans, dp, 0, &bp1); |
---|
1090 | 1195 | if (error) |
---|
1091 | 1196 | goto out; |
---|
1092 | 1197 | |
---|
1093 | | - error = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp2, XFS_ATTR_FORK); |
---|
| 1198 | + error = xfs_da_get_buf(args->trans, dp, blkno, &bp2, XFS_ATTR_FORK); |
---|
1094 | 1199 | if (error) |
---|
1095 | 1200 | goto out; |
---|
1096 | 1201 | |
---|
.. | .. |
---|
1111 | 1216 | if (error) |
---|
1112 | 1217 | goto out; |
---|
1113 | 1218 | node = bp1->b_addr; |
---|
1114 | | - dp->d_ops->node_hdr_from_disk(&icnodehdr, node); |
---|
1115 | | - btree = dp->d_ops->node_tree_p(node); |
---|
| 1219 | + xfs_da3_node_hdr_from_disk(mp, &icnodehdr, node); |
---|
1116 | 1220 | |
---|
1117 | 1221 | leaf = bp2->b_addr; |
---|
1118 | 1222 | xfs_attr3_leaf_hdr_from_disk(args->geo, &icleafhdr, leaf); |
---|
1119 | 1223 | entries = xfs_attr3_leaf_entryp(leaf); |
---|
1120 | 1224 | |
---|
1121 | 1225 | /* both on-disk, don't endian-flip twice */ |
---|
1122 | | - btree[0].hashval = entries[icleafhdr.count - 1].hashval; |
---|
1123 | | - btree[0].before = cpu_to_be32(blkno); |
---|
| 1226 | + icnodehdr.btree[0].hashval = entries[icleafhdr.count - 1].hashval; |
---|
| 1227 | + icnodehdr.btree[0].before = cpu_to_be32(blkno); |
---|
1124 | 1228 | icnodehdr.count = 1; |
---|
1125 | | - dp->d_ops->node_hdr_to_disk(node, &icnodehdr); |
---|
| 1229 | + xfs_da3_node_hdr_to_disk(dp->i_mount, node, &icnodehdr); |
---|
1126 | 1230 | xfs_trans_log_buf(args->trans, bp1, 0, args->geo->blksize - 1); |
---|
1127 | 1231 | error = 0; |
---|
1128 | 1232 | out: |
---|
.. | .. |
---|
1152 | 1256 | |
---|
1153 | 1257 | trace_xfs_attr_leaf_create(args); |
---|
1154 | 1258 | |
---|
1155 | | - error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp, |
---|
| 1259 | + error = xfs_da_get_buf(args->trans, args->dp, blkno, &bp, |
---|
1156 | 1260 | XFS_ATTR_FORK); |
---|
1157 | 1261 | if (error) |
---|
1158 | 1262 | return error; |
---|
.. | .. |
---|
1378 | 1482 | entry->nameidx = cpu_to_be16(ichdr->freemap[mapindex].base + |
---|
1379 | 1483 | ichdr->freemap[mapindex].size); |
---|
1380 | 1484 | entry->hashval = cpu_to_be32(args->hashval); |
---|
1381 | | - entry->flags = tmp ? XFS_ATTR_LOCAL : 0; |
---|
1382 | | - entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); |
---|
| 1485 | + entry->flags = args->attr_filter; |
---|
| 1486 | + if (tmp) |
---|
| 1487 | + entry->flags |= XFS_ATTR_LOCAL; |
---|
1383 | 1488 | if (args->op_flags & XFS_DA_OP_RENAME) { |
---|
1384 | 1489 | entry->flags |= XFS_ATTR_INCOMPLETE; |
---|
1385 | 1490 | if ((args->blkno2 == args->blkno) && |
---|
.. | .. |
---|
1464 | 1569 | |
---|
1465 | 1570 | trace_xfs_attr_leaf_compact(args); |
---|
1466 | 1571 | |
---|
1467 | | - tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP); |
---|
| 1572 | + tmpbuffer = kmem_alloc(args->geo->blksize, 0); |
---|
1468 | 1573 | memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); |
---|
1469 | 1574 | memset(bp->b_addr, 0, args->geo->blksize); |
---|
1470 | 1575 | leaf_src = (xfs_attr_leafblock_t *)tmpbuffer; |
---|
.. | .. |
---|
1538 | 1643 | { |
---|
1539 | 1644 | struct xfs_attr3_icleaf_hdr ichdr1; |
---|
1540 | 1645 | struct xfs_attr3_icleaf_hdr ichdr2; |
---|
1541 | | - struct xfs_mount *mp = leaf1_bp->b_target->bt_mount; |
---|
| 1646 | + struct xfs_mount *mp = leaf1_bp->b_mount; |
---|
1542 | 1647 | |
---|
1543 | 1648 | xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr1, leaf1_bp->b_addr); |
---|
1544 | 1649 | xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr2, leaf2_bp->b_addr); |
---|
.. | .. |
---|
1924 | 2029 | if (blkno == 0) |
---|
1925 | 2030 | continue; |
---|
1926 | 2031 | error = xfs_attr3_leaf_read(state->args->trans, state->args->dp, |
---|
1927 | | - blkno, -1, &bp); |
---|
| 2032 | + blkno, &bp); |
---|
1928 | 2033 | if (error) |
---|
1929 | 2034 | return error; |
---|
1930 | 2035 | |
---|
.. | .. |
---|
2183 | 2288 | struct xfs_attr_leafblock *tmp_leaf; |
---|
2184 | 2289 | struct xfs_attr3_icleaf_hdr tmphdr; |
---|
2185 | 2290 | |
---|
2186 | | - tmp_leaf = kmem_zalloc(state->args->geo->blksize, KM_SLEEP); |
---|
| 2291 | + tmp_leaf = kmem_zalloc(state->args->geo->blksize, 0); |
---|
2187 | 2292 | |
---|
2188 | 2293 | /* |
---|
2189 | 2294 | * Copy the header into the temp leaf so that all the stuff |
---|
.. | .. |
---|
2274 | 2379 | leaf = bp->b_addr; |
---|
2275 | 2380 | xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); |
---|
2276 | 2381 | entries = xfs_attr3_leaf_entryp(leaf); |
---|
2277 | | - if (ichdr.count >= args->geo->blksize / 8) |
---|
| 2382 | + if (ichdr.count >= args->geo->blksize / 8) { |
---|
| 2383 | + xfs_buf_mark_corrupt(bp); |
---|
2278 | 2384 | return -EFSCORRUPTED; |
---|
| 2385 | + } |
---|
2279 | 2386 | |
---|
2280 | 2387 | /* |
---|
2281 | 2388 | * Binary search. (note: small blocks will skip this loop) |
---|
.. | .. |
---|
2291 | 2398 | else |
---|
2292 | 2399 | break; |
---|
2293 | 2400 | } |
---|
2294 | | - if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count))) |
---|
| 2401 | + if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count))) { |
---|
| 2402 | + xfs_buf_mark_corrupt(bp); |
---|
2295 | 2403 | return -EFSCORRUPTED; |
---|
2296 | | - if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval)) |
---|
| 2404 | + } |
---|
| 2405 | + if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval)) { |
---|
| 2406 | + xfs_buf_mark_corrupt(bp); |
---|
2297 | 2407 | return -EFSCORRUPTED; |
---|
| 2408 | + } |
---|
2298 | 2409 | |
---|
2299 | 2410 | /* |
---|
2300 | 2411 | * Since we may have duplicate hashval's, find the first matching |
---|
.. | .. |
---|
2322 | 2433 | /* |
---|
2323 | 2434 | * GROT: Add code to remove incomplete entries. |
---|
2324 | 2435 | */ |
---|
2325 | | - /* |
---|
2326 | | - * If we are looking for INCOMPLETE entries, show only those. |
---|
2327 | | - * If we are looking for complete entries, show only those. |
---|
2328 | | - */ |
---|
2329 | | - if ((args->flags & XFS_ATTR_INCOMPLETE) != |
---|
2330 | | - (entry->flags & XFS_ATTR_INCOMPLETE)) { |
---|
2331 | | - continue; |
---|
2332 | | - } |
---|
2333 | 2436 | if (entry->flags & XFS_ATTR_LOCAL) { |
---|
2334 | 2437 | name_loc = xfs_attr3_leaf_name_local(leaf, probe); |
---|
2335 | | - if (name_loc->namelen != args->namelen) |
---|
2336 | | - continue; |
---|
2337 | | - if (memcmp(args->name, name_loc->nameval, |
---|
2338 | | - args->namelen) != 0) |
---|
2339 | | - continue; |
---|
2340 | | - if (!xfs_attr_namesp_match(args->flags, entry->flags)) |
---|
| 2438 | + if (!xfs_attr_match(args, name_loc->namelen, |
---|
| 2439 | + name_loc->nameval, entry->flags)) |
---|
2341 | 2440 | continue; |
---|
2342 | 2441 | args->index = probe; |
---|
2343 | 2442 | return -EEXIST; |
---|
2344 | 2443 | } else { |
---|
2345 | 2444 | name_rmt = xfs_attr3_leaf_name_remote(leaf, probe); |
---|
2346 | | - if (name_rmt->namelen != args->namelen) |
---|
2347 | | - continue; |
---|
2348 | | - if (memcmp(args->name, name_rmt->name, |
---|
2349 | | - args->namelen) != 0) |
---|
2350 | | - continue; |
---|
2351 | | - if (!xfs_attr_namesp_match(args->flags, entry->flags)) |
---|
| 2445 | + if (!xfs_attr_match(args, name_rmt->namelen, |
---|
| 2446 | + name_rmt->name, entry->flags)) |
---|
2352 | 2447 | continue; |
---|
2353 | 2448 | args->index = probe; |
---|
2354 | 2449 | args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen); |
---|
.. | .. |
---|
2366 | 2461 | /* |
---|
2367 | 2462 | * Get the value associated with an attribute name from a leaf attribute |
---|
2368 | 2463 | * list structure. |
---|
| 2464 | + * |
---|
| 2465 | + * If args->valuelen is zero, only the length needs to be returned. Unlike a |
---|
| 2466 | + * lookup, we only return an error if the attribute does not exist or we can't |
---|
| 2467 | + * retrieve the value. |
---|
2369 | 2468 | */ |
---|
2370 | 2469 | int |
---|
2371 | 2470 | xfs_attr3_leaf_getvalue( |
---|
.. | .. |
---|
2377 | 2476 | struct xfs_attr_leaf_entry *entry; |
---|
2378 | 2477 | struct xfs_attr_leaf_name_local *name_loc; |
---|
2379 | 2478 | struct xfs_attr_leaf_name_remote *name_rmt; |
---|
2380 | | - int valuelen; |
---|
2381 | 2479 | |
---|
2382 | 2480 | leaf = bp->b_addr; |
---|
2383 | 2481 | xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); |
---|
.. | .. |
---|
2389 | 2487 | name_loc = xfs_attr3_leaf_name_local(leaf, args->index); |
---|
2390 | 2488 | ASSERT(name_loc->namelen == args->namelen); |
---|
2391 | 2489 | ASSERT(memcmp(args->name, name_loc->nameval, args->namelen) == 0); |
---|
2392 | | - valuelen = be16_to_cpu(name_loc->valuelen); |
---|
2393 | | - if (args->flags & ATTR_KERNOVAL) { |
---|
2394 | | - args->valuelen = valuelen; |
---|
2395 | | - return 0; |
---|
2396 | | - } |
---|
2397 | | - if (args->valuelen < valuelen) { |
---|
2398 | | - args->valuelen = valuelen; |
---|
2399 | | - return -ERANGE; |
---|
2400 | | - } |
---|
2401 | | - args->valuelen = valuelen; |
---|
2402 | | - memcpy(args->value, &name_loc->nameval[args->namelen], valuelen); |
---|
2403 | | - } else { |
---|
2404 | | - name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); |
---|
2405 | | - ASSERT(name_rmt->namelen == args->namelen); |
---|
2406 | | - ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); |
---|
2407 | | - args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen); |
---|
2408 | | - args->rmtblkno = be32_to_cpu(name_rmt->valueblk); |
---|
2409 | | - args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount, |
---|
2410 | | - args->rmtvaluelen); |
---|
2411 | | - if (args->flags & ATTR_KERNOVAL) { |
---|
2412 | | - args->valuelen = args->rmtvaluelen; |
---|
2413 | | - return 0; |
---|
2414 | | - } |
---|
2415 | | - if (args->valuelen < args->rmtvaluelen) { |
---|
2416 | | - args->valuelen = args->rmtvaluelen; |
---|
2417 | | - return -ERANGE; |
---|
2418 | | - } |
---|
2419 | | - args->valuelen = args->rmtvaluelen; |
---|
| 2490 | + return xfs_attr_copy_value(args, |
---|
| 2491 | + &name_loc->nameval[args->namelen], |
---|
| 2492 | + be16_to_cpu(name_loc->valuelen)); |
---|
2420 | 2493 | } |
---|
2421 | | - return 0; |
---|
| 2494 | + |
---|
| 2495 | + name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); |
---|
| 2496 | + ASSERT(name_rmt->namelen == args->namelen); |
---|
| 2497 | + ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); |
---|
| 2498 | + args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen); |
---|
| 2499 | + args->rmtblkno = be32_to_cpu(name_rmt->valueblk); |
---|
| 2500 | + args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount, |
---|
| 2501 | + args->rmtvaluelen); |
---|
| 2502 | + return xfs_attr_copy_value(args, NULL, args->rmtvaluelen); |
---|
2422 | 2503 | } |
---|
2423 | 2504 | |
---|
2424 | 2505 | /*======================================================================== |
---|
.. | .. |
---|
2581 | 2662 | { |
---|
2582 | 2663 | struct xfs_attr3_icleaf_hdr ichdr; |
---|
2583 | 2664 | struct xfs_attr_leaf_entry *entries; |
---|
2584 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 2665 | + struct xfs_mount *mp = bp->b_mount; |
---|
2585 | 2666 | |
---|
2586 | 2667 | xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, bp->b_addr); |
---|
2587 | 2668 | entries = xfs_attr3_leaf_entryp(bp->b_addr); |
---|
.. | .. |
---|
2668 | 2749 | /* |
---|
2669 | 2750 | * Set up the operation. |
---|
2670 | 2751 | */ |
---|
2671 | | - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); |
---|
| 2752 | + error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp); |
---|
2672 | 2753 | if (error) |
---|
2673 | 2754 | return error; |
---|
2674 | 2755 | |
---|
.. | .. |
---|
2708 | 2789 | XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); |
---|
2709 | 2790 | } |
---|
2710 | 2791 | |
---|
2711 | | - /* |
---|
2712 | | - * Commit the flag value change and start the next trans in series. |
---|
2713 | | - */ |
---|
2714 | | - return xfs_trans_roll_inode(&args->trans, args->dp); |
---|
| 2792 | + return 0; |
---|
2715 | 2793 | } |
---|
2716 | 2794 | |
---|
2717 | 2795 | /* |
---|
.. | .. |
---|
2735 | 2813 | /* |
---|
2736 | 2814 | * Set up the operation. |
---|
2737 | 2815 | */ |
---|
2738 | | - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); |
---|
| 2816 | + error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp); |
---|
2739 | 2817 | if (error) |
---|
2740 | 2818 | return error; |
---|
2741 | 2819 | |
---|
.. | .. |
---|
2759 | 2837 | XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); |
---|
2760 | 2838 | } |
---|
2761 | 2839 | |
---|
2762 | | - /* |
---|
2763 | | - * Commit the flag value change and start the next trans in series. |
---|
2764 | | - */ |
---|
2765 | | - return xfs_trans_roll_inode(&args->trans, args->dp); |
---|
| 2840 | + return 0; |
---|
2766 | 2841 | } |
---|
2767 | 2842 | |
---|
2768 | 2843 | /* |
---|
.. | .. |
---|
2797 | 2872 | /* |
---|
2798 | 2873 | * Read the block containing the "old" attr |
---|
2799 | 2874 | */ |
---|
2800 | | - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp1); |
---|
| 2875 | + error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp1); |
---|
2801 | 2876 | if (error) |
---|
2802 | 2877 | return error; |
---|
2803 | 2878 | |
---|
.. | .. |
---|
2806 | 2881 | */ |
---|
2807 | 2882 | if (args->blkno2 != args->blkno) { |
---|
2808 | 2883 | error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno2, |
---|
2809 | | - -1, &bp2); |
---|
| 2884 | + &bp2); |
---|
2810 | 2885 | if (error) |
---|
2811 | 2886 | return error; |
---|
2812 | 2887 | } else { |
---|
.. | .. |
---|
2877 | 2952 | XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt))); |
---|
2878 | 2953 | } |
---|
2879 | 2954 | |
---|
2880 | | - /* |
---|
2881 | | - * Commit the flag value change and start the next trans in series. |
---|
2882 | | - */ |
---|
2883 | | - error = xfs_trans_roll_inode(&args->trans, args->dp); |
---|
2884 | | - |
---|
2885 | | - return error; |
---|
| 2955 | + return 0; |
---|
2886 | 2956 | } |
---|