1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/fs/adfs/super.c
5 * Copyright (C) 1997-1999 Russell King
7 #include <linux/module.h>
8 #include <linux/init.h>
9 #include <linux/parser.h>
10 #include <linux/mount.h>
11 #include <linux/seq_file.h>
12 #include <linux/slab.h>
13 #include <linux/statfs.h>
14 #include <linux/user_namespace.h>
17 #include "dir_fplus.h"
19 #define ADFS_SB_FLAGS SB_NOATIME
21 #define ADFS_DEFAULT_OWNER_MASK S_IRWXU
22 #define ADFS_DEFAULT_OTHER_MASK (S_IRWXG | S_IRWXO)
24 void __adfs_error(struct super_block
*sb
, const char *function
, const char *fmt
, ...)
33 printk(KERN_CRIT
"ADFS-fs error (device %s)%s%s: %pV\n",
34 sb
->s_id
, function
? ": " : "",
35 function
? function
: "", &vaf
);
40 void adfs_msg(struct super_block
*sb
, const char *pfx
, const char *fmt
, ...)
48 printk("%sADFS-fs (%s): %pV\n", pfx
, sb
->s_id
, &vaf
);
52 static int adfs_checkdiscrecord(struct adfs_discrecord
*dr
)
54 unsigned int max_idlen
;
57 /* sector size must be 256, 512 or 1024 bytes */
58 if (dr
->log2secsize
!= 8 &&
59 dr
->log2secsize
!= 9 &&
60 dr
->log2secsize
!= 10)
63 /* idlen must be at least log2secsize + 3 */
64 if (dr
->idlen
< dr
->log2secsize
+ 3)
67 /* we cannot have such a large disc that we
68 * are unable to represent sector offsets in
69 * 32 bits. This works out at 2.0 TB.
71 if (le32_to_cpu(dr
->disc_size_high
) >> dr
->log2secsize
)
75 * Maximum idlen is limited to 16 bits for new directories by
76 * the three-byte storage of an indirect disc address. For
77 * big directories, idlen must be no greater than 19 v2 [1.0]
79 max_idlen
= dr
->format_version
? 19 : 16;
80 if (dr
->idlen
> max_idlen
)
83 /* reserved bytes should be zero */
84 for (i
= 0; i
< sizeof(dr
->unused52
); i
++)
85 if (dr
->unused52
[i
] != 0)
91 static void adfs_put_super(struct super_block
*sb
)
93 struct adfs_sb_info
*asb
= ADFS_SB(sb
);
99 static int adfs_show_options(struct seq_file
*seq
, struct dentry
*root
)
101 struct adfs_sb_info
*asb
= ADFS_SB(root
->d_sb
);
103 if (!uid_eq(asb
->s_uid
, GLOBAL_ROOT_UID
))
104 seq_printf(seq
, ",uid=%u", from_kuid_munged(&init_user_ns
, asb
->s_uid
));
105 if (!gid_eq(asb
->s_gid
, GLOBAL_ROOT_GID
))
106 seq_printf(seq
, ",gid=%u", from_kgid_munged(&init_user_ns
, asb
->s_gid
));
107 if (asb
->s_owner_mask
!= ADFS_DEFAULT_OWNER_MASK
)
108 seq_printf(seq
, ",ownmask=%o", asb
->s_owner_mask
);
109 if (asb
->s_other_mask
!= ADFS_DEFAULT_OTHER_MASK
)
110 seq_printf(seq
, ",othmask=%o", asb
->s_other_mask
);
111 if (asb
->s_ftsuffix
!= 0)
112 seq_printf(seq
, ",ftsuffix=%u", asb
->s_ftsuffix
);
117 enum {Opt_uid
, Opt_gid
, Opt_ownmask
, Opt_othmask
, Opt_ftsuffix
, Opt_err
};
119 static const match_table_t tokens
= {
122 {Opt_ownmask
, "ownmask=%o"},
123 {Opt_othmask
, "othmask=%o"},
124 {Opt_ftsuffix
, "ftsuffix=%u"},
128 static int parse_options(struct super_block
*sb
, struct adfs_sb_info
*asb
,
137 while ((p
= strsep(&options
, ",")) != NULL
) {
138 substring_t args
[MAX_OPT_ARGS
];
143 token
= match_token(p
, tokens
, args
);
146 if (match_int(args
, &option
))
148 asb
->s_uid
= make_kuid(current_user_ns(), option
);
149 if (!uid_valid(asb
->s_uid
))
153 if (match_int(args
, &option
))
155 asb
->s_gid
= make_kgid(current_user_ns(), option
);
156 if (!gid_valid(asb
->s_gid
))
160 if (match_octal(args
, &option
))
162 asb
->s_owner_mask
= option
;
165 if (match_octal(args
, &option
))
167 asb
->s_other_mask
= option
;
170 if (match_int(args
, &option
))
172 asb
->s_ftsuffix
= option
;
175 adfs_msg(sb
, KERN_ERR
,
176 "unrecognised mount option \"%s\" or missing value",
184 static int adfs_remount(struct super_block
*sb
, int *flags
, char *data
)
186 struct adfs_sb_info temp_asb
;
190 *flags
|= ADFS_SB_FLAGS
;
192 temp_asb
= *ADFS_SB(sb
);
193 ret
= parse_options(sb
, &temp_asb
, data
);
195 *ADFS_SB(sb
) = temp_asb
;
200 static int adfs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
202 struct super_block
*sb
= dentry
->d_sb
;
203 struct adfs_sb_info
*sbi
= ADFS_SB(sb
);
204 u64 id
= huge_encode_dev(sb
->s_bdev
->bd_dev
);
206 adfs_map_statfs(sb
, buf
);
208 buf
->f_type
= ADFS_SUPER_MAGIC
;
209 buf
->f_namelen
= sbi
->s_namelen
;
210 buf
->f_bsize
= sb
->s_blocksize
;
211 buf
->f_ffree
= (long)(buf
->f_bfree
* buf
->f_files
) / (long)buf
->f_blocks
;
212 buf
->f_fsid
.val
[0] = (u32
)id
;
213 buf
->f_fsid
.val
[1] = (u32
)(id
>> 32);
218 static struct kmem_cache
*adfs_inode_cachep
;
220 static struct inode
*adfs_alloc_inode(struct super_block
*sb
)
222 struct adfs_inode_info
*ei
;
223 ei
= kmem_cache_alloc(adfs_inode_cachep
, GFP_KERNEL
);
226 return &ei
->vfs_inode
;
229 static void adfs_free_inode(struct inode
*inode
)
231 kmem_cache_free(adfs_inode_cachep
, ADFS_I(inode
));
234 static int adfs_drop_inode(struct inode
*inode
)
236 /* always drop inodes if we are read-only */
237 return !IS_ENABLED(CONFIG_ADFS_FS_RW
) || IS_RDONLY(inode
);
240 static void init_once(void *foo
)
242 struct adfs_inode_info
*ei
= (struct adfs_inode_info
*) foo
;
244 inode_init_once(&ei
->vfs_inode
);
247 static int __init
init_inodecache(void)
249 adfs_inode_cachep
= kmem_cache_create("adfs_inode_cache",
250 sizeof(struct adfs_inode_info
),
251 0, (SLAB_RECLAIM_ACCOUNT
|
252 SLAB_MEM_SPREAD
|SLAB_ACCOUNT
),
254 if (adfs_inode_cachep
== NULL
)
259 static void destroy_inodecache(void)
262 * Make sure all delayed rcu free inodes are flushed before we
266 kmem_cache_destroy(adfs_inode_cachep
);
269 static const struct super_operations adfs_sops
= {
270 .alloc_inode
= adfs_alloc_inode
,
271 .free_inode
= adfs_free_inode
,
272 .drop_inode
= adfs_drop_inode
,
273 .write_inode
= adfs_write_inode
,
274 .put_super
= adfs_put_super
,
275 .statfs
= adfs_statfs
,
276 .remount_fs
= adfs_remount
,
277 .show_options
= adfs_show_options
,
280 static int adfs_probe(struct super_block
*sb
, unsigned int offset
, int silent
,
281 int (*validate
)(struct super_block
*sb
,
282 struct buffer_head
*bh
,
283 struct adfs_discrecord
**bhp
))
285 struct adfs_sb_info
*asb
= ADFS_SB(sb
);
286 struct adfs_discrecord
*dr
;
287 struct buffer_head
*bh
;
288 unsigned int blocksize
= BLOCK_SIZE
;
291 for (try = 0; try < 2; try++) {
292 /* try to set the requested block size */
293 if (sb
->s_blocksize
!= blocksize
&&
294 !sb_set_blocksize(sb
, blocksize
)) {
296 adfs_msg(sb
, KERN_ERR
,
297 "error: unsupported blocksize");
301 /* read the buffer */
302 bh
= sb_bread(sb
, offset
>> sb
->s_blocksize_bits
);
304 adfs_msg(sb
, KERN_ERR
,
305 "error: unable to read block %u, try %d",
306 offset
>> sb
->s_blocksize_bits
, try);
311 ret
= validate(sb
, bh
, &dr
);
317 /* does the block size match the filesystem block size? */
318 blocksize
= 1 << dr
->log2secsize
;
319 if (sb
->s_blocksize
== blocksize
) {
320 asb
->s_map
= adfs_read_map(sb
, dr
);
322 return PTR_ERR_OR_ZERO(asb
->s_map
);
331 static int adfs_validate_bblk(struct super_block
*sb
, struct buffer_head
*bh
,
332 struct adfs_discrecord
**drp
)
334 struct adfs_discrecord
*dr
;
335 unsigned char *b_data
;
337 b_data
= bh
->b_data
+ (ADFS_DISCRECORD
% sb
->s_blocksize
);
338 if (adfs_checkbblk(b_data
))
341 /* Do some sanity checks on the ADFS disc record */
342 dr
= (struct adfs_discrecord
*)(b_data
+ ADFS_DR_OFFSET
);
343 if (adfs_checkdiscrecord(dr
))
350 static int adfs_validate_dr0(struct super_block
*sb
, struct buffer_head
*bh
,
351 struct adfs_discrecord
**drp
)
353 struct adfs_discrecord
*dr
;
355 /* Do some sanity checks on the ADFS disc record */
356 dr
= (struct adfs_discrecord
*)(bh
->b_data
+ 4);
357 if (adfs_checkdiscrecord(dr
) || dr
->nzones_high
|| dr
->nzones
!= 1)
364 static int adfs_fill_super(struct super_block
*sb
, void *data
, int silent
)
366 struct adfs_discrecord
*dr
;
367 struct object_info root_obj
;
368 struct adfs_sb_info
*asb
;
372 sb
->s_flags
|= ADFS_SB_FLAGS
;
374 asb
= kzalloc(sizeof(*asb
), GFP_KERNEL
);
379 sb
->s_magic
= ADFS_SUPER_MAGIC
;
380 sb
->s_time_gran
= 10000000;
382 /* set default options */
383 asb
->s_uid
= GLOBAL_ROOT_UID
;
384 asb
->s_gid
= GLOBAL_ROOT_GID
;
385 asb
->s_owner_mask
= ADFS_DEFAULT_OWNER_MASK
;
386 asb
->s_other_mask
= ADFS_DEFAULT_OTHER_MASK
;
389 if (parse_options(sb
, asb
, data
))
392 /* Try to probe the filesystem boot block */
393 ret
= adfs_probe(sb
, ADFS_DISCRECORD
, 1, adfs_validate_bblk
);
395 ret
= adfs_probe(sb
, 0, silent
, adfs_validate_dr0
);
396 if (ret
== -EILSEQ
) {
398 adfs_msg(sb
, KERN_ERR
,
399 "error: can't find an ADFS filesystem on dev %s.",
406 /* set up enough so that we can read an inode */
407 sb
->s_op
= &adfs_sops
;
409 dr
= adfs_map_discrecord(asb
->s_map
);
411 root_obj
.parent_id
= root_obj
.indaddr
= le32_to_cpu(dr
->root
);
412 root_obj
.name_len
= 0;
413 /* Set root object date as 01 Jan 1987 00:00:00 */
414 root_obj
.loadaddr
= 0xfff0003f;
415 root_obj
.execaddr
= 0xec22c000;
416 root_obj
.size
= ADFS_NEWDIR_SIZE
;
417 root_obj
.attr
= ADFS_NDA_DIRECTORY
| ADFS_NDA_OWNER_READ
|
418 ADFS_NDA_OWNER_WRITE
| ADFS_NDA_PUBLIC_READ
;
421 * If this is a F+ disk with variable length directories,
422 * get the root_size from the disc record.
424 if (dr
->format_version
) {
425 root_obj
.size
= le32_to_cpu(dr
->root_size
);
426 asb
->s_dir
= &adfs_fplus_dir_ops
;
427 asb
->s_namelen
= ADFS_FPLUS_NAME_LEN
;
429 asb
->s_dir
= &adfs_f_dir_ops
;
430 asb
->s_namelen
= ADFS_F_NAME_LEN
;
433 * ,xyz hex filetype suffix may be added by driver
434 * to files that have valid RISC OS filetype
439 sb
->s_d_op
= &adfs_dentry_operations
;
440 root
= adfs_iget(sb
, &root_obj
);
441 sb
->s_root
= d_make_root(root
);
444 adfs_error(sb
, "get root inode failed\n");
451 sb
->s_fs_info
= NULL
;
456 static struct dentry
*adfs_mount(struct file_system_type
*fs_type
,
457 int flags
, const char *dev_name
, void *data
)
459 return mount_bdev(fs_type
, flags
, dev_name
, data
, adfs_fill_super
);
462 static struct file_system_type adfs_fs_type
= {
463 .owner
= THIS_MODULE
,
466 .kill_sb
= kill_block_super
,
467 .fs_flags
= FS_REQUIRES_DEV
,
469 MODULE_ALIAS_FS("adfs");
471 static int __init
init_adfs_fs(void)
473 int err
= init_inodecache();
476 err
= register_filesystem(&adfs_fs_type
);
481 destroy_inodecache();
486 static void __exit
exit_adfs_fs(void)
488 unregister_filesystem(&adfs_fs_type
);
489 destroy_inodecache();
492 module_init(init_adfs_fs
)
493 module_exit(exit_adfs_fs
)
494 MODULE_LICENSE("GPL");