mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-17 18:11:00 +03:00
958826be7a
Callers of zfs_file_get and zfs_file_put can corrupt the reference counts for the file structure resulting in a panic or a soft lockup. When zfs send/recv runs, it will add a reference count to the open file, and begin to send or recv the stream. If the file descriptor is closed, then when dmu_recv_stream() or dmu_send() return we will call zfs_file_put to remove the reference we placed on the file structure. Unfortunately, because zfs_file_put() uses the file descriptor to lookup the file structure, it may end up finding that the file descriptor table no longer contains the file struct, thus leaking the file structure. Or it might end up finding a file descriptor for a different file and blindly updating its reference counts. Other failure modes probably exists. This change reworks the zfs_file_[get|put] interface to not rely on the file descriptor but instead pass the zfs_file_t pointer around. Reviewed-by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Mark Maybee <mark.maybee@delphix.com> Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Co-authored-by: Allan Jude <allan@klarasystems.com> Signed-off-by: George Wilson <gwilson@delphix.com> External-issue: DLPX-76119 Closes #12299
65 lines
2.1 KiB
C
65 lines
2.1 KiB
C
/*
|
|
* CDDL HEADER START
|
|
*
|
|
* The contents of this file are subject to the terms of the
|
|
* Common Development and Distribution License (the "License").
|
|
* You may not use this file except in compliance with the License.
|
|
*
|
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
* or http://www.opensolaris.org/os/licensing.
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
*
|
|
* When distributing Covered Code, include this CDDL HEADER in each
|
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
* If applicable, add the following below this CDDL HEADER, with the
|
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
*
|
|
* CDDL HEADER END
|
|
*/
|
|
|
|
#ifndef _SYS_ZFS_FILE_H
|
|
#define _SYS_ZFS_FILE_H
|
|
|
|
#include <sys/zfs_context.h>
|
|
|
|
#ifndef _KERNEL
|
|
typedef struct zfs_file {
|
|
int f_fd;
|
|
int f_dump_fd;
|
|
} zfs_file_t;
|
|
#elif defined(__linux__) || defined(__FreeBSD__)
|
|
typedef struct file zfs_file_t;
|
|
#else
|
|
#error "unknown OS"
|
|
#endif
|
|
|
|
typedef struct zfs_file_attr {
|
|
uint64_t zfa_size; /* file size */
|
|
mode_t zfa_mode; /* file type */
|
|
} zfs_file_attr_t;
|
|
|
|
int zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fp);
|
|
void zfs_file_close(zfs_file_t *fp);
|
|
|
|
int zfs_file_write(zfs_file_t *fp, const void *buf, size_t len, ssize_t *resid);
|
|
int zfs_file_pwrite(zfs_file_t *fp, const void *buf, size_t len, loff_t off,
|
|
ssize_t *resid);
|
|
int zfs_file_read(zfs_file_t *fp, void *buf, size_t len, ssize_t *resid);
|
|
int zfs_file_pread(zfs_file_t *fp, void *buf, size_t len, loff_t off,
|
|
ssize_t *resid);
|
|
|
|
int zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence);
|
|
int zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr);
|
|
int zfs_file_fsync(zfs_file_t *fp, int flags);
|
|
int zfs_file_fallocate(zfs_file_t *fp, int mode, loff_t offset, loff_t len);
|
|
loff_t zfs_file_off(zfs_file_t *fp);
|
|
int zfs_file_unlink(const char *);
|
|
|
|
zfs_file_t *zfs_file_get(int fd);
|
|
void zfs_file_put(zfs_file_t *fp);
|
|
void *zfs_file_private(zfs_file_t *fp);
|
|
|
|
#endif /* _SYS_ZFS_FILE_H */
|