diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/sysv/dir.c | 50 | ||||
-rw-r--r-- | fs/sysv/itree.c | 23 | ||||
-rw-r--r-- | fs/sysv/sysv.h | 3 |
3 files changed, 52 insertions, 24 deletions
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index e566b387fcf9..56f655254bfe 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pagemap.h> | 16 | #include <linux/pagemap.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/smp_lock.h> | 18 | #include <linux/smp_lock.h> |
19 | #include <linux/swap.h> | ||
19 | #include "sysv.h" | 20 | #include "sysv.h" |
20 | 21 | ||
21 | static int sysv_readdir(struct file *, void *, filldir_t); | 22 | static int sysv_readdir(struct file *, void *, filldir_t); |
@@ -37,12 +38,17 @@ static inline unsigned long dir_pages(struct inode *inode) | |||
37 | return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT; | 38 | return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT; |
38 | } | 39 | } |
39 | 40 | ||
40 | static int dir_commit_chunk(struct page *page, unsigned from, unsigned to) | 41 | static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len) |
41 | { | 42 | { |
42 | struct inode *dir = (struct inode *)page->mapping->host; | 43 | struct address_space *mapping = page->mapping; |
44 | struct inode *dir = mapping->host; | ||
43 | int err = 0; | 45 | int err = 0; |
44 | 46 | ||
45 | page->mapping->a_ops->commit_write(NULL, page, from, to); | 47 | block_write_end(NULL, mapping, pos, len, len, page, NULL); |
48 | if (pos+len > dir->i_size) { | ||
49 | i_size_write(dir, pos+len); | ||
50 | mark_inode_dirty(dir); | ||
51 | } | ||
46 | if (IS_DIRSYNC(dir)) | 52 | if (IS_DIRSYNC(dir)) |
47 | err = write_one_page(page, 1); | 53 | err = write_one_page(page, 1); |
48 | else | 54 | else |
@@ -186,7 +192,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode) | |||
186 | unsigned long npages = dir_pages(dir); | 192 | unsigned long npages = dir_pages(dir); |
187 | unsigned long n; | 193 | unsigned long n; |
188 | char *kaddr; | 194 | char *kaddr; |
189 | unsigned from, to; | 195 | loff_t pos; |
190 | int err; | 196 | int err; |
191 | 197 | ||
192 | /* We take care of directory expansion in the same loop */ | 198 | /* We take care of directory expansion in the same loop */ |
@@ -212,16 +218,17 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode) | |||
212 | return -EINVAL; | 218 | return -EINVAL; |
213 | 219 | ||
214 | got_it: | 220 | got_it: |
215 | from = (char*)de - (char*)page_address(page); | 221 | pos = page_offset(page) + |
216 | to = from + SYSV_DIRSIZE; | 222 | (char*)de - (char*)page_address(page); |
217 | lock_page(page); | 223 | lock_page(page); |
218 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 224 | err = __sysv_write_begin(NULL, page->mapping, pos, SYSV_DIRSIZE, |
225 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
219 | if (err) | 226 | if (err) |
220 | goto out_unlock; | 227 | goto out_unlock; |
221 | memcpy (de->name, name, namelen); | 228 | memcpy (de->name, name, namelen); |
222 | memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2); | 229 | memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2); |
223 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); | 230 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); |
224 | err = dir_commit_chunk(page, from, to); | 231 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); |
225 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 232 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
226 | mark_inode_dirty(dir); | 233 | mark_inode_dirty(dir); |
227 | out_page: | 234 | out_page: |
@@ -238,15 +245,15 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page) | |||
238 | struct address_space *mapping = page->mapping; | 245 | struct address_space *mapping = page->mapping; |
239 | struct inode *inode = (struct inode*)mapping->host; | 246 | struct inode *inode = (struct inode*)mapping->host; |
240 | char *kaddr = (char*)page_address(page); | 247 | char *kaddr = (char*)page_address(page); |
241 | unsigned from = (char*)de - kaddr; | 248 | loff_t pos = page_offset(page) + (char *)de - kaddr; |
242 | unsigned to = from + SYSV_DIRSIZE; | ||
243 | int err; | 249 | int err; |
244 | 250 | ||
245 | lock_page(page); | 251 | lock_page(page); |
246 | err = mapping->a_ops->prepare_write(NULL, page, from, to); | 252 | err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE, |
253 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
247 | BUG_ON(err); | 254 | BUG_ON(err); |
248 | de->inode = 0; | 255 | de->inode = 0; |
249 | err = dir_commit_chunk(page, from, to); | 256 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); |
250 | dir_put_page(page); | 257 | dir_put_page(page); |
251 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; | 258 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; |
252 | mark_inode_dirty(inode); | 259 | mark_inode_dirty(inode); |
@@ -263,12 +270,13 @@ int sysv_make_empty(struct inode *inode, struct inode *dir) | |||
263 | 270 | ||
264 | if (!page) | 271 | if (!page) |
265 | return -ENOMEM; | 272 | return -ENOMEM; |
266 | kmap(page); | 273 | err = __sysv_write_begin(NULL, mapping, 0, 2 * SYSV_DIRSIZE, |
267 | err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * SYSV_DIRSIZE); | 274 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); |
268 | if (err) { | 275 | if (err) { |
269 | unlock_page(page); | 276 | unlock_page(page); |
270 | goto fail; | 277 | goto fail; |
271 | } | 278 | } |
279 | kmap(page); | ||
272 | 280 | ||
273 | base = (char*)page_address(page); | 281 | base = (char*)page_address(page); |
274 | memset(base, 0, PAGE_CACHE_SIZE); | 282 | memset(base, 0, PAGE_CACHE_SIZE); |
@@ -280,9 +288,9 @@ int sysv_make_empty(struct inode *inode, struct inode *dir) | |||
280 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino); | 288 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino); |
281 | strcpy(de->name,".."); | 289 | strcpy(de->name,".."); |
282 | 290 | ||
291 | kunmap(page); | ||
283 | err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE); | 292 | err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE); |
284 | fail: | 293 | fail: |
285 | kunmap(page); | ||
286 | page_cache_release(page); | 294 | page_cache_release(page); |
287 | return err; | 295 | return err; |
288 | } | 296 | } |
@@ -336,16 +344,18 @@ not_empty: | |||
336 | void sysv_set_link(struct sysv_dir_entry *de, struct page *page, | 344 | void sysv_set_link(struct sysv_dir_entry *de, struct page *page, |
337 | struct inode *inode) | 345 | struct inode *inode) |
338 | { | 346 | { |
339 | struct inode *dir = (struct inode*)page->mapping->host; | 347 | struct address_space *mapping = page->mapping; |
340 | unsigned from = (char *)de-(char*)page_address(page); | 348 | struct inode *dir = mapping->host; |
341 | unsigned to = from + SYSV_DIRSIZE; | 349 | loff_t pos = page_offset(page) + |
350 | (char *)de-(char*)page_address(page); | ||
342 | int err; | 351 | int err; |
343 | 352 | ||
344 | lock_page(page); | 353 | lock_page(page); |
345 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 354 | err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE, |
355 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
346 | BUG_ON(err); | 356 | BUG_ON(err); |
347 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); | 357 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); |
348 | err = dir_commit_chunk(page, from, to); | 358 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); |
349 | dir_put_page(page); | 359 | dir_put_page(page); |
350 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 360 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
351 | mark_inode_dirty(dir); | 361 | mark_inode_dirty(dir); |
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c index f2bcccd1d6fc..f042eec464c2 100644 --- a/fs/sysv/itree.c +++ b/fs/sysv/itree.c | |||
@@ -453,23 +453,38 @@ static int sysv_writepage(struct page *page, struct writeback_control *wbc) | |||
453 | { | 453 | { |
454 | return block_write_full_page(page,get_block,wbc); | 454 | return block_write_full_page(page,get_block,wbc); |
455 | } | 455 | } |
456 | |||
456 | static int sysv_readpage(struct file *file, struct page *page) | 457 | static int sysv_readpage(struct file *file, struct page *page) |
457 | { | 458 | { |
458 | return block_read_full_page(page,get_block); | 459 | return block_read_full_page(page,get_block); |
459 | } | 460 | } |
460 | static int sysv_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) | 461 | |
462 | int __sysv_write_begin(struct file *file, struct address_space *mapping, | ||
463 | loff_t pos, unsigned len, unsigned flags, | ||
464 | struct page **pagep, void **fsdata) | ||
461 | { | 465 | { |
462 | return block_prepare_write(page,from,to,get_block); | 466 | return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
467 | get_block); | ||
463 | } | 468 | } |
469 | |||
470 | static int sysv_write_begin(struct file *file, struct address_space *mapping, | ||
471 | loff_t pos, unsigned len, unsigned flags, | ||
472 | struct page **pagep, void **fsdata) | ||
473 | { | ||
474 | *pagep = NULL; | ||
475 | return __sysv_write_begin(file, mapping, pos, len, flags, pagep, fsdata); | ||
476 | } | ||
477 | |||
464 | static sector_t sysv_bmap(struct address_space *mapping, sector_t block) | 478 | static sector_t sysv_bmap(struct address_space *mapping, sector_t block) |
465 | { | 479 | { |
466 | return generic_block_bmap(mapping,block,get_block); | 480 | return generic_block_bmap(mapping,block,get_block); |
467 | } | 481 | } |
482 | |||
468 | const struct address_space_operations sysv_aops = { | 483 | const struct address_space_operations sysv_aops = { |
469 | .readpage = sysv_readpage, | 484 | .readpage = sysv_readpage, |
470 | .writepage = sysv_writepage, | 485 | .writepage = sysv_writepage, |
471 | .sync_page = block_sync_page, | 486 | .sync_page = block_sync_page, |
472 | .prepare_write = sysv_prepare_write, | 487 | .write_begin = sysv_write_begin, |
473 | .commit_write = generic_commit_write, | 488 | .write_end = generic_write_end, |
474 | .bmap = sysv_bmap | 489 | .bmap = sysv_bmap |
475 | }; | 490 | }; |
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index 5b4fedf17cc4..64c03bdf06a5 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h | |||
@@ -136,6 +136,9 @@ extern unsigned long sysv_count_free_blocks(struct super_block *); | |||
136 | 136 | ||
137 | /* itree.c */ | 137 | /* itree.c */ |
138 | extern void sysv_truncate(struct inode *); | 138 | extern void sysv_truncate(struct inode *); |
139 | extern int __sysv_write_begin(struct file *file, struct address_space *mapping, | ||
140 | loff_t pos, unsigned len, unsigned flags, | ||
141 | struct page **pagep, void **fsdata); | ||
139 | 142 | ||
140 | /* inode.c */ | 143 | /* inode.c */ |
141 | extern int sysv_write_inode(struct inode *, int); | 144 | extern int sysv_write_inode(struct inode *, int); |