hc
2024-05-10 748e4f3d702def1a4bff191e0cf93b6a05340f01
kernel/fs/adfs/super.c
....@@ -1,44 +1,58 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * linux/fs/adfs/super.c
34 *
45 * Copyright (C) 1997-1999 Russell King
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 */
107 #include <linux/module.h>
118 #include <linux/init.h>
12
-#include <linux/buffer_head.h>
139 #include <linux/parser.h>
1410 #include <linux/mount.h>
1511 #include <linux/seq_file.h>
1612 #include <linux/slab.h>
1713 #include <linux/statfs.h>
1814 #include <linux/user_namespace.h>
15
+#include <linux/blkdev.h>
1916 #include "adfs.h"
2017 #include "dir_f.h"
2118 #include "dir_fplus.h"
19
+
20
+#define ADFS_SB_FLAGS SB_NOATIME
2221
2322 #define ADFS_DEFAULT_OWNER_MASK S_IRWXU
2423 #define ADFS_DEFAULT_OTHER_MASK (S_IRWXG | S_IRWXO)
2524
2625 void __adfs_error(struct super_block *sb, const char *function, const char *fmt, ...)
2726 {
28
- char error_buf[128];
27
+ struct va_format vaf;
2928 va_list args;
3029
3130 va_start(args, fmt);
32
- vsnprintf(error_buf, sizeof(error_buf), fmt, args);
33
- va_end(args);
31
+ vaf.fmt = fmt;
32
+ vaf.va = &args;
3433
35
- printk(KERN_CRIT "ADFS-fs error (device %s)%s%s: %s\n",
34
+ printk(KERN_CRIT "ADFS-fs error (device %s)%s%s: %pV\n",
3635 sb->s_id, function ? ": " : "",
37
- function ? function : "", error_buf);
36
+ function ? function : "", &vaf);
37
+
38
+ va_end(args);
39
+}
40
+
41
+void adfs_msg(struct super_block *sb, const char *pfx, const char *fmt, ...)
42
+{
43
+ struct va_format vaf;
44
+ va_list args;
45
+
46
+ va_start(args, fmt);
47
+ vaf.fmt = fmt;
48
+ vaf.va = &args;
49
+ printk("%sADFS-fs (%s): %pV\n", pfx, sb->s_id, &vaf);
50
+ va_end(args);
3851 }
3952
4053 static int adfs_checkdiscrecord(struct adfs_discrecord *dr)
4154 {
55
+ unsigned int max_idlen;
4256 int i;
4357
4458 /* sector size must be 256, 512 or 1024 bytes */
....@@ -58,8 +72,13 @@
5872 if (le32_to_cpu(dr->disc_size_high) >> dr->log2secsize)
5973 return 1;
6074
61
- /* idlen must be no greater than 19 v2 [1.0] */
62
- if (dr->idlen > 19)
75
+ /*
76
+ * Maximum idlen is limited to 16 bits for new directories by
77
+ * the three-byte storage of an indirect disc address. For
78
+ * big directories, idlen must be no greater than 19 v2 [1.0]
79
+ */
80
+ max_idlen = dr->format_version ? 19 : 16;
81
+ if (dr->idlen > max_idlen)
6382 return 1;
6483
6584 /* reserved bytes should be zero */
....@@ -70,59 +89,11 @@
7089 return 0;
7190 }
7291
73
-static unsigned char adfs_calczonecheck(struct super_block *sb, unsigned char *map)
74
-{
75
- unsigned int v0, v1, v2, v3;
76
- int i;
77
-
78
- v0 = v1 = v2 = v3 = 0;
79
- for (i = sb->s_blocksize - 4; i; i -= 4) {
80
- v0 += map[i] + (v3 >> 8);
81
- v3 &= 0xff;
82
- v1 += map[i + 1] + (v0 >> 8);
83
- v0 &= 0xff;
84
- v2 += map[i + 2] + (v1 >> 8);
85
- v1 &= 0xff;
86
- v3 += map[i + 3] + (v2 >> 8);
87
- v2 &= 0xff;
88
- }
89
- v0 += v3 >> 8;
90
- v1 += map[1] + (v0 >> 8);
91
- v2 += map[2] + (v1 >> 8);
92
- v3 += map[3] + (v2 >> 8);
93
-
94
- return v0 ^ v1 ^ v2 ^ v3;
95
-}
96
-
97
-static int adfs_checkmap(struct super_block *sb, struct adfs_discmap *dm)
98
-{
99
- unsigned char crosscheck = 0, zonecheck = 1;
100
- int i;
101
-
102
- for (i = 0; i < ADFS_SB(sb)->s_map_size; i++) {
103
- unsigned char *map;
104
-
105
- map = dm[i].dm_bh->b_data;
106
-
107
- if (adfs_calczonecheck(sb, map) != map[0]) {
108
- adfs_error(sb, "zone %d fails zonecheck", i);
109
- zonecheck = 0;
110
- }
111
- crosscheck ^= map[3];
112
- }
113
- if (crosscheck != 0xff)
114
- adfs_error(sb, "crosscheck != 0xff");
115
- return crosscheck == 0xff && zonecheck;
116
-}
117
-
11892 static void adfs_put_super(struct super_block *sb)
11993 {
120
- int i;
12194 struct adfs_sb_info *asb = ADFS_SB(sb);
12295
123
- for (i = 0; i < asb->s_map_size; i++)
124
- brelse(asb->s_map[i].dm_bh);
125
- kfree(asb->s_map);
96
+ adfs_free_map(sb);
12697 kfree_rcu(asb, rcu);
12798 }
12899
....@@ -155,10 +126,10 @@
155126 {Opt_err, NULL}
156127 };
157128
158
-static int parse_options(struct super_block *sb, char *options)
129
+static int parse_options(struct super_block *sb, struct adfs_sb_info *asb,
130
+ char *options)
159131 {
160132 char *p;
161
- struct adfs_sb_info *asb = ADFS_SB(sb);
162133 int option;
163134
164135 if (!options)
....@@ -202,8 +173,9 @@
202173 asb->s_ftsuffix = option;
203174 break;
204175 default:
205
- printk("ADFS-fs: unrecognised mount option \"%s\" "
206
- "or missing value\n", p);
176
+ adfs_msg(sb, KERN_ERR,
177
+ "unrecognised mount option \"%s\" or missing value",
178
+ p);
207179 return -EINVAL;
208180 }
209181 }
....@@ -212,9 +184,18 @@
212184
213185 static int adfs_remount(struct super_block *sb, int *flags, char *data)
214186 {
187
+ struct adfs_sb_info temp_asb;
188
+ int ret;
189
+
215190 sync_filesystem(sb);
216
- *flags |= SB_NODIRATIME;
217
- return parse_options(sb, data);
191
+ *flags |= ADFS_SB_FLAGS;
192
+
193
+ temp_asb = *ADFS_SB(sb);
194
+ ret = parse_options(sb, &temp_asb, data);
195
+ if (ret == 0)
196
+ *ADFS_SB(sb) = temp_asb;
197
+
198
+ return ret;
218199 }
219200
220201 static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf)
....@@ -223,16 +204,13 @@
223204 struct adfs_sb_info *sbi = ADFS_SB(sb);
224205 u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
225206
207
+ adfs_map_statfs(sb, buf);
208
+
226209 buf->f_type = ADFS_SUPER_MAGIC;
227210 buf->f_namelen = sbi->s_namelen;
228211 buf->f_bsize = sb->s_blocksize;
229
- buf->f_blocks = sbi->s_size;
230
- buf->f_files = sbi->s_ids_per_zone * sbi->s_map_size;
231
- buf->f_bavail =
232
- buf->f_bfree = adfs_map_free(sb);
233212 buf->f_ffree = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks;
234
- buf->f_fsid.val[0] = (u32)id;
235
- buf->f_fsid.val[1] = (u32)(id >> 32);
213
+ buf->f_fsid = u64_to_fsid(id);
236214
237215 return 0;
238216 }
....@@ -248,15 +226,15 @@
248226 return &ei->vfs_inode;
249227 }
250228
251
-static void adfs_i_callback(struct rcu_head *head)
229
+static void adfs_free_inode(struct inode *inode)
252230 {
253
- struct inode *inode = container_of(head, struct inode, i_rcu);
254231 kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
255232 }
256233
257
-static void adfs_destroy_inode(struct inode *inode)
234
+static int adfs_drop_inode(struct inode *inode)
258235 {
259
- call_rcu(&inode->i_rcu, adfs_i_callback);
236
+ /* always drop inodes if we are read-only */
237
+ return !IS_ENABLED(CONFIG_ADFS_FS_RW) || IS_RDONLY(inode);
260238 }
261239
262240 static void init_once(void *foo)
....@@ -290,8 +268,8 @@
290268
291269 static const struct super_operations adfs_sops = {
292270 .alloc_inode = adfs_alloc_inode,
293
- .destroy_inode = adfs_destroy_inode,
294
- .drop_inode = generic_delete_inode,
271
+ .free_inode = adfs_free_inode,
272
+ .drop_inode = adfs_drop_inode,
295273 .write_inode = adfs_write_inode,
296274 .put_super = adfs_put_super,
297275 .statfs = adfs_statfs,
....@@ -299,87 +277,107 @@
299277 .show_options = adfs_show_options,
300278 };
301279
302
-static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_discrecord *dr)
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))
303284 {
304
- struct adfs_discmap *dm;
305
- unsigned int map_addr, zone_size, nzones;
306
- int i, zone;
307285 struct adfs_sb_info *asb = ADFS_SB(sb);
286
+ struct adfs_discrecord *dr;
287
+ struct buffer_head *bh;
288
+ unsigned int blocksize = BLOCK_SIZE;
289
+ int ret, try;
308290
309
- nzones = asb->s_map_size;
310
- zone_size = (8 << dr->log2secsize) - le16_to_cpu(dr->zone_spare);
311
- map_addr = (nzones >> 1) * zone_size -
312
- ((nzones > 1) ? ADFS_DR_SIZE_BITS : 0);
313
- map_addr = signed_asl(map_addr, asb->s_map2blk);
314
-
315
- asb->s_ids_per_zone = zone_size / (asb->s_idlen + 1);
316
-
317
- dm = kmalloc_array(nzones, sizeof(*dm), GFP_KERNEL);
318
- if (dm == NULL) {
319
- adfs_error(sb, "not enough memory");
320
- return ERR_PTR(-ENOMEM);
321
- }
322
-
323
- for (zone = 0; zone < nzones; zone++, map_addr++) {
324
- dm[zone].dm_startbit = 0;
325
- dm[zone].dm_endbit = zone_size;
326
- dm[zone].dm_startblk = zone * zone_size - ADFS_DR_SIZE_BITS;
327
- dm[zone].dm_bh = sb_bread(sb, map_addr);
328
-
329
- if (!dm[zone].dm_bh) {
330
- adfs_error(sb, "unable to read map");
331
- goto error_free;
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)) {
295
+ if (!silent)
296
+ adfs_msg(sb, KERN_ERR,
297
+ "error: unsupported blocksize");
298
+ return -EINVAL;
332299 }
300
+
301
+ /* read the buffer */
302
+ bh = sb_bread(sb, offset >> sb->s_blocksize_bits);
303
+ if (!bh) {
304
+ adfs_msg(sb, KERN_ERR,
305
+ "error: unable to read block %u, try %d",
306
+ offset >> sb->s_blocksize_bits, try);
307
+ return -EIO;
308
+ }
309
+
310
+ /* validate it */
311
+ ret = validate(sb, bh, &dr);
312
+ if (ret) {
313
+ brelse(bh);
314
+ return ret;
315
+ }
316
+
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);
321
+ brelse(bh);
322
+ return PTR_ERR_OR_ZERO(asb->s_map);
323
+ }
324
+
325
+ brelse(bh);
333326 }
334327
335
- /* adjust the limits for the first and last map zones */
336
- i = zone - 1;
337
- dm[0].dm_startblk = 0;
338
- dm[0].dm_startbit = ADFS_DR_SIZE_BITS;
339
- dm[i].dm_endbit = (le32_to_cpu(dr->disc_size_high) << (32 - dr->log2bpmb)) +
340
- (le32_to_cpu(dr->disc_size) >> dr->log2bpmb) +
341
- (ADFS_DR_SIZE_BITS - i * zone_size);
342
-
343
- if (adfs_checkmap(sb, dm))
344
- return dm;
345
-
346
- adfs_error(sb, "map corrupted");
347
-
348
-error_free:
349
- while (--zone >= 0)
350
- brelse(dm[zone].dm_bh);
351
-
352
- kfree(dm);
353
- return ERR_PTR(-EIO);
328
+ return -EIO;
354329 }
355330
356
-static inline unsigned long adfs_discsize(struct adfs_discrecord *dr, int block_bits)
331
+static int adfs_validate_bblk(struct super_block *sb, struct buffer_head *bh,
332
+ struct adfs_discrecord **drp)
357333 {
358
- unsigned long discsize;
334
+ struct adfs_discrecord *dr;
335
+ unsigned char *b_data;
359336
360
- discsize = le32_to_cpu(dr->disc_size_high) << (32 - block_bits);
361
- discsize |= le32_to_cpu(dr->disc_size) >> block_bits;
337
+ b_data = bh->b_data + (ADFS_DISCRECORD % sb->s_blocksize);
338
+ if (adfs_checkbblk(b_data))
339
+ return -EILSEQ;
362340
363
- return discsize;
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))
344
+ return -EILSEQ;
345
+
346
+ *drp = dr;
347
+ return 0;
348
+}
349
+
350
+static int adfs_validate_dr0(struct super_block *sb, struct buffer_head *bh,
351
+ struct adfs_discrecord **drp)
352
+{
353
+ struct adfs_discrecord *dr;
354
+
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)
358
+ return -EILSEQ;
359
+
360
+ *drp = dr;
361
+ return 0;
364362 }
365363
366364 static int adfs_fill_super(struct super_block *sb, void *data, int silent)
367365 {
368366 struct adfs_discrecord *dr;
369
- struct buffer_head *bh;
370367 struct object_info root_obj;
371
- unsigned char *b_data;
372
- unsigned int blocksize;
373368 struct adfs_sb_info *asb;
374369 struct inode *root;
375370 int ret = -EINVAL;
376371
377
- sb->s_flags |= SB_NODIRATIME;
372
+ sb->s_flags |= ADFS_SB_FLAGS;
378373
379374 asb = kzalloc(sizeof(*asb), GFP_KERNEL);
380375 if (!asb)
381376 return -ENOMEM;
377
+
382378 sb->s_fs_info = asb;
379
+ sb->s_magic = ADFS_SUPER_MAGIC;
380
+ sb->s_time_gran = 10000000;
383381
384382 /* set default options */
385383 asb->s_uid = GLOBAL_ROOT_UID;
....@@ -388,93 +386,29 @@
388386 asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK;
389387 asb->s_ftsuffix = 0;
390388
391
- if (parse_options(sb, data))
389
+ if (parse_options(sb, asb, data))
392390 goto error;
393391
394
- sb_set_blocksize(sb, BLOCK_SIZE);
395
- if (!(bh = sb_bread(sb, ADFS_DISCRECORD / BLOCK_SIZE))) {
396
- adfs_error(sb, "unable to read superblock");
397
- ret = -EIO;
392
+ /* Try to probe the filesystem boot block */
393
+ ret = adfs_probe(sb, ADFS_DISCRECORD, 1, adfs_validate_bblk);
394
+ if (ret == -EILSEQ)
395
+ ret = adfs_probe(sb, 0, silent, adfs_validate_dr0);
396
+ if (ret == -EILSEQ) {
397
+ if (!silent)
398
+ adfs_msg(sb, KERN_ERR,
399
+ "error: can't find an ADFS filesystem on dev %s.",
400
+ sb->s_id);
401
+ ret = -EINVAL;
402
+ }
403
+ if (ret)
398404 goto error;
399
- }
400405
401
- b_data = bh->b_data + (ADFS_DISCRECORD % BLOCK_SIZE);
402
-
403
- if (adfs_checkbblk(b_data)) {
404
- if (!silent)
405
- printk("VFS: Can't find an adfs filesystem on dev "
406
- "%s.\n", sb->s_id);
407
- ret = -EINVAL;
408
- goto error_free_bh;
409
- }
410
-
411
- dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
412
-
413
- /*
414
- * Do some sanity checks on the ADFS disc record
415
- */
416
- if (adfs_checkdiscrecord(dr)) {
417
- if (!silent)
418
- printk("VPS: Can't find an adfs filesystem on dev "
419
- "%s.\n", sb->s_id);
420
- ret = -EINVAL;
421
- goto error_free_bh;
422
- }
423
-
424
- blocksize = 1 << dr->log2secsize;
425
- brelse(bh);
426
-
427
- if (sb_set_blocksize(sb, blocksize)) {
428
- bh = sb_bread(sb, ADFS_DISCRECORD / sb->s_blocksize);
429
- if (!bh) {
430
- adfs_error(sb, "couldn't read superblock on "
431
- "2nd try.");
432
- ret = -EIO;
433
- goto error;
434
- }
435
- b_data = bh->b_data + (ADFS_DISCRECORD % sb->s_blocksize);
436
- if (adfs_checkbblk(b_data)) {
437
- adfs_error(sb, "disc record mismatch, very weird!");
438
- ret = -EINVAL;
439
- goto error_free_bh;
440
- }
441
- dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
442
- } else {
443
- if (!silent)
444
- printk(KERN_ERR "VFS: Unsupported blocksize on dev "
445
- "%s.\n", sb->s_id);
446
- ret = -EINVAL;
447
- goto error;
448
- }
449
-
450
- /*
451
- * blocksize on this device should now be set to the ADFS log2secsize
452
- */
453
-
454
- sb->s_magic = ADFS_SUPER_MAGIC;
455
- asb->s_idlen = dr->idlen;
456
- asb->s_map_size = dr->nzones | (dr->nzones_high << 8);
457
- asb->s_map2blk = dr->log2bpmb - dr->log2secsize;
458
- asb->s_size = adfs_discsize(dr, sb->s_blocksize_bits);
459
- asb->s_version = dr->format_version;
460
- asb->s_log2sharesize = dr->log2sharesize;
461
-
462
- asb->s_map = adfs_read_map(sb, dr);
463
- if (IS_ERR(asb->s_map)) {
464
- ret = PTR_ERR(asb->s_map);
465
- goto error_free_bh;
466
- }
467
-
468
- brelse(bh);
469
-
470
- /*
471
- * set up enough so that we can read an inode
472
- */
406
+ /* set up enough so that we can read an inode */
473407 sb->s_op = &adfs_sops;
474408
475
- dr = (struct adfs_discrecord *)(asb->s_map[0].dm_bh->b_data + 4);
409
+ dr = adfs_map_discrecord(asb->s_map);
476410
477
- root_obj.parent_id = root_obj.file_id = le32_to_cpu(dr->root);
411
+ root_obj.parent_id = root_obj.indaddr = le32_to_cpu(dr->root);
478412 root_obj.name_len = 0;
479413 /* Set root object date as 01 Jan 1987 00:00:00 */
480414 root_obj.loadaddr = 0xfff0003f;
....@@ -482,13 +416,12 @@
482416 root_obj.size = ADFS_NEWDIR_SIZE;
483417 root_obj.attr = ADFS_NDA_DIRECTORY | ADFS_NDA_OWNER_READ |
484418 ADFS_NDA_OWNER_WRITE | ADFS_NDA_PUBLIC_READ;
485
- root_obj.filetype = -1;
486419
487420 /*
488421 * If this is a F+ disk with variable length directories,
489422 * get the root_size from the disc record.
490423 */
491
- if (asb->s_version) {
424
+ if (dr->format_version) {
492425 root_obj.size = le32_to_cpu(dr->root_size);
493426 asb->s_dir = &adfs_fplus_dir_ops;
494427 asb->s_namelen = ADFS_FPLUS_NAME_LEN;
....@@ -507,18 +440,13 @@
507440 root = adfs_iget(sb, &root_obj);
508441 sb->s_root = d_make_root(root);
509442 if (!sb->s_root) {
510
- int i;
511
- for (i = 0; i < asb->s_map_size; i++)
512
- brelse(asb->s_map[i].dm_bh);
513
- kfree(asb->s_map);
443
+ adfs_free_map(sb);
514444 adfs_error(sb, "get root inode failed\n");
515445 ret = -EIO;
516446 goto error;
517447 }
518448 return 0;
519449
520
-error_free_bh:
521
- brelse(bh);
522450 error:
523451 sb->s_fs_info = NULL;
524452 kfree(asb);
....@@ -564,3 +492,4 @@
564492 module_init(init_adfs_fs)
565493 module_exit(exit_adfs_fs)
566494 MODULE_LICENSE("GPL");
495
+MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY);