Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I've been using Linux for a while, but only since I started using "recent" distros (ie.: anything non-Debian) I have started having I/O problems with most of my USB devices. Basically when trying to write any nontrivial amount of data into them the lose connection and or reboot themselves. In the system log I observe these kinds of messages:

kernel: usb 1-7: reset high speed USB device using ehci_hcd and address 2
kernel: usb 2-1: device descriptor read/64, error -71
kernel: usb 2-4: new high speed USB device using ehci_hcd and address 13

This happens with both "pendrives" and USB-connected hard drives. I can not find any useful pattern to detecting which devices will bork and which won't except perhaps size - I've never had 1 or 2 GB pendrives bork with these messages (but then again, no one sells those anymore).

When those errors happen, pending reads to drive get locked, also locking whatever program was doing the work until I physically unplug the drive. Of course, after I reconnect the drive, I find files or partitions corrupted, thus losing me a lot of work and forcing me to some other work.

Researching around I've found links in places such as the ArchWiki or the SUSE Forums or even this very community indicating that the culprit is the default value of the USB tree attribute max_sectors which specifies how much can be read or written to a USB drive in one go. Any more than what the drive supports and the device resets or crashes. I've found mentions that the value is too high in Linux (240) compared to old kernels or Windows installs (128 or even 64) which of course don't face this problem.

Since I value data integrity more than "blinding" speed (and I hope most people do!) I'd like to somehow change the max_sectors value for "any" USB storage device where the meaning of "any" could be ample enough that I can avoid having to write custom commands or rules for the most part. Unfortunately, look where I try I haven't been able to find any configuration line or kernel boot option that can change this value (unlike, say, USB autosuspend).

What have I missed or what can I do next? I know that I can write something like the following in a more or less automatic using the udev system, something like this:

SUBSYSTEMS=="usb", DRIVERS=="usb-storage", ATTRS{manufacturer}=="Some Company", ATTRS{serial}=="xxxxxxxxxx", ATTRS{max_sectors}=="240", ATTRS{max_sectors}="128"

And then reload or reboot the service, but I have not been able to find a generic enough udev rule that would fit as many devices as possible (so long as they are connected via a USB plug). I have the understanding that I can write more specific rules for devices whose max_sectors I want to restore or preserve, but here I'm only interested in a sort of wildcard.

I have tried wildcard in some attributes, such as ATTRS{manufacturer}=="* " to no avail.

What is a generic udev rule that can match me as many USB-plugged devices as possible? Is this even the "correct" way of handling this issue via software? (unloading USB 2.0 modules -as eg.: Ubuntu Forums suggest- seems to be not an option, as at least Fedora seems to have them integrated to the kernel).


EDIT: As suggested by frostschutz, I'm using RUN+= to set up the attribute, which actually works (unlike using ATTR=). That's half a solution. I've been able to create a udev rule that matches pretty much everything, but I fear it matches too much.

SUBSYSTEMS=="usb", DRIVERS=="usb-storage",  \
 RUN+="/bin/sh -c 'echo 64 > /sys/block/%k/device/max_sectors'"

The problem with this rule is that it'll set max_sectors for everything, including devices that have a lower value than 64. I've tried to make it more specific:

SUBSYSTEMS=="usb", DRIVERS=="usb-storage", ATTRS{max_sectors}=="240", \
 RUN+="/bin/sh -c 'echo 64 > /sys/block/%k/device/max_sectors'"

But this doesn't work. I think I'm using the correct scope for udev rules (use attributes from one part of the tree and from one parent). What am I doing wrong?

EDIT2: Accepted the answer below. As it turns out, RUN+= does the trick, whereas using ATTRS{…}= for some reason doesn't. Also, the reason why I couldn't get to make a generic rule work was because I had misunderstood from the udev manpage. A rule must have at most attribute from one parent - that means if I want to use two sections, the second one must be the actual dvice. These two work mostly perfectly:

SUBSYSTEM=="scsi", ATTRS{max_sectors}=="240", \
 RUN+="/bin/sh -c 'echo 64 > /sys/block/%k/device/max_sectors'"

(note the singular for the attribute, first attribute is from the actual USB device and second one from a singular ancestor at the device tree)

SUBSYSTEMS=="usb", DRIVERS=="usb-storage", ATTRS{max_sectors}=="240", \
 RUN+="/bin/sh -c 'echo 64 > /sys/block/%k/device/max_sectors'"

(this one uses two attributes from the same ancestor at the device tree)

share|improve this question
    
In Fedora, using largeish pendrives (up to 16GiB) and a 350GiB hard disk in an enclosure have never given me such problems. Check that the hardware (pendrives, USB port) are OK (might as well use a "non-recent", i.e., Debian ;-) LiveCD. –  vonbrand Mar 12 '13 at 23:47
    
Does the max_sectors actually help? No point finding a way to automate this setting if it does not actually resolve the issue. –  frostschutz Mar 13 '13 at 0:25
    
Changing max_sectors manually for every device I plug does help a lot hence I'm trying to genericize the solution. Also yes, live CDs do work wonders! –  Luis Machuca Mar 13 '13 at 0:41

1 Answer 1

up vote 0 down vote accepted

Sounds like a hardware issue you should go and fix. Powered USB Hub (if it's a power supply related issue), different USB cables, no front panel, a different USB controller (addon card), ...

If it stays unreliable, an option would be using the sync mount option for USB media. That way no caching is done whatsoever, but you will see a big impact on performance as a result. Also (for flash drives) a possibility of extra writes (like if you create a file and immediately delete it, with async it would never be written in the first place, whereas sync always writes everything immediately).

share|improve this answer
    
Changing the hardware is not really an option, at least for the laptops I use, and what's more I sometimes use these systems on the field due to work, so eg.: no external power sources. Hence why I'm looking for a software solution. Generically adding a sync option to the automounts seems a sensible option, aI don't really bother about speed loss; but then again how do I write a generic rule that does that? –  Luis Machuca Mar 13 '13 at 0:38
    
External power source could be as simple as another battery pack. The ones usually used for charging phones or MP3 players on the go. Also, Y-USB-Cable to use an extra USB port for power. On the off chance that a single port doesn't give enough juice. –  frostschutz Mar 13 '13 at 5:13
1  
For the udev rule, if all else fails you can use BUS=="scsi", RUN+="/bin/bash -c 'echo 64 > /sys/block/%k/device/max_sectors'" or something. Attributes would be alot nicer of course, if that works at all. For automounting, no idea, not using that anywhere, good old mount-it-yourself for me... sorry. Search/Make a separate question about it? –  frostschutz Mar 13 '13 at 5:17
    
Using RUN+= instead of ATTR works wonders as the value is actually written to the tree. Thanks. Now I've fell into the problem of writing an overgeneric rule, see updated edit. –  Luis Machuca Mar 13 '13 at 13:54
    
It's possible that you can see some attributes only for a scsi subsystem rule. But if you're going to do a run anyway, you can just as well outsource your checks to there [ $(<max_size) == "240" ] && echo .... (Somehow this question turned into chaos xD) –  frostschutz Mar 13 '13 at 17:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.