diff options
Diffstat (limited to 'fs/xfs/xfs_attr_leaf.c')
-rw-r--r-- | fs/xfs/xfs_attr_leaf.c | 98 |
1 files changed, 62 insertions, 36 deletions
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 08d5457c948e..31d3cd129269 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -931,20 +931,22 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) | |||
931 | */ | 931 | */ |
932 | int | 932 | int |
933 | xfs_attr_shortform_allfit( | 933 | xfs_attr_shortform_allfit( |
934 | struct xfs_buf *bp, | 934 | struct xfs_buf *bp, |
935 | struct xfs_inode *dp) | 935 | struct xfs_inode *dp) |
936 | { | 936 | { |
937 | xfs_attr_leafblock_t *leaf; | 937 | struct xfs_attr_leafblock *leaf; |
938 | xfs_attr_leaf_entry_t *entry; | 938 | struct xfs_attr_leaf_entry *entry; |
939 | xfs_attr_leaf_name_local_t *name_loc; | 939 | xfs_attr_leaf_name_local_t *name_loc; |
940 | int bytes, i; | 940 | struct xfs_attr3_icleaf_hdr leafhdr; |
941 | int bytes; | ||
942 | int i; | ||
941 | 943 | ||
942 | leaf = bp->b_addr; | 944 | leaf = bp->b_addr; |
943 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 945 | xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf); |
946 | entry = xfs_attr3_leaf_entryp(leaf); | ||
944 | 947 | ||
945 | entry = &leaf->entries[0]; | ||
946 | bytes = sizeof(struct xfs_attr_sf_hdr); | 948 | bytes = sizeof(struct xfs_attr_sf_hdr); |
947 | for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { | 949 | for (i = 0; i < leafhdr.count; entry++, i++) { |
948 | if (entry->flags & XFS_ATTR_INCOMPLETE) | 950 | if (entry->flags & XFS_ATTR_INCOMPLETE) |
949 | continue; /* don't copy partial entries */ | 951 | continue; /* don't copy partial entries */ |
950 | if (!(entry->flags & XFS_ATTR_LOCAL)) | 952 | if (!(entry->flags & XFS_ATTR_LOCAL)) |
@@ -954,15 +956,15 @@ xfs_attr_shortform_allfit( | |||
954 | return(0); | 956 | return(0); |
955 | if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX) | 957 | if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX) |
956 | return(0); | 958 | return(0); |
957 | bytes += sizeof(struct xfs_attr_sf_entry)-1 | 959 | bytes += sizeof(struct xfs_attr_sf_entry) - 1 |
958 | + name_loc->namelen | 960 | + name_loc->namelen |
959 | + be16_to_cpu(name_loc->valuelen); | 961 | + be16_to_cpu(name_loc->valuelen); |
960 | } | 962 | } |
961 | if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && | 963 | if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && |
962 | (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && | 964 | (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && |
963 | (bytes == sizeof(struct xfs_attr_sf_hdr))) | 965 | (bytes == sizeof(struct xfs_attr_sf_hdr))) |
964 | return(-1); | 966 | return -1; |
965 | return(xfs_attr_shortform_bytesfit(dp, bytes)); | 967 | return xfs_attr_shortform_bytesfit(dp, bytes); |
966 | } | 968 | } |
967 | 969 | ||
968 | /* | 970 | /* |
@@ -1410,7 +1412,7 @@ xfs_attr3_leaf_add_work( | |||
1410 | name_rmt->valuelen = 0; | 1412 | name_rmt->valuelen = 0; |
1411 | name_rmt->valueblk = 0; | 1413 | name_rmt->valueblk = 0; |
1412 | args->rmtblkno = 1; | 1414 | args->rmtblkno = 1; |
1413 | args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen); | 1415 | args->rmtblkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen); |
1414 | } | 1416 | } |
1415 | xfs_trans_log_buf(args->trans, bp, | 1417 | xfs_trans_log_buf(args->trans, bp, |
1416 | XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index), | 1418 | XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index), |
@@ -1443,11 +1445,12 @@ xfs_attr3_leaf_add_work( | |||
1443 | STATIC void | 1445 | STATIC void |
1444 | xfs_attr3_leaf_compact( | 1446 | xfs_attr3_leaf_compact( |
1445 | struct xfs_da_args *args, | 1447 | struct xfs_da_args *args, |
1446 | struct xfs_attr3_icleaf_hdr *ichdr_d, | 1448 | struct xfs_attr3_icleaf_hdr *ichdr_dst, |
1447 | struct xfs_buf *bp) | 1449 | struct xfs_buf *bp) |
1448 | { | 1450 | { |
1449 | xfs_attr_leafblock_t *leaf_s, *leaf_d; | 1451 | struct xfs_attr_leafblock *leaf_src; |
1450 | struct xfs_attr3_icleaf_hdr ichdr_s; | 1452 | struct xfs_attr_leafblock *leaf_dst; |
1453 | struct xfs_attr3_icleaf_hdr ichdr_src; | ||
1451 | struct xfs_trans *trans = args->trans; | 1454 | struct xfs_trans *trans = args->trans; |
1452 | struct xfs_mount *mp = trans->t_mountp; | 1455 | struct xfs_mount *mp = trans->t_mountp; |
1453 | char *tmpbuffer; | 1456 | char *tmpbuffer; |
@@ -1455,29 +1458,38 @@ xfs_attr3_leaf_compact( | |||
1455 | trace_xfs_attr_leaf_compact(args); | 1458 | trace_xfs_attr_leaf_compact(args); |
1456 | 1459 | ||
1457 | tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP); | 1460 | tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP); |
1458 | ASSERT(tmpbuffer != NULL); | ||
1459 | memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(mp)); | 1461 | memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(mp)); |
1460 | memset(bp->b_addr, 0, XFS_LBSIZE(mp)); | 1462 | memset(bp->b_addr, 0, XFS_LBSIZE(mp)); |
1463 | leaf_src = (xfs_attr_leafblock_t *)tmpbuffer; | ||
1464 | leaf_dst = bp->b_addr; | ||
1461 | 1465 | ||
1462 | /* | 1466 | /* |
1463 | * Copy basic information | 1467 | * Copy the on-disk header back into the destination buffer to ensure |
1468 | * all the information in the header that is not part of the incore | ||
1469 | * header structure is preserved. | ||
1464 | */ | 1470 | */ |
1465 | leaf_s = (xfs_attr_leafblock_t *)tmpbuffer; | 1471 | memcpy(bp->b_addr, tmpbuffer, xfs_attr3_leaf_hdr_size(leaf_src)); |
1466 | leaf_d = bp->b_addr; | 1472 | |
1467 | ichdr_s = *ichdr_d; /* struct copy */ | 1473 | /* Initialise the incore headers */ |
1468 | ichdr_d->firstused = XFS_LBSIZE(mp); | 1474 | ichdr_src = *ichdr_dst; /* struct copy */ |
1469 | ichdr_d->usedbytes = 0; | 1475 | ichdr_dst->firstused = XFS_LBSIZE(mp); |
1470 | ichdr_d->count = 0; | 1476 | ichdr_dst->usedbytes = 0; |
1471 | ichdr_d->holes = 0; | 1477 | ichdr_dst->count = 0; |
1472 | ichdr_d->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_s); | 1478 | ichdr_dst->holes = 0; |
1473 | ichdr_d->freemap[0].size = ichdr_d->firstused - ichdr_d->freemap[0].base; | 1479 | ichdr_dst->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_src); |
1480 | ichdr_dst->freemap[0].size = ichdr_dst->firstused - | ||
1481 | ichdr_dst->freemap[0].base; | ||
1482 | |||
1483 | |||
1484 | /* write the header back to initialise the underlying buffer */ | ||
1485 | xfs_attr3_leaf_hdr_to_disk(leaf_dst, ichdr_dst); | ||
1474 | 1486 | ||
1475 | /* | 1487 | /* |
1476 | * Copy all entry's in the same (sorted) order, | 1488 | * Copy all entry's in the same (sorted) order, |
1477 | * but allocate name/value pairs packed and in sequence. | 1489 | * but allocate name/value pairs packed and in sequence. |
1478 | */ | 1490 | */ |
1479 | xfs_attr3_leaf_moveents(leaf_s, &ichdr_s, 0, leaf_d, ichdr_d, 0, | 1491 | xfs_attr3_leaf_moveents(leaf_src, &ichdr_src, 0, leaf_dst, ichdr_dst, 0, |
1480 | ichdr_s.count, mp); | 1492 | ichdr_src.count, mp); |
1481 | /* | 1493 | /* |
1482 | * this logs the entire buffer, but the caller must write the header | 1494 | * this logs the entire buffer, but the caller must write the header |
1483 | * back to the buffer when it is finished modifying it. | 1495 | * back to the buffer when it is finished modifying it. |
@@ -2179,14 +2191,24 @@ xfs_attr3_leaf_unbalance( | |||
2179 | struct xfs_attr_leafblock *tmp_leaf; | 2191 | struct xfs_attr_leafblock *tmp_leaf; |
2180 | struct xfs_attr3_icleaf_hdr tmphdr; | 2192 | struct xfs_attr3_icleaf_hdr tmphdr; |
2181 | 2193 | ||
2182 | tmp_leaf = kmem_alloc(state->blocksize, KM_SLEEP); | 2194 | tmp_leaf = kmem_zalloc(state->blocksize, KM_SLEEP); |
2183 | memset(tmp_leaf, 0, state->blocksize); | 2195 | |
2184 | memset(&tmphdr, 0, sizeof(tmphdr)); | 2196 | /* |
2197 | * Copy the header into the temp leaf so that all the stuff | ||
2198 | * not in the incore header is present and gets copied back in | ||
2199 | * once we've moved all the entries. | ||
2200 | */ | ||
2201 | memcpy(tmp_leaf, save_leaf, xfs_attr3_leaf_hdr_size(save_leaf)); | ||
2185 | 2202 | ||
2203 | memset(&tmphdr, 0, sizeof(tmphdr)); | ||
2186 | tmphdr.magic = savehdr.magic; | 2204 | tmphdr.magic = savehdr.magic; |
2187 | tmphdr.forw = savehdr.forw; | 2205 | tmphdr.forw = savehdr.forw; |
2188 | tmphdr.back = savehdr.back; | 2206 | tmphdr.back = savehdr.back; |
2189 | tmphdr.firstused = state->blocksize; | 2207 | tmphdr.firstused = state->blocksize; |
2208 | |||
2209 | /* write the header to the temp buffer to initialise it */ | ||
2210 | xfs_attr3_leaf_hdr_to_disk(tmp_leaf, &tmphdr); | ||
2211 | |||
2190 | if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, | 2212 | if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, |
2191 | drop_blk->bp, &drophdr)) { | 2213 | drop_blk->bp, &drophdr)) { |
2192 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, | 2214 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, |
@@ -2330,9 +2352,11 @@ xfs_attr3_leaf_lookup_int( | |||
2330 | if (!xfs_attr_namesp_match(args->flags, entry->flags)) | 2352 | if (!xfs_attr_namesp_match(args->flags, entry->flags)) |
2331 | continue; | 2353 | continue; |
2332 | args->index = probe; | 2354 | args->index = probe; |
2355 | args->valuelen = be32_to_cpu(name_rmt->valuelen); | ||
2333 | args->rmtblkno = be32_to_cpu(name_rmt->valueblk); | 2356 | args->rmtblkno = be32_to_cpu(name_rmt->valueblk); |
2334 | args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, | 2357 | args->rmtblkcnt = xfs_attr3_rmt_blocks( |
2335 | be32_to_cpu(name_rmt->valuelen)); | 2358 | args->dp->i_mount, |
2359 | args->valuelen); | ||
2336 | return XFS_ERROR(EEXIST); | 2360 | return XFS_ERROR(EEXIST); |
2337 | } | 2361 | } |
2338 | } | 2362 | } |
@@ -2383,7 +2407,8 @@ xfs_attr3_leaf_getvalue( | |||
2383 | ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); | 2407 | ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); |
2384 | valuelen = be32_to_cpu(name_rmt->valuelen); | 2408 | valuelen = be32_to_cpu(name_rmt->valuelen); |
2385 | args->rmtblkno = be32_to_cpu(name_rmt->valueblk); | 2409 | args->rmtblkno = be32_to_cpu(name_rmt->valueblk); |
2386 | args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, valuelen); | 2410 | args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount, |
2411 | valuelen); | ||
2387 | if (args->flags & ATTR_KERNOVAL) { | 2412 | if (args->flags & ATTR_KERNOVAL) { |
2388 | args->valuelen = valuelen; | 2413 | args->valuelen = valuelen; |
2389 | return 0; | 2414 | return 0; |
@@ -2709,7 +2734,8 @@ xfs_attr3_leaf_list_int( | |||
2709 | args.valuelen = valuelen; | 2734 | args.valuelen = valuelen; |
2710 | args.value = kmem_alloc(valuelen, KM_SLEEP | KM_NOFS); | 2735 | args.value = kmem_alloc(valuelen, KM_SLEEP | KM_NOFS); |
2711 | args.rmtblkno = be32_to_cpu(name_rmt->valueblk); | 2736 | args.rmtblkno = be32_to_cpu(name_rmt->valueblk); |
2712 | args.rmtblkcnt = XFS_B_TO_FSB(args.dp->i_mount, valuelen); | 2737 | args.rmtblkcnt = xfs_attr3_rmt_blocks( |
2738 | args.dp->i_mount, valuelen); | ||
2713 | retval = xfs_attr_rmtval_get(&args); | 2739 | retval = xfs_attr_rmtval_get(&args); |
2714 | if (retval) | 2740 | if (retval) |
2715 | return retval; | 2741 | return retval; |
@@ -3232,7 +3258,7 @@ xfs_attr3_leaf_inactive( | |||
3232 | name_rmt = xfs_attr3_leaf_name_remote(leaf, i); | 3258 | name_rmt = xfs_attr3_leaf_name_remote(leaf, i); |
3233 | if (name_rmt->valueblk) { | 3259 | if (name_rmt->valueblk) { |
3234 | lp->valueblk = be32_to_cpu(name_rmt->valueblk); | 3260 | lp->valueblk = be32_to_cpu(name_rmt->valueblk); |
3235 | lp->valuelen = XFS_B_TO_FSB(dp->i_mount, | 3261 | lp->valuelen = xfs_attr3_rmt_blocks(dp->i_mount, |
3236 | be32_to_cpu(name_rmt->valuelen)); | 3262 | be32_to_cpu(name_rmt->valuelen)); |
3237 | lp++; | 3263 | lp++; |
3238 | } | 3264 | } |