/* Notes made in the collector */ #define HIT_PENDING 0x01 /* A front op was still pending */ #define NEED_REASSESS 0x02 /* Need to loop round and reassess */ #define MADE_PROGRESS 0x04 /* Made progress cleaning up a stream or the folio set */ #define NEED_UNLOCK 0x08 /* The pagecache needs unlocking */ #define NEED_RETRY 0x10 /* A front op requests retrying */ #define SAW_FAILURE 0x20 /* One stream or hit a permanent failure */
if ((group = netfs_folio_group(folio))) { if (group == NETFS_FOLIO_COPY_TO_CACHE) {
why = netfs_folio_trace_clear_cc;
folio_detach_private(folio); goto end_wb;
}
/* Need to detach the group pointer if the page didn't get *redirtied.Ifithasbeenredirtied,thenitmustbewithin *thesamegroup.
*/
why = netfs_folio_trace_redirtied; if (!folio_test_dirty(folio)) {
folio_detach_private(folio);
gcount++;
why = netfs_folio_trace_clear_g;
}
}
folio = folioq_folio(folioq, slot); if (WARN_ONCE(!folio_test_writeback(folio), "R=%08x: folio %lx is not under writeback\n",
wreq->debug_id, folio->index))
trace_netfs_folio(folio, netfs_folio_trace_not_under_wback);
/* Clean up the head folioq. If we clear an entire folioq, then *wecangetridofitprovidedit'snotalsothetailfolioq *beingfilledbytheissuer.
*/
folioq_clear(folioq, slot);
slot++; if (slot >= folioq_nr_slots(folioq)) {
folioq = rolling_buffer_delete_spent(&wreq->buffer); if (!folioq) goto done;
slot = 0;
}
/* Remove completed subrequests from the front of the streams and *advancethecompletionpointoneachstream.Westopwhenwehit *somethingthat'sinprogress.Theissuerthreadmaybeaddingstuff *tothetailwhilstwe'redoingthis.
*/ for (s = 0; s < NR_IO_STREAMS; s++) {
stream = &wreq->io_streams[s]; /* Read active flag before list pointers */ if (!smp_load_acquire(&stream->active)) continue;
front = stream->front; while (front) {
trace_netfs_collect_sreq(wreq, front); //_debug("sreq [%x] %llx %zx/%zx", // front->debug_index, front->start, front->transferred, front->len);
/* Stall if the front is still undergoing I/O. */ if (netfs_check_subreq_in_progress(front)) {
notes |= HIT_PENDING; break;
}
smp_rmb(); /* Read counters after I-P flag. */
/* If we have an empty stream, we need to jump it forward *otherwisethecollectionpointwillneveradvance.
*/ if (!front && issued_to > stream->collected_to) {
trace_netfs_collect_gap(wreq, stream, issued_to, 'E');
stream->collected_to = issued_to;
}
if (stream->collected_to < collected_to)
collected_to = stream->collected_to;
}
/* Unlock any folios that we have now finished with. */ if (notes & NEED_UNLOCK) { if (wreq->cleaned_to < wreq->collected_to)
netfs_writeback_unlock_folios(wreq, ¬es);
} else {
wreq->cleaned_to = wreq->collected_to;
}
need_retry: /* Okay... We're going to have to retry one or both streams. Note *thatanypartiallycompletedopwillhavehadanywhollytransferred *foliosremovedfromit.
*/
_debug("retry");
netfs_retry_writes(wreq); goto out;
}
/* We're done when the app thread has finished posting subreqs and all *thequeuesinallthestreamsareempty.
*/ if (!test_bit(NETFS_RREQ_ALL_QUEUED, &wreq->flags)) returnfalse;
smp_rmb(); /* Read ALL_QUEUED before lists. */
transferred = LONG_MAX; for (s = 0; s < NR_IO_STREAMS; s++) { struct netfs_io_stream *stream = &wreq->io_streams[s]; if (!stream->active) continue; if (!list_empty(&stream->subrequests)) returnfalse; if (stream->transferred_valid &&
stream->transferred < transferred) {
transferred = stream->transferred;
transferred_valid = true;
}
}
/* Okay, declare that all I/O is complete. */ if (transferred_valid)
wreq->transferred = transferred;
trace_netfs_rreq(wreq, netfs_rreq_trace_write_done);
if (wreq->origin == NETFS_DIO_WRITE &&
wreq->mapping->nrpages) { /* mmap may have got underfoot and we may now have folios *locallycoveringtheregionwejustwrote.Attemptto *discardthefolios,butleaveinplaceanymodifiedlocally. *->write_iter()ispreventedfrominterferingbytheDIO *counter.
*/
pgoff_t first = wreq->start >> PAGE_SHIFT;
pgoff_t last = (wreq->start + wreq->transferred - 1) >> PAGE_SHIFT;
invalidate_inode_pages2_range(wreq->mapping, first, last);
}
if (wreq->origin == NETFS_DIO_WRITE)
inode_dio_end(wreq->inode);
_debug("finished");
netfs_wake_rreq_flag(wreq, NETFS_RREQ_IN_PROGRESS, netfs_rreq_trace_wake_ip); /* As we cleared NETFS_RREQ_IN_PROGRESS, we acquired its ref. */
if (wreq->iocb) {
size_t written = min(wreq->transferred, wreq->len);
wreq->iocb->ki_pos += written; if (wreq->iocb->ki_complete) {
trace_netfs_rreq(wreq, netfs_rreq_trace_ki_complete);
wreq->iocb->ki_complete(
wreq->iocb, wreq->error ? wreq->error : written);
}
wreq->iocb = VFS_PTR_POISON;
}
netfs_see_request(rreq, netfs_rreq_trace_see_work); if (netfs_check_rreq_in_progress(rreq)) { if (netfs_write_collection(rreq)) /* Drop the ref from the IN_PROGRESS flag. */
netfs_put_request(rreq, netfs_rreq_trace_put_work_ip); else
netfs_see_request(rreq, netfs_rreq_trace_see_work_complete);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.