Source-Changes-HG archive

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

[src/trunk]: src/sys/dev Add two new states FSS_CREATING and FSS_DESTROYING a...



details:   https://anonhg.NetBSD.org/src/rev/dbf880b36e3d
branches:  trunk
changeset: 364958:dbf880b36e3d
user:      hannken <hannken%NetBSD.org@localhost>
date:      Wed Aug 29 09:04:40 2018 +0000

description:
Add two new states FSS_CREATING and FSS_DESTROYING and use them
while creating or destroying a snapshot.

Remove now unneeded sc_lock that made fss_ioctl mutually exclusive.

Fss_ioctl no longer blocks forever because a snapshot gets
created or destroyed.

Serialize snapshot creation and make it interruptible.

diffstat:

 sys/dev/fss.c    |  106 ++++++++++++++++++++++++++++++++++++++++--------------
 sys/dev/fssvar.h |    5 +-
 2 files changed, 81 insertions(+), 30 deletions(-)

diffs (243 lines):

diff -r 38153488cd77 -r dbf880b36e3d sys/dev/fss.c
--- a/sys/dev/fss.c     Wed Aug 29 09:04:03 2018 +0000
+++ b/sys/dev/fss.c     Wed Aug 29 09:04:40 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fss.c,v 1.105 2018/08/29 09:04:03 hannken Exp $        */
+/*     $NetBSD: fss.c,v 1.106 2018/08/29 09:04:40 hannken Exp $        */
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fss.c,v 1.105 2018/08/29 09:04:03 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fss.c,v 1.106 2018/08/29 09:04:40 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -93,6 +93,8 @@
 static u_int32_t *fss_bs_indir(struct fss_softc *, u_int32_t);
 
 static kmutex_t fss_device_lock;       /* Protect all units. */
+static kcondvar_t fss_device_cv;       /* Serialize snapshot creation. */
+static bool fss_creating = false;      /* Currently creating a snapshot. */
 static int fss_num_attached = 0;       /* Number of attached devices. */
 static struct vfs_hooks fss_vfs_hooks = {
        .vh_unmount = fss_unmount_hook
@@ -136,6 +138,7 @@
 {
 
        mutex_init(&fss_device_lock, MUTEX_DEFAULT, IPL_NONE);
+       cv_init(&fss_device_cv, "snapwait");
        if (config_cfattach_attach(fss_cd.cd_name, &fss_ca))
                aprint_error("%s: unable to register\n", fss_cd.cd_name);
 }
@@ -154,7 +157,6 @@
        sc->sc_dev = self;
        sc->sc_bdev = NODEV;
        mutex_init(&sc->sc_slock, MUTEX_DEFAULT, IPL_NONE);
-       mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
        cv_init(&sc->sc_work_cv, "fssbs");
        cv_init(&sc->sc_cache_cv, "cowwait");
        bufq_alloc(&sc->sc_bufq, "fcfs", 0);
@@ -185,7 +187,6 @@
 
        pmf_device_deregister(self);
        mutex_destroy(&sc->sc_slock);
-       mutex_destroy(&sc->sc_lock);
        cv_destroy(&sc->sc_work_cv);
        cv_destroy(&sc->sc_cache_cv);
        bufq_drain(sc->sc_bufq);
@@ -341,36 +342,83 @@
                fss->fss_flags = 0;
                /* Fall through */
        case FSSIOCSET:
-               mutex_enter(&sc->sc_lock);
+               mutex_enter(&sc->sc_slock);
                if ((flag & FWRITE) == 0)
                        error = EPERM;
-               mutex_enter(&sc->sc_slock);
-               if (error == 0 && sc->sc_state != FSS_IDLE)
+               if (error == 0 && sc->sc_state != FSS_IDLE) {
                        error = EBUSY;
+               } else {
+                       sc->sc_state = FSS_CREATING;
+                       copyinstr(fss->fss_mount, sc->sc_mntname,
+                           sizeof(sc->sc_mntname), NULL);
+                       memset(&sc->sc_time, 0, sizeof(sc->sc_time));
+                       sc->sc_clshift = 0;
+               }
                mutex_exit(&sc->sc_slock);
-               if (error == 0)
-                       error = fss_create_snapshot(sc, fss, l);
-               if (error == 0)
+               if (error)
+                       break;
+
+               /*
+                * Serialize snapshot creation.
+                */
+               mutex_enter(&fss_device_lock);
+               while (fss_creating) {
+                       error = cv_wait_sig(&fss_device_cv, &fss_device_lock);
+                       if (error) {
+                               mutex_enter(&sc->sc_slock);
+                               KASSERT(sc->sc_state == FSS_CREATING);
+                               sc->sc_state = FSS_IDLE;
+                               mutex_exit(&sc->sc_slock);
+                               mutex_exit(&fss_device_lock);
+                               break;
+                       }
+               }
+               fss_creating = true;
+               mutex_exit(&fss_device_lock);
+
+               error = fss_create_snapshot(sc, fss, l);
+               mutex_enter(&sc->sc_slock);
+               if (error == 0) {
+                       KASSERT(sc->sc_state == FSS_ACTIVE);
                        sc->sc_uflags = fss->fss_flags;
-               mutex_exit(&sc->sc_lock);
+               } else {
+                       KASSERT(sc->sc_state == FSS_CREATING);
+                       sc->sc_state = FSS_IDLE;
+               }
+               mutex_exit(&sc->sc_slock);
+
+               mutex_enter(&fss_device_lock);
+               fss_creating = false;
+               cv_broadcast(&fss_device_cv);
+               mutex_exit(&fss_device_lock);
+
                break;
 
        case FSSIOCCLR:
-               mutex_enter(&sc->sc_lock);
-               if ((flag & FWRITE) == 0)
-                       error = EPERM;
                mutex_enter(&sc->sc_slock);
-               if (error == 0 && sc->sc_state == FSS_IDLE)
-                       error = ENXIO;
+               if ((flag & FWRITE) == 0) {
+                       error = EPERM;
+               } else if (sc->sc_state != FSS_ACTIVE &&
+                   sc->sc_state != FSS_ERROR) {
+                       error = EBUSY;
+               } else {
+                       sc->sc_state = FSS_DESTROYING;
+               }
                mutex_exit(&sc->sc_slock);
-               if (error == 0)
-                       error = fss_delete_snapshot(sc, l);
-               mutex_exit(&sc->sc_lock);
+               if (error)
+                       break;
+
+               error = fss_delete_snapshot(sc, l);
+               mutex_enter(&sc->sc_slock);
+               if (error)
+                       fss_error(sc, "Failed to delete snapshot");
+               else
+                       KASSERT(sc->sc_state == FSS_IDLE);
+               mutex_exit(&sc->sc_slock);
                break;
 
 #ifndef _LP64
        case FSSIOCGET50:
-               mutex_enter(&sc->sc_lock);
                mutex_enter(&sc->sc_slock);
                if (sc->sc_state == FSS_IDLE) {
                        error = ENXIO;
@@ -390,12 +438,10 @@
                        error = 0;
                }
                mutex_exit(&sc->sc_slock);
-               mutex_exit(&sc->sc_lock);
                break;
 #endif /* _LP64 */
 
        case FSSIOCGET:
-               mutex_enter(&sc->sc_lock);
                mutex_enter(&sc->sc_slock);
                if (sc->sc_state == FSS_IDLE) {
                        error = ENXIO;
@@ -415,7 +461,6 @@
                        error = 0;
                }
                mutex_exit(&sc->sc_slock);
-               mutex_exit(&sc->sc_lock);
                break;
 
        case FSSIOFSET:
@@ -902,20 +947,23 @@
        if ((sc->sc_flags & FSS_PERSISTENT) == 0 && sc->sc_state != FSS_ERROR) {
                mutex_exit(&sc->sc_slock);
                fscow_disestablish(sc->sc_mount, fss_copy_on_write, sc);
-               mutex_enter(&sc->sc_slock);
+       } else {
+               mutex_exit(&sc->sc_slock);
        }
-       sc->sc_state = FSS_IDLE;
-       sc->sc_mount = NULL;
-       sc->sc_bdev = NODEV;
-       mutex_exit(&sc->sc_slock);
 
        fss_softc_free(sc);
        if (sc->sc_flags & FSS_PERSISTENT)
                vrele(sc->sc_bs_vp);
        else
                vn_close(sc->sc_bs_vp, FREAD|FWRITE, l->l_cred);
+
+       mutex_enter(&sc->sc_slock);
+       sc->sc_state = FSS_IDLE;
+       sc->sc_mount = NULL;
+       sc->sc_bdev = NODEV;
        sc->sc_bs_vp = NULL;
        sc->sc_flags &= ~FSS_PERSISTENT;
+       mutex_exit(&sc->sc_slock);
 
        return 0;
 }
