/* * super.c * * PURPOSE * Super block routines for OSTA-UDF(tm) filesystem. * * DESCRIPTION * OSTA-UDF(tm) = Optical Storage Technology Association * Universal Disk Format. * * This code is based on version 1.50 of the UDF specification, * and the 2nd edition of ECMA-167 standard [equivalent to ISO 13346]. * * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): * linux_udf@hootie.lvld.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL) version 2.0. Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" /* Thses are defined in inode.c */ extern void udf_read_inode(struct inode *); extern void udf_write_inode(struct inode *); extern void udf_put_inode(struct inode *); extern void udf_delete_inode(struct inode *); /* These are the "meat" - everything else is stuffing */ static struct super_block *udf_read_super(struct super_block *, void *, int); static void udf_put_super(struct super_block *); static int udf_statfs(struct super_block *, struct statfs *, int); /* UDF filesystem type */ static struct file_system_type udf_fstype = { "udf", /* name */ FS_REQUIRES_DEV, /* fs_flags */ udf_read_super, /* read_super */ NULL /* next */ }; /* Superblock operations */ static struct super_operations udf_sb_ops = { udf_read_inode, /* read_inode */ udf_write_inode, /* write_inode */ udf_put_inode, /* put_inode */ udf_delete_inode, /* delete_inode */ NULL, /* notify_change */ udf_put_super, /* put_super */ NULL, /* write_super */ udf_statfs, /* statfs */ NULL /* remount_fs */ }; /* Debugging level. Affects all UDF filesystems! */ int udf_debuglvl; #if defined(MODULE) /* * cleanup_module * * PURPOSE * Unregister the UDF filesystem type. * * DESCRIPTION * Clean-up before the module is unloaded. * This routine only applies when compiled as a module. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ extern int cleanup_module(void) { PRINTK((KERN_NOTICE "udf: unregistering filesystem\n")); return unregister_filesystem(&udf_fstype); } /* * init_module / init_udf_fs * * PURPOSE * Register the UDF filesystem type. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ extern int init_module(void) #else /* if !defined(MODULE) */ __initfunc(int init_udf_fs(void)) #endif { PRINTK((KERN_NOTICE "udf: registering filesystem\n")); udf_debuglvl = DEBUG_NONE; return register_filesystem(&udf_fstype); } /* * udf_parse_options * * PURPOSE * Parse mount options. * * DESCRIPTION * The following mount options are supported: * * bs= Set the block size. * debug= Set the debugging level for _all_ UDF filesystems. * fixed Disable removable media checks. * gid= Set the default group. * mode= Set the default mode. * relaxed Set relaxed conformance. * uid= Set the default user. * * PRE-CONDITIONS * sb Pointer to _locked_ superblock. * opts Pointer to mount options string. * * POST-CONDITIONS * 0 Mount options parsed okay. * -1 Error parsing mount options. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ static __inline__ int udf_parse_options(struct super_block *sb, char *opts) { char *opt, *val; /* Set defaults */ sb->s_blocksize = 0; UDF_SB(sb)->s_flags = UDF_FLAG_STRICT; UDF_SB(sb)->s_mode = S_IRUGO | S_IXUGO; UDF_SB(sb)->s_gid = 0; UDF_SB(sb)->s_uid = 0; /* Break up the mount options */ for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ",")) { /* Make "opt=val" into two strings */ val = strchr(opt, '='); if (val) *(val++) = 0; if (!strcmp(opt, "bs") && !val) sb->s_blocksize = simple_strtoul(val, NULL, 0); if (!strcmp(opt, "debug") &&!val) udf_debuglvl = simple_strtoul(val, NULL, 0); if (!strcmp(opt, "figed") && !val) UDF_SB(sb)->s_flags |= UDF_FLAG_FIXED; else if (!strcmp(opt, "gid") && val) UDF_SB(sb)->s_gid = simple_strtoul(val, NULL, 0); else if (!strcmp(opt, "mode") && val) UDF_SB(sb)->s_mode = simple_strtoul(val, NULL, 0); else if (!strcmp(opt, "relaxed") && !val) UDF_SB(sb)->s_flags &= ~UDF_FLAG_STRICT; else if (!strcmp(opt, "uid") && val) UDF_SB(sb)->s_uid = simple_strtoul(val, NULL, 0); else if (val) { printk(KERN_ERR "udf: bad mount option \"%s=%s\"\n", opt, val); return -1; } else { printk(KERN_ERR "udf: bad mount option \"%s\"\n", opt); return -1; } } return 0; } /* * udf_set_blocksize * * PURPOSE * Set the block size to be used in all transfers. * * DESCRIPTION * To allow room for a DMA transfer, it is best to guess big when unsure. * This routine picks 2048 bytes as the blocksize when guessing. This * should be adequate until devices with larger block sizes become common. * * Note that the Linux kernel can currently only deal with blocksizes of * 512, 1024, 2048, 4096, and 8192 bytes. * * PRE-CONDITIONS * sb Pointer to _locked_ superblock. * * POST-CONDITIONS * sb->s_blocksize Blocksize. * sb->s_blocksize_bits log2 of blocksize. * 0 Blocksize is valid. * 1 Blocksize is invalid. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ static __inline__ int udf_set_blocksize(struct super_block *sb) { int blocksize; /* Use specified block size if specified */ blocksize = sb->s_blocksize ? sb->s_blocksize: get_hardblocksize(sb->s_dev); /* Block size must be an even multiple of 512 */ switch (blocksize) { case 512: sb->s_blocksize_bits = 9; break; case 1024: sb->s_blocksize_bits = 10; break; case 0: case 2048: sb->s_blocksize_bits = 11; break; case 4096: sb->s_blocksize_bits = 12; break; case 8192: sb->s_blocksize_bits = 13; break; default: printk(KERN_ERR "udf: bad block size (%d)\n", blocksize); return -1; } /* Set the block size */ set_blocksize(sb->s_dev, blocksize); sb->s_blocksize = blocksize; return 0; } /* * udf_vrs * * PURPOSE * Process a volume recognition sequence. * * PRE-CONDITIONS * sb Pointer to _locked_ superblock. * * POST-CONDITIONS * 0 Not NSR compliant. * 2 NSR edition 2 compliant. * 3 NSR edition 3 compliant. * * HISTORY * Oct 7, 1997 - Andrew E. Mileski * Written, tested, and released. */ static __inline__ int udf_vrs(struct super_block *sb) { struct E167VolStructDesc *vsd; struct buffer_head *bh; int block, block_inc, not_found; /* First block depends on block size */ block = 32768 >> sb->s_blocksize_bits; if (!block) block = 1; /* Next block depends on block size */ block_inc = 2048 >> sb->s_blocksize bits; if (!block_inc) block_inc = 1; /* Search for the "Beginning Extended Area" descriptor */ if (UDF_STRICT(sb)) { for (not_found = 1; not_found; block += block_inc) { bh = bread(sb->s_dev, block, sb->s_blocksize); if (!bh) return 0; vsd = (E167VolStructDesc *)bh->b_data; not_found = (strncmp(vsd->stdIdent, E167_STDID_BEA01, E167_STDID_LEN) || vsd->structType || vsd->structVersion != 1U); brelse(bh); } } /* Process the extended area */ for (not_found = 1; not_found; block += block_inc) { bh = bread(sb->s_dev, block, sb->s_blocksize); if (!bh) return 0; vsd = (struct E167VolStructDesc *)bh->b_data; if (!strncmp(vsd->stdIdent, E167_STDID_TEA01, E167_STDID_LEN) && (UDF_STRICT(sb) && vsd->structVersion == 1 else if (!strncmp(vsd->stdIdent, E167_STDID_TEA01, E167_STDID_LEN)) { } else { brelse(bh); } return not_found; } /* * udf_find_anchor * * PURPOSE * Find an anchor volume descriptor. * * PRE-CONDITIONS * sb Pointer to _locked_ superblock. * lastblock Last block on media. * * POST-CONDITIONS * Pointer to buffer or NULL. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ static __inline__ struct buffer_head * udf_find_anchor(struct super_block *sb, long lastblock) { struct buffer_head *bh; /* Search for an anchor volume descriptor pointer */ bh = udf_read_tagged(sb, 256); if (!bh || ((tag *)bh->b_data)->tagIdent != ANCHOR_VOL_DESC_PTR) { brelse(bh); bh = udf_read_tagged(sb, 512); } if (!bh || ((tag *)bh->b_data)->tagIdent != ANCHOR_VOL_DESC_PTR) { brelse(bh); bh = udf_read_tagged(sb, lastblock - 256); } if (!bh || ((tag *)bh->b_data)->tagIdent != ANCHOR_VOL_DESC_PTR) { brelse(bh); bh = udf_read_tagged(sb, lastblock); } if (!bh || ((tag *)bh->b_data)->tagIdent != ANCHOR_VOL_DESC_PTR) { brelse(bh); printk(KERN_ERR "udf: couldn't find an anchor\n"); return NULL; } return bh; } /* * udf_process_sequence * * PURPOSE * Process a main/reserve volume descriptor sequence. * * PRE-CONDITIONS * sb Pointer to _locked_ superblock. * block First block of first extent of the sequence. * lastblock Lastblock of first extent of the sequence. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ static __inline__ int udf_process_sequence(struct super_block *sb, long block, long lastblock) { struct buffer_head *bh; __u32 descIdent = UNUSED_DESC; /* Read the main descriptor sequence */ for (; descIdent != TERMINATING_DESC && block <= lastblock; block++) { bh = udf_read_tagged(sb, block); if (!bh) break; /* Process each descriptor (ISO 13346 3/8.3-8.4) */ descIdent = ((tag *)bh->b_data)->tagIdent; switch (descIdent) { case PRIMARY_VOL_DESC: /* ISO 13346 3/10.1 */ break; case VOL_DESC_PTR: /* ISO 13346 3/10.3 */ lastblock = block = le32_to_cpu( ((struct AnchorVolDescPtr *)bh->b_data) ->mainVolDescSeqExt.extLocation); lastblock += le32_to_cpu(((struct AnchorVolDescPtr *) bh->b_data)->mainVolDescSeqExt.extLength) >> sb->s_blocksize_bits; break; case IMP_USE_VOL_DESC: /* ISO 13346 3/10.4 */ break; case PARTITION_DESC: /* ISO 13346 3/10.5 */ break; case LOGICAL_VOL_DESC: /* ISO 13346 3/10.6 */ break; case UNALLOC_SPACE_DESC: /* ISO 13346 3/10.8 */ break; case TERMINATING_DESC: /* ISO 13346 3/10.9 */ break; default: descIdent = TERMINATING_DESC; } brelse(bh); } return 0; } /* * udf_read_super * * PURPOSE * Complete the specified super block. * * PRE-CONDITIONS * sb Pointer to superblock to complete - never NULL. * sb->s_dev Device to read suberblock from. * options Pointer to mount options. * silent Silent flag. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ static struct super_block * udf_read_super(struct super_block *sb, void *options, int silent) { struct inode *inode; long block, lastblock; long main_s, main_e, reserve_s, reserve_e; struct buffer_head *bh; /* Lock the module in memory (if applicable) */ MOD_INC_USE_COUNT; lock_super(sb); /* Parse any mount options */ if (udf_parse_options(sb, (char *)options)) goto error_out; /* Set the block size for all transfers */ if (udf_set_blocksize(sb)) goto error_out; /* Check that it is NSR02 compliant */ if (!udf_vrs(sb)) goto error_out; /* Get the last block of media */ lastblock = 257; if (lastblock < 257) { printk(KERN_ERR "udf: media is too small\n"); goto error_out; } /* Find an anchor volume descriptor pointer */ bh = udf_find_anchor(sb, lastblock); if (!bh) goto error_out; /* Locate the main sequence */ main_s = le32_to_cpu(((struct AnchorVolDescPtr *) bh->b_data)->mainVolDescSeqExt.extLocation); main_e = le32_to_cpu(((struct AnchorVolDescPtr *)bh->b_data) ->mainVolDescSeqExt.extLength) >> sb->s_blocksize_bits; main_e += main_s; lastblock += block; /* Locate the reserve sequence */ reserve_s = le32_to_cpu(((struct AnchorVolDescPtr *) bh->b_data)->mainVolDescSeqExt.extLocation); reserve_e = le32_to_cpu(((struct AnchorVolDescPtr *)bh->b_data) ->mainVolDescSeqExt.extLength) >> sb->s_blocksize_bits; reserve_e += reserve_s; brelse(bh); /* Process the main sequence */ if (udf_process_sequence(sb, block, lastblock) && udf_process_sequence(sb, reserve_s, reserve_e)) goto error_out; /* Fill in the rest of the superblock */ sb->s_op = &udf_sb_ops; sb->s_time = jiffies; sb->dq_op = NULL; sb->s_dirt = 0; sb->s_magic = UDF_SUPER_MAGIC; /* Read the root inode */ /* inode = udf_namei(sb, & (const struct qstr) { "/", 0, 0 }); */ inode = null; if (!inode) goto error_out; /* Allocate a dentry for the root inode */ sb->s_root = d_alloc_root(inode, NULL); if (!sb->s_root) { printk(KERN_ERR "udf: couldn't allocate root dentry\n"); goto error_out; } unlock_super(sb); return sb; error_out: sb->s_dev = NODEV; unlock_super(sb); MOD_DEC_USE_COUNT; return NULL; } /* * udf_put_super * * PURPOSE * Prepare for destruction of the superblock. * * DESCRIPTION * Called before the filesystem is unmounted. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ static void udf_put_super(struct super_block *sb) { lock_super(sb); sb->s_dev = NODEV; unlock_super(sb); MOD_DEC_USE_COUNT; } /* * udf_stat_fs * * PURPOSE * Return info about the filesystem. * * DESCRIPTION * Called by sys_statfs() * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ static int udf_statfs(struct super_block *sb, struct statfs *buf, int bufsize) { int size; struct statfs tmp; size = (bufsize < sizeof(tmp)) ? bufsize: sizeof(tmp); memset(&tmp, 0, sizeof(tmp)); tmp.f_type = UDF_SUPER_MAGIC; tmp.f_bsize = sb->s_blocksize; tmp.f_blocks = 1L; tmp.f_bfree = 0L; tmp.f_bavail = 0L; tmp.f_files = 1L; tmp.f_ffree = 0L; /* __kernel_fsid_t f_fsid */ tmp.f_namelen = UDF_NAME_LEN; return copy_to_user(buf, &tmp, size) ? -EFAULT: 0; }