root/fs/adfs/super.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __adfs_error
  2. adfs_msg
  3. adfs_checkdiscrecord
  4. adfs_calczonecheck
  5. adfs_checkmap
  6. adfs_put_super
  7. adfs_show_options
  8. parse_options
  9. adfs_remount
  10. adfs_statfs
  11. adfs_alloc_inode
  12. adfs_free_inode
  13. init_once
  14. init_inodecache
  15. destroy_inodecache
  16. adfs_read_map
  17. adfs_fill_super
  18. adfs_mount
  19. init_adfs_fs
  20. exit_adfs_fs

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  linux/fs/adfs/super.c
   4  *
   5  *  Copyright (C) 1997-1999 Russell King
   6  */
   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>
  15 #include "adfs.h"
  16 #include "dir_f.h"
  17 #include "dir_fplus.h"
  18 
  19 #define ADFS_SB_FLAGS SB_NOATIME
  20 
  21 #define ADFS_DEFAULT_OWNER_MASK S_IRWXU
  22 #define ADFS_DEFAULT_OTHER_MASK (S_IRWXG | S_IRWXO)
  23 
  24 void __adfs_error(struct super_block *sb, const char *function, const char *fmt, ...)
  25 {
  26         struct va_format vaf;
  27         va_list args;
  28 
  29         va_start(args, fmt);
  30         vaf.fmt = fmt;
  31         vaf.va = &args;
  32 
  33         printk(KERN_CRIT "ADFS-fs error (device %s)%s%s: %pV\n",
  34                 sb->s_id, function ? ": " : "",
  35                 function ? function : "", &vaf);
  36 
  37         va_end(args);
  38 }
  39 
  40 void adfs_msg(struct super_block *sb, const char *pfx, const char *fmt, ...)
  41 {
  42         struct va_format vaf;
  43         va_list args;
  44 
  45         va_start(args, fmt);
  46         vaf.fmt = fmt;
  47         vaf.va = &args;
  48         printk("%sADFS-fs (%s): %pV\n", pfx, sb->s_id, &vaf);
  49         va_end(args);
  50 }
  51 
  52 static int adfs_checkdiscrecord(struct adfs_discrecord *dr)
  53 {
  54         unsigned int max_idlen;
  55         int i;
  56 
  57         /* sector size must be 256, 512 or 1024 bytes */
  58         if (dr->log2secsize != 8 &&
  59             dr->log2secsize != 9 &&
  60             dr->log2secsize != 10)
  61                 return 1;
  62 
  63         /* idlen must be at least log2secsize + 3 */
  64         if (dr->idlen < dr->log2secsize + 3)
  65                 return 1;
  66 
  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.
  70          */
  71         if (le32_to_cpu(dr->disc_size_high) >> dr->log2secsize)
  72                 return 1;
  73 
  74         /*
  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]
  78          */
  79         max_idlen = dr->format_version ? 19 : 16;
  80         if (dr->idlen > max_idlen)
  81                 return 1;
  82 
  83         /* reserved bytes should be zero */
  84         for (i = 0; i < sizeof(dr->unused52); i++)
  85                 if (dr->unused52[i] != 0)
  86                         return 1;
  87 
  88         return 0;
  89 }
  90 
  91 static unsigned char adfs_calczonecheck(struct super_block *sb, unsigned char *map)
  92 {
  93         unsigned int v0, v1, v2, v3;
  94         int i;
  95 
  96         v0 = v1 = v2 = v3 = 0;
  97         for (i = sb->s_blocksize - 4; i; i -= 4) {
  98                 v0 += map[i]     + (v3 >> 8);
  99                 v3 &= 0xff;
 100                 v1 += map[i + 1] + (v0 >> 8);
 101                 v0 &= 0xff;
 102                 v2 += map[i + 2] + (v1 >> 8);
 103                 v1 &= 0xff;
 104                 v3 += map[i + 3] + (v2 >> 8);
 105                 v2 &= 0xff;
 106         }
 107         v0 +=           v3 >> 8;
 108         v1 += map[1] + (v0 >> 8);
 109         v2 += map[2] + (v1 >> 8);
 110         v3 += map[3] + (v2 >> 8);
 111 
 112         return v0 ^ v1 ^ v2 ^ v3;
 113 }
 114 
 115 static int adfs_checkmap(struct super_block *sb, struct adfs_discmap *dm)
 116 {
 117         unsigned char crosscheck = 0, zonecheck = 1;
 118         int i;
 119 
 120         for (i = 0; i < ADFS_SB(sb)->s_map_size; i++) {
 121                 unsigned char *map;
 122 
 123                 map = dm[i].dm_bh->b_data;
 124 
 125                 if (adfs_calczonecheck(sb, map) != map[0]) {
 126                         adfs_error(sb, "zone %d fails zonecheck", i);
 127                         zonecheck = 0;
 128                 }
 129                 crosscheck ^= map[3];
 130         }
 131         if (crosscheck != 0xff)
 132                 adfs_error(sb, "crosscheck != 0xff");
 133         return crosscheck == 0xff && zonecheck;
 134 }
 135 
 136 static void adfs_put_super(struct super_block *sb)
 137 {
 138         int i;
 139         struct adfs_sb_info *asb = ADFS_SB(sb);
 140 
 141         for (i = 0; i < asb->s_map_size; i++)
 142                 brelse(asb->s_map[i].dm_bh);
 143         kfree(asb->s_map);
 144         kfree_rcu(asb, rcu);
 145 }
 146 
 147 static int adfs_show_options(struct seq_file *seq, struct dentry *root)
 148 {
 149         struct adfs_sb_info *asb = ADFS_SB(root->d_sb);
 150 
 151         if (!uid_eq(asb->s_uid, GLOBAL_ROOT_UID))
 152                 seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, asb->s_uid));
 153         if (!gid_eq(asb->s_gid, GLOBAL_ROOT_GID))
 154                 seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, asb->s_gid));
 155         if (asb->s_owner_mask != ADFS_DEFAULT_OWNER_MASK)
 156                 seq_printf(seq, ",ownmask=%o", asb->s_owner_mask);
 157         if (asb->s_other_mask != ADFS_DEFAULT_OTHER_MASK)
 158                 seq_printf(seq, ",othmask=%o", asb->s_other_mask);
 159         if (asb->s_ftsuffix != 0)
 160                 seq_printf(seq, ",ftsuffix=%u", asb->s_ftsuffix);
 161 
 162         return 0;
 163 }
 164 
 165 enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_ftsuffix, Opt_err};
 166 
 167 static const match_table_t tokens = {
 168         {Opt_uid, "uid=%u"},
 169         {Opt_gid, "gid=%u"},
 170         {Opt_ownmask, "ownmask=%o"},
 171         {Opt_othmask, "othmask=%o"},
 172         {Opt_ftsuffix, "ftsuffix=%u"},
 173         {Opt_err, NULL}
 174 };
 175 
 176 static int parse_options(struct super_block *sb, struct adfs_sb_info *asb,
 177                          char *options)
 178 {
 179         char *p;
 180         int option;
 181 
 182         if (!options)
 183                 return 0;
 184 
 185         while ((p = strsep(&options, ",")) != NULL) {
 186                 substring_t args[MAX_OPT_ARGS];
 187                 int token;
 188                 if (!*p)
 189                         continue;
 190 
 191                 token = match_token(p, tokens, args);
 192                 switch (token) {
 193                 case Opt_uid:
 194                         if (match_int(args, &option))
 195                                 return -EINVAL;
 196                         asb->s_uid = make_kuid(current_user_ns(), option);
 197                         if (!uid_valid(asb->s_uid))
 198                                 return -EINVAL;
 199                         break;
 200                 case Opt_gid:
 201                         if (match_int(args, &option))
 202                                 return -EINVAL;
 203                         asb->s_gid = make_kgid(current_user_ns(), option);
 204                         if (!gid_valid(asb->s_gid))
 205                                 return -EINVAL;
 206                         break;
 207                 case Opt_ownmask:
 208                         if (match_octal(args, &option))
 209                                 return -EINVAL;
 210                         asb->s_owner_mask = option;
 211                         break;
 212                 case Opt_othmask:
 213                         if (match_octal(args, &option))
 214                                 return -EINVAL;
 215                         asb->s_other_mask = option;
 216                         break;
 217                 case Opt_ftsuffix:
 218                         if (match_int(args, &option))
 219                                 return -EINVAL;
 220                         asb->s_ftsuffix = option;
 221                         break;
 222                 default:
 223                         adfs_msg(sb, KERN_ERR,
 224                                  "unrecognised mount option \"%s\" or missing value",
 225                                  p);
 226                         return -EINVAL;
 227                 }
 228         }
 229         return 0;
 230 }
 231 
 232 static int adfs_remount(struct super_block *sb, int *flags, char *data)
 233 {
 234         struct adfs_sb_info temp_asb;
 235         int ret;
 236 
 237         sync_filesystem(sb);
 238         *flags |= ADFS_SB_FLAGS;
 239 
 240         temp_asb = *ADFS_SB(sb);
 241         ret = parse_options(sb, &temp_asb, data);
 242         if (ret == 0)
 243                 *ADFS_SB(sb) = temp_asb;
 244 
 245         return ret;
 246 }
 247 
 248 static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 249 {
 250         struct super_block *sb = dentry->d_sb;
 251         struct adfs_sb_info *sbi = ADFS_SB(sb);
 252         struct adfs_discrecord *dr = adfs_map_discrecord(sbi->s_map);
 253         u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 254 
 255         buf->f_type    = ADFS_SUPER_MAGIC;
 256         buf->f_namelen = sbi->s_namelen;
 257         buf->f_bsize   = sb->s_blocksize;
 258         buf->f_blocks  = adfs_disc_size(dr) >> sb->s_blocksize_bits;
 259         buf->f_files   = sbi->s_ids_per_zone * sbi->s_map_size;
 260         buf->f_bavail  =
 261         buf->f_bfree   = adfs_map_free(sb);
 262         buf->f_ffree   = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks;
 263         buf->f_fsid.val[0] = (u32)id;
 264         buf->f_fsid.val[1] = (u32)(id >> 32);
 265 
 266         return 0;
 267 }
 268 
 269 static struct kmem_cache *adfs_inode_cachep;
 270 
 271 static struct inode *adfs_alloc_inode(struct super_block *sb)
 272 {
 273         struct adfs_inode_info *ei;
 274         ei = kmem_cache_alloc(adfs_inode_cachep, GFP_KERNEL);
 275         if (!ei)
 276                 return NULL;
 277         return &ei->vfs_inode;
 278 }
 279 
 280 static void adfs_free_inode(struct inode *inode)
 281 {
 282         kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
 283 }
 284 
 285 static void init_once(void *foo)
 286 {
 287         struct adfs_inode_info *ei = (struct adfs_inode_info *) foo;
 288 
 289         inode_init_once(&ei->vfs_inode);
 290 }
 291 
 292 static int __init init_inodecache(void)
 293 {
 294         adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
 295                                              sizeof(struct adfs_inode_info),
 296                                              0, (SLAB_RECLAIM_ACCOUNT|
 297                                                 SLAB_MEM_SPREAD|SLAB_ACCOUNT),
 298                                              init_once);
 299         if (adfs_inode_cachep == NULL)
 300                 return -ENOMEM;
 301         return 0;
 302 }
 303 
 304 static void destroy_inodecache(void)
 305 {
 306         /*
 307          * Make sure all delayed rcu free inodes are flushed before we
 308          * destroy cache.
 309          */
 310         rcu_barrier();
 311         kmem_cache_destroy(adfs_inode_cachep);
 312 }
 313 
 314 static const struct super_operations adfs_sops = {
 315         .alloc_inode    = adfs_alloc_inode,
 316         .free_inode     = adfs_free_inode,
 317         .drop_inode     = generic_delete_inode,
 318         .write_inode    = adfs_write_inode,
 319         .put_super      = adfs_put_super,
 320         .statfs         = adfs_statfs,
 321         .remount_fs     = adfs_remount,
 322         .show_options   = adfs_show_options,
 323 };
 324 
 325 static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_discrecord *dr)
 326 {
 327         struct adfs_discmap *dm;
 328         unsigned int map_addr, zone_size, nzones;
 329         int i, zone;
 330         struct adfs_sb_info *asb = ADFS_SB(sb);
 331 
 332         nzones    = asb->s_map_size;
 333         zone_size = (8 << dr->log2secsize) - le16_to_cpu(dr->zone_spare);
 334         map_addr  = (nzones >> 1) * zone_size -
 335                      ((nzones > 1) ? ADFS_DR_SIZE_BITS : 0);
 336         map_addr  = signed_asl(map_addr, asb->s_map2blk);
 337 
 338         asb->s_ids_per_zone = zone_size / (asb->s_idlen + 1);
 339 
 340         dm = kmalloc_array(nzones, sizeof(*dm), GFP_KERNEL);
 341         if (dm == NULL) {
 342                 adfs_error(sb, "not enough memory");
 343                 return ERR_PTR(-ENOMEM);
 344         }
 345 
 346         for (zone = 0; zone < nzones; zone++, map_addr++) {
 347                 dm[zone].dm_startbit = 0;
 348                 dm[zone].dm_endbit   = zone_size;
 349                 dm[zone].dm_startblk = zone * zone_size - ADFS_DR_SIZE_BITS;
 350                 dm[zone].dm_bh       = sb_bread(sb, map_addr);
 351 
 352                 if (!dm[zone].dm_bh) {
 353                         adfs_error(sb, "unable to read map");
 354                         goto error_free;
 355                 }
 356         }
 357 
 358         /* adjust the limits for the first and last map zones */
 359         i = zone - 1;
 360         dm[0].dm_startblk = 0;
 361         dm[0].dm_startbit = ADFS_DR_SIZE_BITS;
 362         dm[i].dm_endbit   = (adfs_disc_size(dr) >> dr->log2bpmb) +
 363                             (ADFS_DR_SIZE_BITS - i * zone_size);
 364 
 365         if (adfs_checkmap(sb, dm))
 366                 return dm;
 367 
 368         adfs_error(sb, "map corrupted");
 369 
 370 error_free:
 371         while (--zone >= 0)
 372                 brelse(dm[zone].dm_bh);
 373 
 374         kfree(dm);
 375         return ERR_PTR(-EIO);
 376 }
 377 
 378 static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 379 {
 380         struct adfs_discrecord *dr;
 381         struct buffer_head *bh;
 382         struct object_info root_obj;
 383         unsigned char *b_data;
 384         unsigned int blocksize;
 385         struct adfs_sb_info *asb;
 386         struct inode *root;
 387         int ret = -EINVAL;
 388 
 389         sb->s_flags |= ADFS_SB_FLAGS;
 390 
 391         asb = kzalloc(sizeof(*asb), GFP_KERNEL);
 392         if (!asb)
 393                 return -ENOMEM;
 394         sb->s_fs_info = asb;
 395 
 396         /* set default options */
 397         asb->s_uid = GLOBAL_ROOT_UID;
 398         asb->s_gid = GLOBAL_ROOT_GID;
 399         asb->s_owner_mask = ADFS_DEFAULT_OWNER_MASK;
 400         asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK;
 401         asb->s_ftsuffix = 0;
 402 
 403         if (parse_options(sb, asb, data))
 404                 goto error;
 405 
 406         sb_set_blocksize(sb, BLOCK_SIZE);
 407         if (!(bh = sb_bread(sb, ADFS_DISCRECORD / BLOCK_SIZE))) {
 408                 adfs_msg(sb, KERN_ERR, "error: unable to read superblock");
 409                 ret = -EIO;
 410                 goto error;
 411         }
 412 
 413         b_data = bh->b_data + (ADFS_DISCRECORD % BLOCK_SIZE);
 414 
 415         if (adfs_checkbblk(b_data)) {
 416                 ret = -EINVAL;
 417                 goto error_badfs;
 418         }
 419 
 420         dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
 421 
 422         /*
 423          * Do some sanity checks on the ADFS disc record
 424          */
 425         if (adfs_checkdiscrecord(dr)) {
 426                 ret = -EINVAL;
 427                 goto error_badfs;
 428         }
 429 
 430         blocksize = 1 << dr->log2secsize;
 431         brelse(bh);
 432 
 433         if (sb_set_blocksize(sb, blocksize)) {
 434                 bh = sb_bread(sb, ADFS_DISCRECORD / sb->s_blocksize);
 435                 if (!bh) {
 436                         adfs_msg(sb, KERN_ERR,
 437                                  "error: couldn't read superblock on 2nd try.");
 438                         ret = -EIO;
 439                         goto error;
 440                 }
 441                 b_data = bh->b_data + (ADFS_DISCRECORD % sb->s_blocksize);
 442                 if (adfs_checkbblk(b_data)) {
 443                         adfs_msg(sb, KERN_ERR,
 444                                  "error: disc record mismatch, very weird!");
 445                         ret = -EINVAL;
 446                         goto error_free_bh;
 447                 }
 448                 dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
 449         } else {
 450                 if (!silent)
 451                         adfs_msg(sb, KERN_ERR,
 452                                  "error: unsupported blocksize");
 453                 ret = -EINVAL;
 454                 goto error;
 455         }
 456 
 457         /*
 458          * blocksize on this device should now be set to the ADFS log2secsize
 459          */
 460 
 461         sb->s_magic             = ADFS_SUPER_MAGIC;
 462         asb->s_idlen            = dr->idlen;
 463         asb->s_map_size         = dr->nzones | (dr->nzones_high << 8);
 464         asb->s_map2blk          = dr->log2bpmb - dr->log2secsize;
 465         asb->s_log2sharesize    = dr->log2sharesize;
 466 
 467         asb->s_map = adfs_read_map(sb, dr);
 468         if (IS_ERR(asb->s_map)) {
 469                 ret =  PTR_ERR(asb->s_map);
 470                 goto error_free_bh;
 471         }
 472 
 473         brelse(bh);
 474 
 475         /*
 476          * set up enough so that we can read an inode
 477          */
 478         sb->s_op = &adfs_sops;
 479 
 480         dr = adfs_map_discrecord(asb->s_map);
 481 
 482         root_obj.parent_id = root_obj.indaddr = le32_to_cpu(dr->root);
 483         root_obj.name_len  = 0;
 484         /* Set root object date as 01 Jan 1987 00:00:00 */
 485         root_obj.loadaddr  = 0xfff0003f;
 486         root_obj.execaddr  = 0xec22c000;
 487         root_obj.size      = ADFS_NEWDIR_SIZE;
 488         root_obj.attr      = ADFS_NDA_DIRECTORY   | ADFS_NDA_OWNER_READ |
 489                              ADFS_NDA_OWNER_WRITE | ADFS_NDA_PUBLIC_READ;
 490 
 491         /*
 492          * If this is a F+ disk with variable length directories,
 493          * get the root_size from the disc record.
 494          */
 495         if (dr->format_version) {
 496                 root_obj.size = le32_to_cpu(dr->root_size);
 497                 asb->s_dir     = &adfs_fplus_dir_ops;
 498                 asb->s_namelen = ADFS_FPLUS_NAME_LEN;
 499         } else {
 500                 asb->s_dir     = &adfs_f_dir_ops;
 501                 asb->s_namelen = ADFS_F_NAME_LEN;
 502         }
 503         /*
 504          * ,xyz hex filetype suffix may be added by driver
 505          * to files that have valid RISC OS filetype
 506          */
 507         if (asb->s_ftsuffix)
 508                 asb->s_namelen += 4;
 509 
 510         sb->s_d_op = &adfs_dentry_operations;
 511         root = adfs_iget(sb, &root_obj);
 512         sb->s_root = d_make_root(root);
 513         if (!sb->s_root) {
 514                 int i;
 515                 for (i = 0; i < asb->s_map_size; i++)
 516                         brelse(asb->s_map[i].dm_bh);
 517                 kfree(asb->s_map);
 518                 adfs_error(sb, "get root inode failed\n");
 519                 ret = -EIO;
 520                 goto error;
 521         }
 522         return 0;
 523 
 524 error_badfs:
 525         if (!silent)
 526                 adfs_msg(sb, KERN_ERR,
 527                          "error: can't find an ADFS filesystem on dev %s.",
 528                          sb->s_id);
 529 error_free_bh:
 530         brelse(bh);
 531 error:
 532         sb->s_fs_info = NULL;
 533         kfree(asb);
 534         return ret;
 535 }
 536 
 537 static struct dentry *adfs_mount(struct file_system_type *fs_type,
 538         int flags, const char *dev_name, void *data)
 539 {
 540         return mount_bdev(fs_type, flags, dev_name, data, adfs_fill_super);
 541 }
 542 
 543 static struct file_system_type adfs_fs_type = {
 544         .owner          = THIS_MODULE,
 545         .name           = "adfs",
 546         .mount          = adfs_mount,
 547         .kill_sb        = kill_block_super,
 548         .fs_flags       = FS_REQUIRES_DEV,
 549 };
 550 MODULE_ALIAS_FS("adfs");
 551 
 552 static int __init init_adfs_fs(void)
 553 {
 554         int err = init_inodecache();
 555         if (err)
 556                 goto out1;
 557         err = register_filesystem(&adfs_fs_type);
 558         if (err)
 559                 goto out;
 560         return 0;
 561 out:
 562         destroy_inodecache();
 563 out1:
 564         return err;
 565 }
 566 
 567 static void __exit exit_adfs_fs(void)
 568 {
 569         unregister_filesystem(&adfs_fs_type);
 570         destroy_inodecache();
 571 }
 572 
 573 module_init(init_adfs_fs)
 574 module_exit(exit_adfs_fs)
 575 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */