#include <linux/parser.h>
#include <linux/completion.h>
#include <linux/vfs.h>
+#include <linux/mount.h>
#include <linux/moduleparam.h>
+#include <linux/posix_acl.h>
#include <asm/uaccess.h>
+#include <linux/seq_file.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
+#include "jfs_inode.h"
#include "jfs_metapage.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h"
MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
#endif
-/*
- * External declarations
- */
-extern int jfs_mount(struct super_block *);
-extern int jfs_mount_rw(struct super_block *, int);
-extern int jfs_umount(struct super_block *);
-extern int jfs_umount_rw(struct super_block *);
-
-extern int jfsIOWait(void *);
-extern int jfs_lazycommit(void *);
-extern int jfs_sync(void *);
-
-extern void jfs_read_inode(struct inode *inode);
-extern void jfs_dirty_inode(struct inode *inode);
-extern void jfs_delete_inode(struct inode *inode);
-extern int jfs_write_inode(struct inode *inode, int wait);
-
-extern struct dentry *jfs_get_parent(struct dentry *dentry);
-extern int jfs_extendfs(struct super_block *, s64, int);
-
-extern struct dentry_operations jfs_ci_dentry_operations;
-
-#ifdef PROC_FS_JFS /* see jfs_debug.h */
-extern void jfs_proc_init(void);
-extern void jfs_proc_clean(void);
-#endif
-
-extern wait_queue_head_t jfs_IO_thread_wait;
-extern wait_queue_head_t jfs_commit_thread_wait;
-extern wait_queue_head_t jfs_sync_thread_wait;
-
static void jfs_handle_error(struct super_block *sb)
{
struct jfs_sb_info *sbi = JFS_SBI(sb);
{
struct jfs_inode_info *ji = JFS_IP(inode);
+ BUG_ON(!list_empty(&ji->anon_inode_list));
+
spin_lock_irq(&ji->ag_lock);
if (ji->active_ag != -1) {
struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap;
unload_nls(sbi->nls_tab);
sbi->nls_tab = NULL;
+ truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
+ iput(sbi->direct_inode);
+ sbi->direct_inode = NULL;
+
kfree(sbi);
}
enum {
Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
- Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err,
+ Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
+ Opt_usrquota, Opt_grpquota, Opt_tagxid
};
static match_table_t tokens = {
{Opt_resize, "resize=%u"},
{Opt_resize_nosize, "resize"},
{Opt_errors, "errors=%s"},
+ {Opt_tagxid, "tagxid"},
{Opt_ignore, "noquota"},
{Opt_ignore, "quota"},
- {Opt_ignore, "usrquota"},
- {Opt_ignore, "grpquota"},
+ {Opt_usrquota, "usrquota"},
+ {Opt_grpquota, "grpquota"},
{Opt_err, NULL}
};
static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
int *flag)
{
- void *nls_map = NULL;
+ void *nls_map = (void *)-1; /* -1: no change; NULL: none */
char *p;
struct jfs_sb_info *sbi = JFS_SBI(sb);
/* Don't do anything ;-) */
break;
case Opt_iocharset:
- if (nls_map) /* specified iocharset twice! */
+ if (nls_map && nls_map != (void *) -1)
unload_nls(nls_map);
- nls_map = load_nls(args[0].from);
- if (!nls_map) {
- printk(KERN_ERR "JFS: charset not found\n");
- goto cleanup;
+ if (!strcmp(args[0].from, "none"))
+ nls_map = NULL;
+ else {
+ nls_map = load_nls(args[0].from);
+ if (!nls_map) {
+ printk(KERN_ERR
+ "JFS: charset not found\n");
+ goto cleanup;
+ }
}
break;
case Opt_resize:
}
break;
}
+
+#if defined(CONFIG_QUOTA)
+ case Opt_quota:
+ case Opt_usrquota:
+ *flag |= JFS_USRQUOTA;
+ break;
+ case Opt_grpquota:
+ *flag |= JFS_GRPQUOTA;
+ break;
+#else
+ case Opt_usrquota:
+ case Opt_grpquota:
+ case Opt_quota:
+ printk(KERN_ERR
+ "JFS: quota operations not supported\n");
+ break;
+#endif
+#ifndef CONFIG_INOXID_NONE
+ case Opt_tagxid:
+ *flag |= JFS_TAGXID;
+ break;
+#endif
default:
printk("jfs: Unrecognized mount option \"%s\" "
" or missing value\n", p);
}
}
- if (nls_map) {
+ if (nls_map != (void *) -1) {
/* Discard old (if remount) */
if (sbi->nls_tab)
unload_nls(sbi->nls_tab);
return 1;
cleanup:
- if (nls_map)
+ if (nls_map && nls_map != (void *) -1)
unload_nls(nls_map);
return 0;
}
if (!parse_options(data, sb, &newLVSize, &flag)) {
return -EINVAL;
}
+
+ if ((flag & JFS_TAGXID) && !(sb->s_flags & MS_TAGXID)) {
+ printk(KERN_ERR "JFS: %s: tagxid not permitted on remount.\n",
+ sb->s_id);
+ return -EINVAL;
+ }
+
if (newLVSize) {
if (sb->s_flags & MS_RDONLY) {
printk(KERN_ERR
}
if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
+ /*
+ * Invalidate any previously read metadata. fsck may have
+ * changed the on-disk data since we mounted r/o
+ */
+ truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0);
+
JFS_SBI(sb)->flag = flag;
return jfs_mount_rw(sb, 1);
}
}
sbi->flag = flag;
+#ifdef CONFIG_JFS_POSIX_ACL
+ sb->s_flags |= MS_POSIXACL;
+#endif
+ /* map mount option tagxid */
+ if (sbi->flag & JFS_TAGXID)
+ sb->s_flags |= MS_TAGXID;
+
if (newLVSize) {
printk(KERN_ERR "resize option for remount only\n");
return -EINVAL;
sb->s_op = &jfs_super_operations;
sb->s_export_op = &jfs_export_operations;
+ /*
+ * Initialize direct-mapping inode/address-space
+ */
+ inode = new_inode(sb);
+ if (inode == NULL)
+ goto out_kfree;
+ inode->i_ino = 0;
+ inode->i_nlink = 1;
+ inode->i_size = sb->s_bdev->bd_inode->i_size;
+ inode->i_mapping->a_ops = &jfs_metapage_aops;
+ insert_inode_hash(inode);
+ mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
+
+ sbi->direct_inode = inode;
+
rc = jfs_mount(sb);
if (rc) {
if (!silent) {
jfs_err("jfs_mount failed w/return code = %d", rc);
}
- goto out_kfree;
+ goto out_mount_failed;
}
if (sb->s_flags & MS_RDONLY)
sbi->log = NULL;
*/
sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes);
#endif
-
+ sb->s_time_gran = 1;
return 0;
out_no_root:
if (rc) {
jfs_err("jfs_umount failed with return code %d", rc);
}
+out_mount_failed:
+ filemap_write_and_wait(sbi->direct_inode->i_mapping);
+ truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
+ make_bad_inode(sbi->direct_inode);
+ iput(sbi->direct_inode);
+ sbi->direct_inode = NULL;
out_kfree:
if (sbi->nls_tab)
unload_nls(sbi->nls_tab);
struct jfs_log *log = JFS_SBI(sb)->log;
/* log == NULL indicates read-only mount */
- if (log)
+ if (log) {
jfs_flush_journal(log, wait);
+ jfs_syncpt(log, 0);
+ }
+
+ return 0;
+}
+
+static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+ struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb);
+
+ if (sbi->flag & JFS_NOINTEGRITY)
+ seq_puts(seq, ",nointegrity");
+ else
+ seq_puts(seq, ",integrity");
+
+#if defined(CONFIG_QUOTA)
+ if (sbi->flag & JFS_USRQUOTA)
+ seq_puts(seq, ",usrquota");
+
+ if (sbi->flag & JFS_GRPQUOTA)
+ seq_puts(seq, ",grpquota");
+#endif
return 0;
}
.unlockfs = jfs_unlockfs,
.statfs = jfs_statfs,
.remount_fs = jfs_remount,
+ .show_options = jfs_show_options
};
static struct export_operations jfs_export_operations = {
.fs_flags = FS_REQUIRES_DEV,
};
-extern int metapage_init(void);
-extern int txInit(void);
-extern void txExit(void);
-extern void metapage_exit(void);
-
static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
{
struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
if (commit_threads < 1)
commit_threads = num_online_cpus();
- else if (commit_threads > MAX_COMMIT_THREADS)
+ if (commit_threads > MAX_COMMIT_THREADS)
commit_threads = MAX_COMMIT_THREADS;
for (i = 0; i < commit_threads; i++) {