diff options
author | Marcel Telka <marcel@telka.sk> | 2019-09-13 07:37:39 +0200 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2019-09-23 14:10:00 -0400 |
commit | 20f5f9633a7f7a00734c4c03c7c12016e6935b05 (patch) | |
tree | 21e3a842549201c9fcdd5bf240523a5ef1b34c72 | |
parent | 4cfdb4666c89a959e76ef077c99ae7fb542dcf71 (diff) | |
download | illumos-joyent-20f5f9633a7f7a00734c4c03c7c12016e6935b05.tar.gz |
11675 NFSv4 client: Exclusive create should close the file after setattr failure
Reviewed by: Andy Fiddaman <omnios@citrus-it.co.uk>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Gordon Ross <Gordon.W.Ross@gmail.com>
Reviewed by: Rich Lowe <richlowe@richlowe.net>
Reviewed by: Jan Schlien <illumos-bugs@jan-o-sch.net>
Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs4_vnops.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/usr/src/uts/common/fs/nfs/nfs4_vnops.c b/usr/src/uts/common/fs/nfs/nfs4_vnops.c index 4112cbee05..9f4099c3f8 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_vnops.c +++ b/usr/src/uts/common/fs/nfs/nfs4_vnops.c @@ -175,7 +175,7 @@ static int nfs4_open_non_reg_file(vnode_t **, int, cred_t *); static int nfs4_safelock(vnode_t *, const struct flock64 *, cred_t *); static void nfs4_register_lock_locally(vnode_t *, struct flock64 *, int, u_offset_t); -static int nfs4_lockrelease(vnode_t *, int, offset_t, cred_t *); +static int nfs4_lockrelease(vnode_t *, int, offset_t, cred_t *); static int nfs4_block_and_wait(clock_t *, rnode4_t *); static cred_t *state_to_cred(nfs4_open_stream_t *); static void denied_to_flk(LOCK4denied *, flock64_t *, LOCKT4args *); @@ -184,7 +184,7 @@ static void nfs4_reinstitute_local_lock_state(vnode_t *, flock64_t *, cred_t *, nfs4_lock_owner_t *); static void push_reinstate(vnode_t *, int, flock64_t *, cred_t *, nfs4_lock_owner_t *); -static int open_and_get_osp(vnode_t *, cred_t *, nfs4_open_stream_t **); +static int open_and_get_osp(vnode_t *, cred_t *, nfs4_open_stream_t **); static void nfs4_delmap_callback(struct as *, void *, uint_t); static void nfs4_free_delmapcall(nfs4_delmapcall_t *); static nfs4_delmapcall_t *nfs4_init_delmapcall(); @@ -440,7 +440,7 @@ const fs_operation_def_t nfs4_vnodeops_template[] = { VOPNAME_SETSECATTR, { .vop_setsecattr = nfs4_setsecattr }, VOPNAME_GETSECATTR, { .vop_getsecattr = nfs4_getsecattr }, VOPNAME_SHRLOCK, { .vop_shrlock = nfs4_shrlock }, - VOPNAME_VNEVENT, { .vop_vnevent = fs_vnevent_support }, + VOPNAME_VNEVENT, { .vop_vnevent = fs_vnevent_support }, NULL, NULL }; @@ -1556,6 +1556,8 @@ recov_retry: e.error = nfs4setattr(vp, in_va, 0, cr, NULL); if (e.error) { + nfs4_error_t err; + /* * Couldn't correct the attributes of * the newly created file and the @@ -1567,8 +1569,23 @@ recov_retry: NFS4_DEBUG(nfs4_client_state_debug, (CE_NOTE, "nfs4open_otw: EXCLUSIVE4: error %d on SETATTR:" " remove file", e.error)); + + /* + * The file is currently open so try to close it first. + * + * If we do not close the file explicitly here then the + * VN_RELE() would do an (implicit and asynchronous) + * close for us. But such async close could race with + * the nfs4_remove() below. If the async close is + * slower than nfs4_remove() then nfs4_remove() + * wouldn't remove the file but rename it to .nfsXXXX + * instead. + */ + nfs4close_one(vp, NULL, cr, open_flag, NULL, &err, + CLOSE_NORM, 0, 0, 0); VN_RELE(vp); (void) nfs4_remove(dvp, file_name, cr, NULL, 0); + /* * Since we've reled the vnode and removed * the file we now need to return the error. @@ -3102,8 +3119,8 @@ nfs4rdwr_check_osid(vnode_t *vp, nfs4_error_t *ep, cred_t *cr) nfs4_open_owner_t *oop; nfs4_open_stream_t *osp; rnode4_t *rp = VTOR4(vp); - mntinfo4_t *mi = VTOMI4(vp); - int reopen_needed; + mntinfo4_t *mi = VTOMI4(vp); + int reopen_needed; ASSERT(nfs_zone() == mi->mi_zone); @@ -12398,8 +12415,8 @@ nfs4_getsecattr(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr, /* * The function returns: - * - 0 (zero) if the passed in "acl_mask" is a valid request. - * - EINVAL if the passed in "acl_mask" is an invalid request. + * - 0 (zero) if the passed in "acl_mask" is a valid request. + * - EINVAL if the passed in "acl_mask" is an invalid request. * * In the case of getting an acl (op == NFS4_ACL_GET) the mask is invalid if: * - We have a mixture of ACE and ACL requests (e.g. VSA_ACL | VSA_ACE) @@ -13210,7 +13227,7 @@ nfs4frlock_check_deleg(vnode_t *vp, nfs4_error_t *ep, cred_t *cr, int lt) open_delegation_type4 dt; bool_t reopen_needed, force; nfs4_open_stream_t *osp; - open_claim_type4 oclaim; + open_claim_type4 oclaim; rnode4_t *rp = VTOR4(vp); mntinfo4_t *mi = VTOMI4(vp); |