summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2012-10-06 19:27:04 +0000
committeravg <avg@FreeBSD.org>2012-10-06 19:27:04 +0000
commit206248e53f3a5651d6cb7aa841c5c5cc8d4e0ed3 (patch)
tree008871f8445257797389b3349d566103ef003519
parente94fd6dd0bd4747f0f1cc7da1ee1c718aee4a146 (diff)
downloadFreeBSD-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.h1
-rw-r--r--sys/boot/zfs/zfs.c35
-rw-r--r--sys/boot/zfs/zfsimpl.c36
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
OpenPOWER on IntegriCloud