2 * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
38 #include "err_protos.h"
39 #include "attr_repair.h"
44 static int xfs_acl_valid(xfs_acl_t
*aclp
);
45 static int xfs_mac_valid(xfs_mac_label_t
*lp
);
49 * For attribute repair, there are 3 formats to worry about. First, is
50 * shortform attributes which reside in the inode. Second is the leaf
51 * form, and lastly the btree. Much of this models after the directory
52 * structure so code resembles the directory repair cases.
53 * For shortform case, if an attribute looks corrupt, it is removed.
54 * If that leaves the shortform down to 0 attributes, it's okay and
55 * will appear to just have a null attribute fork. Some checks are done
56 * for validity of the value field based on what the security needs are.
57 * Calls will be made to xfs_mac_valid or xfs_acl_valid routines if the
58 * security attributes exist. They will be cleared if invalid.
59 * No other values will be checked. The DMF folks do not have current
60 * requirements, but may in the future.
62 * For leaf block attributes, it requires more processing. One sticky
63 * point is that the attributes can be local (within the leaf) or
64 * remote (outside the leaf in other blocks). Thinking of local only
65 * if you get a bad attribute, and want to delete just one, its a-okay
66 * if it remains large enough to still be a leaf block attribute. Otherwise,
67 * it may have to be converted to shortform. How to convert this and when
68 * is an issue. This call is happening in Phase3. Phase5 will capture empty
69 * blocks, but Phase6 allows you to use the simulation library which knows
70 * how to handle attributes in the kernel for converting formats. What we
71 * could do is mark an attribute to be cleared now, but in phase6 somehow
72 * have it cleared for real and then the format changed to shortform if
73 * applicable. Since this requires more work than I anticipate can be
74 * accomplished for the next release, we will instead just say any bad
75 * attribute in the leaf block will make the entire attribute fork be
76 * cleared. The simplest way to do that is to ignore the leaf format, and
77 * call clear_dinode_attr to just make a shortform attribute fork with
80 * Another issue with handling repair on leaf attributes is the remote
81 * blocks. To make sure that they look good and are not used multiple times
82 * by the attribute fork, some mechanism to keep track of all them is necessary.
83 * Do this in the future, time permitting. For now, note that there is no
84 * check for remote blocks and their allocations.
86 * For btree formatted attributes, the model can follow directories. That
87 * would mean go down the tree to the leftmost leaf. From there moving down
88 * the links and processing each. They would call back up the tree, to verify
89 * that the tree structure is okay. Any problems will result in the attribute
90 * fork being emptied and put in shortform format.
94 * This routine just checks what security needs are for attribute values
95 * only called when root flag is set, otherwise these names could exist in
96 * in user attribute land without a conflict.
97 * If value is non-zero, then a remote attribute is being passed in
101 valuecheck(char *namevalue
, char *value
, int namelen
, int valuelen
)
103 /* for proper alignment issues, get the structs and bcopy the values */
104 xfs_mac_label_t macl
;
109 if ((strncmp(namevalue
, SGI_ACL_FILE
, SGI_ACL_FILE_SIZE
) == 0) ||
110 (strncmp(namevalue
, SGI_ACL_DEFAULT
,
111 SGI_ACL_DEFAULT_SIZE
) == 0)) {
113 bzero(&thisacl
, sizeof(xfs_acl_t
));
114 bcopy(namevalue
+namelen
, &thisacl
, valuelen
);
119 if (xfs_acl_valid((xfs_acl_t
*) valuep
) != 0) { /* 0 is valid */
122 _("entry contains illegal value in attribute named SGI_ACL_FILE "
123 "or SGI_ACL_DEFAULT\n"));
125 } else if (strncmp(namevalue
, SGI_MAC_FILE
, SGI_MAC_FILE_SIZE
) == 0) {
127 bzero(&macl
, sizeof(xfs_mac_label_t
));
128 bcopy(namevalue
+namelen
, &macl
, valuelen
);
133 if (xfs_mac_valid((xfs_mac_label_t
*)valuep
) != 1) { /* 1 is valid */
135 * if sysconf says MAC enabled,
136 * temp = mac_from_text("msenhigh/mintlow", NULL)
137 * copy it to value, update valuelen, totsize
138 * This causes pushing up or down of all following
139 * attributes, forcing a attribute format change!!
144 _("entry contains illegal value in attribute named SGI_MAC_LABEL\n"));
146 } else if (strncmp(namevalue
, SGI_CAP_FILE
, SGI_CAP_FILE_SIZE
) == 0) {
147 if ( valuelen
!= sizeof(xfs_cap_set_t
)) {
150 _("entry contains illegal value in attribute named SGI_CAP_FILE\n"));
159 * this routine validates the attributes in shortform format.
160 * a non-zero return repair value means certain attributes are bogus
161 * and were cleared if possible. Warnings do not generate error conditions
162 * if you cannot modify the structures. repair is set to 1, if anything
166 process_shortform_attr(
171 xfs_attr_shortform_t
*asf
;
172 xfs_attr_sf_entry_t
*currententry
, *nextentry
, *tempentry
;
174 int currentsize
, remainingspace
;
178 asf
= (xfs_attr_shortform_t
*) XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
);
180 /* Assumption: hdr.totsize is less than a leaf block and was checked
181 * by lclinode for valid sizes. Check the count though.
183 if (INT_GET(asf
->hdr
.count
, ARCH_CONVERT
) == 0)
184 /* then the total size should just be the header length */
185 if (INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) != sizeof(xfs_attr_sf_hdr_t
)) {
186 /* whoops there's a discrepancy. Clear the hdr */
189 _("there are no attributes in the fork for inode %llu\n"),
191 INT_SET(asf
->hdr
.totsize
, ARCH_CONVERT
,
192 sizeof(xfs_attr_sf_hdr_t
));
197 _("would junk the attribute fork since count is 0 for inode %llu\n"),
203 currentsize
= sizeof(xfs_attr_sf_hdr_t
);
204 remainingspace
= INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) - currentsize
;
205 nextentry
= &asf
->list
[0];
206 for (i
= 0; i
< INT_GET(asf
->hdr
.count
, ARCH_CONVERT
); i
++) {
207 currententry
= nextentry
;
210 /* don't go off the end if the hdr.count was off */
211 if ((currentsize
+ (sizeof(xfs_attr_sf_entry_t
) - 1)) >
212 INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
))
213 break; /* get out and reset count and totSize */
215 /* if the namelen is 0, can't get to the rest of the entries */
216 if (INT_GET(currententry
->namelen
, ARCH_CONVERT
) == 0) {
217 do_warn(_("zero length name entry in attribute fork,"));
220 _(" truncating attributes for inode %llu to %d\n"), ino
, i
);
222 break; /* and then update hdr fields */
225 _(" would truncate attributes for inode %llu to %d\n"), ino
, i
);
229 /* It's okay to have a 0 length valuelen, but do a
230 * rough check to make sure we haven't gone outside of
233 if ((remainingspace
<
234 INT_GET(currententry
->namelen
, ARCH_CONVERT
)) ||
236 INT_GET(currententry
->namelen
, ARCH_CONVERT
)) <
237 INT_GET(currententry
->valuelen
, ARCH_CONVERT
))) {
239 _("name or value attribute lengths are too large,\n"));
242 _(" truncating attributes for inode %llu to %d\n"),
245 break; /* and then update hdr fields */
248 _(" would truncate attributes for inode %llu to %d\n"),
255 /* namecheck checks for / and null terminated for file names.
256 * attributes names currently follow the same rules.
258 if (namecheck((char *)¤tentry
->nameval
[0],
259 INT_GET(currententry
->namelen
, ARCH_CONVERT
))) {
261 _("entry contains illegal character in shortform attribute name\n"));
265 if (INT_GET(currententry
->flags
, ARCH_CONVERT
) & XFS_ATTR_INCOMPLETE
) {
267 _("entry has INCOMPLETE flag on in shortform attribute\n"));
271 /* Only check values for root security attributes */
272 if (INT_GET(currententry
->flags
, ARCH_CONVERT
) & XFS_ATTR_ROOT
)
273 junkit
= valuecheck((char *)¤tentry
->nameval
[0],
275 INT_GET(currententry
->namelen
, ARCH_CONVERT
),
276 INT_GET(currententry
->valuelen
, ARCH_CONVERT
));
278 remainingspace
= remainingspace
-
279 XFS_ATTR_SF_ENTSIZE(currententry
);
283 /* get rid of only this entry */
285 _("removing attribute entry %d for inode %llu\n"),
287 tempentry
= (xfs_attr_sf_entry_t
*)
288 ((__psint_t
) currententry
+
289 XFS_ATTR_SF_ENTSIZE(currententry
));
290 memmove(currententry
,tempentry
,remainingspace
);
291 INT_MOD(asf
->hdr
.count
, ARCH_CONVERT
, -1);
292 i
--; /* no worries, it will wrap back to 0 */
294 continue; /* go back up now */
297 _("would remove attribute entry %d for inode %llu\n"),
302 /* Let's get ready for the next entry... */
303 nextentry
= (xfs_attr_sf_entry_t
*)
304 ((__psint_t
) nextentry
+
305 XFS_ATTR_SF_ENTSIZE(currententry
));
306 currentsize
= currentsize
+ XFS_ATTR_SF_ENTSIZE(currententry
);
310 if (INT_GET(asf
->hdr
.count
, ARCH_CONVERT
) != i
) {
312 do_warn(_("would have corrected attribute entry count "
313 "in inode %llu from %d to %d\n"),
314 ino
, INT_GET(asf
->hdr
.count
, ARCH_CONVERT
), i
);
316 do_warn(_("corrected attribute entry count in inode "
317 "%llu, was %d, now %d\n"),
318 ino
, INT_GET(asf
->hdr
.count
, ARCH_CONVERT
), i
);
319 INT_SET(asf
->hdr
.count
, ARCH_CONVERT
, i
);
324 /* ASSUMPTION: currentsize <= totsize */
325 if (INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) != currentsize
) {
327 do_warn(_("would have corrected attribute totsize in "
328 "inode %llu from %d to %d\n"),
329 ino
, INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
),
332 do_warn(_("corrected attribute entry totsize in "
333 "inode %llu, was %d, now %d\n"),
334 ino
, INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
),
336 INT_SET(asf
->hdr
.totsize
, ARCH_CONVERT
, currentsize
);
344 /* This routine brings in blocks from disk one by one and assembles them
345 * in the value buffer. If get_bmapi gets smarter later to return an extent
346 * or list of extents, that would be great. For now, we don't expect too
347 * many blocks per remote value, so one by one is sufficient.
350 rmtval_get(xfs_mount_t
*mp
, xfs_ino_t ino
, blkmap_t
*blkmap
,
351 xfs_dablk_t blocknum
, int valuelen
, char* value
)
355 int clearit
= 0, i
= 0, length
= 0, amountdone
= 0;
357 /* ASSUMPTION: valuelen is a valid number, so use it for looping */
358 /* Note that valuelen is not a multiple of blocksize */
359 while (amountdone
< valuelen
) {
360 bno
= blkmap_get(blkmap
, blocknum
+ i
);
361 if (bno
== NULLDFSBNO
) {
362 do_warn(_("remote block for attributes of inode %llu"
363 " is missing\n"), ino
);
367 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, bno
),
368 XFS_FSB_TO_BB(mp
, 1), 0);
370 do_warn(_("can't read remote block for attributes"
371 " of inode %llu\n"), ino
);
375 ASSERT(mp
->m_sb
.sb_blocksize
== XFS_BUF_COUNT(bp
));
376 length
= MIN(XFS_BUF_COUNT(bp
), valuelen
- amountdone
);
377 bcopy(XFS_BUF_PTR(bp
), value
, length
);
378 amountdone
+= length
;
387 * freespace map for directory and attribute leaf blocks (1 bit per byte)
388 * 1 == used, 0 == free
390 static da_freemap_t attr_freemap
[DA_BMAP_SIZE
];
392 /* The block is read in. The magic number and forward / backward
393 * links are checked by the caller process_leaf_attr.
394 * If any problems occur the routine returns with non-zero. In
395 * this case the next step is to clear the attribute fork, by
396 * changing it to shortform and zeroing it out. Forkoff need not
401 process_leaf_attr_block(
403 xfs_attr_leafblock_t
*leaf
,
407 xfs_dahash_t last_hashval
,
408 xfs_dahash_t
*current_hashval
,
411 xfs_attr_leaf_entry_t
*entry
;
412 xfs_attr_leaf_name_local_t
*local
;
413 xfs_attr_leaf_name_remote_t
*remotep
;
414 int i
, start
, stop
, clearit
, usedbs
, firstb
, thissize
;
416 clearit
= usedbs
= 0;
418 firstb
= mp
->m_sb
.sb_blocksize
;
419 stop
= sizeof(xfs_attr_leaf_hdr_t
);
421 /* does the count look sorta valid? */
422 if (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
)
423 * sizeof(xfs_attr_leaf_entry_t
)
424 + sizeof(xfs_attr_leaf_hdr_t
)
427 _("bad attribute count %d in attr block %u, inode %llu\n"),
428 (int) INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
),
433 init_da_freemap(attr_freemap
);
434 (void) set_da_freemap(mp
, attr_freemap
, 0, stop
);
436 /* go thru each entry checking for problems */
437 for (i
= 0, entry
= &leaf
->entries
[0];
438 i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
441 /* check if index is within some boundary. */
442 if (INT_GET(entry
->nameidx
, ARCH_CONVERT
) > XFS_LBSIZE(mp
)) {
444 _("bad attribute nameidx %d in attr block %u, inode %llu\n"),
445 (int)INT_GET(entry
->nameidx
, ARCH_CONVERT
),
451 if (INT_GET(entry
->flags
, ARCH_CONVERT
) & XFS_ATTR_INCOMPLETE
) {
452 /* we are inconsistent state. get rid of us */
454 _("attribute entry #%d in attr block %u, inode %llu is INCOMPLETE\n"),
460 /* mark the entry used */
461 start
= (__psint_t
)&leaf
->entries
[i
] - (__psint_t
)leaf
;
462 stop
= start
+ sizeof(xfs_attr_leaf_entry_t
);
463 if (set_da_freemap(mp
, attr_freemap
, start
, stop
)) {
465 _("attribute entry %d in attr block %u, inode %llu claims "
466 "already used space\n"),
469 break; /* got an overlap */
472 if (INT_GET(entry
->flags
, ARCH_CONVERT
) & XFS_ATTR_LOCAL
) {
474 local
= XFS_ATTR_LEAF_NAME_LOCAL(leaf
, i
);
475 if ((INT_GET(local
->namelen
, ARCH_CONVERT
) == 0) ||
476 (namecheck((char *)&local
->nameval
[0],
477 INT_GET(local
->namelen
, ARCH_CONVERT
)))) {
479 _("attribute entry %d in attr block %u, inode %llu "
480 "has bad name (namelen = %d)\n"),
481 i
, da_bno
, ino
, (int)
482 INT_GET(local
->namelen
, ARCH_CONVERT
));
487 /* Check on the hash value. Checking order of values
488 * is not necessary, since one wrong clears the whole
489 * fork. If the ordering's wrong, it's caught here or
490 * the kernel code has a bug with transaction logging
491 * or attributes itself. Being paranoid, let's check
492 * ordering anyway in case both the name value and the
493 * hashvalue were wrong but matched. Unlikely, however.
495 if (INT_GET(entry
->hashval
, ARCH_CONVERT
) !=
496 libxfs_da_hashname((char *)&local
->nameval
[0],
497 INT_GET(local
->namelen
,
499 (INT_GET(entry
->hashval
, ARCH_CONVERT
) <
502 _("bad hashvalue for attribute entry %d in "
503 "attr block %u, inode %llu\n"),
509 /* Only check values for root security attributes */
510 if (INT_GET(entry
->flags
, ARCH_CONVERT
) & XFS_ATTR_ROOT
)
511 if (valuecheck((char *)&local
->nameval
[0], NULL
,
512 INT_GET(local
->namelen
, ARCH_CONVERT
),
513 INT_GET(local
->valuelen
, ARCH_CONVERT
))) {
515 _("bad security value for attribute entry %d in "
516 "attr block %u, inode %llu\n"),
522 thissize
= XFS_ATTR_LEAF_ENTSIZE_LOCAL(
523 INT_GET(local
->namelen
, ARCH_CONVERT
),
524 INT_GET(local
->valuelen
, ARCH_CONVERT
));
527 /* do the remote case */
528 remotep
= XFS_ATTR_LEAF_NAME_REMOTE(leaf
, i
);
529 thissize
= XFS_ATTR_LEAF_ENTSIZE_REMOTE(
530 INT_GET(remotep
->namelen
, ARCH_CONVERT
));
532 if ((INT_GET(remotep
->namelen
, ARCH_CONVERT
) == 0) ||
533 (namecheck((char *)&remotep
->name
[0],
534 INT_GET(remotep
->namelen
, ARCH_CONVERT
))) ||
535 (INT_GET(entry
->hashval
, ARCH_CONVERT
)
536 != libxfs_da_hashname(
537 (char *)&remotep
->name
[0],
538 INT_GET(remotep
->namelen
, ARCH_CONVERT
))) ||
539 (INT_GET(entry
->hashval
, ARCH_CONVERT
)
541 (INT_GET(remotep
->valueblk
, ARCH_CONVERT
) == 0)) {
543 _("inconsistent remote attribute entry %d in "
544 "attr block %u, ino %llu\n"),
550 if (INT_GET(entry
->flags
, ARCH_CONVERT
) & XFS_ATTR_ROOT
) {
553 if ((value
= malloc(INT_GET(remotep
->valuelen
,
554 ARCH_CONVERT
))) == NULL
) {
556 _("cannot malloc enough for remotevalue attribute for inode %llu\n"),
559 _("SKIPPING this remote attribute\n"));
562 if (rmtval_get(mp
, ino
, blkmap
,
563 INT_GET(remotep
->valueblk
,
565 INT_GET(remotep
->valuelen
,
566 ARCH_CONVERT
), value
)) {
568 _("remote attribute get failed for entry %d, inode %llu\n"), i
, ino
);
573 if (valuecheck((char *)&remotep
->name
[0], value
,
574 INT_GET(remotep
->namelen
,
576 INT_GET(remotep
->valuelen
,
579 _("remote attribute value check failed for entry %d, inode %llu\n"),
589 *current_hashval
= last_hashval
590 = INT_GET(entry
->hashval
, ARCH_CONVERT
);
592 if (set_da_freemap(mp
, attr_freemap
,
593 INT_GET(entry
->nameidx
, ARCH_CONVERT
),
594 INT_GET(entry
->nameidx
, ARCH_CONVERT
) +
596 do_warn(_("attribute entry %d in attr block %u, "
597 "inode %llu claims used space\n"),
600 break; /* got an overlap */
603 if (INT_GET(entry
->nameidx
, ARCH_CONVERT
) < firstb
)
604 firstb
= INT_GET(entry
->nameidx
, ARCH_CONVERT
);
609 /* verify the header information is correct */
611 /* if the holes flag is set, don't reset first_used unless it's
612 * pointing to used bytes. we're being conservative here
613 * since the block will get compacted anyhow by the kernel.
616 if ( (INT_GET(leaf
->hdr
.holes
, ARCH_CONVERT
) == 0
617 && firstb
!= INT_GET(leaf
->hdr
.firstused
, ARCH_CONVERT
))
618 || INT_GET(leaf
->hdr
.firstused
, ARCH_CONVERT
) > firstb
) {
621 _("- resetting first used heap value from %d to %d in "
622 "block %u of attribute fork of inode %llu\n"),
623 (int)INT_GET(leaf
->hdr
.firstused
,
624 ARCH_CONVERT
), firstb
,
626 INT_SET(leaf
->hdr
.firstused
,
627 ARCH_CONVERT
, firstb
);
631 _("- would reset first used value from %d to %d in "
632 "block %u of attribute fork of inode %llu\n"),
633 (int)INT_GET(leaf
->hdr
.firstused
,
634 ARCH_CONVERT
), firstb
,
639 if (usedbs
!= INT_GET(leaf
->hdr
.usedbytes
, ARCH_CONVERT
)) {
642 _("- resetting usedbytes cnt from %d to %d in "
643 "block %u of attribute fork of inode %llu\n"),
644 (int)INT_GET(leaf
->hdr
.usedbytes
,
645 ARCH_CONVERT
), usedbs
, da_bno
, ino
);
646 INT_SET(leaf
->hdr
.usedbytes
,
647 ARCH_CONVERT
, usedbs
);
651 _("- would reset usedbytes cnt from %d to %d in "
652 "block %u of attribute fork of %llu\n"),
653 (int)INT_GET(leaf
->hdr
.usedbytes
,
654 ARCH_CONVERT
), usedbs
,da_bno
,ino
);
658 /* there's a lot of work in process_leaf_dir_block to go thru
659 * checking for holes and compacting if appropiate. I don't think
660 * attributes need all that, so let's just leave the holes. If
661 * we discover later that this is a good place to do compaction
662 * we can add it then.
665 return (clearit
); /* and repair */
670 * returns 0 if the attribute fork is ok, 1 if it has to be junked.
673 process_leaf_attr_level(xfs_mount_t
*mp
,
674 da_bt_cursor_t
*da_cursor
)
677 xfs_attr_leafblock_t
*leaf
;
680 xfs_dfsbno_t dev_bno
;
682 xfs_dablk_t prev_bno
;
683 xfs_dahash_t current_hashval
= 0;
684 xfs_dahash_t greatest_hashval
;
686 da_bno
= da_cursor
->level
[0].bno
;
687 ino
= da_cursor
->ino
;
692 dev_bno
= blkmap_get(da_cursor
->blkmap
, da_bno
);
694 * 0 is the root block and no block
695 * pointer can point to the root block of the btree
699 if (dev_bno
== NULLDFSBNO
) {
700 do_warn(_("can't map block %u for attribute fork "
701 "for inode %llu\n"), da_bno
, ino
);
705 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, dev_bno
),
706 XFS_FSB_TO_BB(mp
, 1), 0);
708 do_warn(_("can't read file block %u (fsbno %llu) for"
709 " attribute fork of inode %llu\n"),
710 da_bno
, dev_bno
, ino
);
714 leaf
= (xfs_attr_leafblock_t
*)XFS_BUF_PTR(bp
);
716 /* check magic number for leaf directory btree block */
717 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
)
718 != XFS_ATTR_LEAF_MAGIC
) {
719 do_warn(_("bad attribute leaf magic %#x "
721 leaf
->hdr
.info
.magic
, ino
);
727 * for each block, process the block, verify it's path,
728 * then get next block. update cursor values along the way
730 if (process_leaf_attr_block(mp
, leaf
, da_bno
, ino
,
731 da_cursor
->blkmap
, current_hashval
,
732 &greatest_hashval
, &repair
)) {
738 * index can be set to hdr.count so match the
739 * indexes of the interior blocks -- which at the
740 * end of the block will point to 1 after the final
741 * real entry in the block
743 da_cursor
->level
[0].hashval
= greatest_hashval
;
744 da_cursor
->level
[0].bp
= bp
;
745 da_cursor
->level
[0].bno
= da_bno
;
746 da_cursor
->level
[0].index
747 = INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
748 da_cursor
->level
[0].dirty
= repair
;
750 if (INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
) != prev_bno
) {
751 do_warn(_("bad sibling back pointer for block %u in "
752 "attribute fork for inode %llu\n"),
759 da_bno
= INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
);
761 if (da_bno
!= 0 && verify_da_path(mp
, da_cursor
, 0)) {
766 current_hashval
= greatest_hashval
;
768 if (repair
&& !no_modify
) {
769 libxfs_writebuf(bp
, 0);
774 } while (da_bno
!= 0);
776 if (verify_final_da_path(mp
, da_cursor
, 0)) {
778 * verify the final path up (right-hand-side) if still ok
780 do_warn(_("bad hash path in attribute fork for inode %llu\n"),
785 /* releases all buffers holding interior btree blocks */
786 release_da_cursor(mp
, da_cursor
, 0);
790 /* release all buffers holding interior btree blocks */
791 err_release_da_cursor(mp
, da_cursor
, 0);
797 * a node directory is a true btree -- where the attribute fork
798 * has gotten big enough that it is represented as a non-trivial (e.g.
799 * has more than just a block) btree.
801 * Note that if we run into any problems, we will trash the attribute fork.
803 * returns 0 if things are ok, 1 if bad
804 * Note this code has been based off process_node_dir.
815 da_bt_cursor_t da_cursor
;
818 * try again -- traverse down left-side of tree until we hit
819 * the left-most leaf block setting up the btree cursor along
820 * the way. Then walk the leaf blocks left-to-right, calling
821 * a parent-verification routine each time we traverse a block.
823 bzero(&da_cursor
, sizeof(da_bt_cursor_t
));
824 da_cursor
.active
= 0;
828 da_cursor
.greatest_bno
= 0;
829 da_cursor
.blkmap
= blkmap
;
832 * now process interior node. don't have any buffers held in this path.
834 error
= traverse_int_dablock(mp
, &da_cursor
, &bno
, XFS_ATTR_FORK
);
836 return(1); /* 0 means unsuccessful */
839 * now pass cursor and bno into leaf-block processing routine
840 * the leaf dir level routine checks the interior paths
841 * up to the root including the final right-most path.
844 return (process_leaf_attr_level(mp
, &da_cursor
));
848 * Start processing for a leaf or fuller btree.
849 * A leaf directory is one where the attribute fork is too big for
850 * the inode but is small enough to fit into one btree block
851 * outside the inode. This code is modelled after process_leaf_dir_block.
853 * returns 0 if things are ok, 1 if bad (attributes needs to be junked)
854 * repair is set, if anything was changed, but attributes can live thru it
858 process_longform_attr(
863 int *repair
) /* out - 1 if something was fixed */
865 xfs_attr_leafblock_t
*leaf
;
868 xfs_dahash_t next_hashval
;
873 bno
= blkmap_get(blkmap
, 0);
875 if ( bno
== NULLDFSBNO
) {
876 if (INT_GET(dip
->di_core
.di_anextents
, ARCH_CONVERT
) == 0 &&
877 dip
->di_core
.di_aformat
== XFS_DINODE_FMT_EXTENTS
)
878 /* it's okay the kernel can handle this state */
881 do_warn(_("block 0 of inode %llu attribute fork"
882 " is missing\n"), ino
);
886 /* FIX FOR bug 653709 -- EKN */
887 if (mp
->m_sb
.sb_agcount
< XFS_FSB_TO_AGNO(mp
, bno
)) {
888 do_warn(_("agno of attribute fork of inode %llu out of "
889 "regular partition\n"), ino
);
893 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, bno
),
894 XFS_FSB_TO_BB(mp
, 1), 0);
896 do_warn(_("can't read block 0 of inode %llu attribute fork\n"),
901 /* verify leaf block */
902 leaf
= (xfs_attr_leafblock_t
*)XFS_BUF_PTR(bp
);
904 /* check sibling pointers in leaf block or root block 0 before
905 * we have to release the btree block
907 if ( INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) != 0
908 || INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
) != 0) {
910 do_warn(_("clearing forw/back pointers in block 0 "
911 "for attributes in inode %llu\n"), ino
);
913 INT_SET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
, 0);
914 INT_SET(leaf
->hdr
.info
.back
, ARCH_CONVERT
, 0);
916 do_warn(_("would clear forw/back pointers in block 0 "
917 "for attributes in inode %llu\n"), ino
);
922 * use magic number to tell us what type of attribute this is.
923 * it's possible to have a node or leaf attribute in either an
924 * extent format or btree format attribute fork.
926 switch (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
)) {
927 case XFS_ATTR_LEAF_MAGIC
: /* leaf-form attribute */
928 if (process_leaf_attr_block(mp
, leaf
, 0, ino
, blkmap
,
929 0, &next_hashval
, repair
)) {
930 /* the block is bad. lose the attribute fork. */
934 *repair
= *repair
|| repairlinks
;
937 case XFS_DA_NODE_MAGIC
: /* btree-form attribute */
938 /* must do this now, to release block 0 before the traversal */
941 libxfs_writebuf(bp
, 0);
944 return (process_node_attr(mp
, ino
, dip
, blkmap
)); /* + repair */
946 do_warn(_("bad attribute leaf magic # %#x for dir ino %llu\n"),
947 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), ino
);
952 if (*repair
&& !no_modify
)
953 libxfs_writebuf(bp
, 0);
957 return(0); /* repair may be set */
962 xfs_acl_get_endian(xfs_acl_t
*aclp
)
964 xfs_acl_entry_t
*ace
, *end
;
966 INT_SET(aclp
->acl_cnt
, ARCH_CONVERT
, aclp
->acl_cnt
);
967 end
= &aclp
->acl_entry
[0]+aclp
->acl_cnt
;
968 for (ace
= &aclp
->acl_entry
[0]; ace
< end
; ace
++) {
969 INT_SET(ace
->ae_tag
, ARCH_CONVERT
, ace
->ae_tag
);
970 INT_SET(ace
->ae_id
, ARCH_CONVERT
, ace
->ae_id
);
971 INT_SET(ace
->ae_perm
, ARCH_CONVERT
, ace
->ae_perm
);
976 * returns 1 if attributes got cleared
977 * and 0 if things are ok.
985 int *repair
) /* returned if we did repair */
988 xfs_dinode_core_t
*dinoc
;
990 xfs_attr_shortform_t
*asf
;
992 dinoc
= &dip
->di_core
;
993 asf
= (xfs_attr_shortform_t
*) XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
);
995 if (dinoc
->di_aformat
== XFS_DINODE_FMT_LOCAL
) {
996 ASSERT(INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) <=
997 XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_CONVERT
));
998 err
= process_shortform_attr(ino
, dip
, repair
);
999 } else if (dinoc
->di_aformat
== XFS_DINODE_FMT_EXTENTS
||
1000 dinoc
->di_aformat
== XFS_DINODE_FMT_BTREE
) {
1001 err
= process_longform_attr(mp
, ino
, dip
, blkmap
,
1003 /* if err, convert this to shortform and clear it */
1004 /* if repair and no error, it's taken care of */
1006 do_warn(_("illegal attribute format %d, ino %llu\n"),
1007 dinoc
->di_aformat
, ino
);
1010 return (err
); /* and repair */
1017 xfs_acl_valid(xfs_acl_t
*aclp
)
1019 xfs_acl_entry_t
*entry
, *e
;
1020 int user
= 0, group
= 0, other
= 0, mask
= 0, mask_required
= 0;
1026 xfs_acl_get_endian(aclp
);
1028 if (aclp
->acl_cnt
> XFS_ACL_MAX_ENTRIES
)
1031 for (i
= 0; i
< aclp
->acl_cnt
; i
++) {
1032 entry
= &aclp
->acl_entry
[i
];
1033 if (entry
->ae_perm
& ~(ACL_READ
|ACL_WRITE
|ACL_EXECUTE
))
1035 switch (entry
->ae_tag
) {
1050 for (j
= i
+ 1; j
< aclp
->acl_cnt
; j
++) {
1051 e
= &aclp
->acl_entry
[j
];
1052 if (e
->ae_id
== entry
->ae_id
&&
1053 e
->ae_tag
== entry
->ae_tag
)
1066 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 )