302
|
1 #include "types.h"
|
301
|
2 #include "defs.h"
|
302
|
3 #include "param.h"
|
|
4 #include "stat.h"
|
|
5 #include "mmu.h"
|
|
6 #include "proc.h"
|
|
7 #include "spinlock.h"
|
|
8 #include "buf.h"
|
301
|
9 #include "fs.h"
|
302
|
10 #include "file.h"
|
295
|
11 #interface "fs.dg"
|
294
|
12
|
|
13 // ----
|
|
14 // typedef struct fs_impl<Impl, Isa> impl fs{
|
|
15 // union Data* fs_impl;
|
|
16 //
|
|
17 //
|
|
18 //
|
|
19 //
|
|
20 // } fs_impl;
|
|
21 // ----
|
|
22
|
|
23 fs* createfs_impl(struct Context* cbc_context) {
|
|
24 struct fs* fs = new fs();
|
|
25 struct fs_impl* fs_impl = new fs_impl();
|
|
26 fs->fs = (union Data*)fs_impl;
|
|
27 fs_impl->fs_impl = NULL;
|
|
28 fs->readsb = C_readsbfs_impl;
|
|
29 fs->iinit = C_iinitfs_impl;
|
|
30 fs->ialloc = C_iallocfs_impl;
|
302
|
31 fs_impl->allocinode = C_allocinode;
|
|
32 fs_impl->allocinode_loop = C_allocinode_loop;
|
303
|
33 fs_impl->allocinode_loopcheck = C_allocinode_loopcheck;
|
|
34 fs_impl->allocinode_noloop = C_allocinode_noloop;
|
294
|
35 fs->iupdate = C_iupdatefs_impl;
|
|
36 fs->idup = C_idupfs_impl;
|
|
37 fs->ilock = C_ilockfs_impl;
|
306
|
38 fs_impl->lockinode1 = C_lockinode1;
|
307
|
39 fs_impl->lockinode2 = C_lockinode2;
|
306
|
40 fs_impl->lockinode_sleepcheck = C_lockinode_sleepcheck;
|
294
|
41 fs->iunlock = C_iunlockfs_impl;
|
|
42 fs->iput = C_iputfs_impl;
|
307
|
43 fs_impl->iput_check = C_iput_check;
|
|
44 fs_impl->iput_inode_nolink = C_iput_inode_nolink;
|
294
|
45 fs->iunlockput = C_iunlockputfs_impl;
|
|
46 fs->stati = C_statifs_impl;
|
|
47 fs->readi = C_readifs_impl;
|
|
48 fs->writei = C_writeifs_impl;
|
|
49 fs->namecmp = C_namecmpfs_impl;
|
|
50 fs->dirlookup = C_dirlookupfs_impl;
|
296
|
51 fs->dirlink = C_dirlinkfs_impl;
|
294
|
52 fs->namei = C_nameifs_impl;
|
|
53 fs->nameiparent = C_nameiparentfs_impl;
|
|
54 return fs;
|
|
55 }
|
298
|
56
|
299
|
57 typedef struct superblock superblock;
|
296
|
58 __code readsbfs_impl(struct fs_impl* fs, uint dev, struct superblock* sb, __code next(...)) { //:skip
|
294
|
59
|
301
|
60 struct buf* bp;
|
|
61
|
|
62 bp = bread(dev, 1);
|
|
63 memmove(sb, bp->data, sizeof(*sb));
|
|
64 brelse(bp);
|
|
65
|
294
|
66 goto next(...);
|
|
67 }
|
|
68
|
302
|
69 struct {
|
|
70 struct spinlock lock;
|
|
71 struct inode inode[NINODE];
|
|
72 } icache;
|
|
73
|
294
|
74 __code iinitfs_impl(struct fs_impl* fs, __code next(...)) {
|
|
75
|
302
|
76 initlock(&icache.lock, "icache");
|
|
77
|
294
|
78 goto next(...);
|
|
79 }
|
|
80
|
|
81 __code iallocfs_impl(struct fs_impl* fs, uint dev, short type, __code next(...)) {
|
305
|
82 goto allocinode(fs, dev, sb, next(...));
|
294
|
83 }
|
|
84
|
|
85 __code iupdatefs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
|
|
86
|
305
|
87 struct buf *bp;
|
|
88 struct dinode *dip;
|
|
89
|
|
90 bp = bread(ip->dev, IBLOCK(ip->inum));
|
|
91
|
|
92 dip = (struct dinode*) bp->data + ip->inum % IPB;
|
|
93 dip->type = ip->type;
|
|
94 dip->major = ip->major;
|
|
95 dip->minor = ip->minor;
|
|
96 dip->nlink = ip->nlink;
|
|
97 dip->size = ip->size;
|
|
98
|
|
99 memmove(dip->addrs, ip->addrs, sizeof(ip->addrs));
|
|
100 log_write(bp);
|
|
101 brelse(bp);
|
|
102
|
|
103
|
294
|
104 goto next(...);
|
|
105 }
|
|
106
|
|
107 __code idupfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
|
|
108
|
305
|
109 acquire(&icache.lock);
|
|
110 ip->ref++;
|
|
111 release(&icache.lock);
|
|
112
|
|
113 goto next(ip, ...);
|
|
114
|
294
|
115 }
|
|
116
|
|
117 __code ilockfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
|
|
118
|
306
|
119 goto lockinode1(fs, ip, bp, dip, next(...));
|
294
|
120 }
|
|
121
|
|
122 __code iunlockfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
|
307
|
123
|
|
124 if (ip == 0 || !(ip->flags & I_BUSY) || ip->ref < 1) {
|
|
125 /*
|
|
126 panic("iunlock");
|
|
127 goto panic();
|
|
128 */
|
|
129 }
|
|
130
|
|
131 acquire(&icache.lock);
|
|
132 ip->flags &= ~I_BUSY;
|
|
133 wakeup(ip);
|
|
134 release(&icache.lock);
|
294
|
135
|
|
136 goto next(...);
|
|
137 }
|
|
138
|
|
139 __code iputfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
|
|
140
|
307
|
141 goto iput_check(fs, ip, next(...));
|
|
142
|
294
|
143 }
|
|
144
|
|
145 __code iunlockputfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
|
|
146
|
|
147 goto next(...);
|
|
148 }
|
|
149
|
299
|
150 typedef struct stat stat;
|
296
|
151 __code statifs_impl(struct fs_impl* fs , struct inode* ip, struct stat* st, __code next(...)) { //:skip
|
308
|
152 st->dev = ip->dev;
|
|
153 st->ino = ip->inum;
|
|
154 st->type = ip->type;
|
|
155 st->nlink = ip->nlink;
|
|
156 st->size = ip->size;
|
294
|
157 goto next(...);
|
|
158 }
|
|
159
|
|
160 __code readifs_impl(struct fs_impl* fs, struct inode* ip, char* dst, uint off, uint n, __code next(...)) {
|
|
161
|
|
162 goto next(...);
|
|
163 }
|
|
164
|
|
165 __code writeifs_impl(struct fs_impl* fs, struct inode* ip, char* src, uint off, uint n, __code next(...)) {
|
|
166
|
|
167 goto next(...);
|
|
168 }
|
|
169
|
310
|
170 __code namecmpfs_impl(struct fs_impl* fs, const char* s, const char* t, __code next(int strncmp_val, ...)) {
|
|
171 strncmp_val = strncmp(s, t, DIRSIZ);
|
|
172 goto next(strncmp_val, ...);
|
294
|
173 }
|
|
174
|
312
|
175 __code dirlookupfs_impl(struct fs_impl* fs, struct inode* dp, char* name, uint off, uint* poff, dirent* de, __code next(...)) { //:skip
|
311
|
176 if (dp->type != T_DIR) {
|
|
177 /*
|
|
178 panic("dirlookup not DIR");
|
|
179 */
|
|
180 }
|
312
|
181 Gearef(cbc_context, fs)->off = 0;
|
|
182 goto dirlookup_loopcheck(fs, dp, name, off, poff, de, next(...));
|
294
|
183 }
|
|
184
|
296
|
185 __code dirlinkfs_impl(struct fs_impl* fs, struct inode* dp, char* name, uint inum, __code next(...)) {
|
294
|
186
|
296
|
187 goto next(...);
|
294
|
188 }
|
|
189
|
309
|
190 static struct inode* iget (uint dev, uint inum)
|
|
191 {
|
|
192 struct inode *ip, *empty;
|
|
193
|
|
194 acquire(&icache.lock);
|
|
195
|
|
196 // Is the inode already cached?
|
|
197 empty = 0;
|
|
198
|
|
199 for (ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++) {
|
|
200 if (ip->ref > 0 && ip->dev == dev && ip->inum == inum) {
|
|
201 ip->ref++;
|
|
202 release(&icache.lock);
|
|
203 return ip;
|
|
204 }
|
|
205
|
|
206 if (empty == 0 && ip->ref == 0) { // Remember empty slot.
|
|
207 empty = ip;
|
|
208 }
|
|
209 }
|
|
210
|
|
211 // Recycle an inode cache entry.
|
|
212 if (empty == 0) {
|
|
213 panic("iget: no inodes");
|
|
214 }
|
|
215
|
|
216 ip = empty;
|
|
217 ip->dev = dev;
|
|
218 ip->inum = inum;
|
|
219 ip->ref = 1;
|
|
220 ip->flags = 0;
|
|
221 release(&icache.lock);
|
|
222
|
|
223 return ip;
|
|
224 }
|
308
|
225
|
|
226 static char* skipelem (char *path, char *name)
|
|
227 {
|
|
228 char *s;
|
|
229 int len;
|
|
230
|
|
231 while (*path == '/') {
|
|
232 path++;
|
|
233 }
|
|
234
|
|
235 if (*path == 0) {
|
|
236 return 0;
|
|
237 }
|
|
238
|
|
239 s = path;
|
294
|
240
|
308
|
241 while (*path != '/' && *path != 0) {
|
|
242 path++;
|
|
243 }
|
|
244
|
|
245 len = path - s;
|
|
246
|
|
247 if (len >= DIRSIZ) {
|
|
248 memmove(name, s, DIRSIZ);
|
|
249 } else {
|
|
250 memmove(name, s, len);
|
|
251 name[len] = 0;
|
|
252 }
|
|
253
|
|
254 while (*path == '/') {
|
|
255 path++;
|
|
256 }
|
|
257
|
|
258 return path;
|
294
|
259 }
|
|
260
|
308
|
261
|
|
262 static struct inode* namex (char *path, int nameiparent, char *name)
|
|
263 {
|
|
264 struct inode *ip, *next;
|
|
265
|
|
266 if (*path == '/') {
|
|
267 ip = iget(ROOTDEV, ROOTINO);
|
|
268 } else {
|
|
269 ip = idup(proc->cwd);
|
|
270 }
|
|
271
|
|
272 while ((path = skipelem(path, name)) != 0) {
|
|
273 ilock(ip);
|
|
274
|
|
275 if (ip->type != T_DIR) {
|
|
276 iunlockput(ip);
|
|
277 return 0;
|
|
278 }
|
294
|
279
|
308
|
280 if (nameiparent && *path == '\0') {
|
|
281 // Stop one level early.
|
|
282 iunlock(ip);
|
|
283 return ip;
|
|
284 }
|
|
285
|
|
286 if ((next = dirlookup(ip, name, 0)) == 0) {
|
|
287 iunlockput(ip);
|
|
288 return 0;
|
|
289 }
|
|
290
|
|
291 iunlockput(ip);
|
|
292 ip = next;
|
|
293 }
|
|
294
|
|
295 if (nameiparent) {
|
|
296 iput(ip);
|
|
297 return 0;
|
|
298 }
|
|
299
|
|
300 return ip;
|
294
|
301 }
|
|
302
|
308
|
303 __code nameifs_impl(struct fs_impl* fs, char* path, __code next(int namex_val, ...)) {
|
|
304 char name[DIRSIZ];
|
|
305 namex_val = namex(path, 0, name);
|
|
306 goto next(namex_val, ...);
|
|
307 }
|
|
308
|
|
309 __code nameiparentfs_impl(struct fs_impl* fs, char* path, char* name, __code next(int namex_val, ...)) {
|
|
310
|
|
311 namex_val = namex(path, 1, name);
|
|
312 goto next(namex_val, ...);
|
|
313
|
|
314 }
|
|
315
|