summaryrefslogtreecommitdiffstats
path: root/fs/ceph/super.h
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/super.h
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/super.h')
-rw-r--r--fs/ceph/super.h11
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index daf7e7e64746..5c911586593d 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -581,6 +581,7 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
#define CEPH_I_ODIRECT (1 << 11) /* inode in direct I/O mode */
#define CEPH_ASYNC_CREATE_BIT (12) /* async create in flight for this */
#define CEPH_I_ASYNC_CREATE (1 << CEPH_ASYNC_CREATE_BIT)
+#define CEPH_I_SHUTDOWN (1 << 13) /* inode is no longer usable */
/*
* Masks of ceph inode work.
@@ -1028,6 +1029,16 @@ extern int ceph_setattr(struct user_namespace *mnt_userns,
extern int ceph_getattr(struct user_namespace *mnt_userns,
const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags);
+void ceph_inode_shutdown(struct inode *inode);
+
+static inline bool ceph_inode_is_shutdown(struct inode *inode)
+{
+ unsigned long flags = READ_ONCE(ceph_inode(inode)->i_ceph_flags);
+ struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ int state = READ_ONCE(fsc->mount_state);
+
+ return (flags & CEPH_I_SHUTDOWN) || state >= CEPH_MOUNT_SHUTDOWN;
+}
/* xattr.c */
int __ceph_setxattr(struct inode *, const char *, const void *, size_t, int);