Skip to content(if available)orjump to list(if available)

Resistance to Rust abstractions for DMA mapping

nialv7

My take is this: Hellwig is unhappy because he doesn't want Linux to become a multi-language project, at least if we take his words at face value (he did explicitly say he doesn't dislike rust, quote: ".. this cancer explicitly is a cross-language codebase and not rust itself, just to escape the flameware brigade").

This might have some technical merits, but that ship has already sailed when Linus decided to merge R4L into the kernel. If Hellwig wants to reverse that decision, he'll have to bring it to Linus, instead he's trying to block R4L patches and waste everyone's time and energy.

pjmlp

Additionally regardless of what upstream decides to do, Microsoft and Google are pretty much down on having Rust on their Linux forks, e.g. Sphere OS, Azure Linux, Android, ChromeOS.

flohofwoe

I wonder why that C file which maps a more abstract Rust-friendly C-API on top of the existing API can't live inside the Rust directory and build structure. If I would be one of the Rust maintainers, I would try to be as non-intrusive to the established project structure as possible, ideally completely invisible. It's also cleaner to keep all the Rust-related changes on the 'Rust side' of the project, even if they happen to be written in C (I'm also still wondering why Rust-for-Linux cannot live completely downstream in a temporary fork).

I also can fully understand that a C programmer doesn't want to deal with such a 'Rust idiomatic' C API.

ekimekim

> I wonder why that C file which maps a more abstract Rust-friendly C-API on top of the existing API can't live inside the Rust directory and build structure

This is more or less what the RfL folks are asking for - they have a Rust API to be used by other Rust code, which uses the existing C API, and are promising to maintain that API themselves. It lives in the Rust "directory".

The C maintainer is rejecting this, seemingly because his goal isn't to find a compromise that works but to completely block the project.

dralley

>I wonder why that C file which maps a more abstract Rust-friendly C-API on top of the existing API can't live inside the Rust directory and build structure.

That's what this patch does. It's what the patch _always_ did. Christoph seems not to have actually looked at the patch before rejecting it.

When it was pointed out to him that his initial complaints were in fact unfounded, he didn't say "oh well, I guess it's OK then", he came up with more unfounded reasons to reject it. And when those points were addressed, he basically said "nah, I don't want to".

I should note that he does not actually have any authority to reject the patches, since they're not in his subsystem. They are bindings to the DMA subsystem, he was CC'd as an advisory, but he has no more right to reject the patches than he would to reject a GPU driver that used DMA.

This is a waste of everyone's time.

abacate

> Christoph seems not to have actually looked at the patch before rejecting it.

I had the same impression as well, in particular due to his wording:

> "No rust code in kernel/dma, please"

When, in fact, the code is in "rust/kernel/dma" not "kernel/dma".

It seems like he missed this and then doubled down on his stance when questioned.

esjeon

AFAIK, the merge was for the sake of change, not like he fully agreed with the adoption of Rust nor prioritization of Rust. The point is to have actual discussions, rather than pushing things with 10-feet poles just for being new and different. Anything that make sense will become the outcome of those discussions.

arp242

> that ship has already sailed when Linus decided to merge R4L into the kernel

Of course not. Merging the basic infra for Rust didn't come with "it can be used in every single part of the kernel, regardless of what the people maintaining that think"-kind of guarantee. One way to use Rust is to only use it in drivers for example, and it seems Hellwig is not against that: "do that in your driver so that you have to do it".

UtherII

That's exactly the point. The patch in question is not to be used in any part of the kernel. It is a wrapper around the C API. It has no impact on current code and it will only be used by Rust drivers using DMA, the people of Rust for Linux were clear about it.

Duplicating this wrapper in every driver would just make painful the usage of DMA for Rust drivers for not benefit.

arp242

And Hellwig feels that's better done by "keep[ing] the wrappers in your code instead of making life painful for others".

I can see where he's coming from. I can also see why doing that is painful.

I don't really know what the best possible solution is. I do know that "Linus decided on Rust4Linux, therefore, this must be merged" is not a good argument. "Linus decided «moduke» is merged, therefore, accept my patches that are useful to «module» on «some other subsystem»". That doesn't really work, obviously.

raverbashing

Yeah pretty much this

And I think Linus should be very clear that rust is there to stay

flohofwoe

That still doesn't mean that 'Rust idiomatics' have to creep into every Linux subsystem which the Rust code needs to talk to. It just feels like a poor technical design to not keep both sides entirely separated.

timeon

> It just feels like a poor technical design to not keep both sides entirely separated.

Maybe you should read the mail thread if the article was not clear enough. The PR was inside Rust folder.

simonask

As I understand it, the proposed patches do not "creep" into any other subsystem, but act as another user of the existing APIs, just like any driver using the C API.

oguz-ismail

My daily soap opera fix

sidkshatriya

Seems like one of those situations that the "BDFL" will need to (temporarily) drop the "B" to get things moving.

Joking aside, Rust for Linux seems to be entering a phase where rubber is hitting the road and some maintainers who thought that Rust would just go away are having to express their opposition more honestly. There are definitely reasons for and against Rust in the Linux kernel and I feel for them.

Actually this pattern happens in all spheres of life. Some change is introduced. First, people ignore/deny it thinking it won't affect them or they feel that the system is too strong and the change won't really happen. They are (probabilistically) right because successful change requires really superhuman drive which the Rust for Linux maintainers by luck/unluck (depending on who you are) happen to have.

Now real change is coming to the door of some maintainers. Some of them hate the melange of Rust and C the Linux kernel is likely to become in the coming years. So they are hoping that their subsystem can escape. But it can't if Rust is really going to be a viable rather than toy option.

I think Rust has been baking in the kernel for a long time -- The BDFL/DFL needs to informally poll the maintainers and take a definitive decision to cast Linux's lot with Rust (or not!?). The Experimental tag in Rust gives some people the hope that this Rust experiment could be ended. This experimental tag should be replaced with in-progress/not-mature tag to further send the message down the line.

dralley

Nobody is asking Christoph to maintain Rust code. Just work with the R4L developers occasionally when a breaking change happens, the same way he likely would need to do so with every C-based consumer of those APIs. But he doesn't want to do that, and he also doesn't want to let anyone co-maintain the DMA subsystem. At some point this does need to be called out as gatekeepy and counterproductive behavior by a maintainer who doesn't want to work with others.

But working with others is kind of, like, necessary, in a project as large and critical as the Linux project. Developing new kernel talent was one of Linus' express reasons for doing the project in the first place.

https://www.youtube.com/watch?v=OvuEYtkOH88&t=6m07s

baq

> But Christoph Hellwig, who does a lot of work with the DMA-mapping layer, turned this submission away with a message reading, in its entirety: "No rust code in kernel/dma, please" (despite the fact that the patch did not put any code in that directory). When pressed, he added that developers should keep these abstractions in their own code and said that he had no interest in maintaining multi-language code. Rust developers should keep their wrapping code to themselves, he concluded.

> Danilo Krummrich pointed out that the proposed abstractions were doing exactly that — keeping the Rust code separate from the rest: "We wrote a single piece of Rust code that abstracts the C API for all Rust drivers, which we offer to maintain ourselves".

Please make it make sense. One of these folks is very wrong, but I can’t tell who?

nialv7

IIUC, I think it is kernel policy that if you change some kernel API and break its consumers, you are responsible for fixing those consumers. (correct me if this is wrong.) So in theory DMA devs may need to touch Rust code if they make changes to the DMA subsystem.

Edit: this is wrong/inaccurate, see comments below.

JoshTriplett

That's the general policy, but Rust is currently an exception to that policy: maintainers are not required to keep Rust bindings working when they change C code. The Rust-for-Linux folks will come along and fix them later.

AlotOfReading

C maintainers are not required to consider RfL currently as a compromise to minimize the burden.

taurknaut

how does this ecosystem accept any patches if any possible changes could make the system worse? I understand the implication about languages, I'm just struggling to understand how any changes are possible at all.

kreetx

Not a kernel developer, but I assume that it's done by having relatively stable/long lived APIs, and some form of deprecation process where both a new and old version coexist for a relatively long time.

null

[deleted]

kaladin-jasnah

I like Rust, but my worst experiences with Rust are interop with C. From this LWN article, some people seem very very stubborn against including Rust in Linux. As someone who really likes Rust, I must say its borrow-checker design, and other things like derive and proc-macros. Personally, if Rust people are willing to undergo the full burden of maintaining Rust in the kernel and not place undue burden on the C developers, I feel that it could be a good idea to include Rust. It seems a little petty to just block Rust as a blanket statement.

However, I must ask: is there a world in which interop didn't have to be so bad without hugely sacrificing memory safety? Is this a problem that Zig solves (I must be honest, I don't really know much about Zig)? What _is_ the better solution?

