FreeBSD ZFS
The Zettabyte File System
|
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 }