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

Pull the big VFS changes from Al Viro:
 "This one is *big* and changes quite a few things around VFS.  What's in there:

   - the first of two really major architecture changes - death to open
     intents.

     The former is finally there; it was very long in making, but with
     Miklos getting through really hard and messy final push in
     fs/namei.c, we finally have it.  Unlike his variant, this one
     doesn't introduce struct opendata; what we have instead is
     ->atomic_open() taking preallocated struct file * and passing
     everything via its fields.

     Instead of returning struct file *, it returns -E...  on error, 0
     on success and 1 in "deal with it yourself" case (e.g.  symlink
     found on server, etc.).

     See comments before fs/namei.c:atomic_open().  That made a lot of
     goodies finally possible and quite a few are in that pile:
     ->lookup(), ->d_revalidate() and ->create() do not get struct
     nameidata * anymore; ->lookup() and ->d_revalidate() get lookup
     flags instead, ->create() gets "do we want it exclusive" flag.

     With the introduction of new helper (kern_path_locked()) we are rid
     of all struct nameidata instances outside of fs/namei.c; it's still
     visible in namei.h, but not for long.  Come the next cycle,
     declaration will move either to fs/internal.h or to fs/namei.c
     itself.  [me, miklos, hch]

   - The second major change: behaviour of final fput().  Now we have
     __fput() done without any locks held by caller *and* not from deep
     in call stack.

     That obviously lifts a lot of constraints on the locking in there.
     Moreover, it's legal now to call fput() from atomic contexts (which
     has immediately simplified life for aio.c).  We also don't need
     anti-recursion logics in __scm_destroy() anymore.

     There is a price, though - the damn thing has become partially
     asynchronous.  For fput() from normal process we are guaranteed
     that pending __fput() will be done before the caller returns to
     userland, exits or gets stopped for ptrace.

     For kernel threads and atomic contexts it's done via
     schedule_work(), so theoretically we might need a way to make sure
     it's finished; so far only one such place had been found, but there
     might be more.

     There's flush_delayed_fput() (do all pending __fput()) and there's
     __fput_sync() (fput() analog doing __fput() immediately).  I hope
     we won't need them often; see warnings in fs/file_table.c for
     details.  [me, based on task_work series from Oleg merged last
     cycle]

   - sync series from Jan

   - large part of "death to sync_supers()" work from Artem; the only
     bits missing here are exofs and ext4 ones.  As far as I understand,
     those are going via the exofs and ext4 trees resp.; once they are
     in, we can put ->write_super() to the rest, along with the thread
     calling it.

   - preparatory bits from unionmount series (from dhowells).

   - assorted cleanups and fixes all over the place, as usual.

  This is not the last pile for this cycle; there's at least jlayton's
  ESTALE work and fsfreeze series (the latter - in dire need of fixes,
  so I'm not sure it'll make the cut this cycle).  I'll probably throw
  symlink/hardlink restrictions stuff from Kees into the next pile, too.
  Plus there's a lot of misc patches I hadn't thrown into that one -
  it's large enough as it is..."

* 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (127 commits)
  ext4: switch EXT4_IOC_RESIZE_FS to mnt_want_write_file()
  btrfs: switch btrfs_ioctl_balance() to mnt_want_write_file()
  switch dentry_open() to struct path, make it grab references itself
  spufs: shift dget/mntget towards dentry_open()
  zoran: don't bother with struct file * in zoran_map
  ecryptfs: don't reinvent the wheels, please - use struct completion
  don't expose I_NEW inodes via dentry->d_inode
  tidy up namei.c a bit
  unobfuscate follow_up() a bit
  ext3: pass custom EOF to generic_file_llseek_size()
  ext4: use core vfs llseek code for dir seeks
  vfs: allow custom EOF in generic_file_llseek code
  vfs: Avoid unnecessary WB_SYNC_NONE writeback during sys_sync and reorder sync passes
  vfs: Remove unnecessary flushing of block devices
  vfs: Make sys_sync writeout also block device inodes
  vfs: Create function for iterating over block devices
  vfs: Reorder operations during sys_sync
  quota: Move quota syncing to ->sync_fs method
  quota: Split dquot_quota_sync() to writeback and cache flushing part
  vfs: Move noop_backing_dev_info check from sync into writeback
  ...
