aboutsummaryrefslogtreecommitdiffstats
path: root/fs/adfs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/adfs/super.c')
-rw-r--r--fs/adfs/super.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 4a3af7075c1d..c8bf36a1996a 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -14,7 +14,6 @@
14#include <linux/mount.h> 14#include <linux/mount.h>
15#include <linux/seq_file.h> 15#include <linux/seq_file.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/smp_lock.h>
18#include <linux/statfs.h> 17#include <linux/statfs.h>
19#include "adfs.h" 18#include "adfs.h"
20#include "dir_f.h" 19#include "dir_f.h"
@@ -120,15 +119,11 @@ static void adfs_put_super(struct super_block *sb)
120 int i; 119 int i;
121 struct adfs_sb_info *asb = ADFS_SB(sb); 120 struct adfs_sb_info *asb = ADFS_SB(sb);
122 121
123 lock_kernel();
124
125 for (i = 0; i < asb->s_map_size; i++) 122 for (i = 0; i < asb->s_map_size; i++)
126 brelse(asb->s_map[i].dm_bh); 123 brelse(asb->s_map[i].dm_bh);
127 kfree(asb->s_map); 124 kfree(asb->s_map);
128 kfree(asb); 125 kfree(asb);
129 sb->s_fs_info = NULL; 126 sb->s_fs_info = NULL;
130
131 unlock_kernel();
132} 127}
133 128
134static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt) 129static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
@@ -143,17 +138,20 @@ static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
143 seq_printf(seq, ",ownmask=%o", asb->s_owner_mask); 138 seq_printf(seq, ",ownmask=%o", asb->s_owner_mask);
144 if (asb->s_other_mask != ADFS_DEFAULT_OTHER_MASK) 139 if (asb->s_other_mask != ADFS_DEFAULT_OTHER_MASK)
145 seq_printf(seq, ",othmask=%o", asb->s_other_mask); 140 seq_printf(seq, ",othmask=%o", asb->s_other_mask);
141 if (asb->s_ftsuffix != 0)
142 seq_printf(seq, ",ftsuffix=%u", asb->s_ftsuffix);
146 143
147 return 0; 144 return 0;
148} 145}
149 146
150enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_err}; 147enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_ftsuffix, Opt_err};
151 148
152static const match_table_t tokens = { 149static const match_table_t tokens = {
153 {Opt_uid, "uid=%u"}, 150 {Opt_uid, "uid=%u"},
154 {Opt_gid, "gid=%u"}, 151 {Opt_gid, "gid=%u"},
155 {Opt_ownmask, "ownmask=%o"}, 152 {Opt_ownmask, "ownmask=%o"},
156 {Opt_othmask, "othmask=%o"}, 153 {Opt_othmask, "othmask=%o"},
154 {Opt_ftsuffix, "ftsuffix=%u"},
157 {Opt_err, NULL} 155 {Opt_err, NULL}
158}; 156};
159 157
@@ -194,6 +192,11 @@ static int parse_options(struct super_block *sb, char *options)
194 return -EINVAL; 192 return -EINVAL;
195 asb->s_other_mask = option; 193 asb->s_other_mask = option;
196 break; 194 break;
195 case Opt_ftsuffix:
196 if (match_int(args, &option))
197 return -EINVAL;
198 asb->s_ftsuffix = option;
199 break;
197 default: 200 default:
198 printk("ADFS-fs: unrecognised mount option \"%s\" " 201 printk("ADFS-fs: unrecognised mount option \"%s\" "
199 "or missing value\n", p); 202 "or missing value\n", p);
@@ -240,11 +243,18 @@ static struct inode *adfs_alloc_inode(struct super_block *sb)
240 return &ei->vfs_inode; 243 return &ei->vfs_inode;
241} 244}
242 245
243static void adfs_destroy_inode(struct inode *inode) 246static void adfs_i_callback(struct rcu_head *head)
244{ 247{
248 struct inode *inode = container_of(head, struct inode, i_rcu);
249 INIT_LIST_HEAD(&inode->i_dentry);
245 kmem_cache_free(adfs_inode_cachep, ADFS_I(inode)); 250 kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
246} 251}
247 252
253static void adfs_destroy_inode(struct inode *inode)
254{
255 call_rcu(&inode->i_rcu, adfs_i_callback);
256}
257
248static void init_once(void *foo) 258static void init_once(void *foo)
249{ 259{
250 struct adfs_inode_info *ei = (struct adfs_inode_info *) foo; 260 struct adfs_inode_info *ei = (struct adfs_inode_info *) foo;
@@ -364,6 +374,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
364 asb->s_gid = 0; 374 asb->s_gid = 0;
365 asb->s_owner_mask = ADFS_DEFAULT_OWNER_MASK; 375 asb->s_owner_mask = ADFS_DEFAULT_OWNER_MASK;
366 asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK; 376 asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK;
377 asb->s_ftsuffix = 0;
367 378
368 if (parse_options(sb, data)) 379 if (parse_options(sb, data))
369 goto error; 380 goto error;
@@ -443,11 +454,13 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
443 454
444 root_obj.parent_id = root_obj.file_id = le32_to_cpu(dr->root); 455 root_obj.parent_id = root_obj.file_id = le32_to_cpu(dr->root);
445 root_obj.name_len = 0; 456 root_obj.name_len = 0;
446 root_obj.loadaddr = 0; 457 /* Set root object date as 01 Jan 1987 00:00:00 */
447 root_obj.execaddr = 0; 458 root_obj.loadaddr = 0xfff0003f;
459 root_obj.execaddr = 0xec22c000;
448 root_obj.size = ADFS_NEWDIR_SIZE; 460 root_obj.size = ADFS_NEWDIR_SIZE;
449 root_obj.attr = ADFS_NDA_DIRECTORY | ADFS_NDA_OWNER_READ | 461 root_obj.attr = ADFS_NDA_DIRECTORY | ADFS_NDA_OWNER_READ |
450 ADFS_NDA_OWNER_WRITE | ADFS_NDA_PUBLIC_READ; 462 ADFS_NDA_OWNER_WRITE | ADFS_NDA_PUBLIC_READ;
463 root_obj.filetype = -1;
451 464
452 /* 465 /*
453 * If this is a F+ disk with variable length directories, 466 * If this is a F+ disk with variable length directories,
@@ -461,7 +474,14 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
461 asb->s_dir = &adfs_f_dir_ops; 474 asb->s_dir = &adfs_f_dir_ops;
462 asb->s_namelen = ADFS_F_NAME_LEN; 475 asb->s_namelen = ADFS_F_NAME_LEN;
463 } 476 }
477 /*
478 * ,xyz hex filetype suffix may be added by driver
479 * to files that have valid RISC OS filetype
480 */
481 if (asb->s_ftsuffix)
482 asb->s_namelen += 4;
464 483
484 sb->s_d_op = &adfs_dentry_operations;
465 root = adfs_iget(sb, &root_obj); 485 root = adfs_iget(sb, &root_obj);
466 sb->s_root = d_alloc_root(root); 486 sb->s_root = d_alloc_root(root);
467 if (!sb->s_root) { 487 if (!sb->s_root) {
@@ -472,8 +492,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
472 kfree(asb->s_map); 492 kfree(asb->s_map);
473 adfs_error(sb, "get root inode failed\n"); 493 adfs_error(sb, "get root inode failed\n");
474 goto error; 494 goto error;
475 } else 495 }
476 sb->s_root->d_op = &adfs_dentry_operations;
477 return 0; 496 return 0;
478 497
479error_free_bh: 498error_free_bh:
@@ -484,17 +503,16 @@ error:
484 return -EINVAL; 503 return -EINVAL;
485} 504}
486 505
487static int adfs_get_sb(struct file_system_type *fs_type, 506static struct dentry *adfs_mount(struct file_system_type *fs_type,
488 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 507 int flags, const char *dev_name, void *data)
489{ 508{
490 return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super, 509 return mount_bdev(fs_type, flags, dev_name, data, adfs_fill_super);
491 mnt);
492} 510}
493 511
494static struct file_system_type adfs_fs_type = { 512static struct file_system_type adfs_fs_type = {
495 .owner = THIS_MODULE, 513 .owner = THIS_MODULE,
496 .name = "adfs", 514 .name = "adfs",
497 .get_sb = adfs_get_sb, 515 .mount = adfs_mount,
498 .kill_sb = kill_block_super, 516 .kill_sb = kill_block_super,
499 .fs_flags = FS_REQUIRES_DEV, 517 .fs_flags = FS_REQUIRES_DEV,
500}; 518};