diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/dir.c | 77 | ||||
-rw-r--r-- | fs/nfs/inode.c | 8 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 40 |
4 files changed, 91 insertions, 36 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e257172d438c..17529b5bc551 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "delegation.h" | 38 | #include "delegation.h" |
39 | #include "iostat.h" | 39 | #include "iostat.h" |
40 | #include "internal.h" | 40 | #include "internal.h" |
41 | #include "fscache.h" | ||
41 | 42 | ||
42 | /* #define NFS_DEBUG_VERBOSE 1 */ | 43 | /* #define NFS_DEBUG_VERBOSE 1 */ |
43 | 44 | ||
@@ -1029,9 +1030,61 @@ static int is_atomic_open(struct nameidata *nd) | |||
1029 | return 1; | 1030 | return 1; |
1030 | } | 1031 | } |
1031 | 1032 | ||
1033 | static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd) | ||
1034 | { | ||
1035 | struct path path = { | ||
1036 | .mnt = nd->path.mnt, | ||
1037 | .dentry = dentry, | ||
1038 | }; | ||
1039 | struct nfs_open_context *ctx; | ||
1040 | struct rpc_cred *cred; | ||
1041 | fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); | ||
1042 | |||
1043 | cred = rpc_lookup_cred(); | ||
1044 | if (IS_ERR(cred)) | ||
1045 | return ERR_CAST(cred); | ||
1046 | ctx = alloc_nfs_open_context(&path, cred, fmode); | ||
1047 | put_rpccred(cred); | ||
1048 | if (ctx == NULL) | ||
1049 | return ERR_PTR(-ENOMEM); | ||
1050 | return ctx; | ||
1051 | } | ||
1052 | |||
1053 | static int do_open(struct inode *inode, struct file *filp) | ||
1054 | { | ||
1055 | nfs_fscache_set_inode_cookie(inode, filp); | ||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx) | ||
1060 | { | ||
1061 | struct file *filp; | ||
1062 | int ret = 0; | ||
1063 | |||
1064 | /* If the open_intent is for execute, we have an extra check to make */ | ||
1065 | if (ctx->mode & FMODE_EXEC) { | ||
1066 | ret = nfs_may_open(ctx->path.dentry->d_inode, | ||
1067 | ctx->cred, | ||
1068 | nd->intent.open.flags); | ||
1069 | if (ret < 0) | ||
1070 | goto out; | ||
1071 | } | ||
1072 | filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open); | ||
1073 | if (IS_ERR(filp)) | ||
1074 | ret = PTR_ERR(filp); | ||
1075 | else | ||
1076 | nfs_file_set_open_context(filp, ctx); | ||
1077 | out: | ||
1078 | put_nfs_open_context(ctx); | ||
1079 | return ret; | ||
1080 | } | ||
1081 | |||
1032 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1082 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
1033 | { | 1083 | { |
1084 | struct nfs_open_context *ctx; | ||
1085 | struct iattr attr; | ||
1034 | struct dentry *res = NULL; | 1086 | struct dentry *res = NULL; |
1087 | int open_flags; | ||
1035 | int error; | 1088 | int error; |
1036 | 1089 | ||
1037 | dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n", | 1090 | dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n", |
@@ -1054,9 +1107,27 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1054 | goto out; | 1107 | goto out; |
1055 | } | 1108 | } |
1056 | 1109 | ||
1110 | ctx = nameidata_to_nfs_open_context(dentry, nd); | ||
1111 | res = ERR_CAST(ctx); | ||
1112 | if (IS_ERR(ctx)) | ||
1113 | goto out; | ||
1114 | |||
1115 | open_flags = nd->intent.open.flags; | ||
1116 | if (nd->flags & LOOKUP_CREATE) { | ||
1117 | attr.ia_mode = nd->intent.open.create_mode; | ||
1118 | attr.ia_valid = ATTR_MODE; | ||
1119 | if (!IS_POSIXACL(dir)) | ||
1120 | attr.ia_mode &= ~current_umask(); | ||
1121 | } else { | ||
1122 | open_flags &= ~O_EXCL; | ||
1123 | attr.ia_valid = 0; | ||
1124 | BUG_ON(open_flags & O_CREAT); | ||
1125 | } | ||
1126 | |||
1057 | /* Open the file on the server */ | 1127 | /* Open the file on the server */ |
1058 | res = nfs4_atomic_open(dir, dentry, nd); | 1128 | res = nfs4_atomic_open(dir, ctx, open_flags, &attr); |
1059 | if (IS_ERR(res)) { | 1129 | if (IS_ERR(res)) { |
1130 | put_nfs_open_context(ctx); | ||
1060 | error = PTR_ERR(res); | 1131 | error = PTR_ERR(res); |
1061 | switch (error) { | 1132 | switch (error) { |
1062 | /* Make a negative dentry */ | 1133 | /* Make a negative dentry */ |
@@ -1074,8 +1145,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1074 | default: | 1145 | default: |
1075 | goto out; | 1146 | goto out; |
1076 | } | 1147 | } |
1077 | } else if (res != NULL) | 1148 | } |
1149 | if (res != NULL) | ||
1078 | dentry = res; | 1150 | dentry = res; |
1151 | nfs_intent_set_file(nd, ctx); | ||
1079 | out: | 1152 | out: |
1080 | return res; | 1153 | return res; |
1081 | no_open: | 1154 | no_open: |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 7d2d6c72aa78..2f9266406afc 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -623,7 +623,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync) | |||
623 | nfs_revalidate_inode(server, inode); | 623 | nfs_revalidate_inode(server, inode); |
624 | } | 624 | } |
625 | 625 | ||
626 | static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred) | 626 | struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode) |
627 | { | 627 | { |
628 | struct nfs_open_context *ctx; | 628 | struct nfs_open_context *ctx; |
629 | 629 | ||
@@ -633,6 +633,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct | |||
633 | path_get(&ctx->path); | 633 | path_get(&ctx->path); |
634 | ctx->cred = get_rpccred(cred); | 634 | ctx->cred = get_rpccred(cred); |
635 | ctx->state = NULL; | 635 | ctx->state = NULL; |
636 | ctx->mode = f_mode; | ||
636 | ctx->flags = 0; | 637 | ctx->flags = 0; |
637 | ctx->error = 0; | 638 | ctx->error = 0; |
638 | ctx->dir_cookie = 0; | 639 | ctx->dir_cookie = 0; |
@@ -673,7 +674,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx) | |||
673 | * Ensure that mmap has a recent RPC credential for use when writing out | 674 | * Ensure that mmap has a recent RPC credential for use when writing out |
674 | * shared pages | 675 | * shared pages |
675 | */ | 676 | */ |
676 | static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) | 677 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) |
677 | { | 678 | { |
678 | struct inode *inode = filp->f_path.dentry->d_inode; | 679 | struct inode *inode = filp->f_path.dentry->d_inode; |
679 | struct nfs_inode *nfsi = NFS_I(inode); | 680 | struct nfs_inode *nfsi = NFS_I(inode); |
@@ -730,11 +731,10 @@ int nfs_open(struct inode *inode, struct file *filp) | |||
730 | cred = rpc_lookup_cred(); | 731 | cred = rpc_lookup_cred(); |
731 | if (IS_ERR(cred)) | 732 | if (IS_ERR(cred)) |
732 | return PTR_ERR(cred); | 733 | return PTR_ERR(cred); |
733 | ctx = alloc_nfs_open_context(&filp->f_path, cred); | 734 | ctx = alloc_nfs_open_context(&filp->f_path, cred, filp->f_mode); |
734 | put_rpccred(cred); | 735 | put_rpccred(cred); |
735 | if (ctx == NULL) | 736 | if (ctx == NULL) |
736 | return -ENOMEM; | 737 | return -ENOMEM; |
737 | ctx->mode = filp->f_mode; | ||
738 | nfs_file_set_open_context(filp, ctx); | 738 | nfs_file_set_open_context(filp, ctx); |
739 | put_nfs_open_context(ctx); | 739 | put_nfs_open_context(ctx); |
740 | nfs_fscache_set_inode_cookie(inode, filp); | 740 | nfs_fscache_set_inode_cookie(inode, filp); |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 311e15cc8af0..c5cc2a6aceb0 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -242,7 +242,7 @@ extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); | |||
242 | extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); | 242 | extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); |
243 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); | 243 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); |
244 | extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait); | 244 | extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait); |
245 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); | 245 | extern struct dentry *nfs4_atomic_open(struct inode *, struct nfs_open_context *, int, struct iattr *); |
246 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); | 246 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); |
247 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); | 247 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); |
248 | extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | 248 | extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 089da5b5d20a..38c3bed2240d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2025,39 +2025,17 @@ out_close: | |||
2025 | } | 2025 | } |
2026 | 2026 | ||
2027 | struct dentry * | 2027 | struct dentry * |
2028 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 2028 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) |
2029 | { | 2029 | { |
2030 | struct path path = { | 2030 | struct dentry *dentry = ctx->path.dentry; |
2031 | .mnt = nd->path.mnt, | ||
2032 | .dentry = dentry, | ||
2033 | }; | ||
2034 | struct dentry *parent; | 2031 | struct dentry *parent; |
2035 | struct iattr attr; | ||
2036 | struct rpc_cred *cred; | ||
2037 | struct nfs4_state *state; | 2032 | struct nfs4_state *state; |
2038 | struct dentry *res; | 2033 | struct dentry *res; |
2039 | int open_flags = nd->intent.open.flags; | ||
2040 | fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); | ||
2041 | |||
2042 | if (nd->flags & LOOKUP_CREATE) { | ||
2043 | attr.ia_mode = nd->intent.open.create_mode; | ||
2044 | attr.ia_valid = ATTR_MODE; | ||
2045 | if (!IS_POSIXACL(dir)) | ||
2046 | attr.ia_mode &= ~current_umask(); | ||
2047 | } else { | ||
2048 | open_flags &= ~O_EXCL; | ||
2049 | attr.ia_valid = 0; | ||
2050 | BUG_ON(open_flags & O_CREAT); | ||
2051 | } | ||
2052 | 2034 | ||
2053 | cred = rpc_lookup_cred(); | ||
2054 | if (IS_ERR(cred)) | ||
2055 | return (struct dentry *)cred; | ||
2056 | parent = dentry->d_parent; | 2035 | parent = dentry->d_parent; |
2057 | /* Protect against concurrent sillydeletes */ | 2036 | /* Protect against concurrent sillydeletes */ |
2058 | nfs_block_sillyrename(parent); | 2037 | nfs_block_sillyrename(parent); |
2059 | state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred); | 2038 | state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred); |
2060 | put_rpccred(cred); | ||
2061 | if (IS_ERR(state)) { | 2039 | if (IS_ERR(state)) { |
2062 | if (PTR_ERR(state) == -ENOENT) { | 2040 | if (PTR_ERR(state) == -ENOENT) { |
2063 | d_add(dentry, NULL); | 2041 | d_add(dentry, NULL); |
@@ -2067,11 +2045,15 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
2067 | return (struct dentry *)state; | 2045 | return (struct dentry *)state; |
2068 | } | 2046 | } |
2069 | res = d_add_unique(dentry, igrab(state->inode)); | 2047 | res = d_add_unique(dentry, igrab(state->inode)); |
2070 | if (res != NULL) | 2048 | if (res != NULL) { |
2071 | path.dentry = res; | 2049 | struct dentry *dummy = ctx->path.dentry; |
2072 | nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); | 2050 | |
2051 | ctx->path.dentry = dget(res); | ||
2052 | dput(dummy); | ||
2053 | } | ||
2054 | ctx->state = state; | ||
2055 | nfs_set_verifier(ctx->path.dentry, nfs_save_change_attribute(dir)); | ||
2073 | nfs_unblock_sillyrename(parent); | 2056 | nfs_unblock_sillyrename(parent); |
2074 | nfs4_intent_set_file(nd, &path, state, fmode); | ||
2075 | return res; | 2057 | return res; |
2076 | } | 2058 | } |
2077 | 2059 | ||