The branch main has been updated by khng:

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

commit 49050613ef1fac244c3cb9767cbdff3d10bee670
Author:     Ka Ho Ng <k...@freebsd.org>
AuthorDate: 2021-09-14 19:51:58 +0000
Commit:     Ka Ho Ng <k...@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 <m...@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 <k...@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;
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to