Import 2.3.26pre2
[davej-history.git] / fs / hfs / super.c
blobcb10a760caad708e9f3e1f0c4a12b78f96297269
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 /* default version. 0 just selects the defaults */
187 hsb->s_version = 0;
188 hsb->s_conv = 'b';
189 names = '?';
190 fork = '?';
191 *part = 0;
193 if (!options) {
194 goto done;
196 for (this_char = strtok(options,","); this_char;
197 this_char = strtok(NULL,",")) {
198 if ((value = strchr(this_char,'=')) != NULL) {
199 *value++ = 0;
201 /* Numeric-valued options */
202 if (!strcmp(this_char, "version")) {
203 if (!value || !*value) {
204 return 0;
206 hsb->s_version = simple_strtoul(value,&value,0);
207 if (*value) {
208 return 0;
210 } else if (!strcmp(this_char,"uid")) {
211 if (!value || !*value) {
212 return 0;
214 hsb->s_uid = simple_strtoul(value,&value,0);
215 if (*value) {
216 return 0;
218 } else if (!strcmp(this_char,"gid")) {
219 if (!value || !*value) {
220 return 0;
222 hsb->s_gid = simple_strtoul(value,&value,0);
223 if (*value) {
224 return 0;
226 } else if (!strcmp(this_char,"umask")) {
227 if (!value || !*value) {
228 return 0;
230 hsb->s_umask = simple_strtoul(value,&value,8);
231 if (*value) {
232 return 0;
234 } else if (!strcmp(this_char,"part")) {
235 if (!value || !*value) {
236 return 0;
238 *part = simple_strtoul(value,&value,0);
239 if (*value) {
240 return 0;
242 /* String-valued options */
243 } else if (!strcmp(this_char,"type") && value) {
244 if (strlen(value) != 4) {
245 return 0;
247 hsb->s_type = hfs_get_nl(value);
248 } else if (!strcmp(this_char,"creator") && value) {
249 if (strlen(value) != 4) {
250 return 0;
252 hsb->s_creator = hfs_get_nl(value);
253 /* Boolean-valued options */
254 } else if (!strcmp(this_char,"quiet")) {
255 if (value) {
256 return 0;
258 hsb->s_quiet = 1;
259 } else if (!strcmp(this_char,"afpd")) {
260 if (value) {
261 return 0;
263 hsb->s_afpd = 1;
264 /* Multiple choice options */
265 } else if (!strcmp(this_char,"names") && value) {
266 if ((*value && !value[1] && strchr("ntal78c",*value)) ||
267 !strcmp(value,"netatalk") ||
268 !strcmp(value,"trivial") ||
269 !strcmp(value,"alpha") ||
270 !strcmp(value,"latin") ||
271 !strcmp(value,"7bit") ||
272 !strcmp(value,"8bit") ||
273 !strcmp(value,"cap")) {
274 names = *value;
275 } else {
276 return 0;
278 } else if (!strcmp(this_char,"fork") && value) {
279 if ((*value && !value[1] && strchr("nsdc",*value)) ||
280 !strcmp(value,"netatalk") ||
281 !strcmp(value,"single") ||
282 !strcmp(value,"double") ||
283 !strcmp(value,"cap")) {
284 fork = *value;
285 } else {
286 return 0;
288 } else if (!strcmp(this_char,"case") && value) {
289 if ((*value && !value[1] && strchr("la",*value)) ||
290 !strcmp(value,"lower") ||
291 !strcmp(value,"asis")) {
292 hsb->s_lowercase = (*value == 'l');
293 } else {
294 return 0;
296 } else if (!strcmp(this_char,"conv") && value) {
297 if ((*value && !value[1] && strchr("bta",*value)) ||
298 !strcmp(value,"binary") ||
299 !strcmp(value,"text") ||
300 !strcmp(value,"auto")) {
301 hsb->s_conv = *value;
302 } else {
303 return 0;
305 } else {
306 return 0;
310 done:
311 /* Parse the "fork" and "names" options */
312 if (fork == '?') {
313 fork = hsb->s_afpd ? 'n' : 'c';
315 switch (fork) {
316 default:
317 case 'c':
318 hsb->s_ifill = hfs_cap_ifill;
319 hsb->s_reserved1 = hfs_cap_reserved1;
320 hsb->s_reserved2 = hfs_cap_reserved2;
321 break;
323 case 's':
324 hfs_warn("hfs_fs: AppleSingle not yet implemented.\n");
325 return 0;
326 /* break; */
328 case 'd':
329 hsb->s_ifill = hfs_dbl_ifill;
330 hsb->s_reserved1 = hfs_dbl_reserved1;
331 hsb->s_reserved2 = hfs_dbl_reserved2;
332 break;
334 case 'n':
335 hsb->s_ifill = hfs_nat_ifill;
336 hsb->s_reserved1 = hfs_nat_reserved1;
337 hsb->s_reserved2 = hfs_nat_reserved2;
338 break;
341 if (names == '?') {
342 names = fork;
344 switch (names) {
345 default:
346 case 'n':
347 hsb->s_nameout = hfs_colon2mac;
348 hsb->s_namein = hfs_mac2nat;
349 break;
351 case 'c':
352 hsb->s_nameout = hfs_colon2mac;
353 hsb->s_namein = hfs_mac2cap;
354 break;
356 case 't':
357 hsb->s_nameout = hfs_triv2mac;
358 hsb->s_namein = hfs_mac2triv;
359 break;
361 case '7':
362 hsb->s_nameout = hfs_prcnt2mac;
363 hsb->s_namein = hfs_mac2seven;
364 break;
366 case '8':
367 hsb->s_nameout = hfs_prcnt2mac;
368 hsb->s_namein = hfs_mac2eight;
369 break;
371 case 'l':
372 hsb->s_nameout = hfs_latin2mac;
373 hsb->s_namein = hfs_mac2latin;
374 break;
376 case 'a': /* 's' and 'd' are unadvertised aliases for 'alpha', */
377 case 's': /* since 'alpha' is the default if fork=s or fork=d. */
378 case 'd': /* (It is also helpful for poor typists!) */
379 hsb->s_nameout = hfs_prcnt2mac;
380 hsb->s_namein = hfs_mac2alpha;
381 break;
384 return 1;
387 /*================ Global functions ================*/
390 * hfs_read_super()
392 * This is the function that is responsible for mounting an HFS
393 * filesystem. It performs all the tasks necessary to get enough data
394 * from the disk to read the root inode. This includes parsing the
395 * mount options, dealing with Macintosh partitions, reading the
396 * superblock and the allocation bitmap blocks, calling
397 * hfs_btree_init() to get the necessary data about the extents and
398 * catalog B-trees and, finally, reading the root inode into memory.
400 struct super_block *hfs_read_super(struct super_block *s, void *data,
401 int silent)
403 struct hfs_mdb *mdb;
404 struct hfs_cat_key key;
405 kdev_t dev = s->s_dev;
406 hfs_s32 part_size, part_start;
407 struct inode *root_inode;
408 int part;
410 if (!parse_options((char *)data, HFS_SB(s), &part)) {
411 hfs_warn("hfs_fs: unable to parse mount options.\n");
412 goto bail3;
415 /* in case someone tries to unload the module while we wait on I/O */
416 MOD_INC_USE_COUNT;
418 lock_super(s);
420 /* set the device driver to 512-byte blocks */
421 set_blocksize(dev, HFS_SECTOR_SIZE);
423 #ifdef CONFIG_MAC_PARTITION
424 /* check to see if we're in a partition */
425 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, 0);
427 /* erk. try parsing the partition table ourselves */
428 if (!mdb) {
429 if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
430 goto bail2;
432 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
434 #else
435 if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
436 goto bail2;
439 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
440 #endif
442 if (!mdb) {
443 if (!silent) {
444 hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
445 kdevname(dev));
447 goto bail2;
450 HFS_SB(s)->s_mdb = mdb;
451 if (HFS_ITYPE(mdb->next_id) != 0) {
452 hfs_warn("hfs_fs: too many files.\n");
453 goto bail1;
456 s->s_magic = HFS_SUPER_MAGIC;
457 s->s_blocksize_bits = HFS_SECTOR_SIZE_BITS;
458 s->s_blocksize = HFS_SECTOR_SIZE;
459 s->s_op = &hfs_super_operations;
461 /* try to get the root inode */
462 hfs_cat_build_key(htonl(HFS_POR_CNID),
463 (struct hfs_name *)(mdb->vname), &key);
465 root_inode = hfs_iget(hfs_cat_get(mdb, &key), HFS_ITYPE_NORM, NULL);
466 if (!root_inode)
467 goto bail_no_root;
469 s->s_root = d_alloc_root(root_inode);
470 if (!s->s_root)
471 goto bail_no_root;
473 /* fix up pointers. */
474 HFS_I(root_inode)->entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE_NORM)] =
475 s->s_root;
476 s->s_root->d_op = &hfs_dentry_operations;
478 /* everything's okay */
479 unlock_super(s);
480 return s;
482 bail_no_root:
483 hfs_warn("hfs_fs: get root inode failed.\n");
484 iput(root_inode);
485 bail1:
486 hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
487 bail2:
488 set_blocksize(dev, BLOCK_SIZE);
489 unlock_super(s);
490 MOD_DEC_USE_COUNT;
491 bail3:
492 s->s_dev = 0;
493 return NULL;
496 int __init init_hfs_fs(void)
498 hfs_cat_init();
499 return register_filesystem(&hfs_fs);
502 #ifdef MODULE
503 int init_module(void) {
504 int error;
506 #if defined(DEBUG_SIZES) || defined(DEBUG_ALL)
507 hfs_warn("HFS inode: %d bytes available\n",
508 sizeof(struct ext2_inode_info)-sizeof(struct hfs_inode_info));
509 hfs_warn("HFS super_block: %d bytes available\n",
510 sizeof(struct ext2_sb_info)-sizeof(struct hfs_sb_info));
511 if ((sizeof(struct hfs_inode_info)>sizeof(struct ext2_inode_info)) ||
512 (sizeof(struct hfs_sb_info)>sizeof(struct ext2_sb_info))) {
513 return -ENOMEM; /* well sort of */
515 #endif
516 error = init_hfs_fs();
517 if (!error) {
518 /* register_symtab(NULL); */
520 return error;
523 void cleanup_module(void) {
524 hfs_cat_free();
525 unregister_filesystem(&hfs_fs);
527 #endif
529 #if defined(DEBUG_ALL) || defined(DEBUG_MEM)
530 long int hfs_alloc = 0;
531 #endif