lkml.org 
[lkml]   [2022]   [Aug]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH v9 12/27] rust: add `kernel` crate
    > +unsafe impl GlobalAlloc for KernelAllocator {
    > + unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
    > + // `krealloc()` is used instead of `kmalloc()` because the latter is
    > + // an inline function and cannot be bound to as a result.
    > + unsafe { bindings::krealloc(ptr::null(), layout.size(), bindings::GFP_KERNEL) as *mut u8 }
    > + }
    > +
    > + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
    > + unsafe {
    > + bindings::kfree(ptr as *const core::ffi::c_void);
    > + }
    > + }
    > +}

    I sense possible problems here. It's common for a kernel code to pass
    flags during memory allocations.

    For example:

    struct bio *bio;

    for (...) {
    bio = bio_alloc_bioset(bdev, nr_vecs, opf, GFP_NOIO, bs);
    if (!bio)
    return -ENOMEM;
    }

    Without GFP_NOIO we can run into a deadlock, because the kernel will try
    give us free memory by flushing the dirty pages and we need the memory
    to actually do it and boom, deadlock.

    Or we can be allocating some structs under spinlock (yeah, that happens too):

    struct efc_vport *vport;

    spin_lock_irqsave(...);
    vport = kzalloc(sizeof(*vport), GFP_ATOMIC);
    if (!vport) {
    spin_unlock_irqrestore(...);
    return NULL;
    }
    spin_unlock(...);

    Same can (and probably will) happen to e.g. Vec elements. So some form
    of flags passing should be supported in try_* variants:

    let mut vec = Vec::try_new(GFP_ATOMIC)?;

    vec.try_push(GFP_ATOMIC, 1)?;
    vec.try_push(GFP_ATOMIC, 2)?;
    vec.try_push(GFP_ATOMIC, 3)?;

    \
     
     \ /
      Last update: 2022-08-06 12:25    [W:2.688 / U:0.148 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site