@@ -178,7 +178,8 @@ static void zonefs_update_stats(struct inode *inode, loff_t new_isize)
178
178
* amount of readable data in the zone.
179
179
*/
180
180
static loff_t zonefs_check_zone_condition (struct inode * inode ,
181
- struct blk_zone * zone , bool warn )
181
+ struct blk_zone * zone , bool warn ,
182
+ bool mount )
182
183
{
183
184
struct zonefs_inode_info * zi = ZONEFS_I (inode );
184
185
@@ -196,13 +197,26 @@ static loff_t zonefs_check_zone_condition(struct inode *inode,
196
197
zone -> wp = zone -> start ;
197
198
return 0 ;
198
199
case BLK_ZONE_COND_READONLY :
199
- /* Do not allow writes in read-only zones */
200
+ /*
201
+ * The write pointer of read-only zones is invalid. If such a
202
+ * zone is found during mount, the file size cannot be retrieved
203
+ * so we treat the zone as offline (mount == true case).
204
+ * Otherwise, keep the file size as it was when last updated
205
+ * so that the user can recover data. In both cases, writes are
206
+ * always disabled for the zone.
207
+ */
200
208
if (warn )
201
209
zonefs_warn (inode -> i_sb , "inode %lu: read-only zone\n" ,
202
210
inode -> i_ino );
203
211
inode -> i_flags |= S_IMMUTABLE ;
212
+ if (mount ) {
213
+ zone -> cond = BLK_ZONE_COND_OFFLINE ;
214
+ inode -> i_mode &= ~0777 ;
215
+ zone -> wp = zone -> start ;
216
+ return 0 ;
217
+ }
204
218
inode -> i_mode &= ~0222 ;
205
- /* fallthrough */
219
+ return i_size_read ( inode );
206
220
default :
207
221
if (zi -> i_ztype == ZONEFS_ZTYPE_CNV )
208
222
return zi -> i_max_size ;
@@ -231,7 +245,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
231
245
* as there is no inconsistency between the inode size and the amount of
232
246
* data writen in the zone (data_size).
233
247
*/
234
- data_size = zonefs_check_zone_condition (inode , zone , true);
248
+ data_size = zonefs_check_zone_condition (inode , zone , true, false );
235
249
isize = i_size_read (inode );
236
250
if (zone -> cond != BLK_ZONE_COND_OFFLINE &&
237
251
zone -> cond != BLK_ZONE_COND_READONLY &&
@@ -274,7 +288,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
274
288
if (zone -> cond != BLK_ZONE_COND_OFFLINE ) {
275
289
zone -> cond = BLK_ZONE_COND_OFFLINE ;
276
290
data_size = zonefs_check_zone_condition (inode , zone ,
277
- false);
291
+ false, false );
278
292
}
279
293
} else if (zone -> cond == BLK_ZONE_COND_READONLY ||
280
294
sbi -> s_mount_opts & ZONEFS_MNTOPT_ERRORS_ZRO ) {
@@ -283,7 +297,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
283
297
if (zone -> cond != BLK_ZONE_COND_READONLY ) {
284
298
zone -> cond = BLK_ZONE_COND_READONLY ;
285
299
data_size = zonefs_check_zone_condition (inode , zone ,
286
- false);
300
+ false, false );
287
301
}
288
302
}
289
303
@@ -975,7 +989,7 @@ static void zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone,
975
989
zi -> i_zsector = zone -> start ;
976
990
zi -> i_max_size = min_t (loff_t , MAX_LFS_FILESIZE ,
977
991
zone -> len << SECTOR_SHIFT );
978
- zi -> i_wpoffset = zonefs_check_zone_condition (inode , zone , true);
992
+ zi -> i_wpoffset = zonefs_check_zone_condition (inode , zone , true, true );
979
993
980
994
inode -> i_uid = sbi -> s_uid ;
981
995
inode -> i_gid = sbi -> s_gid ;
0 commit comments