svn commit: r297311 - in head/sys/ufs: ffs ufs

Konstantin Belousov kib at FreeBSD.org
Sun Mar 27 08:21:19 UTC 2016


Author: kib
Date: Sun Mar 27 08:21:17 2016
New Revision: 297311
URL: https://svnweb.freebsd.org/changeset/base/297311

Log:
  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 at talkpoint.com>
  Tested by:	Nick Evans <nevans at talkpoint.com>, pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Modified:
  head/sys/ufs/ffs/ffs_alloc.c
  head/sys/ufs/ffs/ffs_vfsops.c
  head/sys/ufs/ufs/ufsmount.h

Modified: head/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- head/sys/ufs/ffs/ffs_alloc.c	Sun Mar 27 08:12:01 2016	(r297310)
+++ head/sys/ufs/ffs/ffs_alloc.c	Sun Mar 27 08:21:17 2016	(r297311)
@@ -2270,8 +2270,6 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size
 	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, i
 	 * 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;

Modified: head/sys/ufs/ffs/ffs_vfsops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vfsops.c	Sun Mar 27 08:12:01 2016	(r297310)
+++ head/sys/ufs/ffs/ffs_vfsops.c	Sun Mar 27 08:21:17 2016	(r297311)
@@ -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) {

Modified: head/sys/ufs/ufs/ufsmount.h
==============================================================================
--- head/sys/ufs/ufs/ufsmount.h	Sun Mar 27 08:12:01 2016	(r297310)
+++ head/sys/ufs/ufs/ufsmount.h	Sun Mar 27 08:21:17 2016	(r297311)
@@ -50,6 +50,7 @@ MALLOC_DECLARE(M_UFSMNT);
 struct buf;
 struct inode;
 struct nameidata;
+struct taskqueue;
 struct timeval;
 struct ucred;
 struct uio;
@@ -85,6 +86,8 @@ struct ufsmount {
 	int64_t	um_savedmaxfilesize;		/* XXX - limit maxfilesize */
 	int	um_candelete;			/* devvp supports TRIM */
 	int	um_writesuspended;		/* suspension in progress */
+	u_int	um_trim_inflight;
+	struct taskqueue *um_trim_tq;
 	int	(*um_balloc)(struct vnode *, off_t, int, struct ucred *,
 		    int, struct buf **);
 	int	(*um_blkatoff)(struct vnode *, off_t, char **, struct buf **);


More information about the svn-src-head mailing list