Skip to content

Commit

Permalink
Merge tag 'zonefs-5.6-rc7' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/dlemoal/zonefs

Pull zonefs fix from Damien Le Moal:
 "A single fix from me to correctly handle the size of read-only zone
  files"

* tag 'zonefs-5.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs:
  zonfs: Fix handling of read-only zones
  • Loading branch information
Linus Torvalds committed Mar 25, 2020
2 parents 76ccd23 + ccf4ad7 commit e2cf67f
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 12 deletions.
18 changes: 13 additions & 5 deletions Documentation/filesystems/zonefs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -258,19 +258,19 @@ conditions.
| option | condition | size read write read write |
+--------------+-----------+-----------------------------------------+
| | good | fixed yes no yes yes |
| remount-ro | read-only | fixed yes no yes no |
| remount-ro | read-only | as is yes no yes no |
| (default) | offline | 0 no no no no |
+--------------+-----------+-----------------------------------------+
| | good | fixed yes no yes yes |
| zone-ro | read-only | fixed yes no yes no |
| zone-ro | read-only | as is yes no yes no |
| | offline | 0 no no no no |
+--------------+-----------+-----------------------------------------+
| | good | 0 no no yes yes |
| zone-offline | read-only | 0 no no yes no |
| | offline | 0 no no no no |
+--------------+-----------+-----------------------------------------+
| | good | fixed yes yes yes yes |
| repair | read-only | fixed yes no yes no |
| repair | read-only | as is yes no yes no |
| | offline | 0 no no no no |
+--------------+-----------+-----------------------------------------+

Expand Down Expand Up @@ -307,8 +307,16 @@ condition changes. The defined behaviors are as follow:
* zone-offline
* repair

The I/O error actions defined for each behavior are detailed in the previous
section.
The run-time I/O error actions defined for each behavior are detailed in the
previous section. Mount time I/O errors will cause the mount operation to fail.
The handling of read-only zones also differs between mount-time and run-time.
If a read-only zone is found at mount time, the zone is always treated in the
same manner as offline zones, that is, all accesses are disabled and the zone
file size set to 0. This is necessary as the write pointer of read-only zones
is defined as invalib by the ZBC and ZAC standards, making it impossible to
discover the amount of data that has been written to the zone. In the case of a
read-only zone discovered at run-time, as indicated in the previous section.
the size of the zone file is left unchanged from its last updated value.

Zonefs User Space Tools
=======================
Expand Down
28 changes: 21 additions & 7 deletions fs/zonefs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ static void zonefs_update_stats(struct inode *inode, loff_t new_isize)
* amount of readable data in the zone.
*/
static loff_t zonefs_check_zone_condition(struct inode *inode,
struct blk_zone *zone, bool warn)
struct blk_zone *zone, bool warn,
bool mount)
{
struct zonefs_inode_info *zi = ZONEFS_I(inode);

Expand All @@ -196,13 +197,26 @@ static loff_t zonefs_check_zone_condition(struct inode *inode,
zone->wp = zone->start;
return 0;
case BLK_ZONE_COND_READONLY:
/* Do not allow writes in read-only zones */
/*
* The write pointer of read-only zones is invalid. If such a
* zone is found during mount, the file size cannot be retrieved
* so we treat the zone as offline (mount == true case).
* Otherwise, keep the file size as it was when last updated
* so that the user can recover data. In both cases, writes are
* always disabled for the zone.
*/
if (warn)
zonefs_warn(inode->i_sb, "inode %lu: read-only zone\n",
inode->i_ino);
inode->i_flags |= S_IMMUTABLE;
if (mount) {
zone->cond = BLK_ZONE_COND_OFFLINE;
inode->i_mode &= ~0777;
zone->wp = zone->start;
return 0;
}
inode->i_mode &= ~0222;
/* fallthrough */
return i_size_read(inode);
default:
if (zi->i_ztype == ZONEFS_ZTYPE_CNV)
return zi->i_max_size;
Expand Down Expand Up @@ -231,7 +245,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
* as there is no inconsistency between the inode size and the amount of
* data writen in the zone (data_size).
*/
data_size = zonefs_check_zone_condition(inode, zone, true);
data_size = zonefs_check_zone_condition(inode, zone, true, false);
isize = i_size_read(inode);
if (zone->cond != BLK_ZONE_COND_OFFLINE &&
zone->cond != BLK_ZONE_COND_READONLY &&
Expand Down Expand Up @@ -274,7 +288,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
if (zone->cond != BLK_ZONE_COND_OFFLINE) {
zone->cond = BLK_ZONE_COND_OFFLINE;
data_size = zonefs_check_zone_condition(inode, zone,
false);
false, false);
}
} else if (zone->cond == BLK_ZONE_COND_READONLY ||
sbi->s_mount_opts & ZONEFS_MNTOPT_ERRORS_ZRO) {
Expand All @@ -283,7 +297,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
if (zone->cond != BLK_ZONE_COND_READONLY) {
zone->cond = BLK_ZONE_COND_READONLY;
data_size = zonefs_check_zone_condition(inode, zone,
false);
false, false);
}
}

Expand Down Expand Up @@ -975,7 +989,7 @@ static void zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone,
zi->i_zsector = zone->start;
zi->i_max_size = min_t(loff_t, MAX_LFS_FILESIZE,
zone->len << SECTOR_SHIFT);
zi->i_wpoffset = zonefs_check_zone_condition(inode, zone, true);
zi->i_wpoffset = zonefs_check_zone_condition(inode, zone, true, true);

inode->i_uid = sbi->s_uid;
inode->i_gid = sbi->s_gid;
Expand Down

0 comments on commit e2cf67f

Please sign in to comment.