1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "xfs.h"
20#include "xfs_fs.h"
21#include "xfs_shared.h"
22#include "xfs_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
25#include "xfs_bit.h"
26#include "xfs_sb.h"
27#include "xfs_mount.h"
28#include "xfs_da_format.h"
29#include "xfs_da_btree.h"
30#include "xfs_inode.h"
31#include "xfs_trans.h"
32#include "xfs_inode_item.h"
33#include "xfs_bmap_btree.h"
34#include "xfs_bmap.h"
35#include "xfs_attr_sf.h"
36#include "xfs_attr_remote.h"
37#include "xfs_attr.h"
38#include "xfs_attr_leaf.h"
39#include "xfs_error.h"
40#include "xfs_trace.h"
41#include "xfs_buf_item.h"
42#include "xfs_cksum.h"
43#include "xfs_dir2.h"
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59STATIC int xfs_attr3_leaf_create(struct xfs_da_args *args,
60 xfs_dablk_t which_block, struct xfs_buf **bpp);
61STATIC int xfs_attr3_leaf_add_work(struct xfs_buf *leaf_buffer,
62 struct xfs_attr3_icleaf_hdr *ichdr,
63 struct xfs_da_args *args, int freemap_index);
64STATIC void xfs_attr3_leaf_compact(struct xfs_da_args *args,
65 struct xfs_attr3_icleaf_hdr *ichdr,
66 struct xfs_buf *leaf_buffer);
67STATIC void xfs_attr3_leaf_rebalance(xfs_da_state_t *state,
68 xfs_da_state_blk_t *blk1,
69 xfs_da_state_blk_t *blk2);
70STATIC int xfs_attr3_leaf_figure_balance(xfs_da_state_t *state,
71 xfs_da_state_blk_t *leaf_blk_1,
72 struct xfs_attr3_icleaf_hdr *ichdr1,
73 xfs_da_state_blk_t *leaf_blk_2,
74 struct xfs_attr3_icleaf_hdr *ichdr2,
75 int *number_entries_in_blk1,
76 int *number_usedbytes_in_blk1);
77
78
79
80
81STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args,
82 struct xfs_attr_leafblock *src_leaf,
83 struct xfs_attr3_icleaf_hdr *src_ichdr, int src_start,
84 struct xfs_attr_leafblock *dst_leaf,
85 struct xfs_attr3_icleaf_hdr *dst_ichdr, int dst_start,
86 int move_count);
87STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105static void
106xfs_attr3_leaf_firstused_from_disk(
107 struct xfs_da_geometry *geo,
108 struct xfs_attr3_icleaf_hdr *to,
109 struct xfs_attr_leafblock *from)
110{
111 struct xfs_attr3_leaf_hdr *hdr3;
112
113 if (from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) {
114 hdr3 = (struct xfs_attr3_leaf_hdr *) from;
115 to->firstused = be16_to_cpu(hdr3->firstused);
116 } else {
117 to->firstused = be16_to_cpu(from->hdr.firstused);
118 }
119
120
121
122
123
124
125 if (to->firstused == XFS_ATTR3_LEAF_NULLOFF) {
126 ASSERT(!to->count && !to->usedbytes);
127 ASSERT(geo->blksize > USHRT_MAX);
128 to->firstused = geo->blksize;
129 }
130}
131
132static void
133xfs_attr3_leaf_firstused_to_disk(
134 struct xfs_da_geometry *geo,
135 struct xfs_attr_leafblock *to,
136 struct xfs_attr3_icleaf_hdr *from)
137{
138 struct xfs_attr3_leaf_hdr *hdr3;
139 uint32_t firstused;
140
141
142 ASSERT(from->firstused != XFS_ATTR3_LEAF_NULLOFF);
143
144
145
146
147
148
149 firstused = from->firstused;
150 if (firstused > USHRT_MAX) {
151 ASSERT(from->firstused == geo->blksize);
152 firstused = XFS_ATTR3_LEAF_NULLOFF;
153 }
154
155 if (from->magic == XFS_ATTR3_LEAF_MAGIC) {
156 hdr3 = (struct xfs_attr3_leaf_hdr *) to;
157 hdr3->firstused = cpu_to_be16(firstused);
158 } else {
159 to->hdr.firstused = cpu_to_be16(firstused);
160 }
161}
162
163void
164xfs_attr3_leaf_hdr_from_disk(
165 struct xfs_da_geometry *geo,
166 struct xfs_attr3_icleaf_hdr *to,
167 struct xfs_attr_leafblock *from)
168{
169 int i;
170
171 ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC) ||
172 from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC));
173
174 if (from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) {
175 struct xfs_attr3_leaf_hdr *hdr3 = (struct xfs_attr3_leaf_hdr *)from;
176
177 to->forw = be32_to_cpu(hdr3->info.hdr.forw);
178 to->back = be32_to_cpu(hdr3->info.hdr.back);
179 to->magic = be16_to_cpu(hdr3->info.hdr.magic);
180 to->count = be16_to_cpu(hdr3->count);
181 to->usedbytes = be16_to_cpu(hdr3->usedbytes);
182 xfs_attr3_leaf_firstused_from_disk(geo, to, from);
183 to->holes = hdr3->holes;
184
185 for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
186 to->freemap[i].base = be16_to_cpu(hdr3->freemap[i].base);
187 to->freemap[i].size = be16_to_cpu(hdr3->freemap[i].size);
188 }
189 return;
190 }
191 to->forw = be32_to_cpu(from->hdr.info.forw);
192 to->back = be32_to_cpu(from->hdr.info.back);
193 to->magic = be16_to_cpu(from->hdr.info.magic);
194 to->count = be16_to_cpu(from->hdr.count);
195 to->usedbytes = be16_to_cpu(from->hdr.usedbytes);
196 xfs_attr3_leaf_firstused_from_disk(geo, to, from);
197 to->holes = from->hdr.holes;
198
199 for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
200 to->freemap[i].base = be16_to_cpu(from->hdr.freemap[i].base);
201 to->freemap[i].size = be16_to_cpu(from->hdr.freemap[i].size);
202 }
203}
204
205void
206xfs_attr3_leaf_hdr_to_disk(
207 struct xfs_da_geometry *geo,
208 struct xfs_attr_leafblock *to,
209 struct xfs_attr3_icleaf_hdr *from)
210{
211 int i;
212
213 ASSERT(from->magic == XFS_ATTR_LEAF_MAGIC ||
214 from->magic == XFS_ATTR3_LEAF_MAGIC);
215
216 if (from->magic == XFS_ATTR3_LEAF_MAGIC) {
217 struct xfs_attr3_leaf_hdr *hdr3 = (struct xfs_attr3_leaf_hdr *)to;
218
219 hdr3->info.hdr.forw = cpu_to_be32(from->forw);
220 hdr3->info.hdr.back = cpu_to_be32(from->back);
221 hdr3->info.hdr.magic = cpu_to_be16(from->magic);
222 hdr3->count = cpu_to_be16(from->count);
223 hdr3->usedbytes = cpu_to_be16(from->usedbytes);
224 xfs_attr3_leaf_firstused_to_disk(geo, to, from);
225 hdr3->holes = from->holes;
226 hdr3->pad1 = 0;
227
228 for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
229 hdr3->freemap[i].base = cpu_to_be16(from->freemap[i].base);
230 hdr3->freemap[i].size = cpu_to_be16(from->freemap[i].size);
231 }
232 return;
233 }
234 to->hdr.info.forw = cpu_to_be32(from->forw);
235 to->hdr.info.back = cpu_to_be32(from->back);
236 to->hdr.info.magic = cpu_to_be16(from->magic);
237 to->hdr.count = cpu_to_be16(from->count);
238 to->hdr.usedbytes = cpu_to_be16(from->usedbytes);
239 xfs_attr3_leaf_firstused_to_disk(geo, to, from);
240 to->hdr.holes = from->holes;
241 to->hdr.pad1 = 0;
242
243 for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
244 to->hdr.freemap[i].base = cpu_to_be16(from->freemap[i].base);
245 to->hdr.freemap[i].size = cpu_to_be16(from->freemap[i].size);
246 }
247}
248
249static bool
250xfs_attr3_leaf_verify(
251 struct xfs_buf *bp)
252{
253 struct xfs_mount *mp = bp->b_target->bt_mount;
254 struct xfs_attr_leafblock *leaf = bp->b_addr;
255 struct xfs_attr3_icleaf_hdr ichdr;
256
257 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
258
259 if (xfs_sb_version_hascrc(&mp->m_sb)) {
260 struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
261
262 if (ichdr.magic != XFS_ATTR3_LEAF_MAGIC)
263 return false;
264
265 if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_uuid))
266 return false;
267 if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn)
268 return false;
269 } else {
270 if (ichdr.magic != XFS_ATTR_LEAF_MAGIC)
271 return false;
272 }
273 if (ichdr.count == 0)
274 return false;
275
276
277
278
279 return true;
280}
281
282static void
283xfs_attr3_leaf_write_verify(
284 struct xfs_buf *bp)
285{
286 struct xfs_mount *mp = bp->b_target->bt_mount;
287 struct xfs_buf_log_item *bip = bp->b_fspriv;
288 struct xfs_attr3_leaf_hdr *hdr3 = bp->b_addr;
289
290 if (!xfs_attr3_leaf_verify(bp)) {
291 xfs_buf_ioerror(bp, -EFSCORRUPTED);
292 xfs_verifier_error(bp);
293 return;
294 }
295
296 if (!xfs_sb_version_hascrc(&mp->m_sb))
297 return;
298
299 if (bip)
300 hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn);
301
302 xfs_buf_update_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF);
303}
304
305
306
307
308
309
310
311static void
312xfs_attr3_leaf_read_verify(
313 struct xfs_buf *bp)
314{
315 struct xfs_mount *mp = bp->b_target->bt_mount;
316
317 if (xfs_sb_version_hascrc(&mp->m_sb) &&
318 !xfs_buf_verify_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF))
319 xfs_buf_ioerror(bp, -EFSBADCRC);
320 else if (!xfs_attr3_leaf_verify(bp))
321 xfs_buf_ioerror(bp, -EFSCORRUPTED);
322
323 if (bp->b_error)
324 xfs_verifier_error(bp);
325}
326
327const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = {
328 .verify_read = xfs_attr3_leaf_read_verify,
329 .verify_write = xfs_attr3_leaf_write_verify,
330};
331
332int
333xfs_attr3_leaf_read(
334 struct xfs_trans *tp,
335 struct xfs_inode *dp,
336 xfs_dablk_t bno,
337 xfs_daddr_t mappedbno,
338 struct xfs_buf **bpp)
339{
340 int err;
341
342 err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
343 XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops);
344 if (!err && tp)
345 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_ATTR_LEAF_BUF);
346 return err;
347}
348
349
350
351
352
353
354
355
356
357STATIC int
358xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
359{
360 return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags);
361}
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378int
379xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
380{
381 int offset;
382 int minforkoff;
383 int maxforkoff;
384 int dsize;
385 xfs_mount_t *mp = dp->i_mount;
386
387
388 offset = (XFS_LITINO(mp, dp->i_d.di_version) - bytes) >> 3;
389
390 switch (dp->i_d.di_format) {
391 case XFS_DINODE_FMT_DEV:
392 minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
393 return (offset >= minforkoff) ? minforkoff : 0;
394 case XFS_DINODE_FMT_UUID:
395 minforkoff = roundup(sizeof(uuid_t), 8) >> 3;
396 return (offset >= minforkoff) ? minforkoff : 0;
397 }
398
399
400
401
402
403
404
405
406
407
408
409 if (bytes <= XFS_IFORK_ASIZE(dp))
410 return dp->i_d.di_forkoff;
411
412
413
414
415
416
417 if (!(mp->m_flags & XFS_MOUNT_ATTR2))
418 return 0;
419
420 dsize = dp->i_df.if_bytes;
421
422 switch (dp->i_d.di_format) {
423 case XFS_DINODE_FMT_EXTENTS:
424
425
426
427
428
429
430
431 if (!dp->i_d.di_forkoff && dp->i_df.if_bytes >
432 xfs_default_attroffset(dp))
433 dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
434 break;
435 case XFS_DINODE_FMT_BTREE:
436
437
438
439
440
441
442 if (dp->i_d.di_forkoff) {
443 if (offset < dp->i_d.di_forkoff)
444 return 0;
445 return dp->i_d.di_forkoff;
446 }
447 dsize = XFS_BMAP_BROOT_SPACE(mp, dp->i_df.if_broot);
448 break;
449 }
450
451
452
453
454
455 minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
456 minforkoff = roundup(minforkoff, 8) >> 3;
457
458
459 maxforkoff = XFS_LITINO(mp, dp->i_d.di_version) -
460 XFS_BMDR_SPACE_CALC(MINABTPTRS);
461 maxforkoff = maxforkoff >> 3;
462
463 if (offset >= maxforkoff)
464 return maxforkoff;
465 if (offset >= minforkoff)
466 return offset;
467 return 0;
468}
469
470
471
472
473STATIC void
474xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
475{
476 if ((mp->m_flags & XFS_MOUNT_ATTR2) &&
477 !(xfs_sb_version_hasattr2(&mp->m_sb))) {
478 spin_lock(&mp->m_sb_lock);
479 if (!xfs_sb_version_hasattr2(&mp->m_sb)) {
480 xfs_sb_version_addattr2(&mp->m_sb);
481 spin_unlock(&mp->m_sb_lock);
482 xfs_log_sb(tp);
483 } else
484 spin_unlock(&mp->m_sb_lock);
485 }
486}
487
488
489
490
491void
492xfs_attr_shortform_create(xfs_da_args_t *args)
493{
494 xfs_attr_sf_hdr_t *hdr;
495 xfs_inode_t *dp;
496 xfs_ifork_t *ifp;
497
498 trace_xfs_attr_sf_create(args);
499
500 dp = args->dp;
501 ASSERT(dp != NULL);
502 ifp = dp->i_afp;
503 ASSERT(ifp != NULL);
504 ASSERT(ifp->if_bytes == 0);
505 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) {
506 ifp->if_flags &= ~XFS_IFEXTENTS;
507 dp->i_d.di_aformat = XFS_DINODE_FMT_LOCAL;
508 ifp->if_flags |= XFS_IFINLINE;
509 } else {
510 ASSERT(ifp->if_flags & XFS_IFINLINE);
511 }
512 xfs_idata_realloc(dp, sizeof(*hdr), XFS_ATTR_FORK);
513 hdr = (xfs_attr_sf_hdr_t *)ifp->if_u1.if_data;
514 hdr->count = 0;
515 hdr->totsize = cpu_to_be16(sizeof(*hdr));
516 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA);
517}
518
519
520
521
522
523void
524xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
525{
526 xfs_attr_shortform_t *sf;
527 xfs_attr_sf_entry_t *sfe;
528 int i, offset, size;
529 xfs_mount_t *mp;
530 xfs_inode_t *dp;
531 xfs_ifork_t *ifp;
532
533 trace_xfs_attr_sf_add(args);
534
535 dp = args->dp;
536 mp = dp->i_mount;
537 dp->i_d.di_forkoff = forkoff;
538
539 ifp = dp->i_afp;
540 ASSERT(ifp->if_flags & XFS_IFINLINE);
541 sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
542 sfe = &sf->list[0];
543 for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) {
544#ifdef DEBUG
545 if (sfe->namelen != args->namelen)
546 continue;
547 if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
548 continue;
549 if (!xfs_attr_namesp_match(args->flags, sfe->flags))
550 continue;
551 ASSERT(0);
552#endif
553 }
554
555 offset = (char *)sfe - (char *)sf;
556 size = XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
557 xfs_idata_realloc(dp, size, XFS_ATTR_FORK);
558 sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
559 sfe = (xfs_attr_sf_entry_t *)((char *)sf + offset);
560
561 sfe->namelen = args->namelen;
562 sfe->valuelen = args->valuelen;
563 sfe->flags = XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags);
564 memcpy(sfe->nameval, args->name, args->namelen);
565 memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen);
566 sf->hdr.count++;
567 be16_add_cpu(&sf->hdr.totsize, size);
568 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA);
569
570 xfs_sbversion_add_attr2(mp, args->trans);
571}
572
573
574
575
576
577void
578xfs_attr_fork_remove(
579 struct xfs_inode *ip,
580 struct xfs_trans *tp)
581{
582 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
583 ip->i_d.di_forkoff = 0;
584 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
585
586 ASSERT(ip->i_d.di_anextents == 0);
587 ASSERT(ip->i_afp == NULL);
588
589 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
590}
591
592
593
594
595int
596xfs_attr_shortform_remove(xfs_da_args_t *args)
597{
598 xfs_attr_shortform_t *sf;
599 xfs_attr_sf_entry_t *sfe;
600 int base, size=0, end, totsize, i;
601 xfs_mount_t *mp;
602 xfs_inode_t *dp;
603
604 trace_xfs_attr_sf_remove(args);
605
606 dp = args->dp;
607 mp = dp->i_mount;
608 base = sizeof(xfs_attr_sf_hdr_t);
609 sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
610 sfe = &sf->list[0];
611 end = sf->hdr.count;
612 for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe),
613 base += size, i++) {
614 size = XFS_ATTR_SF_ENTSIZE(sfe);
615 if (sfe->namelen != args->namelen)
616 continue;
617 if (memcmp(sfe->nameval, args->name, args->namelen) != 0)
618 continue;
619 if (!xfs_attr_namesp_match(args->flags, sfe->flags))
620 continue;
621 break;
622 }
623 if (i == end)
624 return -ENOATTR;
625
626
627
628
629 end = base + size;
630 totsize = be16_to_cpu(sf->hdr.totsize);
631 if (end != totsize)
632 memmove(&((char *)sf)[base], &((char *)sf)[end], totsize - end);
633 sf->hdr.count--;
634 be16_add_cpu(&sf->hdr.totsize, -size);
635
636
637
638
639 totsize -= size;
640 if (totsize == sizeof(xfs_attr_sf_hdr_t) &&
641 (mp->m_flags & XFS_MOUNT_ATTR2) &&
642 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
643 !(args->op_flags & XFS_DA_OP_ADDNAME)) {
644 xfs_attr_fork_remove(dp, args->trans);
645 } else {
646 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
647 dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
648 ASSERT(dp->i_d.di_forkoff);
649 ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) ||
650 (args->op_flags & XFS_DA_OP_ADDNAME) ||
651 !(mp->m_flags & XFS_MOUNT_ATTR2) ||
652 dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
653 xfs_trans_log_inode(args->trans, dp,
654 XFS_ILOG_CORE | XFS_ILOG_ADATA);
655 }
656
657 xfs_sbversion_add_attr2(mp, args->trans);
658
659 return 0;
660}
661
662
663
664
665
666int
667xfs_attr_shortform_lookup(xfs_da_args_t *args)
668{
669 xfs_attr_shortform_t *sf;
670 xfs_attr_sf_entry_t *sfe;
671 int i;
672 xfs_ifork_t *ifp;
673
674 trace_xfs_attr_sf_lookup(args);
675
676 ifp = args->dp->i_afp;
677 ASSERT(ifp->if_flags & XFS_IFINLINE);
678 sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
679 sfe = &sf->list[0];
680 for (i = 0; i < sf->hdr.count;
681 sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) {
682 if (sfe->namelen != args->namelen)
683 continue;
684 if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
685 continue;
686 if (!xfs_attr_namesp_match(args->flags, sfe->flags))
687 continue;
688 return -EEXIST;
689 }
690 return -ENOATTR;
691}
692
693
694
695
696
697int
698xfs_attr_shortform_getvalue(xfs_da_args_t *args)
699{
700 xfs_attr_shortform_t *sf;
701 xfs_attr_sf_entry_t *sfe;
702 int i;
703
704 ASSERT(args->dp->i_afp->if_flags == XFS_IFINLINE);
705 sf = (xfs_attr_shortform_t *)args->dp->i_afp->if_u1.if_data;
706 sfe = &sf->list[0];
707 for (i = 0; i < sf->hdr.count;
708 sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) {
709 if (sfe->namelen != args->namelen)
710 continue;
711 if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
712 continue;
713 if (!xfs_attr_namesp_match(args->flags, sfe->flags))
714 continue;
715 if (args->flags & ATTR_KERNOVAL) {
716 args->valuelen = sfe->valuelen;
717 return -EEXIST;
718 }
719 if (args->valuelen < sfe->valuelen) {
720 args->valuelen = sfe->valuelen;
721 return -ERANGE;
722 }
723 args->valuelen = sfe->valuelen;
724 memcpy(args->value, &sfe->nameval[args->namelen],
725 args->valuelen);
726 return -EEXIST;
727 }
728 return -ENOATTR;
729}
730
731
732
733
734int
735xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
736{
737 xfs_inode_t *dp;
738 xfs_attr_shortform_t *sf;
739 xfs_attr_sf_entry_t *sfe;
740 xfs_da_args_t nargs;
741 char *tmpbuffer;
742 int error, i, size;
743 xfs_dablk_t blkno;
744 struct xfs_buf *bp;
745 xfs_ifork_t *ifp;
746
747 trace_xfs_attr_sf_to_leaf(args);
748
749 dp = args->dp;
750 ifp = dp->i_afp;
751 sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
752 size = be16_to_cpu(sf->hdr.totsize);
753 tmpbuffer = kmem_alloc(size, KM_SLEEP);
754 ASSERT(tmpbuffer != NULL);
755 memcpy(tmpbuffer, ifp->if_u1.if_data, size);
756 sf = (xfs_attr_shortform_t *)tmpbuffer;
757
758 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
759 xfs_bmap_local_to_extents_empty(dp, XFS_ATTR_FORK);
760
761 bp = NULL;
762 error = xfs_da_grow_inode(args, &blkno);
763 if (error) {
764
765
766
767
768 if (error == -EIO)
769 goto out;
770 xfs_idata_realloc(dp, size, XFS_ATTR_FORK);
771 memcpy(ifp->if_u1.if_data, tmpbuffer, size);
772 goto out;
773 }
774
775 ASSERT(blkno == 0);
776 error = xfs_attr3_leaf_create(args, blkno, &bp);
777 if (error) {
778 error = xfs_da_shrink_inode(args, 0, bp);
779 bp = NULL;
780 if (error)
781 goto out;
782 xfs_idata_realloc(dp, size, XFS_ATTR_FORK);
783 memcpy(ifp->if_u1.if_data, tmpbuffer, size);
784 goto out;
785 }
786
787 memset((char *)&nargs, 0, sizeof(nargs));
788 nargs.dp = dp;
789 nargs.geo = args->geo;
790 nargs.firstblock = args->firstblock;
791 nargs.flist = args->flist;
792 nargs.total = args->total;
793 nargs.whichfork = XFS_ATTR_FORK;
794 nargs.trans = args->trans;
795 nargs.op_flags = XFS_DA_OP_OKNOENT;
796
797 sfe = &sf->list[0];
798 for (i = 0; i < sf->hdr.count; i++) {
799 nargs.name = sfe->nameval;
800 nargs.namelen = sfe->namelen;
801 nargs.value = &sfe->nameval[nargs.namelen];
802 nargs.valuelen = sfe->valuelen;
803 nargs.hashval = xfs_da_hashname(sfe->nameval,
804 sfe->namelen);
805 nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags);
806 error = xfs_attr3_leaf_lookup_int(bp, &nargs);
807 ASSERT(error == -ENOATTR);
808 error = xfs_attr3_leaf_add(bp, &nargs);
809 ASSERT(error != -ENOSPC);
810 if (error)
811 goto out;
812 sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
813 }
814 error = 0;
815
816out:
817 kmem_free(tmpbuffer);
818 return error;
819}
820
821
822
823
824
825int
826xfs_attr_shortform_allfit(
827 struct xfs_buf *bp,
828 struct xfs_inode *dp)
829{
830 struct xfs_attr_leafblock *leaf;
831 struct xfs_attr_leaf_entry *entry;
832 xfs_attr_leaf_name_local_t *name_loc;
833 struct xfs_attr3_icleaf_hdr leafhdr;
834 int bytes;
835 int i;
836 struct xfs_mount *mp = bp->b_target->bt_mount;
837
838 leaf = bp->b_addr;
839 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
840 entry = xfs_attr3_leaf_entryp(leaf);
841
842 bytes = sizeof(struct xfs_attr_sf_hdr);
843 for (i = 0; i < leafhdr.count; entry++, i++) {
844 if (entry->flags & XFS_ATTR_INCOMPLETE)
845 continue;
846 if (!(entry->flags & XFS_ATTR_LOCAL))
847 return 0;
848 name_loc = xfs_attr3_leaf_name_local(leaf, i);
849 if (name_loc->namelen >= XFS_ATTR_SF_ENTSIZE_MAX)
850 return 0;
851 if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX)
852 return 0;
853 bytes += sizeof(struct xfs_attr_sf_entry) - 1
854 + name_loc->namelen
855 + be16_to_cpu(name_loc->valuelen);
856 }
857 if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
858 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
859 (bytes == sizeof(struct xfs_attr_sf_hdr)))
860 return -1;
861 return xfs_attr_shortform_bytesfit(dp, bytes);
862}
863
864
865
866
867int
868xfs_attr3_leaf_to_shortform(
869 struct xfs_buf *bp,
870 struct xfs_da_args *args,
871 int forkoff)
872{
873 struct xfs_attr_leafblock *leaf;
874 struct xfs_attr3_icleaf_hdr ichdr;
875 struct xfs_attr_leaf_entry *entry;
876 struct xfs_attr_leaf_name_local *name_loc;
877 struct xfs_da_args nargs;
878 struct xfs_inode *dp = args->dp;
879 char *tmpbuffer;
880 int error;
881 int i;
882
883 trace_xfs_attr_leaf_to_sf(args);
884
885 tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP);
886 if (!tmpbuffer)
887 return -ENOMEM;
888
889 memcpy(tmpbuffer, bp->b_addr, args->geo->blksize);
890
891 leaf = (xfs_attr_leafblock_t *)tmpbuffer;
892 xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
893 entry = xfs_attr3_leaf_entryp(leaf);
894
895
896 memset(bp->b_addr, 0, args->geo->blksize);
897
898
899
900
901 error = xfs_da_shrink_inode(args, 0, bp);
902 if (error)
903 goto out;
904
905 if (forkoff == -1) {
906 ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
907 ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
908 xfs_attr_fork_remove(dp, args->trans);
909 goto out;
910 }
911
912 xfs_attr_shortform_create(args);
913
914
915
916
917 memset((char *)&nargs, 0, sizeof(nargs));
918 nargs.geo = args->geo;
919 nargs.dp = dp;
920 nargs.firstblock = args->firstblock;
921 nargs.flist = args->flist;
922 nargs.total = args->total;
923 nargs.whichfork = XFS_ATTR_FORK;
924 nargs.trans = args->trans;
925 nargs.op_flags = XFS_DA_OP_OKNOENT;
926
927 for (i = 0; i < ichdr.count; entry++, i++) {
928 if (entry->flags & XFS_ATTR_INCOMPLETE)
929 continue;
930 if (!entry->nameidx)
931 continue;
932 ASSERT(entry->flags & XFS_ATTR_LOCAL);
933 name_loc = xfs_attr3_leaf_name_local(leaf, i);
934 nargs.name = name_loc->nameval;
935 nargs.namelen = name_loc->namelen;
936 nargs.value = &name_loc->nameval[nargs.namelen];
937 nargs.valuelen = be16_to_cpu(name_loc->valuelen);
938 nargs.hashval = be32_to_cpu(entry->hashval);
939 nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags);
940 xfs_attr_shortform_add(&nargs, forkoff);
941 }
942 error = 0;
943
944out:
945 kmem_free(tmpbuffer);
946 return error;
947}
948
949
950
951
952int
953xfs_attr3_leaf_to_node(
954 struct xfs_da_args *args)
955{
956 struct xfs_attr_leafblock *leaf;
957 struct xfs_attr3_icleaf_hdr icleafhdr;
958 struct xfs_attr_leaf_entry *entries;
959 struct xfs_da_node_entry *btree;
960 struct xfs_da3_icnode_hdr icnodehdr;
961 struct xfs_da_intnode *node;
962 struct xfs_inode *dp = args->dp;
963 struct xfs_mount *mp = dp->i_mount;
964 struct xfs_buf *bp1 = NULL;
965 struct xfs_buf *bp2 = NULL;
966 xfs_dablk_t blkno;
967 int error;
968
969 trace_xfs_attr_leaf_to_node(args);
970
971 error = xfs_da_grow_inode(args, &blkno);
972 if (error)
973 goto out;
974 error = xfs_attr3_leaf_read(args->trans, dp, 0, -1, &bp1);
975 if (error)
976 goto out;
977
978 error = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp2, XFS_ATTR_FORK);
979 if (error)
980 goto out;
981
982
983 xfs_trans_buf_set_type(args->trans, bp2, XFS_BLFT_ATTR_LEAF_BUF);
984 bp2->b_ops = bp1->b_ops;
985 memcpy(bp2->b_addr, bp1->b_addr, args->geo->blksize);
986 if (xfs_sb_version_hascrc(&mp->m_sb)) {
987 struct xfs_da3_blkinfo *hdr3 = bp2->b_addr;
988 hdr3->blkno = cpu_to_be64(bp2->b_bn);
989 }
990 xfs_trans_log_buf(args->trans, bp2, 0, args->geo->blksize - 1);
991
992
993
994
995 error = xfs_da3_node_create(args, 0, 1, &bp1, XFS_ATTR_FORK);
996 if (error)
997 goto out;
998 node = bp1->b_addr;
999 dp->d_ops->node_hdr_from_disk(&icnodehdr, node);
1000 btree = dp->d_ops->node_tree_p(node);
1001
1002 leaf = bp2->b_addr;
1003 xfs_attr3_leaf_hdr_from_disk(args->geo, &icleafhdr, leaf);
1004 entries = xfs_attr3_leaf_entryp(leaf);
1005
1006
1007 btree[0].hashval = entries[icleafhdr.count - 1].hashval;
1008 btree[0].before = cpu_to_be32(blkno);
1009 icnodehdr.count = 1;
1010 dp->d_ops->node_hdr_to_disk(node, &icnodehdr);
1011 xfs_trans_log_buf(args->trans, bp1, 0, args->geo->blksize - 1);
1012 error = 0;
1013out:
1014 return error;
1015}
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025STATIC int
1026xfs_attr3_leaf_create(
1027 struct xfs_da_args *args,
1028 xfs_dablk_t blkno,
1029 struct xfs_buf **bpp)
1030{
1031 struct xfs_attr_leafblock *leaf;
1032 struct xfs_attr3_icleaf_hdr ichdr;
1033 struct xfs_inode *dp = args->dp;
1034 struct xfs_mount *mp = dp->i_mount;
1035 struct xfs_buf *bp;
1036 int error;
1037
1038 trace_xfs_attr_leaf_create(args);
1039
1040 error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp,
1041 XFS_ATTR_FORK);
1042 if (error)
1043 return error;
1044 bp->b_ops = &xfs_attr3_leaf_buf_ops;
1045 xfs_trans_buf_set_type(args->trans, bp, XFS_BLFT_ATTR_LEAF_BUF);
1046 leaf = bp->b_addr;
1047 memset(leaf, 0, args->geo->blksize);
1048
1049 memset(&ichdr, 0, sizeof(ichdr));
1050 ichdr.firstused = args->geo->blksize;
1051
1052 if (xfs_sb_version_hascrc(&mp->m_sb)) {
1053 struct xfs_da3_blkinfo *hdr3 = bp->b_addr;
1054
1055 ichdr.magic = XFS_ATTR3_LEAF_MAGIC;
1056
1057 hdr3->blkno = cpu_to_be64(bp->b_bn);
1058 hdr3->owner = cpu_to_be64(dp->i_ino);
1059 uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid);
1060
1061 ichdr.freemap[0].base = sizeof(struct xfs_attr3_leaf_hdr);
1062 } else {
1063 ichdr.magic = XFS_ATTR_LEAF_MAGIC;
1064 ichdr.freemap[0].base = sizeof(struct xfs_attr_leaf_hdr);
1065 }
1066 ichdr.freemap[0].size = ichdr.firstused - ichdr.freemap[0].base;
1067
1068 xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr);
1069 xfs_trans_log_buf(args->trans, bp, 0, args->geo->blksize - 1);
1070
1071 *bpp = bp;
1072 return 0;
1073}
1074
1075
1076
1077
1078int
1079xfs_attr3_leaf_split(
1080 struct xfs_da_state *state,
1081 struct xfs_da_state_blk *oldblk,
1082 struct xfs_da_state_blk *newblk)
1083{
1084 xfs_dablk_t blkno;
1085 int error;
1086
1087 trace_xfs_attr_leaf_split(state->args);
1088
1089
1090
1091
1092 ASSERT(oldblk->magic == XFS_ATTR_LEAF_MAGIC);
1093 error = xfs_da_grow_inode(state->args, &blkno);
1094 if (error)
1095 return error;
1096 error = xfs_attr3_leaf_create(state->args, blkno, &newblk->bp);
1097 if (error)
1098 return error;
1099 newblk->blkno = blkno;
1100 newblk->magic = XFS_ATTR_LEAF_MAGIC;
1101
1102
1103
1104
1105
1106 xfs_attr3_leaf_rebalance(state, oldblk, newblk);
1107 error = xfs_da3_blk_link(state, oldblk, newblk);
1108 if (error)
1109 return error;
1110
1111
1112
1113
1114
1115
1116
1117
1118 if (state->inleaf) {
1119 trace_xfs_attr_leaf_add_old(state->args);
1120 error = xfs_attr3_leaf_add(oldblk->bp, state->args);
1121 } else {
1122 trace_xfs_attr_leaf_add_new(state->args);
1123 error = xfs_attr3_leaf_add(newblk->bp, state->args);
1124 }
1125
1126
1127
1128
1129 oldblk->hashval = xfs_attr_leaf_lasthash(oldblk->bp, NULL);
1130 newblk->hashval = xfs_attr_leaf_lasthash(newblk->bp, NULL);
1131 return error;
1132}
1133
1134
1135
1136
1137int
1138xfs_attr3_leaf_add(
1139 struct xfs_buf *bp,
1140 struct xfs_da_args *args)
1141{
1142 struct xfs_attr_leafblock *leaf;
1143 struct xfs_attr3_icleaf_hdr ichdr;
1144 int tablesize;
1145 int entsize;
1146 int sum;
1147 int tmp;
1148 int i;
1149
1150 trace_xfs_attr_leaf_add(args);
1151
1152 leaf = bp->b_addr;
1153 xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
1154 ASSERT(args->index >= 0 && args->index <= ichdr.count);
1155 entsize = xfs_attr_leaf_newentsize(args, NULL);
1156
1157
1158
1159
1160
1161 tablesize = (ichdr.count + 1) * sizeof(xfs_attr_leaf_entry_t)
1162 + xfs_attr3_leaf_hdr_size(leaf);
1163 for (sum = 0, i = XFS_ATTR_LEAF_MAPSIZE - 1; i >= 0; i--) {
1164 if (tablesize > ichdr.firstused) {
1165 sum += ichdr.freemap[i].size;
1166 continue;
1167 }
1168 if (!ichdr.freemap[i].size)
1169 continue;
1170 tmp = entsize;
1171 if (ichdr.freemap[i].base < ichdr.firstused)
1172 tmp += sizeof(xfs_attr_leaf_entry_t);
1173 if (ichdr.freemap[i].size >= tmp) {
1174 tmp = xfs_attr3_leaf_add_work(bp, &ichdr, args, i);
1175 goto out_log_hdr;
1176 }
1177 sum += ichdr.freemap[i].size;
1178 }
1179
1180
1181
1182
1183
1184
1185 if (!ichdr.holes && sum < entsize)
1186 return -ENOSPC;
1187
1188
1189
1190
1191
1192 xfs_attr3_leaf_compact(args, &ichdr, bp);
1193
1194
1195
1196
1197
1198 if (ichdr.freemap[0].size < (entsize + sizeof(xfs_attr_leaf_entry_t))) {
1199 tmp = -ENOSPC;
1200 goto out_log_hdr;
1201 }
1202
1203 tmp = xfs_attr3_leaf_add_work(bp, &ichdr, args, 0);
1204
1205out_log_hdr:
1206 xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr);
1207 xfs_trans_log_buf(args->trans, bp,
1208 XFS_DA_LOGRANGE(leaf, &leaf->hdr,
1209 xfs_attr3_leaf_hdr_size(leaf)));
1210 return tmp;
1211}
1212
1213
1214
1215
1216STATIC int
1217xfs_attr3_leaf_add_work(
1218 struct xfs_buf *bp,
1219 struct xfs_attr3_icleaf_hdr *ichdr,
1220 struct xfs_da_args *args,
1221 int mapindex)
1222{
1223 struct xfs_attr_leafblock *leaf;
1224 struct xfs_attr_leaf_entry *entry;
1225 struct xfs_attr_leaf_name_local *name_loc;
1226 struct xfs_attr_leaf_name_remote *name_rmt;
1227 struct xfs_mount *mp;
1228 int tmp;
1229 int i;
1230
1231 trace_xfs_attr_leaf_add_work(args);
1232
1233 leaf = bp->b_addr;
1234 ASSERT(mapindex >= 0 && mapindex < XFS_ATTR_LEAF_MAPSIZE);
1235 ASSERT(args->index >= 0 && args->index <= ichdr->count);
1236
1237
1238
1239
1240 entry = &xfs_attr3_leaf_entryp(leaf)[args->index];
1241 if (args->index < ichdr->count) {
1242 tmp = ichdr->count - args->index;
1243 tmp *= sizeof(xfs_attr_leaf_entry_t);
1244 memmove(entry + 1, entry, tmp);
1245 xfs_trans_log_buf(args->trans, bp,
1246 XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry)));
1247 }
1248 ichdr->count++;
1249
1250
1251
1252
1253 mp = args->trans->t_mountp;
1254 ASSERT(ichdr->freemap[mapindex].base < args->geo->blksize);
1255 ASSERT((ichdr->freemap[mapindex].base & 0x3) == 0);
1256 ASSERT(ichdr->freemap[mapindex].size >=
1257 xfs_attr_leaf_newentsize(args, NULL));
1258 ASSERT(ichdr->freemap[mapindex].size < args->geo->blksize);
1259 ASSERT((ichdr->freemap[mapindex].size & 0x3) == 0);
1260
1261 ichdr->freemap[mapindex].size -= xfs_attr_leaf_newentsize(args, &tmp);
1262
1263 entry->nameidx = cpu_to_be16(ichdr->freemap[mapindex].base +
1264 ichdr->freemap[mapindex].size);
1265 entry->hashval = cpu_to_be32(args->hashval);
1266 entry->flags = tmp ? XFS_ATTR_LOCAL : 0;
1267 entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags);
1268 if (args->op_flags & XFS_DA_OP_RENAME) {
1269 entry->flags |= XFS_ATTR_INCOMPLETE;
1270 if ((args->blkno2 == args->blkno) &&
1271 (args->index2 <= args->index)) {
1272 args->index2++;
1273 }
1274 }
1275 xfs_trans_log_buf(args->trans, bp,
1276 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
1277 ASSERT((args->index == 0) ||
1278 (be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval)));
1279 ASSERT((args->index == ichdr->count - 1) ||
1280 (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval)));
1281
1282
1283
1284
1285
1286
1287
1288
1289 if (entry->flags & XFS_ATTR_LOCAL) {
1290 name_loc = xfs_attr3_leaf_name_local(leaf, args->index);
1291 name_loc->namelen = args->namelen;
1292 name_loc->valuelen = cpu_to_be16(args->valuelen);
1293 memcpy((char *)name_loc->nameval, args->name, args->namelen);
1294 memcpy((char *)&name_loc->nameval[args->namelen], args->value,
1295 be16_to_cpu(name_loc->valuelen));
1296 } else {
1297 name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index);
1298 name_rmt->namelen = args->namelen;
1299 memcpy((char *)name_rmt->name, args->name, args->namelen);
1300 entry->flags |= XFS_ATTR_INCOMPLETE;
1301
1302 name_rmt->valuelen = 0;
1303 name_rmt->valueblk = 0;
1304 args->rmtblkno = 1;
1305 args->rmtblkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
1306 args->rmtvaluelen = args->valuelen;
1307 }
1308 xfs_trans_log_buf(args->trans, bp,
1309 XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index),
1310 xfs_attr_leaf_entsize(leaf, args->index)));
1311
1312
1313
1314
1315 if (be16_to_cpu(entry->nameidx) < ichdr->firstused)
1316 ichdr->firstused = be16_to_cpu(entry->nameidx);
1317
1318 ASSERT(ichdr->firstused >= ichdr->count * sizeof(xfs_attr_leaf_entry_t)
1319 + xfs_attr3_leaf_hdr_size(leaf));
1320 tmp = (ichdr->count - 1) * sizeof(xfs_attr_leaf_entry_t)
1321 + xfs_attr3_leaf_hdr_size(leaf);
1322
1323 for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
1324 if (ichdr->freemap[i].base == tmp) {
1325 ichdr->freemap[i].base += sizeof(xfs_attr_leaf_entry_t);
1326 ichdr->freemap[i].size -= sizeof(xfs_attr_leaf_entry_t);
1327 }
1328 }
1329 ichdr->usedbytes += xfs_attr_leaf_entsize(leaf, args->index);
1330 return 0;
1331}
1332
1333
1334
1335
1336STATIC void
1337xfs_attr3_leaf_compact(
1338 struct xfs_da_args *args,
1339 struct xfs_attr3_icleaf_hdr *ichdr_dst,
1340 struct xfs_buf *bp)
1341{
1342 struct xfs_attr_leafblock *leaf_src;
1343 struct xfs_attr_leafblock *leaf_dst;
1344 struct xfs_attr3_icleaf_hdr ichdr_src;
1345 struct xfs_trans *trans = args->trans;
1346 char *tmpbuffer;
1347
1348 trace_xfs_attr_leaf_compact(args);
1349
1350 tmpbuffer = kmem_alloc(args->geo->blksize, KM_SLEEP);
1351 memcpy(tmpbuffer, bp->b_addr, args->geo->blksize);
1352 memset(bp->b_addr, 0, args->geo->blksize);
1353 leaf_src = (xfs_attr_leafblock_t *)tmpbuffer;
1354 leaf_dst = bp->b_addr;
1355
1356
1357
1358
1359
1360
1361 memcpy(bp->b_addr, tmpbuffer, xfs_attr3_leaf_hdr_size(leaf_src));
1362
1363
1364 ichdr_src = *ichdr_dst;
1365 ichdr_dst->firstused = args->geo->blksize;
1366 ichdr_dst->usedbytes = 0;
1367 ichdr_dst->count = 0;
1368 ichdr_dst->holes = 0;
1369 ichdr_dst->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_src);
1370 ichdr_dst->freemap[0].size = ichdr_dst->firstused -
1371 ichdr_dst->freemap[0].base;
1372
1373
1374 xfs_attr3_leaf_hdr_to_disk(args->geo, leaf_dst, ichdr_dst);
1375
1376
1377
1378
1379
1380 xfs_attr3_leaf_moveents(args, leaf_src, &ichdr_src, 0,
1381 leaf_dst, ichdr_dst, 0, ichdr_src.count);
1382
1383
1384
1385
1386 xfs_trans_log_buf(trans, bp, 0, args->geo->blksize - 1);
1387
1388 kmem_free(tmpbuffer);
1389}
1390
1391
1392
1393
1394
1395static int
1396xfs_attr3_leaf_order(
1397 struct xfs_buf *leaf1_bp,
1398 struct xfs_attr3_icleaf_hdr *leaf1hdr,
1399 struct xfs_buf *leaf2_bp,
1400 struct xfs_attr3_icleaf_hdr *leaf2hdr)
1401{
1402 struct xfs_attr_leaf_entry *entries1;
1403 struct xfs_attr_leaf_entry *entries2;
1404
1405 entries1 = xfs_attr3_leaf_entryp(leaf1_bp->b_addr);
1406 entries2 = xfs_attr3_leaf_entryp(leaf2_bp->b_addr);
1407 if (leaf1hdr->count > 0 && leaf2hdr->count > 0 &&
1408 ((be32_to_cpu(entries2[0].hashval) <
1409 be32_to_cpu(entries1[0].hashval)) ||
1410 (be32_to_cpu(entries2[leaf2hdr->count - 1].hashval) <
1411 be32_to_cpu(entries1[leaf1hdr->count - 1].hashval)))) {
1412 return 1;
1413 }
1414 return 0;
1415}
1416
1417int
1418xfs_attr_leaf_order(
1419 struct xfs_buf *leaf1_bp,
1420 struct xfs_buf *leaf2_bp)
1421{
1422 struct xfs_attr3_icleaf_hdr ichdr1;
1423 struct xfs_attr3_icleaf_hdr ichdr2;
1424 struct xfs_mount *mp = leaf1_bp->b_target->bt_mount;
1425
1426 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr1, leaf1_bp->b_addr);
1427 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr2, leaf2_bp->b_addr);
1428 return xfs_attr3_leaf_order(leaf1_bp, &ichdr1, leaf2_bp, &ichdr2);
1429}
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443STATIC void
1444xfs_attr3_leaf_rebalance(
1445 struct xfs_da_state *state,
1446 struct xfs_da_state_blk *blk1,
1447 struct xfs_da_state_blk *blk2)
1448{
1449 struct xfs_da_args *args;
1450 struct xfs_attr_leafblock *leaf1;
1451 struct xfs_attr_leafblock *leaf2;
1452 struct xfs_attr3_icleaf_hdr ichdr1;
1453 struct xfs_attr3_icleaf_hdr ichdr2;
1454 struct xfs_attr_leaf_entry *entries1;
1455 struct xfs_attr_leaf_entry *entries2;
1456 int count;
1457 int totallen;
1458 int max;
1459 int space;
1460 int swap;
1461
1462
1463
1464
1465 ASSERT(blk1->magic == XFS_ATTR_LEAF_MAGIC);
1466 ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC);
1467 leaf1 = blk1->bp->b_addr;
1468 leaf2 = blk2->bp->b_addr;
1469 xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr1, leaf1);
1470 xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr2, leaf2);
1471 ASSERT(ichdr2.count == 0);
1472 args = state->args;
1473
1474 trace_xfs_attr_leaf_rebalance(args);
1475
1476
1477
1478
1479
1480
1481
1482 swap = 0;
1483 if (xfs_attr3_leaf_order(blk1->bp, &ichdr1, blk2->bp, &ichdr2)) {
1484 struct xfs_da_state_blk *tmp_blk;
1485 struct xfs_attr3_icleaf_hdr tmp_ichdr;
1486
1487 tmp_blk = blk1;
1488 blk1 = blk2;
1489 blk2 = tmp_blk;
1490
1491
1492 tmp_ichdr = ichdr1;
1493 ichdr1 = ichdr2;
1494 ichdr2 = tmp_ichdr;
1495
1496 leaf1 = blk1->bp->b_addr;
1497 leaf2 = blk2->bp->b_addr;
1498 swap = 1;
1499 }
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509 state->inleaf = xfs_attr3_leaf_figure_balance(state, blk1, &ichdr1,
1510 blk2, &ichdr2,
1511 &count, &totallen);
1512 if (swap)
1513 state->inleaf = !state->inleaf;
1514
1515
1516
1517
1518 if (count < ichdr1.count) {
1519
1520
1521
1522
1523 count = ichdr1.count - count;
1524 space = ichdr1.usedbytes - totallen;
1525 space += count * sizeof(xfs_attr_leaf_entry_t);
1526
1527
1528
1529
1530 max = ichdr2.firstused - xfs_attr3_leaf_hdr_size(leaf1);
1531 max -= ichdr2.count * sizeof(xfs_attr_leaf_entry_t);
1532 if (space > max)
1533 xfs_attr3_leaf_compact(args, &ichdr2, blk2->bp);
1534
1535
1536
1537
1538 xfs_attr3_leaf_moveents(args, leaf1, &ichdr1,
1539 ichdr1.count - count, leaf2, &ichdr2, 0, count);
1540
1541 } else if (count > ichdr1.count) {
1542
1543
1544
1545
1546 ASSERT(0);
1547
1548
1549
1550
1551
1552 count -= ichdr1.count;
1553 space = totallen - ichdr1.usedbytes;
1554 space += count * sizeof(xfs_attr_leaf_entry_t);
1555
1556
1557
1558
1559 max = ichdr1.firstused - xfs_attr3_leaf_hdr_size(leaf1);
1560 max -= ichdr1.count * sizeof(xfs_attr_leaf_entry_t);
1561 if (space > max)
1562 xfs_attr3_leaf_compact(args, &ichdr1, blk1->bp);
1563
1564
1565
1566
1567 xfs_attr3_leaf_moveents(args, leaf2, &ichdr2, 0, leaf1, &ichdr1,
1568 ichdr1.count, count);
1569 }
1570
1571 xfs_attr3_leaf_hdr_to_disk(state->args->geo, leaf1, &ichdr1);
1572 xfs_attr3_leaf_hdr_to_disk(state->args->geo, leaf2, &ichdr2);
1573 xfs_trans_log_buf(args->trans, blk1->bp, 0, args->geo->blksize - 1);
1574 xfs_trans_log_buf(args->trans, blk2->bp, 0, args->geo->blksize - 1);
1575
1576
1577
1578
1579 entries1 = xfs_attr3_leaf_entryp(leaf1);
1580 entries2 = xfs_attr3_leaf_entryp(leaf2);
1581 blk1->hashval = be32_to_cpu(entries1[ichdr1.count - 1].hashval);
1582 blk2->hashval = be32_to_cpu(entries2[ichdr2.count - 1].hashval);
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596 if (blk1->index > ichdr1.count) {
1597 ASSERT(state->inleaf == 0);
1598 blk2->index = blk1->index - ichdr1.count;
1599 args->index = args->index2 = blk2->index;
1600 args->blkno = args->blkno2 = blk2->blkno;
1601 } else if (blk1->index == ichdr1.count) {
1602 if (state->inleaf) {
1603 args->index = blk1->index;
1604 args->blkno = blk1->blkno;
1605 args->index2 = 0;
1606 args->blkno2 = blk2->blkno;
1607 } else {
1608
1609
1610
1611
1612
1613 blk2->index = blk1->index - ichdr1.count;
1614 args->index = blk2->index;
1615 args->blkno = blk2->blkno;
1616 if (!state->extravalid) {
1617
1618
1619
1620
1621
1622 args->index2 = blk2->index;
1623 args->blkno2 = blk2->blkno;
1624 }
1625 }
1626 } else {
1627 ASSERT(state->inleaf == 1);
1628 args->index = args->index2 = blk1->index;
1629 args->blkno = args->blkno2 = blk1->blkno;
1630 }
1631}
1632
1633
1634
1635
1636
1637
1638
1639
1640STATIC int
1641xfs_attr3_leaf_figure_balance(
1642 struct xfs_da_state *state,
1643 struct xfs_da_state_blk *blk1,
1644 struct xfs_attr3_icleaf_hdr *ichdr1,
1645 struct xfs_da_state_blk *blk2,
1646 struct xfs_attr3_icleaf_hdr *ichdr2,
1647 int *countarg,
1648 int *usedbytesarg)
1649{
1650 struct xfs_attr_leafblock *leaf1 = blk1->bp->b_addr;
1651 struct xfs_attr_leafblock *leaf2 = blk2->bp->b_addr;
1652 struct xfs_attr_leaf_entry *entry;
1653 int count;
1654 int max;
1655 int index;
1656 int totallen = 0;
1657 int half;
1658 int lastdelta;
1659 int foundit = 0;
1660 int tmp;
1661
1662
1663
1664
1665
1666 max = ichdr1->count + ichdr2->count;
1667 half = (max + 1) * sizeof(*entry);
1668 half += ichdr1->usedbytes + ichdr2->usedbytes +
1669 xfs_attr_leaf_newentsize(state->args, NULL);
1670 half /= 2;
1671 lastdelta = state->args->geo->blksize;
1672 entry = xfs_attr3_leaf_entryp(leaf1);
1673 for (count = index = 0; count < max; entry++, index++, count++) {
1674
1675#define XFS_ATTR_ABS(A) (((A) < 0) ? -(A) : (A))
1676
1677
1678
1679 if (count == blk1->index) {
1680 tmp = totallen + sizeof(*entry) +
1681 xfs_attr_leaf_newentsize(state->args, NULL);
1682 if (XFS_ATTR_ABS(half - tmp) > lastdelta)
1683 break;
1684 lastdelta = XFS_ATTR_ABS(half - tmp);
1685 totallen = tmp;
1686 foundit = 1;
1687 }
1688
1689
1690
1691
1692 if (count == ichdr1->count) {
1693 leaf1 = leaf2;
1694 entry = xfs_attr3_leaf_entryp(leaf1);
1695 index = 0;
1696 }
1697
1698
1699
1700
1701 tmp = totallen + sizeof(*entry) + xfs_attr_leaf_entsize(leaf1,
1702 index);
1703 if (XFS_ATTR_ABS(half - tmp) > lastdelta)
1704 break;
1705 lastdelta = XFS_ATTR_ABS(half - tmp);
1706 totallen = tmp;
1707#undef XFS_ATTR_ABS
1708 }
1709
1710
1711
1712
1713
1714 totallen -= count * sizeof(*entry);
1715 if (foundit) {
1716 totallen -= sizeof(*entry) +
1717 xfs_attr_leaf_newentsize(state->args, NULL);
1718 }
1719
1720 *countarg = count;
1721 *usedbytesarg = totallen;
1722 return foundit;
1723}
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740int
1741xfs_attr3_leaf_toosmall(
1742 struct xfs_da_state *state,
1743 int *action)
1744{
1745 struct xfs_attr_leafblock *leaf;
1746 struct xfs_da_state_blk *blk;
1747 struct xfs_attr3_icleaf_hdr ichdr;
1748 struct xfs_buf *bp;
1749 xfs_dablk_t blkno;
1750 int bytes;
1751 int forward;
1752 int error;
1753 int retval;
1754 int i;
1755
1756 trace_xfs_attr_leaf_toosmall(state->args);
1757
1758
1759
1760
1761
1762
1763 blk = &state->path.blk[ state->path.active-1 ];
1764 leaf = blk->bp->b_addr;
1765 xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr, leaf);
1766 bytes = xfs_attr3_leaf_hdr_size(leaf) +
1767 ichdr.count * sizeof(xfs_attr_leaf_entry_t) +
1768 ichdr.usedbytes;
1769 if (bytes > (state->args->geo->blksize >> 1)) {
1770 *action = 0;
1771 return 0;
1772 }
1773
1774
1775
1776
1777
1778
1779
1780 if (ichdr.count == 0) {
1781
1782
1783
1784
1785 forward = (ichdr.forw != 0);
1786 memcpy(&state->altpath, &state->path, sizeof(state->path));
1787 error = xfs_da3_path_shift(state, &state->altpath, forward,
1788 0, &retval);
1789 if (error)
1790 return error;
1791 if (retval) {
1792 *action = 0;
1793 } else {
1794 *action = 2;
1795 }
1796 return 0;
1797 }
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807 forward = ichdr.forw < ichdr.back;
1808 for (i = 0; i < 2; forward = !forward, i++) {
1809 struct xfs_attr3_icleaf_hdr ichdr2;
1810 if (forward)
1811 blkno = ichdr.forw;
1812 else
1813 blkno = ichdr.back;
1814 if (blkno == 0)
1815 continue;
1816 error = xfs_attr3_leaf_read(state->args->trans, state->args->dp,
1817 blkno, -1, &bp);
1818 if (error)
1819 return error;
1820
1821 xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr2, bp->b_addr);
1822
1823 bytes = state->args->geo->blksize -
1824 (state->args->geo->blksize >> 2) -
1825 ichdr.usedbytes - ichdr2.usedbytes -
1826 ((ichdr.count + ichdr2.count) *
1827 sizeof(xfs_attr_leaf_entry_t)) -
1828 xfs_attr3_leaf_hdr_size(leaf);
1829
1830 xfs_trans_brelse(state->args->trans, bp);
1831 if (bytes >= 0)
1832 break;
1833 }
1834 if (i >= 2) {
1835 *action = 0;
1836 return 0;
1837 }
1838
1839
1840
1841
1842
1843 memcpy(&state->altpath, &state->path, sizeof(state->path));
1844 if (blkno < blk->blkno) {
1845 error = xfs_da3_path_shift(state, &state->altpath, forward,
1846 0, &retval);
1847 } else {
1848 error = xfs_da3_path_shift(state, &state->path, forward,
1849 0, &retval);
1850 }
1851 if (error)
1852 return error;
1853 if (retval) {
1854 *action = 0;
1855 } else {
1856 *action = 1;
1857 }
1858 return 0;
1859}
1860
1861
1862
1863
1864
1865
1866
1867int
1868xfs_attr3_leaf_remove(
1869 struct xfs_buf *bp,
1870 struct xfs_da_args *args)
1871{
1872 struct xfs_attr_leafblock *leaf;
1873 struct xfs_attr3_icleaf_hdr ichdr;
1874 struct xfs_attr_leaf_entry *entry;
1875 int before;
1876 int after;
1877 int smallest;
1878 int entsize;
1879 int tablesize;
1880 int tmp;
1881 int i;
1882
1883 trace_xfs_attr_leaf_remove(args);
1884
1885 leaf = bp->b_addr;
1886 xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
1887
1888 ASSERT(ichdr.count > 0 && ichdr.count < args->geo->blksize / 8);
1889 ASSERT(args->index >= 0 && args->index < ichdr.count);
1890 ASSERT(ichdr.firstused >= ichdr.count * sizeof(*entry) +
1891 xfs_attr3_leaf_hdr_size(leaf));
1892
1893 entry = &xfs_attr3_leaf_entryp(leaf)[args->index];
1894
1895 ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused);
1896 ASSERT(be16_to_cpu(entry->nameidx) < args->geo->blksize);
1897
1898
1899
1900
1901
1902
1903
1904 tablesize = ichdr.count * sizeof(xfs_attr_leaf_entry_t)
1905 + xfs_attr3_leaf_hdr_size(leaf);
1906 tmp = ichdr.freemap[0].size;
1907 before = after = -1;
1908 smallest = XFS_ATTR_LEAF_MAPSIZE - 1;
1909 entsize = xfs_attr_leaf_entsize(leaf, args->index);
1910 for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
1911 ASSERT(ichdr.freemap[i].base < args->geo->blksize);
1912 ASSERT(ichdr.freemap[i].size < args->geo->blksize);
1913 if (ichdr.freemap[i].base == tablesize) {
1914 ichdr.freemap[i].base -= sizeof(xfs_attr_leaf_entry_t);
1915 ichdr.freemap[i].size += sizeof(xfs_attr_leaf_entry_t);
1916 }
1917
1918 if (ichdr.freemap[i].base + ichdr.freemap[i].size ==
1919 be16_to_cpu(entry->nameidx)) {
1920 before = i;
1921 } else if (ichdr.freemap[i].base ==
1922 (be16_to_cpu(entry->nameidx) + entsize)) {
1923 after = i;
1924 } else if (ichdr.freemap[i].size < tmp) {
1925 tmp = ichdr.freemap[i].size;
1926 smallest = i;
1927 }
1928 }
1929
1930
1931
1932
1933
1934 if ((before >= 0) || (after >= 0)) {
1935 if ((before >= 0) && (after >= 0)) {
1936 ichdr.freemap[before].size += entsize;
1937 ichdr.freemap[before].size += ichdr.freemap[after].size;
1938 ichdr.freemap[after].base = 0;
1939 ichdr.freemap[after].size = 0;
1940 } else if (before >= 0) {
1941 ichdr.freemap[before].size += entsize;
1942 } else {
1943 ichdr.freemap[after].base = be16_to_cpu(entry->nameidx);
1944 ichdr.freemap[after].size += entsize;
1945 }
1946 } else {
1947
1948
1949
1950 if (ichdr.freemap[smallest].size < entsize) {
1951 ichdr.freemap[smallest].base = be16_to_cpu(entry->nameidx);
1952 ichdr.freemap[smallest].size = entsize;
1953 }
1954 }
1955
1956
1957
1958
1959 if (be16_to_cpu(entry->nameidx) == ichdr.firstused)
1960 smallest = 1;
1961 else
1962 smallest = 0;
1963
1964
1965
1966
1967 memset(xfs_attr3_leaf_name(leaf, args->index), 0, entsize);
1968 ichdr.usedbytes -= entsize;
1969 xfs_trans_log_buf(args->trans, bp,
1970 XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index),
1971 entsize));
1972
1973 tmp = (ichdr.count - args->index) * sizeof(xfs_attr_leaf_entry_t);
1974 memmove(entry, entry + 1, tmp);
1975 ichdr.count--;
1976 xfs_trans_log_buf(args->trans, bp,
1977 XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(xfs_attr_leaf_entry_t)));
1978
1979 entry = &xfs_attr3_leaf_entryp(leaf)[ichdr.count];
1980 memset(entry, 0, sizeof(xfs_attr_leaf_entry_t));
1981
1982
1983
1984
1985
1986
1987
1988 if (smallest) {
1989 tmp = args->geo->blksize;
1990 entry = xfs_attr3_leaf_entryp(leaf);
1991 for (i = ichdr.count - 1; i >= 0; entry++, i--) {
1992 ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused);
1993 ASSERT(be16_to_cpu(entry->nameidx) < args->geo->blksize);
1994
1995 if (be16_to_cpu(entry->nameidx) < tmp)
1996 tmp = be16_to_cpu(entry->nameidx);
1997 }
1998 ichdr.firstused = tmp;
1999 ASSERT(ichdr.firstused != 0);
2000 } else {
2001 ichdr.holes = 1;
2002 }
2003 xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr);
2004 xfs_trans_log_buf(args->trans, bp,
2005 XFS_DA_LOGRANGE(leaf, &leaf->hdr,
2006 xfs_attr3_leaf_hdr_size(leaf)));
2007
2008
2009
2010
2011
2012 tmp = ichdr.usedbytes + xfs_attr3_leaf_hdr_size(leaf) +
2013 ichdr.count * sizeof(xfs_attr_leaf_entry_t);
2014
2015 return tmp < args->geo->magicpct;
2016}
2017
2018
2019
2020
2021void
2022xfs_attr3_leaf_unbalance(
2023 struct xfs_da_state *state,
2024 struct xfs_da_state_blk *drop_blk,
2025 struct xfs_da_state_blk *save_blk)
2026{
2027 struct xfs_attr_leafblock *drop_leaf = drop_blk->bp->b_addr;
2028 struct xfs_attr_leafblock *save_leaf = save_blk->bp->b_addr;
2029 struct xfs_attr3_icleaf_hdr drophdr;
2030 struct xfs_attr3_icleaf_hdr savehdr;
2031 struct xfs_attr_leaf_entry *entry;
2032
2033 trace_xfs_attr_leaf_unbalance(state->args);
2034
2035 drop_leaf = drop_blk->bp->b_addr;
2036 save_leaf = save_blk->bp->b_addr;
2037 xfs_attr3_leaf_hdr_from_disk(state->args->geo, &drophdr, drop_leaf);
2038 xfs_attr3_leaf_hdr_from_disk(state->args->geo, &savehdr, save_leaf);
2039 entry = xfs_attr3_leaf_entryp(drop_leaf);
2040
2041
2042
2043
2044 drop_blk->hashval = be32_to_cpu(entry[drophdr.count - 1].hashval);
2045
2046
2047
2048
2049
2050
2051 if (savehdr.holes == 0) {
2052
2053
2054
2055
2056 if (xfs_attr3_leaf_order(save_blk->bp, &savehdr,
2057 drop_blk->bp, &drophdr)) {
2058 xfs_attr3_leaf_moveents(state->args,
2059 drop_leaf, &drophdr, 0,
2060 save_leaf, &savehdr, 0,
2061 drophdr.count);
2062 } else {
2063 xfs_attr3_leaf_moveents(state->args,
2064 drop_leaf, &drophdr, 0,
2065 save_leaf, &savehdr,
2066 savehdr.count, drophdr.count);
2067 }
2068 } else {
2069
2070
2071
2072
2073 struct xfs_attr_leafblock *tmp_leaf;
2074 struct xfs_attr3_icleaf_hdr tmphdr;
2075
2076 tmp_leaf = kmem_zalloc(state->args->geo->blksize, KM_SLEEP);
2077
2078
2079
2080
2081
2082
2083 memcpy(tmp_leaf, save_leaf, xfs_attr3_leaf_hdr_size(save_leaf));
2084
2085 memset(&tmphdr, 0, sizeof(tmphdr));
2086 tmphdr.magic = savehdr.magic;
2087 tmphdr.forw = savehdr.forw;
2088 tmphdr.back = savehdr.back;
2089 tmphdr.firstused = state->args->geo->blksize;
2090
2091
2092 xfs_attr3_leaf_hdr_to_disk(state->args->geo, tmp_leaf, &tmphdr);
2093
2094 if (xfs_attr3_leaf_order(save_blk->bp, &savehdr,
2095 drop_blk->bp, &drophdr)) {
2096 xfs_attr3_leaf_moveents(state->args,
2097 drop_leaf, &drophdr, 0,
2098 tmp_leaf, &tmphdr, 0,
2099 drophdr.count);
2100 xfs_attr3_leaf_moveents(state->args,
2101 save_leaf, &savehdr, 0,
2102 tmp_leaf, &tmphdr, tmphdr.count,
2103 savehdr.count);
2104 } else {
2105 xfs_attr3_leaf_moveents(state->args,
2106 save_leaf, &savehdr, 0,
2107 tmp_leaf, &tmphdr, 0,
2108 savehdr.count);
2109 xfs_attr3_leaf_moveents(state->args,
2110 drop_leaf, &drophdr, 0,
2111 tmp_leaf, &tmphdr, tmphdr.count,
2112 drophdr.count);
2113 }
2114 memcpy(save_leaf, tmp_leaf, state->args->geo->blksize);
2115 savehdr = tmphdr;
2116 kmem_free(tmp_leaf);
2117 }
2118
2119 xfs_attr3_leaf_hdr_to_disk(state->args->geo, save_leaf, &savehdr);
2120 xfs_trans_log_buf(state->args->trans, save_blk->bp, 0,
2121 state->args->geo->blksize - 1);
2122
2123
2124
2125
2126 entry = xfs_attr3_leaf_entryp(save_leaf);
2127 save_blk->hashval = be32_to_cpu(entry[savehdr.count - 1].hashval);
2128}
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147int
2148xfs_attr3_leaf_lookup_int(
2149 struct xfs_buf *bp,
2150 struct xfs_da_args *args)
2151{
2152 struct xfs_attr_leafblock *leaf;
2153 struct xfs_attr3_icleaf_hdr ichdr;
2154 struct xfs_attr_leaf_entry *entry;
2155 struct xfs_attr_leaf_entry *entries;
2156 struct xfs_attr_leaf_name_local *name_loc;
2157 struct xfs_attr_leaf_name_remote *name_rmt;
2158 xfs_dahash_t hashval;
2159 int probe;
2160 int span;
2161
2162 trace_xfs_attr_leaf_lookup(args);
2163
2164 leaf = bp->b_addr;
2165 xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
2166 entries = xfs_attr3_leaf_entryp(leaf);
2167 ASSERT(ichdr.count < args->geo->blksize / 8);
2168
2169
2170
2171
2172 hashval = args->hashval;
2173 probe = span = ichdr.count / 2;
2174 for (entry = &entries[probe]; span > 4; entry = &entries[probe]) {
2175 span /= 2;
2176 if (be32_to_cpu(entry->hashval) < hashval)
2177 probe += span;
2178 else if (be32_to_cpu(entry->hashval) > hashval)
2179 probe -= span;
2180 else
2181 break;
2182 }
2183 ASSERT(probe >= 0 && (!ichdr.count || probe < ichdr.count));
2184 ASSERT(span <= 4 || be32_to_cpu(entry->hashval) == hashval);
2185
2186
2187
2188
2189
2190 while (probe > 0 && be32_to_cpu(entry->hashval) >= hashval) {
2191 entry--;
2192 probe--;
2193 }
2194 while (probe < ichdr.count &&
2195 be32_to_cpu(entry->hashval) < hashval) {
2196 entry++;
2197 probe++;
2198 }
2199 if (probe == ichdr.count || be32_to_cpu(entry->hashval) != hashval) {
2200 args->index = probe;
2201 return -ENOATTR;
2202 }
2203
2204
2205
2206
2207 for (; probe < ichdr.count && (be32_to_cpu(entry->hashval) == hashval);
2208 entry++, probe++) {
2209
2210
2211
2212
2213
2214
2215
2216 if ((args->flags & XFS_ATTR_INCOMPLETE) !=
2217 (entry->flags & XFS_ATTR_INCOMPLETE)) {
2218 continue;
2219 }
2220 if (entry->flags & XFS_ATTR_LOCAL) {
2221 name_loc = xfs_attr3_leaf_name_local(leaf, probe);
2222 if (name_loc->namelen != args->namelen)
2223 continue;
2224 if (memcmp(args->name, name_loc->nameval,
2225 args->namelen) != 0)
2226 continue;
2227 if (!xfs_attr_namesp_match(args->flags, entry->flags))
2228 continue;
2229 args->index = probe;
2230 return -EEXIST;
2231 } else {
2232 name_rmt = xfs_attr3_leaf_name_remote(leaf, probe);
2233 if (name_rmt->namelen != args->namelen)
2234 continue;
2235 if (memcmp(args->name, name_rmt->name,
2236 args->namelen) != 0)
2237 continue;
2238 if (!xfs_attr_namesp_match(args->flags, entry->flags))
2239 continue;
2240 args->index = probe;
2241 args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen);
2242 args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
2243 args->rmtblkcnt = xfs_attr3_rmt_blocks(
2244 args->dp->i_mount,
2245 args->rmtvaluelen);
2246 return -EEXIST;
2247 }
2248 }
2249 args->index = probe;
2250 return -ENOATTR;
2251}
2252
2253
2254
2255
2256
2257int
2258xfs_attr3_leaf_getvalue(
2259 struct xfs_buf *bp,
2260 struct xfs_da_args *args)
2261{
2262 struct xfs_attr_leafblock *leaf;
2263 struct xfs_attr3_icleaf_hdr ichdr;
2264 struct xfs_attr_leaf_entry *entry;
2265 struct xfs_attr_leaf_name_local *name_loc;
2266 struct xfs_attr_leaf_name_remote *name_rmt;
2267 int valuelen;
2268
2269 leaf = bp->b_addr;
2270 xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
2271 ASSERT(ichdr.count < args->geo->blksize / 8);
2272 ASSERT(args->index < ichdr.count);
2273
2274 entry = &xfs_attr3_leaf_entryp(leaf)[args->index];
2275 if (entry->flags & XFS_ATTR_LOCAL) {
2276 name_loc = xfs_attr3_leaf_name_local(leaf, args->index);
2277 ASSERT(name_loc->namelen == args->namelen);
2278 ASSERT(memcmp(args->name, name_loc->nameval, args->namelen) == 0);
2279 valuelen = be16_to_cpu(name_loc->valuelen);
2280 if (args->flags & ATTR_KERNOVAL) {
2281 args->valuelen = valuelen;
2282 return 0;
2283 }
2284 if (args->valuelen < valuelen) {
2285 args->valuelen = valuelen;
2286 return -ERANGE;
2287 }
2288 args->valuelen = valuelen;
2289 memcpy(args->value, &name_loc->nameval[args->namelen], valuelen);
2290 } else {
2291 name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index);
2292 ASSERT(name_rmt->namelen == args->namelen);
2293 ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0);
2294 args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen);
2295 args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
2296 args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount,
2297 args->rmtvaluelen);
2298 if (args->flags & ATTR_KERNOVAL) {
2299 args->valuelen = args->rmtvaluelen;
2300 return 0;
2301 }
2302 if (args->valuelen < args->rmtvaluelen) {
2303 args->valuelen = args->rmtvaluelen;
2304 return -ERANGE;
2305 }
2306 args->valuelen = args->rmtvaluelen;
2307 }
2308 return 0;
2309}
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320STATIC void
2321xfs_attr3_leaf_moveents(
2322 struct xfs_da_args *args,
2323 struct xfs_attr_leafblock *leaf_s,
2324 struct xfs_attr3_icleaf_hdr *ichdr_s,
2325 int start_s,
2326 struct xfs_attr_leafblock *leaf_d,
2327 struct xfs_attr3_icleaf_hdr *ichdr_d,
2328 int start_d,
2329 int count)
2330{
2331 struct xfs_attr_leaf_entry *entry_s;
2332 struct xfs_attr_leaf_entry *entry_d;
2333 int desti;
2334 int tmp;
2335 int i;
2336
2337
2338
2339
2340 if (count == 0)
2341 return;
2342
2343
2344
2345
2346 ASSERT(ichdr_s->magic == XFS_ATTR_LEAF_MAGIC ||
2347 ichdr_s->magic == XFS_ATTR3_LEAF_MAGIC);
2348 ASSERT(ichdr_s->magic == ichdr_d->magic);
2349 ASSERT(ichdr_s->count > 0 && ichdr_s->count < args->geo->blksize / 8);
2350 ASSERT(ichdr_s->firstused >= (ichdr_s->count * sizeof(*entry_s))
2351 + xfs_attr3_leaf_hdr_size(leaf_s));
2352 ASSERT(ichdr_d->count < args->geo->blksize / 8);
2353 ASSERT(ichdr_d->firstused >= (ichdr_d->count * sizeof(*entry_d))
2354 + xfs_attr3_leaf_hdr_size(leaf_d));
2355
2356 ASSERT(start_s < ichdr_s->count);
2357 ASSERT(start_d <= ichdr_d->count);
2358 ASSERT(count <= ichdr_s->count);
2359
2360
2361
2362
2363
2364 if (start_d < ichdr_d->count) {
2365 tmp = ichdr_d->count - start_d;
2366 tmp *= sizeof(xfs_attr_leaf_entry_t);
2367 entry_s = &xfs_attr3_leaf_entryp(leaf_d)[start_d];
2368 entry_d = &xfs_attr3_leaf_entryp(leaf_d)[start_d + count];
2369 memmove(entry_d, entry_s, tmp);
2370 }
2371
2372
2373
2374
2375
2376 entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s];
2377 entry_d = &xfs_attr3_leaf_entryp(leaf_d)[start_d];
2378 desti = start_d;
2379 for (i = 0; i < count; entry_s++, entry_d++, desti++, i++) {
2380 ASSERT(be16_to_cpu(entry_s->nameidx) >= ichdr_s->firstused);
2381 tmp = xfs_attr_leaf_entsize(leaf_s, start_s + i);
2382#ifdef GROT
2383
2384
2385
2386
2387
2388 if (entry_s->flags & XFS_ATTR_INCOMPLETE) {
2389 memset(xfs_attr3_leaf_name(leaf_s, start_s + i), 0, tmp);
2390 ichdr_s->usedbytes -= tmp;
2391 ichdr_s->count -= 1;
2392 entry_d--;
2393 desti--;
2394 if ((start_s + i) < offset)
2395 result++;
2396 } else {
2397#endif
2398 ichdr_d->firstused -= tmp;
2399
2400 entry_d->hashval = entry_s->hashval;
2401 entry_d->nameidx = cpu_to_be16(ichdr_d->firstused);
2402 entry_d->flags = entry_s->flags;
2403 ASSERT(be16_to_cpu(entry_d->nameidx) + tmp
2404 <= args->geo->blksize);
2405 memmove(xfs_attr3_leaf_name(leaf_d, desti),
2406 xfs_attr3_leaf_name(leaf_s, start_s + i), tmp);
2407 ASSERT(be16_to_cpu(entry_s->nameidx) + tmp
2408 <= args->geo->blksize);
2409 memset(xfs_attr3_leaf_name(leaf_s, start_s + i), 0, tmp);
2410 ichdr_s->usedbytes -= tmp;
2411 ichdr_d->usedbytes += tmp;
2412 ichdr_s->count -= 1;
2413 ichdr_d->count += 1;
2414 tmp = ichdr_d->count * sizeof(xfs_attr_leaf_entry_t)
2415 + xfs_attr3_leaf_hdr_size(leaf_d);
2416 ASSERT(ichdr_d->firstused >= tmp);
2417#ifdef GROT
2418 }
2419#endif
2420 }
2421
2422
2423
2424
2425 if (start_s == ichdr_s->count) {
2426 tmp = count * sizeof(xfs_attr_leaf_entry_t);
2427 entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s];
2428 ASSERT(((char *)entry_s + tmp) <=
2429 ((char *)leaf_s + args->geo->blksize));
2430 memset(entry_s, 0, tmp);
2431 } else {
2432
2433
2434
2435
2436 tmp = (ichdr_s->count - count) * sizeof(xfs_attr_leaf_entry_t);
2437 entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s + count];
2438 entry_d = &xfs_attr3_leaf_entryp(leaf_s)[start_s];
2439 memmove(entry_d, entry_s, tmp);
2440
2441 tmp = count * sizeof(xfs_attr_leaf_entry_t);
2442 entry_s = &xfs_attr3_leaf_entryp(leaf_s)[ichdr_s->count];
2443 ASSERT(((char *)entry_s + tmp) <=
2444 ((char *)leaf_s + args->geo->blksize));
2445 memset(entry_s, 0, tmp);
2446 }
2447
2448
2449
2450
2451 ichdr_d->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_d);
2452 ichdr_d->freemap[0].base += ichdr_d->count * sizeof(xfs_attr_leaf_entry_t);
2453 ichdr_d->freemap[0].size = ichdr_d->firstused - ichdr_d->freemap[0].base;
2454 ichdr_d->freemap[1].base = 0;
2455 ichdr_d->freemap[2].base = 0;
2456 ichdr_d->freemap[1].size = 0;
2457 ichdr_d->freemap[2].size = 0;
2458 ichdr_s->holes = 1;
2459}
2460
2461
2462
2463
2464xfs_dahash_t
2465xfs_attr_leaf_lasthash(
2466 struct xfs_buf *bp,
2467 int *count)
2468{
2469 struct xfs_attr3_icleaf_hdr ichdr;
2470 struct xfs_attr_leaf_entry *entries;
2471 struct xfs_mount *mp = bp->b_target->bt_mount;
2472
2473 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, bp->b_addr);
2474 entries = xfs_attr3_leaf_entryp(bp->b_addr);
2475 if (count)
2476 *count = ichdr.count;
2477 if (!ichdr.count)
2478 return 0;
2479 return be32_to_cpu(entries[ichdr.count - 1].hashval);
2480}
2481
2482
2483
2484
2485
2486STATIC int
2487xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
2488{
2489 struct xfs_attr_leaf_entry *entries;
2490 xfs_attr_leaf_name_local_t *name_loc;
2491 xfs_attr_leaf_name_remote_t *name_rmt;
2492 int size;
2493
2494 entries = xfs_attr3_leaf_entryp(leaf);
2495 if (entries[index].flags & XFS_ATTR_LOCAL) {
2496 name_loc = xfs_attr3_leaf_name_local(leaf, index);
2497 size = xfs_attr_leaf_entsize_local(name_loc->namelen,
2498 be16_to_cpu(name_loc->valuelen));
2499 } else {
2500 name_rmt = xfs_attr3_leaf_name_remote(leaf, index);
2501 size = xfs_attr_leaf_entsize_remote(name_rmt->namelen);
2502 }
2503 return size;
2504}
2505
2506
2507
2508
2509
2510
2511
2512int
2513xfs_attr_leaf_newentsize(
2514 struct xfs_da_args *args,
2515 int *local)
2516{
2517 int size;
2518
2519 size = xfs_attr_leaf_entsize_local(args->namelen, args->valuelen);
2520 if (size < xfs_attr_leaf_entsize_local_max(args->geo->blksize)) {
2521 if (local)
2522 *local = 1;
2523 return size;
2524 }
2525 if (local)
2526 *local = 0;
2527 return xfs_attr_leaf_entsize_remote(args->namelen);
2528}
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538int
2539xfs_attr3_leaf_clearflag(
2540 struct xfs_da_args *args)
2541{
2542 struct xfs_attr_leafblock *leaf;
2543 struct xfs_attr_leaf_entry *entry;
2544 struct xfs_attr_leaf_name_remote *name_rmt;
2545 struct xfs_buf *bp;
2546 int error;
2547#ifdef DEBUG
2548 struct xfs_attr3_icleaf_hdr ichdr;
2549 xfs_attr_leaf_name_local_t *name_loc;
2550 int namelen;
2551 char *name;
2552#endif
2553
2554 trace_xfs_attr_leaf_clearflag(args);
2555
2556
2557
2558 error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
2559 if (error)
2560 return error;
2561
2562 leaf = bp->b_addr;
2563 entry = &xfs_attr3_leaf_entryp(leaf)[args->index];
2564 ASSERT(entry->flags & XFS_ATTR_INCOMPLETE);
2565
2566#ifdef DEBUG
2567 xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
2568 ASSERT(args->index < ichdr.count);
2569 ASSERT(args->index >= 0);
2570
2571 if (entry->flags & XFS_ATTR_LOCAL) {
2572 name_loc = xfs_attr3_leaf_name_local(leaf, args->index);
2573 namelen = name_loc->namelen;
2574 name = (char *)name_loc->nameval;
2575 } else {
2576 name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index);
2577 namelen = name_rmt->namelen;
2578 name = (char *)name_rmt->name;
2579 }
2580 ASSERT(be32_to_cpu(entry->hashval) == args->hashval);
2581 ASSERT(namelen == args->namelen);
2582 ASSERT(memcmp(name, args->name, namelen) == 0);
2583#endif
2584
2585 entry->flags &= ~XFS_ATTR_INCOMPLETE;
2586 xfs_trans_log_buf(args->trans, bp,
2587 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
2588
2589 if (args->rmtblkno) {
2590 ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0);
2591 name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index);
2592 name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
2593 name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen);
2594 xfs_trans_log_buf(args->trans, bp,
2595 XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
2596 }
2597
2598
2599
2600
2601 return xfs_trans_roll(&args->trans, args->dp);
2602}
2603
2604
2605
2606
2607int
2608xfs_attr3_leaf_setflag(
2609 struct xfs_da_args *args)
2610{
2611 struct xfs_attr_leafblock *leaf;
2612 struct xfs_attr_leaf_entry *entry;
2613 struct xfs_attr_leaf_name_remote *name_rmt;
2614 struct xfs_buf *bp;
2615 int error;
2616#ifdef DEBUG
2617 struct xfs_attr3_icleaf_hdr ichdr;
2618#endif
2619
2620 trace_xfs_attr_leaf_setflag(args);
2621
2622
2623
2624
2625 error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
2626 if (error)
2627 return error;
2628
2629 leaf = bp->b_addr;
2630#ifdef DEBUG
2631 xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
2632 ASSERT(args->index < ichdr.count);
2633 ASSERT(args->index >= 0);
2634#endif
2635 entry = &xfs_attr3_leaf_entryp(leaf)[args->index];
2636
2637 ASSERT((entry->flags & XFS_ATTR_INCOMPLETE) == 0);
2638 entry->flags |= XFS_ATTR_INCOMPLETE;
2639 xfs_trans_log_buf(args->trans, bp,
2640 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
2641 if ((entry->flags & XFS_ATTR_LOCAL) == 0) {
2642 name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index);
2643 name_rmt->valueblk = 0;
2644 name_rmt->valuelen = 0;
2645 xfs_trans_log_buf(args->trans, bp,
2646 XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
2647 }
2648
2649
2650
2651
2652 return xfs_trans_roll(&args->trans, args->dp);
2653}
2654
2655
2656
2657
2658
2659
2660
2661
2662int
2663xfs_attr3_leaf_flipflags(
2664 struct xfs_da_args *args)
2665{
2666 struct xfs_attr_leafblock *leaf1;
2667 struct xfs_attr_leafblock *leaf2;
2668 struct xfs_attr_leaf_entry *entry1;
2669 struct xfs_attr_leaf_entry *entry2;
2670 struct xfs_attr_leaf_name_remote *name_rmt;
2671 struct xfs_buf *bp1;
2672 struct xfs_buf *bp2;
2673 int error;
2674#ifdef DEBUG
2675 struct xfs_attr3_icleaf_hdr ichdr1;
2676 struct xfs_attr3_icleaf_hdr ichdr2;
2677 xfs_attr_leaf_name_local_t *name_loc;
2678 int namelen1, namelen2;
2679 char *name1, *name2;
2680#endif
2681
2682 trace_xfs_attr_leaf_flipflags(args);
2683
2684
2685
2686
2687 error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp1);
2688 if (error)
2689 return error;
2690
2691
2692
2693
2694 if (args->blkno2 != args->blkno) {
2695 error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno2,
2696 -1, &bp2);
2697 if (error)
2698 return error;
2699 } else {
2700 bp2 = bp1;
2701 }
2702
2703 leaf1 = bp1->b_addr;
2704 entry1 = &xfs_attr3_leaf_entryp(leaf1)[args->index];
2705
2706 leaf2 = bp2->b_addr;
2707 entry2 = &xfs_attr3_leaf_entryp(leaf2)[args->index2];
2708
2709#ifdef DEBUG
2710 xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr1, leaf1);
2711 ASSERT(args->index < ichdr1.count);
2712 ASSERT(args->index >= 0);
2713
2714 xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr2, leaf2);
2715 ASSERT(args->index2 < ichdr2.count);
2716 ASSERT(args->index2 >= 0);
2717
2718 if (entry1->flags & XFS_ATTR_LOCAL) {
2719 name_loc = xfs_attr3_leaf_name_local(leaf1, args->index);
2720 namelen1 = name_loc->namelen;
2721 name1 = (char *)name_loc->nameval;
2722 } else {
2723 name_rmt = xfs_attr3_leaf_name_remote(leaf1, args->index);
2724 namelen1 = name_rmt->namelen;
2725 name1 = (char *)name_rmt->name;
2726 }
2727 if (entry2->flags & XFS_ATTR_LOCAL) {
2728 name_loc = xfs_attr3_leaf_name_local(leaf2, args->index2);
2729 namelen2 = name_loc->namelen;
2730 name2 = (char *)name_loc->nameval;
2731 } else {
2732 name_rmt = xfs_attr3_leaf_name_remote(leaf2, args->index2);
2733 namelen2 = name_rmt->namelen;
2734 name2 = (char *)name_rmt->name;
2735 }
2736 ASSERT(be32_to_cpu(entry1->hashval) == be32_to_cpu(entry2->hashval));
2737 ASSERT(namelen1 == namelen2);
2738 ASSERT(memcmp(name1, name2, namelen1) == 0);
2739#endif
2740
2741 ASSERT(entry1->flags & XFS_ATTR_INCOMPLETE);
2742 ASSERT((entry2->flags & XFS_ATTR_INCOMPLETE) == 0);
2743
2744 entry1->flags &= ~XFS_ATTR_INCOMPLETE;
2745 xfs_trans_log_buf(args->trans, bp1,
2746 XFS_DA_LOGRANGE(leaf1, entry1, sizeof(*entry1)));
2747 if (args->rmtblkno) {
2748 ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0);
2749 name_rmt = xfs_attr3_leaf_name_remote(leaf1, args->index);
2750 name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
2751 name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen);
2752 xfs_trans_log_buf(args->trans, bp1,
2753 XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt)));
2754 }
2755
2756 entry2->flags |= XFS_ATTR_INCOMPLETE;
2757 xfs_trans_log_buf(args->trans, bp2,
2758 XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2)));
2759 if ((entry2->flags & XFS_ATTR_LOCAL) == 0) {
2760 name_rmt = xfs_attr3_leaf_name_remote(leaf2, args->index2);
2761 name_rmt->valueblk = 0;
2762 name_rmt->valuelen = 0;
2763 xfs_trans_log_buf(args->trans, bp2,
2764 XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt)));
2765 }
2766
2767
2768
2769
2770 error = xfs_trans_roll(&args->trans, args->dp);
2771
2772 return error;
2773}
2774