This commit is contained in:
Linus Torvalds 2012-07-23 12:27:27 -07:00
commit a66d2c8f7e
210 changed files with 2613 additions and 2402 deletions

View file

@ -46,8 +46,8 @@
static int nfs_opendir(struct inode *, struct file *);
static int nfs_closedir(struct inode *, struct file *);
static int nfs_readdir(struct file *, void *, filldir_t);
static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
static int nfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
static struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
static int nfs_create(struct inode *, struct dentry *, umode_t, bool);
static int nfs_mkdir(struct inode *, struct dentry *, umode_t);
static int nfs_rmdir(struct inode *, struct dentry *);
static int nfs_unlink(struct inode *, struct dentry *);
@ -111,11 +111,13 @@ const struct inode_operations nfs3_dir_inode_operations = {
#ifdef CONFIG_NFS_V4
static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
static int nfs_open_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd);
static int nfs_atomic_open(struct inode *, struct dentry *,
struct file *, unsigned, umode_t,
int *);
const struct inode_operations nfs4_dir_inode_operations = {
.create = nfs_open_create,
.lookup = nfs_atomic_lookup,
.create = nfs_create,
.lookup = nfs_lookup,
.atomic_open = nfs_atomic_open,
.link = nfs_link,
.unlink = nfs_unlink,
.symlink = nfs_symlink,
@ -1028,28 +1030,15 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
return 1;
}
/*
* Return the intent data that applies to this particular path component
*
* Note that the current set of intents only apply to the very last
* component of the path and none of them is set before that last
* component.
*/
static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
unsigned int mask)
{
return nd->flags & mask;
}
/*
* Use intent information to check whether or not we're going to do
* an O_EXCL create using this path component.
*/
static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
static int nfs_is_exclusive_create(struct inode *dir, unsigned int flags)
{
if (NFS_PROTO(dir)->version == 2)
return 0;
return nd && nfs_lookup_check_intent(nd, LOOKUP_EXCL);
return flags & LOOKUP_EXCL;
}
/*
@ -1061,25 +1050,20 @@ static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
*
*/
static inline
int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags)
{
struct nfs_server *server = NFS_SERVER(inode);
if (IS_AUTOMOUNT(inode))
return 0;
if (nd != NULL) {
/* VFS wants an on-the-wire revalidation */
if (nd->flags & LOOKUP_REVAL)
goto out_force;
/* This is an open(2) */
if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
!(server->flags & NFS_MOUNT_NOCTO) &&
(S_ISREG(inode->i_mode) ||
S_ISDIR(inode->i_mode)))
goto out_force;
return 0;
}
return nfs_revalidate_inode(server, inode);
/* VFS wants an on-the-wire revalidation */
if (flags & LOOKUP_REVAL)
goto out_force;
/* This is an open(2) */
if ((flags & LOOKUP_OPEN) && !(server->flags & NFS_MOUNT_NOCTO) &&
(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
goto out_force;
return 0;
out_force:
return __nfs_revalidate_inode(server, inode);
}
@ -1093,10 +1077,10 @@ out_force:
*/
static inline
int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
unsigned int flags)
{
/* Don't revalidate a negative dentry if we're creating a new file */
if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
if (flags & LOOKUP_CREATE)
return 0;
if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG)
return 1;
@ -1114,7 +1098,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
* If the parent directory is seen to have changed, we throw out the
* cached dentry and do a new lookup.
*/
static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
{
struct inode *dir;
struct inode *inode;
@ -1123,7 +1107,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
struct nfs_fattr *fattr = NULL;
int error;
if (nd->flags & LOOKUP_RCU)
if (flags & LOOKUP_RCU)
return -ECHILD;
parent = dget_parent(dentry);
@ -1132,7 +1116,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
inode = dentry->d_inode;
if (!inode) {
if (nfs_neg_need_reval(dir, dentry, nd))
if (nfs_neg_need_reval(dir, dentry, flags))
goto out_bad;
goto out_valid_noent;
}
@ -1148,8 +1132,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
goto out_set_verifier;
/* Force a full look up iff the parent directory has changed */
if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) {
if (nfs_lookup_verify_inode(inode, nd))
if (!nfs_is_exclusive_create(dir, flags) && nfs_check_verifier(dir, dentry)) {
if (nfs_lookup_verify_inode(inode, flags))
goto out_zap_parent;
goto out_valid;
}
@ -1286,7 +1270,7 @@ const struct dentry_operations nfs_dentry_operations = {
.d_release = nfs_d_release,
};
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
{
struct dentry *res;
struct dentry *parent;
@ -1307,7 +1291,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
* If we're doing an exclusive create, optimize away the lookup
* but don't hash the dentry.
*/
if (nfs_is_exclusive_create(dir, nd)) {
if (nfs_is_exclusive_create(dir, flags)) {
d_instantiate(dentry, NULL);
res = NULL;
goto out;
@ -1354,7 +1338,7 @@ out:
}
#ifdef CONFIG_NFS_V4
static int nfs4_lookup_revalidate(struct dentry *, struct nameidata *);
static int nfs4_lookup_revalidate(struct dentry *, unsigned int);
const struct dentry_operations nfs4_dentry_operations = {
.d_revalidate = nfs4_lookup_revalidate,
@ -1364,24 +1348,6 @@ const struct dentry_operations nfs4_dentry_operations = {
.d_release = nfs_d_release,
};
/*
* Use intent information to determine whether we need to substitute
* the NFSv4-style stateful OPEN for the LOOKUP call
*/
static int is_atomic_open(struct nameidata *nd)
{
if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
return 0;
/* NFS does not (yet) have a stateful open for directories */
if (nd->flags & LOOKUP_DIRECTORY)
return 0;
/* Are we trying to write to a read only partition? */
if (__mnt_is_readonly(nd->path.mnt) &&
(nd->intent.open.flags & (O_CREAT|O_TRUNC|O_ACCMODE)))
return 0;
return 1;
}
static fmode_t flags_to_mode(int flags)
{
fmode_t res = (__force fmode_t)flags & FMODE_EXEC;
@ -1403,136 +1369,143 @@ static int do_open(struct inode *inode, struct file *filp)
return 0;
}
static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
static int nfs_finish_open(struct nfs_open_context *ctx,
struct dentry *dentry,
struct file *file, unsigned open_flags,
int *opened)
{
struct file *filp;
int ret = 0;
int err;
if (ctx->dentry != dentry) {
dput(ctx->dentry);
ctx->dentry = dget(dentry);
}
/* If the open_intent is for execute, we have an extra check to make */
if (ctx->mode & FMODE_EXEC) {
ret = nfs_may_open(ctx->dentry->d_inode,
ctx->cred,
nd->intent.open.flags);
if (ret < 0)
err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags);
if (err < 0)
goto out;
}
filp = lookup_instantiate_filp(nd, ctx->dentry, do_open);
if (IS_ERR(filp))
ret = PTR_ERR(filp);
else
nfs_file_set_open_context(filp, ctx);
err = finish_open(file, dentry, do_open, opened);
if (err)
goto out;
nfs_file_set_open_context(file, ctx);
out:
put_nfs_open_context(ctx);
return ret;
return err;
}
static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
static int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
struct file *file, unsigned open_flags,
umode_t mode, int *opened)
{
struct nfs_open_context *ctx;
struct iattr attr;
struct dentry *res = NULL;
struct dentry *res;
struct iattr attr = { .ia_valid = ATTR_OPEN };
struct inode *inode;
int open_flags;
int err;
dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
/* Expect a negative dentry */
BUG_ON(dentry->d_inode);
dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n",
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
/* Check that we are indeed trying to open this file */
if (!is_atomic_open(nd))
/* NFS only supports OPEN on regular files */
if ((open_flags & O_DIRECTORY)) {
if (!d_unhashed(dentry)) {
/*
* Hashed negative dentry with O_DIRECTORY: dentry was
* revalidated and is fine, no need to perform lookup
* again
*/
return -ENOENT;
}
goto no_open;
if (dentry->d_name.len > NFS_SERVER(dir)->namelen) {
res = ERR_PTR(-ENAMETOOLONG);
goto out;
}
/* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash
* the dentry. */
if (nd->flags & LOOKUP_EXCL) {
d_instantiate(dentry, NULL);
goto out;
}
if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
return -ENAMETOOLONG;
open_flags = nd->intent.open.flags;
attr.ia_valid = ATTR_OPEN;
ctx = create_nfs_open_context(dentry, open_flags);
res = ERR_CAST(ctx);
if (IS_ERR(ctx))
goto out;
if (nd->flags & LOOKUP_CREATE) {
attr.ia_mode = nd->intent.open.create_mode;
if (open_flags & O_CREAT) {
attr.ia_valid |= ATTR_MODE;
attr.ia_mode &= ~current_umask();
} else
open_flags &= ~(O_EXCL | O_CREAT);
attr.ia_mode = mode & ~current_umask();
}
if (open_flags & O_TRUNC) {
attr.ia_valid |= ATTR_SIZE;
attr.ia_size = 0;
}
/* Open the file on the server */
ctx = create_nfs_open_context(dentry, open_flags);
err = PTR_ERR(ctx);
if (IS_ERR(ctx))
goto out;
nfs_block_sillyrename(dentry->d_parent);
inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
d_drop(dentry);
if (IS_ERR(inode)) {
nfs_unblock_sillyrename(dentry->d_parent);
put_nfs_open_context(ctx);
switch (PTR_ERR(inode)) {
/* Make a negative dentry */
case -ENOENT:
d_add(dentry, NULL);
res = NULL;
goto out;
/* This turned out not to be a regular file */
case -EISDIR:
case -ENOTDIR:
err = PTR_ERR(inode);
switch (err) {
case -ENOENT:
d_add(dentry, NULL);
break;
case -EISDIR:
case -ENOTDIR:
goto no_open;
case -ELOOP:
if (!(open_flags & O_NOFOLLOW))
goto no_open;
case -ELOOP:
if (!(nd->intent.open.flags & O_NOFOLLOW))
goto no_open;
break;
/* case -EINVAL: */
default:
res = ERR_CAST(inode);
goto out;
default:
break;
}
goto out;
}
res = d_add_unique(dentry, inode);
nfs_unblock_sillyrename(dentry->d_parent);
if (res != NULL) {
dput(ctx->dentry);
ctx->dentry = dget(res);
if (res != NULL)
dentry = res;
}
err = nfs_intent_set_file(nd, ctx);
if (err < 0) {
if (res != NULL)
dput(res);
return ERR_PTR(err);
}
out:
nfs_unblock_sillyrename(dentry->d_parent);
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
return res;
err = nfs_finish_open(ctx, dentry, file, open_flags, opened);
dput(res);
out:
return err;
no_open:
return nfs_lookup(dir, dentry, nd);
res = nfs_lookup(dir, dentry, 0);
err = PTR_ERR(res);
if (IS_ERR(res))
goto out;
return finish_no_open(file, res);
}
static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
{
struct dentry *parent = NULL;
struct inode *inode;
struct inode *dir;
int openflags, ret = 0;
int ret = 0;
if (nd->flags & LOOKUP_RCU)
if (flags & LOOKUP_RCU)
return -ECHILD;
inode = dentry->d_inode;
if (!is_atomic_open(nd) || d_mountpoint(dentry))
if (!(flags & LOOKUP_OPEN) || (flags & LOOKUP_DIRECTORY))
goto no_open;
if (d_mountpoint(dentry))
goto no_open;
inode = dentry->d_inode;
parent = dget_parent(dentry);
dir = parent->d_inode;
@ -1540,7 +1513,7 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
* optimize away revalidation of negative dentries.
*/
if (inode == NULL) {
if (!nfs_neg_need_reval(dir, dentry, nd))
if (!nfs_neg_need_reval(dir, dentry, flags))
ret = 1;
goto out;
}
@ -1548,9 +1521,8 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
/* NFS only supports OPEN on regular files */
if (!S_ISREG(inode->i_mode))
goto no_open_dput;
openflags = nd->intent.open.flags;
/* We cannot do exclusive creation on a positive dentry */
if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
if (flags & LOOKUP_EXCL)
goto no_open_dput;
/* Let f_op->open() actually open (and revalidate) the file */
@ -1563,48 +1535,7 @@ out:
no_open_dput:
dput(parent);
no_open:
return nfs_lookup_revalidate(dentry, nd);
}
static int nfs_open_create(struct inode *dir, struct dentry *dentry,
umode_t mode, struct nameidata *nd)
{
struct nfs_open_context *ctx = NULL;
struct iattr attr;
int error;
int open_flags = O_CREAT|O_EXCL;
dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
if (nd)
open_flags = nd->intent.open.flags;
ctx = create_nfs_open_context(dentry, open_flags);
error = PTR_ERR(ctx);
if (IS_ERR(ctx))
goto out_err_drop;
error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
if (error != 0)
goto out_put_ctx;
if (nd) {
error = nfs_intent_set_file(nd, ctx);
if (error < 0)
goto out_err;
} else {
put_nfs_open_context(ctx);
}
return 0;
out_put_ctx:
put_nfs_open_context(ctx);
out_err_drop:
d_drop(dentry);
out_err:
return error;
return nfs_lookup_revalidate(dentry, flags);
}
#endif /* CONFIG_NFSV4 */
@ -1658,11 +1589,11 @@ out_error:
* reply path made it appear to have failed.
*/
static int nfs_create(struct inode *dir, struct dentry *dentry,
umode_t mode, struct nameidata *nd)
umode_t mode, bool excl)
{
struct iattr attr;
int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT;
int error;
int open_flags = O_CREAT|O_EXCL;
dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@ -1670,10 +1601,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry,
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
if (nd)
open_flags = nd->intent.open.flags;
error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL);
error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
if (error != 0)
goto out_err;
return 0;

View file

@ -62,7 +62,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
*/
spin_lock(&sb->s_root->d_inode->i_lock);
spin_lock(&sb->s_root->d_lock);
list_del_init(&sb->s_root->d_alias);
hlist_del_init(&sb->s_root->d_alias);
spin_unlock(&sb->s_root->d_lock);
spin_unlock(&sb->s_root->d_inode->i_lock);
}

View file

@ -314,7 +314,7 @@ static void nfs3_free_createdata(struct nfs3_createdata *data)
*/
static int
nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags, struct nfs_open_context *ctx)
int flags)
{
struct nfs3_createdata *data;
umode_t mode = sattr->ia_mode;

View file

@ -2806,37 +2806,22 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page,
}
/*
* Got race?
* We will need to arrange for the VFS layer to provide an atomic open.
* Until then, this create/open method is prone to inefficiency and race
* conditions due to the lookup, create, and open VFS calls from sys_open()
* placed on the wire.
*
* Given the above sorry state of affairs, I'm simply sending an OPEN.
* The file will be opened again in the subsequent VFS open call
* (nfs4_proc_file_open).
*
* The open for read will just hang around to be used by any process that
* opens the file O_RDONLY. This will all be resolved with the VFS changes.
* This is just for mknod. open(O_CREAT) will always do ->open_context().
*/
static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags, struct nfs_open_context *ctx)
int flags)
{
struct dentry *de = dentry;
struct nfs_open_context *ctx;
struct nfs4_state *state;
struct rpc_cred *cred = NULL;
fmode_t fmode = 0;
int status = 0;
if (ctx != NULL) {
cred = ctx->cred;
de = ctx->dentry;
fmode = ctx->mode;
}
ctx = alloc_nfs_open_context(dentry, FMODE_READ);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
sattr->ia_mode &= ~current_umask();
state = nfs4_do_open(dir, de, fmode, flags, sattr, cred, NULL);
state = nfs4_do_open(dir, dentry, ctx->mode, flags, sattr, ctx->cred, NULL);
d_drop(dentry);
if (IS_ERR(state)) {
status = PTR_ERR(state);
@ -2844,11 +2829,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
}
d_add(dentry, igrab(state->inode));
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
if (ctx != NULL)
ctx->state = state;
else
nfs4_close_sync(state, fmode);
ctx->state = state;
out:
put_nfs_open_context(ctx);
return status;
}

View file

@ -259,7 +259,7 @@ static void nfs_free_createdata(const struct nfs_createdata *data)
static int
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags, struct nfs_open_context *ctx)
int flags)
{
struct nfs_createdata *data;
struct rpc_message msg = {

View file

@ -2419,7 +2419,7 @@ static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type,
sb_mntdata.mntflags |= MS_SYNCHRONOUS;
/* Get a superblock - note that we may end up sharing one that already exists */
s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata);
s = sget(fs_type, compare_super, nfs_set_super, flags, &sb_mntdata);
if (IS_ERR(s)) {
mntroot = ERR_CAST(s);
goto out_err_nosb;