|| ((privbcb)->ref_count==0) \
|| ((privbcb)->ref_count==1 && (privbcb)->leave_func_pending))))
-static void privbcb_set(struct private_bcb *privbcb,gboolean dirty_wanted,gboolean lsn_valid_wanted,gint ref_count_balance)
+enum privbcb_item {
+ PRIVBCB_ITEM_NOP, /* for sanity checks */
+ PRIVBCB_ITEM_DIRTY,
+ PRIVBCB_ITEM_LSN_VALID,
+ PRIVBCB_ITEM_LEAVE_FUNC_PENDING,
+ PRIVBCB_ITEM_REF_COUNT,
+ };
+
+static void privbcb_set(struct private_bcb *privbcb,enum privbcb_item item,gint value)
{
g_return_if_fail(privbcb!=NULL);
- if (dirty_wanted==privbcb->dirty && !ref_count_balance)
- return;
-
private_bcb_flush_tree_init();
g_assert((PRIVBCB_WANTS_FLUSH(privbcb) ? privbcb : NULL)==g_tree_lookup(private_bcb_flush_tree,privbcb));
- privbcb->dirty=dirty_wanted;
- privbcb->lsn_valid=lsn_valid_wanted;
- g_assert(privbcb->ref_count>=0);
- privbcb->ref_count+=ref_count_balance;
- g_assert(privbcb->ref_count>=0);
+ switch (item) {
+ case PRIVBCB_ITEM_NOP:
+ break;
+ case PRIVBCB_ITEM_DIRTY:
+ g_assert(TRUE==value || FALSE==value);
+ privbcb->dirty=value;
+ break;
+ case PRIVBCB_ITEM_LSN_VALID:
+ g_assert(TRUE==value || FALSE==value);
+ privbcb->lsn_valid=value;
+ break;
+ case PRIVBCB_ITEM_LEAVE_FUNC_PENDING:
+ g_assert(TRUE==value || FALSE==value);
+ privbcb->leave_func_pending=value;
+ break;
+ case PRIVBCB_ITEM_REF_COUNT:
+ g_assert(privbcb->ref_count>=0);
+ privbcb->ref_count+=value;
+ g_assert(privbcb->ref_count>=0);
+ break;
+ default: g_assert_not_reached();
+ }
if (!PRIVBCB_WANTS_FLUSH(privbcb))
g_tree_remove(private_bcb_flush_tree,privbcb);
else
g_assert(privbcb->dirty==FALSE); /* it would be fatal */
/* Force 'ref_count' drop to 0. */
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,-privbcb->ref_count);
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,-privbcb->ref_count);
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: WARNING: Deleting file with pending (fortunately non-dirty) BCBs"
"; FileObject=%p,FileOffset=0x%llX,Length=0x%lX",G_STRLOC,
PublicBcb, /* key */
privbcb); /* value */
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,0); /* just for the assertions */
+ privbcb_set(privbcb,PRIVBCB_ITEM_NOP,0); /* just for the assertions */
/* We MUST NOT call captive_Cc_IoPageRead() inside our pagepos filling loop
* below as captive_Cc_IoPageRead() has very big consequences as it calls
/* NEVER re-read any memory from FileObject here! */
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,+1);
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,+1);
/* Memory already mapped by CcMapData(). */
*Bcb=privbcb->PublicBcb;
if (count_CcMapData) {
/* CcPinRead() must always reference-count only by 1 despite any sub-called functions! */
g_assert(privbcb->ref_count>=2);
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,-1);
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,-1);
}
return TRUE;
if (!privbcb->dirty)
return;
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,+1);
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,+1);
logging_notify_privbcb_flush(privbcb);
g_assert(privbcb->ref_count>=2);
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,-1);
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,-1);
if (privbcb->lsn_valid) {
g_assert(last_written_lsn<privbcb->lsn.QuadPart);
base_sectoraligned,(guint64)FileOffset_sectoraligned.QuadPart,(gulong)length_sectoraligned,
(gulong)IoStatus.Information);
- privbcb_set(privbcb,FALSE,privbcb->lsn_valid,0);
+ privbcb_set(privbcb,PRIVBCB_ITEM_DIRTY,FALSE);
}
break;
}
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,+1); /* for safe 'leave_func_pending' clear */
g_assert(privbcb->leave_func_pending==TRUE);
- privbcb->leave_func_pending=FALSE;
-
- g_assert(privbcb->ref_count>0);
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,-2); /* -1 for safe 'leave_func_pending' clear */
+ privbcb_set(privbcb,PRIVBCB_ITEM_LEAVE_FUNC_PENDING,FALSE);
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,-1);
if (privbcb->ref_count) {
if (privbcb->lsn_valid) /* cannout skip LSN-valid BCB */
break;
/* We were called as CcUnpinData()->captive_privbcb_flush()->CcUnpinData()->CcUnpinData_leave_func()
*/
if (privbcb->dirty) {
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,+1);
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,+1);
captive_privbcb_flush(privbcb);
continue;
}
(int)privbcb->leave_func_pending);
g_assert(privbcb->ref_count>0);
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,-1);
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,-1);
if (privbcb->ref_count>0)
return;
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,+1); /* it will get decreased again in CcUnpinData_leave_func() */
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,+1); /* it will get decreased again in CcUnpinData_leave_func() */
g_assert(privbcb->FileObject->SectionObjectPointers!=NULL);
/* It may not 'privbcb->FileObject->SectionObjectPointers->SharedCacheMap==PublicBcb'; see (NOTE*1) */
* I expect it a bug in ntfs.sys.
*/
if (!privbcb->leave_func_pending) {
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,+1);
- privbcb->leave_func_pending=TRUE;
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,-1); /* increase-decrease to safely set 'leave_func_pending' */
+ privbcb_set(privbcb,PRIVBCB_ITEM_LEAVE_FUNC_PENDING,TRUE);
captive_leave_register(
(captive_leave_func)CcUnpinData_leave_func, /* func */
privbcb); /* data; unused */
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Bcb=%p; privbcb->FileObject=%p",G_STRLOC,
Bcb,privbcb->FileObject);
- privbcb_set(privbcb,privbcb->dirty,privbcb->lsn_valid,+1);
+ privbcb_set(privbcb,PRIVBCB_ITEM_REF_COUNT,+1);
}
if (Lsn) {
privbcb->lsn=*Lsn;
- privbcb_set(privbcb,privbcb->dirty,TRUE,0);
+ privbcb_set(privbcb,PRIVBCB_ITEM_LSN_VALID,TRUE);
}
- privbcb_set(privbcb,TRUE,privbcb->lsn_valid,0);
+ privbcb_set(privbcb,PRIVBCB_ITEM_DIRTY,TRUE);
}
g_assert_not_reached();
- privbcb_set(privbcb,FALSE,privbcb->lsn_valid,0); /* purge it */
+ privbcb_set(privbcb,PRIVBCB_ITEM_DIRTY,FALSE); /* purge it */
return TRUE;
}