--- xfsprogs/db/check.c | 2 - xfsprogs/db/sb.c | 2 + xfsprogs/growfs/xfs_growfs.c | 15 +++++--- xfsprogs/include/libxfs.h | 1 xfsprogs/include/xfs_da_btree.h | 21 +++++++++++ xfsprogs/include/xfs_fs.h | 1 xfsprogs/include/xfs_sb.h | 10 +++++ xfsprogs/libxfs/xfs_da_btree.c | 12 ++++++ xfsprogs/libxfs/xfs_dir2.c | 63 +++++++++++++++++++++++++++++++++-- xfsprogs/libxfs/xfs_dir2_block.c | 5 +- xfsprogs/libxfs/xfs_dir2_data.c | 2 - xfsprogs/man/man8/mkfs.xfs.8 | 27 +++++++++------ xfsprogs/mkfs/xfs_mkfs.c | 69 +++++++++++++++++---------------------- xfsprogs/mkfs/xfs_mkfs.h | 9 ++--- xfsprogs/repair/phase6.c | 11 +++--- 15 files changed, 178 insertions(+), 72 deletions(-) Index: ci/xfsprogs/db/check.c =================================================================== --- ci.orig/xfsprogs/db/check.c +++ ci/xfsprogs/db/check.c @@ -2317,7 +2317,7 @@ process_data_dir_v2( tag_err += INT_GET(*tagp, ARCH_CONVERT) != (char *)dep - (char *)data; addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, db, (char *)dep - (char *)data); - hash = libxfs_da_hashname((uchar_t *)dep->name, dep->namelen); + hash = mp->m_dirnameops->hashname((uchar_t *)dep->name, dep->namelen); dir_hash_add(hash, addr); ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen); count++; Index: ci/xfsprogs/db/sb.c =================================================================== --- ci.orig/xfsprogs/db/sb.c +++ ci/xfsprogs/db/sb.c @@ -605,6 +605,8 @@ version_string( strcat(s, ",EXTFLG"); if (XFS_SB_VERSION_HASSECTOR(sbp)) strcat(s, ",SECTOR"); + if (xfs_sb_version_hasasciici(sbp)) + strcat(s, ",ASCII_CI"); if (XFS_SB_VERSION_HASMOREBITS(sbp)) strcat(s, ",MOREBITS"); if (XFS_SB_VERSION_HASATTR2(sbp)) Index: ci/xfsprogs/growfs/xfs_growfs.c =================================================================== --- ci.orig/xfsprogs/growfs/xfs_growfs.c +++ ci/xfsprogs/growfs/xfs_growfs.c @@ -61,14 +61,15 @@ report_info( int lazycount, int dirversion, int logversion, - int attrversion) + int attrversion, + int cimode) { printf(_( "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" - "naming =version %-14u bsize=%-6u\n" + "naming =version %-14u bsize=%-6u mixed-case=%c\n" "log =%-22s bsize=%-6u blocks=%u, version=%u\n" " =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n" "realtime =%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n"), @@ -78,7 +79,7 @@ report_info( "", geo.blocksize, (unsigned long long)geo.datablocks, geo.imaxpct, "", geo.sunit, geo.swidth, - dirversion, geo.dirblocksize, + dirversion, geo.dirblocksize, cimode ? 'N' : 'Y', isint ? _("internal") : logname ? logname : _("external"), geo.blocksize, geo.logblocks, logversion, "", geo.logsectsize, geo.logsunit / geo.blocksize, lazycount, @@ -114,6 +115,7 @@ main(int argc, char **argv) xfs_fsop_geom_t ngeo; /* new fs geometry */ int rflag; /* -r flag */ long long rsize; /* new rt size in fs blocks */ + int ci; /* ASCII case-insensitive fs */ int lazycount; /* lazy superblock counters */ int xflag; /* -x flag */ char *fname; /* mount point name */ @@ -131,6 +133,7 @@ main(int argc, char **argv) maxpct = esize = 0; dsize = lsize = rsize = 0LL; aflag = dflag = iflag = lflag = mflag = nflag = rflag = xflag = 0; + ci = 0; while ((c = getopt(argc, argv, "dD:e:ilL:m:np:rR:t:xV")) != EOF) { switch (c) { @@ -239,11 +242,11 @@ main(int argc, char **argv) logversion = geo.flags & XFS_FSOP_GEOM_FLAGS_LOGV2 ? 2 : 1; attrversion = geo.flags & XFS_FSOP_GEOM_FLAGS_ATTR2 ? 2 : \ (geo.flags & XFS_FSOP_GEOM_FLAGS_ATTR ? 1 : 0); - + ci = geo.flags & XFS_FSOP_GEOM_FLAGS_DIRV2CI ? 1 : 0; if (nflag) { report_info(geo, datadev, isint, logdev, rtdev, lazycount, dirversion, logversion, - attrversion); + attrversion, ci); exit(0); } @@ -280,7 +283,7 @@ main(int argc, char **argv) report_info(geo, datadev, isint, logdev, rtdev, lazycount, dirversion, logversion, - attrversion); + attrversion, ci); ddsize = xi.dsize; dlsize = ( xi.logBBsize? xi.logBBsize : Index: ci/xfsprogs/include/libxfs.h =================================================================== --- ci.orig/xfsprogs/include/libxfs.h +++ ci/xfsprogs/include/libxfs.h @@ -175,6 +175,7 @@ typedef struct xfs_mount { int m_attr_magicpct;/* 37% of the blocksize */ int m_dir_magicpct; /* 37% of the dir blocksize */ __uint8_t m_dirversion; /* 1 or 2 */ + const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */ int m_dirblksize; /* directory block sz--bytes */ int m_dirblkfsbs; /* directory block sz--fsbs */ xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ Index: ci/xfsprogs/include/xfs_da_btree.h =================================================================== --- ci.orig/xfsprogs/include/xfs_da_btree.h +++ ci/xfsprogs/include/xfs_da_btree.h @@ -103,6 +103,15 @@ typedef struct xfs_da_node_entry xfs_da_ *========================================================================*/ /* + * Search comparison results + */ +enum xfs_dacmp { + XFS_CMP_DIFFERENT, /* names are completely different */ + XFS_CMP_EXACT, /* names are exactly the same */ + XFS_CMP_CASE /* names are same but differ in case */ +}; + +/* * Structure to ease passing around component names. */ typedef struct xfs_da_args { @@ -131,6 +140,7 @@ typedef struct xfs_da_args { unsigned char rename; /* T/F: this is an atomic rename op */ unsigned char addname; /* T/F: this is an add operation */ unsigned char oknoent; /* T/F: ok to return ENOENT, else die */ + enum xfs_dacmp cmpresult; /* name compare result for lookups */ } xfs_da_args_t; /* @@ -205,6 +215,14 @@ typedef struct xfs_da_state { (uint)(XFS_DA_LOGOFF(BASE, ADDR)), \ (uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1) +/* + * Name ops for directory and/or attr name operations + */ +struct xfs_nameops { + xfs_dahash_t (*hashname)(const uchar_t *, int); + enum xfs_dacmp (*compname)(const uchar_t *, int, const uchar_t *, int); +}; + #ifdef __KERNEL__ /*======================================================================== @@ -253,6 +271,9 @@ int xfs_da_shrink_inode(xfs_da_args_t *a xfs_dabuf_t *dead_buf); uint xfs_da_hashname(const uchar_t *name_string, int name_length); +enum xfs_dacmp xfs_da_compname(const uchar_t *name1, int len1, + const uchar_t *name2, int len2); + uint xfs_da_log2_roundup(uint i); xfs_da_state_t *xfs_da_state_alloc(void); void xfs_da_state_free(xfs_da_state_t *state); Index: ci/xfsprogs/include/xfs_fs.h =================================================================== --- ci.orig/xfsprogs/include/xfs_fs.h +++ ci/xfsprogs/include/xfs_fs.h @@ -241,6 +241,7 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */ #define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */ #define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */ +#define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */ #define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */ Index: ci/xfsprogs/include/xfs_sb.h =================================================================== --- ci.orig/xfsprogs/include/xfs_sb.h +++ ci/xfsprogs/include/xfs_sb.h @@ -46,10 +46,12 @@ struct xfs_mount; #define XFS_SB_VERSION_SECTORBIT 0x0800 #define XFS_SB_VERSION_EXTFLGBIT 0x1000 #define XFS_SB_VERSION_DIRV2BIT 0x2000 +#define XFS_SB_VERSION_BORGBIT 0x4000 #define XFS_SB_VERSION_MOREBITSBIT 0x8000 #define XFS_SB_VERSION_OKSASHFBITS \ (XFS_SB_VERSION_EXTFLGBIT | \ - XFS_SB_VERSION_DIRV2BIT) + XFS_SB_VERSION_DIRV2BIT | \ + XFS_SB_VERSION_BORGBIT) #define XFS_SB_VERSION_OKREALFBITS \ (XFS_SB_VERSION_ATTRBIT | \ XFS_SB_VERSION_NLINKBIT | \ @@ -416,6 +418,12 @@ static inline int xfs_sb_version_hassect ((sbp)->sb_versionnum & XFS_SB_VERSION_SECTORBIT); } +static inline int xfs_sb_version_hasasciici(xfs_sb_t *sbp) +{ + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ + (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT); +} + #define XFS_SB_VERSION_HASMOREBITS(sbp) xfs_sb_version_hasmorebits(sbp) static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) { Index: ci/xfsprogs/libxfs/xfs_da_btree.c =================================================================== --- ci.orig/xfsprogs/libxfs/xfs_da_btree.c +++ ci/xfsprogs/libxfs/xfs_da_btree.c @@ -1540,6 +1540,18 @@ xfs_da_hashname(const uchar_t *name, int } } +enum xfs_dacmp +xfs_da_compname(const uchar_t *name1, int len1, const uchar_t *name2, int len2) +{ + return (len1 == len2 && memcmp(name1, name2, len1) == 0) ? + XFS_CMP_EXACT : XFS_CMP_DIFFERENT; +} + +const struct xfs_nameops xfs_default_nameops = { + .hashname = xfs_da_hashname, + .compname = xfs_da_compname +}; + /* * Add a block to the btree ahead of the file. * Return the new block number to the caller. Index: ci/xfsprogs/libxfs/xfs_dir2.c =================================================================== --- ci.orig/xfsprogs/libxfs/xfs_dir2.c +++ ci/xfsprogs/libxfs/xfs_dir2.c @@ -23,6 +23,57 @@ #include +extern const struct xfs_nameops xfs_default_nameops; + +/* + * V1/OLDCI case-insensitive support for directories that was used in IRIX. + * + * This is ASCII only case support, ie. A-Z. + */ +static xfs_dahash_t +xfs_ascii_ci_hashname( + const uchar_t *name, + int len) +{ + xfs_dahash_t hash; + int i; + + for (i = 0, hash = 0; i < len; i++) + hash = tolower(name[i]) ^ rol32(hash, 7); + + return hash; +} + +static enum xfs_dacmp +xfs_ascii_ci_compname( + const uchar_t *name1, + int len1, + const uchar_t *name2, + int len2) +{ + enum xfs_dacmp result; + int i; + + if (len1 != len2) + return XFS_CMP_DIFFERENT; + + result = XFS_CMP_EXACT; + for (i = 0; i < len1; i++) { + if (name1[i] == name2[i]) + continue; + if (tolower(name1[i]) != tolower(name2[i])) + return XFS_CMP_DIFFERENT; + result = XFS_CMP_CASE; + } + + return result; +} + +static const struct xfs_nameops xfs_ascii_ci_nameops = { + .hashname = xfs_ascii_ci_hashname, + .compname = xfs_ascii_ci_compname, +}; + /* * Initialize directory-related fields in the mount structure. @@ -46,6 +97,10 @@ xfs_dir2_mount( (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) / (uint)sizeof(xfs_da_node_entry_t); mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; + if (xfs_sb_version_hasasciici(&mp->m_sb)) + mp->m_dirnameops = &xfs_ascii_ci_nameops; + else + mp->m_dirnameops = &xfs_default_nameops; } /* @@ -98,7 +153,7 @@ xfs_dir2_createname( */ args.name = name; args.namelen = namelen; - args.hashval = xfs_da_hashname(name, namelen); + args.hashval = dp->i_mount->m_dirnameops->hashname(name, namelen); args.inumber = inum; args.dp = dp; args.firstblock = first; @@ -149,7 +204,7 @@ xfs_dir2_lookup( */ args.name = name; args.namelen = namelen; - args.hashval = xfs_da_hashname(name, namelen); + args.hashval = dp->i_mount->m_dirnameops->hashname(name, namelen); args.inumber = 0; args.dp = dp; args.firstblock = NULL; @@ -206,7 +261,7 @@ xfs_dir2_removename( */ args.name = name; args.namelen = namelen; - args.hashval = xfs_da_hashname(name, namelen); + args.hashval = dp->i_mount->m_dirnameops->hashname(name, namelen); args.inumber = ino; args.dp = dp; args.firstblock = first; @@ -261,7 +316,7 @@ xfs_dir2_replace( */ args.name = name; args.namelen = namelen; - args.hashval = xfs_da_hashname(name, namelen); + args.hashval = dp->i_mount->m_dirnameops->hashname(name, namelen); args.inumber = inum; args.dp = dp; args.firstblock = first; Index: ci/xfsprogs/libxfs/xfs_dir2_block.c =================================================================== --- ci.orig/xfsprogs/libxfs/xfs_dir2_block.c +++ ci/xfsprogs/libxfs/xfs_dir2_block.c @@ -1046,8 +1046,9 @@ xfs_dir2_sf_to_block( tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); INT_SET(*tagp, ARCH_CONVERT, (xfs_dir2_data_off_t)((char *)dep - (char *)block)); xfs_dir2_data_log_entry(tp, bp, dep); - INT_SET(blp[2 + i].hashval, ARCH_CONVERT, xfs_da_hashname((const uchar_t *)sfep->name, sfep->namelen)); - INT_SET(blp[2 + i].address, ARCH_CONVERT, XFS_DIR2_BYTE_TO_DATAPTR(mp, + blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->hashname( + sfep->name, sfep->namelen)); + blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, (char *)dep - (char *)block)); offset = (int)((char *)(tagp + 1) - (char *)block); if (++i == INT_GET(sfp->hdr.count, ARCH_CONVERT)) Index: ci/xfsprogs/libxfs/xfs_dir2_data.c =================================================================== --- ci.orig/xfsprogs/libxfs/xfs_dir2_data.c +++ ci/xfsprogs/libxfs/xfs_dir2_data.c @@ -126,7 +126,7 @@ xfs_dir2_data_check( addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, (xfs_dir2_data_aoff_t) ((char *)dep - (char *)d)); - hash = xfs_da_hashname((char *)dep->name, dep->namelen); + hash = mp->m_dirnameops->hashname(dep->name, dep->namelen); for (i = 0; i < INT_GET(btp->count, ARCH_CONVERT); i++) { if (INT_GET(lep[i].address, ARCH_CONVERT) == addr && INT_GET(lep[i].hashval, ARCH_CONVERT) == hash) Index: ci/xfsprogs/man/man8/mkfs.xfs.8 =================================================================== --- ci.orig/xfsprogs/man/man8/mkfs.xfs.8 +++ ci/xfsprogs/man/man8/mkfs.xfs.8 @@ -302,8 +302,8 @@ bits. .TP .BI maxpct= value This specifies the maximum percentage of space in the filesystem that -can be allocated to inodes. The default -.I value +can be allocated to inodes. The default +.I value is 25% for filesystems under 1TB, 5% for filesystems under 50TB and 1% for filesystems over 50TB. .IP @@ -314,14 +314,14 @@ allocator will avoid these low blocks to maxpct, so a high value may result in a filesystem with nothing but inodes in a significant portion of the lower blocks of the filesystem. (This restriction is not present when the filesystem is mounted with -the -.I "inode64" +the +.I "inode64" option on 64-bit platforms). .IP Setting the value to 0 means that essentially all of the filesystem can become inode blocks, subject to inode32 restrictions. .IP -This value can be modified with +This value can be modified with .Ixfs_growfs(8) . .TP @@ -340,7 +340,7 @@ filesystem needs to be mountable by a ve that does not have the inode alignment feature (any release of IRIX before 6.2, and IRIX 6.2 without XFS patches). .TP -.BI attr= value +.BI attr= value This is used to specify the version of extended attribute inline allocation policy to be used. By default, this is 2, which uses an efficient algorithm for managing the available inline inode space @@ -489,10 +489,17 @@ filesystem block size. .BI version= value The naming (directory) version .I value -can be either 1 or 2, defaulting to 2 if unspecified. -With version 2 directories, -the directory block size can be any power of 2 size -from the filesystem block size up to 65536. +can be either 2 or 'ci', defaulting to 2 if unspecified. +With version 2 directories, the directory block size can be +any power of 2 size from the filesystem block size up to 65536. +.IP +The +.B version=ci +option enables ASCII only case-insensitive filename lookup and version +2 directories. Filenames are case-preserving, that is, the names +are stored in directories using the case they were created with. +.IP +Note: Version 1 directories are not supported. .RE .TP .BI \-p " protofile" Index: ci/xfsprogs/mkfs/xfs_mkfs.c =================================================================== --- ci.orig/xfsprogs/mkfs/xfs_mkfs.c +++ ci/xfsprogs/mkfs/xfs_mkfs.c @@ -678,6 +678,7 @@ main( xfs_alloc_rec_t *nrec; int nsflag; int nvflag; + int nci; int Nflag; char *p; char *protofile; @@ -720,8 +721,9 @@ main( loginternal = 1; logversion = 2; logagno = logblocks = rtblocks = rtextblocks = 0; - Nflag = nlflag = nsflag = nvflag = 0; - dirblocklog = dirblocksize = dirversion = 0; + Nflag = nlflag = nsflag = nvflag = nci = 0; + dirblocklog = dirblocksize = 0; + dirversion = XFS_DFL_DIR_VERSION; qflag = 0; imaxpct = inodelog = inopblock = isize = 0; iaflag = XFS_IFLAG_ALIGN; @@ -1236,9 +1238,14 @@ main( reqval('n', nopts, N_VERSION); if (nvflag) respec('n', nopts, N_VERSION); - dirversion = atoi(value); - if (dirversion < 1 || dirversion > 2) - illegal(value, "n version"); + if (!strcmp(value, "ci")) { + nci = 1; /* ASCII CI mode */ + } else { + dirversion = atoi(value); + if (dirversion != 2) + illegal(value, + "n version"); + } nvflag = 1; break; default: @@ -1412,33 +1419,19 @@ main( logversion = 2; } - if (!nvflag) - dirversion = (nsflag || nlflag) ? 2 : XFS_DFL_DIR_VERSION; - switch (dirversion) { - case 1: - if ((nsflag || nlflag) && dirblocklog != blocklog) { + if (nsflag || nlflag) { + if (dirblocksize < blocksize || + dirblocksize > XFS_MAX_BLOCKSIZE) { fprintf(stderr, _("illegal directory block size %d\n"), dirblocksize); usage(); } - break; - case 2: - if (nsflag || nlflag) { - if (dirblocksize < blocksize || - dirblocksize > XFS_MAX_BLOCKSIZE) { - fprintf(stderr, - _("illegal directory block size %d\n"), - dirblocksize); - usage(); - } - } else { - if (blocksize < (1 << XFS_MIN_REC_DIRSIZE)) - dirblocklog = XFS_MIN_REC_DIRSIZE; - else - dirblocklog = blocklog; - dirblocksize = 1 << dirblocklog; - } - break; + } else { + if (blocksize < (1 << XFS_MIN_REC_DIRSIZE)) + dirblocklog = XFS_MIN_REC_DIRSIZE; + else + dirblocklog = blocklog; + dirblocksize = 1 << dirblocklog; } if (daflag && dasize) { @@ -2024,7 +2017,7 @@ an AG size that is one stripe unit small " =%-22s sectsz=%-5u attr=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" - "naming =version %-14u bsize=%-6u\n" + "naming =version %-14u bsize=%-6u mixed-case=%c\n" "log =%-22s bsize=%-6d blocks=%lld, version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"), @@ -2033,7 +2026,7 @@ an AG size that is one stripe unit small "", blocksize, (long long)dblocks, calc_default_imaxpct(blocklog, dblocks), "", dsunit, dswidth, - dirversion, dirversion == 1 ? blocksize : dirblocksize, + dirversion, dirblocksize, nci ? 'N' : 'Y', logfile, 1 << blocklog, (long long)logblocks, logversion, "", lsectorsize, lsunit, lazy_sb_counters, rtfile, rtextblocks << blocklog, @@ -2078,8 +2071,7 @@ an AG size that is one stripe unit small sbp->sb_qflags = 0; sbp->sb_unit = dsunit; sbp->sb_width = dswidth; - if (dirversion == 2) - sbp->sb_dirblklog = dirblocklog - blocklog; + sbp->sb_dirblklog = dirblocklog - blocklog; if (logversion == 2) { /* This is stored in bytes */ lsunit = (lsunit == 0) ? 1 : XFS_FSB_TO_B(mp, lsunit); sbp->sb_logsunit = lsunit; @@ -2097,12 +2089,13 @@ an AG size that is one stripe unit small sbp->sb_logsectlog = 0; sbp->sb_logsectsize = 0; } - sbp->sb_features2 = XFS_SB_VERSION2_MKFS(lazy_sb_counters, attrversion == 2, 0); - sbp->sb_versionnum = XFS_SB_VERSION_MKFS( - iaflag, dsunit != 0, - dirversion == 2, logversion == 2, attrversion == 1, - (sectorsize != BBSIZE || lsectorsize != BBSIZE), - sbp->sb_features2 != 0); + sbp->sb_features2 = XFS_SB_VERSION2_MKFS(lazy_sb_counters, + attrversion == 2, 0); + sbp->sb_versionnum = XFS_SB_VERSION_MKFS(iaflag, dsunit != 0, + logversion == 2, attrversion == 1, + (sectorsize != BBSIZE || + lsectorsize != BBSIZE), + nci, sbp->sb_features2 != 0); /* * Due to a structure alignment issue, sb_features2 ended up in one * of two locations, the second "incorrect" location represented by Index: ci/xfsprogs/mkfs/xfs_mkfs.h =================================================================== --- ci.orig/xfsprogs/mkfs/xfs_mkfs.h +++ ci/xfsprogs/mkfs/xfs_mkfs.h @@ -20,17 +20,18 @@ #define XFS_DFL_SB_VERSION_BITS \ (XFS_SB_VERSION_NLINKBIT | \ - XFS_SB_VERSION_EXTFLGBIT) + XFS_SB_VERSION_EXTFLGBIT | \ + XFS_SB_VERSION_DIRV2BIT) -#define XFS_SB_VERSION_MKFS(ia,dia,dir2,log2,attr1,sflag,more) (\ - ((ia)||(dia)||(dir2)||(log2)||(attr1)||(sflag)||(more)) ? \ +#define XFS_SB_VERSION_MKFS(ia,dia,log2,attr1,sflag,ci,more) (\ + ((ia)||(dia)||(log2)||(attr1)||(sflag)||(ci)||(more)) ? \ ( XFS_SB_VERSION_4 | \ ((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) | \ ((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) | \ - ((dir2) ? XFS_SB_VERSION_DIRV2BIT : 0) | \ ((log2) ? XFS_SB_VERSION_LOGV2BIT : 0) | \ ((attr1) ? XFS_SB_VERSION_ATTRBIT : 0) | \ ((sflag) ? XFS_SB_VERSION_SECTORBIT : 0) | \ + ((ci) ? XFS_SB_VERSION_BORGBIT : 0) | \ ((more) ? XFS_SB_VERSION_MOREBITSBIT : 0) | \ XFS_DFL_SB_VERSION_BITS | \ 0 ) : XFS_SB_VERSION_1 ) Index: ci/xfsprogs/repair/phase6.c =================================================================== --- ci.orig/xfsprogs/repair/phase6.c +++ ci/xfsprogs/repair/phase6.c @@ -93,6 +93,7 @@ typedef struct freetab { */ static int dir_hash_add( + xfs_mount_t *mp, dir_hash_tab_t *hashtab, __uint32_t addr, xfs_ino_t inum, @@ -113,7 +114,7 @@ dir_hash_add( dup = 0; if (!junk) { - hash = libxfs_da_hashname(name, namelen); + hash = mp->m_dirnameops->hashname(name, namelen); byhash = DIR_HASH_FUNC(hashtab, hash); /* @@ -1589,7 +1590,7 @@ lf_block_dir_entry_check(xfs_mount_t *m /* * check for duplicate names in directory. */ - if (!dir_hash_add(hashtab, (da_bno << mp->m_sb.sb_blocklog) + + if (!dir_hash_add(mp, hashtab, (da_bno << mp->m_sb.sb_blocklog) + entry->nameidx, lino, entry->namelen, namest->name)) { nbad++; @@ -2260,7 +2261,7 @@ longform_dir2_entry_check_data( /* * check for duplicate names in directory. */ - if (!dir_hash_add(hashtab, addr, inum, dep->namelen, + if (!dir_hash_add(mp, hashtab, addr, inum, dep->namelen, dep->name)) { nbad++; if (entry_junked(_("entry \"%s\" (ino %llu) in dir " @@ -2870,7 +2871,7 @@ shortform_dir_entry_check(xfs_mount_t *m /* * check for duplicate names in directory. */ - if (!dir_hash_add(hashtab, + if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t)(sf_entry - &sf->list[0]), lino, sf_entry->namelen, sf_entry->name)) { do_warn(_("entry \"%s\" (ino %llu) in dir %llu is a " @@ -3275,7 +3276,7 @@ shortform_dir2_entry_check(xfs_mount_t * /* * check for duplicate names in directory. */ - if (!dir_hash_add(hashtab, (xfs_dir2_dataptr_t) + if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t) (sfep - XFS_DIR2_SF_FIRSTENTRY(sfp)), lino, sfep->namelen, sfep->name)) { do_warn(_("entry \"%s\" (ino %llu) in dir %llu is a "