Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 217035
b: refs/heads/master
c: cd9a1c0
h: refs/heads/master
i:
  217033: 9bda7c2
  217031: 16a35a2
v: v3
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Sep 17, 2010
1 parent d825e96 commit 8af4cd0
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 37 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 859d5024f450686ad0a42ed3c06f2fa20295c9e6
refs/heads/master: cd9a1c0e5ac681871d64804f82291649e2a0accb
77 changes: 75 additions & 2 deletions trunk/fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "delegation.h"
#include "iostat.h"
#include "internal.h"
#include "fscache.h"

/* #define NFS_DEBUG_VERBOSE 1 */

Expand Down Expand Up @@ -1029,9 +1030,61 @@ static int is_atomic_open(struct nameidata *nd)
return 1;
}

static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd)
{
struct path path = {
.mnt = nd->path.mnt,
.dentry = dentry,
};
struct nfs_open_context *ctx;
struct rpc_cred *cred;
fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);

cred = rpc_lookup_cred();
if (IS_ERR(cred))
return ERR_CAST(cred);
ctx = alloc_nfs_open_context(&path, cred, fmode);
put_rpccred(cred);
if (ctx == NULL)
return ERR_PTR(-ENOMEM);
return ctx;
}

static int do_open(struct inode *inode, struct file *filp)
{
nfs_fscache_set_inode_cookie(inode, filp);
return 0;
}

static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
{
struct file *filp;
int ret = 0;

/* If the open_intent is for execute, we have an extra check to make */
if (ctx->mode & FMODE_EXEC) {
ret = nfs_may_open(ctx->path.dentry->d_inode,
ctx->cred,
nd->intent.open.flags);
if (ret < 0)
goto out;
}
filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open);
if (IS_ERR(filp))
ret = PTR_ERR(filp);
else
nfs_file_set_open_context(filp, ctx);
out:
put_nfs_open_context(ctx);
return ret;
}

static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct nfs_open_context *ctx;
struct iattr attr;
struct dentry *res = NULL;
int open_flags;
int error;

dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
Expand All @@ -1054,9 +1107,27 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
goto out;
}

ctx = nameidata_to_nfs_open_context(dentry, nd);
res = ERR_CAST(ctx);
if (IS_ERR(ctx))
goto out;

open_flags = nd->intent.open.flags;
if (nd->flags & LOOKUP_CREATE) {
attr.ia_mode = nd->intent.open.create_mode;
attr.ia_valid = ATTR_MODE;
if (!IS_POSIXACL(dir))
attr.ia_mode &= ~current_umask();
} else {
open_flags &= ~O_EXCL;
attr.ia_valid = 0;
BUG_ON(open_flags & O_CREAT);
}

/* Open the file on the server */
res = nfs4_atomic_open(dir, dentry, nd);
res = nfs4_atomic_open(dir, ctx, open_flags, &attr);
if (IS_ERR(res)) {
put_nfs_open_context(ctx);
error = PTR_ERR(res);
switch (error) {
/* Make a negative dentry */
Expand All @@ -1074,8 +1145,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
default:
goto out;
}
} else if (res != NULL)
}
if (res != NULL)
dentry = res;
nfs_intent_set_file(nd, ctx);
out:
return res;
no_open:
Expand Down
8 changes: 4 additions & 4 deletions trunk/fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
nfs_revalidate_inode(server, inode);
}

static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred)
struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode)
{
struct nfs_open_context *ctx;

Expand All @@ -633,6 +633,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
path_get(&ctx->path);
ctx->cred = get_rpccred(cred);
ctx->state = NULL;
ctx->mode = f_mode;
ctx->flags = 0;
ctx->error = 0;
ctx->dir_cookie = 0;
Expand Down Expand Up @@ -673,7 +674,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
* Ensure that mmap has a recent RPC credential for use when writing out
* shared pages
*/
static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
{
struct inode *inode = filp->f_path.dentry->d_inode;
struct nfs_inode *nfsi = NFS_I(inode);
Expand Down Expand Up @@ -730,11 +731,10 @@ int nfs_open(struct inode *inode, struct file *filp)
cred = rpc_lookup_cred();
if (IS_ERR(cred))
return PTR_ERR(cred);
ctx = alloc_nfs_open_context(&filp->f_path, cred);
ctx = alloc_nfs_open_context(&filp->f_path, cred, filp->f_mode);
put_rpccred(cred);
if (ctx == NULL)
return -ENOMEM;
ctx->mode = filp->f_mode;
nfs_file_set_open_context(filp, ctx);
put_nfs_open_context(ctx);
nfs_fscache_set_inode_cookie(inode, filp);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/nfs/nfs4_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern struct dentry *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
Expand Down
40 changes: 11 additions & 29 deletions trunk/fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2025,39 +2025,17 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
}

struct dentry *
nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
{
struct path path = {
.mnt = nd->path.mnt,
.dentry = dentry,
};
struct dentry *dentry = ctx->path.dentry;
struct dentry *parent;
struct iattr attr;
struct rpc_cred *cred;
struct nfs4_state *state;
struct dentry *res;
int open_flags = nd->intent.open.flags;
fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);

if (nd->flags & LOOKUP_CREATE) {
attr.ia_mode = nd->intent.open.create_mode;
attr.ia_valid = ATTR_MODE;
if (!IS_POSIXACL(dir))
attr.ia_mode &= ~current_umask();
} else {
open_flags &= ~O_EXCL;
attr.ia_valid = 0;
BUG_ON(open_flags & O_CREAT);
}

cred = rpc_lookup_cred();
if (IS_ERR(cred))
return (struct dentry *)cred;
parent = dentry->d_parent;
/* Protect against concurrent sillydeletes */
nfs_block_sillyrename(parent);
state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred);
put_rpccred(cred);
state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
if (IS_ERR(state)) {
if (PTR_ERR(state) == -ENOENT) {
d_add(dentry, NULL);
Expand All @@ -2067,11 +2045,15 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
return (struct dentry *)state;
}
res = d_add_unique(dentry, igrab(state->inode));
if (res != NULL)
path.dentry = res;
nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
if (res != NULL) {
struct dentry *dummy = ctx->path.dentry;

ctx->path.dentry = dget(res);
dput(dummy);
}
ctx->state = state;
nfs_set_verifier(ctx->path.dentry, nfs_save_change_attribute(dir));
nfs_unblock_sillyrename(parent);
nfs4_intent_set_file(nd, &path, state, fmode);
return res;
}

Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/nfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
extern void put_nfs_open_context(struct nfs_open_context *ctx);
extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
extern struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode);
extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
extern u64 nfs_compat_user_ino64(u64 fileid);
Expand Down

0 comments on commit 8af4cd0

Please sign in to comment.