pornel

In Rust, unsafe (unchecked) C interop is almost automatic.

The hard part is in translating C code's high-level safety requirements into Rust APIs that enforce them. I'm talking about requirements that aren't expressed in the C syntax, but are arbitrary domain-specific rules defined in English by the C code's authors ("this function can be called only on Wednesdays"). These turn out to be hard, because they may not be precisely defined, and/or the conditions are complex and implementation-specific. That's less of language inteop problem, and more in creating formal definitions of informal documentation.

Having said that, there are a couple of things that Rust made harder for itself:

• Rust allows moving objects to a different address safely. C code often assumes objects never move and their addresses are unique and meaningful. If Rust had built-in support for immovable types, it wouldn't need Pin and macro hacks.

• Rust's reference types require strict immutability or strict pointer aliasing (exclusive access), while C allows memory to be mutated from anywhere, and pointers to const don't mean the data is immutable. This prevents Rust from using its nice safe reference and slice syntax on memory externally mutated in surprising/clever ways (by memory-mapped hardware, shared mem, MMU trickery).

lmm

> However, I must ask: is there a world in which interop didn't have to be so bad without hugely sacrificing memory safety?

You can't really make interop nicer than the lowest common denominator, and when one of the sides is C then that lowest common denominator is very low. Rust is one of very few languages that can potentially interop with memory-safe languages without having to completely buy into a common runtime - e.g. it's increasingly popular to write Python extensions in Rust and I believe there are now libraries for doing that without having to go via C - and when you have richer abstractions available on both sides of the line then you can make use of them. But to work with C you have to work like C, at least at the boundary.

flohofwoe

It's not "C - the language" but "C - the calling convention" that gets in the way of higher level languages. And it's actually also wrong to blame C alone, ABIs are mostly a convention between operating system and CPU vendors, C compilers have to play by those rules just as any other compiler that wants to output code that can call (efficiently) into operating system APIs (and we could just as well be stuck with Pascal calling conventions instead, which was used by 16-bit Windows versions).

lmm

> ABIs are mostly a convention between operating system and CPU vendors, C compilers have to play by those rules just as any other compiler that wants to output code that can call (efficiently) into operating system APIs

Yes and no. Unix has a very C-oriented ABI because it's written in and tied to C, and since Unix and C won other operating systems have felt pressure to make their ABI C-friendly.

> we could just as well be stuck with Pascal calling conventions instead, which was used by 16-bit Windows versions

If we'd gotten Pascal strings in the ABI that alone would have eliminated one major class of bugs.

flohofwoe

Zig has some features to make C interop easier (for instance string literals are both ptr/length-slices and zero-terminated), but in general the problems are quite similar to Rust's.

There is a subset of Zig types that is compatible with C APIs, but most higher-level Zig types (like slices, odd-width integer types, optionals, error unions...) can't be tunneled through or mapped to a C API...

The main thing may be that the Zig compiler doesn't track ownership/lifetimes like the Rust compiler does, so it doesn't matter that this information would be lost at the C-API barrier.

gspr

> I like Rust, but my worst experiences with Rust are interop with C.

Could you elaborate? I find the interop to be quite nice. I mean, obviously, interop between any two languages cannot ever be "better" than the least good language at any one thing.

Kostarrr

Zug does not attempt to solve memory safety. It aims to be a better C

flohofwoe

A bit more nuance please, Zig doesn't attempt to solve compile-time memory safety like Rust does, but at least it provides spatial runtime memory safety (but also doesn't have a builtin solution for temporal memory safety - except a debug allocator which catches most use-after-free attempts on the heap) - so tl;dr: Zig is much better than C or C++ when it comes to memory safety, but isn't watertight like Rust.

