FreeBSD ZFS
The Zettabyte File System

zfs_onexit.c

Go to the documentation of this file.
00001 /*
00002  * CDDL HEADER START
00003  *
00004  * The contents of this file are subject to the terms of the
00005  * Common Development and Distribution License (the "License").
00006  * You may not use this file except in compliance with the License.
00007  *
00008  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
00009  * or http://www.opensolaris.org/os/licensing.
00010  * See the License for the specific language governing permissions
00011  * and limitations under the License.
00012  *
00013  * When distributing Covered Code, include this CDDL HEADER in each
00014  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
00015  * If applicable, add the following below this CDDL HEADER, with the
00016  * fields enclosed by brackets "[]" replaced with your own identifying
00017  * information: Portions Copyright [yyyy] [name of copyright owner]
00018  *
00019  * CDDL HEADER END
00020  */
00021 /*
00022  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
00023  */
00024 
00025 #include <sys/types.h>
00026 #include <sys/param.h>
00027 #include <sys/errno.h>
00028 #include <sys/kmem.h>
00029 #include <sys/conf.h>
00030 #include <sys/sunddi.h>
00031 #include <sys/zfs_ioctl.h>
00032 #include <sys/zfs_onexit.h>
00033 #include <sys/zvol.h>
00034 
00075 void
00076 zfs_onexit_init(zfs_onexit_t **zop)
00077 {
00078         zfs_onexit_t *zo;
00079 
00080         zo = *zop = kmem_zalloc(sizeof (zfs_onexit_t), KM_SLEEP);
00081         mutex_init(&zo->zo_lock, NULL, MUTEX_DEFAULT, NULL);
00082         list_create(&zo->zo_actions, sizeof (zfs_onexit_action_node_t),
00083             offsetof(zfs_onexit_action_node_t, za_link));
00084 }
00085 
00086 void
00087 zfs_onexit_destroy(zfs_onexit_t *zo)
00088 {
00089         zfs_onexit_action_node_t *ap;
00090 
00091         mutex_enter(&zo->zo_lock);
00092         while ((ap = list_head(&zo->zo_actions)) != NULL) {
00093                 list_remove(&zo->zo_actions, ap);
00094                 mutex_exit(&zo->zo_lock);
00095                 ap->za_func(ap->za_data);
00096                 kmem_free(ap, sizeof (zfs_onexit_action_node_t));
00097                 mutex_enter(&zo->zo_lock);
00098         }
00099         mutex_exit(&zo->zo_lock);
00100 
00101         list_destroy(&zo->zo_actions);
00102         mutex_destroy(&zo->zo_lock);
00103         kmem_free(zo, sizeof (zfs_onexit_t));
00104 }
00105 
00106 static int
00107 zfs_onexit_minor_to_state(minor_t minor, zfs_onexit_t **zo)
00108 {
00109         *zo = zfsdev_get_soft_state(minor, ZSST_CTLDEV);
00110         if (*zo == NULL)
00111                 return (EBADF);
00112 
00113         return (0);
00114 }
00115 
00122 int
00123 zfs_onexit_fd_hold(int fd, minor_t *minorp)
00124 {
00125         file_t *fp, *tmpfp;
00126         zfs_onexit_t *zo;
00127         void *data;
00128         int error;
00129 
00130         fp = getf(fd);
00131         if (fp == NULL)
00132                 return (EBADF);
00133 
00134         tmpfp = curthread->td_fpop;
00135         curthread->td_fpop = fp;
00136         error = devfs_get_cdevpriv(&data);
00137         if (error == 0)
00138                 *minorp = (minor_t)(uintptr_t)data;
00139         curthread->td_fpop = tmpfp;
00140         if (error != 0)
00141                 return (error);
00142         return (zfs_onexit_minor_to_state(*minorp, &zo));
00143 }
00144 
00145 void
00146 zfs_onexit_fd_rele(int fd)
00147 {
00148         releasef(fd);
00149 }
00150 
00154 int
00155 zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
00156     uint64_t *action_handle)
00157 {
00158         zfs_onexit_t *zo;
00159         zfs_onexit_action_node_t *ap;
00160         int error;
00161 
00162         error = zfs_onexit_minor_to_state(minor, &zo);
00163         if (error)
00164                 return (error);
00165 
00166         ap = kmem_alloc(sizeof (zfs_onexit_action_node_t), KM_SLEEP);
00167         list_link_init(&ap->za_link);
00168         ap->za_func = func;
00169         ap->za_data = data;
00170 
00171         mutex_enter(&zo->zo_lock);
00172         list_insert_tail(&zo->zo_actions, ap);
00173         mutex_exit(&zo->zo_lock);
00174         if (action_handle)
00175                 *action_handle = (uint64_t)(uintptr_t)ap;
00176 
00177         return (0);
00178 }
00179 
00180 static zfs_onexit_action_node_t *
00181 zfs_onexit_find_cb(zfs_onexit_t *zo, uint64_t action_handle)
00182 {
00183         zfs_onexit_action_node_t *match;
00184         zfs_onexit_action_node_t *ap;
00185         list_t *l;
00186 
00187         ASSERT(MUTEX_HELD(&zo->zo_lock));
00188 
00189         match = (zfs_onexit_action_node_t *)(uintptr_t)action_handle;
00190         l = &zo->zo_actions;
00191         for (ap = list_head(l); ap != NULL; ap = list_next(l, ap)) {
00192                 if (match == ap)
00193                         break;
00194         }
00195         return (ap);
00196 }
00197 
00203 int
00204 zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire)
00205 {
00206         zfs_onexit_t *zo;
00207         zfs_onexit_action_node_t *ap;
00208         int error;
00209 
00210         error = zfs_onexit_minor_to_state(minor, &zo);
00211         if (error)
00212                 return (error);
00213 
00214         mutex_enter(&zo->zo_lock);
00215         ap = zfs_onexit_find_cb(zo, action_handle);
00216         if (ap != NULL) {
00217                 list_remove(&zo->zo_actions, ap);
00218                 mutex_exit(&zo->zo_lock);
00219                 if (fire)
00220                         ap->za_func(ap->za_data);
00221                 kmem_free(ap, sizeof (zfs_onexit_action_node_t));
00222         } else {
00223                 mutex_exit(&zo->zo_lock);
00224                 error = ENOENT;
00225         }
00226 
00227         return (error);
00228 }
00229 
00235 int
00236 zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data)
00237 {
00238         zfs_onexit_t *zo;
00239         zfs_onexit_action_node_t *ap;
00240         int error;
00241 
00242         *data = NULL;
00243 
00244         error = zfs_onexit_minor_to_state(minor, &zo);
00245         if (error)
00246                 return (error);
00247 
00248         mutex_enter(&zo->zo_lock);
00249         ap = zfs_onexit_find_cb(zo, action_handle);
00250         if (ap != NULL)
00251                 *data = ap->za_data;
00252         else
00253                 error = ENOENT;
00254         mutex_exit(&zo->zo_lock);
00255 
00256         return (error);
00257 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines