Skip to content

Commit 55ac8d6

Browse files
committed
Merge PR ceph#55619 into main
* refs/pull/55619/head: client: fix leak of file handles Reviewed-by: Venky Shankar <[email protected]> Reviewed-by: Radoslaw Zarzynski <[email protected]> Reviewed-by: Dhairya Parmar <[email protected]>
2 parents ea0bdc2 + fe5c13d commit 55ac8d6

File tree

2 files changed

+17
-7
lines changed

2 files changed

+17
-7
lines changed

src/client/Client.cc

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,10 @@ int Client::get_fd_inode(int fd, InodeRef *in) {
257257
return r;
258258
}
259259

260-
dir_result_t::dir_result_t(Inode *in, const UserPerm& perms)
260+
dir_result_t::dir_result_t(Inode *in, const UserPerm& perms, int fd)
261261
: inode(in), offset(0), next_offset(2),
262262
release_count(0), ordered_count(0), cache_index(0), start_shared_gen(0),
263-
perms(perms)
263+
perms(perms), fd(fd)
264264
{ }
265265

266266
void Client::_reset_faked_inos()
@@ -9129,19 +9129,21 @@ int Client::fdopendir(int dirfd, dir_result_t **dirpp, const UserPerm &perms) {
91299129
return r;
91309130
}
91319131
}
9132-
r = _opendir(dirinode.get(), dirpp, perms);
9132+
// Posix says that closedir will also close the file descriptor passed to fdopendir, so we associate
9133+
// dirfd to the new dir_result_t so that it can be closed later.
9134+
r = _opendir(dirinode.get(), dirpp, perms, dirfd);
91339135
/* if ENOTDIR, dirpp will be an uninitialized point and it's very dangerous to access its value */
91349136
if (r != -CEPHFS_ENOTDIR) {
91359137
tout(cct) << (uintptr_t)*dirpp << std::endl;
91369138
}
91379139
return r;
91389140
}
91399141

9140-
int Client::_opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms)
9142+
int Client::_opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms, int fd)
91419143
{
91429144
if (!in->is_dir())
91439145
return -CEPHFS_ENOTDIR;
9144-
*dirpp = new dir_result_t(in, perms);
9146+
*dirpp = new dir_result_t(in, perms, fd);
91459147
opened_dirs.insert(*dirpp);
91469148
ldout(cct, 8) << __func__ << "(" << in->ino << ") = " << 0 << " (" << *dirpp << ")" << dendl;
91479149
return 0;
@@ -9169,6 +9171,12 @@ void Client::_closedir(dir_result_t *dirp)
91699171
}
91709172
_readdir_drop_dirp_buffer(dirp);
91719173
opened_dirs.erase(dirp);
9174+
9175+
/* Close the associated fd if this dir_result_t comes from an fdopendir request. */
9176+
if (dirp->fd >= 0) {
9177+
_close(dirp->fd);
9178+
}
9179+
91729180
delete dirp;
91739181
}
91749182

src/client/Client.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ struct dir_result_t {
163163
};
164164

165165

166-
explicit dir_result_t(Inode *in, const UserPerm& perms);
166+
explicit dir_result_t(Inode *in, const UserPerm& perms, int fd);
167167

168168

169169
static uint64_t make_fpos(unsigned h, unsigned l, bool hash) {
@@ -240,6 +240,8 @@ struct dir_result_t {
240240

241241
std::vector<dentry> buffer;
242242
struct dirent de;
243+
244+
int fd; // fd attached using fdopendir (-1 if none)
243245
};
244246

245247
class Client : public Dispatcher, public md_config_obs_t {
@@ -1563,7 +1565,7 @@ class Client : public Dispatcher, public md_config_obs_t {
15631565

15641566
void fill_dirent(struct dirent *de, const char *name, int type, uint64_t ino, loff_t next_off);
15651567

1566-
int _opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms);
1568+
int _opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms, int fd = -1);
15671569
void _readdir_drop_dirp_buffer(dir_result_t *dirp);
15681570
bool _readdir_have_frag(dir_result_t *dirp);
15691571
void _readdir_next_frag(dir_result_t *dirp);

0 commit comments

Comments
 (0)