subr_disk - Keep an open count
authorAlex Hornung <ahornung@gmail.com>
Fri, 19 Nov 2010 14:31:26 +0000 (14:31 +0000)
committerAlex Hornung <ahornung@gmail.com>
Fri, 19 Nov 2010 14:53:33 +0000 (14:53 +0000)
sys/kern/subr_disk.c
sys/sys/disk.h

index 76c141a..f30df63 100644 (file)
@@ -140,7 +140,7 @@ static LIST_HEAD(, disk) disklist = LIST_HEAD_INITIALIZER(&disklist);
 static struct lwkt_token disklist_token;
 
 static struct dev_ops disk_ops = {
-       { "disk", 0, D_DISK | D_MPSAFE },
+       { "disk", 0, D_DISK | D_MPSAFE | D_TRACKCLOSE },
        .d_open = diskopen,
        .d_close = diskclose,
        .d_read = physread,
@@ -681,6 +681,12 @@ disk_setdisktype(struct disk *disk, const char *type)
        return udev_dict_set_cstr(disk->d_cdev, "disk-type", __DECONST(char *, type));
 }
 
+int
+disk_getopencount(struct disk *disk)
+{
+       return disk->d_opencount;
+}
+
 static void
 _setdiskinfo(struct disk *disk, struct disk_info *info)
 {
@@ -959,6 +965,11 @@ out:
        }
        rel_mplock();
 
+       KKASSERT(dp->d_opencount >= 0);
+       /* If the open was successful, bump open count */
+       if (error == 0)
+               atomic_add_int(&dp->d_opencount, 1);
+
        return(error);
 }
 
@@ -976,6 +987,11 @@ diskclose(struct dev_close_args *ap)
        error = 0;
        dp = dev->si_disk;
 
+       KKASSERT(dp->d_opencount >= 1);
+       /* If this is not the last close, just ignore it */
+       if ((atomic_fetchadd_int(&dp->d_opencount, -1)) > 1)
+               return 0;
+
        get_mplock();
        dsclose(dev, ap->a_devtype, dp->d_slice);
        if (!dsisopen(dp->d_slice)) {
index 9477acd..6a3a6da 100644 (file)
@@ -127,6 +127,7 @@ struct disk {
        struct dev_ops          *d_dev_ops;     /* our device switch */
        struct dev_ops          *d_raw_ops;     /* the raw device switch */
        u_int                   d_flags;
+       int                     d_opencount;    /* The current open count */
        cdev_t                  d_rawdev;       /* backing raw device */
        cdev_t                  d_cdev;         /* special whole-disk part */
        struct diskslices       *d_slice;
@@ -153,6 +154,7 @@ cdev_t disk_locate (const char *devname);
 void disk_destroy (struct disk *disk);
 void disk_setdiskinfo (struct disk *disk, struct disk_info *info);
 int disk_setdisktype(struct disk *disk, const char *type);
+int disk_getopencount(struct disk *disk);
 void disk_setdiskinfo_sync(struct disk *disk, struct disk_info *info);
 int disk_dumpcheck (cdev_t dev, u_int64_t *count, u_int64_t *blkno, u_int *secsize);
 int disk_dumpconf(cdev_t dev, u_int onoff);