@@ -1323,6 +1371,7 @@
        switch (cmd) {
        case MODULE_CMD_INIT:
                mutex_init(&fss_device_lock, MUTEX_DEFAULT, IPL_NONE);
+               cv_init(&fss_device_cv, "snapwait");
                error = config_cfdriver_attach(&fss_cd);
                if (error) {
                        mutex_destroy(&fss_device_lock);
@@ -1361,6 +1410,7 @@
                            &fss_cdevsw, &fss_cmajor);
                        break;
                }
+               cv_destroy(&fss_device_cv);
                mutex_destroy(&fss_device_lock);
                break;
 
diff -r 38153488cd77 -r dbf880b36e3d sys/dev/fssvar.h
--- a/sys/dev/fssvar.h  Wed Aug 29 09:04:03 2018 +0000
+++ b/sys/dev/fssvar.h  Wed Aug 29 09:04:40 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fssvar.h,v 1.30 2018/08/29 09:04:03 hannken Exp $      */
+/*     $NetBSD: fssvar.h,v 1.31 2018/08/29 09:04:40 hannken Exp $      */
 
 /*-
  * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@@ -135,14 +135,15 @@
 
 typedef enum {
        FSS_IDLE,                       /* Device is unconfigured */
+       FSS_CREATING,                   /* Device is currently configuring */
        FSS_ACTIVE,                     /* Device is configured */
+       FSS_DESTROYING,                 /* Device is currently unconfiguring */
        FSS_ERROR                       /* Device had errors */
 } fss_state_t;
 
 struct fss_softc {
        device_t        sc_dev;         /* Self */
        kmutex_t        sc_slock;       /* Protect this softc */
-       kmutex_t        sc_lock;        /* Sleep lock for fss_ioctl */
        kcondvar_t      sc_work_cv;     /* Signals work for the kernel thread */
        kcondvar_t      sc_cache_cv;    /* Signals free cache slot */
        fss_state_t     sc_state;       /* Current state */



Home | Main Index | Thread Index | Old Index