void rpc_show_tasks(void) { struct rpc_task *t = all_tasks, *next; struct nfs_wreq *wreq; if (!t) return; printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " "-rpcwait -action- --exit--\n"); for (; t; t = next) { next = t->tk_next_task; printk("%05d %04d %04x %06d %8p %6d %8p %08ld %8s %8p %8p\n", t->tk_pid, t->tk_proc, t->tk_flags, t->tk_status, t->tk_client, t->tk_client->cl_prog, t->tk_rqstp, t->tk_timeout, t->tk_rpcwait ? rpc_qname(t->tk_rpcwait) : " <NULL> ", t->tk_action, t->tk_exit); if (!(t->tk_flags & RPC_TASK_NFSWRITE)) continue; /* NFS write requests */ wreq = (struct nfs_wreq *) t->tk_calldata; printk(" NFS: flgs=%08x, pid=%d, pg=%p, off=(%d, %d)\n", wreq->wb_flags, wreq->wb_pid, wreq->wb_page, wreq->wb_offset, wreq->wb_bytes); printk(" name=%s/%s\n", wreq->wb_dentry->d_parent->d_name.name, wreq->wb_dentry->d_name.name); } }
/* * Prepare for sleeping on a wait queue. * By always appending tasks to the list we ensure FIFO behavior. * NB: An RPC task will only receive interrupt-driven events as long * as it's on a wait queue. */ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, rpc_action action, rpc_action timer) { unsigned long oldflags; int status; dprintk("RPC: %4d sleep_on(queue \"%s\" time %ld)\n", task->tk_pid, rpc_qname(q), jiffies); /* * Protect the execution below. */ save_flags(oldflags); cli(); status = rpc_add_wait_queue(q, task); if (status) { printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status); task->tk_status = status; task->tk_flags |= RPC_TASK_RUNNING; } else { task->tk_callback = action; if (task->tk_timeout) rpc_add_timer(task, timer); task->tk_flags &= ~RPC_TASK_RUNNING; } restore_flags(oldflags); return; }
/* * Remove request from queue. * Note: must be called with interrupts disabled. */ void rpc_remove_wait_queue(struct rpc_task *task) { struct rpc_wait_queue *queue; if (!(queue = task->tk_rpcwait)) return; rpc_remove_list(&queue->task, task); task->tk_rpcwait = NULL; dprintk("RPC: %4d removed from queue %p \"%s\"\n", task->tk_pid, queue, rpc_qname(queue)); }
/* * Wake up the next task on the wait queue. */ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue) { unsigned long oldflags; struct rpc_task *task; dprintk("RPC: wake_up_next(%p \"%s\")\n", queue, rpc_qname(queue)); save_flags(oldflags); cli(); if ((task = queue->task) != 0) __rpc_wake_up(task); restore_flags(oldflags); return task; }
static int tasks_show(struct seq_file *f, void *v) { u32 xid = 0; struct rpc_task *task = v; struct rpc_clnt *clnt = task->tk_client; const char *rpc_waitq = "none"; if (RPC_IS_QUEUED(task)) rpc_waitq = rpc_qname(task->tk_waitqueue); if (task->tk_rqstp) xid = be32_to_cpu(task->tk_rqstp->rq_xid); seq_printf(f, "%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n", task->tk_pid, task->tk_flags, task->tk_status, clnt->cl_clid, xid, rpc_task_timeout(task), task->tk_ops, clnt->cl_program->name, clnt->cl_vers, rpc_proc_name(task), task->tk_action, rpc_waitq); return 0; }
/* * Add new request to wait queue. * * Swapper tasks always get inserted at the head of the queue. * This should avoid many nasty memory deadlocks and hopefully * improve overall performance. * Everyone else gets appended to the queue to ensure proper FIFO behavior. */ int rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task) { if (task->tk_rpcwait) { if (task->tk_rpcwait != queue) { printk(KERN_WARNING "RPC: doubly enqueued task!\n"); return -EWOULDBLOCK; } return 0; } if (RPC_IS_SWAPPER(task)) rpc_insert_list(&queue->task, task); else rpc_append_list(&queue->task, task); task->tk_rpcwait = queue; dprintk("RPC: %4d added to queue %p \"%s\"\n", task->tk_pid, queue, rpc_qname(queue)); return 0; }