diff options
author | rtm <rtm> | 2006-08-13 12:22:44 +0000 |
---|---|---|
committer | rtm <rtm> | 2006-08-13 12:22:44 +0000 |
commit | 211ff0c67ea6737853cf932313cf4e27cc15f55c (patch) | |
tree | e28f2e9f39ddc226203c16e955337216bbdab7f5 /fd.c | |
parent | c372e8dc348e4bb30aae7642db92ecbeedbc83ab (diff) | |
download | xv6-labs-211ff0c67ea6737853cf932313cf4e27cc15f55c.tar.gz xv6-labs-211ff0c67ea6737853cf932313cf4e27cc15f55c.tar.bz2 xv6-labs-211ff0c67ea6737853cf932313cf4e27cc15f55c.zip |
namei returns locked parent dir inode for create / unlink
don't hold fd table lock across idecref() (latter does block i/o)
idecref calls iput() in case last ref -> freeing inode
dir size is 512 * # blocks, so readi/writei &c work
unlink deletes dirent even if ip->nlink > 0
Diffstat (limited to 'fd.c')
-rw-r--r-- | fd.c | 20 |
1 files changed, 12 insertions, 8 deletions
@@ -108,18 +108,22 @@ fd_close(struct fd *fd) panic("fd_close"); if(--fd->ref == 0){ - if(fd->type == FD_PIPE){ - pipe_close(fd->pipe, fd->writeable); - } else if(fd->type == FD_FILE){ - idecref(fd->ip); + struct fd dummy = *fd; + + fd->ref = 0; + fd->type = FD_CLOSED; + release(&fd_table_lock); + + if(dummy.type == FD_PIPE){ + pipe_close(dummy.pipe, dummy.writeable); + } else if(dummy.type == FD_FILE){ + idecref(dummy.ip); } else { panic("fd_close"); } - fd->ref = 0; - fd->type = FD_CLOSED; + } else { + release(&fd_table_lock); } - - release(&fd_table_lock); } int |