- char *upcall, keystr[16];
- char *argv[] = {
- [0] = cache->uc_upcall,
- [1] = cache->uc_name,
- [2] = keystr,
- [3] = NULL
- };
- char *envp[] = {
- [0] = "HOME=/",
- [1] = "PATH=/sbin:/usr/sbin",
- [2] = NULL
- };
- int size, rc;
- ENTRY;
-
- /* There is race condition:
- * "uc_upcall" was changed just after "is_identity_get_disabled" check.
- */
- size = strlen(cache->uc_upcall) + 1;
- OBD_ALLOC(upcall, size);
- if (unlikely(!upcall))
- RETURN(-ENOMEM);
-
- read_lock(&cache->uc_upcall_rwlock);
- memcpy(upcall, cache->uc_upcall, size - 1);
- read_unlock(&cache->uc_upcall_rwlock);
- upcall[size - 1] = 0;
- if (unlikely(!strcmp(upcall, "NONE"))) {
- CERROR("no upcall set\n");
- GOTO(out, rc = -EREMCHG);
- }
-
- argv[0] = upcall;
-
- snprintf(keystr, sizeof(keystr), LPU64, entry->ue_key);
-
- CDEBUG(D_INFO, "The upcall is: %s \n", cache->uc_upcall);
-
- rc = USERMODEHELPER(argv[0], argv, envp);
- if (rc < 0) {
- CERROR("%s: error invoking upcall %s %s %s: rc %d; "
- "check /proc/fs/lustre/mdt/%s/identity_upcall\n",
- cache->uc_name, argv[0], argv[1], argv[2], rc,
- cache->uc_name);
- } else {
- CDEBUG(D_HA, "%s: invoked upcall %s %s %s\n", cache->uc_name,
- argv[0], argv[1], argv[2]);
- rc = 0;
- }
- EXIT;
+ char keystr[16];
+ char *argv[] = {
+ [0] = cache->uc_upcall,
+ [1] = cache->uc_name,
+ [2] = keystr,
+ [3] = NULL
+ };
+ char *envp[] = {
+ [0] = "HOME=/",
+ [1] = "PATH=/sbin:/usr/sbin",
+ [2] = NULL
+ };
+ ktime_t start, end;
+ int rc;
+
+ ENTRY;
+ /* There is race condition:
+ * "uc_upcall" was changed just after "is_identity_get_disabled" check.
+ */
+ down_read(&cache->uc_upcall_rwsem);
+ CDEBUG(D_INFO, "The upcall is: '%s'\n", cache->uc_upcall);
+
+ if (unlikely(!strcmp(cache->uc_upcall, "NONE"))) {
+ CERROR("no upcall set\n");
+ GOTO(out, rc = -EREMCHG);
+ }
+
+ argv[0] = cache->uc_upcall;
+ snprintf(keystr, sizeof(keystr), "%llu", entry->ue_key);
+
+ start = ktime_get();
+ rc = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+ end = ktime_get();
+ if (rc < 0) {
+ CERROR("%s: error invoking upcall %s %s %s: rc %d; check /proc/fs/lustre/mdt/%s/identity_upcall, time %ldus\n",
+ cache->uc_name, argv[0], argv[1], argv[2], rc,
+ cache->uc_name, (long)ktime_us_delta(end, start));
+ } else {
+ CDEBUG(D_HA, "%s: invoked upcall %s %s %s, time %ldus\n",
+ cache->uc_name, argv[0], argv[1], argv[2],
+ (long)ktime_us_delta(end, start));
+ rc = 0;
+ }
+ EXIT;