1 #include "filesys/inode.h"
7 #include "filesys/filesys.h"
8 #include "threads/malloc.h"
11 Must be exactly DISK_SECTOR_SIZE bytes long. */
14 off_t length; /* File size in bytes. */
15 disk_sector_t first_sector; /* Starting sector. */
16 uint32_t unused[126]; /* Unused padding. */
19 /* In-memory inode. */
22 list_elem elem; /* Element in inode list. */
23 disk_sector_t sector; /* Sector number of disk location. */
24 int open_cnt; /* Number of openers. */
25 bool removed; /* True if deleted, false otherwise. */
26 struct inode_disk data; /* On-disk data. */
29 /* List of open inodes, so that opening a single inode twice
30 returns the same `struct inode'. */
31 struct list open_inodes;
33 static struct inode *alloc_inode (disk_sector_t);
35 /* Initializes the inode module. */
39 list_init (&open_inodes);
42 /* Allocates sectors from bitmap B for the content of a file
43 whose size is LENGTH bytes, and returns a new `struct inode'
44 properly initialized for the file.
45 It is the caller's responsible to write the inode to disk with
46 inode_commit(), as well as the bitmap.
47 If memory or disk allocation fails, returns a null pointer,
48 leaving bitmap B is unchanged. */
50 inode_create (struct bitmap *b, disk_sector_t sector, off_t length)
59 idx = alloc_inode (sector);
63 /* Allocate disk sectors. */
64 sector_cnt = DIV_ROUND_UP (length, DISK_SECTOR_SIZE);
65 idx->data.length = length;
66 idx->data.first_sector = bitmap_scan_and_flip (b, 0, sector_cnt, false);
67 if (idx->data.first_sector == BITMAP_ERROR)
70 /* Zero out the file contents. */
73 static const char zero_sector[DISK_SECTOR_SIZE];
76 for (i = 0; i < sector_cnt; i++)
77 disk_write (filesys_disk, idx->data.first_sector + i, zero_sector);
88 /* Reads an inode from SECTOR
89 and returns a `struct inode' that contains it.
90 Returns a null pointer if memory allocation fails. */
92 inode_open (disk_sector_t sector)
97 /* Check whether this inode is already open.
98 (A hash table would be better, but the Pintos base code
99 avoids using the hash table so that users are free to modify
101 for (e = list_begin (&open_inodes); e != list_end (&open_inodes);
104 idx = list_entry (e, struct inode, elem);
105 if (idx->sector == sector)
112 /* Allocate inode. */
113 idx = alloc_inode (sector);
117 /* Read from disk. */
118 ASSERT (sizeof idx->data == DISK_SECTOR_SIZE);
119 disk_read (filesys_disk, sector, &idx->data);
124 /* Closes inode IDX and writes it to disk.
125 If this was the last reference to IDX, frees its memory.
126 If IDX was also a removed inode, frees its blocks. */
128 inode_close (struct inode *idx)
133 if (--idx->open_cnt == 0)
137 struct bitmap *free_map;
139 free_map = bitmap_create (disk_size (filesys_disk));
140 if (free_map != NULL)
142 disk_sector_t start, end;
144 bitmap_read (free_map, free_map_file);
146 /* Reset inode sector bit. */
147 bitmap_reset (free_map, idx->sector);
149 /* Reset inode data sector bits. */
150 start = idx->data.first_sector;
151 end = start + DIV_ROUND_UP (idx->data.length, DISK_SECTOR_SIZE);
152 bitmap_set_multiple (free_map, start, end, false);
154 bitmap_write (free_map, free_map_file);
155 bitmap_destroy (free_map);
158 printf ("inode_close(): can't free blocks");
160 list_remove (&idx->elem);
165 /* Writes IDX to disk. */
167 inode_commit (const struct inode *idx)
169 ASSERT (idx != NULL);
170 ASSERT (sizeof idx->data == DISK_SECTOR_SIZE);
171 disk_write (filesys_disk, idx->sector, &idx->data);
174 /* Marks IDX to be deleted when it is closed by the last caller who
177 inode_remove (struct inode *idx)
179 ASSERT (idx != NULL);
183 /* Returns the disk sector that contains byte offset POS within
184 the file with inode IDX.
185 Returns -1 if IDX does not contain data for a byte at offset
188 inode_byte_to_sector (const struct inode *idx, off_t pos)
190 ASSERT (idx != NULL);
192 if (pos < idx->data.length)
193 return idx->data.first_sector + pos / DISK_SECTOR_SIZE;
195 return (disk_sector_t) -1;
198 /* Returns the length, in bytes, of the file with inode IDX. */
200 inode_length (const struct inode *idx)
202 ASSERT (idx != NULL);
203 return idx->data.length;
206 /* Prints a representation of IDX to the system console. */
208 inode_print (const struct inode *idx)
210 printf ("Inode %"PRDSNu": %"PRDSNu" bytes, "
211 "%zu sectors starting at %"PRDSNu"\n",
212 idx->sector, idx->data.length,
213 (size_t) DIV_ROUND_UP (idx->data.length, DISK_SECTOR_SIZE),
214 idx->data.first_sector);
217 /* Returns a newly allocated and initialized inode. */
218 static struct inode *
219 alloc_inode (disk_sector_t sector)
221 /* Allocate memory. */
222 struct inode *idx = calloc (1, sizeof *idx);
227 list_push_front (&open_inodes, &idx->elem);
228 idx->sector = sector;
230 idx->removed = false;