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:
parent
95f2e86095
commit
8622923b66
2 changed files with 101 additions and 30 deletions
19
ChangeLog
19
ChangeLog
|
@ -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>
|
||||
|
||||
Support second redundancy strip on raidz(2,3).
|
||||
|
|
|
@ -1448,7 +1448,8 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf,
|
|||
*/
|
||||
static grub_err_t
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
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
|
||||
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];
|
||||
const grub_uint8_t *cp;
|
||||
|
@ -1507,8 +1510,12 @@ zap_hash (grub_uint64_t salt, const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
for (cp = (const grub_uint8_t *) name; (c = *cp) != '\0'; cp++)
|
||||
crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF];
|
||||
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++)
|
||||
crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF];
|
||||
|
||||
/*
|
||||
* Only use 28 bits, since we need 4 bits in the cookie for the
|
||||
|
@ -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).
|
||||
* 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 */
|
||||
static int
|
||||
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;
|
||||
|
||||
|
@ -1541,7 +1572,8 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
|
|||
if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft))
|
||||
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;
|
||||
chunk = grub_zfs_to_cpu16 (la->la_next, endian);
|
||||
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
|
||||
zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
|
||||
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;
|
||||
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,
|
||||
grub_zfs_to_cpu16 (le->le_name_chunk,endian),
|
||||
grub_zfs_to_cpu16 (le->le_name_length, endian),
|
||||
name))
|
||||
name, case_insensitive))
|
||||
{
|
||||
struct zap_leaf_array *la;
|
||||
|
||||
|
@ -1658,7 +1691,8 @@ zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian)
|
|||
/* XXX */
|
||||
static grub_err_t
|
||||
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;
|
||||
grub_uint64_t hash, idx, blkid;
|
||||
|
@ -1671,7 +1705,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
hash = zap_hash (zap->zap_salt, name);
|
||||
hash = zap_hash (zap->zap_salt, name, case_insensitive);
|
||||
|
||||
/* get block id from index */
|
||||
if (zap->zap_ptrtbl.zt_numblks != 0)
|
||||
|
@ -1687,7 +1721,8 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
|||
if (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);
|
||||
return err;
|
||||
}
|
||||
|
@ -1806,7 +1841,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
|||
*/
|
||||
static grub_err_t
|
||||
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;
|
||||
int size;
|
||||
|
@ -1829,7 +1864,8 @@ zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val,
|
|||
if (block_type == ZBT_MICRO)
|
||||
{
|
||||
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_free (zapbuf);
|
||||
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");
|
||||
/* 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_free (zapbuf);
|
||||
return err;
|
||||
|
@ -1964,9 +2001,9 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type,
|
|||
*/
|
||||
static grub_err_t
|
||||
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;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
grub_free (dn_new);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (version > ZPL_VERSION)
|
||||
{
|
||||
grub_free (dn_new);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
break;
|
||||
|
||||
|
@ -2296,7 +2345,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
|
|||
|
||||
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)
|
||||
return err;
|
||||
|
||||
|
@ -2331,7 +2380,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = zap_lookup (mdn, cname, &objnum, data);
|
||||
err = zap_lookup (mdn, cname, &objnum, data, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -2374,7 +2423,7 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
|
|||
static grub_err_t
|
||||
dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn,
|
||||
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;
|
||||
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,
|
||||
DMU_OT_DSL_DS_SNAP_MAP, mdn, data);
|
||||
if (!err)
|
||||
err = zap_lookup (mdn, snapname, &headobj, data);
|
||||
err = zap_lookup (mdn, snapname, &headobj, data, 0);
|
||||
if (!err)
|
||||
err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data);
|
||||
if (err)
|
||||
|
@ -2476,7 +2525,7 @@ dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn,
|
|||
grub_free (snapname);
|
||||
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 (snapname);
|
||||
return err;
|
||||
|
@ -2916,7 +2965,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename)
|
|||
return grub_errno;
|
||||
|
||||
err = dnode_get_fullpath (fsfilename, &(data->mdn), 0,
|
||||
&(data->dnode), &isfs, data);
|
||||
&(data->dnode), &isfs, data, NULL);
|
||||
if (err)
|
||||
{
|
||||
zfs_unmount (data);
|
||||
|
@ -3080,7 +3129,7 @@ grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename,
|
|||
return grub_errno;
|
||||
|
||||
err = dnode_get_fullpath (fsfilename, &(data->mdn), mdnobj,
|
||||
&(data->dnode), &isfs, data);
|
||||
&(data->dnode), &isfs, data, NULL);
|
||||
zfs_unmount (data);
|
||||
return err;
|
||||
}
|
||||
|
@ -3118,7 +3167,7 @@ fill_fs_info (struct grub_dirhook_info *info,
|
|||
return;
|
||||
}
|
||||
|
||||
err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data);
|
||||
err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data, 0);
|
||||
if (err)
|
||||
{
|
||||
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;
|
||||
grub_err_t err;
|
||||
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_fs (const char *name,
|
||||
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));
|
||||
info.mtimeset = 1;
|
||||
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)
|
||||
|
@ -3273,7 +3324,8 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
data = zfs_mount (device);
|
||||
if (! data)
|
||||
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)
|
||||
{
|
||||
zfs_unmount (data);
|
||||
|
|
Loading…
Reference in a new issue