+ /* This is always a (sub)log, not the catalog */
+ LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN);
+
+ if (rec->cr.cr_index > endrec)
+ /* records are in order, so we're done */
+ RETURN(LLOG_PROC_BREAK);
+
+ cookie.lgc_lgl = llh->lgh_id;
+ cookie.lgc_index = hdr->lrh_index;
+ obd = llh->lgh_ctxt->loc_exp->exp_obd;
+ inode = llh->lgh_file->f_dentry->d_inode;
+
+ /* XXX This is a workaround for the deadlock of changelog adding vs.
+ * changelog cancelling. Changelog adding always start transaction
+ * before acquiring the catlog lock (lgh_lock), whereas, changelog
+ * cancelling do start transaction after holding catlog lock.
+ *
+ * We start the transaction earlier here to keep the locking ordering:
+ * 'start transaction -> catlog lock'. LU-81. */
+ trans_h = fsfilt_start_log(obd, inode, FSFILT_OP_CANCEL_UNLINK,
+ NULL, 1);
+ if (IS_ERR(trans_h)) {
+ CERROR("fsfilt_start_log failed: %ld\n", PTR_ERR(trans_h));
+ RETURN(PTR_ERR(trans_h));
+ }
+
+ /* cancel them one at a time. I suppose we could store up the cookies
+ and cancel them all at once; probably more efficient, but this is
+ done as a user call, so who cares... */
+ rc = llog_cat_cancel_records(llh->u.phd.phd_cat_handle, 1, &cookie);
+
+ err = fsfilt_commit(obd, inode, trans_h, 0);
+ if (err) {
+ CERROR("fsfilt_commit failed: %d\n", err);
+ rc = (rc >= 0) ? err : rc;
+ }
+
+ RETURN(rc < 0 ? rc : 0);