@@ -44,6 +44,19 @@ static inline int zonefs_zone_mgmt(struct inode *inode,
4444 return 0 ;
4545}
4646
47+ static inline void zonefs_i_size_write (struct inode * inode , loff_t isize )
48+ {
49+ struct zonefs_inode_info * zi = ZONEFS_I (inode );
50+
51+ i_size_write (inode , isize );
52+ /*
53+ * A full zone is no longer open/active and does not need
54+ * explicit closing.
55+ */
56+ if (isize >= zi -> i_max_size )
57+ zi -> i_flags &= ~ZONEFS_ZONE_OPEN ;
58+ }
59+
4760static int zonefs_iomap_begin (struct inode * inode , loff_t offset , loff_t length ,
4861 unsigned int flags , struct iomap * iomap ,
4962 struct iomap * srcmap )
@@ -321,6 +334,17 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
321334 }
322335 }
323336
337+ /*
338+ * If the filesystem is mounted with the explicit-open mount option, we
339+ * need to clear the ZONEFS_ZONE_OPEN flag if the zone transitioned to
340+ * the read-only or offline condition, to avoid attempting an explicit
341+ * close of the zone when the inode file is closed.
342+ */
343+ if ((sbi -> s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN ) &&
344+ (zone -> cond == BLK_ZONE_COND_OFFLINE ||
345+ zone -> cond == BLK_ZONE_COND_READONLY ))
346+ zi -> i_flags &= ~ZONEFS_ZONE_OPEN ;
347+
324348 /*
325349 * If error=remount-ro was specified, any error result in remounting
326350 * the volume as read-only.
@@ -335,7 +359,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
335359 * invalid data.
336360 */
337361 zonefs_update_stats (inode , data_size );
338- i_size_write (inode , data_size );
362+ zonefs_i_size_write (inode , data_size );
339363 zi -> i_wpoffset = data_size ;
340364
341365 return 0 ;
@@ -426,6 +450,25 @@ static int zonefs_file_truncate(struct inode *inode, loff_t isize)
426450 if (ret )
427451 goto unlock ;
428452
453+ /*
454+ * If the mount option ZONEFS_MNTOPT_EXPLICIT_OPEN is set,
455+ * take care of open zones.
456+ */
457+ if (zi -> i_flags & ZONEFS_ZONE_OPEN ) {
458+ /*
459+ * Truncating a zone to EMPTY or FULL is the equivalent of
460+ * closing the zone. For a truncation to 0, we need to
461+ * re-open the zone to ensure new writes can be processed.
462+ * For a truncation to the maximum file size, the zone is
463+ * closed and writes cannot be accepted anymore, so clear
464+ * the open flag.
465+ */
466+ if (!isize )
467+ ret = zonefs_zone_mgmt (inode , REQ_OP_ZONE_OPEN );
468+ else
469+ zi -> i_flags &= ~ZONEFS_ZONE_OPEN ;
470+ }
471+
429472 zonefs_update_stats (inode , isize );
430473 truncate_setsize (inode , isize );
431474 zi -> i_wpoffset = isize ;
@@ -604,7 +647,7 @@ static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
604647 mutex_lock (& zi -> i_truncate_mutex );
605648 if (i_size_read (inode ) < iocb -> ki_pos + size ) {
606649 zonefs_update_stats (inode , iocb -> ki_pos + size );
607- i_size_write (inode , iocb -> ki_pos + size );
650+ zonefs_i_size_write (inode , iocb -> ki_pos + size );
608651 }
609652 mutex_unlock (& zi -> i_truncate_mutex );
610653 }
@@ -885,8 +928,128 @@ static ssize_t zonefs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
885928 return ret ;
886929}
887930
931+ static inline bool zonefs_file_use_exp_open (struct inode * inode , struct file * file )
932+ {
933+ struct zonefs_inode_info * zi = ZONEFS_I (inode );
934+ struct zonefs_sb_info * sbi = ZONEFS_SB (inode -> i_sb );
935+
936+ if (!(sbi -> s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN ))
937+ return false;
938+
939+ if (zi -> i_ztype != ZONEFS_ZTYPE_SEQ )
940+ return false;
941+
942+ if (!(file -> f_mode & FMODE_WRITE ))
943+ return false;
944+
945+ return true;
946+ }
947+
948+ static int zonefs_open_zone (struct inode * inode )
949+ {
950+ struct zonefs_inode_info * zi = ZONEFS_I (inode );
951+ struct zonefs_sb_info * sbi = ZONEFS_SB (inode -> i_sb );
952+ int ret = 0 ;
953+
954+ mutex_lock (& zi -> i_truncate_mutex );
955+
956+ zi -> i_wr_refcnt ++ ;
957+ if (zi -> i_wr_refcnt == 1 ) {
958+
959+ if (atomic_inc_return (& sbi -> s_open_zones ) > sbi -> s_max_open_zones ) {
960+ atomic_dec (& sbi -> s_open_zones );
961+ ret = - EBUSY ;
962+ goto unlock ;
963+ }
964+
965+ if (i_size_read (inode ) < zi -> i_max_size ) {
966+ ret = zonefs_zone_mgmt (inode , REQ_OP_ZONE_OPEN );
967+ if (ret ) {
968+ zi -> i_wr_refcnt -- ;
969+ atomic_dec (& sbi -> s_open_zones );
970+ goto unlock ;
971+ }
972+ zi -> i_flags |= ZONEFS_ZONE_OPEN ;
973+ }
974+ }
975+
976+ unlock :
977+ mutex_unlock (& zi -> i_truncate_mutex );
978+
979+ return ret ;
980+ }
981+
982+ static int zonefs_file_open (struct inode * inode , struct file * file )
983+ {
984+ int ret ;
985+
986+ ret = generic_file_open (inode , file );
987+ if (ret )
988+ return ret ;
989+
990+ if (zonefs_file_use_exp_open (inode , file ))
991+ return zonefs_open_zone (inode );
992+
993+ return 0 ;
994+ }
995+
996+ static void zonefs_close_zone (struct inode * inode )
997+ {
998+ struct zonefs_inode_info * zi = ZONEFS_I (inode );
999+ int ret = 0 ;
1000+
1001+ mutex_lock (& zi -> i_truncate_mutex );
1002+ zi -> i_wr_refcnt -- ;
1003+ if (!zi -> i_wr_refcnt ) {
1004+ struct zonefs_sb_info * sbi = ZONEFS_SB (inode -> i_sb );
1005+ struct super_block * sb = inode -> i_sb ;
1006+
1007+ /*
1008+ * If the file zone is full, it is not open anymore and we only
1009+ * need to decrement the open count.
1010+ */
1011+ if (!(zi -> i_flags & ZONEFS_ZONE_OPEN ))
1012+ goto dec ;
1013+
1014+ ret = zonefs_zone_mgmt (inode , REQ_OP_ZONE_CLOSE );
1015+ if (ret ) {
1016+ __zonefs_io_error (inode , false);
1017+ /*
1018+ * Leaving zones explicitly open may lead to a state
1019+ * where most zones cannot be written (zone resources
1020+ * exhausted). So take preventive action by remounting
1021+ * read-only.
1022+ */
1023+ if (zi -> i_flags & ZONEFS_ZONE_OPEN &&
1024+ !(sb -> s_flags & SB_RDONLY )) {
1025+ zonefs_warn (sb , "closing zone failed, remounting filesystem read-only\n" );
1026+ sb -> s_flags |= SB_RDONLY ;
1027+ }
1028+ }
1029+ zi -> i_flags &= ~ZONEFS_ZONE_OPEN ;
1030+ dec :
1031+ atomic_dec (& sbi -> s_open_zones );
1032+ }
1033+ mutex_unlock (& zi -> i_truncate_mutex );
1034+ }
1035+
1036+ static int zonefs_file_release (struct inode * inode , struct file * file )
1037+ {
1038+ /*
1039+ * If we explicitly open a zone we must close it again as well, but the
1040+ * zone management operation can fail (either due to an IO error or as
1041+ * the zone has gone offline or read-only). Make sure we don't fail the
1042+ * close(2) for user-space.
1043+ */
1044+ if (zonefs_file_use_exp_open (inode , file ))
1045+ zonefs_close_zone (inode );
1046+
1047+ return 0 ;
1048+ }
1049+
8881050static const struct file_operations zonefs_file_operations = {
889- .open = generic_file_open ,
1051+ .open = zonefs_file_open ,
1052+ .release = zonefs_file_release ,
8901053 .fsync = zonefs_file_fsync ,
8911054 .mmap = zonefs_file_mmap ,
8921055 .llseek = zonefs_file_llseek ,
@@ -910,6 +1073,7 @@ static struct inode *zonefs_alloc_inode(struct super_block *sb)
9101073 inode_init_once (& zi -> i_vnode );
9111074 mutex_init (& zi -> i_truncate_mutex );
9121075 init_rwsem (& zi -> i_mmap_sem );
1076+ zi -> i_wr_refcnt = 0 ;
9131077
9141078 return & zi -> i_vnode ;
9151079}
@@ -960,14 +1124,15 @@ static int zonefs_statfs(struct dentry *dentry, struct kstatfs *buf)
9601124
9611125enum {
9621126 Opt_errors_ro , Opt_errors_zro , Opt_errors_zol , Opt_errors_repair ,
963- Opt_err ,
1127+ Opt_explicit_open , Opt_err ,
9641128};
9651129
9661130static const match_table_t tokens = {
9671131 { Opt_errors_ro , "errors=remount-ro" },
9681132 { Opt_errors_zro , "errors=zone-ro" },
9691133 { Opt_errors_zol , "errors=zone-offline" },
9701134 { Opt_errors_repair , "errors=repair" },
1135+ { Opt_explicit_open , "explicit-open" },
9711136 { Opt_err , NULL }
9721137};
9731138
@@ -1004,6 +1169,9 @@ static int zonefs_parse_options(struct super_block *sb, char *options)
10041169 sbi -> s_mount_opts &= ~ZONEFS_MNTOPT_ERRORS_MASK ;
10051170 sbi -> s_mount_opts |= ZONEFS_MNTOPT_ERRORS_REPAIR ;
10061171 break ;
1172+ case Opt_explicit_open :
1173+ sbi -> s_mount_opts |= ZONEFS_MNTOPT_EXPLICIT_OPEN ;
1174+ break ;
10071175 default :
10081176 return - EINVAL ;
10091177 }
@@ -1423,6 +1591,13 @@ static int zonefs_fill_super(struct super_block *sb, void *data, int silent)
14231591 sbi -> s_gid = GLOBAL_ROOT_GID ;
14241592 sbi -> s_perm = 0640 ;
14251593 sbi -> s_mount_opts = ZONEFS_MNTOPT_ERRORS_RO ;
1594+ sbi -> s_max_open_zones = bdev_max_open_zones (sb -> s_bdev );
1595+ atomic_set (& sbi -> s_open_zones , 0 );
1596+ if (!sbi -> s_max_open_zones &&
1597+ sbi -> s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN ) {
1598+ zonefs_info (sb , "No open zones limit. Ignoring explicit_open mount option\n" );
1599+ sbi -> s_mount_opts &= ~ZONEFS_MNTOPT_EXPLICIT_OPEN ;
1600+ }
14261601
14271602 ret = zonefs_read_super (sb );
14281603 if (ret )
0 commit comments