aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBarry Naujok <bnaujok@sgi.com>2008-05-21 02:58:55 -0400
committerNiv Sardi <xaiki@debian.org>2008-07-28 02:58:42 -0400
commit189f4bf22bdc3c2402b038016d11fd3cb1c89f07 (patch)
tree98a168b063b87609fc28685ace7ce0fec589beff
parent384f3ced07efdddf6838f6527366089d37843c94 (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.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c5
-rw-r--r--fs/xfs/xfs_dir2.c51
-rw-r--r--fs/xfs/xfs_fs.h1
-rw-r--r--fs/xfs/xfs_fsops.c4
-rw-r--r--fs/xfs/xfs_sb.h10
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
49extern const struct xfs_nameops xfs_default_nameops; 49extern 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 */
55STATIC xfs_dahash_t
56xfs_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
68STATIC enum xfs_dacmp
69xfs_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
92static struct xfs_nameops xfs_ascii_ci_nameops = {
93 .hashname = xfs_ascii_ci_hashname,
94 .compname = xfs_ascii_ci_compname,
95};
96
51void 97void
52xfs_dir_mount( 98xfs_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
442static 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
440static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) 448static 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) && \