File: /usr/src/linux/fs/hpfs/super.c

1     /*
2      *  linux/fs/hpfs/super.c
3      *
4      *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
5      *
6      *  mouning, unmounting, error handling
7      */
8     
9     #include <linux/string.h>
10     #include "hpfs_fn.h"
11     #include <linux/module.h>
12     #include <linux/init.h>
13     
14     /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
15     
16     static void mark_dirty(struct super_block *s)
17     {
18     	if (s->s_hpfs_chkdsk && !(s->s_flags & MS_RDONLY)) {
19     		struct buffer_head *bh;
20     		struct hpfs_spare_block *sb;
21     		if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {
22     			sb->dirty = 1;
23     			sb->old_wrote = 0;
24     			mark_buffer_dirty(bh);
25     			brelse(bh);
26     		}
27     	}
28     }
29     
30     /* Mark the filesystem clean (mark it dirty for chkdsk if chkdsk==2 or if there
31        were errors) */
32     
33     static void unmark_dirty(struct super_block *s)
34     {
35     	struct buffer_head *bh;
36     	struct hpfs_spare_block *sb;
37     	if (s->s_flags & MS_RDONLY) return;
38     	if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {
39     		sb->dirty = s->s_hpfs_chkdsk > 1 - s->s_hpfs_was_error;
40     		sb->old_wrote = s->s_hpfs_chkdsk >= 2 && !s->s_hpfs_was_error;
41     		mark_buffer_dirty(bh);
42     		brelse(bh);
43     	}
44     }
45     
46     /* Filesystem error... */
47     
48     #define ERR_BUF_SIZE 1024
49     
50     void hpfs_error(struct super_block *s, char *m,...)
51     {
52     	char *buf;
53     	va_list l;
54     	va_start(l, m);
55     	if (!(buf = kmalloc(ERR_BUF_SIZE, GFP_KERNEL)))
56     		printk("HPFS: No memory for error message '%s'\n",m);
57     	else if (vsprintf(buf, m, l) >= ERR_BUF_SIZE)
58     		printk("HPFS: Grrrr... Kernel memory corrupted ... going on, but it'll crash very soon :-(\n");
59     	printk("HPFS: filesystem error: ");
60     	if (buf) printk("%s", buf);
61     	else printk("%s\n",m);
62     	if (!s->s_hpfs_was_error) {
63     		if (s->s_hpfs_err == 2) {
64     			printk("; crashing the system because you wanted it\n");
65     			mark_dirty(s);
66     			panic("HPFS panic");
67     		} else if (s->s_hpfs_err == 1) {
68     			if (s->s_flags & MS_RDONLY) printk("; already mounted read-only\n");
69     			else {
70     				printk("; remounting read-only\n");
71     				mark_dirty(s);
72     				s->s_flags |= MS_RDONLY;
73     			}
74     		} else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n");
75     		else printk("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n");
76     	} else printk("\n");
77     	if (buf) kfree(buf);
78     	s->s_hpfs_was_error = 1;
79     }
80     
81     /* 
82      * A little trick to detect cycles in many hpfs structures and don't let the
83      * kernel crash on corrupted filesystem. When first called, set c2 to 0.
84      *
85      * BTW. chkdsk doesn't detect cycles correctly. When I had 2 lost directories
86      * nested each in other, chkdsk locked up happilly.
87      */
88     
89     int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2,
90     		char *msg)
91     {
92     	if (*c2 && *c1 == key) {
93     		hpfs_error(s, "cycle detected on key %08x in %s", key, msg);
94     		return 1;
95     	}
96     	(*c2)++;
97     	if (!((*c2 - 1) & *c2)) *c1 = key;
98     	return 0;
99     }
100     
101     void hpfs_put_super(struct super_block *s)
102     {
103     	if (s->s_hpfs_cp_table) kfree(s->s_hpfs_cp_table);
104     	if (s->s_hpfs_bmp_dir) kfree(s->s_hpfs_bmp_dir);
105     	unmark_dirty(s);
106     }
107     
108     unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
109     {
110     	struct quad_buffer_head qbh;
111     	unsigned *bits;
112     	unsigned i, count;
113     	if (!(bits = hpfs_map_4sectors(s, secno, &qbh, 4))) return 0;
114     	count = 0;
115     	for (i = 0; i < 2048 / sizeof(unsigned); i++) {
116     		unsigned b; 
117     		if (!bits[i]) continue;
118     		for (b = bits[i]; b; b>>=1) count += b & 1;
119     	}
120     	hpfs_brelse4(&qbh);
121     	return count;
122     }
123     
124     static unsigned count_bitmaps(struct super_block *s)
125     {
126     	unsigned n, count, n_bands;
127     	n_bands = (s->s_hpfs_fs_size + 0x3fff) >> 14;
128     	count = 0;
129     	for (n = 0; n < n_bands; n++)
130     		count += hpfs_count_one_bitmap(s, s->s_hpfs_bmp_dir[n]);
131     	return count;
132     }
133     
134     int hpfs_statfs(struct super_block *s, struct statfs *buf)
135     {
136     	/*if (s->s_hpfs_n_free == -1) {*/
137     		s->s_hpfs_n_free = count_bitmaps(s);
138     		s->s_hpfs_n_free_dnodes = hpfs_count_one_bitmap(s, s->s_hpfs_dmap);
139     	/*}*/
140     	buf->f_type = s->s_magic;
141     	buf->f_bsize = 512;
142     	buf->f_blocks = s->s_hpfs_fs_size;
143     	buf->f_bfree = s->s_hpfs_n_free;
144     	buf->f_bavail = s->s_hpfs_n_free;
145     	buf->f_files = s->s_hpfs_dirband_size / 4;
146     	buf->f_ffree = s->s_hpfs_n_free_dnodes;
147     	buf->f_namelen = 254;
148     	return 0;
149     }
150     
151     /* Super operations */
152     
153     static struct super_operations hpfs_sops =
154     {
155             read_inode:	hpfs_read_inode,
156     	delete_inode:	hpfs_delete_inode,
157     	put_super:	hpfs_put_super,
158     	statfs:		hpfs_statfs,
159     	remount_fs:	hpfs_remount_fs,
160     };
161     
162     /*
163      * A tiny parser for option strings, stolen from dosfs.
164      *
165      * Stolen again from read-only hpfs.
166      */
167     
168     int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
169     	       int *lowercase, int *conv, int *eas, int *chk, int *errs,
170     	       int *chkdsk, int *timeshift)
171     {
172     	char *p, *rhs;
173     
174     	if (!opts)
175     		return 1;
176     
177     	/*printk("Parsing opts: '%s'\n",opts);*/
178     
179     	for (p = strtok(opts, ","); p != 0; p = strtok(0, ",")) {
180     		if ((rhs = strchr(p, '=')) != 0)
181     			*rhs++ = '\0';
182     		if (!strcmp(p, "help")) return 2;
183     		if (!strcmp(p, "uid")) {
184     			if (!rhs || !*rhs)
185     				return 0;
186     			*uid = simple_strtoul(rhs, &rhs, 0);
187     			if (*rhs)
188     				return 0;
189     		}
190     		else if (!strcmp(p, "gid")) {
191     			if (!rhs || !*rhs)
192     				return 0;
193     			*gid = simple_strtoul(rhs, &rhs, 0);
194     			if (*rhs)
195     				return 0;
196     		}
197     		else if (!strcmp(p, "umask")) {
198     			if (!rhs || !*rhs)
199     				return 0;
200     			*umask = simple_strtoul(rhs, &rhs, 8);
201     			if (*rhs)
202     				return 0;
203     		}
204     		else if (!strcmp(p, "timeshift")) {
205     			int m = 1;
206     			if (!rhs || !*rhs)
207     				return 0;
208     			if (*rhs == '-') m = -1;
209     			if (*rhs == '+' || *rhs == '-') rhs++;
210     			*timeshift = simple_strtoul(rhs, &rhs, 0) * m;
211     			if (*rhs)
212     				return 0;
213     		}
214     		else if (!strcmp(p, "case")) {
215     			if (!rhs || !*rhs)
216     				return 0;
217     			if (!strcmp(rhs, "lower"))
218     				*lowercase = 1;
219     			else if (!strcmp(rhs, "asis"))
220     				*lowercase = 0;
221     			else
222     				return 0;
223     		}
224     		else if (!strcmp(p, "conv")) {
225     			if (!rhs || !*rhs)
226     				return 0;
227     			if (!strcmp(rhs, "binary"))
228     				*conv = CONV_BINARY;
229     			else if (!strcmp(rhs, "text"))
230     				*conv = CONV_TEXT;
231     			else if (!strcmp(rhs, "auto"))
232     				*conv = CONV_AUTO;
233     			else
234     				return 0;
235     		}
236     		else if (!strcmp(p, "check")) {
237     			if (!rhs || !*rhs)
238     				return 0;
239     			if (!strcmp(rhs, "none"))
240     				*chk = 0;
241     			else if (!strcmp(rhs, "normal"))
242     				*chk = 1;
243     			else if (!strcmp(rhs, "strict"))
244     				*chk = 2;
245     			else
246     				return 0;
247     		}
248     		else if (!strcmp(p, "errors")) {
249     			if (!rhs || !*rhs)
250     				return 0;
251     			if (!strcmp(rhs, "continue"))
252     				*errs = 0;
253     			else if (!strcmp(rhs, "remount-ro"))
254     				*errs = 1;
255     			else if (!strcmp(rhs, "panic"))
256     				*errs = 2;
257     			else
258     				return 0;
259     		}
260     		else if (!strcmp(p, "eas")) {
261     			if (!rhs || !*rhs)
262     				return 0;
263     			if (!strcmp(rhs, "no"))
264     				*eas = 0;
265     			else if (!strcmp(rhs, "ro"))
266     				*eas = 1;
267     			else if (!strcmp(rhs, "rw"))
268     				*eas = 2;
269     			else
270     				return 0;
271     		}
272     		else if (!strcmp(p, "chkdsk")) {
273     			if (!rhs || !*rhs)
274     				return 0;
275     			if (!strcmp(rhs, "no"))
276     				*chkdsk = 0;
277     			else if (!strcmp(rhs, "errors"))
278     				*chkdsk = 1;
279     			else if (!strcmp(rhs, "always"))
280     				*chkdsk = 2;
281     			else
282     				return 0;
283     		}
284     		else
285     			return 0;
286     	}
287     	return 1;
288     }
289     
290     static inline void hpfs_help(void)
291     {
292     	printk("\n\
293     HPFS filesystem options:\n\
294           help              do not mount and display this text\n\
295           uid=xxx           set uid of files that don't have uid specified in eas\n\
296           gid=xxx           set gid of files that don't have gid specified in eas\n\
297           umask=xxx         set mode of files that don't have mode specified in eas\n\
298           case=lower        lowercase all files\n\
299           case=asis         do not lowercase files (default)\n\
300           conv=binary       do not convert CR/LF -> LF (default)\n\
301           conv=auto         convert only files with known text extensions\n\
302           conv=text         convert all files\n\
303           check=none        no fs checks - kernel may crash on corrupted filesystem\n\
304           check=normal      do some checks - it should not crash (default)\n\
305           check=strict      do extra time-consuming checks, used for debugging\n\
306           errors=continue   continue on errors\n\
307           errors=remount-ro remount read-only if errors found (default)\n\
308           errors=panic      panic on errors\n\
309           chkdsk=no         do not mark fs for chkdsking even if there were errors\n\
310           chkdsk=errors     mark fs dirty if errors found (default)\n\
311           chkdsk=always     always mark fs dirty - used for debugging\n\
312           eas=no            ignore extended attributes\n\
313           eas=ro            read but do not write extended attributes\n\
314           eas=rw            r/w eas => enables chmod, chown, mknod, ln -s (default)\n\
315           timeshift=nnn	add nnn seconds to file times\n\
316     \n");
317     }
318     
319     int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
320     {
321     	uid_t uid;
322     	gid_t gid;
323     	umode_t umask;
324     	int lowercase, conv, eas, chk, errs, chkdsk, timeshift;
325     	int o;
326     	
327     	*flags |= MS_NOATIME;
328     	
329     	uid = s->s_hpfs_uid; gid = s->s_hpfs_gid;
330     	umask = 0777 & ~s->s_hpfs_mode;
331     	lowercase = s->s_hpfs_lowercase; conv = s->s_hpfs_conv;
332     	eas = s->s_hpfs_eas; chk = s->s_hpfs_chk; chkdsk = s->s_hpfs_chkdsk;
333     	errs = s->s_hpfs_err; timeshift = s->s_hpfs_timeshift;
334     
335     	if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase, &conv,
336     	    &eas, &chk, &errs, &chkdsk, &timeshift))) {
337     		printk("HPFS: bad mount options.\n");
338     	    	return 1;
339     	}
340     	if (o == 2) {
341     		hpfs_help();
342     		return 1;
343     	}
344     	if (timeshift != s->s_hpfs_timeshift) {
345     		printk("HPFS: timeshift can't be changed using remount.\n");
346     		return 1;
347     	}
348     
349     	unmark_dirty(s);
350     
351     	s->s_hpfs_uid = uid; s->s_hpfs_gid = gid;
352     	s->s_hpfs_mode = 0777 & ~umask;
353     	s->s_hpfs_lowercase = lowercase; s->s_hpfs_conv = conv;
354     	s->s_hpfs_eas = eas; s->s_hpfs_chk = chk; s->s_hpfs_chkdsk = chkdsk;
355     	s->s_hpfs_err = errs; s->s_hpfs_timeshift = timeshift;
356     
357     	if (!(*flags & MS_RDONLY)) mark_dirty(s);
358     
359     	return 0;
360     }
361     
362     struct super_block *hpfs_read_super(struct super_block *s, void *options,
363     				    int silent)
364     {
365     	kdev_t dev;
366     	struct buffer_head *bh0, *bh1, *bh2;
367     	struct hpfs_boot_block *bootblock;
368     	struct hpfs_super_block *superblock;
369     	struct hpfs_spare_block *spareblock;
370     
371     	uid_t uid;
372     	gid_t gid;
373     	umode_t umask;
374     	int lowercase, conv, eas, chk, errs, chkdsk, timeshift;
375     
376     	dnode_secno root_dno;
377     	struct hpfs_dirent *de = NULL;
378     	struct quad_buffer_head qbh;
379     
380     	int o;
381     
382     	s->s_hpfs_bmp_dir = NULL;
383     	s->s_hpfs_cp_table = NULL;
384     
385     	s->s_hpfs_creation_de_lock = s->s_hpfs_rd_inode = 0;
386     	init_waitqueue_head(&s->s_hpfs_creation_de);
387     	init_waitqueue_head(&s->s_hpfs_iget_q);
388     
389     	uid = current->uid;
390     	gid = current->gid;
391     	umask = current->fs->umask;
392     	lowercase = 0;
393     	conv = CONV_BINARY;
394     	eas = 2;
395     	chk = 1;
396     	errs = 1;
397     	chkdsk = 1;
398     	timeshift = 0;
399     
400     	if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase, &conv,
401     	    &eas, &chk, &errs, &chkdsk, &timeshift))) {
402     		printk("HPFS: bad mount options.\n");
403     		goto bail0;
404     	}
405     	if (o==2) {
406     		hpfs_help();
407     		goto bail0;
408     	}
409     
410     	/*s->s_hpfs_mounting = 1;*/
411     	dev = s->s_dev;
412     	set_blocksize(dev, 512);
413     	s->s_hpfs_fs_size = -1;
414     	if (!(bootblock = hpfs_map_sector(s, 0, &bh0, 0))) goto bail1;
415     	if (!(superblock = hpfs_map_sector(s, 16, &bh1, 1))) goto bail2;
416     	if (!(spareblock = hpfs_map_sector(s, 17, &bh2, 0))) goto bail3;
417     
418     	/* Check magics */
419     	if (/*bootblock->magic != BB_MAGIC
420     	    ||*/ superblock->magic != SB_MAGIC
421     	    || spareblock->magic != SP_MAGIC) {
422     		if (!silent) printk("HPFS: Bad magic ... probably not HPFS\n");
423     		goto bail4;
424     	}
425     
426     	/* Check version */
427     	if (!(s->s_flags & MS_RDONLY) &&
428     	      superblock->funcversion != 2 && superblock->funcversion != 3) {
429     		printk("HPFS: Bad version %d,%d. Mount readonly to go around\n",
430     			(int)superblock->version, (int)superblock->funcversion);
431     		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");
432     		goto bail4;
433     	}
434     
435     	s->s_flags |= MS_NOATIME;
436     
437     	/* Fill superblock stuff */
438     	s->s_magic = HPFS_SUPER_MAGIC;
439     	s->s_blocksize = 512;
440     	s->s_blocksize_bits = 9;
441     	s->s_op = &hpfs_sops;
442     
443     	s->s_hpfs_root = superblock->root;
444     	s->s_hpfs_fs_size = superblock->n_sectors;
445     	s->s_hpfs_bitmaps = superblock->bitmaps;
446     	s->s_hpfs_dirband_start = superblock->dir_band_start;
447     	s->s_hpfs_dirband_size = superblock->n_dir_band;
448     	s->s_hpfs_dmap = superblock->dir_band_bitmap;
449     	s->s_hpfs_uid = uid;
450     	s->s_hpfs_gid = gid;
451     	s->s_hpfs_mode = 0777 & ~umask;
452     	s->s_hpfs_n_free = -1;
453     	s->s_hpfs_n_free_dnodes = -1;
454     	s->s_hpfs_lowercase = lowercase;
455     	s->s_hpfs_conv = conv;
456     	s->s_hpfs_eas = eas;
457     	s->s_hpfs_chk = chk;
458     	s->s_hpfs_chkdsk = chkdsk;
459     	s->s_hpfs_err = errs;
460     	s->s_hpfs_timeshift = timeshift;
461     	s->s_hpfs_was_error = 0;
462     	s->s_hpfs_cp_table = NULL;
463     	s->s_hpfs_c_bitmap = -1;
464     	
465     	/* Load bitmap directory */
466     	if (!(s->s_hpfs_bmp_dir = hpfs_load_bitmap_directory(s, superblock->bitmaps)))
467     		goto bail4;
468     	
469     	/* Check for general fs errors*/
470     	if (spareblock->dirty && !spareblock->old_wrote) {
471     		if (errs == 2) {
472     			printk("HPFS: Improperly stopped, not mounted\n");
473     			goto bail4;
474     		}
475     		hpfs_error(s, "improperly stopped");
476     	}
477     
478     	if (!(s->s_flags & MS_RDONLY)) {
479     		spareblock->dirty = 1;
480     		spareblock->old_wrote = 0;
481     		mark_buffer_dirty(bh2);
482     	}
483     
484     	if (spareblock->hotfixes_used || spareblock->n_spares_used) {
485     		if (errs >= 2) {
486     			printk("HPFS: Hotfixes not supported here, try chkdsk\n");
487     			mark_dirty(s);
488     			goto bail4;
489     		}
490     		hpfs_error(s, "hotfixes not supported here, try chkdsk");
491     		if (errs == 0) printk("HPFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n");
492     		else printk("HPFS: This driver may read bad files or crash when operating on disk with hotfixes.\n");
493     	}
494     	if (spareblock->n_dnode_spares != spareblock->n_dnode_spares_free) {
495     		if (errs >= 2) {
496     			printk("HPFS: Spare dnodes used, try chkdsk\n");
497     			mark_dirty(s);
498     			goto bail4;
499     		}
500     		hpfs_error(s, "warning: spare dnodes used, try chkdsk");
501     		if (errs == 0) printk("HPFS: Proceeding, but your filesystem could be corrupted if you delete files or directories\n");
502     	}
503     	if (chk) {
504     		unsigned a;
505     		if (superblock->dir_band_end - superblock->dir_band_start + 1 != superblock->n_dir_band ||
506     		    superblock->dir_band_end < superblock->dir_band_start || superblock->n_dir_band > 0x4000) {
507     			hpfs_error(s, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x",
508     				superblock->dir_band_start, superblock->dir_band_end, superblock->n_dir_band);
509     			goto bail4;
510     		}
511     		a = s->s_hpfs_dirband_size;
512     		s->s_hpfs_dirband_size = 0;
513     		if (hpfs_chk_sectors(s, superblock->dir_band_start, superblock->n_dir_band, "dir_band") ||
514     		    hpfs_chk_sectors(s, superblock->dir_band_bitmap, 4, "dir_band_bitmap") ||
515     		    hpfs_chk_sectors(s, superblock->bitmaps, 4, "bitmaps")) {
516     			mark_dirty(s);
517     			goto bail4;
518     		}
519     		s->s_hpfs_dirband_size = a;
520     	} else printk("HPFS: You really don't want any checks? You are crazy...\n");
521     
522     	/* Load code page table */
523     	if (spareblock->n_code_pages)
524     		if (!(s->s_hpfs_cp_table = hpfs_load_code_page(s, spareblock->code_page_dir)))
525     			printk("HPFS: Warning: code page support is disabled\n");
526     
527     	brelse(bh2);
528     	brelse(bh1);
529     	brelse(bh0);
530     
531     	hpfs_lock_iget(s, 1);
532     	s->s_root = d_alloc_root(iget(s, s->s_hpfs_root));
533     	hpfs_unlock_iget(s);
534     	if (!s->s_root || !s->s_root->d_inode) {
535     		printk("HPFS: iget failed. Why???\n");
536     		goto bail0;
537     	}
538     	hpfs_set_dentry_operations(s->s_root);
539     
540     	/*
541     	 * find the root directory's . pointer & finish filling in the inode
542     	 */
543     
544     	root_dno = hpfs_fnode_dno(s, s->s_hpfs_root);
545     	if (root_dno)
546     		de = map_dirent(s->s_root->d_inode, root_dno, "\001\001", 2, NULL, &qbh);
547     	if (!root_dno || !de) hpfs_error(s, "unable to find root dir");
548     	else {
549     		s->s_root->d_inode->i_atime = local_to_gmt(s, de->read_date);
550     		s->s_root->d_inode->i_mtime = local_to_gmt(s, de->write_date);
551     		s->s_root->d_inode->i_ctime = local_to_gmt(s, de->creation_date);
552     		s->s_root->d_inode->i_hpfs_ea_size = de->ea_size;
553     		s->s_root->d_inode->i_hpfs_parent_dir = s->s_root->d_inode->i_ino;
554     		if (s->s_root->d_inode->i_size == -1) s->s_root->d_inode->i_size = 2048;
555     		if (s->s_root->d_inode->i_blocks == -1) s->s_root->d_inode->i_blocks = 5;
556     	}
557     	if (de) hpfs_brelse4(&qbh);
558     
559     	return s;
560     
561     bail4:	brelse(bh2);
562     bail3:	brelse(bh1);
563     bail2:	brelse(bh0);
564     bail1:
565     bail0:
566     	if (s->s_hpfs_bmp_dir) kfree(s->s_hpfs_bmp_dir);
567     	if (s->s_hpfs_cp_table) kfree(s->s_hpfs_cp_table);
568     	return NULL;
569     }
570     
571     DECLARE_FSTYPE_DEV(hpfs_fs_type, "hpfs", hpfs_read_super);
572     
573     static int __init init_hpfs_fs(void)
574     {
575     	return register_filesystem(&hpfs_fs_type);
576     }
577     
578     static void __exit exit_hpfs_fs(void)
579     {
580     	unregister_filesystem(&hpfs_fs_type);
581     }
582     
583     EXPORT_NO_SYMBOLS;
584     
585     module_init(init_hpfs_fs)
586     module_exit(exit_hpfs_fs)
587