26
26
*/
27
27
28
28
#include <sys/spa.h>
29
+ #include <sys/fm/fs/zfs.h>
29
30
#include <sys/spa_impl.h>
30
31
#include <sys/nvpair.h>
31
32
#include <sys/uio.h>
@@ -145,22 +146,22 @@ spa_config_load(void)
145
146
kobj_close_file (file );
146
147
}
147
148
148
- static void
149
+ static int
149
150
spa_config_write (spa_config_dirent_t * dp , nvlist_t * nvl )
150
151
{
151
152
size_t buflen ;
152
153
char * buf ;
153
154
vnode_t * vp ;
154
155
int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX ;
155
- int error ;
156
156
char * temp ;
157
+ int err ;
157
158
158
159
/*
159
160
* If the nvlist is empty (NULL), then remove the old cachefile.
160
161
*/
161
162
if (nvl == NULL ) {
162
- ( void ) vn_remove (dp -> scd_path , UIO_SYSSPACE , RMFILE );
163
- return ;
163
+ err = vn_remove (dp -> scd_path , UIO_SYSSPACE , RMFILE );
164
+ return ( err ) ;
164
165
}
165
166
166
167
/*
@@ -181,16 +182,16 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
181
182
* and overwritten in place. In the event of an error the file is
182
183
* unlinked to make sure we always have a consistent view of the data.
183
184
*/
184
- error = vn_open (dp -> scd_path , UIO_SYSSPACE , oflags , 0644 , & vp , 0 , 0 );
185
- if (error == 0 ) {
186
- error = vn_rdwr (UIO_WRITE , vp , buf , buflen , 0 ,
185
+ err = vn_open (dp -> scd_path , UIO_SYSSPACE , oflags , 0644 , & vp , 0 , 0 );
186
+ if (err == 0 ) {
187
+ err = vn_rdwr (UIO_WRITE , vp , buf , buflen , 0 ,
187
188
UIO_SYSSPACE , 0 , RLIM64_INFINITY , kcred , NULL );
188
- if (error == 0 )
189
- error = VOP_FSYNC (vp , FSYNC , kcred , NULL );
189
+ if (err == 0 )
190
+ err = VOP_FSYNC (vp , FSYNC , kcred , NULL );
190
191
191
192
(void ) VOP_CLOSE (vp , oflags , 1 , 0 , kcred , NULL );
192
193
193
- if (error )
194
+ if (err )
194
195
(void ) vn_remove (dp -> scd_path , UIO_SYSSPACE , RMFILE );
195
196
}
196
197
#else
@@ -201,13 +202,14 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
201
202
*/
202
203
(void ) snprintf (temp , MAXPATHLEN , "%s.tmp" , dp -> scd_path );
203
204
204
- error = vn_open (temp , UIO_SYSSPACE , oflags , 0644 , & vp , CRCREAT , 0 );
205
- if (error == 0 ) {
206
- if (vn_rdwr (UIO_WRITE , vp , buf , buflen , 0 , UIO_SYSSPACE ,
207
- 0 , RLIM64_INFINITY , kcred , NULL ) == 0 &&
208
- VOP_FSYNC (vp , FSYNC , kcred , NULL ) == 0 ) {
209
- (void ) vn_rename (temp , dp -> scd_path , UIO_SYSSPACE );
210
- }
205
+ err = vn_open (temp , UIO_SYSSPACE , oflags , 0644 , & vp , CRCREAT , 0 );
206
+ if (err == 0 ) {
207
+ err = vn_rdwr (UIO_WRITE , vp , buf , buflen , 0 , UIO_SYSSPACE ,
208
+ 0 , RLIM64_INFINITY , kcred , NULL );
209
+ if (err == 0 )
210
+ err = VOP_FSYNC (vp , FSYNC , kcred , NULL );
211
+ if (err == 0 )
212
+ err = vn_rename (temp , dp -> scd_path , UIO_SYSSPACE );
211
213
(void ) VOP_CLOSE (vp , oflags , 1 , 0 , kcred , NULL );
212
214
}
213
215
@@ -216,6 +218,7 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
216
218
217
219
vmem_free (buf , buflen );
218
220
kmem_free (temp , MAXPATHLEN );
221
+ return (err );
219
222
}
220
223
221
224
/*
@@ -233,6 +236,8 @@ spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
233
236
spa_config_dirent_t * dp , * tdp ;
234
237
nvlist_t * nvl ;
235
238
char * pool_name ;
239
+ boolean_t ccw_failure ;
240
+ int error = 0 ;
236
241
237
242
ASSERT (MUTEX_HELD (& spa_namespace_lock ));
238
243
@@ -244,6 +249,7 @@ spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
244
249
* cachefile is changed, the new one is pushed onto this list, allowing
245
250
* us to update previous cachefiles that no longer contain this pool.
246
251
*/
252
+ ccw_failure = B_FALSE ;
247
253
for (dp = list_head (& target -> spa_config_list ); dp != NULL ;
248
254
dp = list_next (& target -> spa_config_list , dp )) {
249
255
spa_t * spa = NULL ;
@@ -290,10 +296,32 @@ spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
290
296
mutex_exit (& spa -> spa_props_lock );
291
297
}
292
298
293
- spa_config_write (dp , nvl );
299
+ error = spa_config_write (dp , nvl );
300
+ if (error != 0 )
301
+ ccw_failure = B_TRUE ;
294
302
nvlist_free (nvl );
295
303
}
296
304
305
+ if (ccw_failure ) {
306
+ /*
307
+ * Keep trying so that configuration data is
308
+ * written if/when any temporary filesystem
309
+ * resource issues are resolved.
310
+ */
311
+ if (target -> spa_ccw_fail_time == 0 ) {
312
+ zfs_ereport_post (FM_EREPORT_ZFS_CONFIG_CACHE_WRITE ,
313
+ target , NULL , NULL , 0 , 0 );
314
+ }
315
+ target -> spa_ccw_fail_time = gethrtime ();
316
+ spa_async_request (target , SPA_ASYNC_CONFIG_UPDATE );
317
+ } else {
318
+ /*
319
+ * Do not rate limit future attempts to update
320
+ * the config cache.
321
+ */
322
+ target -> spa_ccw_fail_time = 0 ;
323
+ }
324
+
297
325
/*
298
326
* Remove any config entries older than the current one.
299
327
*/
0 commit comments