bread
iget mkfs makes a file system image put this in your .bochsrc: ata0-slave: type=disk, mode=flat, path="fs.img", cylinders=1024, heads=1, spt=1
This commit is contained in:
		
							parent
							
								
									2927081628
								
							
						
					
					
						commit
						11a9947f1a
					
				
					 12 changed files with 376 additions and 31 deletions
				
			
		
							
								
								
									
										13
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -16,6 +16,8 @@ OBJS = \ | |||
| 	trapasm.o\
 | ||||
| 	trap.o\
 | ||||
| 	vectors.o\
 | ||||
| 	bio.o\
 | ||||
| 	fs.o\
 | ||||
| 
 | ||||
| # Cross-compiling (e.g., on Mac OS X)
 | ||||
| TOOLPREFIX = i386-jos-elf- | ||||
|  | @ -30,7 +32,7 @@ OBJDUMP = $(TOOLPREFIX)objdump | |||
| CFLAGS = -fno-builtin -O2 -Wall -MD | ||||
| AS = $(TOOLPREFIX)gas | ||||
| 
 | ||||
| xv6.img : bootblock kernel | ||||
| xv6.img : bootblock kernel fs.img | ||||
| 	dd if=/dev/zero of=xv6.img count=10000 | ||||
| 	dd if=bootblock of=xv6.img conv=notrunc | ||||
| 	dd if=kernel of=xv6.img seek=1 conv=notrunc | ||||
|  | @ -68,8 +70,15 @@ userfs : userfs.o $(ULIB) | |||
| 	$(LD) -N -e main -Ttext 0 -o userfs userfs.o $(ULIB) | ||||
| 	$(OBJDUMP) -S userfs > userfs.asm | ||||
| 
 | ||||
| mkfs : mkfs.c fs.h | ||||
| 	cc -o mkfs mkfs.c | ||||
| 
 | ||||
| fs.img : mkfs | ||||
| 	./mkfs fs.img | ||||
| 
 | ||||
| -include *.d | ||||
| 
 | ||||
| clean :  | ||||
| 	rm -f *.o *.d *.asm vectors.S parport.out \
 | ||||
| 		bootblock kernel xv6.img user1 userfs usertests | ||||
| 		bootblock kernel xv6.img user1 userfs usertests \
 | ||||
| 		fs.img mkfs | ||||
|  |  | |||
							
								
								
									
										66
									
								
								bio.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								bio.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| #include "types.h" | ||||
| #include "param.h" | ||||
| #include "x86.h" | ||||
| #include "mmu.h" | ||||
| #include "proc.h" | ||||
| #include "defs.h" | ||||
| #include "spinlock.h" | ||||
| #include "buf.h" | ||||
| 
 | ||||
| struct buf buf[NBUF]; | ||||
| struct spinlock buf_table_lock; | ||||
| 
 | ||||
| struct buf * | ||||
| getblk() | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   acquire(&buf_table_lock); | ||||
| 
 | ||||
|   // XXX need to lock the block even if not caching, to
 | ||||
|   // avoid read modify write problems.
 | ||||
| 
 | ||||
