Difference between revisions of "USB storage devices"

From ArchWiki
Jump to: navigation, search
m (Mount to /media: merged into udev#Udisks)
m (Poor copy performance to USB pendrive: added link, merge request, expansion flag)
Line 230: Line 230:
  
 
===== Poor copy performance to USB pendrive  =====
 
===== Poor copy performance to USB pendrive  =====
 +
 +
{{Merge|Maximizing Performance}}
 +
 +
{{Expansion|provide better description, or at least some reference}}
  
 
If you experienced slow copy speed to pendrive (mainly in KDE), then append these three lines in a [[systemd]] tmpfile:
 
If you experienced slow copy speed to pendrive (mainly in KDE), then append these three lines in a [[systemd]] tmpfile:
 +
 
{{hc|/etc/tmpfiles.d/local.conf|
 
{{hc|/etc/tmpfiles.d/local.conf|
 
w /sys/kernel/mm/transparent_hugepage/enabled - - - - madvise
 
w /sys/kernel/mm/transparent_hugepage/enabled - - - - madvise
Line 237: Line 242:
 
w /sys/kernel/mm/transparent_hugepage/khugepaged/defrag - - - - 0
 
w /sys/kernel/mm/transparent_hugepage/khugepaged/defrag - - - - 0
 
}}
 
}}
And paste these at the end of your {{ic|/etc/sysctl.conf}}:
+
 
kernel.shmmax=134217728
+
See also [[Maximizing Performance#Tuning kernel parameters]].
vm.dirty_background_bytes = 4194304
+
vm.dirty_bytes = 4194304
+
Reboot. This also reduces the freezes of the KDE's panel.
+

Revision as of 09:39, 20 August 2013

This document describes how to use the popular USB memory sticks with Linux. However, it is also valid for other devices such as digital cameras that act as if they were just a USB storage device.

Mounting USB devices

If you have an up-to-date system with the standard Arch kernel and a modern Desktop environment your device should just show up on your desktop, with no need to open a console.

Otherwise see sections below.

Auto-mounting with udev

See Udev:Auto mounting USB devices.

A lightweight solution to automount drives using udev, for single-user systems, is the following: create a file named /etc/udev/rules.d/automount.rules with the following content:

# ignore sda*
KERNEL!="sd[b-z]*", GOTO="end"

# run the script
ACTION=="add", ENV{ID_BUS}=="usb", ENV{DEVTYPE}=="partition", RUN+="domount %N"

# exit
LABEL="end"

and a file (executable by root) named /usr/lib/udev/domount with (set the variables on top to the correct values):

#!/bin/sh

#edit the following variables to suit your needs
MYUID=1000              # your user uid
MYGID=100               # your user gid
MYLOGIN=al              # your login
TERM=lxterminal         # your terminal emulator
MYSHELL=zsh             # your shell
export DISPLAY=:0       # your X display


TMPFILE=/run/automount.$RANDOM
DIR=$(grep -v '#' /etc/fstab | grep $* | awk '{print $2;}')
if [ -z "$DIR" ]; then
    LABEL=$(lsblk -no LABEL $*)
    if [ -z "$LABEL" ]; then
        UUID=$(lsblk -no UUID $*)
        if [ -z "$UUID" ]; then
            DIR=/run/media/"unknown"
        else
            DIR=/run/media/"$UUID"
        fi
    else
        DIR=/run/media/"$LABEL"
    fi
fi
mkdir -p $DIR

cat > $TMPFILE << EOF
#!/bin/sh
echo "$* was mounted on $DIR. "
cd $DIR
$MYSHELL
EOF
chmod a+x $TMPFILE

/bin/mount -o uid=$MYUID,gid=$MYGID $* $DIR
su $MYLOGIN -c "$TERM -t 'Terminal - $* mounted on $DIR' -e $TMPFILE"
/bin/umount $DIR

sleep 1; rm -f $TMPFILE

When a drive is inserted, it will be mounted, and a Terminal will pop-up. To umount the device, simply press Control+D in the terminal window. The mountpoint is looked for in /etc/fstab or, if absent, generated from the label of the partition.

If the terminal doesn't appear as expected, that may because wrong options are used. For example, in XFCE4, we use "Terminal -T title -e script-file instead"

Auto-mounting with udev and systemd

The above solution does not work, since the RUN directive is for only short processes, and udev enforces this; Scripts will be killed shortly after starting. Instead, the following solution based on the previous one uses systemd, udev and screen to create a more elegant solution.

First, we create a systemd service template (/etc/systemd/system/automount@.service):

[Unit]
Description=Automount removable storage

[Service]
Type=forking
ExecStart=/usr/lib/udev/domount %I

We also create a udev rule in /etc/udev/rules.d/automount.rules very similar to the previous solution.

# ignore sda*
KERNEL!="sd[b-z]*", GOTO="end"
# Also allow SD cards
KERNEL=="mmcblk[0-9]p[0-9]", GOTO="MMC"

# USB: run the script
LABEL="USB"
ACTION=="add", ENV{ID_BUS}=="usb", ENV{DEVTYPE}=="partition", RUN+="/usr/bin/systemctl start automount@%N.service", GOTO="end"
ACTION=="add", ENV{ID_BUS}=="ata", ENV{DEVTYPE}=="partition", RUN+="/usr/bin/systemctl start automount@%N.service", GOTO="end"

LABEL="MMC"
ACTION=="add", ENV{DEVTYPE}=="partition", RUN+="/usr/bin/systemctl start automount@%N.service", GOTO="end"

# exit
LABEL="end"

The juice of the solution is placed in /usr/lib/udev/domount:

#!/bin/sh

#edit the following variables to suit your needs
MYUID=1000              # your user uid
MYGID=100               # your user gid
MYLOGIN="ME"            # your login


USERSCRIPT="/usr/lib/udev/domount_user";

BASE='/media'
DIR=`basename $*`;
i=0;
while [ -d "$BASE/$DIR" ]; do
  DIR="`basename $*`.$i";
  i=$((i+1));
done

mkdir -p "$BASE/$DIR" && /bin/mount -o uid=$MYUID,gid=$MYGID "$*" "$BASE/$DIR"

if [ -z "`su $MYLOGIN -c 'screen -ls | grep AUTOMOUNT'`" ]; then
  su $MYLOGIN -c "screen -dm -S AUTOMOUNT -t $DIR $USERSCRIPT $* $BASE $DIR";
  exit;
fi
su $MYLOGIN -c "screen -S AUTOMOUNT -X screen -t $DIR $USERSCRIPT $* $BASE $DIR";

and in /usr/lib/udev/domount_user:

#!/bin/sh
DEV="$1";
BASE="$2";
DIR="$3";

echo "$DEV mounted on $BASE/$DIR"
echo "Contents:"
ls --color=auto "$BASE/$DIR"
echo -e "\n------------------------------------\nExit shell to unmount when finished.";
while true; do
  d=$HOME;
  cd $BASE/$DIR
  bash
  cd $dir;

  echo "------------------------------------"
  lsof | grep $BASE/$DIR;
  if [ $? -eq 1 ]; then
    break;
  else
    echo "------------------------------------";
    echo "The above processes will block the unmount. Please end them.";
  fi
done

sudo /bin/umount "$BASE/$DIR" && sudo rmdir "$BASE/$DIR";

To access the screen session which controls the mounted partitions, simply run

$ screen -d -r AUTOMOUNT

I would suggest putting this in a command key shortcut, for example with xbindkeys to run in a terminal.

Manual mounting

Note: Before you decide that Arch Linux does not mount your USB device, be sure to check all available ports. Some ports might not share the same controller, preventing you from mounting the device.

Getting a kernel that supports usb_storage

If you do not use a custom-made kernel, you are ready to go, for all Arch Linux stock kernels are properly configured. If you do use a custom-made kernel, ensure it is compiled with SCSI-Support, SCSI-Disk-Support and usb_storage. If you use the latest udev, you may just plug your device in and the system will automatically load all necessary kernel modules. Older releases of udev would need hotplug installed too. Otherwise, you can do the same thing manually:

# modprobe usb-storage
# modprobe sd_mod      (only for non SCSI kernels)

Identifying device

First thing one need to access storage device is it's identifier assigned by kernel. See fstab#Identifying filesystems for details.

Tip: To see which device is your USB device, you can compare the output of lsblk -f (explained in the linked article) when the USB device is connected and when it is unconnected.

Mounting USB memory

You need to create the directory in which you are going to mount the device:

# mkdir /mnt/usbstick
As root

Mount the device as root with this command (do not forget to replace device_node by the path you found):

# mount device_node /mnt/usbstick

or

# mount -U UUID /mnt/usbstick

If mount does not recognize the format of the device you can try to use the -t argument, see man mount for details.

Note: If mounting your stick does not work you can try to repartition it, see Format a device.
As normal user with mount

If you want non-root users to be able to write to the USB stick, you can issue the following command:

# mount -o gid=users,fmask=113,dmask=002 /dev/sda1 /mnt/usbstick
As normal user with fstab

If you want non-root users to be able to mount a USB memory stick via fstab, add the following line to your /etc/fstab file:

/dev/sda1 /mnt/usbstick vfat user,noauto,noatime,flush 0 0

or better:

UUID=E8F1-5438 /mnt/usbstick vfat user,noauto,noatime,flush 0 0

(see description of user and other options in the main article)

Note: Where /dev/sda1 is replaced with the path to your own usbstick, see Mounting USB memory.

Now, any user can mount it with:

$ mount /mnt/usbstick

And unmount it with:

$ umount /mnt/usbstick
Poor copy performance to USB pendrive

Merge-arrows-2.pngThis article or section is a candidate for merging with Maximizing Performance.Merge-arrows-2.png

Notes: please use the second argument of the template to provide more detailed indications. (Discuss in Talk:USB storage devices#)

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: provide better description, or at least some reference (Discuss in Talk:USB storage devices#)

If you experienced slow copy speed to pendrive (mainly in KDE), then append these three lines in a systemd tmpfile:

/etc/tmpfiles.d/local.conf
w /sys/kernel/mm/transparent_hugepage/enabled - - - - madvise
w /sys/kernel/mm/transparent_hugepage/defrag - - - - madvise
w /sys/kernel/mm/transparent_hugepage/khugepaged/defrag - - - - 0

See also Maximizing Performance#Tuning kernel parameters.