Skip to content

Commit fd97ceb

Browse files
committed
Fix file descriptor leak on pool import.
While here, return the error we get from fgets() instead of pretending we succeeded. Descriptor leak can be easily reproduced by doing: # zpool import tank # sysctl kern.openfiles # zpool export tank; zpool import tank # sysctl kern.openfiles We were leaking four file descriptors on every import. Signed-off-by: Pawel Jakub Dawidek <[email protected]>
1 parent 014265f commit fd97ceb

File tree

2 files changed

+55
-24
lines changed

2 files changed

+55
-24
lines changed

include/sys/zfs_file.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@ typedef struct zfs_file {
2929
int f_fd;
3030
int f_dump_fd;
3131
} zfs_file_t;
32-
#elif defined(__linux__) || defined(__FreeBSD__)
32+
#elif defined(__linux__)
3333
typedef struct file zfs_file_t;
34+
#elif defined(__FreeBSD__)
35+
typedef struct zfs_file {
36+
int zf_fd;
37+
struct file *zf_fp;
38+
} zfs_file_t;
3439
#else
3540
#error "unknown OS"
3641
#endif

module/os/freebsd/zfs/zfs_file_os.c

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@
4747
#include <sys/stat.h>
4848

4949
int
50-
zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp)
50+
zfs_file_open(const char *path, int flags, int mode, zfs_file_t **zfpp)
5151
{
5252
struct thread *td;
53+
struct file *fp;
54+
zfs_file_t *zfp;
5355
int rc, fd;
5456

5557
td = curthread;
@@ -61,20 +63,31 @@ zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp)
6163
return (SET_ERROR(rc));
6264
fd = td->td_retval[0];
6365
td->td_retval[0] = 0;
64-
if (fget(curthread, fd, &cap_no_rights, fpp))
66+
rc = fget(curthread, fd, &cap_no_rights, &fp);
67+
if (rc) {
6568
kern_close(td, fd);
69+
return (SET_ERROR(rc));
70+
}
71+
zfp = kmem_alloc(sizeof (*zfp), KM_SLEEP);
72+
zfp->zf_fd = fd;
73+
zfp->zf_fp = fp;
74+
*zfpp = zfp;
6675
return (0);
6776
}
6877

6978
void
70-
zfs_file_close(zfs_file_t *fp)
79+
zfs_file_close(zfs_file_t *zfp)
7180
{
72-
fo_close(fp, curthread);
81+
struct thread *td = curthread;
82+
83+
fdrop(zfp->zf_fp, td);
84+
kern_close(td, zfp->zf_fd);
85+
kmem_free(zfp, sizeof (*zfp));
7386
}
7487

7588
static int
76-
zfs_file_write_impl(zfs_file_t *fp, const void *buf, size_t count, loff_t *offp,
77-
ssize_t *resid)
89+
zfs_file_write_impl(struct file *fp, const void *buf, size_t count,
90+
loff_t *offp, ssize_t *resid)
7891
{
7992
ssize_t rc;
8093
struct uio auio;
@@ -110,8 +123,9 @@ zfs_file_write_impl(zfs_file_t *fp, const void *buf, size_t count, loff_t *offp,
110123
}
111124

112125
int
113-
zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid)
126+
zfs_file_write(zfs_file_t *zfp, const void *buf, size_t count, ssize_t *resid)
114127
{
128+
struct file *fp = zfp->zf_fp;
115129
loff_t off = fp->f_offset;
116130
ssize_t rc;
117131

@@ -123,14 +137,14 @@ zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid)
123137
}
124138

