Here's a better explanation as to why I initially mixed lock_user() and copy_to_user():
On Tue, 2007-11-06 at 01:05 +0000, Paul Brook wrote: > > access_ok() and lock_user() perform essential functions. lock_user(), > > however, isn't directly comparable to how the kernel operates and should > > therefore be encapsulated inside more typical kernel functions such as > > {get,put}_user(), copy_{to,from}_user() and the like. access_ok() and > > lock_user() also have overhead and should therefore be used with the > > largest memory hunks possible (e.g.: they should be used with an entire > > structure - not with each individual data member of the structure). > > That is why __{get,put}_user() exist: for copying the individual data > > members of a structure once the *entire* structure has had access > > checked and the address translation is performed. > > > I don't think there's an appropriate way > > to eliminate either {lock,unlock}_user() or {get,put}_user() and keep > > comparable coding semantics to the kernel. > > Your argument seems inconsistent to me. The kernel doesn't have lock_user at > all, so how can using it be consistent with kernel code? See your comment below about how qemu differs from the kernel. > There are two different strategies for accessing user data. Either: > > - Use a copying interface. i.e. get_user (for single values) or > copy_from_user (for blocks/structures). > - Use a locking interface. i.e. lock_user. > > Personally I like the locking interface as it allows a zero-copy > implementation. However the kernel uses a copying interface, and my > understanding is that other qemu maintainers also prefer the copying > interface. The "zero-copy" nature of lock_user() is why I mixed the two. lock_user() was pushed down inside of wrapper functions. External to the wrapper functions the code was very comparable to the kernel code. It was the best of both worlds. > Part of the problem may be that linux assumes that both kernel and userspace > pointers can be represented by the compiler. This allows it to do address > arithmetic and take the address of members of pointers to userspace > structures. qemu can not do this. It is precisely this difference that I felt that a minor deviation was acceptable: mixing lock_user() with copy_to_user(). My solution had the zero-copy capability while making high-level syscall wrapper code very comparable to kernel code. In the end I'd just rather code it your way and move on then argue why I think my way is better - just keep in mind that there were intelligent decisions behind why I did it the way I did it - it wasn't haphazard (although I did send a few half-baked patches that weren't correct to the list - I can be a bonehead in other ways 8-)).