summaryrefslogtreecommitdiffstats
path: root/fs/ceph/export.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@kernel.org>2021-08-31 19:39:13 +0200
committerIlya Dryomov <idryomov@gmail.com>2021-11-08 03:29:51 +0100
commit5d6451b1489ad1781a0778cc876bf26a21910413 (patch)
tree57009050cfeab77b517d5a6cfcba388aa824e7ca /fs/ceph/export.c
parentceph: refactor remove_session_caps_cb (diff)
downloadlinux-5d6451b1489ad1781a0778cc876bf26a21910413.tar.xz
linux-5d6451b1489ad1781a0778cc876bf26a21910413.zip
ceph: shut down access to inode when async create fails
Add proper error handling for when an async create fails. The inode never existed, so any dirty caps or data are now toast. We already d_drop the dentry in that case, but the now-stale inode may still be around. We want to shut down access to these inodes, and ensure that they can't harbor any more dirty data, which can cause problems at umount time. When this occurs, flag such inodes as being SHUTDOWN, and trash any caps and cap flushes that may be in flight for them, and invalidate the pagecache for the inode. Add a new helper that can check whether an inode or an entire mount is now shut down, and call it instead of accessing the mount_state directly in places where we test that now. URL: https://tracker.ceph.com/issues/51279 Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph/export.c')
-rw-r--r--fs/ceph/export.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
index 1d65934c1262..e0fa66ac8b9f 100644
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -157,6 +157,11 @@ static struct inode *__lookup_inode(struct super_block *sb, u64 ino)
ceph_mdsc_put_request(req);
if (!inode)
return err < 0 ? ERR_PTR(err) : ERR_PTR(-ESTALE);
+ } else {
+ if (ceph_inode_is_shutdown(inode)) {
+ iput(inode);
+ return ERR_PTR(-ESTALE);
+ }
}
return inode;
}
@@ -223,8 +228,13 @@ static struct dentry *__snapfh_to_dentry(struct super_block *sb,
return ERR_PTR(-ESTALE);
inode = ceph_find_inode(sb, vino);
- if (inode)
+ if (inode) {
+ if (ceph_inode_is_shutdown(inode)) {
+ iput(inode);
+ return ERR_PTR(-ESTALE);
+ }
return d_obtain_alias(inode);
+ }
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPINO,
USE_ANY_MDS);