#define IOC_PORTAL_DEL_ROUTE _IOWR('e', 53, IOCTL_PORTAL_TYPE)
#define IOC_PORTAL_GET_ROUTE _IOWR('e', 54, IOCTL_PORTAL_TYPE)
#define IOC_PORTAL_NOTIFY_ROUTER _IOWR('e', 55, IOCTL_PORTAL_TYPE)
+#define IOC_PORTAL_UNCONFIGURE _IOWR('e', 56, IOCTL_PORTAL_TYPE)
/* nal ioctls */
#define IOC_PORTAL_REGISTER_MYNID _IOWR('e', 70, IOCTL_PORTAL_TYPE)
#define IOC_PORTAL_CLOSE_CONNECTION _IOWR('e', 71, IOCTL_PORTAL_TYPE)
ptl_queue_zombie_ni(ni);
}
+extern ptl_err_t ptl_get_apinih (ptl_handle_ni_t *nih);
+
extern ptl_ni_t *ptl_net2ni (__u32 net);
extern void ptl_enq_event_locked (void *private,
ptl_eq_t *eq, ptl_event_t *ev);
ptl_queue_zombie_ni(ni);
}
+extern ptl_err_t ptl_get_apinih (ptl_handle_ni_t *nih);
+
extern ptl_ni_t *ptl_net2ni (__u32 net);
extern void ptl_enq_event_locked (void *private,
ptl_eq_t *eq, ptl_event_t *ev);
/* Stuff initialised at PtlInit() */
int apini_init; /* PtlInit() called? */
int apini_refcount; /* PtlNIInit/PtlNIFini counter */
+ int apini_niinit_self; /* Have I called PtlNIInit myself? */
struct list_head apini_nals; /* registered NALs */
#ifdef __KERNEL__
EXPORT_SYMBOL(libcfs_isknown_nal);
+EXPORT_SYMBOL(libcfs_nal2modname);
EXPORT_SYMBOL(libcfs_nal2str);
EXPORT_SYMBOL(libcfs_str2nal);
EXPORT_SYMBOL(libcfs_net2str);
CFS_MODULE_PARM(networks, "s", charp, 0444,
"local networks (default='"DEFAULT_NETWORKS"')");
+static int nal_load_timeout = 10;
+CFS_MODULE_PARM(nal_load_timeout, "i", int, 0444,
+ "seconds to wait for a NAL to load");
+
ptl_apini_t ptl_apini; /* THE network interface (at the API) */
void ptl_assert_wire_constants (void)
ptl_err_t
ptl_load_nal (int type)
{
- CERROR("Automatic NAL loading not implemented (%s)\n",
- libcfs_nal2str(type));
- return PTL_FAIL;
+ /* Called holding api_mutex */
+ static char cmd[256];
+
+ char *envp[] = {
+ "HOME=/",
+ "PATH=/sbin:/bin:/usr/sbin:/usr/bin",
+ NULL};
+ char *argv[] = {
+ "/bin/sh",
+ "-c",
+ cmd,
+ NULL};
+ int timeout = nal_load_timeout;
+ int rc;
+
+ snprintf(cmd, sizeof(cmd), "modprobe %s > /dev/console",
+ libcfs_nal2modname(type));
+
+ rc = USERMODEHELPER(argv[0], argv, envp);
+ if (rc < 0) {
+ CERROR("Error %d trying '%s' '%s' '%s'\n",
+ rc, argv[0], argv[1], argv[2]);
+ return PTL_FAIL;
+ }
+
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(cfs_time_seconds(1));
+ timeout--;
+
+ PTL_MUTEX_DOWN(&ptl_apini.apini_nal_mutex);
+ rc = (ptl_find_nal_by_type(type) == NULL) ? PTL_FAIL : PTL_OK;
+ PTL_MUTEX_UP(&ptl_apini.apini_nal_mutex);
+
+ } while (rc != PTL_OK && timeout > 0);
+
+ if (rc != PTL_OK) {
+ LCONSOLE_ERROR("Timeout waiting for NAL %s to load\n",
+ libcfs_nal2str(type));
+ LCONSOLE_ERROR("cmd: \"%s %s '%s'\"\n",
+ argv[0], argv[1], argv[2]);
+ }
+
+ return rc;
}
ptl_err_t
for (retry = 0;; retry = 1) {
nal = ptl_find_nal_by_type(nal_type);
- if (nal != NULL)
+ if (nal != NULL)
break;
PTL_MUTEX_UP(&ptl_apini.apini_nal_mutex);
break;
}
PTL_UNLOCK(flags);
- break;
+ return rc;
case IOC_PORTAL_FAIL_NID:
- rc = ptl_fail_nid(data->ioc_nid, data->ioc_count);
- break;
+ return ptl_fail_nid(data->ioc_nid, data->ioc_count);
case IOC_PORTAL_ADD_ROUTE:
case IOC_PORTAL_DEL_ROUTE:
case IOC_PORTAL_GET_ROUTE:
case IOC_PORTAL_NOTIFY_ROUTER:
- rc = kpr_ctl(cmd, arg);
- break;
+ return kpr_ctl(cmd, arg);
default:
ni = ptl_net2ni(data->ioc_net);
- if (ni == NULL) {
+ if (ni == NULL)
+ return -EINVAL;
+
+ if (ni->ni_nal->nal_ctl == NULL)
rc = -EINVAL;
- } else {
- if (ni->ni_nal->nal_ctl == NULL)
- rc = -EINVAL;
- else
- rc = ni->ni_nal->nal_ctl(ni, cmd, arg);
+ else
+ rc = ni->ni_nal->nal_ctl(ni, cmd, arg);
- ptl_ni_decref(ni);
- }
- break;
+ ptl_ni_decref(ni);
+ return rc;
}
-
- return rc;
+ /* not reached */
}
ptl_err_t
LCONSOLE_ERROR("Error parsing '%s=\"%s\"'\n", name, str);
LCONSOLE_ERROR("here...........%.*s..%.*s|%.*s|\n",
- strlen(name), dots, offset, dots,
+ (int)strlen(name), dots, offset, dots,
(width < 1) ? 0 : width - 1, dashes);
}
static int kportal_ioctl(unsigned int cmd, struct portal_ioctl_data *data)
{
+ ptl_err_t initrc;
int rc;
ptl_handle_ni_t nih;
- rc = PtlNIInit(PTL_IFACE_DEFAULT, LUSTRE_SRV_PTL_PID,
- NULL, NULL, &nih);
- if (!(rc == PTL_OK || rc == PTL_IFACE_DUP))
+ if (cmd == IOC_PORTAL_UNCONFIGURE) {
+ /* ghastly hack to prevent repeated net config */
+ PTL_MUTEX_DOWN(&ptl_apini.apini_api_mutex);
+ initrc = ptl_apini.apini_niinit_self;
+ ptl_apini.apini_niinit_self = 0;
+ rc = ptl_apini.apini_refcount;
+ PTL_MUTEX_UP(&ptl_apini.apini_api_mutex);
+
+ if (initrc) {
+ rc--;
+ PtlNIFini((ptl_handle_ni_t){0});
+ }
+
+ return rc == 0 ? 0 : -EBUSY;
+ }
+
+ initrc = PtlNIInit(PTL_IFACE_DEFAULT, LUSTRE_SRV_PTL_PID,
+ NULL, NULL, &nih);
+ if (!(initrc == PTL_OK || initrc == PTL_IFACE_DUP))
RETURN (-EINVAL);
rc = PtlNICtl(nih, cmd, data);
- PtlNIFini(nih);
+ if (initrc == PTL_OK) {
+ PTL_MUTEX_DOWN(&ptl_apini.apini_api_mutex);
+ /* I instantiated the network */
+ ptl_apini.apini_niinit_self = 1;
+ PTL_MUTEX_UP(&ptl_apini.apini_api_mutex);
+ } else {
+ PtlNIFini(nih);
+ }
+
return rc;
}
int set = argc >= 2;
int count;
int rc;
+
+ if (set && !strcmp(argv[1], "unconfigure")) {
+ PORTAL_IOC_INIT(data);
+ rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_UNCONFIGURE, &data);
+
+ if (rc == 0) {
+ printf ("portals ready to unload\n");
+ return 0;
+ }
+
+ if (errno == EBUSY)
+ fprintf(stderr, "Portals still in use\n");
+ else
+ fprintf(stderr, "Unconfigure error %d: %s\n",
+ errno, strerror(errno));
+ return -1;
+ }
if (set) {
net = libcfs_str2net(argv[1]);