* [PATCH] sg: protect access to to 'reserved' page array
@ 2017-02-01 11:22 Hannes Reinecke
2017-02-01 11:23 ` Johannes Thumshirn
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Hannes Reinecke @ 2017-02-01 11:22 UTC (permalink / raw)
To: Martin K. Petersen
Cc: James Bottomley, Christoph Hellwig, linux-scsi,
Johannes Thumshirn, Dmitry Vyukov, Hannes Reinecke, stable,
Hannes Reinecke
The 'reserved' page array is used as a short-cut for mapping
data, saving us to allocate pages per request.
However, the 'reserved' array is only capable of holding one
request, so we need to protect it against concurrent accesses.
Cc: stable@vger.kernel.org
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Link: http://www.spinics.net/lists/linux-scsi/msg104326.html
Signed-off-by: Hannes Reinecke <hare@suse.com>
Tested-by: Johannes Thumshirn <jth@kernel.org>
---
drivers/scsi/sg.c | 30 ++++++++++++------------------
1 file changed, 12 insertions(+), 18 deletions(-)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 652b934..6a8601c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -155,6 +155,8 @@
unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
char mmap_called; /* 0 -> mmap() never called on this fd */
+ unsigned long flags;
+#define SG_RESERVED_IN_USE 1
struct kref f_ref;
struct execute_work ew;
} Sg_fd;
@@ -198,7 +200,6 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
static Sg_request *sg_add_request(Sg_fd * sfp);
static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
-static int sg_res_in_use(Sg_fd * sfp);
static Sg_device *sg_get_dev(int dev);
static void sg_device_destroy(struct kref *kref);
@@ -721,7 +722,7 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
sg_remove_request(sfp, srp);
return -EINVAL; /* either MMAP_IO or DIRECT_IO (not both) */
}
- if (sg_res_in_use(sfp)) {
+ if (test_bit(SG_RESERVED_IN_USE, &sfp->flags)) {
sg_remove_request(sfp, srp);
return -EBUSY; /* reserve buffer already being used */
}
@@ -963,10 +964,14 @@ static int max_sectors_bytes(struct request_queue *q)
val = min_t(int, val,
max_sectors_bytes(sdp->device->request_queue));
if (val != sfp->reserve.bufflen) {
- if (sg_res_in_use(sfp) || sfp->mmap_called)
+ if (sfp->mmap_called)
+ return -EBUSY;
+ if (test_and_set_bit(SG_RESERVED_IN_USE, &sfp->flags))
return -EBUSY;
+
sg_remove_scat(sfp, &sfp->reserve);
sg_build_reserve(sfp, val);
+ clear_bit(SG_RESERVED_IN_USE, &sfp->flags);
}
return 0;
case SG_GET_RESERVED_SIZE:
@@ -1720,7 +1725,9 @@ static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned lon
md = &map_data;
if (md) {
- if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen)
+ if (dxfer_len <= rsv_schp->bufflen &&
+ test_and_set_bit(SG_RESERVED_IN_USE,
+ &sfp->flags) == 0)
sg_link_reserve(sfp, srp, dxfer_len);
else {
res = sg_build_indirect(req_schp, sfp, dxfer_len);
@@ -2013,6 +2020,7 @@ static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned lon
req_schp->sglist_len = 0;
sfp->save_scat_len = 0;
srp->res_used = 0;
+ clear_bit(SG_RESERVED_IN_USE, &sfp->flags);
}
static Sg_request *
@@ -2199,20 +2207,6 @@ static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned lon
schedule_work(&sfp->ew.work);
}
-static int
-sg_res_in_use(Sg_fd * sfp)
-{
- const Sg_request *srp;
- unsigned long iflags;
-
- read_lock_irqsave(&sfp->rq_list_lock, iflags);
- for (srp = sfp->headrp; srp; srp = srp->nextrp)
- if (srp->res_used)
- break;
- read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
- return srp ? 1 : 0;
-}
-
#ifdef CONFIG_SCSI_PROC_FS
static int
sg_idr_max_id(int id, void *p, void *data)
--
1.8.5.6
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] sg: protect access to to 'reserved' page array
2017-02-01 11:22 [PATCH] sg: protect access to to 'reserved' page array Hannes Reinecke
@ 2017-02-01 11:23 ` Johannes Thumshirn
2017-02-01 11:46 ` kbuild test robot
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Johannes Thumshirn @ 2017-02-01 11:23 UTC (permalink / raw)
To: Hannes Reinecke
Cc: Martin K. Petersen, James Bottomley, Christoph Hellwig,
linux-scsi, Johannes Thumshirn, Dmitry Vyukov, stable,
Hannes Reinecke
On Wed, Feb 01, 2017 at 12:22:15PM +0100, Hannes Reinecke wrote:
> The 'reserved' page array is used as a short-cut for mapping
> data, saving us to allocate pages per request.
> However, the 'reserved' array is only capable of holding one
> request, so we need to protect it against concurrent accesses.
>
> Cc: stable@vger.kernel.org
> Reported-by: Dmitry Vyukov <dvyukov@google.com>
> Link: http://www.spinics.net/lists/linux-scsi/msg104326.html
> Signed-off-by: Hannes Reinecke <hare@suse.com>
> Tested-by: Johannes Thumshirn <jth@kernel.org>
> ---
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
--
Johannes Thumshirn Storage
jthumshirn@suse.de +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] sg: protect access to to 'reserved' page array
2017-02-01 11:22 [PATCH] sg: protect access to to 'reserved' page array Hannes Reinecke
2017-02-01 11:23 ` Johannes Thumshirn
@ 2017-02-01 11:46 ` kbuild test robot
2017-02-01 11:49 ` kbuild test robot
2017-02-01 13:12 ` Christoph Hellwig
3 siblings, 0 replies; 9+ messages in thread
From: kbuild test robot @ 2017-02-01 11:46 UTC (permalink / raw)
Cc: kbuild-all, Martin K. Petersen, James Bottomley,
Christoph Hellwig, linux-scsi, Johannes Thumshirn, Dmitry Vyukov,
Hannes Reinecke, stable, Hannes Reinecke
[-- Attachment #1: Type: text/plain, Size: 2134 bytes --]
Hi Hannes,
[auto build test ERROR on scsi/for-next]
[also build test ERROR on v4.10-rc6 next-20170201]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Hannes-Reinecke/sg-protect-access-to-to-reserved-page-array/20170201-192716
base: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
config: x86_64-randconfig-x009-201705 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
drivers/scsi/sg.c: In function 'sg_ioctl':
>> drivers/scsi/sg.c:896:37: error: implicit declaration of function 'sg_res_in_use' [-Werror=implicit-function-declaration]
if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) {
^~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/sg_res_in_use +896 drivers/scsi/sg.c
^1da177e Linus Torvalds 2005-04-16 890 case SG_SET_FORCE_LOW_DMA:
^1da177e Linus Torvalds 2005-04-16 891 result = get_user(val, ip);
^1da177e Linus Torvalds 2005-04-16 892 if (result)
^1da177e Linus Torvalds 2005-04-16 893 return result;
^1da177e Linus Torvalds 2005-04-16 894 if (val) {
^1da177e Linus Torvalds 2005-04-16 895 sfp->low_dma = 1;
^1da177e Linus Torvalds 2005-04-16 @896 if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) {
^1da177e Linus Torvalds 2005-04-16 897 val = (int) sfp->reserve.bufflen;
95e159d6 Hannes Reinecke 2014-06-25 898 sg_remove_scat(sfp, &sfp->reserve);
^1da177e Linus Torvalds 2005-04-16 899 sg_build_reserve(sfp, val);
:::::: The code at line 896 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2
:::::: TO: Linus Torvalds <torvalds@ppc970.osdl.org>
:::::: CC: Linus Torvalds <torvalds@ppc970.osdl.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28708 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] sg: protect access to to 'reserved' page array
2017-02-01 11:22 [PATCH] sg: protect access to to 'reserved' page array Hannes Reinecke
2017-02-01 11:23 ` Johannes Thumshirn
2017-02-01 11:46 ` kbuild test robot
@ 2017-02-01 11:49 ` kbuild test robot
2017-02-01 13:12 ` Christoph Hellwig
3 siblings, 0 replies; 9+ messages in thread
From: kbuild test robot @ 2017-02-01 11:49 UTC (permalink / raw)
Cc: kbuild-all, Martin K. Petersen, James Bottomley,
Christoph Hellwig, linux-scsi, Johannes Thumshirn, Dmitry Vyukov,
Hannes Reinecke, stable, Hannes Reinecke
[-- Attachment #1: Type: text/plain, Size: 3989 bytes --]
Hi Hannes,
[auto build test WARNING on scsi/for-next]
[also build test WARNING on v4.10-rc6 next-20170201]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Hannes-Reinecke/sg-protect-access-to-to-reserved-page-array/20170201-192716
base: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
config: i386-randconfig-x004-201705 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All warnings (new ones prefixed by >>):
In file included from include/uapi/linux/stddef.h:1:0,
from include/linux/stddef.h:4,
from include/uapi/linux/posix_types.h:4,
from include/uapi/linux/types.h:13,
from include/linux/types.h:5,
from include/linux/list.h:4,
from include/linux/module.h:9,
from drivers/scsi/sg.c:29:
drivers/scsi/sg.c: In function 'sg_ioctl':
drivers/scsi/sg.c:896:37: error: implicit declaration of function 'sg_res_in_use' [-Werror=implicit-function-declaration]
if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) {
^
include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
>> drivers/scsi/sg.c:896:4: note: in expansion of macro 'if'
if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) {
^~
cc1: some warnings being treated as errors
vim +/if +896 drivers/scsi/sg.c
f8630bd7e Paul Burton 2016-08-19 880 if (val >= mult_frac((s64)INT_MAX, USER_HZ, HZ))
f8630bd7e Paul Burton 2016-08-19 881 val = min_t(s64, mult_frac((s64)INT_MAX, USER_HZ, HZ),
b9b6e80ad Paul Burton 2016-08-19 882 INT_MAX);
^1da177e4 Linus Torvalds 2005-04-16 883 sfp->timeout_user = val;
f8630bd7e Paul Burton 2016-08-19 884 sfp->timeout = mult_frac(val, HZ, USER_HZ);
^1da177e4 Linus Torvalds 2005-04-16 885
^1da177e4 Linus Torvalds 2005-04-16 886 return 0;
^1da177e4 Linus Torvalds 2005-04-16 887 case SG_GET_TIMEOUT: /* N.B. User receives timeout as return value */
^1da177e4 Linus Torvalds 2005-04-16 888 /* strange ..., for backward compatibility */
^1da177e4 Linus Torvalds 2005-04-16 889 return sfp->timeout_user;
^1da177e4 Linus Torvalds 2005-04-16 890 case SG_SET_FORCE_LOW_DMA:
^1da177e4 Linus Torvalds 2005-04-16 891 result = get_user(val, ip);
^1da177e4 Linus Torvalds 2005-04-16 892 if (result)
^1da177e4 Linus Torvalds 2005-04-16 893 return result;
^1da177e4 Linus Torvalds 2005-04-16 894 if (val) {
^1da177e4 Linus Torvalds 2005-04-16 895 sfp->low_dma = 1;
^1da177e4 Linus Torvalds 2005-04-16 @896 if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) {
^1da177e4 Linus Torvalds 2005-04-16 897 val = (int) sfp->reserve.bufflen;
95e159d6d Hannes Reinecke 2014-06-25 898 sg_remove_scat(sfp, &sfp->reserve);
^1da177e4 Linus Torvalds 2005-04-16 899 sg_build_reserve(sfp, val);
^1da177e4 Linus Torvalds 2005-04-16 900 }
^1da177e4 Linus Torvalds 2005-04-16 901 } else {
cc833acbe Douglas Gilbert 2014-06-25 902 if (atomic_read(&sdp->detaching))
^1da177e4 Linus Torvalds 2005-04-16 903 return -ENODEV;
^1da177e4 Linus Torvalds 2005-04-16 904 sfp->low_dma = sdp->device->host->unchecked_isa_dma;
:::::: The code at line 896 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2
:::::: TO: Linus Torvalds <torvalds@ppc970.osdl.org>
:::::: CC: Linus Torvalds <torvalds@ppc970.osdl.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 30735 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] sg: protect access to to 'reserved' page array
2017-02-01 11:22 [PATCH] sg: protect access to to 'reserved' page array Hannes Reinecke
` (2 preceding siblings ...)
2017-02-01 11:49 ` kbuild test robot
@ 2017-02-01 13:12 ` Christoph Hellwig
2017-02-01 13:18 ` Johannes Thumshirn
2017-02-01 13:21 ` Hannes Reinecke
3 siblings, 2 replies; 9+ messages in thread
From: Christoph Hellwig @ 2017-02-01 13:12 UTC (permalink / raw)
To: Hannes Reinecke
Cc: Martin K. Petersen, James Bottomley, Christoph Hellwig,
linux-scsi, Johannes Thumshirn, Dmitry Vyukov, stable,
Hannes Reinecke
On Wed, Feb 01, 2017 at 12:22:15PM +0100, Hannes Reinecke wrote:
> The 'reserved' page array is used as a short-cut for mapping
> data, saving us to allocate pages per request.
> However, the 'reserved' array is only capable of holding one
> request, so we need to protect it against concurrent accesses.
>
> Cc: stable@vger.kernel.org
> Reported-by: Dmitry Vyukov <dvyukov@google.com>
> Link: http://www.spinics.net/lists/linux-scsi/msg104326.html
> Signed-off-by: Hannes Reinecke <hare@suse.com>
> Tested-by: Johannes Thumshirn <jth@kernel.org>
> ---
> drivers/scsi/sg.c | 30 ++++++++++++------------------
> 1 file changed, 12 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
> index 652b934..6a8601c 100644
> --- a/drivers/scsi/sg.c
> +++ b/drivers/scsi/sg.c
> @@ -155,6 +155,8 @@
> unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
> char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
> char mmap_called; /* 0 -> mmap() never called on this fd */
> + unsigned long flags;
> +#define SG_RESERVED_IN_USE 1
> struct kref f_ref;
> struct execute_work ew;
> } Sg_fd;
> @@ -198,7 +200,6 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
> static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
> static Sg_request *sg_add_request(Sg_fd * sfp);
> static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
> -static int sg_res_in_use(Sg_fd * sfp);
> static Sg_device *sg_get_dev(int dev);
> static void sg_device_destroy(struct kref *kref);
>
> @@ -721,7 +722,7 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
> sg_remove_request(sfp, srp);
> return -EINVAL; /* either MMAP_IO or DIRECT_IO (not both) */
> }
> - if (sg_res_in_use(sfp)) {
> + if (test_bit(SG_RESERVED_IN_USE, &sfp->flags)) {
> sg_remove_request(sfp, srp);
> return -EBUSY; /* reserve buffer already being used */
> }
> @@ -963,10 +964,14 @@ static int max_sectors_bytes(struct request_queue *q)
> val = min_t(int, val,
> max_sectors_bytes(sdp->device->request_queue));
> if (val != sfp->reserve.bufflen) {
> - if (sg_res_in_use(sfp) || sfp->mmap_called)
> + if (sfp->mmap_called)
> + return -EBUSY;
> + if (test_and_set_bit(SG_RESERVED_IN_USE, &sfp->flags))
> return -EBUSY;
> +
> sg_remove_scat(sfp, &sfp->reserve);
> sg_build_reserve(sfp, val);
> + clear_bit(SG_RESERVED_IN_USE, &sfp->flags);
This seems to be abusing an atomic bitflag as a lock. And I think
in general we have two different things here that this patch conflates:
a) a lock to protect building and using the reserve lists
b) a flag is a reservations is in use
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] sg: protect access to to 'reserved' page array
2017-02-01 13:12 ` Christoph Hellwig
@ 2017-02-01 13:18 ` Johannes Thumshirn
2017-02-01 13:21 ` Hannes Reinecke
1 sibling, 0 replies; 9+ messages in thread
From: Johannes Thumshirn @ 2017-02-01 13:18 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Hannes Reinecke, Martin K. Petersen, James Bottomley, linux-scsi,
Johannes Thumshirn, Dmitry Vyukov, stable, Hannes Reinecke
On Wed, Feb 01, 2017 at 02:12:48PM +0100, Christoph Hellwig wrote:
>
> This seems to be abusing an atomic bitflag as a lock. And I think
> in general we have two different things here that this patch conflates:
>
> a) a lock to protect building and using the reserve lists
> b) a flag is a reservations is in use
I did have a patch doing exactly that but (appart from lockdep complaints) we
decided to drop it, as it made the code even more confusing.
--
Johannes Thumshirn Storage
jthumshirn@suse.de +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] sg: protect access to to 'reserved' page array
2017-02-01 13:12 ` Christoph Hellwig
2017-02-01 13:18 ` Johannes Thumshirn
@ 2017-02-01 13:21 ` Hannes Reinecke
2017-02-14 20:48 ` Dmitry Vyukov
1 sibling, 1 reply; 9+ messages in thread
From: Hannes Reinecke @ 2017-02-01 13:21 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Martin K. Petersen, James Bottomley, linux-scsi,
Johannes Thumshirn, Dmitry Vyukov, stable, Hannes Reinecke
On 02/01/2017 02:12 PM, Christoph Hellwig wrote:
> On Wed, Feb 01, 2017 at 12:22:15PM +0100, Hannes Reinecke wrote:
>> The 'reserved' page array is used as a short-cut for mapping
>> data, saving us to allocate pages per request.
>> However, the 'reserved' array is only capable of holding one
>> request, so we need to protect it against concurrent accesses.
>>
>> Cc: stable@vger.kernel.org
>> Reported-by: Dmitry Vyukov <dvyukov@google.com>
>> Link: http://www.spinics.net/lists/linux-scsi/msg104326.html
>> Signed-off-by: Hannes Reinecke <hare@suse.com>
>> Tested-by: Johannes Thumshirn <jth@kernel.org>
>> ---
>> drivers/scsi/sg.c | 30 ++++++++++++------------------
>> 1 file changed, 12 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
>> index 652b934..6a8601c 100644
>> --- a/drivers/scsi/sg.c
>> +++ b/drivers/scsi/sg.c
>> @@ -155,6 +155,8 @@
>> unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
>> char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
>> char mmap_called; /* 0 -> mmap() never called on this fd */
>> + unsigned long flags;
>> +#define SG_RESERVED_IN_USE 1
>> struct kref f_ref;
>> struct execute_work ew;
>> } Sg_fd;
>> @@ -198,7 +200,6 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
>> static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
>> static Sg_request *sg_add_request(Sg_fd * sfp);
>> static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
>> -static int sg_res_in_use(Sg_fd * sfp);
>> static Sg_device *sg_get_dev(int dev);
>> static void sg_device_destroy(struct kref *kref);
>>
>> @@ -721,7 +722,7 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
>> sg_remove_request(sfp, srp);
>> return -EINVAL; /* either MMAP_IO or DIRECT_IO (not both) */
>> }
>> - if (sg_res_in_use(sfp)) {
>> + if (test_bit(SG_RESERVED_IN_USE, &sfp->flags)) {
>> sg_remove_request(sfp, srp);
>> return -EBUSY; /* reserve buffer already being used */
>> }
>> @@ -963,10 +964,14 @@ static int max_sectors_bytes(struct request_queue *q)
>> val = min_t(int, val,
>> max_sectors_bytes(sdp->device->request_queue));
>> if (val != sfp->reserve.bufflen) {
>> - if (sg_res_in_use(sfp) || sfp->mmap_called)
>> + if (sfp->mmap_called)
>> + return -EBUSY;
>> + if (test_and_set_bit(SG_RESERVED_IN_USE, &sfp->flags))
>> return -EBUSY;
>> +
>> sg_remove_scat(sfp, &sfp->reserve);
>> sg_build_reserve(sfp, val);
>> + clear_bit(SG_RESERVED_IN_USE, &sfp->flags);
>
>
> This seems to be abusing an atomic bitflag as a lock.
Hmm. I wouldn't call it 'abusing'; the driver can proceed quite happily
without the 'reserved' buffer, so taking a lock would be overkill.
I could modify it to use a mutex if you insist ...
> And I think
> in general we have two different things here that this patch conflates:
>
> a) a lock to protect building and using the reserve lists
> b) a flag is a reservations is in use
>
No. This is not about reservations, this is about the internal
'reserved' page buffer array.
(Just in case to avoid any misunderstandings).
We need to have an atomic / protected check in the 'sfp' structure if
the 'reserved' page buffer array is in use; there's an additional check
in the 'sg_request' structure (res_in_use) telling us which of the
requests is using it.
Cheers,
Hannes
--
Dr. Hannes Reinecke Teamlead Storage & Networking
hare@suse.de +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] sg: protect access to to 'reserved' page array
2017-02-01 13:21 ` Hannes Reinecke
@ 2017-02-14 20:48 ` Dmitry Vyukov
2017-02-15 6:54 ` Hannes Reinecke
0 siblings, 1 reply; 9+ messages in thread
From: Dmitry Vyukov @ 2017-02-14 20:48 UTC (permalink / raw)
To: Hannes Reinecke
Cc: Christoph Hellwig, Martin K. Petersen, James Bottomley,
linux-scsi, Johannes Thumshirn, stable, Hannes Reinecke
On Wed, Feb 1, 2017 at 2:21 PM, Hannes Reinecke <hare@suse.de> wrote:
> On 02/01/2017 02:12 PM, Christoph Hellwig wrote:
>> On Wed, Feb 01, 2017 at 12:22:15PM +0100, Hannes Reinecke wrote:
>>> The 'reserved' page array is used as a short-cut for mapping
>>> data, saving us to allocate pages per request.
>>> However, the 'reserved' array is only capable of holding one
>>> request, so we need to protect it against concurrent accesses.
>>>
>>> Cc: stable@vger.kernel.org
>>> Reported-by: Dmitry Vyukov <dvyukov@google.com>
>>> Link: http://www.spinics.net/lists/linux-scsi/msg104326.html
>>> Signed-off-by: Hannes Reinecke <hare@suse.com>
>>> Tested-by: Johannes Thumshirn <jth@kernel.org>
>>> ---
>>> drivers/scsi/sg.c | 30 ++++++++++++------------------
>>> 1 file changed, 12 insertions(+), 18 deletions(-)
>>>
>>> diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
>>> index 652b934..6a8601c 100644
>>> --- a/drivers/scsi/sg.c
>>> +++ b/drivers/scsi/sg.c
>>> @@ -155,6 +155,8 @@
>>> unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
>>> char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
>>> char mmap_called; /* 0 -> mmap() never called on this fd */
>>> + unsigned long flags;
>>> +#define SG_RESERVED_IN_USE 1
>>> struct kref f_ref;
>>> struct execute_work ew;
>>> } Sg_fd;
>>> @@ -198,7 +200,6 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
>>> static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
>>> static Sg_request *sg_add_request(Sg_fd * sfp);
>>> static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
>>> -static int sg_res_in_use(Sg_fd * sfp);
>>> static Sg_device *sg_get_dev(int dev);
>>> static void sg_device_destroy(struct kref *kref);
>>>
>>> @@ -721,7 +722,7 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
>>> sg_remove_request(sfp, srp);
>>> return -EINVAL; /* either MMAP_IO or DIRECT_IO (not both) */
>>> }
>>> - if (sg_res_in_use(sfp)) {
>>> + if (test_bit(SG_RESERVED_IN_USE, &sfp->flags)) {
>>> sg_remove_request(sfp, srp);
>>> return -EBUSY; /* reserve buffer already being used */
>>> }
>>> @@ -963,10 +964,14 @@ static int max_sectors_bytes(struct request_queue *q)
>>> val = min_t(int, val,
>>> max_sectors_bytes(sdp->device->request_queue));
>>> if (val != sfp->reserve.bufflen) {
>>> - if (sg_res_in_use(sfp) || sfp->mmap_called)
>>> + if (sfp->mmap_called)
>>> + return -EBUSY;
>>> + if (test_and_set_bit(SG_RESERVED_IN_USE, &sfp->flags))
>>> return -EBUSY;
>>> +
>>> sg_remove_scat(sfp, &sfp->reserve);
>>> sg_build_reserve(sfp, val);
>>> + clear_bit(SG_RESERVED_IN_USE, &sfp->flags);
>>
>>
>> This seems to be abusing an atomic bitflag as a lock.
>
> Hmm. I wouldn't call it 'abusing'; the driver can proceed quite happily
> without the 'reserved' buffer, so taking a lock would be overkill.
> I could modify it to use a mutex if you insist ...
>
>> And I think
>> in general we have two different things here that this patch conflates:
>>
>> a) a lock to protect building and using the reserve lists
>> b) a flag is a reservations is in use
>>
> No. This is not about reservations, this is about the internal
> 'reserved' page buffer array.
> (Just in case to avoid any misunderstandings).
> We need to have an atomic / protected check in the 'sfp' structure if
> the 'reserved' page buffer array is in use; there's an additional check
> in the 'sg_request' structure (res_in_use) telling us which of the
> requests is using it.
So, how should we proceed here?
We could use a mutex with only trylock, but it would be effectively the same.
There is one missed user of sg_res_in_use in "case SG_SET_FORCE_LOW_DMA".
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] sg: protect access to to 'reserved' page array
2017-02-14 20:48 ` Dmitry Vyukov
@ 2017-02-15 6:54 ` Hannes Reinecke
0 siblings, 0 replies; 9+ messages in thread
From: Hannes Reinecke @ 2017-02-15 6:54 UTC (permalink / raw)
To: Dmitry Vyukov
Cc: Christoph Hellwig, Martin K. Petersen, James Bottomley,
linux-scsi, Johannes Thumshirn, stable, Hannes Reinecke
On 02/14/2017 09:48 PM, Dmitry Vyukov wrote:
> On Wed, Feb 1, 2017 at 2:21 PM, Hannes Reinecke <hare@suse.de> wrote:
>> On 02/01/2017 02:12 PM, Christoph Hellwig wrote:
>>> On Wed, Feb 01, 2017 at 12:22:15PM +0100, Hannes Reinecke wrote:
>>>> The 'reserved' page array is used as a short-cut for mapping
>>>> data, saving us to allocate pages per request.
>>>> However, the 'reserved' array is only capable of holding one
>>>> request, so we need to protect it against concurrent accesses.
>>>>
>>>> Cc: stable@vger.kernel.org
>>>> Reported-by: Dmitry Vyukov <dvyukov@google.com>
>>>> Link: http://www.spinics.net/lists/linux-scsi/msg104326.html
>>>> Signed-off-by: Hannes Reinecke <hare@suse.com>
>>>> Tested-by: Johannes Thumshirn <jth@kernel.org>
>>>> ---
>>>> drivers/scsi/sg.c | 30 ++++++++++++------------------
>>>> 1 file changed, 12 insertions(+), 18 deletions(-)
>>>>
>>>> diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
>>>> index 652b934..6a8601c 100644
>>>> --- a/drivers/scsi/sg.c
>>>> +++ b/drivers/scsi/sg.c
>>>> @@ -155,6 +155,8 @@
>>>> unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
>>>> char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
>>>> char mmap_called; /* 0 -> mmap() never called on this fd */
>>>> + unsigned long flags;
>>>> +#define SG_RESERVED_IN_USE 1
>>>> struct kref f_ref;
>>>> struct execute_work ew;
>>>> } Sg_fd;
>>>> @@ -198,7 +200,6 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
>>>> static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
>>>> static Sg_request *sg_add_request(Sg_fd * sfp);
>>>> static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
>>>> -static int sg_res_in_use(Sg_fd * sfp);
>>>> static Sg_device *sg_get_dev(int dev);
>>>> static void sg_device_destroy(struct kref *kref);
>>>>
>>>> @@ -721,7 +722,7 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
>>>> sg_remove_request(sfp, srp);
>>>> return -EINVAL; /* either MMAP_IO or DIRECT_IO (not both) */
>>>> }
>>>> - if (sg_res_in_use(sfp)) {
>>>> + if (test_bit(SG_RESERVED_IN_USE, &sfp->flags)) {
>>>> sg_remove_request(sfp, srp);
>>>> return -EBUSY; /* reserve buffer already being used */
>>>> }
>>>> @@ -963,10 +964,14 @@ static int max_sectors_bytes(struct request_queue *q)
>>>> val = min_t(int, val,
>>>> max_sectors_bytes(sdp->device->request_queue));
>>>> if (val != sfp->reserve.bufflen) {
>>>> - if (sg_res_in_use(sfp) || sfp->mmap_called)
>>>> + if (sfp->mmap_called)
>>>> + return -EBUSY;
>>>> + if (test_and_set_bit(SG_RESERVED_IN_USE, &sfp->flags))
>>>> return -EBUSY;
>>>> +
>>>> sg_remove_scat(sfp, &sfp->reserve);
>>>> sg_build_reserve(sfp, val);
>>>> + clear_bit(SG_RESERVED_IN_USE, &sfp->flags);
>>>
>>>
>>> This seems to be abusing an atomic bitflag as a lock.
>>
>> Hmm. I wouldn't call it 'abusing'; the driver can proceed quite happily
>> without the 'reserved' buffer, so taking a lock would be overkill.
>> I could modify it to use a mutex if you insist ...
>>
>>> And I think
>>> in general we have two different things here that this patch conflates:
>>>
>>> a) a lock to protect building and using the reserve lists
>>> b) a flag is a reservations is in use
>>>
>> No. This is not about reservations, this is about the internal
>> 'reserved' page buffer array.
>> (Just in case to avoid any misunderstandings).
>> We need to have an atomic / protected check in the 'sfp' structure if
>> the 'reserved' page buffer array is in use; there's an additional check
>> in the 'sg_request' structure (res_in_use) telling us which of the
>> requests is using it.
>
>
> So, how should we proceed here?
> We could use a mutex with only trylock, but it would be effectively the same.
>
> There is one missed user of sg_res_in_use in "case SG_SET_FORCE_LOW_DMA".
>
I've played around using a spinlock (can't use a mutex as one access in
done from softirq context), but always ended up in lockdep hell.
And in the end, we really only need to have a marker whether the
reserved array is in use or not. Which should be atomic, so we _could_
be using an atomic variable here.
Which would only ever have a value of '0' or '1', hence the use of a
bitfield here.
But if that fall foul of some style guide I could modify it to use an
atomic counter.
Cheers,
Hannes
--
Dr. Hannes Reinecke Teamlead Storage & Networking
hare@suse.de +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2017-02-15 6:55 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-01 11:22 [PATCH] sg: protect access to to 'reserved' page array Hannes Reinecke
2017-02-01 11:23 ` Johannes Thumshirn
2017-02-01 11:46 ` kbuild test robot
2017-02-01 11:49 ` kbuild test robot
2017-02-01 13:12 ` Christoph Hellwig
2017-02-01 13:18 ` Johannes Thumshirn
2017-02-01 13:21 ` Hannes Reinecke
2017-02-14 20:48 ` Dmitry Vyukov
2017-02-15 6:54 ` Hannes Reinecke
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).