ntfs: read() and write() now pass a kernel buffer to libntfs.

when a user buffer is provided, we now pass a 128KB kernel buffer
to libntfs. The old loop in case of partial buffer read/write
was useless as ntfs_attr_pread() and ntfs_attr_pwrite() were
provided the same buffer. The new loop fills/dumps the user buffer
from/to the kernel buffer.
when a kernel buffer is provided, it is passed to libntfs, the new
loop exits after one cycle.
This commit is contained in:
Jérôme Duval 2018-07-08 13:06:25 +02:00
parent b0e0298370
commit f8d3a9ee49
2 changed files with 67 additions and 16 deletions

View File

@ -34,9 +34,11 @@
#include <time.h>
#include <unistd.h>
#include <disk_device_manager.h>
#include <driver_settings.h>
#include <KernelExport.h>
#include <disk_device_manager.h>
#include <kernel.h>
#include "attributes.h"
#include "fake_attributes.h"
@ -44,6 +46,7 @@
#include "ntfs.h"
#include "volume_util.h"
extern int mkntfs_main(const char *devpath, const char *label);
typedef struct identify_cookie {
@ -1191,8 +1194,10 @@ fs_read(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t offset, void *buf
ntfs_inode *ni = NULL;
ntfs_attr *na = NULL;
size_t size = *len;
int total = 0;
size_t total = 0;
status_t result = B_OK;
void *tempBuffer = NULL;
addr_t buffer = (addr_t)buf;
LOCK_VOL(ns);
@ -1227,26 +1232,47 @@ fs_read(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t offset, void *buf
if (offset + size > na->data_size)
size = na->data_size - offset;
while (size) {
off_t bytesRead = ntfs_attr_pread(na, offset, size, buf);
if (bytesRead < (s64)size) {
ntfs_log_error("ntfs_attr_pread returned less bytes than "
"requested.\n");
}
if (bytesRead <= 0) {
if (IS_USER_ADDRESS(buf)) {
tempBuffer = malloc(TEMP_BUFFER_SIZE);
if (tempBuffer == NULL) {
*len = 0;
result = EINVAL;
result = B_NO_MEMORY;
goto exit;
}
}
while (size > 0) {
s64 sizeToRead = size;
if (tempBuffer != NULL && size > TEMP_BUFFER_SIZE)
sizeToRead = TEMP_BUFFER_SIZE;
s64 bytesRead = ntfs_attr_pread(na, offset, sizeToRead,
tempBuffer != NULL ? tempBuffer : (void*)buffer);
if (bytesRead <= 0) {
*len = 0;
result = errno;
goto exit;
}
if (tempBuffer != NULL
&& user_memcpy((void*)buffer, tempBuffer, bytesRead) < B_OK) {
result = B_BAD_ADDRESS;
goto exit;
}
buffer += bytesRead;
size -= bytesRead;
offset += bytesRead;
total += bytesRead;
if (bytesRead < sizeToRead) {
ntfs_log_error("ntfs_attr_pread returned less bytes than "
"requested.\n");
break;
}
}
*len = total;
fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME);
exit:
free(tempBuffer);
if (na != NULL)
ntfs_attr_close(na);
@ -1271,9 +1297,11 @@ fs_write(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t offset,
filecookie *cookie = (filecookie*)_cookie;
ntfs_inode *ni = NULL;
ntfs_attr *na = NULL;
int total = 0;
size_t total = 0;
size_t size = *len;
status_t result = B_OK;
void *tempBuffer = NULL;
addr_t buffer = (addr_t)buf;
if (ns->flags & B_FS_IS_READONLY) {
ERROR("ntfs is read-only\n");
@ -1324,21 +1352,42 @@ fs_write(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t offset,
notify_stat_changed(ns->id, -1, node->vnid, B_STAT_SIZE);
}
while (size) {
off_t bytesWritten = ntfs_attr_pwrite(na, offset, size, buf);
if (bytesWritten < (s64)size) {
ERROR("fs_write - ntfs_attr_pwrite returned less bytes than "
"requested.\n");
if (IS_USER_ADDRESS(buf)) {
tempBuffer = malloc(TEMP_BUFFER_SIZE);
if (tempBuffer == NULL) {
*len = 0;
result = B_NO_MEMORY;
goto exit;
}
}
while (size > 0) {
s64 sizeToWrite = size;
if (tempBuffer != NULL) {
if (size > TEMP_BUFFER_SIZE)
sizeToWrite = TEMP_BUFFER_SIZE;
if (user_memcpy(tempBuffer, (void*)buffer, sizeToWrite) < B_OK) {
result = B_BAD_ADDRESS;
goto exit;
}
}
s64 bytesWritten = ntfs_attr_pwrite(na, offset, sizeToWrite,
tempBuffer != NULL ? tempBuffer : (void*)buffer);
if (bytesWritten <= 0) {
ERROR("fs_write - ntfs_attr_pwrite()<=0\n");
*len = 0;
result = EINVAL;
goto exit;
}
buffer += bytesWritten;
size -= bytesWritten;
offset += bytesWritten;
total += bytesWritten;
if (bytesWritten < sizeToWrite) {
ERROR("fs_write - ntfs_attr_pwrite returned less bytes than "
"requested.\n");
break;
}
}
*len = total;
@ -1348,6 +1397,7 @@ fs_write(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t offset,
TRACE("fs_write - OK\n");
exit:
free(tempBuffer);
if (na != NULL)
ntfs_attr_close(na);
exit2:

View File

@ -59,6 +59,7 @@ extern "C" {
#define ERROR dprintf
#define DEV_FD(dev) (*(int *)dev->d_private)
#define TEMP_BUFFER_SIZE (B_PAGE_SIZE * 32)
#define LOCK_VOL(vol) \
{ \