Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6081434 authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Maintain the fuse buffer pool keyed by inode instead of threadId.

In order to save memory, FuseAppLoop maintains a buffer pool to use
when dispatching the read/write requests. Currently, it uses
the threadId of the ProxyFileDescriptorCallback as the key for this
buffer pool and this can result in an issue when a caller creates
multiple ProxyFileDescriptors with ProxyFileDescriptorCallbacks
running on the same thread. When this happens, it is possible that
a buffer is reused before a read/write request which was using it
earlier has been handled and would result in data from read/write
requests on different fds getting mixed up.

Bug: 158568683
Test: atest --test-mapping apex/blobstore
Change-Id: Iaffd54f4430ecb3778f01c80f5a1684ac448f8dc
parent 38da493a
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -210,7 +210,7 @@ public class FuseAppLoop implements Handler.Callback {
                        if (mInstance != 0) {
                            native_replySimple(mInstance, unique, FUSE_OK);
                        }
                        mBytesMap.stopUsing(entry.getThreadId());
                        mBytesMap.stopUsing(inode);
                        recycleLocked(args);
                    }
                    break;
@@ -270,7 +270,7 @@ public class FuseAppLoop implements Handler.Callback {
                if (mInstance != 0) {
                    native_replyOpen(mInstance, unique, /* fh */ inode);
                    entry.opened = true;
                    return mBytesMap.startUsing(entry.getThreadId());
                    return mBytesMap.startUsing(inode);
                }
            } catch (ErrnoException error) {
                replySimpleLocked(unique, getError(error));
@@ -354,27 +354,27 @@ public class FuseAppLoop implements Handler.Callback {
    }

    /**
     * Map between Thread ID and byte buffer.
     * Map between inode and byte buffer.
     */
    private static class BytesMap {
        final Map<Long, BytesMapEntry> mEntries = new HashMap<>();

        byte[] startUsing(long threadId) {
            BytesMapEntry entry = mEntries.get(threadId);
        byte[] startUsing(long inode) {
            BytesMapEntry entry = mEntries.get(inode);
            if (entry == null) {
                entry = new BytesMapEntry();
                mEntries.put(threadId, entry);
                mEntries.put(inode, entry);
            }
            entry.counter++;
            return entry.bytes;
        }

        void stopUsing(long threadId) {
            final BytesMapEntry entry = mEntries.get(threadId);
        void stopUsing(long inode) {
            final BytesMapEntry entry = mEntries.get(inode);
            Objects.requireNonNull(entry);
            entry.counter--;
            if (entry.counter <= 0) {
                mEntries.remove(threadId);
                mEntries.remove(inode);
            }
        }