xref: /xv6-public/fs.c (revision 22bac2cb)
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