Support version 33 including symlinks

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-10-27 02:04:04 +02:00
parent 11e50e923a
commit 34c5965451
3 changed files with 141 additions and 13 deletions

View file

@ -1839,19 +1839,18 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
break; break;
*path = ch; *path = ch;
if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa) if (dnode_path->dn.dn.dn_bonustype == DMU_OT_ZNODE
&& ((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
{ {
char *sym_value; char *sym_value;
grub_size_t avail_in_dnode;
grub_size_t sym_sz; grub_size_t sym_sz;
int free_symval = 0; int free_symval = 0;
char *oldpath = path, *oldpathbuf = path_buf; char *oldpath = path, *oldpathbuf = path_buf;
sym_value = ((char *) DN_BONUS (&dnode_path->dn.dn) + sizeof (struct znode_phys)); sym_value = ((char *) DN_BONUS (&dnode_path->dn.dn) + sizeof (struct znode_phys));
avail_in_dnode = (char *) (&dnode_path->dn + 1) - sym_value;
sym_sz = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_size, dnode_path->dn.endian); 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) if (dnode_path->dn.dn.dn_flags & 1)
{ {
grub_size_t block; grub_size_t block;
grub_size_t blksz; grub_size_t blksz;
@ -1905,6 +1904,62 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
grub_free (dn_new); grub_free (dn_new);
} }
} }
if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA)
{
void *sahdrp;
int hdrsize;
if (dnode_path->dn.dn.dn_bonuslen != 0)
{
sahdrp = DN_BONUS (&dnode_path->dn.dn);
}
else if (dnode_path->dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
{
blkptr_t *bp = &dnode_path->dn.dn.dn_spill;
err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data);
if (err)
return err;
}
else
{
return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
}
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
if (((grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_TYPE_OFFSET), dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
{
char *sym_value = (char *) sahdrp + hdrsize + SA_SYMLINK_OFFSET;
grub_size_t sym_sz =
grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), dnode_path->dn.endian);
char *oldpath = path, *oldpathbuf = path_buf;
path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
if (!path_buf)
{
grub_free (oldpathbuf);
return grub_errno;
}
grub_memcpy (path, sym_value, sym_sz);
path [sym_sz] = 0;
grub_memcpy (path + grub_strlen (path), oldpath,
grub_strlen (oldpath) + 1);
grub_free (oldpathbuf);
if (path[0] != '/')
{
dn_new = dnode_path;
dnode_path = dn_new->next;
grub_free (dn_new);
}
else while (dnode_path != root)
{
dn_new = dnode_path;
dnode_path = dn_new->next;
grub_free (dn_new);
}
}
}
} }
if (!err) if (!err)
@ -2666,12 +2721,14 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename)
} }
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
file->size = *(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET); file->size = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian);
} }
else else if (data->dnode.dn.dn_bonustype == DMU_OT_ZNODE)
{ {
file->size = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&data->dnode.dn))->zp_size, data->dnode.endian); file->size = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&data->dnode.dn))->zp_size, data->dnode.endian);
} }
else
return grub_error (GRUB_ERR_BAD_FS, "bad bonus type");
file->data = data; file->data = data;
file->offset = 0; file->offset = 0;
@ -2830,8 +2887,39 @@ fill_fs_info (struct grub_dirhook_info *info,
return; return;
} }
info->mtimeset = 1; if (dn.dn.dn_bonustype == DMU_OT_SA)
info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian); {
void *sahdrp;
int hdrsize;
if (dn.dn.dn_bonuslen != 0)
{
sahdrp = (sa_hdr_phys_t *) DN_BONUS (&dn.dn);
}
else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
{
blkptr_t *bp = &dn.dn.dn_spill;
err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
if (err)
return;
}
else
{
grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
return;
}
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);
}
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
{
info->mtimeset = 1;
info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
}
return; return;
} }
@ -2855,10 +2943,47 @@ grub_zfs_dir (grub_device_t device, const char *path,
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
dnode_get (&(data->mdn), val, 0, &dn, data); dnode_get (&(data->mdn), val, 0, &dn, data);
info.mtimeset = 1;
info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian); if (dn.dn.dn_bonustype == DMU_OT_SA)
info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); {
grub_dprintf ("zfs", "type=%d, name=%s\n", void *sahdrp;
int hdrsize;
if (dn.dn.dn_bonuslen != 0)
{
sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn);
}
else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
{
blkptr_t *bp = &dn.dn.dn_spill;
err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
if (err)
{
grub_print_error ();
return 0;
}
}
else
{
grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
grub_print_error ();
return 0;
}
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);
}
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
{
info.mtimeset = 1;
info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
dn.endian);
}
info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
grub_dprintf ("zfs", "type=%d, name=%s\n",
(int)dn.dn.dn_type, (char *)name); (int)dn.dn.dn_type, (char *)name);
return hook (name, &info); return hook (name, &info);
} }

View file

@ -29,6 +29,9 @@ typedef struct sa_hdr_phys {
} sa_hdr_phys_t; } sa_hdr_phys_t;
#define SA_HDR_SIZE(hdr) BF32_GET_SB(hdr->sa_layout_info, 10, 16, 3, 0) #define SA_HDR_SIZE(hdr) BF32_GET_SB(hdr->sa_layout_info, 10, 16, 3, 0)
#define SA_TYPE_OFFSET 0x0
#define SA_SIZE_OFFSET 0x8 #define SA_SIZE_OFFSET 0x8
#define SA_MTIME_OFFSET 0x38
#define SA_SYMLINK_OFFSET 0xa0
#endif /* _SYS_SA_IMPL_H */ #endif /* _SYS_SA_IMPL_H */

View file

@ -28,7 +28,7 @@
/* /*
* On-disk version number. * On-disk version number.
*/ */
#define SPA_VERSION 31ULL #define SPA_VERSION 33ULL
/* /*
* The following are configuration names used in the nvlist describing a pool's * The following are configuration names used in the nvlist describing a pool's