diff options
| author | Gustav Sörnäs <gustav@sornas.net> | 2021-03-16 10:31:43 +0100 |
|---|---|---|
| committer | Gustav Sörnäs <gustav@sornas.net> | 2021-03-16 10:31:43 +0100 |
| commit | 6b6af5c6dea1a6011d7e116e6e285111f033a34d (patch) | |
| tree | 74a34e6b6fb4a4eb3b1cc7b21445416fa760459c | |
| parent | d2f11d48b29de49265f1a0d997548074f80fe431 (diff) | |
| download | pintos-6b6af5c6dea1a6011d7e116e6e285111f033a34d.tar.gz | |
lock inode with lock and data with rwlock
| -rw-r--r-- | src/filesys/inode.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/src/filesys/inode.c b/src/filesys/inode.c index b053019..dca5432 100644 --- a/src/filesys/inode.c +++ b/src/filesys/inode.c @@ -32,11 +32,14 @@ bytes_to_sectors (off_t size) /* In-memory inode. */ struct inode { + struct lock lock; /* Lock for inode metadata. */ struct list_elem elem; /* Element in inode list. */ disk_sector_t sector; /* Sector number of disk location. */ int open_cnt; /* Number of openers. */ bool removed; /* True if deleted, false otherwise. */ int deny_write_cnt; /* 0: writes ok, >0: deny writes. */ + + struct rwlock rwlock; /* RwLock for inode_disk data. */ struct inode_disk data; /* Inode content. */ }; @@ -141,13 +144,17 @@ inode_open (disk_sector_t sector) } /* Initialize. */ + lock_init (&inode->lock); + lock_acquire (&inode->lock); list_push_front (&open_inodes, &inode->elem); + lock_release (&open_inodes_lock); inode->sector = sector; inode->open_cnt = 1; inode->deny_write_cnt = 0; inode->removed = false; - lock_release (&open_inodes_lock); // delayed unlock so no one can read the half-initialized inode + rwlock_init (&inode->rwlock); disk_read (filesys_disk, inode->sector, &inode->data); + lock_release (&inode->lock); return inode; } @@ -157,8 +164,10 @@ inode_reopen (struct inode *inode) { if (inode != NULL) { + lock_acquire (&inode->lock); ASSERT(inode->open_cnt != 0); inode->open_cnt++; + lock_release (&inode->lock); } return inode; } @@ -180,9 +189,13 @@ inode_close (struct inode *inode) if (inode == NULL) return; + lock_acquire (&inode->lock); + /* Release resources if this was the last opener. */ - if (--inode->open_cnt == 0) + if (--inode->open_cnt > 0) { + lock_release (&inode->lock); + } else { /* Remove from inode list. */ lock_acquire (&open_inodes_lock); list_remove (&inode->elem); @@ -206,7 +219,9 @@ void inode_remove (struct inode *inode) { ASSERT (inode != NULL); + lock_acquire (&inode->lock); inode->removed = true; + lock_release (&inode->lock); } /* Reads SIZE bytes from INODE into BUFFER, starting at position OFFSET. @@ -219,6 +234,8 @@ inode_read_at (struct inode *inode, void *buffer_, off_t size, off_t offset) off_t bytes_read = 0; uint8_t *bounce = NULL; + rwlock_read_p (&inode->rwlock); + while (size > 0) { /* Disk sector to read, starting byte offset within sector. */ @@ -259,6 +276,8 @@ inode_read_at (struct inode *inode, void *buffer_, off_t size, off_t offset) offset += chunk_size; bytes_read += chunk_size; } + + rwlock_read_v (&inode->rwlock); free (bounce); return bytes_read; @@ -280,6 +299,8 @@ inode_write_at (struct inode *inode, const void *buffer_, off_t size, if (inode->deny_write_cnt) return 0; + rwlock_write_p (&inode->rwlock); + while (size > 0) { /* Sector to write, starting byte offset within sector. */ @@ -327,6 +348,8 @@ inode_write_at (struct inode *inode, const void *buffer_, off_t size, offset += chunk_size; bytes_written += chunk_size; } + + rwlock_write_v (&inode->rwlock); free (bounce); return bytes_written; @@ -337,8 +360,10 @@ inode_write_at (struct inode *inode, const void *buffer_, off_t size, void inode_deny_write (struct inode *inode) { + lock_acquire (&inode->lock); inode->deny_write_cnt++; ASSERT (inode->deny_write_cnt <= inode->open_cnt); + lock_release (&inode->lock); } /* Re-enables writes to INODE. @@ -347,9 +372,11 @@ inode_deny_write (struct inode *inode) void inode_allow_write (struct inode *inode) { + lock_acquire (&inode->lock); ASSERT (inode->deny_write_cnt > 0); ASSERT (inode->deny_write_cnt <= inode->open_cnt); inode->deny_write_cnt--; + lock_release (&inode->lock); } /* Returns the length, in bytes, of INODE's data. */ |
