return r;
}
-dir_result_t::dir_result_t(Inode *in, const UserPerm& perms)
+dir_result_t::dir_result_t(Inode *in, const UserPerm& perms, int fd)
: inode(in), offset(0), next_offset(2),
release_count(0), ordered_count(0), cache_index(0), start_shared_gen(0),
- perms(perms)
+ perms(perms), fd(fd)
{ }
void Client::_reset_faked_inos()
return r;
}
}
- r = _opendir(dirinode.get(), dirpp, perms);
+ // Posix says that closedir will also close the file descriptor passed to fdopendir, so we associate
+ // dirfd to the new dir_result_t so that it can be closed later.
+ r = _opendir(dirinode.get(), dirpp, perms, dirfd);
/* if ENOTDIR, dirpp will be an uninitialized point and it's very dangerous to access its value */
if (r != -CEPHFS_ENOTDIR) {
tout(cct) << (uintptr_t)*dirpp << std::endl;
return r;
}
-int Client::_opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms)
+int Client::_opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms, int fd)
{
if (!in->is_dir())
return -CEPHFS_ENOTDIR;
- *dirpp = new dir_result_t(in, perms);
+ *dirpp = new dir_result_t(in, perms, fd);
opened_dirs.insert(*dirpp);
ldout(cct, 8) << __func__ << "(" << in->ino << ") = " << 0 << " (" << *dirpp << ")" << dendl;
return 0;
}
_readdir_drop_dirp_buffer(dirp);
opened_dirs.erase(dirp);
+
+ /* Close the associated fd if this dir_result_t comes from an fdopendir request. */
+ if (dirp->fd >= 0) {
+ _close(dirp->fd);
+ }
+
delete dirp;
}
};
- explicit dir_result_t(Inode *in, const UserPerm& perms);
+ explicit dir_result_t(Inode *in, const UserPerm& perms, int fd);
static uint64_t make_fpos(unsigned h, unsigned l, bool hash) {
std::vector<dentry> buffer;
struct dirent de;
+
+ int fd; // fd attached using fdopendir (-1 if none)
};
class Client : public Dispatcher, public md_config_obs_t {
void fill_dirent(struct dirent *de, const char *name, int type, uint64_t ino, loff_t next_off);
- int _opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms);
+ int _opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms, int fd = -1);
void _readdir_drop_dirp_buffer(dir_result_t *dirp);
bool _readdir_have_frag(dir_result_t *dirp);
void _readdir_next_frag(dir_result_t *dirp);