summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2016-03-27 08:21:17 +0000
committerkib <kib@FreeBSD.org>2016-03-27 08:21:17 +0000
commitdae532b324d6299b693cf731a6c4dd2b97e0be87 (patch)
tree755dac2eb6231a130cb58adf174fe635757001ad /sys/ufs/ffs
parent22c1ebea2165a7ab10a96ecfa28eeadff62b87e2 (diff)
downloadFreeBSD-src-dae532b324d6299b693cf731a6c4dd2b97e0be87.zip
FreeBSD-src-dae532b324d6299b693cf731a6c4dd2b97e0be87.tar.gz
Split the global taskqueue used to process all UFS trim completions,
into per-mount taskqueue with the private taskqueue processing thread. This allows to drain the taskqueue on unmount, to ensure that all TRIMs are finished before mount structures are freed. But just draining the taskqueue where TRIM biodone geom-up completions are processed is not enough, since ffs_blkfree(), called by the task, might result in more writes. Count inflight delayed blkfree's and pause() unmount until the counter drains as well. Reported by: Nick Evans <nevans@talkpoint.com> Tested by: Nick Evans <nevans@talkpoint.com>, pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r--sys/ufs/ffs/ffs_alloc.c6
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c13
2 files changed, 16 insertions, 3 deletions
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 19c00de..799efe3 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -2270,8 +2270,6 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd)
bdwrite(bp);
}
-TASKQUEUE_DEFINE_THREAD(ffs_trim);
-
struct ffs_blkfree_trim_params {
struct task task;
struct ufsmount *ump;
@@ -2294,6 +2292,7 @@ ffs_blkfree_trim_task(ctx, pending)
ffs_blkfree_cg(tp->ump, tp->ump->um_fs, tp->devvp, tp->bno, tp->size,
tp->inum, tp->pdephd);
vn_finished_secondary_write(UFSTOVFS(tp->ump));
+ atomic_add_int(&tp->ump->um_trim_inflight, -1);
free(tp, M_TEMP);
}
@@ -2306,7 +2305,7 @@ ffs_blkfree_trim_completed(bip)
tp = bip->bio_caller2;
g_destroy_bio(bip);
TASK_INIT(&tp->task, 0, ffs_blkfree_trim_task, tp);
- taskqueue_enqueue(taskqueue_ffs_trim, &tp->task);
+ taskqueue_enqueue(tp->ump->um_trim_tq, &tp->task);
}
void
@@ -2350,6 +2349,7 @@ ffs_blkfree(ump, fs, devvp, bno, size, inum, vtype, dephd)
* reordering, TRIM might be issued after we reuse the block
* and write some new data into it.
*/
+ atomic_add_int(&ump->um_trim_inflight, 1);
tp = malloc(sizeof(struct ffs_blkfree_trim_params), M_TEMP, M_WAITOK);
tp->ump = ump;
tp->devvp = devvp;
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index a82ef61..b89dc33 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/namei.h>
#include <sys/priv.h>
#include <sys/proc.h>
+#include <sys/taskqueue.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/mount.h>
@@ -1005,6 +1006,12 @@ ffs_mountfs(devvp, mp, td)
mp->mnt_stat.f_mntonname);
ump->um_candelete = 0;
}
+ if (ump->um_candelete) {
+ ump->um_trim_tq = taskqueue_create("trim", M_WAITOK,
+ taskqueue_thread_enqueue, &ump->um_trim_tq);
+ taskqueue_start_threads(&ump->um_trim_tq, 1, PVFS,
+ "%s trim", mp->mnt_stat.f_mntonname);
+ }
}
ump->um_mountp = mp;
@@ -1260,6 +1267,12 @@ ffs_unmount(mp, mntflags)
}
if (susp)
vfs_write_resume(mp, VR_START_WRITE);
+ if (ump->um_trim_tq != NULL) {
+ while (ump->um_trim_inflight != 0)
+ pause("ufsutr", hz);
+ taskqueue_drain_all(ump->um_trim_tq);
+ taskqueue_free(ump->um_trim_tq);
+ }
DROP_GIANT();
g_topology_lock();
if (ump->um_fsckpid > 0) {
OpenPOWER on IntegriCloud