9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2012 by Delphix. All rights reserved.
26 */
27
28 #include <sys/spa.h>
29 #include <sys/spa_impl.h>
30 #include <sys/nvpair.h>
31 #include <sys/uio.h>
32 #include <sys/fs/zfs.h>
33 #include <sys/vdev_impl.h>
34 #include <sys/zfs_ioctl.h>
35 #include <sys/utsname.h>
36 #include <sys/systeminfo.h>
37 #include <sys/sunddi.h>
38 #include <sys/zfeature.h>
39 #ifdef _KERNEL
40 #include <sys/kobj.h>
41 #include <sys/zone.h>
42 #endif
43
44 /*
45 * Pool configuration repository.
46 *
47 * Pool configuration is stored as a packed nvlist on the filesystem. By
48 * default, all pools are stored in /etc/zfs/zpool.cache and loaded on boot
123 if (nvpair_type(nvpair) != DATA_TYPE_NVLIST)
124 continue;
125
126 VERIFY(nvpair_value_nvlist(nvpair, &child) == 0);
127
128 if (spa_lookup(nvpair_name(nvpair)) != NULL)
129 continue;
130 (void) spa_add(nvpair_name(nvpair), child, NULL);
131 }
132 mutex_exit(&spa_namespace_lock);
133
134 nvlist_free(nvlist);
135
136 out:
137 if (buf != NULL)
138 kmem_free(buf, fsize);
139
140 kobj_close_file(file);
141 }
142
143 static void
144 spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
145 {
146 size_t buflen;
147 char *buf;
148 vnode_t *vp;
149 int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX;
150 char *temp;
151
152 /*
153 * If the nvlist is empty (NULL), then remove the old cachefile.
154 */
155 if (nvl == NULL) {
156 (void) vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE);
157 return;
158 }
159
160 /*
161 * Pack the configuration into a buffer.
162 */
163 VERIFY(nvlist_size(nvl, &buflen, NV_ENCODE_XDR) == 0);
164
165 buf = kmem_alloc(buflen, KM_SLEEP);
166 temp = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
167
168 VERIFY(nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_XDR,
169 KM_SLEEP) == 0);
170
171 /*
172 * Write the configuration to disk. We need to do the traditional
173 * 'write to temporary file, sync, move over original' to make sure we
174 * always have a consistent view of the data.
175 */
176 (void) snprintf(temp, MAXPATHLEN, "%s.tmp", dp->scd_path);
177
178 if (vn_open(temp, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0) == 0) {
179 if (vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE,
180 0, RLIM64_INFINITY, kcred, NULL) == 0 &&
181 VOP_FSYNC(vp, FSYNC, kcred, NULL) == 0) {
182 (void) vn_rename(temp, dp->scd_path, UIO_SYSSPACE);
183 }
184 (void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL);
185 VN_RELE(vp);
186 }
187
188 (void) vn_remove(temp, UIO_SYSSPACE, RMFILE);
189
190 kmem_free(buf, buflen);
191 kmem_free(temp, MAXPATHLEN);
192 }
193
194 /*
195 * Synchronize pool configuration to disk. This must be called with the
196 * namespace lock held.
197 */
198 void
199 spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
200 {
201 spa_config_dirent_t *dp, *tdp;
202 nvlist_t *nvl;
203
204 ASSERT(MUTEX_HELD(&spa_namespace_lock));
205
206 if (rootdir == NULL || !(spa_mode_global & FWRITE))
207 return;
208
209 /*
210 * Iterate over all cachefiles for the pool, past or present. When the
211 * cachefile is changed, the new one is pushed onto this list, allowing
212 * us to update previous cachefiles that no longer contain this pool.
213 */
214 for (dp = list_head(&target->spa_config_list); dp != NULL;
215 dp = list_next(&target->spa_config_list, dp)) {
216 spa_t *spa = NULL;
217 if (dp->scd_path == NULL)
218 continue;
219
220 /*
221 * Iterate over all pools, adding any matching pools to 'nvl'.
222 */
223 nvl = NULL;
224 while ((spa = spa_next(spa)) != NULL) {
225 /*
226 * Skip over our own pool if we're about to remove
227 * ourselves from the spa namespace or any pool that
228 * is readonly. Since we cannot guarantee that a
229 * readonly pool would successfully import upon reboot,
230 * we don't allow them to be written to the cache file.
231 */
232 if ((spa == target && removing) ||
233 !spa_writeable(spa))
234 continue;
235
236 mutex_enter(&spa->spa_props_lock);
237 tdp = list_head(&spa->spa_config_list);
238 if (spa->spa_config == NULL ||
239 tdp->scd_path == NULL ||
240 strcmp(tdp->scd_path, dp->scd_path) != 0) {
241 mutex_exit(&spa->spa_props_lock);
242 continue;
243 }
244
245 if (nvl == NULL)
246 VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME,
247 KM_SLEEP) == 0);
248
249 VERIFY(nvlist_add_nvlist(nvl, spa->spa_name,
250 spa->spa_config) == 0);
251 mutex_exit(&spa->spa_props_lock);
252 }
253
254 spa_config_write(dp, nvl);
255 nvlist_free(nvl);
256 }
257
258 /*
259 * Remove any config entries older than the current one.
260 */
261 dp = list_head(&target->spa_config_list);
262 while ((tdp = list_next(&target->spa_config_list, dp)) != NULL) {
263 list_remove(&target->spa_config_list, tdp);
264 if (tdp->scd_path != NULL)
265 spa_strfree(tdp->scd_path);
266 kmem_free(tdp, sizeof (spa_config_dirent_t));
267 }
268
269 spa_config_generation++;
270
271 if (postsysevent)
272 spa_event_notify(target, NULL, ESC_ZFS_CONFIG_SYNC);
273 }
274
275 /*
276 * Sigh. Inside a local zone, we don't have access to /etc/zfs/zpool.cache,
277 * and we don't want to allow the local zone to see all the pools anyway.
|
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2012 by Delphix. All rights reserved.
26 */
27
28 #include <sys/spa.h>
29 #include <sys/fm/fs/zfs.h>
30 #include <sys/spa_impl.h>
31 #include <sys/nvpair.h>
32 #include <sys/uio.h>
33 #include <sys/fs/zfs.h>
34 #include <sys/vdev_impl.h>
35 #include <sys/zfs_ioctl.h>
36 #include <sys/utsname.h>
37 #include <sys/systeminfo.h>
38 #include <sys/sunddi.h>
39 #include <sys/zfeature.h>
40 #ifdef _KERNEL
41 #include <sys/kobj.h>
42 #include <sys/zone.h>
43 #endif
44
45 /*
46 * Pool configuration repository.
47 *
48 * Pool configuration is stored as a packed nvlist on the filesystem. By
49 * default, all pools are stored in /etc/zfs/zpool.cache and loaded on boot
124 if (nvpair_type(nvpair) != DATA_TYPE_NVLIST)
125 continue;
126
127 VERIFY(nvpair_value_nvlist(nvpair, &child) == 0);
128
129 if (spa_lookup(nvpair_name(nvpair)) != NULL)
130 continue;
131 (void) spa_add(nvpair_name(nvpair), child, NULL);
132 }
133 mutex_exit(&spa_namespace_lock);
134
135 nvlist_free(nvlist);
136
137 out:
138 if (buf != NULL)
139 kmem_free(buf, fsize);
140
141 kobj_close_file(file);
142 }
143
144 static int
145 spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
146 {
147 size_t buflen;
148 char *buf;
149 vnode_t *vp;
150 int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX;
151 char *temp;
152 int err;
153
154 /*
155 * If the nvlist is empty (NULL), then remove the old cachefile.
156 */
157 if (nvl == NULL) {
158 err = vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE);
159 return (err);
160 }
161
162 /*
163 * Pack the configuration into a buffer.
164 */
165 VERIFY(nvlist_size(nvl, &buflen, NV_ENCODE_XDR) == 0);
166
167 buf = kmem_alloc(buflen, KM_SLEEP);
168 temp = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
169
170 VERIFY(nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_XDR,
171 KM_SLEEP) == 0);
172
173 /*
174 * Write the configuration to disk. We need to do the traditional
175 * 'write to temporary file, sync, move over original' to make sure we
176 * always have a consistent view of the data.
177 */
178 (void) snprintf(temp, MAXPATHLEN, "%s.tmp", dp->scd_path);
179
180 err = vn_open(temp, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0);
181 if (err == 0) {
182 err = vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE,
183 0, RLIM64_INFINITY, kcred, NULL);
184 if (err == 0)
185 err = VOP_FSYNC(vp, FSYNC, kcred, NULL);
186 if (err == 0)
187 err = vn_rename(temp, dp->scd_path, UIO_SYSSPACE);
188 (void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL);
189 VN_RELE(vp);
190 }
191
192 (void) vn_remove(temp, UIO_SYSSPACE, RMFILE);
193
194 kmem_free(buf, buflen);
195 kmem_free(temp, MAXPATHLEN);
196 return (err);
197 }
198
199 /*
200 * Synchronize pool configuration to disk. This must be called with the
201 * namespace lock held.
202 */
203 void
204 spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
205 {
206 spa_config_dirent_t *dp, *tdp;
207 nvlist_t *nvl;
208 boolean_t ccw_failure;
209 int error;
210
211 ASSERT(MUTEX_HELD(&spa_namespace_lock));
212
213 if (rootdir == NULL || !(spa_mode_global & FWRITE))
214 return;
215
216 /*
217 * Iterate over all cachefiles for the pool, past or present. When the
218 * cachefile is changed, the new one is pushed onto this list, allowing
219 * us to update previous cachefiles that no longer contain this pool.
220 */
221 ccw_failure = B_FALSE;
222 for (dp = list_head(&target->spa_config_list); dp != NULL;
223 dp = list_next(&target->spa_config_list, dp)) {
224 spa_t *spa = NULL;
225 if (dp->scd_path == NULL)
226 continue;
227
228 /*
229 * Iterate over all pools, adding any matching pools to 'nvl'.
230 */
231 nvl = NULL;
232 while ((spa = spa_next(spa)) != NULL) {
233 /*
234 * Skip over our own pool if we're about to remove
235 * ourselves from the spa namespace or any pool that
236 * is readonly. Since we cannot guarantee that a
237 * readonly pool would successfully import upon reboot,
238 * we don't allow them to be written to the cache file.
239 */
240 if ((spa == target && removing) ||
241 !spa_writeable(spa))
242 continue;
243
244 mutex_enter(&spa->spa_props_lock);
245 tdp = list_head(&spa->spa_config_list);
246 if (spa->spa_config == NULL ||
247 tdp->scd_path == NULL ||
248 strcmp(tdp->scd_path, dp->scd_path) != 0) {
249 mutex_exit(&spa->spa_props_lock);
250 continue;
251 }
252
253 if (nvl == NULL)
254 VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME,
255 KM_SLEEP) == 0);
256
257 VERIFY(nvlist_add_nvlist(nvl, spa->spa_name,
258 spa->spa_config) == 0);
259 mutex_exit(&spa->spa_props_lock);
260 }
261
262 error = spa_config_write(dp, nvl);
263 if (error != 0)
264 ccw_failure = B_TRUE;
265 nvlist_free(nvl);
266 }
267
268 if (ccw_failure) {
269 /*
270 * Keep trying so that configuration data is
271 * written if/when any temporary filesystem
272 * resource issues are resolved.
273 */
274 target->spa_ccw_fail_time = ddi_get_lbolt64();
275 spa_async_request(target, SPA_ASYNC_CONFIG_UPDATE);
276 zfs_ereport_post(FM_EREPORT_ZFS_CONFIG_CACHE_WRITE,
277 target, NULL, NULL, 0, 0);
278 } else {
279 /*
280 * Do not rate limit future attempts to update
281 * the config cache.
282 */
283 target->spa_ccw_fail_time = 0;
284 }
285
286 /*
287 * Remove any config entries older than the current one.
288 */
289 dp = list_head(&target->spa_config_list);
290 while ((tdp = list_next(&target->spa_config_list, dp)) != NULL) {
291 list_remove(&target->spa_config_list, tdp);
292 if (tdp->scd_path != NULL)
293 spa_strfree(tdp->scd_path);
294 kmem_free(tdp, sizeof (spa_config_dirent_t));
295 }
296
297 spa_config_generation++;
298
299 if (postsysevent)
300 spa_event_notify(target, NULL, ESC_ZFS_CONFIG_SYNC);
301 }
302
303 /*
304 * Sigh. Inside a local zone, we don't have access to /etc/zfs/zpool.cache,
305 * and we don't want to allow the local zone to see all the pools anyway.
|