diff options
-rw-r--r-- | share/man/man9/disk.9 | 4 | ||||
-rw-r--r-- | sys/geom/geom_disk.c | 22 | ||||
-rw-r--r-- | sys/geom/geom_disk.h | 1 |
3 files changed, 25 insertions, 2 deletions
diff --git a/share/man/man9/disk.9 b/share/man/man9/disk.9 index d8d446b..d071613 100644 --- a/share/man/man9/disk.9 +++ b/share/man/man9/disk.9 @@ -94,8 +94,10 @@ Currently supported flags are (maintained by device driver), .Dv DISKFLAG_OPEN (maintained by storage framework), -and .Dv DISKFLAG_CANDELETE +(maintained by device driver), +and +.Dv DISKFLAG_CANFLUSHCACHE (maintained by device driver). .It Vt "const char *" Va d_name Holds the name of the storage device class, e.g., diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 6115106..1a65d89 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -202,8 +202,10 @@ g_disk_done(struct bio *bp) if (bp2->bio_error == 0) bp2->bio_error = bp->bio_error; bp2->bio_completed += bp->bio_completed; - if ((dp = bp2->bio_to->geom->softc)) + if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) && + (dp = bp2->bio_to->geom->softc)) { devstat_end_transaction_bio(dp->d_devstat, bp); + } g_destroy_bio(bp); bp2->bio_inbed++; if (bp2->bio_children == bp2->bio_inbed) { @@ -304,6 +306,24 @@ g_disk_start(struct bio *bp) else error = ENOIOCTL; break; + case BIO_FLUSH: + g_trace(G_T_TOPOLOGY, "g_disk_flushcache(%s)", + bp->bio_to->name); + if (!(dp->d_flags & DISKFLAG_CANFLUSHCACHE)) { + g_io_deliver(bp, ENODEV); + return; + } + bp2 = g_clone_bio(bp); + if (bp2 == NULL) { + g_io_deliver(bp, ENOMEM); + return; + } + bp2->bio_done = g_disk_done; + bp2->bio_disk = dp; + g_disk_lock_giant(dp); + dp->d_strategy(bp2); + g_disk_unlock_giant(dp); + break; default: error = EOPNOTSUPP; break; diff --git a/sys/geom/geom_disk.h b/sys/geom/geom_disk.h index 23719bf..9e8b1ef 100644 --- a/sys/geom/geom_disk.h +++ b/sys/geom/geom_disk.h @@ -91,6 +91,7 @@ struct disk { #define DISKFLAG_NEEDSGIANT 0x1 #define DISKFLAG_OPEN 0x2 #define DISKFLAG_CANDELETE 0x4 +#define DISKFLAG_CANFLUSHCACHE 0x8 struct disk *disk_alloc(void); void disk_create(struct disk *disk, int version); |