ANDROID: fuse: Adjust Passthrough for writeback cache
This adjusts some tracking to allow passthrough and writeback cache to
co-exist with eachother
Change-Id: I5b8b3940a8c096cd3598d7c188439c6c636c01a1
Bug: 372951405
Fixes: 3ae410445f ("ANDROID: fuse: Allow passthrough and not passthrough")
test: atest android.scopedstorage.cts.general.ScopedStorageDeviceTest
Signed-off-by: Daniel Rosenberg <drosen@google.com>
This commit is contained in:
@@ -3539,6 +3539,7 @@ void fuse_init_file_inode(struct inode *inode, unsigned int flags)
|
||||
INIT_LIST_HEAD(&fi->queued_writes);
|
||||
fi->writectr = 0;
|
||||
fi->iocachectr = 0;
|
||||
fi->iopassctr = 0;
|
||||
init_waitqueue_head(&fi->page_waitq);
|
||||
init_waitqueue_head(&fi->direct_io_waitq);
|
||||
fi->writepages = RB_ROOT;
|
||||
|
||||
+4
-1
@@ -195,6 +195,9 @@ struct fuse_inode {
|
||||
/** Number of files/maps using page cache */
|
||||
int iocachectr;
|
||||
|
||||
/* Number of files using passthrough */
|
||||
int iopassctr;
|
||||
|
||||
/* Waitq for writepage completion */
|
||||
wait_queue_head_t page_waitq;
|
||||
|
||||
@@ -328,7 +331,7 @@ struct fuse_file {
|
||||
wait_queue_head_t poll_wait;
|
||||
|
||||
/** Does file hold a fi->iocachectr refcount? */
|
||||
enum { IOM_NONE, IOM_CACHED, IOM_UNCACHED } iomode;
|
||||
enum { IOM_NONE, IOM_CACHED, IOM_UNCACHED, IOM_PASSTHROUGH } iomode;
|
||||
|
||||
#ifdef CONFIG_FUSE_PASSTHROUGH
|
||||
/** Reference to backing file in passthrough mode */
|
||||
|
||||
@@ -184,6 +184,7 @@ static void fuse_evict_inode(struct inode *inode)
|
||||
}
|
||||
if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) {
|
||||
WARN_ON(fi->iocachectr != 0);
|
||||
WARN_ON(fi->iopassctr != 0);
|
||||
WARN_ON(!list_empty(&fi->write_files));
|
||||
WARN_ON(!list_empty(&fi->queued_writes));
|
||||
}
|
||||
|
||||
+36
-5
@@ -62,6 +62,7 @@ int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff)
|
||||
#endif
|
||||
|
||||
WARN_ON(ff->iomode == IOM_UNCACHED);
|
||||
WARN_ON(ff->iomode == IOM_PASSTHROUGH);
|
||||
if (ff->iomode == IOM_NONE) {
|
||||
ff->iomode = IOM_CACHED;
|
||||
if (fi->iocachectr == 0)
|
||||
@@ -85,7 +86,7 @@ static void fuse_file_cached_io_release(struct fuse_file *ff,
|
||||
spin_unlock(&fi->lock);
|
||||
}
|
||||
|
||||
/* Start strictly uncached io mode where cache access is not allowed */
|
||||
/* Start strictly uncached io mode where cache access is not allowed if not in passthrough mode */
|
||||
int fuse_inode_uncached_io_start(struct fuse_inode *fi, struct fuse_backing *fb)
|
||||
{
|
||||
struct fuse_backing *oldfb;
|
||||
@@ -98,11 +99,14 @@ int fuse_inode_uncached_io_start(struct fuse_inode *fi, struct fuse_backing *fb)
|
||||
err = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
if (fi->iocachectr > 0) {
|
||||
if (!fb && fi->iocachectr > 0) {
|
||||
err = -ETXTBSY;
|
||||
goto unlock;
|
||||
}
|
||||
fi->iocachectr--;
|
||||
if (fb)
|
||||
fi->iopassctr++;
|
||||
else
|
||||
fi->iocachectr--;
|
||||
|
||||
/* fuse inode holds a single refcount of backing file */
|
||||
if (fb && !oldfb) {
|
||||
@@ -129,7 +133,7 @@ static int fuse_file_uncached_io_open(struct inode *inode,
|
||||
return err;
|
||||
|
||||
WARN_ON(ff->iomode != IOM_NONE);
|
||||
ff->iomode = IOM_UNCACHED;
|
||||
ff->iomode = IOM_PASSTHROUGH;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -158,6 +162,30 @@ static void fuse_file_uncached_io_release(struct fuse_file *ff,
|
||||
fuse_inode_uncached_io_end(fi);
|
||||
}
|
||||
|
||||
static void fuse_inode_passthrough_io_end(struct fuse_inode *fi)
|
||||
{
|
||||
struct fuse_backing *oldfb = NULL;
|
||||
|
||||
spin_lock(&fi->lock);
|
||||
WARN_ON(fi->iopassctr == 0);
|
||||
fi->iopassctr--;
|
||||
if (!fi->iopassctr) {
|
||||
oldfb = fuse_inode_backing_set(fi, NULL);
|
||||
}
|
||||
spin_unlock(&fi->lock);
|
||||
if (oldfb)
|
||||
fuse_backing_put(oldfb);
|
||||
}
|
||||
|
||||
/* Drop uncached_io reference from passthrough open */
|
||||
static void fuse_file_passthrough_io_release(struct fuse_file *ff,
|
||||
struct fuse_inode *fi)
|
||||
{
|
||||
WARN_ON(ff->iomode != IOM_PASSTHROUGH);
|
||||
ff->iomode = IOM_NONE;
|
||||
fuse_inode_passthrough_io_end(fi);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open flags that are allowed in combination with FOPEN_PASSTHROUGH.
|
||||
* A combination of FOPEN_PASSTHROUGH and FOPEN_DIRECT_IO means that read/write
|
||||
@@ -167,7 +195,7 @@ static void fuse_file_uncached_io_release(struct fuse_file *ff,
|
||||
*/
|
||||
#define FOPEN_PASSTHROUGH_MASK \
|
||||
(FOPEN_PASSTHROUGH | FOPEN_DIRECT_IO | FOPEN_PARALLEL_DIRECT_WRITES | \
|
||||
FOPEN_NOFLUSH)
|
||||
FOPEN_NOFLUSH | FOPEN_KEEP_CACHE)
|
||||
|
||||
static int fuse_file_passthrough_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
@@ -277,5 +305,8 @@ void fuse_file_io_release(struct fuse_file *ff, struct inode *inode)
|
||||
case IOM_CACHED:
|
||||
fuse_file_cached_io_release(ff, fi);
|
||||
break;
|
||||
case IOM_PASSTHROUGH:
|
||||
fuse_file_passthrough_io_release(ff, fi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user