123396Smckusick /* 251494Sbostic * Copyright (c) 1989, 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*56160Smargo * @(#)lfs_balloc.c 7.37 (Berkeley) 09/02/92 823396Smckusick */ 97443Sroot 1051486Sbostic #include <sys/param.h> 1151486Sbostic #include <sys/buf.h> 1251486Sbostic #include <sys/proc.h> 1351486Sbostic #include <sys/vnode.h> 1451486Sbostic #include <sys/mount.h> 1551486Sbostic #include <sys/resourcevar.h> 1651486Sbostic #include <sys/trace.h> 177443Sroot 1855048Smckusick #include <miscfs/specfs/specdev.h> 1955048Smckusick 2051494Sbostic #include <ufs/ufs/quota.h> 2151494Sbostic #include <ufs/ufs/inode.h> 2251494Sbostic #include <ufs/ufs/ufsmount.h> 2347571Skarels 2451494Sbostic #include <ufs/lfs/lfs.h> 2551494Sbostic #include <ufs/lfs/lfs_extern.h> 2651486Sbostic 2751962Sbostic int lfs_getlbns __P((struct vnode *, daddr_t, INDIR *, int *)); 2851855Sbostic 297443Sroot /* 3051486Sbostic * Bmap converts a the logical block number of a file to its physical block 3151486Sbostic * number on the disk. The conversion is done by using the logical block 3251486Sbostic * number to index into the array of block pointers described by the dinode. 3351855Sbostic */ 3451855Sbostic int 3554687Sbostic lfs_bmap(ap) 3654687Sbostic struct vop_bmap_args /* { 3754687Sbostic struct vnode *a_vp; 3854687Sbostic daddr_t a_bn; 3954687Sbostic struct vnode **a_vpp; 4054687Sbostic daddr_t *a_bnp; 4154687Sbostic } */ *ap; 4251855Sbostic { 4351855Sbostic /* 4451855Sbostic * Check for underlying vnode requests and ensure that logical 4551855Sbostic * to physical mapping is requested. 4651855Sbostic */ 4753591Sheideman if (ap->a_vpp != NULL) 4853591Sheideman *ap->a_vpp = VTOI(ap->a_vp)->i_devvp; 4953591Sheideman if (ap->a_bnp == NULL) 5051855Sbostic return (0); 5151855Sbostic 5253591Sheideman return (lfs_bmaparray(ap->a_vp, ap->a_bn, ap->a_bnp, NULL, NULL)); 5351855Sbostic } 5451855Sbostic 5551855Sbostic /* 5651846Sbostic * LFS has a different version of bmap from FFS because of a naming conflict. 5751846Sbostic * In FFS, meta blocks are given real disk addresses at allocation time, and 5851846Sbostic * are linked into the device vnode, using a logical block number which is 5951846Sbostic * the same as the physical block number. This can't be done by LFS because 6051846Sbostic * blocks aren't given disk addresses until they're written, so there's no 6151846Sbostic * way to distinguish the meta-data blocks for one file from any other file. 6251846Sbostic * This means that meta-data blocks have to be on the vnode for the file so 6351846Sbostic * they can be found, and have to have "names" different from the standard 6451846Sbostic * data blocks. To do this, we divide the name space into positive and 6551846Sbostic * negative block numbers, and give the meta-data blocks negative logical 6651847Sbostic * numbers. Indirect blocks are addressed by the negative address of the 6751847Sbostic * first data block to which they point. Double indirect blocks are addressed 6851847Sbostic * by one less than the address of the first indirect block to which they 6951847Sbostic * point. Triple indirect blocks are addressed by one less than the address 7051847Sbostic * of the first double indirect block to which they point. 717443Sroot */ 7251348Sroot int 7351855Sbostic lfs_bmaparray(vp, bn, bnp, ap, nump) 7451561Smckusick struct vnode *vp; 7537736Smckusick register daddr_t bn; 7651561Smckusick daddr_t *bnp; 7751855Sbostic INDIR *ap; 7851855Sbostic int *nump; 797443Sroot { 8051561Smckusick register struct inode *ip; 8151846Sbostic struct buf *bp; 8251855Sbostic struct lfs *fs; 8351561Smckusick struct vnode *devvp; 8451855Sbostic INDIR a[NIADDR], *xap; 8551855Sbostic daddr_t *bap, daddr; 8651855Sbostic long metalbn; 87*56160Smargo int bb, error, num, off; 8854687Sbostic struct vop_strategy_args vop_strategy_a; 8937736Smckusick 9051561Smckusick ip = VTOI(vp); 9151855Sbostic #ifdef DIAGNOSTIC 9251855Sbostic if (ap != NULL && nump == NULL || ap == NULL && nump != NULL) 9351855Sbostic panic("lfs_bmaparray: invalid arguments"); 9451855Sbostic #endif 9551847Sbostic 9651855Sbostic xap = ap == NULL ? a : ap; 9755457Sbostic if (!nump) 9855457Sbostic nump = # 9951855Sbostic if (error = lfs_getlbns(vp, bn, xap, nump)) 10051855Sbostic return (error); 10151855Sbostic 10251855Sbostic num = *nump; 10351855Sbostic if (num == 0) { 10451855Sbostic *bnp = ip->i_db[bn]; 10551855Sbostic if (*bnp == 0) 10651348Sroot *bnp = UNASSIGNED; 10737736Smckusick return (0); 10837736Smckusick } 10951486Sbostic 11052994Sbostic 11152994Sbostic /* Get disk address out of indirect block array */ 11252994Sbostic daddr = ip->i_ib[xap->in_off]; 11352994Sbostic 11451855Sbostic /* Fetch through the indirect blocks. */ 11552994Sbostic fs = ip->i_lfs; 11651183Sbostic devvp = VFSTOUFS(vp->v_mount)->um_devvp; 11752994Sbostic 11855942Sbostic for (bp = NULL, ++xap; --num; ++xap) { 11955942Sbostic /* 12055942Sbostic * If we were called explicitly then we don't want to create 12155942Sbostic * indirect blocks. Since BMAP calls pass NULL for the ap, 12255942Sbostic * we can use that to detect if we are called from BMAP or not. 12355942Sbostic */ 12455942Sbostic if (daddr == 0 && ap != NULL) 12555942Sbostic break; 12655942Sbostic 12752994Sbostic /* If looking for a meta-block, break out when we find it. */ 12851855Sbostic metalbn = xap->in_lbn; 12951855Sbostic if (metalbn == bn) 13051847Sbostic break; 13151847Sbostic 13251846Sbostic /* 13351846Sbostic * Read in the appropriate indirect block. LFS can't do a 13451846Sbostic * bread because bread knows that FFS will hand it the device 13551846Sbostic * vnode, not the file vnode, so the b_dev and b_blkno would 13651846Sbostic * be wrong. 13751846Sbostic * 13851846Sbostic * XXX 13951846Sbostic * This REALLY needs to be fixed, at the very least it needs 14051855Sbostic * to be rethought when the buffer cache goes away. When it's 14151855Sbostic * fixed, change lfs_bmaparray and lfs_getlbns to take an ip, 14251855Sbostic * not a vp. 14351846Sbostic */ 14451183Sbostic if (bp) 14537736Smckusick brelse(bp); 14651847Sbostic bp = getblk(vp, metalbn, fs->lfs_bsize); 14751183Sbostic if (bp->b_flags & (B_DONE | B_DELWRI)) { 14851847Sbostic trace(TR_BREADHIT, pack(vp, size), metalbn); 14955942Sbostic } else if (!daddr) { 15055942Sbostic /* Need to create an indirect block */ 15155942Sbostic trace(TR_BREADMISS, pack(vp, size), metalbn); 15255942Sbostic bzero(bp->b_un.b_addr, fs->lfs_bsize); 15355942Sbostic *bnp = UNASSIGNED; 154*56160Smargo bb = fsbtodb(fs, 1); 155*56160Smargo /* XXX Need to figure out how to get a cred */ 156*56160Smargo if (!ISSPACE_XXX(fs, bb)) { 157*56160Smargo bp->b_flags |= B_INVAL; 158*56160Smargo brelse (bp); 159*56160Smargo return (ENOSPC); 160*56160Smargo } 161*56160Smargo ip->i_blocks += bb; 162*56160Smargo fs->lfs_bfree -= bb; 16355942Sbostic daddr = bp->b_un.b_daddr[xap->in_off]; 16455942Sbostic if (error = VOP_BWRITE(bp)) 16555942Sbostic return (error); 16655942Sbostic bp = NULL; 16755942Sbostic continue; 16851183Sbostic } else { 16951847Sbostic trace(TR_BREADMISS, pack(vp, size), metalbn); 17051847Sbostic bp->b_blkno = daddr; 17151846Sbostic bp->b_flags |= B_READ; 17251183Sbostic bp->b_dev = devvp->v_rdev; 17353574Sheideman /* 17453574Sheideman * Call a strategy VOP by hand. 17553574Sheideman */ 17653574Sheideman vop_strategy_a.a_desc = VDESC(vop_strategy); 17753574Sheideman vop_strategy_a.a_bp=bp; 17853574Sheideman VOCALL(devvp->v_op, VOFFSET(vop_strategy), \ 17953574Sheideman &vop_strategy_a); 18051183Sbostic curproc->p_stats->p_ru.ru_inblock++; /* XXX */ 18151183Sbostic if (error = biowait(bp)) { 18251183Sbostic brelse(bp); 18351183Sbostic return (error); 18451183Sbostic } 18537736Smckusick } 18652994Sbostic daddr = bp->b_un.b_daddr[xap->in_off]; 18751183Sbostic } 18851183Sbostic if (bp) 18939679Smckusick brelse(bp); 19051183Sbostic 19152994Sbostic *bnp = daddr == 0 ? UNASSIGNED : daddr; 19237736Smckusick return (0); 19337736Smckusick } 19451855Sbostic 19551855Sbostic /* 19651855Sbostic * Create an array of logical block number/offset pairs which represent the 19751855Sbostic * path of indirect blocks required to access a data block. The first "pair" 19851855Sbostic * contains the logical block number of the appropriate single, double or 19951855Sbostic * triple indirect block and the offset into the inode indirect block array. 20051855Sbostic * Note, the logical block number of the inode single/double/triple indirect 20151855Sbostic * block appears twice in the array, once with the offset into the i_ib and 20251855Sbostic * once with the offset into the page itself. 20351855Sbostic */ 20451855Sbostic int 20551855Sbostic lfs_getlbns(vp, bn, ap, nump) 20651855Sbostic struct vnode *vp; 20751855Sbostic register daddr_t bn; 20851855Sbostic INDIR *ap; 20951855Sbostic int *nump; 21051855Sbostic { 21151855Sbostic struct lfs *fs; 21251855Sbostic long metalbn, realbn; 21354687Sbostic int j, numlevels, off, sh; 21451855Sbostic 21554687Sbostic if (nump) 21654687Sbostic *nump = 0; 21754687Sbostic numlevels = 0; 21851855Sbostic realbn = bn; 21951855Sbostic if ((long)bn < 0) 22051855Sbostic bn = -(long)bn; 22151855Sbostic 22251855Sbostic /* The first NDADDR blocks are direct blocks. */ 22351855Sbostic if (bn < NDADDR) 22452994Sbostic return (0); 22551855Sbostic 22651855Sbostic /* 22751855Sbostic * Determine the number of levels of indirection. After this loop 22851855Sbostic * is done, sh indicates the number of data blocks possible at the 22951855Sbostic * given level of indirection, and NIADDR - j is the number of levels 23051855Sbostic * of indirection needed to locate the requested block. 23151855Sbostic */ 23251855Sbostic bn -= NDADDR; 23351855Sbostic fs = VTOI(vp)->i_lfs; 23451855Sbostic sh = 1; 23551855Sbostic for (j = NIADDR; j > 0; j--) { 23651855Sbostic sh *= NINDIR(fs); 23751855Sbostic if (bn < sh) 23851855Sbostic break; 23951855Sbostic bn -= sh; 24051855Sbostic } 24151855Sbostic if (j == 0) 24251855Sbostic return (EFBIG); 24351855Sbostic 24451855Sbostic /* Calculate the address of the first meta-block. */ 24551855Sbostic if (realbn >= 0) 24651855Sbostic metalbn = -(realbn - bn + NIADDR - j); 24751855Sbostic else 24851855Sbostic metalbn = -(-realbn - bn + NIADDR - j); 24951855Sbostic 25051855Sbostic /* 25151855Sbostic * At each iteration, off is the offset into the bap array which is 25251855Sbostic * an array of disk addresses at the current level of indirection. 25351855Sbostic * The logical block number and the offset in that block are stored 25451855Sbostic * into the argument array. 25551855Sbostic */ 25654687Sbostic ++numlevels; 25751855Sbostic ap->in_lbn = metalbn; 25851855Sbostic ap->in_off = off = NIADDR - j; 25951855Sbostic ap++; 26051855Sbostic for (; j <= NIADDR; j++) { 26151855Sbostic /* If searching for a meta-data block, quit when found. */ 26251855Sbostic if (metalbn == realbn) 26351855Sbostic break; 26451855Sbostic 26551855Sbostic sh /= NINDIR(fs); 26651855Sbostic off = (bn / sh) % NINDIR(fs); 26751855Sbostic 26854687Sbostic ++numlevels; 26951855Sbostic ap->in_lbn = metalbn; 27051855Sbostic ap->in_off = off; 27151855Sbostic ++ap; 27251855Sbostic 27351855Sbostic metalbn -= -1 + off * sh; 27451855Sbostic } 27554687Sbostic if (nump) 27654687Sbostic *nump = numlevels; 27751855Sbostic return (0); 27851855Sbostic } 27952082Sbostic 28052082Sbostic int 28152082Sbostic lfs_balloc(vp, iosize, lbn, bpp) 28252082Sbostic struct vnode *vp; 28352082Sbostic u_long iosize; 28452082Sbostic daddr_t lbn; 28552082Sbostic struct buf **bpp; 28652082Sbostic { 28752082Sbostic struct buf *bp; 28852082Sbostic struct inode *ip; 28952082Sbostic struct lfs *fs; 29052082Sbostic daddr_t daddr; 291*56160Smargo int bb, error; 29252082Sbostic 29352082Sbostic ip = VTOI(vp); 29452082Sbostic fs = ip->i_lfs; 29552082Sbostic 29652082Sbostic /* 29752082Sbostic * Three cases: it's a block beyond the end of file, it's a block in 29852082Sbostic * the file that may or may not have been assigned a disk address or 29952082Sbostic * we're writing an entire block. Note, if the daddr is unassigned, 30052082Sbostic * the block might still have existed in the cache. If it did, make 30152082Sbostic * sure we don't count it as a new block or zero out its contents. 30255942Sbostic * Note that we always call bmap, even if it's a new block beyond 30355942Sbostic * the end of file. The reason is so that we can allocate any new 30455942Sbostic * indirect blocks that are necessary. 30552082Sbostic */ 30655942Sbostic 30755942Sbostic *bpp = NULL; 30855942Sbostic if (error = VOP_BMAP(vp, lbn, NULL, &daddr)) 30952994Sbostic return (error); 31052082Sbostic 31155942Sbostic if (daddr == UNASSIGNED || iosize == fs->lfs_bsize) { 31252082Sbostic *bpp = bp = getblk(vp, lbn, fs->lfs_bsize); 31355942Sbostic if (daddr == UNASSIGNED && !(bp->b_flags & B_CACHE)) { 314*56160Smargo bb = fsbtodb(fs, 1); 315*56160Smargo if (!ISSPACE_XXX(fs, bb)) { 316*56160Smargo bp->b_flags |= B_INVAL; 317*56160Smargo *bpp = NULL; 318*56160Smargo brelse(bp); 319*56160Smargo return (ENOSPC); 320*56160Smargo } 321*56160Smargo ip->i_blocks += bb; 322*56160Smargo fs->lfs_bfree -= bb; 32352082Sbostic if (iosize != fs->lfs_bsize) 32452082Sbostic clrbuf(bp); 32552082Sbostic } 32652994Sbostic return (0); 32752082Sbostic } 32852994Sbostic return (bread(vp, lbn, fs->lfs_bsize, NOCRED, bpp)); 32952082Sbostic } 330