udev rule for USB flash drive

For some requirements I needed to call a script whenever there is a flash drive inserted into my Arch Linux system, So got to know udev is the better option for this. So wrote small udev rule to achieve this.  One specific requirement I had is, the script should be called only for partion devices like sda1, sda2 etc not for sda.

Lets start with the device info:

$ udevadm info -a /dev/sdb1

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

looking at device ‘/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host27/target27:0:0/27:0:0:0/block/sdb/sdb1’:
KERNEL==”sdb1″
SUBSYSTEM==”block”
DRIVER==””
ATTR{alignment_offset}==”0″
ATTR{discard_alignment}==”0″
ATTR{inflight}==”       0        0″
ATTR{partition}==”1″
ATTR{ro}==”0″
ATTR{size}==”2097152″
ATTR{start}==”2048″
ATTR{stat}==”      60        0     4160      580        0        0        0        0        0      480      580″

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host27/target27:0:0/27:0:0:0/block/sdb’:
KERNELS==”sdb”
SUBSYSTEMS==”block”
DRIVERS==””
ATTRS{alignment_offset}==”0″
ATTRS{capability}==”51″
ATTRS{discard_alignment}==”0″
ATTRS{events}==”media_change”
ATTRS{events_async}==””
ATTRS{events_poll_msecs}==”-1″
ATTRS{ext_range}==”256″
ATTRS{inflight}==”       0        0″
ATTRS{range}==”16″
ATTRS{removable}==”1″
ATTRS{ro}==”0″
ATTRS{size}==”7837696″
ATTRS{stat}==”     279        0    18680     2540        0        0        0        0        0      643     2540″

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host27/target27:0:0/27:0:0:0’:
KERNELS==”27:0:0:0″
SUBSYSTEMS==”scsi”
DRIVERS==”sd”
ATTRS{device_blocked}==”0″
ATTRS{device_busy}==”0″
ATTRS{dh_state}==”detached”
ATTRS{eh_timeout}==”10″
ATTRS{evt_capacity_change_reported}==”0″
ATTRS{evt_inquiry_change_reported}==”0″
ATTRS{evt_lun_change_reported}==”0″
ATTRS{evt_media_change}==”0″
ATTRS{evt_mode_parameter_change_reported}==”0″
ATTRS{evt_soft_threshold_reached}==”0″
ATTRS{inquiry}==””
ATTRS{iocounterbits}==”32″
ATTRS{iodone_cnt}==”0x27d”
ATTRS{ioerr_cnt}==”0x1″
ATTRS{iorequest_cnt}==”0x27d”
ATTRS{max_sectors}==”240″
ATTRS{model}==”Cruzer Blade    ”
ATTRS{queue_depth}==”1″
ATTRS{queue_type}==”none”
ATTRS{rev}==”1.00″
ATTRS{scsi_level}==”3″
ATTRS{state}==”running”
ATTRS{timeout}==”30″
ATTRS{type}==”0″
ATTRS{vendor}==”SanDisk ”

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host27/target27:0:0’:
KERNELS==”target27:0:0″
SUBSYSTEMS==”scsi”
DRIVERS==””

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host27’:
KERNELS==”host27″
SUBSYSTEMS==”scsi”
DRIVERS==””

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0’:
KERNELS==”5-1:1.0″
SUBSYSTEMS==”usb”
DRIVERS==”usb-storage”
ATTRS{authorized}==”1″
ATTRS{bAlternateSetting}==” 0″
ATTRS{bInterfaceClass}==”08″
ATTRS{bInterfaceNumber}==”00″
ATTRS{bInterfaceProtocol}==”50″
ATTRS{bInterfaceSubClass}==”06″
ATTRS{bNumEndpoints}==”02″
ATTRS{supports_autosuspend}==”1″

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb5/5-1’:
KERNELS==”5-1″
SUBSYSTEMS==”usb”
DRIVERS==”usb”
ATTRS{authorized}==”1″
ATTRS{avoid_reset_quirk}==”0″
ATTRS{bConfigurationValue}==”1″
ATTRS{bDeviceClass}==”00″
ATTRS{bDeviceProtocol}==”00″
ATTRS{bDeviceSubClass}==”00″
ATTRS{bMaxPacketSize0}==”64″
ATTRS{bMaxPower}==”200mA”
ATTRS{bNumConfigurations}==”1″
ATTRS{bNumInterfaces}==” 1″
ATTRS{bcdDevice}==”0100″
ATTRS{bmAttributes}==”80″
ATTRS{busnum}==”5″
ATTRS{configuration}==””
ATTRS{devnum}==”23″
ATTRS{devpath}==”1″
ATTRS{idProduct}==”5567″
ATTRS{idVendor}==”0781″
ATTRS{ltm_capable}==”no”
ATTRS{manufacturer}==”SanDisk”
ATTRS{maxchild}==”0″
ATTRS{product}==”Cruzer Blade”
ATTRS{quirks}==”0x0″
ATTRS{removable}==”unknown”
ATTRS{serial}==”200517373009D12387AD”
ATTRS{speed}==”480″
ATTRS{urbnum}==”1610″
ATTRS{version}==” 2.00″

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb5’:
KERNELS==”usb5″
SUBSYSTEMS==”usb”
DRIVERS==”usb”
ATTRS{authorized}==”1″
ATTRS{authorized_default}==”1″
ATTRS{avoid_reset_quirk}==”0″
ATTRS{bConfigurationValue}==”1″
ATTRS{bDeviceClass}==”09″
ATTRS{bDeviceProtocol}==”00″
ATTRS{bDeviceSubClass}==”00″
ATTRS{bMaxPacketSize0}==”64″
ATTRS{bMaxPower}==”0mA”
ATTRS{bNumConfigurations}==”1″
ATTRS{bNumInterfaces}==” 1″
ATTRS{bcdDevice}==”0404″
ATTRS{bmAttributes}==”e0″
ATTRS{busnum}==”5″
ATTRS{configuration}==””
ATTRS{devnum}==”1″
ATTRS{devpath}==”0″
ATTRS{idProduct}==”0002″
ATTRS{idVendor}==”1d6b”
ATTRS{interface_authorized_default}==”1″
ATTRS{ltm_capable}==”no”
ATTRS{manufacturer}==”Linux 4.4.1-2-ARCH ehci_hcd”
ATTRS{maxchild}==”6″
ATTRS{product}==”EHCI Host Controller”
ATTRS{quirks}==”0x0″
ATTRS{removable}==”unknown”
ATTRS{serial}==”0000:00:1d.7″
ATTRS{speed}==”480″
ATTRS{urbnum}==”534″
ATTRS{version}==” 2.00″

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7’:
KERNELS==”0000:00:1d.7″
SUBSYSTEMS==”pci”
DRIVERS==”ehci-pci”
ATTRS{broken_parity_status}==”0″
ATTRS{class}==”0x0c0320″
ATTRS{companion}==””
ATTRS{consistent_dma_mask_bits}==”32″
ATTRS{d3cold_allowed}==”1″
ATTRS{device}==”0x293a”
ATTRS{dma_mask_bits}==”32″
ATTRS{driver_override}==”(null)”
ATTRS{enable}==”1″
ATTRS{irq}==”23″
ATTRS{local_cpulist}==”0-1″
ATTRS{local_cpus}==”3″
ATTRS{msi_bus}==”1″
ATTRS{numa_node}==”-1″
ATTRS{subsystem_device}==”0x02be”
ATTRS{subsystem_vendor}==”0x1028″
ATTRS{uframe_periodic_max}==”100″
ATTRS{vendor}==”0x8086″

