Skip to content

Commit 67be068

Browse files
committed
Merge tag 'vfs-6.8-release.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: - Get rid of copy_mc flag in iov_iter which really only makes sense for the core dumping code so move it out of the generic iov iter code and make it coredump's problem. See the detailed commit description. - Revert fs/aio: Make io_cancel() generate completions again The initial fix here was predicated on the assumption that calling ki_cancel() didn't complete aio requests. However, that turned out to be wrong since the two drivers that actually make use of this set a cancellation function that performs the cancellation correctly. So revert this change. - Ensure that the test for IOCB_AIO_RW always happens before the read from ki_ctx. * tag 'vfs-6.8-release.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: iov_iter: get rid of 'copy_mc' flag fs/aio: Check IOCB_AIO_RW before the struct aio_kiocb conversion Revert "fs/aio: Make io_cancel() generate completions again"
2 parents 5274d26 + a50026b commit 67be068

File tree

4 files changed

+64
-55
lines changed

4 files changed

+64
-55
lines changed

fs/aio.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -589,8 +589,8 @@ static int aio_setup_ring(struct kioctx *ctx, unsigned int nr_events)
589589

590590
void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
591591
{
592-
struct aio_kiocb *req = container_of(iocb, struct aio_kiocb, rw);
593-
struct kioctx *ctx = req->ki_ctx;
592+
struct aio_kiocb *req;
593+
struct kioctx *ctx;
594594
unsigned long flags;
595595

596596
/*
@@ -600,9 +600,13 @@ void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
600600
if (!(iocb->ki_flags & IOCB_AIO_RW))
601601
return;
602602

603+
req = container_of(iocb, struct aio_kiocb, rw);
604+
603605
if (WARN_ON_ONCE(!list_empty(&req->ki_list)))
604606
return;
605607

608+
ctx = req->ki_ctx;
609+
606610
spin_lock_irqsave(&ctx->ctx_lock, flags);
607611
list_add_tail(&req->ki_list, &ctx->active_reqs);
608612
req->ki_cancel = cancel;
@@ -2165,11 +2169,14 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
21652169
#endif
21662170

21672171
/* sys_io_cancel:
2168-
* Attempts to cancel an iocb previously passed to io_submit(). If the
2169-
* operation is successfully cancelled 0 is returned. May fail with
2170-
* -EFAULT if any of the data structures pointed to are invalid. May
2171-
* fail with -EINVAL if aio_context specified by ctx_id is invalid. Will
2172-
* fail with -ENOSYS if not implemented.
2172+
* Attempts to cancel an iocb previously passed to io_submit. If
2173+
* the operation is successfully cancelled, the resulting event is
2174+
* copied into the memory pointed to by result without being placed
2175+
* into the completion queue and 0 is returned. May fail with
2176+
* -EFAULT if any of the data structures pointed to are invalid.
2177+
* May fail with -EINVAL if aio_context specified by ctx_id is
2178+
* invalid. May fail with -EAGAIN if the iocb specified was not
2179+
* cancelled. Will fail with -ENOSYS if not implemented.
21732180
*/
21742181
SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
21752182
struct io_event __user *, result)
@@ -2200,12 +2207,14 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
22002207
}
22012208
spin_unlock_irq(&ctx->ctx_lock);
22022209

2203-
/*
2204-
* The result argument is no longer used - the io_event is always
2205-
* delivered via the ring buffer.
2206-
*/
2207-
if (ret == 0 && kiocb->rw.ki_flags & IOCB_AIO_RW)
2208-
aio_complete_rw(&kiocb->rw, -EINTR);
2210+
if (!ret) {
2211+
/*
2212+
* The result argument is no longer used - the io_event is
2213+
* always delivered via the ring buffer. -EINPROGRESS indicates
2214+
* cancellation is progress:
2215+
*/
2216+
ret = -EINPROGRESS;
2217+
}
22092218

22102219
percpu_ref_put(&ctx->users);
22112220

