Commit 33ec9c5c authored by Al Viro's avatar Al Viro

lustre: switch struct ksock_conn to iov_iter

Merge ksnc_rx_{no_wanted,iov,kiov,niov,nkiov} into a single iov_iter
(ksnc_rx_to).
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 2f240c4a
...@@ -1688,10 +1688,10 @@ ksocknal_destroy_conn(struct ksock_conn *conn) ...@@ -1688,10 +1688,10 @@ ksocknal_destroy_conn(struct ksock_conn *conn)
case SOCKNAL_RX_LNET_PAYLOAD: case SOCKNAL_RX_LNET_PAYLOAD:
last_rcv = conn->ksnc_rx_deadline - last_rcv = conn->ksnc_rx_deadline -
cfs_time_seconds(*ksocknal_tunables.ksnd_timeout); cfs_time_seconds(*ksocknal_tunables.ksnd_timeout);
CERROR("Completing partial receive from %s[%d], ip %pI4h:%d, with error, wanted: %d, left: %d, last alive is %ld secs ago\n", CERROR("Completing partial receive from %s[%d], ip %pI4h:%d, with error, wanted: %zd, left: %d, last alive is %ld secs ago\n",
libcfs_id2str(conn->ksnc_peer->ksnp_id), conn->ksnc_type, libcfs_id2str(conn->ksnc_peer->ksnp_id), conn->ksnc_type,
&conn->ksnc_ipaddr, conn->ksnc_port, &conn->ksnc_ipaddr, conn->ksnc_port,
conn->ksnc_rx_nob_wanted, conn->ksnc_rx_nob_left, iov_iter_count(&conn->ksnc_rx_to), conn->ksnc_rx_nob_left,
cfs_duration_sec(cfs_time_sub(cfs_time_current(), cfs_duration_sec(cfs_time_sub(cfs_time_current(),
last_rcv))); last_rcv)));
lnet_finalize(conn->ksnc_peer->ksnp_ni, lnet_finalize(conn->ksnc_peer->ksnp_ni,
......
...@@ -357,11 +357,7 @@ struct ksock_conn { ...@@ -357,11 +357,7 @@ struct ksock_conn {
__u8 ksnc_rx_scheduled; /* being progressed */ __u8 ksnc_rx_scheduled; /* being progressed */
__u8 ksnc_rx_state; /* what is being read */ __u8 ksnc_rx_state; /* what is being read */
int ksnc_rx_nob_left; /* # bytes to next hdr/body */ int ksnc_rx_nob_left; /* # bytes to next hdr/body */
int ksnc_rx_nob_wanted;/* bytes actually wanted */ struct iov_iter ksnc_rx_to; /* copy destination */
int ksnc_rx_niov; /* # iovec frags */
struct kvec *ksnc_rx_iov; /* the iovec frags */
int ksnc_rx_nkiov; /* # page frags */
struct bio_vec *ksnc_rx_kiov; /* the page frags */
union ksock_rxiovspace ksnc_rx_iov_space; /* space for frag descriptors */ union ksock_rxiovspace ksnc_rx_iov_space; /* space for frag descriptors */
__u32 ksnc_rx_csum; /* partial checksum for incoming __u32 ksnc_rx_csum; /* partial checksum for incoming
* data * data
......
...@@ -251,14 +251,11 @@ ksocknal_transmit(struct ksock_conn *conn, struct ksock_tx *tx) ...@@ -251,14 +251,11 @@ ksocknal_transmit(struct ksock_conn *conn, struct ksock_tx *tx)
static int static int
ksocknal_recv_iov(struct ksock_conn *conn) ksocknal_recv_iov(struct ksock_conn *conn)
{ {
struct kvec *iov = conn->ksnc_rx_iov;
int nob; int nob;
int rc; int rc;
LASSERT(conn->ksnc_rx_niov > 0);
/* /*
* Never touch conn->ksnc_rx_iov or change connection * Never touch conn->ksnc_rx_to or change connection
* status inside ksocknal_lib_recv_iov * status inside ksocknal_lib_recv_iov
*/ */
rc = ksocknal_lib_recv_iov(conn); rc = ksocknal_lib_recv_iov(conn);
...@@ -275,22 +272,11 @@ ksocknal_recv_iov(struct ksock_conn *conn) ...@@ -275,22 +272,11 @@ ksocknal_recv_iov(struct ksock_conn *conn)
mb(); /* order with setting rx_started */ mb(); /* order with setting rx_started */
conn->ksnc_rx_started = 1; conn->ksnc_rx_started = 1;
conn->ksnc_rx_nob_wanted -= nob;
conn->ksnc_rx_nob_left -= nob; conn->ksnc_rx_nob_left -= nob;
do { iov_iter_advance(&conn->ksnc_rx_to, nob);
LASSERT(conn->ksnc_rx_niov > 0); if (iov_iter_count(&conn->ksnc_rx_to))
if (nob < (int)iov->iov_len) {
iov->iov_len -= nob;
iov->iov_base += nob;
return -EAGAIN; return -EAGAIN;
}
nob -= iov->iov_len;
conn->ksnc_rx_iov = ++iov;
conn->ksnc_rx_niov--;
} while (nob);
return rc; return rc;
} }
...@@ -298,14 +284,11 @@ ksocknal_recv_iov(struct ksock_conn *conn) ...@@ -298,14 +284,11 @@ ksocknal_recv_iov(struct ksock_conn *conn)
static int static int
ksocknal_recv_kiov(struct ksock_conn *conn) ksocknal_recv_kiov(struct ksock_conn *conn)
{ {
struct bio_vec *kiov = conn->ksnc_rx_kiov;
int nob; int nob;
int rc; int rc;
LASSERT(conn->ksnc_rx_nkiov > 0);
/* /*
* Never touch conn->ksnc_rx_kiov or change connection * Never touch conn->ksnc_rx_to or change connection
* status inside ksocknal_lib_recv_iov * status inside ksocknal_lib_recv_iov
*/ */
rc = ksocknal_lib_recv_kiov(conn); rc = ksocknal_lib_recv_kiov(conn);
...@@ -322,22 +305,10 @@ ksocknal_recv_kiov(struct ksock_conn *conn) ...@@ -322,22 +305,10 @@ ksocknal_recv_kiov(struct ksock_conn *conn)
mb(); /* order with setting rx_started */ mb(); /* order with setting rx_started */
conn->ksnc_rx_started = 1; conn->ksnc_rx_started = 1;
conn->ksnc_rx_nob_wanted -= nob;
conn->ksnc_rx_nob_left -= nob; conn->ksnc_rx_nob_left -= nob;
iov_iter_advance(&conn->ksnc_rx_to, nob);
do { if (iov_iter_count(&conn->ksnc_rx_to))
LASSERT(conn->ksnc_rx_nkiov > 0);
if (nob < (int)kiov->bv_len) {
kiov->bv_offset += nob;
kiov->bv_len -= nob;
return -EAGAIN; return -EAGAIN;
}
nob -= kiov->bv_len;
conn->ksnc_rx_kiov = ++kiov;
conn->ksnc_rx_nkiov--;
} while (nob);
return 1; return 1;
} }
...@@ -347,7 +318,7 @@ ksocknal_receive(struct ksock_conn *conn) ...@@ -347,7 +318,7 @@ ksocknal_receive(struct ksock_conn *conn)
{ {
/* /*
* Return 1 on success, 0 on EOF, < 0 on error. * Return 1 on success, 0 on EOF, < 0 on error.
* Caller checks ksnc_rx_nob_wanted to determine * Caller checks ksnc_rx_to to determine
* progress/completion. * progress/completion.
*/ */
int rc; int rc;
...@@ -364,7 +335,7 @@ ksocknal_receive(struct ksock_conn *conn) ...@@ -364,7 +335,7 @@ ksocknal_receive(struct ksock_conn *conn)
} }
for (;;) { for (;;) {
if (conn->ksnc_rx_niov) if (conn->ksnc_rx_to.type & ITER_KVEC)
rc = ksocknal_recv_iov(conn); rc = ksocknal_recv_iov(conn);
else else
rc = ksocknal_recv_kiov(conn); rc = ksocknal_recv_kiov(conn);
...@@ -382,7 +353,7 @@ ksocknal_receive(struct ksock_conn *conn) ...@@ -382,7 +353,7 @@ ksocknal_receive(struct ksock_conn *conn)
/* Completed a fragment */ /* Completed a fragment */
if (!conn->ksnc_rx_nob_wanted) { if (!iov_iter_count(&conn->ksnc_rx_to)) {
rc = 1; rc = 1;
break; break;
} }
...@@ -1050,6 +1021,7 @@ int ...@@ -1050,6 +1021,7 @@ int
ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip) ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip)
{ {
static char ksocknal_slop_buffer[4096]; static char ksocknal_slop_buffer[4096];
struct kvec *kvec = (struct kvec *)&conn->ksnc_rx_iov_space;
int nob; int nob;
unsigned int niov; unsigned int niov;
...@@ -1070,32 +1042,26 @@ ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip) ...@@ -1070,32 +1042,26 @@ ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip)
case KSOCK_PROTO_V2: case KSOCK_PROTO_V2:
case KSOCK_PROTO_V3: case KSOCK_PROTO_V3:
conn->ksnc_rx_state = SOCKNAL_RX_KSM_HEADER; conn->ksnc_rx_state = SOCKNAL_RX_KSM_HEADER;
conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; kvec->iov_base = &conn->ksnc_msg;
conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg; kvec->iov_len = offsetof(struct ksock_msg, ksm_u);
conn->ksnc_rx_nob_wanted = offsetof(struct ksock_msg, ksm_u);
conn->ksnc_rx_nob_left = offsetof(struct ksock_msg, ksm_u); conn->ksnc_rx_nob_left = offsetof(struct ksock_msg, ksm_u);
conn->ksnc_rx_iov[0].iov_len = offsetof(struct ksock_msg, ksm_u); iov_iter_kvec(&conn->ksnc_rx_to, READ|ITER_KVEC, kvec,
1, offsetof(struct ksock_msg, ksm_u));
break; break;
case KSOCK_PROTO_V1: case KSOCK_PROTO_V1:
/* Receiving bare struct lnet_hdr */ /* Receiving bare struct lnet_hdr */
conn->ksnc_rx_state = SOCKNAL_RX_LNET_HEADER; conn->ksnc_rx_state = SOCKNAL_RX_LNET_HEADER;
conn->ksnc_rx_nob_wanted = sizeof(struct lnet_hdr); kvec->iov_base = &conn->ksnc_msg.ksm_u.lnetmsg;
kvec->iov_len = sizeof(struct lnet_hdr);
conn->ksnc_rx_nob_left = sizeof(struct lnet_hdr); conn->ksnc_rx_nob_left = sizeof(struct lnet_hdr);
iov_iter_kvec(&conn->ksnc_rx_to, READ|ITER_KVEC, kvec,
conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; 1, sizeof(struct lnet_hdr));
conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg.ksm_u.lnetmsg;
conn->ksnc_rx_iov[0].iov_len = sizeof(struct lnet_hdr);
break; break;
default: default:
LBUG(); LBUG();
} }
conn->ksnc_rx_niov = 1;
conn->ksnc_rx_kiov = NULL;
conn->ksnc_rx_nkiov = 0;
conn->ksnc_rx_csum = ~0; conn->ksnc_rx_csum = ~0;
return 1; return 1;
} }
...@@ -1106,15 +1072,14 @@ ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip) ...@@ -1106,15 +1072,14 @@ ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip)
*/ */
conn->ksnc_rx_state = SOCKNAL_RX_SLOP; conn->ksnc_rx_state = SOCKNAL_RX_SLOP;
conn->ksnc_rx_nob_left = nob_to_skip; conn->ksnc_rx_nob_left = nob_to_skip;
conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space;
skipped = 0; skipped = 0;
niov = 0; niov = 0;
do { do {
nob = min_t(int, nob_to_skip, sizeof(ksocknal_slop_buffer)); nob = min_t(int, nob_to_skip, sizeof(ksocknal_slop_buffer));
conn->ksnc_rx_iov[niov].iov_base = ksocknal_slop_buffer; kvec[niov].iov_base = ksocknal_slop_buffer;
conn->ksnc_rx_iov[niov].iov_len = nob; kvec[niov].iov_len = nob;
niov++; niov++;
skipped += nob; skipped += nob;
nob_to_skip -= nob; nob_to_skip -= nob;
...@@ -1122,16 +1087,14 @@ ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip) ...@@ -1122,16 +1087,14 @@ ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip)
} while (nob_to_skip && /* mustn't overflow conn's rx iov */ } while (nob_to_skip && /* mustn't overflow conn's rx iov */
niov < sizeof(conn->ksnc_rx_iov_space) / sizeof(struct iovec)); niov < sizeof(conn->ksnc_rx_iov_space) / sizeof(struct iovec));
conn->ksnc_rx_niov = niov; iov_iter_kvec(&conn->ksnc_rx_to, READ|ITER_KVEC, kvec, niov, skipped);
conn->ksnc_rx_kiov = NULL;
conn->ksnc_rx_nkiov = 0;
conn->ksnc_rx_nob_wanted = skipped;
return 0; return 0;
} }
static int static int
ksocknal_process_receive(struct ksock_conn *conn) ksocknal_process_receive(struct ksock_conn *conn)
{ {
struct kvec *kvec = (struct kvec *)&conn->ksnc_rx_iov_space;
struct lnet_hdr *lhdr; struct lnet_hdr *lhdr;
struct lnet_process_id *id; struct lnet_process_id *id;
int rc; int rc;
...@@ -1145,7 +1108,7 @@ ksocknal_process_receive(struct ksock_conn *conn) ...@@ -1145,7 +1108,7 @@ ksocknal_process_receive(struct ksock_conn *conn)
conn->ksnc_rx_state == SOCKNAL_RX_LNET_HEADER || conn->ksnc_rx_state == SOCKNAL_RX_LNET_HEADER ||
conn->ksnc_rx_state == SOCKNAL_RX_SLOP); conn->ksnc_rx_state == SOCKNAL_RX_SLOP);
again: again:
if (conn->ksnc_rx_nob_wanted) { if (iov_iter_count(&conn->ksnc_rx_to)) {
rc = ksocknal_receive(conn); rc = ksocknal_receive(conn);
if (rc <= 0) { if (rc <= 0) {
...@@ -1170,7 +1133,7 @@ ksocknal_process_receive(struct ksock_conn *conn) ...@@ -1170,7 +1133,7 @@ ksocknal_process_receive(struct ksock_conn *conn)
return (!rc ? -ESHUTDOWN : rc); return (!rc ? -ESHUTDOWN : rc);
} }
if (conn->ksnc_rx_nob_wanted) { if (iov_iter_count(&conn->ksnc_rx_to)) {
/* short read */ /* short read */
return -EAGAIN; return -EAGAIN;
} }
...@@ -1233,16 +1196,13 @@ ksocknal_process_receive(struct ksock_conn *conn) ...@@ -1233,16 +1196,13 @@ ksocknal_process_receive(struct ksock_conn *conn)
} }
conn->ksnc_rx_state = SOCKNAL_RX_LNET_HEADER; conn->ksnc_rx_state = SOCKNAL_RX_LNET_HEADER;
conn->ksnc_rx_nob_wanted = sizeof(struct ksock_lnet_msg);
conn->ksnc_rx_nob_left = sizeof(struct ksock_lnet_msg); conn->ksnc_rx_nob_left = sizeof(struct ksock_lnet_msg);
conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; kvec->iov_base = &conn->ksnc_msg.ksm_u.lnetmsg;
conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; kvec->iov_len = sizeof(struct ksock_lnet_msg);
conn->ksnc_rx_iov[0].iov_len = sizeof(struct ksock_lnet_msg);
conn->ksnc_rx_niov = 1; iov_iter_kvec(&conn->ksnc_rx_to, READ|ITER_KVEC, kvec,
conn->ksnc_rx_kiov = NULL; 1, sizeof(struct ksock_lnet_msg));
conn->ksnc_rx_nkiov = 0;
goto again; /* read lnet header now */ goto again; /* read lnet header now */
...@@ -1344,26 +1304,9 @@ ksocknal_recv(struct lnet_ni *ni, void *private, struct lnet_msg *msg, ...@@ -1344,26 +1304,9 @@ ksocknal_recv(struct lnet_ni *ni, void *private, struct lnet_msg *msg,
LASSERT(to->nr_segs <= LNET_MAX_IOV); LASSERT(to->nr_segs <= LNET_MAX_IOV);
conn->ksnc_cookie = msg; conn->ksnc_cookie = msg;
conn->ksnc_rx_nob_wanted = iov_iter_count(to);
conn->ksnc_rx_nob_left = rlen; conn->ksnc_rx_nob_left = rlen;
if (to->type & ITER_KVEC) { conn->ksnc_rx_to = *to;
conn->ksnc_rx_nkiov = 0;
conn->ksnc_rx_kiov = NULL;
conn->ksnc_rx_iov = conn->ksnc_rx_iov_space.iov;
conn->ksnc_rx_niov =
lnet_extract_iov(LNET_MAX_IOV, conn->ksnc_rx_iov,
to->nr_segs, to->kvec,
to->iov_offset, iov_iter_count(to));
} else {
conn->ksnc_rx_niov = 0;
conn->ksnc_rx_iov = NULL;
conn->ksnc_rx_kiov = conn->ksnc_rx_iov_space.kiov;
conn->ksnc_rx_nkiov =
lnet_extract_kiov(LNET_MAX_IOV, conn->ksnc_rx_kiov,
to->nr_segs, to->bvec,
to->iov_offset, iov_iter_count(to));
}
LASSERT(conn->ksnc_rx_scheduled); LASSERT(conn->ksnc_rx_scheduled);
...@@ -2328,12 +2271,12 @@ ksocknal_find_timed_out_conn(struct ksock_peer *peer) ...@@ -2328,12 +2271,12 @@ ksocknal_find_timed_out_conn(struct ksock_peer *peer)
conn->ksnc_rx_deadline)) { conn->ksnc_rx_deadline)) {
/* Timed out incomplete incoming message */ /* Timed out incomplete incoming message */
ksocknal_conn_addref(conn); ksocknal_conn_addref(conn);
CNETERR("Timeout receiving from %s (%pI4h:%d), state %d wanted %d left %d\n", CNETERR("Timeout receiving from %s (%pI4h:%d), state %d wanted %zd left %d\n",
libcfs_id2str(peer->ksnp_id), libcfs_id2str(peer->ksnp_id),
&conn->ksnc_ipaddr, &conn->ksnc_ipaddr,
conn->ksnc_port, conn->ksnc_port,
conn->ksnc_rx_state, conn->ksnc_rx_state,
conn->ksnc_rx_nob_wanted, iov_iter_count(&conn->ksnc_rx_to),
conn->ksnc_rx_nob_left); conn->ksnc_rx_nob_left);
return conn; return conn;
} }
......
...@@ -164,26 +164,19 @@ ksocknal_lib_eager_ack(struct ksock_conn *conn) ...@@ -164,26 +164,19 @@ ksocknal_lib_eager_ack(struct ksock_conn *conn)
int int
ksocknal_lib_recv_iov(struct ksock_conn *conn) ksocknal_lib_recv_iov(struct ksock_conn *conn)
{ {
unsigned int niov = conn->ksnc_rx_niov; unsigned int niov = conn->ksnc_rx_to.nr_segs;
struct kvec *iov = conn->ksnc_rx_iov; const struct iovec *iov = conn->ksnc_rx_to.iov;
struct msghdr msg = { struct msghdr msg = {
.msg_flags = 0 .msg_flags = 0
}; };
int nob;
int i; int i;
int rc; int rc;
int fragnob; int fragnob;
int sum; int sum;
__u32 saved_csum; __u32 saved_csum;
int off = conn->ksnc_rx_to.iov_offset;
LASSERT(niov > 0); msg.msg_iter = conn->ksnc_rx_to;
for (nob = i = 0; i < niov; i++)
nob += iov[i].iov_len;
LASSERT(nob <= conn->ksnc_rx_nob_wanted);
iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, iov, niov, nob);
rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT);
saved_csum = 0; saved_csum = 0;
...@@ -197,13 +190,14 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) ...@@ -197,13 +190,14 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn)
for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) {
LASSERT(i < niov); LASSERT(i < niov);
fragnob = iov[i].iov_len; fragnob = iov[i].iov_len - off;
if (fragnob > sum) if (fragnob > sum)
fragnob = sum; fragnob = sum;
conn->ksnc_rx_csum = crc32_le(conn->ksnc_rx_csum, conn->ksnc_rx_csum = crc32_le(conn->ksnc_rx_csum,
iov[i].iov_base, iov[i].iov_base + off,
fragnob); fragnob);
off = 0;
} }
conn->ksnc_msg.ksm_csum = saved_csum; conn->ksnc_msg.ksm_csum = saved_csum;
} }
...@@ -214,32 +208,29 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) ...@@ -214,32 +208,29 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn)
int int
ksocknal_lib_recv_kiov(struct ksock_conn *conn) ksocknal_lib_recv_kiov(struct ksock_conn *conn)
{ {
unsigned int niov = conn->ksnc_rx_nkiov; unsigned int niov = conn->ksnc_rx_to.nr_segs;
struct bio_vec *kiov = conn->ksnc_rx_kiov; const struct bio_vec *kiov = conn->ksnc_rx_to.bvec;
int off = conn->ksnc_rx_to.iov_offset;
struct msghdr msg = { struct msghdr msg = {
.msg_flags = 0 .msg_flags = 0
}; };
int nob;
int i; int i;
int rc; int rc;
void *base; void *base;
int sum; int sum;
int fragnob; int fragnob;
for (nob = i = 0; i < niov; i++) msg.msg_iter = conn->ksnc_rx_to;
nob += kiov[i].bv_len;
LASSERT(nob <= conn->ksnc_rx_nob_wanted);
iov_iter_bvec(&msg.msg_iter, READ | ITER_BVEC, kiov, niov, nob);
rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT);
if (rc <= 0)
return rc;
if (conn->ksnc_msg.ksm_csum) { if (conn->ksnc_msg.ksm_csum) {
for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) {
LASSERT(i < niov); LASSERT(i < niov);
base = kmap(kiov[i].bv_page) + kiov[i].bv_offset; base = kmap(kiov[i].bv_page) + kiov[i].bv_offset + off;
fragnob = kiov[i].bv_len; fragnob = kiov[i].bv_len - off;
if (fragnob > sum) if (fragnob > sum)
fragnob = sum; fragnob = sum;
...@@ -247,6 +238,7 @@ ksocknal_lib_recv_kiov(struct ksock_conn *conn) ...@@ -247,6 +238,7 @@ ksocknal_lib_recv_kiov(struct ksock_conn *conn)
base, fragnob); base, fragnob);
kunmap(kiov[i].bv_page); kunmap(kiov[i].bv_page);
off = 0;
} }
} }
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment