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:
Vladimir 'phcoder' Serbinenko 2011-10-26 17:32:21 +02:00
parent c0584900ee
commit 5587329c91
2 changed files with 59 additions and 13 deletions

View file

@ -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.

View file

@ -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)