summaryrefslogtreecommitdiffstats
path: root/sys/geom/mirror/g_mirror.c
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2012-07-01 15:43:52 +0000
committerglebius <glebius@FreeBSD.org>2012-07-01 15:43:52 +0000
commit1a62bb322429c1e61662250887fdaf2659cfa436 (patch)
tree3a047de63c50bf5051cb25a37c411188befef27c /sys/geom/mirror/g_mirror.c
parent2c999b9f213cb3d7bd6cab0686c20ec839d2619f (diff)
downloadFreeBSD-src-1a62bb322429c1e61662250887fdaf2659cfa436.zip
FreeBSD-src-1a62bb322429c1e61662250887fdaf2659cfa436.tar.gz
Make geom_mirror more friendly to SSDs. To properly support TRIM,
we need to pass BIO_DELETE requests down to providers that support it. Also, we need to announce our support for BIO_DELETE to upper consumer. This requires: - In g_mirror_start() return true for "GEOM::candelete" request. - In g_mirror_init_disk() probe below provider for "GEOM::candelete" attribute, and mark disk with a flag if it does support BIO_DELETE. - In g_mirror_register_request() distribute BIO_DELETE requests only to those disks, that do support it. Note that we announce "GEOM::candelete" as true unconditionally of whether we have TRIM-capable media down below or not. This is made intentionally, because upper consumer (usually UFS) requests the attribite only once at mount time. And if user ever migrates his mirror from HDDs to SSDs, then he/she would get TRIM working without remounting filesystem. Reviewed by: pjd
Diffstat (limited to 'sys/geom/mirror/g_mirror.c')
-rw-r--r--sys/geom/mirror/g_mirror.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c
index 21efd81..3f60fd2 100644
--- a/sys/geom/mirror/g_mirror.c
+++ b/sys/geom/mirror/g_mirror.c
@@ -440,7 +440,7 @@ g_mirror_init_disk(struct g_mirror_softc *sc, struct g_provider *pp,
struct g_mirror_metadata *md, int *errorp)
{
struct g_mirror_disk *disk;
- int error;
+ int i, error;
disk = malloc(sizeof(*disk), M_MIRROR, M_NOWAIT | M_ZERO);
if (disk == NULL) {
@@ -455,6 +455,11 @@ g_mirror_init_disk(struct g_mirror_softc *sc, struct g_provider *pp,
disk->d_state = G_MIRROR_DISK_STATE_NONE;
disk->d_priority = md->md_priority;
disk->d_flags = md->md_dflags;
+ error = g_getattr("GEOM::candelete", disk->d_consumer, &i);
+ if (error != 0)
+ goto fail;
+ if (i)
+ disk->d_flags |= G_MIRROR_DISK_FLAG_CANDELETE;
if (md->md_provider[0] != '\0')
disk->d_flags |= G_MIRROR_DISK_FLAG_HARDCODED;
disk->d_sync.ds_consumer = NULL;
@@ -1085,7 +1090,9 @@ g_mirror_start(struct bio *bp)
g_mirror_flush(sc, bp);
return;
case BIO_GETATTR:
- if (strcmp("GEOM::kerneldump", bp->bio_attribute) == 0) {
+ if (g_handleattr_int(bp, "GEOM::candelete", 1))
+ return;
+ else if (strcmp("GEOM::kerneldump", bp->bio_attribute) == 0) {
g_mirror_kernel_dump(bp);
return;
}
@@ -1632,6 +1639,9 @@ g_mirror_register_request(struct bio *bp)
default:
continue;
}
+ if (bp->bio_cmd == BIO_DELETE &&
+ (disk->d_flags & G_MIRROR_DISK_FLAG_CANDELETE) == 0)
+ continue;
cbp = g_clone_bio(bp);
if (cbp == NULL) {
for (cbp = bioq_first(&queue); cbp != NULL;
OpenPOWER on IntegriCloud