diff options
Diffstat (limited to 'fs/udf')
-rw-r--r-- | fs/udf/file.c | 8 | ||||
-rw-r--r-- | fs/udf/inode.c | 21 |
2 files changed, 22 insertions, 7 deletions
diff --git a/fs/udf/file.c b/fs/udf/file.c index 2a346bb1d9f..dca0c3881e8 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -125,7 +125,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
125 | err = udf_expand_file_adinicb(inode); | 125 | err = udf_expand_file_adinicb(inode); |
126 | if (err) { | 126 | if (err) { |
127 | udf_debug("udf_expand_adinicb: err=%d\n", err); | 127 | udf_debug("udf_expand_adinicb: err=%d\n", err); |
128 | up_write(&iinfo->i_data_sem); | ||
129 | return err; | 128 | return err; |
130 | } | 129 | } |
131 | } else { | 130 | } else { |
@@ -133,9 +132,10 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
133 | iinfo->i_lenAlloc = pos + count; | 132 | iinfo->i_lenAlloc = pos + count; |
134 | else | 133 | else |
135 | iinfo->i_lenAlloc = inode->i_size; | 134 | iinfo->i_lenAlloc = inode->i_size; |
135 | up_write(&iinfo->i_data_sem); | ||
136 | } | 136 | } |
137 | } | 137 | } else |
138 | up_write(&iinfo->i_data_sem); | 138 | up_write(&iinfo->i_data_sem); |
139 | 139 | ||
140 | retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); | 140 | retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); |
141 | if (retval > 0) | 141 | if (retval > 0) |
@@ -150,7 +150,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
150 | long old_block, new_block; | 150 | long old_block, new_block; |
151 | int result = -EINVAL; | 151 | int result = -EINVAL; |
152 | 152 | ||
153 | if (file_permission(filp, MAY_READ) != 0) { | 153 | if (inode_permission(inode, MAY_READ) != 0) { |
154 | udf_debug("no permission to access inode %lu\n", inode->i_ino); | 154 | udf_debug("no permission to access inode %lu\n", inode->i_ino); |
155 | result = -EPERM; | 155 | result = -EPERM; |
156 | goto out; | 156 | goto out; |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 1d1358ed80c..262050f2eb6 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -145,6 +145,12 @@ const struct address_space_operations udf_aops = { | |||
145 | .bmap = udf_bmap, | 145 | .bmap = udf_bmap, |
146 | }; | 146 | }; |
147 | 147 | ||
148 | /* | ||
149 | * Expand file stored in ICB to a normal one-block-file | ||
150 | * | ||
151 | * This function requires i_data_sem for writing and releases it. | ||
152 | * This function requires i_mutex held | ||
153 | */ | ||
148 | int udf_expand_file_adinicb(struct inode *inode) | 154 | int udf_expand_file_adinicb(struct inode *inode) |
149 | { | 155 | { |
150 | struct page *page; | 156 | struct page *page; |
@@ -163,9 +169,15 @@ int udf_expand_file_adinicb(struct inode *inode) | |||
163 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; | 169 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; |
164 | /* from now on we have normal address_space methods */ | 170 | /* from now on we have normal address_space methods */ |
165 | inode->i_data.a_ops = &udf_aops; | 171 | inode->i_data.a_ops = &udf_aops; |
172 | up_write(&iinfo->i_data_sem); | ||
166 | mark_inode_dirty(inode); | 173 | mark_inode_dirty(inode); |
167 | return 0; | 174 | return 0; |
168 | } | 175 | } |
176 | /* | ||
177 | * Release i_data_sem so that we can lock a page - page lock ranks | ||
178 | * above i_data_sem. i_mutex still protects us against file changes. | ||
179 | */ | ||
180 | up_write(&iinfo->i_data_sem); | ||
169 | 181 | ||
170 | page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS); | 182 | page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS); |
171 | if (!page) | 183 | if (!page) |
@@ -181,6 +193,7 @@ int udf_expand_file_adinicb(struct inode *inode) | |||
181 | SetPageUptodate(page); | 193 | SetPageUptodate(page); |
182 | kunmap(page); | 194 | kunmap(page); |
183 | } | 195 | } |
196 | down_write(&iinfo->i_data_sem); | ||
184 | memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, | 197 | memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, |
185 | iinfo->i_lenAlloc); | 198 | iinfo->i_lenAlloc); |
186 | iinfo->i_lenAlloc = 0; | 199 | iinfo->i_lenAlloc = 0; |
@@ -190,17 +203,20 @@ int udf_expand_file_adinicb(struct inode *inode) | |||
190 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; | 203 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; |
191 | /* from now on we have normal address_space methods */ | 204 | /* from now on we have normal address_space methods */ |
192 | inode->i_data.a_ops = &udf_aops; | 205 | inode->i_data.a_ops = &udf_aops; |
206 | up_write(&iinfo->i_data_sem); | ||
193 | err = inode->i_data.a_ops->writepage(page, &udf_wbc); | 207 | err = inode->i_data.a_ops->writepage(page, &udf_wbc); |
194 | if (err) { | 208 | if (err) { |
195 | /* Restore everything back so that we don't lose data... */ | 209 | /* Restore everything back so that we don't lose data... */ |
196 | lock_page(page); | 210 | lock_page(page); |
197 | kaddr = kmap(page); | 211 | kaddr = kmap(page); |
212 | down_write(&iinfo->i_data_sem); | ||
198 | memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, | 213 | memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, |
199 | inode->i_size); | 214 | inode->i_size); |
200 | kunmap(page); | 215 | kunmap(page); |
201 | unlock_page(page); | 216 | unlock_page(page); |
202 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; | 217 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; |
203 | inode->i_data.a_ops = &udf_adinicb_aops; | 218 | inode->i_data.a_ops = &udf_adinicb_aops; |
219 | up_write(&iinfo->i_data_sem); | ||
204 | } | 220 | } |
205 | page_cache_release(page); | 221 | page_cache_release(page); |
206 | mark_inode_dirty(inode); | 222 | mark_inode_dirty(inode); |
@@ -1105,10 +1121,9 @@ int udf_setsize(struct inode *inode, loff_t newsize) | |||
1105 | if (bsize < | 1121 | if (bsize < |
1106 | (udf_file_entry_alloc_offset(inode) + newsize)) { | 1122 | (udf_file_entry_alloc_offset(inode) + newsize)) { |
1107 | err = udf_expand_file_adinicb(inode); | 1123 | err = udf_expand_file_adinicb(inode); |
1108 | if (err) { | 1124 | if (err) |
1109 | up_write(&iinfo->i_data_sem); | ||
1110 | return err; | 1125 | return err; |
1111 | } | 1126 | down_write(&iinfo->i_data_sem); |
1112 | } else | 1127 | } else |
1113 | iinfo->i_lenAlloc = newsize; | 1128 | iinfo->i_lenAlloc = newsize; |
1114 | } | 1129 | } |