1515#include "xfs_da_btree.h"
1616#include "xfs_attr.h"
1717#include "xfs_attr_leaf.h"
18+ #include "xfs_attr_sf.h"
1819#include "scrub/scrub.h"
1920#include "scrub/common.h"
2021#include "scrub/dabtree.h"
@@ -487,6 +488,73 @@ xchk_xattr_rec(
487488 return error ;
488489}
489490
491+ /* Check space usage of shortform attrs. */
492+ STATIC int
493+ xchk_xattr_check_sf (
494+ struct xfs_scrub * sc )
495+ {
496+ struct xchk_xattr_buf * ab = sc -> buf ;
497+ struct xfs_attr_shortform * sf ;
498+ struct xfs_attr_sf_entry * sfe ;
499+ struct xfs_attr_sf_entry * next ;
500+ struct xfs_ifork * ifp ;
501+ unsigned char * end ;
502+ int i ;
503+ int error = 0 ;
504+
505+ ifp = xfs_ifork_ptr (sc -> ip , XFS_ATTR_FORK );
506+
507+ bitmap_zero (ab -> usedmap , ifp -> if_bytes );
508+ sf = (struct xfs_attr_shortform * )sc -> ip -> i_af .if_u1 .if_data ;
509+ end = (unsigned char * )ifp -> if_u1 .if_data + ifp -> if_bytes ;
510+ xchk_xattr_set_map (sc , ab -> usedmap , 0 , sizeof (sf -> hdr ));
511+
512+ sfe = & sf -> list [0 ];
513+ if ((unsigned char * )sfe > end ) {
514+ xchk_fblock_set_corrupt (sc , XFS_ATTR_FORK , 0 );
515+ return 0 ;
516+ }
517+
518+ for (i = 0 ; i < sf -> hdr .count ; i ++ ) {
519+ unsigned char * name = sfe -> nameval ;
520+ unsigned char * value = & sfe -> nameval [sfe -> namelen ];
521+
522+ if (xchk_should_terminate (sc , & error ))
523+ return error ;
524+
525+ next = xfs_attr_sf_nextentry (sfe );
526+ if ((unsigned char * )next > end ) {
527+ xchk_fblock_set_corrupt (sc , XFS_ATTR_FORK , 0 );
528+ break ;
529+ }
530+
531+ if (!xchk_xattr_set_map (sc , ab -> usedmap ,
532+ (char * )sfe - (char * )sf ,
533+ sizeof (struct xfs_attr_sf_entry ))) {
534+ xchk_fblock_set_corrupt (sc , XFS_ATTR_FORK , 0 );
535+ break ;
536+ }
537+
538+ if (!xchk_xattr_set_map (sc , ab -> usedmap ,
539+ (char * )name - (char * )sf ,
540+ sfe -> namelen )) {
541+ xchk_fblock_set_corrupt (sc , XFS_ATTR_FORK , 0 );
542+ break ;
543+ }
544+
545+ if (!xchk_xattr_set_map (sc , ab -> usedmap ,
546+ (char * )value - (char * )sf ,
547+ sfe -> valuelen )) {
548+ xchk_fblock_set_corrupt (sc , XFS_ATTR_FORK , 0 );
549+ break ;
550+ }
551+
552+ sfe = next ;
553+ }
554+
555+ return 0 ;
556+ }
557+
490558/* Scrub the extended attribute metadata. */
491559int
492560xchk_xattr (
@@ -506,17 +574,20 @@ xchk_xattr(
506574 if (error )
507575 return error ;
508576
509- memset (& sx , 0 , sizeof (sx ));
510- /* Check attribute tree structure */
511- error = xchk_da_btree (sc , XFS_ATTR_FORK , xchk_xattr_rec ,
512- & last_checked );
577+ /* Check the physical structure of the xattr. */
578+ if (sc -> ip -> i_af .if_format == XFS_DINODE_FMT_LOCAL )
579+ error = xchk_xattr_check_sf (sc );
580+ else
581+ error = xchk_da_btree (sc , XFS_ATTR_FORK , xchk_xattr_rec ,
582+ & last_checked );
513583 if (error )
514584 goto out ;
515585
516586 if (sc -> sm -> sm_flags & XFS_SCRUB_OFLAG_CORRUPT )
517587 goto out ;
518588
519589 /* Check that every attr key can also be looked up by hash. */
590+ memset (& sx , 0 , sizeof (sx ));
520591 sx .context .dp = sc -> ip ;
521592 sx .context .resynch = 1 ;
522593 sx .context .put_listent = xchk_xattr_listent ;
0 commit comments