looking at parent device ‘/devices/pci0000:00’:
KERNELS==”pci0000:00″
SUBSYSTEMS==””
DRIVERS==””
/div>

 

When I execute the command “udevadm info -a /dev/sdb1” , it displays above information.

based on that, have written a small rule in  “/etc/udev/rules.d/jesh.rules” file and reload the udev daemon using command “sudo udevadm control –reload-rules” to apply the change rules in the same boot. I have added one line mentioned below in my rule file.

ACTION==”add”, SUBSYSTEM==”block”, SUBSYSTEMS==”usb”, KERNEL==”sd[a-z]*”, ATTR{partition}==”[1-4]”,RUN+=”/home/jeshwanth/junk/udev.sh %k”

ACTION – this key is to mention whether adding device or removing device from the system. In above rule I have mentioned “add”, so this rule valid for when the USB is inserted into the system, not when removed.

SUBSYSTEM -Driver subsystem, like block, char etc. Here USB flash drive is a block device.

SUBSYSTEMS – subsystem information like usb, pci etc.

KERNEL – this is the device node which is goinf to create, we can mention in regular expression format to match vast numbr of names. like mentioned above it matches sda to sdz and sda1, sda2 etc.

ATTR{partition} – Here is the interesting thing, for my requirement I don’t want to execute my script for nodes which is not a partition type, so considering sdb, sdb1, sdb2, sdb3 etc. sdb is not a partition node, but sdb1, sdb2, sdb2 are. So, I am executing script only for sdb1, sdb2, sdb3.

RUN+ – path for script  or command to execute.

To run systemd service in udev rules:

ACTION==”add”, SUBSYSTEM==”block”, SUBSYSTEMS==”usb”, KERNEL==”sd[a-z]*”, ATTR{partition}==”[1-4]”, TAG+=”systemd”, ENV{SYSTEMD_WANTS}=”usb_attach.service”

TAG+ – is to tag the udev device to systemd.

ENV{SYSTEMD_WANTS} – mention the service needs to be started for rhis rule.

 

References: 1 , 2