EBUSY failure from write() when writing large blocks (>256k) of data...
Linux - KernelThis forum is for all discussion relating to the Linux kernel.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
EBUSY failure from write() when writing large blocks (>256k) of data...
I suspect there is a simple answer to this and that it is just a problem of my own ignorance... so I've come here looking to correct that.
I am using the mhvtl Virtual Tape Library driver under Fedora 8 (kernel 2.6.23.9). (mhvtl, for those who aren't familiar with it, lets you emulate a virtual tape library... i.e. a set of tape drives with autoloaders, etc. using files on one of your hard disks.) I've downloaded the sources, built and loaded the kernel module and user-space drivers, and gotten the basics working fine. My defined 'tape drives' show up under /dev and seem to function, for the most part, like real tape drives.
But one problem has me stumped... if I try to write more than about 256K in a single write() call, I get a failure status with errno = EBUSY. Calls to write anything <= 256k seem to work fine.
I dug into the code... both the kernel module (which looks like it accomplishes all its reads/writes via the ioctl file_operation), and the user-mode Virtual Tape driver... but from the debugging output I put into those guys, it looks like the 300k write call never even gets that far... it's getting filtered out somewhere before it gets to the mhvtl drivers. I'm just guessing here that some other driver earlier in the call chain is returning the failure code.
This same test program works fine, though, when writing to a real Tape drive. So there must be some way of letting the intermediate driver know that the mhvtl driver can handle a larger write. I just haven't been able to find out what that is. I don't see any 256K limit anywhere in the mhvtl driver code. (Perhaps 256k is a default value?)
So that's the crux of my problem, and the reason I come to you folks. Would anyone happen to have experience with this, and could you offer any suggestions on where to look?
I'm just guessing here that some other driver earlier in the call chain is returning the failure code.
Did you try running "strace" on your application to see exactly what function fails?
"EBUSY" is not in the list of normal "errno" values for "write". However, from the man page for WRITE(2): "Other errors may occur, depending on the object connected to fd."
You might also try grepping for "EBUSY" in the driver and the library.
Did you try running "strace" on your application to see exactly what function fails?
Yep. strace says the write() call failed with an errno of EBUSY.
Quote:
You might also try grepping for "EBUSY" in the driver and the library.
I had that thought as well. EBUSY doesn't appear anywhere in any of the driver code.
So I got 'determined' and went in and put syslog() (or printk for the kernal driver) calls in almost every function in the kernel mode source file and in the user-mode driver. Rebuilt, reloaded the drivers, and ran the test program again. I could see my new log calls for the shorter writes, but not for the 300k write. It's as if my test program had simply not made that call... though strace verified that it had.
I've also been trading e-mails with Mark Harvey, the fellow developing mhvtl... he's confirmed the same behavior on Ubuntu. Curious, but at least it's consistent. :-)
I've also been trading e-mails with Mark Harvey, the fellow developing mhvtl...
The only thing I found that might be related is that if kzalloc fails in the SCSI tape driver (drivers/scsi/st.c) it returns EBUSY if kzalloc does not fail because it was interrupted:
To copy from user space to kernel space, a driver needs to use copy_from_user. If some part of the kernel or some other driver is trying to allocate the target buffer on-the-fly, the allocation of 256KB might fail, and the code might return EBUSY. This may seem strange because ENOMEM would appear to be the more appropriate choice. However, not every line of the kernel makes sense to the casual observer.
Are you trying to do back-to-back 256KB writes? If so, if you are not opening the device with O_SYNC, you may be returning early from write (i.e. before it is finished). This might cause the next write to fail with EBUSY.
Last edited by David1357; 08-25-2009 at 10:38 AM.
Reason: Fixed a typo
The only thing I found that might be related is that if kzalloc fails in the SCSI tape driver (drivers/scsi/st.c) it returns EBUSY if kzalloc does not fail because it was interrupted:
. . .
Are you trying to do back-to-back 256KB writes? If so, if you are not opening the device with O_SYNC, you may be returning early from write (i.e. before it is finished). This might cause the next write to fail with EBUSY.
I suspect it may not be this function itself (since that call seems to be allocating an st_request*), but it may be the equivalent function that tries to allocate the buffer to hold the data to be written. It probably defaults to 256k and has a bug in the logic for handling requests that take more than one of its default buffers.
Re: doing back-to-back writes, yes, my test program is doing that. But it seems to be the size of the write request that consistently causes the failure, and not the frequency. I can do a whole bunch of smaller writes with no EBUSY failure, but even *one* write of a block larger than 256k will cause a failure.
I'm still poking at it a bit, but have been pulled off to fight other 'fires', as it were, so this is a background task. (Isn't that always the way it goes?) We've set the Blocking size in our app down to 256k, which lets us use vtl for testing... so I'm really just chasing this one now to try and improve vtl itself.
Anyway, thanks for the feedback. That's a good lead on where to look.
Mark Harvey, the mhvtl maintainer, tracked it down. The mhvtl driver was specifying an sg_tablesize of 64 in its scsi_host_template structure when it called scsi_host_alloc(). Apparently, this tells the SCSI driver to allocate 64 pages, at 4096k each on our system, for data transfer.
He says he'll be raising that limit in the next mhvtl release.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.