Page MenuHomeFreeBSD

D36035.1776148258.diff
No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None

D36035.1776148258.diff

Index: sys/cam/cam_ccb.h
===================================================================
--- sys/cam/cam_ccb.h
+++ sys/cam/cam_ccb.h
@@ -163,6 +163,9 @@
/* Path statistics (error counts, etc.) */
XPT_GDEV_STATS = 0x0c,
/* Device statistics (error counts, etc.) */
+ XPT_DEFERRED_CALLBACK = 0x0d | XPT_FC_QUEUED | XPT_FC_USER_CCB
+ | XPT_FC_XPT_ONLY,
+ /* Deferred callback */
XPT_DEV_ADVINFO = 0x0e,
/* Get/Set Device advanced information */
XPT_ASYNC = 0x0f | XPT_FC_QUEUED | XPT_FC_USER_CCB
@@ -1336,6 +1339,18 @@
void *async_arg_ptr;
};
+/*
+ * CCB for sending deferred calls to a specific async callback that needs to be
+ * deferred to the async thread.
+ */
+struct ccb_deferred_callback {
+ struct ccb_hdr ccb_h;
+ ac_callback_t *deferred_callback;
+ uint32_t code; /* an async code */
+ off_t arg_size;
+ void *arg_ptr;
+};
+
/*
* Union of all CCB types for kernel space allocation. This union should
* never be used for manipulating CCBs - its only use is for the allocation
@@ -1376,6 +1391,7 @@
struct ccb_ataio ataio;
struct ccb_dev_advinfo cdai;
struct ccb_async casync;
+ struct ccb_deferred_callback cdc;
struct ccb_nvmeio nvmeio;
struct ccb_mmcio mmcio;
};
Index: sys/cam/cam_xpt.c
===================================================================
--- sys/cam/cam_xpt.c
+++ sys/cam/cam_xpt.c
@@ -3122,6 +3122,7 @@
start_ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(start_ccb);
break;
+ case XPT_DEFERRED_CALLBACK:
case XPT_ASYNC:
/*
* Queue the async operation so it can be run from a sleepable
@@ -4346,6 +4347,96 @@
}
}
+/* Note: periph will always be NULL */
+static void
+xpt_dc_process(struct cam_periph *periph, union ccb *ccb)
+{
+ struct cam_eb *bus;
+ struct cam_path *path;
+ void *arg;
+ u_int32_t code;
+
+ path = ccb->ccb_h.path;
+ code = ccb->cdc.code;
+ arg = ccb->cdc.arg_ptr;
+ CAM_DEBUG(path, CAM_DEBUG_TRACE | CAM_DEBUG_INFO,
+ ("xpt_deffered_callback(%s)\n", xpt_async_string(code)));
+ bus = path->bus;
+
+ ccb->cdc.defferred_callback(periph, code, path, arg)l
+
+ if (path->device != NULL && path->device->lun_id != CAM_LUN_WILDCARD)
+ xpt_release_devq(path, 1, TRUE);
+ else
+ xpt_release_simq(path->bus->sim, TRUE);
+ if (ccb->cdc.arg_size > 0)
+ free(arg, M_CAMXPT);
+ xpt_free_path(path);
+ xpt_free_ccb(ccb);
+}
+
+/*
+ * Defer a single callback. The deferred callback is similar to an async
+ * callback, except it's is a call to a specific function instead of a
+ * dispatched call based on the target device. We pass in path information, but
+ * we clone the path in case this is used by code that destroys the path (like
+ * camperiphfree). We wind up calling this function with a first argument of
+ * NULL to indicate no async context, and callbacks that use this must tolerate
+ * that for the code they pass in here. We also assume that the periph in the
+ * path is 'unstable' so we NULL that out. The callback must be tolerant of that
+a * as well.
+ */
+void
+xpt_deferred_callback(ac_callback_t *deferred_callback, uint32_t code,
+ struct cam_path *path, void *arg, size_t arglen)
+{
+ union ccb *ccb;
+ struct ccb_deferred_callback *cdc;
+ int size;
+
+ ccb = xpt_alloc_ccb_nowait();
+ if (ccb == NULL) {
+ xpt_print(path, "Can't allocate CCB to defer %s\n",
+ xpt_async_string(code));
+ return;
+ }
+
+ if (xpt_clone_path(&ccb->ccb_h.path, path) != 0) {
+ xpt_print(path, "Can't allocate path to defer %s\n",
+ xpt_async_string(code));
+ xpt_free_ccb(ccb);
+ return;
+ }
+ cdc = &ccb->cdc;
+ cdc->ccb_h.path->periph = NULL;
+ cdc->ccb_h.func_code = XPT_DEFERRED_CALLBACK;
+ cdc->ccb_h.cbfcnp = xpt_dc_process;
+ cdc->ccb_h.flags |= CAM_UNLOCKED;
+ cdc->deferred_callback = deferred_callback;
+ cdc->code = code;
+ cdc->arg_size = 0;
+ if (arglen > 0 && arg != NULL) {
+ cdc->arg_ptr = malloc(arglen, M_CAMXPT, M_NOWAIT);
+ if (cdc->arg_ptr == NULL) {
+ xpt_print(path, "Can't allocate argument to defer %s\n",
+ xpt_async_string(code));
+ xpt_free_path(ccb->ccb_h.path);
+ xpt_free_ccb(ccb);
+ return;
+ }
+ memcpy(cdc->arg_ptr, arg, arglen);
+ cdc->arg_size = arglen;
+ }
+ /*
+ * Freeze processing of other events while we process this out of band
+ */
+ if (path->device != NULL && path->device->lun_id != CAM_LUN_WILDCARD)
+ xpt_freeze_devq(path, 1);
+ else
+ xpt_freeze_simq(path->bus->sim, 1);
+ xpt_action(ccb);
+}
+
void
xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg)
{

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 14, 6:30 AM (12 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28342361
Default Alt Text
D36035.1776148258.diff (4 KB)

Event Timeline