/* If the caller asked us to seek for data before doing the read, then *weshoulddothatnow.Ifwefindagap,wefillitwithzeros.
*/ if (read_hole != NETFS_READ_HOLE_IGNORE) {
loff_t off = start_pos, off2;
if (off2 == -ENXIO || off2 >= start_pos + len) { /* The region is beyond the EOF or there's no more data *intheregion,socleartherestofthebufferand *returnsuccess.
*/
ret = -ENODATA; if (read_hole == NETFS_READ_HOLE_FAIL) goto presubmission_error;
trace_cachefiles_read(object, file_inode(file), ki->iocb.ki_pos, len - skipped);
old_nofs = memalloc_nofs_save();
ret = cachefiles_inject_read_error(); if (ret == 0)
ret = vfs_iocb_iter_read(file, &ki->iocb, iter);
memalloc_nofs_restore(old_nofs); switch (ret) { case -EIOCBQUEUED: goto in_progress;
case -ERESTARTSYS: case -ERESTARTNOINTR: case -ERESTARTNOHAND: case -ERESTART_RESTARTBLOCK: /* There's no easy way to restart the syscall since other AIO's *maybealreadyrunning.JustfailthisIOwithEINTR.
*/
ret = -EINTR;
fallthrough; default:
ki->was_async = false;
cachefiles_read_complete(&ki->iocb, ret); if (ret > 0)
ret = 0; break;
}
off = cachefiles_inject_read_error(); if (off == 0)
off = vfs_llseek(file, start, SEEK_DATA); if (off == -ENXIO) return -ENODATA; /* Beyond EOF */ if (off < 0 && off >= (loff_t)-MAX_ERRNO) return -ENOBUFS; /* Error. */ if (round_up(off, granularity) >= start + len) return -ENODATA; /* No data in range */
trace_cachefiles_write(object, file_inode(file), ki->iocb.ki_pos, len);
old_nofs = memalloc_nofs_save();
ret = cachefiles_inject_write_error(); if (ret == 0)
ret = vfs_iocb_iter_write(file, &ki->iocb, iter);
memalloc_nofs_restore(old_nofs); switch (ret) { case -EIOCBQUEUED: goto in_progress;
case -ERESTARTSYS: case -ERESTARTNOINTR: case -ERESTARTNOHAND: case -ERESTART_RESTARTBLOCK: /* There's no easy way to restart the syscall since other AIO's *maybealreadyrunning.JustfailthisIOwithEINTR.
*/
ret = -EINTR;
fallthrough; default:
ki->was_async = false;
cachefiles_write_complete(&ki->iocb, ret); break;
}
if (start >= i_size) {
ret = NETFS_FILL_WITH_ZEROES;
why = cachefiles_trace_read_after_eof; goto out_no_object;
}
if (test_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags)) {
__set_bit(NETFS_SREQ_COPY_TO_CACHE, _flags);
why = cachefiles_trace_read_no_data; if (!test_bit(NETFS_SREQ_ONDEMAND, _flags)) goto out_no_object;
}
/* The object and the file may be being created in the background. */ if (!file) {
why = cachefiles_trace_read_no_file; if (!fscache_wait_for_operation(cres, FSCACHE_WANT_READ)) goto out_no_object;
file = cachefiles_cres_file(cres); if (!file) goto out_no_object;
ino = file_inode(file)->i_ino;
}
object = cachefiles_cres_object(cres);
cache = object->volume->cache;
cachefiles_begin_secure(cache, &saved_cred);
retry:
off = cachefiles_inject_read_error(); if (off == 0)
off = vfs_llseek(file, start, SEEK_DATA); if (off < 0 && off >= (loff_t)-MAX_ERRNO) { if (off == (loff_t)-ENXIO) {
why = cachefiles_trace_read_seek_nxio; goto download_and_store;
}
trace_cachefiles_io_error(object, file_inode(file), off,
cachefiles_trace_seek_error);
why = cachefiles_trace_read_seek_error; goto out;
}
if (off > start) {
off = round_up(off, cache->bsize);
len = off - start;
*_len = len;
why = cachefiles_trace_read_found_part; goto download_and_store;
}
to = cachefiles_inject_read_error(); if (to == 0)
to = vfs_llseek(file, start, SEEK_HOLE); if (to < 0 && to >= (loff_t)-MAX_ERRNO) {
trace_cachefiles_io_error(object, file_inode(file), to,
cachefiles_trace_seek_error);
why = cachefiles_trace_read_seek_error; goto out;
}
if (to < start + len) { if (start + len >= i_size)
to = round_up(to, cache->bsize); else
to = round_down(to, cache->bsize);
len = to - start;
*_len = len;
}
why = cachefiles_trace_read_have_data;
ret = NETFS_READ_FROM_CACHE; goto out;
/* Round to DIO size */
start = round_down(*_start, PAGE_SIZE); if (start != *_start || *_len > upper_len) { /* Probably asked to cache a streaming write written into the *pagecachewhenthecookiewastemporarilyoutofserviceto *culling.
*/
fscache_count_dio_misfit(); return -ENOBUFS;
}
*_len = round_up(len, PAGE_SIZE);
/* We need to work out whether there's sufficient disk space to perform *thewrite-butwecanskipthatcheckifwehavespacealready *allocated.
*/ if (no_space_allocated_yet) goto check_space;
pos = cachefiles_inject_read_error(); if (pos == 0)
pos = vfs_llseek(file, start, SEEK_DATA); if (pos < 0 && pos >= (loff_t)-MAX_ERRNO) { if (pos == -ENXIO) goto check_space; /* Unallocated tail */
trace_cachefiles_io_error(object, file_inode(file), pos,
cachefiles_trace_seek_error); return pos;
} if ((u64)pos >= (u64)start + *_len) goto check_space; /* Unallocated region */
/* We have a block that's at least partially filled - if we're low on *space,weneedtoseeifit'sfullyallocated.Ifit'snot,wemay *wanttocullit.
*/ if (cachefiles_has_space(cache, 0, *_len / PAGE_SIZE,
cachefiles_has_space_check) == 0) return0; /* Enough space to simply overwrite the whole block */
if (!cachefiles_cres_file(cres)) { if (!fscache_wait_for_operation(cres, FSCACHE_WANT_WRITE)) return -ENOBUFS; if (!cachefiles_cres_file(cres)) return -ENOBUFS;
}
if (!cachefiles_cres_file(cres)) { if (!fscache_wait_for_operation(cres, FSCACHE_WANT_WRITE)) return netfs_prepare_write_failed(subreq); if (!cachefiles_cres_file(cres)) return netfs_prepare_write_failed(subreq);
}
}
_enter("W=%x[%x] %llx-%llx",
wreq->debug_id, subreq->debug_index, start, start + len - 1);
/* We need to start on the cache granularity boundary */
off = start & (CACHEFILES_DIO_BLOCK_SIZE - 1); if (off) {
pre = CACHEFILES_DIO_BLOCK_SIZE - off; if (pre >= len) {
fscache_count_dio_misfit();
netfs_write_subrequest_terminated(subreq, len); return;
}
subreq->transferred += pre;
start += pre;
len -= pre;
iov_iter_advance(&subreq->io_iter, pre);
}
/* We also need to end on the cache granularity boundary */ if (start + len == wreq->i_size) {
size_t part = len % CACHEFILES_DIO_BLOCK_SIZE;
size_t need = CACHEFILES_DIO_BLOCK_SIZE - part;
if (part && stream->submit_extendable_to >= need) {
len += need;
subreq->len += need;
subreq->io_iter.count += need;
}
}
post = len & (CACHEFILES_DIO_BLOCK_SIZE - 1); if (post) {
len -= post; if (len == 0) {
fscache_count_dio_misfit();
netfs_write_subrequest_terminated(subreq, post); return;
}
iov_iter_truncate(&subreq->io_iter, len);
}
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.