123396Smckusick /* 251494Sbostic * Copyright (c) 1989, 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*55048Smckusick * @(#)lfs_balloc.c 7.32 (Berkeley) 07/12/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 18*55048Smckusick #include <miscfs/specfs/specdev.h> 19*55048Smckusick 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 #ifdef VERBOSE 4451855Sbostic printf("lfs_bmap\n"); 4551855Sbostic #endif 4651855Sbostic /* 4751855Sbostic * Check for underlying vnode requests and ensure that logical 4851855Sbostic * to physical mapping is requested. 4951855Sbostic */ 5053591Sheideman if (ap->a_vpp != NULL) 5153591Sheideman *ap->a_vpp = VTOI(ap->a_vp)->i_devvp; 5253591Sheideman if (ap->a_bnp == NULL) 5351855Sbostic return (0); 5451855Sbostic 5553591Sheideman return (lfs_bmaparray(ap->a_vp, ap->a_bn, ap->a_bnp, NULL, NULL)); 5651855Sbostic } 5751855Sbostic 5851855Sbostic /* 5951846Sbostic * LFS has a different version of bmap from FFS because of a naming conflict. 6051846Sbostic * In FFS, meta blocks are given real disk addresses at allocation time, and 6151846Sbostic * are linked into the device vnode, using a logical block number which is 6251846Sbostic * the same as the physical block number. This can't be done by LFS because 6351846Sbostic * blocks aren't given disk addresses until they're written, so there's no 6451846Sbostic * way to distinguish the meta-data blocks for one file from any other file. 6551846Sbostic * This means that meta-data blocks have to be on the vnode for the file so 6651846Sbostic * they can be found, and have to have "names" different from the standard 6751846Sbostic * data blocks. To do this, we divide the name space into positive and 6851846Sbostic * negative block numbers, and give the meta-data blocks negative logical 6951847Sbostic * numbers. Indirect blocks are addressed by the negative address of the 7051847Sbostic * first data block to which they point. Double indirect blocks are addressed 7151847Sbostic * by one less than the address of the first indirect block to which they 7251847Sbostic * point. Triple indirect blocks are addressed by one less than the address 7351847Sbostic * of the first double indirect block to which they point. 747443Sroot */ 7551348Sroot int 7651855Sbostic lfs_bmaparray(vp, bn, bnp, ap, nump) 7751561Smckusick struct vnode *vp; 7837736Smckusick register daddr_t bn; 7951561Smckusick daddr_t *bnp; 8051855Sbostic INDIR *ap; 8151855Sbostic int *nump; 827443Sroot { 8351561Smckusick register struct inode *ip; 8451846Sbostic struct buf *bp; 8551855Sbostic struct lfs *fs; 8651561Smckusick struct vnode *devvp; 8751855Sbostic INDIR a[NIADDR], *xap; 8851855Sbostic daddr_t *bap, daddr; 8951855Sbostic long metalbn; 9051855Sbostic int error, num, off; 9154687Sbostic struct vop_strategy_args vop_strategy_a; 9237736Smckusick 9351561Smckusick ip = VTOI(vp); 9451846Sbostic #ifdef VERBOSE 9551855Sbostic printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number); 9651846Sbostic #endif 9751855Sbostic #ifdef DIAGNOSTIC 9851855Sbostic if (ap != NULL && nump == NULL || ap == NULL && nump != NULL) 9951855Sbostic panic("lfs_bmaparray: invalid arguments"); 10051855Sbostic #endif 10151847Sbostic 10251855Sbostic xap = ap == NULL ? a : ap; 10351855Sbostic if (error = lfs_getlbns(vp, bn, xap, nump)) 10451855Sbostic return (error); 10551855Sbostic 10651855Sbostic num = *nump; 10752994Sbostic 10851855Sbostic if (num == 0) { 10951855Sbostic *bnp = ip->i_db[bn]; 11051855Sbostic if (*bnp == 0) 11151348Sroot *bnp = UNASSIGNED; 11237736Smckusick return (0); 11337736Smckusick } 11451486Sbostic 11552994Sbostic 11652994Sbostic /* Get disk address out of indirect block array */ 11752994Sbostic daddr = ip->i_ib[xap->in_off]; 11852994Sbostic 11951855Sbostic /* Fetch through the indirect blocks. */ 12052994Sbostic fs = ip->i_lfs; 12151183Sbostic devvp = VFSTOUFS(vp->v_mount)->um_devvp; 12252994Sbostic 12352994Sbostic for (bp = NULL, ++xap; daddr && --num; ++xap) { 12452994Sbostic /* If looking for a meta-block, break out when we find it. */ 12551855Sbostic metalbn = xap->in_lbn; 12651855Sbostic if (metalbn == bn) 12751847Sbostic break; 12851847Sbostic 12951846Sbostic /* 13051846Sbostic * Read in the appropriate indirect block. LFS can't do a 13151846Sbostic * bread because bread knows that FFS will hand it the device 13251846Sbostic * vnode, not the file vnode, so the b_dev and b_blkno would 13351846Sbostic * be wrong. 13451846Sbostic * 13551846Sbostic * XXX 13651846Sbostic * This REALLY needs to be fixed, at the very least it needs 13751855Sbostic * to be rethought when the buffer cache goes away. When it's 13851855Sbostic * fixed, change lfs_bmaparray and lfs_getlbns to take an ip, 13951855Sbostic * not a vp. 14051846Sbostic */ 14151183Sbostic if (bp) 14237736Smckusick brelse(bp); 14351847Sbostic bp = getblk(vp, metalbn, fs->lfs_bsize); 14451183Sbostic if (bp->b_flags & (B_DONE | B_DELWRI)) { 14551847Sbostic trace(TR_BREADHIT, pack(vp, size), metalbn); 14651183Sbostic } else { 14751847Sbostic trace(TR_BREADMISS, pack(vp, size), metalbn); 14851847Sbostic bp->b_blkno = daddr; 14951846Sbostic bp->b_flags |= B_READ; 15051183Sbostic bp->b_dev = devvp->v_rdev; 15153574Sheideman /* 15253574Sheideman * Call a strategy VOP by hand. 15353574Sheideman */ 15453574Sheideman vop_strategy_a.a_desc = VDESC(vop_strategy); 15553574Sheideman vop_strategy_a.a_bp=bp; 15653574Sheideman VOCALL(devvp->v_op, VOFFSET(vop_strategy), \ 15753574Sheideman &vop_strategy_a); 15851183Sbostic curproc->p_stats->p_ru.ru_inblock++; /* XXX */ 15951183Sbostic if (error = biowait(bp)) { 16051183Sbostic brelse(bp); 16151183Sbostic return (error); 16251183Sbostic } 16337736Smckusick } 16452994Sbostic daddr = bp->b_un.b_daddr[xap->in_off]; 16551183Sbostic } 16651183Sbostic if (bp) 16739679Smckusick brelse(bp); 16851183Sbostic 16952994Sbostic *bnp = daddr == 0 ? UNASSIGNED : daddr; 17037736Smckusick return (0); 17137736Smckusick } 17251855Sbostic 17351855Sbostic /* 17451855Sbostic * Create an array of logical block number/offset pairs which represent the 17551855Sbostic * path of indirect blocks required to access a data block. The first "pair" 17651855Sbostic * contains the logical block number of the appropriate single, double or 17751855Sbostic * triple indirect block and the offset into the inode indirect block array. 17851855Sbostic * Note, the logical block number of the inode single/double/triple indirect 17951855Sbostic * block appears twice in the array, once with the offset into the i_ib and 18051855Sbostic * once with the offset into the page itself. 18151855Sbostic */ 18251855Sbostic int 18351855Sbostic lfs_getlbns(vp, bn, ap, nump) 18451855Sbostic struct vnode *vp; 18551855Sbostic register daddr_t bn; 18651855Sbostic INDIR *ap; 18751855Sbostic int *nump; 18851855Sbostic { 18951855Sbostic struct lfs *fs; 19051855Sbostic long metalbn, realbn; 19154687Sbostic int j, numlevels, off, sh; 19251855Sbostic 19351855Sbostic #ifdef VERBOSE 19451855Sbostic printf("lfs_getlbns: bn %d, inode %d\n", bn, VTOI(vp)->i_number); 19551855Sbostic #endif 19654687Sbostic if (nump) 19754687Sbostic *nump = 0; 19854687Sbostic numlevels = 0; 19951855Sbostic realbn = bn; 20051855Sbostic if ((long)bn < 0) 20151855Sbostic bn = -(long)bn; 20251855Sbostic 20351855Sbostic /* The first NDADDR blocks are direct blocks. */ 20451855Sbostic if (bn < NDADDR) 20552994Sbostic return (0); 20651855Sbostic 20751855Sbostic /* 20851855Sbostic * Determine the number of levels of indirection. After this loop 20951855Sbostic * is done, sh indicates the number of data blocks possible at the 21051855Sbostic * given level of indirection, and NIADDR - j is the number of levels 21151855Sbostic * of indirection needed to locate the requested block. 21251855Sbostic */ 21351855Sbostic bn -= NDADDR; 21451855Sbostic fs = VTOI(vp)->i_lfs; 21551855Sbostic sh = 1; 21651855Sbostic for (j = NIADDR; j > 0; j--) { 21751855Sbostic sh *= NINDIR(fs); 21851855Sbostic if (bn < sh) 21951855Sbostic break; 22051855Sbostic bn -= sh; 22151855Sbostic } 22251855Sbostic if (j == 0) 22351855Sbostic return (EFBIG); 22451855Sbostic 22551855Sbostic /* Calculate the address of the first meta-block. */ 22651855Sbostic if (realbn >= 0) 22751855Sbostic metalbn = -(realbn - bn + NIADDR - j); 22851855Sbostic else 22951855Sbostic metalbn = -(-realbn - bn + NIADDR - j); 23051855Sbostic 23151855Sbostic /* 23251855Sbostic * At each iteration, off is the offset into the bap array which is 23351855Sbostic * an array of disk addresses at the current level of indirection. 23451855Sbostic * The logical block number and the offset in that block are stored 23551855Sbostic * into the argument array. 23651855Sbostic */ 23754687Sbostic ++numlevels; 23851855Sbostic ap->in_lbn = metalbn; 23951855Sbostic ap->in_off = off = NIADDR - j; 24051855Sbostic ap++; 24151855Sbostic for (; j <= NIADDR; j++) { 24251855Sbostic /* If searching for a meta-data block, quit when found. */ 24351855Sbostic if (metalbn == realbn) 24451855Sbostic break; 24551855Sbostic 24651855Sbostic sh /= NINDIR(fs); 24751855Sbostic off = (bn / sh) % NINDIR(fs); 24851855Sbostic 24954687Sbostic ++numlevels; 25051855Sbostic ap->in_lbn = metalbn; 25151855Sbostic ap->in_off = off; 25251855Sbostic ++ap; 25351855Sbostic 25451855Sbostic metalbn -= -1 + off * sh; 25551855Sbostic } 25654687Sbostic if (nump) 25754687Sbostic *nump = numlevels; 25851855Sbostic return (0); 25951855Sbostic } 26052082Sbostic 26152082Sbostic int 26252082Sbostic lfs_balloc(vp, iosize, lbn, bpp) 26352082Sbostic struct vnode *vp; 26452082Sbostic u_long iosize; 26552082Sbostic daddr_t lbn; 26652082Sbostic struct buf **bpp; 26752082Sbostic { 26852082Sbostic struct buf *bp; 26952082Sbostic struct inode *ip; 27052082Sbostic struct lfs *fs; 27152082Sbostic daddr_t daddr; 27252082Sbostic int error, newblock; 27352082Sbostic 27452082Sbostic ip = VTOI(vp); 27552082Sbostic fs = ip->i_lfs; 27652082Sbostic 27752082Sbostic /* 27852082Sbostic * Three cases: it's a block beyond the end of file, it's a block in 27952082Sbostic * the file that may or may not have been assigned a disk address or 28052082Sbostic * we're writing an entire block. Note, if the daddr is unassigned, 28152082Sbostic * the block might still have existed in the cache. If it did, make 28252082Sbostic * sure we don't count it as a new block or zero out its contents. 28352082Sbostic */ 28452082Sbostic newblock = ip->i_size <= lbn << fs->lfs_bshift; 28553528Sheideman if (!newblock && (error = VOP_BMAP(vp, lbn, NULL, &daddr))) 28652994Sbostic return (error); 28752082Sbostic 28852172Sbostic if (newblock || daddr == UNASSIGNED || iosize == fs->lfs_bsize) { 28952082Sbostic *bpp = bp = getblk(vp, lbn, fs->lfs_bsize); 29052082Sbostic if (newblock || 29152172Sbostic daddr == UNASSIGNED && !(bp->b_flags & B_CACHE)) { 29252082Sbostic ++ip->i_blocks; 29352082Sbostic if (iosize != fs->lfs_bsize) 29452082Sbostic clrbuf(bp); 29552082Sbostic } 29652994Sbostic return (0); 29752082Sbostic } 29852994Sbostic return (bread(vp, lbn, fs->lfs_bsize, NOCRED, bpp)); 29952082Sbostic 30052082Sbostic } 301