every iput() and namei() must be inside a transaction
This commit is contained in:
		
							parent
							
								
									020c8e2384
								
							
						
					
					
						commit
						2c56547272
					
				
					 6 changed files with 145 additions and 17 deletions
				
			
		
							
								
								
									
										10
									
								
								exec.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								exec.c
									
										
									
									
									
								
							| 
						 | 
					@ -18,8 +18,11 @@ exec(char *path, char **argv)
 | 
				
			||||||
  struct proghdr ph;
 | 
					  struct proghdr ph;
 | 
				
			||||||
  pde_t *pgdir, *oldpgdir;
 | 
					  pde_t *pgdir, *oldpgdir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if((ip = namei(path)) == 0)
 | 
					  begin_trans();
 | 
				
			||||||
 | 
					  if((ip = namei(path)) == 0){
 | 
				
			||||||
 | 
					    commit_trans();
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  ilock(ip);
 | 
					  ilock(ip);
 | 
				
			||||||
  pgdir = 0;
 | 
					  pgdir = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +50,7 @@ exec(char *path, char **argv)
 | 
				
			||||||
      goto bad;
 | 
					      goto bad;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  iunlockput(ip);
 | 
					  iunlockput(ip);
 | 
				
			||||||
 | 
					  commit_trans();
 | 
				
			||||||
  ip = 0;
 | 
					  ip = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Allocate two pages at the next page boundary.
 | 
					  // Allocate two pages at the next page boundary.
 | 
				
			||||||
| 
						 | 
					@ -95,7 +99,9 @@ exec(char *path, char **argv)
 | 
				
			||||||
 bad:
 | 
					 bad:
 | 
				
			||||||
  if(pgdir)
 | 
					  if(pgdir)
 | 
				
			||||||
    freevm(pgdir);
 | 
					    freevm(pgdir);
 | 
				
			||||||
  if(ip)
 | 
					  if(ip){
 | 
				
			||||||
    iunlockput(ip);
 | 
					    iunlockput(ip);
 | 
				
			||||||
 | 
					    commit_trans();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  return -1;
 | 
					  return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								fs.c
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								fs.c
									
										
									
									
									
								
							| 
						 | 
					@ -314,6 +314,8 @@ iunlock(struct inode *ip)
 | 
				
			||||||
// be recycled.
 | 
					// be recycled.
 | 
				
			||||||
// If that was the last reference and the inode has no links
 | 
					// If that was the last reference and the inode has no links
 | 
				
			||||||
// to it, free the inode (and its content) on disk.
 | 
					// to it, free the inode (and its content) on disk.
 | 
				
			||||||
 | 
					// All calls to iput() must be inside a transaction in
 | 
				
			||||||
 | 
					// case it has to free the inode.
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
iput(struct inode *ip)
 | 
					iput(struct inode *ip)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -601,6 +603,7 @@ skipelem(char *path, char *name)
 | 
				
			||||||
// Look up and return the inode for a path name.
 | 
					// Look up and return the inode for a path name.
 | 
				
			||||||
// If parent != 0, return the inode for the parent and copy the final
 | 
					// If parent != 0, return the inode for the parent and copy the final
 | 
				
			||||||
// path element into name, which must have room for DIRSIZ bytes.
 | 
					// path element into name, which must have room for DIRSIZ bytes.
 | 
				
			||||||
 | 
					// Must be called inside a transaction since it calls iput().
 | 
				
			||||||
static struct inode*
 | 
					static struct inode*
 | 
				
			||||||
namex(char *path, int nameiparent, char *name)
 | 
					namex(char *path, int nameiparent, char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								log.c
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								log.c
									
										
									
									
									
								
							| 
						 | 
					@ -5,7 +5,7 @@
 | 
				
			||||||
#include "fs.h"
 | 
					#include "fs.h"
 | 
				
			||||||
#include "buf.h"
 | 
					#include "buf.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Simple logging. Each system call that might write the file system
 | 
					// Simple logging. Each file system system call
 | 
				
			||||||
// should be surrounded with begin_trans() and commit_trans() calls.
 | 
					// should be surrounded with begin_trans() and commit_trans() calls.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// The log holds at most one transaction at a time. Commit forces
 | 
					// The log holds at most one transaction at a time. Commit forces
 | 
				
			||||||
| 
						 | 
					@ -18,10 +18,6 @@
 | 
				
			||||||
// one transaction reading a block that another one has modified,
 | 
					// one transaction reading a block that another one has modified,
 | 
				
			||||||
// for example an i-node block.
 | 
					// for example an i-node block.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Read-only system calls don't need to use transactions, though
 | 
					 | 
				
			||||||
// this means that they may observe uncommitted data. I-node and
 | 
					 | 
				
			||||||
// buffer locks prevent read-only calls from seeing inconsistent data.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// The log is a physical re-do log containing disk blocks.
 | 
					// The log is a physical re-do log containing disk blocks.
 | 
				
			||||||
// The on-disk log format:
 | 
					// The on-disk log format:
 | 
				
			||||||
//   header block, containing sector #s for block A, B, C, ...
 | 
					//   header block, containing sector #s for block A, B, C, ...
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								proc.c
									
										
									
									
									
								
							| 
						 | 
					@ -186,7 +186,9 @@ exit(void)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  begin_trans();
 | 
				
			||||||
  iput(proc->cwd);
 | 
					  iput(proc->cwd);
 | 
				
			||||||
 | 
					  commit_trans();
 | 
				
			||||||
  proc->cwd = 0;
 | 
					  proc->cwd = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  acquire(&ptable.lock);
 | 
					  acquire(&ptable.lock);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										35
									
								
								sysfile.c
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								sysfile.c
									
										
									
									
									
								
							| 
						 | 
					@ -120,10 +120,12 @@ sys_link(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
 | 
					  if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
  if((ip = namei(old)) == 0)
 | 
					 | 
				
			||||||
    return -1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  begin_trans();
 | 
					  begin_trans();
 | 
				
			||||||
 | 
					  if((ip = namei(old)) == 0){
 | 
				
			||||||
 | 
					    commit_trans();
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ilock(ip);
 | 
					  ilock(ip);
 | 
				
			||||||
  if(ip->type == T_DIR){
 | 
					  if(ip->type == T_DIR){
 | 
				
			||||||
| 
						 | 
					@ -186,10 +188,12 @@ sys_unlink(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(argstr(0, &path) < 0)
 | 
					  if(argstr(0, &path) < 0)
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
  if((dp = nameiparent(path, name)) == 0)
 | 
					 | 
				
			||||||
    return -1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  begin_trans();
 | 
					  begin_trans();
 | 
				
			||||||
 | 
					  if((dp = nameiparent(path, name)) == 0){
 | 
				
			||||||
 | 
					    commit_trans();
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ilock(dp);
 | 
					  ilock(dp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -286,18 +290,24 @@ sys_open(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
 | 
					  if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  begin_trans();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(omode & O_CREATE){
 | 
					  if(omode & O_CREATE){
 | 
				
			||||||
    begin_trans();
 | 
					 | 
				
			||||||
    ip = create(path, T_FILE, 0, 0);
 | 
					    ip = create(path, T_FILE, 0, 0);
 | 
				
			||||||
    commit_trans();
 | 
					    if(ip == 0){
 | 
				
			||||||
    if(ip == 0)
 | 
					      commit_trans();
 | 
				
			||||||
      return -1;
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    if((ip = namei(path)) == 0)
 | 
					    if((ip = namei(path)) == 0){
 | 
				
			||||||
 | 
					      commit_trans();
 | 
				
			||||||
      return -1;
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    ilock(ip);
 | 
					    ilock(ip);
 | 
				
			||||||
    if(ip->type == T_DIR && omode != O_RDONLY){
 | 
					    if(ip->type == T_DIR && omode != O_RDONLY){
 | 
				
			||||||
      iunlockput(ip);
 | 
					      iunlockput(ip);
 | 
				
			||||||
 | 
					      commit_trans();
 | 
				
			||||||
      return -1;
 | 
					      return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -306,9 +316,11 @@ sys_open(void)
 | 
				
			||||||
    if(f)
 | 
					    if(f)
 | 
				
			||||||
      fileclose(f);
 | 
					      fileclose(f);
 | 
				
			||||||
    iunlockput(ip);
 | 
					    iunlockput(ip);
 | 
				
			||||||
 | 
					    commit_trans();
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  iunlock(ip);
 | 
					  iunlock(ip);
 | 
				
			||||||
 | 
					  commit_trans();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  f->type = FD_INODE;
 | 
					  f->type = FD_INODE;
 | 
				
			||||||
  f->ip = ip;
 | 
					  f->ip = ip;
 | 
				
			||||||
| 
						 | 
					@ -361,15 +373,20 @@ sys_chdir(void)
 | 
				
			||||||
  char *path;
 | 
					  char *path;
 | 
				
			||||||
  struct inode *ip;
 | 
					  struct inode *ip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(argstr(0, &path) < 0 || (ip = namei(path)) == 0)
 | 
					  begin_trans();
 | 
				
			||||||
 | 
					  if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){
 | 
				
			||||||
 | 
					    commit_trans();
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  ilock(ip);
 | 
					  ilock(ip);
 | 
				
			||||||
  if(ip->type != T_DIR){
 | 
					  if(ip->type != T_DIR){
 | 
				
			||||||
    iunlockput(ip);
 | 
					    iunlockput(ip);
 | 
				
			||||||
 | 
					    commit_trans();
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  iunlock(ip);
 | 
					  iunlock(ip);
 | 
				
			||||||
  iput(proc->cwd);
 | 
					  iput(proc->cwd);
 | 
				
			||||||
 | 
					  commit_trans();
 | 
				
			||||||
  proc->cwd = ip;
 | 
					  proc->cwd = ip;
 | 
				
			||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										106
									
								
								usertests.c
									
										
									
									
									
								
							
							
						
						
									
										106
									
								
								usertests.c
									
										
									
									
									
								
							| 
						 | 
					@ -13,6 +13,106 @@ char name[3];
 | 
				
			||||||
char *echoargv[] = { "echo", "ALL", "TESTS", "PASSED", 0 };
 | 
					char *echoargv[] = { "echo", "ALL", "TESTS", "PASSED", 0 };
 | 
				
			||||||
int stdout = 1;
 | 
					int stdout = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// does chdir() call iput(p->cwd) in a transaction?
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					iputtest(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  printf(stdout, "iput test\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if(mkdir("iputdir") < 0){
 | 
				
			||||||
 | 
					    printf(stdout, "mkdir failed\n");
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if(chdir("iputdir") < 0){
 | 
				
			||||||
 | 
					    printf(stdout, "chdir iputdir failed\n");
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if(unlink("../iputdir") < 0){
 | 
				
			||||||
 | 
					    printf(stdout, "unlink ../iputdir failed\n");
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if(chdir("/") < 0){
 | 
				
			||||||
 | 
					    printf(stdout, "chdir / failed\n");
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  printf(stdout, "iput test ok\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// does exit() call iput(p->cwd) in a transaction?
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					exitiputtest(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  printf(stdout, "exitiput test\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pid = fork();
 | 
				
			||||||
 | 
					  if(pid < 0){
 | 
				
			||||||
 | 
					    printf(stdout, "fork failed\n");
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if(pid == 0){
 | 
				
			||||||
 | 
					    if(mkdir("iputdir") < 0){
 | 
				
			||||||
 | 
					      printf(stdout, "mkdir failed\n");
 | 
				
			||||||
 | 
					      exit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(chdir("iputdir") < 0){
 | 
				
			||||||
 | 
					      printf(stdout, "child chdir failed\n");
 | 
				
			||||||
 | 
					      exit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(unlink("../iputdir") < 0){
 | 
				
			||||||
 | 
					      printf(stdout, "unlink ../iputdir failed\n");
 | 
				
			||||||
 | 
					      exit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  wait();
 | 
				
			||||||
 | 
					  printf(stdout, "exitiput test ok\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// does the error path in open() for attempt to write a
 | 
				
			||||||
 | 
					// directory call iput() in a transaction?
 | 
				
			||||||
 | 
					// needs a hacked kernel that pauses just after the namei()
 | 
				
			||||||
 | 
					// call in sys_open():
 | 
				
			||||||
 | 
					//    if((ip = namei(path)) == 0)
 | 
				
			||||||
 | 
					//      return -1;
 | 
				
			||||||
 | 
					//    {
 | 
				
			||||||
 | 
					//      int i;
 | 
				
			||||||
 | 
					//      for(i = 0; i < 10000; i++)
 | 
				
			||||||
 | 
					//        yield();
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					openiputtest(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  printf(stdout, "openiput test\n");
 | 
				
			||||||
 | 
					  if(mkdir("oidir") < 0){
 | 
				
			||||||
 | 
					    printf(stdout, "mkdir oidir failed\n");
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  pid = fork();
 | 
				
			||||||
 | 
					  if(pid < 0){
 | 
				
			||||||
 | 
					    printf(stdout, "fork failed\n");
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if(pid == 0){
 | 
				
			||||||
 | 
					    int fd = open("oidir", O_RDWR);
 | 
				
			||||||
 | 
					    if(fd >= 0){
 | 
				
			||||||
 | 
					      printf(stdout, "open directory for write succeeded\n");
 | 
				
			||||||
 | 
					      exit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  sleep(1);
 | 
				
			||||||
 | 
					  if(unlink("oidir") != 0){
 | 
				
			||||||
 | 
					    printf(stdout, "unlink failed\n");
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  wait();
 | 
				
			||||||
 | 
					  printf(stdout, "openiput test ok\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// simple file system tests
 | 
					// simple file system tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
| 
						 | 
					@ -187,7 +287,7 @@ void dirtest(void)
 | 
				
			||||||
    printf(stdout, "unlink dir0 failed\n");
 | 
					    printf(stdout, "unlink dir0 failed\n");
 | 
				
			||||||
    exit();
 | 
					    exit();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  printf(stdout, "mkdir test\n");
 | 
					  printf(stdout, "mkdir test ok\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
| 
						 | 
					@ -1628,6 +1728,10 @@ main(int argc, char *argv[])
 | 
				
			||||||
  writetest1();
 | 
					  writetest1();
 | 
				
			||||||
  createtest();
 | 
					  createtest();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  openiputtest();
 | 
				
			||||||
 | 
					  exitiputtest();
 | 
				
			||||||
 | 
					  iputtest();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mem();
 | 
					  mem();
 | 
				
			||||||
  pipe1();
 | 
					  pipe1();
 | 
				
			||||||
  preempt();
 | 
					  preempt();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue