[rh7] fuse: allow kernel to access "direct_io" files

Submitted by Andrey Ryabinin on Sept. 27, 2019, 11:24 a.m.

Details

Message ID c943ec64-cf17-8ce9-7e0c-88660cb7b046@virtuozzo.com
State New
Series "fuse: allow kernel to access "direct_io" files"
Headers show

Commit Message

Andrey Ryabinin Sept. 27, 2019, 11:24 a.m.
On 9/27/19 2:18 PM, Evgenii Shatokhin wrote:
> On 26.09.2019 18:52, Andrey Ryabinin wrote:
>> From: Miklos Szeredi <mszeredi@suse.cz>
>>
>> Allow the kernel read and write on "direct_io" files.  This is
>> necessary for nfs export and execute support.
>>
>> The implementation is simple: if an access from the kernel is
>> detected, don't perform get_user_pages(), just use the kernel address
>> provided by the requester to copy from/to the userspace filesystem.
>>
>> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
>>
>> https://jira.sw.ru/browse/PSBM-97905
>> (cherry picked from commit f4975c67dd9ad8eb47a4c77af0521a2b16ee0197)
>> Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
>> ---
>>   fs/fuse/file.c | 12 ++++++++++++
>>   1 file changed, 12 insertions(+)
>>
>> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
>> index 344f35562bbe..ec8a0b07a5d6 100644
>> --- a/fs/fuse/file.c
>> +++ b/fs/fuse/file.c
>> @@ -1702,6 +1702,18 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
>>   			       size_t *nbytesp, int write)
>>   {
>>   	size_t nbytes = 0;  /* # bytes already packed in req */
>> +	/* Special case for kernel I/O: can copy directly into the buffer */
>> +	if (segment_eq(get_fs(), KERNEL_DS)) {
>> +		unsigned long user_addr = fuse_get_user_addr(ii);
>> +		size_t frag_size = fuse_get_frag_size(ii, *nbytesp);
> 
> 'frag_size' is not used here. Should it be removed?

Nope it should be used. Fixup:

---
 fs/fuse/file.c | 2 ++
 1 file changed, 2 insertions(+)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index ec8a0b07a5d6..cd51a16bc296 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1712,6 +1712,8 @@  static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
 		else
 			req->out.args[0].value = (void *) user_addr;
 
+		iov_iter_advance(ii, frag_size);
+		*nbytesp = frag_size;
 		return 0;
 	}
 

Comments

Andrey Ryabinin Sept. 27, 2019, 11:45 a.m.
On 9/27/19 2:24 PM, Andrey Ryabinin wrote:
> 
> 
> On 9/27/19 2:18 PM, Evgenii Shatokhin wrote:
>> On 26.09.2019 18:52, Andrey Ryabinin wrote:
>>> From: Miklos Szeredi <mszeredi@suse.cz>
>>>
>>> Allow the kernel read and write on "direct_io" files.  This is
>>> necessary for nfs export and execute support.
>>>
>>> The implementation is simple: if an access from the kernel is
>>> detected, don't perform get_user_pages(), just use the kernel address
>>> provided by the requester to copy from/to the userspace filesystem.
>>>
>>> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
>>>
>>> https://jira.sw.ru/browse/PSBM-97905
>>> (cherry picked from commit f4975c67dd9ad8eb47a4c77af0521a2b16ee0197)
>>> Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
>>> ---
>>>   fs/fuse/file.c | 12 ++++++++++++
>>>   1 file changed, 12 insertions(+)
>>>
>>> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
>>> index 344f35562bbe..ec8a0b07a5d6 100644
>>> --- a/fs/fuse/file.c
>>> +++ b/fs/fuse/file.c
>>> @@ -1702,6 +1702,18 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
>>>   			       size_t *nbytesp, int write)
>>>   {
>>>   	size_t nbytes = 0;  /* # bytes already packed in req */
>>> +	/* Special case for kernel I/O: can copy directly into the buffer */
>>> +	if (segment_eq(get_fs(), KERNEL_DS)) {
>>> +		unsigned long user_addr = fuse_get_user_addr(ii);
>>> +		size_t frag_size = fuse_get_frag_size(ii, *nbytesp);
>>
>> 'frag_size' is not used here. Should it be removed?
> 
> Nope it should be used. Fixup:
> 

Sent corrected version, also changed commit message, since we actually have f4975c67dd9ad8eb47a4c77af0521a2b16ee0197 ("fuse: allow kernel to access "direct_io" files")
in our kernel. We just lost the hunk in some patch later.