summaryrefslogtreecommitdiff
path: root/sysfile.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2011-08-15 12:44:20 -0400
committerRobert Morris <[email protected]>2011-08-15 12:44:20 -0400
commit5053dd6a6d2b481bfcddbd91bacc885b9f0e0ff5 (patch)
treeca7d000f9996082466bdfe8c7a0c9667341f2dfa /sysfile.c
parentc95ce31c5978bd43e1f0d34e51a4e3d7bcc41b14 (diff)
downloadxv6-labs-5053dd6a6d2b481bfcddbd91bacc885b9f0e0ff5.tar.gz
xv6-labs-5053dd6a6d2b481bfcddbd91bacc885b9f0e0ff5.tar.bz2
xv6-labs-5053dd6a6d2b481bfcddbd91bacc885b9f0e0ff5.zip
avoid deadlock by calling begin_trans() before locking any inodes
Diffstat (limited to 'sysfile.c')
-rw-r--r--sysfile.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/sysfile.c b/sysfile.c
index ca54013..c9d3594 100644
--- a/sysfile.c
+++ b/sysfile.c
@@ -116,14 +116,16 @@ sys_link(void)
return -1;
if((ip = namei(old)) == 0)
return -1;
+
+ begin_trans();
+
ilock(ip);
if(ip->type == T_DIR){
iunlockput(ip);
+ commit_trans();
return -1;
}
- begin_trans();
-
ip->nlink++;
iupdate(ip);
iunlock(ip);
@@ -180,16 +182,21 @@ sys_unlink(void)
return -1;
if((dp = nameiparent(path, name)) == 0)
return -1;
+
+ begin_trans();
+
ilock(dp);
// Cannot unlink "." or "..".
if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0){
iunlockput(dp);
+ commit_trans();
return -1;
}
if((ip = dirlookup(dp, name, &off)) == 0){
iunlockput(dp);
+ commit_trans();
return -1;
}
ilock(ip);
@@ -199,11 +206,10 @@ sys_unlink(void)
if(ip->type == T_DIR && !isdirempty(ip)){
iunlockput(ip);
iunlockput(dp);
+ commit_trans();
return -1;
}
- begin_trans();
-
memset(&de, 0, sizeof(de));
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
panic("unlink: writei");