ZFS fixes.
* grub-core/fs/zfs/zfs.c (fzap_iterate): Fix handling of indexes sharing the same block. Iterate over correct number of indices. (dnode_get_path): Handle symlinks correctly.
This commit is contained in:
parent
c0584900ee
commit
5587329c91
2 changed files with 59 additions and 13 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2011-10-25 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
ZFS fixes.
|
||||||
|
|
||||||
|
* grub-core/fs/zfs/zfs.c (fzap_iterate): Fix handling of indexes
|
||||||
|
sharing the same block. Iterate over correct number of indices.
|
||||||
|
(dnode_get_path): Handle symlinks correctly.
|
||||||
|
|
||||||
2011-10-25 Vladimir Serbinenko <phcoder@gmail.com>
|
2011-10-25 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/fs/jfs.c (grub_jfs_sblock): Fix offset to volname.
|
* grub-core/fs/jfs.c (grub_jfs_sblock): Fix offset to volname.
|
||||||
|
|
|
@ -941,7 +941,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||||
{
|
{
|
||||||
zap_leaf_phys_t *l;
|
zap_leaf_phys_t *l;
|
||||||
void *l_in;
|
void *l_in;
|
||||||
grub_uint64_t idx, blkid;
|
grub_uint64_t idx, idx2, blkid;
|
||||||
grub_uint16_t chunk;
|
grub_uint16_t chunk;
|
||||||
int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec,
|
int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec,
|
||||||
zap_dnode->endian) << DNODE_SHIFT);
|
zap_dnode->endian) << DNODE_SHIFT);
|
||||||
|
@ -964,10 +964,16 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||||
grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small");
|
grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (idx = 0; idx < zap->zap_ptrtbl.zt_numblks; idx++)
|
for (idx = 0; idx < (1ULL << zap->zap_ptrtbl.zt_shift); idx++)
|
||||||
{
|
{
|
||||||
blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))];
|
blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))];
|
||||||
|
|
||||||
|
for (idx2 = 0; idx2 < idx; idx2++)
|
||||||
|
if (blkid == ((grub_uint64_t *) zap)[idx2 + (1 << (blksft - 3 - 1))])
|
||||||
|
break;
|
||||||
|
if (idx2 != idx)
|
||||||
|
continue;
|
||||||
|
|
||||||
err = dmu_read (zap_dnode, blkid, &l_in, &endian, data);
|
err = dmu_read (zap_dnode, blkid, &l_in, &endian, data);
|
||||||
l = l_in;
|
l = l_in;
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1093,7 +1099,7 @@ zap_iterate (dnode_end_t * zap_dnode,
|
||||||
return 0;
|
return 0;
|
||||||
block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
|
block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
|
||||||
|
|
||||||
grub_dprintf ("zfs", "zap read\n");
|
grub_dprintf ("zfs", "zap iterate\n");
|
||||||
|
|
||||||
if (block_type == ZBT_MICRO)
|
if (block_type == ZBT_MICRO)
|
||||||
{
|
{
|
||||||
|
@ -1310,22 +1316,55 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
*path = ch;
|
*path = ch;
|
||||||
#if 0
|
if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
|
||||||
if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa && ch)
|
|
||||||
{
|
{
|
||||||
|
char *sym_value;
|
||||||
|
grub_size_t avail_in_dnode;
|
||||||
|
grub_size_t sym_sz;
|
||||||
|
int free_symval = 0;
|
||||||
char *oldpath = path, *oldpathbuf = path_buf;
|
char *oldpath = path, *oldpathbuf = path_buf;
|
||||||
path = path_buf
|
sym_value = ((char *) DN_BONUS (&dnode_path->dn.dn) + sizeof (struct znode_phys));
|
||||||
= grub_malloc (sizeof (dnode_path->dn.dn.dn_bonus)
|
avail_in_dnode = (char *) (&dnode_path->dn + 1) - sym_value;
|
||||||
- sizeof (znode_phys_t) + grub_strlen (oldpath) + 1);
|
|
||||||
|
sym_sz = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_size, dnode_path->dn.endian);
|
||||||
|
|
||||||
|
if (sym_sz > avail_in_dnode - 8)
|
||||||
|
{
|
||||||
|
grub_size_t block;
|
||||||
|
grub_size_t blksz;
|
||||||
|
blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec,
|
||||||
|
dnode_path->dn.endian)
|
||||||
|
<< SPA_MINBLOCKSHIFT);
|
||||||
|
|
||||||
|
sym_value = grub_malloc (sym_sz);
|
||||||
|
if (!sym_value)
|
||||||
|
return grub_errno;
|
||||||
|
for (block = 0; block < (sym_sz + blksz - 1) / blksz; block++)
|
||||||
|
{
|
||||||
|
void *t;
|
||||||
|
grub_size_t movesize;
|
||||||
|
|
||||||
|
err = dmu_read (&(dnode_path->dn), block, &t, 0, data);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
movesize = MIN (sym_sz - block * blksz, blksz);
|
||||||
|
|
||||||
|
grub_memcpy (sym_value + block * blksz, t, movesize);
|
||||||
|
grub_free (t);
|
||||||
|
}
|
||||||
|
free_symval = 1;
|
||||||
|
}
|
||||||
|
path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
|
||||||
if (!path_buf)
|
if (!path_buf)
|
||||||
{
|
{
|
||||||
grub_free (oldpathbuf);
|
grub_free (oldpathbuf);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
grub_memcpy (path,
|
grub_memcpy (path, sym_value, sym_sz);
|
||||||
(char *) DN_BONUS(&dnode_path->dn.dn) + sizeof (znode_phys_t),
|
if (free_symval)
|
||||||
sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t));
|
grub_free (sym_value);
|
||||||
path [sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t)] = 0;
|
path [sym_sz] = 0;
|
||||||
grub_memcpy (path + grub_strlen (path), oldpath,
|
grub_memcpy (path + grub_strlen (path), oldpath,
|
||||||
grub_strlen (oldpath) + 1);
|
grub_strlen (oldpath) + 1);
|
||||||
|
|
||||||
|
@ -1343,7 +1382,6 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
|
||||||
grub_free (dn_new);
|
grub_free (dn_new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
|
|
Loading…
Reference in a new issue