int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st) { int err; struct msghdr msg; BUG_ON(!t->iovec.iov_len); BUG_ON(t->iovec.iov_len > 1024*1024*1024); netfs_state_lock_send(st); if (!st->socket) { err = netfs_state_init(st); if (err) goto err_out_unlock_return; } msg.msg_iov = &t->iovec; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = MSG_WAITALL; if (t->attached_pages) msg.msg_flags |= MSG_MORE; err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, t->iovec.iov_len); if (err <= 0) { printk("%s: failed to send contig transaction: t: %p, gen: %u, size: %zu, err: %d.\n", __func__, t, t->gen, t->iovec.iov_len, err); if (err == 0) err = -ECONNRESET; goto err_out_unlock_return; } dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n", __func__, (t->page_num)?"partial":"full", t, t->gen, t->iovec.iov_len, t->page_num); err = 0; if (t->attached_pages) err = netfs_trans_send_pages(t, st); err_out_unlock_return: if (st->need_reset) netfs_state_exit(st); netfs_state_unlock_send(st); dprintk("%s: t: %p, gen: %u, err: %d.\n", __func__, t, t->gen, err); t->result = err; return err; }
static int pohmelfs_data_recv(struct netfs_state *st, void *data, unsigned int size) { unsigned int revents = 0; unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; unsigned int mask = err_mask | POLLIN; int err = 0; while (size && !err) { revents = netfs_state_poll(st); if (!(revents & mask)) { DEFINE_WAIT(wait); for (;;) { prepare_to_wait(&st->thread_wait, &wait, TASK_INTERRUPTIBLE); if (kthread_should_stop()) break; revents = netfs_state_poll(st); if (revents & mask) break; if (signal_pending(current)) break; schedule(); continue; } finish_wait(&st->thread_wait, &wait); } err = 0; netfs_state_lock(st); if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) { err = netfs_data_recv(st, data, size); if (err > 0) { data += err; size -= err; err = 0; } else if (err == 0) err = -ECONNRESET; } if (revents & err_mask) { printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n", __func__, revents, st->socket, size, err); err = -ECONNRESET; } netfs_state_unlock(st); if (err < 0) { if (netfs_state_trylock_send(st)) { netfs_state_exit(st); err = netfs_state_init(st); if (!err) err = -EAGAIN; netfs_state_unlock_send(st); } else { st->need_reset = 1; } } if (kthread_should_stop()) err = -ENODEV; if (err) printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, " "should_stop: %d, size: %u, err: %d.\n", __func__, st->socket, st->read_socket, revents, revents & err_mask, kthread_should_stop(), size, err); } return err; }