Support case-insensitive ZFS subvolumes.

* grub-core/fs/zfs/zfs.c (mzap_lookup): New parameter case_insensitive.
	All users updated.
	(zap_hash): Likewise.
	(name_cmp): New function.
	(zap_leaf_array_equal): New parameter case_insensitive.
	All users updated.
	(zap_leaf_lookup): Likewise.
	(fzap_lookup): Likewise.
	(zap_lookup): Likewise.
	(dnode_get_path): New parameter case_insensitive. Retrieve case
	sensitiviness of a volume. All users updated.
	(dnode_get_fullpath): New parameter case_insensitive.
	All users updated.
	(grub_zfs_dir): Set info.case_insensitiveness.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-11-04 13:44:56 +01:00
parent 95f2e86095
commit 8622923b66
2 changed files with 101 additions and 30 deletions

View file

@ -1,3 +1,22 @@
2011-11-04 Vladimir Serbinenko <phcoder@gmail.com>
Support case-insensitive ZFS subvolumes.
* grub-core/fs/zfs/zfs.c (mzap_lookup): New parameter case_insensitive.
All users updated.
(zap_hash): Likewise.
(name_cmp): New function.
(zap_leaf_array_equal): New parameter case_insensitive.
All users updated.
(zap_leaf_lookup): Likewise.
(fzap_lookup): Likewise.
(zap_lookup): Likewise.
(dnode_get_path): New parameter case_insensitive. Retrieve case
sensitiviness of a volume. All users updated.
(dnode_get_fullpath): New parameter case_insensitive.
All users updated.
(grub_zfs_dir): Set info.case_insensitiveness.
2011-11-04 Vladimir Serbinenko <phcoder@gmail.com> 2011-11-04 Vladimir Serbinenko <phcoder@gmail.com>
Support second redundancy strip on raidz(2,3). Support second redundancy strip on raidz(2,3).

View file

@ -1448,7 +1448,8 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf,
*/ */
static grub_err_t static grub_err_t
mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
int objsize, char *name, grub_uint64_t * value) int objsize, char *name, grub_uint64_t * value,
int case_insensitive)
{ {
int i, chunks; int i, chunks;
mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk; mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
@ -1456,7 +1457,8 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
chunks = objsize / MZAP_ENT_LEN - 1; chunks = objsize / MZAP_ENT_LEN - 1;
for (i = 0; i < chunks; i++) for (i = 0; i < chunks; i++)
{ {
if (grub_strcmp (mzap_ent[i].mze_name, name) == 0) if (case_insensitive ? (grub_strcasecmp (mzap_ent[i].mze_name, name) == 0)
: (grub_strcmp (mzap_ent[i].mze_name, name) == 0))
{ {
*value = grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian); *value = grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -1489,7 +1491,8 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize,
} }
static grub_uint64_t static grub_uint64_t
zap_hash (grub_uint64_t salt, const char *name) zap_hash (grub_uint64_t salt, const char *name,
int case_insensitive)
{ {
static grub_uint64_t table[256]; static grub_uint64_t table[256];
const grub_uint8_t *cp; const grub_uint8_t *cp;
@ -1507,6 +1510,10 @@ zap_hash (grub_uint64_t salt, const char *name)
} }
} }
if (case_insensitive)
for (cp = (const grub_uint8_t *) name; (c = *cp) != '\0'; cp++)
crc = (crc >> 8) ^ table[(crc ^ grub_toupper (c)) & 0xFF];
else
for (cp = (const grub_uint8_t *) name; (c = *cp) != '\0'; cp++) for (cp = (const grub_uint8_t *) name; (c = *cp) != '\0'; cp++)
crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF]; crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF];
@ -1526,10 +1533,34 @@ zap_hash (grub_uint64_t salt, const char *name)
* array_len is actual len in bytes (not encoded le_value_length). * array_len is actual len in bytes (not encoded le_value_length).
* buf is null-terminated. * buf is null-terminated.
*/ */
static inline int
name_cmp (const char *s1, const char *s2, grub_size_t n,
int case_insensitive)
{
const char *t1 = (const char *) s1;
const char *t2 = (const char *) s2;
if (!case_insensitive)
return grub_memcmp (t1, t2, n);
while (n--)
{
if (grub_toupper (*t1) != grub_toupper (*t2))
return (int) grub_toupper (*t1) - (int) grub_toupper (*t2);
t1++;
t2++;
}
return 0;
}
/* XXX */ /* XXX */
static int static int
zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
int blksft, int chunk, int array_len, const char *buf) int blksft, int chunk, int array_len, const char *buf,
int case_insensitive)
{ {
int bseen = 0; int bseen = 0;
@ -1541,7 +1572,8 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft)) if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft))
return (0); return (0);
if (grub_memcmp (la->la_array, buf + bseen, toread) != 0) if (name_cmp ((char *) la->la_array, buf + bseen, toread,
case_insensitive) != 0)
break; break;
chunk = grub_zfs_to_cpu16 (la->la_next, endian); chunk = grub_zfs_to_cpu16 (la->la_next, endian);
bseen += toread; bseen += toread;
@ -1582,7 +1614,8 @@ zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft,
static grub_err_t static grub_err_t
zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
int blksft, grub_uint64_t h, int blksft, grub_uint64_t h,
const char *name, grub_uint64_t * value) const char *name, grub_uint64_t * value,
int case_insensitive)
{ {
grub_uint16_t chunk; grub_uint16_t chunk;
struct zap_leaf_entry *le; struct zap_leaf_entry *le;
@ -1614,7 +1647,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
if (zap_leaf_array_equal (l, endian, blksft, if (zap_leaf_array_equal (l, endian, blksft,
grub_zfs_to_cpu16 (le->le_name_chunk,endian), grub_zfs_to_cpu16 (le->le_name_chunk,endian),
grub_zfs_to_cpu16 (le->le_name_length, endian), grub_zfs_to_cpu16 (le->le_name_length, endian),
name)) name, case_insensitive))
{ {
struct zap_leaf_array *la; struct zap_leaf_array *la;
@ -1658,7 +1691,8 @@ zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian)
/* XXX */ /* XXX */
static grub_err_t static grub_err_t
fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
char *name, grub_uint64_t * value, struct grub_zfs_data *data) char *name, grub_uint64_t * value, struct grub_zfs_data *data,
int case_insensitive)
{ {
void *l; void *l;
grub_uint64_t hash, idx, blkid; grub_uint64_t hash, idx, blkid;
@ -1671,7 +1705,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
if (err) if (err)
return err; return err;
hash = zap_hash (zap->zap_salt, name); hash = zap_hash (zap->zap_salt, name, case_insensitive);
/* get block id from index */ /* get block id from index */
if (zap->zap_ptrtbl.zt_numblks != 0) if (zap->zap_ptrtbl.zt_numblks != 0)
@ -1687,7 +1721,8 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
if (err) if (err)
return err; return err;
err = zap_leaf_lookup (l, leafendian, blksft, hash, name, value); err = zap_leaf_lookup (l, leafendian, blksft, hash, name, value,
case_insensitive);
grub_free (l); grub_free (l);
return err; return err;
} }
@ -1806,7 +1841,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
*/ */
static grub_err_t static grub_err_t
zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val, zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val,
struct grub_zfs_data *data) struct grub_zfs_data *data, int case_insensitive)
{ {
grub_uint64_t block_type; grub_uint64_t block_type;
int size; int size;
@ -1829,7 +1864,8 @@ zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val,
if (block_type == ZBT_MICRO) if (block_type == ZBT_MICRO)
{ {
grub_dprintf ("zfs", "micro zap\n"); grub_dprintf ("zfs", "micro zap\n");
err = (mzap_lookup (zapbuf, endian, size, name, val)); err = mzap_lookup (zapbuf, endian, size, name, val,
case_insensitive);
grub_dprintf ("zfs", "returned %d\n", err); grub_dprintf ("zfs", "returned %d\n", err);
grub_free (zapbuf); grub_free (zapbuf);
return err; return err;
@ -1838,7 +1874,8 @@ zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val,
{ {
grub_dprintf ("zfs", "fat zap\n"); grub_dprintf ("zfs", "fat zap\n");
/* this is a fat zap */ /* this is a fat zap */
err = (fzap_lookup (zap_dnode, zapbuf, name, val, data)); err = fzap_lookup (zap_dnode, zapbuf, name, val, data,
case_insensitive);
grub_dprintf ("zfs", "returned %d\n", err); grub_dprintf ("zfs", "returned %d\n", err);
grub_free (zapbuf); grub_free (zapbuf);
return err; return err;
@ -1964,9 +2001,9 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type,
*/ */
static grub_err_t static grub_err_t
dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
struct grub_zfs_data *data) struct grub_zfs_data *data, int *case_insensitive)
{ {
grub_uint64_t objnum, version; grub_uint64_t objnum, version, insensitivity;
char *cname, ch; char *cname, ch;
grub_err_t err = GRUB_ERR_NONE; grub_err_t err = GRUB_ERR_NONE;
char *path, *path_buf; char *path, *path_buf;
@ -1991,19 +2028,31 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
return err; return err;
} }
err = zap_lookup (&(dnode_path->dn), ZPL_VERSION_STR, &version, data); err = zap_lookup (&(dnode_path->dn), ZPL_VERSION_STR, &version,
data, 0);
if (err) if (err)
{ {
grub_free (dn_new); grub_free (dn_new);
return err; return err;
} }
if (version > ZPL_VERSION) if (version > ZPL_VERSION)
{ {
grub_free (dn_new); grub_free (dn_new);
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "too new ZPL version"); return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "too new ZPL version");
} }
err = zap_lookup (&(dnode_path->dn), ZFS_ROOT_OBJ, &objnum, data); err = zap_lookup (&(dnode_path->dn), "casesensitivity", &insensitivity,
data, 0);
if (err == GRUB_ERR_FILE_NOT_FOUND)
{
grub_errno = GRUB_ERR_NONE;
insensitivity = 0;
}
if (case_insensitive)
*case_insensitive = insensitivity;
err = zap_lookup (&(dnode_path->dn), ZFS_ROOT_OBJ, &objnum, data, 0);
if (err) if (err)
{ {
grub_free (dn_new); grub_free (dn_new);
@ -2064,7 +2113,7 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
grub_free (path_buf); grub_free (path_buf);
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
} }
err = zap_lookup (&(dnode_path->dn), cname, &objnum, data); err = zap_lookup (&(dnode_path->dn), cname, &objnum, data, insensitivity);
if (err) if (err)
break; break;
@ -2296,7 +2345,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
grub_dprintf ("zfs", "alive\n"); grub_dprintf ("zfs", "alive\n");
err = zap_lookup (mdn, DMU_POOL_ROOT_DATASET, &objnum, data); err = zap_lookup (mdn, DMU_POOL_ROOT_DATASET, &objnum, data, 0);
if (err) if (err)
return err; return err;
@ -2331,7 +2380,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
if (err) if (err)
return err; return err;
err = zap_lookup (mdn, cname, &objnum, data); err = zap_lookup (mdn, cname, &objnum, data, 0);
if (err) if (err)
return err; return err;
@ -2374,7 +2423,7 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
static grub_err_t static grub_err_t
dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn, dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn,
grub_uint64_t *mdnobj, dnode_end_t * dn, int *isfs, grub_uint64_t *mdnobj, dnode_end_t * dn, int *isfs,
struct grub_zfs_data *data) struct grub_zfs_data *data, int *case_insensitive)
{ {
char *fsname, *snapname; char *fsname, *snapname;
const char *ptr_at, *filename; const char *ptr_at, *filename;
@ -2452,7 +2501,7 @@ dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn,
err = dnode_get (&(data->mos), snapobj, err = dnode_get (&(data->mos), snapobj,
DMU_OT_DSL_DS_SNAP_MAP, mdn, data); DMU_OT_DSL_DS_SNAP_MAP, mdn, data);
if (!err) if (!err)
err = zap_lookup (mdn, snapname, &headobj, data); err = zap_lookup (mdn, snapname, &headobj, data, 0);
if (!err) if (!err)
err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data); err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data);
if (err) if (err)
@ -2476,7 +2525,7 @@ dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn,
grub_free (snapname); grub_free (snapname);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
err = dnode_get_path (mdn, filename, dn, data); err = dnode_get_path (mdn, filename, dn, data, case_insensitive);
grub_free (fsname); grub_free (fsname);
grub_free (snapname); grub_free (snapname);
return err; return err;
@ -2916,7 +2965,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename)
return grub_errno; return grub_errno;
err = dnode_get_fullpath (fsfilename, &(data->mdn), 0, err = dnode_get_fullpath (fsfilename, &(data->mdn), 0,
&(data->dnode), &isfs, data); &(data->dnode), &isfs, data, NULL);
if (err) if (err)
{ {
zfs_unmount (data); zfs_unmount (data);
@ -3080,7 +3129,7 @@ grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename,
return grub_errno; return grub_errno;
err = dnode_get_fullpath (fsfilename, &(data->mdn), mdnobj, err = dnode_get_fullpath (fsfilename, &(data->mdn), mdnobj,
&(data->dnode), &isfs, data); &(data->dnode), &isfs, data, NULL);
zfs_unmount (data); zfs_unmount (data);
return err; return err;
} }
@ -3118,7 +3167,7 @@ fill_fs_info (struct grub_dirhook_info *info,
return; return;
} }
err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data); err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data, 0);
if (err) if (err)
{ {
grub_dprintf ("zfs", "failed here\n"); grub_dprintf ("zfs", "failed here\n");
@ -3175,6 +3224,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
struct grub_zfs_data *data; struct grub_zfs_data *data;
grub_err_t err; grub_err_t err;
int isfs; int isfs;
int case_insensitive = 0;
auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val); auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val);
auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name,
grub_uint64_t val); grub_uint64_t val);
@ -3219,6 +3269,7 @@ grub_zfs_dir (grub_device_t device, const char *path,
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); info.mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
info.case_insensitive = case_insensitive;
} }
if (dn.dn.dn_bonustype == DMU_OT_ZNODE) if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
@ -3273,7 +3324,8 @@ grub_zfs_dir (grub_device_t device, const char *path,
data = zfs_mount (device); data = zfs_mount (device);
if (! data) if (! data)
return grub_errno; return grub_errno;
err = dnode_get_fullpath (path, &(data->mdn), 0, &(data->dnode), &isfs, data); err = dnode_get_fullpath (path, &(data->mdn), 0, &(data->dnode), &isfs, data,
&case_insensitive);
if (err) if (err)
{ {
zfs_unmount (data); zfs_unmount (data);