125139
int
126-
zfs_file_pwrite(zfs_file_t *fp, const void *buf, size_t count, loff_t off,
140+
zfs_file_pwrite(zfs_file_t *zfp, const void *buf, size_t count, loff_t off,
127141
ssize_t *resid)
128142
{
129-
return (zfs_file_write_impl(fp, buf, count, &off, resid));
143+
return (zfs_file_write_impl(zfp->zf_fp, buf, count, &off, resid));
130144
}
131145

132146
static int
133-
zfs_file_read_impl(zfs_file_t *fp, void *buf, size_t count, loff_t *offp,
147+
zfs_file_read_impl(struct file *fp, void *buf, size_t count, loff_t *offp,
134148
ssize_t *resid)
135149
{
136150
ssize_t rc;
@@ -162,8 +176,9 @@ zfs_file_read_impl(zfs_file_t *fp, void *buf, size_t count, loff_t *offp,
162176
}
163177

164178
int
165-
zfs_file_read(zfs_file_t *fp, void *buf, size_t count, ssize_t *resid)
179+
zfs_file_read(zfs_file_t *zfp, void *buf, size_t count, ssize_t *resid)
166180
{
181+
struct file *fp = zfp->zf_fp;
167182
loff_t off = fp->f_offset;
168183
ssize_t rc;
169184

@@ -174,17 +189,18 @@ zfs_file_read(zfs_file_t *fp, void *buf, size_t count, ssize_t *resid)
174189
}
175190

176191
int
177-
zfs_file_pread(zfs_file_t *fp, void *buf, size_t count, loff_t off,
192+
zfs_file_pread(zfs_file_t *zfp, void *buf, size_t count, loff_t off,
178193
ssize_t *resid)
179194
{
180-
return (zfs_file_read_impl(fp, buf, count, &off, resid));
195+
return (zfs_file_read_impl(zfp->zf_fp, buf, count, &off, resid));
181196
}
182197

183198
int
184-
zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence)
199+
zfs_file_seek(zfs_file_t *zfp, loff_t *offp, int whence)
185200
{
186-
int rc;
201+
struct file *fp = zfp->zf_fp;
187202
struct thread *td;
203+
int rc;
188204

189205
td = curthread;
190206
if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE) == 0)
@@ -196,8 +212,9 @@ zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence)
196212
}
197213

198214
int
199-
zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr)
215+
zfs_file_getattr(zfs_file_t *zfp, zfs_file_attr_t *zfattr)
200216
{
217+
struct file *fp = zfp->zf_fp;
201218
struct thread *td;
202219
struct stat sb;
203220
int rc;
@@ -238,8 +255,10 @@ zfs_vop_fsync(vnode_t *vp)
238255
}
239256

240257
int
241-
zfs_file_fsync(zfs_file_t *fp, int flags)
258+
zfs_file_fsync(zfs_file_t *zfp, int flags)
242259
{
260+
struct file *fp = zfp->zf_fp;
261+
243262
if (fp->f_type != DTYPE_VNODE)
244263
return (EINVAL);
245264

@@ -249,29 +268,36 @@ zfs_file_fsync(zfs_file_t *fp, int flags)
249268
zfs_file_t *
250269
zfs_file_get(int fd)
251270
{
271+
zfs_file_t *zfp;
252272
struct file *fp;
253273

254274
if (fget(curthread, fd, &cap_no_rights, &fp))
255275
return (NULL);
256276

257-
return (fp);
277+
zfp = kmem_alloc(sizeof (*zfp), KM_SLEEP);
278+
zfp->zf_fd = fd;
279+
zfp->zf_fp = fp;
280+
281+
return (zfp);
258282
}
259283

260284
void
261-
zfs_file_put(zfs_file_t *fp)
285+
zfs_file_put(zfs_file_t *zfp)
262286
{
263-
fdrop(fp, curthread);
287+
fdrop(zfp->zf_fp, curthread);
288+
kmem_free(zfp, sizeof (*zfp));
264289
}
265290

266291
loff_t
267-
zfs_file_off(zfs_file_t *fp)
292+
zfs_file_off(zfs_file_t *zfp)
268293
{
269-
return (fp->f_offset);
294+
return (zfp->zf_fp->f_offset);
270295
}
271296

272297
void *
273-
zfs_file_private(zfs_file_t *fp)
298+
zfs_file_private(zfs_file_t *zfp)
274299
{
300+
struct file *fp = zfp->zf_fp;
275301
file_t *tmpfp;
276302
void *data;
277303
int error;

0 commit comments

Comments
 (0)