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
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user