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>