Re: [PATCH] null_blk: support readonly and offline zone conditions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Damien, thanks for the review. I will reflect most of your comments. Please find
my responses in line.

On Nov 30, 2022 / 19:18, Damien Le Moal wrote:
> On 11/30/22 18:41, Shin'ichiro Kawasaki wrote:
> 
> [...]
> 
> > @@ -627,6 +631,12 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_op op,
> >  
> >  	null_lock_zone(dev, zone);
> >  
> > +	if (zone->cond == BLK_ZONE_COND_READONLY ||
> > +	    zone->cond == BLK_ZONE_COND_OFFLINE) {
> > +		ret = BLK_STS_IOERR;
> > +		goto unlock;
> > +	}
> > +
> >  	switch (op) {
> >  	case REQ_OP_ZONE_RESET:
> >  		ret = null_reset_zone(dev, zone);
> > @@ -648,6 +658,7 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_op op,
> >  	if (ret == BLK_STS_OK)
> >  		trace_nullb_zone_op(cmd, zone_no, zone->cond);
> >  
> > +unlock:
> >  	null_unlock_zone(dev, zone);
> >  
> >  	return ret;
> > @@ -674,10 +685,103 @@ blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_op op,
> >  	default:
> >  		dev = cmd->nq->dev;
> >  		zone = &dev->zones[null_zone_no(dev, sector)];
> > -
> 
> I would prefer keeping this blank line after the "return BLK_STS_IOERR" below.
> 
> > +		if (zone->cond == BLK_ZONE_COND_OFFLINE)
> > +			return BLK_STS_IOERR;
> >  		null_lock_zone(dev, zone);
> >  		sts = null_process_cmd(cmd, op, sector, nr_sectors);
> >  		null_unlock_zone(dev, zone);
> >  		return sts;
> >  	}
> >  }
> > +
> > +/*
> > + * Set specified condition COND_READONLY or COND_OFFLINE to a zone.
> 
> May be "Set a zone in the read-only or offline condition."
> 
> > + */
> > +static int null_set_zone_cond(struct nullb_device *dev, struct nullb_zone *zone,
> > +			      enum blk_zone_cond cond)
> > +{
> > +	enum blk_zone_cond old_cond;
> > +	int ret;
> > +
> > +	if (WARN_ON_ONCE(cond != BLK_ZONE_COND_READONLY &&
> > +			 cond != BLK_ZONE_COND_OFFLINE))
> > +		return -EINVAL;
> > +
> > +	null_lock_zone(dev, zone);
> > +
> > +	/*
> > +	 * When current zone condition is readonly or offline, handle the zone
> > +	 * as full condition to avoid failure of zone reset or zone finish.
> > +	 */
> > +	old_cond = zone->cond;
> > +	if (zone->cond == BLK_ZONE_COND_READONLY ||
> > +	    zone->cond == BLK_ZONE_COND_OFFLINE)
> > +		zone->cond = BLK_ZONE_COND_FULL;
> > +
> > +	/*
> > +	 * If readonly condition is requested again to zones already in readonly
> 
> If the...
> 
> > +	 * condition, reset the zones to restore back normal empty condition.
> > +	 * Do same if offline condition is requested for offline zones.
> 
> Do the same if the...
> 
> > +	 * Otherwise, set desired zone condition to the zones. Finish the zones
> 
> Otherwise, set the specified zone condition. Finish...
> 
> > +	 * beforehand to free up zone resources.
> > +	 */
> > +	if (old_cond == cond) {
> > +		ret = null_reset_zone(dev, zone);
> 
> This will not restore conventional zones since reset will be an error for
> these... So you need to do the reset "manually":
> 
> You could simply do:
> 
> 		/* Restore the zone to a usable condition */
> 		if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) {
> 			zone->cond = BLK_ZONE_COND_NOT_WP;
> 			zone->wp = (sector_t)-1;
> 		} else {
> 			zone->cond = BLK_ZONE_COND_EMPTY;
> 			zone->wp = zone->start;

I see, manual zone status change to empty status could be straight forward.
Looking in null_reset_zone(), I think additional null_handle_discard() call will
be required here, if the device is memory backed.

> 		}
> 
> Then the hunk above that set the zone to FULL is not needed, and the
> variable "old_cond" is also not needed as the "if" above can be:
> 
> 	if (zone->cond == cond)

I agree that old_cond is not required to restore empty condition manually.
However, still I think we need to set the zone to FULL before calling
null_finish_zone(). Let's say that the target zone is already set read-only,
then it is made offline. In such a case, null_fininsh_zone() fails for the
read-only zone. To allow such condition change, I added the old_cond.

> > +	} else {
> > +		ret = null_finish_zone(dev, zone);
> 
> Do the finish only for seq zones. Otherwise, setting a conventional zone
> to read only or offline will always fail.

As I will comment below, I don't think conventional zones can be read-only or
offline. So conventional zones are handled as an error in zone_cond_store().

> 
> > +		if (!ret) {
> > +			zone->cond = cond;
> > +			zone->wp = (sector_t)-1;
> > +		}
> > +	}
> > +
> > +	if (ret)
> > +		zone->cond = old_cond;
> 
> There should never be any failure with this. So we should not need this.
> 
> > +
> > +	null_unlock_zone(dev, zone);
> > +	return ret;
> > +}
> > +
> > +/*
> > + * Identify a zone from the sector written to configfs file. Then set zone
> > + * condition to the zone.
> > + */
> > +ssize_t zone_cond_store(struct nullb_device *dev, const char *page,
> > +			size_t count, enum blk_zone_cond cond)
> > +{
> > +	unsigned long long sector;
> > +	unsigned int zone_no;
> > +	int ret;
> > +
> > +	if (!dev->zoned) {
> > +		pr_err("null_blk device is not zoned\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!dev->zones) {
> > +		pr_err("null_blk device is not yet powered\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ret = kstrtoull(page, 0, &sector);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	zone_no = null_zone_no(dev, sector);
> > +
> 
> Remove the blank line here.
> 
> > +	if (zone_no >= dev->nr_zones) {
> > +		pr_err("Sector out of range\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (dev->zones[zone_no].type == BLK_ZONE_TYPE_CONVENTIONAL) {
> > +		pr_err("Can not change condition of conventional zones\n");
> 
> Why ? Conventional zones can go read-only or offline too. At least on
> ZBC/ZAC SMR HDDs, they can. So allowing this to happen with null_blk is
> desired too.

As far as I refer ZBC r05 Table 10 and ZAC r05 Table 5, conventional zones can
have only zone condition "NOT WRITE POINTER". I think the tables show that the
zone conditions "READ ONLY" and "OFFLINE" are valid for sequential write
required zones (and sequential write preferred zones). Do I misinterpret the
specs?

-- 
Shin'ichiro Kawasaki



[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux