aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/sysv/dir.c50
-rw-r--r--fs/sysv/itree.c23
-rw-r--r--fs/sysv/sysv.h3
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
21static int sysv_readdir(struct file *, void *, filldir_t); 22static 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
40static int dir_commit_chunk(struct page *page, unsigned from, unsigned to) 41static 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
214got_it: 220got_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);
227out_page: 234out_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);
284fail: 293fail:
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:
336void sysv_set_link(struct sysv_dir_entry *de, struct page *page, 344void 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
456static int sysv_readpage(struct file *file, struct page *page) 457static 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}
460static int sysv_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) 461
462int __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
470static 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
464static sector_t sysv_bmap(struct address_space *mapping, sector_t block) 478static 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
468const struct address_space_operations sysv_aops = { 483const 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 */
138extern void sysv_truncate(struct inode *); 138extern void sysv_truncate(struct inode *);
139extern 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 */
141extern int sysv_write_inode(struct inode *, int); 144extern int sysv_write_inode(struct inode *, int);