Home | History | Annotate | Line # | Download | only in lfs
lfs_syscalls.c revision 1.3
      1  1.3      cgd /*	$NetBSD: lfs_syscalls.c,v 1.3 1994/06/29 06:47:02 cgd Exp $	*/
      2  1.3      cgd 
      3  1.1  mycroft /*-
      4  1.1  mycroft  * Copyright (c) 1991, 1993, 1994
      5  1.1  mycroft  *	The Regents of the University of California.  All rights reserved.
      6  1.1  mycroft  *
      7  1.1  mycroft  * Redistribution and use in source and binary forms, with or without
      8  1.1  mycroft  * modification, are permitted provided that the following conditions
      9  1.1  mycroft  * are met:
     10  1.1  mycroft  * 1. Redistributions of source code must retain the above copyright
     11  1.1  mycroft  *    notice, this list of conditions and the following disclaimer.
     12  1.1  mycroft  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  mycroft  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  mycroft  *    documentation and/or other materials provided with the distribution.
     15  1.1  mycroft  * 3. All advertising materials mentioning features or use of this software
     16  1.1  mycroft  *    must display the following acknowledgement:
     17  1.1  mycroft  *	This product includes software developed by the University of
     18  1.1  mycroft  *	California, Berkeley and its contributors.
     19  1.1  mycroft  * 4. Neither the name of the University nor the names of its contributors
     20  1.1  mycroft  *    may be used to endorse or promote products derived from this software
     21  1.1  mycroft  *    without specific prior written permission.
     22  1.1  mycroft  *
     23  1.1  mycroft  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  1.1  mycroft  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  1.1  mycroft  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  1.1  mycroft  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  1.1  mycroft  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  1.1  mycroft  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  1.1  mycroft  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  1.1  mycroft  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  1.1  mycroft  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  1.1  mycroft  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  1.1  mycroft  * SUCH DAMAGE.
     34  1.1  mycroft  *
     35  1.3      cgd  *	@(#)lfs_syscalls.c	8.5 (Berkeley) 4/20/94
     36  1.1  mycroft  */
     37  1.1  mycroft 
     38  1.1  mycroft #include <sys/param.h>
     39  1.1  mycroft #include <sys/proc.h>
     40  1.1  mycroft #include <sys/buf.h>
     41  1.1  mycroft #include <sys/mount.h>
     42  1.1  mycroft #include <sys/vnode.h>
     43  1.1  mycroft #include <sys/malloc.h>
     44  1.1  mycroft #include <sys/kernel.h>
     45  1.1  mycroft 
     46  1.1  mycroft #include <ufs/ufs/quota.h>
     47  1.1  mycroft #include <ufs/ufs/inode.h>
     48  1.1  mycroft #include <ufs/ufs/ufsmount.h>
     49  1.1  mycroft #include <ufs/ufs/ufs_extern.h>
     50  1.1  mycroft 
     51  1.1  mycroft #include <ufs/lfs/lfs.h>
     52  1.1  mycroft #include <ufs/lfs/lfs_extern.h>
     53  1.1  mycroft #define BUMP_FIP(SP) \
     54  1.1  mycroft 	(SP)->fip = (FINFO *) (&(SP)->fip->fi_blocks[(SP)->fip->fi_nblocks])
     55  1.1  mycroft 
     56  1.1  mycroft #define INC_FINFO(SP) ++((SEGSUM *)((SP)->segsum))->ss_nfinfo
     57  1.1  mycroft #define DEC_FINFO(SP) --((SEGSUM *)((SP)->segsum))->ss_nfinfo
     58  1.1  mycroft 
     59  1.1  mycroft /*
     60  1.1  mycroft  * Before committing to add something to a segment summary, make sure there
     61  1.1  mycroft  * is enough room.  S is the bytes added to the summary.
     62  1.1  mycroft  */
     63  1.1  mycroft #define	CHECK_SEG(s)			\
     64  1.1  mycroft if (sp->sum_bytes_left < (s)) {		\
     65  1.1  mycroft 	(void) lfs_writeseg(fs, sp);	\
     66  1.1  mycroft }
     67  1.1  mycroft struct buf *lfs_fakebuf __P((struct vnode *, int, size_t, caddr_t));
     68  1.1  mycroft 
     69  1.1  mycroft /*
     70  1.1  mycroft  * lfs_markv:
     71  1.1  mycroft  *
     72  1.1  mycroft  * This will mark inodes and blocks dirty, so they are written into the log.
     73  1.1  mycroft  * It will block until all the blocks have been written.  The segment create
     74  1.1  mycroft  * time passed in the block_info and inode_info structures is used to decide
     75  1.1  mycroft  * if the data is valid for each block (in case some process dirtied a block
     76  1.1  mycroft  * or inode that is being cleaned between the determination that a block is
     77  1.1  mycroft  * live and the lfs_markv call).
     78  1.1  mycroft  *
     79  1.1  mycroft  *  0 on success
     80  1.1  mycroft  * -1/errno is return on error.
     81  1.1  mycroft  */
     82  1.1  mycroft struct lfs_markv_args {
     83  1.1  mycroft 	fsid_t *fsidp;		/* file system */
     84  1.1  mycroft 	BLOCK_INFO *blkiov;	/* block array */
     85  1.1  mycroft 	int blkcnt;		/* count of block array entries */
     86  1.1  mycroft };
     87  1.1  mycroft int
     88  1.1  mycroft lfs_markv(p, uap, retval)
     89  1.1  mycroft 	struct proc *p;
     90  1.1  mycroft 	struct lfs_markv_args *uap;
     91  1.1  mycroft 	int *retval;
     92  1.1  mycroft {
     93  1.1  mycroft 	struct segment *sp;
     94  1.1  mycroft 	BLOCK_INFO *blkp;
     95  1.1  mycroft 	IFILE *ifp;
     96  1.1  mycroft 	struct buf *bp, **bpp;
     97  1.1  mycroft 	struct inode *ip;
     98  1.1  mycroft 	struct lfs *fs;
     99  1.1  mycroft 	struct mount *mntp;
    100  1.1  mycroft 	struct vnode *vp;
    101  1.1  mycroft 	fsid_t fsid;
    102  1.1  mycroft 	void *start;
    103  1.1  mycroft 	ino_t lastino;
    104  1.1  mycroft 	daddr_t b_daddr, v_daddr;
    105  1.1  mycroft 	u_long bsize;
    106  1.1  mycroft 	int cnt, error;
    107  1.1  mycroft 
    108  1.1  mycroft 	if (error = suser(p->p_ucred, &p->p_acflag))
    109  1.1  mycroft 		return (error);
    110  1.1  mycroft 
    111  1.1  mycroft 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
    112  1.1  mycroft 		return (error);
    113  1.1  mycroft 	if ((mntp = getvfs(&fsid)) == NULL)
    114  1.1  mycroft 		return (EINVAL);
    115  1.1  mycroft 
    116  1.1  mycroft 	cnt = uap->blkcnt;
    117  1.1  mycroft 	start = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
    118  1.1  mycroft 	if (error = copyin(uap->blkiov, start, cnt * sizeof(BLOCK_INFO)))
    119  1.1  mycroft 		goto err1;
    120  1.1  mycroft 
    121  1.1  mycroft 	/* Mark blocks/inodes dirty.  */
    122  1.1  mycroft 	fs = VFSTOUFS(mntp)->um_lfs;
    123  1.1  mycroft 	bsize = fs->lfs_bsize;
    124  1.1  mycroft 	error = 0;
    125  1.1  mycroft 
    126  1.1  mycroft 	lfs_seglock(fs, SEGM_SYNC | SEGM_CLEAN);
    127  1.1  mycroft 	sp = fs->lfs_sp;
    128  1.1  mycroft 	for (v_daddr = LFS_UNUSED_DADDR, lastino = LFS_UNUSED_INUM,
    129  1.1  mycroft 	    blkp = start; cnt--; ++blkp) {
    130  1.1  mycroft 		/*
    131  1.1  mycroft 		 * Get the IFILE entry (only once) and see if the file still
    132  1.1  mycroft 		 * exists.
    133  1.1  mycroft 		 */
    134  1.1  mycroft 		if (lastino != blkp->bi_inode) {
    135  1.1  mycroft 			if (lastino != LFS_UNUSED_INUM) {
    136  1.1  mycroft 				/* Finish up last file */
    137  1.1  mycroft 				if (sp->fip->fi_nblocks == 0) {
    138  1.1  mycroft 					DEC_FINFO(sp);
    139  1.1  mycroft 					sp->sum_bytes_left +=
    140  1.1  mycroft 					    sizeof(FINFO) - sizeof(daddr_t);
    141  1.1  mycroft 				} else {
    142  1.1  mycroft 					lfs_updatemeta(sp);
    143  1.1  mycroft 					BUMP_FIP(sp);
    144  1.1  mycroft 				}
    145  1.1  mycroft 
    146  1.1  mycroft 				lfs_writeinode(fs, sp, ip);
    147  1.1  mycroft 				lfs_vunref(vp);
    148  1.1  mycroft 			}
    149  1.1  mycroft 
    150  1.1  mycroft 			/* Start a new file */
    151  1.1  mycroft 			CHECK_SEG(sizeof(FINFO));
    152  1.1  mycroft 			sp->sum_bytes_left -= sizeof(FINFO) - sizeof(daddr_t);
    153  1.1  mycroft 			INC_FINFO(sp);
    154  1.1  mycroft 			sp->start_lbp = &sp->fip->fi_blocks[0];
    155  1.1  mycroft 			sp->vp = NULL;
    156  1.1  mycroft 			sp->fip->fi_version = blkp->bi_version;
    157  1.1  mycroft 			sp->fip->fi_nblocks = 0;
    158  1.1  mycroft 			sp->fip->fi_ino = blkp->bi_inode;
    159  1.1  mycroft 			lastino = blkp->bi_inode;
    160  1.1  mycroft 			if (blkp->bi_inode == LFS_IFILE_INUM)
    161  1.1  mycroft 				v_daddr = fs->lfs_idaddr;
    162  1.1  mycroft 			else {
    163  1.1  mycroft 				LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
    164  1.1  mycroft 				v_daddr = ifp->if_daddr;
    165  1.1  mycroft 				brelse(bp);
    166  1.1  mycroft 			}
    167  1.1  mycroft 			if (v_daddr == LFS_UNUSED_DADDR)
    168  1.1  mycroft 				continue;
    169  1.1  mycroft 
    170  1.1  mycroft 			/* Get the vnode/inode. */
    171  1.1  mycroft 			if (lfs_fastvget(mntp, blkp->bi_inode, v_daddr, &vp,
    172  1.1  mycroft 			    blkp->bi_lbn == LFS_UNUSED_LBN ?
    173  1.1  mycroft 			    blkp->bi_bp : NULL)) {
    174  1.1  mycroft #ifdef DIAGNOSTIC
    175  1.1  mycroft 				printf("lfs_markv: VFS_VGET failed (%d)\n",
    176  1.1  mycroft 				    blkp->bi_inode);
    177  1.1  mycroft #endif
    178  1.1  mycroft 				lastino = LFS_UNUSED_INUM;
    179  1.1  mycroft 				v_daddr = LFS_UNUSED_DADDR;
    180  1.1  mycroft 				continue;
    181  1.1  mycroft 			}
    182  1.1  mycroft 			sp->vp = vp;
    183  1.1  mycroft 			ip = VTOI(vp);
    184  1.1  mycroft 		} else if (v_daddr == LFS_UNUSED_DADDR)
    185  1.1  mycroft 			continue;
    186  1.1  mycroft 
    187  1.1  mycroft 		/* If this BLOCK_INFO didn't contain a block, keep going. */
    188  1.1  mycroft 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
    189  1.1  mycroft 			continue;
    190  1.1  mycroft 		if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr, NULL) ||
    191  1.1  mycroft 		    b_daddr != blkp->bi_daddr)
    192  1.1  mycroft 			continue;
    193  1.1  mycroft 		/*
    194  1.1  mycroft 		 * If we got to here, then we are keeping the block.  If it
    195  1.1  mycroft 		 * is an indirect block, we want to actually put it in the
    196  1.1  mycroft 		 * buffer cache so that it can be updated in the finish_meta
    197  1.1  mycroft 		 * section.  If it's not, we need to allocate a fake buffer
    198  1.1  mycroft 		 * so that writeseg can perform the copyin and write the buffer.
    199  1.1  mycroft 		 */
    200  1.1  mycroft 		if (blkp->bi_lbn >= 0)	/* Data Block */
    201  1.1  mycroft 			bp = lfs_fakebuf(vp, blkp->bi_lbn, bsize,
    202  1.1  mycroft 			    blkp->bi_bp);
    203  1.1  mycroft 		else {
    204  1.1  mycroft 			bp = getblk(vp, blkp->bi_lbn, bsize, 0, 0);
    205  1.1  mycroft 			if (!(bp->b_flags & (B_DELWRI | B_DONE | B_CACHE)) &&
    206  1.1  mycroft 			    (error = copyin(blkp->bi_bp, bp->b_data,
    207  1.1  mycroft 			    bsize)))
    208  1.1  mycroft 				goto err2;
    209  1.1  mycroft 			if (error = VOP_BWRITE(bp))
    210  1.1  mycroft 				goto err2;
    211  1.1  mycroft 		}
    212  1.1  mycroft 		while (lfs_gatherblock(sp, bp, NULL));
    213  1.1  mycroft 	}
    214  1.1  mycroft 	if (sp->vp) {
    215  1.1  mycroft 		if (sp->fip->fi_nblocks == 0) {
    216  1.1  mycroft 			DEC_FINFO(sp);
    217  1.1  mycroft 			sp->sum_bytes_left +=
    218  1.1  mycroft 			    sizeof(FINFO) - sizeof(daddr_t);
    219  1.1  mycroft 		} else
    220  1.1  mycroft 			lfs_updatemeta(sp);
    221  1.1  mycroft 
    222  1.1  mycroft 		lfs_writeinode(fs, sp, ip);
    223  1.1  mycroft 		lfs_vunref(vp);
    224  1.1  mycroft 	}
    225  1.1  mycroft 	(void) lfs_writeseg(fs, sp);
    226  1.1  mycroft 	lfs_segunlock(fs);
    227  1.1  mycroft 	free(start, M_SEGMENT);
    228  1.1  mycroft 	return (error);
    229  1.1  mycroft 
    230  1.1  mycroft /*
    231  1.1  mycroft  * XXX
    232  1.1  mycroft  * If we come in to error 2, we might have indirect blocks that were
    233  1.1  mycroft  * updated and now have bad block pointers.  I don't know what to do
    234  1.1  mycroft  * about this.
    235  1.1  mycroft  */
    236  1.1  mycroft 
    237  1.1  mycroft err2:	lfs_vunref(vp);
    238  1.1  mycroft 	/* Free up fakebuffers */
    239  1.1  mycroft 	for (bpp = --sp->cbpp; bpp >= sp->bpp; --bpp)
    240  1.1  mycroft 		if ((*bpp)->b_flags & B_CALL) {
    241  1.1  mycroft 			brelvp(*bpp);
    242  1.1  mycroft 			free(*bpp, M_SEGMENT);
    243  1.1  mycroft 		} else
    244  1.1  mycroft 			brelse(*bpp);
    245  1.1  mycroft 	lfs_segunlock(fs);
    246  1.1  mycroft err1:
    247  1.1  mycroft 	free(start, M_SEGMENT);
    248  1.1  mycroft 	return (error);
    249  1.1  mycroft }
    250  1.1  mycroft 
    251  1.1  mycroft /*
    252  1.1  mycroft  * lfs_bmapv:
    253  1.1  mycroft  *
    254  1.1  mycroft  * This will fill in the current disk address for arrays of blocks.
    255  1.1  mycroft  *
    256  1.1  mycroft  *  0 on success
    257  1.1  mycroft  * -1/errno is return on error.
    258  1.1  mycroft  */
    259  1.1  mycroft struct lfs_bmapv_args {
    260  1.1  mycroft 	fsid_t *fsidp;		/* file system */
    261  1.1  mycroft 	BLOCK_INFO *blkiov;	/* block array */
    262  1.1  mycroft 	int blkcnt;		/* count of block array entries */
    263  1.1  mycroft };
    264  1.1  mycroft int
    265  1.1  mycroft lfs_bmapv(p, uap, retval)
    266  1.1  mycroft 	struct proc *p;
    267  1.1  mycroft 	struct lfs_bmapv_args *uap;
    268  1.1  mycroft 	int *retval;
    269  1.1  mycroft {
    270  1.1  mycroft 	BLOCK_INFO *blkp;
    271  1.1  mycroft 	struct mount *mntp;
    272  1.1  mycroft 	struct vnode *vp;
    273  1.1  mycroft 	fsid_t fsid;
    274  1.1  mycroft 	void *start;
    275  1.1  mycroft 	daddr_t daddr;
    276  1.1  mycroft 	int cnt, error, step;
    277  1.1  mycroft 
    278  1.1  mycroft 	if (error = suser(p->p_ucred, &p->p_acflag))
    279  1.1  mycroft 		return (error);
    280  1.1  mycroft 
    281  1.1  mycroft 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
    282  1.1  mycroft 		return (error);
    283  1.1  mycroft 	if ((mntp = getvfs(&fsid)) == NULL)
    284  1.1  mycroft 		return (EINVAL);
    285  1.1  mycroft 
    286  1.1  mycroft 	cnt = uap->blkcnt;
    287  1.1  mycroft 	start = blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
    288  1.1  mycroft 	if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) {
    289  1.1  mycroft 		free(blkp, M_SEGMENT);
    290  1.1  mycroft 		return (error);
    291  1.1  mycroft 	}
    292  1.1  mycroft 
    293  1.1  mycroft 	for (step = cnt; step--; ++blkp) {
    294  1.1  mycroft 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
    295  1.1  mycroft 			continue;
    296  1.1  mycroft 		/* Could be a deadlock ? */
    297  1.1  mycroft 		if (VFS_VGET(mntp, blkp->bi_inode, &vp))
    298  1.1  mycroft 			daddr = LFS_UNUSED_DADDR;
    299  1.1  mycroft 		else {
    300  1.1  mycroft 			if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL))
    301  1.1  mycroft 				daddr = LFS_UNUSED_DADDR;
    302  1.1  mycroft 			vput(vp);
    303  1.1  mycroft 		}
    304  1.1  mycroft 		blkp->bi_daddr = daddr;
    305  1.1  mycroft         }
    306  1.1  mycroft 	copyout(start, uap->blkiov, cnt * sizeof(BLOCK_INFO));
    307  1.1  mycroft 	free(start, M_SEGMENT);
    308  1.1  mycroft 	return (0);
    309  1.1  mycroft }
    310  1.1  mycroft 
    311  1.1  mycroft /*
    312  1.1  mycroft  * lfs_segclean:
    313  1.1  mycroft  *
    314  1.1  mycroft  * Mark the segment clean.
    315  1.1  mycroft  *
    316  1.1  mycroft  *  0 on success
    317  1.1  mycroft  * -1/errno is return on error.
    318  1.1  mycroft  */
    319  1.1  mycroft struct lfs_segclean_args {
    320  1.1  mycroft 	fsid_t *fsidp;		/* file system */
    321  1.1  mycroft 	u_long segment;		/* segment number */
    322  1.1  mycroft };
    323  1.1  mycroft int
    324  1.1  mycroft lfs_segclean(p, uap, retval)
    325  1.1  mycroft 	struct proc *p;
    326  1.1  mycroft 	struct lfs_segclean_args *uap;
    327  1.1  mycroft 	int *retval;
    328  1.1  mycroft {
    329  1.1  mycroft 	CLEANERINFO *cip;
    330  1.1  mycroft 	SEGUSE *sup;
    331  1.1  mycroft 	struct buf *bp;
    332  1.1  mycroft 	struct mount *mntp;
    333  1.1  mycroft 	struct lfs *fs;
    334  1.1  mycroft 	fsid_t fsid;
    335  1.1  mycroft 	int error;
    336  1.1  mycroft 
    337  1.1  mycroft 	if (error = suser(p->p_ucred, &p->p_acflag))
    338  1.1  mycroft 		return (error);
    339  1.1  mycroft 
    340  1.1  mycroft 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
    341  1.1  mycroft 		return (error);
    342  1.1  mycroft 	if ((mntp = getvfs(&fsid)) == NULL)
    343  1.1  mycroft 		return (EINVAL);
    344  1.1  mycroft 
    345  1.1  mycroft 	fs = VFSTOUFS(mntp)->um_lfs;
    346  1.1  mycroft 
    347  1.1  mycroft 	if (datosn(fs, fs->lfs_curseg) == uap->segment)
    348  1.1  mycroft 		return (EBUSY);
    349  1.1  mycroft 
    350  1.1  mycroft 	LFS_SEGENTRY(sup, fs, uap->segment, bp);
    351  1.1  mycroft 	if (sup->su_flags & SEGUSE_ACTIVE) {
    352  1.1  mycroft 		brelse(bp);
    353  1.1  mycroft 		return (EBUSY);
    354  1.1  mycroft 	}
    355  1.1  mycroft 	fs->lfs_avail += fsbtodb(fs, fs->lfs_ssize) - 1;
    356  1.1  mycroft 	fs->lfs_bfree += (sup->su_nsums * LFS_SUMMARY_SIZE / DEV_BSIZE) +
    357  1.1  mycroft 	    sup->su_ninos * btodb(fs->lfs_bsize);
    358  1.1  mycroft 	sup->su_flags &= ~SEGUSE_DIRTY;
    359  1.1  mycroft 	(void) VOP_BWRITE(bp);
    360  1.1  mycroft 
    361  1.1  mycroft 	LFS_CLEANERINFO(cip, fs, bp);
    362  1.1  mycroft 	++cip->clean;
    363  1.1  mycroft 	--cip->dirty;
    364  1.1  mycroft 	(void) VOP_BWRITE(bp);
    365  1.1  mycroft 	wakeup(&fs->lfs_avail);
    366  1.1  mycroft 	return (0);
    367  1.1  mycroft }
    368  1.1  mycroft 
    369  1.1  mycroft /*
    370  1.1  mycroft  * lfs_segwait:
    371  1.1  mycroft  *
    372  1.1  mycroft  * This will block until a segment in file system fsid is written.  A timeout
    373  1.1  mycroft  * in milliseconds may be specified which will awake the cleaner automatically.
    374  1.1  mycroft  * An fsid of -1 means any file system, and a timeout of 0 means forever.
    375  1.1  mycroft  *
    376  1.1  mycroft  *  0 on success
    377  1.1  mycroft  *  1 on timeout
    378  1.1  mycroft  * -1/errno is return on error.
    379  1.1  mycroft  */
    380  1.1  mycroft struct lfs_segwait_args {
    381  1.1  mycroft 	fsid_t *fsidp;		/* file system */
    382  1.1  mycroft 	struct timeval *tv;	/* timeout */
    383  1.1  mycroft };
    384  1.1  mycroft int
    385  1.1  mycroft lfs_segwait(p, uap, retval)
    386  1.1  mycroft 	struct proc *p;
    387  1.1  mycroft 	struct lfs_segwait_args *uap;
    388  1.1  mycroft 	int *retval;
    389  1.1  mycroft {
    390  1.1  mycroft 	extern int lfs_allclean_wakeup;
    391  1.1  mycroft 	struct mount *mntp;
    392  1.1  mycroft 	struct timeval atv;
    393  1.1  mycroft 	fsid_t fsid;
    394  1.1  mycroft 	void *addr;
    395  1.1  mycroft 	u_long timeout;
    396  1.1  mycroft 	int error, s;
    397  1.1  mycroft 
    398  1.1  mycroft 	if (error = suser(p->p_ucred, &p->p_acflag)) {
    399  1.1  mycroft 		return (error);
    400  1.1  mycroft }
    401  1.1  mycroft #ifdef WHEN_QUADS_WORK
    402  1.1  mycroft 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
    403  1.1  mycroft 		return (error);
    404  1.1  mycroft 	if (fsid == (fsid_t)-1)
    405  1.1  mycroft 		addr = &lfs_allclean_wakeup;
    406  1.1  mycroft 	else {
    407  1.1  mycroft 		if ((mntp = getvfs(&fsid)) == NULL)
    408  1.1  mycroft 			return (EINVAL);
    409  1.1  mycroft 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
    410  1.1  mycroft 	}
    411  1.1  mycroft #else
    412  1.1  mycroft 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
    413  1.1  mycroft 		return (error);
    414  1.1  mycroft 	if ((mntp = getvfs(&fsid)) == NULL)
    415  1.1  mycroft 		addr = &lfs_allclean_wakeup;
    416  1.1  mycroft 	else
    417  1.1  mycroft 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
    418  1.1  mycroft #endif
    419  1.1  mycroft 
    420  1.1  mycroft 	if (uap->tv) {
    421  1.1  mycroft 		if (error = copyin(uap->tv, &atv, sizeof(struct timeval)))
    422  1.1  mycroft 			return (error);
    423  1.1  mycroft 		if (itimerfix(&atv))
    424  1.1  mycroft 			return (EINVAL);
    425  1.1  mycroft 		s = splclock();
    426  1.1  mycroft 		timevaladd(&atv, (struct timeval *)&time);
    427  1.1  mycroft 		timeout = hzto(&atv);
    428  1.1  mycroft 		splx(s);
    429  1.1  mycroft 	} else
    430  1.1  mycroft 		timeout = 0;
    431  1.1  mycroft 
    432  1.1  mycroft 	error = tsleep(addr, PCATCH | PUSER, "segment", timeout);
    433  1.1  mycroft 	return (error == ERESTART ? EINTR : 0);
    434  1.1  mycroft }
    435  1.1  mycroft 
    436  1.1  mycroft /*
    437  1.1  mycroft  * VFS_VGET call specialized for the cleaner.  The cleaner already knows the
    438  1.1  mycroft  * daddr from the ifile, so don't look it up again.  If the cleaner is
    439  1.1  mycroft  * processing IINFO structures, it may have the ondisk inode already, so
    440  1.1  mycroft  * don't go retrieving it again.
    441  1.1  mycroft  */
    442  1.1  mycroft int
    443  1.1  mycroft lfs_fastvget(mp, ino, daddr, vpp, dinp)
    444  1.1  mycroft 	struct mount *mp;
    445  1.1  mycroft 	ino_t ino;
    446  1.1  mycroft 	daddr_t daddr;
    447  1.1  mycroft 	struct vnode **vpp;
    448  1.1  mycroft 	struct dinode *dinp;
    449  1.1  mycroft {
    450  1.1  mycroft 	register struct inode *ip;
    451  1.1  mycroft 	struct vnode *vp;
    452  1.1  mycroft 	struct ufsmount *ump;
    453  1.1  mycroft 	struct buf *bp;
    454  1.1  mycroft 	dev_t dev;
    455  1.1  mycroft 	int error;
    456  1.1  mycroft 
    457  1.1  mycroft 	ump = VFSTOUFS(mp);
    458  1.1  mycroft 	dev = ump->um_dev;
    459  1.1  mycroft 	/*
    460  1.1  mycroft 	 * This is playing fast and loose.  Someone may have the inode
    461  1.1  mycroft 	 * locked, in which case they are going to be distinctly unhappy
    462  1.1  mycroft 	 * if we trash something.
    463  1.1  mycroft 	 */
    464  1.1  mycroft 	if ((*vpp = ufs_ihashlookup(dev, ino)) != NULL) {
    465  1.1  mycroft 		lfs_vref(*vpp);
    466  1.1  mycroft 		if ((*vpp)->v_flag & VXLOCK)
    467  1.1  mycroft 			printf ("Cleaned vnode VXLOCKED\n");
    468  1.1  mycroft 		ip = VTOI(*vpp);
    469  1.2  mycroft 		if (ip->i_flag & IN_LOCKED)
    470  1.1  mycroft 			printf("cleaned vnode locked\n");
    471  1.1  mycroft 		if (!(ip->i_flag & IN_MODIFIED)) {
    472  1.1  mycroft 			++ump->um_lfs->lfs_uinodes;
    473  1.1  mycroft 			ip->i_flag |= IN_MODIFIED;
    474  1.1  mycroft 		}
    475  1.1  mycroft 		ip->i_flag |= IN_MODIFIED;
    476  1.1  mycroft 		return (0);
    477  1.1  mycroft 	}
    478  1.1  mycroft 
    479  1.1  mycroft 	/* Allocate new vnode/inode. */
    480  1.1  mycroft 	if (error = lfs_vcreate(mp, ino, &vp)) {
    481  1.1  mycroft 		*vpp = NULL;
    482  1.1  mycroft 		return (error);
    483  1.1  mycroft 	}
    484  1.1  mycroft 
    485  1.1  mycroft 	/*
    486  1.1  mycroft 	 * Put it onto its hash chain and lock it so that other requests for
    487  1.1  mycroft 	 * this inode will block if they arrive while we are sleeping waiting
    488  1.1  mycroft 	 * for old data structures to be purged or for the contents of the
    489  1.1  mycroft 	 * disk portion of this inode to be read.
    490  1.1  mycroft 	 */
    491  1.1  mycroft 	ip = VTOI(vp);
    492  1.1  mycroft 	ufs_ihashins(ip);
    493  1.1  mycroft 
    494  1.1  mycroft 	/*
    495  1.1  mycroft 	 * XXX
    496  1.1  mycroft 	 * This may not need to be here, logically it should go down with
    497  1.1  mycroft 	 * the i_devvp initialization.
    498  1.1  mycroft 	 * Ask Kirk.
    499  1.1  mycroft 	 */
    500  1.1  mycroft 	ip->i_lfs = ump->um_lfs;
    501  1.1  mycroft 
    502  1.1  mycroft 	/* Read in the disk contents for the inode, copy into the inode. */
    503  1.1  mycroft 	if (dinp)
    504  1.1  mycroft 		if (error = copyin(dinp, &ip->i_din, sizeof(struct dinode)))
    505  1.1  mycroft 			return (error);
    506  1.1  mycroft 	else {
    507  1.1  mycroft 		if (error = bread(ump->um_devvp, daddr,
    508  1.1  mycroft 		    (int)ump->um_lfs->lfs_bsize, NOCRED, &bp)) {
    509  1.1  mycroft 			/*
    510  1.1  mycroft 			 * The inode does not contain anything useful, so it
    511  1.1  mycroft 			 * would be misleading to leave it on its hash chain.
    512  1.1  mycroft 			 * Iput() will return it to the free list.
    513  1.1  mycroft 			 */
    514  1.1  mycroft 			ufs_ihashrem(ip);
    515  1.1  mycroft 
    516  1.1  mycroft 			/* Unlock and discard unneeded inode. */
    517  1.1  mycroft 			lfs_vunref(vp);
    518  1.1  mycroft 			brelse(bp);
    519  1.1  mycroft 			*vpp = NULL;
    520  1.1  mycroft 			return (error);
    521  1.1  mycroft 		}
    522  1.1  mycroft 		ip->i_din =
    523  1.1  mycroft 		    *lfs_ifind(ump->um_lfs, ino, (struct dinode *)bp->b_data);
    524  1.1  mycroft 		brelse(bp);
    525  1.1  mycroft 	}
    526  1.1  mycroft 
    527  1.1  mycroft 	/* Inode was just read from user space or disk, make sure it's locked */
    528  1.1  mycroft 	ip->i_flag |= IN_LOCKED;
    529  1.1  mycroft 
    530  1.1  mycroft 	/*
    531  1.1  mycroft 	 * Initialize the vnode from the inode, check for aliases.  In all
    532  1.1  mycroft 	 * cases re-init ip, the underlying vnode/inode may have changed.
    533  1.1  mycroft 	 */
    534  1.1  mycroft 	if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) {
    535  1.1  mycroft 		lfs_vunref(vp);
    536  1.1  mycroft 		*vpp = NULL;
    537  1.1  mycroft 		return (error);
    538  1.1  mycroft 	}
    539  1.1  mycroft 	/*
    540  1.1  mycroft 	 * Finish inode initialization now that aliasing has been resolved.
    541  1.1  mycroft 	 */
    542  1.1  mycroft 	ip->i_devvp = ump->um_devvp;
    543  1.1  mycroft 	ip->i_flag |= IN_MODIFIED;
    544  1.1  mycroft 	++ump->um_lfs->lfs_uinodes;
    545  1.1  mycroft 	VREF(ip->i_devvp);
    546  1.1  mycroft 	*vpp = vp;
    547  1.1  mycroft 	return (0);
    548  1.1  mycroft }
    549  1.1  mycroft struct buf *
    550  1.1  mycroft lfs_fakebuf(vp, lbn, size, uaddr)
    551  1.1  mycroft 	struct vnode *vp;
    552  1.1  mycroft 	int lbn;
    553  1.1  mycroft 	size_t size;
    554  1.1  mycroft 	caddr_t uaddr;
    555  1.1  mycroft {
    556  1.1  mycroft 	struct buf *bp;
    557  1.1  mycroft 
    558  1.1  mycroft 	bp = lfs_newbuf(vp, lbn, 0);
    559  1.1  mycroft 	bp->b_saveaddr = uaddr;
    560  1.1  mycroft 	bp->b_bufsize = size;
    561  1.1  mycroft 	bp->b_bcount = size;
    562  1.1  mycroft 	bp->b_flags |= B_INVAL;
    563  1.1  mycroft 	return (bp);
    564  1.1  mycroft }
    565