18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/fs/ufs/super.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1998 68c2ecf20Sopenharmony_ci * Daniel Pirkl <daniel.pirkl@email.cz> 78c2ecf20Sopenharmony_ci * Charles University, Faculty of Mathematics and Physics 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci/* Derived from 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * linux/fs/ext2/super.c 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Copyright (C) 1992, 1993, 1994, 1995 158c2ecf20Sopenharmony_ci * Remy Card (card@masi.ibp.fr) 168c2ecf20Sopenharmony_ci * Laboratoire MASI - Institut Blaise Pascal 178c2ecf20Sopenharmony_ci * Universite Pierre et Marie Curie (Paris VI) 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * from 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * linux/fs/minix/inode.c 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * Big-endian to little-endian byte-swapping/bitmaps by 268c2ecf20Sopenharmony_ci * David S. Miller (davem@caip.rutgers.edu), 1995 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* 308c2ecf20Sopenharmony_ci * Inspired by 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * linux/fs/ufs/super.c 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Copyright (C) 1996 358c2ecf20Sopenharmony_ci * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) 368c2ecf20Sopenharmony_ci * Laboratory for Computer Science Research Computing Facility 378c2ecf20Sopenharmony_ci * Rutgers, The State University of New Jersey 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * Kernel module support added on 96/04/26 by 428c2ecf20Sopenharmony_ci * Stefan Reinauer <stepan@home.culture.mipt.ru> 438c2ecf20Sopenharmony_ci * 448c2ecf20Sopenharmony_ci * Module usage counts added on 96/04/29 by 458c2ecf20Sopenharmony_ci * Gertjan van Wingerde <gwingerde@gmail.com> 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * Clean swab support on 19970406 by 488c2ecf20Sopenharmony_ci * Francois-Rene Rideau <fare@tunes.org> 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * 4.4BSD (FreeBSD) support added on February 1st 1998 by 518c2ecf20Sopenharmony_ci * Niels Kristian Bech Jensen <nkbj@image.dk> partially based 528c2ecf20Sopenharmony_ci * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. 538c2ecf20Sopenharmony_ci * 548c2ecf20Sopenharmony_ci * NeXTstep support added on February 5th 1998 by 558c2ecf20Sopenharmony_ci * Niels Kristian Bech Jensen <nkbj@image.dk>. 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * write support Daniel Pirkl <daniel.pirkl@email.cz> 1998 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * HP/UX hfs filesystem support added by 608c2ecf20Sopenharmony_ci * Martin K. Petersen <mkp@mkp.net>, August 1999 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * UFS2 (of FreeBSD 5.x) support added by 638c2ecf20Sopenharmony_ci * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004 648c2ecf20Sopenharmony_ci * 658c2ecf20Sopenharmony_ci * UFS2 write support added by 668c2ecf20Sopenharmony_ci * Evgeniy Dushistov <dushistov@mail.ru>, 2007 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#include <linux/exportfs.h> 708c2ecf20Sopenharmony_ci#include <linux/module.h> 718c2ecf20Sopenharmony_ci#include <linux/bitops.h> 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#include <stdarg.h> 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#include <linux/errno.h> 788c2ecf20Sopenharmony_ci#include <linux/fs.h> 798c2ecf20Sopenharmony_ci#include <linux/slab.h> 808c2ecf20Sopenharmony_ci#include <linux/time.h> 818c2ecf20Sopenharmony_ci#include <linux/stat.h> 828c2ecf20Sopenharmony_ci#include <linux/string.h> 838c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 848c2ecf20Sopenharmony_ci#include <linux/backing-dev.h> 858c2ecf20Sopenharmony_ci#include <linux/init.h> 868c2ecf20Sopenharmony_ci#include <linux/parser.h> 878c2ecf20Sopenharmony_ci#include <linux/buffer_head.h> 888c2ecf20Sopenharmony_ci#include <linux/vfs.h> 898c2ecf20Sopenharmony_ci#include <linux/log2.h> 908c2ecf20Sopenharmony_ci#include <linux/mount.h> 918c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 928c2ecf20Sopenharmony_ci#include <linux/iversion.h> 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci#include "ufs_fs.h" 958c2ecf20Sopenharmony_ci#include "ufs.h" 968c2ecf20Sopenharmony_ci#include "swab.h" 978c2ecf20Sopenharmony_ci#include "util.h" 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 1028c2ecf20Sopenharmony_ci struct inode *inode; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (ino < UFS_ROOTINO || ino > (u64)uspi->s_ncg * uspi->s_ipg) 1058c2ecf20Sopenharmony_ci return ERR_PTR(-ESTALE); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci inode = ufs_iget(sb, ino); 1088c2ecf20Sopenharmony_ci if (IS_ERR(inode)) 1098c2ecf20Sopenharmony_ci return ERR_CAST(inode); 1108c2ecf20Sopenharmony_ci if (generation && inode->i_generation != generation) { 1118c2ecf20Sopenharmony_ci iput(inode); 1128c2ecf20Sopenharmony_ci return ERR_PTR(-ESTALE); 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci return inode; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic struct dentry *ufs_fh_to_dentry(struct super_block *sb, struct fid *fid, 1188c2ecf20Sopenharmony_ci int fh_len, int fh_type) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci return generic_fh_to_dentry(sb, fid, fh_len, fh_type, ufs_nfs_get_inode); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic struct dentry *ufs_fh_to_parent(struct super_block *sb, struct fid *fid, 1248c2ecf20Sopenharmony_ci int fh_len, int fh_type) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci return generic_fh_to_parent(sb, fid, fh_len, fh_type, ufs_nfs_get_inode); 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic struct dentry *ufs_get_parent(struct dentry *child) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct qstr dot_dot = QSTR_INIT("..", 2); 1328c2ecf20Sopenharmony_ci ino_t ino; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci ino = ufs_inode_by_name(d_inode(child), &dot_dot); 1358c2ecf20Sopenharmony_ci if (!ino) 1368c2ecf20Sopenharmony_ci return ERR_PTR(-ENOENT); 1378c2ecf20Sopenharmony_ci return d_obtain_alias(ufs_iget(child->d_sb, ino)); 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic const struct export_operations ufs_export_ops = { 1418c2ecf20Sopenharmony_ci .fh_to_dentry = ufs_fh_to_dentry, 1428c2ecf20Sopenharmony_ci .fh_to_parent = ufs_fh_to_parent, 1438c2ecf20Sopenharmony_ci .get_parent = ufs_get_parent, 1448c2ecf20Sopenharmony_ci}; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci#ifdef CONFIG_UFS_DEBUG 1478c2ecf20Sopenharmony_ci/* 1488c2ecf20Sopenharmony_ci * Print contents of ufs_super_block, useful for debugging 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_cistatic void ufs_print_super_stuff(struct super_block *sb, 1518c2ecf20Sopenharmony_ci struct ufs_super_block_first *usb1, 1528c2ecf20Sopenharmony_ci struct ufs_super_block_second *usb2, 1538c2ecf20Sopenharmony_ci struct ufs_super_block_third *usb3) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci u32 magic = fs32_to_cpu(sb, usb3->fs_magic); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci pr_debug("ufs_print_super_stuff\n"); 1588c2ecf20Sopenharmony_ci pr_debug(" magic: 0x%x\n", magic); 1598c2ecf20Sopenharmony_ci if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) { 1608c2ecf20Sopenharmony_ci pr_debug(" fs_size: %llu\n", (unsigned long long) 1618c2ecf20Sopenharmony_ci fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size)); 1628c2ecf20Sopenharmony_ci pr_debug(" fs_dsize: %llu\n", (unsigned long long) 1638c2ecf20Sopenharmony_ci fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize)); 1648c2ecf20Sopenharmony_ci pr_debug(" bsize: %u\n", 1658c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb1->fs_bsize)); 1668c2ecf20Sopenharmony_ci pr_debug(" fsize: %u\n", 1678c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb1->fs_fsize)); 1688c2ecf20Sopenharmony_ci pr_debug(" fs_volname: %s\n", usb2->fs_un.fs_u2.fs_volname); 1698c2ecf20Sopenharmony_ci pr_debug(" fs_sblockloc: %llu\n", (unsigned long long) 1708c2ecf20Sopenharmony_ci fs64_to_cpu(sb, usb2->fs_un.fs_u2.fs_sblockloc)); 1718c2ecf20Sopenharmony_ci pr_debug(" cs_ndir(No of dirs): %llu\n", (unsigned long long) 1728c2ecf20Sopenharmony_ci fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir)); 1738c2ecf20Sopenharmony_ci pr_debug(" cs_nbfree(No of free blocks): %llu\n", 1748c2ecf20Sopenharmony_ci (unsigned long long) 1758c2ecf20Sopenharmony_ci fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)); 1768c2ecf20Sopenharmony_ci pr_info(" cs_nifree(Num of free inodes): %llu\n", 1778c2ecf20Sopenharmony_ci (unsigned long long) 1788c2ecf20Sopenharmony_ci fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree)); 1798c2ecf20Sopenharmony_ci pr_info(" cs_nffree(Num of free frags): %llu\n", 1808c2ecf20Sopenharmony_ci (unsigned long long) 1818c2ecf20Sopenharmony_ci fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree)); 1828c2ecf20Sopenharmony_ci pr_info(" fs_maxsymlinklen: %u\n", 1838c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen)); 1848c2ecf20Sopenharmony_ci } else { 1858c2ecf20Sopenharmony_ci pr_debug(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno)); 1868c2ecf20Sopenharmony_ci pr_debug(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno)); 1878c2ecf20Sopenharmony_ci pr_debug(" iblkno: %u\n", fs32_to_cpu(sb, usb1->fs_iblkno)); 1888c2ecf20Sopenharmony_ci pr_debug(" dblkno: %u\n", fs32_to_cpu(sb, usb1->fs_dblkno)); 1898c2ecf20Sopenharmony_ci pr_debug(" cgoffset: %u\n", 1908c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb1->fs_cgoffset)); 1918c2ecf20Sopenharmony_ci pr_debug(" ~cgmask: 0x%x\n", 1928c2ecf20Sopenharmony_ci ~fs32_to_cpu(sb, usb1->fs_cgmask)); 1938c2ecf20Sopenharmony_ci pr_debug(" size: %u\n", fs32_to_cpu(sb, usb1->fs_size)); 1948c2ecf20Sopenharmony_ci pr_debug(" dsize: %u\n", fs32_to_cpu(sb, usb1->fs_dsize)); 1958c2ecf20Sopenharmony_ci pr_debug(" ncg: %u\n", fs32_to_cpu(sb, usb1->fs_ncg)); 1968c2ecf20Sopenharmony_ci pr_debug(" bsize: %u\n", fs32_to_cpu(sb, usb1->fs_bsize)); 1978c2ecf20Sopenharmony_ci pr_debug(" fsize: %u\n", fs32_to_cpu(sb, usb1->fs_fsize)); 1988c2ecf20Sopenharmony_ci pr_debug(" frag: %u\n", fs32_to_cpu(sb, usb1->fs_frag)); 1998c2ecf20Sopenharmony_ci pr_debug(" fragshift: %u\n", 2008c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb1->fs_fragshift)); 2018c2ecf20Sopenharmony_ci pr_debug(" ~fmask: %u\n", ~fs32_to_cpu(sb, usb1->fs_fmask)); 2028c2ecf20Sopenharmony_ci pr_debug(" fshift: %u\n", fs32_to_cpu(sb, usb1->fs_fshift)); 2038c2ecf20Sopenharmony_ci pr_debug(" sbsize: %u\n", fs32_to_cpu(sb, usb1->fs_sbsize)); 2048c2ecf20Sopenharmony_ci pr_debug(" spc: %u\n", fs32_to_cpu(sb, usb1->fs_spc)); 2058c2ecf20Sopenharmony_ci pr_debug(" cpg: %u\n", fs32_to_cpu(sb, usb1->fs_cpg)); 2068c2ecf20Sopenharmony_ci pr_debug(" ipg: %u\n", fs32_to_cpu(sb, usb1->fs_ipg)); 2078c2ecf20Sopenharmony_ci pr_debug(" fpg: %u\n", fs32_to_cpu(sb, usb1->fs_fpg)); 2088c2ecf20Sopenharmony_ci pr_debug(" csaddr: %u\n", fs32_to_cpu(sb, usb1->fs_csaddr)); 2098c2ecf20Sopenharmony_ci pr_debug(" cssize: %u\n", fs32_to_cpu(sb, usb1->fs_cssize)); 2108c2ecf20Sopenharmony_ci pr_debug(" cgsize: %u\n", fs32_to_cpu(sb, usb1->fs_cgsize)); 2118c2ecf20Sopenharmony_ci pr_debug(" fstodb: %u\n", 2128c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb1->fs_fsbtodb)); 2138c2ecf20Sopenharmony_ci pr_debug(" nrpos: %u\n", fs32_to_cpu(sb, usb3->fs_nrpos)); 2148c2ecf20Sopenharmony_ci pr_debug(" ndir %u\n", 2158c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir)); 2168c2ecf20Sopenharmony_ci pr_debug(" nifree %u\n", 2178c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree)); 2188c2ecf20Sopenharmony_ci pr_debug(" nbfree %u\n", 2198c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)); 2208c2ecf20Sopenharmony_ci pr_debug(" nffree %u\n", 2218c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree)); 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci pr_debug("\n"); 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci/* 2278c2ecf20Sopenharmony_ci * Print contents of ufs_cylinder_group, useful for debugging 2288c2ecf20Sopenharmony_ci */ 2298c2ecf20Sopenharmony_cistatic void ufs_print_cylinder_stuff(struct super_block *sb, 2308c2ecf20Sopenharmony_ci struct ufs_cylinder_group *cg) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci pr_debug("\nufs_print_cylinder_stuff\n"); 2338c2ecf20Sopenharmony_ci pr_debug("size of ucg: %zu\n", sizeof(struct ufs_cylinder_group)); 2348c2ecf20Sopenharmony_ci pr_debug(" magic: %x\n", fs32_to_cpu(sb, cg->cg_magic)); 2358c2ecf20Sopenharmony_ci pr_debug(" time: %u\n", fs32_to_cpu(sb, cg->cg_time)); 2368c2ecf20Sopenharmony_ci pr_debug(" cgx: %u\n", fs32_to_cpu(sb, cg->cg_cgx)); 2378c2ecf20Sopenharmony_ci pr_debug(" ncyl: %u\n", fs16_to_cpu(sb, cg->cg_ncyl)); 2388c2ecf20Sopenharmony_ci pr_debug(" niblk: %u\n", fs16_to_cpu(sb, cg->cg_niblk)); 2398c2ecf20Sopenharmony_ci pr_debug(" ndblk: %u\n", fs32_to_cpu(sb, cg->cg_ndblk)); 2408c2ecf20Sopenharmony_ci pr_debug(" cs_ndir: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_ndir)); 2418c2ecf20Sopenharmony_ci pr_debug(" cs_nbfree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nbfree)); 2428c2ecf20Sopenharmony_ci pr_debug(" cs_nifree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nifree)); 2438c2ecf20Sopenharmony_ci pr_debug(" cs_nffree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nffree)); 2448c2ecf20Sopenharmony_ci pr_debug(" rotor: %u\n", fs32_to_cpu(sb, cg->cg_rotor)); 2458c2ecf20Sopenharmony_ci pr_debug(" frotor: %u\n", fs32_to_cpu(sb, cg->cg_frotor)); 2468c2ecf20Sopenharmony_ci pr_debug(" irotor: %u\n", fs32_to_cpu(sb, cg->cg_irotor)); 2478c2ecf20Sopenharmony_ci pr_debug(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", 2488c2ecf20Sopenharmony_ci fs32_to_cpu(sb, cg->cg_frsum[0]), fs32_to_cpu(sb, cg->cg_frsum[1]), 2498c2ecf20Sopenharmony_ci fs32_to_cpu(sb, cg->cg_frsum[2]), fs32_to_cpu(sb, cg->cg_frsum[3]), 2508c2ecf20Sopenharmony_ci fs32_to_cpu(sb, cg->cg_frsum[4]), fs32_to_cpu(sb, cg->cg_frsum[5]), 2518c2ecf20Sopenharmony_ci fs32_to_cpu(sb, cg->cg_frsum[6]), fs32_to_cpu(sb, cg->cg_frsum[7])); 2528c2ecf20Sopenharmony_ci pr_debug(" btotoff: %u\n", fs32_to_cpu(sb, cg->cg_btotoff)); 2538c2ecf20Sopenharmony_ci pr_debug(" boff: %u\n", fs32_to_cpu(sb, cg->cg_boff)); 2548c2ecf20Sopenharmony_ci pr_debug(" iuseoff: %u\n", fs32_to_cpu(sb, cg->cg_iusedoff)); 2558c2ecf20Sopenharmony_ci pr_debug(" freeoff: %u\n", fs32_to_cpu(sb, cg->cg_freeoff)); 2568c2ecf20Sopenharmony_ci pr_debug(" nextfreeoff: %u\n", fs32_to_cpu(sb, cg->cg_nextfreeoff)); 2578c2ecf20Sopenharmony_ci pr_debug(" clustersumoff %u\n", 2588c2ecf20Sopenharmony_ci fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff)); 2598c2ecf20Sopenharmony_ci pr_debug(" clusteroff %u\n", 2608c2ecf20Sopenharmony_ci fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff)); 2618c2ecf20Sopenharmony_ci pr_debug(" nclusterblks %u\n", 2628c2ecf20Sopenharmony_ci fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks)); 2638c2ecf20Sopenharmony_ci pr_debug("\n"); 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci#else 2668c2ecf20Sopenharmony_ci# define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/ 2678c2ecf20Sopenharmony_ci# define ufs_print_cylinder_stuff(sb, cg) /**/ 2688c2ecf20Sopenharmony_ci#endif /* CONFIG_UFS_DEBUG */ 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic const struct super_operations ufs_super_ops; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_civoid ufs_error (struct super_block * sb, const char * function, 2738c2ecf20Sopenharmony_ci const char * fmt, ...) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci struct ufs_sb_private_info * uspi; 2768c2ecf20Sopenharmony_ci struct ufs_super_block_first * usb1; 2778c2ecf20Sopenharmony_ci struct va_format vaf; 2788c2ecf20Sopenharmony_ci va_list args; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci uspi = UFS_SB(sb)->s_uspi; 2818c2ecf20Sopenharmony_ci usb1 = ubh_get_usb_first(uspi); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) { 2848c2ecf20Sopenharmony_ci usb1->fs_clean = UFS_FSBAD; 2858c2ecf20Sopenharmony_ci ubh_mark_buffer_dirty(USPI_UBH(uspi)); 2868c2ecf20Sopenharmony_ci ufs_mark_sb_dirty(sb); 2878c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci va_start(args, fmt); 2908c2ecf20Sopenharmony_ci vaf.fmt = fmt; 2918c2ecf20Sopenharmony_ci vaf.va = &args; 2928c2ecf20Sopenharmony_ci switch (UFS_SB(sb)->s_mount_opt & UFS_MOUNT_ONERROR) { 2938c2ecf20Sopenharmony_ci case UFS_MOUNT_ONERROR_PANIC: 2948c2ecf20Sopenharmony_ci panic("panic (device %s): %s: %pV\n", 2958c2ecf20Sopenharmony_ci sb->s_id, function, &vaf); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci case UFS_MOUNT_ONERROR_LOCK: 2988c2ecf20Sopenharmony_ci case UFS_MOUNT_ONERROR_UMOUNT: 2998c2ecf20Sopenharmony_ci case UFS_MOUNT_ONERROR_REPAIR: 3008c2ecf20Sopenharmony_ci pr_crit("error (device %s): %s: %pV\n", 3018c2ecf20Sopenharmony_ci sb->s_id, function, &vaf); 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci va_end(args); 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_civoid ufs_panic (struct super_block * sb, const char * function, 3078c2ecf20Sopenharmony_ci const char * fmt, ...) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci struct ufs_sb_private_info * uspi; 3108c2ecf20Sopenharmony_ci struct ufs_super_block_first * usb1; 3118c2ecf20Sopenharmony_ci struct va_format vaf; 3128c2ecf20Sopenharmony_ci va_list args; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci uspi = UFS_SB(sb)->s_uspi; 3158c2ecf20Sopenharmony_ci usb1 = ubh_get_usb_first(uspi); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) { 3188c2ecf20Sopenharmony_ci usb1->fs_clean = UFS_FSBAD; 3198c2ecf20Sopenharmony_ci ubh_mark_buffer_dirty(USPI_UBH(uspi)); 3208c2ecf20Sopenharmony_ci ufs_mark_sb_dirty(sb); 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci va_start(args, fmt); 3238c2ecf20Sopenharmony_ci vaf.fmt = fmt; 3248c2ecf20Sopenharmony_ci vaf.va = &args; 3258c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 3268c2ecf20Sopenharmony_ci pr_crit("panic (device %s): %s: %pV\n", 3278c2ecf20Sopenharmony_ci sb->s_id, function, &vaf); 3288c2ecf20Sopenharmony_ci va_end(args); 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_civoid ufs_warning (struct super_block * sb, const char * function, 3328c2ecf20Sopenharmony_ci const char * fmt, ...) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci struct va_format vaf; 3358c2ecf20Sopenharmony_ci va_list args; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci va_start(args, fmt); 3388c2ecf20Sopenharmony_ci vaf.fmt = fmt; 3398c2ecf20Sopenharmony_ci vaf.va = &args; 3408c2ecf20Sopenharmony_ci pr_warn("(device %s): %s: %pV\n", 3418c2ecf20Sopenharmony_ci sb->s_id, function, &vaf); 3428c2ecf20Sopenharmony_ci va_end(args); 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cienum { 3468c2ecf20Sopenharmony_ci Opt_type_old = UFS_MOUNT_UFSTYPE_OLD, 3478c2ecf20Sopenharmony_ci Opt_type_sunx86 = UFS_MOUNT_UFSTYPE_SUNx86, 3488c2ecf20Sopenharmony_ci Opt_type_sun = UFS_MOUNT_UFSTYPE_SUN, 3498c2ecf20Sopenharmony_ci Opt_type_sunos = UFS_MOUNT_UFSTYPE_SUNOS, 3508c2ecf20Sopenharmony_ci Opt_type_44bsd = UFS_MOUNT_UFSTYPE_44BSD, 3518c2ecf20Sopenharmony_ci Opt_type_ufs2 = UFS_MOUNT_UFSTYPE_UFS2, 3528c2ecf20Sopenharmony_ci Opt_type_hp = UFS_MOUNT_UFSTYPE_HP, 3538c2ecf20Sopenharmony_ci Opt_type_nextstepcd = UFS_MOUNT_UFSTYPE_NEXTSTEP_CD, 3548c2ecf20Sopenharmony_ci Opt_type_nextstep = UFS_MOUNT_UFSTYPE_NEXTSTEP, 3558c2ecf20Sopenharmony_ci Opt_type_openstep = UFS_MOUNT_UFSTYPE_OPENSTEP, 3568c2ecf20Sopenharmony_ci Opt_onerror_panic = UFS_MOUNT_ONERROR_PANIC, 3578c2ecf20Sopenharmony_ci Opt_onerror_lock = UFS_MOUNT_ONERROR_LOCK, 3588c2ecf20Sopenharmony_ci Opt_onerror_umount = UFS_MOUNT_ONERROR_UMOUNT, 3598c2ecf20Sopenharmony_ci Opt_onerror_repair = UFS_MOUNT_ONERROR_REPAIR, 3608c2ecf20Sopenharmony_ci Opt_err 3618c2ecf20Sopenharmony_ci}; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic const match_table_t tokens = { 3648c2ecf20Sopenharmony_ci {Opt_type_old, "ufstype=old"}, 3658c2ecf20Sopenharmony_ci {Opt_type_sunx86, "ufstype=sunx86"}, 3668c2ecf20Sopenharmony_ci {Opt_type_sun, "ufstype=sun"}, 3678c2ecf20Sopenharmony_ci {Opt_type_sunos, "ufstype=sunos"}, 3688c2ecf20Sopenharmony_ci {Opt_type_44bsd, "ufstype=44bsd"}, 3698c2ecf20Sopenharmony_ci {Opt_type_ufs2, "ufstype=ufs2"}, 3708c2ecf20Sopenharmony_ci {Opt_type_ufs2, "ufstype=5xbsd"}, 3718c2ecf20Sopenharmony_ci {Opt_type_hp, "ufstype=hp"}, 3728c2ecf20Sopenharmony_ci {Opt_type_nextstepcd, "ufstype=nextstep-cd"}, 3738c2ecf20Sopenharmony_ci {Opt_type_nextstep, "ufstype=nextstep"}, 3748c2ecf20Sopenharmony_ci {Opt_type_openstep, "ufstype=openstep"}, 3758c2ecf20Sopenharmony_ci/*end of possible ufs types */ 3768c2ecf20Sopenharmony_ci {Opt_onerror_panic, "onerror=panic"}, 3778c2ecf20Sopenharmony_ci {Opt_onerror_lock, "onerror=lock"}, 3788c2ecf20Sopenharmony_ci {Opt_onerror_umount, "onerror=umount"}, 3798c2ecf20Sopenharmony_ci {Opt_onerror_repair, "onerror=repair"}, 3808c2ecf20Sopenharmony_ci {Opt_err, NULL} 3818c2ecf20Sopenharmony_ci}; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic int ufs_parse_options (char * options, unsigned * mount_options) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci char * p; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci UFSD("ENTER\n"); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci if (!options) 3908c2ecf20Sopenharmony_ci return 1; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci while ((p = strsep(&options, ",")) != NULL) { 3938c2ecf20Sopenharmony_ci substring_t args[MAX_OPT_ARGS]; 3948c2ecf20Sopenharmony_ci int token; 3958c2ecf20Sopenharmony_ci if (!*p) 3968c2ecf20Sopenharmony_ci continue; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci token = match_token(p, tokens, args); 3998c2ecf20Sopenharmony_ci switch (token) { 4008c2ecf20Sopenharmony_ci case Opt_type_old: 4018c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, UFSTYPE); 4028c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, UFSTYPE_OLD); 4038c2ecf20Sopenharmony_ci break; 4048c2ecf20Sopenharmony_ci case Opt_type_sunx86: 4058c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, UFSTYPE); 4068c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, UFSTYPE_SUNx86); 4078c2ecf20Sopenharmony_ci break; 4088c2ecf20Sopenharmony_ci case Opt_type_sun: 4098c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, UFSTYPE); 4108c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, UFSTYPE_SUN); 4118c2ecf20Sopenharmony_ci break; 4128c2ecf20Sopenharmony_ci case Opt_type_sunos: 4138c2ecf20Sopenharmony_ci ufs_clear_opt(*mount_options, UFSTYPE); 4148c2ecf20Sopenharmony_ci ufs_set_opt(*mount_options, UFSTYPE_SUNOS); 4158c2ecf20Sopenharmony_ci break; 4168c2ecf20Sopenharmony_ci case Opt_type_44bsd: 4178c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, UFSTYPE); 4188c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, UFSTYPE_44BSD); 4198c2ecf20Sopenharmony_ci break; 4208c2ecf20Sopenharmony_ci case Opt_type_ufs2: 4218c2ecf20Sopenharmony_ci ufs_clear_opt(*mount_options, UFSTYPE); 4228c2ecf20Sopenharmony_ci ufs_set_opt(*mount_options, UFSTYPE_UFS2); 4238c2ecf20Sopenharmony_ci break; 4248c2ecf20Sopenharmony_ci case Opt_type_hp: 4258c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, UFSTYPE); 4268c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, UFSTYPE_HP); 4278c2ecf20Sopenharmony_ci break; 4288c2ecf20Sopenharmony_ci case Opt_type_nextstepcd: 4298c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, UFSTYPE); 4308c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP_CD); 4318c2ecf20Sopenharmony_ci break; 4328c2ecf20Sopenharmony_ci case Opt_type_nextstep: 4338c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, UFSTYPE); 4348c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP); 4358c2ecf20Sopenharmony_ci break; 4368c2ecf20Sopenharmony_ci case Opt_type_openstep: 4378c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, UFSTYPE); 4388c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP); 4398c2ecf20Sopenharmony_ci break; 4408c2ecf20Sopenharmony_ci case Opt_onerror_panic: 4418c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, ONERROR); 4428c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, ONERROR_PANIC); 4438c2ecf20Sopenharmony_ci break; 4448c2ecf20Sopenharmony_ci case Opt_onerror_lock: 4458c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, ONERROR); 4468c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, ONERROR_LOCK); 4478c2ecf20Sopenharmony_ci break; 4488c2ecf20Sopenharmony_ci case Opt_onerror_umount: 4498c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, ONERROR); 4508c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, ONERROR_UMOUNT); 4518c2ecf20Sopenharmony_ci break; 4528c2ecf20Sopenharmony_ci case Opt_onerror_repair: 4538c2ecf20Sopenharmony_ci pr_err("Unable to do repair on error, will lock lock instead\n"); 4548c2ecf20Sopenharmony_ci ufs_clear_opt (*mount_options, ONERROR); 4558c2ecf20Sopenharmony_ci ufs_set_opt (*mount_options, ONERROR_REPAIR); 4568c2ecf20Sopenharmony_ci break; 4578c2ecf20Sopenharmony_ci default: 4588c2ecf20Sopenharmony_ci pr_err("Invalid option: \"%s\" or missing value\n", p); 4598c2ecf20Sopenharmony_ci return 0; 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci return 1; 4638c2ecf20Sopenharmony_ci} 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci/* 4668c2ecf20Sopenharmony_ci * Different types of UFS hold fs_cstotal in different 4678c2ecf20Sopenharmony_ci * places, and use different data structure for it. 4688c2ecf20Sopenharmony_ci * To make things simpler we just copy fs_cstotal to ufs_sb_private_info 4698c2ecf20Sopenharmony_ci */ 4708c2ecf20Sopenharmony_cistatic void ufs_setup_cstotal(struct super_block *sb) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci struct ufs_sb_info *sbi = UFS_SB(sb); 4738c2ecf20Sopenharmony_ci struct ufs_sb_private_info *uspi = sbi->s_uspi; 4748c2ecf20Sopenharmony_ci struct ufs_super_block_first *usb1; 4758c2ecf20Sopenharmony_ci struct ufs_super_block_second *usb2; 4768c2ecf20Sopenharmony_ci struct ufs_super_block_third *usb3; 4778c2ecf20Sopenharmony_ci unsigned mtype = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci UFSD("ENTER, mtype=%u\n", mtype); 4808c2ecf20Sopenharmony_ci usb1 = ubh_get_usb_first(uspi); 4818c2ecf20Sopenharmony_ci usb2 = ubh_get_usb_second(uspi); 4828c2ecf20Sopenharmony_ci usb3 = ubh_get_usb_third(uspi); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && 4858c2ecf20Sopenharmony_ci (usb2->fs_un.fs_u2.fs_maxbsize == usb1->fs_bsize)) || 4868c2ecf20Sopenharmony_ci mtype == UFS_MOUNT_UFSTYPE_UFS2) { 4878c2ecf20Sopenharmony_ci /*we have statistic in different place, then usual*/ 4888c2ecf20Sopenharmony_ci uspi->cs_total.cs_ndir = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir); 4898c2ecf20Sopenharmony_ci uspi->cs_total.cs_nbfree = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree); 4908c2ecf20Sopenharmony_ci uspi->cs_total.cs_nifree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree); 4918c2ecf20Sopenharmony_ci uspi->cs_total.cs_nffree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree); 4928c2ecf20Sopenharmony_ci } else { 4938c2ecf20Sopenharmony_ci uspi->cs_total.cs_ndir = fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir); 4948c2ecf20Sopenharmony_ci uspi->cs_total.cs_nbfree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree); 4958c2ecf20Sopenharmony_ci uspi->cs_total.cs_nifree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree); 4968c2ecf20Sopenharmony_ci uspi->cs_total.cs_nffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree); 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci UFSD("EXIT\n"); 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci/* 5028c2ecf20Sopenharmony_ci * Read on-disk structures associated with cylinder groups 5038c2ecf20Sopenharmony_ci */ 5048c2ecf20Sopenharmony_cistatic int ufs_read_cylinder_structures(struct super_block *sb) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci struct ufs_sb_info *sbi = UFS_SB(sb); 5078c2ecf20Sopenharmony_ci struct ufs_sb_private_info *uspi = sbi->s_uspi; 5088c2ecf20Sopenharmony_ci struct ufs_buffer_head * ubh; 5098c2ecf20Sopenharmony_ci unsigned char * base, * space; 5108c2ecf20Sopenharmony_ci unsigned size, blks, i; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci UFSD("ENTER\n"); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci /* 5158c2ecf20Sopenharmony_ci * Read cs structures from (usually) first data block 5168c2ecf20Sopenharmony_ci * on the device. 5178c2ecf20Sopenharmony_ci */ 5188c2ecf20Sopenharmony_ci size = uspi->s_cssize; 5198c2ecf20Sopenharmony_ci blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; 5208c2ecf20Sopenharmony_ci base = space = kmalloc(size, GFP_NOFS); 5218c2ecf20Sopenharmony_ci if (!base) 5228c2ecf20Sopenharmony_ci goto failed; 5238c2ecf20Sopenharmony_ci sbi->s_csp = (struct ufs_csum *)space; 5248c2ecf20Sopenharmony_ci for (i = 0; i < blks; i += uspi->s_fpb) { 5258c2ecf20Sopenharmony_ci size = uspi->s_bsize; 5268c2ecf20Sopenharmony_ci if (i + uspi->s_fpb > blks) 5278c2ecf20Sopenharmony_ci size = (blks - i) * uspi->s_fsize; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci ubh = ubh_bread(sb, uspi->s_csaddr + i, size); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci if (!ubh) 5328c2ecf20Sopenharmony_ci goto failed; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci ubh_ubhcpymem (space, ubh, size); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci space += size; 5378c2ecf20Sopenharmony_ci ubh_brelse (ubh); 5388c2ecf20Sopenharmony_ci ubh = NULL; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci /* 5428c2ecf20Sopenharmony_ci * Read cylinder group (we read only first fragment from block 5438c2ecf20Sopenharmony_ci * at this time) and prepare internal data structures for cg caching. 5448c2ecf20Sopenharmony_ci */ 5458c2ecf20Sopenharmony_ci sbi->s_ucg = kmalloc_array(uspi->s_ncg, sizeof(struct buffer_head *), 5468c2ecf20Sopenharmony_ci GFP_NOFS); 5478c2ecf20Sopenharmony_ci if (!sbi->s_ucg) 5488c2ecf20Sopenharmony_ci goto failed; 5498c2ecf20Sopenharmony_ci for (i = 0; i < uspi->s_ncg; i++) 5508c2ecf20Sopenharmony_ci sbi->s_ucg[i] = NULL; 5518c2ecf20Sopenharmony_ci for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { 5528c2ecf20Sopenharmony_ci sbi->s_ucpi[i] = NULL; 5538c2ecf20Sopenharmony_ci sbi->s_cgno[i] = UFS_CGNO_EMPTY; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci for (i = 0; i < uspi->s_ncg; i++) { 5568c2ecf20Sopenharmony_ci UFSD("read cg %u\n", i); 5578c2ecf20Sopenharmony_ci if (!(sbi->s_ucg[i] = sb_bread(sb, ufs_cgcmin(i)))) 5588c2ecf20Sopenharmony_ci goto failed; 5598c2ecf20Sopenharmony_ci if (!ufs_cg_chkmagic (sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data)) 5608c2ecf20Sopenharmony_ci goto failed; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data); 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { 5658c2ecf20Sopenharmony_ci if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_NOFS))) 5668c2ecf20Sopenharmony_ci goto failed; 5678c2ecf20Sopenharmony_ci sbi->s_cgno[i] = UFS_CGNO_EMPTY; 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci sbi->s_cg_loaded = 0; 5708c2ecf20Sopenharmony_ci UFSD("EXIT\n"); 5718c2ecf20Sopenharmony_ci return 1; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_cifailed: 5748c2ecf20Sopenharmony_ci kfree (base); 5758c2ecf20Sopenharmony_ci if (sbi->s_ucg) { 5768c2ecf20Sopenharmony_ci for (i = 0; i < uspi->s_ncg; i++) 5778c2ecf20Sopenharmony_ci if (sbi->s_ucg[i]) 5788c2ecf20Sopenharmony_ci brelse (sbi->s_ucg[i]); 5798c2ecf20Sopenharmony_ci kfree (sbi->s_ucg); 5808c2ecf20Sopenharmony_ci for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) 5818c2ecf20Sopenharmony_ci kfree (sbi->s_ucpi[i]); 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci UFSD("EXIT (FAILED)\n"); 5848c2ecf20Sopenharmony_ci return 0; 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci/* 5888c2ecf20Sopenharmony_ci * Sync our internal copy of fs_cstotal with disk 5898c2ecf20Sopenharmony_ci */ 5908c2ecf20Sopenharmony_cistatic void ufs_put_cstotal(struct super_block *sb) 5918c2ecf20Sopenharmony_ci{ 5928c2ecf20Sopenharmony_ci unsigned mtype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE; 5938c2ecf20Sopenharmony_ci struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 5948c2ecf20Sopenharmony_ci struct ufs_super_block_first *usb1; 5958c2ecf20Sopenharmony_ci struct ufs_super_block_second *usb2; 5968c2ecf20Sopenharmony_ci struct ufs_super_block_third *usb3; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci UFSD("ENTER\n"); 5998c2ecf20Sopenharmony_ci usb1 = ubh_get_usb_first(uspi); 6008c2ecf20Sopenharmony_ci usb2 = ubh_get_usb_second(uspi); 6018c2ecf20Sopenharmony_ci usb3 = ubh_get_usb_third(uspi); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci if (mtype == UFS_MOUNT_UFSTYPE_UFS2) { 6048c2ecf20Sopenharmony_ci /*we have statistic in different place, then usual*/ 6058c2ecf20Sopenharmony_ci usb2->fs_un.fs_u2.cs_ndir = 6068c2ecf20Sopenharmony_ci cpu_to_fs64(sb, uspi->cs_total.cs_ndir); 6078c2ecf20Sopenharmony_ci usb2->fs_un.fs_u2.cs_nbfree = 6088c2ecf20Sopenharmony_ci cpu_to_fs64(sb, uspi->cs_total.cs_nbfree); 6098c2ecf20Sopenharmony_ci usb3->fs_un1.fs_u2.cs_nifree = 6108c2ecf20Sopenharmony_ci cpu_to_fs64(sb, uspi->cs_total.cs_nifree); 6118c2ecf20Sopenharmony_ci usb3->fs_un1.fs_u2.cs_nffree = 6128c2ecf20Sopenharmony_ci cpu_to_fs64(sb, uspi->cs_total.cs_nffree); 6138c2ecf20Sopenharmony_ci goto out; 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (mtype == UFS_MOUNT_UFSTYPE_44BSD && 6178c2ecf20Sopenharmony_ci (usb2->fs_un.fs_u2.fs_maxbsize == usb1->fs_bsize)) { 6188c2ecf20Sopenharmony_ci /* store stats in both old and new places */ 6198c2ecf20Sopenharmony_ci usb2->fs_un.fs_u2.cs_ndir = 6208c2ecf20Sopenharmony_ci cpu_to_fs64(sb, uspi->cs_total.cs_ndir); 6218c2ecf20Sopenharmony_ci usb2->fs_un.fs_u2.cs_nbfree = 6228c2ecf20Sopenharmony_ci cpu_to_fs64(sb, uspi->cs_total.cs_nbfree); 6238c2ecf20Sopenharmony_ci usb3->fs_un1.fs_u2.cs_nifree = 6248c2ecf20Sopenharmony_ci cpu_to_fs64(sb, uspi->cs_total.cs_nifree); 6258c2ecf20Sopenharmony_ci usb3->fs_un1.fs_u2.cs_nffree = 6268c2ecf20Sopenharmony_ci cpu_to_fs64(sb, uspi->cs_total.cs_nffree); 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci usb1->fs_cstotal.cs_ndir = cpu_to_fs32(sb, uspi->cs_total.cs_ndir); 6298c2ecf20Sopenharmony_ci usb1->fs_cstotal.cs_nbfree = cpu_to_fs32(sb, uspi->cs_total.cs_nbfree); 6308c2ecf20Sopenharmony_ci usb1->fs_cstotal.cs_nifree = cpu_to_fs32(sb, uspi->cs_total.cs_nifree); 6318c2ecf20Sopenharmony_ci usb1->fs_cstotal.cs_nffree = cpu_to_fs32(sb, uspi->cs_total.cs_nffree); 6328c2ecf20Sopenharmony_ciout: 6338c2ecf20Sopenharmony_ci ubh_mark_buffer_dirty(USPI_UBH(uspi)); 6348c2ecf20Sopenharmony_ci ufs_print_super_stuff(sb, usb1, usb2, usb3); 6358c2ecf20Sopenharmony_ci UFSD("EXIT\n"); 6368c2ecf20Sopenharmony_ci} 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci/** 6398c2ecf20Sopenharmony_ci * ufs_put_super_internal() - put on-disk intrenal structures 6408c2ecf20Sopenharmony_ci * @sb: pointer to super_block structure 6418c2ecf20Sopenharmony_ci * Put on-disk structures associated with cylinder groups 6428c2ecf20Sopenharmony_ci * and write them back to disk, also update cs_total on disk 6438c2ecf20Sopenharmony_ci */ 6448c2ecf20Sopenharmony_cistatic void ufs_put_super_internal(struct super_block *sb) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci struct ufs_sb_info *sbi = UFS_SB(sb); 6478c2ecf20Sopenharmony_ci struct ufs_sb_private_info *uspi = sbi->s_uspi; 6488c2ecf20Sopenharmony_ci struct ufs_buffer_head * ubh; 6498c2ecf20Sopenharmony_ci unsigned char * base, * space; 6508c2ecf20Sopenharmony_ci unsigned blks, size, i; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci UFSD("ENTER\n"); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci ufs_put_cstotal(sb); 6568c2ecf20Sopenharmony_ci size = uspi->s_cssize; 6578c2ecf20Sopenharmony_ci blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; 6588c2ecf20Sopenharmony_ci base = space = (char*) sbi->s_csp; 6598c2ecf20Sopenharmony_ci for (i = 0; i < blks; i += uspi->s_fpb) { 6608c2ecf20Sopenharmony_ci size = uspi->s_bsize; 6618c2ecf20Sopenharmony_ci if (i + uspi->s_fpb > blks) 6628c2ecf20Sopenharmony_ci size = (blks - i) * uspi->s_fsize; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci ubh = ubh_bread(sb, uspi->s_csaddr + i, size); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci ubh_memcpyubh (ubh, space, size); 6678c2ecf20Sopenharmony_ci space += size; 6688c2ecf20Sopenharmony_ci ubh_mark_buffer_uptodate (ubh, 1); 6698c2ecf20Sopenharmony_ci ubh_mark_buffer_dirty (ubh); 6708c2ecf20Sopenharmony_ci ubh_brelse (ubh); 6718c2ecf20Sopenharmony_ci } 6728c2ecf20Sopenharmony_ci for (i = 0; i < sbi->s_cg_loaded; i++) { 6738c2ecf20Sopenharmony_ci ufs_put_cylinder (sb, i); 6748c2ecf20Sopenharmony_ci kfree (sbi->s_ucpi[i]); 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci for (; i < UFS_MAX_GROUP_LOADED; i++) 6778c2ecf20Sopenharmony_ci kfree (sbi->s_ucpi[i]); 6788c2ecf20Sopenharmony_ci for (i = 0; i < uspi->s_ncg; i++) 6798c2ecf20Sopenharmony_ci brelse (sbi->s_ucg[i]); 6808c2ecf20Sopenharmony_ci kfree (sbi->s_ucg); 6818c2ecf20Sopenharmony_ci kfree (base); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci UFSD("EXIT\n"); 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic int ufs_sync_fs(struct super_block *sb, int wait) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci struct ufs_sb_private_info * uspi; 6898c2ecf20Sopenharmony_ci struct ufs_super_block_first * usb1; 6908c2ecf20Sopenharmony_ci struct ufs_super_block_third * usb3; 6918c2ecf20Sopenharmony_ci unsigned flags; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci mutex_lock(&UFS_SB(sb)->s_lock); 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci UFSD("ENTER\n"); 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci flags = UFS_SB(sb)->s_flags; 6988c2ecf20Sopenharmony_ci uspi = UFS_SB(sb)->s_uspi; 6998c2ecf20Sopenharmony_ci usb1 = ubh_get_usb_first(uspi); 7008c2ecf20Sopenharmony_ci usb3 = ubh_get_usb_third(uspi); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci usb1->fs_time = ufs_get_seconds(sb); 7038c2ecf20Sopenharmony_ci if ((flags & UFS_ST_MASK) == UFS_ST_SUN || 7048c2ecf20Sopenharmony_ci (flags & UFS_ST_MASK) == UFS_ST_SUNOS || 7058c2ecf20Sopenharmony_ci (flags & UFS_ST_MASK) == UFS_ST_SUNx86) 7068c2ecf20Sopenharmony_ci ufs_set_fs_state(sb, usb1, usb3, 7078c2ecf20Sopenharmony_ci UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); 7088c2ecf20Sopenharmony_ci ufs_put_cstotal(sb); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci UFSD("EXIT\n"); 7118c2ecf20Sopenharmony_ci mutex_unlock(&UFS_SB(sb)->s_lock); 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci return 0; 7148c2ecf20Sopenharmony_ci} 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cistatic void delayed_sync_fs(struct work_struct *work) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci struct ufs_sb_info *sbi; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci sbi = container_of(work, struct ufs_sb_info, sync_work.work); 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci spin_lock(&sbi->work_lock); 7238c2ecf20Sopenharmony_ci sbi->work_queued = 0; 7248c2ecf20Sopenharmony_ci spin_unlock(&sbi->work_lock); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci ufs_sync_fs(sbi->sb, 1); 7278c2ecf20Sopenharmony_ci} 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_civoid ufs_mark_sb_dirty(struct super_block *sb) 7308c2ecf20Sopenharmony_ci{ 7318c2ecf20Sopenharmony_ci struct ufs_sb_info *sbi = UFS_SB(sb); 7328c2ecf20Sopenharmony_ci unsigned long delay; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci spin_lock(&sbi->work_lock); 7358c2ecf20Sopenharmony_ci if (!sbi->work_queued) { 7368c2ecf20Sopenharmony_ci delay = msecs_to_jiffies(dirty_writeback_interval * 10); 7378c2ecf20Sopenharmony_ci queue_delayed_work(system_long_wq, &sbi->sync_work, delay); 7388c2ecf20Sopenharmony_ci sbi->work_queued = 1; 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci spin_unlock(&sbi->work_lock); 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_cistatic void ufs_put_super(struct super_block *sb) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci struct ufs_sb_info * sbi = UFS_SB(sb); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci UFSD("ENTER\n"); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) 7508c2ecf20Sopenharmony_ci ufs_put_super_internal(sb); 7518c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&sbi->sync_work); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci ubh_brelse_uspi (sbi->s_uspi); 7548c2ecf20Sopenharmony_ci kfree (sbi->s_uspi); 7558c2ecf20Sopenharmony_ci kfree (sbi); 7568c2ecf20Sopenharmony_ci sb->s_fs_info = NULL; 7578c2ecf20Sopenharmony_ci UFSD("EXIT\n"); 7588c2ecf20Sopenharmony_ci return; 7598c2ecf20Sopenharmony_ci} 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_cistatic u64 ufs_max_bytes(struct super_block *sb) 7628c2ecf20Sopenharmony_ci{ 7638c2ecf20Sopenharmony_ci struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 7648c2ecf20Sopenharmony_ci int bits = uspi->s_apbshift; 7658c2ecf20Sopenharmony_ci u64 res; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci if (bits > 21) 7688c2ecf20Sopenharmony_ci res = ~0ULL; 7698c2ecf20Sopenharmony_ci else 7708c2ecf20Sopenharmony_ci res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) + 7718c2ecf20Sopenharmony_ci (1LL << (3*bits)); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift)) 7748c2ecf20Sopenharmony_ci return MAX_LFS_FILESIZE; 7758c2ecf20Sopenharmony_ci return res << uspi->s_bshift; 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic int ufs_fill_super(struct super_block *sb, void *data, int silent) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci struct ufs_sb_info * sbi; 7818c2ecf20Sopenharmony_ci struct ufs_sb_private_info * uspi; 7828c2ecf20Sopenharmony_ci struct ufs_super_block_first * usb1; 7838c2ecf20Sopenharmony_ci struct ufs_super_block_second * usb2; 7848c2ecf20Sopenharmony_ci struct ufs_super_block_third * usb3; 7858c2ecf20Sopenharmony_ci struct ufs_buffer_head * ubh; 7868c2ecf20Sopenharmony_ci struct inode *inode; 7878c2ecf20Sopenharmony_ci unsigned block_size, super_block_size; 7888c2ecf20Sopenharmony_ci unsigned flags; 7898c2ecf20Sopenharmony_ci unsigned super_block_offset; 7908c2ecf20Sopenharmony_ci unsigned maxsymlen; 7918c2ecf20Sopenharmony_ci int ret = -EINVAL; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci uspi = NULL; 7948c2ecf20Sopenharmony_ci ubh = NULL; 7958c2ecf20Sopenharmony_ci flags = 0; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci UFSD("ENTER\n"); 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci#ifndef CONFIG_UFS_FS_WRITE 8008c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) { 8018c2ecf20Sopenharmony_ci pr_err("ufs was compiled with read-only support, can't be mounted as read-write\n"); 8028c2ecf20Sopenharmony_ci return -EROFS; 8038c2ecf20Sopenharmony_ci } 8048c2ecf20Sopenharmony_ci#endif 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci sbi = kzalloc(sizeof(struct ufs_sb_info), GFP_KERNEL); 8078c2ecf20Sopenharmony_ci if (!sbi) 8088c2ecf20Sopenharmony_ci goto failed_nomem; 8098c2ecf20Sopenharmony_ci sb->s_fs_info = sbi; 8108c2ecf20Sopenharmony_ci sbi->sb = sb; 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci UFSD("flag %u\n", (int)(sb_rdonly(sb))); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci mutex_init(&sbi->s_lock); 8158c2ecf20Sopenharmony_ci spin_lock_init(&sbi->work_lock); 8168c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); 8178c2ecf20Sopenharmony_ci /* 8188c2ecf20Sopenharmony_ci * Set default mount options 8198c2ecf20Sopenharmony_ci * Parse mount options 8208c2ecf20Sopenharmony_ci */ 8218c2ecf20Sopenharmony_ci sbi->s_mount_opt = 0; 8228c2ecf20Sopenharmony_ci ufs_set_opt (sbi->s_mount_opt, ONERROR_LOCK); 8238c2ecf20Sopenharmony_ci if (!ufs_parse_options ((char *) data, &sbi->s_mount_opt)) { 8248c2ecf20Sopenharmony_ci pr_err("wrong mount options\n"); 8258c2ecf20Sopenharmony_ci goto failed; 8268c2ecf20Sopenharmony_ci } 8278c2ecf20Sopenharmony_ci if (!(sbi->s_mount_opt & UFS_MOUNT_UFSTYPE)) { 8288c2ecf20Sopenharmony_ci if (!silent) 8298c2ecf20Sopenharmony_ci pr_err("You didn't specify the type of your ufs filesystem\n\n" 8308c2ecf20Sopenharmony_ci "mount -t ufs -o ufstype=" 8318c2ecf20Sopenharmony_ci "sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|nextstep-cd|openstep ...\n\n" 8328c2ecf20Sopenharmony_ci ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, " 8338c2ecf20Sopenharmony_ci "default is ufstype=old\n"); 8348c2ecf20Sopenharmony_ci ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD); 8358c2ecf20Sopenharmony_ci } 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci uspi = kzalloc(sizeof(struct ufs_sb_private_info), GFP_KERNEL); 8388c2ecf20Sopenharmony_ci sbi->s_uspi = uspi; 8398c2ecf20Sopenharmony_ci if (!uspi) 8408c2ecf20Sopenharmony_ci goto failed; 8418c2ecf20Sopenharmony_ci uspi->s_dirblksize = UFS_SECTOR_SIZE; 8428c2ecf20Sopenharmony_ci super_block_offset=UFS_SBLOCK; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci sb->s_maxbytes = MAX_LFS_FILESIZE; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci sb->s_time_gran = NSEC_PER_SEC; 8478c2ecf20Sopenharmony_ci sb->s_time_min = S32_MIN; 8488c2ecf20Sopenharmony_ci sb->s_time_max = S32_MAX; 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { 8518c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_44BSD: 8528c2ecf20Sopenharmony_ci UFSD("ufstype=44bsd\n"); 8538c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 512; 8548c2ecf20Sopenharmony_ci uspi->s_fmask = ~(512 - 1); 8558c2ecf20Sopenharmony_ci uspi->s_fshift = 9; 8568c2ecf20Sopenharmony_ci uspi->s_sbsize = super_block_size = 1536; 8578c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 8588c2ecf20Sopenharmony_ci flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; 8598c2ecf20Sopenharmony_ci break; 8608c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_UFS2: 8618c2ecf20Sopenharmony_ci UFSD("ufstype=ufs2\n"); 8628c2ecf20Sopenharmony_ci super_block_offset=SBLOCK_UFS2; 8638c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 512; 8648c2ecf20Sopenharmony_ci uspi->s_fmask = ~(512 - 1); 8658c2ecf20Sopenharmony_ci uspi->s_fshift = 9; 8668c2ecf20Sopenharmony_ci uspi->s_sbsize = super_block_size = 1536; 8678c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 8688c2ecf20Sopenharmony_ci sb->s_time_gran = 1; 8698c2ecf20Sopenharmony_ci sb->s_time_min = S64_MIN; 8708c2ecf20Sopenharmony_ci sb->s_time_max = S64_MAX; 8718c2ecf20Sopenharmony_ci flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; 8728c2ecf20Sopenharmony_ci break; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_SUN: 8758c2ecf20Sopenharmony_ci UFSD("ufstype=sun\n"); 8768c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 1024; 8778c2ecf20Sopenharmony_ci uspi->s_fmask = ~(1024 - 1); 8788c2ecf20Sopenharmony_ci uspi->s_fshift = 10; 8798c2ecf20Sopenharmony_ci uspi->s_sbsize = super_block_size = 2048; 8808c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 8818c2ecf20Sopenharmony_ci uspi->s_maxsymlinklen = 0; /* Not supported on disk */ 8828c2ecf20Sopenharmony_ci flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN; 8838c2ecf20Sopenharmony_ci break; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_SUNOS: 8868c2ecf20Sopenharmony_ci UFSD("ufstype=sunos\n"); 8878c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 1024; 8888c2ecf20Sopenharmony_ci uspi->s_fmask = ~(1024 - 1); 8898c2ecf20Sopenharmony_ci uspi->s_fshift = 10; 8908c2ecf20Sopenharmony_ci uspi->s_sbsize = 2048; 8918c2ecf20Sopenharmony_ci super_block_size = 2048; 8928c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 8938c2ecf20Sopenharmony_ci uspi->s_maxsymlinklen = 0; /* Not supported on disk */ 8948c2ecf20Sopenharmony_ci flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_SUNOS | UFS_CG_SUN; 8958c2ecf20Sopenharmony_ci break; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_SUNx86: 8988c2ecf20Sopenharmony_ci UFSD("ufstype=sunx86\n"); 8998c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 1024; 9008c2ecf20Sopenharmony_ci uspi->s_fmask = ~(1024 - 1); 9018c2ecf20Sopenharmony_ci uspi->s_fshift = 10; 9028c2ecf20Sopenharmony_ci uspi->s_sbsize = super_block_size = 2048; 9038c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 9048c2ecf20Sopenharmony_ci uspi->s_maxsymlinklen = 0; /* Not supported on disk */ 9058c2ecf20Sopenharmony_ci flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUNx86 | UFS_CG_SUN; 9068c2ecf20Sopenharmony_ci break; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_OLD: 9098c2ecf20Sopenharmony_ci UFSD("ufstype=old\n"); 9108c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 1024; 9118c2ecf20Sopenharmony_ci uspi->s_fmask = ~(1024 - 1); 9128c2ecf20Sopenharmony_ci uspi->s_fshift = 10; 9138c2ecf20Sopenharmony_ci uspi->s_sbsize = super_block_size = 2048; 9148c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 9158c2ecf20Sopenharmony_ci flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; 9168c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) { 9178c2ecf20Sopenharmony_ci if (!silent) 9188c2ecf20Sopenharmony_ci pr_info("ufstype=old is supported read-only\n"); 9198c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci break; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_NEXTSTEP: 9248c2ecf20Sopenharmony_ci UFSD("ufstype=nextstep\n"); 9258c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 1024; 9268c2ecf20Sopenharmony_ci uspi->s_fmask = ~(1024 - 1); 9278c2ecf20Sopenharmony_ci uspi->s_fshift = 10; 9288c2ecf20Sopenharmony_ci uspi->s_sbsize = super_block_size = 2048; 9298c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 9308c2ecf20Sopenharmony_ci uspi->s_dirblksize = 1024; 9318c2ecf20Sopenharmony_ci flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; 9328c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) { 9338c2ecf20Sopenharmony_ci if (!silent) 9348c2ecf20Sopenharmony_ci pr_info("ufstype=nextstep is supported read-only\n"); 9358c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 9368c2ecf20Sopenharmony_ci } 9378c2ecf20Sopenharmony_ci break; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD: 9408c2ecf20Sopenharmony_ci UFSD("ufstype=nextstep-cd\n"); 9418c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 2048; 9428c2ecf20Sopenharmony_ci uspi->s_fmask = ~(2048 - 1); 9438c2ecf20Sopenharmony_ci uspi->s_fshift = 11; 9448c2ecf20Sopenharmony_ci uspi->s_sbsize = super_block_size = 2048; 9458c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 9468c2ecf20Sopenharmony_ci uspi->s_dirblksize = 1024; 9478c2ecf20Sopenharmony_ci flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; 9488c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) { 9498c2ecf20Sopenharmony_ci if (!silent) 9508c2ecf20Sopenharmony_ci pr_info("ufstype=nextstep-cd is supported read-only\n"); 9518c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci break; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_OPENSTEP: 9568c2ecf20Sopenharmony_ci UFSD("ufstype=openstep\n"); 9578c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 1024; 9588c2ecf20Sopenharmony_ci uspi->s_fmask = ~(1024 - 1); 9598c2ecf20Sopenharmony_ci uspi->s_fshift = 10; 9608c2ecf20Sopenharmony_ci uspi->s_sbsize = super_block_size = 2048; 9618c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 9628c2ecf20Sopenharmony_ci uspi->s_dirblksize = 1024; 9638c2ecf20Sopenharmony_ci flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; 9648c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) { 9658c2ecf20Sopenharmony_ci if (!silent) 9668c2ecf20Sopenharmony_ci pr_info("ufstype=openstep is supported read-only\n"); 9678c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 9688c2ecf20Sopenharmony_ci } 9698c2ecf20Sopenharmony_ci break; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci case UFS_MOUNT_UFSTYPE_HP: 9728c2ecf20Sopenharmony_ci UFSD("ufstype=hp\n"); 9738c2ecf20Sopenharmony_ci uspi->s_fsize = block_size = 1024; 9748c2ecf20Sopenharmony_ci uspi->s_fmask = ~(1024 - 1); 9758c2ecf20Sopenharmony_ci uspi->s_fshift = 10; 9768c2ecf20Sopenharmony_ci uspi->s_sbsize = super_block_size = 2048; 9778c2ecf20Sopenharmony_ci uspi->s_sbbase = 0; 9788c2ecf20Sopenharmony_ci flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; 9798c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) { 9808c2ecf20Sopenharmony_ci if (!silent) 9818c2ecf20Sopenharmony_ci pr_info("ufstype=hp is supported read-only\n"); 9828c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 9838c2ecf20Sopenharmony_ci } 9848c2ecf20Sopenharmony_ci break; 9858c2ecf20Sopenharmony_ci default: 9868c2ecf20Sopenharmony_ci if (!silent) 9878c2ecf20Sopenharmony_ci pr_err("unknown ufstype\n"); 9888c2ecf20Sopenharmony_ci goto failed; 9898c2ecf20Sopenharmony_ci } 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ciagain: 9928c2ecf20Sopenharmony_ci if (!sb_set_blocksize(sb, block_size)) { 9938c2ecf20Sopenharmony_ci pr_err("failed to set blocksize\n"); 9948c2ecf20Sopenharmony_ci goto failed; 9958c2ecf20Sopenharmony_ci } 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci /* 9988c2ecf20Sopenharmony_ci * read ufs super block from device 9998c2ecf20Sopenharmony_ci */ 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + super_block_offset/block_size, super_block_size); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci if (!ubh) 10048c2ecf20Sopenharmony_ci goto failed; 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci usb1 = ubh_get_usb_first(uspi); 10078c2ecf20Sopenharmony_ci usb2 = ubh_get_usb_second(uspi); 10088c2ecf20Sopenharmony_ci usb3 = ubh_get_usb_third(uspi); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci /* Sort out mod used on SunOS 4.1.3 for fs_state */ 10118c2ecf20Sopenharmony_ci uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat); 10128c2ecf20Sopenharmony_ci if (((flags & UFS_ST_MASK) == UFS_ST_SUNOS) && 10138c2ecf20Sopenharmony_ci (uspi->s_postblformat != UFS_42POSTBLFMT)) { 10148c2ecf20Sopenharmony_ci flags &= ~UFS_ST_MASK; 10158c2ecf20Sopenharmony_ci flags |= UFS_ST_SUN; 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci if ((flags & UFS_ST_MASK) == UFS_ST_44BSD && 10198c2ecf20Sopenharmony_ci uspi->s_postblformat == UFS_42POSTBLFMT) { 10208c2ecf20Sopenharmony_ci if (!silent) 10218c2ecf20Sopenharmony_ci pr_err("this is not a 44bsd filesystem"); 10228c2ecf20Sopenharmony_ci goto failed; 10238c2ecf20Sopenharmony_ci } 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci /* 10268c2ecf20Sopenharmony_ci * Check ufs magic number 10278c2ecf20Sopenharmony_ci */ 10288c2ecf20Sopenharmony_ci sbi->s_bytesex = BYTESEX_LE; 10298c2ecf20Sopenharmony_ci switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) { 10308c2ecf20Sopenharmony_ci case UFS_MAGIC: 10318c2ecf20Sopenharmony_ci case UFS_MAGIC_BW: 10328c2ecf20Sopenharmony_ci case UFS2_MAGIC: 10338c2ecf20Sopenharmony_ci case UFS_MAGIC_LFN: 10348c2ecf20Sopenharmony_ci case UFS_MAGIC_FEA: 10358c2ecf20Sopenharmony_ci case UFS_MAGIC_4GB: 10368c2ecf20Sopenharmony_ci goto magic_found; 10378c2ecf20Sopenharmony_ci } 10388c2ecf20Sopenharmony_ci sbi->s_bytesex = BYTESEX_BE; 10398c2ecf20Sopenharmony_ci switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) { 10408c2ecf20Sopenharmony_ci case UFS_MAGIC: 10418c2ecf20Sopenharmony_ci case UFS_MAGIC_BW: 10428c2ecf20Sopenharmony_ci case UFS2_MAGIC: 10438c2ecf20Sopenharmony_ci case UFS_MAGIC_LFN: 10448c2ecf20Sopenharmony_ci case UFS_MAGIC_FEA: 10458c2ecf20Sopenharmony_ci case UFS_MAGIC_4GB: 10468c2ecf20Sopenharmony_ci goto magic_found; 10478c2ecf20Sopenharmony_ci } 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci if ((((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP) 10508c2ecf20Sopenharmony_ci || ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP_CD) 10518c2ecf20Sopenharmony_ci || ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_OPENSTEP)) 10528c2ecf20Sopenharmony_ci && uspi->s_sbbase < 256) { 10538c2ecf20Sopenharmony_ci ubh_brelse_uspi(uspi); 10548c2ecf20Sopenharmony_ci ubh = NULL; 10558c2ecf20Sopenharmony_ci uspi->s_sbbase += 8; 10568c2ecf20Sopenharmony_ci goto again; 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci if (!silent) 10598c2ecf20Sopenharmony_ci pr_err("%s(): bad magic number\n", __func__); 10608c2ecf20Sopenharmony_ci goto failed; 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_cimagic_found: 10638c2ecf20Sopenharmony_ci /* 10648c2ecf20Sopenharmony_ci * Check block and fragment sizes 10658c2ecf20Sopenharmony_ci */ 10668c2ecf20Sopenharmony_ci uspi->s_bsize = fs32_to_cpu(sb, usb1->fs_bsize); 10678c2ecf20Sopenharmony_ci uspi->s_fsize = fs32_to_cpu(sb, usb1->fs_fsize); 10688c2ecf20Sopenharmony_ci uspi->s_sbsize = fs32_to_cpu(sb, usb1->fs_sbsize); 10698c2ecf20Sopenharmony_ci uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask); 10708c2ecf20Sopenharmony_ci uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci if (!is_power_of_2(uspi->s_fsize)) { 10738c2ecf20Sopenharmony_ci pr_err("%s(): fragment size %u is not a power of 2\n", 10748c2ecf20Sopenharmony_ci __func__, uspi->s_fsize); 10758c2ecf20Sopenharmony_ci goto failed; 10768c2ecf20Sopenharmony_ci } 10778c2ecf20Sopenharmony_ci if (uspi->s_fsize < 512) { 10788c2ecf20Sopenharmony_ci pr_err("%s(): fragment size %u is too small\n", 10798c2ecf20Sopenharmony_ci __func__, uspi->s_fsize); 10808c2ecf20Sopenharmony_ci goto failed; 10818c2ecf20Sopenharmony_ci } 10828c2ecf20Sopenharmony_ci if (uspi->s_fsize > 4096) { 10838c2ecf20Sopenharmony_ci pr_err("%s(): fragment size %u is too large\n", 10848c2ecf20Sopenharmony_ci __func__, uspi->s_fsize); 10858c2ecf20Sopenharmony_ci goto failed; 10868c2ecf20Sopenharmony_ci } 10878c2ecf20Sopenharmony_ci if (!is_power_of_2(uspi->s_bsize)) { 10888c2ecf20Sopenharmony_ci pr_err("%s(): block size %u is not a power of 2\n", 10898c2ecf20Sopenharmony_ci __func__, uspi->s_bsize); 10908c2ecf20Sopenharmony_ci goto failed; 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci if (uspi->s_bsize < 4096) { 10938c2ecf20Sopenharmony_ci pr_err("%s(): block size %u is too small\n", 10948c2ecf20Sopenharmony_ci __func__, uspi->s_bsize); 10958c2ecf20Sopenharmony_ci goto failed; 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci if (uspi->s_bsize / uspi->s_fsize > 8) { 10988c2ecf20Sopenharmony_ci pr_err("%s(): too many fragments per block (%u)\n", 10998c2ecf20Sopenharmony_ci __func__, uspi->s_bsize / uspi->s_fsize); 11008c2ecf20Sopenharmony_ci goto failed; 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) { 11038c2ecf20Sopenharmony_ci ubh_brelse_uspi(uspi); 11048c2ecf20Sopenharmony_ci ubh = NULL; 11058c2ecf20Sopenharmony_ci block_size = uspi->s_fsize; 11068c2ecf20Sopenharmony_ci super_block_size = uspi->s_sbsize; 11078c2ecf20Sopenharmony_ci UFSD("another value of block_size or super_block_size %u, %u\n", block_size, super_block_size); 11088c2ecf20Sopenharmony_ci goto again; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci sbi->s_flags = flags;/*after that line some functions use s_flags*/ 11128c2ecf20Sopenharmony_ci ufs_print_super_stuff(sb, usb1, usb2, usb3); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci /* 11158c2ecf20Sopenharmony_ci * Check, if file system was correctly unmounted. 11168c2ecf20Sopenharmony_ci * If not, make it read only. 11178c2ecf20Sopenharmony_ci */ 11188c2ecf20Sopenharmony_ci if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) || 11198c2ecf20Sopenharmony_ci ((flags & UFS_ST_MASK) == UFS_ST_OLD) || 11208c2ecf20Sopenharmony_ci (((flags & UFS_ST_MASK) == UFS_ST_SUN || 11218c2ecf20Sopenharmony_ci (flags & UFS_ST_MASK) == UFS_ST_SUNOS || 11228c2ecf20Sopenharmony_ci (flags & UFS_ST_MASK) == UFS_ST_SUNx86) && 11238c2ecf20Sopenharmony_ci (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) { 11248c2ecf20Sopenharmony_ci switch(usb1->fs_clean) { 11258c2ecf20Sopenharmony_ci case UFS_FSCLEAN: 11268c2ecf20Sopenharmony_ci UFSD("fs is clean\n"); 11278c2ecf20Sopenharmony_ci break; 11288c2ecf20Sopenharmony_ci case UFS_FSSTABLE: 11298c2ecf20Sopenharmony_ci UFSD("fs is stable\n"); 11308c2ecf20Sopenharmony_ci break; 11318c2ecf20Sopenharmony_ci case UFS_FSLOG: 11328c2ecf20Sopenharmony_ci UFSD("fs is logging fs\n"); 11338c2ecf20Sopenharmony_ci break; 11348c2ecf20Sopenharmony_ci case UFS_FSOSF1: 11358c2ecf20Sopenharmony_ci UFSD("fs is DEC OSF/1\n"); 11368c2ecf20Sopenharmony_ci break; 11378c2ecf20Sopenharmony_ci case UFS_FSACTIVE: 11388c2ecf20Sopenharmony_ci pr_err("%s(): fs is active\n", __func__); 11398c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 11408c2ecf20Sopenharmony_ci break; 11418c2ecf20Sopenharmony_ci case UFS_FSBAD: 11428c2ecf20Sopenharmony_ci pr_err("%s(): fs is bad\n", __func__); 11438c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 11448c2ecf20Sopenharmony_ci break; 11458c2ecf20Sopenharmony_ci default: 11468c2ecf20Sopenharmony_ci pr_err("%s(): can't grok fs_clean 0x%x\n", 11478c2ecf20Sopenharmony_ci __func__, usb1->fs_clean); 11488c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 11498c2ecf20Sopenharmony_ci break; 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci } else { 11528c2ecf20Sopenharmony_ci pr_err("%s(): fs needs fsck\n", __func__); 11538c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 11548c2ecf20Sopenharmony_ci } 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci /* 11578c2ecf20Sopenharmony_ci * Read ufs_super_block into internal data structures 11588c2ecf20Sopenharmony_ci */ 11598c2ecf20Sopenharmony_ci sb->s_op = &ufs_super_ops; 11608c2ecf20Sopenharmony_ci sb->s_export_op = &ufs_export_ops; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci sb->s_magic = fs32_to_cpu(sb, usb3->fs_magic); 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci uspi->s_sblkno = fs32_to_cpu(sb, usb1->fs_sblkno); 11658c2ecf20Sopenharmony_ci uspi->s_cblkno = fs32_to_cpu(sb, usb1->fs_cblkno); 11668c2ecf20Sopenharmony_ci uspi->s_iblkno = fs32_to_cpu(sb, usb1->fs_iblkno); 11678c2ecf20Sopenharmony_ci uspi->s_dblkno = fs32_to_cpu(sb, usb1->fs_dblkno); 11688c2ecf20Sopenharmony_ci uspi->s_cgoffset = fs32_to_cpu(sb, usb1->fs_cgoffset); 11698c2ecf20Sopenharmony_ci uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask); 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { 11728c2ecf20Sopenharmony_ci uspi->s_size = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size); 11738c2ecf20Sopenharmony_ci uspi->s_dsize = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); 11748c2ecf20Sopenharmony_ci } else { 11758c2ecf20Sopenharmony_ci uspi->s_size = fs32_to_cpu(sb, usb1->fs_size); 11768c2ecf20Sopenharmony_ci uspi->s_dsize = fs32_to_cpu(sb, usb1->fs_dsize); 11778c2ecf20Sopenharmony_ci } 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci uspi->s_ncg = fs32_to_cpu(sb, usb1->fs_ncg); 11808c2ecf20Sopenharmony_ci /* s_bsize already set */ 11818c2ecf20Sopenharmony_ci /* s_fsize already set */ 11828c2ecf20Sopenharmony_ci uspi->s_fpb = fs32_to_cpu(sb, usb1->fs_frag); 11838c2ecf20Sopenharmony_ci uspi->s_minfree = fs32_to_cpu(sb, usb1->fs_minfree); 11848c2ecf20Sopenharmony_ci uspi->s_bmask = fs32_to_cpu(sb, usb1->fs_bmask); 11858c2ecf20Sopenharmony_ci uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask); 11868c2ecf20Sopenharmony_ci uspi->s_bshift = fs32_to_cpu(sb, usb1->fs_bshift); 11878c2ecf20Sopenharmony_ci uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); 11888c2ecf20Sopenharmony_ci UFSD("uspi->s_bshift = %d,uspi->s_fshift = %d", uspi->s_bshift, 11898c2ecf20Sopenharmony_ci uspi->s_fshift); 11908c2ecf20Sopenharmony_ci uspi->s_fpbshift = fs32_to_cpu(sb, usb1->fs_fragshift); 11918c2ecf20Sopenharmony_ci uspi->s_fsbtodb = fs32_to_cpu(sb, usb1->fs_fsbtodb); 11928c2ecf20Sopenharmony_ci /* s_sbsize already set */ 11938c2ecf20Sopenharmony_ci uspi->s_csmask = fs32_to_cpu(sb, usb1->fs_csmask); 11948c2ecf20Sopenharmony_ci uspi->s_csshift = fs32_to_cpu(sb, usb1->fs_csshift); 11958c2ecf20Sopenharmony_ci uspi->s_nindir = fs32_to_cpu(sb, usb1->fs_nindir); 11968c2ecf20Sopenharmony_ci uspi->s_inopb = fs32_to_cpu(sb, usb1->fs_inopb); 11978c2ecf20Sopenharmony_ci uspi->s_nspf = fs32_to_cpu(sb, usb1->fs_nspf); 11988c2ecf20Sopenharmony_ci uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3); 11998c2ecf20Sopenharmony_ci uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave); 12008c2ecf20Sopenharmony_ci uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci if (uspi->fs_magic == UFS2_MAGIC) 12038c2ecf20Sopenharmony_ci uspi->s_csaddr = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr); 12048c2ecf20Sopenharmony_ci else 12058c2ecf20Sopenharmony_ci uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr); 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize); 12088c2ecf20Sopenharmony_ci uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize); 12098c2ecf20Sopenharmony_ci uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak); 12108c2ecf20Sopenharmony_ci uspi->s_nsect = fs32_to_cpu(sb, usb1->fs_nsect); 12118c2ecf20Sopenharmony_ci uspi->s_spc = fs32_to_cpu(sb, usb1->fs_spc); 12128c2ecf20Sopenharmony_ci uspi->s_ipg = fs32_to_cpu(sb, usb1->fs_ipg); 12138c2ecf20Sopenharmony_ci uspi->s_fpg = fs32_to_cpu(sb, usb1->fs_fpg); 12148c2ecf20Sopenharmony_ci uspi->s_cpc = fs32_to_cpu(sb, usb2->fs_un.fs_u1.fs_cpc); 12158c2ecf20Sopenharmony_ci uspi->s_contigsumsize = fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_contigsumsize); 12168c2ecf20Sopenharmony_ci uspi->s_qbmask = ufs_get_fs_qbmask(sb, usb3); 12178c2ecf20Sopenharmony_ci uspi->s_qfmask = ufs_get_fs_qfmask(sb, usb3); 12188c2ecf20Sopenharmony_ci uspi->s_nrpos = fs32_to_cpu(sb, usb3->fs_nrpos); 12198c2ecf20Sopenharmony_ci uspi->s_postbloff = fs32_to_cpu(sb, usb3->fs_postbloff); 12208c2ecf20Sopenharmony_ci uspi->s_rotbloff = fs32_to_cpu(sb, usb3->fs_rotbloff); 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci uspi->s_root_blocks = mul_u64_u32_div(uspi->s_dsize, 12238c2ecf20Sopenharmony_ci uspi->s_minfree, 100); 12248c2ecf20Sopenharmony_ci if (uspi->s_minfree <= 5) { 12258c2ecf20Sopenharmony_ci uspi->s_time_to_space = ~0ULL; 12268c2ecf20Sopenharmony_ci uspi->s_space_to_time = 0; 12278c2ecf20Sopenharmony_ci usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTSPACE); 12288c2ecf20Sopenharmony_ci } else { 12298c2ecf20Sopenharmony_ci uspi->s_time_to_space = (uspi->s_root_blocks / 2) + 1; 12308c2ecf20Sopenharmony_ci uspi->s_space_to_time = mul_u64_u32_div(uspi->s_dsize, 12318c2ecf20Sopenharmony_ci uspi->s_minfree - 2, 100) - 1; 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci /* 12358c2ecf20Sopenharmony_ci * Compute another frequently used values 12368c2ecf20Sopenharmony_ci */ 12378c2ecf20Sopenharmony_ci uspi->s_fpbmask = uspi->s_fpb - 1; 12388c2ecf20Sopenharmony_ci if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 12398c2ecf20Sopenharmony_ci uspi->s_apbshift = uspi->s_bshift - 3; 12408c2ecf20Sopenharmony_ci else 12418c2ecf20Sopenharmony_ci uspi->s_apbshift = uspi->s_bshift - 2; 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci uspi->s_2apbshift = uspi->s_apbshift * 2; 12448c2ecf20Sopenharmony_ci uspi->s_3apbshift = uspi->s_apbshift * 3; 12458c2ecf20Sopenharmony_ci uspi->s_apb = 1 << uspi->s_apbshift; 12468c2ecf20Sopenharmony_ci uspi->s_2apb = 1 << uspi->s_2apbshift; 12478c2ecf20Sopenharmony_ci uspi->s_3apb = 1 << uspi->s_3apbshift; 12488c2ecf20Sopenharmony_ci uspi->s_apbmask = uspi->s_apb - 1; 12498c2ecf20Sopenharmony_ci uspi->s_nspfshift = uspi->s_fshift - UFS_SECTOR_BITS; 12508c2ecf20Sopenharmony_ci uspi->s_nspb = uspi->s_nspf << uspi->s_fpbshift; 12518c2ecf20Sopenharmony_ci uspi->s_inopf = uspi->s_inopb >> uspi->s_fpbshift; 12528c2ecf20Sopenharmony_ci uspi->s_bpf = uspi->s_fsize << 3; 12538c2ecf20Sopenharmony_ci uspi->s_bpfshift = uspi->s_fshift + 3; 12548c2ecf20Sopenharmony_ci uspi->s_bpfmask = uspi->s_bpf - 1; 12558c2ecf20Sopenharmony_ci if ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_44BSD || 12568c2ecf20Sopenharmony_ci (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_UFS2) 12578c2ecf20Sopenharmony_ci uspi->s_maxsymlinklen = 12588c2ecf20Sopenharmony_ci fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen); 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci if (uspi->fs_magic == UFS2_MAGIC) 12618c2ecf20Sopenharmony_ci maxsymlen = 2 * 4 * (UFS_NDADDR + UFS_NINDIR); 12628c2ecf20Sopenharmony_ci else 12638c2ecf20Sopenharmony_ci maxsymlen = 4 * (UFS_NDADDR + UFS_NINDIR); 12648c2ecf20Sopenharmony_ci if (uspi->s_maxsymlinklen > maxsymlen) { 12658c2ecf20Sopenharmony_ci ufs_warning(sb, __func__, "ufs_read_super: excessive maximum " 12668c2ecf20Sopenharmony_ci "fast symlink size (%u)\n", uspi->s_maxsymlinklen); 12678c2ecf20Sopenharmony_ci uspi->s_maxsymlinklen = maxsymlen; 12688c2ecf20Sopenharmony_ci } 12698c2ecf20Sopenharmony_ci sb->s_maxbytes = ufs_max_bytes(sb); 12708c2ecf20Sopenharmony_ci sb->s_max_links = UFS_LINK_MAX; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci inode = ufs_iget(sb, UFS_ROOTINO); 12738c2ecf20Sopenharmony_ci if (IS_ERR(inode)) { 12748c2ecf20Sopenharmony_ci ret = PTR_ERR(inode); 12758c2ecf20Sopenharmony_ci goto failed; 12768c2ecf20Sopenharmony_ci } 12778c2ecf20Sopenharmony_ci sb->s_root = d_make_root(inode); 12788c2ecf20Sopenharmony_ci if (!sb->s_root) { 12798c2ecf20Sopenharmony_ci ret = -ENOMEM; 12808c2ecf20Sopenharmony_ci goto failed; 12818c2ecf20Sopenharmony_ci } 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci ufs_setup_cstotal(sb); 12848c2ecf20Sopenharmony_ci /* 12858c2ecf20Sopenharmony_ci * Read cylinder group structures 12868c2ecf20Sopenharmony_ci */ 12878c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) 12888c2ecf20Sopenharmony_ci if (!ufs_read_cylinder_structures(sb)) 12898c2ecf20Sopenharmony_ci goto failed; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci UFSD("EXIT\n"); 12928c2ecf20Sopenharmony_ci return 0; 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_cifailed: 12958c2ecf20Sopenharmony_ci if (ubh) 12968c2ecf20Sopenharmony_ci ubh_brelse_uspi (uspi); 12978c2ecf20Sopenharmony_ci kfree (uspi); 12988c2ecf20Sopenharmony_ci kfree(sbi); 12998c2ecf20Sopenharmony_ci sb->s_fs_info = NULL; 13008c2ecf20Sopenharmony_ci UFSD("EXIT (FAILED)\n"); 13018c2ecf20Sopenharmony_ci return ret; 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_cifailed_nomem: 13048c2ecf20Sopenharmony_ci UFSD("EXIT (NOMEM)\n"); 13058c2ecf20Sopenharmony_ci return -ENOMEM; 13068c2ecf20Sopenharmony_ci} 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_cistatic int ufs_remount (struct super_block *sb, int *mount_flags, char *data) 13098c2ecf20Sopenharmony_ci{ 13108c2ecf20Sopenharmony_ci struct ufs_sb_private_info * uspi; 13118c2ecf20Sopenharmony_ci struct ufs_super_block_first * usb1; 13128c2ecf20Sopenharmony_ci struct ufs_super_block_third * usb3; 13138c2ecf20Sopenharmony_ci unsigned new_mount_opt, ufstype; 13148c2ecf20Sopenharmony_ci unsigned flags; 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci sync_filesystem(sb); 13178c2ecf20Sopenharmony_ci mutex_lock(&UFS_SB(sb)->s_lock); 13188c2ecf20Sopenharmony_ci uspi = UFS_SB(sb)->s_uspi; 13198c2ecf20Sopenharmony_ci flags = UFS_SB(sb)->s_flags; 13208c2ecf20Sopenharmony_ci usb1 = ubh_get_usb_first(uspi); 13218c2ecf20Sopenharmony_ci usb3 = ubh_get_usb_third(uspi); 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci /* 13248c2ecf20Sopenharmony_ci * Allow the "check" option to be passed as a remount option. 13258c2ecf20Sopenharmony_ci * It is not possible to change ufstype option during remount 13268c2ecf20Sopenharmony_ci */ 13278c2ecf20Sopenharmony_ci ufstype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE; 13288c2ecf20Sopenharmony_ci new_mount_opt = 0; 13298c2ecf20Sopenharmony_ci ufs_set_opt (new_mount_opt, ONERROR_LOCK); 13308c2ecf20Sopenharmony_ci if (!ufs_parse_options (data, &new_mount_opt)) { 13318c2ecf20Sopenharmony_ci mutex_unlock(&UFS_SB(sb)->s_lock); 13328c2ecf20Sopenharmony_ci return -EINVAL; 13338c2ecf20Sopenharmony_ci } 13348c2ecf20Sopenharmony_ci if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { 13358c2ecf20Sopenharmony_ci new_mount_opt |= ufstype; 13368c2ecf20Sopenharmony_ci } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { 13378c2ecf20Sopenharmony_ci pr_err("ufstype can't be changed during remount\n"); 13388c2ecf20Sopenharmony_ci mutex_unlock(&UFS_SB(sb)->s_lock); 13398c2ecf20Sopenharmony_ci return -EINVAL; 13408c2ecf20Sopenharmony_ci } 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci if ((bool)(*mount_flags & SB_RDONLY) == sb_rdonly(sb)) { 13438c2ecf20Sopenharmony_ci UFS_SB(sb)->s_mount_opt = new_mount_opt; 13448c2ecf20Sopenharmony_ci mutex_unlock(&UFS_SB(sb)->s_lock); 13458c2ecf20Sopenharmony_ci return 0; 13468c2ecf20Sopenharmony_ci } 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci /* 13498c2ecf20Sopenharmony_ci * fs was mouted as rw, remounting ro 13508c2ecf20Sopenharmony_ci */ 13518c2ecf20Sopenharmony_ci if (*mount_flags & SB_RDONLY) { 13528c2ecf20Sopenharmony_ci ufs_put_super_internal(sb); 13538c2ecf20Sopenharmony_ci usb1->fs_time = ufs_get_seconds(sb); 13548c2ecf20Sopenharmony_ci if ((flags & UFS_ST_MASK) == UFS_ST_SUN 13558c2ecf20Sopenharmony_ci || (flags & UFS_ST_MASK) == UFS_ST_SUNOS 13568c2ecf20Sopenharmony_ci || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) 13578c2ecf20Sopenharmony_ci ufs_set_fs_state(sb, usb1, usb3, 13588c2ecf20Sopenharmony_ci UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); 13598c2ecf20Sopenharmony_ci ubh_mark_buffer_dirty (USPI_UBH(uspi)); 13608c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 13618c2ecf20Sopenharmony_ci } else { 13628c2ecf20Sopenharmony_ci /* 13638c2ecf20Sopenharmony_ci * fs was mounted as ro, remounting rw 13648c2ecf20Sopenharmony_ci */ 13658c2ecf20Sopenharmony_ci#ifndef CONFIG_UFS_FS_WRITE 13668c2ecf20Sopenharmony_ci pr_err("ufs was compiled with read-only support, can't be mounted as read-write\n"); 13678c2ecf20Sopenharmony_ci mutex_unlock(&UFS_SB(sb)->s_lock); 13688c2ecf20Sopenharmony_ci return -EINVAL; 13698c2ecf20Sopenharmony_ci#else 13708c2ecf20Sopenharmony_ci if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 13718c2ecf20Sopenharmony_ci ufstype != UFS_MOUNT_UFSTYPE_SUNOS && 13728c2ecf20Sopenharmony_ci ufstype != UFS_MOUNT_UFSTYPE_44BSD && 13738c2ecf20Sopenharmony_ci ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && 13748c2ecf20Sopenharmony_ci ufstype != UFS_MOUNT_UFSTYPE_UFS2) { 13758c2ecf20Sopenharmony_ci pr_err("this ufstype is read-only supported\n"); 13768c2ecf20Sopenharmony_ci mutex_unlock(&UFS_SB(sb)->s_lock); 13778c2ecf20Sopenharmony_ci return -EINVAL; 13788c2ecf20Sopenharmony_ci } 13798c2ecf20Sopenharmony_ci if (!ufs_read_cylinder_structures(sb)) { 13808c2ecf20Sopenharmony_ci pr_err("failed during remounting\n"); 13818c2ecf20Sopenharmony_ci mutex_unlock(&UFS_SB(sb)->s_lock); 13828c2ecf20Sopenharmony_ci return -EPERM; 13838c2ecf20Sopenharmony_ci } 13848c2ecf20Sopenharmony_ci sb->s_flags &= ~SB_RDONLY; 13858c2ecf20Sopenharmony_ci#endif 13868c2ecf20Sopenharmony_ci } 13878c2ecf20Sopenharmony_ci UFS_SB(sb)->s_mount_opt = new_mount_opt; 13888c2ecf20Sopenharmony_ci mutex_unlock(&UFS_SB(sb)->s_lock); 13898c2ecf20Sopenharmony_ci return 0; 13908c2ecf20Sopenharmony_ci} 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_cistatic int ufs_show_options(struct seq_file *seq, struct dentry *root) 13938c2ecf20Sopenharmony_ci{ 13948c2ecf20Sopenharmony_ci struct ufs_sb_info *sbi = UFS_SB(root->d_sb); 13958c2ecf20Sopenharmony_ci unsigned mval = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE; 13968c2ecf20Sopenharmony_ci const struct match_token *tp = tokens; 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci while (tp->token != Opt_onerror_panic && tp->token != mval) 13998c2ecf20Sopenharmony_ci ++tp; 14008c2ecf20Sopenharmony_ci BUG_ON(tp->token == Opt_onerror_panic); 14018c2ecf20Sopenharmony_ci seq_printf(seq, ",%s", tp->pattern); 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci mval = sbi->s_mount_opt & UFS_MOUNT_ONERROR; 14048c2ecf20Sopenharmony_ci while (tp->token != Opt_err && tp->token != mval) 14058c2ecf20Sopenharmony_ci ++tp; 14068c2ecf20Sopenharmony_ci BUG_ON(tp->token == Opt_err); 14078c2ecf20Sopenharmony_ci seq_printf(seq, ",%s", tp->pattern); 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci return 0; 14108c2ecf20Sopenharmony_ci} 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cistatic int ufs_statfs(struct dentry *dentry, struct kstatfs *buf) 14138c2ecf20Sopenharmony_ci{ 14148c2ecf20Sopenharmony_ci struct super_block *sb = dentry->d_sb; 14158c2ecf20Sopenharmony_ci struct ufs_sb_private_info *uspi= UFS_SB(sb)->s_uspi; 14168c2ecf20Sopenharmony_ci unsigned flags = UFS_SB(sb)->s_flags; 14178c2ecf20Sopenharmony_ci u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci mutex_lock(&UFS_SB(sb)->s_lock); 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 14228c2ecf20Sopenharmony_ci buf->f_type = UFS2_MAGIC; 14238c2ecf20Sopenharmony_ci else 14248c2ecf20Sopenharmony_ci buf->f_type = UFS_MAGIC; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci buf->f_blocks = uspi->s_dsize; 14278c2ecf20Sopenharmony_ci buf->f_bfree = ufs_freefrags(uspi); 14288c2ecf20Sopenharmony_ci buf->f_ffree = uspi->cs_total.cs_nifree; 14298c2ecf20Sopenharmony_ci buf->f_bsize = sb->s_blocksize; 14308c2ecf20Sopenharmony_ci buf->f_bavail = (buf->f_bfree > uspi->s_root_blocks) 14318c2ecf20Sopenharmony_ci ? (buf->f_bfree - uspi->s_root_blocks) : 0; 14328c2ecf20Sopenharmony_ci buf->f_files = uspi->s_ncg * uspi->s_ipg; 14338c2ecf20Sopenharmony_ci buf->f_namelen = UFS_MAXNAMLEN; 14348c2ecf20Sopenharmony_ci buf->f_fsid = u64_to_fsid(id); 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci mutex_unlock(&UFS_SB(sb)->s_lock); 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci return 0; 14398c2ecf20Sopenharmony_ci} 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_cistatic struct kmem_cache * ufs_inode_cachep; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_cistatic struct inode *ufs_alloc_inode(struct super_block *sb) 14448c2ecf20Sopenharmony_ci{ 14458c2ecf20Sopenharmony_ci struct ufs_inode_info *ei; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci ei = kmem_cache_alloc(ufs_inode_cachep, GFP_NOFS); 14488c2ecf20Sopenharmony_ci if (!ei) 14498c2ecf20Sopenharmony_ci return NULL; 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci inode_set_iversion(&ei->vfs_inode, 1); 14528c2ecf20Sopenharmony_ci seqlock_init(&ei->meta_lock); 14538c2ecf20Sopenharmony_ci mutex_init(&ei->truncate_mutex); 14548c2ecf20Sopenharmony_ci return &ei->vfs_inode; 14558c2ecf20Sopenharmony_ci} 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_cistatic void ufs_free_in_core_inode(struct inode *inode) 14588c2ecf20Sopenharmony_ci{ 14598c2ecf20Sopenharmony_ci kmem_cache_free(ufs_inode_cachep, UFS_I(inode)); 14608c2ecf20Sopenharmony_ci} 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_cistatic void init_once(void *foo) 14638c2ecf20Sopenharmony_ci{ 14648c2ecf20Sopenharmony_ci struct ufs_inode_info *ei = (struct ufs_inode_info *) foo; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci inode_init_once(&ei->vfs_inode); 14678c2ecf20Sopenharmony_ci} 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_cistatic int __init init_inodecache(void) 14708c2ecf20Sopenharmony_ci{ 14718c2ecf20Sopenharmony_ci ufs_inode_cachep = kmem_cache_create_usercopy("ufs_inode_cache", 14728c2ecf20Sopenharmony_ci sizeof(struct ufs_inode_info), 0, 14738c2ecf20Sopenharmony_ci (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD| 14748c2ecf20Sopenharmony_ci SLAB_ACCOUNT), 14758c2ecf20Sopenharmony_ci offsetof(struct ufs_inode_info, i_u1.i_symlink), 14768c2ecf20Sopenharmony_ci sizeof_field(struct ufs_inode_info, 14778c2ecf20Sopenharmony_ci i_u1.i_symlink), 14788c2ecf20Sopenharmony_ci init_once); 14798c2ecf20Sopenharmony_ci if (ufs_inode_cachep == NULL) 14808c2ecf20Sopenharmony_ci return -ENOMEM; 14818c2ecf20Sopenharmony_ci return 0; 14828c2ecf20Sopenharmony_ci} 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_cistatic void destroy_inodecache(void) 14858c2ecf20Sopenharmony_ci{ 14868c2ecf20Sopenharmony_ci /* 14878c2ecf20Sopenharmony_ci * Make sure all delayed rcu free inodes are flushed before we 14888c2ecf20Sopenharmony_ci * destroy cache. 14898c2ecf20Sopenharmony_ci */ 14908c2ecf20Sopenharmony_ci rcu_barrier(); 14918c2ecf20Sopenharmony_ci kmem_cache_destroy(ufs_inode_cachep); 14928c2ecf20Sopenharmony_ci} 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_cistatic const struct super_operations ufs_super_ops = { 14958c2ecf20Sopenharmony_ci .alloc_inode = ufs_alloc_inode, 14968c2ecf20Sopenharmony_ci .free_inode = ufs_free_in_core_inode, 14978c2ecf20Sopenharmony_ci .write_inode = ufs_write_inode, 14988c2ecf20Sopenharmony_ci .evict_inode = ufs_evict_inode, 14998c2ecf20Sopenharmony_ci .put_super = ufs_put_super, 15008c2ecf20Sopenharmony_ci .sync_fs = ufs_sync_fs, 15018c2ecf20Sopenharmony_ci .statfs = ufs_statfs, 15028c2ecf20Sopenharmony_ci .remount_fs = ufs_remount, 15038c2ecf20Sopenharmony_ci .show_options = ufs_show_options, 15048c2ecf20Sopenharmony_ci}; 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_cistatic struct dentry *ufs_mount(struct file_system_type *fs_type, 15078c2ecf20Sopenharmony_ci int flags, const char *dev_name, void *data) 15088c2ecf20Sopenharmony_ci{ 15098c2ecf20Sopenharmony_ci return mount_bdev(fs_type, flags, dev_name, data, ufs_fill_super); 15108c2ecf20Sopenharmony_ci} 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_cistatic struct file_system_type ufs_fs_type = { 15138c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 15148c2ecf20Sopenharmony_ci .name = "ufs", 15158c2ecf20Sopenharmony_ci .mount = ufs_mount, 15168c2ecf20Sopenharmony_ci .kill_sb = kill_block_super, 15178c2ecf20Sopenharmony_ci .fs_flags = FS_REQUIRES_DEV, 15188c2ecf20Sopenharmony_ci}; 15198c2ecf20Sopenharmony_ciMODULE_ALIAS_FS("ufs"); 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_cistatic int __init init_ufs_fs(void) 15228c2ecf20Sopenharmony_ci{ 15238c2ecf20Sopenharmony_ci int err = init_inodecache(); 15248c2ecf20Sopenharmony_ci if (err) 15258c2ecf20Sopenharmony_ci goto out1; 15268c2ecf20Sopenharmony_ci err = register_filesystem(&ufs_fs_type); 15278c2ecf20Sopenharmony_ci if (err) 15288c2ecf20Sopenharmony_ci goto out; 15298c2ecf20Sopenharmony_ci return 0; 15308c2ecf20Sopenharmony_ciout: 15318c2ecf20Sopenharmony_ci destroy_inodecache(); 15328c2ecf20Sopenharmony_ciout1: 15338c2ecf20Sopenharmony_ci return err; 15348c2ecf20Sopenharmony_ci} 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_cistatic void __exit exit_ufs_fs(void) 15378c2ecf20Sopenharmony_ci{ 15388c2ecf20Sopenharmony_ci unregister_filesystem(&ufs_fs_type); 15398c2ecf20Sopenharmony_ci destroy_inodecache(); 15408c2ecf20Sopenharmony_ci} 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_cimodule_init(init_ufs_fs) 15438c2ecf20Sopenharmony_cimodule_exit(exit_ufs_fs) 15448c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1545