Blame view

fs/hpfs/super.c 20.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   *  linux/fs/hpfs/super.c
   *
   *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
   *
   *  mounting, unmounting, error handling
   */
  
  #include "hpfs_fn.h"
  #include <linux/module.h>
  #include <linux/parser.h>
  #include <linux/init.h>
  #include <linux/statfs.h>
e18fa700c   Jeff Garzik   Move several *_SU...
14
  #include <linux/magic.h>
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
15
  #include <linux/sched.h>
f4c54fcf3   Akinobu Mita   hpfs: use bitmap_...
16
  #include <linux/bitmap.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/slab.h>
037369b87   Mikulas Patocka   hpfs: implement t...
18
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  
  /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
dab4c82a6   Mikulas Patocka   HPFS: Fix a bug t...
21
  static void mark_dirty(struct super_block *s, int remount)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  {
bc98a42c1   David Howells   VFS: Convert sb->...
23
  	if (hpfs_sb(s)->sb_chkdsk && (remount || !sb_rdonly(s))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
29
  		struct buffer_head *bh;
  		struct hpfs_spare_block *sb;
  		if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {
  			sb->dirty = 1;
  			sb->old_wrote = 0;
  			mark_buffer_dirty(bh);
f73976818   Mikulas Patocka   HPFS: When markin...
30
  			sync_dirty_buffer(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
34
35
36
37
38
39
40
41
42
  			brelse(bh);
  		}
  	}
  }
  
  /* Mark the filesystem clean (mark it dirty for chkdsk if chkdsk==2 or if there
     were errors) */
  
  static void unmark_dirty(struct super_block *s)
  {
  	struct buffer_head *bh;
  	struct hpfs_spare_block *sb;
bc98a42c1   David Howells   VFS: Convert sb->...
43
  	if (sb_rdonly(s)) return;
f73976818   Mikulas Patocka   HPFS: When markin...
44
  	sync_blockdev(s->s_bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
  	if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {
  		sb->dirty = hpfs_sb(s)->sb_chkdsk > 1 - hpfs_sb(s)->sb_was_error;
  		sb->old_wrote = hpfs_sb(s)->sb_chkdsk >= 2 && !hpfs_sb(s)->sb_was_error;
  		mark_buffer_dirty(bh);
f73976818   Mikulas Patocka   HPFS: When markin...
49
  		sync_dirty_buffer(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
  		brelse(bh);
  	}
  }
  
  /* Filesystem error... */
352d94d04   Alexey Dobriyan   [PATCH] hpfs: bri...
55
  void hpfs_error(struct super_block *s, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  {
a28e4b2b1   Joe Perches   hpfs: hpfs_error:...
57
  	struct va_format vaf;
352d94d04   Alexey Dobriyan   [PATCH] hpfs: bri...
58
59
60
  	va_list args;
  
  	va_start(args, fmt);
a28e4b2b1   Joe Perches   hpfs: hpfs_error:...
61
62
63
64
65
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	pr_err("filesystem error: %pV", &vaf);
352d94d04   Alexey Dobriyan   [PATCH] hpfs: bri...
66
  	va_end(args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
  	if (!hpfs_sb(s)->sb_was_error) {
  		if (hpfs_sb(s)->sb_err == 2) {
b7cb1ce22   Fabian Frederick   fs/hpfs: convert ...
69
70
  			pr_cont("; crashing the system because you wanted it
  ");
dab4c82a6   Mikulas Patocka   HPFS: Fix a bug t...
71
  			mark_dirty(s, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
  			panic("HPFS panic");
  		} else if (hpfs_sb(s)->sb_err == 1) {
bc98a42c1   David Howells   VFS: Convert sb->...
74
  			if (sb_rdonly(s))
b7cb1ce22   Fabian Frederick   fs/hpfs: convert ...
75
76
  				pr_cont("; already mounted read-only
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
  			else {
b7cb1ce22   Fabian Frederick   fs/hpfs: convert ...
78
79
  				pr_cont("; remounting read-only
  ");
dab4c82a6   Mikulas Patocka   HPFS: Fix a bug t...
80
  				mark_dirty(s, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
  				s->s_flags |= MS_RDONLY;
  			}
bc98a42c1   David Howells   VFS: Convert sb->...
83
  		} else if (sb_rdonly(s))
b7cb1ce22   Fabian Frederick   fs/hpfs: convert ...
84
85
86
87
88
89
90
91
  				pr_cont("; going on - but anything won't be destroyed because it's read-only
  ");
  		else
  			pr_cont("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!
  ");
  	} else
  		pr_cont("
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  	hpfs_sb(s)->sb_was_error = 1;
  }
  
  /* 
   * A little trick to detect cycles in many hpfs structures and don't let the
   * kernel crash on corrupted filesystem. When first called, set c2 to 0.
   *
   * BTW. chkdsk doesn't detect cycles correctly. When I had 2 lost directories
   * nested each in other, chkdsk locked up happilly.
   */
  
  int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2,
  		char *msg)
  {
  	if (*c2 && *c1 == key) {
  		hpfs_error(s, "cycle detected on key %08x in %s", key, msg);
  		return 1;
  	}
  	(*c2)++;
  	if (!((*c2 - 1) & *c2)) *c1 = key;
  	return 0;
  }
30687e0a4   Al Viro   hpfs: make freein...
114
  static void free_sbi(struct hpfs_sb_info *sbi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  {
30687e0a4   Al Viro   hpfs: make freein...
116
117
118
119
  	kfree(sbi->sb_cp_table);
  	kfree(sbi->sb_bmp_dir);
  	kfree(sbi);
  }
6cfd01484   Christoph Hellwig   push BKL down int...
120

30687e0a4   Al Viro   hpfs: make freein...
121
122
123
124
125
126
127
  static void lazy_free_sbi(struct rcu_head *rcu)
  {
  	free_sbi(container_of(rcu, struct hpfs_sb_info, rcu));
  }
  
  static void hpfs_put_super(struct super_block *s)
  {
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
128
129
130
  	hpfs_lock(s);
  	unmark_dirty(s);
  	hpfs_unlock(s);
30687e0a4   Al Viro   hpfs: make freein...
131
  	call_rcu(&hpfs_sb(s)->rcu, lazy_free_sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  }
2cbe5c76f   Mikulas Patocka   hpfs: remember fr...
133
  static unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  {
  	struct quad_buffer_head qbh;
f4c54fcf3   Akinobu Mita   hpfs: use bitmap_...
136
137
  	unsigned long *bits;
  	unsigned count;
275f495db   Mikulas Patocka   hpfs: implement p...
138
  	bits = hpfs_map_4sectors(s, secno, &qbh, 0);
f4c54fcf3   Akinobu Mita   hpfs: use bitmap_...
139
  	if (!bits)
2cbe5c76f   Mikulas Patocka   hpfs: remember fr...
140
  		return (unsigned)-1;
f4c54fcf3   Akinobu Mita   hpfs: use bitmap_...
141
  	count = bitmap_weight(bits, 2048 * BITS_PER_BYTE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
144
145
146
147
148
149
150
  	hpfs_brelse4(&qbh);
  	return count;
  }
  
  static unsigned count_bitmaps(struct super_block *s)
  {
  	unsigned n, count, n_bands;
  	n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
  	count = 0;
275f495db   Mikulas Patocka   hpfs: implement p...
151
152
153
154
  	for (n = 0; n < COUNT_RD_AHEAD; n++) {
  		hpfs_prefetch_bitmap(s, n);
  	}
  	for (n = 0; n < n_bands; n++) {
2cbe5c76f   Mikulas Patocka   hpfs: remember fr...
155
  		unsigned c;
275f495db   Mikulas Patocka   hpfs: implement p...
156
  		hpfs_prefetch_bitmap(s, n + COUNT_RD_AHEAD);
2cbe5c76f   Mikulas Patocka   hpfs: remember fr...
157
158
159
  		c = hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
  		if (c != (unsigned)-1)
  			count += c;
275f495db   Mikulas Patocka   hpfs: implement p...
160
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
  	return count;
  }
2cbe5c76f   Mikulas Patocka   hpfs: remember fr...
163
164
165
166
167
168
169
170
171
172
173
  unsigned hpfs_get_free_dnodes(struct super_block *s)
  {
  	struct hpfs_sb_info *sbi = hpfs_sb(s);
  	if (sbi->sb_n_free_dnodes == (unsigned)-1) {
  		unsigned c = hpfs_count_one_bitmap(s, sbi->sb_dmap);
  		if (c == (unsigned)-1)
  			return 0;
  		sbi->sb_n_free_dnodes = c;
  	}
  	return sbi->sb_n_free_dnodes;
  }
726c33422   David Howells   [PATCH] VFS: Perm...
174
  static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  {
726c33422   David Howells   [PATCH] VFS: Perm...
176
  	struct super_block *s = dentry->d_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  	struct hpfs_sb_info *sbi = hpfs_sb(s);
604d295c2   Coly Li   fs/hpfs: return f...
178
  	u64 id = huge_encode_dev(s->s_bdev->bd_dev);
2cbe5c76f   Mikulas Patocka   hpfs: remember fr...
179

9a311b96c   Arnd Bergmann   hpfs: remove the BKL
180
  	hpfs_lock(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181

2cbe5c76f   Mikulas Patocka   hpfs: remember fr...
182
  	if (sbi->sb_n_free == (unsigned)-1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  		sbi->sb_n_free = count_bitmaps(s);
2cbe5c76f   Mikulas Patocka   hpfs: remember fr...
184

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
189
190
  	buf->f_type = s->s_magic;
  	buf->f_bsize = 512;
  	buf->f_blocks = sbi->sb_fs_size;
  	buf->f_bfree = sbi->sb_n_free;
  	buf->f_bavail = sbi->sb_n_free;
  	buf->f_files = sbi->sb_dirband_size / 4;
2cbe5c76f   Mikulas Patocka   hpfs: remember fr...
191
  	buf->f_ffree = hpfs_get_free_dnodes(s);
604d295c2   Coly Li   fs/hpfs: return f...
192
193
  	buf->f_fsid.val[0] = (u32)id;
  	buf->f_fsid.val[1] = (u32)(id >> 32);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
  	buf->f_namelen = 254;
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
195
  	hpfs_unlock(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
  
  	return 0;
  }
a27b5b97d   Mikulas Patocka   hpfs: add fstrim ...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  
  long hpfs_ioctl(struct file *file, unsigned cmd, unsigned long arg)
  {
  	switch (cmd) {
  		case FITRIM: {
  			struct fstrim_range range;
  			secno n_trimmed;
  			int r;
  			if (!capable(CAP_SYS_ADMIN))
  				return -EPERM;
  			if (copy_from_user(&range, (struct fstrim_range __user *)arg, sizeof(range)))
  				return -EFAULT;
  			r = hpfs_trim_fs(file_inode(file)->i_sb, range.start >> 9, (range.start + range.len) >> 9, (range.minlen + 511) >> 9, &n_trimmed);
  			if (r)
  				return r;
  			range.len = (u64)n_trimmed << 9;
  			if (copy_to_user((struct fstrim_range __user *)arg, &range, sizeof(range)))
  				return -EFAULT;
  			return 0;
  		}
  		default: {
  			return -ENOIOCTLCMD;
  		}
  	}
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
224
  static struct kmem_cache * hpfs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
  
  static struct inode *hpfs_alloc_inode(struct super_block *sb)
  {
  	struct hpfs_inode_info *ei;
d7b04097c   Firo Yang   hpfs: Remove unes...
229
  	ei = kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
234
  	if (!ei)
  		return NULL;
  	ei->vfs_inode.i_version = 1;
  	return &ei->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
235
  static void hpfs_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
237
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
  	kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
240
241
242
243
  static void hpfs_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, hpfs_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
244
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
  {
  	struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
247
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  }
20c2df83d   Paul Mundt   mm: Remove slab d...
249

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
252
253
  static int init_inodecache(void)
  {
  	hpfs_inode_cachep = kmem_cache_create("hpfs_inode_cache",
  					     sizeof(struct hpfs_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
254
  					     0, (SLAB_RECLAIM_ACCOUNT|
5d097056c   Vladimir Davydov   kmemcg: account c...
255
  						SLAB_MEM_SPREAD|SLAB_ACCOUNT),
20c2df83d   Paul Mundt   mm: Remove slab d...
256
  					     init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
259
260
261
262
263
  	if (hpfs_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  static void destroy_inodecache(void)
  {
8c0a85377   Kirill A. Shutemov   fs: push rcu_barr...
264
265
266
267
268
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
269
  	kmem_cache_destroy(hpfs_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
274
275
276
277
278
279
  }
  
  /*
   * A tiny parser for option strings, stolen from dosfs.
   * Stolen again from read-only hpfs.
   * And updated for table-driven option parsing.
   */
  
  enum {
  	Opt_help, Opt_uid, Opt_gid, Opt_umask, Opt_case_lower, Opt_case_asis,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
284
285
  	Opt_check_none, Opt_check_normal, Opt_check_strict,
  	Opt_err_cont, Opt_err_ro, Opt_err_panic,
  	Opt_eas_no, Opt_eas_ro, Opt_eas_rw,
  	Opt_chkdsk_no, Opt_chkdsk_errors, Opt_chkdsk_always,
  	Opt_timeshift, Opt_err,
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
286
  static const match_table_t tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
289
290
291
292
  	{Opt_help, "help"},
  	{Opt_uid, "uid=%u"},
  	{Opt_gid, "gid=%u"},
  	{Opt_umask, "umask=%o"},
  	{Opt_case_lower, "case=lower"},
  	{Opt_case_asis, "case=asis"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  	{Opt_check_none, "check=none"},
  	{Opt_check_normal, "check=normal"},
  	{Opt_check_strict, "check=strict"},
  	{Opt_err_cont, "errors=continue"},
  	{Opt_err_ro, "errors=remount-ro"},
  	{Opt_err_panic, "errors=panic"},
  	{Opt_eas_no, "eas=no"},
  	{Opt_eas_ro, "eas=ro"},
  	{Opt_eas_rw, "eas=rw"},
  	{Opt_chkdsk_no, "chkdsk=no"},
  	{Opt_chkdsk_errors, "chkdsk=errors"},
  	{Opt_chkdsk_always, "chkdsk=always"},
  	{Opt_timeshift, "timeshift=%d"},
  	{Opt_err, NULL},
  };
0e1a43c71   Eric W. Biederman   userns: Convert h...
308
  static int parse_opts(char *opts, kuid_t *uid, kgid_t *gid, umode_t *umask,
0fe105aa2   Mikulas Patocka   HPFS: Remove CR/L...
309
  		      int *lowercase, int *eas, int *chk, int *errs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
312
313
314
315
316
  		      int *chkdsk, int *timeshift)
  {
  	char *p;
  	int option;
  
  	if (!opts)
  		return 1;
b7cb1ce22   Fabian Frederick   fs/hpfs: convert ...
317
318
  	/*pr_info("Parsing opts: '%s'
  ",opts);*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
321
322
323
324
325
326
327
328
329
330
331
332
  
  	while ((p = strsep(&opts, ",")) != NULL) {
  		substring_t args[MAX_OPT_ARGS];
  		int token;
  		if (!*p)
  			continue;
  
  		token = match_token(p, tokens, args);
  		switch (token) {
  		case Opt_help:
  			return 2;
  		case Opt_uid:
  			if (match_int(args, &option))
  				return 0;
0e1a43c71   Eric W. Biederman   userns: Convert h...
333
334
335
  			*uid = make_kuid(current_user_ns(), option);
  			if (!uid_valid(*uid))
  				return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
339
  			break;
  		case Opt_gid:
  			if (match_int(args, &option))
  				return 0;
0e1a43c71   Eric W. Biederman   userns: Convert h...
340
341
342
  			*gid = make_kgid(current_user_ns(), option);
  			if (!gid_valid(*gid))
  				return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
346
347
348
349
350
351
352
353
354
  			break;
  		case Opt_umask:
  			if (match_octal(args, &option))
  				return 0;
  			*umask = option;
  			break;
  		case Opt_case_lower:
  			*lowercase = 1;
  			break;
  		case Opt_case_asis:
  			*lowercase = 0;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  		case Opt_check_none:
  			*chk = 0;
  			break;
  		case Opt_check_normal:
  			*chk = 1;
  			break;
  		case Opt_check_strict:
  			*chk = 2;
  			break;
  		case Opt_err_cont:
  			*errs = 0;
  			break;
  		case Opt_err_ro:
  			*errs = 1;
  			break;
  		case Opt_err_panic:
  			*errs = 2;
  			break;
  		case Opt_eas_no:
  			*eas = 0;
  			break;
  		case Opt_eas_ro:
  			*eas = 1;
  			break;
  		case Opt_eas_rw:
  			*eas = 2;
  			break;
  		case Opt_chkdsk_no:
  			*chkdsk = 0;
  			break;
  		case Opt_chkdsk_errors:
  			*chkdsk = 1;
  			break;
  		case Opt_chkdsk_always:
  			*chkdsk = 2;
  			break;
  		case Opt_timeshift:
  		{
  			int m = 1;
  			char *rhs = args[0].from;
  			if (!rhs || !*rhs)
  				return 0;
  			if (*rhs == '-') m = -1;
  			if (*rhs == '+' || *rhs == '-') rhs++;
  			*timeshift = simple_strtoul(rhs, &rhs, 0) * m;
  			if (*rhs)
  				return 0;
  			break;
  		}
  		default:
  			return 0;
  		}
  	}
  	return 1;
  }
  
  static inline void hpfs_help(void)
  {
b7cb1ce22   Fabian Frederick   fs/hpfs: convert ...
413
414
  	pr_info("
  \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
417
418
419
420
421
422
423
424
425
426
427
428
  HPFS filesystem options:
  \
        help              do not mount and display this text
  \
        uid=xxx           set uid of files that don't have uid specified in eas
  \
        gid=xxx           set gid of files that don't have gid specified in eas
  \
        umask=xxx         set mode of files that don't have mode specified in eas
  \
        case=lower        lowercase all files
  \
        case=asis         do not lowercase files (default)
  \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
        check=none        no fs checks - kernel may crash on corrupted filesystem
  \
        check=normal      do some checks - it should not crash (default)
  \
        check=strict      do extra time-consuming checks, used for debugging
  \
        errors=continue   continue on errors
  \
        errors=remount-ro remount read-only if errors found (default)
  \
        errors=panic      panic on errors
  \
        chkdsk=no         do not mark fs for chkdsking even if there were errors
  \
        chkdsk=errors     mark fs dirty if errors found (default)
  \
        chkdsk=always     always mark fs dirty - used for debugging
  \
        eas=no            ignore extended attributes
  \
        eas=ro            read but do not write extended attributes
  \
        eas=rw            r/w eas => enables chmod, chown, mknod, ln -s (default)
  \
        timeshift=nnn	add nnn seconds to file times
  \
  
  ");
  }
  
  static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
  {
0e1a43c71   Eric W. Biederman   userns: Convert h...
461
462
  	kuid_t uid;
  	kgid_t gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
  	umode_t umask;
0fe105aa2   Mikulas Patocka   HPFS: Remove CR/L...
464
  	int lowercase, eas, chk, errs, chkdsk, timeshift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
  	int o;
  	struct hpfs_sb_info *sbi = hpfs_sb(s);
ce657611b   Sanidhya Kashyap   hpfs: kstrdup() o...
467

02b9984d6   Theodore Ts'o   fs: push sync_fil...
468
  	sync_filesystem(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  	*flags |= MS_NOATIME;
ce657611b   Sanidhya Kashyap   hpfs: kstrdup() o...
470

9a311b96c   Arnd Bergmann   hpfs: remove the BKL
471
  	hpfs_lock(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
  	uid = sbi->sb_uid; gid = sbi->sb_gid;
  	umask = 0777 & ~sbi->sb_mode;
0fe105aa2   Mikulas Patocka   HPFS: Remove CR/L...
474
  	lowercase = sbi->sb_lowercase;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
  	eas = sbi->sb_eas; chk = sbi->sb_chk; chkdsk = sbi->sb_chkdsk;
  	errs = sbi->sb_err; timeshift = sbi->sb_timeshift;
0fe105aa2   Mikulas Patocka   HPFS: Remove CR/L...
477
  	if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
  	    &eas, &chk, &errs, &chkdsk, &timeshift))) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
479
480
  		pr_err("bad mount options.
  ");
6d9c1fd42   Miklos Szeredi   mount options: fi...
481
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
484
  	}
  	if (o == 2) {
  		hpfs_help();
6d9c1fd42   Miklos Szeredi   mount options: fi...
485
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
  	}
  	if (timeshift != sbi->sb_timeshift) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
488
489
  		pr_err("timeshift can't be changed using remount.
  ");
6d9c1fd42   Miklos Szeredi   mount options: fi...
490
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
493
494
495
496
  	}
  
  	unmark_dirty(s);
  
  	sbi->sb_uid = uid; sbi->sb_gid = gid;
  	sbi->sb_mode = 0777 & ~umask;
0fe105aa2   Mikulas Patocka   HPFS: Remove CR/L...
497
  	sbi->sb_lowercase = lowercase;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
  	sbi->sb_eas = eas; sbi->sb_chk = chk; sbi->sb_chkdsk = chkdsk;
  	sbi->sb_err = errs; sbi->sb_timeshift = timeshift;
dab4c82a6   Mikulas Patocka   HPFS: Fix a bug t...
500
  	if (!(*flags & MS_RDONLY)) mark_dirty(s, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501

9a311b96c   Arnd Bergmann   hpfs: remove the BKL
502
  	hpfs_unlock(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
  	return 0;
6d9c1fd42   Miklos Szeredi   mount options: fi...
504
505
  
  out_err:
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
506
  	hpfs_unlock(s);
6d9c1fd42   Miklos Szeredi   mount options: fi...
507
  	return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
  }
037369b87   Mikulas Patocka   hpfs: implement t...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
  static int hpfs_show_options(struct seq_file *seq, struct dentry *root)
  {
  	struct hpfs_sb_info *sbi = hpfs_sb(root->d_sb);
  
  	seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, sbi->sb_uid));
  	seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, sbi->sb_gid));
  	seq_printf(seq, ",umask=%03o", (~sbi->sb_mode & 0777));
  	if (sbi->sb_lowercase)
  		seq_printf(seq, ",case=lower");
  	if (!sbi->sb_chk)
  		seq_printf(seq, ",check=none");
  	if (sbi->sb_chk == 2)
  		seq_printf(seq, ",check=strict");
  	if (!sbi->sb_err)
  		seq_printf(seq, ",errors=continue");
  	if (sbi->sb_err == 2)
  		seq_printf(seq, ",errors=panic");
  	if (!sbi->sb_chkdsk)
  		seq_printf(seq, ",chkdsk=no");
  	if (sbi->sb_chkdsk == 2)
  		seq_printf(seq, ",chkdsk=always");
  	if (!sbi->sb_eas)
  		seq_printf(seq, ",eas=no");
  	if (sbi->sb_eas == 1)
  		seq_printf(seq, ",eas=ro");
  	if (sbi->sb_timeshift)
  		seq_printf(seq, ",timeshift=%d", sbi->sb_timeshift);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
  /* Super operations */
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
539
  static const struct super_operations hpfs_sops =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
  {
  	.alloc_inode	= hpfs_alloc_inode,
  	.destroy_inode	= hpfs_destroy_inode,
ea5440092   Al Viro   switch hpfs to ->...
543
  	.evict_inode	= hpfs_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
546
  	.put_super	= hpfs_put_super,
  	.statfs		= hpfs_statfs,
  	.remount_fs	= hpfs_remount_fs,
037369b87   Mikulas Patocka   hpfs: implement t...
547
  	.show_options	= hpfs_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
550
551
552
553
554
555
556
557
  };
  
  static int hpfs_fill_super(struct super_block *s, void *options, int silent)
  {
  	struct buffer_head *bh0, *bh1, *bh2;
  	struct hpfs_boot_block *bootblock;
  	struct hpfs_super_block *superblock;
  	struct hpfs_spare_block *spareblock;
  	struct hpfs_sb_info *sbi;
  	struct inode *root;
0e1a43c71   Eric W. Biederman   userns: Convert h...
558
559
  	kuid_t uid;
  	kgid_t gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
  	umode_t umask;
0fe105aa2   Mikulas Patocka   HPFS: Remove CR/L...
561
  	int lowercase, eas, chk, errs, chkdsk, timeshift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
564
565
566
567
  
  	dnode_secno root_dno;
  	struct hpfs_dirent *de = NULL;
  	struct quad_buffer_head qbh;
  
  	int o;
f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
568
  	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
db7192221   Jan Blunck   BKL: Explicitly a...
569
  	if (!sbi) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
  		return -ENOMEM;
db7192221   Jan Blunck   BKL: Explicitly a...
571
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
  	s->s_fs_info = sbi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573

7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
574
575
  	mutex_init(&sbi->hpfs_mutex);
  	hpfs_lock(s);
de395b8ac   David Howells   CRED: Wrap task c...
576
577
  	uid = current_uid();
  	gid = current_gid();
ce3b0f8d5   Al Viro   New helper - curr...
578
  	umask = current_umask();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
  	lowercase = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
  	eas = 2;
  	chk = 1;
  	errs = 1;
  	chkdsk = 1;
  	timeshift = 0;
0fe105aa2   Mikulas Patocka   HPFS: Remove CR/L...
585
  	if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  	    &eas, &chk, &errs, &chkdsk, &timeshift))) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
587
588
  		pr_err("bad mount options.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
  		goto bail0;
  	}
  	if (o==2) {
  		hpfs_help();
  		goto bail0;
  	}
  
  	/*sbi->sb_mounting = 1;*/
  	sb_set_blocksize(s, 512);
  	sbi->sb_fs_size = -1;
  	if (!(bootblock = hpfs_map_sector(s, 0, &bh0, 0))) goto bail1;
  	if (!(superblock = hpfs_map_sector(s, 16, &bh1, 1))) goto bail2;
  	if (!(spareblock = hpfs_map_sector(s, 17, &bh2, 0))) goto bail3;
  
  	/* Check magics */
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
604
605
606
  	if (/*le16_to_cpu(bootblock->magic) != BB_MAGIC
  	    ||*/ le32_to_cpu(superblock->magic) != SB_MAGIC
  	    || le32_to_cpu(spareblock->magic) != SP_MAGIC) {
b7cb1ce22   Fabian Frederick   fs/hpfs: convert ...
607
  		if (!silent)
a19189e55   Fabian Frederick   fs/hpfs: increase...
608
609
  			pr_err("Bad magic ... probably not HPFS
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
612
613
  		goto bail4;
  	}
  
  	/* Check version */
bc98a42c1   David Howells   VFS: Convert sb->...
614
  	if (!sb_rdonly(s) && superblock->funcversion != 2 && superblock->funcversion != 3) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
615
616
  		pr_err("Bad version %d,%d. Mount readonly to go around
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
  			(int)superblock->version, (int)superblock->funcversion);
a19189e55   Fabian Frederick   fs/hpfs: increase...
618
619
  		pr_err("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
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
621
622
623
624
625
626
627
  		goto bail4;
  	}
  
  	s->s_flags |= MS_NOATIME;
  
  	/* Fill superblock stuff */
  	s->s_magic = HPFS_SUPER_MAGIC;
  	s->s_op = &hpfs_sops;
43d344d77   Al Viro   switch hpfs
628
  	s->s_d_op = &hpfs_dentry_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629

0b69760be   Mikulas Patocka   HPFS: Fix endiani...
630
631
632
633
634
635
  	sbi->sb_root = le32_to_cpu(superblock->root);
  	sbi->sb_fs_size = le32_to_cpu(superblock->n_sectors);
  	sbi->sb_bitmaps = le32_to_cpu(superblock->bitmaps);
  	sbi->sb_dirband_start = le32_to_cpu(superblock->dir_band_start);
  	sbi->sb_dirband_size = le32_to_cpu(superblock->n_dir_band);
  	sbi->sb_dmap = le32_to_cpu(superblock->dir_band_bitmap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
638
639
640
641
  	sbi->sb_uid = uid;
  	sbi->sb_gid = gid;
  	sbi->sb_mode = 0777 & ~umask;
  	sbi->sb_n_free = -1;
  	sbi->sb_n_free_dnodes = -1;
  	sbi->sb_lowercase = lowercase;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
644
645
646
647
648
649
650
  	sbi->sb_eas = eas;
  	sbi->sb_chk = chk;
  	sbi->sb_chkdsk = chkdsk;
  	sbi->sb_err = errs;
  	sbi->sb_timeshift = timeshift;
  	sbi->sb_was_error = 0;
  	sbi->sb_cp_table = NULL;
  	sbi->sb_c_bitmap = -1;
  	sbi->sb_max_fwd_alloc = 0xffffff;
3ebacb050   Mikulas Patocka   hpfs: better test...
651
652
653
654
655
656
  
  	if (sbi->sb_fs_size >= 0x80000000) {
  		hpfs_error(s, "invalid size in superblock: %08x",
  			(unsigned)sbi->sb_fs_size);
  		goto bail4;
  	}
a64eefaac   Mikulas Patocka   hpfs: support hot...
657
658
  	if (spareblock->n_spares_used)
  		hpfs_load_hotfix_map(s, spareblock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
  	/* Load bitmap directory */
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
660
  	if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
663
664
665
  		goto bail4;
  	
  	/* Check for general fs errors*/
  	if (spareblock->dirty && !spareblock->old_wrote) {
  		if (errs == 2) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
666
667
  			pr_err("Improperly stopped, not mounted
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
670
671
  			goto bail4;
  		}
  		hpfs_error(s, "improperly stopped");
  	}
bc98a42c1   David Howells   VFS: Convert sb->...
672
  	if (!sb_rdonly(s)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
675
676
  		spareblock->dirty = 1;
  		spareblock->old_wrote = 0;
  		mark_buffer_dirty(bh2);
  	}
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
677
  	if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
  		if (errs >= 2) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
679
680
  			pr_err("Spare dnodes used, try chkdsk
  ");
dab4c82a6   Mikulas Patocka   HPFS: Fix a bug t...
681
  			mark_dirty(s, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
  			goto bail4;
  		}
  		hpfs_error(s, "warning: spare dnodes used, try chkdsk");
b7cb1ce22   Fabian Frederick   fs/hpfs: convert ...
685
  		if (errs == 0)
a19189e55   Fabian Frederick   fs/hpfs: increase...
686
687
  			pr_err("Proceeding, but your filesystem could be corrupted if you delete files or directories
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
690
  	}
  	if (chk) {
  		unsigned a;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
691
692
  		if (le32_to_cpu(superblock->dir_band_end) - le32_to_cpu(superblock->dir_band_start) + 1 != le32_to_cpu(superblock->n_dir_band) ||
  		    le32_to_cpu(superblock->dir_band_end) < le32_to_cpu(superblock->dir_band_start) || le32_to_cpu(superblock->n_dir_band) > 0x4000) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  			hpfs_error(s, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x",
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
694
  				le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->dir_band_end), le32_to_cpu(superblock->n_dir_band));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
696
697
698
  			goto bail4;
  		}
  		a = sbi->sb_dirband_size;
  		sbi->sb_dirband_size = 0;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
699
700
701
  		if (hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->n_dir_band), "dir_band") ||
  		    hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_bitmap), 4, "dir_band_bitmap") ||
  		    hpfs_chk_sectors(s, le32_to_cpu(superblock->bitmaps), 4, "bitmaps")) {
dab4c82a6   Mikulas Patocka   HPFS: Fix a bug t...
702
  			mark_dirty(s, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
  			goto bail4;
  		}
  		sbi->sb_dirband_size = a;
b7cb1ce22   Fabian Frederick   fs/hpfs: convert ...
706
  	} else
a19189e55   Fabian Frederick   fs/hpfs: increase...
707
708
  		pr_err("You really don't want any checks? You are crazy...
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
710
  
  	/* Load code page table */
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
711
712
  	if (le32_to_cpu(spareblock->n_code_pages))
  		if (!(sbi->sb_cp_table = hpfs_load_code_page(s, le32_to_cpu(spareblock->code_page_dir))))
a19189e55   Fabian Frederick   fs/hpfs: increase...
713
714
  			pr_err("code page support is disabled
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
718
719
720
721
722
723
724
725
  
  	brelse(bh2);
  	brelse(bh1);
  	brelse(bh0);
  
  	root = iget_locked(s, sbi->sb_root);
  	if (!root)
  		goto bail0;
  	hpfs_init_inode(root);
  	hpfs_read_inode(root);
  	unlock_new_inode(root);
48fde701a   Al Viro   switch open-coded...
726
727
  	s->s_root = d_make_root(root);
  	if (!s->s_root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
  		goto bail0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
730
731
732
733
734
735
736
737
738
739
  
  	/*
  	 * find the root directory's . pointer & finish filling in the inode
  	 */
  
  	root_dno = hpfs_fnode_dno(s, sbi->sb_root);
  	if (root_dno)
  		de = map_dirent(root, root_dno, "\001\001", 2, NULL, &qbh);
  	if (!de)
  		hpfs_error(s, "unable to find root dir");
  	else {
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
740
  		root->i_atime.tv_sec = local_to_gmt(s, le32_to_cpu(de->read_date));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  		root->i_atime.tv_nsec = 0;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
742
  		root->i_mtime.tv_sec = local_to_gmt(s, le32_to_cpu(de->write_date));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
  		root->i_mtime.tv_nsec = 0;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
744
  		root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
  		root->i_ctime.tv_nsec = 0;
de5e2b362   Al Viro   hpfs: endianness ...
746
  		hpfs_i(root)->i_ea_size = le32_to_cpu(de->ea_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747
748
749
750
751
752
753
  		hpfs_i(root)->i_parent_dir = root->i_ino;
  		if (root->i_size == -1)
  			root->i_size = 2048;
  		if (root->i_blocks == -1)
  			root->i_blocks = 5;
  		hpfs_brelse4(&qbh);
  	}
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
754
  	hpfs_unlock(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
756
757
758
759
760
761
  	return 0;
  
  bail4:	brelse(bh2);
  bail3:	brelse(bh1);
  bail2:	brelse(bh0);
  bail1:
  bail0:
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
762
  	hpfs_unlock(s);
30687e0a4   Al Viro   hpfs: make freein...
763
  	free_sbi(sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
  	return -EINVAL;
  }
152a08366   Al Viro   new helper: mount...
766
767
  static struct dentry *hpfs_mount(struct file_system_type *fs_type,
  	int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
  {
152a08366   Al Viro   new helper: mount...
769
  	return mount_bdev(fs_type, flags, dev_name, data, hpfs_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
771
772
773
774
  }
  
  static struct file_system_type hpfs_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "hpfs",
152a08366   Al Viro   new helper: mount...
775
  	.mount		= hpfs_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
777
778
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,
  };
3e64fe5b2   Eric W. Biederman   fs: Limit sys_mou...
779
  MODULE_ALIAS_FS("hpfs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
  
  static int __init init_hpfs_fs(void)
  {
  	int err = init_inodecache();
  	if (err)
  		goto out1;
  	err = register_filesystem(&hpfs_fs_type);
  	if (err)
  		goto out;
  	return 0;
  out:
  	destroy_inodecache();
  out1:
  	return err;
  }
  
  static void __exit exit_hpfs_fs(void)
  {
  	unregister_filesystem(&hpfs_fs_type);
  	destroy_inodecache();
  }
  
  module_init(init_hpfs_fs)
  module_exit(exit_hpfs_fs)
  MODULE_LICENSE("GPL");