2 * linux/fs/hpfs/super.c
4 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
6 * mouning, unmounting, error handling
10 #include <linux/module.h>
12 /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
14 static void mark_dirty(struct super_block
*s
)
16 if (s
->s_hpfs_chkdsk
&& !(s
->s_flags
& MS_RDONLY
)) {
17 struct buffer_head
*bh
;
18 struct hpfs_spare_block
*sb
;
19 if ((sb
= hpfs_map_sector(s
, 17, &bh
, 0))) {
22 mark_buffer_dirty(bh
, 1);
28 /* Mark the filesystem clean (mark it dirty for chkdsk if chkdsk==2 or if there
31 static void unmark_dirty(struct super_block
*s
)
33 struct buffer_head
*bh
;
34 struct hpfs_spare_block
*sb
;
35 if (s
->s_flags
& MS_RDONLY
) return;
36 if ((sb
= hpfs_map_sector(s
, 17, &bh
, 0))) {
37 sb
->dirty
= s
->s_hpfs_chkdsk
> 1 - s
->s_hpfs_was_error
;
38 sb
->old_wrote
= s
->s_hpfs_chkdsk
>= 2 && !s
->s_hpfs_was_error
;
39 mark_buffer_dirty(bh
, 1);
44 /* Filesystem error... */
46 #define ERR_BUF_SIZE 1024
48 void hpfs_error(struct super_block
*s
, char *m
,...)
53 if (!(buf
= kmalloc(ERR_BUF_SIZE
, GFP_KERNEL
)))
54 printk("HPFS: No memory for error message '%s'\n",m
);
55 else if (vsprintf(buf
, m
, l
) >= ERR_BUF_SIZE
)
56 printk("HPFS: Grrrr... Kernel memory corrupted ... going on, but it'll crash very soon :-(\n");
57 printk("HPFS: filesystem error: ");
58 if (buf
) printk("%s", buf
);
59 else printk("%s\n",m
);
60 if (!s
->s_hpfs_was_error
) {
61 if (s
->s_hpfs_err
== 2) {
62 printk("; crashing the system because you wanted it\n");
65 } else if (s
->s_hpfs_err
== 1) {
66 if (s
->s_flags
& MS_RDONLY
) printk("; already mounted read-only\n");
68 printk("; remounting read-only\n");
70 s
->s_flags
|= MS_RDONLY
;
72 } else if (s
->s_flags
& MS_RDONLY
) printk("; going on - but anything won't be destroyed because it's read-only\n");
73 else printk("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n");
76 s
->s_hpfs_was_error
= 1;
80 * A little trick to detect cycles in many hpfs structures and don't let the
81 * kernel crash on corrupted filesystem. When first called, set c2 to 0.
83 * BTW. chkdsk doesn't detect cycles correctly. When I had 2 lost directories
84 * nested each in other, chkdsk locked up happilly.
87 int hpfs_stop_cycles(struct super_block
*s
, int key
, int *c1
, int *c2
,
90 if (*c2
&& *c1
== key
) {
91 hpfs_error(s
, "cycle detected on key %08x in %s", key
, msg
);
95 if (!((*c2
- 1) & *c2
)) *c1
= key
;
99 void hpfs_put_super(struct super_block
*s
)
101 if (s
->s_hpfs_cp_table
) kfree(s
->s_hpfs_cp_table
);
102 if (s
->s_hpfs_bmp_dir
) kfree(s
->s_hpfs_bmp_dir
);
108 static unsigned count_one_bitmap(struct super_block
*s
, secno secno
)
110 struct quad_buffer_head qbh
;
113 if (!(bits
= hpfs_map_4sectors(s
, secno
, &qbh
, 4))) return 0;
115 for (i
= 0; i
< 2048 / sizeof(unsigned); i
++) {
117 for (b
= bits
[i
]; b
; b
>>=1) count
+= b
& 1;
123 static unsigned count_bitmaps(struct super_block
*s
)
125 unsigned n
, count
, n_bands
;
126 n_bands
= (s
->s_hpfs_fs_size
+ 0x3fff) >> 14;
128 for (n
= 0; n
< n_bands
; n
++)
129 count
+= count_one_bitmap(s
, s
->s_hpfs_bmp_dir
[n
]);
133 int hpfs_statfs(struct super_block
*s
, struct statfs
*buf
, int bufsiz
)
136 /*if (s->s_hpfs_n_free == -1) {*/
137 s
->s_hpfs_n_free
= count_bitmaps(s
);
138 s
->s_hpfs_n_free_dnodes
= count_one_bitmap(s
, s
->s_hpfs_dmap
);
140 tmp
.f_type
= s
->s_magic
;
142 tmp
.f_blocks
= s
->s_hpfs_fs_size
;
143 tmp
.f_bfree
= s
->s_hpfs_n_free
;
144 tmp
.f_bavail
= s
->s_hpfs_n_free
;
145 tmp
.f_files
= s
->s_hpfs_dirband_size
/ 4;
146 tmp
.f_ffree
= s
->s_hpfs_n_free_dnodes
;
148 return copy_to_user(buf
, &tmp
, bufsiz
) ? -EFAULT
: 0;
151 /* Super operations */
153 static const struct super_operations hpfs_sops
=
155 hpfs_read_inode
, /* read_inode */
156 NULL
, /* write_inode */
157 NULL
, /* put_inode */
158 hpfs_delete_inode
, /* delete inode */
159 hpfs_notify_change
, /* notify_change */
160 hpfs_put_super
, /* put_super */
161 NULL
, /* write_super */
162 hpfs_statfs
, /* statfs */
163 hpfs_remount_fs
, /* remount_fs */
164 NULL
, /* clear inode */
165 NULL
, /* umount_begin */
169 * A tiny parser for option strings, stolen from dosfs.
171 * Stolen again from read-only hpfs.
174 int parse_opts(char *opts
, uid_t
*uid
, gid_t
*gid
, umode_t
*umask
,
175 int *lowercase
, int *conv
, int *eas
, int *chk
, int *errs
,
176 int *chkdsk
, int *timeshift
)
183 /*printk("Parsing opts: '%s'\n",opts);*/
185 for (p
= strtok(opts
, ","); p
!= 0; p
= strtok(0, ",")) {
186 if ((rhs
= strchr(p
, '=')) != 0)
188 if (!strcmp(p
, "help")) return 2;
189 if (!strcmp(p
, "uid")) {
192 *uid
= simple_strtoul(rhs
, &rhs
, 0);
196 else if (!strcmp(p
, "gid")) {
199 *gid
= simple_strtoul(rhs
, &rhs
, 0);
203 else if (!strcmp(p
, "umask")) {
206 *umask
= simple_strtoul(rhs
, &rhs
, 8);
210 else if (!strcmp(p
, "timeshift")) {
214 if (*rhs
== '-') m
= -1;
215 if (*rhs
== '+' || *rhs
== '-') rhs
++;
216 *timeshift
= simple_strtoul(rhs
, &rhs
, 0) * m
;
220 else if (!strcmp(p
, "case")) {
221 if (!strcmp(rhs
, "lower"))
223 else if (!strcmp(rhs
, "asis"))
228 else if (!strcmp(p
, "conv")) {
229 if (!strcmp(rhs
, "binary"))
231 else if (!strcmp(rhs
, "text"))
233 else if (!strcmp(rhs
, "auto"))
238 else if (!strcmp(p
, "check")) {
239 if (!strcmp(rhs
, "none"))
241 else if (!strcmp(rhs
, "normal"))
243 else if (!strcmp(rhs
, "strict"))
248 else if (!strcmp(p
, "errors")) {
249 if (!strcmp(rhs
, "continue"))
251 else if (!strcmp(rhs
, "remount-ro"))
253 else if (!strcmp(rhs
, "panic"))
258 else if (!strcmp(p
, "eas")) {
259 if (!strcmp(rhs
, "no"))
261 else if (!strcmp(rhs
, "ro"))
263 else if (!strcmp(rhs
, "rw"))
268 else if (!strcmp(p
, "chkdsk")) {
269 if (!strcmp(rhs
, "no"))
271 else if (!strcmp(rhs
, "errors"))
273 else if (!strcmp(rhs
, "always"))
284 static inline void hpfs_help()
287 HPFS filesystem options:\n\
288 help do not mount and display this text\n\
289 uid=xxx set uid of files that don't have uid specified in eas\n\
290 gid=xxx set gid of files that don't have gid specified in eas\n\
291 umask=xxx set mode of files that don't have mode specified in eas\n\
292 case=lower lowercase all files\n\
293 case=asis do not lowercase files (default)\n\
294 conv=binary do not convert CR/LF -> LF (default)\n\
295 conv=auto convert only files with known text extensions\n\
296 conv=text convert all files\n\
297 check=none no fs checks - kernel may crash on corrupted filesystem\n\
298 check=normal do some checks - it should not crash (default)\n\
299 check=strict do extra time-consuming checks, used for debugging\n\
300 errors=continue continue on errors\n\
301 errors=remount-ro remount read-only if errors found (default)\n\
302 errors=panic panic on errors\n\
303 chkdsk=no do not mark fs for chkdsking even if there were errors\n\
304 chkdsk=errors mark fs dirty if errors found (default)\n\
305 chkdsk=always always mark fs dirty - used for debugging\n\
306 eas=no ignore extended attributes\n\
307 eas=ro read but do not write extended attributes\n\
308 eas=rw r/w eas => enables chmod, chown, mknod, ln -s (default)\n\
309 timeshift=nnn add nnn seconds to file times\n\
313 int hpfs_remount_fs(struct super_block
*s
, int *flags
, char *data
)
318 int lowercase
, conv
, eas
, chk
, errs
, chkdsk
, timeshift
;
321 *flags
|= MS_NOATIME
;
323 uid
= s
->s_hpfs_uid
; gid
= s
->s_hpfs_gid
;
324 umask
= 0777 & ~s
->s_hpfs_mode
;
325 lowercase
= s
->s_hpfs_lowercase
; conv
= s
->s_hpfs_conv
;
326 eas
= s
->s_hpfs_eas
; chk
= s
->s_hpfs_chk
; chkdsk
= s
->s_hpfs_chkdsk
;
327 errs
= s
->s_hpfs_err
; timeshift
= s
->s_hpfs_timeshift
;
329 if (!(o
= parse_opts(data
, &uid
, &gid
, &umask
, &lowercase
, &conv
,
330 &eas
, &chk
, &errs
, &chkdsk
, ×hift
))) {
331 printk("HPFS: bad mount options.\n");
338 if (timeshift
!= s
->s_hpfs_timeshift
) {
339 printk("HPFS: timeshift can't be changed using remount.\n");
345 s
->s_hpfs_uid
= uid
; s
->s_hpfs_gid
= gid
;
346 s
->s_hpfs_mode
= 0777 & ~umask
;
347 s
->s_hpfs_lowercase
= lowercase
; s
->s_hpfs_conv
= conv
;
348 s
->s_hpfs_eas
= eas
; s
->s_hpfs_chk
= chk
; s
->s_hpfs_chkdsk
= chkdsk
;
349 s
->s_hpfs_err
= errs
; s
->s_hpfs_timeshift
= timeshift
;
351 if (!(*flags
& MS_RDONLY
)) mark_dirty(s
);
356 struct super_block
*hpfs_read_super(struct super_block
*s
, void *options
,
360 struct buffer_head
*bh0
, *bh1
, *bh2
;
361 struct hpfs_boot_block
*bootblock
;
362 struct hpfs_super_block
*superblock
;
363 struct hpfs_spare_block
*spareblock
;
368 int lowercase
, conv
, eas
, chk
, errs
, chkdsk
, timeshift
;
370 dnode_secno root_dno
;
371 struct hpfs_dirent
*de
= NULL
;
372 struct quad_buffer_head qbh
;
378 s
->s_hpfs_bmp_dir
= NULL
;
379 s
->s_hpfs_cp_table
= NULL
;
381 s
->s_hpfs_creation_de_lock
= s
->s_hpfs_rd_inode
= 0;
382 s
->s_hpfs_creation_de
= s
->s_hpfs_iget_q
= NULL
;
386 umask
= current
->fs
->umask
;
395 if (!(o
= parse_opts(options
, &uid
, &gid
, &umask
, &lowercase
, &conv
,
396 &eas
, &chk
, &errs
, &chkdsk
, ×hift
))) {
397 printk("HPFS: bad mount options.\n");
405 /*s->s_hpfs_mounting = 1;*/
408 set_blocksize(dev
, 512);
409 s
->s_hpfs_fs_size
= -1;
410 if (!(bootblock
= hpfs_map_sector(s
, 0, &bh0
, 0))) goto bail1
;
411 if (!(superblock
= hpfs_map_sector(s
, 16, &bh1
, 1))) goto bail2
;
412 if (!(spareblock
= hpfs_map_sector(s
, 17, &bh2
, 0))) goto bail3
;
415 if (/*bootblock->magic != BB_MAGIC
416 ||*/ superblock
->magic
!= SB_MAGIC
417 || spareblock
->magic
!= SP_MAGIC
) {
418 if (!silent
) printk("HPFS: Bad magic ... probably not HPFS\n");
423 if (!(s
->s_flags
& MS_RDONLY
) &&
424 superblock
->funcversion
!= 2 && superblock
->funcversion
!= 3) {
425 printk("HPFS: Bad version %d,%d. Mount readonly to go around\n",
426 (int)superblock
->version
, (int)superblock
->funcversion
);
427 printk("HPFS: please try recent version of HPFS driver at http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi and if it still can't understand this format, contact author - mikulas@artax.karlin.mff.cuni.cz\n");
431 s
->s_flags
|= MS_NOATIME
;
433 /* Fill superblock stuff */
434 s
->s_magic
= HPFS_SUPER_MAGIC
;
435 s
->s_blocksize
= 512;
436 s
->s_blocksize_bits
= 9;
437 s
->s_op
= (struct super_operations
*) &hpfs_sops
;
439 s
->s_hpfs_root
= superblock
->root
;
440 s
->s_hpfs_fs_size
= superblock
->n_sectors
;
441 s
->s_hpfs_bitmaps
= superblock
->bitmaps
;
442 s
->s_hpfs_dirband_start
= superblock
->dir_band_start
;
443 s
->s_hpfs_dirband_size
= superblock
->n_dir_band
;
444 s
->s_hpfs_dmap
= superblock
->dir_band_bitmap
;
447 s
->s_hpfs_mode
= 0777 & ~umask
;
448 s
->s_hpfs_n_free
= -1;
449 s
->s_hpfs_n_free_dnodes
= -1;
450 s
->s_hpfs_lowercase
= lowercase
;
451 s
->s_hpfs_conv
= conv
;
454 s
->s_hpfs_chkdsk
= chkdsk
;
455 s
->s_hpfs_err
= errs
;
456 s
->s_hpfs_timeshift
= timeshift
;
457 s
->s_hpfs_was_error
= 0;
458 s
->s_hpfs_cp_table
= NULL
;
459 s
->s_hpfs_c_bitmap
= -1;
461 /* Load bitmap directory */
462 if (!(s
->s_hpfs_bmp_dir
= hpfs_load_bitmap_directory(s
, superblock
->bitmaps
)))
465 /* Check for general fs errors*/
466 if (spareblock
->dirty
&& !spareblock
->old_wrote
) {
468 printk("HPFS: Improperly stopped, not mounted\n");
471 hpfs_error(s
, "improperly stopped");
474 if (!(s
->s_flags
& MS_RDONLY
)) {
475 spareblock
->dirty
= 1;
476 spareblock
->old_wrote
= 0;
477 mark_buffer_dirty(bh2
, 1);
480 if (spareblock
->hotfixes_used
|| spareblock
->n_spares_used
) {
482 printk("HPFS: Hotfixes not supported here, try chkdsk\n");
486 hpfs_error(s
, "hotfixes not supported here, try chkdsk");
487 if (errs
== 0) printk("HPFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n");
488 else printk("HPFS: This driver may read bad files or crash when operating on disk with hotfixes.\n");
490 if (spareblock
->n_dnode_spares
!= spareblock
->n_dnode_spares_free
) {
492 printk("HPFS: Spare dnodes used, try chkdsk\n");
496 hpfs_error(s
, "warning: spare dnodes used, try chkdsk");
497 if (errs
== 0) printk("HPFS: Proceeding, but your filesystem could be corrupted if you delete files or directories\n");
501 if (superblock
->dir_band_end
- superblock
->dir_band_start
+ 1 != superblock
->n_dir_band
||
502 superblock
->dir_band_end
< superblock
->dir_band_start
|| superblock
->n_dir_band
> 0x4000) {
503 hpfs_error(s
, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x",
504 superblock
->dir_band_start
, superblock
->dir_band_end
, superblock
->n_dir_band
);
507 a
= s
->s_hpfs_dirband_size
;
508 s
->s_hpfs_dirband_size
= 0;
509 if (hpfs_chk_sectors(s
, superblock
->dir_band_start
, superblock
->n_dir_band
, "dir_band") ||
510 hpfs_chk_sectors(s
, superblock
->dir_band_bitmap
, 4, "dir_band_bitmap") ||
511 hpfs_chk_sectors(s
, superblock
->bitmaps
, 4, "bitmaps")) {
515 s
->s_hpfs_dirband_size
= a
;
516 } else printk("HPFS: You really don't want any checks? You are crazy...\n");
518 /* Load code page table */
519 if (spareblock
->n_code_pages
)
520 if (!(s
->s_hpfs_cp_table
= hpfs_load_code_page(s
, spareblock
->code_page_dir
)))
521 printk("HPFS: Warning: code page support is disabled\n");
527 hpfs_lock_iget(s
, 1);
528 s
->s_root
= d_alloc_root(iget(s
, s
->s_hpfs_root
), NULL
);
531 if (!s
->s_root
|| !s
->s_root
->d_inode
) {
532 printk("HPFS: iget failed. Why???\n");
535 hpfs_set_dentry_operations(s
->s_root
);
538 * find the root directory's . pointer & finish filling in the inode
541 root_dno
= hpfs_fnode_dno(s
, s
->s_hpfs_root
);
543 de
= map_dirent(s
->s_root
->d_inode
, root_dno
, "\001\001", 2, NULL
, &qbh
, NULL
);
544 if (!root_dno
|| !de
) hpfs_error(s
, "unable to find root dir");
546 s
->s_root
->d_inode
->i_atime
= local_to_gmt(s
, de
->read_date
);
547 s
->s_root
->d_inode
->i_mtime
= local_to_gmt(s
, de
->write_date
);
548 s
->s_root
->d_inode
->i_ctime
= local_to_gmt(s
, de
->creation_date
);
549 s
->s_root
->d_inode
->i_hpfs_ea_size
= de
->ea_size
;
550 s
->s_root
->d_inode
->i_hpfs_parent_dir
= s
->s_root
->d_inode
->i_ino
;
551 if (s
->s_root
->d_inode
->i_size
== -1) s
->s_root
->d_inode
->i_size
= 2048;
552 if (s
->s_root
->d_inode
->i_blocks
== -1) s
->s_root
->d_inode
->i_blocks
= 5;
554 if (de
) hpfs_brelse4(&qbh
);
561 bail1
: unlock_super(s
);
563 if (s
->s_hpfs_bmp_dir
) kfree(s
->s_hpfs_bmp_dir
);
564 if (s
->s_hpfs_cp_table
) kfree(s
->s_hpfs_cp_table
);
569 struct file_system_type hpfs_fs_type
= {
570 "hpfs", FS_REQUIRES_DEV
, hpfs_read_super
, NULL
573 int init_hpfs_fs(void)
575 return register_filesystem(&hpfs_fs_type
);
580 /*int register_symtab_from(struct symbol_table *, long *);*/
582 int init_module(void)
585 if (!(status = init_hpfs_fs())) register_symtab(NULL);
587 return init_hpfs_fs();
590 void cleanup_module(void)
592 unregister_filesystem(&hpfs_fs_type
);