Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: f_mass_storage: forced_eject attribute

It allows to reset prevent_medium_removal flag and "eject" the image.
This can be useful to free the drive from a hunging host or if the host
continues to use the drive even after unmounting (Linux does this).
It's also a bit like using an unfolded paperclip on an optical drive.

Previously, the undocumented method of sending SIGUSR1 to a special
"file-storage" kernel thread could be used for these purposes,
but when using multiple storages there was no way to distinguish
one from the other, so we had to send a signal to everyone.

Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Maxim Devaev <mdevaev@gmail.com>
Link: https://lore.kernel.org/r/20220711102956.19642-1-mdevaev@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Maxim Devaev and committed by
Greg Kroah-Hartman
421c8d9a 8097cf2f

+63
+6
Documentation/ABI/testing/configfs-usb-gadget-mass-storage
··· 32 32 being a CD-ROM. 33 33 nofua Flag specifying that FUA flag 34 34 in SCSI WRITE(10,12) 35 + forced_eject This write-only file is useful only when 36 + the function is active. It causes the backing 37 + file to be forcibly detached from the LUN, 38 + regardless of whether the host has allowed it. 39 + Any non-zero number of bytes written will 40 + result in ejection. 35 41 =========== ==============================================
+6
Documentation/usb/gadget-testing.rst
··· 333 333 being a CD-ROM. 334 334 nofua Flag specifying that FUA flag 335 335 in SCSI WRITE(10,12) 336 + forced_eject This write-only file is useful only when 337 + the function is active. It causes the backing 338 + file to be forcibly detached from the LUN, 339 + regardless of whether the host has allowed it. 340 + Any non-zero number of bytes written will 341 + result in ejection. 336 342 =============== ============================================== 337 343 338 344 Testing the MASS STORAGE function
+9
Documentation/usb/mass-storage.rst
··· 181 181 Reflects the state of nofua flag for given logical unit. It can 182 182 be read and written. 183 183 184 + - forced_eject 185 + 186 + When written into, it causes the backing file to be forcibly 187 + detached from the LUN, regardless of whether the host has allowed 188 + it. The content doesn't matter, any non-zero number of bytes 189 + written will result in ejection. 190 + 191 + Can not be read. 192 + 184 193 Other then those, as usual, the values of module parameters can be 185 194 read from /sys/module/g_mass_storage/parameters/* files. 186 195
+25
drivers/usb/gadget/function/f_mass_storage.c
··· 2651 2651 return fsg_store_file(curlun, filesem, buf, count); 2652 2652 } 2653 2653 2654 + static ssize_t forced_eject_store(struct device *dev, 2655 + struct device_attribute *attr, 2656 + const char *buf, size_t count) 2657 + { 2658 + struct fsg_lun *curlun = fsg_lun_from_dev(dev); 2659 + struct rw_semaphore *filesem = dev_get_drvdata(dev); 2660 + 2661 + return fsg_store_forced_eject(curlun, filesem, buf, count); 2662 + } 2663 + 2654 2664 static DEVICE_ATTR_RW(nofua); 2655 2665 /* mode wil be set in fsg_lun_attr_is_visible() */ 2656 2666 static DEVICE_ATTR(ro, 0, ro_show, ro_store); 2657 2667 static DEVICE_ATTR(file, 0, file_show, file_store); 2668 + static DEVICE_ATTR_WO(forced_eject); 2658 2669 2659 2670 /****************************** FSG COMMON ******************************/ 2660 2671 ··· 2819 2808 &dev_attr_ro.attr, 2820 2809 &dev_attr_file.attr, 2821 2810 &dev_attr_nofua.attr, 2811 + &dev_attr_forced_eject.attr, 2822 2812 NULL 2823 2813 }; 2824 2814 ··· 3233 3221 3234 3222 CONFIGFS_ATTR(fsg_lun_opts_, inquiry_string); 3235 3223 3224 + static ssize_t fsg_lun_opts_forced_eject_store(struct config_item *item, 3225 + const char *page, size_t len) 3226 + { 3227 + struct fsg_lun_opts *opts = to_fsg_lun_opts(item); 3228 + struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent); 3229 + 3230 + return fsg_store_forced_eject(opts->lun, &fsg_opts->common->filesem, 3231 + page, len); 3232 + } 3233 + 3234 + CONFIGFS_ATTR_WO(fsg_lun_opts_, forced_eject); 3235 + 3236 3236 static struct configfs_attribute *fsg_lun_attrs[] = { 3237 3237 &fsg_lun_opts_attr_file, 3238 3238 &fsg_lun_opts_attr_ro, ··· 3252 3228 &fsg_lun_opts_attr_cdrom, 3253 3229 &fsg_lun_opts_attr_nofua, 3254 3230 &fsg_lun_opts_attr_inquiry_string, 3231 + &fsg_lun_opts_attr_forced_eject, 3255 3232 NULL, 3256 3233 }; 3257 3234
+15
drivers/usb/gadget/function/storage_common.c
··· 519 519 } 520 520 EXPORT_SYMBOL_GPL(fsg_store_inquiry_string); 521 521 522 + ssize_t fsg_store_forced_eject(struct fsg_lun *curlun, struct rw_semaphore *filesem, 523 + const char *buf, size_t count) 524 + { 525 + int ret; 526 + 527 + /* 528 + * Forcibly detach the backing file from the LUN 529 + * regardless of whether the host has allowed it. 530 + */ 531 + curlun->prevent_medium_removal = 0; 532 + ret = fsg_store_file(curlun, filesem, "", 0); 533 + return ret < 0 ? ret : count; 534 + } 535 + EXPORT_SYMBOL_GPL(fsg_store_forced_eject); 536 + 522 537 MODULE_LICENSE("GPL");
+2
drivers/usb/gadget/function/storage_common.h
··· 219 219 size_t count); 220 220 ssize_t fsg_store_inquiry_string(struct fsg_lun *curlun, const char *buf, 221 221 size_t count); 222 + ssize_t fsg_store_forced_eject(struct fsg_lun *curlun, struct rw_semaphore *filesem, 223 + const char *buf, size_t count); 222 224 223 225 #endif /* USB_STORAGE_COMMON_H */