fs/coredump.c

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,9 @@ static int dump_emit_page(struct coredump_params *cprm, struct page *page)
872872
loff_t pos;
873873
ssize_t n;
874874

875+
if (!page)
876+
return 0;
877+
875878
if (cprm->to_skip) {
876879
if (!__dump_skip(cprm, cprm->to_skip))
877880
return 0;
@@ -884,7 +887,6 @@ static int dump_emit_page(struct coredump_params *cprm, struct page *page)
884887
pos = file->f_pos;
885888
bvec_set_page(&bvec, page, PAGE_SIZE, 0);
886889
iov_iter_bvec(&iter, ITER_SOURCE, &bvec, 1, PAGE_SIZE);
887-
iov_iter_set_copy_mc(&iter);
888890
n = __kernel_write_iter(cprm->file, &iter, &pos);
889891
if (n != PAGE_SIZE)
890892
return 0;
@@ -895,10 +897,44 @@ static int dump_emit_page(struct coredump_params *cprm, struct page *page)
895897
return 1;
896898
}
897899

900+
/*
901+
* If we might get machine checks from kernel accesses during the
902+
* core dump, let's get those errors early rather than during the
903+
* IO. This is not performance-critical enough to warrant having
904+
* all the machine check logic in the iovec paths.
905+
*/
906+
#ifdef copy_mc_to_kernel
907+
908+
#define dump_page_alloc() alloc_page(GFP_KERNEL)
909+
#define dump_page_free(x) __free_page(x)
910+
static struct page *dump_page_copy(struct page *src, struct page *dst)
911+
{
912+
void *buf = kmap_local_page(src);
913+
size_t left = copy_mc_to_kernel(page_address(dst), buf, PAGE_SIZE);
914+
kunmap_local(buf);
915+
return left ? NULL : dst;
916+
}
917+
918+
#else
919+
920+
/* We just want to return non-NULL; it's never used. */
921+
#define dump_page_alloc() ERR_PTR(-EINVAL)
922+
#define dump_page_free(x) ((void)(x))
923+
static inline struct page *dump_page_copy(struct page *src, struct page *dst)
924+
{
925+
return src;
926+
}
927+
#endif
928+
898929
int dump_user_range(struct coredump_params *cprm, unsigned long start,
899930
unsigned long len)
900931
{
901932
unsigned long addr;
933+
struct page *dump_page;
934+
935+
dump_page = dump_page_alloc();
936+
if (!dump_page)
937+
return 0;
902938

903939
for (addr = start; addr < start + len; addr += PAGE_SIZE) {
904940
struct page *page;
@@ -912,14 +948,17 @@ int dump_user_range(struct coredump_params *cprm, unsigned long start,
912948
*/
913949
page = get_dump_page(addr);
914950
if (page) {
915-
int stop = !dump_emit_page(cprm, page);
951+
int stop = !dump_emit_page(cprm, dump_page_copy(page, dump_page));
916952
put_page(page);
917-
if (stop)
953+
if (stop) {
954+
dump_page_free(dump_page);
918955
return 0;
956+
}
919957
} else {
920958
dump_skip(cprm, PAGE_SIZE);
921959
}
922960
}
961+
dump_page_free(dump_page);
923962
return 1;
924963
}
925964
#endif

include/linux/uio.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ struct iov_iter_state {
4040

4141
struct iov_iter {
4242
u8 iter_type;
43-
bool copy_mc;
4443
bool nofault;
4544
bool data_source;
4645
size_t iov_offset;
@@ -248,22 +247,8 @@ size_t _copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i);
248247

249248
#ifdef CONFIG_ARCH_HAS_COPY_MC
250249
size_t _copy_mc_to_iter(const void *addr, size_t bytes, struct iov_iter *i);
251-
static inline void iov_iter_set_copy_mc(struct iov_iter *i)
252-
{
253-
i->copy_mc = true;
254-
}
255-
256-
static inline bool iov_iter_is_copy_mc(const struct iov_iter *i)
257-
{
258-
return i->copy_mc;
259-
}
260250
#else
261251
#define _copy_mc_to_iter _copy_to_iter
262-
static inline void iov_iter_set_copy_mc(struct iov_iter *i) { }
263-
static inline bool iov_iter_is_copy_mc(const struct iov_iter *i)
264-
{
265-
return false;
266-
}
267252
#endif
268253

269254
size_t iov_iter_zero(size_t bytes, struct iov_iter *);
@@ -355,7 +340,6 @@ static inline void iov_iter_ubuf(struct iov_iter *i, unsigned int direction,
355340
WARN_ON(direction & ~(READ | WRITE));
356341
*i = (struct iov_iter) {
357342
.iter_type = ITER_UBUF,
358-
.copy_mc = false,
359343
.data_source = direction,
360344
.ubuf = buf,
361345
.count = count,

lib/iov_iter.c

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ void iov_iter_init(struct iov_iter *i, unsigned int direction,
166166
WARN_ON(direction & ~(READ | WRITE));
167167
*i = (struct iov_iter) {
168168
.iter_type = ITER_IOVEC,
169-
.copy_mc = false,
170169
.nofault = false,
171170
.data_source = direction,
172171
.__iov = iov,
@@ -244,27 +243,9 @@ size_t _copy_mc_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
244243
EXPORT_SYMBOL_GPL(_copy_mc_to_iter);
245244
#endif /* CONFIG_ARCH_HAS_COPY_MC */
246245

247-
static __always_inline
248-
size_t memcpy_from_iter_mc(void *iter_from, size_t progress,
249-
size_t len, void *to, void *priv2)
250-
{
251-
return copy_mc_to_kernel(to + progress, iter_from, len);
252-
}
253-
254-
static size_t __copy_from_iter_mc(void *addr, size_t bytes, struct iov_iter *i)
255-
{
256-
if (unlikely(i->count < bytes))
257-
bytes = i->count;
258-
if (unlikely(!bytes))
259-
return 0;
260-
return iterate_bvec(i, bytes, addr, NULL, memcpy_from_iter_mc);
261-
}
262-
263246
static __always_inline
264247
size_t __copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
265248
{
266-
if (unlikely(iov_iter_is_copy_mc(i)))
267-
return __copy_from_iter_mc(addr, bytes, i);
268249
return iterate_and_advance(i, bytes, addr,
269250
copy_from_user_iter, memcpy_from_iter);
270251
}
@@ -633,7 +614,6 @@ void iov_iter_kvec(struct iov_iter *i, unsigned int direction,
633614
WARN_ON(direction & ~(READ | WRITE));
634615
*i = (struct iov_iter){
635616
.iter_type = ITER_KVEC,
636-
.copy_mc = false,
637617
.data_source = direction,
638618
.kvec = kvec,
639619
.nr_segs = nr_segs,
@@ -650,7 +630,6 @@ void iov_iter_bvec(struct iov_iter *i, unsigned int direction,
650630
WARN_ON(direction & ~(READ | WRITE));
651631
*i = (struct iov_iter){
652632
.iter_type = ITER_BVEC,
653-
.copy_mc = false,
654633
.data_source = direction,
655634
.bvec = bvec,
656635
.nr_segs = nr_segs,
@@ -679,7 +658,6 @@ void iov_iter_xarray(struct iov_iter *i, unsigned int direction,
679658
BUG_ON(direction & ~1);
680659
*i = (struct iov_iter) {
681660
.iter_type = ITER_XARRAY,
682-
.copy_mc = false,
683661
.data_source = direction,
684662
.xarray = xarray,
685663
.xarray_start = start,
@@ -703,7 +681,6 @@ void iov_iter_discard(struct iov_iter *i, unsigned int direction, size_t count)
703681
BUG_ON(direction != READ);
704682
*i = (struct iov_iter){
705683
.iter_type = ITER_DISCARD,
706-
.copy_mc = false,
707684
.data_source = false,
708685
.count = count,
709686
.iov_offset = 0

0 commit comments

Comments
 (0)