00001 #include "filesys/inode.h"
00002
00003 #include <list.h>
00004 #include <debug.h>
00005 #include <round.h>
00006 #include <string.h>
00007 #include "filesys/filesys.h"
00008 #include "filesys/free-map.h"
00009 #include "threads/malloc.h"
00010
00011
00012 #define INODE_MAGIC 0x494e4f44
00013
00014
00015
00016 struct inode_disk
00017 {
00018 block_sector_t start;
00019 off_t length;
00020 unsigned magic;
00021 uint32_t unused[125];
00022 };
00023
00024
00025
00026 static inline size_t
00027 bytes_to_sectors (off_t size)
00028 {
00029 return DIV_ROUND_UP (size, BLOCK_SECTOR_SIZE);
00030 }
00031
00032
00033 struct inode
00034 {
00035 struct list_elem elem;
00036 block_sector_t sector;
00037 int open_cnt;
00038 bool removed;
00039 int deny_write_cnt;
00040 struct inode_disk data;
00041 };
00042
00043
00044
00045
00046
00047 static block_sector_t
00048 byte_to_sector (const struct inode *inode, off_t pos)
00049 {
00050 ASSERT (inode != NULL);
00051 if (pos < inode->data.length)
00052 return inode->data.start + pos / BLOCK_SECTOR_SIZE;
00053 else
00054 return -1;
00055 }
00056
00057
00058
00059 static struct list open_inodes;
00060
00061
00062 void
00063 inode_init (void)
00064 {
00065 list_init (&open_inodes);
00066 }
00067
00068
00069
00070
00071
00072
00073 bool
00074 inode_create (block_sector_t sector, off_t length)
00075 {
00076 struct inode_disk *disk_inode = NULL;
00077 bool success = false;
00078
00079 ASSERT (length >= 0);
00080
00081
00082
00083 ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);
00084
00085 disk_inode = calloc (1, sizeof *disk_inode);
00086 if (disk_inode != NULL)
00087 {
00088 size_t sectors = bytes_to_sectors (length);
00089 disk_inode->length = length;
00090 disk_inode->magic = INODE_MAGIC;
00091 if (free_map_allocate (sectors, &disk_inode->start))
00092 {
00093 block_write (fs_device, sector, disk_inode);
00094 if (sectors > 0)
00095 {
00096 static char zeros[BLOCK_SECTOR_SIZE];
00097 size_t i;
00098
00099 for (i = 0; i < sectors; i++)
00100 block_write (fs_device, disk_inode->start + i, zeros);
00101 }
00102 success = true;
00103 }
00104 free (disk_inode);
00105 }
00106 return success;
00107 }
00108
00109
00110
00111
00112 struct inode *
00113 inode_open (block_sector_t sector)
00114 {
00115 struct list_elem *e;
00116 struct inode *inode;
00117
00118
00119 for (e = list_begin (&open_inodes); e != list_end (&open_inodes);
00120 e = list_next (e))
00121 {
00122 inode = list_entry (e, struct inode, elem);
00123 if (inode->sector == sector)
00124 {
00125 inode_reopen (inode);
00126 return inode;
00127 }
00128 }
00129
00130
00131 inode = malloc (sizeof *inode);
00132 if (inode == NULL)
00133 return NULL;
00134
00135
00136 list_push_front (&open_inodes, &inode->elem);
00137 inode->sector = sector;
00138 inode->open_cnt = 1;
00139 inode->deny_write_cnt = 0;
00140 inode->removed = false;
00141 block_read (fs_device, inode->sector, &inode->data);
00142 return inode;
00143 }
00144
00145
00146 struct inode *
00147 inode_reopen (struct inode *inode)
00148 {
00149 if (inode != NULL)
00150 inode->open_cnt++;
00151 return inode;
00152 }
00153
00154
00155 block_sector_t
00156 inode_get_inumber (const struct inode *inode)
00157 {
00158 return inode->sector;
00159 }
00160
00161
00162
00163
00164 void
00165 inode_close (struct inode *inode)
00166 {
00167
00168 if (inode == NULL)
00169 return;
00170
00171
00172 if (--inode->open_cnt == 0)
00173 {
00174
00175 list_remove (&inode->elem);
00176
00177
00178 if (inode->removed)
00179 {
00180 free_map_release (inode->sector, 1);
00181 free_map_release (inode->data.start,
00182 bytes_to_sectors (inode->data.length));
00183 }
00184
00185 free (inode);
00186 }
00187 }
00188
00189
00190
00191 void
00192 inode_remove (struct inode *inode)
00193 {
00194 ASSERT (inode != NULL);
00195 inode->removed = true;
00196 }
00197
00198
00199
00200
00201 off_t
00202 inode_read_at (struct inode *inode, void *buffer_, off_t size, off_t offset)
00203 {
00204 uint8_t *buffer = buffer_;
00205 off_t bytes_read = 0;
00206 uint8_t *bounce = NULL;
00207
00208 while (size > 0)
00209 {
00210
00211 block_sector_t sector_idx = byte_to_sector (inode, offset);
00212 int sector_ofs = offset % BLOCK_SECTOR_SIZE;
00213
00214
00215 off_t inode_left = inode_length (inode) - offset;
00216 int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
00217 int min_left = inode_left < sector_left ? inode_left : sector_left;
00218
00219
00220 int chunk_size = size < min_left ? size : min_left;
00221 if (chunk_size <= 0)
00222 break;
00223
00224 if (sector_ofs == 0 && chunk_size == BLOCK_SECTOR_SIZE)
00225 {
00226
00227 block_read (fs_device, sector_idx, buffer + bytes_read);
00228 }
00229 else
00230 {
00231
00232
00233 if (bounce == NULL)
00234 {
00235 bounce = malloc (BLOCK_SECTOR_SIZE);
00236 if (bounce == NULL)
00237 break;
00238 }
00239 block_read (fs_device, sector_idx, bounce);
00240 memcpy (buffer + bytes_read, bounce + sector_ofs, chunk_size);
00241 }
00242
00243
00244 size -= chunk_size;
00245 offset += chunk_size;
00246 bytes_read += chunk_size;
00247 }
00248 free (bounce);
00249
00250 return bytes_read;
00251 }
00252
00253
00254
00255
00256
00257
00258 off_t
00259 inode_write_at (struct inode *inode, const void *buffer_, off_t size,
00260 off_t offset)
00261 {
00262 const uint8_t *buffer = buffer_;
00263 off_t bytes_written = 0;
00264 uint8_t *bounce = NULL;
00265
00266 if (inode->deny_write_cnt)
00267 return 0;
00268
00269 while (size > 0)
00270 {
00271
00272 block_sector_t sector_idx = byte_to_sector (inode, offset);
00273 int sector_ofs = offset % BLOCK_SECTOR_SIZE;
00274
00275
00276 off_t inode_left = inode_length (inode) - offset;
00277 int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
00278 int min_left = inode_left < sector_left ? inode_left : sector_left;
00279
00280
00281 int chunk_size = size < min_left ? size : min_left;
00282 if (chunk_size <= 0)
00283 break;
00284
00285 if (sector_ofs == 0 && chunk_size == BLOCK_SECTOR_SIZE)
00286 {
00287
00288 block_write (fs_device, sector_idx, buffer + bytes_written);
00289 }
00290 else
00291 {
00292
00293 if (bounce == NULL)
00294 {
00295 bounce = malloc (BLOCK_SECTOR_SIZE);
00296 if (bounce == NULL)
00297 break;
00298 }
00299
00300
00301
00302
00303 if (sector_ofs > 0 || chunk_size < sector_left)
00304 block_read (fs_device, sector_idx, bounce);
00305 else
00306 memset (bounce, 0, BLOCK_SECTOR_SIZE);
00307 memcpy (bounce + sector_ofs, buffer + bytes_written, chunk_size);
00308 block_write (fs_device, sector_idx, bounce);
00309 }
00310
00311
00312 size -= chunk_size;
00313 offset += chunk_size;
00314 bytes_written += chunk_size;
00315 }
00316 free (bounce);
00317
00318 return bytes_written;
00319 }
00320
00321
00322
00323 void
00324 inode_deny_write (struct inode *inode)
00325 {
00326 inode->deny_write_cnt++;
00327 ASSERT (inode->deny_write_cnt <= inode->open_cnt);
00328 }
00329
00330
00331
00332
00333 void
00334 inode_allow_write (struct inode *inode)
00335 {
00336 ASSERT (inode->deny_write_cnt > 0);
00337 ASSERT (inode->deny_write_cnt <= inode->open_cnt);
00338 inode->deny_write_cnt--;
00339 }
00340
00341
00342 off_t
00343 inode_length (const struct inode *inode)
00344 {
00345 return inode->data.length;
00346 }