patch-2.2.5 linux/fs/adfs/super.c
Next file: linux/fs/buffer.c
Previous file: linux/fs/adfs/inode.c
Back to the patch index
Back to the overall index
- Lines: 381
- Date:
Fri Mar 26 13:57:41 1999
- Orig file:
v2.2.4/linux/fs/adfs/super.c
- Orig date:
Mon Apr 6 17:41:00 1998
diff -u --recursive --new-file v2.2.4/linux/fs/adfs/super.c linux/fs/adfs/super.c
@@ -21,25 +21,26 @@
#include <stdarg.h>
-static void adfs_put_super (struct super_block *sb);
-static int adfs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz);
-void adfs_read_inode (struct inode *inode);
+static void adfs_put_super(struct super_block *sb);
+static int adfs_remount(struct super_block *sb, int *flags, char *data);
+static int adfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+void adfs_read_inode(struct inode *inode);
-void adfs_error (struct super_block *sb, const char *function, const char *fmt, ...)
+void adfs_error(struct super_block *sb, const char *function, const char *fmt, ...)
{
char error_buf[128];
va_list args;
- va_start (args, fmt);
- vsprintf (error_buf, fmt, args);
- va_end (args);
+ va_start(args, fmt);
+ vsprintf(error_buf, fmt, args);
+ va_end(args);
- printk (KERN_CRIT "ADFS-fs error (device %s)%s%s: %s\n",
- kdevname (sb->s_dev), function ? ": " : "",
+ printk(KERN_CRIT "ADFS-fs error (device %s)%s%s: %s\n",
+ kdevname(sb->s_dev), function ? ": " : "",
function ? function : "", error_buf);
}
-unsigned char adfs_calccrosscheck (struct super_block *sb, char *map)
+static unsigned char adfs_calczonecheck(struct super_block *sb, char *map)
{
unsigned int v0, v1, v2, v3;
int i;
@@ -63,7 +64,7 @@
return v0 ^ v1 ^ v2 ^ v3;
}
-static int adfs_checkmap (struct super_block *sb)
+static int adfs_checkmap(struct super_block *sb)
{
unsigned char crosscheck = 0, zonecheck = 1;
int i;
@@ -72,14 +73,14 @@
char *map;
map = sb->u.adfs_sb.s_map[i]->b_data;
- if (adfs_calccrosscheck (sb, map) != map[0]) {
- adfs_error (sb, "adfs_checkmap", "zone %d fails zonecheck", i);
+ if (adfs_calczonecheck(sb, map) != map[0]) {
+ adfs_error(sb, "adfs_checkmap", "zone %d fails zonecheck", i);
zonecheck = 0;
}
crosscheck ^= map[3];
}
if (crosscheck != 0xff)
- adfs_error (sb, "adfs_checkmap", "crosscheck != 0xff");
+ adfs_error(sb, "adfs_checkmap", "crosscheck != 0xff");
return crosscheck == 0xff && zonecheck;
}
@@ -92,21 +93,73 @@
adfs_put_super,
NULL,
adfs_statfs,
- NULL
+ adfs_remount
};
-static void adfs_put_super (struct super_block *sb)
+static void adfs_put_super(struct super_block *sb)
{
int i;
for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
- brelse (sb->u.adfs_sb.s_map[i]);
- kfree (sb->u.adfs_sb.s_map);
- brelse (sb->u.adfs_sb.s_sbh);
+ brelse(sb->u.adfs_sb.s_map[i]);
+ kfree(sb->u.adfs_sb.s_map);
+ brelse(sb->u.adfs_sb.s_sbh);
MOD_DEC_USE_COUNT;
}
-struct super_block *adfs_read_super (struct super_block *sb, void *data, int silent)
+static int parse_options(struct super_block *sb, char *options)
+{
+ char *value, *opt;
+
+ if (!options)
+ return 0;
+
+ for (opt = strtok(options, ","); opt != NULL; opt = strtok(NULL, ",")) {
+ value = strchr(opt, '=');
+ if (value)
+ *value++ = '\0';
+
+ if (!strcmp(opt, "uid")) { /* owner of all files */
+ if (!value || !*value)
+ return -EINVAL;
+ sb->u.adfs_sb.s_uid = simple_strtoul(value, &value, 0);
+ if (*value)
+ return -EINVAL;
+ } else
+ if (!strcmp(opt, "gid")) { /* group owner of all files */
+ if (!value || !*value)
+ return -EINVAL;
+ sb->u.adfs_sb.s_gid = simple_strtoul(value, &value, 0);
+ if (*value)
+ return -EINVAL;
+ } else
+ if (!strcmp(opt, "ownmask")) { /* owner permission mask */
+ if (!value || !*value)
+ return -EINVAL;
+ sb->u.adfs_sb.s_owner_mask = simple_strtoul(value, &value, 8);
+ if (*value)
+ return -EINVAL;
+ } else
+ if (!strcmp(opt, "othmask")) { /* others permission mask */
+ if (!value || !*value)
+ return -EINVAL;
+ sb->u.adfs_sb.s_other_mask = simple_strtoul(value, &value, 8);
+ if (*value)
+ return -EINVAL;
+ } else { /* eh? say again. */
+ printk("ADFS-fs: unrecognised mount option %s\n", opt);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int adfs_remount(struct super_block *sb, int *flags, char *data)
+{
+ return parse_options(sb, data);
+}
+
+struct super_block *adfs_read_super(struct super_block *sb, void *data, int silent)
{
struct adfs_discrecord *dr;
struct buffer_head *bh;
@@ -114,28 +167,30 @@
kdev_t dev = sb->s_dev;
int i, j;
+ /* set default options */
+ sb->u.adfs_sb.s_uid = 0;
+ sb->u.adfs_sb.s_gid = 0;
+ sb->u.adfs_sb.s_owner_mask = S_IRWXU;
+ sb->u.adfs_sb.s_other_mask = S_IRWXG | S_IRWXO;
+
+ if (parse_options(sb, data))
+ goto error;
+
MOD_INC_USE_COUNT;
- lock_super (sb);
- set_blocksize (dev, BLOCK_SIZE);
- if (!(bh = bread (dev, ADFS_DISCRECORD / BLOCK_SIZE, BLOCK_SIZE))) {
- unlock_super (sb);
- adfs_error (sb, NULL, "unable to read superblock");
- MOD_DEC_USE_COUNT;
- return NULL;
+ lock_super(sb);
+ set_blocksize(dev, BLOCK_SIZE);
+ if (!(bh = bread(dev, ADFS_DISCRECORD / BLOCK_SIZE, BLOCK_SIZE))) {
+ adfs_error(sb, NULL, "unable to read superblock");
+ goto error_unlock;
}
b_data = bh->b_data + (ADFS_DISCRECORD % BLOCK_SIZE);
- if (adfs_checkbblk (b_data)) {
+ if (adfs_checkbblk(b_data)) {
if (!silent)
- printk ("VFS: Can't find an adfs filesystem on dev "
+ printk("VFS: Can't find an adfs filesystem on dev "
"%s.\n", kdevname(dev));
-failed_mount:
- unlock_super (sb);
- if (bh)
- brelse (bh);
- MOD_DEC_USE_COUNT;
- return NULL;
+ goto error_free_bh;
}
dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
@@ -145,26 +200,26 @@
(sb->s_blocksize == 512 || sb->s_blocksize == 1024 ||
sb->s_blocksize == 2048 || sb->s_blocksize == 4096)) {
- brelse (bh);
- set_blocksize (dev, sb->s_blocksize);
- bh = bread (dev, ADFS_DISCRECORD / sb->s_blocksize, sb->s_blocksize);
+ brelse(bh);
+ set_blocksize(dev, sb->s_blocksize);
+ bh = bread(dev, ADFS_DISCRECORD / sb->s_blocksize, sb->s_blocksize);
if (!bh) {
- adfs_error (sb, NULL, "couldn't read superblock on "
+ adfs_error(sb, NULL, "couldn't read superblock on "
"2nd try.");
- goto failed_mount;
+ goto error_unlock;
}
b_data = bh->b_data + (ADFS_DISCRECORD % sb->s_blocksize);
- if (adfs_checkbblk (b_data)) {
- adfs_error (sb, NULL, "disc record mismatch, very weird!");
- goto failed_mount;
+ if (adfs_checkbblk(b_data)) {
+ adfs_error(sb, NULL, "disc record mismatch, very weird!");
+ goto error_free_bh;
}
dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
}
if (sb->s_blocksize != bh->b_size) {
if (!silent)
- printk (KERN_ERR "VFS: Unsupported blocksize on dev "
- "%s.\n", kdevname (dev));
- goto failed_mount;
+ printk(KERN_ERR "VFS: Unsupported blocksize on dev "
+ "%s.\n", kdevname(dev));
+ goto error_free_bh;
}
/* blocksize on this device should now be set to the adfs log2secsize */
@@ -202,71 +257,81 @@
else
sb->u.adfs_sb.s_map_block >>= -sb->u.adfs_sb.s_map2blk;
- printk (KERN_DEBUG "ADFS: zone size %d, IDs per zone %d, map address %X size %d sectors\n",
+ printk(KERN_DEBUG "ADFS: zone size %d, IDs per zone %d, map address %X size %d sectors\n",
sb->u.adfs_sb.s_zone_size, sb->u.adfs_sb.s_ids_per_zone,
sb->u.adfs_sb.s_map_block, sb->u.adfs_sb.s_map_size);
- printk (KERN_DEBUG "ADFS: sector size %d, map bit size %d\n",
- 1 << dr->log2secsize, 1 << dr->log2bpmb);
+ printk(KERN_DEBUG "ADFS: sector size %d, map bit size %d, share size %d\n",
+ 1 << dr->log2secsize, 1 << dr->log2bpmb,
+ 1 << (dr->log2secsize + dr->log2sharesize));
sb->s_magic = ADFS_SUPER_MAGIC;
- sb->s_flags |= MS_RDONLY; /* we don't support writing yet */
- sb->u.adfs_sb.s_map = kmalloc (sb->u.adfs_sb.s_map_size *
- sizeof (struct buffer_head *), GFP_KERNEL);
+ sb->u.adfs_sb.s_map = kmalloc(sb->u.adfs_sb.s_map_size *
+ sizeof(struct buffer_head *), GFP_KERNEL);
if (sb->u.adfs_sb.s_map == NULL) {
- adfs_error (sb, NULL, "not enough memory");
- goto failed_mount;
+ adfs_error(sb, NULL, "not enough memory");
+ goto error_free_bh;
}
for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) {
- sb->u.adfs_sb.s_map[i] = bread (dev,
+ sb->u.adfs_sb.s_map[i] = bread(dev,
sb->u.adfs_sb.s_map_block + i,
sb->s_blocksize);
if (!sb->u.adfs_sb.s_map[i]) {
for (j = 0; j < i; j++)
- brelse (sb->u.adfs_sb.s_map[j]);
- kfree (sb->u.adfs_sb.s_map);
- adfs_error (sb, NULL, "unable to read map");
- goto failed_mount;
+ brelse(sb->u.adfs_sb.s_map[j]);
+ kfree(sb->u.adfs_sb.s_map);
+ adfs_error(sb, NULL, "unable to read map");
+ goto error_free_bh;
}
}
- if (!adfs_checkmap (sb)) {
+ if (!adfs_checkmap(sb)) {
for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
- brelse (sb->u.adfs_sb.s_map[i]);
- adfs_error (sb, NULL, "map corrupted");
- goto failed_mount;
+ brelse(sb->u.adfs_sb.s_map[i]);
+ adfs_error(sb, NULL, "map corrupted");
+ goto error_free_bh;
}
dr = (struct adfs_discrecord *)(sb->u.adfs_sb.s_map[0]->b_data + 4);
- unlock_super (sb);
+ unlock_super(sb);
/*
* set up enough so that it can read an inode
*/
sb->s_op = &adfs_sops;
- sb->u.adfs_sb.s_root = adfs_inode_generate (dr->root, 0);
+ sb->u.adfs_sb.s_root = adfs_inode_generate(dr->root, 0);
sb->s_root = d_alloc_root(iget(sb, sb->u.adfs_sb.s_root), NULL);
if (!sb->s_root) {
- sb->s_dev = 0;
for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
- brelse (sb->u.adfs_sb.s_map[i]);
- brelse (bh);
- adfs_error (sb, NULL, "get root inode failed\n");
- MOD_DEC_USE_COUNT;
- return NULL;
+ brelse(sb->u.adfs_sb.s_map[i]);
+ brelse(bh);
+ adfs_error(sb, NULL, "get root inode failed\n");
+ goto error_dec_use;
}
return sb;
+
+error_free_bh:
+ if (bh)
+ brelse(bh);
+error_unlock:
+ unlock_super(sb);
+error_dec_use:
+ MOD_DEC_USE_COUNT;
+error:
+ sb->s_dev = 0;
+ return NULL;
}
-static int adfs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
+static int adfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
struct statfs tmp;
const unsigned int nidlen = sb->u.adfs_sb.s_idlen + 1;
tmp.f_type = ADFS_SUPER_MAGIC;
tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = (sb->u.adfs_sb.s_dr->disc_size) >> (sb->s_blocksize_bits);
+ tmp.f_blocks = sb->u.adfs_sb.s_dr->disc_size_high << (32 - sb->s_blocksize_bits) |
+ sb->u.adfs_sb.s_dr->disc_size >> sb->s_blocksize_bits;
tmp.f_files = tmp.f_blocks >> nidlen;
{
unsigned int i, j = 0;
@@ -305,35 +370,35 @@
if (freelink <= nidlen) break;
} while (mapindex < 8 * sb->s_blocksize);
if (mapindex > 8 * sb->s_blocksize)
- adfs_error (sb, NULL, "oversized free fragment\n");
+ adfs_error(sb, NULL, "oversized free fragment\n");
else if (freelink)
- adfs_error (sb, NULL, "undersized free fragment\n");
+ adfs_error(sb, NULL, "undersized free fragment\n");
}
tmp.f_bfree = tmp.f_bavail = j <<
(sb->u.adfs_sb.s_dr->log2bpmb - sb->s_blocksize_bits);
}
tmp.f_ffree = tmp.f_bfree >> nidlen;
tmp.f_namelen = ADFS_NAME_LEN;
- return copy_to_user (buf, &tmp, bufsiz) ? -EFAULT : 0;
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
static struct file_system_type adfs_fs_type = {
"adfs", FS_REQUIRES_DEV, adfs_read_super, NULL
};
-__initfunc(int init_adfs_fs (void))
+__initfunc(int init_adfs_fs(void))
{
- return register_filesystem (&adfs_fs_type);
+ return register_filesystem(&adfs_fs_type);
}
#ifdef MODULE
-int init_module (void)
+int init_module(void)
{
return init_adfs_fs();
}
-void cleanup_module (void)
+void cleanup_module(void)
{
- unregister_filesystem (&adfs_fs_type);
+ unregister_filesystem(&adfs_fs_type);
}
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)