diff options
| -rw-r--r-- | fs/fuse/dir.c | 13 | ||||
| -rw-r--r-- | fs/fuse/file.c | 8 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 62 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 16 |
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, | |||
| 1414 | file = NULL; | 1414 | file = NULL; |
| 1415 | } | 1415 | } |
| 1416 | 1416 | ||
| 1417 | if (attr->ia_valid & ATTR_SIZE) | 1417 | if (attr->ia_valid & ATTR_SIZE) { |
| 1418 | if (WARN_ON(!S_ISREG(inode->i_mode))) | ||
| 1419 | return -EIO; | ||
| 1418 | is_truncate = true; | 1420 | is_truncate = true; |
| 1421 | } | ||
| 1419 | 1422 | ||
| 1420 | if (is_truncate) { | 1423 | if (is_truncate) { |
| 1421 | fuse_set_nowrite(inode); | 1424 | fuse_set_nowrite(inode); |
| @@ -1619,8 +1622,16 @@ void fuse_init_common(struct inode *inode) | |||
| 1619 | 1622 | ||
| 1620 | void fuse_init_dir(struct inode *inode) | 1623 | void fuse_init_dir(struct inode *inode) |
| 1621 | { | 1624 | { |
| 1625 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 1626 | |||
| 1622 | inode->i_op = &fuse_dir_inode_operations; | 1627 | inode->i_op = &fuse_dir_inode_operations; |
| 1623 | inode->i_fop = &fuse_dir_operations; | 1628 | inode->i_fop = &fuse_dir_operations; |
| 1629 | |||
| 1630 | spin_lock_init(&fi->rdc.lock); | ||
| 1631 | fi->rdc.cached = false; | ||
| 1632 | fi->rdc.size = 0; | ||
| 1633 | fi->rdc.pos = 0; | ||
| 1634 | fi->rdc.version = 0; | ||
| 1624 | } | 1635 | } |
| 1625 | 1636 | ||
| 1626 | void fuse_init_symlink(struct inode *inode) | 1637 | 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 = { | |||
| 3143 | 3143 | ||
| 3144 | void fuse_init_file_inode(struct inode *inode) | 3144 | void fuse_init_file_inode(struct inode *inode) |
| 3145 | { | 3145 | { |
| 3146 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 3147 | |||
| 3146 | inode->i_fop = &fuse_file_operations; | 3148 | inode->i_fop = &fuse_file_operations; |
| 3147 | inode->i_data.a_ops = &fuse_file_aops; | 3149 | inode->i_data.a_ops = &fuse_file_aops; |
| 3150 | |||
| 3151 | INIT_LIST_HEAD(&fi->write_files); | ||
| 3152 | INIT_LIST_HEAD(&fi->queued_writes); | ||
| 3153 | fi->writectr = 0; | ||
| 3154 | init_waitqueue_head(&fi->page_waitq); | ||
| 3155 | INIT_LIST_HEAD(&fi->writepages); | ||
| 3148 | } | 3156 | } |
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 { | |||
| 87 | /** Version of last attribute change */ | 87 | /** Version of last attribute change */ |
| 88 | u64 attr_version; | 88 | u64 attr_version; |
| 89 | 89 | ||
| 90 | /** Files usable in writepage. Protected by fc->lock */ | 90 | union { |
| 91 | struct list_head write_files; | 91 | /* Write related fields (regular file only) */ |
| 92 | struct { | ||
| 93 | /* Files usable in writepage. Protected by fc->lock */ | ||
| 94 | struct list_head write_files; | ||
| 92 | 95 | ||
| 93 | /** Writepages pending on truncate or fsync */ | 96 | /* Writepages pending on truncate or fsync */ |
| 94 | struct list_head queued_writes; | 97 | struct list_head queued_writes; |
| 95 | 98 | ||
| 96 | /** Number of sent writes, a negative bias (FUSE_NOWRITE) | 99 | /* Number of sent writes, a negative bias |
| 97 | * means more writes are blocked */ | 100 | * (FUSE_NOWRITE) means more writes are blocked */ |
| 98 | int writectr; | 101 | int writectr; |
| 99 | 102 | ||
| 100 | /** Waitq for writepage completion */ | 103 | /* Waitq for writepage completion */ |
| 101 | wait_queue_head_t page_waitq; | 104 | wait_queue_head_t page_waitq; |
| 102 | 105 | ||
| 103 | /** List of writepage requestst (pending or sent) */ | 106 | /* List of writepage requestst (pending or sent) */ |
| 104 | struct list_head writepages; | 107 | struct list_head writepages; |
| 108 | }; | ||
| 105 | 109 | ||
| 106 | /* readdir cache */ | 110 | /* readdir cache (directory only) */ |
| 107 | struct { | 111 | struct { |
| 108 | /* true if fully cached */ | 112 | /* true if fully cached */ |
| 109 | bool cached; | 113 | bool cached; |
| 110 | 114 | ||
| 111 | /* size of cache */ | 115 | /* size of cache */ |
| 112 | loff_t size; | 116 | loff_t size; |
| 113 | 117 | ||
| 114 | /* position at end of cache (position of next entry) */ | 118 | /* position at end of cache (position of next entry) */ |
| 115 | loff_t pos; | 119 | loff_t pos; |
| 116 | 120 | ||
| 117 | /* version of the cache */ | 121 | /* version of the cache */ |
| 118 | u64 version; | 122 | u64 version; |
| 119 | 123 | ||
| 120 | /* modification time of directory when cache was started */ | 124 | /* modification time of directory when cache was |
| 121 | struct timespec64 mtime; | 125 | * started */ |
| 126 | struct timespec64 mtime; | ||
| 122 | 127 | ||
| 123 | /* iversion of directory when cache was started */ | 128 | /* iversion of directory when cache was started */ |
| 124 | u64 iversion; | 129 | u64 iversion; |
| 125 | 130 | ||
| 126 | /* protects above fields */ | 131 | /* protects above fields */ |
| 127 | spinlock_t lock; | 132 | spinlock_t lock; |
| 128 | } rdc; | 133 | } rdc; |
| 134 | }; | ||
| 129 | 135 | ||
| 130 | /** Miscellaneous bits describing inode state */ | 136 | /** Miscellaneous bits describing inode state */ |
| 131 | unsigned long state; | 137 | 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) | |||
| 93 | fi->nodeid = 0; | 93 | fi->nodeid = 0; |
| 94 | fi->nlookup = 0; | 94 | fi->nlookup = 0; |
| 95 | fi->attr_version = 0; | 95 | fi->attr_version = 0; |
| 96 | fi->writectr = 0; | ||
| 97 | fi->orig_ino = 0; | 96 | fi->orig_ino = 0; |
| 98 | fi->state = 0; | 97 | fi->state = 0; |
| 99 | INIT_LIST_HEAD(&fi->write_files); | ||
| 100 | INIT_LIST_HEAD(&fi->queued_writes); | ||
| 101 | INIT_LIST_HEAD(&fi->writepages); | ||
| 102 | init_waitqueue_head(&fi->page_waitq); | ||
| 103 | spin_lock_init(&fi->rdc.lock); | ||
| 104 | fi->rdc.cached = false; | ||
| 105 | fi->rdc.size = 0; | ||
| 106 | fi->rdc.pos = 0; | ||
| 107 | fi->rdc.version = 0; | ||
| 108 | mutex_init(&fi->mutex); | 98 | mutex_init(&fi->mutex); |
| 109 | fi->forget = fuse_alloc_forget(); | 99 | fi->forget = fuse_alloc_forget(); |
| 110 | if (!fi->forget) { | 100 | if (!fi->forget) { |
| @@ -124,8 +114,10 @@ static void fuse_i_callback(struct rcu_head *head) | |||
| 124 | static void fuse_destroy_inode(struct inode *inode) | 114 | static void fuse_destroy_inode(struct inode *inode) |
| 125 | { | 115 | { |
| 126 | struct fuse_inode *fi = get_fuse_inode(inode); | 116 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 127 | BUG_ON(!list_empty(&fi->write_files)); | 117 | if (S_ISREG(inode->i_mode)) { |
| 128 | BUG_ON(!list_empty(&fi->queued_writes)); | 118 | WARN_ON(!list_empty(&fi->write_files)); |
| 119 | WARN_ON(!list_empty(&fi->queued_writes)); | ||
| 120 | } | ||
| 129 | mutex_destroy(&fi->mutex); | 121 | mutex_destroy(&fi->mutex); |
| 130 | kfree(fi->forget); | 122 | kfree(fi->forget); |
| 131 | call_rcu(&inode->i_rcu, fuse_i_callback); | 123 | call_rcu(&inode->i_rcu, fuse_i_callback); |
