mirror of https://gitee.com/openkylin/linux.git
usb: gadget: mass_storage: fail fsg_store_file() early if colud not open file
Currently, when a new value is stored to the “file” sysfs entry, fsg_store_file() will release existing backing file and only then attempt to open a new one. If that fails, no new backing file is open. This commit changes the fsg_lun_open() so that it closes existing backing file only after the new backing file has been successfully opened. With that change, fsg_store_file() may use it to perform an atomic open operation with guarantee that logical unit will either point to the new backing file or still to the old one. Signed-off-by: Michal Nazarewicz <mina86@mina86.com> Acked-by: Alan Stern <stern@rowland.harvard.edu Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
f87cabf4d5
commit
d6e16a8957
|
@ -617,6 +617,16 @@ static struct usb_gadget_strings fsg_stringtab = {
|
||||||
* the caller must own fsg->filesem for writing.
|
* the caller must own fsg->filesem for writing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void fsg_lun_close(struct fsg_lun *curlun)
|
||||||
|
{
|
||||||
|
if (curlun->filp) {
|
||||||
|
LDBG(curlun, "close backing file\n");
|
||||||
|
fput(curlun->filp);
|
||||||
|
curlun->filp = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
|
static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
|
||||||
{
|
{
|
||||||
int ro;
|
int ro;
|
||||||
|
@ -626,6 +636,8 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
|
||||||
loff_t size;
|
loff_t size;
|
||||||
loff_t num_sectors;
|
loff_t num_sectors;
|
||||||
loff_t min_sectors;
|
loff_t min_sectors;
|
||||||
|
unsigned int blkbits;
|
||||||
|
unsigned int blksize;
|
||||||
|
|
||||||
/* R/W if we can, R/O if we must */
|
/* R/W if we can, R/O if we must */
|
||||||
ro = curlun->initially_ro;
|
ro = curlun->initially_ro;
|
||||||
|
@ -670,17 +682,17 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curlun->cdrom) {
|
if (curlun->cdrom) {
|
||||||
curlun->blksize = 2048;
|
blksize = 2048;
|
||||||
curlun->blkbits = 11;
|
blkbits = 11;
|
||||||
} else if (inode->i_bdev) {
|
} else if (inode->i_bdev) {
|
||||||
curlun->blksize = bdev_logical_block_size(inode->i_bdev);
|
blksize = bdev_logical_block_size(inode->i_bdev);
|
||||||
curlun->blkbits = blksize_bits(curlun->blksize);
|
blkbits = blksize_bits(blksize);
|
||||||
} else {
|
} else {
|
||||||
curlun->blksize = 512;
|
blksize = 512;
|
||||||
curlun->blkbits = 9;
|
blkbits = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_sectors = size >> curlun->blkbits; /* File size in logic-block-size blocks */
|
num_sectors = size >> blkbits; /* File size in logic-block-size blocks */
|
||||||
min_sectors = 1;
|
min_sectors = 1;
|
||||||
if (curlun->cdrom) {
|
if (curlun->cdrom) {
|
||||||
min_sectors = 300; /* Smallest track is 300 frames */
|
min_sectors = 300; /* Smallest track is 300 frames */
|
||||||
|
@ -697,7 +709,12 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fsg_lun_is_open(curlun))
|
||||||
|
fsg_lun_close(curlun);
|
||||||
|
|
||||||
get_file(filp);
|
get_file(filp);
|
||||||
|
curlun->blksize = blksize;
|
||||||
|
curlun->blkbits = blkbits;
|
||||||
curlun->ro = ro;
|
curlun->ro = ro;
|
||||||
curlun->filp = filp;
|
curlun->filp = filp;
|
||||||
curlun->file_length = size;
|
curlun->file_length = size;
|
||||||
|
@ -711,16 +728,6 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void fsg_lun_close(struct fsg_lun *curlun)
|
|
||||||
{
|
|
||||||
if (curlun->filp) {
|
|
||||||
LDBG(curlun, "close backing file\n");
|
|
||||||
fput(curlun->filp);
|
|
||||||
curlun->filp = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -871,19 +878,18 @@ static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
|
||||||
if (count > 0 && buf[count-1] == '\n')
|
if (count > 0 && buf[count-1] == '\n')
|
||||||
((char *) buf)[count-1] = 0; /* Ugh! */
|
((char *) buf)[count-1] = 0; /* Ugh! */
|
||||||
|
|
||||||
/* Eject current medium */
|
|
||||||
down_write(filesem);
|
|
||||||
if (fsg_lun_is_open(curlun)) {
|
|
||||||
fsg_lun_close(curlun);
|
|
||||||
curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load new medium */
|
/* Load new medium */
|
||||||
|
down_write(filesem);
|
||||||
if (count > 0 && buf[0]) {
|
if (count > 0 && buf[0]) {
|
||||||
|
/* fsg_lun_open() will close existing file if any. */
|
||||||
rc = fsg_lun_open(curlun, buf);
|
rc = fsg_lun_open(curlun, buf);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
curlun->unit_attention_data =
|
curlun->unit_attention_data =
|
||||||
SS_NOT_READY_TO_READY_TRANSITION;
|
SS_NOT_READY_TO_READY_TRANSITION;
|
||||||
|
} else if (fsg_lun_is_open(curlun)) {
|
||||||
|
fsg_lun_close(curlun);
|
||||||
|
curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
|
||||||
}
|
}
|
||||||
up_write(filesem);
|
up_write(filesem);
|
||||||
return (rc < 0 ? rc : count);
|
return (rc < 0 ? rc : count);
|
||||||
|
|
Loading…
Reference in New Issue