Skip to content

Commit 416c794

Browse files
authored
Merge pull request ceph#62488 from dparmar18/i70553
client: fix unmount hang after lookups Reviewed-by: Venky Shankar <[email protected]>
2 parents 0542a5e + aa6ffa5 commit 416c794

File tree

2 files changed

+98
-5
lines changed

2 files changed

+98
-5
lines changed

src/client/Client.cc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7519,6 +7519,11 @@ int Client::_lookup(const InodeRef& dir, const std::string& name, std::string& a
75197519
mask &= CEPH_CAP_ANY_SHARED | CEPH_STAT_RSTAT;
75207520
std::string dname = name;
75217521

7522+
if (!dir->is_dir()) {
7523+
r = -ENOTDIR;
7524+
goto done;
7525+
}
7526+
75227527
if (dname == ".."sv) {
75237528
if (dir->dentries.empty()) {
75247529
MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPPARENT);
@@ -7545,11 +7550,6 @@ int Client::_lookup(const InodeRef& dir, const std::string& name, std::string& a
75457550
goto done;
75467551
}
75477552

7548-
if (!dir->is_dir()) {
7549-
r = -ENOTDIR;
7550-
goto done;
7551-
}
7552-
75537553
if (dname.size() > NAME_MAX) {
75547554
r = -ENAMETOOLONG;
75557555
goto done;
@@ -7724,6 +7724,11 @@ int Client::path_walk(InodeRef dirinode, const filepath& origpath, walk_dentry_r
77247724
ldout(cct, 10) << " " << i << " " << *diri << " " << dname << dendl;
77257725
ldout(cct, 20) << " (path is " << path << ")" << dendl;
77267726
InodeRef next;
7727+
if (!diri.get()->is_dir()) {
7728+
ldout(cct, 20) << diri.get() << " is not a dir inode, name " << dname.c_str() << dendl;
7729+
rc = -ENOTDIR;
7730+
goto out;
7731+
}
77277732
if (should_check_perms()) {
77287733
int r = may_lookup(diri.get(), perms);
77297734
if (r < 0) {

src/test/libcephfs/test.cc

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4251,3 +4251,91 @@ TEST(LibCephFS, AsyncReadAndWriteMultiClient) {
42514251
ceph_shutdown(w_cmount);
42524252
ceph_shutdown(r_cmount);
42534253
}
4254+
4255+
TEST(LibCephFS, UmountHangAfterLlLookupFilePath) {
4256+
struct ceph_statx stx;
4257+
struct ceph_mount_info *cmount;
4258+
UserPerm *perms;
4259+
Inode *root, *file, *tmp;
4260+
Fh *fh;
4261+
4262+
int mypid = getpid();
4263+
char filename[NAME_MAX];
4264+
4265+
sprintf(filename, "test_umounthangafterlookup%u", mypid);
4266+
4267+
ASSERT_EQ(ceph_create(&cmount, NULL), 0);
4268+
ASSERT_EQ(ceph_conf_read_file(cmount, NULL), 0);
4269+
ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
4270+
ASSERT_EQ(0, ceph_mount(cmount, NULL));
4271+
4272+
perms = ceph_userperm_new(0, 0, 0, NULL);
4273+
4274+
ASSERT_EQ(ceph_ll_lookup_root(cmount, &root), 0);
4275+
4276+
ASSERT_EQ(ceph_ll_create(cmount, root, filename, 0777,
4277+
O_CREAT | O_TRUNC | O_RDWR, &file, &fh, &stx,
4278+
CEPH_STATX_INO, 0, perms), 0);
4279+
ASSERT_EQ(ceph_ll_close(cmount, fh), 0);
4280+
4281+
ASSERT_EQ(ceph_ll_lookup(cmount, file, ".", &tmp, &stx, CEPH_STATX_INO,
4282+
0 , perms), -ENOTDIR);
4283+
4284+
ASSERT_EQ(ceph_ll_unlink(cmount, root, filename, perms), 0);
4285+
4286+
ceph_ll_put(cmount, file);
4287+
ceph_ll_put(cmount, root);
4288+
4289+
std::cout << "Before ceph_unmount()" << std::endl;
4290+
ASSERT_EQ(0, ceph_unmount(cmount));
4291+
std::cout << "After ceph_unmount()" << std::endl;
4292+
4293+
ceph_release(cmount);
4294+
ceph_userperm_destroy(perms);
4295+
}
4296+
4297+
TEST(LibCephFS, UnmountHangAfterOpenatFilePath) {
4298+
pid_t mypid = getpid();
4299+
struct ceph_mount_info *cmount;
4300+
ASSERT_EQ(ceph_create(&cmount, NULL), 0);
4301+
ASSERT_EQ(ceph_conf_read_file(cmount, NULL), 0);
4302+
ASSERT_EQ(ceph_conf_parse_env(cmount, NULL), 0);
4303+
ASSERT_EQ(ceph_mount(cmount, "/"), 0);
4304+
4305+
char c_rel_dir[64];
4306+
char c_dir[128];
4307+
sprintf(c_rel_dir, "open_test_%d", mypid);
4308+
sprintf(c_dir, "/%s", c_rel_dir);
4309+
ASSERT_EQ(ceph_mkdir(cmount, c_dir, 0777), 0);
4310+
4311+
int root_fd = ceph_open(cmount, "/", O_DIRECTORY, 0777);
4312+
ASSERT_GT(root_fd, 0);
4313+
4314+
int dir_fd = ceph_openat(cmount, root_fd, c_rel_dir, O_DIRECTORY, 0777);
4315+
ASSERT_GT(dir_fd, 0);
4316+
4317+
struct ceph_statx stx;
4318+
ASSERT_EQ(ceph_statxat(cmount, root_fd, c_rel_dir, &stx, 0, 0), 0);
4319+
4320+
char c_rel_path[PATH_MAX];
4321+
char c_path[PATH_MAX];
4322+
sprintf(c_rel_path, "created_file_%d", mypid);
4323+
sprintf(c_path, "%s/%s", c_dir, c_rel_path);
4324+
int file_fd = ceph_openat(cmount, dir_fd, c_rel_path, O_RDONLY | O_CREAT, 0777);
4325+
ASSERT_GT(file_fd, 0);
4326+
int fd = ceph_openat(cmount, file_fd, ".", O_RDONLY, 0777);
4327+
ASSERT_EQ(fd, -ENOTDIR);
4328+
4329+
ASSERT_EQ(ceph_close(cmount, file_fd), 0);
4330+
ASSERT_EQ(ceph_close(cmount, dir_fd), 0);
4331+
ASSERT_EQ(ceph_close(cmount, root_fd), 0);
4332+
4333+
ASSERT_EQ(0, ceph_unlink(cmount, c_path));
4334+
ASSERT_EQ(0, ceph_rmdir(cmount, c_dir));
4335+
4336+
std::cout << "Before ceph_unmount()" << std::endl;
4337+
ASSERT_EQ(0, ceph_unmount(cmount));
4338+
std::cout << "After ceph_unmount()" << std::endl;
4339+
4340+
ASSERT_EQ(0, ceph_release(cmount));
4341+
}

0 commit comments

Comments
 (0)