* Mark ready "count" units of I/O starting with "m". Most mbufs * count as a single unit of I/O except for M_EXTPG mbufs which * are backed by multiple pages. */
| 197 | * are backed by multiple pages. |
| 198 | */ |
| 199 | int |
| 200 | sbready(struct sockbuf *sb, struct mbuf *m0, int count) |
| 201 | { |
| 202 | struct mbuf *m; |
| 203 | u_int blocker; |
| 204 | |
| 205 | SOCKBUF_LOCK_ASSERT(sb); |
| 206 | KASSERT(sb->sb_fnrdy != NULL, ("%s: sb %p NULL fnrdy", __func__, sb)); |
| 207 | KASSERT(count > 0, ("%s: invalid count %d", __func__, count)); |
| 208 | |
| 209 | m = m0; |
| 210 | blocker = (sb->sb_fnrdy == m) ? M_BLOCKED : 0; |
| 211 | |
| 212 | while (count > 0) { |
| 213 | KASSERT(m->m_flags & M_NOTREADY, |
| 214 | ("%s: m %p !M_NOTREADY", __func__, m)); |
| 215 | if ((m->m_flags & M_EXTPG) != 0 && m->m_epg_npgs != 0) { |
| 216 | if (count < m->m_epg_nrdy) { |
| 217 | m->m_epg_nrdy -= count; |
| 218 | count = 0; |
| 219 | break; |
| 220 | } |
| 221 | count -= m->m_epg_nrdy; |
| 222 | m->m_epg_nrdy = 0; |
| 223 | } else |
| 224 | count--; |
| 225 | |
| 226 | m->m_flags &= ~(M_NOTREADY | blocker); |
| 227 | if (blocker) |
| 228 | sb->sb_acc += m->m_len; |
| 229 | m = m->m_next; |
| 230 | } |
| 231 | |
| 232 | /* |
| 233 | * If the first mbuf is still not fully ready because only |
| 234 | * some of its backing pages were readied, no further progress |
| 235 | * can be made. |
| 236 | */ |
| 237 | if (m0 == m) { |
| 238 | MPASS(m->m_flags & M_NOTREADY); |
| 239 | return (EINPROGRESS); |
| 240 | } |
| 241 | |
| 242 | if (!blocker) { |
| 243 | sbready_compress(sb, m0, m); |
| 244 | return (EINPROGRESS); |
| 245 | } |
| 246 | |
| 247 | /* This one was blocking all the queue. */ |
| 248 | for (; m && (m->m_flags & M_NOTREADY) == 0; m = m->m_next) { |
| 249 | KASSERT(m->m_flags & M_BLOCKED, |
| 250 | ("%s: m %p !M_BLOCKED", __func__, m)); |
| 251 | m->m_flags &= ~M_BLOCKED; |
| 252 | sb->sb_acc += m->m_len; |
| 253 | } |
| 254 | |
| 255 | sb->sb_fnrdy = m; |
| 256 | sbready_compress(sb, m0, m); |
no test coverage detected