Import 2.3.1pre2
[davej-history.git] / fs / hfs / super.c
blob6f177f136d93d8e06659ed02e5410685bef94e63
1 /*
2 * linux/fs/hfs/super.c
4 * Copyright (C) 1995-1997 Paul H. Hargrove
5 * This file may be distributed under the terms of the GNU Public License.
7 * This file contains hfs_read_super(), some of the super_ops and
8 * init_module() and cleanup_module(). The remaining super_ops are in
9 * inode.c since they deal with inodes.
11 * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
13 * "XXX" in a comment is a note to myself to consider changing something.
15 * In function preconditions the term "valid" applied to a pointer to
16 * a structure means that the pointer is non-NULL and the structure it
17 * points to has all fields initialized to consistent values.
19 * The code in this file initializes some structures which contain
20 * pointers by calling memset(&foo, 0, sizeof(foo)).
21 * This produces the desired behavior only due to the non-ANSI
22 * assumption that the machine representation of NULL is all zeros.
25 #include "hfs.h"
26 #include <linux/hfs_fs_sb.h>
27 #include <linux/hfs_fs_i.h>
28 #include <linux/hfs_fs.h>
30 #include <linux/config.h> /* for CONFIG_MAC_PARTITION */
31 #include <linux/blkdev.h>
32 #include <linux/module.h>
33 #include <linux/init.h>
35 /*================ Forward declarations ================*/
37 static void hfs_read_inode(struct inode *);
38 static void hfs_put_super(struct super_block *);
39 static int hfs_statfs(struct super_block *, struct statfs *, int);
40 static void hfs_write_super(struct super_block *);
42 /*================ Global variables ================*/
44 static struct super_operations hfs_super_operations = {
45 hfs_read_inode, /* read_inode */
46 NULL, /* write_inode */
47 hfs_put_inode, /* put_inode - in inode.c */
48 NULL, /* delete_inode */
49 hfs_notify_change, /* notify_change - in inode.c */
50 hfs_put_super, /* put_super */
51 hfs_write_super, /* write_super */
52 hfs_statfs, /* statfs */
53 NULL /* remount_fs */
56 /*================ File-local variables ================*/
58 static struct file_system_type hfs_fs = {
59 "hfs",
60 FS_REQUIRES_DEV,
61 hfs_read_super,
62 NULL};
64 /*================ File-local functions ================*/
66 /*
67 * hfs_read_inode()
69 * this doesn't actually do much. hfs_iget actually fills in the
70 * necessary inode information.
72 static void hfs_read_inode(struct inode *inode)
74 inode->i_mode = 0;
75 inode->i_op = NULL;
79 * hfs_write_super()
81 * Description:
82 * This function is called by the VFS only. When the filesystem
83 * is mounted r/w it updates the MDB on disk.
84 * Input Variable(s):
85 * struct super_block *sb: Pointer to the hfs superblock
86 * Output Variable(s):
87 * NONE
88 * Returns:
89 * void
90 * Preconditions:
91 * 'sb' points to a "valid" (struct super_block).
92 * Postconditions:
93 * The MDB is marked 'unsuccessfully unmounted' by clearing bit 8 of drAtrb
94 * (hfs_put_super() must set this flag!). Some MDB fields are updated
95 * and the MDB buffer is written to disk by calling hfs_mdb_commit().
97 static void hfs_write_super(struct super_block *sb)
99 struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
101 /* is this a valid hfs superblock? */
102 if (!sb || sb->s_magic != HFS_SUPER_MAGIC) {
103 return;
106 if (!(sb->s_flags & MS_RDONLY)) {
107 /* sync everything to the buffers */
108 hfs_mdb_commit(mdb, 0);
110 sb->s_dirt = 0;
114 * hfs_put_super()
116 * This is the put_super() entry in the super_operations structure for
117 * HFS filesystems. The purpose is to release the resources
118 * associated with the superblock sb.
120 static void hfs_put_super(struct super_block *sb)
122 struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
124 if (!(sb->s_flags & MS_RDONLY)) {
125 hfs_mdb_commit(mdb, 0);
126 sb->s_dirt = 0;
129 /* release the MDB's resources */
130 hfs_mdb_put(mdb, sb->s_flags & MS_RDONLY);
132 /* restore default blocksize for the device */
133 set_blocksize(sb->s_dev, BLOCK_SIZE);
135 MOD_DEC_USE_COUNT;
139 * hfs_statfs()
141 * This is the statfs() entry in the super_operations structure for
142 * HFS filesystems. The purpose is to return various data about the
143 * filesystem.
145 * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
147 static int hfs_statfs(struct super_block *sb, struct statfs *buf, int len)
149 struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
150 struct statfs tmp;
152 tmp.f_type = HFS_SUPER_MAGIC;
153 tmp.f_bsize = HFS_SECTOR_SIZE;
154 tmp.f_blocks = mdb->alloc_blksz * mdb->fs_ablocks;
155 tmp.f_bfree = mdb->alloc_blksz * mdb->free_ablocks;
156 tmp.f_bavail = tmp.f_bfree;
157 tmp.f_files = mdb->fs_ablocks;
158 tmp.f_ffree = mdb->free_ablocks;
159 tmp.f_namelen = HFS_NAMELEN;
161 return copy_to_user(buf, &tmp, len) ? -EFAULT : 0;
165 * parse_options()
167 * adapted from linux/fs/msdos/inode.c written 1992,93 by Werner Almesberger
168 * This function is called by hfs_read_super() to parse the mount options.
170 static int parse_options(char *options, struct hfs_sb_info *hsb, int *part)
172 char *this_char, *value;
173 char names, fork;
175 /* initialize the sb with defaults */
176 memset(hsb, 0, sizeof(*hsb));
177 hsb->magic = HFS_SB_MAGIC;
178 hsb->s_uid = current->uid;
179 hsb->s_gid = current->gid;
180 hsb->s_umask = current->fs->umask;
181 hsb->s_type = 0x3f3f3f3f; /* == '????' */
182 hsb->s_creator = 0x3f3f3f3f; /* == '????' */
183 hsb->s_lowercase = 0;
184 hsb->s_quiet = 0;
185 hsb->s_afpd = 0;
186 hsb->s_conv = 'b';
187 names = '?';
188 fork = '?';
189 *part = 0;
191 if (!options) {
192 goto done;
194 for (this_char = strtok(options,","); this_char;
195 this_char = strtok(NULL,",")) {
196 if ((value = strchr(this_char,'=')) != NULL) {
197 *value++ = 0;
199 /* Numeric-valued options */
200 if (!strcmp(this_char,"uid")) {
201 if (!value || !*value) {
202 return 0;
204 hsb->s_uid = simple_strtoul(value,&value,0);
205 if (*value) {
206 return 0;
208 } else if (!strcmp(this_char,"gid")) {
209 if (!value || !*value) {
210 return 0;
212 hsb->s_gid = simple_strtoul(value,&value,0);
213 if (*value) {
214 return 0;
216 } else if (!strcmp(this_char,"umask")) {
217 if (!value || !*value) {
218 return 0;
220 hsb->s_umask = simple_strtoul(value,&value,8);
221 if (*value) {
222 return 0;
224 } else if (!strcmp(this_char,"part")) {
225 if (!value || !*value) {
226 return 0;
228 *part = simple_strtoul(value,&value,0);
229 if (*value) {
230 return 0;
232 /* String-valued options */
233 } else if (!strcmp(this_char,"type") && value) {
234 if (strlen(value) != 4) {
235 return 0;
237 hsb->s_type = hfs_get_nl(value);
238 } else if (!strcmp(this_char,"creator") && value) {
239 if (strlen(value) != 4) {
240 return 0;
242 hsb->s_creator = hfs_get_nl(value);
243 /* Boolean-valued options */
244 } else if (!strcmp(this_char,"quiet")) {
245 if (value) {
246 return 0;
248 hsb->s_quiet = 1;
249 } else if (!strcmp(this_char,"afpd")) {
250 if (value) {
251 return 0;
253 hsb->s_afpd = 1;
254 /* Multiple choice options */
255 } else if (!strcmp(this_char,"names") && value) {
256 if ((*value && !value[1] && strchr("ntal78c",*value)) ||
257 !strcmp(value,"netatalk") ||
258 !strcmp(value,"trivial") ||
259 !strcmp(value,"alpha") ||
260 !strcmp(value,"latin") ||
261 !strcmp(value,"7bit") ||
262 !strcmp(value,"8bit") ||
263 !strcmp(value,"cap")) {
264 names = *value;
265 } else {
266 return 0;
268 } else if (!strcmp(this_char,"fork") && value) {
269 if ((*value && !value[1] && strchr("nsdc",*value)) ||
270 !strcmp(value,"netatalk") ||
271 !strcmp(value,"single") ||
272 !strcmp(value,"double") ||
273 !strcmp(value,"cap")) {
274 fork = *value;
275 } else {
276 return 0;
278 } else if (!strcmp(this_char,"case") && value) {
279 if ((*value && !value[1] && strchr("la",*value)) ||
280 !strcmp(value,"lower") ||
281 !strcmp(value,"asis")) {
282 hsb->s_lowercase = (*value == 'l');
283 } else {
284 return 0;
286 } else if (!strcmp(this_char,"conv") && value) {
287 if ((*value && !value[1] && strchr("bta",*value)) ||
288 !strcmp(value,"binary") ||
289 !strcmp(value,"text") ||
290 !strcmp(value,"auto")) {
291 hsb->s_conv = *value;
292 } else {
293 return 0;
295 } else {
296 return 0;
300 done:
301 /* Parse the "fork" and "names" options */
302 if (fork == '?') {
303 fork = hsb->s_afpd ? 'n' : 'c';
305 switch (fork) {
306 default:
307 case 'c':
308 hsb->s_ifill = hfs_cap_ifill;
309 hsb->s_reserved1 = hfs_cap_reserved1;
310 hsb->s_reserved2 = hfs_cap_reserved2;
311 break;
313 case 's':
314 hfs_warn("hfs_fs: AppleSingle not yet implemented.\n");
315 return 0;
316 /* break; */
318 case 'd':
319 hsb->s_ifill = hfs_dbl_ifill;
320 hsb->s_reserved1 = hfs_dbl_reserved1;
321 hsb->s_reserved2 = hfs_dbl_reserved2;
322 break;
324 case 'n':
325 hsb->s_ifill = hfs_nat_ifill;
326 hsb->s_reserved1 = hfs_nat_reserved1;
327 hsb->s_reserved2 = hfs_nat_reserved2;
328 break;
331 if (names == '?') {
332 names = fork;
334 switch (names) {
335 default:
336 case 'n':
337 hsb->s_nameout = hfs_colon2mac;
338 hsb->s_namein = hfs_mac2nat;
339 break;
341 case 'c':
342 hsb->s_nameout = hfs_colon2mac;
343 hsb->s_namein = hfs_mac2cap;
344 break;
346 case 't':
347 hsb->s_nameout = hfs_triv2mac;
348 hsb->s_namein = hfs_mac2triv;
349 break;
351 case '7':
352 hsb->s_nameout = hfs_prcnt2mac;
353 hsb->s_namein = hfs_mac2seven;
354 break;
356 case '8':
357 hsb->s_nameout = hfs_prcnt2mac;
358 hsb->s_namein = hfs_mac2eight;
359 break;
361 case 'l':
362 hsb->s_nameout = hfs_latin2mac;
363 hsb->s_namein = hfs_mac2latin;
364 break;
366 case 'a': /* 's' and 'd' are unadvertised aliases for 'alpha', */
367 case 's': /* since 'alpha' is the default if fork=s or fork=d. */
368 case 'd': /* (It is also helpful for poor typists!) */
369 hsb->s_nameout = hfs_prcnt2mac;
370 hsb->s_namein = hfs_mac2alpha;
371 break;
374 return 1;
377 /*================ Global functions ================*/
380 * hfs_read_super()
382 * This is the function that is responsible for mounting an HFS
383 * filesystem. It performs all the tasks necessary to get enough data
384 * from the disk to read the root inode. This includes parsing the
385 * mount options, dealing with Macintosh partitions, reading the
386 * superblock and the allocation bitmap blocks, calling
387 * hfs_btree_init() to get the necessary data about the extents and
388 * catalog B-trees and, finally, reading the root inode into memory.
390 struct super_block *hfs_read_super(struct super_block *s, void *data,
391 int silent)
393 struct hfs_mdb *mdb;
394 struct hfs_cat_key key;
395 kdev_t dev = s->s_dev;
396 hfs_s32 part_size, part_start;
397 struct inode *root_inode;
398 int part;
400 if (!parse_options((char *)data, HFS_SB(s), &part)) {
401 hfs_warn("hfs_fs: unable to parse mount options.\n");
402 goto bail3;
405 /* in case someone tries to unload the module while we wait on I/O */
406 MOD_INC_USE_COUNT;
408 lock_super(s);
410 /* set the device driver to 512-byte blocks */
411 set_blocksize(dev, HFS_SECTOR_SIZE);
413 #ifdef CONFIG_MAC_PARTITION
414 /* check to see if we're in a partition */
415 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, 0);
417 /* erk. try parsing the partition table ourselves */
418 if (!mdb) {
419 if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
420 goto bail2;
422 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
424 #else
425 if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
426 goto bail2;
429 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
430 #endif
432 if (!mdb) {
433 if (!silent) {
434 hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
435 kdevname(dev));
437 goto bail2;
440 HFS_SB(s)->s_mdb = mdb;
441 if (HFS_ITYPE(mdb->next_id) != 0) {
442 hfs_warn("hfs_fs: too many files.\n");
443 goto bail1;
446 s->s_magic = HFS_SUPER_MAGIC;
447 s->s_blocksize_bits = HFS_SECTOR_SIZE_BITS;
448 s->s_blocksize = HFS_SECTOR_SIZE;
449 s->s_op = &hfs_super_operations;
451 /* try to get the root inode */
452 hfs_cat_build_key(htonl(HFS_POR_CNID),
453 (struct hfs_name *)(mdb->vname), &key);
455 root_inode = hfs_iget(hfs_cat_get(mdb, &key), HFS_ITYPE_NORM, NULL);
456 if (!root_inode)
457 goto bail_no_root;
459 s->s_root = d_alloc_root(root_inode, NULL);
460 if (!s->s_root)
461 goto bail_no_root;
463 /* fix up pointers. */
464 HFS_I(root_inode)->entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE_NORM)] =
465 s->s_root;
466 s->s_root->d_op = &hfs_dentry_operations;
468 /* everything's okay */
469 unlock_super(s);
470 return s;
472 bail_no_root:
473 hfs_warn("hfs_fs: get root inode failed.\n");
474 iput(root_inode);
475 bail1:
476 hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
477 bail2:
478 set_blocksize(dev, BLOCK_SIZE);
479 unlock_super(s);
480 MOD_DEC_USE_COUNT;
481 bail3:
482 s->s_dev = 0;
483 return NULL;
486 __initfunc(int init_hfs_fs(void))
488 hfs_cat_init();
489 return register_filesystem(&hfs_fs);
492 #ifdef MODULE
493 int init_module(void) {
494 int error;
496 #if defined(DEBUG_SIZES) || defined(DEBUG_ALL)
497 hfs_warn("HFS inode: %d bytes available\n",
498 sizeof(struct ext2_inode_info)-sizeof(struct hfs_inode_info));
499 hfs_warn("HFS super_block: %d bytes available\n",
500 sizeof(struct ext2_sb_info)-sizeof(struct hfs_sb_info));
501 if ((sizeof(struct hfs_inode_info)>sizeof(struct ext2_inode_info)) ||
502 (sizeof(struct hfs_sb_info)>sizeof(struct ext2_sb_info))) {
503 return -ENOMEM; /* well sort of */
505 #endif
506 error = init_hfs_fs();
507 if (!error) {
508 /* register_symtab(NULL); */
510 return error;
513 void cleanup_module(void) {
514 hfs_cat_free();
515 unregister_filesystem(&hfs_fs);
517 #endif
519 #if defined(DEBUG_ALL) || defined(DEBUG_MEM)
520 long int hfs_alloc = 0;
521 #endif