userlandfs_fuse_lowlevel: fix opening directories in Tracker

- It is possible to call open() on a directory, but FUSE lowlevel
  filesystems don't implement that and expect it to be re-routed to the
  opendir call. BRoster uses this to read the dir/file attributes to
  identify it, so it could not identify directories properly.
- In ReadDir, make sure to not return more entries than asked, as this
  confuses the userlandfs protocol communication (the kernel does not
  acknowledge the readdir reply, and then the server hits an assert when
  receiving the next request instead of the ack).

Change-Id: I9c4e9a3f0fc6e9879d4cfbc0d5402a4733d2218a
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5482
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
PulkoMandy 2022-07-17 22:58:12 +02:00 committed by waddlesplash
parent 03f7a1848f
commit f0ee02b25e
3 changed files with 28 additions and 28 deletions

View File

@ -38,7 +38,7 @@ enum {
SYNC_VOLUME_REQUEST,
SYNC_VOLUME_REPLY,
READ_FS_INFO_REQUEST,
READ_FS_INFO_REPLY,
READ_FS_INFO_REPLY, // 10
WRITE_FS_INFO_REQUEST,
WRITE_FS_INFO_REPLY,
@ -50,7 +50,7 @@ enum {
READ_VNODE_REQUEST,
READ_VNODE_REPLY,
WRITE_VNODE_REQUEST,
WRITE_VNODE_REPLY,
WRITE_VNODE_REPLY, // 20
FS_REMOVE_VNODE_REQUEST,
FS_REMOVE_VNODE_REPLY,
@ -62,7 +62,7 @@ enum {
ITERATIVE_IO_GET_VECS_REQUEST,
ITERATIVE_IO_GET_VECS_REPLY,
ITERATIVE_IO_FINISHED_REQUEST,
ITERATIVE_IO_FINISHED_REPLY,
ITERATIVE_IO_FINISHED_REPLY, // 30
// nodes
IOCTL_REQUEST,
@ -74,7 +74,7 @@ enum {
DESELECT_REQUEST,
DESELECT_REPLY,
FSYNC_REQUEST,
FSYNC_REPLY,
FSYNC_REPLY, // 40
READ_SYMLINK_REQUEST,
READ_SYMLINK_REPLY,
@ -85,7 +85,7 @@ enum {
UNLINK_REQUEST,
UNLINK_REPLY,
RENAME_REQUEST,
RENAME_REPLY,
RENAME_REPLY, // 50
ACCESS_REQUEST,
ACCESS_REPLY,
@ -98,7 +98,7 @@ enum {
CREATE_REQUEST,
CREATE_REPLY,
OPEN_REQUEST,
OPEN_REPLY,
OPEN_REPLY, // 60
CLOSE_REQUEST,
CLOSE_REPLY,
FREE_COOKIE_REQUEST,
@ -110,7 +110,7 @@ enum {
// directories
CREATE_DIR_REQUEST,
CREATE_DIR_REPLY,
CREATE_DIR_REPLY, // 70
REMOVE_DIR_REQUEST,
REMOVE_DIR_REPLY,
OPEN_DIR_REQUEST,
@ -120,7 +120,7 @@ enum {
FREE_DIR_COOKIE_REQUEST,
FREE_DIR_COOKIE_REPLY,
READ_DIR_REQUEST,
READ_DIR_REPLY,
READ_DIR_REPLY, // 80
REWIND_DIR_REQUEST,
REWIND_DIR_REPLY,
@ -132,7 +132,7 @@ enum {
FREE_ATTR_DIR_COOKIE_REQUEST,
FREE_ATTR_DIR_COOKIE_REPLY,
READ_ATTR_DIR_REQUEST,
READ_ATTR_DIR_REPLY,
READ_ATTR_DIR_REPLY, // 90
REWIND_ATTR_DIR_REQUEST,
REWIND_ATTR_DIR_REPLY,
@ -144,7 +144,7 @@ enum {
CLOSE_ATTR_REQUEST,
CLOSE_ATTR_REPLY,
FREE_ATTR_COOKIE_REQUEST,
FREE_ATTR_COOKIE_REPLY,
FREE_ATTR_COOKIE_REPLY, // 100
READ_ATTR_REQUEST,
READ_ATTR_REPLY,
WRITE_ATTR_REQUEST,
@ -154,7 +154,7 @@ enum {
WRITE_ATTR_STAT_REQUEST,
WRITE_ATTR_STAT_REPLY,
RENAME_ATTR_REQUEST,
RENAME_ATTR_REPLY,
RENAME_ATTR_REPLY, // 110
REMOVE_ATTR_REQUEST,
REMOVE_ATTR_REPLY,
@ -166,7 +166,7 @@ enum {
FREE_INDEX_DIR_COOKIE_REQUEST,
FREE_INDEX_DIR_COOKIE_REPLY,
READ_INDEX_DIR_REQUEST,
READ_INDEX_DIR_REPLY,
READ_INDEX_DIR_REPLY, // 120
REWIND_INDEX_DIR_REQUEST,
REWIND_INDEX_DIR_REPLY,
CREATE_INDEX_REQUEST,
@ -178,7 +178,7 @@ enum {
// queries
OPEN_QUERY_REQUEST,
OPEN_QUERY_REPLY,
OPEN_QUERY_REPLY, // 130
CLOSE_QUERY_REQUEST,
CLOSE_QUERY_REPLY,
FREE_QUERY_COOKIE_REQUEST,
@ -190,7 +190,7 @@ enum {
// node monitoring
NODE_MONITORING_EVENT_REQUEST,
NODE_MONITORING_EVENT_REPLY,
NODE_MONITORING_EVENT_REPLY, // 140
// userland -> kernel requests
// notifications
@ -205,7 +205,7 @@ enum {
GET_VNODE_REQUEST,
GET_VNODE_REPLY,
PUT_VNODE_REQUEST,
PUT_VNODE_REPLY,
PUT_VNODE_REPLY, // 150
ACQUIRE_VNODE_REQUEST,
ACQUIRE_VNODE_REPLY,
NEW_VNODE_REQUEST,
@ -215,7 +215,7 @@ enum {
REMOVE_VNODE_REQUEST,
REMOVE_VNODE_REPLY,
UNREMOVE_VNODE_REQUEST,
UNREMOVE_VNODE_REPLY,
UNREMOVE_VNODE_REPLY, // 160
GET_VNODE_REMOVED_REQUEST,
GET_VNODE_REMOVED_REPLY,
@ -227,7 +227,7 @@ enum {
FILE_CACHE_SET_ENABLED_REQUEST,
FILE_CACHE_SET_ENABLED_REPLY,
FILE_CACHE_SET_SIZE_REQUEST,
FILE_CACHE_SET_SIZE_REPLY,
FILE_CACHE_SET_SIZE_REPLY, // 170
FILE_CACHE_SYNC_REQUEST,
FILE_CACHE_SYNC_REPLY,
FILE_CACHE_READ_REQUEST,
@ -239,7 +239,7 @@ enum {
DO_ITERATIVE_FD_IO_REQUEST,
DO_ITERATIVE_FD_IO_REPLY,
READ_FROM_IO_REQUEST_REQUEST,
READ_FROM_IO_REQUEST_REPLY,
READ_FROM_IO_REQUEST_REPLY, // 180
WRITE_TO_IO_REQUEST_REQUEST,
WRITE_TO_IO_REQUEST_REPLY,
NOTIFY_IO_REQUEST_REQUEST,
@ -255,7 +255,7 @@ enum {
RECEIPT_ACK_REPLY,
// invalid request ID (e.g. for request handlers)
NO_REQUEST,
NO_REQUEST, // 190
};
namespace UserlandFSUtil {

View File

@ -506,8 +506,7 @@ FUSEFileSystem::_InitCapabilities()
bool hasAttributes = fLowLevelOps.listxattr != NULL;
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_OPEN_ATTR_DIR, hasAttributes);
// not needed: FS_VNODE_CAPABILITY_CLOSE_ATTR_DIR
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_DIR_COOKIE,
hasAttributes);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_DIR_COOKIE, hasAttributes);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_DIR, hasAttributes);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_REWIND_ATTR_DIR, hasAttributes);
@ -521,8 +520,7 @@ FUSEFileSystem::_InitCapabilities()
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR, fLowLevelOps.getxattr);
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_ATTR, fLowLevelOps.write_attr);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_STAT,
fLowLevelOps.getxattr);
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_STAT, fLowLevelOps.getxattr);
// // missing: FS_VNODE_CAPABILITY_WRITE_ATTR_STAT
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_RENAME_ATTR, fLowLevelOps.rename_attr);
} else {

View File

@ -1654,12 +1654,14 @@ FUSEVolume::Open(void* _node, int openMode, void** _cookie)
size_t pathLen;
int fuseError;
struct fuse_file_info llCookie;
struct fuse_file_info llCookie = { 0 };
// FIXME store this in the FileCookie for lowlevel streams, we'll need it in read, write...
if (fOps != NULL) {
llCookie.flags = openMode;
// TODO do we need to perform a conversion here?
fuseError = fuse_ll_open(fOps, node->id, &llCookie);
if (S_ISDIR(node->type))
fuseError = fuse_ll_opendir(fOps, node->id, &llCookie);
else
fuseError = fuse_ll_open(fOps, node->id, &llCookie);
} else {
AutoLocker<Locker> locker(fLock);
@ -2154,8 +2156,8 @@ FUSEVolume::ReadDir(void* _node, void* _cookie, void* buffer, size_t bufferSize,
// currentEntryOffset.
if (fuseError > 0) {
struct dirent* dirent = (struct dirent*)buffer;
countRead = 0;
while ((char*)dirent + dirent->d_reclen <= (char*)buffer + fuseError) {
while (countRead < count
&& (char*)dirent + dirent->d_reclen <= (char*)buffer + fuseError) {
countRead++;
dirent = (struct dirent*)(((char*)dirent) + dirent->d_reclen);
if (dirent->d_reclen == 0)