This source file includes following definitions.
- UMSDOS_put_inode
- UMSDOS_put_super
- UMSDOS_statfs
- umsdos_real_lookup
- umsdos_setup_dir_inode
- umsdos_set_dirinfo
- umsdos_isinit
- umsdos_patch_inode
- umsdos_get_dirowner
- UMSDOS_read_inode
- UMSDOS_write_inode
- UMSDOS_notify_change
- UMSDOS_read_super
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9 #include <linux/module.h>
10
11 #include <linux/fs.h>
12 #include <linux/msdos_fs.h>
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
15 #include <linux/errno.h>
16 #include <asm/segment.h>
17 #include <linux/string.h>
18 #include <linux/stat.h>
19 #include <linux/umsdos_fs.h>
20
21 struct inode *pseudo_root=NULL;
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #define PRINTK(x)
36 #define Printk(x) printk x
37
38
39 void UMSDOS_put_inode(struct inode *inode)
40 {
41 PRINTK (("put inode %x owner %x pos %d dir %x\n",inode
42 ,inode->u.umsdos_i.i_emd_owner,inode->u.umsdos_i.pos
43 ,inode->u.umsdos_i.i_emd_dir));
44 if (inode != NULL && inode == pseudo_root){
45 printk ("Umsdos: Oops releasing pseudo_root. Notify jacques@solucorp.qc.ca\n");
46 }
47 msdos_put_inode(inode);
48 }
49
50
51 void UMSDOS_put_super(struct super_block *sb)
52 {
53 msdos_put_super(sb);
54 MOD_DEC_USE_COUNT;
55 }
56
57
58 void UMSDOS_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
59 {
60 msdos_statfs(sb,buf,bufsiz);
61 }
62
63
64
65
66
67
68 int umsdos_real_lookup (
69 struct inode *dir,
70 const char *name,
71 int len,
72 struct inode **result)
73 {
74 int ret;
75 dir->i_count++;
76 ret = msdos_lookup (dir,name,len,result);
77 return ret;
78 }
79
80
81
82
83
84
85 void umsdos_setup_dir_inode (struct inode *inode)
86 {
87 inode->u.umsdos_i.i_emd_dir = 0;
88 {
89 struct inode *emd_dir = umsdos_emd_dir_lookup (inode,0);
90 extern struct inode_operations umsdos_rdir_inode_operations;
91 inode->i_op = emd_dir != NULL
92 ? &umsdos_dir_inode_operations
93 : &umsdos_rdir_inode_operations;
94 iput (emd_dir);
95 }
96 }
97
98
99
100 void umsdos_set_dirinfo(
101 struct inode *inode,
102 struct inode *dir,
103 off_t f_pos)
104 {
105 struct inode *emd_owner = umsdos_emd_dir_lookup(dir,1);
106 inode->u.umsdos_i.i_dir_owner = dir->i_ino;
107 inode->u.umsdos_i.i_emd_owner = emd_owner->i_ino;
108 iput (emd_owner);
109 inode->u.umsdos_i.pos = f_pos;
110 }
111
112
113
114
115 int umsdos_isinit (struct inode *inode)
116 {
117 #if 1
118 return inode->u.umsdos_i.i_emd_owner != 0;
119 #elif 0
120 return inode->i_atime != 0;
121 #else
122 return inode->i_count > 1;
123 #endif
124 }
125
126
127
128 void umsdos_patch_inode (
129 struct inode *inode,
130 struct inode *dir,
131 off_t f_pos)
132 {
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 if (!umsdos_isinit(inode)){
150 inode->u.umsdos_i.i_emd_dir = 0;
151 if (S_ISREG(inode->i_mode)){
152 if (inode->i_op->bmap != NULL){
153 inode->i_op = &umsdos_file_inode_operations;
154 }else{
155 inode->i_op = &umsdos_file_inode_operations_no_bmap;
156 }
157 }else if (S_ISDIR(inode->i_mode)){
158 if (dir != NULL){
159 umsdos_setup_dir_inode(inode);
160 }
161 }else if (S_ISLNK(inode->i_mode)){
162 inode->i_op = &umsdos_symlink_inode_operations;
163 }else if (S_ISCHR(inode->i_mode)){
164 inode->i_op = &chrdev_inode_operations;
165 }else if (S_ISBLK(inode->i_mode)){
166 inode->i_op = &blkdev_inode_operations;
167 }else if (S_ISFIFO(inode->i_mode)){
168 init_fifo(inode);
169 }
170 if (dir != NULL){
171
172
173
174
175
176
177
178
179
180
181 umsdos_set_dirinfo (inode,dir,f_pos);
182 }
183 }else if (dir != NULL){
184
185
186
187
188 struct inode *emd_owner = umsdos_emd_dir_lookup(dir,1);
189 iput (emd_owner);
190 if (emd_owner->i_ino != inode->u.umsdos_i.i_emd_owner){
191 printk ("UMSDOS: *** EMD_OWNER ??? *** ino = %ld %ld <> %ld "
192 ,inode->i_ino,emd_owner->i_ino,inode->u.umsdos_i.i_emd_owner);
193 }
194 }
195 }
196
197
198
199
200 int umsdos_get_dirowner(
201 struct inode *inode,
202 struct inode **result)
203
204 {
205 int ret = -EIO;
206 unsigned long ino = inode->u.umsdos_i.i_dir_owner;
207 *result = NULL;
208 if (ino == 0){
209 printk ("UMSDOS: umsdos_get_dirowner ino == 0\n");
210 }else{
211 struct inode *dir = *result = iget(inode->i_sb,ino);
212 if (dir != NULL){
213 umsdos_patch_inode (dir,NULL,0);
214 ret = 0;
215 }
216 }
217 return ret;
218 }
219
220
221
222 void UMSDOS_read_inode(struct inode *inode)
223 {
224 PRINTK (("read inode %x ino = %d ",inode,inode->i_ino));
225 msdos_read_inode(inode);
226 PRINTK (("ino = %d %d\n",inode->i_ino,inode->i_count));
227 if (S_ISDIR(inode->i_mode)
228 && (inode->u.umsdos_i.u.dir_info.creating != 0
229 || inode->u.umsdos_i.u.dir_info.looking != 0
230 || inode->u.umsdos_i.u.dir_info.p != NULL)){
231 Printk (("read inode %d %d %p\n"
232 ,inode->u.umsdos_i.u.dir_info.creating
233 ,inode->u.umsdos_i.u.dir_info.looking
234 ,inode->u.umsdos_i.u.dir_info.p));
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249 umsdos_patch_inode(inode,NULL,0);
250 }
251
252
253
254
255 void UMSDOS_write_inode(struct inode *inode)
256 {
257 struct iattr newattrs;
258
259 PRINTK (("UMSDOS_write_inode emd %d\n",inode->u.umsdos_i.i_emd_owner));
260 msdos_write_inode(inode);
261 newattrs.ia_mtime = inode->i_mtime;
262 newattrs.ia_atime = inode->i_atime;
263 newattrs.ia_ctime = inode->i_ctime;
264 newattrs.ia_valid = ATTR_MTIME | ATTR_ATIME | ATTR_CTIME;
265
266
267
268
269
270 UMSDOS_notify_change (inode, &newattrs);
271 inode->i_dirt = 0;
272 }
273
274 int UMSDOS_notify_change(struct inode *inode, struct iattr *attr)
275 {
276 int ret = 0;
277
278 if ((ret = inode_change_ok(inode, attr)) != 0)
279 return ret;
280
281 if (inode->i_nlink > 0){
282
283
284
285
286
287 unsigned long i_emd_owner = inode->u.umsdos_i.i_emd_owner;
288 if (inode == inode->i_sb->s_mounted){
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 }else if (i_emd_owner != 0xffffffff && i_emd_owner != 0){
304
305
306
307
308 struct inode *emd_owner = iget (inode->i_sb,i_emd_owner);
309 PRINTK (("notify change %p ",inode));
310 if (emd_owner == NULL){
311 printk ("UMSDOS: emd_owner = NULL ???");
312 ret = -EPERM;
313 }else{
314 struct file filp;
315 struct umsdos_dirent entry;
316 filp.f_pos = inode->u.umsdos_i.pos;
317 filp.f_reada = 0;
318 PRINTK (("pos = %d ",filp.f_pos));
319
320
321 ret = umsdos_emd_dir_read (emd_owner,&filp,(char*)&entry
322 ,UMSDOS_REC_SIZE);
323 if (ret == 0){
324 if (attr->ia_valid & ATTR_UID)
325 entry.uid = attr->ia_uid;
326 if (attr->ia_valid & ATTR_GID)
327 entry.gid = attr->ia_gid;
328 if (attr->ia_valid & ATTR_MODE)
329 entry.mode = attr->ia_mode;
330 if (attr->ia_valid & ATTR_ATIME)
331 entry.atime = attr->ia_atime;
332 if (attr->ia_valid & ATTR_MTIME)
333 entry.mtime = attr->ia_mtime;
334 if (attr->ia_valid & ATTR_CTIME)
335 entry.ctime = attr->ia_ctime;
336
337 entry.nlink = inode->i_nlink;
338 filp.f_pos = inode->u.umsdos_i.pos;
339 ret = umsdos_emd_dir_write (emd_owner,&filp,(char*)&entry
340 ,UMSDOS_REC_SIZE);
341
342 PRINTK (("notify pos %d ret %d nlink %d "
343 ,inode->u.umsdos_i.pos
344 ,ret,entry.nlink));
345
346
347
348
349 }
350 iput (emd_owner);
351 }
352 PRINTK (("\n"));
353 }
354 }
355 if (ret == 0)
356 inode_setattr(inode, attr);
357 return ret;
358 }
359
360
361
362
363
364
365
366
367
368
369 static struct super_operations umsdos_sops = {
370 UMSDOS_read_inode,
371 UMSDOS_notify_change,
372 UMSDOS_write_inode,
373 UMSDOS_put_inode,
374 UMSDOS_put_super,
375 NULL,
376 UMSDOS_statfs,
377 NULL
378 };
379
380
381
382
383 struct super_block *UMSDOS_read_super(
384 struct super_block *s,
385 void *data,
386 int silent)
387 {
388
389
390
391
392
393
394
395
396
397
398
399
400
401 struct super_block *sb;
402 MOD_INC_USE_COUNT;
403 sb = msdos_read_super(s,data,silent);
404 printk ("UMSDOS Beta 0.6 (compatibility level %d.%d, fast msdos)\n"
405 ,UMSDOS_VERSION,UMSDOS_RELEASE);
406 if (sb != NULL){
407 MSDOS_SB(sb)->dotsOK = 0;
408 sb->s_op = &umsdos_sops;
409 PRINTK (("umsdos_read_super %p\n",sb->s_mounted));
410 umsdos_setup_dir_inode (sb->s_mounted);
411 PRINTK (("End umsdos_read_super\n"));
412 if (s == super_blocks){
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444 struct inode *pseudo;
445 Printk (("Mounting root\n"));
446 if (umsdos_real_lookup (sb->s_mounted,UMSDOS_PSDROOT_NAME
447 ,UMSDOS_PSDROOT_LEN,&pseudo)==0
448 && S_ISDIR(pseudo->i_mode)){
449 struct inode *etc = NULL;
450 struct inode *sbin = NULL;
451 int pseudo_ok = 0;
452 Printk (("/%s is there\n",UMSDOS_PSDROOT_NAME));
453 if (umsdos_real_lookup (pseudo,"etc",3,&etc)==0
454 && S_ISDIR(etc->i_mode)){
455 struct inode *init = NULL;
456 struct inode *rc = NULL;
457 Printk (("/%s/etc is there\n",UMSDOS_PSDROOT_NAME));
458 if ((umsdos_real_lookup (etc,"init",4,&init)==0
459 && S_ISREG(init->i_mode))
460 || (umsdos_real_lookup (etc,"rc",2,&rc)==0
461 && S_ISREG(rc->i_mode))){
462 pseudo_ok = 1;
463 }
464 iput (init);
465 iput (rc);
466 }
467 if (!pseudo_ok
468 && umsdos_real_lookup (pseudo,"sbin",4,&sbin)==0
469 && S_ISDIR(sbin->i_mode)){
470 struct inode *init = NULL;
471 Printk (("/%s/sbin is there\n",UMSDOS_PSDROOT_NAME));
472 if (umsdos_real_lookup (sbin,"init",4,&init)==0
473 && S_ISREG(init->i_mode)){
474 pseudo_ok = 1;
475 }
476 iput (init);
477 }
478 if (pseudo_ok){
479 umsdos_setup_dir_inode (pseudo);
480 Printk (("Activating pseudo root /%s\n",UMSDOS_PSDROOT_NAME));
481 pseudo_root = pseudo;
482 pseudo->i_count++;
483 pseudo = NULL;
484 }
485 iput (sbin);
486 iput (etc);
487 }
488 iput (pseudo);
489 }
490 } else {
491 MOD_DEC_USE_COUNT;
492 }
493 return sb;
494 }
495
496
497 #ifdef MODULE
498
499 static struct file_system_type umsdos_fs_type = {
500 UMSDOS_read_super, "umsdos", 1, NULL
501 };
502
503 int init_module(void)
504 {
505 return register_filesystem(&umsdos_fs_type);
506 }
507
508 void cleanup_module(void)
509 {
510 unregister_filesystem(&umsdos_fs_type);
511 }
512
513 #endif
514