diff options
Diffstat (limited to 'fs/nfs/dir.c')
| -rw-r--r-- | fs/nfs/dir.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 36f2e8588922..49394123bd09 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2208,6 +2208,10 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, goto out; } file->f_mode |= FMODE_CAN_ODIRECT; + if (test_bit(NFS_CONTEXT_O_DIRECT, &ctx->flags)) { + file->f_flags |= O_DIRECT; + open_flags |= O_DIRECT; + } err = nfs_finish_open(ctx, ctx->dentry, file, open_flags); trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); @@ -2319,6 +2323,13 @@ int nfs_atomic_open_v23(struct inode *dir, struct dentry *dentry, if (open_flags & O_CREAT) { error = nfs_do_create(dir, dentry, mode, open_flags); if (!error) { + /* With UNCHECKED mode, a server may return NFS3_OK for + * a pre-existing non-regular file (e.g. a symlink). + * Let the VFS handle it; calling finish_open() would + * hit no_open() and return -ENXIO. + */ + if (!d_is_reg(dentry)) + return finish_no_open(file, NULL); file->f_mode |= FMODE_CREATED; return finish_open(file, dentry, NULL); } else if (error != -EEXIST || open_flags & O_EXCL) @@ -2669,6 +2680,12 @@ int nfs_symlink(struct mnt_idmap *idmap, struct inode *dir, return error; } + if (unlikely(!d_is_symlink(dentry))) { + d_drop(dentry); + folio_put(folio); + return 0; + } + nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); /* |