nikbackm

So similar in that regard to Herb Sutter's experimental Cpp2 perhaps?

ultimaweapon

Actually the interoperability is very good. C can directly call into Rust and Rust can directly call into C. Rust can construct any C type and can expose opaque pointers to C world.

3836293648

That's... not what the issue is, that is the bare minimum expectation.

gspr

But then again: for a language as bare-bones as C, what more is there really to a good FFI system?

magicalhippo

As a non-Rust dev, what is the issue with C interop?

eviks

> Already overworked kernel maintainers will have to find time to learn Rust well enough to manage it within their subsystems.

Well sure, but only if you explicitly reject any help and make up empty claims about impossibility of maintenance like Hellwig does

neerajsi

Seems like rfl people should do the work downstream like the rt folks did for a while. Maybe be an upstream for Android and the various corporate kernels.

Linus can decide whether to pull from their versions or not but basically maybe they should run a bit freer than having to deal with these maintainers.

A soft fork might clarify things like the old gcc fork did.

sidkshatriya

> Maybe be an upstream for Android and the various corporate kernels.

> A soft fork might clarify things like the old gcc fork did.

Nice idea but in practice there is absolutely no chance that this would be a successful strategy for those people in favor of Rust.

Being out of mainline tree would perpetually put Rust in the "future" (like Nuclear Fusion -- always just "20 years away"). Meanwhile Linux would continue to evolve in ways that could be very disruptive for Rust integration. For example, Rust interop needs to think very carefully about locks, memory order etc. Any change in the mainline kernel could really mess the assumptions made in the Rust fork. A year or two of evolution of the slightly independent evolution of the two branches may make it almost impossible to merge the two.

Only companies as large as Google could maintain the Android fork. The RFL team is small and I don't think large vendors would like to invest their time and energy on forks. Who would pick up and package the fork ? Red Hat ? Debian ? Arch ? They are already complaining about compilation and maintainability of Rust when it is in the mainline kernel. No chance that they start using the down stream rust kernel in their main kernels.

The only way Rust for Linux succeeds is if it has the blessing and push from Greg/Linus.

shmerl

Sounds like this needs a higher level decision to overrule that resistance. Those who refuse it are too late though, it was already decided to accept Rust in the kernel in general, so they should accommodate it otherwise such kind of attitude will only slow down the progress.

tayo42

The scenario where someone wants to drive by dump some code, then you reject it, then they offer to maintain it, kind of sucks. Ive had this happen in the past, at least in my experience you can't force someone to keep maintaining it. When they offer to maintain it, they look like such a great collaborator or team mate, you look like shit for saying no still. What happens is someone quits, gets reorged, your oncall and they aren't so your fixing and supporting it anyway. If they do stick around, now there is communication overhead from a part time maintainer

I get kernel development is a different environment then corporate programming. Im not 100% what the deal is with the Rust for Linux people. but in a vacuum, I am sympathetic to reasons like maintenance complexity for rejecting changes

estebank

> The scenario where someone wants to drive by dump some code, then you reject it, then they offer to maintain it, kind of sucks.

That's not what happened here.

This was a maintainer that was CCd on a Rust wrapper to a subsystem he maintains as a courtesy, immediately replying that that code shouldn't live in that subsystem and blocking the patch set from being merged by NAking, but the change was already not in the subsystem but rather the rust subdirectory, which gives the impression he didn't read the patch to begin with. After he was told this, he said that having multiple languages is a cancer that would kill the maintainability of Linux and he would block it any way he could.

That's a very different situation to the one you describe.

meltyness

  The caller takes ownership of the returned resources, i.e., will have the responsibility in calling `bindings::dma_free_attrs`.
Hm, doesn't this violate RAII? Does this need to be public?

lmm

> doesn't this violate RAII?

It's C, you don't get any RAII.

meltyness

Not the Rust abstraction. If mutation is needed, you'd write closures into the interface, or provider borrows. It's definitely weird to barf out ownership of half of the fields.

E: I guess it sort of depends whether the handle is Copy semantics or not.

E2: I guess they're correctly leaking the resource, but I question whether they should, protections like that are kind of the whole point of using Rust to begin with.

