요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. _usb-persist:
USB device persistence during system suspend
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Author: Alan Stern <[email protected]>
:Date: September 2, 2006 (Updated February 25, 2008)
What is the problem?
====================
According to the USB specification, when a USB bus is suspended the
bus must continue to supply suspend current (around 1-5 mA). This
is so that devices can maintain their internal state and hubs can
detect connect-change events (devices being plugged in or unplugged).
The technical term is "power session".
If a USB device's power session is interrupted then the system is
required to behave as though the device has been unplugged. It's a
conservative approach; in the absence of suspend current the computer
has no way to know what has actually happened. Perhaps the same
device is still attached or perhaps it was removed and a different
device plugged into the port. The system must assume the worst.
By default, Linux behaves according to the spec. If a USB host
controller loses power during a system suspend, then when the system
wakes up all the devices attached to that controller are treated as
though they had disconnected. This is always safe and it is the
"officially correct" thing to do.
For many sorts of devices this behavior doesn't matter in the least.
If the kernel wants to believe that your USB keyboard was unplugged
while the system was asleep and a new keyboard was plugged in when the
system woke up, who cares? It'll still work the same when you type on
it.
Unfortunately problems _can_ arise, particularly with mass-storage
devices. The effect is exactly the same as if the device really had
been unplugged while the system was suspended. If you had a mounted
filesystem on the device, you're out of luck -- everything in that
filesystem is now inaccessible. This is especially annoying if your
root filesystem was located on the device, since your system will
instantly crash.
Loss of power isn't the only mechanism to worry about. Anything that
interrupts a power session will have the same effect. For example,
even though suspend current may have been maintained while the system
was asleep, on many systems during the initial stages of wakeup the
firmware (i.e., the BIOS) resets the motherboard's USB host
controllers. Result: all the power sessions are destroyed and again
it's as though you had unplugged all the USB devices. Yes, it's
entirely the BIOS's fault, but that doesn't do _you_ any good unless
you can convince the BIOS supplier to fix the problem (lots of luck!).
On many systems the USB host controllers will get reset after a
suspend-to-RAM. On almost all systems, no suspend current is
available during hibernation (also known as swsusp or suspend-to-disk).
You can check the kernel log after resuming to see if either of these
has happened; look for lines saying "root hub lost power or was reset".
In practice, people are forced to unmount any filesystems on a USB
device before suspending. If the root filesystem is on a USB device,
the system can't be suspended at all. (All right, it _can_ be
suspended -- but it will crash as soon as it wakes up, which isn't
much better.)
What is the solution?
=====================
The kernel includes a feature called USB-persist. It tries to work
around these issues by allowing the core USB device data structures to
persist across a power-session disruption.
It works like this. If the kernel sees that a USB host controller is
not in the expected state during resume (i.e., if the controller was
reset or otherwise had lost power) then it applies a persistence check
to each of the USB devices below that controller for which the
"persist" attribute is set. It doesn't try to resume the device; that
can't work once the power session is gone. Instead it issues a USB
port reset and then re-enumerates the device. (This is exactly the
same thing that happens whenever a USB device is reset.) If the
re-enumeration shows that the device now attached to that port has the
same descriptors as before, including the Vendor and Product IDs, then
the kernel continues to use the same device structure. In effect, the
kernel treats the device as though it had merely been reset instead of
unplugged.
The same thing happens if the host controller is in the expected state
but a USB device was unplugged and then replugged, or if a USB device
fails to carry out a normal resume.
If no device is now attached to the port, or if the descriptors are
different from what the kernel remembers, then the treatment is what
you would expect. The kernel destroys the old device structure and
behaves as though the old device had been unplugged and a new device
plugged in.
The end result is that the USB device remains available and usable.
Filesystem mounts and memory mappings are unaffected, and the world is
now a good and happy place.
Note that the "USB-persist" feature will be applied only to those
devices for which it is enabled. You can enable the feature by doing
(as root)::
echo 1 >/sys/bus/usb/devices/.../power/persist
where the "..." should be filled in the with the device's ID. Disable
the feature by writing 0 instead of 1. For hubs the feature is
automatically and permanently enabled and the power/persist file
doesn't even exist, so you only have to worry about setting it for
devices where it really matters.
Is this the best solution?
==========================
Perhaps not. Arguably, keeping track of mounted filesystems and
memory mappings across device disconnects should be handled by a
centralized Logical Volume Manager. Such a solution would allow you
to plug in a USB flash device, create a persistent volume associated
with it, unplug the flash device, plug it back in later, and still
have the same persistent volume associated with the device. As such
it would be more far-reaching than USB-persist.
On the other hand, writing a persistent volume manager would be a big
job and using it would require significant input from the user. This
solution is much quicker and easier -- and it exists now, a giant
point in its favor!
Furthermore, the USB-persist feature applies to _all_ USB devices, not
just mass-storage devices. It might turn out to be equally useful for
other device types, such as network interfaces.
WARNING: USB-persist can be dangerous!!
=======================================
When recovering an interrupted power session the kernel does its best
to make sure the USB device hasn't been changed; that is, the same
device is still plugged into the port as before. But the checks
aren't guaranteed to be 100% accurate.
If you replace one USB device with another of the same type (same
manufacturer, same IDs, and so on) there's an excellent chance the
kernel won't detect the change. The serial number string and other
descriptors are compared with the kernel's stored values, but this
might not help since manufacturers frequently omit serial numbers
entirely in their devices.
Furthermore it's quite possible to leave a USB device exactly the same
while changing its media. If you replace the flash memory card in a
USB card reader while the system is asleep, the kernel will have no
way to know you did it. The kernel will assume that nothing has
happened and will continue to use the partition tables, inodes, and
memory mappings for the old card.
If the kernel gets fooled in this way, it's almost certain to cause
data corruption and to crash your system. You'll have no one to blame
but yourself.
For those devices with avoid_reset_quirk attribute being set, persist
maybe fail because they may morph after reset.
YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK!
That having been said, most of the time there shouldn't be any trouble
at all. The USB-persist feature can be extremely useful. Make the
most of it.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Suspend 중 power session 손실 문제
1-68USB specification에 따르면 USB bus가 suspend된 동안에도 약 1~5 mA의 suspend current를 계속 공급해야 합니다. 그래야 device가 내부 상태를 유지하고 hub가 device 연결·분리 같은 connect-change event를 감지할 수 있습니다. 이 전원 유지 구간을 `power session`이라고 합니다.
USB device의 power session이 끊기면 system은 device가 unplug된 것처럼 동작해야 합니다. Suspend current가 없으면 같은 device가 계속 연결됐는지, 기존 device가 제거되고 다른 device가 연결됐는지 알 수 없으므로 최악의 경우를 가정하는 보수적 규칙입니다.
Linux의 기본 동작도 specification을 따릅니다. System suspend 중 USB host controller가 power를 잃으면 wakeup 뒤 그 controller 아래의 모든 device를 disconnect된 것으로 처리합니다. 이는 항상 안전하고 공식적으로 올바른 동작입니다.
Keyboard처럼 다시 연결된 것으로 처리해도 사용 결과가 같은 device에는 문제가 거의 없지만 mass-storage device에는 심각합니다. Mounted filesystem이 접근 불가능해지고 root filesystem이 USB device에 있으면 system이 즉시 crash할 수 있습니다.
Power loss만이 원인은 아닙니다. Power session을 끊는 모든 동작이 같은 결과를 냅니다. System sleep 중 suspend current가 유지됐더라도 wakeup 초기 단계에서 BIOS가 motherboard USB host controller를 reset하면 모든 power session이 사라집니다.
많은 system에서 suspend-to-RAM 뒤 controller가 reset되고, 거의 모든 system의 hibernation 또는 swsusp·suspend-to-disk 중에는 suspend current가 없습니다. Resume 뒤 kernel log에서 `root hub lost power or was reset`을 찾아 확인할 수 있습니다.
실제로는 suspend 전에 USB filesystem을 unmount해야 하며 root filesystem이 USB device에 있으면 정상적인 suspend가 불가능합니다.
USB specification을 그대로 따를 때의 suspend·resume 흐름입니다.
.. _usb-persist:
USB device persistence during system suspend
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Author: Alan Stern <[email protected]>
:Date: September 2, 2006 (Updated February 25, 2008)
What is the problem?
====================
According to the USB specification, when a USB bus is suspended the
bus must continue to supply suspend current (around 1-5 mA). This
is so that devices can maintain their internal state and hubs can
detect connect-change events (devices being plugged in or unplugged).
The technical term is "power session".
If a USB device's power session is interrupted then the system is
required to behave as though the device has been unplugged. It's a
conservative approach; in the absence of suspend current the computer
has no way to know what has actually happened. Perhaps the same
device is still attached or perhaps it was removed and a different
device plugged into the port. The system must assume the worst.
By default, Linux behaves according to the spec. If a USB host
controller loses power during a system suspend, then when the system
wakes up all the devices attached to that controller are treated as
though they had disconnected. This is always safe and it is the
"officially correct" thing to do.
For many sorts of devices this behavior doesn't matter in the least.
If the kernel wants to believe that your USB keyboard was unplugged
while the system was asleep and a new keyboard was plugged in when the
system woke up, who cares? It'll still work the same when you type on
it.
Unfortunately problems _can_ arise, particularly with mass-storage
devices. The effect is exactly the same as if the device really had
been unplugged while the system was suspended. If you had a mounted
filesystem on the device, you're out of luck -- everything in that
filesystem is now inaccessible. This is especially annoying if your
root filesystem was located on the device, since your system will
instantly crash.
Loss of power isn't the only mechanism to worry about. Anything that
interrupts a power session will have the same effect. For example,
even though suspend current may have been maintained while the system
was asleep, on many systems during the initial stages of wakeup the
firmware (i.e., the BIOS) resets the motherboard's USB host
controllers. Result: all the power sessions are destroyed and again
it's as though you had unplugged all the USB devices. Yes, it's
entirely the BIOS's fault, but that doesn't do _you_ any good unless
you can convince the BIOS supplier to fix the problem (lots of luck!).
On many systems the USB host controllers will get reset after a
suspend-to-RAM. On almost all systems, no suspend current is
available during hibernation (also known as swsusp or suspend-to-disk).
You can check the kernel log after resuming to see if either of these
has happened; look for lines saying "root hub lost power or was reset".
In practice, people are forced to unmount any filesystems on a USB
device before suspending. If the root filesystem is on a USB device,
the system can't be suspended at all. (All right, it _can_ be
suspended -- but it will crash as soon as it wakes up, which isn't
much better.)
USB-persist 복구 절차와 설정
69-116Kernel의 USB-persist 기능은 power-session 중단을 지나서도 core USB device data structure를 유지하도록 허용해 이 문제를 우회합니다.
Resume 중 USB host controller가 예상 상태가 아니면, 즉 reset됐거나 power를 잃었다면 kernel은 `persist` attribute가 설정된 각 하위 USB device에 persistence check를 적용합니다.
Power session이 사라진 뒤에는 정상 resume이 불가능하므로 device를 resume하지 않습니다. 대신 USB port reset을 수행하고 device를 re-enumerate합니다. 이는 일반적인 USB device reset 때와 같은 동작입니다.
Re-enumeration 결과 현재 port의 device descriptor가 Vendor·Product ID를 포함해 이전과 같으면 기존 device structure를 계속 사용합니다. Kernel은 unplug가 아니라 단순 reset으로 처리합니다.
Host controller 상태가 정상이더라도 device가 unplug 후 replug됐거나 정상 resume에 실패하면 같은 검사를 수행합니다. Device가 없거나 descriptor가 기억한 값과 다르면 기존 structure를 파괴하고 old device unplug와 new device plug로 처리합니다.
Identity가 일치하면 filesystem mount와 memory mapping을 유지한 채 USB device를 계속 사용할 수 있습니다.
USB-persist는 enable한 device에만 적용됩니다. Root 권한으로 `echo 1 >/sys/bus/usb/devices/.../power/persist`를 실행하고 `...`에 device ID를 넣습니다. `0`을 쓰면 disable됩니다. Hub에는 자동으로 영구 enable되며 `power/persist` file 자체가 없습니다.
Power session이 끊긴 뒤 기존 device object를 재사용할지 결정합니다.
What is the solution?
=====================
The kernel includes a feature called USB-persist. It tries to work
around these issues by allowing the core USB device data structures to
persist across a power-session disruption.
It works like this. If the kernel sees that a USB host controller is
not in the expected state during resume (i.e., if the controller was
reset or otherwise had lost power) then it applies a persistence check
to each of the USB devices below that controller for which the
"persist" attribute is set. It doesn't try to resume the device; that
can't work once the power session is gone. Instead it issues a USB
port reset and then re-enumerates the device. (This is exactly the
same thing that happens whenever a USB device is reset.) If the
re-enumeration shows that the device now attached to that port has the
same descriptors as before, including the Vendor and Product IDs, then
the kernel continues to use the same device structure. In effect, the
kernel treats the device as though it had merely been reset instead of
unplugged.
The same thing happens if the host controller is in the expected state
but a USB device was unplugged and then replugged, or if a USB device
fails to carry out a normal resume.
If no device is now attached to the port, or if the descriptors are
different from what the kernel remembers, then the treatment is what
you would expect. The kernel destroys the old device structure and
behaves as though the old device had been unplugged and a new device
plugged in.
The end result is that the USB device remains available and usable.
Filesystem mounts and memory mappings are unaffected, and the world is
now a good and happy place.
Note that the "USB-persist" feature will be applied only to those
devices for which it is enabled. You can enable the feature by doing
(as root)::
echo 1 >/sys/bus/usb/devices/.../power/persist
where the "..." should be filled in the with the device's ID. Disable
the feature by writing 0 instead of 1. For hubs the feature is
automatically and permanently enabled and the power/persist file
doesn't even exist, so you only have to worry about setting it for
devices where it really matters.
Logical Volume Manager 대안과 적용 범위
117-137USB-persist가 최선의 해법이라고 단정할 수는 없습니다. Device disconnect를 넘어 mounted filesystem과 memory mapping을 추적하는 일은 중앙화된 Logical Volume Manager가 맡아야 한다는 관점도 있습니다.
Persistent volume manager를 사용하면 USB flash device를 연결해 volume을 만들고 분리했다가 나중에 다시 연결해도 같은 persistent volume을 연관시킬 수 있어 USB-persist보다 적용 범위가 넓습니다.
그러나 이런 volume manager를 작성하는 일은 크고 복잡하며 사용자의 상당한 설정이 필요합니다. USB-persist는 훨씬 빠르고 단순하며 이미 사용할 수 있다는 장점이 있습니다.
또한 USB-persist는 mass storage뿐 아니라 모든 USB device에 적용되므로 network interface 같은 다른 device type에도 유용할 수 있습니다.
Is this the best solution?
==========================
Perhaps not. Arguably, keeping track of mounted filesystems and
memory mappings across device disconnects should be handled by a
centralized Logical Volume Manager. Such a solution would allow you
to plug in a USB flash device, create a persistent volume associated
with it, unplug the flash device, plug it back in later, and still
have the same persistent volume associated with the device. As such
it would be more far-reaching than USB-persist.
On the other hand, writing a persistent volume manager would be a big
job and using it would require significant input from the user. This
solution is much quicker and easier -- and it exists now, a giant
point in its favor!
Furthermore, the USB-persist feature applies to _all_ USB devices, not
just mass-storage devices. It might turn out to be equally useful for
other device types, such as network interfaces.
Identity 오판과 데이터 손상 경고
138-171USB-persist는 위험할 수 있습니다. Kernel은 power session 복구 시 같은 device가 port에 계속 연결됐는지 최선을 다해 확인하지만 검사가 100% 정확하다고 보장할 수 없습니다.
같은 manufacturer와 같은 ID를 가진 동일 type device로 교체하면 kernel이 변경을 감지하지 못할 가능성이 큽니다. Serial number string과 다른 descriptor도 저장값과 비교하지만 제조사가 serial number를 생략하는 경우가 많아 충분하지 않을 수 있습니다.
Device는 그대로 두고 media만 바꾸는 경우는 더 어렵습니다. System sleep 중 USB card reader의 flash memory card를 교체해도 kernel은 알 수 없으며, old card의 partition table·inode·memory mapping을 계속 사용합니다.
이렇게 identity를 잘못 판단하면 data corruption과 system crash가 거의 확실합니다. 사용자는 위험을 이해하고 자기 책임으로 기능을 사용해야 합니다.
`avoid_reset_quirk` attribute가 설정된 device는 reset 뒤 형태가 바뀔 수 있으므로 persistence check가 실패할 수 있습니다.
이 경고에도 불구하고 대부분의 경우 문제없이 동작하며 USB-persist는 매우 유용할 수 있습니다.
WARNING: USB-persist can be dangerous!!
=======================================
When recovering an interrupted power session the kernel does its best
to make sure the USB device hasn't been changed; that is, the same
device is still plugged into the port as before. But the checks
aren't guaranteed to be 100% accurate.
If you replace one USB device with another of the same type (same
manufacturer, same IDs, and so on) there's an excellent chance the
kernel won't detect the change. The serial number string and other
descriptors are compared with the kernel's stored values, but this
might not help since manufacturers frequently omit serial numbers
entirely in their devices.
Furthermore it's quite possible to leave a USB device exactly the same
while changing its media. If you replace the flash memory card in a
USB card reader while the system is asleep, the kernel will have no
way to know you did it. The kernel will assume that nothing has
happened and will continue to use the partition tables, inodes, and
memory mappings for the old card.
If the kernel gets fooled in this way, it's almost certain to cause
data corruption and to crash your system. You'll have no one to blame
but yourself.
For those devices with avoid_reset_quirk attribute being set, persist
maybe fail because they may morph after reset.
YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK!
That having been said, most of the time there shouldn't be any trouble
at all. The USB-persist feature can be extremely useful. Make the
most of it.
요약·해설
persist.rst:1-171USB-persist는 suspend 중 controller power session이 끊겨도 port reset과 descriptor 재검사로 기존 device object를 유지합니다. 같은 ID의 다른 device나 교체된 media를 오인하면 data corruption이 생길 수 있어 선택적으로 enable해야 합니다.