fuse: reduce size of struct fuse_inode
authorMiklos Szeredi <mszeredi@redhat.com>
Mon, 1 Oct 2018 08:07:05 +0000 (10:07 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Mon, 1 Oct 2018 08:07:05 +0000 (10:07 +0200)
Do this by grouping fields used for cached writes and putting them into a
union with fileds used for cached readdir (with obviously no overlap, since
we don't have hybrid objects).

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c

index 6800fdc3e73094ea9c9472c40e376d2f674a8522..d1b2f42d746e9fa6710f67e21586001edae35d9a 100644 (file)
@@ -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)
index e10c0443c56fa58f51689c492d756c3c97229ff0..b10d14baeb1f0711ee4005e1321f411817556af0 100644 (file)
@@ -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);
 }
index d9d1ea78efa6e442dde3ac8362b412f70ada75fd..f5bdce84e76673a20d21a32be0efce8ffaa92587 100644 (file)
@@ -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;
index eef2ae713f75a55bcbfcb59b8d609cfc29c9e97d..82db1ab53420955c146955482fac3d5b58ceb1b2 100644 (file)
@@ -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);