|   while(1){ | ||||
|     for(i = 0; i < NBUF; i++){ | ||||
|       if((buf[i].flags & B_BUSY) == 0){ | ||||
|         buf[i].flags |= B_BUSY; | ||||
|         release(&buf_table_lock); | ||||
|         return buf + i; | ||||
|       } | ||||
|     } | ||||
|     sleep(buf, &buf_table_lock); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| struct buf * | ||||
| bread(uint dev, uint sector) | ||||
| { | ||||
|   void *c; | ||||
|   struct buf *b; | ||||
|   extern struct spinlock ide_lock; | ||||
| 
 | ||||
|   b = getblk(); | ||||
| 
 | ||||
|   acquire(&ide_lock); | ||||
|   c = ide_start_read(dev & 0xff, sector, b->data, 1); | ||||
|   // sleep (c, &ide_lock);
 | ||||
|   ide_finish_read(c); | ||||
|   release(&ide_lock); | ||||
| 
 | ||||
|   return b; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| brelse(struct buf *b) | ||||
| { | ||||
|   if((b->flags & B_BUSY) == 0) | ||||
|     panic("brelse"); | ||||
|    | ||||
|   acquire(&buf_table_lock); | ||||
| 
 | ||||
|   b->flags &= ~B_BUSY; | ||||
|   wakeup(buf); | ||||
| 
 | ||||
|   release(&buf_table_lock); | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										5
									
								
								buf.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								buf.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| struct buf { | ||||
|   int flags; | ||||
|   uchar data[512]; | ||||
| }; | ||||
| #define B_BUSY 0x1 | ||||
							
								
								
									
										10
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								defs.h
									
										
									
									
									
								
							|  | @ -87,6 +87,14 @@ void fd_incref(struct fd *fd); | |||
| // ide.c
 | ||||
| void ide_init(void); | ||||
| void ide_intr(void); | ||||
| void* ide_start_read(uint secno, void *dst, uint nsecs); | ||||
| void* ide_start_read(int diskno, uint secno, void *dst, uint nsecs); | ||||
| int ide_finish_read(void *); | ||||
| 
 | ||||
| // bio.c
 | ||||
| struct buf; | ||||
| struct buf *bread(uint, uint); | ||||
| void brelse(struct buf *); | ||||
| 
 | ||||
| // fs.c
 | ||||
| struct inode * iget(uint dev, uint inum); | ||||
| void iput(struct inode *ip); | ||||
|  |  | |||
							
								
								
									
										73
									
								
								fs.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								fs.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | |||
| #include "types.h" | ||||
| #include "param.h" | ||||
| #include "x86.h" | ||||
| #include "mmu.h" | ||||
| #include "proc.h" | ||||
| #include "defs.h" | ||||
| #include "spinlock.h" | ||||
| #include "buf.h" | ||||
| #include "fs.h" | ||||
| #include "fsvar.h" | ||||
| 
 | ||||
| // these are inodes currently in use
 | ||||
| // an entry is free if count == 0
 | ||||
| struct inode inode[NINODE]; | ||||
| struct spinlock inode_table_lock; | ||||
| 
 | ||||
| struct inode * | ||||
| iget(uint dev, uint inum) | ||||
| { | ||||
|   struct inode *ip, *nip = 0; | ||||
|   struct dinode *dip; | ||||
|   struct buf *bp; | ||||
| 
 | ||||
|   acquire(&inode_table_lock); | ||||
| 
 | ||||
|  loop: | ||||
|   for(ip = &inode[0]; ip < &inode[NINODE]; ip++){ | ||||
|     if(ip->count > 0 && ip->dev == dev && ip->inum == inum){ | ||||
|       if(ip->busy){ | ||||
|         sleep(ip, &inode_table_lock); | ||||
|         goto loop; | ||||
|       } | ||||
|       ip->count++; | ||||
|       release(&inode_table_lock); | ||||
|       return ip; | ||||
|     } | ||||
|     if(nip == 0 && ip->count == 0) | ||||
|       nip = ip; | ||||
|   } | ||||
| 
 | ||||
|   if(nip == 0) | ||||
|     panic("out of inodes"); | ||||
| 
 | ||||
|   nip->dev = dev; | ||||
|   nip->inum = inum; | ||||
|   nip->count = 1; | ||||
|   nip->busy = 1; | ||||
| 
 | ||||
|   release(&inode_table_lock); | ||||
| 
 | ||||
|   bp = bread(dev, inum / IPB + 2); | ||||
|   dip = &((struct dinode *)(bp->data))[inum % IPB]; | ||||
|   nip->type = dip->type; | ||||
|   nip->nlink = dip->nlink; | ||||
|   nip->size = dip->size; | ||||
|   memmove(nip->addrs, dip->addrs, sizeof(nip->addrs)); | ||||
|   cprintf("bn %d off %d\n", inum / IPB + 2, (unsigned)dip - (unsigned)bp->data); | ||||
|   brelse(bp); | ||||
| 
 | ||||
|   return nip; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| iput(struct inode *ip) | ||||
| { | ||||
|   acquire(&inode_table_lock); | ||||
| 
 | ||||
|   ip->count -= 1; | ||||
|   ip->busy = 0; | ||||
|   wakeup(ip); | ||||
| 
 | ||||
|   release(&inode_table_lock); | ||||
| } | ||||
							
								
								
									
										28
									
								
								fs.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								fs.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| // on-disk file system format
 | ||||
| 
 | ||||
| // second sector
 | ||||
| struct superblock{ | ||||
|   int nblocks; | ||||
|   int ninodes; | ||||
| }; | ||||
| 
 | ||||
| #define NDIRECT 14 | ||||
| 
 | ||||
| // inodes start at the third sector
 | ||||
| // and blocks start at (ninodes * sizeof(dinode) + 511) / 512
 | ||||
| struct dinode { | ||||
|   short type; | ||||
|   short nlink; | ||||
|   uint size; | ||||
|   uint addrs[NDIRECT]; | ||||
| }; | ||||
| #define T_DIR 1 | ||||
| #define T_FILE 2 | ||||
| 
 | ||||
| #define IPB (512 / sizeof(struct dinode)) | ||||
| 
 | ||||
| struct dirent { | ||||
|   ushort inum; | ||||
|   char name[14]; | ||||
| }; | ||||
| 
 | ||||
							
								
								
									
										12
									
								
								fsvar.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								fsvar.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| // in-core file system types
 | ||||
| 
 | ||||
| struct inode { | ||||
|   uint dev; | ||||
|   uint inum; | ||||
|   int count; | ||||
|   int busy; | ||||
|   short type; | ||||
|   short nlink; | ||||
|   uint size; | ||||
|   uint addrs[NDIRECT]; | ||||
| }; | ||||
							
								
								
									
										16
									
								
								ide.c
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								ide.c
									
										
									
									
									
								
							|  | @ -84,7 +84,7 @@ ide_start_request (void) | |||
| { | ||||
|   struct ide_request *r; | ||||
| 
 | ||||
|   if (head == tail) { | ||||
|   if (head != tail) { | ||||
|     r = &request[tail]; | ||||
|     ide_wait_ready(0); | ||||
|     outb(0x3f6, 0); | ||||
|  | @ -98,7 +98,7 @@ ide_start_request (void) | |||
| } | ||||
| 
 | ||||
| void * | ||||
| ide_start_read(uint secno, void *dst, uint nsecs) | ||||
| ide_start_read(int diskno, uint secno, void *dst, uint nsecs) | ||||
| { | ||||
|   struct ide_request *r; | ||||
|   if(!holding(&ide_lock)) | ||||
|  | @ -114,12 +114,12 @@ ide_start_read(uint secno, void *dst, uint nsecs) | |||
|   r->secno = secno; | ||||
|   r->dst = dst; | ||||
|   r->nsecs = nsecs; | ||||
|   r->diskno = 0; | ||||
| 
 | ||||
|   ide_start_request(); | ||||
|   r->diskno = diskno; | ||||
| 
 | ||||
|   head = (head + 1) % NREQUEST; | ||||
| 
 | ||||
|   ide_start_request(); | ||||
| 
 | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
|  | @ -129,6 +129,9 @@ ide_finish_read(void *c) | |||
|   int r = 0; | ||||
|   struct ide_request *req = (struct ide_request *) c; | ||||
| 
 | ||||
|   if(c != &request[tail]) | ||||
|     panic("ide_finish_read"); | ||||
| 
 | ||||
|   if(!holding(&ide_lock)) | ||||
|     panic("ide_start_read: not holding ide_lock"); | ||||
|   for (; req->nsecs > 0; req->nsecs--, req->dst += 512) { | ||||
|  | @ -148,10 +151,9 @@ ide_finish_read(void *c) | |||
| } | ||||
| 
 | ||||
| int | ||||
| ide_write(uint secno, const void *src, uint nsecs) | ||||
| ide_write(int diskno, uint secno, const void *src, uint nsecs) | ||||
| { | ||||
|   int r; | ||||
|   int diskno = 0; | ||||
| 	 | ||||
|   if(nsecs > 256) | ||||
|     panic("ide_write"); | ||||
|  |  | |||
							
								
								
									
										140
									
								
								mkfs.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								mkfs.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,140 @@ | |||
| #include <stdio.h> | ||||
| #include <unistd.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <fcntl.h> | ||||
| #include "types.h" | ||||
| #include "param.h" | ||||
| #include "fs.h" | ||||
| 
 | ||||
| int nblocks = 1009; | ||||
| int ninodes = 100; | ||||
| 
 | ||||
| int fd; | ||||
| struct superblock sb; | ||||
| char zeroes[512]; | ||||
| uint freeblock; | ||||
| 
 | ||||
| void wsect(uint, void *); | ||||
| void winode(uint, struct dinode *); | ||||
| void rsect(uint sec, void *buf); | ||||
| 
 | ||||
| // convert to intel byte order
 | ||||
| ushort | ||||
| xshort(ushort x) | ||||
| { | ||||
|   ushort y; | ||||
|   uchar *a = &y; | ||||
|   a[0] = x; | ||||
|   a[1] = x >> 8; | ||||
|   return y; | ||||
| } | ||||
| 
 | ||||
| uint | ||||
| xint(uint x) | ||||
| { | ||||
|   uint y; | ||||
|   uchar *a = &y; | ||||
|   a[0] = x; | ||||
|   a[1] = x >> 8; | ||||
|   a[2] = x >> 16; | ||||
|   a[3] = x >> 24; | ||||
|   return y; | ||||
| } | ||||
| 
 | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
|   int i; | ||||
|   struct dinode din; | ||||
|   char dbuf[512]; | ||||
| 
 | ||||
|   if(argc != 2){ | ||||
|     fprintf(stderr, "Usage: mkfs fs.img\n"); | ||||
|     exit(1); | ||||
|   } | ||||
| 
 | ||||
|   if(sizeof(struct dinode) * IPB != 512){ | ||||
|     fprintf(stderr, "sizeof(dinode) must divide 512\n"); | ||||
|     exit(1); | ||||
|   } | ||||
| 
 | ||||
|   fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); | ||||
|   if(fd < 0){ | ||||
|     perror(argv[1]); | ||||
|     exit(1); | ||||
|   } | ||||
| 
 | ||||
|   sb.nblocks = xint(nblocks); // so whole disk is 1024 sectors
 | ||||
|   sb.ninodes = xint(ninodes); | ||||
| 
 | ||||
|   freeblock = ninodes / IPB + 2; | ||||
| 
 | ||||
|   for(i = 0; i < nblocks + (ninodes / IPB) + 3; i++) | ||||
|     wsect(i, zeroes); | ||||
| 
 | ||||
|   wsect(1, &sb); | ||||
| 
 | ||||
|   bzero(&din, sizeof(din)); | ||||
|   din.type = xshort(T_DIR); | ||||
|   din.nlink = xshort(2); | ||||
|   din.size = xint(512); | ||||
|   din.addrs[0] = xint(freeblock++); | ||||
|   winode(1, &din); | ||||
| 
 | ||||
|   bzero(dbuf, sizeof(dbuf)); | ||||
|   ((struct dirent *) dbuf)[0].inum = xshort(1); | ||||
|   strcpy(((struct dirent *) dbuf)[0].name, "."); | ||||
|   ((struct dirent *) dbuf)[1].inum = xshort(1); | ||||
|   strcpy(((struct dirent *) dbuf)[1].name, ".."); | ||||
|   wsect(din.addrs[0], dbuf); | ||||
| 
 | ||||
|   exit(0); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| wsect(uint sec, void *buf) | ||||
| { | ||||
|   if(lseek(fd, sec * 512L, 0) != sec * 512L){ | ||||
|     perror("lseek"); | ||||
|     exit(1); | ||||
|   } | ||||
|   if(write(fd, buf, 512) != 512){ | ||||
|     perror("write"); | ||||
|     exit(1); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| uint | ||||
| i2b(uint inum) | ||||
| { | ||||
|   return (inum / IPB) + 2; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| winode(uint inum, struct dinode *ip) | ||||
| { | ||||
|   char buf[512]; | ||||
|   uint bn; | ||||
|   struct dinode *dip; | ||||
| 
 | ||||
|   bn = i2b(inum); | ||||
|   rsect(bn, buf); | ||||
|   dip = ((struct dinode *) buf) + (inum % IPB); | ||||
|   *dip = *ip; | ||||
|   printf("bn %d off %d\n", | ||||
|          bn, (unsigned)dip - (unsigned) buf); | ||||
|   wsect(bn, buf); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| rsect(uint sec, void *buf) | ||||
| { | ||||
|   if(lseek(fd, sec * 512L, 0) != sec * 512L){ | ||||
|     perror("lseek"); | ||||
|     exit(1); | ||||
|   } | ||||
|   if(read(fd, buf, 512) != 512){ | ||||
|     perror("read"); | ||||
|     exit(1); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										2
									
								
								mmu.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								mmu.h
									
										
									
									
									
								
							|  | @ -125,7 +125,7 @@ struct segdesc { | |||
| // Task state segment format (as described by the Pentium architecture book)
 | ||||
| struct taskstate { | ||||
| 	uint link;	// Old ts selector
 | ||||
| 	uint * esp0;	// Stack pointers and segment selectors
 | ||||
| 	uint esp0;	// Stack pointers and segment selectors
 | ||||
| 	ushort ss0;	//   after an increase in privilege level
 | ||||
| 	ushort padding1; | ||||
| 	uint * esp1; | ||||
|  |  | |||
							
								
								
									
										2
									
								
								param.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								param.h
									
										
									
									
									
								
							|  | @ -5,3 +5,5 @@ | |||
| #define NOFILE 16 // file descriptors per process
 | ||||
| #define NFD 100 // file descriptors per system
 | ||||
| #define NREQUEST 100 // outstanding disk requests
 | ||||
| #define NBUF 10 | ||||
| #define NINODE 100 | ||||
|  |  | |||
							
								
								
									
										40
									
								
								syscall.c
									
										
									
									
									
								
							
							
						
						
									
										40
									
								
								syscall.c
									
										
									
									
									
								
							|  | @ -7,6 +7,9 @@ | |||
| #include "traps.h" | ||||
| #include "syscall.h" | ||||
| #include "spinlock.h" | ||||
| #include "buf.h" | ||||
| #include "fs.h" | ||||
| #include "fsvar.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * User code makes a system call with INT T_SYSCALL. | ||||
|  | @ -224,30 +227,27 @@ sys_cons_puts(void) | |||
| int | ||||
| sys_block(void) | ||||
| { | ||||
|   char buf[512]; | ||||
|   int i, j; | ||||
|   void *c; | ||||
|   extern struct spinlock ide_lock; | ||||
|   struct buf *b; | ||||
|   struct inode *ip; | ||||
| 
 | ||||
|   cprintf("%d: call sys_block\n", cpu()); | ||||
|   for (i = 0; i < 100; i++) { | ||||
|     acquire(&ide_lock); | ||||
|     if ((c = ide_start_read(i, buf, 1)) == 0) { | ||||
|       panic("couldn't start read\n"); | ||||
|     } | ||||
| #if 0 | ||||
|     cprintf("call sleep\n"); | ||||
|     sleep (c, &ide_lock); | ||||
| #endif | ||||
|     if (ide_finish_read(c)) { | ||||
|       panic("couldn't do read\n"); | ||||
|     } | ||||
|     release(&ide_lock); | ||||
|     cprintf("sector %d: ", i); | ||||
|     for (j = 0; j < 2; j++) | ||||
|       cprintf("%x ", buf[j] & 0xff); | ||||
|   for (i = 0; i < 2; i++) { | ||||
|     b = bread(1, i); | ||||
| 
 | ||||
|     cprintf("disk 1 sector %d: ", i); | ||||
|     for (j = 0; j < 4; j++) | ||||
|       cprintf("%x ", b->data[j] & 0xff); | ||||
|     cprintf("\n"); | ||||
| 
 | ||||
|     brelse(b); | ||||
|   } | ||||
| 
 | ||||
|   ip = iget(1, 1); | ||||
|   cprintf("%d %d %d %d %d %d %d %d\n", | ||||
|           ip->dev, ip->inum, ip->count, ip->busy, | ||||
|           ip->type, ip->nlink, ip->size, ip->addrs[0]); | ||||
|   iput(ip); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 rtm
						rtm