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)
This commit is contained in:
parent
a8b8bc0730
commit
0375c9f2b8
@ -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.
|
||||
*/
|
||||
|
@ -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",
|
||||
|
@ -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 $
|
||||
#
|
||||
|
||||
#
|
||||
@ -466,6 +466,20 @@ vop_putpages {
|
||||
IN vm_ooffset_t offset;
|
||||
};
|
||||
|
||||
#
|
||||
#% 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?
|
||||
#
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user