111a9947fSrtm #include "types.h" 21f544842Skaashoek #include "stat.h" 311a9947fSrtm #include "param.h" 411a9947fSrtm #include "x86.h" 511a9947fSrtm #include "mmu.h" 611a9947fSrtm #include "proc.h" 711a9947fSrtm #include "defs.h" 811a9947fSrtm #include "spinlock.h" 911a9947fSrtm #include "buf.h" 1011a9947fSrtm #include "fs.h" 1111a9947fSrtm #include "fsvar.h" 126fa5ffb5Skaashoek #include "dev.h" 1311a9947fSrtm 1411a9947fSrtm // these are inodes currently in use 1511a9947fSrtm // an entry is free if count == 0 1611a9947fSrtm struct inode inode[NINODE]; 175be0039cSrtm struct spinlock inode_table_lock; 1811a9947fSrtm 199d3fb671Srtm uint rootdev = 1; 209d3fb671Srtm 215be0039cSrtm void 225be0039cSrtm iinit(void) 235be0039cSrtm { 245be0039cSrtm initlock(&inode_table_lock, "inode_table"); 255be0039cSrtm } 265be0039cSrtm 2724111398Skaashoek static uint 2824111398Skaashoek balloc(uint dev) 2924111398Skaashoek { 3024111398Skaashoek int b; 3124111398Skaashoek struct buf *bp; 3224111398Skaashoek struct superblock *sb; 3328d9ef04Skaashoek int bi = 0; 3424111398Skaashoek int size; 3524111398Skaashoek int ninodes; 3624111398Skaashoek uchar m; 3724111398Skaashoek 3824111398Skaashoek bp = bread(dev, 1); 3924111398Skaashoek sb = (struct superblock *) bp->data; 4024111398Skaashoek size = sb->size; 4124111398Skaashoek ninodes = sb->ninodes; 4224111398Skaashoek 4324111398Skaashoek for (b = 0; b < size; b++) { 4424111398Skaashoek if (b % BPB == 0) { 4524111398Skaashoek brelse(bp); 4624111398Skaashoek bp = bread(dev, BBLOCK(b, ninodes)); 4724111398Skaashoek } 4824111398Skaashoek bi = b % BPB; 4924111398Skaashoek m = 0x1 << (bi % 8); 5024111398Skaashoek if ((bp->data[bi/8] & m) == 0) { // is block free? 5124111398Skaashoek break; 5224111398Skaashoek } 5324111398Skaashoek } 5424111398Skaashoek if (b >= size) 5524111398Skaashoek panic("balloc: out of blocks\n"); 5624111398Skaashoek 5724111398Skaashoek cprintf ("balloc: allocate block %d\n", b); 5824111398Skaashoek bp->data[bi/8] |= 0x1 << (bi % 8); 5924111398Skaashoek bwrite (dev, bp, BBLOCK(b, ninodes)); // mark it allocated on disk 6028d9ef04Skaashoek brelse(bp); 6124111398Skaashoek return b; 6224111398Skaashoek } 6324111398Skaashoek 6428d9ef04Skaashoek static void 6528d9ef04Skaashoek bfree(int dev, uint b) 6628d9ef04Skaashoek { 6728d9ef04Skaashoek struct buf *bp; 6828d9ef04Skaashoek struct superblock *sb; 6928d9ef04Skaashoek int bi; 7028d9ef04Skaashoek int ninodes; 7128d9ef04Skaashoek uchar m; 7228d9ef04Skaashoek 7328d9ef04Skaashoek cprintf ("bfree: free block %d\n", b); 7428d9ef04Skaashoek bp = bread(dev, 1); 7528d9ef04Skaashoek sb = (struct superblock *) bp->data; 7628d9ef04Skaashoek ninodes = sb->ninodes; 7728d9ef04Skaashoek brelse(bp); 7828d9ef04Skaashoek 7928d9ef04Skaashoek bp = bread(dev, BBLOCK(b, ninodes)); 8028d9ef04Skaashoek bi = b % BPB; 8128d9ef04Skaashoek m = ~(0x1 << (bi %8)); 8228d9ef04Skaashoek bp->data[bi/8] &= m; 8328d9ef04Skaashoek bwrite (dev, bp, BBLOCK(b, ninodes)); // mark it free on disk 8428d9ef04Skaashoek brelse(bp); 8528d9ef04Skaashoek } 8624111398Skaashoek 879d3fb671Srtm // returns an inode with busy set and incremented reference count. 8811a9947fSrtm struct inode * 8911a9947fSrtm iget(uint dev, uint inum) 9011a9947fSrtm { 9111a9947fSrtm struct inode *ip, *nip = 0; 9211a9947fSrtm struct dinode *dip; 9311a9947fSrtm struct buf *bp; 9411a9947fSrtm 9511a9947fSrtm acquire(&inode_table_lock); 9611a9947fSrtm 9711a9947fSrtm loop: 9811a9947fSrtm for(ip = &inode[0]; ip < &inode[NINODE]; ip++){ 9911a9947fSrtm if(ip->count > 0 && ip->dev == dev && ip->inum == inum){ 10011a9947fSrtm if(ip->busy){ 10111a9947fSrtm sleep(ip, &inode_table_lock); 10211a9947fSrtm goto loop; 10311a9947fSrtm } 10411a9947fSrtm ip->count++; 10517a85657Srtm ip->busy = 1; 10611a9947fSrtm release(&inode_table_lock); 10711a9947fSrtm return ip; 10811a9947fSrtm } 10911a9947fSrtm if(nip == 0 && ip->count == 0) 11011a9947fSrtm nip = ip; 11111a9947fSrtm } 11211a9947fSrtm 11311a9947fSrtm if(nip == 0) 11411a9947fSrtm panic("out of inodes"); 11511a9947fSrtm 11611a9947fSrtm nip->dev = dev; 11711a9947fSrtm nip->inum = inum; 11811a9947fSrtm nip->count = 1; 11911a9947fSrtm nip->busy = 1; 12011a9947fSrtm 12111a9947fSrtm release(&inode_table_lock); 12211a9947fSrtm 12324111398Skaashoek bp = bread(dev, IBLOCK(inum)); 12411a9947fSrtm dip = &((struct dinode *)(bp->data))[inum % IPB]; 12511a9947fSrtm nip->type = dip->type; 126e8d11c2eSkaashoek nip->major = dip->major; 127e8d11c2eSkaashoek nip->minor = dip->minor; 12811a9947fSrtm nip->nlink = dip->nlink; 12911a9947fSrtm nip->size = dip->size; 13011a9947fSrtm memmove(nip->addrs, dip->addrs, sizeof(nip->addrs)); 13111a9947fSrtm brelse(bp); 13211a9947fSrtm 13311a9947fSrtm return nip; 13411a9947fSrtm } 13511a9947fSrtm 13628d9ef04Skaashoek void 13728d9ef04Skaashoek iupdate (struct inode *ip) 13828d9ef04Skaashoek { 13928d9ef04Skaashoek struct buf *bp; 14028d9ef04Skaashoek struct dinode *dip; 14128d9ef04Skaashoek 14228d9ef04Skaashoek bp = bread(ip->dev, IBLOCK(ip->inum)); 14328d9ef04Skaashoek dip = &((struct dinode *)(bp->data))[ip->inum % IPB]; 14428d9ef04Skaashoek dip->type = ip->type; 14528d9ef04Skaashoek dip->major = ip->major; 14628d9ef04Skaashoek dip->minor = ip->minor; 14728d9ef04Skaashoek dip->nlink = ip->nlink; 14828d9ef04Skaashoek dip->size = ip->size; 14928d9ef04Skaashoek memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); 15028d9ef04Skaashoek bwrite (ip->dev, bp, IBLOCK(ip->inum)); // mark it allocated on the disk 15128d9ef04Skaashoek brelse(bp); 15228d9ef04Skaashoek } 15328d9ef04Skaashoek 154e8d11c2eSkaashoek struct inode * 155e8d11c2eSkaashoek ialloc(uint dev, short type) 156e8d11c2eSkaashoek { 157e8d11c2eSkaashoek struct inode *ip; 158e8d11c2eSkaashoek struct dinode *dip = 0; 159e8d11c2eSkaashoek struct superblock *sb; 160e8d11c2eSkaashoek int ninodes; 161e8d11c2eSkaashoek int inum; 162e8d11c2eSkaashoek struct buf *bp; 163e8d11c2eSkaashoek 164e8d11c2eSkaashoek bp = bread(dev, 1); 16524111398Skaashoek sb = (struct superblock *) bp->data; 166e8d11c2eSkaashoek ninodes = sb->ninodes; 167e8d11c2eSkaashoek brelse(bp); 168e8d11c2eSkaashoek 169e8d11c2eSkaashoek for (inum = 1; inum < ninodes; inum++) { // loop over inode blocks 17024111398Skaashoek bp = bread(dev, IBLOCK(inum)); 171e8d11c2eSkaashoek dip = &((struct dinode *)(bp->data))[inum % IPB]; 172e8d11c2eSkaashoek if (dip->type == 0) { // a free inode 173e8d11c2eSkaashoek break; 174e8d11c2eSkaashoek } 175e8d11c2eSkaashoek brelse(bp); 176e8d11c2eSkaashoek } 177e8d11c2eSkaashoek 178e8d11c2eSkaashoek if (inum >= ninodes) { 17924111398Skaashoek panic ("ialloc: no inodes left\n"); 180e8d11c2eSkaashoek } 181e8d11c2eSkaashoek 182e8d11c2eSkaashoek cprintf ("ialloc: %d\n", inum); 183e8d11c2eSkaashoek dip->type = type; 18424111398Skaashoek bwrite (dev, bp, IBLOCK(inum)); // mark it allocated on the disk 185e8d11c2eSkaashoek brelse(bp); 186e8d11c2eSkaashoek ip = iget (dev, inum); 187e8d11c2eSkaashoek return ip; 188e8d11c2eSkaashoek } 189e8d11c2eSkaashoek 19028d9ef04Skaashoek static void 19124437cd5Skaashoek ifree(struct inode *ip) 192e8d11c2eSkaashoek { 1930633b971Skaashoek cprintf("ifree: %d\n", ip->inum); 19428d9ef04Skaashoek ip->type = 0; 19528d9ef04Skaashoek iupdate(ip); 196e8d11c2eSkaashoek } 197e8d11c2eSkaashoek 19811a9947fSrtm void 1999d3fb671Srtm ilock(struct inode *ip) 2009d3fb671Srtm { 2019d3fb671Srtm if(ip->count < 1) 2029d3fb671Srtm panic("ilock"); 2039d3fb671Srtm 2049d3fb671Srtm acquire(&inode_table_lock); 2059d3fb671Srtm 2069d3fb671Srtm while(ip->busy) 2079d3fb671Srtm sleep(ip, &inode_table_lock); 2089d3fb671Srtm ip->busy = 1; 2099d3fb671Srtm 2109d3fb671Srtm release(&inode_table_lock); 2119d3fb671Srtm } 2129d3fb671Srtm 2139d3fb671Srtm // caller is holding onto a reference to this inode, but no 2149d3fb671Srtm // longer needs to examine or change it, so clear ip->busy. 2159d3fb671Srtm void 2169d3fb671Srtm iunlock(struct inode *ip) 2179d3fb671Srtm { 2189d3fb671Srtm if(ip->busy != 1) 2199d3fb671Srtm panic("iunlock"); 2209d3fb671Srtm 2219d3fb671Srtm acquire(&inode_table_lock); 2229d3fb671Srtm 2239d3fb671Srtm ip->busy = 0; 2249d3fb671Srtm wakeup(ip); 2259d3fb671Srtm 2269d3fb671Srtm release(&inode_table_lock); 2279d3fb671Srtm } 2289d3fb671Srtm 229*22bac2cbSkaashoek uint 230*22bac2cbSkaashoek bmap(struct inode *ip, uint bn) 231*22bac2cbSkaashoek { 232*22bac2cbSkaashoek unsigned x; 233*22bac2cbSkaashoek 234*22bac2cbSkaashoek if(bn >= NDIRECT) 235*22bac2cbSkaashoek panic("bmap 1"); 236*22bac2cbSkaashoek x = ip->addrs[bn]; 237*22bac2cbSkaashoek if(x == 0) 238*22bac2cbSkaashoek panic("bmap 2"); 239*22bac2cbSkaashoek return x; 240*22bac2cbSkaashoek } 241*22bac2cbSkaashoek 242*22bac2cbSkaashoek void 243*22bac2cbSkaashoek iunlink(struct inode *ip) 244*22bac2cbSkaashoek { 245*22bac2cbSkaashoek int i; 246*22bac2cbSkaashoek 247*22bac2cbSkaashoek // free inode, its blocks, and remove dir entry 248*22bac2cbSkaashoek for (i = 0; i < NDIRECT; i++) { 249*22bac2cbSkaashoek if (ip->addrs[i] != 0) { 250*22bac2cbSkaashoek bfree(ip->dev, ip->addrs[i]); 251*22bac2cbSkaashoek ip->addrs[i] = 0; 252*22bac2cbSkaashoek } 253*22bac2cbSkaashoek } 254*22bac2cbSkaashoek ip->size = 0; 255*22bac2cbSkaashoek ip->major = 0; 256*22bac2cbSkaashoek ip->minor = 0; 257*22bac2cbSkaashoek iupdate(ip); 258*22bac2cbSkaashoek ifree(ip); // is this the right order? 259*22bac2cbSkaashoek } 260*22bac2cbSkaashoek 2619d3fb671Srtm // caller is releasing a reference to this inode. 2629d3fb671Srtm // you must have the inode lock. 2639d3fb671Srtm void 26411a9947fSrtm iput(struct inode *ip) 26511a9947fSrtm { 2669d3fb671Srtm if(ip->count < 1 || ip->busy != 1) 2679d3fb671Srtm panic("iput"); 2689d3fb671Srtm 269*22bac2cbSkaashoek if ((ip->count <= 1) && (ip->nlink <= 0)) 270*22bac2cbSkaashoek iunlink(ip); 271*22bac2cbSkaashoek 27211a9947fSrtm acquire(&inode_table_lock); 27311a9947fSrtm 27411a9947fSrtm ip->count -= 1; 27511a9947fSrtm ip->busy = 0; 27611a9947fSrtm wakeup(ip); 27711a9947fSrtm 27811a9947fSrtm release(&inode_table_lock); 27911a9947fSrtm } 2809d3fb671Srtm 2819d3fb671Srtm void 28232630628Srtm idecref(struct inode *ip) 2839d3fb671Srtm { 2849d3fb671Srtm acquire(&inode_table_lock); 2859d3fb671Srtm 28632630628Srtm if(ip->count < 1) 28732630628Srtm panic("idecref"); 28832630628Srtm 28932630628Srtm ip->count -= 1; 2909d3fb671Srtm 2919d3fb671Srtm release(&inode_table_lock); 2929d3fb671Srtm } 2939d3fb671Srtm 2941f544842Skaashoek void 2951f544842Skaashoek stati(struct inode *ip, struct stat *st) 2961f544842Skaashoek { 2971f544842Skaashoek st->st_dev = ip->dev; 2981f544842Skaashoek st->st_ino = ip->inum; 2991f544842Skaashoek st->st_type = ip->type; 3001f544842Skaashoek st->st_nlink = ip->nlink; 3011f544842Skaashoek st->st_size = ip->size; 3021f544842Skaashoek } 3031f544842Skaashoek 304*22bac2cbSkaashoek #define min(a, b) ((a) < (b) ? (a) : (b)) 305*22bac2cbSkaashoek 306c59361f1Srtm int 30717a85657Srtm readi(struct inode *ip, char *dst, uint off, uint n) 308c59361f1Srtm { 309c59361f1Srtm uint target = n, n1; 310c59361f1Srtm struct buf *bp; 311c59361f1Srtm 312939f9edeSkaashoek if (ip->type == T_DEV) { 313939f9edeSkaashoek if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_read) 314939f9edeSkaashoek return -1; 31517a85657Srtm return devsw[ip->major].d_read (ip->minor, dst, n); 316939f9edeSkaashoek } 317939f9edeSkaashoek 318c59361f1Srtm while(n > 0 && off < ip->size){ 31924111398Skaashoek bp = bread(ip->dev, bmap(ip, off / BSIZE)); 320c59361f1Srtm n1 = min(n, ip->size - off); 32124111398Skaashoek n1 = min(n1, BSIZE - (off % BSIZE)); 32224111398Skaashoek memmove(dst, bp->data + (off % BSIZE), n1); 323c59361f1Srtm n -= n1; 324c59361f1Srtm off += n1; 325c59361f1Srtm dst += n1; 326c59361f1Srtm brelse(bp); 327c59361f1Srtm } 328c59361f1Srtm 329c59361f1Srtm return target - n; 330c59361f1Srtm } 331c59361f1Srtm 3326fa5ffb5Skaashoek int 33317a85657Srtm writei(struct inode *ip, char *addr, uint off, uint n) 3346fa5ffb5Skaashoek { 3356fa5ffb5Skaashoek if (ip->type == T_DEV) { 336939f9edeSkaashoek if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_write) 337939f9edeSkaashoek return -1; 3386fa5ffb5Skaashoek return devsw[ip->major].d_write (ip->minor, addr, n); 33928d9ef04Skaashoek } else if (ip->type == T_FILE || ip->type == T_DIR) { // XXX dir here too? 34028d9ef04Skaashoek struct buf *bp; 34128d9ef04Skaashoek int r = 0; 34228d9ef04Skaashoek int m; 34328d9ef04Skaashoek int lbn; 34428d9ef04Skaashoek uint b; 34528d9ef04Skaashoek while (r < n) { 34628d9ef04Skaashoek lbn = off / BSIZE; 34728d9ef04Skaashoek if (lbn >= NDIRECT) return r; 34828d9ef04Skaashoek if (ip->addrs[lbn] == 0) { 34928d9ef04Skaashoek b = balloc(ip->dev); 35028d9ef04Skaashoek if (b <= 0) return r; 35128d9ef04Skaashoek ip->addrs[lbn] = b; 35228d9ef04Skaashoek } 353*22bac2cbSkaashoek m = min(BSIZE - off % BSIZE, n-r); 35428d9ef04Skaashoek bp = bread(ip->dev, bmap(ip, off / BSIZE)); 35528d9ef04Skaashoek memmove (bp->data + off % BSIZE, addr, m); 35628d9ef04Skaashoek bwrite (ip->dev, bp, bmap(ip, off/BSIZE)); 35728d9ef04Skaashoek brelse (bp); 35828d9ef04Skaashoek r += m; 35928d9ef04Skaashoek off += m; 36028d9ef04Skaashoek } 36128d9ef04Skaashoek if (r > 0) { 36228d9ef04Skaashoek if (off > ip->size) { 36328d9ef04Skaashoek ip->size = off; 36428d9ef04Skaashoek } 36528d9ef04Skaashoek iupdate(ip); 36628d9ef04Skaashoek } 36728d9ef04Skaashoek return r; 3686fa5ffb5Skaashoek } else { 3696fa5ffb5Skaashoek panic ("writei: unknown type\n"); 3708a8be1b8Srtm return 0; 3716fa5ffb5Skaashoek } 3726fa5ffb5Skaashoek } 3736fa5ffb5Skaashoek 3749d3fb671Srtm struct inode * 3750633b971Skaashoek namei(char *path, uint *ret_pinum) 3769d3fb671Srtm { 3779d3fb671Srtm struct inode *dp; 3789d3fb671Srtm char *cp = path; 3799d3fb671Srtm uint off, dev; 3809d3fb671Srtm struct buf *bp; 3819d3fb671Srtm struct dirent *ep; 3829d3fb671Srtm int i; 3839d3fb671Srtm unsigned ninum; 3840633b971Skaashoek unsigned pinum; 3859d3fb671Srtm 3869d3fb671Srtm dp = iget(rootdev, 1); 3870633b971Skaashoek pinum = dp->inum; 3889d3fb671Srtm 3899d3fb671Srtm while(*cp == '/') 3909d3fb671Srtm cp++; 3919d3fb671Srtm 3929d3fb671Srtm while(1){ 3930633b971Skaashoek if(*cp == '\0') { 3940633b971Skaashoek if (ret_pinum) 3950633b971Skaashoek *ret_pinum = pinum; 3969d3fb671Srtm return dp; 3970633b971Skaashoek } 3989d3fb671Srtm 3999d3fb671Srtm if(dp->type != T_DIR){ 4000633b971Skaashoek if (ret_pinum) 4010633b971Skaashoek *ret_pinum = pinum; 4029d3fb671Srtm iput(dp); 4039d3fb671Srtm return 0; 4049d3fb671Srtm } 4059d3fb671Srtm 40624111398Skaashoek for(off = 0; off < dp->size; off += BSIZE){ 40724111398Skaashoek bp = bread(dp->dev, bmap(dp, off / BSIZE)); 4089d3fb671Srtm for(ep = (struct dirent *) bp->data; 40924111398Skaashoek ep < (struct dirent *) (bp->data + BSIZE); 4109d3fb671Srtm ep++){ 4119d3fb671Srtm if(ep->inum == 0) 4129d3fb671Srtm continue; 4139d3fb671Srtm for(i = 0; i < DIRSIZ && cp[i] != '/' && cp[i]; i++) 4149d3fb671Srtm if(cp[i] != ep->name[i]) 4159d3fb671Srtm break; 4169d3fb671Srtm if((cp[i] == '\0' || cp[i] == '/') && (i >= DIRSIZ || ep->name[i] == '\0')){ 4179d3fb671Srtm ninum = ep->inum; 4189d3fb671Srtm brelse(bp); 4199d3fb671Srtm cp += i; 4209d3fb671Srtm goto found; 4219d3fb671Srtm } 4229d3fb671Srtm } 4239d3fb671Srtm brelse(bp); 4249d3fb671Srtm } 4259d3fb671Srtm iput(dp); 4260633b971Skaashoek if (ret_pinum) 4270633b971Skaashoek *ret_pinum = pinum; 4289d3fb671Srtm return 0; 4299d3fb671Srtm 4309d3fb671Srtm found: 4319d3fb671Srtm dev = dp->dev; 4320633b971Skaashoek pinum = dp->inum; 4339d3fb671Srtm iput(dp); 4349d3fb671Srtm dp = iget(dev, ninum); 4357ce01cf9Srtm if(dp->type == 0 || dp->nlink < 1) 4367ce01cf9Srtm panic("namei"); 4379d3fb671Srtm while(*cp == '/') 4389d3fb671Srtm cp++; 4399d3fb671Srtm } 4409d3fb671Srtm } 441e8d11c2eSkaashoek 442e8d11c2eSkaashoek struct inode * 4430633b971Skaashoek mknod(char *cp, short type, short major, short minor) 444e8d11c2eSkaashoek { 4450633b971Skaashoek struct inode *ip, *dp; 446e8d11c2eSkaashoek struct dirent *ep = 0; 447e8d11c2eSkaashoek int off; 448e8d11c2eSkaashoek int i; 449e8d11c2eSkaashoek struct buf *bp = 0; 4500633b971Skaashoek uint pinum = 0; 451e8d11c2eSkaashoek 4520633b971Skaashoek cprintf("mknod: %s %d %d %d\n", cp, type, major, minor); 453e8d11c2eSkaashoek 4540633b971Skaashoek if ((ip = namei(cp, &pinum)) != 0) { 4550633b971Skaashoek iput(ip); 4560633b971Skaashoek return 0; 4570633b971Skaashoek } 4580633b971Skaashoek cprintf("mknod: pinum = %d\n", pinum); 4590633b971Skaashoek dp = iget(rootdev, pinum); 460e8d11c2eSkaashoek ip = ialloc(dp->dev, type); 4610633b971Skaashoek if (ip == 0) { 4620633b971Skaashoek iput(dp); 4630633b971Skaashoek return 0; 4640633b971Skaashoek } 465e8d11c2eSkaashoek ip->major = major; 466e8d11c2eSkaashoek ip->minor = minor; 4676c0e444fSkaashoek ip->size = 0; 4687ce01cf9Srtm ip->nlink = 1; 4696c0e444fSkaashoek 4706c0e444fSkaashoek iupdate (ip); // write new inode to disk 471e8d11c2eSkaashoek 47224111398Skaashoek for(off = 0; off < dp->size; off += BSIZE) { 47324111398Skaashoek bp = bread(dp->dev, bmap(dp, off / BSIZE)); 474e8d11c2eSkaashoek for(ep = (struct dirent *) bp->data; 47524111398Skaashoek ep < (struct dirent *) (bp->data + BSIZE); 476e8d11c2eSkaashoek ep++){ 477e8d11c2eSkaashoek if(ep->inum == 0) { 478e8d11c2eSkaashoek goto found; 479e8d11c2eSkaashoek } 480e8d11c2eSkaashoek } 481e8d11c2eSkaashoek brelse(bp); 482e8d11c2eSkaashoek } 48328d9ef04Skaashoek panic("mknod: XXXX no dir entry free\n"); 484e8d11c2eSkaashoek 485e8d11c2eSkaashoek found: 486e8d11c2eSkaashoek ep->inum = ip->inum; 487e8d11c2eSkaashoek for(i = 0; i < DIRSIZ && cp[i]; i++) ep->name[i] = cp[i]; 4886c0e444fSkaashoek bwrite (dp->dev, bp, bmap(dp, off/BSIZE)); // write directory block 489e8d11c2eSkaashoek brelse(bp); 4906c0e444fSkaashoek dp->size += sizeof(struct dirent); // update directory inode 4916c0e444fSkaashoek iupdate (dp); 4920633b971Skaashoek iput(dp); 493e8d11c2eSkaashoek return ip; 494e8d11c2eSkaashoek } 49524437cd5Skaashoek 49624437cd5Skaashoek int 49724437cd5Skaashoek unlink(char *cp) 49824437cd5Skaashoek { 499*22bac2cbSkaashoek struct inode *ip; 500*22bac2cbSkaashoek struct inode *dp; 50124437cd5Skaashoek struct dirent *ep = 0; 50224437cd5Skaashoek int off; 50324437cd5Skaashoek struct buf *bp = 0; 5040633b971Skaashoek uint pinum; 50524437cd5Skaashoek 506*22bac2cbSkaashoek 5070633b971Skaashoek if ((ip = namei(cp, &pinum)) == 0) { 50824437cd5Skaashoek cprintf("file to be unlinked doesn't exist\n"); 50924437cd5Skaashoek return -1; 51024437cd5Skaashoek } 51124437cd5Skaashoek 51224437cd5Skaashoek ip->nlink--; 51324437cd5Skaashoek if (ip->nlink > 0) { 514*22bac2cbSkaashoek iput(ip); 51524437cd5Skaashoek return 0; 51624437cd5Skaashoek } 51724437cd5Skaashoek 5180633b971Skaashoek dp = iget(rootdev, pinum); 51924437cd5Skaashoek for(off = 0; off < dp->size; off += BSIZE) { 52024437cd5Skaashoek bp = bread(dp->dev, bmap(dp, off / BSIZE)); 52124437cd5Skaashoek for(ep = (struct dirent *) bp->data; 52224437cd5Skaashoek ep < (struct dirent *) (bp->data + BSIZE); 52324437cd5Skaashoek ep++){ 52424437cd5Skaashoek if(ep->inum == ip->inum) { 52524437cd5Skaashoek goto found; 52624437cd5Skaashoek } 52724437cd5Skaashoek } 52824437cd5Skaashoek brelse(bp); 52924437cd5Skaashoek } 53024437cd5Skaashoek panic("mknod: XXXX no dir entry free\n"); 53124437cd5Skaashoek 53224437cd5Skaashoek found: 53324437cd5Skaashoek ep->inum = 0; 53424437cd5Skaashoek bwrite (dp->dev, bp, bmap(dp, off/BSIZE)); // write directory block 53524437cd5Skaashoek brelse(bp); 53624437cd5Skaashoek iupdate (dp); 53724437cd5Skaashoek iput(dp); 538*22bac2cbSkaashoek iput(ip); 53924437cd5Skaashoek return 0; 54024437cd5Skaashoek } 541