RE: do_loop_readv_writev() not as described for drivers implementing only write()?

From: Mike McTernan
Date: Wed Mar 03 2010 - 08:51:34 EST


Hi,

> I would say that the libc enforces atomicity, but I have to dig deeper
for
> a real answer :).

If libc did do it, it would have to be fancy since readv() and writev()
are documented as being atomic between processes, as well as threads.

Still, all things being possible, I visually checked the glibc I'm
using.

glibc-2.8/sysdeps/unix/sysv/linux/writev.c:

ssize_t
__libc_writev (fd, vector, count)
int fd;
const struct iovec *vector;
int count;
{
if (SINGLE_THREAD_P)
return do_writev (fd, vector, count);

int oldtype = LIBC_CANCEL_ASYNC ();

ssize_t result = do_writev (fd, vector, count);

LIBC_CANCEL_RESET (oldtype);

return result;
}

So we end up in do_writev(), which is defined in the same file:

static ssize_t
do_writev (int fd, const struct iovec *vector, int count)
{
ssize_t bytes_written;

bytes_written = INLINE_SYSCALL (writev, 3, fd, CHECK_N (vector,
count), count);

if (bytes_written >= 0 || errno != EINVAL || count <= UIO_FASTIOV)
return bytes_written;

return __atomic_writev_replacement (fd, vector, count);
}

So assuming the syscall to writev() returns >= 0 (which is true for my
driver), I can't see locking being provided here unless
LIBC_CANCEL_ASYNC is doing something spectacular which I've overlooked.

The other observation from this is that the kernel could detect a case
where writev() is not supported by a driver (i.e. write() is implemented
but aio_write() is not) and return -ENOSYS instead of calling
do_loop_readv_writev(). This would allow the libc to use it's
replacement function - __atomic_writev_replacement() in this case.

How writev() correctly works is still a mystery to me at this point.

Regards,

Mike
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/