Commit 78dcf734 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull ->s_options removal from Al Viro:
 "Preparations for fsmount/fsopen stuff (coming next cycle). Everything
  gets moved to explicit ->show_options(), killing ->s_options off +
  some cosmetic bits around fs/namespace.c and friends. Basically, the
  stuff needed to work with fsmount series with minimum of conflicts
  with other work.

  It's not strictly required for this merge window, but it would reduce
  the PITA during the coming cycle, so it would be nice to have those
  bits and pieces out of the way"

* 'work.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  isofs: Fix isofs_show_options()
  VFS: Kill off s_options and helpers
  orangefs: Implement show_options
  9p: Implement show_options
  isofs: Implement show_options
  afs: Implement show_options
  affs: Implement show_options
  befs: Implement show_options
  spufs: Implement show_options
  bpf: Implement show_options
  ramfs: Implement show_options
  pstore: Implement show_options
  omfs: Implement show_options
  hugetlbfs: Implement show_options
  VFS: Don't use save/replace_mount_options if not using generic_show_options
  VFS: Provide empty name qstr
  VFS: Make get_filesystem() return the affected filesystem
  VFS: Clean up whitespace in fs/namespace.c and fs/super.c
  Provide a function to create a NUL-terminated string from unterminated data
parents 93ff8185 fdb254db
......@@ -1225,12 +1225,6 @@ The underlying reason for the above rules is to make sure, that a
mount can be accurately replicated (e.g. umounting and mounting again)
based on the information found in /proc/mounts.
A simple method of saving options at mount/remount time and showing
them is provided with the save_mount_options() and
generic_show_options() helper functions. Please note, that using
these may have drawbacks. For more info see header comments for these
functions in fs/namespace.c.
Resources
=========
......
......@@ -605,6 +605,24 @@ static const match_table_t spufs_tokens = {
{ Opt_err, NULL },
};
static int spufs_show_options(struct seq_file *m, struct dentry *root)
{
struct spufs_sb_info *sbi = spufs_get_sb_info(root->d_sb);
struct inode *inode = root->d_inode;
if (!uid_eq(inode->i_uid, GLOBAL_ROOT_UID))
seq_printf(m, ",uid=%u",
from_kuid_munged(&init_user_ns, inode->i_uid));
if (!gid_eq(inode->i_gid, GLOBAL_ROOT_GID))
seq_printf(m, ",gid=%u",
from_kgid_munged(&init_user_ns, inode->i_gid));
if ((inode->i_mode & S_IALLUGO) != 0775)
seq_printf(m, ",mode=%o", inode->i_mode);
if (sbi->debug)
seq_puts(m, ",debug");
return 0;
}
static int
spufs_parse_options(struct super_block *sb, char *options, struct inode *root)
{
......@@ -724,11 +742,9 @@ spufs_fill_super(struct super_block *sb, void *data, int silent)
.destroy_inode = spufs_destroy_inode,
.statfs = simple_statfs,
.evict_inode = spufs_evict_inode,
.show_options = generic_show_options,
.show_options = spufs_show_options,
};
save_mount_options(sb, data);
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
......
......@@ -33,6 +33,7 @@
#include <linux/parser.h>
#include <linux/idr.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>
#include <net/9p/transport.h>
......@@ -82,6 +83,13 @@ static const match_table_t tokens = {
{Opt_err, NULL}
};
static const char *const v9fs_cache_modes[nr__p9_cache_modes] = {
[CACHE_NONE] = "none",
[CACHE_MMAP] = "mmap",
[CACHE_LOOSE] = "loose",
[CACHE_FSCACHE] = "fscache",
};
/* Interpret mount options for cache mode */
static int get_cache_mode(char *s)
{
......@@ -104,6 +112,58 @@ static int get_cache_mode(char *s)
return version;
}
/*
* Display the mount options in /proc/mounts.
*/
int v9fs_show_options(struct seq_file *m, struct dentry *root)
{
struct v9fs_session_info *v9ses = root->d_sb->s_fs_info;
if (v9ses->debug)
seq_printf(m, ",debug=%x", v9ses->debug);
if (!uid_eq(v9ses->dfltuid, V9FS_DEFUID))
seq_printf(m, ",dfltuid=%u",
from_kuid_munged(&init_user_ns, v9ses->dfltuid));
if (!gid_eq(v9ses->dfltgid, V9FS_DEFGID))
seq_printf(m, ",dfltgid=%u",
from_kgid_munged(&init_user_ns, v9ses->dfltgid));
if (v9ses->afid != ~0)
seq_printf(m, ",afid=%u", v9ses->afid);
if (strcmp(v9ses->uname, V9FS_DEFUSER) != 0)
seq_printf(m, ",uname=%s", v9ses->uname);
if (strcmp(v9ses->aname, V9FS_DEFANAME) != 0)
seq_printf(m, ",aname=%s", v9ses->aname);
if (v9ses->nodev)
seq_puts(m, ",nodevmap");
if (v9ses->cache)
seq_printf(m, ",%s", v9fs_cache_modes[v9ses->cache]);
#ifdef CONFIG_9P_FSCACHE
if (v9ses->cachetag && v9ses->cache == CACHE_FSCACHE)
seq_printf(m, ",cachetag=%s", v9ses->cachetag);
#endif
switch (v9ses->flags & V9FS_ACCESS_MASK) {
case V9FS_ACCESS_USER:
seq_puts(m, ",access=user");
break;
case V9FS_ACCESS_ANY:
seq_puts(m, ",access=any");
break;
case V9FS_ACCESS_CLIENT:
seq_puts(m, ",access=client");
break;
case V9FS_ACCESS_SINGLE:
seq_printf(m, ",access=%u",
from_kuid_munged(&init_user_ns, v9ses->uid));
break;
}
if (v9ses->flags & V9FS_POSIX_ACL)
seq_puts(m, ",posixacl");
return p9_show_client_options(m, v9ses->clnt);
}
/**
* v9fs_parse_options - parse mount options into session structure
* @v9ses: existing v9fs session information
......@@ -230,6 +290,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
break;
case Opt_cachetag:
#ifdef CONFIG_9P_FSCACHE
kfree(v9ses->cachetag);
v9ses->cachetag = match_strdup(&args[0]);
#endif
break;
......
......@@ -67,6 +67,7 @@ enum p9_cache_modes {
CACHE_MMAP,
CACHE_LOOSE,
CACHE_FSCACHE,
nr__p9_cache_modes
};
/**
......@@ -137,6 +138,8 @@ static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
return container_of(inode, struct v9fs_inode, vfs_inode);
}
extern int v9fs_show_options(struct seq_file *m, struct dentry *root);
struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
char *);
extern void v9fs_session_close(struct v9fs_session_info *v9ses);
......
......@@ -33,7 +33,6 @@
#include <linux/string.h>
#include <linux/inet.h>
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
#include <linux/idr.h>
#include <linux/sched.h>
......@@ -104,7 +103,6 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
sb->s_flags |= MS_POSIXACL;
#endif
save_mount_options(sb, data);
return 0;
}
......@@ -349,7 +347,7 @@ static const struct super_operations v9fs_super_ops = {
.destroy_inode = v9fs_destroy_inode,
.statfs = simple_statfs,
.evict_inode = v9fs_evict_inode,
.show_options = generic_show_options,
.show_options = v9fs_show_options,
.umount_begin = v9fs_umount_begin,
.write_inode = v9fs_write_inode,
};
......@@ -360,7 +358,7 @@ static const struct super_operations v9fs_super_ops_dotl = {
.statfs = v9fs_statfs,
.drop_inode = v9fs_drop_inode,
.evict_inode = v9fs_evict_inode,
.show_options = generic_show_options,
.show_options = v9fs_show_options,
.umount_begin = v9fs_umount_begin,
.write_inode = v9fs_write_inode_dotl,
};
......
......@@ -20,9 +20,11 @@
#include <linux/slab.h>
#include <linux/writeback.h>
#include <linux/blkdev.h>
#include <linux/seq_file.h>
#include "affs.h"
static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
static int affs_show_options(struct seq_file *m, struct dentry *root);
static int affs_remount (struct super_block *sb, int *flags, char *data);
static void
......@@ -159,7 +161,7 @@ static const struct super_operations affs_sops = {
.sync_fs = affs_sync_fs,
.statfs = affs_statfs,
.remount_fs = affs_remount,
.show_options = generic_show_options,
.show_options = affs_show_options,
};
enum {
......@@ -293,6 +295,40 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved,
return 1;
}
static int affs_show_options(struct seq_file *m, struct dentry *root)
{
struct super_block *sb = root->d_sb;
struct affs_sb_info *sbi = AFFS_SB(sb);
if (sb->s_blocksize)
seq_printf(m, ",bs=%lu", sb->s_blocksize);
if (affs_test_opt(sbi->s_flags, SF_SETMODE))
seq_printf(m, ",mode=%o", sbi->s_mode);
if (affs_test_opt(sbi->s_flags, SF_MUFS))
seq_puts(m, ",mufs");
if (affs_test_opt(sbi->s_flags, SF_NO_TRUNCATE))
seq_puts(m, ",nofilenametruncate");
if (affs_test_opt(sbi->s_flags, SF_PREFIX))
seq_printf(m, ",prefix=%s", sbi->s_prefix);
if (affs_test_opt(sbi->s_flags, SF_IMMUTABLE))
seq_puts(m, ",protect");
if (sbi->s_reserved != 2)
seq_printf(m, ",reserved=%u", sbi->s_reserved);
if (sbi->s_root_block != (sbi->s_reserved + sbi->s_partition_size - 1) / 2)
seq_printf(m, ",root=%u", sbi->s_root_block);
if (affs_test_opt(sbi->s_flags, SF_SETGID))
seq_printf(m, ",setgid=%u",
from_kgid_munged(&init_user_ns, sbi->s_gid));
if (affs_test_opt(sbi->s_flags, SF_SETUID))
seq_printf(m, ",setuid=%u",
from_kuid_munged(&init_user_ns, sbi->s_uid));
if (affs_test_opt(sbi->s_flags, SF_VERBOSE))
seq_puts(m, ",verbose");
if (sbi->s_volume[0])
seq_printf(m, ",volume=%s", sbi->s_volume);
return 0;
}
/* This function definitely needs to be split up. Some fine day I'll
* hopefully have the guts to do so. Until then: sorry for the mess.
*/
......@@ -316,8 +352,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
u8 sig[4];
int ret;
save_mount_options(sb, data);
pr_debug("read_super(%s)\n", data ? (const char *)data : "no options");
sb->s_magic = AFFS_SUPER_MAGIC;
......@@ -548,8 +582,6 @@ affs_remount(struct super_block *sb, int *flags, char *data)
}
flush_delayed_work(&sbi->sb_work);
if (new_opts)
replace_mount_options(sb, new_opts);
sbi->s_flags = mount_flags;
sbi->s_mode = mode;
......
......@@ -37,6 +37,8 @@ static void afs_kill_super(struct super_block *sb);
static struct inode *afs_alloc_inode(struct super_block *sb);
static void afs_destroy_inode(struct inode *inode);
static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
static int afs_show_devname(struct seq_file *m, struct dentry *root);
static int afs_show_options(struct seq_file *m, struct dentry *root);
struct file_system_type afs_fs_type = {
.owner = THIS_MODULE,
......@@ -53,7 +55,8 @@ static const struct super_operations afs_super_ops = {
.drop_inode = afs_drop_inode,
.destroy_inode = afs_destroy_inode,
.evict_inode = afs_evict_inode,
.show_options = generic_show_options,
.show_devname = afs_show_devname,
.show_options = afs_show_options,
};
static struct kmem_cache *afs_inode_cachep;
......@@ -135,6 +138,45 @@ void __exit afs_fs_exit(void)
_leave("");
}
/*
* Display the mount device name in /proc/mounts.
*/
static int afs_show_devname(struct seq_file *m, struct dentry *root)
{
struct afs_super_info *as = root->d_sb->s_fs_info;
struct afs_volume *volume = as->volume;
struct afs_cell *cell = volume->cell;
const char *suf = "";
char pref = '%';
switch (volume->type) {
case AFSVL_RWVOL:
break;
case AFSVL_ROVOL:
pref = '#';
if (volume->type_force)
suf = ".readonly";
break;
case AFSVL_BACKVOL:
pref = '#';
suf = ".backup";
break;
}
seq_printf(m, "%c%s:%s%s", pref, cell->name, volume->vlocation->vldb.name, suf);
return 0;
}
/*
* Display the mount options in /proc/mounts.
*/
static int afs_show_options(struct seq_file *m, struct dentry *root)
{
if (test_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(d_inode(root))->flags))
seq_puts(m, "autocell");
return 0;
}
/*
* parse the mount options
* - this function has been shamelessly adapted from the ext3 fs which
......@@ -427,7 +469,6 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
deactivate_locked_super(sb);
goto error;
}
save_mount_options(sb, new_opts);
sb->s_flags |= MS_ACTIVE;
} else {
_debug("reuse");
......
......@@ -20,6 +20,7 @@
#include <linux/sched.h>
#include <linux/cred.h>
#include <linux/exportfs.h>
#include <linux/seq_file.h>
#include "befs.h"
#include "btree.h"
......@@ -53,6 +54,7 @@ static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
static void befs_put_super(struct super_block *);
static int befs_remount(struct super_block *, int *, char *);
static int befs_statfs(struct dentry *, struct kstatfs *);
static int befs_show_options(struct seq_file *, struct dentry *);
static int parse_options(char *, struct befs_mount_options *);
static struct dentry *befs_fh_to_dentry(struct super_block *sb,
struct fid *fid, int fh_len, int fh_type);
......@@ -66,7 +68,7 @@ static const struct super_operations befs_sops = {
.put_super = befs_put_super, /* uninit super */
.statfs = befs_statfs, /* statfs */
.remount_fs = befs_remount,
.show_options = generic_show_options,
.show_options = befs_show_options,
};
/* slab cache for befs_inode_info objects */
......@@ -771,6 +773,24 @@ parse_options(char *options, struct befs_mount_options *opts)
return 1;
}
static int befs_show_options(struct seq_file *m, struct dentry *root)
{
struct befs_sb_info *befs_sb = BEFS_SB(root->d_sb);
struct befs_mount_options *opts = &befs_sb->mount_opts;
if (!uid_eq(opts->uid, GLOBAL_ROOT_UID))
seq_printf(m, ",uid=%u",
from_kuid_munged(&init_user_ns, opts->uid));
if (!gid_eq(opts->gid, GLOBAL_ROOT_GID))
seq_printf(m, ",gid=%u",
from_kgid_munged(&init_user_ns, opts->gid));
if (opts->iocharset)
seq_printf(m, ",charset=%s", opts->iocharset);
if (opts->debug)
seq_puts(m, ",debug");
return 0;
}
/* This function has the responsibiltiy of getting the
* filesystem ready for unmounting.
* Basically, we free everything that we allocated in
......@@ -804,8 +824,6 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
const off_t x86_sb_off = 512;
int blocksize;
save_mount_options(sb, data);
sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL);
if (sb->s_fs_info == NULL)
goto unacquire_none;
......
......@@ -1154,7 +1154,6 @@ static int btrfs_fill_super(struct super_block *sb,
goto fail_close;
}
save_mount_options(sb, data);
cleancache_init_fs(sb);
sb->s_flags |= MS_ACTIVE;
return 0;
......
......@@ -90,6 +90,11 @@ EXPORT_SYMBOL(rename_lock);
static struct kmem_cache *dentry_cache __read_mostly;
const struct qstr empty_name = QSTR_INIT("", 0);
EXPORT_SYMBOL(empty_name);
const struct qstr slash_name = QSTR_INIT("/", 1);
EXPORT_SYMBOL(slash_name);
/*
* This is the single most critical data structure when it comes
* to the dcache: the hashtable for lookups. Somebody should try
......@@ -1606,8 +1611,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
*/
dentry->d_iname[DNAME_INLINE_LEN-1] = 0;
if (unlikely(!name)) {
static const struct qstr anon = QSTR_INIT("/", 1);
name = &anon;
name = &slash_name;
dname = dentry->d_iname;
} else if (name->len > DNAME_INLINE_LEN-1) {
size_t size = offsetof(struct external_name, name[1]);
......
......@@ -203,8 +203,6 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent)
struct debugfs_fs_info *fsi;
int err;
save_mount_options(sb, data);
fsi = kzalloc(sizeof(struct debugfs_fs_info), GFP_KERNEL);
sb->s_fs_info = fsi;
if (!fsi) {
......
......@@ -29,7 +29,6 @@ static const struct super_operations efivarfs_ops = {
.statfs = simple_statfs,
.drop_inode = generic_delete_inode,
.evict_inode = efivarfs_evict_inode,
.show_options = generic_show_options,
};
static struct super_block *efivarfs_sb;
......
......@@ -33,9 +33,10 @@ static struct file_system_type *file_systems;
static DEFINE_RWLOCK(file_systems_lock);
/* WARNING: This can be used only if we _already_ own a reference */
void get_filesystem(struct file_system_type *fs)
struct file_system_type *get_filesystem(struct file_system_type *fs)
{
__module_get(fs->owner);
return fs;
}
void put_filesystem(struct file_system_type *fs)
......
......@@ -872,7 +872,6 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
struct buffer_head *bh;
struct gfs2_leaf *leaf;
struct gfs2_dirent *dent;
struct qstr name = { .name = "" };
struct timespec tv = current_time(inode);
error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
......@@ -896,7 +895,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
leaf->lf_sec = cpu_to_be64(tv.tv_sec);
memset(leaf->lf_reserved2, 0, sizeof(leaf->lf_reserved2));
dent = (struct gfs2_dirent *)(leaf+1);
gfs2_qstr2dirent(&name, bh->b_size - sizeof(struct gfs2_leaf), dent);
gfs2_qstr2dirent(&empty_name, bh->b_size - sizeof(struct gfs2_leaf), dent);
*pbh = bh;
return leaf;
}
......
......@@ -46,13 +46,13 @@ static const struct inode_operations hugetlbfs_dir_inode_operations;
static const struct inode_operations hugetlbfs_inode_operations;
struct hugetlbfs_config {
kuid_t uid;
kgid_t gid;
umode_t mode;
long max_hpages;
long nr_inodes;
struct hstate *hstate;
long min_hpages;
struct hstate *hstate;
long max_hpages;
long nr_inodes;
long min_hpages;
kuid_t uid;
kgid_t gid;
umode_t mode;
};
struct hugetlbfs_inode_info {
......@@ -861,6 +861,46 @@ static int hugetlbfs_error_remove_page(struct address_space *mapping,
return 0;
}
/*
* Display the mount options in /proc/mounts.
*/
static int hugetlbfs_show_options(struct seq_file *m, struct dentry *root)
{
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(root->d_sb);
struct hugepage_subpool *spool = sbinfo->spool;
unsigned long hpage_size = huge_page_size(sbinfo->hstate);
unsigned hpage_shift = huge_page_shift(sbinfo->hstate);
char mod;
if (!uid_eq(sbinfo->uid, GLOBAL_ROOT_UID))
seq_printf(m, ",uid=%u",
from_kuid_munged(&init_user_ns, sbinfo->uid));
if (!gid_eq(sbinfo->gid, GLOBAL_ROOT_GID))
seq_printf(m, ",gid=%u",
from_kgid_munged(&init_user_ns, sbinfo->gid));
if (sbinfo->mode != 0755)
seq_printf(m, ",mode=%o", sbinfo->mode);
if (sbinfo->max_inodes != -1)
seq_printf(m, ",nr_inodes=%lu", sbinfo->max_inodes);
hpage_size /= 1024;
mod = 'K';
if (hpage_size >= 1024) {
hpage_size /= 1024;
mod = 'M';
}
seq_printf(m, ",pagesize=%lu%c", hpage_size, mod);
if (spool) {
if (spool->max_hpages != -1)
seq_printf(m, ",size=%llu",
(unsigned long long)spool->max_hpages << hpage_shift);
if (spool->min_hpages != -1)
seq_printf(m, ",min_size=%llu",
(unsigned long long)spool->min_hpages << hpage_shift);
}
return 0;
}
static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
......@@ -1019,19 +1059,19 @@ static const struct super_operations hugetlbfs_ops = {
.evict_inode = hugetlbfs_evict_inode,
.statfs = hugetlbfs_statfs,
.put_super = hugetlbfs_put_super,
.show_options = generic_show_options,
.show_options = hugetlbfs_show_options,
};
enum { NO_SIZE, SIZE_STD, SIZE_PERCENT };
enum hugetlbfs_size_type { NO_SIZE, SIZE_STD, SIZE_PERCENT };
/*
* Convert size option passed from command line to number of huge pages
* in the pool specified by hstate. Size option could be in bytes
* (val_type == SIZE_STD) or percentage of the pool (val_type == SIZE_PERCENT).
*/
static long long
static long
hugetlbfs_size_to_hpages(struct hstate *h, unsigned long long size_opt,
int val_type)
enum hugetlbfs_size_type val_type)
{
if (val_type == NO_SIZE)
return -1;
......@@ -1053,7 +1093,7 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
substring_t args[MAX_OPT_ARGS];
int option;
unsigned long long max_size_opt = 0, min_size_opt = 0;
int max_val_type = NO_SIZE, min_val_type = NO_SIZE;
enum hugetlbfs_size_type max_val_type = NO_SIZE, min_val_type = NO_SIZE;
if (!options)
return 0;
......@@ -1167,8 +1207,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
struct hugetlbfs_config config;
struct hugetlbfs_sb_info *sbinfo;
save_mount_options(sb, data);
config.max_hpages = -1; /* No limit on size by default */
config.nr_inodes = -1; /* No limit on number of inodes by default */
config.uid = current_fsuid();
......@@ -1189,6 +1227,10 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
sbinfo->max_inodes = config.nr_inodes;
sbinfo->free_inodes = config.nr_inodes;
sbinfo->spool = NULL;
sbinfo->uid = config.uid;
sbinfo->gid = config.gid;
sbinfo->mode = config.mode;
/*
* Allocate and initialize subpool if maximum or minimum size is
* specified. Any needed reservations (for minimim size) are taken
......
......@@ -23,6 +23,7 @@
#include <linux/parser.h>
#include <linux/mpage.h>
#include <linux/user_namespace.h>
#include <linux/seq_file.h>
#include "isofs.h"
#include "zisofs.h"
......@@ -57,6 +58,7 @@ static void isofs_put_super(struct super_block *sb)
static int isofs_read_inode(struct inode *, int relocated);
static int isofs_statfs (struct dentry *, struct kstatfs *);
static int isofs_show_options(struct seq_file *, struct dentry *);
static struct kmem_cache *isofs_inode_cachep;
......@@ -123,7 +125,7 @@ static const struct super_operations isofs_sops = {
.put_super = isofs_put_super,
.statfs = isofs_statfs,
.remount_fs = isofs_remount,
.show_options = generic_show_options,
.show_options = isofs_show_options,
};
......@@ -472,6 +474,48 @@ static int parse_options(char *options, struct iso9660_options *popt)
return 1;
}
/*
* Display the mount options in /proc/mounts.
*/
static int isofs_show_options(struct seq_file *m, struct dentry *root)
{
struct isofs_sb_info *sbi = ISOFS_SB(root->d_sb);
if (!sbi->s_rock) seq_puts(m, ",norock");
else if (!sbi->s_joliet_level) seq_puts(m, ",nojoliet");
if (sbi->s_cruft) seq_puts(m, ",cruft");
if (sbi->s_hide) seq_puts(m, ",hide");
if (sbi->s_nocompress) seq_puts(m, ",nocompress");
if (sbi->s_overriderockperm) seq_puts(m, ",overriderockperm");
if (sbi->s_showassoc) seq_puts(m, ",showassoc");
if (sbi->s_utf8) seq_puts(m, ",utf8");
if (sbi->s_check) seq_printf(m, ",check=%c", sbi->s_check);
if (sbi->s_mapping) seq_printf(m, ",map=%c", sbi->s_mapping);
if (sbi->s_session != 255) seq_printf(m, ",session=%u", sbi->s_session - 1);
if (sbi->s_sbsector != -1) seq_printf(m, ",sbsector=%u", sbi->s_sbsector);
if (root->d_sb->s_blocksize != 1024)
seq_printf(m, ",blocksize=%lu", root->d_sb->s_blocksize);
if (sbi->s_uid_set)
seq_printf(m, ",uid=%u",
from_kuid_munged(&init_user_ns, sbi->s_uid));
if (sbi->s_gid_set)
seq_printf(m, ",gid=%u",
from_kgid_munged(&init_user_ns, sbi->s_gid));
if (sbi->s_dmode != ISOFS_INVALID_MODE)
seq_printf(m, ",dmode=%o", sbi->s_dmode);
if (sbi->s_fmode != ISOFS_INVALID_MODE)
seq_printf(m, ",fmode=%o", sbi->s_fmode);
if (sbi->s_nls_iocharset &&
strcmp(sbi->s_nls_iocharset->charset, CONFIG_NLS_DEFAULT) != 0)
seq_printf(m, ",iocharset=%s", sbi->s_nls_iocharset->charset);
return 0;
}
/*
* look if the driver can tell the multi session redirection value
*
......@@ -583,8 +627,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
int table, error = -EINVAL;
unsigned int vol_desc_start;
save_mount_options(s, data);
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
......@@ -605,6 +647,8 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
opt.blocksize = sb_min_blocksize(s, opt.blocksize);
sbi->s_high_sierra = 0; /* default is iso9660 */
sbi->s_session = opt.session;
sbi->s_sbsector = opt.sbsector;
vol_desc_start = (opt.sbsector != -1) ?
opt.sbsector : isofs_get_last_session(s,opt.session);
......@@ -911,6 +955,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
table += 2;
if (opt.check == 'r')
table++;
sbi->s_check = opt.check;
if (table)
s->s_d_op = &isofs_dentry_ops[table - 1];
......
......@@ -36,8 +36,11 @@ struct isofs_sb_info {
unsigned long s_max_size;
int s_rock_offset; /* offset of SUSP fields within SU area */
s32 s_sbsector;
unsigned char s_joliet_level;
unsigned char s_mapping;
unsigned char s_check;
unsigned char s_session;
unsigned int s_high_sierra:1;
unsigned int s_rock:2;
unsigned int s_utf8:1;
......
......@@ -3400,7 +3400,6 @@ static int do_last(struct nameidata *nd,
struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, int open_flag)
{
static const struct qstr name = QSTR_INIT("/", 1);
struct dentry *child = NULL;
struct inode *dir = dentry->d_inode;
struct inode *inode;
......@@ -3414,7 +3413,7 @@ struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, int open_flag)
if (!dir->i_op->tmpfile)
goto out_err;
error = -ENOMEM;
child = d_alloc(dentry, &name);
child = d_alloc(dentry, &slash_name);
if (unlikely(!child))
goto out_err;
error = dir->i_op->tmpfile(dir, child, mode);
......