diff options
author | phk <phk@FreeBSD.org> | 1998-09-05 14:13:12 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 1998-09-05 14:13:12 +0000 |
commit | 4630814c8bc51e668f785289086657fbd5e775f2 (patch) | |
tree | e5449931fffd8e8dd0e4d28f5b7b28dc6e36ba5c | |
parent | ec3c90cf78eb16d4a8906a64e2a6f76cf27b8441 (diff) | |
download | FreeBSD-src-4630814c8bc51e668f785289086657fbd5e775f2.zip FreeBSD-src-4630814c8bc51e668f785289086657fbd5e775f2.tar.gz |
Add a new vnode op, VOP_FREEBLKS(), which filesystems can use to inform
device drivers about sectors no longer in use.
Device-drivers receive the call through d_strategy, if they have
D_CANFREE in d_flags.
This allows flash based devices to erase the sectors and avoid
pointlessly carrying them around in compactions.
Reviewed by: Kirk Mckusick, bde
Sponsored by: M-Systems (www.m-sys.com)
-rw-r--r-- | sys/fs/specfs/spec_vnops.c | 27 | ||||
-rw-r--r-- | sys/kern/vfs_bio.c | 19 | ||||
-rw-r--r-- | sys/kern/vnode_if.src | 16 | ||||
-rw-r--r-- | sys/miscfs/specfs/spec_vnops.c | 27 | ||||
-rw-r--r-- | sys/sys/bio.h | 10 | ||||
-rw-r--r-- | sys/sys/buf.h | 10 | ||||
-rw-r--r-- | sys/sys/conf.h | 3 | ||||
-rw-r--r-- | sys/sys/linedisc.h | 3 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_alloc.c | 3 |
9 files changed, 99 insertions, 19 deletions
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c index 8a3e124..31519d3 100644 --- a/sys/fs/specfs/spec_vnops.c +++ b/sys/fs/specfs/spec_vnops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95 - * $Id: spec_vnops.c,v 1.71 1998/08/25 17:48:54 phk Exp $ + * $Id: spec_vnops.c,v 1.72 1998/09/04 08:06:56 dfr Exp $ */ #include <sys/param.h> @@ -61,6 +61,7 @@ static int spec_advlock __P((struct vop_advlock_args *)); static int spec_badop __P((void)); static int spec_bmap __P((struct vop_bmap_args *)); static int spec_close __P((struct vop_close_args *)); +static void spec_freeblks __P((struct vop_freeblks_args *)); static int spec_fsync __P((struct vop_fsync_args *)); static int spec_getattr __P((struct vop_getattr_args *)); static int spec_getpages __P((struct vop_getpages_args *)); @@ -109,6 +110,7 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = { { &vop_strategy_desc, (vop_t *) spec_strategy }, { &vop_symlink_desc, (vop_t *) spec_badop }, { &vop_write_desc, (vop_t *) spec_write }, + { &vop_freeblks_desc, (vop_t *) spec_freeblks }, { NULL, NULL } }; static struct vnodeopv_desc spec_vnodeop_opv_desc = @@ -540,6 +542,29 @@ spec_strategy(ap) return (0); } +static void +spec_freeblks(ap) + struct vop_freeblks_args /* { + struct vnode *a_vp; + daddr_t a_addr; + daddr_t a_length; + } */ *ap; +{ + struct cdevsw *bsw; + struct buf *bp; + + bsw = bdevsw[major(ap->a_vp->v_rdev)]; + if ((bsw->d_flags & D_CANFREE) == 0) + return; + bp = geteblk(ap->a_length); + bp->b_flags |= B_FREEBUF | B_BUSY; + bp->b_dev = ap->a_vp->v_rdev; + bp->b_blkno = ap->a_addr; + bp->b_offset = dbtob(ap->a_addr); + bp->b_bcount = ap->a_length; + (*bsw->d_strategy)(bp); +} + /* * This is a noop, simply returning what one has been given. */ diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 06130f9..6db20aa2 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -11,7 +11,7 @@ * 2. Absolutely no warranty of function or purpose is made by the author * John S. Dyson. * - * $Id: vfs_bio.c,v 1.173 1998/08/28 20:07:13 luoqi Exp $ + * $Id: vfs_bio.c,v 1.174 1998/09/04 08:06:55 dfr Exp $ */ /* @@ -587,14 +587,14 @@ brelse(struct buf * bp) if (bp->b_flags & B_LOCKED) bp->b_flags &= ~B_ERROR; - if ((bp->b_flags & (B_NOCACHE | B_INVAL | B_ERROR)) || + if ((bp->b_flags & (B_NOCACHE | B_INVAL | B_ERROR | B_FREEBUF)) || (bp->b_bufsize <= 0)) { bp->b_flags |= B_INVAL; if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_deallocate) (*bioops.io_deallocate)(bp); if (bp->b_flags & B_DELWRI) --numdirtybuffers; - bp->b_flags &= ~(B_DELWRI | B_CACHE); + bp->b_flags &= ~(B_DELWRI | B_CACHE | B_FREEBUF); if ((bp->b_flags & B_VMIO) == 0) { if (bp->b_bufsize) allocbuf(bp, 0); @@ -1895,6 +1895,12 @@ biodone(register struct buf * bp) } bp->b_flags |= B_DONE; + if (bp->b_flags & B_FREEBUF) { + brelse(bp); + splx(s); + return; + } + if ((bp->b_flags & B_READ) == 0) { vwakeup(bp); } @@ -2415,12 +2421,7 @@ DB_SHOW_COMMAND(buffer, db_show_buffer) } db_printf("b_proc = %p,\nb_flags = 0x%b\n", (void *)bp->b_proc, - (u_int)bp->b_flags, - "\20\40bounce\37cluster\36vmio\35ram\34ordered" - "\33paging\32xxx\31writeinprog\30wanted\27relbuf\26avail3" - "\25read\24raw\23phys\22clusterok\21malloc\20nocache" - "\17locked\16inval\15avail2\14error\13eintr\12done\11avail1" - "\10delwri\7call\6cache\5busy\4bad\3async\2needcommit\1age"); + (u_int)bp->b_flags, PRINT_BUF_FLAGS); db_printf("b_error = %d, b_bufsize = %ld, b_bcount = %ld, " "b_resid = %ld\nb_dev = 0x%x, b_data = %p, " "b_blkno = %d, b_pblkno = %d\n", diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 4dd64cd..48c9fef 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -31,7 +31,7 @@ # SUCH DAMAGE. # # @(#)vnode_if.src 8.12 (Berkeley) 5/14/95 -# $Id: vnode_if.src,v 1.17 1998/05/07 04:58:26 msmith Exp $ +# $Id: vnode_if.src,v 1.18 1998/07/04 20:45:32 julian Exp $ # # @@ -467,6 +467,20 @@ vop_putpages { }; # +#% freeblks vp - - - +# +# This call is used by the filesystem to release blocks back to +# device-driver. This is useful if the driver has a lengthy +# erase handling or similar. +# + +vop_freeblks { + IN struct vnode *vp; + IN daddr_t addr; + IN daddr_t length; +}; + +# # Needs work: no vp? # #vop_bwrite { diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c index 8a3e124..31519d3 100644 --- a/sys/miscfs/specfs/spec_vnops.c +++ b/sys/miscfs/specfs/spec_vnops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95 - * $Id: spec_vnops.c,v 1.71 1998/08/25 17:48:54 phk Exp $ + * $Id: spec_vnops.c,v 1.72 1998/09/04 08:06:56 dfr Exp $ */ #include <sys/param.h> @@ -61,6 +61,7 @@ static int spec_advlock __P((struct vop_advlock_args *)); static int spec_badop __P((void)); static int spec_bmap __P((struct vop_bmap_args *)); static int spec_close __P((struct vop_close_args *)); +static void spec_freeblks __P((struct vop_freeblks_args *)); static int spec_fsync __P((struct vop_fsync_args *)); static int spec_getattr __P((struct vop_getattr_args *)); static int spec_getpages __P((struct vop_getpages_args *)); @@ -109,6 +110,7 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = { { &vop_strategy_desc, (vop_t *) spec_strategy }, { &vop_symlink_desc, (vop_t *) spec_badop }, { &vop_write_desc, (vop_t *) spec_write }, + { &vop_freeblks_desc, (vop_t *) spec_freeblks }, { NULL, NULL } }; static struct vnodeopv_desc spec_vnodeop_opv_desc = @@ -540,6 +542,29 @@ spec_strategy(ap) return (0); } +static void +spec_freeblks(ap) + struct vop_freeblks_args /* { + struct vnode *a_vp; + daddr_t a_addr; + daddr_t a_length; + } */ *ap; +{ + struct cdevsw *bsw; + struct buf *bp; + + bsw = bdevsw[major(ap->a_vp->v_rdev)]; + if ((bsw->d_flags & D_CANFREE) == 0) + return; + bp = geteblk(ap->a_length); + bp->b_flags |= B_FREEBUF | B_BUSY; + bp->b_dev = ap->a_vp->v_rdev; + bp->b_blkno = ap->a_addr; + bp->b_offset = dbtob(ap->a_addr); + bp->b_bcount = ap->a_length; + (*bsw->d_strategy)(bp); +} + /* * This is a noop, simply returning what one has been given. */ diff --git a/sys/sys/bio.h b/sys/sys/bio.h index 6e54e83..26ce956 100644 --- a/sys/sys/bio.h +++ b/sys/sys/bio.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)buf.h 8.9 (Berkeley) 3/30/95 - * $Id: buf.h,v 1.53 1998/07/15 04:17:48 bde Exp $ + * $Id: buf.h,v 1.54 1998/08/24 17:47:08 phk Exp $ */ #ifndef _SYS_BUF_H_ @@ -136,7 +136,7 @@ struct buf { #define B_CACHE 0x00000020 /* Bread found us in the cache. */ #define B_CALL 0x00000040 /* Call b_iodone from biodone. */ #define B_DELWRI 0x00000080 /* Delay I/O until buffer reused. */ -#define B_AVAIL1 0x00000100 /* Available flag */ +#define B_FREEBUF 0x00000100 /* Instruct driver: free blocks */ #define B_DONE 0x00000200 /* I/O completed. */ #define B_EINTR 0x00000400 /* I/O was interrupted */ #define B_ERROR 0x00000800 /* I/O error occurred. */ @@ -162,6 +162,12 @@ struct buf { #define B_CLUSTER 0x40000000 /* pagein op, so swap() can count it */ #define B_BOUNCE 0x80000000 /* bounce buffer flag */ +#define PRINT_BUF_FLAGS "\20\40bounce\37cluster\36vmio\35ram\34ordered" \ + "\33paging\32xxx\31writeinprog\30wanted\27relbuf\26avail3" \ + "\25read\24raw\23phys\22clusterok\21malloc\20nocache" \ + "\17locked\16inval\15avail2\14error\13eintr\12done\11freebuf" \ + "\10delwri\7call\6cache\5busy\4bad\3async\2needcommit\1age" + #define NOOFFSET (-1LL) /* No buffer offset calculated yet */ typedef struct buf_queue_head { diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 6e54e83..26ce956 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)buf.h 8.9 (Berkeley) 3/30/95 - * $Id: buf.h,v 1.53 1998/07/15 04:17:48 bde Exp $ + * $Id: buf.h,v 1.54 1998/08/24 17:47:08 phk Exp $ */ #ifndef _SYS_BUF_H_ @@ -136,7 +136,7 @@ struct buf { #define B_CACHE 0x00000020 /* Bread found us in the cache. */ #define B_CALL 0x00000040 /* Call b_iodone from biodone. */ #define B_DELWRI 0x00000080 /* Delay I/O until buffer reused. */ -#define B_AVAIL1 0x00000100 /* Available flag */ +#define B_FREEBUF 0x00000100 /* Instruct driver: free blocks */ #define B_DONE 0x00000200 /* I/O completed. */ #define B_EINTR 0x00000400 /* I/O was interrupted */ #define B_ERROR 0x00000800 /* I/O error occurred. */ @@ -162,6 +162,12 @@ struct buf { #define B_CLUSTER 0x40000000 /* pagein op, so swap() can count it */ #define B_BOUNCE 0x80000000 /* bounce buffer flag */ +#define PRINT_BUF_FLAGS "\20\40bounce\37cluster\36vmio\35ram\34ordered" \ + "\33paging\32xxx\31writeinprog\30wanted\27relbuf\26avail3" \ + "\25read\24raw\23phys\22clusterok\21malloc\20nocache" \ + "\17locked\16inval\15avail2\14error\13eintr\12done\11freebuf" \ + "\10delwri\7call\6cache\5busy\4bad\3async\2needcommit\1age" + #define NOOFFSET (-1LL) /* No buffer offset calculated yet */ typedef struct buf_queue_head { diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 904e71e..80e4e36 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)conf.h 8.5 (Berkeley) 1/9/95 - * $Id: conf.h,v 1.43 1998/07/04 22:30:26 julian Exp $ + * $Id: conf.h,v 1.44 1998/08/20 06:10:42 bde Exp $ */ #ifndef _SYS_CONF_H_ @@ -93,6 +93,7 @@ typedef int l_modem_t __P((struct tty *tp, int flag)); #define D_NOCLUSTERR 0x10000 /* disables cluter read */ #define D_NOCLUSTERW 0x20000 /* disables cluster write */ #define D_NOCLUSTERRW (D_NOCLUSTERR | D_NOCLUSTERW) +#define D_CANFREE 0x40000 /* can free blocks */ /* diff --git a/sys/sys/linedisc.h b/sys/sys/linedisc.h index 904e71e..80e4e36 100644 --- a/sys/sys/linedisc.h +++ b/sys/sys/linedisc.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)conf.h 8.5 (Berkeley) 1/9/95 - * $Id: conf.h,v 1.43 1998/07/04 22:30:26 julian Exp $ + * $Id: conf.h,v 1.44 1998/08/20 06:10:42 bde Exp $ */ #ifndef _SYS_CONF_H_ @@ -93,6 +93,7 @@ typedef int l_modem_t __P((struct tty *tp, int flag)); #define D_NOCLUSTERR 0x10000 /* disables cluter read */ #define D_NOCLUSTERW 0x20000 /* disables cluster write */ #define D_NOCLUSTERRW (D_NOCLUSTERR | D_NOCLUSTERW) +#define D_CANFREE 0x40000 /* can free blocks */ /* diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 6a57a26..e73638d 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ffs_alloc.c 8.18 (Berkeley) 5/26/95 - * $Id: ffs_alloc.c,v 1.50 1998/07/11 07:46:04 bde Exp $ + * $Id: ffs_alloc.c,v 1.51 1998/08/17 19:09:36 bde Exp $ */ #include "opt_quota.h" @@ -1300,6 +1300,7 @@ ffs_blkfree(ip, bno, size) int i, error, cg, blk, frags, bbase; fs = ip->i_fs; + VOP_FREEBLKS(ip->i_devvp, fsbtodb(fs, bno), size); if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 || fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) { printf("dev=0x%lx, bno = %d, bsize = %d, size = %ld, fs = %s\n", |