History

NFSv4: Honour the 'opened' parameter in the atomic_open() filesystem method

Determine if we've created a new file by examining the directory change attribute and/or the O_EXCL flag. This fixes a regression when doing a non-exclusive create of a new file. If the FILE_CREATED flag is not set, the atomic_open() command will perform full file access permissions checks instead of just checking for MAY_OPEN.

Trond Myklebust committed 13 years ago

Commit 5bc2afc1 parent 4a10c2a4 files · +24 −10Browse files

Unified · Split

4 files
  1. fs/nfs/dir.c +1 −1
  2. fs/nfs/nfs4file.c +2 −1
  3. fs/nfs/nfs4proc.c +19 −7
  4. include/linux/nfs_xdr.h +2 −1
fs/nfs/dir.c+1−1
@@ -1458,7 +1458,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, · 1457 unmodified lines
1458 1458
1459 trace_nfs_atomic_open_enter(dir, ctx, open_flags);1459 trace_nfs_atomic_open_enter(dir, ctx, open_flags);
1460 nfs_block_sillyrename(dentry->d_parent);1460 nfs_block_sillyrename(dentry->d_parent);
1461 inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);1461 inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, opened);
1462 nfs_unblock_sillyrename(dentry->d_parent);1462 nfs_unblock_sillyrename(dentry->d_parent);
1463 if (IS_ERR(inode)) {1463 if (IS_ERR(inode)) {
1464 err = PTR_ERR(inode);1464 err = PTR_ERR(inode);
fs/nfs/nfs4file.c+2−1
@@ -19,6 +19,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) · 18 unmodified lines
19 struct inode *dir;19 struct inode *dir;
20 unsigned openflags = filp->f_flags;20 unsigned openflags = filp->f_flags;
21 struct iattr attr;21 struct iattr attr;
22 int opened = 0;
22 int err;23 int err;
23 24
24 /*25 /*
@@ -55,7 +56,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) · 30 unmodified lines
55 nfs_wb_all(inode);56 nfs_wb_all(inode);
56 }57 }
57 58
58 inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);59 inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened);
59 if (IS_ERR(inode)) {60 if (IS_ERR(inode)) {
60 err = PTR_ERR(inode);61 err = PTR_ERR(inode);
61 switch (err) {62 switch (err) {
fs/nfs/nfs4proc.c+19−7
@@ -912,6 +912,7 @@ struct nfs4_opendata { · 911 unmodified lines
912 struct iattr attrs;912 struct iattr attrs;
913 unsigned long timestamp;913 unsigned long timestamp;
914 unsigned int rpc_done : 1;914 unsigned int rpc_done : 1;
915 unsigned int file_created : 1;
915 unsigned int is_recover : 1;916 unsigned int is_recover : 1;
916 int rpc_status;917 int rpc_status;
917 int cancelled;918 int cancelled;
@@ -1946,8 +1947,13 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) · 1028 unmodified lines
1946 1947
1947 nfs_fattr_map_and_free_names(server, &data->f_attr);1948 nfs_fattr_map_and_free_names(server, &data->f_attr);
1948 1949
1949 if (o_arg->open_flags & O_CREAT)1950 if (o_arg->open_flags & O_CREAT) {
1950 update_changeattr(dir, &o_res->cinfo);1951 update_changeattr(dir, &o_res->cinfo);
1952 if (o_arg->open_flags & O_EXCL)
1953 data->file_created = 1;
1954 else if (o_res->cinfo.before != o_res->cinfo.after)
1955 data->file_created = 1;
1956 }
1951 if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)1957 if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
1952 server->caps &= ~NFS_CAP_POSIX_LOCK;1958 server->caps &= ~NFS_CAP_POSIX_LOCK;
1953 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {1959 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
@@ -2191,7 +2197,8 @@ static int _nfs4_do_open(struct inode *dir, · 237 unmodified lines
2191 struct nfs_open_context *ctx,2197 struct nfs_open_context *ctx,
2192 int flags,2198 int flags,
2193 struct iattr *sattr,2199 struct iattr *sattr,
2194 struct nfs4_label *label)2200 struct nfs4_label *label,
2201 int *opened)
2195{2202{
2196 struct nfs4_state_owner *sp;2203 struct nfs4_state_owner *sp;
2197 struct nfs4_state *state = NULL;2204 struct nfs4_state *state = NULL;
@@ -2261,6 +2268,8 @@ static int _nfs4_do_open(struct inode *dir, · 63 unmodified lines
2261 nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel);2268 nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel);
2262 }2269 }
2263 }2270 }
2271 if (opendata->file_created)
2272 *opened |= FILE_CREATED;
2264 2273
2265 if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server))2274 if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server))
2266 *ctx_th = opendata->f_attr.mdsthreshold;2275 *ctx_th = opendata->f_attr.mdsthreshold;
@@ -2289,7 +2298,8 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, · 22 unmodified lines
2289 struct nfs_open_context *ctx,2298 struct nfs_open_context *ctx,
2290 int flags,2299 int flags,
2291 struct iattr *sattr,2300 struct iattr *sattr,
2292 struct nfs4_label *label)2301 struct nfs4_label *label,
2302 int *opened)
2293{2303{
2294 struct nfs_server *server = NFS_SERVER(dir);2304 struct nfs_server *server = NFS_SERVER(dir);
2295 struct nfs4_exception exception = { };2305 struct nfs4_exception exception = { };
@@ -2297,7 +2307,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, · 1 unmodified line
2297 int status;2307 int status;
2298 2308
2299 do {2309 do {
2300 status = _nfs4_do_open(dir, ctx, flags, sattr, label);2310 status = _nfs4_do_open(dir, ctx, flags, sattr, label, opened);
2301 res = ctx->state;2311 res = ctx->state;
2302 trace_nfs4_open_file(ctx, flags, status);2312 trace_nfs4_open_file(ctx, flags, status);
2303 if (status == 0)2313 if (status == 0)
@@ -2659,7 +2669,8 @@ out: · 355 unmodified lines
2659}2669}
2660 2670
2661static struct inode *2671static struct inode *
2662nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)2672nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx,
2673 int open_flags, struct iattr *attr, int *opened)
2663{2674{
2664 struct nfs4_state *state;2675 struct nfs4_state *state;
2665 struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL;2676 struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL;
@@ -2667,7 +2678,7 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags · 1 unmodified line
2667 label = nfs4_label_init_security(dir, ctx->dentry, attr, &l);2678 label = nfs4_label_init_security(dir, ctx->dentry, attr, &l);
2668 2679
2669 /* Protect against concurrent sillydeletes */2680 /* Protect against concurrent sillydeletes */
2670 state = nfs4_do_open(dir, ctx, open_flags, attr, label);2681 state = nfs4_do_open(dir, ctx, open_flags, attr, label, opened);
2671 2682
2672 nfs4_label_release_security(label);2683 nfs4_label_release_security(label);
2673 2684
@@ -3332,6 +3343,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, · 658 unmodified lines
3332 struct nfs4_label l, *ilabel = NULL;3343 struct nfs4_label l, *ilabel = NULL;
3333 struct nfs_open_context *ctx;3344 struct nfs_open_context *ctx;
3334 struct nfs4_state *state;3345 struct nfs4_state *state;
3346 int opened = 0;
3335 int status = 0;3347 int status = 0;
3336 3348
3337 ctx = alloc_nfs_open_context(dentry, FMODE_READ);3349 ctx = alloc_nfs_open_context(dentry, FMODE_READ);
@@ -3341,7 +3353,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, · 3 unmodified lines
3341 ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);3353 ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);
3342 3354
3343 sattr->ia_mode &= ~current_umask();3355 sattr->ia_mode &= ~current_umask();
3344 state = nfs4_do_open(dir, ctx, flags, sattr, ilabel);3356 state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, &opened);
3345 if (IS_ERR(state)) {3357 if (IS_ERR(state)) {
3346 status = PTR_ERR(state);3358 status = PTR_ERR(state);
3347 goto out;3359 goto out;
include/linux/nfs_xdr.h+2−1
@@ -1455,7 +1455,8 @@ struct nfs_rpc_ops { · 1454 unmodified lines
1455 struct inode * (*open_context) (struct inode *dir,1455 struct inode * (*open_context) (struct inode *dir,
1456 struct nfs_open_context *ctx,1456 struct nfs_open_context *ctx,
1457 int open_flags,1457 int open_flags,
1458 struct iattr *iattr);1458 struct iattr *iattr,
1459 int *);
1459 int (*have_delegation)(struct inode *, fmode_t);1460 int (*have_delegation)(struct inode *, fmode_t);
1460 int (*return_delegation)(struct inode *);1461 int (*return_delegation)(struct inode *);
1461 struct nfs_client *(*alloc_client) (const struct nfs_client_initdata *);1462 struct nfs_client *(*alloc_client) (const struct nfs_client_initdata *);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t