mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
A fix to facilitate prompt cap releases on async creates from Xiubo.
This should address sporadic "client isn't responding to mclientcaps (revoke) ..." warnings and potential associated MDS hangs. -----BEGIN PGP SIGNATURE----- iQFHBAABCAAxFiEEydHwtzie9C7TfviiSn/eOAIR84sFAmOaBqYTHGlkcnlvbW92 QGdtYWlsLmNvbQAKCRBKf944AhHzi3otB/4nPootwqg54bB59SR9hf5qEKoE1sFR wypGuOfP7KK40JrfFBWJM1NEiLAaYKTGYc5pSX6zxXNIFfTE4w0TrmCJI07XxAs3 Li8smmFKrqdmkYcAzTxEZHi99MoW942emfFXJvM+/smNbts7lI4OTJ1T4geQ03x0 DVlrZEV0Wp682cPD9SzN7dqlVvdLae1yfxqmj2KIuAXSYqJIqv0KxGlavrZIEpLt bW/WssvfFTGpbA4jmGYinx797kPkg477DsZYFwNDi1RSCnysT+iR5bEBoVPPQuUK SP4hLBp2bDBVIS3DVT00TbKYcH5YJRaSBUE8TN04cFLQKHG+Me11Qmiy =Pw+O -----END PGP SIGNATURE----- Merge tag 'ceph-for-6.2-rc1' of https://github.com/ceph/ceph-client Pull cph update from Ilya Dryomov: "A fix to facilitate prompt cap releases on async creates from Xiubo. This should address sporadic "client isn't responding to mclientcaps (revoke) ..." warnings and potential associated MDS hangs" * tag 'ceph-for-6.2-rc1' of https://github.com/ceph/ceph-client: ceph: try to check caps immediately after async creating finishes ceph: remove useless session parameter for check_caps()
This commit is contained in:
commit
cfb3162495
|
@ -1367,7 +1367,7 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
|
|||
folio_put(folio);
|
||||
|
||||
if (check_cap)
|
||||
ceph_check_caps(ceph_inode(inode), CHECK_CAPS_AUTHONLY, NULL);
|
||||
ceph_check_caps(ceph_inode(inode), CHECK_CAPS_AUTHONLY);
|
||||
|
||||
return copied;
|
||||
}
|
||||
|
|
|
@ -1898,8 +1898,7 @@ bool __ceph_should_report_size(struct ceph_inode_info *ci)
|
|||
* CHECK_CAPS_FLUSH - we should flush any dirty caps immediately, without
|
||||
* further delay.
|
||||
*/
|
||||
void ceph_check_caps(struct ceph_inode_info *ci, int flags,
|
||||
struct ceph_mds_session *session)
|
||||
void ceph_check_caps(struct ceph_inode_info *ci, int flags)
|
||||
{
|
||||
struct inode *inode = &ci->netfs.inode;
|
||||
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
|
||||
|
@ -1913,15 +1912,14 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
|
|||
bool queue_invalidate = false;
|
||||
bool tried_invalidate = false;
|
||||
bool queue_writeback = false;
|
||||
|
||||
if (session)
|
||||
ceph_get_mds_session(session);
|
||||
struct ceph_mds_session *session = NULL;
|
||||
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE) {
|
||||
ci->i_ceph_flags |= CEPH_I_ASYNC_CHECK_CAPS;
|
||||
|
||||
/* Don't send messages until we get async create reply */
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
ceph_put_mds_session(session);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2851,7 +2849,7 @@ static void check_max_size(struct inode *inode, loff_t endoff)
|
|||
check = 1;
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
if (check)
|
||||
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);
|
||||
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY);
|
||||
}
|
||||
|
||||
static inline int get_used_fmode(int caps)
|
||||
|
@ -3140,7 +3138,7 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
|
|||
switch (mode) {
|
||||
case PUT_CAP_REFS_SYNC:
|
||||
if (last)
|
||||
ceph_check_caps(ci, 0, NULL);
|
||||
ceph_check_caps(ci, 0);
|
||||
else if (flushsnaps)
|
||||
ceph_flush_snaps(ci, NULL);
|
||||
break;
|
||||
|
@ -3255,7 +3253,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
|
|||
spin_unlock(&ci->i_ceph_lock);
|
||||
|
||||
if (last) {
|
||||
ceph_check_caps(ci, 0, NULL);
|
||||
ceph_check_caps(ci, 0);
|
||||
} else if (flush_snaps) {
|
||||
ceph_flush_snaps(ci, NULL);
|
||||
}
|
||||
|
@ -3604,10 +3602,9 @@ static void handle_cap_grant(struct inode *inode,
|
|||
|
||||
mutex_unlock(&session->s_mutex);
|
||||
if (check_caps == 1)
|
||||
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL,
|
||||
session);
|
||||
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL);
|
||||
else if (check_caps == 2)
|
||||
ceph_check_caps(ci, CHECK_CAPS_NOINVAL, session);
|
||||
ceph_check_caps(ci, CHECK_CAPS_NOINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4333,7 +4330,7 @@ unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
|
|||
if (inode) {
|
||||
spin_unlock(&mdsc->cap_delay_lock);
|
||||
dout("check_delayed_caps on %p\n", inode);
|
||||
ceph_check_caps(ci, 0, NULL);
|
||||
ceph_check_caps(ci, 0);
|
||||
iput(inode);
|
||||
spin_lock(&mdsc->cap_delay_lock);
|
||||
}
|
||||
|
@ -4362,7 +4359,7 @@ static void flush_dirty_session_caps(struct ceph_mds_session *s)
|
|||
dout("flush_dirty_caps %llx.%llx\n", ceph_vinop(inode));
|
||||
spin_unlock(&mdsc->cap_dirty_lock);
|
||||
ceph_wait_on_async_create(inode);
|
||||
ceph_check_caps(ci, CHECK_CAPS_FLUSH, NULL);
|
||||
ceph_check_caps(ci, CHECK_CAPS_FLUSH);
|
||||
iput(inode);
|
||||
spin_lock(&mdsc->cap_dirty_lock);
|
||||
}
|
||||
|
|
|
@ -313,7 +313,7 @@ int ceph_renew_caps(struct inode *inode, int fmode)
|
|||
spin_unlock(&ci->i_ceph_lock);
|
||||
dout("renew caps %p want %s issued %s updating mds_wanted\n",
|
||||
inode, ceph_cap_string(wanted), ceph_cap_string(issued));
|
||||
ceph_check_caps(ci, 0, NULL);
|
||||
ceph_check_caps(ci, 0);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
|
@ -408,7 +408,7 @@ int ceph_open(struct inode *inode, struct file *file)
|
|||
if ((issued & wanted) != wanted &&
|
||||
(mds_wanted & wanted) != wanted &&
|
||||
ceph_snap(inode) != CEPH_SNAPDIR)
|
||||
ceph_check_caps(ci, 0, NULL);
|
||||
ceph_check_caps(ci, 0);
|
||||
|
||||
return ceph_init_file(inode, file, fmode);
|
||||
} else if (ceph_snap(inode) != CEPH_NOSNAP &&
|
||||
|
@ -534,14 +534,23 @@ static void wake_async_create_waiters(struct inode *inode,
|
|||
struct ceph_mds_session *session)
|
||||
{
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
bool check_cap = false;
|
||||
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE) {
|
||||
ci->i_ceph_flags &= ~CEPH_I_ASYNC_CREATE;
|
||||
wake_up_bit(&ci->i_ceph_flags, CEPH_ASYNC_CREATE_BIT);
|
||||
|
||||
if (ci->i_ceph_flags & CEPH_I_ASYNC_CHECK_CAPS) {
|
||||
ci->i_ceph_flags &= ~CEPH_I_ASYNC_CHECK_CAPS;
|
||||
check_cap = true;
|
||||
}
|
||||
}
|
||||
ceph_kick_flushing_inode_caps(session, ci);
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
|
||||
if (check_cap)
|
||||
ceph_check_caps(ci, CHECK_CAPS_FLUSH);
|
||||
}
|
||||
|
||||
static void ceph_async_create_cb(struct ceph_mds_client *mdsc,
|
||||
|
@ -1092,7 +1101,7 @@ static void ceph_aio_complete(struct inode *inode,
|
|||
loff_t endoff = aio_req->iocb->ki_pos + aio_req->total_len;
|
||||
if (endoff > i_size_read(inode)) {
|
||||
if (ceph_inode_set_size(inode, endoff))
|
||||
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);
|
||||
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY);
|
||||
}
|
||||
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
|
@ -1421,8 +1430,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
|
|||
if (write && pos > size) {
|
||||
if (ceph_inode_set_size(inode, pos))
|
||||
ceph_check_caps(ceph_inode(inode),
|
||||
CHECK_CAPS_AUTHONLY,
|
||||
NULL);
|
||||
CHECK_CAPS_AUTHONLY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1577,8 +1585,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
|
|||
check_caps = ceph_inode_set_size(inode, pos);
|
||||
if (check_caps)
|
||||
ceph_check_caps(ceph_inode(inode),
|
||||
CHECK_CAPS_AUTHONLY,
|
||||
NULL);
|
||||
CHECK_CAPS_AUTHONLY);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1906,7 +1913,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
|||
if (dirty)
|
||||
__mark_inode_dirty(inode, dirty);
|
||||
if (ceph_quota_is_max_bytes_approaching(inode, iocb->ki_pos))
|
||||
ceph_check_caps(ci, CHECK_CAPS_FLUSH, NULL);
|
||||
ceph_check_caps(ci, CHECK_CAPS_FLUSH);
|
||||
}
|
||||
|
||||
dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n",
|
||||
|
@ -2521,8 +2528,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
|
|||
/* Let the MDS know about dst file size change */
|
||||
if (ceph_inode_set_size(dst_inode, dst_off) ||
|
||||
ceph_quota_is_max_bytes_approaching(dst_inode, dst_off))
|
||||
ceph_check_caps(dst_ci, CHECK_CAPS_AUTHONLY | CHECK_CAPS_FLUSH,
|
||||
NULL);
|
||||
ceph_check_caps(dst_ci, CHECK_CAPS_AUTHONLY | CHECK_CAPS_FLUSH);
|
||||
}
|
||||
/* Mark Fw dirty */
|
||||
spin_lock(&dst_ci->i_ceph_lock);
|
||||
|
|
|
@ -1909,7 +1909,7 @@ static void ceph_do_invalidate_pages(struct inode *inode)
|
|||
mutex_unlock(&ci->i_truncate_mutex);
|
||||
out:
|
||||
if (check)
|
||||
ceph_check_caps(ci, 0, NULL);
|
||||
ceph_check_caps(ci, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1969,7 +1969,7 @@ void __ceph_do_pending_vmtruncate(struct inode *inode)
|
|||
mutex_unlock(&ci->i_truncate_mutex);
|
||||
|
||||
if (wrbuffer_refs == 0)
|
||||
ceph_check_caps(ci, 0, NULL);
|
||||
ceph_check_caps(ci, 0);
|
||||
|
||||
wake_up_all(&ci->i_cap_wq);
|
||||
}
|
||||
|
@ -1991,7 +1991,7 @@ static void ceph_inode_work(struct work_struct *work)
|
|||
__ceph_do_pending_vmtruncate(inode);
|
||||
|
||||
if (test_and_clear_bit(CEPH_I_WORK_CHECK_CAPS, &ci->i_work_mask))
|
||||
ceph_check_caps(ci, 0, NULL);
|
||||
ceph_check_caps(ci, 0);
|
||||
|
||||
if (test_and_clear_bit(CEPH_I_WORK_FLUSH_SNAPS, &ci->i_work_mask))
|
||||
ceph_flush_snaps(ci, NULL);
|
||||
|
|
|
@ -253,7 +253,7 @@ static long ceph_ioctl_lazyio(struct file *file)
|
|||
spin_unlock(&ci->i_ceph_lock);
|
||||
dout("ioctl_layzio: file %p marked lazy\n", file);
|
||||
|
||||
ceph_check_caps(ci, 0, NULL);
|
||||
ceph_check_caps(ci, 0);
|
||||
} else {
|
||||
dout("ioctl_layzio: file %p already lazy\n", file);
|
||||
}
|
||||
|
|
|
@ -593,6 +593,8 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
|
|||
#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 */
|
||||
#define CEPH_I_ASYNC_CHECK_CAPS (1 << 14) /* check caps immediately after async
|
||||
creating finishes */
|
||||
|
||||
/*
|
||||
* Masks of ceph inode work.
|
||||
|
@ -1200,8 +1202,7 @@ extern void ceph_remove_capsnap(struct inode *inode,
|
|||
extern void ceph_flush_snaps(struct ceph_inode_info *ci,
|
||||
struct ceph_mds_session **psession);
|
||||
extern bool __ceph_should_report_size(struct ceph_inode_info *ci);
|
||||
extern void ceph_check_caps(struct ceph_inode_info *ci, int flags,
|
||||
struct ceph_mds_session *session);
|
||||
extern void ceph_check_caps(struct ceph_inode_info *ci, int flags);
|
||||
extern unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc);
|
||||
extern void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc);
|
||||
extern int ceph_drop_caps_for_unlink(struct inode *inode);
|
||||
|
|
Loading…
Reference in a new issue