| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * fs/bfs/inode.c |
|---|
| 3 | 4 | * BFS superblock and inode operations. |
|---|
| 4 | | - * Copyright (C) 1999-2006 Tigran Aivazian <aivazian.tigran@gmail.com> |
|---|
| 5 | + * Copyright (C) 1999-2018 Tigran Aivazian <aivazian.tigran@gmail.com> |
|---|
| 5 | 6 | * From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds. |
|---|
| 6 | | - * |
|---|
| 7 | | - * Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005. |
|---|
| 7 | + * Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005. |
|---|
| 8 | 8 | */ |
|---|
| 9 | 9 | |
|---|
| 10 | 10 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 22 | 22 | MODULE_AUTHOR("Tigran Aivazian <aivazian.tigran@gmail.com>"); |
|---|
| 23 | 23 | MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux"); |
|---|
| 24 | 24 | MODULE_LICENSE("GPL"); |
|---|
| 25 | +MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY); |
|---|
| 25 | 26 | |
|---|
| 26 | 27 | #undef DEBUG |
|---|
| 27 | 28 | |
|---|
| .. | .. |
|---|
| 118 | 119 | { |
|---|
| 119 | 120 | struct bfs_sb_info *info = BFS_SB(inode->i_sb); |
|---|
| 120 | 121 | unsigned int ino = (u16)inode->i_ino; |
|---|
| 121 | | - unsigned long i_sblock; |
|---|
| 122 | + unsigned long i_sblock; |
|---|
| 122 | 123 | struct bfs_inode *di; |
|---|
| 123 | 124 | struct buffer_head *bh; |
|---|
| 124 | 125 | int err = 0; |
|---|
| 125 | 126 | |
|---|
| 126 | | - dprintf("ino=%08x\n", ino); |
|---|
| 127 | + dprintf("ino=%08x\n", ino); |
|---|
| 127 | 128 | |
|---|
| 128 | 129 | di = find_inode(inode->i_sb, ino, &bh); |
|---|
| 129 | 130 | if (IS_ERR(di)) |
|---|
| .. | .. |
|---|
| 144 | 145 | di->i_atime = cpu_to_le32(inode->i_atime.tv_sec); |
|---|
| 145 | 146 | di->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); |
|---|
| 146 | 147 | di->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec); |
|---|
| 147 | | - i_sblock = BFS_I(inode)->i_sblock; |
|---|
| 148 | + i_sblock = BFS_I(inode)->i_sblock; |
|---|
| 148 | 149 | di->i_sblock = cpu_to_le32(i_sblock); |
|---|
| 149 | 150 | di->i_eblock = cpu_to_le32(BFS_I(inode)->i_eblock); |
|---|
| 150 | 151 | di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1); |
|---|
| .. | .. |
|---|
| 188 | 189 | mark_buffer_dirty(bh); |
|---|
| 189 | 190 | brelse(bh); |
|---|
| 190 | 191 | |
|---|
| 191 | | - if (bi->i_dsk_ino) { |
|---|
| 192 | + if (bi->i_dsk_ino) { |
|---|
| 192 | 193 | if (bi->i_sblock) |
|---|
| 193 | 194 | info->si_freeb += bi->i_eblock + 1 - bi->i_sblock; |
|---|
| 194 | 195 | info->si_freei++; |
|---|
| 195 | 196 | clear_bit(ino, info->si_imap); |
|---|
| 196 | | - bfs_dump_imap("delete_inode", s); |
|---|
| 197 | | - } |
|---|
| 197 | + bfs_dump_imap("evict_inode", s); |
|---|
| 198 | + } |
|---|
| 198 | 199 | |
|---|
| 199 | 200 | /* |
|---|
| 200 | 201 | * If this was the last file, make the previous block |
|---|
| .. | .. |
|---|
| 214 | 215 | return; |
|---|
| 215 | 216 | |
|---|
| 216 | 217 | mutex_destroy(&info->bfs_lock); |
|---|
| 217 | | - kfree(info->si_imap); |
|---|
| 218 | 218 | kfree(info); |
|---|
| 219 | 219 | s->s_fs_info = NULL; |
|---|
| 220 | 220 | } |
|---|
| .. | .. |
|---|
| 230 | 230 | buf->f_bfree = buf->f_bavail = info->si_freeb; |
|---|
| 231 | 231 | buf->f_files = info->si_lasti + 1 - BFS_ROOT_INO; |
|---|
| 232 | 232 | buf->f_ffree = info->si_freei; |
|---|
| 233 | | - buf->f_fsid.val[0] = (u32)id; |
|---|
| 234 | | - buf->f_fsid.val[1] = (u32)(id >> 32); |
|---|
| 233 | + buf->f_fsid = u64_to_fsid(id); |
|---|
| 235 | 234 | buf->f_namelen = BFS_NAMELEN; |
|---|
| 236 | 235 | return 0; |
|---|
| 237 | 236 | } |
|---|
| .. | .. |
|---|
| 247 | 246 | return &bi->vfs_inode; |
|---|
| 248 | 247 | } |
|---|
| 249 | 248 | |
|---|
| 250 | | -static void bfs_i_callback(struct rcu_head *head) |
|---|
| 249 | +static void bfs_free_inode(struct inode *inode) |
|---|
| 251 | 250 | { |
|---|
| 252 | | - struct inode *inode = container_of(head, struct inode, i_rcu); |
|---|
| 253 | 251 | kmem_cache_free(bfs_inode_cachep, BFS_I(inode)); |
|---|
| 254 | | -} |
|---|
| 255 | | - |
|---|
| 256 | | -static void bfs_destroy_inode(struct inode *inode) |
|---|
| 257 | | -{ |
|---|
| 258 | | - call_rcu(&inode->i_rcu, bfs_i_callback); |
|---|
| 259 | 252 | } |
|---|
| 260 | 253 | |
|---|
| 261 | 254 | static void init_once(void *foo) |
|---|
| .. | .. |
|---|
| 289 | 282 | |
|---|
| 290 | 283 | static const struct super_operations bfs_sops = { |
|---|
| 291 | 284 | .alloc_inode = bfs_alloc_inode, |
|---|
| 292 | | - .destroy_inode = bfs_destroy_inode, |
|---|
| 285 | + .free_inode = bfs_free_inode, |
|---|
| 293 | 286 | .write_inode = bfs_write_inode, |
|---|
| 294 | 287 | .evict_inode = bfs_evict_inode, |
|---|
| 295 | 288 | .put_super = bfs_put_super, |
|---|
| .. | .. |
|---|
| 311 | 304 | else |
|---|
| 312 | 305 | strcat(tmpbuf, "0"); |
|---|
| 313 | 306 | } |
|---|
| 314 | | - printf("BFS-fs: %s: lasti=%08lx <%s>\n", |
|---|
| 315 | | - prefix, BFS_SB(s)->si_lasti, tmpbuf); |
|---|
| 307 | + printf("%s: lasti=%08lx <%s>\n", prefix, BFS_SB(s)->si_lasti, tmpbuf); |
|---|
| 316 | 308 | free_page((unsigned long)tmpbuf); |
|---|
| 317 | 309 | #endif |
|---|
| 318 | 310 | } |
|---|
| .. | .. |
|---|
| 322 | 314 | struct buffer_head *bh, *sbh; |
|---|
| 323 | 315 | struct bfs_super_block *bfs_sb; |
|---|
| 324 | 316 | struct inode *inode; |
|---|
| 325 | | - unsigned i, imap_len; |
|---|
| 317 | + unsigned i; |
|---|
| 326 | 318 | struct bfs_sb_info *info; |
|---|
| 327 | 319 | int ret = -EINVAL; |
|---|
| 328 | 320 | unsigned long i_sblock, i_eblock, i_eoff, s_size; |
|---|
| .. | .. |
|---|
| 332 | 324 | return -ENOMEM; |
|---|
| 333 | 325 | mutex_init(&info->bfs_lock); |
|---|
| 334 | 326 | s->s_fs_info = info; |
|---|
| 327 | + s->s_time_min = 0; |
|---|
| 328 | + s->s_time_max = U32_MAX; |
|---|
| 335 | 329 | |
|---|
| 336 | 330 | sb_set_blocksize(s, BFS_BSIZE); |
|---|
| 337 | 331 | |
|---|
| .. | .. |
|---|
| 341 | 335 | bfs_sb = (struct bfs_super_block *)sbh->b_data; |
|---|
| 342 | 336 | if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) { |
|---|
| 343 | 337 | if (!silent) |
|---|
| 344 | | - printf("No BFS filesystem on %s (magic=%08x)\n", |
|---|
| 345 | | - s->s_id, le32_to_cpu(bfs_sb->s_magic)); |
|---|
| 338 | + printf("No BFS filesystem on %s (magic=%08x)\n", s->s_id, le32_to_cpu(bfs_sb->s_magic)); |
|---|
| 346 | 339 | goto out1; |
|---|
| 347 | 340 | } |
|---|
| 348 | 341 | if (BFS_UNCLEAN(bfs_sb, s) && !silent) |
|---|
| .. | .. |
|---|
| 351 | 344 | s->s_magic = BFS_MAGIC; |
|---|
| 352 | 345 | |
|---|
| 353 | 346 | if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end) || |
|---|
| 354 | | - le32_to_cpu(bfs_sb->s_start) < BFS_BSIZE) { |
|---|
| 355 | | - printf("Superblock is corrupted\n"); |
|---|
| 347 | + le32_to_cpu(bfs_sb->s_start) < sizeof(struct bfs_super_block) + sizeof(struct bfs_dirent)) { |
|---|
| 348 | + printf("Superblock is corrupted on %s\n", s->s_id); |
|---|
| 356 | 349 | goto out1; |
|---|
| 357 | 350 | } |
|---|
| 358 | 351 | |
|---|
| 359 | | - info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / |
|---|
| 360 | | - sizeof(struct bfs_inode) |
|---|
| 361 | | - + BFS_ROOT_INO - 1; |
|---|
| 362 | | - imap_len = (info->si_lasti / 8) + 1; |
|---|
| 363 | | - info->si_imap = kzalloc(imap_len, GFP_KERNEL | __GFP_NOWARN); |
|---|
| 364 | | - if (!info->si_imap) { |
|---|
| 365 | | - printf("Cannot allocate %u bytes\n", imap_len); |
|---|
| 352 | + info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / sizeof(struct bfs_inode) + BFS_ROOT_INO - 1; |
|---|
| 353 | + if (info->si_lasti == BFS_MAX_LASTI) |
|---|
| 354 | + printf("NOTE: filesystem %s was created with 512 inodes, the real maximum is 511, mounting anyway\n", s->s_id); |
|---|
| 355 | + else if (info->si_lasti > BFS_MAX_LASTI) { |
|---|
| 356 | + printf("Impossible last inode number %lu > %d on %s\n", info->si_lasti, BFS_MAX_LASTI, s->s_id); |
|---|
| 366 | 357 | goto out1; |
|---|
| 367 | 358 | } |
|---|
| 368 | 359 | for (i = 0; i < BFS_ROOT_INO; i++) |
|---|
| .. | .. |
|---|
| 372 | 363 | inode = bfs_iget(s, BFS_ROOT_INO); |
|---|
| 373 | 364 | if (IS_ERR(inode)) { |
|---|
| 374 | 365 | ret = PTR_ERR(inode); |
|---|
| 375 | | - goto out2; |
|---|
| 366 | + goto out1; |
|---|
| 376 | 367 | } |
|---|
| 377 | 368 | s->s_root = d_make_root(inode); |
|---|
| 378 | 369 | if (!s->s_root) { |
|---|
| 379 | 370 | ret = -ENOMEM; |
|---|
| 380 | | - goto out2; |
|---|
| 371 | + goto out1; |
|---|
| 381 | 372 | } |
|---|
| 382 | 373 | |
|---|
| 383 | 374 | info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS; |
|---|
| 384 | | - info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 |
|---|
| 385 | | - - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS; |
|---|
| 375 | + info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS; |
|---|
| 386 | 376 | info->si_freei = 0; |
|---|
| 387 | 377 | info->si_lf_eblk = 0; |
|---|
| 388 | 378 | |
|---|
| 389 | 379 | /* can we read the last block? */ |
|---|
| 390 | 380 | bh = sb_bread(s, info->si_blocks - 1); |
|---|
| 391 | 381 | if (!bh) { |
|---|
| 392 | | - printf("Last block not available: %lu\n", info->si_blocks - 1); |
|---|
| 382 | + printf("Last block not available on %s: %lu\n", s->s_id, info->si_blocks - 1); |
|---|
| 393 | 383 | ret = -EIO; |
|---|
| 394 | | - goto out3; |
|---|
| 384 | + goto out2; |
|---|
| 395 | 385 | } |
|---|
| 396 | 386 | brelse(bh); |
|---|
| 397 | 387 | |
|---|
| .. | .. |
|---|
| 425 | 415 | (i_eoff != le32_to_cpu(-1) && i_eoff > s_size) || |
|---|
| 426 | 416 | i_sblock * BFS_BSIZE > i_eoff) { |
|---|
| 427 | 417 | |
|---|
| 428 | | - printf("Inode 0x%08x corrupted\n", i); |
|---|
| 418 | + printf("Inode 0x%08x corrupted on %s\n", i, s->s_id); |
|---|
| 429 | 419 | |
|---|
| 430 | 420 | brelse(bh); |
|---|
| 431 | 421 | ret = -EIO; |
|---|
| 432 | | - goto out3; |
|---|
| 422 | + goto out2; |
|---|
| 433 | 423 | } |
|---|
| 434 | 424 | |
|---|
| 435 | 425 | if (!di->i_ino) { |
|---|
| .. | .. |
|---|
| 445 | 435 | } |
|---|
| 446 | 436 | brelse(bh); |
|---|
| 447 | 437 | brelse(sbh); |
|---|
| 448 | | - bfs_dump_imap("read_super", s); |
|---|
| 438 | + bfs_dump_imap("fill_super", s); |
|---|
| 449 | 439 | return 0; |
|---|
| 450 | 440 | |
|---|
| 451 | | -out3: |
|---|
| 441 | +out2: |
|---|
| 452 | 442 | dput(s->s_root); |
|---|
| 453 | 443 | s->s_root = NULL; |
|---|
| 454 | | -out2: |
|---|
| 455 | | - kfree(info->si_imap); |
|---|
| 456 | 444 | out1: |
|---|
| 457 | 445 | brelse(sbh); |
|---|
| 458 | 446 | out: |
|---|
| .. | .. |
|---|
| 482 | 470 | int err = init_inodecache(); |
|---|
| 483 | 471 | if (err) |
|---|
| 484 | 472 | goto out1; |
|---|
| 485 | | - err = register_filesystem(&bfs_fs_type); |
|---|
| 473 | + err = register_filesystem(&bfs_fs_type); |
|---|
| 486 | 474 | if (err) |
|---|
| 487 | 475 | goto out; |
|---|
| 488 | 476 | return 0; |
|---|