Commit 4b4f1d01 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (87 commits)
  nilfs2: get rid of bd_mount_sem use from nilfs
  nilfs2: correct exclusion control in nilfs_remount function
  nilfs2: simplify remaining sget() use
  nilfs2: get rid of sget use for checking if current mount is present
  nilfs2: get rid of sget use for acquiring nilfs object
  nilfs2: remove meaningless EBUSY case from nilfs_get_sb function
  remove the call to ->write_super in __sync_filesystem
  nilfs2: call nilfs2_write_super from nilfs2_sync_fs
  jffs2: call jffs2_write_super from jffs2_sync_fs
  ufs: add ->sync_fs
  sysv: add ->sync_fs
  hfsplus: add ->sync_fs
  hfs: add ->sync_fs
  fat: add ->sync_fs
  ext2: add ->sync_fs
  exofs: add ->sync_fs
  bfs: add ->sync_fs
  affs: add ->sync_fs
  sanitize ->fsync() for affs
  repair bfs_write_inode(), switch bfs to simple_fsync()
  ...
parents 875287ca aa7dfb89
......@@ -736,6 +736,8 @@ static void ncp_put_super(struct super_block *sb)
{
struct ncp_server *server = NCP_SBP(sb);
lock_kernel();
ncp_lock_server(server);
ncp_disconnect(server);
ncp_unlock_server(server);
......@@ -769,6 +771,8 @@ static void ncp_put_super(struct super_block *sb)
vfree(server->packet);
sb->s_fs_info = NULL;
kfree(server);
unlock_kernel();
}
static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
......
......@@ -154,7 +154,7 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
goto out;
out_follow:
while (d_mountpoint(nd->path.dentry) &&
follow_down(&nd->path.mnt, &nd->path.dentry))
follow_down(&nd->path))
;
err = 0;
goto out;
......
......@@ -1813,6 +1813,7 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
if (data == NULL)
return -ENOMEM;
lock_kernel();
/* fill out struct with values from existing mount */
data->flags = nfss->flags;
data->rsize = nfss->rsize;
......@@ -1837,6 +1838,7 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
error = nfs_compare_remount_data(nfss, data);
out:
kfree(data);
unlock_kernel();
return error;
}
......
......@@ -847,9 +847,8 @@ exp_get_fsid_key(svc_client *clp, int fsid)
return exp_find_key(clp, FSID_NUM, fsidv, NULL);
}
static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt,
struct dentry *dentry,
struct cache_req *reqp)
static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
struct cache_req *reqp)
{
struct svc_export *exp, key;
int err;
......@@ -858,8 +857,7 @@ static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt,
return ERR_PTR(-ENOENT);
key.ex_client = clp;
key.ex_path.mnt = mnt;
key.ex_path.dentry = dentry;
key.ex_path = *path;
exp = svc_export_lookup(&key);
if (exp == NULL)
......@@ -873,24 +871,19 @@ static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt,
/*
* Find the export entry for a given dentry.
*/
static struct svc_export *exp_parent(svc_client *clp, struct vfsmount *mnt,
struct dentry *dentry,
struct cache_req *reqp)
static struct svc_export *exp_parent(svc_client *clp, struct path *path)
{
svc_export *exp;
dget(dentry);
exp = exp_get_by_name(clp, mnt, dentry, reqp);
while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
struct dentry *parent;
parent = dget_parent(dentry);
dput(dentry);
dentry = parent;
exp = exp_get_by_name(clp, mnt, dentry, reqp);
struct dentry *saved = dget(path->dentry);
svc_export *exp = exp_get_by_name(clp, path, NULL);
while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
struct dentry *parent = dget_parent(path->dentry);
dput(path->dentry);
path->dentry = parent;
exp = exp_get_by_name(clp, path, NULL);
}
dput(dentry);
dput(path->dentry);
path->dentry = saved;
return exp;
}
......@@ -1018,7 +1011,7 @@ exp_export(struct nfsctl_export *nxp)
goto out_put_clp;
err = -EINVAL;
exp = exp_get_by_name(clp, path.mnt, path.dentry, NULL);
exp = exp_get_by_name(clp, &path, NULL);
memset(&new, 0, sizeof(new));
......@@ -1135,7 +1128,7 @@ exp_unexport(struct nfsctl_export *nxp)
goto out_domain;
err = -EINVAL;
exp = exp_get_by_name(dom, path.mnt, path.dentry, NULL);
exp = exp_get_by_name(dom, &path, NULL);
path_put(&path);
if (IS_ERR(exp))
goto out_domain;
......@@ -1177,7 +1170,7 @@ exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize)
dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
name, path.dentry, clp->name,
inode->i_sb->s_id, inode->i_ino);
exp = exp_parent(clp, path.mnt, path.dentry, NULL);
exp = exp_parent(clp, &path);
if (IS_ERR(exp)) {
err = PTR_ERR(exp);
goto out;
......@@ -1207,7 +1200,7 @@ static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type,
if (IS_ERR(ek))
return ERR_CAST(ek);
exp = exp_get_by_name(clp, ek->ek_path.mnt, ek->ek_path.dentry, reqp);
exp = exp_get_by_name(clp, &ek->ek_path, reqp);
cache_put(&ek->h, &svc_expkey_cache);
if (IS_ERR(exp))
......@@ -1247,8 +1240,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
* use exp_get_by_name() or exp_find().
*/
struct svc_export *
rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
struct dentry *dentry)
rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path)
{
struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
......@@ -1256,8 +1248,7 @@ rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
goto gss;
/* First try the auth_unix client: */
exp = exp_get_by_name(rqstp->rq_client, mnt, dentry,
&rqstp->rq_chandle);
exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle);
if (PTR_ERR(exp) == -ENOENT)
goto gss;
if (IS_ERR(exp))
......@@ -1269,8 +1260,7 @@ rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
/* Otherwise, try falling back on gss client */
if (rqstp->rq_gssclient == NULL)
return exp;
gssexp = exp_get_by_name(rqstp->rq_gssclient, mnt, dentry,
&rqstp->rq_chandle);
gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle);
if (PTR_ERR(gssexp) == -ENOENT)
return exp;
if (!IS_ERR(exp))
......@@ -1309,23 +1299,19 @@ rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
}
struct svc_export *
rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt,
struct dentry *dentry)
rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
{
struct svc_export *exp;
dget(dentry);
exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
struct dentry *parent;
parent = dget_parent(dentry);
dput(dentry);
dentry = parent;
exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
struct dentry *saved = dget(path->dentry);
struct svc_export *exp = rqst_exp_get_by_name(rqstp, path);
while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
struct dentry *parent = dget_parent(path->dentry);
dput(path->dentry);
path->dentry = parent;
exp = rqst_exp_get_by_name(rqstp, path);
}
dput(dentry);
dput(path->dentry);
path->dentry = saved;
return exp;
}
......
......@@ -101,36 +101,35 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
{
struct svc_export *exp = *expp, *exp2 = NULL;
struct dentry *dentry = *dpp;
struct vfsmount *mnt = mntget(exp->ex_path.mnt);
struct dentry *mounts = dget(dentry);
struct path path = {.mnt = mntget(exp->ex_path.mnt),
.dentry = dget(dentry)};
int err = 0;
while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts));
while (d_mountpoint(path.dentry) && follow_down(&path))
;
exp2 = rqst_exp_get_by_name(rqstp, mnt, mounts);
exp2 = rqst_exp_get_by_name(rqstp, &path);
if (IS_ERR(exp2)) {
if (PTR_ERR(exp2) != -ENOENT)
err = PTR_ERR(exp2);
dput(mounts);
mntput(mnt);
path_put(&path);
goto out;
}
if ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) {
/* successfully crossed mount point */
/*
* This is subtle: dentry is *not* under mnt at this point.
* The only reason we are safe is that original mnt is pinned
* down by exp, so we should dput before putting exp.
* This is subtle: path.dentry is *not* on path.mnt
* at this point. The only reason we are safe is that
* original mnt is pinned down by exp, so we should
* put path *before* putting exp
*/
dput(dentry);
*dpp = mounts;
exp_put(exp);
*dpp = path.dentry;
path.dentry = dentry;
*expp = exp2;
} else {
exp_put(exp2);
dput(mounts);
exp2 = exp;
}
mntput(mnt);
path_put(&path);
exp_put(exp2);
out:
return err;
}
......@@ -169,28 +168,29 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
/* checking mountpoint crossing is very different when stepping up */
struct svc_export *exp2 = NULL;
struct dentry *dp;
struct vfsmount *mnt = mntget(exp->ex_path.mnt);
dentry = dget(dparent);
while(dentry == mnt->mnt_root && follow_up(&mnt, &dentry))
struct path path = {.mnt = mntget(exp->ex_path.mnt),
.dentry = dget(dparent)};
while (path.dentry == path.mnt->mnt_root &&
follow_up(&path))
;
dp = dget_parent(dentry);
dput(dentry);
dentry = dp;
dp = dget_parent(path.dentry);
dput(path.dentry);
path.dentry = dp;
exp2 = rqst_exp_parent(rqstp, mnt, dentry);
exp2 = rqst_exp_parent(rqstp, &path);
if (PTR_ERR(exp2) == -ENOENT) {
dput(dentry);
dentry = dget(dparent);
} else if (IS_ERR(exp2)) {
host_err = PTR_ERR(exp2);
dput(dentry);
mntput(mnt);
path_put(&path);
goto out_nfserr;
} else {
dentry = dget(path.dentry);
exp_put(exp);
exp = exp2;
}
mntput(mnt);
path_put(&path);
}
} else {
fh_lock(fhp);
......
......@@ -864,11 +864,11 @@ int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode)
case NILFS_CHECKPOINT:
/*
* Check for protecting existing snapshot mounts:
* bd_mount_sem is used to make this operation atomic and
* ns_mount_mutex is used to make this operation atomic and
* exclusive with a new mount job. Though it doesn't cover
* umount, it's enough for the purpose.
*/
down(&nilfs->ns_bdev->bd_mount_sem);
mutex_lock(&nilfs->ns_mount_mutex);
if (nilfs_checkpoint_is_mounted(nilfs, cno, 1)) {
/* Current implementation does not have to protect
plain read-only mounts since they are exclusive
......@@ -877,7 +877,7 @@ int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode)
ret = -EBUSY;
} else
ret = nilfs_cpfile_clear_snapshot(cpfile, cno);
up(&nilfs->ns_bdev->bd_mount_sem);
mutex_unlock(&nilfs->ns_mount_mutex);
return ret;
case NILFS_SNAPSHOT:
return nilfs_cpfile_set_snapshot(cpfile, cno);
......
......@@ -60,6 +60,7 @@ struct nilfs_sb_info {
struct super_block *s_super; /* reverse pointer to super_block */
struct the_nilfs *s_nilfs;
struct list_head s_list; /* list head for nilfs->ns_supers */
atomic_t s_count; /* reference count */
/* Segment constructor */
struct list_head s_dirty_files; /* dirty files list */
......
......@@ -65,9 +65,8 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem "
"(NILFS)");
MODULE_LICENSE("GPL");
static void nilfs_write_super(struct super_block *sb);
static int nilfs_remount(struct super_block *sb, int *flags, char *data);
static int test_exclusive_mount(struct file_system_type *fs_type,
struct block_device *bdev, int flags);
/**
* nilfs_error() - report failure condition on a filesystem
......@@ -315,6 +314,11 @@ static void nilfs_put_super(struct super_block *sb)
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
lock_kernel();
if (sb->s_dirt)
nilfs_write_super(sb);
nilfs_detach_segment_constructor(sbi);
if (!(sb->s_flags & MS_RDONLY)) {
......@@ -323,12 +327,18 @@ static void nilfs_put_super(struct super_block *sb)
nilfs_commit_super(sbi, 1);
up_write(&nilfs->ns_sem);
}
down_write(&nilfs->ns_super_sem);
if (nilfs->ns_current == sbi)
nilfs->ns_current = NULL;
up_write(&nilfs->ns_super_sem);
nilfs_detach_checkpoint(sbi);
put_nilfs(sbi->s_nilfs);
sbi->s_super = NULL;
sb->s_fs_info = NULL;
kfree(sbi);
nilfs_put_sbinfo(sbi);
unlock_kernel();
}
/**
......@@ -383,6 +393,8 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
{
int err = 0;
nilfs_write_super(sb);
/* This function is called when super block should be written back */
if (wait)
err = nilfs_construct_segment(sb);
......@@ -396,9 +408,9 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno)
struct buffer_head *bh_cp;
int err;
down_write(&nilfs->ns_sem);
down_write(&nilfs->ns_super_sem);
list_add(&sbi->s_list, &nilfs->ns_supers);
up_write(&nilfs->ns_sem);
up_write(&nilfs->ns_super_sem);
sbi->s_ifile = nilfs_mdt_new(
nilfs, sbi->s_super, NILFS_IFILE_INO, NILFS_IFILE_GFP);
......@@ -436,9 +448,9 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno)
nilfs_mdt_destroy(sbi->s_ifile);
sbi->s_ifile = NULL;
down_write(&nilfs->ns_sem);
down_write(&nilfs->ns_super_sem);
list_del_init(&sbi->s_list);
up_write(&nilfs->ns_sem);
up_write(&nilfs->ns_super_sem);
return err;
}
......@@ -450,9 +462,9 @@ void nilfs_detach_checkpoint(struct nilfs_sb_info *sbi)
nilfs_mdt_clear(sbi->s_ifile);
nilfs_mdt_destroy(sbi->s_ifile);
sbi->s_ifile = NULL;
down_write(&nilfs->ns_sem);
down_write(&nilfs->ns_super_sem);
list_del_init(&sbi->s_list);
up_write(&nilfs->ns_sem);
up_write(&nilfs->ns_super_sem);
}
static int nilfs_mark_recovery_complete(struct nilfs_sb_info *sbi)
......@@ -752,7 +764,7 @@ int nilfs_store_magic_and_option(struct super_block *sb,
* @silent: silent mode flag
* @nilfs: the_nilfs struct
*
* This function is called exclusively by bd_mount_mutex.
* This function is called exclusively by nilfs->ns_mount_mutex.
* So, the recovery process is protected from other simultaneous mounts.
*/
static int
......@@ -773,6 +785,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent,
get_nilfs(nilfs);
sbi->s_nilfs = nilfs;
sbi->s_super = sb;
atomic_set(&sbi->s_count, 1);
err = init_nilfs(nilfs, sbi, (char *)data);
if (err)
......@@ -870,6 +883,11 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent,
goto failed_root;
}
down_write(&nilfs->ns_super_sem);
if (!nilfs_test_opt(sbi, SNAPSHOT))
nilfs->ns_current = sbi;
up_write(&nilfs->ns_super_sem);
return 0;
failed_root:
......@@ -885,7 +903,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent,
failed_sbi:
put_nilfs(nilfs);
sb->s_fs_info = NULL;
kfree(sbi);
nilfs_put_sbinfo(sbi);
return err;
}
......@@ -898,6 +916,9 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
struct nilfs_mount_options old_opts;
int err;
lock_kernel();
down_write(&nilfs->ns_super_sem);
old_sb_flags = sb->s_flags;
old_opts.mount_opt = sbi->s_mount_opt;
old_opts.snapshot_cno = sbi->s_snapshot_cno;
......@@ -945,14 +966,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
* store the current valid flag. (It may have been changed
* by fsck since we originally mounted the partition.)
*/
down(&sb->s_bdev->bd_mount_sem);
/* Check existing RW-mount */
if (test_exclusive_mount(sb->s_type, sb->s_bdev, 0)) {
if (nilfs->ns_current && nilfs->ns_current != sbi) {
printk(KERN_WARNING "NILFS (device %s): couldn't "
"remount because a RW-mount exists.\n",
"remount because an RW-mount exists.\n",
sb->s_id);
err = -EBUSY;
goto rw_remount_failed;
goto restore_opts;
}
if (sbi->s_snapshot_cno != nilfs_last_cno(nilfs)) {
printk(KERN_WARNING "NILFS (device %s): couldn't "
......@@ -960,7 +979,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
"the latest one.\n",
sb->s_id);
err = -EINVAL;
goto rw_remount_failed;
goto restore_opts;
}
sb->s_flags &= ~MS_RDONLY;
nilfs_clear_opt(sbi, SNAPSHOT);
......@@ -968,28 +987,31 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
err = nilfs_attach_segment_constructor(sbi);
if (err)
goto rw_remount_failed;
goto restore_opts;
down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi);
up_write(&nilfs->ns_sem);
up(&sb->s_bdev->bd_mount_sem);
nilfs->ns_current = sbi;
}
out:
up_write(&nilfs->ns_super_sem);
unlock_kernel();
return 0;
rw_remount_failed:
up(&sb->s_bdev->bd_mount_sem);
restore_opts:
sb->s_flags = old_sb_flags;
sbi->s_mount_opt = old_opts.mount_opt;
sbi->s_snapshot_cno = old_opts.snapshot_cno;
up_write(&nilfs->ns_super_sem);
unlock_kernel();
return err;
}
struct nilfs_super_data {
struct block_device *bdev;
struct nilfs_sb_info *sbi;
__u64 cno;
int flags;
};
......@@ -1048,33 +1070,7 @@ static int nilfs_test_bdev_super(struct super_block *s, void *data)
{
struct nilfs_super_data *sd = data;
return s->s_bdev == sd->bdev;
}
static int nilfs_test_bdev_super2(struct super_block *s, void *data)
{
struct nilfs_super_data *sd = data;
int ret;
if (s->s_bdev != sd->bdev)
return 0;
if (!((s->s_flags | sd->flags) & MS_RDONLY))
return 1; /* Reuse an old R/W-mode super_block */
if (s->s_flags & sd->flags & MS_RDONLY) {
if (down_read_trylock(&s->s_umount)) {
ret = s->s_root &&
(sd->cno == NILFS_SB(s)->s_snapshot_cno);
up_read(&s->s_umount);
/*
* This path is locked with sb_lock by sget().
* So, drop_super() causes deadlock.
*/
return ret;
}
}
return 0;
return sd->sbi && s->s_fs_info == (void *)sd->sbi;
}
static int
......@@ -1082,8 +1078,8 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data, struct vfsmount *mnt)
{
struct nilfs_super_data sd;
struct super_block *s, *s2;
struct the_nilfs *nilfs = NULL;
struct super_block *s;
struct the_nilfs *nilfs;
int err, need_to_close = 1;
sd.bdev = open_bdev_exclusive(dev_name, flags, fs_type);
......@@ -1095,7 +1091,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
* much more information than normal filesystems to identify mount
* instance. For snapshot mounts, not only a mount type (ro-mount
* or rw-mount) but also a checkpoint number is required.
* The results are passed in sget() using nilfs_super_data.
*/
sd.cno = 0;
sd.flags = flags;
......@@ -1104,64 +1099,59 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
goto failed;
}
/*
* once the super is inserted into the list by sget, s_umount
* will protect the lockfs code from trying to start a snapshot
* while we are mounting
*/
down(&sd.bdev->bd_mount_sem);
if (!sd.cno &&
(err = test_exclusive_mount(fs_type, sd.bdev, flags ^ MS_RDONLY))) {
err = (err < 0) ? : -EBUSY;
goto failed_unlock;
nilfs = find_or_create_nilfs(sd.bdev);
if (!nilfs) {
err = -ENOMEM;
goto failed;
}
/*
* Phase-1: search any existent instance and get the_nilfs
*/
s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd);
if (IS_ERR(s))
goto error_s;
if (!s->s_root) {
err = -ENOMEM;
nilfs = alloc_nilfs(sd.bdev);
if (!nilfs)
goto cancel_new;
} else {
struct nilfs_sb_info *sbi = NILFS_SB(s);
mutex_lock(&nilfs->ns_mount_mutex);
if (!sd.cno) {
/*
* s_umount protects super_block from unmount process;
* It covers pointers of nilfs_sb_info and the_nilfs.
* Check if an exclusive mount exists or not.
* Snapshot mounts coexist with a current mount
* (i.e. rw-mount or ro-mount), whereas rw-mount and
* ro-mount are mutually exclusive.
*/
nilfs = sbi->s_nilfs;
get_nilfs(nilfs);
up_write(&s->s_umount);
down_read(&nilfs->ns_super_sem);
if (nilfs->ns_current &&
((nilfs->ns_current->s_super->s_flags ^ flags)
& MS_RDONLY)) {
up_read(&nilfs->ns_super_sem);
err = -EBUSY;
goto failed_unlock;
}
up_read(&nilfs->ns_super_sem);
}
/*
* Phase-2: search specified snapshot or R/W mode super_block
*/
if (!sd.cno)
/* trying to get the latest checkpoint. */
sd.cno = nilfs_last_cno(nilfs);
/*
* Find existing nilfs_sb_info struct
*/
sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno);
s2 = sget(fs_type, nilfs_test_bdev_super2,
nilfs_set_bdev_super, &sd);
deactivate_super(s);
/*
* Although deactivate_super() invokes close_bdev_exclusive() at
* kill_block_super(). Here, s is an existent mount; we need
* one more close_bdev_exclusive() call.
*/
s = s2;
if (IS_ERR(s))
goto error_s;
if (!sd.cno)
/* trying to get the latest checkpoint. */
sd.cno = nilfs_last_cno(nilfs);
/*
* Get super block instance holding the nilfs_sb_info struct.
* A new instance is allocated if no existing mount is present or
* existing instance has been unmounted.
*/
s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd);
if (sd.sbi)
nilfs_put_sbinfo(sd.sbi);
if (IS_ERR(s)) {
err = PTR_ERR(s);
goto failed_unlock;
}
if (!s->s_root) {
char b[BDEVNAME_SIZE];
/* New superblock instance created */
s->s_flags = flags;
strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id));
sb_set_blocksize(s, block_size(sd.bdev));
......@@ -1172,26 +1162,18 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
s->s_flags |= MS_ACTIVE;
need_to_close = 0;
} else if (!(s->s_flags & MS_RDONLY)) {
err = -EBUSY;
}
up(&sd.bdev->bd_mount_sem);
mutex_unlock(&nilfs->ns_mount_mutex);
put_nilfs(nilfs);
if (need_to_close)
close_bdev_exclusive(sd.bdev, flags);
simple_set_mnt(mnt, s);
return 0;
error_s:
up(&sd.bdev->bd_mount_sem);
if (nilfs)
put_nilfs(nilfs);
close_bdev_exclusive(sd.bdev, flags);
return PTR_ERR(s);
failed_unlock:
up(&sd.bdev->bd_mount_sem);
mutex_unlock(&nilfs->ns_mount_mutex);
put_nilfs(nilfs);
failed:
close_bdev_exclusive(sd.bdev, flags);
......@@ -1199,70 +1181,18 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
cancel_new:
/* Abandoning the newly allocated superblock */
up(&sd.bdev->bd_mount_sem);
if (nilfs)
put_nilfs(nilfs);
mutex_unlock(&nilfs->ns_mount_mutex);
put_nilfs(nilfs);
up_write(&s->s_umount);
deactivate_super(s);
/*
* deactivate_super() invokes close_bdev_exclusive().
* We must finish all post-cleaning before this call;
* put_nilfs() and unlocking bd_mount_sem need the block device.
* put_nilfs() needs the block device.
*/
return err;
}
static int nilfs_test_bdev_super3(struct super_block *s, void *data)
{
struct nilfs_super_data *sd = data;
int ret;
if (s->s_bdev != sd->bdev)
return 0;
if (down_read_trylock(&s->s_umount)) {
ret = (s->s_flags & MS_RDONLY) && s->s_root &&
nilfs_test_opt(NILFS_SB(s), SNAPSHOT);
up_read(&s->s_umount);
if (ret)
return 0; /* ignore snapshot mounts */
}
return !((sd->flags ^ s->s_flags) & MS_RDONLY);
}
static int __false_bdev_super(struct super_block *s, void *data)
{
#if 0 /* XXX: workaround for lock debug. This is not good idea */
up_write(&s->s_umount);
#endif
return -EFAULT;
}
/**
* test_exclusive_mount - check whether an exclusive RW/RO mount exists or not.
* fs_type: filesystem type
* bdev: block device
* flag: 0 (check rw-mount) or MS_RDONLY (check ro-mount)
* res: pointer to an integer to store result
*
* This function must be called within a section protected by bd_mount_mutex.
*/
static int test_exclusive_mount(struct file_system_type *fs_type,
struct block_device *bdev, int flags)
{
struct super_block *s;
struct nilfs_super_data sd = { .flags = flags, .bdev = bdev };
s = sget(fs_type, nilfs_test_bdev_super3, __false_bdev_super, &sd);
if (IS_ERR(s)) {
if (PTR_ERR(s) != -EFAULT)
return PTR_ERR(s);
return 0; /* Not found */
}
up_write(&s->s_umount);
deactivate_super(s);
return 1; /* Found */
}
struct file_system_type nilfs_fs_type = {
.owner = THIS_MODULE,
.name = "nilfs2",
......
......@@ -35,6 +35,10 @@
#include "seglist.h"
#include "segbuf.h"
static LIST_HEAD(nilfs_objects);
static DEFINE_SPINLOCK(nilfs_lock);
void nilfs_set_last_segment(struct the_nilfs *nilfs,
sector_t start_blocknr, u64 seq, __u64 cno)
{
......@@ -55,7 +59,7 @@ void nilfs_set_last_segment(struct the_nilfs *nilfs,
* Return Value: On success, pointer to the_nilfs is returned.
* On error, NULL is returned.
*/
struct the_nilfs *alloc_nilfs(struct block_device *bdev)
static struct the_nilfs *alloc_nilfs(struct block_device *bdev)
{
struct the_nilfs *nilfs;
......@@ -68,7 +72,10 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
atomic_set(&nilfs->ns_writer_refcount, -1);
atomic_set(&nilfs->ns_ndirtyblks, 0);
init_rwsem(&nilfs->ns_sem);
init_rwsem(&nilfs->ns_super_sem);
mutex_init(&nilfs->ns_mount_mutex);
mutex_init(&nilfs->ns_writer_mutex);
INIT_LIST_HEAD(&nilfs->ns_list);
INIT_LIST_HEAD(&nilfs->ns_supers);
spin_lock_init(&nilfs->ns_last_segment_lock);
nilfs->ns_gc_inodes_h = NULL;
......@@ -77,6 +84,45 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
return nilfs;
}
/**
* find_or_create_nilfs - find or create nilfs object
* @bdev: block device to which the_nilfs is related
*
* find_nilfs() looks up an existent nilfs object created on the
* device and gets the reference count of the object. If no nilfs object
* is found on the device, a new nilfs object is allocated.
*
* Return Value: On success, pointer to the nilfs object is returned.
* On error, NULL is returned.
*/
struct the_nilfs *find_or_create_nilfs(struct block_device *bdev)
{
struct the_nilfs *nilfs, *new = NULL;
retry:
spin_lock(&nilfs_lock);
list_for_each_entry(nilfs, &nilfs_objects, ns_list) {
if (nilfs->ns_bdev == bdev) {
get_nilfs(nilfs);
spin_unlock(&nilfs_lock);
if (new)
put_nilfs(new);
return nilfs; /* existing object */
}
}
if (new) {
list_add_tail(&new->ns_list, &nilfs_objects);
spin_unlock(&nilfs_lock);
return new; /* new object */
}
spin_unlock(&nilfs_lock);
new = alloc_nilfs(bdev);
if (new)
goto retry;
return NULL; /* insufficient memory */
}
/**
* put_nilfs - release a reference to the_nilfs
* @nilfs: the_nilfs structure to be released
......@@ -86,13 +132,20 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
*/
void put_nilfs(struct the_nilfs *nilfs)
{
if (!atomic_dec_and_test(&nilfs->ns_count))
spin_lock(&nilfs_lock);
if (!atomic_dec_and_test(&nilfs->ns_count)) {
spin_unlock(&nilfs_lock);
return;
}
list_del_init(&nilfs->ns_list);
spin_unlock(&nilfs_lock);
/*
* Increment of ns_count never occur below because the caller
* Increment of ns_count never occurs below because the caller
* of get_nilfs() holds at least one reference to the_nilfs.
* Thus its exclusion control is not required here.
*/
might_sleep();
if (nilfs_loaded(nilfs)) {
nilfs_mdt_clear(nilfs->ns_sufile);
......@@ -613,13 +666,63 @@ int nilfs_near_disk_full(struct the_nilfs *nilfs)
return ret;
}
/**
* nilfs_find_sbinfo - find existing nilfs_sb_info structure
* @nilfs: nilfs object
* @rw_mount: mount type (non-zero value for read/write mount)
* @cno: checkpoint number (zero for read-only mount)
*
* nilfs_find_sbinfo() returns the nilfs_sb_info structure which
* @rw_mount and @cno (in case of snapshots) matched. If no instance
* was found, NULL is returned. Although the super block instance can
* be unmounted after this function returns, the nilfs_sb_info struct
* is kept on memory until nilfs_put_sbinfo() is called.
*/
struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *nilfs,
int rw_mount, __u64 cno)
{
struct nilfs_sb_info *sbi;
down_read(&nilfs->ns_super_sem);
/*
* The SNAPSHOT flag and sb->s_flags are supposed to be
* protected with nilfs->ns_super_sem.
*/
sbi = nilfs->ns_current;
if (rw_mount) {
if (sbi && !(sbi->s_super->s_flags & MS_RDONLY))
goto found; /* read/write mount */
else
goto out;
} else if (cno == 0) {
if (sbi && (sbi->s_super->s_flags & MS_RDONLY))
goto found; /* read-only mount */
else
goto out;
}
list_for_each_entry(sbi, &nilfs->ns_supers, s_list) {
if (nilfs_test_opt(sbi, SNAPSHOT) &&
sbi->s_snapshot_cno == cno)
goto found; /* snapshot mount */
}
out:
up_read(&nilfs->ns_super_sem);
return NULL;
found:
atomic_inc(&sbi->s_count);
up_read(&nilfs->ns_super_sem);
return sbi;
}
int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno,
int snapshot_mount)
{
struct nilfs_sb_info *sbi;
int ret = 0;
down_read(&nilfs->ns_sem);
down_read(&nilfs->ns_super_sem);
if (cno == 0 || cno > nilfs->ns_cno)
goto out_unlock;
......@@ -636,6 +739,6 @@ int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno,
ret++;
out_unlock:
up_read(&nilfs->ns_sem);
up_read(&nilfs->ns_super_sem);
return ret;
}
......@@ -43,12 +43,16 @@ enum {
* struct the_nilfs - struct to supervise multiple nilfs mount points
* @ns_flags: flags
* @ns_count: reference count
* @ns_list: list head for nilfs_list
* @ns_bdev: block device
* @ns_bdi: backing dev info
* @ns_writer: back pointer to writable nilfs_sb_info
* @ns_sem: semaphore for shared states
* @ns_super_sem: semaphore for global operations across super block instances
* @ns_mount_mutex: mutex protecting mount process of nilfs
* @ns_writer_mutex: mutex protecting ns_writer attach/detach
* @ns_writer_refcount: number of referrers on ns_writer
* @ns_current: back pointer to current mount
* @ns_sbh: buffer heads of on-disk super blocks
* @ns_sbp: pointers to super block data
* @ns_sbwtime: previous write time of super blocks
......@@ -88,14 +92,23 @@ enum {
struct the_nilfs {
unsigned long ns_flags;
atomic_t ns_count;
struct list_head ns_list;
struct block_device *ns_bdev;
struct backing_dev_info *ns_bdi;
struct nilfs_sb_info *ns_writer;
struct rw_semaphore ns_sem;
struct rw_semaphore ns_super_sem;
struct mutex ns_mount_mutex;
struct mutex ns_writer_mutex;
atomic_t ns_writer_refcount;
/*
* components protected by ns_super_sem
*/
struct nilfs_sb_info *ns_current;
struct list_head ns_supers;
/*
* used for
* - loading the latest checkpoint exclusively.
......@@ -108,7 +121,6 @@ struct the_nilfs {
time_t ns_sbwtime[2];
unsigned ns_sbsize;
unsigned ns_mount_state;
struct list_head ns_supers;
/*
* Following fields are dedicated to a writable FS-instance.
......@@ -191,11 +203,12 @@ THE_NILFS_FNS(DISCONTINUED, discontinued)
#define NILFS_ALTSB_FREQ 60 /* spare superblock */
void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64);
struct the_nilfs *alloc_nilfs(struct block_device *);
struct the_nilfs *find_or_create_nilfs(struct block_device *);
void put_nilfs(struct the_nilfs *);
int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
int nilfs_near_disk_full(struct the_nilfs *);
void nilfs_fall_back_super_block(struct the_nilfs *);
......@@ -238,6 +251,12 @@ nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
mutex_unlock(&nilfs->ns_writer_mutex);
}
static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi)
{
if (!atomic_dec_and_test(&sbi->s_count))
kfree(sbi);
}
static inline void
nilfs_get_segment_range(struct the_nilfs *nilfs, __u64 segnum,
sector_t *seg_start, sector_t *seg_end)
......
......@@ -443,6 +443,8 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
ntfs_volume *vol = NTFS_SB(sb);
ntfs_debug("Entering with remount options string: %s", opt);
lock_kernel();
#ifndef NTFS_RW
/* For read-only compiled driver, enforce read-only flag. */
*flags |= MS_RDONLY;
......@@ -466,15 +468,18 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
if (NVolErrors(vol)) {
ntfs_error(sb, "Volume has errors and is read-only%s",
es);
unlock_kernel();
return -EROFS;
}
if (vol->vol_flags & VOLUME_IS_DIRTY) {
ntfs_error(sb, "Volume is dirty and read-only%s", es);
unlock_kernel();
return -EROFS;
}
if (vol->vol_flags & VOLUME_MODIFIED_BY_CHKDSK) {
ntfs_error(sb, "Volume has been modified by chkdsk "
"and is read-only%s", es);
unlock_kernel();
return -EROFS;
}
if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) {
......@@ -482,11 +487,13 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
"(0x%x) and is read-only%s",
(unsigned)le16_to_cpu(vol->vol_flags),
es);
unlock_kernel();
return -EROFS;
}
if (ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) {
ntfs_error(sb, "Failed to set dirty bit in volume "
"information flags%s", es);
unlock_kernel();
return -EROFS;
}
#if 0
......@@ -506,18 +513,21 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
ntfs_error(sb, "Failed to empty journal $LogFile%s",
es);
NVolSetErrors(vol);
unlock_kernel();
return -EROFS;
}
if (!ntfs_mark_quotas_out_of_date(vol)) {
ntfs_error(sb, "Failed to mark quotas out of date%s",
es);
NVolSetErrors(vol);
unlock_kernel();
return -EROFS;
}
if (!ntfs_stamp_usnjrnl(vol)) {
ntfs_error(sb, "Failed to stamp transation log "
"($UsnJrnl)%s", es);
NVolSetErrors(vol);
unlock_kernel();
return -EROFS;
}
} else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
......@@ -533,8 +543,11 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
// TODO: Deal with *flags.
if (!parse_options(vol, opt))
if (!parse_options(vol, opt)) {
unlock_kernel();
return -EINVAL;
}
unlock_kernel();
ntfs_debug("Done.");
return 0;
}
......@@ -2246,6 +2259,9 @@ static void ntfs_put_super(struct super_block *sb)
ntfs_volume *vol = NTFS_SB(sb);
ntfs_debug("Entering.");
lock_kernel();
#ifdef NTFS_RW
/*
* Commit all inodes while they are still open in case some of them
......@@ -2373,39 +2389,12 @@ static void ntfs_put_super(struct super_block *sb)
vol->mftmirr_ino = NULL;
}
/*
* If any dirty inodes are left, throw away all mft data page cache
* pages to allow a clean umount. This should never happen any more
* due to mft.c::ntfs_mft_writepage() cleaning all the dirty pages as
* the underlying mft records are written out and cleaned. If it does,
* happen anyway, we want to know...
* We should have no dirty inodes left, due to
* mft.c::ntfs_mft_writepage() cleaning all the dirty pages as
* the underlying mft records are written out and cleaned.
*/
ntfs_commit_inode(vol->mft_ino);
write_inode_now(vol->mft_ino, 1);
if (sb_has_dirty_inodes(sb)) {
const char *s1, *s2;
mutex_lock(&vol->mft_ino->i_mutex);
truncate_inode_pages(vol->mft_ino->i_mapping, 0);
mutex_unlock(&vol->mft_ino->i_mutex);
write_inode_now(vol->mft_ino, 1);
if (sb_has_dirty_inodes(sb)) {
static const char *_s1 = "inodes";
static const char *_s2 = "";
s1 = _s1;
s2 = _s2;
} else {
static const char *_s1 = "mft pages";
static const char *_s2 = "They have been thrown "
"away. ";
s1 = _s1;
s2 = _s2;
}
ntfs_error(sb, "Dirty %s found at umount time. %sYou should "
"run chkdsk. Please email "
"linux-ntfs-dev@lists.sourceforge.net and say "
"that you saw this message. Thank you.", s1,
s2);
}
#endif /* NTFS_RW */
iput(vol->mft_ino);
......@@ -2444,7 +2433,8 @@ static void ntfs_put_super(struct super_block *sb)
}
sb->s_fs_info = NULL;
kfree(vol);
return;
unlock_kernel();
}
/**
......
......@@ -42,6 +42,7 @@
#include <linux/mount.h>
#include <linux/seq_file.h>
#include <linux/quotaops.h>
#include <linux/smp_lock.h>
#define MLOG_MASK_PREFIX ML_SUPER
#include <cluster/masklog.h>
......@@ -126,7 +127,6 @@ static int ocfs2_get_sector(struct super_block *sb,
struct buffer_head **bh,
int block,
int sect_size);
static void ocfs2_write_super(struct super_block *sb);
static struct inode *ocfs2_alloc_inode(struct super_block *sb);
static void ocfs2_destroy_inode(struct inode *inode);
static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend);
......@@ -141,7 +141,6 @@ static const struct super_operations ocfs2_sops = {
.clear_inode = ocfs2_clear_inode,
.delete_inode = ocfs2_delete_inode,
.sync_fs = ocfs2_sync_fs,
.write_super = ocfs2_write_super,
.put_super = ocfs2_put_super,
.remount_fs = ocfs2_remount,
.show_options = ocfs2_show_options,
......@@ -365,24 +364,12 @@ static struct file_operations ocfs2_osb_debug_fops = {
.llseek = generic_file_llseek,
};
/*
* write_super and sync_fs ripped right out of ext3.
*/
static void ocfs2_write_super(struct super_block *sb)
{
if (mutex_trylock(&sb->s_lock) != 0)
BUG();
sb->s_dirt = 0;
}
static int ocfs2_sync_fs(struct super_block *sb, int wait)
{
int status;
tid_t target;
struct ocfs2_super *osb = OCFS2_SB(sb);
sb->s_dirt = 0;
if (ocfs2_is_hard_readonly(osb))
return -EROFS;
......@@ -595,6 +582,8 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
struct mount_options parsed_options;
struct ocfs2_super *osb = OCFS2_SB(sb);
lock_kernel();
if (!ocfs2_parse_options(sb, data, &parsed_options, 1)) {
ret = -EINVAL;
goto out;
......@@ -698,6 +687,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
ocfs2_set_journal_params(osb);
}
out:
unlock_kernel();
return ret;
}
......@@ -1550,9 +1540,13 @@ static void ocfs2_put_super(struct super_block *sb)
{
mlog_entry("(0x%p)\n", sb);
lock_kernel();
ocfs2_sync_blockdev(sb);
ocfs2_dismount_volume(sb, 0);
unlock_kernel();
mlog_exit_void();
}
......
......@@ -11,21 +11,6 @@
#include <linux/mpage.h>
#include "omfs.h"
static int omfs_sync_file(struct file *file, struct dentry *dentry,
int datasync)
{
struct inode *inode = dentry->d_inode;
int err;
err = sync_mapping_buffers(inode->i_mapping);
if (!(inode->i_state & I_DIRTY))
return err;
if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
return err;
err |= omfs_sync_inode(inode);
return err ? -EIO : 0;
}
static u32 omfs_max_extents(struct omfs_sb_info *sbi, int offset)
{
return (sbi->s_sys_blocksize - offset -
......@@ -344,7 +329,7 @@ struct file_operations omfs_file_operations = {
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = omfs_sync_file,
.fsync = simple_fsync,
.splice_read = generic_file_splice_read,
};
......
......@@ -612,7 +612,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
audit_inode(NULL, dentry);
err = mnt_want_write(file->f_path.mnt);
err = mnt_want_write_file(file);
if (err)
goto out_putf;
mutex_lock(&inode->i_mutex);
......@@ -761,7 +761,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
if (!file)
goto out;
error = mnt_want_write(file->f_path.mnt);
error = mnt_want_write_file(file);
if (error)
goto out_fput;
dentry = file->f_path.dentry;
......
......@@ -92,3 +92,28 @@ struct pde_opener {
struct list_head lh;
};
void pde_users_dec(struct proc_dir_entry *pde);
extern spinlock_t proc_subdir_lock;
struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
unsigned long task_vsize(struct mm_struct *);
int task_statm(struct mm_struct *, int *, int *, int *, int *);
void task_mem(struct seq_file *, struct mm_struct *);
struct proc_dir_entry *de_get(struct proc_dir_entry *de);
void de_put(struct proc_dir_entry *de);
extern struct vfsmount *proc_mnt;
int proc_fill_super(struct super_block *);
struct inode *proc_get_inode(struct super_block *, unsigned int, struct proc_dir_entry *);
/*
* These are generic /proc routines that use the internal
* "struct proc_dir_entry" tree to traverse the filesystem.
*
* The /proc root directory has extended versions to take care
* of the /proc/<pid> subdirectories.
*/
int proc_readdir(struct file *, void *, filldir_t);
struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
......@@ -11,6 +11,7 @@
#include <linux/string.h>
#include <asm/prom.h>
#include <asm/uaccess.h>
#include "internal.h"
#ifndef HAVE_ARCH_DEVTREE_FIXUPS
static inline void set_node_proc_entry(struct device_node *np,
......
......@@ -4,4 +4,4 @@
obj-$(CONFIG_QNX4FS_FS) += qnx4.o
qnx4-objs := inode.o dir.o namei.o file.o bitmap.o truncate.o fsync.o
qnx4-objs := inode.o dir.o namei.o file.o bitmap.o truncate.o
......@@ -13,14 +13,9 @@
* 28-06-1998 by Frank Denis : qnx4_free_inode (to be fixed) .
*/
#include <linux/time.h>
#include <linux/fs.h>
#include <linux/qnx4_fs.h>
#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/buffer_head.h>
#include <linux/bitops.h>
#include "qnx4.h"
#if 0
int qnx4_new_block(struct super_block *sb)
......
......@@ -11,14 +11,9 @@
* 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support.
*/
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/qnx4_fs.h>
#include <linux/stat.h>
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
#include "qnx4.h"
static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
......@@ -84,7 +79,7 @@ const struct file_operations qnx4_dir_operations =
{
.read = generic_read_dir,
.readdir = qnx4_readdir,
.fsync = file_fsync,
.fsync = simple_fsync,
};
const struct inode_operations qnx4_dir_inode_operations =
......
......@@ -12,8 +12,7 @@
* 27-06-1998 by Frank Denis : file overwriting.
*/
#include <linux/fs.h>
#include <linux/qnx4_fs.h>
#include "qnx4.h"
/*
* We have mostly NULL's here: the current defaults are ok for
......@@ -29,7 +28,7 @@ const struct file_operations qnx4_file_operations =
#ifdef CONFIG_QNX4FS_RW
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.fsync = qnx4_sync_file,
.fsync = simple_fsync,
#endif
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment