diff options
author | avg <avg@FreeBSD.org> | 2012-10-06 19:27:04 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2012-10-06 19:27:04 +0000 |
commit | 206248e53f3a5651d6cb7aa841c5c5cc8d4e0ed3 (patch) | |
tree | 008871f8445257797389b3349d566103ef003519 | |
parent | e94fd6dd0bd4747f0f1cc7da1ee1c718aee4a146 (diff) | |
download | FreeBSD-src-206248e53f3a5651d6cb7aa841c5c5cc8d4e0ed3.zip FreeBSD-src-206248e53f3a5651d6cb7aa841c5c5cc8d4e0ed3.tar.gz |
zfs boot: add code for listing child datasets of a given dataset
- only filesystem datasets are supported
- children names are printed to stdout
To do: allow to iterate over the list and fetch names programatically
MFC after: 17 days
-rw-r--r-- | sys/boot/zfs/libzfs.h | 1 | ||||
-rw-r--r-- | sys/boot/zfs/zfs.c | 35 | ||||
-rw-r--r-- | sys/boot/zfs/zfsimpl.c | 36 |
3 files changed, 68 insertions, 4 deletions
diff --git a/sys/boot/zfs/libzfs.h b/sys/boot/zfs/libzfs.h index 5c114db..92611db 100644 --- a/sys/boot/zfs/libzfs.h +++ b/sys/boot/zfs/libzfs.h @@ -59,6 +59,7 @@ int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, const char **path); char *zfs_fmtdev(void *vdev); int zfs_probe_dev(const char *devname, uint64_t *pool_guid); +int zfs_list(const char *name); extern struct devsw zfs_dev; extern struct fs_ops zfs_fsops; diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c index eb8833f..3fc5f50 100644 --- a/sys/boot/zfs/zfs.c +++ b/sys/boot/zfs/zfs.c @@ -658,3 +658,38 @@ zfs_fmtdev(void *vdev) rootname); return (buf); } + +int +zfs_list(const char *name) +{ + static char poolname[ZFS_MAXNAMELEN]; + uint64_t objid; + spa_t *spa; + const char *dsname; + int len; + int rv; + + len = strlen(name); + dsname = strchr(name, '/'); + if (dsname != NULL) { + len = dsname - name; + dsname++; + } + memcpy(poolname, name, len); + poolname[len] = '\0'; + + spa = spa_find_by_name(poolname); + if (!spa) + return (ENXIO); + rv = zfs_spa_init(spa); + if (rv != 0) + return (rv); + if (dsname != NULL) + rv = zfs_lookup_dataset(spa, dsname, &objid); + else + rv = zfs_get_root(spa, &objid); + if (rv != 0) + return (rv); + rv = zfs_list_dataset(spa, objid); + return (0); +} diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c index d387a6e..3ce57f8 100644 --- a/sys/boot/zfs/zfsimpl.c +++ b/sys/boot/zfs/zfsimpl.c @@ -1387,8 +1387,6 @@ zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64 return (EIO); } -#ifdef BOOT2 - /* * List a microzap directory. Assumes that the zap scratch buffer contains * the directory contents. @@ -1513,8 +1511,6 @@ zap_list(const spa_t *spa, const dnode_phys_t *dnode) return fzap_list(spa, dnode); } -#endif - static int objset_get_dnode(const spa_t *spa, const objset_phys_t *os, uint64_t objnum, dnode_phys_t *dnode) { @@ -1751,6 +1747,38 @@ zfs_lookup_dataset(const spa_t *spa, const char *name, uint64_t *objnum) return (0); } +#ifndef BOOT2 +static int +zfs_list_dataset(const spa_t *spa, uint64_t objnum/*, int pos, char *entry*/) +{ + uint64_t dir_obj, child_dir_zapobj; + dnode_phys_t child_dir_zap, dir, dataset; + dsl_dataset_phys_t *ds; + dsl_dir_phys_t *dd; + + if (objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset)) { + printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum); + return (EIO); + } + ds = (dsl_dataset_phys_t *) &dataset.dn_bonus; + dir_obj = ds->ds_dir_obj; + + if (objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir)) { + printf("ZFS: can't find dirobj %ju\n", (uintmax_t)dir_obj); + return (EIO); + } + dd = (dsl_dir_phys_t *)&dir.dn_bonus; + + child_dir_zapobj = dd->dd_child_dir_zapobj; + if (objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj, &child_dir_zap) != 0) { + printf("ZFS: can't find child zap %ju\n", (uintmax_t)dir_obj); + return (EIO); + } + + return (zap_list(spa, &child_dir_zap) != 0); +} +#endif + /* * Find the object set given the object number of its dataset object * and return its details in *objset |