1*51882Sbostic /*- 2*51882Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*51882Sbostic * All rights reserved. 4*51882Sbostic * 5*51882Sbostic * %sccs.include.redist.c% 6*51882Sbostic * 7*51882Sbostic * @(#)lfs_syscalls.c 7.1 (Berkeley) 12/11/91 8*51882Sbostic */ 9*51882Sbostic 10*51882Sbostic #include <sys/param.h> 11*51882Sbostic #include <sys/proc.h> 12*51882Sbostic #include <sys/buf.h> 13*51882Sbostic #include <sys/mount.h> 14*51882Sbostic #include <sys/vnode.h> 15*51882Sbostic #include <sys/malloc.h> 16*51882Sbostic #include <sys/kernel.h> 17*51882Sbostic 18*51882Sbostic #include <ufs/ufs/quota.h> 19*51882Sbostic #include <ufs/ufs/inode.h> 20*51882Sbostic #include <ufs/ufs/ufsmount.h> 21*51882Sbostic 22*51882Sbostic #include <ufs/lfs/lfs.h> 23*51882Sbostic #include <ufs/lfs/lfs_extern.h> 24*51882Sbostic 25*51882Sbostic /* 26*51882Sbostic * lfs_markv: 27*51882Sbostic * 28*51882Sbostic * This will mark inodes and blocks dirty, so they are written into the log. 29*51882Sbostic * It will block until all the blocks have been written. The segment create 30*51882Sbostic * time passed in the block_info and inode_info structures is used to decide 31*51882Sbostic * if the data is valid for each block (in case some process dirtied a block 32*51882Sbostic * or inode that is being cleaned between the determination that a block is 33*51882Sbostic * live and the lfs_markv call). 34*51882Sbostic * 35*51882Sbostic * 0 on success 36*51882Sbostic * -1/errno is return on error. 37*51882Sbostic */ 38*51882Sbostic int 39*51882Sbostic lfs_markv(p, uap, retval) 40*51882Sbostic struct proc *p; 41*51882Sbostic struct args { 42*51882Sbostic fsid_t fsid; /* file system */ 43*51882Sbostic BLOCK_INFO *blkiov; /* block array */ 44*51882Sbostic int blkcnt; /* count of block array entries */ 45*51882Sbostic INODE_INFO *inoiov; /* inode array */ 46*51882Sbostic int inocnt; /* count of inode array entries */ 47*51882Sbostic } *uap; 48*51882Sbostic int *retval; 49*51882Sbostic { 50*51882Sbostic BLOCK_INFO *blkp; 51*51882Sbostic IFILE *ifp; 52*51882Sbostic INODE_INFO *inop; 53*51882Sbostic struct buf *bp; 54*51882Sbostic struct lfs *fs; 55*51882Sbostic struct mount *mntp; 56*51882Sbostic struct vnode *vp; 57*51882Sbostic daddr_t daddr; 58*51882Sbostic u_long bsize; 59*51882Sbostic int cnt, error; 60*51882Sbostic 61*51882Sbostic if (error = suser(p->p_ucred, &p->p_acflag)) 62*51882Sbostic return (error); 63*51882Sbostic 64*51882Sbostic if ((mntp = getvfs(&uap->fsid)) == NULL) 65*51882Sbostic return (EINVAL); 66*51882Sbostic 67*51882Sbostic cnt = uap->blkcnt; 68*51882Sbostic blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); 69*51882Sbostic if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) { 70*51882Sbostic free(blkp, M_SEGMENT); 71*51882Sbostic return (error); 72*51882Sbostic } 73*51882Sbostic 74*51882Sbostic /* 75*51882Sbostic * Mark blocks/inodes dirty. For blocks, we get the vnode, and check 76*51882Sbostic * to see if the modified or disk address is newer than the cleaner 77*51882Sbostic * thinks. If so, we're done. Otherwise, we get the block, from core 78*51882Sbostic * if we have it, otherwise from the cleaner, and write it. Note that 79*51882Sbostic * errors are mostly ignored. If we can't get the info, the block is 80*51882Sbostic * probably not all that useful, and hopefully subsequent calls from 81*51882Sbostic * the cleaner will fix everything. 82*51882Sbostic */ 83*51882Sbostic bsize = VFSTOUFS(mntp)->um_lfs->lfs_bsize; 84*51882Sbostic for (; cnt--; ++blkp) { 85*51882Sbostic if (lfs_vget(mntp, blkp->bi_inode, &vp) || 86*51882Sbostic VTOI(vp)->i_mtime >= blkp->bi_segcreate || 87*51882Sbostic lfs_bmap(vp, blkp->bi_lbn, NULL, &daddr) || 88*51882Sbostic daddr != blkp->bi_daddr) 89*51882Sbostic continue; 90*51882Sbostic bp = getblk(vp, blkp->bi_lbn, bsize); 91*51882Sbostic if (!(bp->b_flags & B_CACHE) && 92*51882Sbostic (error = copyin(blkp->bi_bp, bp->b_un.b_daddr, bsize))) { 93*51882Sbostic brelse(bp); 94*51882Sbostic free(blkp, M_SEGMENT); 95*51882Sbostic return (error); 96*51882Sbostic } 97*51882Sbostic lfs_bwrite(bp); 98*51882Sbostic brelse(bp); 99*51882Sbostic } 100*51882Sbostic free(blkp, M_SEGMENT); 101*51882Sbostic 102*51882Sbostic cnt = uap->inocnt; 103*51882Sbostic inop = malloc(cnt * sizeof(INODE_INFO), M_SEGMENT, M_WAITOK); 104*51882Sbostic if (error = copyin(uap->inoiov, inop, cnt * sizeof(INODE_INFO))) { 105*51882Sbostic free(inop, M_SEGMENT); 106*51882Sbostic return (error); 107*51882Sbostic } 108*51882Sbostic 109*51882Sbostic fs = VFSTOUFS(mntp)->um_lfs; 110*51882Sbostic for (; cnt--; ++inop) { 111*51882Sbostic LFS_IENTRY(ifp, fs, inop->ii_inode, bp); 112*51882Sbostic daddr = ifp->if_daddr; 113*51882Sbostic brelse(bp); 114*51882Sbostic if (daddr != inop->ii_daddr) 115*51882Sbostic continue; 116*51882Sbostic /* 117*51882Sbostic * XXX 118*51882Sbostic * This is grossly inefficient since the cleaner just handed 119*51882Sbostic * us a copy of the inode and we're going to have to seek 120*51882Sbostic * to get our own. The fix requires creating a version of 121*51882Sbostic * lfs_vget that takes the copy and uses it instead of reading 122*51882Sbostic * from disk, if it's not already in the cache. 123*51882Sbostic */ 124*51882Sbostic if (!lfs_vget(mntp, inop->ii_inode, &vp)) 125*51882Sbostic VTOI(vp)->i_flag |= IMOD; 126*51882Sbostic } 127*51882Sbostic free(inop, M_SEGMENT); 128*51882Sbostic return (lfs_segwrite(mntp, 1)); 129*51882Sbostic } 130*51882Sbostic 131*51882Sbostic /* 132*51882Sbostic * lfs_bmapv: 133*51882Sbostic * 134*51882Sbostic * This will fill in the current disk address for arrays of inodes and blocks. 135*51882Sbostic * 136*51882Sbostic * 0 on success 137*51882Sbostic * -1/errno is return on error. 138*51882Sbostic */ 139*51882Sbostic int 140*51882Sbostic lfs_bmapv(p, uap, retval) 141*51882Sbostic struct proc *p; 142*51882Sbostic struct args { 143*51882Sbostic fsid_t fsid; /* file system */ 144*51882Sbostic BLOCK_INFO *blkiov; /* block array */ 145*51882Sbostic int blkcnt; /* count of block array entries */ 146*51882Sbostic } *uap; 147*51882Sbostic int *retval; 148*51882Sbostic { 149*51882Sbostic BLOCK_INFO *blkp; 150*51882Sbostic struct mount *mntp; 151*51882Sbostic struct vnode *vp; 152*51882Sbostic daddr_t daddr; 153*51882Sbostic int cnt, error; 154*51882Sbostic 155*51882Sbostic if (error = suser(p->p_ucred, &p->p_acflag)) 156*51882Sbostic return (error); 157*51882Sbostic 158*51882Sbostic if ((mntp = getvfs(&uap->fsid)) == NULL) 159*51882Sbostic return (EINVAL); 160*51882Sbostic 161*51882Sbostic cnt = uap->blkcnt; 162*51882Sbostic blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); 163*51882Sbostic if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) { 164*51882Sbostic free(blkp, M_SEGMENT); 165*51882Sbostic return (error); 166*51882Sbostic } 167*51882Sbostic 168*51882Sbostic for (; cnt--; ++blkp) 169*51882Sbostic blkp->bi_daddr = 170*51882Sbostic lfs_vget(mntp, blkp->bi_inode, &vp) || 171*51882Sbostic lfs_bmap(vp, blkp->bi_lbn, NULL, &daddr) ? 172*51882Sbostic LFS_UNUSED_DADDR : daddr; 173*51882Sbostic free(blkp, M_SEGMENT); 174*51882Sbostic return (0); 175*51882Sbostic } 176*51882Sbostic 177*51882Sbostic /* 178*51882Sbostic * lfs_segclean: 179*51882Sbostic * 180*51882Sbostic * Mark the segment clean. 181*51882Sbostic * 182*51882Sbostic * 0 on success 183*51882Sbostic * -1/errno is return on error. 184*51882Sbostic */ 185*51882Sbostic int 186*51882Sbostic lfs_segclean(p, uap, retval) 187*51882Sbostic struct proc *p; 188*51882Sbostic struct args { 189*51882Sbostic fsid_t fsid; /* file system */ 190*51882Sbostic u_long segment; /* segment number */ 191*51882Sbostic } *uap; 192*51882Sbostic int *retval; 193*51882Sbostic { 194*51882Sbostic SEGUSE *sup; 195*51882Sbostic struct buf *bp; 196*51882Sbostic struct mount *mntp; 197*51882Sbostic struct lfs *fs; 198*51882Sbostic int error; 199*51882Sbostic 200*51882Sbostic if (error = suser(p->p_ucred, &p->p_acflag)) 201*51882Sbostic return (error); 202*51882Sbostic 203*51882Sbostic if ((mntp = getvfs(&uap->fsid)) == NULL) 204*51882Sbostic return (EINVAL); 205*51882Sbostic 206*51882Sbostic fs = VFSTOUFS(mntp)->um_lfs; 207*51882Sbostic LFS_SEGENTRY(sup, fs, uap->segment, bp); 208*51882Sbostic sup->su_flags &= ~SEGUSE_DIRTY; 209*51882Sbostic brelse(bp); 210*51882Sbostic return (0); 211*51882Sbostic } 212*51882Sbostic 213*51882Sbostic /* 214*51882Sbostic * lfs_segwait: 215*51882Sbostic * 216*51882Sbostic * This will block until a segment in file system fsid is written. A timeout 217*51882Sbostic * in milliseconds may be specified which will awake the cleaner automatically. 218*51882Sbostic * An fsid of -1 means any file system, and a timeout of 0 means forever. 219*51882Sbostic * 220*51882Sbostic * 0 on success 221*51882Sbostic * 1 on timeout 222*51882Sbostic * -1/errno is return on error. 223*51882Sbostic */ 224*51882Sbostic int 225*51882Sbostic lfs_segwait(p, uap, retval) 226*51882Sbostic struct proc *p; 227*51882Sbostic struct args { 228*51882Sbostic fsid_t fsid; /* file system */ 229*51882Sbostic struct timeval *tv; /* timeout */ 230*51882Sbostic } *uap; 231*51882Sbostic int *retval; 232*51882Sbostic { 233*51882Sbostic extern int lfs_allclean_wakeup; 234*51882Sbostic struct mount *mntp; 235*51882Sbostic struct timeval atv; 236*51882Sbostic void *addr; 237*51882Sbostic u_long timeout; 238*51882Sbostic int error, s; 239*51882Sbostic 240*51882Sbostic if (error = suser(p->p_ucred, &p->p_acflag)) 241*51882Sbostic return (error); 242*51882Sbostic 243*51882Sbostic #ifdef WHEN_QUADS_WORK 244*51882Sbostic if (uap->fsid == (fsid_t)-1) 245*51882Sbostic addr = &lfs_allclean_wakeup; 246*51882Sbostic else { 247*51882Sbostic if ((mntp = getvfs(&uap->fsid)) == NULL) 248*51882Sbostic return (EINVAL); 249*51882Sbostic addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg; 250*51882Sbostic } 251*51882Sbostic #else 252*51882Sbostic if ((mntp = getvfs(&uap->fsid)) == NULL) 253*51882Sbostic addr = &lfs_allclean_wakeup; 254*51882Sbostic else 255*51882Sbostic addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg; 256*51882Sbostic #endif 257*51882Sbostic 258*51882Sbostic if (uap->tv) { 259*51882Sbostic if (error = copyin(uap->tv, &atv, sizeof(struct timeval))) 260*51882Sbostic return (error); 261*51882Sbostic if (itimerfix(&atv)) 262*51882Sbostic return (EINVAL); 263*51882Sbostic s = splhigh(); timevaladd(&atv, &time); splx(s); 264*51882Sbostic timeout = hzto(&atv); 265*51882Sbostic } else 266*51882Sbostic timeout = 0; 267*51882Sbostic 268*51882Sbostic error = tsleep(addr, PCATCH | PUSER, "segment", timeout); 269*51882Sbostic return (error == ERESTART ? EINTR : 0); 270*51882Sbostic } 271