Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144681767
D36035.1776148258.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D36035.1776148258.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D36035: cam: Create xpt_deferred_callback
Attached
Detach File
Event Timeline
Log In to Comment