18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *   Copyright (C) International Business Machines Corp., 2000-2004
48c2ecf20Sopenharmony_ci *   Portions Copyright (C) Christoph Hellwig, 2001-2002
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/fs.h>
88c2ecf20Sopenharmony_ci#include <linux/module.h>
98c2ecf20Sopenharmony_ci#include <linux/parser.h>
108c2ecf20Sopenharmony_ci#include <linux/completion.h>
118c2ecf20Sopenharmony_ci#include <linux/vfs.h>
128c2ecf20Sopenharmony_ci#include <linux/quotaops.h>
138c2ecf20Sopenharmony_ci#include <linux/mount.h>
148c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
158c2ecf20Sopenharmony_ci#include <linux/kthread.h>
168c2ecf20Sopenharmony_ci#include <linux/posix_acl.h>
178c2ecf20Sopenharmony_ci#include <linux/buffer_head.h>
188c2ecf20Sopenharmony_ci#include <linux/exportfs.h>
198c2ecf20Sopenharmony_ci#include <linux/crc32.h>
208c2ecf20Sopenharmony_ci#include <linux/slab.h>
218c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
228c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
238c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#include "jfs_incore.h"
268c2ecf20Sopenharmony_ci#include "jfs_filsys.h"
278c2ecf20Sopenharmony_ci#include "jfs_inode.h"
288c2ecf20Sopenharmony_ci#include "jfs_metapage.h"
298c2ecf20Sopenharmony_ci#include "jfs_superblock.h"
308c2ecf20Sopenharmony_ci#include "jfs_dmap.h"
318c2ecf20Sopenharmony_ci#include "jfs_imap.h"
328c2ecf20Sopenharmony_ci#include "jfs_acl.h"
338c2ecf20Sopenharmony_ci#include "jfs_debug.h"
348c2ecf20Sopenharmony_ci#include "jfs_xattr.h"
358c2ecf20Sopenharmony_ci#include "jfs_dinode.h"
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("The Journaled Filesystem (JFS)");
388c2ecf20Sopenharmony_ciMODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM");
398c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic struct kmem_cache *jfs_inode_cachep;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic const struct super_operations jfs_super_operations;
448c2ecf20Sopenharmony_cistatic const struct export_operations jfs_export_operations;
458c2ecf20Sopenharmony_cistatic struct file_system_type jfs_fs_type;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define MAX_COMMIT_THREADS 64
488c2ecf20Sopenharmony_cistatic int commit_threads;
498c2ecf20Sopenharmony_cimodule_param(commit_threads, int, 0);
508c2ecf20Sopenharmony_ciMODULE_PARM_DESC(commit_threads, "Number of commit threads");
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic struct task_struct *jfsCommitThread[MAX_COMMIT_THREADS];
538c2ecf20Sopenharmony_cistruct task_struct *jfsIOthread;
548c2ecf20Sopenharmony_cistruct task_struct *jfsSyncThread;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#ifdef CONFIG_JFS_DEBUG
578c2ecf20Sopenharmony_ciint jfsloglevel = JFS_LOGLEVEL_WARN;
588c2ecf20Sopenharmony_cimodule_param(jfsloglevel, int, 0644);
598c2ecf20Sopenharmony_ciMODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
608c2ecf20Sopenharmony_ci#endif
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic void jfs_handle_error(struct super_block *sb)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (sb_rdonly(sb))
678c2ecf20Sopenharmony_ci		return;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	updateSuper(sb, FM_DIRTY);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	if (sbi->flag & JFS_ERR_PANIC)
728c2ecf20Sopenharmony_ci		panic("JFS (device %s): panic forced after error\n",
738c2ecf20Sopenharmony_ci			sb->s_id);
748c2ecf20Sopenharmony_ci	else if (sbi->flag & JFS_ERR_REMOUNT_RO) {
758c2ecf20Sopenharmony_ci		jfs_err("ERROR: (device %s): remounting filesystem as read-only",
768c2ecf20Sopenharmony_ci			sb->s_id);
778c2ecf20Sopenharmony_ci		sb->s_flags |= SB_RDONLY;
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	/* nothing is done for continue beyond marking the superblock dirty */
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_civoid jfs_error(struct super_block *sb, const char *fmt, ...)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	struct va_format vaf;
868c2ecf20Sopenharmony_ci	va_list args;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	va_start(args, fmt);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	vaf.fmt = fmt;
918c2ecf20Sopenharmony_ci	vaf.va = &args;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	pr_err("ERROR: (device %s): %ps: %pV\n",
948c2ecf20Sopenharmony_ci	       sb->s_id, __builtin_return_address(0), &vaf);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	va_end(args);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	jfs_handle_error(sb);
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cistatic struct inode *jfs_alloc_inode(struct super_block *sb)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	struct jfs_inode_info *jfs_inode;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	jfs_inode = kmem_cache_alloc(jfs_inode_cachep, GFP_NOFS);
1068c2ecf20Sopenharmony_ci	if (!jfs_inode)
1078c2ecf20Sopenharmony_ci		return NULL;
1088c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA
1098c2ecf20Sopenharmony_ci	memset(&jfs_inode->i_dquot, 0, sizeof(jfs_inode->i_dquot));
1108c2ecf20Sopenharmony_ci#endif
1118c2ecf20Sopenharmony_ci	return &jfs_inode->vfs_inode;
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistatic void jfs_free_inode(struct inode *inode)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	kmem_cache_free(jfs_inode_cachep, JFS_IP(inode));
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistatic int jfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb);
1228c2ecf20Sopenharmony_ci	s64 maxinodes;
1238c2ecf20Sopenharmony_ci	struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	jfs_info("In jfs_statfs");
1268c2ecf20Sopenharmony_ci	buf->f_type = JFS_SUPER_MAGIC;
1278c2ecf20Sopenharmony_ci	buf->f_bsize = sbi->bsize;
1288c2ecf20Sopenharmony_ci	buf->f_blocks = sbi->bmap->db_mapsize;
1298c2ecf20Sopenharmony_ci	buf->f_bfree = sbi->bmap->db_nfree;
1308c2ecf20Sopenharmony_ci	buf->f_bavail = sbi->bmap->db_nfree;
1318c2ecf20Sopenharmony_ci	/*
1328c2ecf20Sopenharmony_ci	 * If we really return the number of allocated & free inodes, some
1338c2ecf20Sopenharmony_ci	 * applications will fail because they won't see enough free inodes.
1348c2ecf20Sopenharmony_ci	 * We'll try to calculate some guess as to how many inodes we can
1358c2ecf20Sopenharmony_ci	 * really allocate
1368c2ecf20Sopenharmony_ci	 *
1378c2ecf20Sopenharmony_ci	 * buf->f_files = atomic_read(&imap->im_numinos);
1388c2ecf20Sopenharmony_ci	 * buf->f_ffree = atomic_read(&imap->im_numfree);
1398c2ecf20Sopenharmony_ci	 */
1408c2ecf20Sopenharmony_ci	maxinodes = min((s64) atomic_read(&imap->im_numinos) +
1418c2ecf20Sopenharmony_ci			((sbi->bmap->db_nfree >> imap->im_l2nbperiext)
1428c2ecf20Sopenharmony_ci			 << L2INOSPEREXT), (s64) 0xffffffffLL);
1438c2ecf20Sopenharmony_ci	buf->f_files = maxinodes;
1448c2ecf20Sopenharmony_ci	buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) -
1458c2ecf20Sopenharmony_ci				    atomic_read(&imap->im_numfree));
1468c2ecf20Sopenharmony_ci	buf->f_fsid.val[0] = crc32_le(0, (char *)&sbi->uuid,
1478c2ecf20Sopenharmony_ci				      sizeof(sbi->uuid)/2);
1488c2ecf20Sopenharmony_ci	buf->f_fsid.val[1] = crc32_le(0,
1498c2ecf20Sopenharmony_ci				      (char *)&sbi->uuid + sizeof(sbi->uuid)/2,
1508c2ecf20Sopenharmony_ci				      sizeof(sbi->uuid)/2);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	buf->f_namelen = JFS_NAME_MAX;
1538c2ecf20Sopenharmony_ci	return 0;
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA
1578c2ecf20Sopenharmony_cistatic int jfs_quota_off(struct super_block *sb, int type);
1588c2ecf20Sopenharmony_cistatic int jfs_quota_on(struct super_block *sb, int type, int format_id,
1598c2ecf20Sopenharmony_ci			const struct path *path);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic void jfs_quota_off_umount(struct super_block *sb)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	int type;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	for (type = 0; type < MAXQUOTAS; type++)
1668c2ecf20Sopenharmony_ci		jfs_quota_off(sb, type);
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic const struct quotactl_ops jfs_quotactl_ops = {
1708c2ecf20Sopenharmony_ci	.quota_on	= jfs_quota_on,
1718c2ecf20Sopenharmony_ci	.quota_off	= jfs_quota_off,
1728c2ecf20Sopenharmony_ci	.quota_sync	= dquot_quota_sync,
1738c2ecf20Sopenharmony_ci	.get_state	= dquot_get_state,
1748c2ecf20Sopenharmony_ci	.set_info	= dquot_set_dqinfo,
1758c2ecf20Sopenharmony_ci	.get_dqblk	= dquot_get_dqblk,
1768c2ecf20Sopenharmony_ci	.set_dqblk	= dquot_set_dqblk,
1778c2ecf20Sopenharmony_ci	.get_nextdqblk	= dquot_get_next_dqblk,
1788c2ecf20Sopenharmony_ci};
1798c2ecf20Sopenharmony_ci#else
1808c2ecf20Sopenharmony_cistatic inline void jfs_quota_off_umount(struct super_block *sb)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci#endif
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic void jfs_put_super(struct super_block *sb)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
1888c2ecf20Sopenharmony_ci	int rc;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	jfs_info("In jfs_put_super");
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	jfs_quota_off_umount(sb);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	rc = jfs_umount(sb);
1958c2ecf20Sopenharmony_ci	if (rc)
1968c2ecf20Sopenharmony_ci		jfs_err("jfs_umount failed with return code %d", rc);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	unload_nls(sbi->nls_tab);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
2018c2ecf20Sopenharmony_ci	iput(sbi->direct_inode);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	kfree(sbi);
2048c2ecf20Sopenharmony_ci}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cienum {
2078c2ecf20Sopenharmony_ci	Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
2088c2ecf20Sopenharmony_ci	Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
2098c2ecf20Sopenharmony_ci	Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask,
2108c2ecf20Sopenharmony_ci	Opt_discard, Opt_nodiscard, Opt_discard_minblk
2118c2ecf20Sopenharmony_ci};
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic const match_table_t tokens = {
2148c2ecf20Sopenharmony_ci	{Opt_integrity, "integrity"},
2158c2ecf20Sopenharmony_ci	{Opt_nointegrity, "nointegrity"},
2168c2ecf20Sopenharmony_ci	{Opt_iocharset, "iocharset=%s"},
2178c2ecf20Sopenharmony_ci	{Opt_resize, "resize=%u"},
2188c2ecf20Sopenharmony_ci	{Opt_resize_nosize, "resize"},
2198c2ecf20Sopenharmony_ci	{Opt_errors, "errors=%s"},
2208c2ecf20Sopenharmony_ci	{Opt_ignore, "noquota"},
2218c2ecf20Sopenharmony_ci	{Opt_quota, "quota"},
2228c2ecf20Sopenharmony_ci	{Opt_usrquota, "usrquota"},
2238c2ecf20Sopenharmony_ci	{Opt_grpquota, "grpquota"},
2248c2ecf20Sopenharmony_ci	{Opt_uid, "uid=%u"},
2258c2ecf20Sopenharmony_ci	{Opt_gid, "gid=%u"},
2268c2ecf20Sopenharmony_ci	{Opt_umask, "umask=%u"},
2278c2ecf20Sopenharmony_ci	{Opt_discard, "discard"},
2288c2ecf20Sopenharmony_ci	{Opt_nodiscard, "nodiscard"},
2298c2ecf20Sopenharmony_ci	{Opt_discard_minblk, "discard=%u"},
2308c2ecf20Sopenharmony_ci	{Opt_err, NULL}
2318c2ecf20Sopenharmony_ci};
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_cistatic int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
2348c2ecf20Sopenharmony_ci			 int *flag)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	void *nls_map = (void *)-1;	/* -1: no change;  NULL: none */
2378c2ecf20Sopenharmony_ci	char *p;
2388c2ecf20Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	*newLVSize = 0;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (!options)
2438c2ecf20Sopenharmony_ci		return 1;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	while ((p = strsep(&options, ",")) != NULL) {
2468c2ecf20Sopenharmony_ci		substring_t args[MAX_OPT_ARGS];
2478c2ecf20Sopenharmony_ci		int token;
2488c2ecf20Sopenharmony_ci		if (!*p)
2498c2ecf20Sopenharmony_ci			continue;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci		token = match_token(p, tokens, args);
2528c2ecf20Sopenharmony_ci		switch (token) {
2538c2ecf20Sopenharmony_ci		case Opt_integrity:
2548c2ecf20Sopenharmony_ci			*flag &= ~JFS_NOINTEGRITY;
2558c2ecf20Sopenharmony_ci			break;
2568c2ecf20Sopenharmony_ci		case Opt_nointegrity:
2578c2ecf20Sopenharmony_ci			*flag |= JFS_NOINTEGRITY;
2588c2ecf20Sopenharmony_ci			break;
2598c2ecf20Sopenharmony_ci		case Opt_ignore:
2608c2ecf20Sopenharmony_ci			/* Silently ignore the quota options */
2618c2ecf20Sopenharmony_ci			/* Don't do anything ;-) */
2628c2ecf20Sopenharmony_ci			break;
2638c2ecf20Sopenharmony_ci		case Opt_iocharset:
2648c2ecf20Sopenharmony_ci			if (nls_map && nls_map != (void *) -1)
2658c2ecf20Sopenharmony_ci				unload_nls(nls_map);
2668c2ecf20Sopenharmony_ci			if (!strcmp(args[0].from, "none"))
2678c2ecf20Sopenharmony_ci				nls_map = NULL;
2688c2ecf20Sopenharmony_ci			else {
2698c2ecf20Sopenharmony_ci				nls_map = load_nls(args[0].from);
2708c2ecf20Sopenharmony_ci				if (!nls_map) {
2718c2ecf20Sopenharmony_ci					pr_err("JFS: charset not found\n");
2728c2ecf20Sopenharmony_ci					goto cleanup;
2738c2ecf20Sopenharmony_ci				}
2748c2ecf20Sopenharmony_ci			}
2758c2ecf20Sopenharmony_ci			break;
2768c2ecf20Sopenharmony_ci		case Opt_resize:
2778c2ecf20Sopenharmony_ci		{
2788c2ecf20Sopenharmony_ci			char *resize = args[0].from;
2798c2ecf20Sopenharmony_ci			int rc = kstrtoll(resize, 0, newLVSize);
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci			if (rc)
2828c2ecf20Sopenharmony_ci				goto cleanup;
2838c2ecf20Sopenharmony_ci			break;
2848c2ecf20Sopenharmony_ci		}
2858c2ecf20Sopenharmony_ci		case Opt_resize_nosize:
2868c2ecf20Sopenharmony_ci		{
2878c2ecf20Sopenharmony_ci			*newLVSize = i_size_read(sb->s_bdev->bd_inode) >>
2888c2ecf20Sopenharmony_ci				sb->s_blocksize_bits;
2898c2ecf20Sopenharmony_ci			if (*newLVSize == 0)
2908c2ecf20Sopenharmony_ci				pr_err("JFS: Cannot determine volume size\n");
2918c2ecf20Sopenharmony_ci			break;
2928c2ecf20Sopenharmony_ci		}
2938c2ecf20Sopenharmony_ci		case Opt_errors:
2948c2ecf20Sopenharmony_ci		{
2958c2ecf20Sopenharmony_ci			char *errors = args[0].from;
2968c2ecf20Sopenharmony_ci			if (!errors || !*errors)
2978c2ecf20Sopenharmony_ci				goto cleanup;
2988c2ecf20Sopenharmony_ci			if (!strcmp(errors, "continue")) {
2998c2ecf20Sopenharmony_ci				*flag &= ~JFS_ERR_REMOUNT_RO;
3008c2ecf20Sopenharmony_ci				*flag &= ~JFS_ERR_PANIC;
3018c2ecf20Sopenharmony_ci				*flag |= JFS_ERR_CONTINUE;
3028c2ecf20Sopenharmony_ci			} else if (!strcmp(errors, "remount-ro")) {
3038c2ecf20Sopenharmony_ci				*flag &= ~JFS_ERR_CONTINUE;
3048c2ecf20Sopenharmony_ci				*flag &= ~JFS_ERR_PANIC;
3058c2ecf20Sopenharmony_ci				*flag |= JFS_ERR_REMOUNT_RO;
3068c2ecf20Sopenharmony_ci			} else if (!strcmp(errors, "panic")) {
3078c2ecf20Sopenharmony_ci				*flag &= ~JFS_ERR_CONTINUE;
3088c2ecf20Sopenharmony_ci				*flag &= ~JFS_ERR_REMOUNT_RO;
3098c2ecf20Sopenharmony_ci				*flag |= JFS_ERR_PANIC;
3108c2ecf20Sopenharmony_ci			} else {
3118c2ecf20Sopenharmony_ci				pr_err("JFS: %s is an invalid error handler\n",
3128c2ecf20Sopenharmony_ci				       errors);
3138c2ecf20Sopenharmony_ci				goto cleanup;
3148c2ecf20Sopenharmony_ci			}
3158c2ecf20Sopenharmony_ci			break;
3168c2ecf20Sopenharmony_ci		}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA
3198c2ecf20Sopenharmony_ci		case Opt_quota:
3208c2ecf20Sopenharmony_ci		case Opt_usrquota:
3218c2ecf20Sopenharmony_ci			*flag |= JFS_USRQUOTA;
3228c2ecf20Sopenharmony_ci			break;
3238c2ecf20Sopenharmony_ci		case Opt_grpquota:
3248c2ecf20Sopenharmony_ci			*flag |= JFS_GRPQUOTA;
3258c2ecf20Sopenharmony_ci			break;
3268c2ecf20Sopenharmony_ci#else
3278c2ecf20Sopenharmony_ci		case Opt_usrquota:
3288c2ecf20Sopenharmony_ci		case Opt_grpquota:
3298c2ecf20Sopenharmony_ci		case Opt_quota:
3308c2ecf20Sopenharmony_ci			pr_err("JFS: quota operations not supported\n");
3318c2ecf20Sopenharmony_ci			break;
3328c2ecf20Sopenharmony_ci#endif
3338c2ecf20Sopenharmony_ci		case Opt_uid:
3348c2ecf20Sopenharmony_ci		{
3358c2ecf20Sopenharmony_ci			char *uid = args[0].from;
3368c2ecf20Sopenharmony_ci			uid_t val;
3378c2ecf20Sopenharmony_ci			int rc = kstrtouint(uid, 0, &val);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci			if (rc)
3408c2ecf20Sopenharmony_ci				goto cleanup;
3418c2ecf20Sopenharmony_ci			sbi->uid = make_kuid(current_user_ns(), val);
3428c2ecf20Sopenharmony_ci			if (!uid_valid(sbi->uid))
3438c2ecf20Sopenharmony_ci				goto cleanup;
3448c2ecf20Sopenharmony_ci			break;
3458c2ecf20Sopenharmony_ci		}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci		case Opt_gid:
3488c2ecf20Sopenharmony_ci		{
3498c2ecf20Sopenharmony_ci			char *gid = args[0].from;
3508c2ecf20Sopenharmony_ci			gid_t val;
3518c2ecf20Sopenharmony_ci			int rc = kstrtouint(gid, 0, &val);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci			if (rc)
3548c2ecf20Sopenharmony_ci				goto cleanup;
3558c2ecf20Sopenharmony_ci			sbi->gid = make_kgid(current_user_ns(), val);
3568c2ecf20Sopenharmony_ci			if (!gid_valid(sbi->gid))
3578c2ecf20Sopenharmony_ci				goto cleanup;
3588c2ecf20Sopenharmony_ci			break;
3598c2ecf20Sopenharmony_ci		}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci		case Opt_umask:
3628c2ecf20Sopenharmony_ci		{
3638c2ecf20Sopenharmony_ci			char *umask = args[0].from;
3648c2ecf20Sopenharmony_ci			int rc = kstrtouint(umask, 8, &sbi->umask);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci			if (rc)
3678c2ecf20Sopenharmony_ci				goto cleanup;
3688c2ecf20Sopenharmony_ci			if (sbi->umask & ~0777) {
3698c2ecf20Sopenharmony_ci				pr_err("JFS: Invalid value of umask\n");
3708c2ecf20Sopenharmony_ci				goto cleanup;
3718c2ecf20Sopenharmony_ci			}
3728c2ecf20Sopenharmony_ci			break;
3738c2ecf20Sopenharmony_ci		}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci		case Opt_discard:
3768c2ecf20Sopenharmony_ci		{
3778c2ecf20Sopenharmony_ci			struct request_queue *q = bdev_get_queue(sb->s_bdev);
3788c2ecf20Sopenharmony_ci			/* if set to 1, even copying files will cause
3798c2ecf20Sopenharmony_ci			 * trimming :O
3808c2ecf20Sopenharmony_ci			 * -> user has more control over the online trimming
3818c2ecf20Sopenharmony_ci			 */
3828c2ecf20Sopenharmony_ci			sbi->minblks_trim = 64;
3838c2ecf20Sopenharmony_ci			if (blk_queue_discard(q))
3848c2ecf20Sopenharmony_ci				*flag |= JFS_DISCARD;
3858c2ecf20Sopenharmony_ci			else
3868c2ecf20Sopenharmony_ci				pr_err("JFS: discard option not supported on device\n");
3878c2ecf20Sopenharmony_ci			break;
3888c2ecf20Sopenharmony_ci		}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci		case Opt_nodiscard:
3918c2ecf20Sopenharmony_ci			*flag &= ~JFS_DISCARD;
3928c2ecf20Sopenharmony_ci			break;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci		case Opt_discard_minblk:
3958c2ecf20Sopenharmony_ci		{
3968c2ecf20Sopenharmony_ci			struct request_queue *q = bdev_get_queue(sb->s_bdev);
3978c2ecf20Sopenharmony_ci			char *minblks_trim = args[0].from;
3988c2ecf20Sopenharmony_ci			int rc;
3998c2ecf20Sopenharmony_ci			if (blk_queue_discard(q)) {
4008c2ecf20Sopenharmony_ci				*flag |= JFS_DISCARD;
4018c2ecf20Sopenharmony_ci				rc = kstrtouint(minblks_trim, 0,
4028c2ecf20Sopenharmony_ci						&sbi->minblks_trim);
4038c2ecf20Sopenharmony_ci				if (rc)
4048c2ecf20Sopenharmony_ci					goto cleanup;
4058c2ecf20Sopenharmony_ci			} else
4068c2ecf20Sopenharmony_ci				pr_err("JFS: discard option not supported on device\n");
4078c2ecf20Sopenharmony_ci			break;
4088c2ecf20Sopenharmony_ci		}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci		default:
4118c2ecf20Sopenharmony_ci			printk("jfs: Unrecognized mount option \"%s\" or missing value\n",
4128c2ecf20Sopenharmony_ci			       p);
4138c2ecf20Sopenharmony_ci			goto cleanup;
4148c2ecf20Sopenharmony_ci		}
4158c2ecf20Sopenharmony_ci	}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	if (nls_map != (void *) -1) {
4188c2ecf20Sopenharmony_ci		/* Discard old (if remount) */
4198c2ecf20Sopenharmony_ci		unload_nls(sbi->nls_tab);
4208c2ecf20Sopenharmony_ci		sbi->nls_tab = nls_map;
4218c2ecf20Sopenharmony_ci	}
4228c2ecf20Sopenharmony_ci	return 1;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_cicleanup:
4258c2ecf20Sopenharmony_ci	if (nls_map && nls_map != (void *) -1)
4268c2ecf20Sopenharmony_ci		unload_nls(nls_map);
4278c2ecf20Sopenharmony_ci	return 0;
4288c2ecf20Sopenharmony_ci}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_cistatic int jfs_remount(struct super_block *sb, int *flags, char *data)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	s64 newLVSize = 0;
4338c2ecf20Sopenharmony_ci	int rc = 0;
4348c2ecf20Sopenharmony_ci	int flag = JFS_SBI(sb)->flag;
4358c2ecf20Sopenharmony_ci	int ret;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	sync_filesystem(sb);
4388c2ecf20Sopenharmony_ci	if (!parse_options(data, sb, &newLVSize, &flag))
4398c2ecf20Sopenharmony_ci		return -EINVAL;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	if (newLVSize) {
4428c2ecf20Sopenharmony_ci		if (sb_rdonly(sb)) {
4438c2ecf20Sopenharmony_ci			pr_err("JFS: resize requires volume to be mounted read-write\n");
4448c2ecf20Sopenharmony_ci			return -EROFS;
4458c2ecf20Sopenharmony_ci		}
4468c2ecf20Sopenharmony_ci		rc = jfs_extendfs(sb, newLVSize, 0);
4478c2ecf20Sopenharmony_ci		if (rc)
4488c2ecf20Sopenharmony_ci			return rc;
4498c2ecf20Sopenharmony_ci	}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (sb_rdonly(sb) && !(*flags & SB_RDONLY)) {
4528c2ecf20Sopenharmony_ci		/*
4538c2ecf20Sopenharmony_ci		 * Invalidate any previously read metadata.  fsck may have
4548c2ecf20Sopenharmony_ci		 * changed the on-disk data since we mounted r/o
4558c2ecf20Sopenharmony_ci		 */
4568c2ecf20Sopenharmony_ci		truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0);
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci		JFS_SBI(sb)->flag = flag;
4598c2ecf20Sopenharmony_ci		ret = jfs_mount_rw(sb, 1);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci		/* mark the fs r/w for quota activity */
4628c2ecf20Sopenharmony_ci		sb->s_flags &= ~SB_RDONLY;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci		dquot_resume(sb, -1);
4658c2ecf20Sopenharmony_ci		return ret;
4668c2ecf20Sopenharmony_ci	}
4678c2ecf20Sopenharmony_ci	if (!sb_rdonly(sb) && (*flags & SB_RDONLY)) {
4688c2ecf20Sopenharmony_ci		rc = dquot_suspend(sb, -1);
4698c2ecf20Sopenharmony_ci		if (rc < 0)
4708c2ecf20Sopenharmony_ci			return rc;
4718c2ecf20Sopenharmony_ci		rc = jfs_umount_rw(sb);
4728c2ecf20Sopenharmony_ci		JFS_SBI(sb)->flag = flag;
4738c2ecf20Sopenharmony_ci		return rc;
4748c2ecf20Sopenharmony_ci	}
4758c2ecf20Sopenharmony_ci	if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY))
4768c2ecf20Sopenharmony_ci		if (!sb_rdonly(sb)) {
4778c2ecf20Sopenharmony_ci			rc = jfs_umount_rw(sb);
4788c2ecf20Sopenharmony_ci			if (rc)
4798c2ecf20Sopenharmony_ci				return rc;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci			JFS_SBI(sb)->flag = flag;
4828c2ecf20Sopenharmony_ci			ret = jfs_mount_rw(sb, 1);
4838c2ecf20Sopenharmony_ci			return ret;
4848c2ecf20Sopenharmony_ci		}
4858c2ecf20Sopenharmony_ci	JFS_SBI(sb)->flag = flag;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	return 0;
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_cistatic int jfs_fill_super(struct super_block *sb, void *data, int silent)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	struct jfs_sb_info *sbi;
4938c2ecf20Sopenharmony_ci	struct inode *inode;
4948c2ecf20Sopenharmony_ci	int rc;
4958c2ecf20Sopenharmony_ci	s64 newLVSize = 0;
4968c2ecf20Sopenharmony_ci	int flag, ret = -EINVAL;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	jfs_info("In jfs_read_super: s_flags=0x%lx", sb->s_flags);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	sbi = kzalloc(sizeof(struct jfs_sb_info), GFP_KERNEL);
5018c2ecf20Sopenharmony_ci	if (!sbi)
5028c2ecf20Sopenharmony_ci		return -ENOMEM;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	sb->s_fs_info = sbi;
5058c2ecf20Sopenharmony_ci	sb->s_max_links = JFS_LINK_MAX;
5068c2ecf20Sopenharmony_ci	sb->s_time_min = 0;
5078c2ecf20Sopenharmony_ci	sb->s_time_max = U32_MAX;
5088c2ecf20Sopenharmony_ci	sbi->sb = sb;
5098c2ecf20Sopenharmony_ci	sbi->uid = INVALID_UID;
5108c2ecf20Sopenharmony_ci	sbi->gid = INVALID_GID;
5118c2ecf20Sopenharmony_ci	sbi->umask = -1;
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	/* initialize the mount flag and determine the default error handler */
5148c2ecf20Sopenharmony_ci	flag = JFS_ERR_REMOUNT_RO;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	if (!parse_options((char *) data, sb, &newLVSize, &flag))
5178c2ecf20Sopenharmony_ci		goto out_kfree;
5188c2ecf20Sopenharmony_ci	sbi->flag = flag;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci#ifdef CONFIG_JFS_POSIX_ACL
5218c2ecf20Sopenharmony_ci	sb->s_flags |= SB_POSIXACL;
5228c2ecf20Sopenharmony_ci#endif
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	if (newLVSize) {
5258c2ecf20Sopenharmony_ci		pr_err("resize option for remount only\n");
5268c2ecf20Sopenharmony_ci		goto out_kfree;
5278c2ecf20Sopenharmony_ci	}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	/*
5308c2ecf20Sopenharmony_ci	 * Initialize blocksize to 4K.
5318c2ecf20Sopenharmony_ci	 */
5328c2ecf20Sopenharmony_ci	sb_set_blocksize(sb, PSIZE);
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	/*
5358c2ecf20Sopenharmony_ci	 * Set method vectors.
5368c2ecf20Sopenharmony_ci	 */
5378c2ecf20Sopenharmony_ci	sb->s_op = &jfs_super_operations;
5388c2ecf20Sopenharmony_ci	sb->s_export_op = &jfs_export_operations;
5398c2ecf20Sopenharmony_ci	sb->s_xattr = jfs_xattr_handlers;
5408c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA
5418c2ecf20Sopenharmony_ci	sb->dq_op = &dquot_operations;
5428c2ecf20Sopenharmony_ci	sb->s_qcop = &jfs_quotactl_ops;
5438c2ecf20Sopenharmony_ci	sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
5448c2ecf20Sopenharmony_ci#endif
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	/*
5478c2ecf20Sopenharmony_ci	 * Initialize direct-mapping inode/address-space
5488c2ecf20Sopenharmony_ci	 */
5498c2ecf20Sopenharmony_ci	inode = new_inode(sb);
5508c2ecf20Sopenharmony_ci	if (inode == NULL) {
5518c2ecf20Sopenharmony_ci		ret = -ENOMEM;
5528c2ecf20Sopenharmony_ci		goto out_unload;
5538c2ecf20Sopenharmony_ci	}
5548c2ecf20Sopenharmony_ci	inode->i_ino = 0;
5558c2ecf20Sopenharmony_ci	inode->i_size = i_size_read(sb->s_bdev->bd_inode);
5568c2ecf20Sopenharmony_ci	inode->i_mapping->a_ops = &jfs_metapage_aops;
5578c2ecf20Sopenharmony_ci	inode_fake_hash(inode);
5588c2ecf20Sopenharmony_ci	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	sbi->direct_inode = inode;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	rc = jfs_mount(sb);
5638c2ecf20Sopenharmony_ci	if (rc) {
5648c2ecf20Sopenharmony_ci		if (!silent)
5658c2ecf20Sopenharmony_ci			jfs_err("jfs_mount failed w/return code = %d", rc);
5668c2ecf20Sopenharmony_ci		goto out_mount_failed;
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci	if (sb_rdonly(sb))
5698c2ecf20Sopenharmony_ci		sbi->log = NULL;
5708c2ecf20Sopenharmony_ci	else {
5718c2ecf20Sopenharmony_ci		rc = jfs_mount_rw(sb, 0);
5728c2ecf20Sopenharmony_ci		if (rc) {
5738c2ecf20Sopenharmony_ci			if (!silent) {
5748c2ecf20Sopenharmony_ci				jfs_err("jfs_mount_rw failed, return code = %d",
5758c2ecf20Sopenharmony_ci					rc);
5768c2ecf20Sopenharmony_ci			}
5778c2ecf20Sopenharmony_ci			goto out_no_rw;
5788c2ecf20Sopenharmony_ci		}
5798c2ecf20Sopenharmony_ci	}
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	sb->s_magic = JFS_SUPER_MAGIC;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	if (sbi->mntflag & JFS_OS2)
5848c2ecf20Sopenharmony_ci		sb->s_d_op = &jfs_ci_dentry_operations;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	inode = jfs_iget(sb, ROOT_I);
5878c2ecf20Sopenharmony_ci	if (IS_ERR(inode)) {
5888c2ecf20Sopenharmony_ci		ret = PTR_ERR(inode);
5898c2ecf20Sopenharmony_ci		goto out_no_rw;
5908c2ecf20Sopenharmony_ci	}
5918c2ecf20Sopenharmony_ci	sb->s_root = d_make_root(inode);
5928c2ecf20Sopenharmony_ci	if (!sb->s_root)
5938c2ecf20Sopenharmony_ci		goto out_no_root;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	/* logical blocks are represented by 40 bits in pxd_t, etc.
5968c2ecf20Sopenharmony_ci	 * and page cache is indexed by long
5978c2ecf20Sopenharmony_ci	 */
5988c2ecf20Sopenharmony_ci	sb->s_maxbytes = min(((loff_t)sb->s_blocksize) << 40, MAX_LFS_FILESIZE);
5998c2ecf20Sopenharmony_ci	sb->s_time_gran = 1;
6008c2ecf20Sopenharmony_ci	return 0;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ciout_no_root:
6038c2ecf20Sopenharmony_ci	jfs_err("jfs_read_super: get root dentry failed");
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ciout_no_rw:
6068c2ecf20Sopenharmony_ci	rc = jfs_umount(sb);
6078c2ecf20Sopenharmony_ci	if (rc)
6088c2ecf20Sopenharmony_ci		jfs_err("jfs_umount failed with return code %d", rc);
6098c2ecf20Sopenharmony_ciout_mount_failed:
6108c2ecf20Sopenharmony_ci	filemap_write_and_wait(sbi->direct_inode->i_mapping);
6118c2ecf20Sopenharmony_ci	truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
6128c2ecf20Sopenharmony_ci	make_bad_inode(sbi->direct_inode);
6138c2ecf20Sopenharmony_ci	iput(sbi->direct_inode);
6148c2ecf20Sopenharmony_ci	sbi->direct_inode = NULL;
6158c2ecf20Sopenharmony_ciout_unload:
6168c2ecf20Sopenharmony_ci	unload_nls(sbi->nls_tab);
6178c2ecf20Sopenharmony_ciout_kfree:
6188c2ecf20Sopenharmony_ci	kfree(sbi);
6198c2ecf20Sopenharmony_ci	return ret;
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic int jfs_freeze(struct super_block *sb)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
6258c2ecf20Sopenharmony_ci	struct jfs_log *log = sbi->log;
6268c2ecf20Sopenharmony_ci	int rc = 0;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	if (!sb_rdonly(sb)) {
6298c2ecf20Sopenharmony_ci		txQuiesce(sb);
6308c2ecf20Sopenharmony_ci		rc = lmLogShutdown(log);
6318c2ecf20Sopenharmony_ci		if (rc) {
6328c2ecf20Sopenharmony_ci			jfs_error(sb, "lmLogShutdown failed\n");
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci			/* let operations fail rather than hang */
6358c2ecf20Sopenharmony_ci			txResume(sb);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci			return rc;
6388c2ecf20Sopenharmony_ci		}
6398c2ecf20Sopenharmony_ci		rc = updateSuper(sb, FM_CLEAN);
6408c2ecf20Sopenharmony_ci		if (rc) {
6418c2ecf20Sopenharmony_ci			jfs_err("jfs_freeze: updateSuper failed");
6428c2ecf20Sopenharmony_ci			/*
6438c2ecf20Sopenharmony_ci			 * Don't fail here. Everything succeeded except
6448c2ecf20Sopenharmony_ci			 * marking the superblock clean, so there's really
6458c2ecf20Sopenharmony_ci			 * no harm in leaving it frozen for now.
6468c2ecf20Sopenharmony_ci			 */
6478c2ecf20Sopenharmony_ci		}
6488c2ecf20Sopenharmony_ci	}
6498c2ecf20Sopenharmony_ci	return 0;
6508c2ecf20Sopenharmony_ci}
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_cistatic int jfs_unfreeze(struct super_block *sb)
6538c2ecf20Sopenharmony_ci{
6548c2ecf20Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
6558c2ecf20Sopenharmony_ci	struct jfs_log *log = sbi->log;
6568c2ecf20Sopenharmony_ci	int rc = 0;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	if (!sb_rdonly(sb)) {
6598c2ecf20Sopenharmony_ci		rc = updateSuper(sb, FM_MOUNT);
6608c2ecf20Sopenharmony_ci		if (rc) {
6618c2ecf20Sopenharmony_ci			jfs_error(sb, "updateSuper failed\n");
6628c2ecf20Sopenharmony_ci			goto out;
6638c2ecf20Sopenharmony_ci		}
6648c2ecf20Sopenharmony_ci		rc = lmLogInit(log);
6658c2ecf20Sopenharmony_ci		if (rc)
6668c2ecf20Sopenharmony_ci			jfs_error(sb, "lmLogInit failed\n");
6678c2ecf20Sopenharmony_ciout:
6688c2ecf20Sopenharmony_ci		txResume(sb);
6698c2ecf20Sopenharmony_ci	}
6708c2ecf20Sopenharmony_ci	return rc;
6718c2ecf20Sopenharmony_ci}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_cistatic struct dentry *jfs_do_mount(struct file_system_type *fs_type,
6748c2ecf20Sopenharmony_ci	int flags, const char *dev_name, void *data)
6758c2ecf20Sopenharmony_ci{
6768c2ecf20Sopenharmony_ci	return mount_bdev(fs_type, flags, dev_name, data, jfs_fill_super);
6778c2ecf20Sopenharmony_ci}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_cistatic int jfs_sync_fs(struct super_block *sb, int wait)
6808c2ecf20Sopenharmony_ci{
6818c2ecf20Sopenharmony_ci	struct jfs_log *log = JFS_SBI(sb)->log;
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	/* log == NULL indicates read-only mount */
6848c2ecf20Sopenharmony_ci	if (log) {
6858c2ecf20Sopenharmony_ci		/*
6868c2ecf20Sopenharmony_ci		 * Write quota structures to quota file, sync_blockdev() will
6878c2ecf20Sopenharmony_ci		 * write them to disk later
6888c2ecf20Sopenharmony_ci		 */
6898c2ecf20Sopenharmony_ci		dquot_writeback_dquots(sb, -1);
6908c2ecf20Sopenharmony_ci		jfs_flush_journal(log, wait);
6918c2ecf20Sopenharmony_ci		jfs_syncpt(log, 0);
6928c2ecf20Sopenharmony_ci	}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	return 0;
6958c2ecf20Sopenharmony_ci}
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_cistatic int jfs_show_options(struct seq_file *seq, struct dentry *root)
6988c2ecf20Sopenharmony_ci{
6998c2ecf20Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(root->d_sb);
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	if (uid_valid(sbi->uid))
7028c2ecf20Sopenharmony_ci		seq_printf(seq, ",uid=%d", from_kuid(&init_user_ns, sbi->uid));
7038c2ecf20Sopenharmony_ci	if (gid_valid(sbi->gid))
7048c2ecf20Sopenharmony_ci		seq_printf(seq, ",gid=%d", from_kgid(&init_user_ns, sbi->gid));
7058c2ecf20Sopenharmony_ci	if (sbi->umask != -1)
7068c2ecf20Sopenharmony_ci		seq_printf(seq, ",umask=%03o", sbi->umask);
7078c2ecf20Sopenharmony_ci	if (sbi->flag & JFS_NOINTEGRITY)
7088c2ecf20Sopenharmony_ci		seq_puts(seq, ",nointegrity");
7098c2ecf20Sopenharmony_ci	if (sbi->flag & JFS_DISCARD)
7108c2ecf20Sopenharmony_ci		seq_printf(seq, ",discard=%u", sbi->minblks_trim);
7118c2ecf20Sopenharmony_ci	if (sbi->nls_tab)
7128c2ecf20Sopenharmony_ci		seq_printf(seq, ",iocharset=%s", sbi->nls_tab->charset);
7138c2ecf20Sopenharmony_ci	if (sbi->flag & JFS_ERR_CONTINUE)
7148c2ecf20Sopenharmony_ci		seq_printf(seq, ",errors=continue");
7158c2ecf20Sopenharmony_ci	if (sbi->flag & JFS_ERR_PANIC)
7168c2ecf20Sopenharmony_ci		seq_printf(seq, ",errors=panic");
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA
7198c2ecf20Sopenharmony_ci	if (sbi->flag & JFS_USRQUOTA)
7208c2ecf20Sopenharmony_ci		seq_puts(seq, ",usrquota");
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	if (sbi->flag & JFS_GRPQUOTA)
7238c2ecf20Sopenharmony_ci		seq_puts(seq, ",grpquota");
7248c2ecf20Sopenharmony_ci#endif
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	return 0;
7278c2ecf20Sopenharmony_ci}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci/* Read data from quotafile - avoid pagecache and such because we cannot afford
7328c2ecf20Sopenharmony_ci * acquiring the locks... As quota files are never truncated and quota code
7338c2ecf20Sopenharmony_ci * itself serializes the operations (and no one else should touch the files)
7348c2ecf20Sopenharmony_ci * we don't have to be afraid of races */
7358c2ecf20Sopenharmony_cistatic ssize_t jfs_quota_read(struct super_block *sb, int type, char *data,
7368c2ecf20Sopenharmony_ci			      size_t len, loff_t off)
7378c2ecf20Sopenharmony_ci{
7388c2ecf20Sopenharmony_ci	struct inode *inode = sb_dqopt(sb)->files[type];
7398c2ecf20Sopenharmony_ci	sector_t blk = off >> sb->s_blocksize_bits;
7408c2ecf20Sopenharmony_ci	int err = 0;
7418c2ecf20Sopenharmony_ci	int offset = off & (sb->s_blocksize - 1);
7428c2ecf20Sopenharmony_ci	int tocopy;
7438c2ecf20Sopenharmony_ci	size_t toread;
7448c2ecf20Sopenharmony_ci	struct buffer_head tmp_bh;
7458c2ecf20Sopenharmony_ci	struct buffer_head *bh;
7468c2ecf20Sopenharmony_ci	loff_t i_size = i_size_read(inode);
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	if (off > i_size)
7498c2ecf20Sopenharmony_ci		return 0;
7508c2ecf20Sopenharmony_ci	if (off+len > i_size)
7518c2ecf20Sopenharmony_ci		len = i_size-off;
7528c2ecf20Sopenharmony_ci	toread = len;
7538c2ecf20Sopenharmony_ci	while (toread > 0) {
7548c2ecf20Sopenharmony_ci		tocopy = sb->s_blocksize - offset < toread ?
7558c2ecf20Sopenharmony_ci				sb->s_blocksize - offset : toread;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci		tmp_bh.b_state = 0;
7588c2ecf20Sopenharmony_ci		tmp_bh.b_size = i_blocksize(inode);
7598c2ecf20Sopenharmony_ci		err = jfs_get_block(inode, blk, &tmp_bh, 0);
7608c2ecf20Sopenharmony_ci		if (err)
7618c2ecf20Sopenharmony_ci			return err;
7628c2ecf20Sopenharmony_ci		if (!buffer_mapped(&tmp_bh))	/* A hole? */
7638c2ecf20Sopenharmony_ci			memset(data, 0, tocopy);
7648c2ecf20Sopenharmony_ci		else {
7658c2ecf20Sopenharmony_ci			bh = sb_bread(sb, tmp_bh.b_blocknr);
7668c2ecf20Sopenharmony_ci			if (!bh)
7678c2ecf20Sopenharmony_ci				return -EIO;
7688c2ecf20Sopenharmony_ci			memcpy(data, bh->b_data+offset, tocopy);
7698c2ecf20Sopenharmony_ci			brelse(bh);
7708c2ecf20Sopenharmony_ci		}
7718c2ecf20Sopenharmony_ci		offset = 0;
7728c2ecf20Sopenharmony_ci		toread -= tocopy;
7738c2ecf20Sopenharmony_ci		data += tocopy;
7748c2ecf20Sopenharmony_ci		blk++;
7758c2ecf20Sopenharmony_ci	}
7768c2ecf20Sopenharmony_ci	return len;
7778c2ecf20Sopenharmony_ci}
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci/* Write to quotafile */
7808c2ecf20Sopenharmony_cistatic ssize_t jfs_quota_write(struct super_block *sb, int type,
7818c2ecf20Sopenharmony_ci			       const char *data, size_t len, loff_t off)
7828c2ecf20Sopenharmony_ci{
7838c2ecf20Sopenharmony_ci	struct inode *inode = sb_dqopt(sb)->files[type];
7848c2ecf20Sopenharmony_ci	sector_t blk = off >> sb->s_blocksize_bits;
7858c2ecf20Sopenharmony_ci	int err = 0;
7868c2ecf20Sopenharmony_ci	int offset = off & (sb->s_blocksize - 1);
7878c2ecf20Sopenharmony_ci	int tocopy;
7888c2ecf20Sopenharmony_ci	size_t towrite = len;
7898c2ecf20Sopenharmony_ci	struct buffer_head tmp_bh;
7908c2ecf20Sopenharmony_ci	struct buffer_head *bh;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	inode_lock(inode);
7938c2ecf20Sopenharmony_ci	while (towrite > 0) {
7948c2ecf20Sopenharmony_ci		tocopy = sb->s_blocksize - offset < towrite ?
7958c2ecf20Sopenharmony_ci				sb->s_blocksize - offset : towrite;
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci		tmp_bh.b_state = 0;
7988c2ecf20Sopenharmony_ci		tmp_bh.b_size = i_blocksize(inode);
7998c2ecf20Sopenharmony_ci		err = jfs_get_block(inode, blk, &tmp_bh, 1);
8008c2ecf20Sopenharmony_ci		if (err)
8018c2ecf20Sopenharmony_ci			goto out;
8028c2ecf20Sopenharmony_ci		if (offset || tocopy != sb->s_blocksize)
8038c2ecf20Sopenharmony_ci			bh = sb_bread(sb, tmp_bh.b_blocknr);
8048c2ecf20Sopenharmony_ci		else
8058c2ecf20Sopenharmony_ci			bh = sb_getblk(sb, tmp_bh.b_blocknr);
8068c2ecf20Sopenharmony_ci		if (!bh) {
8078c2ecf20Sopenharmony_ci			err = -EIO;
8088c2ecf20Sopenharmony_ci			goto out;
8098c2ecf20Sopenharmony_ci		}
8108c2ecf20Sopenharmony_ci		lock_buffer(bh);
8118c2ecf20Sopenharmony_ci		memcpy(bh->b_data+offset, data, tocopy);
8128c2ecf20Sopenharmony_ci		flush_dcache_page(bh->b_page);
8138c2ecf20Sopenharmony_ci		set_buffer_uptodate(bh);
8148c2ecf20Sopenharmony_ci		mark_buffer_dirty(bh);
8158c2ecf20Sopenharmony_ci		unlock_buffer(bh);
8168c2ecf20Sopenharmony_ci		brelse(bh);
8178c2ecf20Sopenharmony_ci		offset = 0;
8188c2ecf20Sopenharmony_ci		towrite -= tocopy;
8198c2ecf20Sopenharmony_ci		data += tocopy;
8208c2ecf20Sopenharmony_ci		blk++;
8218c2ecf20Sopenharmony_ci	}
8228c2ecf20Sopenharmony_ciout:
8238c2ecf20Sopenharmony_ci	if (len == towrite) {
8248c2ecf20Sopenharmony_ci		inode_unlock(inode);
8258c2ecf20Sopenharmony_ci		return err;
8268c2ecf20Sopenharmony_ci	}
8278c2ecf20Sopenharmony_ci	if (inode->i_size < off+len-towrite)
8288c2ecf20Sopenharmony_ci		i_size_write(inode, off+len-towrite);
8298c2ecf20Sopenharmony_ci	inode->i_mtime = inode->i_ctime = current_time(inode);
8308c2ecf20Sopenharmony_ci	mark_inode_dirty(inode);
8318c2ecf20Sopenharmony_ci	inode_unlock(inode);
8328c2ecf20Sopenharmony_ci	return len - towrite;
8338c2ecf20Sopenharmony_ci}
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_cistatic struct dquot **jfs_get_dquots(struct inode *inode)
8368c2ecf20Sopenharmony_ci{
8378c2ecf20Sopenharmony_ci	return JFS_IP(inode)->i_dquot;
8388c2ecf20Sopenharmony_ci}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_cistatic int jfs_quota_on(struct super_block *sb, int type, int format_id,
8418c2ecf20Sopenharmony_ci			const struct path *path)
8428c2ecf20Sopenharmony_ci{
8438c2ecf20Sopenharmony_ci	int err;
8448c2ecf20Sopenharmony_ci	struct inode *inode;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	err = dquot_quota_on(sb, type, format_id, path);
8478c2ecf20Sopenharmony_ci	if (err)
8488c2ecf20Sopenharmony_ci		return err;
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	inode = d_inode(path->dentry);
8518c2ecf20Sopenharmony_ci	inode_lock(inode);
8528c2ecf20Sopenharmony_ci	JFS_IP(inode)->mode2 |= JFS_NOATIME_FL | JFS_IMMUTABLE_FL;
8538c2ecf20Sopenharmony_ci	inode_set_flags(inode, S_NOATIME | S_IMMUTABLE,
8548c2ecf20Sopenharmony_ci			S_NOATIME | S_IMMUTABLE);
8558c2ecf20Sopenharmony_ci	inode_unlock(inode);
8568c2ecf20Sopenharmony_ci	mark_inode_dirty(inode);
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	return 0;
8598c2ecf20Sopenharmony_ci}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_cistatic int jfs_quota_off(struct super_block *sb, int type)
8628c2ecf20Sopenharmony_ci{
8638c2ecf20Sopenharmony_ci	struct inode *inode = sb_dqopt(sb)->files[type];
8648c2ecf20Sopenharmony_ci	int err;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	if (!inode || !igrab(inode))
8678c2ecf20Sopenharmony_ci		goto out;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	err = dquot_quota_off(sb, type);
8708c2ecf20Sopenharmony_ci	if (err)
8718c2ecf20Sopenharmony_ci		goto out_put;
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	inode_lock(inode);
8748c2ecf20Sopenharmony_ci	JFS_IP(inode)->mode2 &= ~(JFS_NOATIME_FL | JFS_IMMUTABLE_FL);
8758c2ecf20Sopenharmony_ci	inode_set_flags(inode, 0, S_NOATIME | S_IMMUTABLE);
8768c2ecf20Sopenharmony_ci	inode_unlock(inode);
8778c2ecf20Sopenharmony_ci	mark_inode_dirty(inode);
8788c2ecf20Sopenharmony_ciout_put:
8798c2ecf20Sopenharmony_ci	iput(inode);
8808c2ecf20Sopenharmony_ci	return err;
8818c2ecf20Sopenharmony_ciout:
8828c2ecf20Sopenharmony_ci	return dquot_quota_off(sb, type);
8838c2ecf20Sopenharmony_ci}
8848c2ecf20Sopenharmony_ci#endif
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_cistatic const struct super_operations jfs_super_operations = {
8878c2ecf20Sopenharmony_ci	.alloc_inode	= jfs_alloc_inode,
8888c2ecf20Sopenharmony_ci	.free_inode	= jfs_free_inode,
8898c2ecf20Sopenharmony_ci	.dirty_inode	= jfs_dirty_inode,
8908c2ecf20Sopenharmony_ci	.write_inode	= jfs_write_inode,
8918c2ecf20Sopenharmony_ci	.evict_inode	= jfs_evict_inode,
8928c2ecf20Sopenharmony_ci	.put_super	= jfs_put_super,
8938c2ecf20Sopenharmony_ci	.sync_fs	= jfs_sync_fs,
8948c2ecf20Sopenharmony_ci	.freeze_fs	= jfs_freeze,
8958c2ecf20Sopenharmony_ci	.unfreeze_fs	= jfs_unfreeze,
8968c2ecf20Sopenharmony_ci	.statfs		= jfs_statfs,
8978c2ecf20Sopenharmony_ci	.remount_fs	= jfs_remount,
8988c2ecf20Sopenharmony_ci	.show_options	= jfs_show_options,
8998c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA
9008c2ecf20Sopenharmony_ci	.quota_read	= jfs_quota_read,
9018c2ecf20Sopenharmony_ci	.quota_write	= jfs_quota_write,
9028c2ecf20Sopenharmony_ci	.get_dquots	= jfs_get_dquots,
9038c2ecf20Sopenharmony_ci#endif
9048c2ecf20Sopenharmony_ci};
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_cistatic const struct export_operations jfs_export_operations = {
9078c2ecf20Sopenharmony_ci	.fh_to_dentry	= jfs_fh_to_dentry,
9088c2ecf20Sopenharmony_ci	.fh_to_parent	= jfs_fh_to_parent,
9098c2ecf20Sopenharmony_ci	.get_parent	= jfs_get_parent,
9108c2ecf20Sopenharmony_ci};
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_cistatic struct file_system_type jfs_fs_type = {
9138c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
9148c2ecf20Sopenharmony_ci	.name		= "jfs",
9158c2ecf20Sopenharmony_ci	.mount		= jfs_do_mount,
9168c2ecf20Sopenharmony_ci	.kill_sb	= kill_block_super,
9178c2ecf20Sopenharmony_ci	.fs_flags	= FS_REQUIRES_DEV,
9188c2ecf20Sopenharmony_ci};
9198c2ecf20Sopenharmony_ciMODULE_ALIAS_FS("jfs");
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_cistatic void init_once(void *foo)
9228c2ecf20Sopenharmony_ci{
9238c2ecf20Sopenharmony_ci	struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	memset(jfs_ip, 0, sizeof(struct jfs_inode_info));
9268c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
9278c2ecf20Sopenharmony_ci	init_rwsem(&jfs_ip->rdwrlock);
9288c2ecf20Sopenharmony_ci	mutex_init(&jfs_ip->commit_mutex);
9298c2ecf20Sopenharmony_ci	init_rwsem(&jfs_ip->xattr_sem);
9308c2ecf20Sopenharmony_ci	spin_lock_init(&jfs_ip->ag_lock);
9318c2ecf20Sopenharmony_ci	jfs_ip->active_ag = -1;
9328c2ecf20Sopenharmony_ci	inode_init_once(&jfs_ip->vfs_inode);
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_cistatic int __init init_jfs_fs(void)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	int i;
9388c2ecf20Sopenharmony_ci	int rc;
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	jfs_inode_cachep =
9418c2ecf20Sopenharmony_ci	    kmem_cache_create_usercopy("jfs_ip", sizeof(struct jfs_inode_info),
9428c2ecf20Sopenharmony_ci			0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|SLAB_ACCOUNT,
9438c2ecf20Sopenharmony_ci			offsetof(struct jfs_inode_info, i_inline), IDATASIZE,
9448c2ecf20Sopenharmony_ci			init_once);
9458c2ecf20Sopenharmony_ci	if (jfs_inode_cachep == NULL)
9468c2ecf20Sopenharmony_ci		return -ENOMEM;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	/*
9498c2ecf20Sopenharmony_ci	 * Metapage initialization
9508c2ecf20Sopenharmony_ci	 */
9518c2ecf20Sopenharmony_ci	rc = metapage_init();
9528c2ecf20Sopenharmony_ci	if (rc) {
9538c2ecf20Sopenharmony_ci		jfs_err("metapage_init failed w/rc = %d", rc);
9548c2ecf20Sopenharmony_ci		goto free_slab;
9558c2ecf20Sopenharmony_ci	}
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci	/*
9588c2ecf20Sopenharmony_ci	 * Transaction Manager initialization
9598c2ecf20Sopenharmony_ci	 */
9608c2ecf20Sopenharmony_ci	rc = txInit();
9618c2ecf20Sopenharmony_ci	if (rc) {
9628c2ecf20Sopenharmony_ci		jfs_err("txInit failed w/rc = %d", rc);
9638c2ecf20Sopenharmony_ci		goto free_metapage;
9648c2ecf20Sopenharmony_ci	}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	/*
9678c2ecf20Sopenharmony_ci	 * I/O completion thread (endio)
9688c2ecf20Sopenharmony_ci	 */
9698c2ecf20Sopenharmony_ci	jfsIOthread = kthread_run(jfsIOWait, NULL, "jfsIO");
9708c2ecf20Sopenharmony_ci	if (IS_ERR(jfsIOthread)) {
9718c2ecf20Sopenharmony_ci		rc = PTR_ERR(jfsIOthread);
9728c2ecf20Sopenharmony_ci		jfs_err("init_jfs_fs: fork failed w/rc = %d", rc);
9738c2ecf20Sopenharmony_ci		goto end_txmngr;
9748c2ecf20Sopenharmony_ci	}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	if (commit_threads < 1)
9778c2ecf20Sopenharmony_ci		commit_threads = num_online_cpus();
9788c2ecf20Sopenharmony_ci	if (commit_threads > MAX_COMMIT_THREADS)
9798c2ecf20Sopenharmony_ci		commit_threads = MAX_COMMIT_THREADS;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	for (i = 0; i < commit_threads; i++) {
9828c2ecf20Sopenharmony_ci		jfsCommitThread[i] = kthread_run(jfs_lazycommit, NULL,
9838c2ecf20Sopenharmony_ci						 "jfsCommit");
9848c2ecf20Sopenharmony_ci		if (IS_ERR(jfsCommitThread[i])) {
9858c2ecf20Sopenharmony_ci			rc = PTR_ERR(jfsCommitThread[i]);
9868c2ecf20Sopenharmony_ci			jfs_err("init_jfs_fs: fork failed w/rc = %d", rc);
9878c2ecf20Sopenharmony_ci			commit_threads = i;
9888c2ecf20Sopenharmony_ci			goto kill_committask;
9898c2ecf20Sopenharmony_ci		}
9908c2ecf20Sopenharmony_ci	}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	jfsSyncThread = kthread_run(jfs_sync, NULL, "jfsSync");
9938c2ecf20Sopenharmony_ci	if (IS_ERR(jfsSyncThread)) {
9948c2ecf20Sopenharmony_ci		rc = PTR_ERR(jfsSyncThread);
9958c2ecf20Sopenharmony_ci		jfs_err("init_jfs_fs: fork failed w/rc = %d", rc);
9968c2ecf20Sopenharmony_ci		goto kill_committask;
9978c2ecf20Sopenharmony_ci	}
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci#ifdef PROC_FS_JFS
10008c2ecf20Sopenharmony_ci	jfs_proc_init();
10018c2ecf20Sopenharmony_ci#endif
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	rc = register_filesystem(&jfs_fs_type);
10048c2ecf20Sopenharmony_ci	if (!rc)
10058c2ecf20Sopenharmony_ci		return 0;
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci#ifdef PROC_FS_JFS
10088c2ecf20Sopenharmony_ci	jfs_proc_clean();
10098c2ecf20Sopenharmony_ci#endif
10108c2ecf20Sopenharmony_ci	kthread_stop(jfsSyncThread);
10118c2ecf20Sopenharmony_cikill_committask:
10128c2ecf20Sopenharmony_ci	for (i = 0; i < commit_threads; i++)
10138c2ecf20Sopenharmony_ci		kthread_stop(jfsCommitThread[i]);
10148c2ecf20Sopenharmony_ci	kthread_stop(jfsIOthread);
10158c2ecf20Sopenharmony_ciend_txmngr:
10168c2ecf20Sopenharmony_ci	txExit();
10178c2ecf20Sopenharmony_cifree_metapage:
10188c2ecf20Sopenharmony_ci	metapage_exit();
10198c2ecf20Sopenharmony_cifree_slab:
10208c2ecf20Sopenharmony_ci	kmem_cache_destroy(jfs_inode_cachep);
10218c2ecf20Sopenharmony_ci	return rc;
10228c2ecf20Sopenharmony_ci}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_cistatic void __exit exit_jfs_fs(void)
10258c2ecf20Sopenharmony_ci{
10268c2ecf20Sopenharmony_ci	int i;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	jfs_info("exit_jfs_fs called");
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci	txExit();
10318c2ecf20Sopenharmony_ci	metapage_exit();
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	kthread_stop(jfsIOthread);
10348c2ecf20Sopenharmony_ci	for (i = 0; i < commit_threads; i++)
10358c2ecf20Sopenharmony_ci		kthread_stop(jfsCommitThread[i]);
10368c2ecf20Sopenharmony_ci	kthread_stop(jfsSyncThread);
10378c2ecf20Sopenharmony_ci#ifdef PROC_FS_JFS
10388c2ecf20Sopenharmony_ci	jfs_proc_clean();
10398c2ecf20Sopenharmony_ci#endif
10408c2ecf20Sopenharmony_ci	unregister_filesystem(&jfs_fs_type);
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	/*
10438c2ecf20Sopenharmony_ci	 * Make sure all delayed rcu free inodes are flushed before we
10448c2ecf20Sopenharmony_ci	 * destroy cache.
10458c2ecf20Sopenharmony_ci	 */
10468c2ecf20Sopenharmony_ci	rcu_barrier();
10478c2ecf20Sopenharmony_ci	kmem_cache_destroy(jfs_inode_cachep);
10488c2ecf20Sopenharmony_ci}
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_cimodule_init(init_jfs_fs)
10518c2ecf20Sopenharmony_cimodule_exit(exit_jfs_fs)
1052