diff options
author | Chunwei Chen <[email protected]> | 2013-12-17 10:18:25 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2013-12-17 10:28:27 -0800 |
commit | 7dc71949f2f013a7bf744230d60770893ce23a6a (patch) | |
tree | 3ae0c13c4f599ce5a619542519646c2a9b007c42 /module/zfs/zfs_vnops.c | |
parent | c2d439dffd4c404d39e82e5b174a338515080f26 (diff) |
Fix z_sync_cnt decrement in zfs_close
The comment in zfs_close states that "Under Linux the zfs_close() hook
is not symmetric with zfs_open()". This is not true. zfs_open/zfs_close
is associated with every successful struct file creation/deletion, which
should always be balanced.
Here is an example of what's wrong:
Process A B
open(O_SYNC)
z_sync_cnt = 1
open(O_SYNC)
z_sync_cnt = 2
close()
z_sync_cnt = 0
So z_sync_cnt is 0 even if B still has the file with O_SYNC.
Also moves the generic_file_open call before zfs_open to ensure that in
the case generic_file_open fails z_sync_cnt is not incremented. This
is safe because generic_file_open has no side effects.
Signed-off-by: Chunwei Chen <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Issue #1962
Diffstat (limited to 'module/zfs/zfs_vnops.c')
-rw-r--r-- | module/zfs/zfs_vnops.c | 8 |
1 files changed, 2 insertions, 6 deletions
diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 4a34f055a..8e4694ff6 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -235,13 +235,9 @@ zfs_close(struct inode *ip, int flag, cred_t *cr) ZFS_ENTER(zsb); ZFS_VERIFY_ZP(zp); - /* - * Zero the synchronous opens in the znode. Under Linux the - * zfs_close() hook is not symmetric with zfs_open(), it is - * only called once when the last reference is dropped. - */ + /* Decrement the synchronous opens in the znode */ if (flag & O_SYNC) - zp->z_sync_cnt = 0; + atomic_dec_32(&zp->z_sync_cnt); if (!zfs_has_ctldir(zp) && zsb->z_vscan && S_ISREG(ip->i_mode) && !(zp->z_pflags & ZFS_AV_QUARANTINED) && zp->z_size > 0) |