summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1997-03-23 00:45:27 +0000
committerbde <bde@FreeBSD.org>1997-03-23 00:45:27 +0000
commit3dc0739b4b3a164a9b9573b85bd93536d65c17ee (patch)
treeefa32895546394d68bb68f530ad7b4bc185501de /sys/ufs
parent953b4a2c981017b3338bb9d6f2fcd194e034bda8 (diff)
downloadFreeBSD-src-3dc0739b4b3a164a9b9573b85bd93536d65c17ee.zip
FreeBSD-src-3dc0739b4b3a164a9b9573b85bd93536d65c17ee.tar.gz
Merged the rest of lfs from Lite2. It compiles (uncleanly) but is as
unlikely to work as before.
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/lfs/lfs_alloc.c15
-rw-r--r--sys/ufs/lfs/lfs_balloc.c138
-rw-r--r--sys/ufs/lfs/lfs_bio.c33
-rw-r--r--sys/ufs/lfs/lfs_cksum.c6
-rw-r--r--sys/ufs/lfs/lfs_extern.h16
-rw-r--r--sys/ufs/lfs/lfs_segment.c189
-rw-r--r--sys/ufs/lfs/lfs_syscalls.c53
-rw-r--r--sys/ufs/lfs/lfs_vfsops.c136
-rw-r--r--sys/ufs/lfs/lfs_vnops.c59
9 files changed, 460 insertions, 185 deletions
diff --git a/sys/ufs/lfs/lfs_alloc.c b/sys/ufs/lfs/lfs_alloc.c
index 9145a3e..6cde979 100644
--- a/sys/ufs/lfs/lfs_alloc.c
+++ b/sys/ufs/lfs/lfs_alloc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1991, 1993
+ * Copyright (c) 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_alloc.c 8.4 (Berkeley) 1/4/94
- * $Id$
+ * @(#)lfs_alloc.c 8.7 (Berkeley) 5/14/95
+ * $Id: lfs_alloc.c,v 1.13 1997/02/22 09:47:16 peter Exp $
*/
#include "opt_quota.h"
@@ -75,7 +75,7 @@ lfs_valloc(ap)
struct ifile *ifp;
struct inode *ip;
struct vnode *vp;
- daddr_t blkno;
+ ufs_daddr_t blkno;
ino_t new_ino;
u_long i, max;
int error;
@@ -102,7 +102,7 @@ lfs_valloc(ap)
vp = fs->lfs_ivnode;
ip = VTOI(vp);
blkno = lblkno(fs, ip->i_size);
- lfs_balloc(vp, fs->lfs_bsize, blkno, &bp);
+ lfs_balloc(vp, 0, fs->lfs_bsize, blkno, &bp);
ip->i_size += fs->lfs_bsize;
vnode_pager_setsize(vp, (u_long)ip->i_size);
@@ -184,14 +184,13 @@ lfs_vcreate(mp, ino, vpp)
ump = VFSTOUFS(mp);
/* Initialize the inode. */
+ lockinit(&ip->i_lock, PINOD, "lfsinode", 0, 0);
(*vpp)->v_data = ip;
ip->i_vnode = *vpp;
ip->i_devvp = ump->um_devvp;
ip->i_flag = IN_MODIFIED;
ip->i_dev = ump->um_dev;
ip->i_number = ip->i_din.di_inumber = ino;
-ip->i_din.di_spare[0] = 0xdeadc0de;
-ip->i_din.di_spare[1] = 0xdeadc0de;
ip->i_lfs = ump->um_lfs;
#ifdef QUOTA
for (i = 0; i < MAXQUOTAS; i++)
@@ -221,7 +220,7 @@ lfs_vfree(ap)
struct ifile *ifp;
struct inode *ip;
struct lfs *fs;
- daddr_t old_iaddr;
+ ufs_daddr_t old_iaddr;
ino_t ino;
/* Get the inode number and file system. */
diff --git a/sys/ufs/lfs/lfs_balloc.c b/sys/ufs/lfs/lfs_balloc.c
index ee2a86b..695049d 100644
--- a/sys/ufs/lfs/lfs_balloc.c
+++ b/sys/ufs/lfs/lfs_balloc.c
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_balloc.c 8.1 (Berkeley) 6/11/93
- * $Id$
+ * @(#)lfs_balloc.c 8.4 (Berkeley) 5/8/95
+ * $Id: lfs_balloc.c,v 1.10 1997/02/22 09:47:17 peter Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
@@ -52,18 +52,20 @@
#include <ufs/lfs/lfs_extern.h>
int
-lfs_balloc(vp, iosize, lbn, bpp)
+lfs_balloc(vp, offset, iosize, lbn, bpp)
struct vnode *vp;
+ int offset;
u_long iosize;
- daddr_t lbn;
+ ufs_daddr_t lbn;
struct buf **bpp;
{
struct buf *ibp, *bp;
struct inode *ip;
struct lfs *fs;
struct indir indirs[NIADDR+2];
- daddr_t daddr;
- int bb, error, i, num;
+ ufs_daddr_t daddr, lastblock;
+ int bb; /* number of disk blocks in a block disk blocks */
+ int error, frags, i, nsize, osize, num;
ip = VTOI(vp);
fs = ip->i_lfs;
@@ -76,21 +78,37 @@ lfs_balloc(vp, iosize, lbn, bpp)
* or written earlier). If it did, make sure we don't count it as a
* new block or zero out its contents. If it did not, make sure
* we allocate any necessary indirect blocks.
+ * If we are writing a block beyond the end of the file, we need to
+ * check if the old last block was a fragment. If it was, we need
+ * to rewrite it.
*/
*bpp = NULL;
if (error = ufs_bmaparray(vp, lbn, &daddr, &indirs[0], &num, NULL, NULL ))
return (error);
- *bpp = bp = getblk(vp, lbn, fs->lfs_bsize, 0, 0);
+ /* Check for block beyond end of file and fragment extension needed. */
+ lastblock = lblkno(fs, ip->i_size);
+ if (lastblock < NDADDR && lastblock < lbn) {
+ osize = blksize(fs, ip, lastblock);
+ if (osize < fs->lfs_bsize && osize > 0) {
+ if (error = lfs_fragextend(vp, osize, fs->lfs_bsize,
+ lastblock, &bp))
+ return(error);
+ ip->i_size = (lastblock + 1) * fs->lfs_bsize;
+ vnode_pager_setsize(vp, (u_long)ip->i_size);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ VOP_BWRITE(bp);
+ }
+ }
+
bb = VFSTOUFS(vp->v_mount)->um_seqinc;
if (daddr == UNASSIGNED)
/* May need to allocate indirect blocks */
for (i = 1; i < num; ++i)
if (!indirs[i].in_exists) {
- ibp =
- getblk(vp, indirs[i].in_lbn, fs->lfs_bsize,
- 0, 0);
+ ibp = getblk(vp, indirs[i].in_lbn, fs->lfs_bsize,
+ 0, 0);
if (!(ibp->b_flags & (B_DONE | B_DELWRI))) {
if (!ISSPACE(fs, bb, curproc->p_ucred)){
ibp->b_flags |= B_INVAL;
@@ -104,15 +122,57 @@ lfs_balloc(vp, iosize, lbn, bpp)
}
} else
panic ("Indirect block should not exist");
+
+ if (!ISSPACE(fs, bb, curproc->p_ucred)){
+ ibp->b_flags |= B_INVAL;
+ brelse(ibp);
+ return(ENOSPC);
+ } else {
+ ip->i_blocks += bb;
+ ip->i_lfs->lfs_bfree -= bb;
+ clrbuf(ibp);
+ if(error = VOP_BWRITE(ibp))
+ return(error);
+ }
}
- if (error) {
- if (bp)
- brelse(bp);
- return(error);
- }
+ /*
+ * If the block we are writing is a direct block, it's the last
+ * block in the file, and offset + iosize is less than a full
+ * block, we can write one or more fragments. There are two cases:
+ * the block is brand new and we should allocate it the correct
+ * size or it already exists and contains some fragments and
+ * may need to extend it.
+ */
+ if (lbn < NDADDR && lblkno(fs, ip->i_size) == lbn) {
+ nsize = fragroundup(fs, offset + iosize);
+ frags = numfrags(fs, nsize);
+ bb = fragstodb(fs, frags);
+ if (lblktosize(fs, lbn) == ip->i_size)
+ /* Brand new block or fragment */
+ *bpp = bp = getblk(vp, lbn, nsize, 0, 0);
+ else {
+ /* Extend existing block */
+ if (error = lfs_fragextend(vp, (int)blksize(fs, ip, lbn),
+ nsize, lbn, &bp))
+ return(error);
+ *bpp = bp;
+ }
+ } else {
+ /*
+ * Get the existing block from the cache either because the
+ * block is 1) not a direct block or because it's not the last
+ * block in the file.
+ */
+ frags = dbtofrags(fs, bb);
+ *bpp = bp = getblk(vp, lbn, blksize(fs, ip, lbn), 0, 0);
+ }
- /* Now, we may need to allocate the data block */
+ /*
+ * The block we are writing may be a brand new block
+ * in which case we need to do accounting (i.e. check
+ * for free space and update the inode number of blocks.
+ */
if (!(bp->b_flags & (B_CACHE | B_DONE | B_DELWRI))) {
if (daddr == UNASSIGNED)
if (!ISSPACE(fs, bb, curproc->p_ucred)) {
@@ -126,8 +186,13 @@ lfs_balloc(vp, iosize, lbn, bpp)
vfs_bio_clrbuf(bp);
}
else if (iosize == fs->lfs_bsize)
- bp->b_blkno = daddr; /* Skip the I/O */
+ /* Optimization: I/O is unnecessary. */
+ bp->b_blkno = daddr;
else {
+ /*
+ * We need to read the block to preserve the
+ * existing bytes.
+ */
bp->b_blkno = daddr;
bp->b_flags |= B_READ;
vfs_busy_pages(bp, 0);
@@ -135,5 +200,42 @@ lfs_balloc(vp, iosize, lbn, bpp)
return(biowait(bp));
}
}
- return (error);
+ return (0);
+}
+
+lfs_fragextend(vp, osize, nsize, lbn, bpp)
+ struct vnode *vp;
+ int osize;
+ int nsize;
+ daddr_t lbn;
+ struct buf **bpp;
+{
+ struct inode *ip;
+ struct lfs *fs;
+ long bb;
+ int error;
+
+ ip = VTOI(vp);
+ fs = ip->i_lfs;
+ bb = (long)fragstodb(fs, numfrags(fs, nsize - osize));
+ if (!ISSPACE(fs, bb, curproc->p_ucred)) {
+ return(ENOSPC);
+ }
+
+ if (error = bread(vp, lbn, osize, NOCRED, bpp)) {
+ brelse(*bpp);
+ return(error);
+ }
+#ifdef QUOTA
+ if (error = chkdq(ip, bb, curproc->p_ucred, 0)) {
+ brelse(*bpp);
+ return (error);
+ }
+#endif
+ ip->i_blocks += bb;
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ fs->lfs_bfree -= fragstodb(fs, numfrags(fs, (nsize - osize)));
+ allocbuf(*bpp, nsize);
+ bzero((char *)((*bpp)->b_data) + osize, (u_int)(nsize - osize));
+ return(0);
}
diff --git a/sys/ufs/lfs/lfs_bio.c b/sys/ufs/lfs/lfs_bio.c
index fabf0a4..3fc1050 100644
--- a/sys/ufs/lfs/lfs_bio.c
+++ b/sys/ufs/lfs/lfs_bio.c
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_bio.c 8.4 (Berkeley) 12/30/93
- * $Id$
+ * @(#)lfs_bio.c 8.10 (Berkeley) 6/10/95
+ * $Id: lfs_bio.c,v 1.11 1997/02/22 09:47:17 peter Exp $
*/
#include <sys/param.h>
@@ -80,7 +80,7 @@ lfs_bwrite(ap)
register struct buf *bp = ap->a_bp;
struct lfs *fs;
struct inode *ip;
- int error, s;
+ int db, error, s;
/*
* Set the delayed write flag and use reassignbuf to move the buffer
@@ -98,10 +98,12 @@ lfs_bwrite(ap)
*/
if (!(bp->b_flags & B_LOCKED)) {
fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs;
- while (!LFS_FITS(fs, fsbtodb(fs, 1)) && !IS_IFILE(bp) &&
+ db = fragstodb(fs, numfrags(fs, bp->b_bcount));
+ while (!LFS_FITS(fs, db) && !IS_IFILE(bp) &&
bp->b_lblkno > 0) {
/* Out of space, need cleaner to run */
wakeup(&lfs_allclean_wakeup);
+ wakeup(&fs->lfs_nextseg);
error = tsleep(&fs->lfs_avail, PCATCH | PUSER,
"cleaner", 0);
if (error) {
@@ -113,7 +115,7 @@ lfs_bwrite(ap)
if (!(ip->i_flag & IN_MODIFIED))
++fs->lfs_uinodes;
ip->i_flag |= IN_CHANGE | IN_MODIFIED | IN_UPDATE;
- fs->lfs_avail -= fsbtodb(fs, 1);
+ fs->lfs_avail -= db;
++locked_queue_count;
bp->b_flags |= B_DELWRI | B_LOCKED;
bp->b_flags &= ~(B_READ | B_ERROR);
@@ -136,7 +138,8 @@ lfs_bwrite(ap)
static void
lfs_flush()
{
- register struct mount *mp;
+ register struct mount *mp, *nmp;
+ struct proc *p = curproc; /* XXX */
#ifdef DOSTATS
++lfs_stats.write_exceeded;
@@ -144,10 +147,14 @@ lfs_flush()
if (lfs_writing)
return;
lfs_writing = 1;
- for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = mp->mnt_list.cqe_next) {
- /* The lock check below is to avoid races with unmount. */
- if (mp->mnt_stat.f_type == MOUNT_LFS &&
- (mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_UNMOUNT)) == 0 &&
+ simple_lock(&mountlist_slock);
+ for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ nmp = mp->mnt_list.cqe_next;
+ continue;
+ }
+ if (mp->mnt_stat.f_type == lfs_mount_type &&
+ (mp->mnt_flag & MNT_RDONLY) == 0 &&
!((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) {
/*
* We set the queue to 0 here because we are about to
@@ -161,14 +168,18 @@ lfs_flush()
#endif
lfs_segwrite(mp, 0);
}
+ simple_lock(&mountlist_slock);
+ nmp = mp->mnt_list.cqe_next;
+ vfs_unbusy(mp, p);
}
+ simple_unlock(&mountlist_slock);
lfs_writing = 0;
}
int
lfs_check(vp, blkno)
struct vnode *vp;
- daddr_t blkno;
+ ufs_daddr_t blkno;
{
int error;
diff --git a/sys/ufs/lfs/lfs_cksum.c b/sys/ufs/lfs/lfs_cksum.c
index 9fa895a..c1c627e 100644
--- a/sys/ufs/lfs/lfs_cksum.c
+++ b/sys/ufs/lfs/lfs_cksum.c
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_cksum.c 8.1 (Berkeley) 6/11/93
- * $Id$
+ * @(#)lfs_cksum.c 8.2 (Berkeley) 10/9/94
+ * $Id: lfs_cksum.c,v 1.7 1997/02/22 09:47:18 peter Exp $
*/
#ifdef KERNEL
@@ -63,7 +63,7 @@ cksum(str, len)
len &= ~(sizeof(u_short) - 1);
for (sum = 0; len; len -= sizeof(u_short)) {
sum ^= *(u_short *)str;
- ++(u_short *)str;
+ str = (void *)((u_short *)str + 1);
}
return (sum);
}
diff --git a/sys/ufs/lfs/lfs_extern.h b/sys/ufs/lfs/lfs_extern.h
index b86d7d8..86e417c 100644
--- a/sys/ufs/lfs/lfs_extern.h
+++ b/sys/ufs/lfs/lfs_extern.h
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_extern.h 8.2 (Berkeley) 4/16/94
- * $Id$
+ * @(#)lfs_extern.h 8.6 (Berkeley) 5/8/95
+ * $Id: lfs_extern.h,v 1.14 1997/02/22 09:47:20 peter Exp $
*/
#ifndef _UFS_LFS_LFS_EXTERN_H_
@@ -43,23 +43,26 @@ struct inode;
struct mount;
struct nameidata;
-int lfs_balloc __P((struct vnode *, u_long, daddr_t, struct buf **));
+int lfs_balloc __P((struct vnode *, int, u_long, ufs_daddr_t, struct buf **));
int lfs_blkatoff __P((struct vop_blkatoff_args *));
int lfs_bwrite __P((struct vop_bwrite_args *));
-int lfs_check __P((struct vnode *, daddr_t));
+int lfs_check __P((struct vnode *, ufs_daddr_t));
void lfs_free_buffer __P((caddr_t, int));
int lfs_gatherblock __P((struct segment *, struct buf *, int *));
struct dinode *
lfs_ifind __P((struct lfs *, ino_t, struct dinode *));
-int lfs_init __P((void));
+int lfs_init __P((struct vfsconf *));
int lfs_initseg __P((struct lfs *));
int lfs_makeinode __P((int, struct nameidata *, struct inode **));
int lfs_mountroot __P((void));
struct buf *
- lfs_newbuf __P((struct vnode *, daddr_t, size_t));
+ lfs_newbuf __P((struct vnode *, ufs_daddr_t, size_t));
+int lfs_reclaim __P((struct vop_reclaim_args *));
void lfs_seglock __P((struct lfs *, unsigned long flags));
void lfs_segunlock __P((struct lfs *));
int lfs_segwrite __P((struct mount *, int));
+#define lfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
int lfs_truncate __P((struct vop_truncate_args *));
int lfs_update __P((struct vop_update_args *));
void lfs_updatemeta __P((struct segment *));
@@ -74,6 +77,7 @@ int lfs_writeseg __P((struct lfs *, struct segment *));
void lfs_writesuper __P((struct lfs *));
extern int lfs_allclean_wakeup;
+extern int lfs_mount_type;
extern int locked_queue_count;
extern vop_t **lfs_vnodeop_p;
extern vop_t **lfs_specop_p;
diff --git a/sys/ufs/lfs/lfs_segment.c b/sys/ufs/lfs/lfs_segment.c
index 5d2c250..7c2c0a5 100644
--- a/sys/ufs/lfs/lfs_segment.c
+++ b/sys/ufs/lfs/lfs_segment.c
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_segment.c 8.5 (Berkeley) 1/4/94
- * $Id$
+ * @(#)lfs_segment.c 8.10 (Berkeley) 6/10/95
+ * $Id: lfs_segment.c,v 1.20 1997/02/22 09:47:22 peter Exp $
*/
#include <sys/param.h>
@@ -148,7 +148,7 @@ lfs_alloc_buffer(int size) {
static void lfs_callback __P((struct buf *));
static void lfs_gather __P((struct lfs *, struct segment *,
struct vnode *, int (*) __P((struct lfs *, struct buf *))));
-void lfs_iset __P((struct inode *, daddr_t, time_t));
+void lfs_iset __P((struct inode *, ufs_daddr_t, time_t));
static int lfs_match_data __P((struct lfs *, struct buf *));
static int lfs_match_dindir __P((struct lfs *, struct buf *));
static int lfs_match_indir __P((struct lfs *, struct buf *));
@@ -156,7 +156,7 @@ static int lfs_match_indir __P((struct lfs *, struct buf *));
static int lfs_match_tindir __P((struct lfs *, struct buf *));
#endif
static void lfs_newseg __P((struct lfs *));
-static void lfs_shellsort __P((struct buf **, daddr_t *, register int));
+static void lfs_shellsort __P((struct buf **, ufs_daddr_t *, register int));
static void lfs_supercallback __P((struct buf *));
static void lfs_writefile __P((struct lfs *, struct segment *, struct vnode *));
static void lfs_writevnodes __P((struct lfs *fs, struct mount *mp,
@@ -245,10 +245,23 @@ lfs_writevnodes(fs, mp, sp, op)
struct inode *ip;
struct vnode *vp;
+/* BEGIN HACK */
+#define VN_OFFSET (((void *)&vp->v_mntvnodes.le_next) - (void *)vp)
+#define BACK_VP(VP) ((struct vnode *)(((void *)VP->v_mntvnodes.le_prev) - VN_OFFSET))
+#define BEG_OF_VLIST ((struct vnode *)(((void *)&mp->mnt_vnodelist.lh_first) - VN_OFFSET))
+
+/* Find last vnode. */
+loop: for (vp = mp->mnt_vnodelist.lh_first;
+ vp && vp->v_mntvnodes.le_next != NULL;
+ vp = vp->v_mntvnodes.le_next);
+ for (; vp && vp != BEG_OF_VLIST; vp = BACK_VP(vp)) {
+/* END HACK */
+/*
loop:
for (vp = mp->mnt_vnodelist.lh_first;
vp != NULL;
vp = vp->v_mntvnodes.le_next) {
+*/
/*
* If the vnode that we are about to sync is no longer
* associated with this mount point, start over.
@@ -294,13 +307,14 @@ lfs_segwrite(mp, flags)
struct mount *mp;
int flags; /* Do a checkpoint. */
{
+ struct proc *p = curproc; /* XXX */
struct buf *bp;
struct inode *ip;
struct lfs *fs;
struct segment *sp;
struct vnode *vp;
SEGUSE *segusep;
- daddr_t ibno;
+ ufs_daddr_t ibno;
CLEANERINFO *cip;
int clean, do_ckp, error, i;
@@ -314,14 +328,15 @@ lfs_segwrite(mp, flags)
LFS_CLEANERINFO(cip, fs, bp);
clean = cip->clean;
brelse(bp);
- if (clean <= 2) {
+ if (clean <= 2 || fs->lfs_avail <= 0) {
printf("lfs_segwrite: ran out of clean segments, waiting for cleaner\n");
wakeup(&lfs_allclean_wakeup);
+ wakeup(&fs->lfs_nextseg);
if (error = tsleep(&fs->lfs_avail, PRIBIO + 1,
"lfs writer", 0))
return (error);
}
- } while (clean <= 2 );
+ } while (clean <= 2 || fs->lfs_avail <= 0);
/*
* Allocate a segment structure and enough space to hold pointers to
@@ -369,7 +384,8 @@ lfs_segwrite(mp, flags)
if (do_ckp || fs->lfs_doifile) {
redo:
vp = fs->lfs_ivnode;
- while (vget(vp, 1));
+ while (vget(vp, LK_EXCLUSIVE, p))
+ continue;
ip = VTOI(vp);
if (vp->v_dirtyblkhd.lh_first != NULL)
lfs_writefile(fs, sp, vp);
@@ -418,7 +434,7 @@ lfs_writefile(fs, sp, vp)
sp->sum_bytes_left < sizeof(struct finfo))
(void) lfs_writeseg(fs, sp);
- sp->sum_bytes_left -= sizeof(struct finfo) - sizeof(daddr_t);
+ sp->sum_bytes_left -= sizeof(struct finfo) - sizeof(ufs_daddr_t);
++((SEGSUM *)(sp->segsum))->ss_nfinfo;
fip = sp->fip;
@@ -444,10 +460,10 @@ lfs_writefile(fs, sp, vp)
if (fip->fi_nblocks != 0) {
sp->fip =
(struct finfo *)((caddr_t)fip + sizeof(struct finfo) +
- sizeof(daddr_t) * (fip->fi_nblocks - 1));
+ sizeof(ufs_daddr_t) * (fip->fi_nblocks - 1));
sp->start_lbp = &sp->fip->fi_blocks[0];
} else {
- sp->sum_bytes_left += sizeof(struct finfo) - sizeof(daddr_t);
+ sp->sum_bytes_left += sizeof(struct finfo) - sizeof(ufs_daddr_t);
--((SEGSUM *)(sp->segsum))->ss_nfinfo;
}
}
@@ -461,7 +477,7 @@ lfs_writeinode(fs, sp, ip)
struct buf *bp, *ibp;
IFILE *ifp;
SEGUSE *sup;
- daddr_t daddr;
+ ufs_daddr_t daddr;
ino_t ino;
int error, i, ndx;
int redo_ifile = 0;
@@ -473,7 +489,7 @@ lfs_writeinode(fs, sp, ip)
if (sp->ibp == NULL) {
/* Allocate a new segment if necessary. */
if (sp->seg_bytes_left < fs->lfs_bsize ||
- sp->sum_bytes_left < sizeof(daddr_t))
+ sp->sum_bytes_left < sizeof(ufs_daddr_t))
(void) lfs_writeseg(fs, sp);
/* Get next inode block. */
@@ -489,10 +505,10 @@ lfs_writeinode(fs, sp, ip)
fs->lfs_avail -= fsbtodb(fs, 1);
/* Set remaining space counters. */
sp->seg_bytes_left -= fs->lfs_bsize;
- sp->sum_bytes_left -= sizeof(daddr_t);
- ndx = LFS_SUMMARY_SIZE / sizeof(daddr_t) -
+ sp->sum_bytes_left -= sizeof(ufs_daddr_t);
+ ndx = LFS_SUMMARY_SIZE / sizeof(ufs_daddr_t) -
sp->ninodes / INOPB(fs) - 1;
- ((daddr_t *)(sp->segsum))[ndx] = daddr;
+ ((ufs_daddr_t *)(sp->segsum))[ndx] = daddr;
}
/* Update the inode times and copy the inode onto the inode page. */
@@ -565,8 +581,8 @@ lfs_gatherblock(sp, bp, sptr)
panic ("lfs_gatherblock: Null vp in segment");
#endif
fs = sp->fs;
- if (sp->sum_bytes_left < sizeof(daddr_t) ||
- sp->seg_bytes_left < fs->lfs_bsize) {
+ if (sp->sum_bytes_left < sizeof(ufs_daddr_t) ||
+ sp->seg_bytes_left < bp->b_bcount) {
if (sptr)
splx(*sptr);
lfs_updatemeta(sp);
@@ -579,7 +595,7 @@ lfs_gatherblock(sp, bp, sptr)
/* Add the current file to the segment summary. */
++((SEGSUM *)(sp->segsum))->ss_nfinfo;
sp->sum_bytes_left -=
- sizeof(struct finfo) - sizeof(daddr_t);
+ sizeof(struct finfo) - sizeof(ufs_daddr_t);
if (sptr)
*sptr = splbio();
@@ -591,8 +607,8 @@ lfs_gatherblock(sp, bp, sptr)
*sp->cbpp++ = bp;
sp->fip->fi_blocks[sp->fip->fi_nblocks++] = bp->b_lblkno;
- sp->sum_bytes_left -= sizeof(daddr_t);
- sp->seg_bytes_left -= fs->lfs_bsize;
+ sp->sum_bytes_left -= sizeof(ufs_daddr_t);
+ sp->seg_bytes_left -= bp->b_bcount;
return(0);
}
@@ -608,7 +624,19 @@ lfs_gather(fs, sp, vp, match)
sp->vp = vp;
s = splbio();
-loop: for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = bp->b_vnbufs.le_next) {
+/* This is a hack to see if ordering the blocks in LFS makes a difference. */
+/* BEGIN HACK */
+#define BUF_OFFSET (((void *)&bp->b_vnbufs.le_next) - (void *)bp)
+#define BACK_BUF(BP) ((struct buf *)(((void *)BP->b_vnbufs.le_prev) - BUF_OFFSET))
+#define BEG_OF_LIST ((struct buf *)(((void *)&vp->v_dirtyblkhd.lh_first) - BUF_OFFSET))
+
+
+/*loop: for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = bp->b_vnbufs.le_next) {*/
+/* Find last buffer. */
+loop: for (bp = vp->v_dirtyblkhd.lh_first; bp && bp->b_vnbufs.le_next != NULL;
+ bp = bp->b_vnbufs.le_next);
+ for (; bp && bp != BEG_OF_LIST; bp = BACK_BUF(bp)) {
+/* END HACK */
if (bp->b_flags & B_BUSY || !match(fs, bp) ||
bp->b_flags & B_GATHERED)
continue;
@@ -641,11 +669,13 @@ lfs_updatemeta(sp)
struct vnode *vp;
struct indir a[NIADDR + 2], *ap;
struct inode *ip;
- daddr_t daddr, lbn, off;
- int db_per_fsb, error, i, nblocks, num;
+ ufs_daddr_t daddr, lbn, off;
+ int error, i, nblocks, num;
vp = sp->vp;
nblocks = &sp->fip->fi_blocks[sp->fip->fi_nblocks] - sp->start_lbp;
+ if (nblocks < 0)
+ panic("This is a bad thing\n");
if (vp == NULL || nblocks == 0)
return;
@@ -654,15 +684,23 @@ lfs_updatemeta(sp)
lfs_shellsort(sp->start_bpp, sp->start_lbp, nblocks);
/*
+ * Record the length of the last block in case it's a fragment.
+ * If there are indirect blocks present, they sort last. An
+ * indirect block will be lfs_bsize and its presence indicates
+ * that you cannot have fragments.
+ */
+ sp->fip->fi_lastlength = sp->start_bpp[nblocks - 1]->b_bcount;
+
+ /*
* Assign disk addresses, and update references to the logical
* block and the segment usage information.
*/
fs = sp->fs;
- db_per_fsb = fsbtodb(fs, 1);
for (i = nblocks; i--; ++sp->start_bpp) {
lbn = *sp->start_lbp++;
(*sp->start_bpp)->b_blkno = off = fs->lfs_offset;
- fs->lfs_offset += db_per_fsb;
+ fs->lfs_offset +=
+ fragstodb(fs, numfrags(fs, (*sp->start_bpp)->b_bcount));
if (error = ufs_bmaparray(vp, lbn, &daddr, a, &num, NULL, NULL))
panic("lfs_updatemeta: ufs_bmaparray %d", error);
@@ -684,11 +722,10 @@ lfs_updatemeta(sp)
* to get counted for the inode.
*/
if (bp->b_blkno == -1 && !(bp->b_flags & B_CACHE)) {
- printf ("Updatemeta allocating indirect block: shouldn't happen\n");
- ip->i_blocks += btodb(fs->lfs_bsize);
- fs->lfs_bfree -= btodb(fs->lfs_bsize);
+ ip->i_blocks += fsbtodb(fs, 1);
+ fs->lfs_bfree -= fragstodb(fs, fs->lfs_frag);
}
- ((daddr_t *)bp->b_data)[ap->in_off] = off;
+ ((ufs_daddr_t *)bp->b_data)[ap->in_off] = off;
VOP_BWRITE(bp);
}
@@ -697,14 +734,16 @@ lfs_updatemeta(sp)
!(daddr >= fs->lfs_lastpseg && daddr <= off)) {
LFS_SEGENTRY(sup, fs, datosn(fs, daddr), bp);
#ifdef DIAGNOSTIC
- if (sup->su_nbytes < fs->lfs_bsize) {
+ if (sup->su_nbytes < (*sp->start_bpp)->b_bcount) {
/* XXX -- Change to a panic. */
printf("lfs: negative bytes (segment %ld)\n",
datosn(fs, daddr));
+ printf("lfs: bp = 0x%x, addr = 0x%x\n",
+ bp, bp->b_un.b_addr);
panic ("Negative Bytes");
}
#endif
- sup->su_nbytes -= fs->lfs_bsize;
+ sup->su_nbytes -= (*sp->start_bpp)->b_bcount;
error = VOP_BWRITE(bp);
}
}
@@ -730,6 +769,7 @@ lfs_initseg(fs)
if (!LFS_PARTIAL_FITS(fs)) {
/* Wake up any cleaning procs waiting on this file system. */
wakeup(&lfs_allclean_wakeup);
+ wakeup(&fs->lfs_nextseg);
lfs_newseg(fs);
repeat = 1;
@@ -771,11 +811,13 @@ lfs_initseg(fs)
ssp = sp->segsum;
ssp->ss_next = fs->lfs_nextseg;
ssp->ss_nfinfo = ssp->ss_ninos = 0;
+ ssp->ss_magic = SS_MAGIC;
/* Set pointer to first FINFO, initialize it. */
- sp->fip = (struct finfo *)((char *)sp->segsum + sizeof(SEGSUM));
+ sp->fip = (struct finfo *)((caddr_t)sp->segsum + sizeof(SEGSUM));
sp->fip->fi_nblocks = 0;
sp->start_lbp = &sp->fip->fi_blocks[0];
+ sp->fip->fi_lastlength = 0;
sp->seg_bytes_left -= LFS_SUMMARY_SIZE;
sp->sum_bytes_left = LFS_SUMMARY_SIZE - sizeof(SEGSUM);
@@ -836,9 +878,8 @@ lfs_writeseg(fs, sp)
SEGUSE *sup;
SEGSUM *ssp;
dev_t i_dev;
- size_t size;
u_long *datap, *dp;
- int ch_per_blk, do_again, i, nblocks, num, s;
+ int do_again, i, nblocks, s;
int (*strategy)__P((struct vop_strategy_args *));
struct vop_strategy_args vop_strategy_a;
u_short ninos;
@@ -852,12 +893,16 @@ lfs_writeseg(fs, sp)
if ((nblocks = sp->cbpp - sp->bpp) == 1)
return (0);
- ssp = (SEGSUM *)sp->segsum;
-
/* Update the segment usage information. */
LFS_SEGENTRY(sup, fs, sp->seg_number, bp);
+
+ /* Loop through all blocks, except the segment summary. */
+ for (bpp = sp->bpp; ++bpp < sp->cbpp; )
+ sup->su_nbytes += (*bpp)->b_bcount;
+
+ ssp = (SEGSUM *)sp->segsum;
+
ninos = (ssp->ss_ninos + INOPB(fs) - 1) / INOPB(fs);
- sup->su_nbytes += nblocks - 1 - ninos << fs->lfs_bshift;
sup->su_nbytes += ssp->ss_ninos * sizeof(struct dinode);
sup->su_nbytes += LFS_SUMMARY_SIZE;
sup->su_lastmod = time.tv_sec;
@@ -910,23 +955,21 @@ lfs_writeseg(fs, sp)
* easily make the buffers contiguous in kernel memory and if that's
* fast enough.
*/
- ch_per_blk = MAXPHYS / fs->lfs_bsize;
for (bpp = sp->bpp, i = nblocks; i;) {
- num = ch_per_blk;
- if (num > i)
- num = i;
- i -= num;
- size = num * fs->lfs_bsize;
-
cbp = lfs_newbuf(VTOI(fs->lfs_ivnode)->i_devvp,
- (*bpp)->b_blkno, size);
+ (*bpp)->b_blkno, MAXPHYS);
cbp->b_dev = i_dev;
cbp->b_flags |= B_ASYNC | B_BUSY;
+ cbp->b_bcount = 0;
s = splbio();
++fs->lfs_iocount;
- for (p = cbp->b_data; num--;) {
- bp = *bpp++;
+ for (p = cbp->b_data; i && cbp->b_bcount < MAXPHYS; i--) {
+ bp = *bpp;
+ if (bp->b_bcount > (MAXPHYS - cbp->b_bcount))
+ break;
+ bpp++;
+
/*
* Fake buffers from the cleaner are marked as B_INVAL.
* We need to copy the data from user space rather than
@@ -939,7 +982,8 @@ lfs_writeseg(fs, sp)
} else
bcopy(bp->b_data, p, bp->b_bcount);
p += bp->b_bcount;
- if (bp->b_flags & B_LOCKED)
+ cbp->b_bcount += bp->b_bcount;
+ if (bp->b_flags & B_LOCKED)
--locked_queue_count;
bp->b_flags &= ~(B_ERROR | B_READ | B_DELWRI |
B_LOCKED | B_GATHERED);
@@ -955,7 +999,6 @@ lfs_writeseg(fs, sp)
brelse(bp);
}
}
- cbp->b_bcount = p - (char *)cbp->b_data;
++cbp->b_vp->v_numoutput;
splx(s);
/*
@@ -1079,7 +1122,7 @@ lfs_match_tindir(fs, bp)
struct buf *
lfs_newbuf(vp, daddr, size)
struct vnode *vp;
- daddr_t daddr;
+ ufs_daddr_t daddr;
size_t size;
{
struct buf *bp;
@@ -1144,7 +1187,7 @@ lfs_supercallback(bp)
static void
lfs_shellsort(bp_array, lb_array, nmemb)
struct buf **bp_array;
- daddr_t *lb_array;
+ ufs_daddr_t *lb_array;
register int nmemb;
{
static int __rsshell_increments[] = { 4, 1, 0 };
@@ -1174,24 +1217,38 @@ int
lfs_vref(vp)
register struct vnode *vp;
{
- if ((vp->v_flag & VXLOCK) ||
- (vp->v_usecount == 0 &&
- vp->v_freelist.tqe_prev == (struct vnode **)0xdeadb))
- return(1);
- return (vget(vp, 0));
+ struct proc *p = curproc; /* XXX */
+
+ if ((vp->v_flag & VXLOCK) || /* XXX */
+ (vp->v_usecount == 0 &&
+ vp->v_freelist.tqe_prev == (struct vnode **)0xdeadb))
+ return(1);
+ return (vget(vp, 0, p));
}
+/*
+ * This is vrele except that we do not want to VOP_INACTIVE this vnode. We
+ * inline vrele here to avoid the vn_lock and VOP_INACTIVE call at the end.
+ */
void
lfs_vunref(vp)
register struct vnode *vp;
{
- /*
- * This is vrele except that we do not want to VOP_INACTIVE
- * this vnode. Rather than inline vrele here, we flag the vnode
- * to tell lfs_inactive not to run on this vnode. Not as gross as
- * a global.
- */
- vp->v_flag |= VNINACT;
- vrele(vp);
- vp->v_flag &= ~VNINACT;
+ struct proc *p = curproc; /* XXX */
+ extern struct simplelock vnode_free_list_slock; /* XXX */
+ extern TAILQ_HEAD(freelst, vnode) vnode_free_list; /* XXX */
+
+ simple_lock(&vp->v_interlock);
+ vp->v_usecount--;
+ if (vp->v_usecount > 0) {
+ simple_unlock(&vp->v_interlock);
+ return;
+ }
+ /*
+ * insert at tail of LRU list
+ */
+ simple_lock(&vnode_free_list_slock);
+ TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+ simple_unlock(&vnode_free_list_slock);
+ simple_unlock(&vp->v_interlock);
}
diff --git a/sys/ufs/lfs/lfs_syscalls.c b/sys/ufs/lfs/lfs_syscalls.c
index feb484b..2024109 100644
--- a/sys/ufs/lfs/lfs_syscalls.c
+++ b/sys/ufs/lfs/lfs_syscalls.c
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_syscalls.c 8.5 (Berkeley) 4/20/94
- * $Id: lfs_syscalls.c,v 1.17 1997/02/22 09:47:24 peter Exp $
+ * @(#)lfs_syscalls.c 8.10 (Berkeley) 5/14/95
+ * $Id: lfs_syscalls.c,v 1.18 1997/03/22 08:03:51 bde Exp $
*/
#include <sys/param.h>
@@ -69,6 +69,10 @@ static struct buf *lfs_fakebuf __P((struct vnode *, int, size_t, caddr_t));
static int lfs_fastvget __P((struct mount *, ino_t, daddr_t, struct vnode **,
struct dinode *));
+int debug_cleaner = 0;
+int clean_vnlocked = 0;
+int clean_inlocked = 0;
+
/*
* lfs_markv:
*
@@ -106,7 +110,7 @@ lfs_markv(p, uap, retval)
fsid_t fsid;
void *start;
ino_t lastino;
- daddr_t b_daddr, v_daddr;
+ ufs_daddr_t b_daddr, v_daddr;
u_long bsize;
int cnt, error;
@@ -142,7 +146,7 @@ lfs_markv(p, uap, retval)
if (sp->fip->fi_nblocks == 0) {
DEC_FINFO(sp);
sp->sum_bytes_left +=
- sizeof(FINFO) - sizeof(daddr_t);
+ sizeof(FINFO) - sizeof(ufs_daddr_t);
} else {
lfs_updatemeta(sp);
BUMP_FIP(sp);
@@ -154,7 +158,7 @@ lfs_markv(p, uap, retval)
/* Start a new file */
CHECK_SEG(sizeof(FINFO));
- sp->sum_bytes_left -= sizeof(FINFO) - sizeof(daddr_t);
+ sp->sum_bytes_left -= sizeof(FINFO) - sizeof(ufs_daddr_t);
INC_FINFO(sp);
sp->start_lbp = &sp->fip->fi_blocks[0];
sp->vp = NULL;
@@ -179,6 +183,7 @@ lfs_markv(p, uap, retval)
#ifdef DIAGNOSTIC
printf("lfs_markv: VFS_VGET failed (%ld)\n",
blkp->bi_inode);
+ panic("lfs_markv VFS_VGET FAILED");
#endif
lastino = LFS_UNUSED_INUM;
v_daddr = LFS_UNUSED_DADDR;
@@ -209,7 +214,7 @@ lfs_markv(p, uap, retval)
bp = getblk(vp, blkp->bi_lbn, bsize, 0, 0);
if (!(bp->b_flags & (B_DELWRI | B_DONE | B_CACHE)) &&
(error = copyin(blkp->bi_bp, bp->b_data,
- bsize)))
+ blkp->bi_size)))
goto err2;
if (error = VOP_BWRITE(bp))
goto err2;
@@ -220,7 +225,7 @@ lfs_markv(p, uap, retval)
if (sp->fip->fi_nblocks == 0) {
DEC_FINFO(sp);
sp->sum_bytes_left +=
- sizeof(FINFO) - sizeof(daddr_t);
+ sizeof(FINFO) - sizeof(ufs_daddr_t);
} else
lfs_updatemeta(sp);
@@ -275,10 +280,11 @@ lfs_bmapv(p, uap, retval)
{
BLOCK_INFO *blkp;
struct mount *mntp;
+ struct ufsmount *ump;
struct vnode *vp;
fsid_t fsid;
void *start;
- daddr_t daddr;
+ ufs_daddr_t daddr;
int cnt, error, step;
if (error = suser(p->p_ucred, &p->p_acflag))
@@ -299,8 +305,16 @@ lfs_bmapv(p, uap, retval)
for (step = cnt; step--; ++blkp) {
if (blkp->bi_lbn == LFS_UNUSED_LBN)
continue;
- /* Could be a deadlock ? */
- if (VFS_VGET(mntp, blkp->bi_inode, &vp))
+ /*
+ * A regular call to VFS_VGET could deadlock
+ * here. Instead, we try an unlocked access.
+ */
+ ump = VFSTOUFS(mntp);
+ if ((vp =
+ ufs_ihashlookup(ump->um_dev, blkp->bi_inode)) != NULL) {
+ if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL, NULL))
+ daddr = LFS_UNUSED_DADDR;
+ } else if (VFS_VGET(mntp, blkp->bi_inode, &vp))
daddr = LFS_UNUSED_DADDR;
else {
if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL, NULL))
@@ -452,7 +466,7 @@ static int
lfs_fastvget(mp, ino, daddr, vpp, dinp)
struct mount *mp;
ino_t ino;
- daddr_t daddr;
+ ufs_daddr_t daddr;
struct vnode **vpp;
struct dinode *dinp;
{
@@ -473,15 +487,13 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp)
if ((*vpp = ufs_ihashlookup(dev, ino)) != NULL) {
lfs_vref(*vpp);
if ((*vpp)->v_flag & VXLOCK)
- printf ("Cleaned vnode VXLOCKED\n");
+ clean_vnlocked++;
ip = VTOI(*vpp);
- if (ip->i_flags & IN_LOCKED)
- printf("cleaned vnode locked\n");
- if (!(ip->i_flag & IN_MODIFIED)) {
+ if (lockstatus(&ip->i_lock))
+ clean_inlocked++;
+ if (!(ip->i_flag & IN_MODIFIED))
++ump->um_lfs->lfs_uinodes;
- ip->i_flag |= IN_MODIFIED;
- }
- ip->i_flag |= IN_MODIFIED; /* XXX why is this here? it's redundant */
+ ip->i_flag |= IN_MODIFIED;
return (0);
}
@@ -533,11 +545,6 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp)
brelse(bp);
}
- /* Inode was just read from user space or disk, make sure it's locked */
- ip->i_flag |= IN_LOCKED;
- ip->i_lockholder = curproc->p_pid;
- ip->i_lockcount = 1;
-
/*
* Initialize the vnode from the inode, check for aliases. In all
* cases re-init ip, the underlying vnode/inode may have changed.
diff --git a/sys/ufs/lfs/lfs_vfsops.c b/sys/ufs/lfs/lfs_vfsops.c
index cab3818..265a580 100644
--- a/sys/ufs/lfs/lfs_vfsops.c
+++ b/sys/ufs/lfs/lfs_vfsops.c
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_vfsops.c 8.7 (Berkeley) 4/16/94
- * $Id$
+ * @(#)lfs_vfsops.c 8.20 (Berkeley) 6/10/95
+ * $Id: lfs_vfsops.c,v 1.16 1997/02/22 09:47:25 peter Exp $
*/
#include "opt_quota.h"
@@ -85,10 +85,47 @@ struct vfsops lfs_vfsops = {
lfs_fhtovp,
lfs_vptofh,
lfs_init,
+#ifdef notyet
+ lfs_sysctl,
+#endif
};
VFS_SET(lfs_vfsops, lfs, MOUNT_LFS, 0);
+/*
+ * Called by main() when ufs is going to be mounted as root.
+ */
+lfs_mountroot()
+{
+ extern struct vnode *rootvp;
+ struct fs *fs;
+ struct mount *mp;
+ struct proc *p = curproc; /* XXX */
+ int error;
+
+ /*
+ * Get vnodes for swapdev and rootdev.
+ */
+ if ((error = bdevvp(swapdev, &swapdev_vp)) ||
+ (error = bdevvp(rootdev, &rootvp))) {
+ printf("lfs_mountroot: can't setup bdevvp's");
+ return (error);
+ }
+ if (error = vfs_rootmountalloc("lfs", "root_device", &mp))
+ return (error);
+ if (error = lfs_mountfs(rootvp, mp, p)) {
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
+ free(mp, M_MOUNT);
+ return (error);
+ }
+ simple_lock(&mountlist_slock);
+ CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
+ simple_unlock(&mountlist_slock);
+ (void)lfs_statfs(mp, &mp->mnt_stat, p);
+ vfs_unbusy(mp, p);
+ return (0);
+}
/*
* lfs_mount
@@ -143,6 +180,7 @@ lfs_mount(mp, path, data, ndp, p)
register struct lfs *fs; /* LFS */
u_int size;
int err;
+ mode_t accessmode;
/*
* Use NULL path to flag a root mount
@@ -180,15 +218,23 @@ lfs_mount(mp, path, data, ndp, p)
*/
if (mp->mnt_flag & MNT_UPDATE) {
ump = VFSTOUFS(mp);
-#ifdef NOTLFS /* LFS */
- fs = ump->um_fs;
- if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
- fs->fs_ronly = 0;
-#else
- fs = ump->um_lfs;
- if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
+ if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
+ /*
+ * If upgrade to read-write by non-root, then verify
+ * that user has necessary permissions on the device.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY,
+ p);
+ if (err = VOP_ACCESS(ump->um_devvp,
+ VREAD | VWRITE, p->p_ucred, p)) {
+ VOP_UNLOCK(ump->um_devvp, 0, p);
+ return (err);
+ }
+ VOP_UNLOCK(ump->um_devvp, 0, p);
+ }
fs->lfs_ronly = 0;
-#endif
+ }
if (args.fspec == 0) {
/*
* Process export requests. Jumping to "success"
@@ -214,6 +260,21 @@ lfs_mount(mp, path, data, ndp, p)
err = ENXIO;
goto error_2;
}
+ /*
+ * If mount by non-root, then verify that user has necessary
+ * permissions on the device.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ accessmode = VREAD;
+ if ((mp->mnt_flag & MNT_RDONLY) == 0)
+ accessmode |= VWRITE;
+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (err = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
+ vput(devvp);
+ return (err);
+ }
+ VOP_UNLOCK(devvp, 0, p);
+ }
if ((mp->mnt_flag & MNT_UPDATE) == 0)
err = lfs_mountfs(devvp, mp, p); /* LFS */
else {
@@ -277,7 +338,9 @@ lfs_mountfs(devvp, mp, p)
struct partinfo dpart;
dev_t dev;
int error, i, ronly, size;
+ struct ucred *cred;
+ cred = p ? p->p_ucred : NOCRED;
/*
* Disallow multiple mounts of the same device.
* Disallow mounting of a device that is currently in use
@@ -288,14 +351,14 @@ lfs_mountfs(devvp, mp, p)
return (error);
if (vcount(devvp) > 1 && devvp != rootvp)
return (EBUSY);
- if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0))
+ if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
return (error);
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
return (error);
- if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
+ if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
size = DEV_BSIZE;
else {
size = dpart.disklab->d_secsize;
@@ -312,7 +375,7 @@ lfs_mountfs(devvp, mp, p)
ump = NULL;
/* Read in the superblock. */
- if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp))
+ if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp))
goto out;
fs = (struct lfs *)bp->b_data;
@@ -350,9 +413,9 @@ lfs_mountfs(devvp, mp, p)
dev = devvp->v_rdev;
mp->mnt_data = (qaddr_t)ump;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
- mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS;
- mp->mnt_flag |= MNT_LOCAL;
+ mp->mnt_stat.f_fsid.val[1] = lfs_mount_type;
mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen;
+ mp->mnt_flag |= MNT_LOCAL;
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
@@ -379,7 +442,7 @@ lfs_mountfs(devvp, mp, p)
out:
if (bp)
brelse(bp);
- (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
+ (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
if (ump) {
free(ump->um_lfs, M_UFSMNT);
free(ump, M_UFSMNT);
@@ -402,11 +465,8 @@ lfs_unmount(mp, mntflags, p)
int i, error, flags, ronly;
flags = 0;
- if (mntflags & MNT_FORCE) {
- if (!doforce)
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
ump = VFSTOUFS(mp);
fs = ump->um_lfs;
@@ -463,17 +523,23 @@ lfs_statfs(mp, sbp, p)
fs = ump->um_lfs;
if (fs->lfs_magic != LFS_MAGIC)
panic("lfs_statfs: magic");
- sbp->f_type = MOUNT_LFS;
- sbp->f_bsize = fs->lfs_bsize;
+ sbp->f_bsize = fs->lfs_fsize;
sbp->f_iosize = fs->lfs_bsize;
- sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize);
- sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree);
- sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
- (fs->lfs_dsize - fs->lfs_bfree);
- sbp->f_bavail = dbtofsb(fs, sbp->f_bavail);
+ sbp->f_blocks = dbtofrags(fs,fs->lfs_dsize);
+ sbp->f_bfree = dbtofrags(fs, fs->lfs_bfree);
+ /*
+ * To compute the available space. Subtract the minimum free
+ * from the total number of blocks in the file system. Set avail
+ * to the smaller of this number and fs->lfs_bfree.
+ */
+ sbp->f_bavail = fs->lfs_dsize * (100 - fs->lfs_minfree) / 100;
+ sbp->f_bavail =
+ sbp->f_bavail > fs->lfs_bfree ? fs->lfs_bfree : sbp->f_bavail;
+ sbp->f_bavail = dbtofrags(fs, sbp->f_bavail);
sbp->f_files = fs->lfs_nfiles;
sbp->f_ffree = sbp->f_bfree * INOPB(fs);
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy((caddr_t)mp->mnt_stat.f_mntonname,
(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
@@ -523,7 +589,7 @@ lfs_vget(mp, ino, vpp)
struct ifile *ifp;
struct vnode *vp;
struct ufsmount *ump;
- daddr_t daddr;
+ ufs_daddr_t daddr;
dev_t dev;
int error;
@@ -653,3 +719,17 @@ lfs_vptofh(vp, fhp)
ufhp->ufid_gen = ip->i_gen;
return (0);
}
+
+/*
+ * Initialize the filesystem, most work done by ufs_init.
+ */
+int lfs_mount_type;
+
+int
+lfs_init(vfsp)
+ struct vfsconf *vfsp;
+{
+
+ lfs_mount_type = vfsp->vfc_typenum;
+ return (ufs_init(vfsp));
+}
diff --git a/sys/ufs/lfs/lfs_vnops.c b/sys/ufs/lfs/lfs_vnops.c
index bff2bcc..2879cf8 100644
--- a/sys/ufs/lfs/lfs_vnops.c
+++ b/sys/ufs/lfs/lfs_vnops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1986, 1989, 1991, 1993
+ * Copyright (c) 1986, 1989, 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_vnops.c 8.5 (Berkeley) 12/30/93
- * $Id: lfs_vnops.c,v 1.19 1997/02/22 09:47:26 peter Exp $
+ * @(#)lfs_vnops.c 8.13 (Berkeley) 6/10/95
+ * $Id: lfs_vnops.c,v 1.20 1997/03/22 06:53:38 bde Exp $
*/
#include <sys/param.h>
@@ -83,6 +83,7 @@ static struct vnodeopv_entry_desc lfs_vnodeop_entries[] = {
{ &vop_lookup_desc, (vop_t *)ufs_lookup }, /* lookup */
{ &vop_create_desc, (vop_t *)ufs_create }, /* create */
{ &vop_mknod_desc, (vop_t *)ufs_mknod }, /* mknod */
+ { &vop_whiteout_desc, (vop_t *)ufs_whiteout }, /* whiteout */
{ &vop_open_desc, (vop_t *)ufs_open }, /* open */
{ &vop_close_desc, (vop_t *)lfs_close }, /* close */
{ &vop_access_desc, (vop_t *)ufs_access }, /* access */
@@ -90,8 +91,10 @@ static struct vnodeopv_entry_desc lfs_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)ufs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)lfs_read }, /* read */
{ &vop_write_desc, (vop_t *)lfs_write }, /* write */
+ { &vop_lease_desc, (vop_t *)ufs_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)ufs_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)ufs_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)ufs_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)ufs_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)lfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)ufs_seek }, /* seek */
@@ -104,8 +107,8 @@ static struct vnodeopv_entry_desc lfs_vnodeop_entries[] = {
{ &vop_readdir_desc, (vop_t *)ufs_readdir }, /* readdir */
{ &vop_readlink_desc, (vop_t *)ufs_readlink }, /* readlink */
{ &vop_abortop_desc, (vop_t *)ufs_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)lfs_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)ufs_reclaim }, /* reclaim */
+ { &vop_inactive_desc, (vop_t *)ufs_inactive }, /* inactive */
+ { &vop_reclaim_desc, (vop_t *)lfs_reclaim }, /* reclaim */
{ &vop_lock_desc, (vop_t *)ufs_lock }, /* lock */
{ &vop_unlock_desc, (vop_t *)ufs_unlock }, /* unlock */
{ &vop_bmap_desc, (vop_t *)ufs_bmap }, /* bmap */
@@ -138,8 +141,10 @@ static struct vnodeopv_entry_desc lfs_specop_entries[] = {
{ &vop_setattr_desc, (vop_t *)ufs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)ufsspec_read }, /* read */
{ &vop_write_desc, (vop_t *)ufsspec_write }, /* write */
+ { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)spec_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
@@ -152,8 +157,8 @@ static struct vnodeopv_entry_desc lfs_specop_entries[] = {
{ &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */
{ &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */
{ &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)lfs_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)ufs_reclaim }, /* reclaim */
+ { &vop_inactive_desc, (vop_t *)ufs_inactive }, /* inactive */
+ { &vop_reclaim_desc, (vop_t *)lfs_reclaim }, /* reclaim */
{ &vop_lock_desc, (vop_t *)ufs_lock }, /* lock */
{ &vop_unlock_desc, (vop_t *)ufs_unlock }, /* unlock */
{ &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */
@@ -186,8 +191,10 @@ static struct vnodeopv_entry_desc lfs_fifoop_entries[] = {
{ &vop_setattr_desc, (vop_t *)ufs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)ufsfifo_read }, /* read */
{ &vop_write_desc, (vop_t *)ufsfifo_write }, /* write */
+ { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fifo_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
@@ -200,8 +207,8 @@ static struct vnodeopv_entry_desc lfs_fifoop_entries[] = {
{ &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
{ &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
{ &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)lfs_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)ufs_reclaim }, /* reclaim */
+ { &vop_inactive_desc, (vop_t *)ufs_inactive }, /* inactive */
+ { &vop_reclaim_desc, (vop_t *)lfs_reclaim }, /* reclaim */
{ &vop_lock_desc, (vop_t *)ufs_lock }, /* lock */
{ &vop_unlock_desc, (vop_t *)ufs_unlock }, /* unlock */
{ &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
@@ -298,9 +305,12 @@ lfs_getattr(ap)
vap->va_gid = ip->i_gid;
vap->va_rdev = (dev_t)ip->i_rdev;
vap->va_size = ip->i_din.di_size;
- vap->va_atime = ip->i_atime;
- vap->va_mtime = ip->i_mtime;
- vap->va_ctime = ip->i_ctime;
+ vap->va_atime.tv_sec = ip->i_atime;
+ vap->va_atime.tv_nsec = ip->i_atimensec;
+ vap->va_mtime.tv_sec = ip->i_mtime;
+ vap->va_mtime.tv_nsec = ip->i_mtimensec;
+ vap->va_ctime.tv_sec = ip->i_ctime;
+ vap->va_ctime.tv_nsec = ip->i_ctimensec;
vap->va_flags = ip->i_flags;
vap->va_gen = ip->i_gen;
/* this doesn't belong here */
@@ -336,28 +346,33 @@ lfs_close(ap)
register struct inode *ip = VTOI(vp);
int mod;
- if (vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) {
+ simple_lock(&vp->v_interlock);
+ if (vp->v_usecount > 1) {
mod = ip->i_flag & IN_MODIFIED;
ITIMES(ip, &time, &time);
if (!mod && ip->i_flag & IN_MODIFIED)
ip->i_lfs->lfs_uinodes++;
}
+ simple_unlock(&vp->v_interlock);
return (0);
}
/*
- * Stub inactive routine that avoids calling ufs_inactive in some cases.
+ * Reclaim an inode so that it can be used for other purposes.
*/
-
-static int
-lfs_inactive(ap)
- struct vop_inactive_args /* {
+int
+lfs_reclaim(ap)
+ struct vop_reclaim_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
+ register struct vnode *vp = ap->a_vp;
+ int error;
- if (ap->a_vp->v_flag & VNINACT) {
- return(0);
- }
- return (ufs_inactive(ap));
+ if (error = ufs_reclaim(vp, ap->a_p))
+ return (error);
+ FREE(vp->v_data, M_LFSNODE);
+ vp->v_data = NULL;
+ return (0);
}
OpenPOWER on IntegriCloud