/** * call_usermodehelper_keys - start a usermode application * @path: pathname for the application * @argv: null-terminated argument list * @envp: null-terminated environment list * @session_keyring: session keyring for process (NULL for an empty keyring) * @wait: wait for the application to finish and return status. * * Runs a user-space application. The application is started * asynchronously if wait is not set, and runs as a child of keventd. * (ie. it runs with full root capabilities). * * Must be called from process context. Returns a negative error code * if program was not execed successfully, or 0. */ int call_usermodehelper_keys(char *path, char **argv, char **envp, struct key *session_keyring, int wait) { DECLARE_COMPLETION(done); struct subprocess_info sub_info = { .complete = &done, .path = path, .argv = argv, .envp = envp, .ring = session_keyring, .wait = wait, .retval = 0, }; DECLARE_WORK(work, __call_usermodehelper, &sub_info); OSA_REGISTER_SPINLOCK(&done.wait.lock, "wait_queue_head_t->lock", 23); if (!khelper_wq) return -EBUSY; if (path[0] == '\0') return 0; queue_work(khelper_wq, &work); wait_for_completion(&done); return sub_info.retval; } EXPORT_SYMBOL(call_usermodehelper_keys); void __init usermodehelper_init(void) { khelper_wq = create_singlethread_workqueue("khelper"); BUG_ON(!khelper_wq); }
static int blk_do_rq(request_queue_t *q, struct block_device *bdev, struct request *rq) { char sense[SCSI_SENSE_BUFFERSIZE]; DECLARE_COMPLETION(wait); int err = 0; rq->rq_disk = bdev->bd_disk; /* * we need an extra reference to the request, so we can look at * it after io completion */ rq->ref_count++; if (!rq->sense) { memset(sense, 0, sizeof(sense)); rq->sense = sense; rq->sense_len = 0; } rq->flags |= REQ_NOMERGE; rq->waiting = &wait; elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); generic_unplug_device(q); wait_for_completion(&wait); if (rq->errors) err = -EIO; return err; }
int start_sync_thread(int state, char *mcast_ifn) { DECLARE_COMPLETION(startup); pid_t pid; if (sync_pid) return -EEXIST; IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid); IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %d bytes\n", sizeof(struct ip_vs_sync_conn)); ip_vs_sync_state = state; strcpy(ip_vs_mcast_ifn, mcast_ifn); repeat: if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) { IP_VS_ERR("could not create fork_sync_thread due to %d... " "retrying.\n", pid); current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ); goto repeat; } wait_for_completion(&startup); return 0; }
static int send_request(request_queue_t * q, struct bio *bio, struct block_device *bdev, struct tbio_interface *inter, int writing) { struct request *rq; void *buffer = NULL; unsigned long start_time; int err; rq = blk_get_request(q, writing ? WRITE : READ, __GFP_WAIT); rq->cmd_len = inter->cmd_len; //printk("inter.cmd %s\n" , inter->cmd); if (copy_from_user(rq->cmd, inter->cmd, inter->cmd_len)) goto out_request; //printk("tbio: rq->cmd : %s\n",rq->cmd); if (sizeof(rq->cmd) != inter->cmd_len) memset(rq->cmd + inter->cmd_len, 0, sizeof(rq->cmd) - inter->cmd_len); rq->bio = rq->biotail = NULL; blk_rq_bio_prep(q, rq, bio); rq->data = buffer; rq->data_len = inter->data_len; rq->timeout = 0; if (!rq->timeout) rq->timeout = q->sg_timeout; if (!rq->timeout) rq->timeout = BLK_DEFAULT_TIMEOUT; start_time = jiffies; DECLARE_COMPLETION(wait); rq->rq_disk = bdev->bd_disk; rq->waiting = &wait; elv_add_request(q, rq, 1, 1); generic_unplug_device(q); wait_for_completion(&wait); //printk("tbio: completion\n"); if (rq->errors) { err = -EIO; printk("tbio: rq->errors\n"); return err; } blk_put_request(rq); return 0; out_request: blk_put_request(rq); return -EFAULT; }
int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) { DECLARE_COMPLETION(complete); mrq->done_data = &complete; mrq->done = mmc_wait_done; mmc_start_request(host, mrq); wait_for_completion(&complete); return 0; }
static int erase_write (struct mtd_info *mtd, unsigned long pos, int len, const char *buf) { struct erase_info erase = {}; DECLARE_COMPLETION(erase_completion); size_t retlen; int ret; /* * First, let's erase the flash block. */ erase.mtd = mtd; erase.priv = (u_long)&erase_completion; erase.callback = erase_callback; erase.addr = pos; erase.len = len; ret = mtd->erase(mtd, &erase); if (ret) { printk (KERN_WARNING "mtdblock: erase of region [0x%lx, 0x%x] " "on \"%s\" failed\n", pos, len, mtd->name); return ret; } wait_for_completion_interruptible(&erase_completion); /* * Next, writhe data to flash. */ ret = mtd->write(mtd, pos, len, &retlen, buf); if (ret) return ret; if (retlen != len) return -EIO; return 0; }
/** * call_usermodehelper - start a usermode application * @path: pathname for the application * @argv: null-terminated argument list * @envp: null-terminated environment list * * Runs a user-space application. The application is started asynchronously. It * runs as a child of keventd. It runs with full root capabilities. keventd silently * reaps the child when it exits. * * Must be called from process context. Returns zero on success, else a negative * error code. */ int call_usermodehelper(char *path, char **argv, char **envp) { DECLARE_COMPLETION(work); struct subprocess_info sub_info = { complete: &work, path: path, argv: argv, envp: envp, retval: 0, }; struct tq_struct tqs = { routine: __call_usermodehelper, data: &sub_info, };
/* * This should be a separate module. */ int usb_hub_init(void) { DECLARE_COMPLETION(startup); if (usb_register(&hub_driver) < 0) { err("Unable to register USB hub driver"); return -1; } if (kernel_thread(usb_hub_thread, &startup, CLONE_FS | CLONE_FILES | CLONE_SIGHAND) >= 0) { wait_for_completion(&startup); return 0; } /* Fall through if kernel_thread failed */ usb_deregister(&hub_driver); err("failed to start usb_hub_thread"); return -1; }
int xixcore_call xixcore_HaveLotLock( uint8 * HostMac, uint8 * LockOwnerMac, uint64 LotNumber, uint8 * VolumeId, uint8 * LockOwnerId ) { // Request LotLock state to Lock Owner int RC = 0; PXIXFSDG_PKT pPacket = NULL; PXIXFS_LOCK_REQUEST pPacketData = NULL; int waitStatus = LOCK_INVALID; DECLARE_COMPLETION(wait); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB|DEBUG_TARGET_LOCK), ("Enter xixfs_AreYouHaveLotLock \n")); RC = xixfs_AllocDGPkt( &pPacket, HostMac, LockOwnerMac, XIXFS_TYPE_LOCK_REQUEST ) ; if(RC < 0 ) { DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("Error (0x%x) xixfs_AreYouHaveLotLock:xixfs_AllocDGPkt \n", RC)); return RC; } // Changed by ILGU HONG // chesung suggest DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB|DEBUG_TARGET_LOCK), ("Packet Dest Info [0x%02x:%02x:%02x:%02x:%02x:%02x]\n", LockOwnerMac[26], LockOwnerMac[27], LockOwnerMac[28], LockOwnerMac[29], LockOwnerMac[30], LockOwnerMac[31])); pPacketData = &(pPacket->RawDataDG.LockReq); memcpy(pPacketData->LotOwnerID, LockOwnerId, 6); // Changed by ILGU HONG // chesung suggest memcpy(pPacketData->VolumeId, VolumeId, 16); memcpy(pPacketData->LotOwnerMac, LockOwnerMac, 32); pPacketData->LotNumber = XI_HTONLL(LotNumber); pPacketData->PacketNumber = XI_HTONL(atomic_read(&(xixfs_linux_global.EventCtx.PacketNumber))); atomic_inc(&(xixfs_linux_global.EventCtx.PacketNumber)); pPacket->TimeOut = xixcore_GetCurrentTime64()+ DEFAULT_REQUEST_MAX_TIMEOUT; pPacket->PkCtl.PktCompletion = &wait; pPacket->PkCtl.status=&waitStatus; printk(KERN_DEBUG "WAIT lock request\n"); xixfs_Pkt_add_sendqueue( &xixfs_linux_global.EventCtx, pPacket ); wait_for_completion(&wait); printk(KERN_DEBUG "END WAIT lock request\n"); if(waitStatus == LOCK_OWNED_BY_OWNER){ DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB|DEBUG_TARGET_LOCK), ("Exit xixfs_AreYouHaveLotLock Lock is realy acquired by other \n")); return 1; }else{ DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB|DEBUG_TARGET_LOCK), ("Exit XifsdAreYouHaveLotLock Lock is status(0x%x) \n", waitStatus)); return 0; } }
/* * This is the task which runs the usermode application */ static int ____call_usermodehelper(void *data) { struct subprocess_info *sub_info = data; int retval; /* Install input pipe when needed */ if (sub_info->stdin) { struct files_struct *f = current->files; struct fdtable *fdt; /* no races because files should be private here */ sys_close(0); fd_install(0, sub_info->stdin); spin_lock(&f->file_lock); fdt = files_fdtable(f); FD_SET(0, fdt->open_fds); FD_CLR(0, fdt->close_on_exec); spin_unlock(&f->file_lock); /* and disallow core files too */ current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0}; } /* We can run anywhere, unlike our parent keventd(). */ set_cpus_allowed(current, CPU_MASK_ALL); retval = __exec_usermodehelper(sub_info->path, sub_info->argv, sub_info->envp, sub_info->ring); /* Exec failed? */ sub_info->retval = retval; do_exit(0); } /* Keventd can't block, but this (a child) can. */ static int wait_for_helper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; struct k_sigaction sa; /* Install a handler: if SIGCLD isn't handled sys_wait4 won't * populate the status, but will return -ECHILD. */ sa.sa.sa_handler = SIG_IGN; sa.sa.sa_flags = 0; siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD)); do_sigaction(SIGCHLD, &sa, NULL); allow_signal(SIGCHLD); pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD); if (pid < 0) { sub_info->retval = pid; } else { /* * Normally it is bogus to call wait4() from in-kernel because * wait4() wants to write the exit code to a userspace address. * But wait_for_helper() always runs as keventd, and put_user() * to a kernel address works OK for kernel threads, due to their * having an mm_segment_t which spans the entire address space. * * Thus the __user pointer cast is valid here. */ sys_wait4(pid, (int __user *) &sub_info->retval, 0, NULL); } complete(sub_info->complete); return 0; } /* This is run by khelper thread */ static void __call_usermodehelper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; int wait = sub_info->wait; /* CLONE_VFORK: wait until the usermode helper has execve'd * successfully We need the data structures to stay around * until that is done. */ if (wait) pid = kernel_thread(wait_for_helper, sub_info, CLONE_FS | CLONE_FILES | SIGCHLD); else pid = kernel_thread(____call_usermodehelper, sub_info, CLONE_VFORK | SIGCHLD); if (pid < 0) { sub_info->retval = pid; complete(sub_info->complete); } else if (!wait) complete(sub_info->complete); } /** * call_usermodehelper_keys - start a usermode application * @path: pathname for the application * @argv: null-terminated argument list * @envp: null-terminated environment list * @session_keyring: session keyring for process (NULL for an empty keyring) * @wait: wait for the application to finish and return status. * * Runs a user-space application. The application is started * asynchronously if wait is not set, and runs as a child of keventd. * (ie. it runs with full root capabilities). * * Must be called from process context. Returns a negative error code * if program was not execed successfully, or 0. */ int call_usermodehelper_keys(char *path, char **argv, char **envp, struct key *session_keyring, int wait) { DECLARE_COMPLETION_ONSTACK(done); struct subprocess_info sub_info = { .complete = &done, .path = path, .argv = argv, .envp = envp, .ring = session_keyring, .wait = wait, .retval = 0, }; DECLARE_WORK(work, __call_usermodehelper, &sub_info); if (!khelper_wq) return -EBUSY; if (path[0] == '\0') return 0; queue_work(khelper_wq, &work); wait_for_completion(&done); return sub_info.retval; } EXPORT_SYMBOL(call_usermodehelper_keys); int call_usermodehelper_pipe(char *path, char **argv, char **envp, struct file **filp) { DECLARE_COMPLETION(done); struct subprocess_info sub_info = { .complete = &done, .path = path, .argv = argv, .envp = envp, .retval = 0, }; struct file *f; DECLARE_WORK(work, __call_usermodehelper, &sub_info); if (!khelper_wq) return -EBUSY; if (path[0] == '\0') return 0; f = create_write_pipe(); if (!f) return -ENOMEM; *filp = f; f = create_read_pipe(f); if (!f) { free_write_pipe(*filp); return -ENOMEM; } sub_info.stdin = f; queue_work(khelper_wq, &work); wait_for_completion(&done); return sub_info.retval; } EXPORT_SYMBOL(call_usermodehelper_pipe); void __init usermodehelper_init(void) { khelper_wq = create_singlethread_workqueue("khelper"); BUG_ON(!khelper_wq); }