git: 49050613ef1f - main - ctl(4): Do hole-punching for UNMAP to file-backed LUNs

Ka Ho Ng khng at FreeBSD.org
Tue Sep 14 19:52:33 UTC 2021


The branch main has been updated by khng:

URL: https://cgit.FreeBSD.org/src/commit/?id=49050613ef1fac244c3cb9767cbdff3d10bee670

commit 49050613ef1fac244c3cb9767cbdff3d10bee670
Author:     Ka Ho Ng <khng at FreeBSD.org>
AuthorDate: 2021-09-14 19:51:58 +0000
Commit:     Ka Ho Ng <khng at FreeBSD.org>
CommitDate: 2021-09-14 19:51:58 +0000

    ctl(4): Do hole-punching for UNMAP to file-backed LUNs
    
    This adds support for SCSI UNMAP command to file-backed LUNs, if the
    underlying file system has a non-zerofilling VOP_DEALLOCATE
    implementation where some or all parts of the requested operation range
    may be deallocated.
    
    Sponsored by:   The FreeBSD Foundation
    Reviewed by:    mav
    Differential Revision:  https://reviews.freebsd.org/D31922
---
 sys/cam/ctl/ctl_backend_block.c | 99 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index 83ea6b43dac3..8c126d8be229 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -3,13 +3,16 @@
  *
  * Copyright (c) 2003 Silicon Graphics International Corp.
  * Copyright (c) 2009-2011 Spectra Logic Corporation
- * Copyright (c) 2012 The FreeBSD Foundation
+ * Copyright (c) 2012,2021 The FreeBSD Foundation
  * Copyright (c) 2014-2015 Alexander Motin <mav at FreeBSD.org>
  * All rights reserved.
  *
  * Portions of this software were developed by Edward Tomasz Napierala
  * under sponsorship from the FreeBSD Foundation.
  *
+ * Portions of this software were developed by Ka Ho Ng <khng at FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -81,6 +84,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/nv.h>
 #include <sys/dnv.h>
 #include <sys/sx.h>
+#include <sys/unistd.h>
 
 #include <geom/geom.h>
 
@@ -245,6 +249,8 @@ static void ctl_be_block_gls_file(struct ctl_be_block_lun *be_lun,
 				  struct ctl_be_block_io *beio);
 static uint64_t ctl_be_block_getattr_file(struct ctl_be_block_lun *be_lun,
 					 const char *attrname);
+static void ctl_be_block_unmap_file(struct ctl_be_block_lun *be_lun,
+				    struct ctl_be_block_io *beio);
 static void ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
 				   struct ctl_be_block_io *beio);
 static void ctl_be_block_unmap_dev(struct ctl_be_block_lun *be_lun,
@@ -854,6 +860,84 @@ ctl_be_block_getattr_file(struct ctl_be_block_lun *be_lun, const char *attrname)
 	return (val);
 }
 
+static void
+ctl_be_block_unmap_file(struct ctl_be_block_lun *be_lun,
+		        struct ctl_be_block_io *beio)
+{
+	struct ctl_be_block_filedata *file_data;
+	union ctl_io *io;
+	struct ctl_ptr_len_flags *ptrlen;
+	struct scsi_unmap_desc *buf, *end;
+	struct mount *mp;
+	off_t off, len;
+	int error;
+
+	io = beio->io;
+	file_data = &be_lun->backend.file;
+	mp = NULL;
+	error = 0;
+
+	binuptime(&beio->ds_t0);
+	devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
+
+	(void)vn_start_write(be_lun->vn, &mp, V_WAIT);
+	vn_lock(be_lun->vn, vn_lktype_write(mp, be_lun->vn) | LK_RETRY);
+	if (beio->io_offset == -1) {
+		beio->io_len = 0;
+		ptrlen = (struct ctl_ptr_len_flags *)
+		    &io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
+		buf = (struct scsi_unmap_desc *)ptrlen->ptr;
+		end = buf + ptrlen->len / sizeof(*buf);
+		for (; buf < end; buf++) {
+			off = (off_t)scsi_8btou64(buf->lba) *
+			    be_lun->cbe_lun.blocksize;
+			len = (off_t)scsi_4btoul(buf->length) *
+			    be_lun->cbe_lun.blocksize;
+			beio->io_len += len;
+			error = vn_deallocate(be_lun->vn, &off, &len,
+			    0, IO_NOMACCHECK | IO_NODELOCKED, file_data->cred,
+			    NOCRED);
+			if (error != 0)
+				break;
+		}
+	} else {
+		/* WRITE_SAME */
+		off = beio->io_offset;
+		len = beio->io_len;
+		error = vn_deallocate(be_lun->vn, &off, &len, 0,
+		    IO_NOMACCHECK | IO_NODELOCKED, file_data->cred, NOCRED);
+	}
+	VOP_UNLOCK(be_lun->vn);
+	vn_finished_write(mp);
+
+	mtx_lock(&be_lun->io_lock);
+	devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
+	    beio->ds_tag_type, beio->ds_trans_type,
+	    /*now*/ NULL, /*then*/&beio->ds_t0);
+	mtx_unlock(&be_lun->io_lock);
+
+	/*
+	 * If we got an error, set the sense data to "MEDIUM ERROR" and
+	 * return the I/O to the user.
+	 */
+	switch (error) {
+	case 0:
+		ctl_set_success(&io->scsiio);
+		break;
+	case ENOSPC:
+	case EDQUOT:
+		ctl_set_space_alloc_fail(&io->scsiio);
+		break;
+	case EROFS:
+	case EACCES:
+		ctl_set_hw_write_protected(&io->scsiio);
+		break;
+	default:
+		ctl_set_medium_error(&io->scsiio, false);
+	}
+	ctl_complete_beio(beio);
+}
+
 static void
 ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun,
 			   struct ctl_be_block_io *beio)
@@ -1804,6 +1888,7 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
 	struct vattr		      vattr;
 	off_t			      ps, pss, po, pos, us, uss, uo, uos;
 	int			      error;
+	long			      pconf;
 
 	cbe_lun = &be_lun->cbe_lun;
 	file_data = &be_lun->backend.file;
@@ -1814,7 +1899,7 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
 	be_lun->lun_flush = ctl_be_block_flush_file;
 	be_lun->get_lba_status = ctl_be_block_gls_file;
 	be_lun->getattr = ctl_be_block_getattr_file;
-	be_lun->unmap = NULL;
+	be_lun->unmap = ctl_be_block_unmap_file;
 	cbe_lun->flags &= ~CTL_LUN_FLAG_UNMAP;
 
 	error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
@@ -1825,6 +1910,16 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
 		return (error);
 	}
 
+	error = VOP_PATHCONF(be_lun->vn, _PC_DEALLOC_PRESENT, &pconf);
+	if (error != 0) {
+		snprintf(req->error_str, sizeof(req->error_str),
+		    "error calling VOP_PATHCONF() for file %s",
+		    be_lun->dev_path);
+		return (error);
+	}
+	if (pconf == 1)
+		cbe_lun->flags |= CTL_LUN_FLAG_UNMAP;
+
 	file_data->cred = crhold(curthread->td_ucred);
 	if (params->lun_size_bytes != 0)
 		be_lun->size_bytes = params->lun_size_bytes;


More information about the dev-commits-src-main mailing list