diff options
| author | Pawel Jakub Dawidek <pjd@FreeBSD.org> | 2008-11-17 20:49:29 +0000 |
|---|---|---|
| committer | Pawel Jakub Dawidek <pjd@FreeBSD.org> | 2008-11-17 20:49:29 +0000 |
| commit | 1ba4a712dde6e6c613fc411a96958b4ade67de4c (patch) | |
| tree | 81b89fa4ac6467771d5aa291a97f4665981a6108 /sys/cddl/compat/opensolaris/kern/opensolaris_zone.c | |
| parent | 8fc061164d74a4c9775f39da3c0b5d02112866c8 (diff) | |
Notes
Diffstat (limited to 'sys/cddl/compat/opensolaris/kern/opensolaris_zone.c')
| -rw-r--r-- | sys/cddl/compat/opensolaris/kern/opensolaris_zone.c | 104 |
1 files changed, 57 insertions, 47 deletions
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_zone.c b/sys/cddl/compat/opensolaris/kern/opensolaris_zone.c index 3059a787d98c..8489052373d0 100644 --- a/sys/cddl/compat/opensolaris/kern/opensolaris_zone.c +++ b/sys/cddl/compat/opensolaris/kern/opensolaris_zone.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/queue.h> #include <sys/jail.h> +#include <sys/osd.h> #include <sys/priv.h> #include <sys/zone.h> @@ -52,7 +53,7 @@ typedef struct zone_dataset { LIST_HEAD(zone_dataset_head, zone_dataset); -static struct prison_service *zone_prison_service = NULL; +static int zone_slot; int zone_dataset_attach(struct ucred *cred, const char *dataset, int jailid) @@ -60,7 +61,7 @@ zone_dataset_attach(struct ucred *cred, const char *dataset, int jailid) struct zone_dataset_head *head; zone_dataset_t *zd, *zd2; struct prison *pr; - int error; + int dofree, error; if ((error = priv_check_cred(cred, PRIV_ZFS_JAIL, 0)) != 0) return (error); @@ -76,18 +77,33 @@ zone_dataset_attach(struct ucred *cred, const char *dataset, int jailid) return (ENOENT); } - head = prison_service_data_get(zone_prison_service, pr); - LIST_FOREACH(zd2, head, zd_next) { - if (strcmp(dataset, zd2->zd_dataset) == 0) { - free(zd, M_ZONES); - error = EEXIST; - goto failure; + head = osd_jail_get(pr, zone_slot); + if (head != NULL) { + dofree = 0; + LIST_FOREACH(zd2, head, zd_next) { + if (strcmp(dataset, zd2->zd_dataset) == 0) { + free(zd, M_ZONES); + error = EEXIST; + goto end; + } } + } else { + dofree = 1; + prison_hold_locked(pr); + mtx_unlock(&pr->pr_mtx); + head = malloc(sizeof(*head), M_ZONES, M_WAITOK); + LIST_INIT(head); + mtx_lock(&pr->pr_mtx); + error = osd_jail_set(pr, zone_slot, head); + KASSERT(error == 0, ("osd_jail_set() failed (error=%d)", error)); } strcpy(zd->zd_dataset, dataset); LIST_INSERT_HEAD(head, zd, zd_next); -failure: - mtx_unlock(&pr->pr_mtx); +end: + if (dofree) + prison_free_locked(pr); + else + mtx_unlock(&pr->pr_mtx); return (error); } @@ -107,16 +123,25 @@ zone_dataset_detach(struct ucred *cred, const char *dataset, int jailid) sx_sunlock(&allprison_lock); if (pr == NULL) return (ENOENT); - head = prison_service_data_get(zone_prison_service, pr); + head = osd_jail_get(pr, zone_slot); + if (head == NULL) { + error = ENOENT; + goto end; + } LIST_FOREACH(zd, head, zd_next) { - if (strcmp(dataset, zd->zd_dataset) == 0) { - LIST_REMOVE(zd, zd_next); - free(zd, M_ZONES); - goto success; - } + if (strcmp(dataset, zd->zd_dataset) == 0) + break; } - error = ENOENT; -success: + if (zd == NULL) + error = ENOENT; + else { + LIST_REMOVE(zd, zd_next); + free(zd, M_ZONES); + if (LIST_EMPTY(head)) + osd_jail_del(pr, zone_slot); + error = 0; + } +end: mtx_unlock(&pr->pr_mtx); return (error); } @@ -136,14 +161,16 @@ zone_dataset_visible(const char *dataset, int *write) if (dataset[0] == '\0') return (0); - if (INGLOBALZONE(curproc)) { + if (INGLOBALZONE(curthread)) { if (write != NULL) *write = 1; return (1); } pr = curthread->td_ucred->cr_prison; mtx_lock(&pr->pr_mtx); - head = prison_service_data_get(zone_prison_service, pr); + head = osd_jail_get(pr, zone_slot); + if (head == NULL) + goto end; /* * Walk the list once, looking for datasets which match exactly, or @@ -188,49 +215,32 @@ end: return (ret); } -static int -zone_create(struct prison_service *psrv, struct prison *pr) -{ - struct zone_dataset_head *head; - - head = malloc(sizeof(*head), M_ZONES, M_WAITOK); - LIST_INIT(head); - mtx_lock(&pr->pr_mtx); - prison_service_data_set(psrv, pr, head); - mtx_unlock(&pr->pr_mtx); - return (0); -} - -static int -zone_destroy(struct prison_service *psrv, struct prison *pr) +static void +zone_destroy(void *arg) { struct zone_dataset_head *head; zone_dataset_t *zd; - mtx_lock(&pr->pr_mtx); - head = prison_service_data_del(psrv, pr); - mtx_unlock(&pr->pr_mtx); - while ((zd = LIST_FIRST(head)) != NULL) { - LIST_REMOVE(zd, zd_next); - free(zd, M_ZONES); - } - free(head, M_ZONES); - return (0); + head = arg; + while ((zd = LIST_FIRST(head)) != NULL) { + LIST_REMOVE(zd, zd_next); + free(zd, M_ZONES); + } + free(head, M_ZONES); } static void zone_sysinit(void *arg __unused) { - zone_prison_service = prison_service_register("zfs", zone_create, - zone_destroy); + zone_slot = osd_jail_register(zone_destroy); } static void zone_sysuninit(void *arg __unused) { - prison_service_deregister(zone_prison_service); + osd_jail_deregister(zone_slot); } SYSINIT(zone_sysinit, SI_SUB_DRIVERS, SI_ORDER_ANY, zone_sysinit, NULL); |
