1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * QNX6 file system, Linux implementation. 4 * 5 * Version : 1.0.0 6 * 7 * History : 8 * 9 * 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release. 10 * 16-02-2012 pagemap extension by Al Viro 11 * 12 */ 13 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/slab.h> 17 #include <linux/highuid.h> 18 #include <linux/pagemap.h> 19 #include <linux/buffer_head.h> 20 #include <linux/writeback.h> 21 #include <linux/statfs.h> 22 #include <linux/seq_file.h> 23 #include <linux/crc32.h> 24 #include <linux/mpage.h> 25 #include <linux/fs_parser.h> 26 #include <linux/fs_context.h> 27 #include "qnx6.h" 28 29 static const struct super_operations qnx6_sops; 30 31 static void qnx6_put_super(struct super_block *sb); 32 static struct inode *qnx6_alloc_inode(struct super_block *sb); 33 static void qnx6_free_inode(struct inode *inode); 34 static int qnx6_reconfigure(struct fs_context *fc); 35 static int qnx6_statfs(struct dentry *dentry, struct kstatfs *buf); 36 static int qnx6_show_options(struct seq_file *seq, struct dentry *root); 37 38 static const struct super_operations qnx6_sops = { 39 .alloc_inode = qnx6_alloc_inode, 40 .free_inode = qnx6_free_inode, 41 .put_super = qnx6_put_super, 42 .statfs = qnx6_statfs, 43 .show_options = qnx6_show_options, 44 }; 45 46 static int qnx6_show_options(struct seq_file *seq, struct dentry *root) 47 { 48 struct super_block *sb = root->d_sb; 49 struct qnx6_sb_info *sbi = QNX6_SB(sb); 50 51 if (sbi->s_mount_opt & QNX6_MOUNT_MMI_FS) 52 seq_puts(seq, ",mmi_fs"); 53 return 0; 54 } 55 56 static int qnx6_reconfigure(struct fs_context *fc) 57 { 58 struct super_block *sb = fc->root->d_sb; 59 60 sync_filesystem(sb); 61 fc->sb_flags |= SB_RDONLY; 62 return 0; 63 } 64 65 static unsigned qnx6_get_devblock(struct super_block *sb, __fs32 block) 66 { 67 struct qnx6_sb_info *sbi = QNX6_SB(sb); 68 return fs32_to_cpu(sbi, block) + sbi->s_blks_off; 69 } 70 71 static unsigned qnx6_block_map(struct inode *inode, unsigned iblock); 72 73 static int qnx6_get_block(struct inode *inode, sector_t iblock, 74 struct buffer_head *bh, int create) 75 { 76 unsigned phys; 77 78 pr_debug("qnx6_get_block inode=[%ld] iblock=[%ld]\n", 79 inode->i_ino, (unsigned long)iblock); 80 81 phys = qnx6_block_map(inode, iblock); 82 if (phys) { 83 /* logical block is before EOF */ 84 map_bh(bh, inode->i_sb, phys); 85 } 86 return 0; 87 } 88 89 static int qnx6_check_blockptr(__fs32 ptr) 90 { 91 if (ptr == ~(__fs32)0) { 92 pr_err("hit unused blockpointer.\n"); 93 return 0; 94 } 95 return 1; 96 } 97 98 static int qnx6_read_folio(struct file *file, struct folio *folio) 99 { 100 return mpage_read_folio(folio, qnx6_get_block); 101 } 102 103 static void qnx6_readahead(struct readahead_control *rac) 104 { 105 mpage_readahead(rac, qnx6_get_block); 106 } 107 108 /* 109 * returns the block number for the no-th element in the tree 110 * inodebits requred as there are multiple inodes in one inode block 111 */ 112 static unsigned qnx6_block_map(struct inode *inode, unsigned no) 113 { 114 struct super_block *s = inode->i_sb; 115 struct qnx6_sb_info *sbi = QNX6_SB(s); 116 struct qnx6_inode_info *ei = QNX6_I(inode); 117 unsigned block = 0; 118 struct buffer_head *bh; 119 __fs32 ptr; 120 int levelptr; 121 int ptrbits = sbi->s_ptrbits; 122 int bitdelta; 123 u32 mask = (1 << ptrbits) - 1; 124 int depth = ei->di_filelevels; 125 int i; 126 127 bitdelta = ptrbits * depth; 128 levelptr = no >> bitdelta; 129 130 if (levelptr > QNX6_NO_DIRECT_POINTERS - 1) { 131 pr_err("Requested file block number (%u) too big.", no); 132 return 0; 133 } 134 135 block = qnx6_get_devblock(s, ei->di_block_ptr[levelptr]); 136 137 for (i = 0; i < depth; i++) { 138 bh = sb_bread(s, block); 139 if (!bh) { 140 pr_err("Error reading block (%u)\n", block); 141 return 0; 142 } 143 bitdelta -= ptrbits; 144 levelptr = (no >> bitdelta) & mask; 145 ptr = ((__fs32 *)bh->b_data)[levelptr]; 146 147 if (!qnx6_check_blockptr(ptr)) 148 return 0; 149 150 block = qnx6_get_devblock(s, ptr); 151 brelse(bh); 152 } 153 return block; 154 } 155 156 static int qnx6_statfs(struct dentry *dentry, struct kstatfs *buf) 157 { 158 struct super_block *sb = dentry->d_sb; 159 struct qnx6_sb_info *sbi = QNX6_SB(sb); 160 u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 161 162 buf->f_type = sb->s_magic; 163 buf->f_bsize = sb->s_blocksize; 164 buf->f_blocks = fs32_to_cpu(sbi, sbi->sb->sb_num_blocks); 165 buf->f_bfree = fs32_to_cpu(sbi, sbi->sb->sb_free_blocks); 166 buf->f_files = fs32_to_cpu(sbi, sbi->sb->sb_num_inodes); 167 buf->f_ffree = fs32_to_cpu(sbi, sbi->sb->sb_free_inodes); 168 buf->f_bavail = buf->f_bfree; 169 buf->f_namelen = QNX6_LONG_NAME_MAX; 170 buf->f_fsid = u64_to_fsid(id); 171 172 return 0; 173 } 174 175 /* 176 * Check the root directory of the filesystem to make sure 177 * it really _is_ a qnx6 filesystem, and to check the size 178 * of the directory entry. 179 */ 180 static const char *qnx6_checkroot(struct super_block *s) 181 { 182 static char match_root[2][3] = {".\0\0", "..\0"}; 183 int i, error = 0; 184 struct qnx6_dir_entry *dir_entry; 185 struct inode *root = d_inode(s->s_root); 186 struct address_space *mapping = root->i_mapping; 187 struct page *page = read_mapping_page(mapping, 0, NULL); 188 if (IS_ERR(page)) 189 return "error reading root directory"; 190 kmap(page); 191 dir_entry = page_address(page); 192 for (i = 0; i < 2; i++) { 193 /* maximum 3 bytes - due to match_root limitation */ 194 if (strncmp(dir_entry[i].de_fname, match_root[i], 3)) 195 error = 1; 196 } 197 qnx6_put_page(page); 198 if (error) 199 return "error reading root directory."; 200 return NULL; 201 } 202 203 #ifdef CONFIG_QNX6FS_DEBUG 204 void qnx6_superblock_debug(struct qnx6_super_block *sb, struct super_block *s) 205 { 206 struct qnx6_sb_info *sbi = QNX6_SB(s); 207 208 pr_debug("magic: %08x\n", fs32_to_cpu(sbi, sb->sb_magic)); 209 pr_debug("checksum: %08x\n", fs32_to_cpu(sbi, sb->sb_checksum)); 210 pr_debug("serial: %llx\n", fs64_to_cpu(sbi, sb->sb_serial)); 211 pr_debug("flags: %08x\n", fs32_to_cpu(sbi, sb->sb_flags)); 212 pr_debug("blocksize: %08x\n", fs32_to_cpu(sbi, sb->sb_blocksize)); 213 pr_debug("num_inodes: %08x\n", fs32_to_cpu(sbi, sb->sb_num_inodes)); 214 pr_debug("free_inodes: %08x\n", fs32_to_cpu(sbi, sb->sb_free_inodes)); 215 pr_debug("num_blocks: %08x\n", fs32_to_cpu(sbi, sb->sb_num_blocks)); 216 pr_debug("free_blocks: %08x\n", fs32_to_cpu(sbi, sb->sb_free_blocks)); 217 pr_debug("inode_levels: %02x\n", sb->Inode.levels); 218 } 219 #endif 220 221 enum { 222 Opt_mmifs 223 }; 224 225 struct qnx6_context { 226 unsigned long s_mount_opts; 227 }; 228 229 static const struct fs_parameter_spec qnx6_param_spec[] = { 230 fsparam_flag ("mmi_fs", Opt_mmifs), 231 {} 232 }; 233 234 static int qnx6_parse_param(struct fs_context *fc, struct fs_parameter *param) 235 { 236 struct qnx6_context *ctx = fc->fs_private; 237 struct fs_parse_result result; 238 int opt; 239 240 opt = fs_parse(fc, qnx6_param_spec, param, &result); 241 if (opt < 0) 242 return opt; 243 244 switch (opt) { 245 case Opt_mmifs: 246 ctx->s_mount_opts |= QNX6_MOUNT_MMI_FS; 247 break; 248 default: 249 return -EINVAL; 250 } 251 return 0; 252 } 253 254 static struct buffer_head *qnx6_check_first_superblock(struct super_block *s, 255 int offset, int silent) 256 { 257 struct qnx6_sb_info *sbi = QNX6_SB(s); 258 struct buffer_head *bh; 259 struct qnx6_super_block *sb; 260 261 /* Check the superblock signatures 262 start with the first superblock */ 263 bh = sb_bread(s, offset); 264 if (!bh) { 265 pr_err("unable to read the first superblock\n"); 266 return NULL; 267 } 268 sb = (struct qnx6_super_block *)bh->b_data; 269 if (fs32_to_cpu(sbi, sb->sb_magic) != QNX6_SUPER_MAGIC) { 270 sbi->s_bytesex = BYTESEX_BE; 271 if (fs32_to_cpu(sbi, sb->sb_magic) == QNX6_SUPER_MAGIC) { 272 /* we got a big endian fs */ 273 pr_debug("fs got different endianness.\n"); 274 return bh; 275 } else 276 sbi->s_bytesex = BYTESEX_LE; 277 if (!silent) { 278 if (offset == 0) { 279 pr_err("wrong signature (magic) in superblock #1.\n"); 280 } else { 281 pr_info("wrong signature (magic) at position (0x%lx) - will try alternative position (0x0000).\n", 282 offset * s->s_blocksize); 283 } 284 } 285 brelse(bh); 286 return NULL; 287 } 288 return bh; 289 } 290 291 static struct inode *qnx6_private_inode(struct super_block *s, 292 struct qnx6_root_node *p); 293 294 static int qnx6_fill_super(struct super_block *s, struct fs_context *fc) 295 { 296 struct buffer_head *bh1 = NULL, *bh2 = NULL; 297 struct qnx6_super_block *sb1 = NULL, *sb2 = NULL; 298 struct qnx6_sb_info *sbi; 299 struct qnx6_context *ctx = fc->fs_private; 300 struct inode *root; 301 const char *errmsg; 302 struct qnx6_sb_info *qs; 303 int ret = -EINVAL; 304 u64 offset; 305 int bootblock_offset = QNX6_BOOTBLOCK_SIZE; 306 int silent = fc->sb_flags & SB_SILENT; 307 308 qs = kzalloc(sizeof(struct qnx6_sb_info), GFP_KERNEL); 309 if (!qs) 310 return -ENOMEM; 311 s->s_fs_info = qs; 312 qs->s_mount_opt = ctx->s_mount_opts; 313 314 /* Superblock always is 512 Byte long */ 315 if (!sb_set_blocksize(s, QNX6_SUPERBLOCK_SIZE)) { 316 pr_err("unable to set blocksize\n"); 317 goto outnobh; 318 } 319 320 if (qs->s_mount_opt == QNX6_MOUNT_MMI_FS) { 321 sb1 = qnx6_mmi_fill_super(s, silent); 322 if (sb1) 323 goto mmi_success; 324 else 325 goto outnobh; 326 } 327 sbi = QNX6_SB(s); 328 sbi->s_bytesex = BYTESEX_LE; 329 /* Check the superblock signatures 330 start with the first superblock */ 331 bh1 = qnx6_check_first_superblock(s, 332 bootblock_offset / QNX6_SUPERBLOCK_SIZE, silent); 333 if (!bh1) { 334 /* try again without bootblock offset */ 335 bh1 = qnx6_check_first_superblock(s, 0, silent); 336 if (!bh1) { 337 pr_err("unable to read the first superblock\n"); 338 goto outnobh; 339 } 340 /* seems that no bootblock at partition start */ 341 bootblock_offset = 0; 342 } 343 sb1 = (struct qnx6_super_block *)bh1->b_data; 344 345 #ifdef CONFIG_QNX6FS_DEBUG 346 qnx6_superblock_debug(sb1, s); 347 #endif 348 349 /* checksum check - start at byte 8 and end at byte 512 */ 350 if (fs32_to_cpu(sbi, sb1->sb_checksum) != 351 crc32_be(0, (char *)(bh1->b_data + 8), 504)) { 352 pr_err("superblock #1 checksum error\n"); 353 goto out; 354 } 355 356 /* set new blocksize */ 357 if (!sb_set_blocksize(s, fs32_to_cpu(sbi, sb1->sb_blocksize))) { 358 pr_err("unable to set blocksize\n"); 359 goto out; 360 } 361 /* blocksize invalidates bh - pull it back in */ 362 brelse(bh1); 363 bh1 = sb_bread(s, bootblock_offset >> s->s_blocksize_bits); 364 if (!bh1) 365 goto outnobh; 366 sb1 = (struct qnx6_super_block *)bh1->b_data; 367 368 /* calculate second superblock blocknumber */ 369 offset = fs32_to_cpu(sbi, sb1->sb_num_blocks) + 370 (bootblock_offset >> s->s_blocksize_bits) + 371 (QNX6_SUPERBLOCK_AREA >> s->s_blocksize_bits); 372 373 /* set bootblock offset */ 374 sbi->s_blks_off = (bootblock_offset >> s->s_blocksize_bits) + 375 (QNX6_SUPERBLOCK_AREA >> s->s_blocksize_bits); 376 377 /* next the second superblock */ 378 bh2 = sb_bread(s, offset); 379 if (!bh2) { 380 pr_err("unable to read the second superblock\n"); 381 goto out; 382 } 383 sb2 = (struct qnx6_super_block *)bh2->b_data; 384 if (fs32_to_cpu(sbi, sb2->sb_magic) != QNX6_SUPER_MAGIC) { 385 if (!silent) 386 pr_err("wrong signature (magic) in superblock #2.\n"); 387 goto out; 388 } 389 390 /* checksum check - start at byte 8 and end at byte 512 */ 391 if (fs32_to_cpu(sbi, sb2->sb_checksum) != 392 crc32_be(0, (char *)(bh2->b_data + 8), 504)) { 393 pr_err("superblock #2 checksum error\n"); 394 goto out; 395 } 396 397 if (fs64_to_cpu(sbi, sb1->sb_serial) >= 398 fs64_to_cpu(sbi, sb2->sb_serial)) { 399 /* superblock #1 active */ 400 sbi->sb_buf = bh1; 401 sbi->sb = (struct qnx6_super_block *)bh1->b_data; 402 brelse(bh2); 403 pr_info("superblock #1 active\n"); 404 } else { 405 /* superblock #2 active */ 406 sbi->sb_buf = bh2; 407 sbi->sb = (struct qnx6_super_block *)bh2->b_data; 408 brelse(bh1); 409 pr_info("superblock #2 active\n"); 410 } 411 mmi_success: 412 /* sanity check - limit maximum indirect pointer levels */ 413 if (sb1->Inode.levels > QNX6_PTR_MAX_LEVELS) { 414 pr_err("too many inode levels (max %i, sb %i)\n", 415 QNX6_PTR_MAX_LEVELS, sb1->Inode.levels); 416 goto out; 417 } 418 if (sb1->Longfile.levels > QNX6_PTR_MAX_LEVELS) { 419 pr_err("too many longfilename levels (max %i, sb %i)\n", 420 QNX6_PTR_MAX_LEVELS, sb1->Longfile.levels); 421 goto out; 422 } 423 s->s_op = &qnx6_sops; 424 s->s_magic = QNX6_SUPER_MAGIC; 425 s->s_flags |= SB_RDONLY; /* Yup, read-only yet */ 426 s->s_time_min = 0; 427 s->s_time_max = U32_MAX; 428 429 /* ease the later tree level calculations */ 430 sbi = QNX6_SB(s); 431 sbi->s_ptrbits = ilog2(s->s_blocksize / 4); 432 sbi->inodes = qnx6_private_inode(s, &sb1->Inode); 433 if (!sbi->inodes) 434 goto out; 435 sbi->longfile = qnx6_private_inode(s, &sb1->Longfile); 436 if (!sbi->longfile) 437 goto out1; 438 439 /* prefetch root inode */ 440 root = qnx6_iget(s, QNX6_ROOT_INO); 441 if (IS_ERR(root)) { 442 pr_err("get inode failed\n"); 443 ret = PTR_ERR(root); 444 goto out2; 445 } 446 447 ret = -ENOMEM; 448 s->s_root = d_make_root(root); 449 if (!s->s_root) 450 goto out2; 451 452 ret = -EINVAL; 453 errmsg = qnx6_checkroot(s); 454 if (errmsg != NULL) { 455 if (!silent) 456 pr_err("%s\n", errmsg); 457 goto out3; 458 } 459 return 0; 460 461 out3: 462 dput(s->s_root); 463 s->s_root = NULL; 464 out2: 465 iput(sbi->longfile); 466 out1: 467 iput(sbi->inodes); 468 out: 469 brelse(bh1); 470 brelse(bh2); 471 outnobh: 472 kfree(qs); 473 s->s_fs_info = NULL; 474 return ret; 475 } 476 477 static void qnx6_put_super(struct super_block *sb) 478 { 479 struct qnx6_sb_info *qs = QNX6_SB(sb); 480 brelse(qs->sb_buf); 481 iput(qs->longfile); 482 iput(qs->inodes); 483 kfree(qs); 484 sb->s_fs_info = NULL; 485 return; 486 } 487 488 static sector_t qnx6_bmap(struct address_space *mapping, sector_t block) 489 { 490 return generic_block_bmap(mapping, block, qnx6_get_block); 491 } 492 static const struct address_space_operations qnx6_aops = { 493 .read_folio = qnx6_read_folio, 494 .readahead = qnx6_readahead, 495 .bmap = qnx6_bmap 496 }; 497 498 static struct inode *qnx6_private_inode(struct super_block *s, 499 struct qnx6_root_node *p) 500 { 501 struct inode *inode = new_inode(s); 502 if (inode) { 503 struct qnx6_inode_info *ei = QNX6_I(inode); 504 struct qnx6_sb_info *sbi = QNX6_SB(s); 505 inode->i_size = fs64_to_cpu(sbi, p->size); 506 memcpy(ei->di_block_ptr, p->ptr, sizeof(p->ptr)); 507 ei->di_filelevels = p->levels; 508 inode->i_mode = S_IFREG | S_IRUSR; /* probably wrong */ 509 inode->i_mapping->a_ops = &qnx6_aops; 510 } 511 return inode; 512 } 513 514 struct inode *qnx6_iget(struct super_block *sb, unsigned ino) 515 { 516 struct qnx6_sb_info *sbi = QNX6_SB(sb); 517 struct qnx6_inode_entry *raw_inode; 518 struct inode *inode; 519 struct qnx6_inode_info *ei; 520 struct address_space *mapping; 521 struct page *page; 522 u32 n, offs; 523 524 inode = iget_locked(sb, ino); 525 if (!inode) 526 return ERR_PTR(-ENOMEM); 527 if (!(inode->i_state & I_NEW)) 528 return inode; 529 530 ei = QNX6_I(inode); 531 532 inode->i_mode = 0; 533 534 if (ino == 0) { 535 pr_err("bad inode number on dev %s: %u is out of range\n", 536 sb->s_id, ino); 537 iget_failed(inode); 538 return ERR_PTR(-EIO); 539 } 540 n = (ino - 1) >> (PAGE_SHIFT - QNX6_INODE_SIZE_BITS); 541 offs = (ino - 1) & (~PAGE_MASK >> QNX6_INODE_SIZE_BITS); 542 mapping = sbi->inodes->i_mapping; 543 page = read_mapping_page(mapping, n, NULL); 544 if (IS_ERR(page)) { 545 pr_err("major problem: unable to read inode from dev %s\n", 546 sb->s_id); 547 iget_failed(inode); 548 return ERR_CAST(page); 549 } 550 kmap(page); 551 raw_inode = ((struct qnx6_inode_entry *)page_address(page)) + offs; 552 553 inode->i_mode = fs16_to_cpu(sbi, raw_inode->di_mode); 554 i_uid_write(inode, (uid_t)fs32_to_cpu(sbi, raw_inode->di_uid)); 555 i_gid_write(inode, (gid_t)fs32_to_cpu(sbi, raw_inode->di_gid)); 556 inode->i_size = fs64_to_cpu(sbi, raw_inode->di_size); 557 inode_set_mtime(inode, fs32_to_cpu(sbi, raw_inode->di_mtime), 0); 558 inode_set_atime(inode, fs32_to_cpu(sbi, raw_inode->di_atime), 0); 559 inode_set_ctime(inode, fs32_to_cpu(sbi, raw_inode->di_ctime), 0); 560 561 /* calc blocks based on 512 byte blocksize */ 562 inode->i_blocks = (inode->i_size + 511) >> 9; 563 564 memcpy(&ei->di_block_ptr, &raw_inode->di_block_ptr, 565 sizeof(raw_inode->di_block_ptr)); 566 ei->di_filelevels = raw_inode->di_filelevels; 567 568 if (S_ISREG(inode->i_mode)) { 569 inode->i_fop = &generic_ro_fops; 570 inode->i_mapping->a_ops = &qnx6_aops; 571 } else if (S_ISDIR(inode->i_mode)) { 572 inode->i_op = &qnx6_dir_inode_operations; 573 inode->i_fop = &qnx6_dir_operations; 574 inode->i_mapping->a_ops = &qnx6_aops; 575 } else if (S_ISLNK(inode->i_mode)) { 576 inode->i_op = &page_symlink_inode_operations; 577 inode_nohighmem(inode); 578 inode->i_mapping->a_ops = &qnx6_aops; 579 } else 580 init_special_inode(inode, inode->i_mode, 0); 581 qnx6_put_page(page); 582 unlock_new_inode(inode); 583 return inode; 584 } 585 586 static struct kmem_cache *qnx6_inode_cachep; 587 588 static struct inode *qnx6_alloc_inode(struct super_block *sb) 589 { 590 struct qnx6_inode_info *ei; 591 ei = alloc_inode_sb(sb, qnx6_inode_cachep, GFP_KERNEL); 592 if (!ei) 593 return NULL; 594 return &ei->vfs_inode; 595 } 596 597 static void qnx6_free_inode(struct inode *inode) 598 { 599 kmem_cache_free(qnx6_inode_cachep, QNX6_I(inode)); 600 } 601 602 static void init_once(void *foo) 603 { 604 struct qnx6_inode_info *ei = (struct qnx6_inode_info *) foo; 605 606 inode_init_once(&ei->vfs_inode); 607 } 608 609 static int init_inodecache(void) 610 { 611 qnx6_inode_cachep = kmem_cache_create("qnx6_inode_cache", 612 sizeof(struct qnx6_inode_info), 613 0, (SLAB_RECLAIM_ACCOUNT| 614 SLAB_ACCOUNT), 615 init_once); 616 if (!qnx6_inode_cachep) 617 return -ENOMEM; 618 return 0; 619 } 620 621 static void destroy_inodecache(void) 622 { 623 /* 624 * Make sure all delayed rcu free inodes are flushed before we 625 * destroy cache. 626 */ 627 rcu_barrier(); 628 kmem_cache_destroy(qnx6_inode_cachep); 629 } 630 631 static int qnx6_get_tree(struct fs_context *fc) 632 { 633 return get_tree_bdev(fc, qnx6_fill_super); 634 } 635 636 static void qnx6_free_fc(struct fs_context *fc) 637 { 638 kfree(fc->fs_private); 639 } 640 641 static const struct fs_context_operations qnx6_context_ops = { 642 .parse_param = qnx6_parse_param, 643 .get_tree = qnx6_get_tree, 644 .reconfigure = qnx6_reconfigure, 645 .free = qnx6_free_fc, 646 }; 647 648 static int qnx6_init_fs_context(struct fs_context *fc) 649 { 650 struct qnx6_context *ctx; 651 652 ctx = kzalloc(sizeof(struct qnx6_context), GFP_KERNEL); 653 if (!ctx) 654 return -ENOMEM; 655 fc->ops = &qnx6_context_ops; 656 fc->fs_private = ctx; 657 658 return 0; 659 } 660 661 static struct file_system_type qnx6_fs_type = { 662 .owner = THIS_MODULE, 663 .name = "qnx6", 664 .kill_sb = kill_block_super, 665 .fs_flags = FS_REQUIRES_DEV, 666 .init_fs_context = qnx6_init_fs_context, 667 .parameters = qnx6_param_spec, 668 }; 669 MODULE_ALIAS_FS("qnx6"); 670 671 static int __init init_qnx6_fs(void) 672 { 673 int err; 674 675 err = init_inodecache(); 676 if (err) 677 return err; 678 679 err = register_filesystem(&qnx6_fs_type); 680 if (err) { 681 destroy_inodecache(); 682 return err; 683 } 684 685 pr_info("QNX6 filesystem 1.0.0 registered.\n"); 686 return 0; 687 } 688 689 static void __exit exit_qnx6_fs(void) 690 { 691 unregister_filesystem(&qnx6_fs_type); 692 destroy_inodecache(); 693 } 694 695 module_init(init_qnx6_fs) 696 module_exit(exit_qnx6_fs) 697 MODULE_DESCRIPTION("QNX6 file system"); 698 MODULE_LICENSE("GPL"); 699
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.