1 #include "filesys/inode.h"
7 #include "filesys/filesys.h"
8 #include "devices/partition.h"
9 #include "threads/malloc.h"
12 Must be exactly DISK_SECTOR_SIZE bytes long. */
15 off_t length; /* File size in bytes. */
16 disk_sector_t start; /* Starting sector. */
17 uint32_t unused[126]; /* Unused padding. */
20 /* Returns the number of sectors to allocate for a file SIZE
23 bytes_to_sectors (off_t size)
25 return DIV_ROUND_UP (size, DISK_SECTOR_SIZE);
28 /* In-memory inode. */
31 list_elem elem; /* Element in inode list. */
32 disk_sector_t sector; /* Sector number of disk location. */
33 int open_cnt; /* Number of openers. */
34 bool removed; /* True if deleted, false otherwise. */
35 struct inode_disk data; /* On-disk data. */
38 /* List of open inodes, so that opening a single inode twice
39 returns the same `struct inode'. */
40 static struct list open_inodes;
42 static void deallocate_inode (const struct inode *);
44 /* Initializes the inode module. */
48 list_init (&open_inodes);
51 /* Initializes an inode for a file LENGTH bytes in size and
52 writes the new inode to sector SECTOR on the file system
53 disk. Allocates sectors for the file from FREE_MAP.
54 Returns true if successful.
55 Returns false if memory or disk allocation fails. FREE_MAP
56 may be modified regardless. */
58 inode_create (struct bitmap *free_map, disk_sector_t sector, off_t length)
60 static const char zero_sector[DISK_SECTOR_SIZE];
61 struct inode_disk *idx;
65 ASSERT (free_map != NULL);
68 /* Allocate sectors. */
69 start = bitmap_scan_and_flip (free_map, 0, bytes_to_sectors (length), false);
70 if (start == BITMAP_ERROR)
74 idx = calloc (sizeof *idx, 1);
81 partition_write (filesys_partition, sector, idx);
82 for (i = 0; i < bytes_to_sectors (length); i++)
83 partition_write (filesys_partition, idx->start + i, zero_sector);
89 /* Reads an inode from SECTOR
90 and returns a `struct inode' that contains it.
91 Returns a null pointer if memory allocation fails. */
93 inode_open (disk_sector_t sector)
98 /* Check whether this inode is already open.
99 (A hash table would be better, but the Pintos base code
100 avoids using the hash table so that users are free to modify
102 for (e = list_begin (&open_inodes); e != list_end (&open_inodes);
105 idx = list_entry (e, struct inode, elem);
106 if (idx->sector == sector)
113 /* Allocate memory. */
114 idx = calloc (1, sizeof *idx);
119 list_push_front (&open_inodes, &idx->elem);
120 idx->sector = sector;
122 idx->removed = false;
124 /* Read from disk. */
125 ASSERT (sizeof idx->data == DISK_SECTOR_SIZE);
126 partition_read (filesys_partition, sector, &idx->data);
131 /* Closes inode IDX and writes it to disk.
132 If this was the last reference to IDX, frees its memory.
133 If IDX was also a removed inode, frees its blocks. */
135 inode_close (struct inode *idx)
137 /* Ignore null pointer. */
141 /* Release resources if this was the last opener. */
142 if (--idx->open_cnt == 0)
144 /* Deallocate blocks if removed. */
146 deallocate_inode (idx);
148 /* Remove from inode list and free memory. */
149 list_remove (&idx->elem);
154 /* Deallocates the blocks allocated for IDX. */
156 deallocate_inode (const struct inode *idx)
158 struct bitmap *free_map = bitmap_create (partition_size (filesys_partition));
159 if (free_map != NULL)
161 bitmap_read (free_map, free_map_file);
162 bitmap_reset (free_map, idx->sector);
163 bitmap_set_multiple (free_map, idx->data.start,
164 bytes_to_sectors (idx->data.length), false);
165 bitmap_write (free_map, free_map_file);
166 bitmap_destroy (free_map);
169 printf ("inode_close(): can't free blocks");
172 /* Marks IDX to be deleted when it is closed by the last caller who
175 inode_remove (struct inode *idx)
177 ASSERT (idx != NULL);
181 /* Returns the disk sector that contains byte offset POS within
182 the file with inode IDX.
183 Returns -1 if IDX does not contain data for a byte at offset
186 inode_byte_to_sector (const struct inode *idx, off_t pos)
188 ASSERT (idx != NULL);
189 ASSERT (pos < idx->data.length);
190 return idx->data.start + pos / DISK_SECTOR_SIZE;
193 /* Returns the length, in bytes, of the file with inode IDX. */
195 inode_length (const struct inode *idx)
197 ASSERT (idx != NULL);
198 return idx->data.length;
201 /* Prints a representation of IDX to the system console. */
203 inode_print (const struct inode *idx)
205 ASSERT (idx != NULL);
206 printf ("Inode %"PRDSNu": %"PRDSNu" bytes, "
207 "%zu sectors starting at %"PRDSNu"\n",
208 idx->sector, idx->data.length,
209 (size_t) DIV_ROUND_UP (idx->data.length, DISK_SECTOR_SIZE),