Overcoming the obvious difficulties, including "new" being a variable name in a library, there were no technical difficulties. (Had no one in history EVER written in C++ on linux before?)
The argument FOR C++ in the linux kernel is the same argument for using C++ anywhere else - object abstractions are useful. The project took far less time. The bugs were fewer. The code was of course more readable - because of the tremendous wealth of context that C++ provides thru strong typing.
C people argue its easier to use simple constructs, since they are instantly understandable. What is NOT understandable is WHY the code is putting an int into an array. Those types have no obvious meaning beyond the line of code they are in.
In an object-typed language, you CAN learn the scenery and rapidly become familiar with the object set. The argument above (write) is largely silly - right-click and GoToDefinition works in almost any IDE - yes there may be more than one possibility, the IDE will display them all. So navigation thru code is vastly simpler than grepping for names.
Anyway, in 18 months we had an Infiniband layer integrated into linux, not too hard. Had to invent fundamental kernel/user page primitives that were missing. Interesting to note: Windows had all the driver support we needed, didn't have to invent anything.
Even mathematics has different processes for the same operators on different types. If you see 'a * b' you should be able to assume that it's multiplying two variables, but if those two are real numbers it's different than if they're two matrices of real numbers, for example.
Implementing a Matrix class that overrides * to imlement matrix multiplication seems perfectly fine for me - It's just the same as implementing a Multiply(a, b) method. Just as someone who writes a Multiply method could in theory make it do anything, it is assumed by reading the word 'Multiply' that that is what it does. Just as someone who makes a Multiply() function that does something other than multiply is an idiot, so is someone who overrides operator * to do something other than multiply.
(Note that my point here is that for sane/good code, you normally can be sure that it does what it looks like -- for C++ just the same way as for C.)
My favorite part of the whole man page is the Linus quote:
"The thing that has always disturbed me about O_DIRECT is that the whole interface is
just stupid, and was probably designed by a deranged monkey on some serious mind-con-
trolling substances." -- Linus
But thats not a language failing. A language that actually prevents you from writing complicated interfaces is probably entirely unsuitable for... almost anything.* If you write to an NFS-mounted file and write() returns an error, does it mean the block wasn't written to the remote disk?
* If you write to a TCP socket and write() returns OK, does it mean data was received by your network peer?
* UNIX pipes: how many times is your block being copied before it reaches your peer's buffer supplied to read()?
And don't get me started on signals.
Really? write a block of data of size on bytes "bytes" on the file-pipe-network... pointed by the file descriptor "fd"??
It is extremely simple to understand, it makes a very simple thing, always right. I doubt you can make it simpler.
I have been using this all my life for NFS-mounted file, pipe, network or local socket... Never had any problems, and I have done very complex things.
Of course, in c++ you will use the very same function under a different calling, you can make it part of a class, whatever, but is going to use the same backend internally(because the OS only uses one), only that you can add a lot of abstraction(complexity) from c++ code.
Of course C++ could be clean, but the question is: what will happen if we make it into the kernel?. Linux thinks it won't work. I agree with him.