diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-07-16 12:01:42 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-07-16 12:01:42 -0400 |
commit | 8626e4a42675ff9903f7d4fbf14d8ebc11b5926c (patch) | |
tree | c631dfe2854cb1382a5d8f5aa11b071762ddf27d /fs/nfs/dir.c | |
parent | a8d8f02cf0c379693762107afe812b9e52090e39 (diff) | |
parent | 9249e17fe094d853d1ef7475dd559a2cc7e23d42 (diff) |
Merge commit '9249e17fe094d853d1ef7475dd559a2cc7e23d42' into nfs-for-3.6
Resolve conflicts with the VFS atomic open and sget changes.
Conflicts:
fs/nfs/nfs4proc.c
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 314 |
1 files changed, 121 insertions, 193 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 68e451f59305..b7136853ca9c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -46,8 +46,8 @@ | |||
46 | static int nfs_opendir(struct inode *, struct file *); | 46 | static int nfs_opendir(struct inode *, struct file *); |
47 | static int nfs_closedir(struct inode *, struct file *); | 47 | static int nfs_closedir(struct inode *, struct file *); |
48 | static int nfs_readdir(struct file *, void *, filldir_t); | 48 | static int nfs_readdir(struct file *, void *, filldir_t); |
49 | static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 49 | static struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int); |
50 | static int nfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *); | 50 | static int nfs_create(struct inode *, struct dentry *, umode_t, bool); |
51 | static int nfs_mkdir(struct inode *, struct dentry *, umode_t); | 51 | static int nfs_mkdir(struct inode *, struct dentry *, umode_t); |
52 | static int nfs_rmdir(struct inode *, struct dentry *); | 52 | static int nfs_rmdir(struct inode *, struct dentry *); |
53 | static int nfs_unlink(struct inode *, struct dentry *); | 53 | static int nfs_unlink(struct inode *, struct dentry *); |
@@ -111,11 +111,13 @@ const struct inode_operations nfs3_dir_inode_operations = { | |||
111 | 111 | ||
112 | #ifdef CONFIG_NFS_V4 | 112 | #ifdef CONFIG_NFS_V4 |
113 | 113 | ||
114 | static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); | 114 | static int nfs_atomic_open(struct inode *, struct dentry *, |
115 | static int nfs_open_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd); | 115 | struct file *, unsigned, umode_t, |
116 | int *); | ||
116 | const struct inode_operations nfs4_dir_inode_operations = { | 117 | const struct inode_operations nfs4_dir_inode_operations = { |
117 | .create = nfs_open_create, | 118 | .create = nfs_create, |
118 | .lookup = nfs_atomic_lookup, | 119 | .lookup = nfs_lookup, |
120 | .atomic_open = nfs_atomic_open, | ||
119 | .link = nfs_link, | 121 | .link = nfs_link, |
120 | .unlink = nfs_unlink, | 122 | .unlink = nfs_unlink, |
121 | .symlink = nfs_symlink, | 123 | .symlink = nfs_symlink, |
@@ -1029,27 +1031,14 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | |||
1029 | } | 1031 | } |
1030 | 1032 | ||
1031 | /* | 1033 | /* |
1032 | * Return the intent data that applies to this particular path component | ||
1033 | * | ||
1034 | * Note that the current set of intents only apply to the very last | ||
1035 | * component of the path and none of them is set before that last | ||
1036 | * component. | ||
1037 | */ | ||
1038 | static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, | ||
1039 | unsigned int mask) | ||
1040 | { | ||
1041 | return nd->flags & mask; | ||
1042 | } | ||
1043 | |||
1044 | /* | ||
1045 | * Use intent information to check whether or not we're going to do | 1034 | * Use intent information to check whether or not we're going to do |
1046 | * an O_EXCL create using this path component. | 1035 | * an O_EXCL create using this path component. |
1047 | */ | 1036 | */ |
1048 | static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | 1037 | static int nfs_is_exclusive_create(struct inode *dir, unsigned int flags) |
1049 | { | 1038 | { |
1050 | if (NFS_PROTO(dir)->version == 2) | 1039 | if (NFS_PROTO(dir)->version == 2) |
1051 | return 0; | 1040 | return 0; |
1052 | return nd && nfs_lookup_check_intent(nd, LOOKUP_EXCL); | 1041 | return flags & LOOKUP_EXCL; |
1053 | } | 1042 | } |
1054 | 1043 | ||
1055 | /* | 1044 | /* |
@@ -1061,25 +1050,20 @@ static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | |||
1061 | * | 1050 | * |
1062 | */ | 1051 | */ |
1063 | static inline | 1052 | static inline |
1064 | int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | 1053 | int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags) |
1065 | { | 1054 | { |
1066 | struct nfs_server *server = NFS_SERVER(inode); | 1055 | struct nfs_server *server = NFS_SERVER(inode); |
1067 | 1056 | ||
1068 | if (IS_AUTOMOUNT(inode)) | 1057 | if (IS_AUTOMOUNT(inode)) |
1069 | return 0; | 1058 | return 0; |
1070 | if (nd != NULL) { | 1059 | /* VFS wants an on-the-wire revalidation */ |
1071 | /* VFS wants an on-the-wire revalidation */ | 1060 | if (flags & LOOKUP_REVAL) |
1072 | if (nd->flags & LOOKUP_REVAL) | 1061 | goto out_force; |
1073 | goto out_force; | 1062 | /* This is an open(2) */ |
1074 | /* This is an open(2) */ | 1063 | if ((flags & LOOKUP_OPEN) && !(server->flags & NFS_MOUNT_NOCTO) && |
1075 | if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 && | 1064 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) |
1076 | !(server->flags & NFS_MOUNT_NOCTO) && | 1065 | goto out_force; |
1077 | (S_ISREG(inode->i_mode) || | 1066 | return 0; |
1078 | S_ISDIR(inode->i_mode))) | ||
1079 | goto out_force; | ||
1080 | return 0; | ||
1081 | } | ||
1082 | return nfs_revalidate_inode(server, inode); | ||
1083 | out_force: | 1067 | out_force: |
1084 | return __nfs_revalidate_inode(server, inode); | 1068 | return __nfs_revalidate_inode(server, inode); |
1085 | } | 1069 | } |
@@ -1093,10 +1077,10 @@ out_force: | |||
1093 | */ | 1077 | */ |
1094 | static inline | 1078 | static inline |
1095 | int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, | 1079 | int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, |
1096 | struct nameidata *nd) | 1080 | unsigned int flags) |
1097 | { | 1081 | { |
1098 | /* Don't revalidate a negative dentry if we're creating a new file */ | 1082 | /* Don't revalidate a negative dentry if we're creating a new file */ |
1099 | if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0) | 1083 | if (flags & LOOKUP_CREATE) |
1100 | return 0; | 1084 | return 0; |
1101 | if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) | 1085 | if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) |
1102 | return 1; | 1086 | return 1; |
@@ -1114,7 +1098,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, | |||
1114 | * If the parent directory is seen to have changed, we throw out the | 1098 | * If the parent directory is seen to have changed, we throw out the |
1115 | * cached dentry and do a new lookup. | 1099 | * cached dentry and do a new lookup. |
1116 | */ | 1100 | */ |
1117 | static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | 1101 | static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) |
1118 | { | 1102 | { |
1119 | struct inode *dir; | 1103 | struct inode *dir; |
1120 | struct inode *inode; | 1104 | struct inode *inode; |
@@ -1123,7 +1107,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1123 | struct nfs_fattr *fattr = NULL; | 1107 | struct nfs_fattr *fattr = NULL; |
1124 | int error; | 1108 | int error; |
1125 | 1109 | ||
1126 | if (nd->flags & LOOKUP_RCU) | 1110 | if (flags & LOOKUP_RCU) |
1127 | return -ECHILD; | 1111 | return -ECHILD; |
1128 | 1112 | ||
1129 | parent = dget_parent(dentry); | 1113 | parent = dget_parent(dentry); |
@@ -1132,7 +1116,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1132 | inode = dentry->d_inode; | 1116 | inode = dentry->d_inode; |
1133 | 1117 | ||
1134 | if (!inode) { | 1118 | if (!inode) { |
1135 | if (nfs_neg_need_reval(dir, dentry, nd)) | 1119 | if (nfs_neg_need_reval(dir, dentry, flags)) |
1136 | goto out_bad; | 1120 | goto out_bad; |
1137 | goto out_valid_noent; | 1121 | goto out_valid_noent; |
1138 | } | 1122 | } |
@@ -1148,8 +1132,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1148 | goto out_set_verifier; | 1132 | goto out_set_verifier; |
1149 | 1133 | ||
1150 | /* Force a full look up iff the parent directory has changed */ | 1134 | /* Force a full look up iff the parent directory has changed */ |
1151 | if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) { | 1135 | if (!nfs_is_exclusive_create(dir, flags) && nfs_check_verifier(dir, dentry)) { |
1152 | if (nfs_lookup_verify_inode(inode, nd)) | 1136 | if (nfs_lookup_verify_inode(inode, flags)) |
1153 | goto out_zap_parent; | 1137 | goto out_zap_parent; |
1154 | goto out_valid; | 1138 | goto out_valid; |
1155 | } | 1139 | } |
@@ -1286,7 +1270,7 @@ const struct dentry_operations nfs_dentry_operations = { | |||
1286 | .d_release = nfs_d_release, | 1270 | .d_release = nfs_d_release, |
1287 | }; | 1271 | }; |
1288 | 1272 | ||
1289 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 1273 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) |
1290 | { | 1274 | { |
1291 | struct dentry *res; | 1275 | struct dentry *res; |
1292 | struct dentry *parent; | 1276 | struct dentry *parent; |
@@ -1307,7 +1291,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
1307 | * If we're doing an exclusive create, optimize away the lookup | 1291 | * If we're doing an exclusive create, optimize away the lookup |
1308 | * but don't hash the dentry. | 1292 | * but don't hash the dentry. |
1309 | */ | 1293 | */ |
1310 | if (nfs_is_exclusive_create(dir, nd)) { | 1294 | if (nfs_is_exclusive_create(dir, flags)) { |
1311 | d_instantiate(dentry, NULL); | 1295 | d_instantiate(dentry, NULL); |
1312 | res = NULL; | 1296 | res = NULL; |
1313 | goto out; | 1297 | goto out; |
@@ -1354,7 +1338,7 @@ out: | |||
1354 | } | 1338 | } |
1355 | 1339 | ||
1356 | #ifdef CONFIG_NFS_V4 | 1340 | #ifdef CONFIG_NFS_V4 |
1357 | static int nfs4_lookup_revalidate(struct dentry *, struct nameidata *); | 1341 | static int nfs4_lookup_revalidate(struct dentry *, unsigned int); |
1358 | 1342 | ||
1359 | const struct dentry_operations nfs4_dentry_operations = { | 1343 | const struct dentry_operations nfs4_dentry_operations = { |
1360 | .d_revalidate = nfs4_lookup_revalidate, | 1344 | .d_revalidate = nfs4_lookup_revalidate, |
@@ -1364,24 +1348,6 @@ const struct dentry_operations nfs4_dentry_operations = { | |||
1364 | .d_release = nfs_d_release, | 1348 | .d_release = nfs_d_release, |
1365 | }; | 1349 | }; |
1366 | 1350 | ||
1367 | /* | ||
1368 | * Use intent information to determine whether we need to substitute | ||
1369 | * the NFSv4-style stateful OPEN for the LOOKUP call | ||
1370 | */ | ||
1371 | static int is_atomic_open(struct nameidata *nd) | ||
1372 | { | ||
1373 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0) | ||
1374 | return 0; | ||
1375 | /* NFS does not (yet) have a stateful open for directories */ | ||
1376 | if (nd->flags & LOOKUP_DIRECTORY) | ||
1377 | return 0; | ||
1378 | /* Are we trying to write to a read only partition? */ | ||
1379 | if (__mnt_is_readonly(nd->path.mnt) && | ||
1380 | (nd->intent.open.flags & (O_CREAT|O_TRUNC|O_ACCMODE))) | ||
1381 | return 0; | ||
1382 | return 1; | ||
1383 | } | ||
1384 | |||
1385 | static fmode_t flags_to_mode(int flags) | 1351 | static fmode_t flags_to_mode(int flags) |
1386 | { | 1352 | { |
1387 | fmode_t res = (__force fmode_t)flags & FMODE_EXEC; | 1353 | fmode_t res = (__force fmode_t)flags & FMODE_EXEC; |
@@ -1403,136 +1369,143 @@ static int do_open(struct inode *inode, struct file *filp) | |||
1403 | return 0; | 1369 | return 0; |
1404 | } | 1370 | } |
1405 | 1371 | ||
1406 | static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx) | 1372 | static int nfs_finish_open(struct nfs_open_context *ctx, |
1373 | struct dentry *dentry, | ||
1374 | struct file *file, unsigned open_flags, | ||
1375 | int *opened) | ||
1407 | { | 1376 | { |
1408 | struct file *filp; | 1377 | int err; |
1409 | int ret = 0; | 1378 | |
1379 | if (ctx->dentry != dentry) { | ||
1380 | dput(ctx->dentry); | ||
1381 | ctx->dentry = dget(dentry); | ||
1382 | } | ||
1410 | 1383 | ||
1411 | /* If the open_intent is for execute, we have an extra check to make */ | 1384 | /* If the open_intent is for execute, we have an extra check to make */ |
1412 | if (ctx->mode & FMODE_EXEC) { | 1385 | if (ctx->mode & FMODE_EXEC) { |
1413 | ret = nfs_may_open(ctx->dentry->d_inode, | 1386 | err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags); |
1414 | ctx->cred, | 1387 | if (err < 0) |
1415 | nd->intent.open.flags); | ||
1416 | if (ret < 0) | ||
1417 | goto out; | 1388 | goto out; |
1418 | } | 1389 | } |
1419 | filp = lookup_instantiate_filp(nd, ctx->dentry, do_open); | 1390 | |
1420 | if (IS_ERR(filp)) | 1391 | err = finish_open(file, dentry, do_open, opened); |
1421 | ret = PTR_ERR(filp); | 1392 | if (err) |
1422 | else | 1393 | goto out; |
1423 | nfs_file_set_open_context(filp, ctx); | 1394 | nfs_file_set_open_context(file, ctx); |
1395 | |||
1424 | out: | 1396 | out: |
1425 | put_nfs_open_context(ctx); | 1397 | put_nfs_open_context(ctx); |
1426 | return ret; | 1398 | return err; |
1427 | } | 1399 | } |
1428 | 1400 | ||
1429 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1401 | static int nfs_atomic_open(struct inode *dir, struct dentry *dentry, |
1402 | struct file *file, unsigned open_flags, | ||
1403 | umode_t mode, int *opened) | ||
1430 | { | 1404 | { |
1431 | struct nfs_open_context *ctx; | 1405 | struct nfs_open_context *ctx; |
1432 | struct iattr attr; | 1406 | struct dentry *res; |
1433 | struct dentry *res = NULL; | 1407 | struct iattr attr = { .ia_valid = ATTR_OPEN }; |
1434 | struct inode *inode; | 1408 | struct inode *inode; |
1435 | int open_flags; | ||
1436 | int err; | 1409 | int err; |
1437 | 1410 | ||
1438 | dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n", | 1411 | /* Expect a negative dentry */ |
1412 | BUG_ON(dentry->d_inode); | ||
1413 | |||
1414 | dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n", | ||
1439 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1415 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
1440 | 1416 | ||
1441 | /* Check that we are indeed trying to open this file */ | 1417 | /* NFS only supports OPEN on regular files */ |
1442 | if (!is_atomic_open(nd)) | 1418 | if ((open_flags & O_DIRECTORY)) { |
1419 | if (!d_unhashed(dentry)) { | ||
1420 | /* | ||
1421 | * Hashed negative dentry with O_DIRECTORY: dentry was | ||
1422 | * revalidated and is fine, no need to perform lookup | ||
1423 | * again | ||
1424 | */ | ||
1425 | return -ENOENT; | ||
1426 | } | ||
1443 | goto no_open; | 1427 | goto no_open; |
1444 | |||
1445 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) { | ||
1446 | res = ERR_PTR(-ENAMETOOLONG); | ||
1447 | goto out; | ||
1448 | } | ||
1449 | |||
1450 | /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash | ||
1451 | * the dentry. */ | ||
1452 | if (nd->flags & LOOKUP_EXCL) { | ||
1453 | d_instantiate(dentry, NULL); | ||
1454 | goto out; | ||
1455 | } | 1428 | } |
1456 | 1429 | ||
1457 | open_flags = nd->intent.open.flags; | 1430 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) |
1458 | attr.ia_valid = ATTR_OPEN; | 1431 | return -ENAMETOOLONG; |
1459 | |||
1460 | ctx = create_nfs_open_context(dentry, open_flags); | ||
1461 | res = ERR_CAST(ctx); | ||
1462 | if (IS_ERR(ctx)) | ||
1463 | goto out; | ||
1464 | 1432 | ||
1465 | if (nd->flags & LOOKUP_CREATE) { | 1433 | if (open_flags & O_CREAT) { |
1466 | attr.ia_mode = nd->intent.open.create_mode; | ||
1467 | attr.ia_valid |= ATTR_MODE; | 1434 | attr.ia_valid |= ATTR_MODE; |
1468 | attr.ia_mode &= ~current_umask(); | 1435 | attr.ia_mode = mode & ~current_umask(); |
1469 | } else | 1436 | } |
1470 | open_flags &= ~(O_EXCL | O_CREAT); | ||
1471 | |||
1472 | if (open_flags & O_TRUNC) { | 1437 | if (open_flags & O_TRUNC) { |
1473 | attr.ia_valid |= ATTR_SIZE; | 1438 | attr.ia_valid |= ATTR_SIZE; |
1474 | attr.ia_size = 0; | 1439 | attr.ia_size = 0; |
1475 | } | 1440 | } |
1476 | 1441 | ||
1477 | /* Open the file on the server */ | 1442 | ctx = create_nfs_open_context(dentry, open_flags); |
1443 | err = PTR_ERR(ctx); | ||
1444 | if (IS_ERR(ctx)) | ||
1445 | goto out; | ||
1446 | |||
1478 | nfs_block_sillyrename(dentry->d_parent); | 1447 | nfs_block_sillyrename(dentry->d_parent); |
1479 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1448 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); |
1449 | d_drop(dentry); | ||
1480 | if (IS_ERR(inode)) { | 1450 | if (IS_ERR(inode)) { |
1481 | nfs_unblock_sillyrename(dentry->d_parent); | 1451 | nfs_unblock_sillyrename(dentry->d_parent); |
1482 | put_nfs_open_context(ctx); | 1452 | put_nfs_open_context(ctx); |
1483 | switch (PTR_ERR(inode)) { | 1453 | err = PTR_ERR(inode); |
1484 | /* Make a negative dentry */ | 1454 | switch (err) { |
1485 | case -ENOENT: | 1455 | case -ENOENT: |
1486 | d_add(dentry, NULL); | 1456 | d_add(dentry, NULL); |
1487 | res = NULL; | 1457 | break; |
1488 | goto out; | 1458 | case -EISDIR: |
1489 | /* This turned out not to be a regular file */ | 1459 | case -ENOTDIR: |
1490 | case -EISDIR: | 1460 | goto no_open; |
1491 | case -ENOTDIR: | 1461 | case -ELOOP: |
1462 | if (!(open_flags & O_NOFOLLOW)) | ||
1492 | goto no_open; | 1463 | goto no_open; |
1493 | case -ELOOP: | 1464 | break; |
1494 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | ||
1495 | goto no_open; | ||
1496 | /* case -EINVAL: */ | 1465 | /* case -EINVAL: */ |
1497 | default: | 1466 | default: |
1498 | res = ERR_CAST(inode); | 1467 | break; |
1499 | goto out; | ||
1500 | } | 1468 | } |
1469 | goto out; | ||
1501 | } | 1470 | } |
1502 | res = d_add_unique(dentry, inode); | 1471 | res = d_add_unique(dentry, inode); |
1503 | nfs_unblock_sillyrename(dentry->d_parent); | 1472 | if (res != NULL) |
1504 | if (res != NULL) { | ||
1505 | dput(ctx->dentry); | ||
1506 | ctx->dentry = dget(res); | ||
1507 | dentry = res; | 1473 | dentry = res; |
1508 | } | 1474 | |
1509 | err = nfs_intent_set_file(nd, ctx); | 1475 | nfs_unblock_sillyrename(dentry->d_parent); |
1510 | if (err < 0) { | ||
1511 | if (res != NULL) | ||
1512 | dput(res); | ||
1513 | return ERR_PTR(err); | ||
1514 | } | ||
1515 | out: | ||
1516 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1476 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1517 | return res; | 1477 | |
1478 | err = nfs_finish_open(ctx, dentry, file, open_flags, opened); | ||
1479 | |||
1480 | dput(res); | ||
1481 | out: | ||
1482 | return err; | ||
1483 | |||
1518 | no_open: | 1484 | no_open: |
1519 | return nfs_lookup(dir, dentry, nd); | 1485 | res = nfs_lookup(dir, dentry, 0); |
1486 | err = PTR_ERR(res); | ||
1487 | if (IS_ERR(res)) | ||
1488 | goto out; | ||
1489 | |||
1490 | return finish_no_open(file, res); | ||
1520 | } | 1491 | } |
1521 | 1492 | ||
1522 | static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | 1493 | static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags) |
1523 | { | 1494 | { |
1524 | struct dentry *parent = NULL; | 1495 | struct dentry *parent = NULL; |
1525 | struct inode *inode; | 1496 | struct inode *inode; |
1526 | struct inode *dir; | 1497 | struct inode *dir; |
1527 | int openflags, ret = 0; | 1498 | int ret = 0; |
1528 | 1499 | ||
1529 | if (nd->flags & LOOKUP_RCU) | 1500 | if (flags & LOOKUP_RCU) |
1530 | return -ECHILD; | 1501 | return -ECHILD; |
1531 | 1502 | ||
1532 | inode = dentry->d_inode; | 1503 | if (!(flags & LOOKUP_OPEN) || (flags & LOOKUP_DIRECTORY)) |
1533 | if (!is_atomic_open(nd) || d_mountpoint(dentry)) | 1504 | goto no_open; |
1505 | if (d_mountpoint(dentry)) | ||
1534 | goto no_open; | 1506 | goto no_open; |
1535 | 1507 | ||
1508 | inode = dentry->d_inode; | ||
1536 | parent = dget_parent(dentry); | 1509 | parent = dget_parent(dentry); |
1537 | dir = parent->d_inode; | 1510 | dir = parent->d_inode; |
1538 | 1511 | ||
@@ -1540,7 +1513,7 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1540 | * optimize away revalidation of negative dentries. | 1513 | * optimize away revalidation of negative dentries. |
1541 | */ | 1514 | */ |
1542 | if (inode == NULL) { | 1515 | if (inode == NULL) { |
1543 | if (!nfs_neg_need_reval(dir, dentry, nd)) | 1516 | if (!nfs_neg_need_reval(dir, dentry, flags)) |
1544 | ret = 1; | 1517 | ret = 1; |
1545 | goto out; | 1518 | goto out; |
1546 | } | 1519 | } |
@@ -1548,9 +1521,8 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1548 | /* NFS only supports OPEN on regular files */ | 1521 | /* NFS only supports OPEN on regular files */ |
1549 | if (!S_ISREG(inode->i_mode)) | 1522 | if (!S_ISREG(inode->i_mode)) |
1550 | goto no_open_dput; | 1523 | goto no_open_dput; |
1551 | openflags = nd->intent.open.flags; | ||
1552 | /* We cannot do exclusive creation on a positive dentry */ | 1524 | /* We cannot do exclusive creation on a positive dentry */ |
1553 | if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) | 1525 | if (flags & LOOKUP_EXCL) |
1554 | goto no_open_dput; | 1526 | goto no_open_dput; |
1555 | 1527 | ||
1556 | /* Let f_op->open() actually open (and revalidate) the file */ | 1528 | /* Let f_op->open() actually open (and revalidate) the file */ |
@@ -1563,48 +1535,7 @@ out: | |||
1563 | no_open_dput: | 1535 | no_open_dput: |
1564 | dput(parent); | 1536 | dput(parent); |
1565 | no_open: | 1537 | no_open: |
1566 | return nfs_lookup_revalidate(dentry, nd); | 1538 | return nfs_lookup_revalidate(dentry, flags); |
1567 | } | ||
1568 | |||
1569 | static int nfs_open_create(struct inode *dir, struct dentry *dentry, | ||
1570 | umode_t mode, struct nameidata *nd) | ||
1571 | { | ||
1572 | struct nfs_open_context *ctx = NULL; | ||
1573 | struct iattr attr; | ||
1574 | int error; | ||
1575 | int open_flags = O_CREAT|O_EXCL; | ||
1576 | |||
1577 | dfprintk(VFS, "NFS: create(%s/%ld), %s\n", | ||
1578 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | ||
1579 | |||
1580 | attr.ia_mode = mode; | ||
1581 | attr.ia_valid = ATTR_MODE; | ||
1582 | |||
1583 | if (nd) | ||
1584 | open_flags = nd->intent.open.flags; | ||
1585 | |||
1586 | ctx = create_nfs_open_context(dentry, open_flags); | ||
1587 | error = PTR_ERR(ctx); | ||
1588 | if (IS_ERR(ctx)) | ||
1589 | goto out_err_drop; | ||
1590 | |||
1591 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx); | ||
1592 | if (error != 0) | ||
1593 | goto out_put_ctx; | ||
1594 | if (nd) { | ||
1595 | error = nfs_intent_set_file(nd, ctx); | ||
1596 | if (error < 0) | ||
1597 | goto out_err; | ||
1598 | } else { | ||
1599 | put_nfs_open_context(ctx); | ||
1600 | } | ||
1601 | return 0; | ||
1602 | out_put_ctx: | ||
1603 | put_nfs_open_context(ctx); | ||
1604 | out_err_drop: | ||
1605 | d_drop(dentry); | ||
1606 | out_err: | ||
1607 | return error; | ||
1608 | } | 1539 | } |
1609 | 1540 | ||
1610 | #endif /* CONFIG_NFSV4 */ | 1541 | #endif /* CONFIG_NFSV4 */ |
@@ -1658,11 +1589,11 @@ out_error: | |||
1658 | * reply path made it appear to have failed. | 1589 | * reply path made it appear to have failed. |
1659 | */ | 1590 | */ |
1660 | static int nfs_create(struct inode *dir, struct dentry *dentry, | 1591 | static int nfs_create(struct inode *dir, struct dentry *dentry, |
1661 | umode_t mode, struct nameidata *nd) | 1592 | umode_t mode, bool excl) |
1662 | { | 1593 | { |
1663 | struct iattr attr; | 1594 | struct iattr attr; |
1595 | int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT; | ||
1664 | int error; | 1596 | int error; |
1665 | int open_flags = O_CREAT|O_EXCL; | ||
1666 | 1597 | ||
1667 | dfprintk(VFS, "NFS: create(%s/%ld), %s\n", | 1598 | dfprintk(VFS, "NFS: create(%s/%ld), %s\n", |
1668 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1599 | 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, | |||
1670 | attr.ia_mode = mode; | 1601 | attr.ia_mode = mode; |
1671 | attr.ia_valid = ATTR_MODE; | 1602 | attr.ia_valid = ATTR_MODE; |
1672 | 1603 | ||
1673 | if (nd) | 1604 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); |
1674 | open_flags = nd->intent.open.flags; | ||
1675 | |||
1676 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL); | ||
1677 | if (error != 0) | 1605 | if (error != 0) |
1678 | goto out_err; | 1606 | goto out_err; |
1679 | return 0; | 1607 | return 0; |