Skip to content

Commit 3e10a15

Browse files
jtlaytonAl Viro
authored andcommitted
ceph: fix up error handling with snapdirs
There are several warts in the snapdir error handling. The -EOPNOTSUPP return in __snapfh_to_dentry is currently lost, and the call to ceph_handle_snapdir is not currently checked at all. Fix all of this up and eliminate a BUG_ON in ceph_get_snapdir. We can handle that case with a warning and return an error. Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 6e3e2c4 commit 3e10a15

3 files changed

Lines changed: 20 additions & 5 deletions

File tree

fs/ceph/dir.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,8 @@ int ceph_handle_snapdir(struct ceph_mds_request *req,
677677
strcmp(dentry->d_name.name,
678678
fsc->mount_options->snapdir_name) == 0) {
679679
struct inode *inode = ceph_get_snapdir(parent);
680+
if (IS_ERR(inode))
681+
return PTR_ERR(inode);
680682
dout("ENOENT on snapdir %p '%pd', linking to snapdir %p\n",
681683
dentry, dentry, inode);
682684
BUG_ON(!d_unhashed(dentry));

fs/ceph/export.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,10 @@ static struct dentry *__snapfh_to_dentry(struct super_block *sb,
248248
ihold(inode);
249249
} else {
250250
/* mds does not support lookup snapped inode */
251-
err = -EOPNOTSUPP;
252-
inode = NULL;
251+
inode = ERR_PTR(-EOPNOTSUPP);
253252
}
253+
} else {
254+
inode = ERR_PTR(-ESTALE);
254255
}
255256
ceph_mdsc_put_request(req);
256257

@@ -261,8 +262,8 @@ static struct dentry *__snapfh_to_dentry(struct super_block *sb,
261262
dout("snapfh_to_dentry %llx.%llx parent %llx hash %x err=%d",
262263
vino.ino, vino.snap, sfh->parent_ino, sfh->hash, err);
263264
}
264-
if (!inode)
265-
return ERR_PTR(-ESTALE);
265+
if (IS_ERR(inode))
266+
return ERR_CAST(inode);
266267
/* see comments in ceph_get_parent() */
267268
return unlinked ? d_obtain_root(inode) : d_obtain_alias(inode);
268269
}

fs/ceph/inode.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,21 @@ struct inode *ceph_get_snapdir(struct inode *parent)
7878
struct inode *inode = ceph_get_inode(parent->i_sb, vino);
7979
struct ceph_inode_info *ci = ceph_inode(inode);
8080

81-
BUG_ON(!S_ISDIR(parent->i_mode));
8281
if (IS_ERR(inode))
8382
return inode;
83+
84+
if (!S_ISDIR(parent->i_mode)) {
85+
pr_warn_once("bad snapdir parent type (mode=0%o)\n",
86+
parent->i_mode);
87+
return ERR_PTR(-ENOTDIR);
88+
}
89+
90+
if (!(inode->i_state & I_NEW) && !S_ISDIR(inode->i_mode)) {
91+
pr_warn_once("bad snapdir inode type (mode=0%o)\n",
92+
inode->i_mode);
93+
return ERR_PTR(-ENOTDIR);
94+
}
95+
8496
inode->i_mode = parent->i_mode;
8597
inode->i_uid = parent->i_uid;
8698
inode->i_gid = parent->i_gid;

0 commit comments

Comments
 (0)