2 * Copyright (c) 2000-2002,2004-2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "err_protos.h"
22 #include "attr_repair.h"
28 static int xfs_acl_valid(xfs_acl_disk_t
*daclp
);
29 static int xfs_mac_valid(xfs_mac_label_t
*lp
);
33 * For attribute repair, there are 3 formats to worry about. First, is
34 * shortform attributes which reside in the inode. Second is the leaf
35 * form, and lastly the btree. Much of this models after the directory
36 * structure so code resembles the directory repair cases.
37 * For shortform case, if an attribute looks corrupt, it is removed.
38 * If that leaves the shortform down to 0 attributes, it's okay and
39 * will appear to just have a null attribute fork. Some checks are done
40 * for validity of the value field based on what the security needs are.
41 * Calls will be made to xfs_mac_valid or xfs_acl_valid routines if the
42 * security attributes exist. They will be cleared if invalid.
43 * No other values will be checked. The DMF folks do not have current
44 * requirements, but may in the future.
46 * For leaf block attributes, it requires more processing. One sticky
47 * point is that the attributes can be local (within the leaf) or
48 * remote (outside the leaf in other blocks). Thinking of local only
49 * if you get a bad attribute, and want to delete just one, it's a-okay
50 * if it remains large enough to still be a leaf block attribute. Otherwise,
51 * it may have to be converted to shortform. How to convert this and when
52 * is an issue. This call is happening in Phase3. Phase5 will capture empty
53 * blocks, but Phase6 allows you to use the libxfs library which knows
54 * how to handle attributes in the kernel for converting formats. What we
55 * could do is mark an attribute to be cleared now, but in phase6 somehow
56 * have it cleared for real and then the format changed to shortform if
57 * applicable. Since this requires more work than I anticipate can be
58 * accomplished for the next release, we will instead just say any bad
59 * attribute in the leaf block will make the entire attribute fork be
60 * cleared. The simplest way to do that is to ignore the leaf format, and
61 * call clear_dinode_attr to just make a shortform attribute fork with
64 * Another issue with handling repair on leaf attributes is the remote
65 * blocks. To make sure that they look good and are not used multiple times
66 * by the attribute fork, some mechanism to keep track of all them is necessary.
67 * Do this in the future, time permitting. For now, note that there is no
68 * check for remote blocks and their allocations.
70 * For btree formatted attributes, the model can follow directories. That
71 * would mean go down the tree to the leftmost leaf. From there moving down
72 * the links and processing each. They would call back up the tree, to verify
73 * that the tree structure is okay. Any problems will result in the attribute
74 * fork being emptied and put in shortform format.
78 * This routine just checks what security needs are for attribute values
79 * only called when root flag is set, otherwise these names could exist in
80 * in user attribute land without a conflict.
81 * If value is non-zero, then a remote attribute is being passed in
85 valuecheck(char *namevalue
, char *value
, int namelen
, int valuelen
)
87 /* for proper alignment issues, get the structs and memmove the values */
93 if ((strncmp(namevalue
, SGI_ACL_FILE
, SGI_ACL_FILE_SIZE
) == 0) ||
94 (strncmp(namevalue
, SGI_ACL_DEFAULT
,
95 SGI_ACL_DEFAULT_SIZE
) == 0)) {
97 memset(&thisacl
, 0, sizeof(xfs_acl_t
));
98 memmove(&thisacl
, namevalue
+namelen
, valuelen
);
103 if (xfs_acl_valid((xfs_acl_disk_t
*)valuep
) != 0) {
106 _("entry contains illegal value in attribute named SGI_ACL_FILE "
107 "or SGI_ACL_DEFAULT\n"));
109 } else if (strncmp(namevalue
, SGI_MAC_FILE
, SGI_MAC_FILE_SIZE
) == 0) {
111 memset(&macl
, 0, sizeof(xfs_mac_label_t
));
112 memmove(&macl
, namevalue
+namelen
, valuelen
);
117 if (xfs_mac_valid((xfs_mac_label_t
*)valuep
) != 1) { /* 1 is valid */
119 * if sysconf says MAC enabled,
120 * temp = mac_from_text("msenhigh/mintlow", NULL)
121 * copy it to value, update valuelen, totsize
122 * This causes pushing up or down of all following
123 * attributes, forcing a attribute format change!!
128 _("entry contains illegal value in attribute named SGI_MAC_LABEL\n"));
130 } else if (strncmp(namevalue
, SGI_CAP_FILE
, SGI_CAP_FILE_SIZE
) == 0) {
131 if ( valuelen
!= sizeof(xfs_cap_set_t
)) {
134 _("entry contains illegal value in attribute named SGI_CAP_FILE\n"));
143 * this routine validates the attributes in shortform format.
144 * a non-zero return repair value means certain attributes are bogus
145 * and were cleared if possible. Warnings do not generate error conditions
146 * if you cannot modify the structures. repair is set to 1, if anything
150 process_shortform_attr(
155 xfs_attr_shortform_t
*asf
;
156 xfs_attr_sf_entry_t
*currententry
, *nextentry
, *tempentry
;
158 int currentsize
, remainingspace
;
162 asf
= (xfs_attr_shortform_t
*) XFS_DFORK_APTR(dip
);
164 /* Assumption: hdr.totsize is less than a leaf block and was checked
165 * by lclinode for valid sizes. Check the count though.
167 if (asf
->hdr
.count
== 0)
168 /* then the total size should just be the header length */
169 if (be16_to_cpu(asf
->hdr
.totsize
) != sizeof(xfs_attr_sf_hdr_t
)) {
170 /* whoops there's a discrepancy. Clear the hdr */
173 _("there are no attributes in the fork for inode %" PRIu64
"\n"),
176 cpu_to_be16(sizeof(xfs_attr_sf_hdr_t
));
181 _("would junk the attribute fork since count is 0 for inode %" PRIu64
"\n"),
187 currentsize
= sizeof(xfs_attr_sf_hdr_t
);
188 remainingspace
= be16_to_cpu(asf
->hdr
.totsize
) - currentsize
;
189 nextentry
= &asf
->list
[0];
190 for (i
= 0; i
< asf
->hdr
.count
; i
++) {
191 currententry
= nextentry
;
194 /* don't go off the end if the hdr.count was off */
195 if ((currentsize
+ (sizeof(xfs_attr_sf_entry_t
) - 1)) >
196 be16_to_cpu(asf
->hdr
.totsize
))
197 break; /* get out and reset count and totSize */
199 /* if the namelen is 0, can't get to the rest of the entries */
200 if (currententry
->namelen
== 0) {
201 do_warn(_("zero length name entry in attribute fork,"));
204 _(" truncating attributes for inode %" PRIu64
" to %d\n"), ino
, i
);
206 break; /* and then update hdr fields */
209 _(" would truncate attributes for inode %" PRIu64
" to %d\n"), ino
, i
);
213 /* It's okay to have a 0 length valuelen, but do a
214 * rough check to make sure we haven't gone outside of
217 if (remainingspace
< currententry
->namelen
||
218 ((remainingspace
- currententry
->
219 namelen
) < currententry
->valuelen
)) {
221 _("name or value attribute lengths are too large,\n"));
224 _(" truncating attributes for inode %" PRIu64
" to %d\n"),
227 break; /* and then update hdr fields */
230 _(" would truncate attributes for inode %" PRIu64
" to %d\n"),
237 /* namecheck checks for / and null terminated for file names.
238 * attributes names currently follow the same rules.
240 if (namecheck((char *)¤tentry
->nameval
[0],
241 currententry
->namelen
)) {
243 _("entry contains illegal character in shortform attribute name\n"));
247 if (currententry
->flags
& XFS_ATTR_INCOMPLETE
) {
249 _("entry has INCOMPLETE flag on in shortform attribute\n"));
253 /* Only check values for root security attributes */
254 if (currententry
->flags
& XFS_ATTR_ROOT
)
255 junkit
= valuecheck((char *)¤tentry
->nameval
[0],
256 NULL
, currententry
->namelen
,
257 currententry
->valuelen
);
259 remainingspace
= remainingspace
-
260 XFS_ATTR_SF_ENTSIZE(currententry
);
264 /* get rid of only this entry */
266 _("removing attribute entry %d for inode %" PRIu64
"\n"),
268 tempentry
= (xfs_attr_sf_entry_t
*)
269 ((__psint_t
) currententry
+
270 XFS_ATTR_SF_ENTSIZE(currententry
));
271 memmove(currententry
,tempentry
,remainingspace
);
273 i
--; /* no worries, it will wrap back to 0 */
275 continue; /* go back up now */
278 _("would remove attribute entry %d for inode %" PRIu64
"\n"),
283 /* Let's get ready for the next entry... */
284 nextentry
= (xfs_attr_sf_entry_t
*)((__psint_t
) nextentry
+
285 XFS_ATTR_SF_ENTSIZE(currententry
));
286 currentsize
= currentsize
+ XFS_ATTR_SF_ENTSIZE(currententry
);
290 if (asf
->hdr
.count
!= i
) {
293 _("would have corrected attribute entry count in inode %" PRIu64
" from %d to %d\n"),
294 ino
, asf
->hdr
.count
, i
);
297 _("corrected attribute entry count in inode %" PRIu64
", was %d, now %d\n"),
298 ino
, asf
->hdr
.count
, i
);
304 /* ASSUMPTION: currentsize <= totsize */
305 if (be16_to_cpu(asf
->hdr
.totsize
) != currentsize
) {
308 _("would have corrected attribute totsize in inode %" PRIu64
" from %d to %d\n"),
309 ino
, be16_to_cpu(asf
->hdr
.totsize
),
313 _("corrected attribute entry totsize in inode %" PRIu64
", was %d, now %d\n"),
314 ino
, be16_to_cpu(asf
->hdr
.totsize
),
316 asf
->hdr
.totsize
= cpu_to_be16(currentsize
);
324 /* This routine brings in blocks from disk one by one and assembles them
325 * in the value buffer. If get_bmapi gets smarter later to return an extent
326 * or list of extents, that would be great. For now, we don't expect too
327 * many blocks per remote value, so one by one is sufficient.
330 rmtval_get(xfs_mount_t
*mp
, xfs_ino_t ino
, blkmap_t
*blkmap
,
331 xfs_dablk_t blocknum
, int valuelen
, char* value
)
335 int clearit
= 0, i
= 0, length
= 0, amountdone
= 0;
337 /* ASSUMPTION: valuelen is a valid number, so use it for looping */
338 /* Note that valuelen is not a multiple of blocksize */
339 while (amountdone
< valuelen
) {
340 bno
= blkmap_get(blkmap
, blocknum
+ i
);
341 if (bno
== NULLDFSBNO
) {
343 _("remote block for attributes of inode %" PRIu64
" is missing\n"), ino
);
347 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, bno
),
348 XFS_FSB_TO_BB(mp
, 1), 0);
351 _("can't read remote block for attributes of inode %" PRIu64
"\n"), ino
);
355 ASSERT(mp
->m_sb
.sb_blocksize
== XFS_BUF_COUNT(bp
));
356 length
= MIN(XFS_BUF_COUNT(bp
), valuelen
- amountdone
);
357 memmove(value
, XFS_BUF_PTR(bp
), length
);
358 amountdone
+= length
;
367 * freespace map for directory and attribute leaf blocks (1 bit per byte)
368 * 1 == used, 0 == free
370 size_t ts_attr_freemap_size
= sizeof(da_freemap_t
) * DA_BMAP_SIZE
;
372 /* The block is read in. The magic number and forward / backward
373 * links are checked by the caller process_leaf_attr.
374 * If any problems occur the routine returns with non-zero. In
375 * this case the next step is to clear the attribute fork, by
376 * changing it to shortform and zeroing it out. Forkoff need not
381 process_leaf_attr_local(
382 xfs_attr_leafblock_t
*leaf
,
384 xfs_attr_leaf_entry_t
*entry
,
385 xfs_dahash_t last_hashval
,
389 xfs_attr_leaf_name_local_t
*local
;
391 local
= xfs_attr_leaf_name_local(leaf
, i
);
392 if (local
->namelen
== 0 || namecheck((char *)&local
->nameval
[0],
395 _("attribute entry %d in attr block %u, inode %" PRIu64
" has bad name (namelen = %d)\n"),
396 i
, da_bno
, ino
, local
->namelen
);
400 /* Check on the hash value. Checking order of values
401 * is not necessary, since one wrong clears the whole
402 * fork. If the ordering's wrong, it's caught here or
403 * the kernel code has a bug with transaction logging
404 * or attributes itself. Being paranoid, let's check
405 * ordering anyway in case both the name value and the
406 * hashvalue were wrong but matched. Unlikely, however.
408 if (be32_to_cpu(entry
->hashval
) != libxfs_da_hashname(
409 &local
->nameval
[0], local
->namelen
) ||
410 be32_to_cpu(entry
->hashval
) < last_hashval
) {
412 _("bad hashvalue for attribute entry %d in attr block %u, inode %" PRIu64
"\n"),
417 /* Only check values for root security attributes */
418 if (entry
->flags
& XFS_ATTR_ROOT
) {
419 if (valuecheck((char *)&local
->nameval
[0], NULL
,
420 local
->namelen
, be16_to_cpu(local
->valuelen
))) {
422 _("bad security value for attribute entry %d in attr block %u, inode %" PRIu64
"\n"),
427 return xfs_attr_leaf_entsize_local(local
->namelen
,
428 be16_to_cpu(local
->valuelen
));
432 process_leaf_attr_remote(
433 xfs_attr_leafblock_t
*leaf
,
435 xfs_attr_leaf_entry_t
*entry
,
436 xfs_dahash_t last_hashval
,
442 xfs_attr_leaf_name_remote_t
*remotep
;
445 remotep
= xfs_attr_leaf_name_remote(leaf
, i
);
447 if (remotep
->namelen
== 0 || namecheck((char *)&remotep
->name
[0],
449 be32_to_cpu(entry
->hashval
) !=
450 libxfs_da_hashname((uchar_t
*)&remotep
->name
[0],
452 be32_to_cpu(entry
->hashval
) < last_hashval
||
453 be32_to_cpu(remotep
->valueblk
) == 0) {
455 _("inconsistent remote attribute entry %d in attr block %u, ino %" PRIu64
"\n"), i
, da_bno
, ino
);
459 if (!(entry
->flags
& XFS_ATTR_ROOT
))
462 value
= malloc(be32_to_cpu(remotep
->valuelen
));
465 _("cannot malloc enough for remotevalue attribute for inode %" PRIu64
"\n"),
467 do_warn(_("SKIPPING this remote attribute\n"));
470 if (rmtval_get(mp
, ino
, blkmap
, be32_to_cpu(remotep
->valueblk
),
471 be32_to_cpu(remotep
->valuelen
), value
)) {
473 _("remote attribute get failed for entry %d, inode %" PRIu64
"\n"),
477 if (valuecheck((char *)&remotep
->name
[0], value
, remotep
->namelen
,
478 be32_to_cpu(remotep
->valuelen
))) {
480 _("remote attribute value check failed for entry %d, inode %" PRIu64
"\n"),
486 return xfs_attr_leaf_entsize_remote(remotep
->namelen
);
494 process_leaf_attr_block(
496 xfs_attr_leafblock_t
*leaf
,
500 xfs_dahash_t last_hashval
,
501 xfs_dahash_t
*current_hashval
,
504 xfs_attr_leaf_entry_t
*entry
;
505 int i
, start
, stop
, clearit
, usedbs
, firstb
, thissize
;
506 da_freemap_t
*attr_freemap
= ts_attr_freemap();
508 clearit
= usedbs
= 0;
510 firstb
= mp
->m_sb
.sb_blocksize
;
511 stop
= sizeof(xfs_attr_leaf_hdr_t
);
513 /* does the count look sorta valid? */
514 if (be16_to_cpu(leaf
->hdr
.count
) * sizeof(xfs_attr_leaf_entry_t
)
515 + sizeof(xfs_attr_leaf_hdr_t
) > XFS_LBSIZE(mp
)) {
517 _("bad attribute count %d in attr block %u, inode %" PRIu64
"\n"),
518 be16_to_cpu(leaf
->hdr
.count
), da_bno
, ino
);
522 init_da_freemap(attr_freemap
);
523 (void) set_da_freemap(mp
, attr_freemap
, 0, stop
);
525 /* go thru each entry checking for problems */
526 for (i
= 0, entry
= &leaf
->entries
[0];
527 i
< be16_to_cpu(leaf
->hdr
.count
); i
++, entry
++) {
529 /* check if index is within some boundary. */
530 if (be16_to_cpu(entry
->nameidx
) > XFS_LBSIZE(mp
)) {
532 _("bad attribute nameidx %d in attr block %u, inode %" PRIu64
"\n"),
533 be16_to_cpu(entry
->nameidx
), da_bno
, ino
);
538 if (entry
->flags
& XFS_ATTR_INCOMPLETE
) {
539 /* we are inconsistent state. get rid of us */
541 _("attribute entry #%d in attr block %u, inode %" PRIu64
" is INCOMPLETE\n"),
547 /* mark the entry used */
548 start
= (__psint_t
)&leaf
->entries
[i
] - (__psint_t
)leaf
;
549 stop
= start
+ sizeof(xfs_attr_leaf_entry_t
);
550 if (set_da_freemap(mp
, attr_freemap
, start
, stop
)) {
552 _("attribute entry %d in attr block %u, inode %" PRIu64
" claims already used space\n"),
555 break; /* got an overlap */
558 if (entry
->flags
& XFS_ATTR_LOCAL
)
559 thissize
= process_leaf_attr_local(leaf
, i
, entry
,
560 last_hashval
, da_bno
, ino
);
562 thissize
= process_leaf_attr_remote(leaf
, i
, entry
,
563 last_hashval
, da_bno
, ino
,
570 *current_hashval
= last_hashval
= be32_to_cpu(entry
->hashval
);
572 if (set_da_freemap(mp
, attr_freemap
, be16_to_cpu(entry
->nameidx
),
573 be16_to_cpu(entry
->nameidx
) + thissize
)) {
575 _("attribute entry %d in attr block %u, inode %" PRIu64
" claims used space\n"),
578 break; /* got an overlap */
581 if (be16_to_cpu(entry
->nameidx
) < firstb
)
582 firstb
= be16_to_cpu(entry
->nameidx
);
587 /* verify the header information is correct */
589 /* if the holes flag is set, don't reset first_used unless it's
590 * pointing to used bytes. we're being conservative here
591 * since the block will get compacted anyhow by the kernel.
594 if ((leaf
->hdr
.holes
== 0 &&
595 firstb
!= be16_to_cpu(leaf
->hdr
.firstused
)) ||
596 be16_to_cpu(leaf
->hdr
.firstused
) > firstb
) {
599 _("- resetting first used heap value from %d to %d in "
600 "block %u of attribute fork of inode %" PRIu64
"\n"),
601 be16_to_cpu(leaf
->hdr
.firstused
),
602 firstb
, da_bno
, ino
);
603 leaf
->hdr
.firstused
= cpu_to_be16(firstb
);
607 _("- would reset first used value from %d to %d in "
608 "block %u of attribute fork of inode %" PRIu64
"\n"),
609 be16_to_cpu(leaf
->hdr
.firstused
),
610 firstb
, da_bno
, ino
);
614 if (usedbs
!= be16_to_cpu(leaf
->hdr
.usedbytes
)) {
617 _("- resetting usedbytes cnt from %d to %d in "
618 "block %u of attribute fork of inode %" PRIu64
"\n"),
619 be16_to_cpu(leaf
->hdr
.usedbytes
),
620 usedbs
, da_bno
, ino
);
621 leaf
->hdr
.usedbytes
= cpu_to_be16(usedbs
);
625 _("- would reset usedbytes cnt from %d to %d in "
626 "block %u of attribute fork of %" PRIu64
"\n"),
627 be16_to_cpu(leaf
->hdr
.usedbytes
),
628 usedbs
, da_bno
, ino
);
632 /* there's a lot of work in process_leaf_dir_block to go thru
633 * checking for holes and compacting if appropiate. I don't think
634 * attributes need all that, so let's just leave the holes. If
635 * we discover later that this is a good place to do compaction
636 * we can add it then.
639 return (clearit
); /* and repair */
644 * returns 0 if the attribute fork is ok, 1 if it has to be junked.
647 process_leaf_attr_level(xfs_mount_t
*mp
,
648 da_bt_cursor_t
*da_cursor
)
651 xfs_attr_leafblock_t
*leaf
;
654 xfs_dfsbno_t dev_bno
;
656 xfs_dablk_t prev_bno
;
657 xfs_dahash_t current_hashval
= 0;
658 xfs_dahash_t greatest_hashval
;
660 da_bno
= da_cursor
->level
[0].bno
;
661 ino
= da_cursor
->ino
;
666 dev_bno
= blkmap_get(da_cursor
->blkmap
, da_bno
);
668 * 0 is the root block and no block
669 * pointer can point to the root block of the btree
673 if (dev_bno
== NULLDFSBNO
) {
675 _("can't map block %u for attribute fork for inode %" PRIu64
"\n"),
680 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, dev_bno
),
681 XFS_FSB_TO_BB(mp
, 1), 0);
684 _("can't read file block %u (fsbno %" PRIu64
") for attribute fork of inode %" PRIu64
"\n"),
685 da_bno
, dev_bno
, ino
);
689 leaf
= (xfs_attr_leafblock_t
*)XFS_BUF_PTR(bp
);
691 /* check magic number for leaf directory btree block */
692 if (be16_to_cpu(leaf
->hdr
.info
.magic
) != XFS_ATTR_LEAF_MAGIC
) {
694 _("bad attribute leaf magic %#x for inode %" PRIu64
"\n"),
695 leaf
->hdr
.info
.magic
, ino
);
701 * for each block, process the block, verify its path,
702 * then get next block. update cursor values along the way
704 if (process_leaf_attr_block(mp
, leaf
, da_bno
, ino
,
705 da_cursor
->blkmap
, current_hashval
,
706 &greatest_hashval
, &repair
)) {
712 * index can be set to hdr.count so match the
713 * indexes of the interior blocks -- which at the
714 * end of the block will point to 1 after the final
715 * real entry in the block
717 da_cursor
->level
[0].hashval
= greatest_hashval
;
718 da_cursor
->level
[0].bp
= bp
;
719 da_cursor
->level
[0].bno
= da_bno
;
720 da_cursor
->level
[0].index
= be16_to_cpu(leaf
->hdr
.count
);
721 da_cursor
->level
[0].dirty
= repair
;
723 if (be32_to_cpu(leaf
->hdr
.info
.back
) != prev_bno
) {
725 _("bad sibling back pointer for block %u in attribute fork for inode %" PRIu64
"\n"),
732 da_bno
= be32_to_cpu(leaf
->hdr
.info
.forw
);
734 if (da_bno
!= 0 && verify_da_path(mp
, da_cursor
, 0)) {
739 current_hashval
= greatest_hashval
;
741 if (repair
&& !no_modify
)
742 libxfs_writebuf(bp
, 0);
745 } while (da_bno
!= 0);
747 if (verify_final_da_path(mp
, da_cursor
, 0)) {
749 * verify the final path up (right-hand-side) if still ok
752 _("bad hash path in attribute fork for inode %" PRIu64
"\n"),
757 /* releases all buffers holding interior btree blocks */
758 release_da_cursor(mp
, da_cursor
, 0);
762 /* release all buffers holding interior btree blocks */
763 err_release_da_cursor(mp
, da_cursor
, 0);
769 * a node directory is a true btree -- where the attribute fork
770 * has gotten big enough that it is represented as a non-trivial (e.g.
771 * has more than just a block) btree.
773 * Note that if we run into any problems, we will trash the attribute fork.
775 * returns 0 if things are ok, 1 if bad
776 * Note this code has been based off process_node_dir.
787 da_bt_cursor_t da_cursor
;
790 * try again -- traverse down left-side of tree until we hit
791 * the left-most leaf block setting up the btree cursor along
792 * the way. Then walk the leaf blocks left-to-right, calling
793 * a parent-verification routine each time we traverse a block.
795 memset(&da_cursor
, 0, sizeof(da_bt_cursor_t
));
796 da_cursor
.active
= 0;
800 da_cursor
.greatest_bno
= 0;
801 da_cursor
.blkmap
= blkmap
;
804 * now process interior node. don't have any buffers held in this path.
806 error
= traverse_int_dablock(mp
, &da_cursor
, &bno
, XFS_ATTR_FORK
);
808 return(1); /* 0 means unsuccessful */
811 * now pass cursor and bno into leaf-block processing routine
812 * the leaf dir level routine checks the interior paths
813 * up to the root including the final right-most path.
816 return (process_leaf_attr_level(mp
, &da_cursor
));
820 * Start processing for a leaf or fuller btree.
821 * A leaf directory is one where the attribute fork is too big for
822 * the inode but is small enough to fit into one btree block
823 * outside the inode. This code is modelled after process_leaf_dir_block.
825 * returns 0 if things are ok, 1 if bad (attributes needs to be junked)
826 * repair is set, if anything was changed, but attributes can live thru it
830 process_longform_attr(
835 int *repair
) /* out - 1 if something was fixed */
837 xfs_attr_leafblock_t
*leaf
;
840 xfs_dahash_t next_hashval
;
845 bno
= blkmap_get(blkmap
, 0);
847 if ( bno
== NULLDFSBNO
) {
848 if (dip
->di_aformat
== XFS_DINODE_FMT_EXTENTS
&&
849 be16_to_cpu(dip
->di_anextents
) == 0)
850 return(0); /* the kernel can handle this state */
852 _("block 0 of inode %" PRIu64
" attribute fork is missing\n"),
856 /* FIX FOR bug 653709 -- EKN */
857 if (mp
->m_sb
.sb_agcount
< XFS_FSB_TO_AGNO(mp
, bno
)) {
859 _("agno of attribute fork of inode %" PRIu64
" out of regular partition\n"), ino
);
863 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, bno
),
864 XFS_FSB_TO_BB(mp
, 1), 0);
867 _("can't read block 0 of inode %" PRIu64
" attribute fork\n"),
872 /* verify leaf block */
873 leaf
= (xfs_attr_leafblock_t
*)XFS_BUF_PTR(bp
);
875 /* check sibling pointers in leaf block or root block 0 before
876 * we have to release the btree block
878 if (be32_to_cpu(leaf
->hdr
.info
.forw
) != 0 ||
879 be32_to_cpu(leaf
->hdr
.info
.back
) != 0) {
882 _("clearing forw/back pointers in block 0 for attributes in inode %" PRIu64
"\n"),
885 leaf
->hdr
.info
.forw
= cpu_to_be32(0);
886 leaf
->hdr
.info
.back
= cpu_to_be32(0);
889 _("would clear forw/back pointers in block 0 for attributes in inode %" PRIu64
"\n"), ino
);
894 * use magic number to tell us what type of attribute this is.
895 * it's possible to have a node or leaf attribute in either an
896 * extent format or btree format attribute fork.
898 switch (be16_to_cpu(leaf
->hdr
.info
.magic
)) {
899 case XFS_ATTR_LEAF_MAGIC
: /* leaf-form attribute */
900 if (process_leaf_attr_block(mp
, leaf
, 0, ino
, blkmap
,
901 0, &next_hashval
, repair
)) {
902 /* the block is bad. lose the attribute fork. */
906 *repair
= *repair
|| repairlinks
;
909 case XFS_DA_NODE_MAGIC
: /* btree-form attribute */
910 /* must do this now, to release block 0 before the traversal */
913 libxfs_writebuf(bp
, 0);
916 return (process_node_attr(mp
, ino
, dip
, blkmap
)); /* + repair */
919 _("bad attribute leaf magic # %#x for dir ino %" PRIu64
"\n"),
920 be16_to_cpu(leaf
->hdr
.info
.magic
), ino
);
925 if (*repair
&& !no_modify
)
926 libxfs_writebuf(bp
, 0);
930 return(0); /* repair may be set */
935 xfs_acl_from_disk(struct xfs_acl
**aclp
, struct xfs_acl_disk
*dacl
)
939 xfs_acl_entry_t
*ace
;
940 xfs_acl_entry_disk_t
*dace
, *end
;
942 count
= be32_to_cpu(dacl
->acl_cnt
);
943 if (count
> XFS_ACL_MAX_ENTRIES
) {
944 do_warn(_("Too many ACL entries, count %d\n"), count
);
950 end
= &dacl
->acl_entry
[0] + count
;
951 acl
= malloc((int)((char *)end
- (char *)dacl
));
953 do_warn(_("cannot malloc enough for ACL attribute\n"));
954 do_warn(_("SKIPPING this ACL\n"));
959 acl
->acl_cnt
= count
;
960 ace
= &acl
->acl_entry
[0];
961 for (dace
= &dacl
->acl_entry
[0]; dace
< end
; ace
++, dace
++) {
962 ace
->ae_tag
= be32_to_cpu(dace
->ae_tag
);
963 ace
->ae_id
= be32_to_cpu(dace
->ae_id
);
964 ace
->ae_perm
= be16_to_cpu(dace
->ae_perm
);
972 * returns 1 if attributes got cleared
973 * and 0 if things are ok.
981 int *repair
) /* returned if we did repair */
984 __u8 aformat
= dip
->di_aformat
;
985 xfs_attr_shortform_t
*asf
;
987 asf
= (xfs_attr_shortform_t
*) XFS_DFORK_APTR(dip
);
989 if (aformat
== XFS_DINODE_FMT_LOCAL
) {
990 ASSERT(be16_to_cpu(asf
->hdr
.totsize
) <=
991 XFS_DFORK_ASIZE(dip
, mp
));
992 err
= process_shortform_attr(ino
, dip
, repair
);
993 } else if (aformat
== XFS_DINODE_FMT_EXTENTS
||
994 aformat
== XFS_DINODE_FMT_BTREE
) {
995 err
= process_longform_attr(mp
, ino
, dip
, blkmap
,
997 /* if err, convert this to shortform and clear it */
998 /* if repair and no error, it's taken care of */
1000 do_warn(_("illegal attribute format %d, ino %" PRIu64
"\n"),
1004 return (err
); /* and repair */
1011 xfs_acl_valid(xfs_acl_disk_t
*daclp
)
1014 xfs_acl_entry_t
*entry
, *e
;
1015 int user
= 0, group
= 0, other
= 0, mask
= 0, mask_required
= 0;
1021 switch (xfs_acl_from_disk(&aclp
, daclp
)) {
1030 for (i
= 0; i
< aclp
->acl_cnt
; i
++) {
1031 entry
= &aclp
->acl_entry
[i
];
1032 if (entry
->ae_perm
& ~(ACL_READ
|ACL_WRITE
|ACL_EXECUTE
))
1034 switch (entry
->ae_tag
) {
1049 for (j
= i
+ 1; j
< aclp
->acl_cnt
; j
++) {
1050 e
= &aclp
->acl_entry
[j
];
1051 if (e
->ae_id
== entry
->ae_id
&&
1052 e
->ae_tag
== entry
->ae_tag
)
1065 if (!user
|| !group
|| !other
|| (mask_required
&& !mask
))
1076 * Check a category or division set to ensure that all values are in
1077 * ascending order and each division or category appears only once.
1080 __check_setvalue(const unsigned short *list
, unsigned short count
)
1084 for (i
= 1; i
< count
; i
++)
1085 if (list
[i
] <= list
[i
-1])
1092 * Check the validity of a MAC label.
1095 xfs_mac_valid(xfs_mac_label_t
*lp
)
1101 * if the total category set and division set is greater than 250
1104 if ((lp
->ml_catcount
+ lp
->ml_divcount
) > XFS_MAC_MAX_SETS
)
1108 * check whether the msentype value is valid, and do they have
1109 * appropriate level, category association.
1111 switch (lp
->ml_msen_type
) {
1112 case XFS_MSEN_ADMIN_LABEL
:
1113 case XFS_MSEN_EQUAL_LABEL
:
1114 case XFS_MSEN_HIGH_LABEL
:
1115 case XFS_MSEN_MLD_HIGH_LABEL
:
1116 case XFS_MSEN_LOW_LABEL
:
1117 case XFS_MSEN_MLD_LOW_LABEL
:
1118 if (lp
->ml_level
!= 0 || lp
->ml_catcount
> 0 )
1121 case XFS_MSEN_TCSEC_LABEL
:
1122 case XFS_MSEN_MLD_LABEL
:
1123 if (lp
->ml_catcount
> 0 &&
1124 __check_setvalue(lp
->ml_list
,
1125 lp
->ml_catcount
) == -1)
1128 case XFS_MSEN_UNKNOWN_LABEL
:
1134 * check whether the minttype value is valid, and do they have
1135 * appropriate grade, division association.
1137 switch (lp
->ml_mint_type
) {
1138 case XFS_MINT_BIBA_LABEL
:
1139 if (lp
->ml_divcount
> 0 &&
1140 __check_setvalue(lp
->ml_list
+ lp
->ml_catcount
,
1141 lp
->ml_divcount
) == -1)
1144 case XFS_MINT_EQUAL_LABEL
:
1145 case XFS_MINT_HIGH_LABEL
:
1146 case XFS_MINT_LOW_LABEL
:
1147 if (lp
->ml_grade
!= 0 || lp
->ml_divcount
> 0 )