qsd_op_end() shouldn't be called before the transaction stopped,
because qsd_op_end() is a quite heavy operation which could
probably allocate memory with standard allocator flag (__GFP_IO),
and allocating memory could result in dirty flush on other
filesystems, that will lead to opening transaction on different
journal and trigger the assert in jbd2_journal_start():
J_ASSERT(handle->h_transaction->t_journal == journal) at the end.
Signed-off-by: Niu Yawei <yawei.niu@intel.com>
Change-Id: I4ea3ff011fa7e44460b9912050e90b174813e01a
Reviewed-on: http://review.whamcloud.com/8968
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Johann Lombardi <johann.lombardi@intel.com>
static int osd_trans_stop(const struct lu_env *env, struct dt_device *dt,
struct thandle *th)
{
static int osd_trans_stop(const struct lu_env *env, struct dt_device *dt,
struct thandle *th)
{
- int rc = 0;
- struct osd_thandle *oh;
- struct osd_thread_info *oti = osd_oti_get(env);
- struct osd_iobuf *iobuf = &oti->oti_iobuf;
+ int rc = 0;
+ struct osd_thandle *oh;
+ struct osd_thread_info *oti = osd_oti_get(env);
+ struct osd_iobuf *iobuf = &oti->oti_iobuf;
struct qsd_instance *qsd = oti->oti_dev->od_quota_slave;
struct qsd_instance *qsd = oti->oti_dev->od_quota_slave;
+ struct lquota_trans *qtrans;
+ ENTRY;
- oh = container_of0(th, struct osd_thandle, ot_super);
+ oh = container_of0(th, struct osd_thandle, ot_super);
- if (qsd != NULL)
- /* inform the quota slave device that the transaction is
- * stopping */
- qsd_op_end(env, qsd, oh->ot_quota_trans);
+ qtrans = oh->ot_quota_trans;
oh->ot_quota_trans = NULL;
if (oh->ot_handle != NULL) {
oh->ot_quota_trans = NULL;
if (oh->ot_handle != NULL) {
thandle_put(&oh->ot_super);
}
thandle_put(&oh->ot_super);
}
+ /* inform the quota slave device that the transaction is stopping */
+ qsd_op_end(env, qsd, qtrans);
+
/* as we want IO to journal and data IO be concurrent, we don't block
* awaiting data IO completion in osd_do_bio(), instead we wait here
* once transaction is submitted to the journal. all reqular requests
/* as we want IO to journal and data IO be concurrent, we don't block
* awaiting data IO completion in osd_do_bio(), instead we wait here
* once transaction is submitted to the journal. all reqular requests