@@ -246,16 +246,18 @@ static void zonefs_inode_update_mode(struct inode *inode)
246
246
z -> z_mode = inode -> i_mode ;
247
247
}
248
248
249
- struct zonefs_ioerr_data {
250
- struct inode * inode ;
251
- bool write ;
252
- };
253
-
254
249
static int zonefs_io_error_cb (struct blk_zone * zone , unsigned int idx ,
255
250
void * data )
256
251
{
257
- struct zonefs_ioerr_data * err = data ;
258
- struct inode * inode = err -> inode ;
252
+ struct blk_zone * z = data ;
253
+
254
+ * z = * zone ;
255
+ return 0 ;
256
+ }
257
+
258
+ static void zonefs_handle_io_error (struct inode * inode , struct blk_zone * zone ,
259
+ bool write )
260
+ {
259
261
struct zonefs_zone * z = zonefs_inode_zone (inode );
260
262
struct super_block * sb = inode -> i_sb ;
261
263
struct zonefs_sb_info * sbi = ZONEFS_SB (sb );
@@ -270,8 +272,8 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
270
272
data_size = zonefs_check_zone_condition (sb , z , zone );
271
273
isize = i_size_read (inode );
272
274
if (!(z -> z_flags & (ZONEFS_ZONE_READONLY | ZONEFS_ZONE_OFFLINE )) &&
273
- !err -> write && isize == data_size )
274
- return 0 ;
275
+ !write && isize == data_size )
276
+ return ;
275
277
276
278
/*
277
279
* At this point, we detected either a bad zone or an inconsistency
@@ -292,7 +294,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
292
294
* In all cases, warn about inode size inconsistency and handle the
293
295
* IO error according to the zone condition and to the mount options.
294
296
*/
295
- if (zonefs_zone_is_seq ( z ) && isize != data_size )
297
+ if (isize != data_size )
296
298
zonefs_warn (sb ,
297
299
"inode %lu: invalid size %lld (should be %lld)\n" ,
298
300
inode -> i_ino , isize , data_size );
@@ -352,8 +354,6 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
352
354
zonefs_i_size_write (inode , data_size );
353
355
z -> z_wpoffset = data_size ;
354
356
zonefs_inode_account_active (inode );
355
-
356
- return 0 ;
357
357
}
358
358
359
359
/*
@@ -367,23 +367,25 @@ void __zonefs_io_error(struct inode *inode, bool write)
367
367
{
368
368
struct zonefs_zone * z = zonefs_inode_zone (inode );
369
369
struct super_block * sb = inode -> i_sb ;
370
- struct zonefs_sb_info * sbi = ZONEFS_SB (sb );
371
370
unsigned int noio_flag ;
372
- unsigned int nr_zones = 1 ;
373
- struct zonefs_ioerr_data err = {
374
- .inode = inode ,
375
- .write = write ,
376
- };
371
+ struct blk_zone zone ;
377
372
int ret ;
378
373
379
374
/*
380
- * The only files that have more than one zone are conventional zone
381
- * files with aggregated conventional zones, for which the inode zone
382
- * size is always larger than the device zone size.
375
+ * Conventional zone have no write pointer and cannot become read-only
376
+ * or offline. So simply fake a report for a single or aggregated zone
377
+ * and let zonefs_handle_io_error() correct the zone inode information
378
+ * according to the mount options.
383
379
*/
384
- if (z -> z_size > bdev_zone_sectors (sb -> s_bdev ))
385
- nr_zones = z -> z_size >>
386
- (sbi -> s_zone_sectors_shift + SECTOR_SHIFT );
380
+ if (!zonefs_zone_is_seq (z )) {
381
+ zone .start = z -> z_sector ;
382
+ zone .len = z -> z_size >> SECTOR_SHIFT ;
383
+ zone .wp = zone .start + zone .len ;
384
+ zone .type = BLK_ZONE_TYPE_CONVENTIONAL ;
385
+ zone .cond = BLK_ZONE_COND_NOT_WP ;
386
+ zone .capacity = zone .len ;
387
+ goto handle_io_error ;
388
+ }
387
389
388
390
/*
389
391
* Memory allocations in blkdev_report_zones() can trigger a memory
@@ -394,12 +396,20 @@ void __zonefs_io_error(struct inode *inode, bool write)
394
396
* the GFP_NOIO context avoids both problems.
395
397
*/
396
398
noio_flag = memalloc_noio_save ();
397
- ret = blkdev_report_zones (sb -> s_bdev , z -> z_sector , nr_zones ,
398
- zonefs_io_error_cb , & err );
399
- if (ret != nr_zones )
399
+ ret = blkdev_report_zones (sb -> s_bdev , z -> z_sector , 1 ,
400
+ zonefs_io_error_cb , & zone );
401
+ memalloc_noio_restore (noio_flag );
402
+
403
+ if (ret != 1 ) {
400
404
zonefs_err (sb , "Get inode %lu zone information failed %d\n" ,
401
405
inode -> i_ino , ret );
402
- memalloc_noio_restore (noio_flag );
406
+ zonefs_warn (sb , "remounting filesystem read-only\n" );
407
+ sb -> s_flags |= SB_RDONLY ;
408
+ return ;
409
+ }
410
+
411
+ handle_io_error :
412
+ zonefs_handle_io_error (inode , & zone , write );
403
413
}
404
414
405
415
static struct kmem_cache * zonefs_inode_cachep ;
0 commit comments