pjmlp

No, but you get defer via compiler extensions, and maybe in C2y as standard language feature.

flohofwoe

I seem to remember that the Linux kernel already uses __attribute__((cleanup) (which is basically GCC's non-standard defer).

Dagonfly

This is similar to `Box::into_raw` in Rust `std`. It destructs the RAII struct into a raw pointer. After that it's pretty much expected that you are responsible for cleanup.

meltyness

Seems like the preferred interface would be a purely functional block that provides the access.

Obviously forcing callers to free means adding lints and docs. Returning borrows leaves the likelihood of entering into explicit lifetimes hell and such in calling code.

A functional interface like (paraphrasing)

  // pub fn apply_op(&mut self, FnMut(&mut T, &bindings::dma_addr_t... ))
Keeps pandora inside the box.

Dagonfly

As most of the kernel is in C, they probably need a raw pointer quite regularly to pass it into existing C APIs.

Just like `Box::into_raw`, this method shouldn't be used in pure Rust code. It's only available for C FFI.

Tobu

The method is called `CoherentAllocation::into_parts`. And it takes self by value, which means the struct is consumed (this is implied by the into_ prefix). Of course you would either reconstruct the allocation or free the allocation yourself after this.

See Vec::into_raw_parts or Box::into_raw for an stdlib analogy.

LelouBil

Can someone explain what NAking means in this context ?

I didn't find any explanation online.

chambers

This reporting feels a bit slanted. The author implies the big blockers are human beings; specific people & interactions he's called out for seemingly stalling the project.

Personally, I'm curious if there's hard technical blockers. Like, if there's features that Linux (or Rust) needs which could incur a serious burden that no team can sustainably maintain. That kind of reporting— deep insights into technical trade-offs— would be much more interesting than a play-by-play of drama.

On a side note, there's one paper on Rust in Linux that's been recommended but I've not seen it deeply discussed yet https://www.usenix.org/conference/atc24/presentation/li-hong...

magicalhippo

The uncharitable take is that it's just job protection. That is current maintainer doesn't want to be replaced with some new Rust-writing folks.

A more charitable take is that the current maintainer is worried not about extra work now, but later when more things use Rust.

For example, say the Rust changes were merged and maintained by RfL folks. Then say NVIDIA replaces their current GPU drivers with a new Rust-based drivers.

Later a change to the DMA layer kernel code breaks the Rust code in a way that's not trivially fixable, and with that no NVIDIA GPU drivers.

Would the DMA changes still be allowed to be merged without any additional work by the current DMA layer maintainer?

This seems like something that could happen down the line, if the RfL project continues.

mjg59

> That is current maintainer doesn't want to be replaced with some new Rust-writing folks.

Almost anyone paying Christoph is not doing so because of his involvement in the DMA subsystem - he's got a sufficiently strong involvement in any number of core parts of the kernel that if he dropped all involvement in DMA he'd still have enough employment opportunities to spend as much of his time skiing as he wanted.

mustache_kimono

> Personally, I'm curious if there's hard technical blockers.

That LWN or the kernel devs are keeping secret? I would be amazed why, if Christoph Hellwig had technical blockers, he wouldn't raise them in the LKML, right now, of all times.

cyberax

The author has been professionally writing about the Linux kernel for close to 30 years. He's also maintaining the Linux kernel documentation.

> Personally, I'm curious if there's hard technical blockers.

Not really, apart from the sheer size of Linux.

null

[deleted]

matt3210

Putting the mappings in the driver that needs them has no effect on the maintainability of the kernel.

Putting them in the kernel has an effect if the maintainability of the kernel.

AlotOfReading

The kernel maintains in-tree drivers that break, so it does impact kernel maintenance. This isn't currently true for RfL, but in the case of a C driver anyone who wanted to go and make a breaking change would have to go and fix up breakages to merge.

Dagonfly

Nitpick: There are actually a handful Rust drivers in-tree, e.g. https://github.com/torvalds/linux/blob/master/drivers/net/ph...

Though, I think all of them are direct ports of existing drivers.

superb_dev

If it’s a common abstraction then wouldn’t it be more work to maintain the same piece of code in many different drivers?