diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-18 17:20:17 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-18 17:20:17 -0400 |
commit | 02a913a73b52071e93f4b76db3e86138d19efffd (patch) | |
tree | 1dc1abbd2d8f57a6fd593dd252d6d7ecc7c811c5 /fs/nfs/dir.c | |
parent | 834f2a4a1554dc5b2598038b3fe8703defcbe467 (diff) |
NFSv4: Eliminate nfsv4 open race...
Make NFSv4 return the fully initialized file pointer with the
stateid that it created in the lookup w/intent.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 29 |
1 files changed, 13 insertions, 16 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c70eabd6d17..a6e251f21fd 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -914,7 +914,6 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd) | |||
914 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 914 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
915 | { | 915 | { |
916 | struct dentry *res = NULL; | 916 | struct dentry *res = NULL; |
917 | struct inode *inode = NULL; | ||
918 | int error; | 917 | int error; |
919 | 918 | ||
920 | /* Check that we are indeed trying to open this file */ | 919 | /* Check that we are indeed trying to open this file */ |
@@ -928,8 +927,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
928 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 927 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; |
929 | 928 | ||
930 | /* Let vfs_create() deal with O_EXCL */ | 929 | /* Let vfs_create() deal with O_EXCL */ |
931 | if (nd->intent.open.flags & O_EXCL) | 930 | if (nd->intent.open.flags & O_EXCL) { |
932 | goto no_entry; | 931 | d_add(dentry, NULL); |
932 | goto out; | ||
933 | } | ||
933 | 934 | ||
934 | /* Open the file on the server */ | 935 | /* Open the file on the server */ |
935 | lock_kernel(); | 936 | lock_kernel(); |
@@ -943,18 +944,18 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
943 | 944 | ||
944 | if (nd->intent.open.flags & O_CREAT) { | 945 | if (nd->intent.open.flags & O_CREAT) { |
945 | nfs_begin_data_update(dir); | 946 | nfs_begin_data_update(dir); |
946 | inode = nfs4_atomic_open(dir, dentry, nd); | 947 | res = nfs4_atomic_open(dir, dentry, nd); |
947 | nfs_end_data_update(dir); | 948 | nfs_end_data_update(dir); |
948 | } else | 949 | } else |
949 | inode = nfs4_atomic_open(dir, dentry, nd); | 950 | res = nfs4_atomic_open(dir, dentry, nd); |
950 | unlock_kernel(); | 951 | unlock_kernel(); |
951 | if (IS_ERR(inode)) { | 952 | if (IS_ERR(res)) { |
952 | error = PTR_ERR(inode); | 953 | error = PTR_ERR(res); |
953 | switch (error) { | 954 | switch (error) { |
954 | /* Make a negative dentry */ | 955 | /* Make a negative dentry */ |
955 | case -ENOENT: | 956 | case -ENOENT: |
956 | inode = NULL; | 957 | res = NULL; |
957 | break; | 958 | goto out; |
958 | /* This turned out not to be a regular file */ | 959 | /* This turned out not to be a regular file */ |
959 | case -ELOOP: | 960 | case -ELOOP: |
960 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 961 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
@@ -962,13 +963,9 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
962 | /* case -EISDIR: */ | 963 | /* case -EISDIR: */ |
963 | /* case -EINVAL: */ | 964 | /* case -EINVAL: */ |
964 | default: | 965 | default: |
965 | res = ERR_PTR(error); | ||
966 | goto out; | 966 | goto out; |
967 | } | 967 | } |
968 | } | 968 | } else if (res != NULL) |
969 | no_entry: | ||
970 | res = d_add_unique(dentry, inode); | ||
971 | if (res != NULL) | ||
972 | dentry = res; | 969 | dentry = res; |
973 | nfs_renew_times(dentry); | 970 | nfs_renew_times(dentry); |
974 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 971 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
@@ -1012,7 +1009,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1012 | */ | 1009 | */ |
1013 | lock_kernel(); | 1010 | lock_kernel(); |
1014 | verifier = nfs_save_change_attribute(dir); | 1011 | verifier = nfs_save_change_attribute(dir); |
1015 | ret = nfs4_open_revalidate(dir, dentry, openflags); | 1012 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); |
1016 | if (!ret) | 1013 | if (!ret) |
1017 | nfs_set_verifier(dentry, verifier); | 1014 | nfs_set_verifier(dentry, verifier); |
1018 | unlock_kernel(); | 1015 | unlock_kernel(); |
@@ -1135,7 +1132,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1135 | 1132 | ||
1136 | lock_kernel(); | 1133 | lock_kernel(); |
1137 | nfs_begin_data_update(dir); | 1134 | nfs_begin_data_update(dir); |
1138 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); | 1135 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd); |
1139 | nfs_end_data_update(dir); | 1136 | nfs_end_data_update(dir); |
1140 | if (error != 0) | 1137 | if (error != 0) |
1141 | goto out_err; | 1138 | goto out_err; |