Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 Jan 2011 22:51:28 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r218079 - in stable/8/sys/ufs: ffs ufs
Message-ID:  <201101292251.p0TMpSTW048372@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Jan 29 22:51:27 2011
New Revision: 218079
URL: http://svn.freebsd.org/changeset/base/218079

Log:
  MFC r216796:
  Add kernel side support for BIO_DELETE/TRIM on UFS.
  
  Tested by:	pho

Modified:
  stable/8/sys/ufs/ffs/ffs_alloc.c
  stable/8/sys/ufs/ffs/ffs_vfsops.c
  stable/8/sys/ufs/ffs/fs.h
  stable/8/sys/ufs/ufs/ufsmount.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- stable/8/sys/ufs/ffs/ffs_alloc.c	Sat Jan 29 22:11:13 2011	(r218078)
+++ stable/8/sys/ufs/ffs/ffs_alloc.c	Sat Jan 29 22:51:27 2011	(r218079)
@@ -78,6 +78,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
+#include <sys/taskqueue.h>
+
+#include <geom/geom.h>
 
 #include <ufs/ufs/extattr.h>
 #include <ufs/ufs/quota.h>
@@ -94,6 +97,10 @@ typedef ufs2_daddr_t allocfcn_t(struct i
 static ufs2_daddr_t ffs_alloccg(struct inode *, u_int, ufs2_daddr_t, int);
 static ufs2_daddr_t
 	      ffs_alloccgblk(struct inode *, struct buf *, ufs2_daddr_t);
+static void	ffs_blkfree_cg(struct ufsmount *, struct fs *,
+		    struct vnode *, ufs2_daddr_t, long, ino_t);
+static void	ffs_blkfree_trim_completed(struct bio *);
+static void	ffs_blkfree_trim_task(void *ctx, int pending __unused);
 #ifdef INVARIANTS
 static int	ffs_checkblk(struct inode *, ufs2_daddr_t, long);
 #endif
@@ -1843,8 +1850,8 @@ ffs_isfreeblock(struct fs *fs, u_char *c
  * free map. If a fragment is deallocated, a possible
  * block reassembly is checked.
  */
-void
-ffs_blkfree(ump, fs, devvp, bno, size, inum)
+static void
+ffs_blkfree_cg(ump, fs, devvp, bno, size, inum)
 	struct ufsmount *ump;
 	struct fs *fs;
 	struct vnode *devvp;
@@ -1970,6 +1977,86 @@ ffs_blkfree(ump, fs, devvp, bno, size, i
 	bdwrite(bp);
 }
 
+TASKQUEUE_DEFINE_THREAD(ffs_trim);
+
+struct ffs_blkfree_trim_params {
+	struct task task;
+	struct ufsmount *ump;
+	struct vnode *devvp;
+	ufs2_daddr_t bno;
+	long size;
+	ino_t inum;
+};
+
+static void
+ffs_blkfree_trim_task(ctx, pending)
+	void *ctx;
+	int pending;
+{
+	struct ffs_blkfree_trim_params *tp;
+
+	tp = ctx;
+	ffs_blkfree_cg(tp->ump, tp->ump->um_fs, tp->devvp, tp->bno, tp->size,
+	    tp->inum);
+	vn_finished_secondary_write(UFSTOVFS(tp->ump));
+	free(tp, M_TEMP);
+}
+
+static void
+ffs_blkfree_trim_completed(bip)
+	struct bio *bip;
+{
+	struct ffs_blkfree_trim_params *tp;
+
+	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);
+}
+
+void
+ffs_blkfree(ump, fs, devvp, bno, size, inum)
+	struct ufsmount *ump;
+	struct fs *fs;
+	struct vnode *devvp;
+	ufs2_daddr_t bno;
+	long size;
+	ino_t inum;
+{
+	struct mount *mp;
+	struct bio *bip;
+	struct ffs_blkfree_trim_params *tp;
+
+	if (!ump->um_candelete) {
+		ffs_blkfree_cg(ump, fs, devvp, bno, size, inum);
+		return;
+	}
+
+	/*
+	 * Postpone the set of the free bit in the cg bitmap until the
+	 * BIO_DELETE is completed.  Otherwise, due to disk queue
+	 * reordering, TRIM might be issued after we reuse the block
+	 * and write some new data into it.
+	 */
+	tp = malloc(sizeof(struct ffs_blkfree_trim_params), M_TEMP, M_WAITOK);
+	tp->ump = ump;
+	tp->devvp = devvp;
+	tp->bno = bno;
+	tp->size = size;
+	tp->inum = inum;
+
+	bip = g_alloc_bio();
+	bip->bio_cmd = BIO_DELETE;
+	bip->bio_offset = dbtob(fsbtodb(fs, bno));
+	bip->bio_done = ffs_blkfree_trim_completed;
+	bip->bio_length = size;
+	bip->bio_caller2 = tp;
+
+	mp = UFSTOVFS(ump);
+	vn_start_secondary_write(NULL, &mp, 0);
+	g_io_request(bip, (struct g_consumer *)devvp->v_bufobj.bo_private);
+}
+
 #ifdef INVARIANTS
 /*
  * Verify allocation of a block or fragment. Returns true if block or

Modified: stable/8/sys/ufs/ffs/ffs_vfsops.c
==============================================================================
--- stable/8/sys/ufs/ffs/ffs_vfsops.c	Sat Jan 29 22:11:13 2011	(r218078)
+++ stable/8/sys/ufs/ffs/ffs_vfsops.c	Sat Jan 29 22:51:27 2011	(r218079)
@@ -891,6 +891,21 @@ ffs_mountfs(devvp, mp, td)
 		    mp->mnt_stat.f_mntonname);
 #endif
 	}
+	if ((fs->fs_flags & FS_TRIM) != 0) {
+		size = sizeof(int);
+		if (g_io_getattr("GEOM::candelete", cp, &size,
+		    &ump->um_candelete) == 0) {
+			if (!ump->um_candelete)
+				printf(
+"WARNING: %s: TRIM flag on fs but disk does not support TRIM\n",
+				    mp->mnt_stat.f_mntonname);
+		} else {
+			printf(
+"WARNING: %s: TRIM flag on fs but cannot get whether disk supports TRIM\n",
+			    mp->mnt_stat.f_mntonname);
+			ump->um_candelete = 0;
+		}
+	}
 
 	ump->um_mountp = mp;
 	ump->um_dev = dev;

Modified: stable/8/sys/ufs/ffs/fs.h
==============================================================================
--- stable/8/sys/ufs/ffs/fs.h	Sat Jan 29 22:11:13 2011	(r218078)
+++ stable/8/sys/ufs/ffs/fs.h	Sat Jan 29 22:51:27 2011	(r218079)
@@ -411,6 +411,7 @@ CTASSERT(sizeof(struct fs) == 1376);
 #define FS_GJOURNAL	0x0040	/* gjournaled file system */
 #define FS_FLAGS_UPDATED 0x0080	/* flags have been moved to new location */
 #define FS_NFS4ACLS	0x0100	/* file system has NFSv4 ACLs enabled */
+#define	FS_TRIM		0x0400	/* issue BIO_DELETE for deleted blocks */
 
 /*
  * Macros to access bits in the fs_active array.

Modified: stable/8/sys/ufs/ufs/ufsmount.h
==============================================================================
--- stable/8/sys/ufs/ufs/ufsmount.h	Sat Jan 29 22:11:13 2011	(r218078)
+++ stable/8/sys/ufs/ufs/ufsmount.h	Sat Jan 29 22:51:27 2011	(r218079)
@@ -86,6 +86,7 @@ struct ufsmount {
 	time_t	um_itime[MAXQUOTAS];		/* inode quota time limit */
 	char	um_qflags[MAXQUOTAS];		/* quota specific flags */
 	int64_t	um_savedmaxfilesize;		/* XXX - limit maxfilesize */
+	int	um_candelete;			/* devvp supports TRIM */
 	int	(*um_balloc)(struct vnode *, off_t, int, struct ucred *, int, struct buf **);
 	int	(*um_blkatoff)(struct vnode *, off_t, char **, struct buf **);
 	int	(*um_truncate)(struct vnode *, off_t, int, struct ucred *, struct thread *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101292251.p0TMpSTW048372>