aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dir.c13
-rw-r--r--fs/fuse/file.c8
-rw-r--r--fs/fuse/fuse_i.h62
-rw-r--r--fs/fuse/inode.c16
4 files changed, 58 insertions, 41 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 6800fdc3e730..d1b2f42d746e 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1414,8 +1414,11 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
file = NULL;
}
- if (attr->ia_valid & ATTR_SIZE)
+ if (attr->ia_valid & ATTR_SIZE) {
+ if (WARN_ON(!S_ISREG(inode->i_mode)))
+ return -EIO;
is_truncate = true;
+ }
if (is_truncate) {
fuse_set_nowrite(inode);
@@ -1619,8 +1622,16 @@ void fuse_init_common(struct inode *inode)
void fuse_init_dir(struct inode *inode)
{
+ struct fuse_inode *fi = get_fuse_inode(inode);
+
inode->i_op = &fuse_dir_inode_operations;
inode->i_fop = &fuse_dir_operations;
+
+ spin_lock_init(&fi->rdc.lock);
+ fi->rdc.cached = false;
+ fi->rdc.size = 0;
+ fi->rdc.pos = 0;
+ fi->rdc.version = 0;
}
void fuse_init_symlink(struct inode *inode)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e10c0443c56f..b10d14baeb1f 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -3143,6 +3143,14 @@ static const struct address_space_operations fuse_file_aops = {
void fuse_init_file_inode(struct inode *inode)
{
+ struct fuse_inode *fi = get_fuse_inode(inode);
+
inode->i_fop = &fuse_file_operations;
inode->i_data.a_ops = &fuse_file_aops;
+
+ INIT_LIST_HEAD(&fi->write_files);
+ INIT_LIST_HEAD(&fi->queued_writes);
+ fi->writectr = 0;
+ init_waitqueue_head(&fi->page_waitq);
+ INIT_LIST_HEAD(&fi->writepages);
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d9d1ea78efa6..f5bdce84e766 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -87,45 +87,51 @@ struct fuse_inode {
/** Version of last attribute change */
u64 attr_version;
- /** Files usable in writepage. Protected by fc->lock */
- struct list_head write_files;
+ union {
+ /* Write related fields (regular file only) */
+ struct {
+ /* Files usable in writepage. Protected by fc->lock */
+ struct list_head write_files;
- /** Writepages pending on truncate or fsync */
- struct list_head queued_writes;
+ /* Writepages pending on truncate or fsync */
+ struct list_head queued_writes;
- /** Number of sent writes, a negative bias (FUSE_NOWRITE)
- * means more writes are blocked */
- int writectr;
+ /* Number of sent writes, a negative bias
+ * (FUSE_NOWRITE) means more writes are blocked */
+ int writectr;
- /** Waitq for writepage completion */
- wait_queue_head_t page_waitq;
+ /* Waitq for writepage completion */
+ wait_queue_head_t page_waitq;
- /** List of writepage requestst (pending or sent) */
- struct list_head writepages;
+ /* List of writepage requestst (pending or sent) */
+ struct list_head writepages;
+ };
- /* readdir cache */
- struct {
- /* true if fully cached */
- bool cached;
+ /* readdir cache (directory only) */
+ struct {
+ /* true if fully cached */
+ bool cached;
- /* size of cache */
- loff_t size;
+ /* size of cache */
+ loff_t size;
- /* position at end of cache (position of next entry) */
- loff_t pos;
+ /* position at end of cache (position of next entry) */
+ loff_t pos;
- /* version of the cache */
- u64 version;
+ /* version of the cache */
+ u64 version;
- /* modification time of directory when cache was started */
- struct timespec64 mtime;
+ /* modification time of directory when cache was
+ * started */
+ struct timespec64 mtime;
- /* iversion of directory when cache was started */
- u64 iversion;
+ /* iversion of directory when cache was started */
+ u64 iversion;
- /* protects above fields */
- spinlock_t lock;
- } rdc;
+ /* protects above fields */
+ spinlock_t lock;
+ } rdc;
+ };
/** Miscellaneous bits describing inode state */
unsigned long state;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index eef2ae713f75..82db1ab53420 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -93,18 +93,8 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
fi->nodeid = 0;
fi->nlookup = 0;
fi->attr_version = 0;
- fi->writectr = 0;
fi->orig_ino = 0;
fi->state = 0;
- INIT_LIST_HEAD(&fi->write_files);
- INIT_LIST_HEAD(&fi->queued_writes);
- INIT_LIST_HEAD(&fi->writepages);
- init_waitqueue_head(&fi->page_waitq);
- spin_lock_init(&fi->rdc.lock);
- fi->rdc.cached = false;
- fi->rdc.size = 0;
- fi->rdc.pos = 0;
- fi->rdc.version = 0;
mutex_init(&fi->mutex);
fi->forget = fuse_alloc_forget();
if (!fi->forget) {
@@ -124,8 +114,10 @@ static void fuse_i_callback(struct rcu_head *head)
static void fuse_destroy_inode(struct inode *inode)
{
struct fuse_inode *fi = get_fuse_inode(inode);
- BUG_ON(!list_empty(&fi->write_files));
- BUG_ON(!list_empty(&fi->queued_writes));
+ if (S_ISREG(inode->i_mode)) {
+ WARN_ON(!list_empty(&fi->write_files));
+ WARN_ON(!list_empty(&fi->queued_writes));
+ }
mutex_destroy(&fi->mutex);
kfree(fi->forget);
call_rcu(&inode->i_rcu, fuse_i_callback);