diff options
author | Barry Naujok <bnaujok@sgi.com> | 2008-05-21 02:58:55 -0400 |
---|---|---|
committer | Niv Sardi <xaiki@debian.org> | 2008-07-28 02:58:42 -0400 |
commit | 189f4bf22bdc3c2402b038016d11fd3cb1c89f07 (patch) | |
tree | 98a168b063b87609fc28685ace7ce0fec589beff | |
parent | 384f3ced07efdddf6838f6527366089d37843c94 (diff) |
[XFS] XFS: ASCII case-insensitive support
Implement ASCII case-insensitive support. It's primary purpose is for
supporting existing filesystems that already use this case-insensitive
mode migrated from IRIX. But, if you only need ASCII-only case-insensitive
support (ie. English only) and will never use another language, then this
mode is perfectly adequate.
ASCII-CI is implemented by generating hashes based on lower-case letters
and doing lower-case compares. It implements a new xfs_nameops vector for
doing the hashes and comparisons for all filename operations.
To create a filesystem with this CI mode, use: # mkfs.xfs -n version=ci
<device>
SGI-PV: 981516
SGI-Modid: xfs-linux-melb:xfs-kern:31209a
Signed-off-by: Barry Naujok <bnaujok@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
-rw-r--r-- | fs/xfs/linux-2.6/xfs_linux.h | 1 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.c | 51 | ||||
-rw-r--r-- | fs/xfs/xfs_fs.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_fsops.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_sb.h | 10 |
6 files changed, 68 insertions, 4 deletions
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 4edc46915b57..aded57321b12 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -76,6 +76,7 @@ | |||
76 | #include <linux/log2.h> | 76 | #include <linux/log2.h> |
77 | #include <linux/spinlock.h> | 77 | #include <linux/spinlock.h> |
78 | #include <linux/random.h> | 78 | #include <linux/random.h> |
79 | #include <linux/ctype.h> | ||
79 | 80 | ||
80 | #include <asm/page.h> | 81 | #include <asm/page.h> |
81 | #include <asm/div64.h> | 82 | #include <asm/div64.h> |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 41eea24a46e4..cce59cc6e748 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -569,7 +569,10 @@ xfs_set_inodeops( | |||
569 | inode->i_mapping->a_ops = &xfs_address_space_operations; | 569 | inode->i_mapping->a_ops = &xfs_address_space_operations; |
570 | break; | 570 | break; |
571 | case S_IFDIR: | 571 | case S_IFDIR: |
572 | inode->i_op = &xfs_dir_inode_operations; | 572 | if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) |
573 | inode->i_op = &xfs_dir_ci_inode_operations; | ||
574 | else | ||
575 | inode->i_op = &xfs_dir_inode_operations; | ||
573 | inode->i_fop = &xfs_dir_file_operations; | 576 | inode->i_fop = &xfs_dir_file_operations; |
574 | break; | 577 | break; |
575 | case S_IFLNK: | 578 | case S_IFLNK: |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 882609c699c8..b445ec314764 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -48,6 +48,52 @@ struct xfs_name xfs_name_dotdot = {"..", 2}; | |||
48 | 48 | ||
49 | extern const struct xfs_nameops xfs_default_nameops; | 49 | extern const struct xfs_nameops xfs_default_nameops; |
50 | 50 | ||
51 | /* | ||
52 | * ASCII case-insensitive (ie. A-Z) support for directories that was | ||
53 | * used in IRIX. | ||
54 | */ | ||
55 | STATIC xfs_dahash_t | ||
56 | xfs_ascii_ci_hashname( | ||
57 | struct xfs_name *name) | ||
58 | { | ||
59 | xfs_dahash_t hash; | ||
60 | int i; | ||
61 | |||
62 | for (i = 0, hash = 0; i < name->len; i++) | ||
63 | hash = tolower(name->name[i]) ^ rol32(hash, 7); | ||
64 | |||
65 | return hash; | ||
66 | } | ||
67 | |||
68 | STATIC enum xfs_dacmp | ||
69 | xfs_ascii_ci_compname( | ||
70 | struct xfs_da_args *args, | ||
71 | const char *name, | ||
72 | int len) | ||
73 | { | ||
74 | enum xfs_dacmp result; | ||
75 | int i; | ||
76 | |||
77 | if (args->namelen != len) | ||
78 | return XFS_CMP_DIFFERENT; | ||
79 | |||
80 | result = XFS_CMP_EXACT; | ||
81 | for (i = 0; i < len; i++) { | ||
82 | if (args->name[i] == name[i]) | ||
83 | continue; | ||
84 | if (tolower(args->name[i]) != tolower(name[i])) | ||
85 | return XFS_CMP_DIFFERENT; | ||
86 | result = XFS_CMP_CASE; | ||
87 | } | ||
88 | |||
89 | return result; | ||
90 | } | ||
91 | |||
92 | static struct xfs_nameops xfs_ascii_ci_nameops = { | ||
93 | .hashname = xfs_ascii_ci_hashname, | ||
94 | .compname = xfs_ascii_ci_compname, | ||
95 | }; | ||
96 | |||
51 | void | 97 | void |
52 | xfs_dir_mount( | 98 | xfs_dir_mount( |
53 | xfs_mount_t *mp) | 99 | xfs_mount_t *mp) |
@@ -67,7 +113,10 @@ xfs_dir_mount( | |||
67 | (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) / | 113 | (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) / |
68 | (uint)sizeof(xfs_da_node_entry_t); | 114 | (uint)sizeof(xfs_da_node_entry_t); |
69 | mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; | 115 | mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; |
70 | mp->m_dirnameops = &xfs_default_nameops; | 116 | if (xfs_sb_version_hasasciici(&mp->m_sb)) |
117 | mp->m_dirnameops = &xfs_ascii_ci_nameops; | ||
118 | else | ||
119 | mp->m_dirnameops = &xfs_default_nameops; | ||
71 | } | 120 | } |
72 | 121 | ||
73 | /* | 122 | /* |
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index 3bed6433d050..6ca749897c58 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h | |||
@@ -239,6 +239,7 @@ typedef struct xfs_fsop_resblks { | |||
239 | #define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */ | 239 | #define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */ |
240 | #define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */ | 240 | #define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */ |
241 | #define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */ | 241 | #define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */ |
242 | #define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */ | ||
242 | #define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */ | 243 | #define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */ |
243 | 244 | ||
244 | 245 | ||
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 381ebda4f7bc..84583cf73db3 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -95,6 +95,8 @@ xfs_fs_geometry( | |||
95 | XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) | | 95 | XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) | |
96 | (xfs_sb_version_hassector(&mp->m_sb) ? | 96 | (xfs_sb_version_hassector(&mp->m_sb) ? |
97 | XFS_FSOP_GEOM_FLAGS_SECTOR : 0) | | 97 | XFS_FSOP_GEOM_FLAGS_SECTOR : 0) | |
98 | (xfs_sb_version_hasasciici(&mp->m_sb) ? | ||
99 | XFS_FSOP_GEOM_FLAGS_DIRV2CI : 0) | | ||
98 | (xfs_sb_version_haslazysbcount(&mp->m_sb) ? | 100 | (xfs_sb_version_haslazysbcount(&mp->m_sb) ? |
99 | XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) | | 101 | XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) | |
100 | (xfs_sb_version_hasattr2(&mp->m_sb) ? | 102 | (xfs_sb_version_hasattr2(&mp->m_sb) ? |
@@ -625,7 +627,7 @@ xfs_fs_goingdown( | |||
625 | xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT); | 627 | xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT); |
626 | thaw_bdev(sb->s_bdev, sb); | 628 | thaw_bdev(sb->s_bdev, sb); |
627 | } | 629 | } |
628 | 630 | ||
629 | break; | 631 | break; |
630 | } | 632 | } |
631 | case XFS_FSOP_GOING_FLAGS_LOGFLUSH: | 633 | case XFS_FSOP_GOING_FLAGS_LOGFLUSH: |
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h index e3204a36a222..3f8cf1587f4c 100644 --- a/fs/xfs/xfs_sb.h +++ b/fs/xfs/xfs_sb.h | |||
@@ -46,10 +46,12 @@ struct xfs_mount; | |||
46 | #define XFS_SB_VERSION_SECTORBIT 0x0800 | 46 | #define XFS_SB_VERSION_SECTORBIT 0x0800 |
47 | #define XFS_SB_VERSION_EXTFLGBIT 0x1000 | 47 | #define XFS_SB_VERSION_EXTFLGBIT 0x1000 |
48 | #define XFS_SB_VERSION_DIRV2BIT 0x2000 | 48 | #define XFS_SB_VERSION_DIRV2BIT 0x2000 |
49 | #define XFS_SB_VERSION_BORGBIT 0x4000 /* ASCII only case-insens. */ | ||
49 | #define XFS_SB_VERSION_MOREBITSBIT 0x8000 | 50 | #define XFS_SB_VERSION_MOREBITSBIT 0x8000 |
50 | #define XFS_SB_VERSION_OKSASHFBITS \ | 51 | #define XFS_SB_VERSION_OKSASHFBITS \ |
51 | (XFS_SB_VERSION_EXTFLGBIT | \ | 52 | (XFS_SB_VERSION_EXTFLGBIT | \ |
52 | XFS_SB_VERSION_DIRV2BIT) | 53 | XFS_SB_VERSION_DIRV2BIT | \ |
54 | XFS_SB_VERSION_BORGBIT) | ||
53 | #define XFS_SB_VERSION_OKREALFBITS \ | 55 | #define XFS_SB_VERSION_OKREALFBITS \ |
54 | (XFS_SB_VERSION_ATTRBIT | \ | 56 | (XFS_SB_VERSION_ATTRBIT | \ |
55 | XFS_SB_VERSION_NLINKBIT | \ | 57 | XFS_SB_VERSION_NLINKBIT | \ |
@@ -437,6 +439,12 @@ static inline int xfs_sb_version_hassector(xfs_sb_t *sbp) | |||
437 | ((sbp)->sb_versionnum & XFS_SB_VERSION_SECTORBIT); | 439 | ((sbp)->sb_versionnum & XFS_SB_VERSION_SECTORBIT); |
438 | } | 440 | } |
439 | 441 | ||
442 | static inline int xfs_sb_version_hasasciici(xfs_sb_t *sbp) | ||
443 | { | ||
444 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ | ||
445 | (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT); | ||
446 | } | ||
447 | |||
440 | static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) | 448 | static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) |
441 | { | 449 | { |
442 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ | 450 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ |