diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/afs/internal.h | 2 | ||||
-rw-r--r-- | fs/binfmt_flat.c | 2 | ||||
-rw-r--r-- | fs/compat.c | 17 | ||||
-rw-r--r-- | fs/compat_ioctl.c | 33 | ||||
-rw-r--r-- | fs/ecryptfs/file.c | 59 | ||||
-rw-r--r-- | fs/ecryptfs/mmap.c | 38 | ||||
-rw-r--r-- | fs/exec.c | 3 | ||||
-rw-r--r-- | fs/ext4/balloc.c | 6 | ||||
-rw-r--r-- | fs/ext4/extents.c | 148 | ||||
-rw-r--r-- | fs/ext4/inode.c | 4 | ||||
-rw-r--r-- | fs/ext4/namei.c | 4 | ||||
-rw-r--r-- | fs/ext4/super.c | 2 | ||||
-rw-r--r-- | fs/fuse/dir.c | 2 | ||||
-rw-r--r-- | fs/fuse/file.c | 4 | ||||
-rw-r--r-- | fs/fuse/inode.c | 1 | ||||
-rw-r--r-- | fs/ioctl.c | 14 | ||||
-rw-r--r-- | fs/jffs2/readinode.c | 22 | ||||
-rw-r--r-- | fs/jffs2/super.c | 194 | ||||
-rw-r--r-- | fs/jffs2/xattr.c | 6 | ||||
-rw-r--r-- | fs/nfs/direct.c | 65 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 20 | ||||
-rw-r--r-- | fs/nfs/write.c | 6 | ||||
-rw-r--r-- | fs/ntfs/inode.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 31 | ||||
-rw-r--r-- | fs/ocfs2/cluster/masklog.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 33 | ||||
-rw-r--r-- | fs/ocfs2/localalloc.c | 7 | ||||
-rw-r--r-- | fs/ramfs/file-nommu.c | 7 | ||||
-rw-r--r-- | fs/reiserfs/dir.c | 2 | ||||
-rw-r--r-- | fs/signalfd.c | 120 | ||||
-rw-r--r-- | fs/splice.c | 70 | ||||
-rw-r--r-- | fs/udf/inode.c | 12 | ||||
-rw-r--r-- | fs/udf/super.c | 2 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 26 |
34 files changed, 475 insertions, 492 deletions
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 2dac3ad2c44b..2c55dd94a1de 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/rxrpc.h> | 17 | #include <linux/rxrpc.h> |
18 | #include <linux/key.h> | 18 | #include <linux/key.h> |
19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
20 | #include <linux/sched.h> | ||
21 | |||
20 | #include "afs.h" | 22 | #include "afs.h" |
21 | #include "afs_vl.h" | 23 | #include "afs_vl.h" |
22 | 24 | ||
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 7b0265d7f3a8..861141b4f6d6 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -558,7 +558,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
558 | if (!realdatastart) | 558 | if (!realdatastart) |
559 | realdatastart = (unsigned long) -ENOMEM; | 559 | realdatastart = (unsigned long) -ENOMEM; |
560 | printk("Unable to allocate RAM for process data, errno %d\n", | 560 | printk("Unable to allocate RAM for process data, errno %d\n", |
561 | (int)-datapos); | 561 | (int)-realdatastart); |
562 | do_munmap(current->mm, textpos, text_len); | 562 | do_munmap(current->mm, textpos, text_len); |
563 | ret = realdatastart; | 563 | ret = realdatastart; |
564 | goto err; | 564 | goto err; |
diff --git a/fs/compat.c b/fs/compat.c index 1de2331db844..4db6216e5266 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1544,9 +1544,10 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
1544 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout) | 1544 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout) |
1545 | { | 1545 | { |
1546 | fd_set_bits fds; | 1546 | fd_set_bits fds; |
1547 | char *bits; | 1547 | void *bits; |
1548 | int size, max_fds, ret = -EINVAL; | 1548 | int size, max_fds, ret = -EINVAL; |
1549 | struct fdtable *fdt; | 1549 | struct fdtable *fdt; |
1550 | long stack_fds[SELECT_STACK_ALLOC/sizeof(long)]; | ||
1550 | 1551 | ||
1551 | if (n < 0) | 1552 | if (n < 0) |
1552 | goto out_nofds; | 1553 | goto out_nofds; |
@@ -1564,11 +1565,14 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
1564 | * since we used fdset we need to allocate memory in units of | 1565 | * since we used fdset we need to allocate memory in units of |
1565 | * long-words. | 1566 | * long-words. |
1566 | */ | 1567 | */ |
1567 | ret = -ENOMEM; | ||
1568 | size = FDS_BYTES(n); | 1568 | size = FDS_BYTES(n); |
1569 | bits = kmalloc(6 * size, GFP_KERNEL); | 1569 | bits = stack_fds; |
1570 | if (!bits) | 1570 | if (size > sizeof(stack_fds) / 6) { |
1571 | goto out_nofds; | 1571 | bits = kmalloc(6 * size, GFP_KERNEL); |
1572 | ret = -ENOMEM; | ||
1573 | if (!bits) | ||
1574 | goto out_nofds; | ||
1575 | } | ||
1572 | fds.in = (unsigned long *) bits; | 1576 | fds.in = (unsigned long *) bits; |
1573 | fds.out = (unsigned long *) (bits + size); | 1577 | fds.out = (unsigned long *) (bits + size); |
1574 | fds.ex = (unsigned long *) (bits + 2*size); | 1578 | fds.ex = (unsigned long *) (bits + 2*size); |
@@ -1600,7 +1604,8 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
1600 | compat_set_fd_set(n, exp, fds.res_ex)) | 1604 | compat_set_fd_set(n, exp, fds.res_ex)) |
1601 | ret = -EFAULT; | 1605 | ret = -EFAULT; |
1602 | out: | 1606 | out: |
1603 | kfree(bits); | 1607 | if (bits != stack_fds) |
1608 | kfree(bits); | ||
1604 | out_nofds: | 1609 | out_nofds: |
1605 | return ret; | 1610 | return ret; |
1606 | } | 1611 | } |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 65643def3182..6b44cdc96fac 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -1194,6 +1194,7 @@ static int vt_check(struct file *file) | |||
1194 | { | 1194 | { |
1195 | struct tty_struct *tty; | 1195 | struct tty_struct *tty; |
1196 | struct inode *inode = file->f_path.dentry->d_inode; | 1196 | struct inode *inode = file->f_path.dentry->d_inode; |
1197 | struct vc_data *vc; | ||
1197 | 1198 | ||
1198 | if (file->f_op->ioctl != tty_ioctl) | 1199 | if (file->f_op->ioctl != tty_ioctl) |
1199 | return -EINVAL; | 1200 | return -EINVAL; |
@@ -1204,12 +1205,16 @@ static int vt_check(struct file *file) | |||
1204 | 1205 | ||
1205 | if (tty->driver->ioctl != vt_ioctl) | 1206 | if (tty->driver->ioctl != vt_ioctl) |
1206 | return -EINVAL; | 1207 | return -EINVAL; |
1207 | 1208 | ||
1209 | vc = (struct vc_data *)tty->driver_data; | ||
1210 | if (!vc_cons_allocated(vc->vc_num)) /* impossible? */ | ||
1211 | return -ENOIOCTLCMD; | ||
1212 | |||
1208 | /* | 1213 | /* |
1209 | * To have permissions to do most of the vt ioctls, we either have | 1214 | * To have permissions to do most of the vt ioctls, we either have |
1210 | * to be the owner of the tty, or super-user. | 1215 | * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. |
1211 | */ | 1216 | */ |
1212 | if (current->signal->tty == tty || capable(CAP_SYS_ADMIN)) | 1217 | if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) |
1213 | return 1; | 1218 | return 1; |
1214 | return 0; | 1219 | return 0; |
1215 | } | 1220 | } |
@@ -1310,16 +1315,28 @@ static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, | |||
1310 | struct unimapdesc32 tmp; | 1315 | struct unimapdesc32 tmp; |
1311 | struct unimapdesc32 __user *user_ud = compat_ptr(arg); | 1316 | struct unimapdesc32 __user *user_ud = compat_ptr(arg); |
1312 | int perm = vt_check(file); | 1317 | int perm = vt_check(file); |
1313 | 1318 | struct vc_data *vc; | |
1314 | if (perm < 0) return perm; | 1319 | |
1320 | if (perm < 0) | ||
1321 | return perm; | ||
1315 | if (copy_from_user(&tmp, user_ud, sizeof tmp)) | 1322 | if (copy_from_user(&tmp, user_ud, sizeof tmp)) |
1316 | return -EFAULT; | 1323 | return -EFAULT; |
1324 | if (tmp.entries) | ||
1325 | if (!access_ok(VERIFY_WRITE, compat_ptr(tmp.entries), | ||
1326 | tmp.entry_ct*sizeof(struct unipair))) | ||
1327 | return -EFAULT; | ||
1328 | vc = ((struct tty_struct *)file->private_data)->driver_data; | ||
1317 | switch (cmd) { | 1329 | switch (cmd) { |
1318 | case PIO_UNIMAP: | 1330 | case PIO_UNIMAP: |
1319 | if (!perm) return -EPERM; | 1331 | if (!perm) |
1320 | return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries)); | 1332 | return -EPERM; |
1333 | return con_set_unimap(vc, tmp.entry_ct, | ||
1334 | compat_ptr(tmp.entries)); | ||
1321 | case GIO_UNIMAP: | 1335 | case GIO_UNIMAP: |
1322 | return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries)); | 1336 | if (!perm && fg_console != vc->vc_num) |
1337 | return -EPERM; | ||
1338 | return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), | ||
1339 | compat_ptr(tmp.entries)); | ||
1323 | } | 1340 | } |
1324 | return 0; | 1341 | return 0; |
1325 | } | 1342 | } |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 9881b5c5de59..59288d817078 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -33,63 +33,6 @@ | |||
33 | #include "ecryptfs_kernel.h" | 33 | #include "ecryptfs_kernel.h" |
34 | 34 | ||
35 | /** | 35 | /** |
36 | * ecryptfs_llseek | ||
37 | * @file: File we are seeking in | ||
38 | * @offset: The offset to seek to | ||
39 | * @origin: 2 - offset from i_size; 1 - offset from f_pos | ||
40 | * | ||
41 | * Returns the position we have seeked to, or negative on error | ||
42 | */ | ||
43 | static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin) | ||
44 | { | ||
45 | loff_t rv; | ||
46 | loff_t new_end_pos; | ||
47 | int rc; | ||
48 | int expanding_file = 0; | ||
49 | struct inode *inode = file->f_mapping->host; | ||
50 | |||
51 | /* If our offset is past the end of our file, we're going to | ||
52 | * need to grow it so we have a valid length of 0's */ | ||
53 | new_end_pos = offset; | ||
54 | switch (origin) { | ||
55 | case 2: | ||
56 | new_end_pos += i_size_read(inode); | ||
57 | expanding_file = 1; | ||
58 | break; | ||
59 | case 1: | ||
60 | new_end_pos += file->f_pos; | ||
61 | if (new_end_pos > i_size_read(inode)) { | ||
62 | ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) " | ||
63 | "> i_size_read(inode)(=[0x%.16x])\n", | ||
64 | new_end_pos, i_size_read(inode)); | ||
65 | expanding_file = 1; | ||
66 | } | ||
67 | break; | ||
68 | default: | ||
69 | if (new_end_pos > i_size_read(inode)) { | ||
70 | ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) " | ||
71 | "> i_size_read(inode)(=[0x%.16x])\n", | ||
72 | new_end_pos, i_size_read(inode)); | ||
73 | expanding_file = 1; | ||
74 | } | ||
75 | } | ||
76 | ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos); | ||
77 | if (expanding_file) { | ||
78 | rc = ecryptfs_truncate(file->f_path.dentry, new_end_pos); | ||
79 | if (rc) { | ||
80 | rv = rc; | ||
81 | ecryptfs_printk(KERN_ERR, "Error on attempt to " | ||
82 | "truncate to (higher) offset [0x%.16x];" | ||
83 | " rc = [%d]\n", new_end_pos, rc); | ||
84 | goto out; | ||
85 | } | ||
86 | } | ||
87 | rv = generic_file_llseek(file, offset, origin); | ||
88 | out: | ||
89 | return rv; | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * ecryptfs_read_update_atime | 36 | * ecryptfs_read_update_atime |
94 | * | 37 | * |
95 | * generic_file_read updates the atime of upper layer inode. But, it | 38 | * generic_file_read updates the atime of upper layer inode. But, it |
@@ -425,7 +368,7 @@ const struct file_operations ecryptfs_dir_fops = { | |||
425 | }; | 368 | }; |
426 | 369 | ||
427 | const struct file_operations ecryptfs_main_fops = { | 370 | const struct file_operations ecryptfs_main_fops = { |
428 | .llseek = ecryptfs_llseek, | 371 | .llseek = generic_file_llseek, |
429 | .read = do_sync_read, | 372 | .read = do_sync_read, |
430 | .aio_read = ecryptfs_read_update_atime, | 373 | .aio_read = ecryptfs_read_update_atime, |
431 | .write = do_sync_write, | 374 | .write = do_sync_write, |
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 88ea6697908f..55cec98a84e7 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -376,9 +376,31 @@ out: | |||
376 | return 0; | 376 | return 0; |
377 | } | 377 | } |
378 | 378 | ||
379 | /** | ||
380 | * eCryptfs does not currently support holes. When writing after a | ||
381 | * seek past the end of the file, eCryptfs fills in 0's through to the | ||
382 | * current location. The code to fill in the 0's to all the | ||
383 | * intermediate pages calls ecryptfs_prepare_write_no_truncate(). | ||
384 | */ | ||
385 | static int | ||
386 | ecryptfs_prepare_write_no_truncate(struct file *file, struct page *page, | ||
387 | unsigned from, unsigned to) | ||
388 | { | ||
389 | int rc = 0; | ||
390 | |||
391 | if (from == 0 && to == PAGE_CACHE_SIZE) | ||
392 | goto out; /* If we are writing a full page, it will be | ||
393 | up to date. */ | ||
394 | if (!PageUptodate(page)) | ||
395 | rc = ecryptfs_do_readpage(file, page, page->index); | ||
396 | out: | ||
397 | return rc; | ||
398 | } | ||
399 | |||
379 | static int ecryptfs_prepare_write(struct file *file, struct page *page, | 400 | static int ecryptfs_prepare_write(struct file *file, struct page *page, |
380 | unsigned from, unsigned to) | 401 | unsigned from, unsigned to) |
381 | { | 402 | { |
403 | loff_t pos; | ||
382 | int rc = 0; | 404 | int rc = 0; |
383 | 405 | ||
384 | if (from == 0 && to == PAGE_CACHE_SIZE) | 406 | if (from == 0 && to == PAGE_CACHE_SIZE) |
@@ -386,6 +408,16 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page, | |||
386 | up to date. */ | 408 | up to date. */ |
387 | if (!PageUptodate(page)) | 409 | if (!PageUptodate(page)) |
388 | rc = ecryptfs_do_readpage(file, page, page->index); | 410 | rc = ecryptfs_do_readpage(file, page, page->index); |
411 | pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; | ||
412 | if (pos > i_size_read(page->mapping->host)) { | ||
413 | rc = ecryptfs_truncate(file->f_path.dentry, pos); | ||
414 | if (rc) { | ||
415 | printk(KERN_ERR "Error on attempt to " | ||
416 | "truncate to (higher) offset [%lld];" | ||
417 | " rc = [%d]\n", pos, rc); | ||
418 | goto out; | ||
419 | } | ||
420 | } | ||
389 | out: | 421 | out: |
390 | return rc; | 422 | return rc; |
391 | } | 423 | } |
@@ -744,10 +776,10 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) | |||
744 | rc = PTR_ERR(tmp_page); | 776 | rc = PTR_ERR(tmp_page); |
745 | goto out; | 777 | goto out; |
746 | } | 778 | } |
747 | rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros); | 779 | if ((rc = ecryptfs_prepare_write_no_truncate(file, tmp_page, start, |
748 | if (rc) { | 780 | (start + num_zeros)))) { |
749 | ecryptfs_printk(KERN_ERR, "Error preparing to write zero's " | 781 | ecryptfs_printk(KERN_ERR, "Error preparing to write zero's " |
750 | "to remainder of page at index [0x%.16x]\n", | 782 | "to page at index [0x%.16x]\n", |
751 | index); | 783 | index); |
752 | page_cache_release(tmp_page); | 784 | page_cache_release(tmp_page); |
753 | goto out; | 785 | goto out; |
@@ -134,6 +134,9 @@ asmlinkage long sys_uselib(const char __user * library) | |||
134 | if (error) | 134 | if (error) |
135 | goto out; | 135 | goto out; |
136 | 136 | ||
137 | error = -EACCES; | ||
138 | if (nd.mnt->mnt_flags & MNT_NOEXEC) | ||
139 | goto exit; | ||
137 | error = -EINVAL; | 140 | error = -EINVAL; |
138 | if (!S_ISREG(nd.dentry->d_inode->i_mode)) | 141 | if (!S_ISREG(nd.dentry->d_inode->i_mode)) |
139 | goto exit; | 142 | goto exit; |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 8a23483ca8d0..3b64bb16c727 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -30,15 +30,15 @@ | |||
30 | void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, | 30 | void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, |
31 | unsigned long *blockgrpp, ext4_grpblk_t *offsetp) | 31 | unsigned long *blockgrpp, ext4_grpblk_t *offsetp) |
32 | { | 32 | { |
33 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | 33 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
34 | ext4_grpblk_t offset; | 34 | ext4_grpblk_t offset; |
35 | 35 | ||
36 | blocknr = blocknr - le32_to_cpu(es->s_first_data_block); | 36 | blocknr = blocknr - le32_to_cpu(es->s_first_data_block); |
37 | offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb)); | 37 | offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb)); |
38 | if (offsetp) | 38 | if (offsetp) |
39 | *offsetp = offset; | 39 | *offsetp = offset; |
40 | if (blockgrpp) | 40 | if (blockgrpp) |
41 | *blockgrpp = blocknr; | 41 | *blockgrpp = blocknr; |
42 | 42 | ||
43 | } | 43 | } |
44 | 44 | ||
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index a0f0c04e79b2..b9ce24129070 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -374,7 +374,7 @@ ext4_ext_binsearch_idx(struct inode *inode, struct ext4_ext_path *path, int bloc | |||
374 | le32_to_cpu(ix[-1].ei_block)); | 374 | le32_to_cpu(ix[-1].ei_block)); |
375 | } | 375 | } |
376 | BUG_ON(k && le32_to_cpu(ix->ei_block) | 376 | BUG_ON(k && le32_to_cpu(ix->ei_block) |
377 | <= le32_to_cpu(ix[-1].ei_block)); | 377 | <= le32_to_cpu(ix[-1].ei_block)); |
378 | if (block < le32_to_cpu(ix->ei_block)) | 378 | if (block < le32_to_cpu(ix->ei_block)) |
379 | break; | 379 | break; |
380 | chix = ix; | 380 | chix = ix; |
@@ -423,8 +423,8 @@ ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block) | |||
423 | 423 | ||
424 | path->p_ext = l - 1; | 424 | path->p_ext = l - 1; |
425 | ext_debug(" -> %d:%llu:%d ", | 425 | ext_debug(" -> %d:%llu:%d ", |
426 | le32_to_cpu(path->p_ext->ee_block), | 426 | le32_to_cpu(path->p_ext->ee_block), |
427 | ext_pblock(path->p_ext), | 427 | ext_pblock(path->p_ext), |
428 | le16_to_cpu(path->p_ext->ee_len)); | 428 | le16_to_cpu(path->p_ext->ee_len)); |
429 | 429 | ||
430 | #ifdef CHECK_BINSEARCH | 430 | #ifdef CHECK_BINSEARCH |
@@ -435,7 +435,7 @@ ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block) | |||
435 | chex = ex = EXT_FIRST_EXTENT(eh); | 435 | chex = ex = EXT_FIRST_EXTENT(eh); |
436 | for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ex++) { | 436 | for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ex++) { |
437 | BUG_ON(k && le32_to_cpu(ex->ee_block) | 437 | BUG_ON(k && le32_to_cpu(ex->ee_block) |
438 | <= le32_to_cpu(ex[-1].ee_block)); | 438 | <= le32_to_cpu(ex[-1].ee_block)); |
439 | if (block < le32_to_cpu(ex->ee_block)) | 439 | if (block < le32_to_cpu(ex->ee_block)) |
440 | break; | 440 | break; |
441 | chex = ex; | 441 | chex = ex; |
@@ -577,7 +577,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, | |||
577 | curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1); | 577 | curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1); |
578 | 578 | ||
579 | BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries) | 579 | BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries) |
580 | > le16_to_cpu(curp->p_hdr->eh_max)); | 580 | > le16_to_cpu(curp->p_hdr->eh_max)); |
581 | BUG_ON(ix > EXT_LAST_INDEX(curp->p_hdr)); | 581 | BUG_ON(ix > EXT_LAST_INDEX(curp->p_hdr)); |
582 | 582 | ||
583 | err = ext4_ext_dirty(handle, inode, curp); | 583 | err = ext4_ext_dirty(handle, inode, curp); |
@@ -621,12 +621,12 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
621 | border = path[depth].p_ext[1].ee_block; | 621 | border = path[depth].p_ext[1].ee_block; |
622 | ext_debug("leaf will be split." | 622 | ext_debug("leaf will be split." |
623 | " next leaf starts at %d\n", | 623 | " next leaf starts at %d\n", |
624 | le32_to_cpu(border)); | 624 | le32_to_cpu(border)); |
625 | } else { | 625 | } else { |
626 | border = newext->ee_block; | 626 | border = newext->ee_block; |
627 | ext_debug("leaf will be added." | 627 | ext_debug("leaf will be added." |
628 | " next leaf starts at %d\n", | 628 | " next leaf starts at %d\n", |
629 | le32_to_cpu(border)); | 629 | le32_to_cpu(border)); |
630 | } | 630 | } |
631 | 631 | ||
632 | /* | 632 | /* |
@@ -684,9 +684,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
684 | while (path[depth].p_ext <= | 684 | while (path[depth].p_ext <= |
685 | EXT_MAX_EXTENT(path[depth].p_hdr)) { | 685 | EXT_MAX_EXTENT(path[depth].p_hdr)) { |
686 | ext_debug("move %d:%llu:%d in new leaf %llu\n", | 686 | ext_debug("move %d:%llu:%d in new leaf %llu\n", |
687 | le32_to_cpu(path[depth].p_ext->ee_block), | 687 | le32_to_cpu(path[depth].p_ext->ee_block), |
688 | ext_pblock(path[depth].p_ext), | 688 | ext_pblock(path[depth].p_ext), |
689 | le16_to_cpu(path[depth].p_ext->ee_len), | 689 | le16_to_cpu(path[depth].p_ext->ee_len), |
690 | newblock); | 690 | newblock); |
691 | /*memmove(ex++, path[depth].p_ext++, | 691 | /*memmove(ex++, path[depth].p_ext++, |
692 | sizeof(struct ext4_extent)); | 692 | sizeof(struct ext4_extent)); |
@@ -765,9 +765,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
765 | EXT_LAST_INDEX(path[i].p_hdr)); | 765 | EXT_LAST_INDEX(path[i].p_hdr)); |
766 | while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { | 766 | while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { |
767 | ext_debug("%d: move %d:%d in new index %llu\n", i, | 767 | ext_debug("%d: move %d:%d in new index %llu\n", i, |
768 | le32_to_cpu(path[i].p_idx->ei_block), | 768 | le32_to_cpu(path[i].p_idx->ei_block), |
769 | idx_pblock(path[i].p_idx), | 769 | idx_pblock(path[i].p_idx), |
770 | newblock); | 770 | newblock); |
771 | /*memmove(++fidx, path[i].p_idx++, | 771 | /*memmove(++fidx, path[i].p_idx++, |
772 | sizeof(struct ext4_extent_idx)); | 772 | sizeof(struct ext4_extent_idx)); |
773 | neh->eh_entries++; | 773 | neh->eh_entries++; |
@@ -1128,6 +1128,55 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | |||
1128 | } | 1128 | } |
1129 | 1129 | ||
1130 | /* | 1130 | /* |
1131 | * check if a portion of the "newext" extent overlaps with an | ||
1132 | * existing extent. | ||
1133 | * | ||
1134 | * If there is an overlap discovered, it updates the length of the newext | ||
1135 | * such that there will be no overlap, and then returns 1. | ||
1136 | * If there is no overlap found, it returns 0. | ||
1137 | */ | ||
1138 | unsigned int ext4_ext_check_overlap(struct inode *inode, | ||
1139 | struct ext4_extent *newext, | ||
1140 | struct ext4_ext_path *path) | ||
1141 | { | ||
1142 | unsigned long b1, b2; | ||
1143 | unsigned int depth, len1; | ||
1144 | unsigned int ret = 0; | ||
1145 | |||
1146 | b1 = le32_to_cpu(newext->ee_block); | ||
1147 | len1 = le16_to_cpu(newext->ee_len); | ||
1148 | depth = ext_depth(inode); | ||
1149 | if (!path[depth].p_ext) | ||
1150 | goto out; | ||
1151 | b2 = le32_to_cpu(path[depth].p_ext->ee_block); | ||
1152 | |||
1153 | /* | ||
1154 | * get the next allocated block if the extent in the path | ||
1155 | * is before the requested block(s) | ||
1156 | */ | ||
1157 | if (b2 < b1) { | ||
1158 | b2 = ext4_ext_next_allocated_block(path); | ||
1159 | if (b2 == EXT_MAX_BLOCK) | ||
1160 | goto out; | ||
1161 | } | ||
1162 | |||
1163 | /* check for wrap through zero */ | ||
1164 | if (b1 + len1 < b1) { | ||
1165 | len1 = EXT_MAX_BLOCK - b1; | ||
1166 | newext->ee_len = cpu_to_le16(len1); | ||
1167 | ret = 1; | ||
1168 | } | ||
1169 | |||
1170 | /* check for overlap */ | ||
1171 | if (b1 + len1 > b2) { | ||
1172 | newext->ee_len = cpu_to_le16(b2 - b1); | ||
1173 | ret = 1; | ||
1174 | } | ||
1175 | out: | ||
1176 | return ret; | ||
1177 | } | ||
1178 | |||
1179 | /* | ||
1131 | * ext4_ext_insert_extent: | 1180 | * ext4_ext_insert_extent: |
1132 | * tries to merge requsted extent into the existing extent or | 1181 | * tries to merge requsted extent into the existing extent or |
1133 | * inserts requested extent as new one into the tree, | 1182 | * inserts requested extent as new one into the tree, |
@@ -1212,12 +1261,12 @@ has_space: | |||
1212 | if (!nearex) { | 1261 | if (!nearex) { |
1213 | /* there is no extent in this leaf, create first one */ | 1262 | /* there is no extent in this leaf, create first one */ |
1214 | ext_debug("first extent in the leaf: %d:%llu:%d\n", | 1263 | ext_debug("first extent in the leaf: %d:%llu:%d\n", |
1215 | le32_to_cpu(newext->ee_block), | 1264 | le32_to_cpu(newext->ee_block), |
1216 | ext_pblock(newext), | 1265 | ext_pblock(newext), |
1217 | le16_to_cpu(newext->ee_len)); | 1266 | le16_to_cpu(newext->ee_len)); |
1218 | path[depth].p_ext = EXT_FIRST_EXTENT(eh); | 1267 | path[depth].p_ext = EXT_FIRST_EXTENT(eh); |
1219 | } else if (le32_to_cpu(newext->ee_block) | 1268 | } else if (le32_to_cpu(newext->ee_block) |
1220 | > le32_to_cpu(nearex->ee_block)) { | 1269 | > le32_to_cpu(nearex->ee_block)) { |
1221 | /* BUG_ON(newext->ee_block == nearex->ee_block); */ | 1270 | /* BUG_ON(newext->ee_block == nearex->ee_block); */ |
1222 | if (nearex != EXT_LAST_EXTENT(eh)) { | 1271 | if (nearex != EXT_LAST_EXTENT(eh)) { |
1223 | len = EXT_MAX_EXTENT(eh) - nearex; | 1272 | len = EXT_MAX_EXTENT(eh) - nearex; |
@@ -1225,9 +1274,9 @@ has_space: | |||
1225 | len = len < 0 ? 0 : len; | 1274 | len = len < 0 ? 0 : len; |
1226 | ext_debug("insert %d:%llu:%d after: nearest 0x%p, " | 1275 | ext_debug("insert %d:%llu:%d after: nearest 0x%p, " |
1227 | "move %d from 0x%p to 0x%p\n", | 1276 | "move %d from 0x%p to 0x%p\n", |
1228 | le32_to_cpu(newext->ee_block), | 1277 | le32_to_cpu(newext->ee_block), |
1229 | ext_pblock(newext), | 1278 | ext_pblock(newext), |
1230 | le16_to_cpu(newext->ee_len), | 1279 | le16_to_cpu(newext->ee_len), |
1231 | nearex, len, nearex + 1, nearex + 2); | 1280 | nearex, len, nearex + 1, nearex + 2); |
1232 | memmove(nearex + 2, nearex + 1, len); | 1281 | memmove(nearex + 2, nearex + 1, len); |
1233 | } | 1282 | } |
@@ -1358,9 +1407,9 @@ int ext4_ext_walk_space(struct inode *inode, unsigned long block, | |||
1358 | cbex.ec_start = 0; | 1407 | cbex.ec_start = 0; |
1359 | cbex.ec_type = EXT4_EXT_CACHE_GAP; | 1408 | cbex.ec_type = EXT4_EXT_CACHE_GAP; |
1360 | } else { | 1409 | } else { |
1361 | cbex.ec_block = le32_to_cpu(ex->ee_block); | 1410 | cbex.ec_block = le32_to_cpu(ex->ee_block); |
1362 | cbex.ec_len = le16_to_cpu(ex->ee_len); | 1411 | cbex.ec_len = le16_to_cpu(ex->ee_len); |
1363 | cbex.ec_start = ext_pblock(ex); | 1412 | cbex.ec_start = ext_pblock(ex); |
1364 | cbex.ec_type = EXT4_EXT_CACHE_EXTENT; | 1413 | cbex.ec_type = EXT4_EXT_CACHE_EXTENT; |
1365 | } | 1414 | } |
1366 | 1415 | ||
@@ -1431,16 +1480,16 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, | |||
1431 | len = le32_to_cpu(ex->ee_block) - block; | 1480 | len = le32_to_cpu(ex->ee_block) - block; |
1432 | ext_debug("cache gap(before): %lu [%lu:%lu]", | 1481 | ext_debug("cache gap(before): %lu [%lu:%lu]", |
1433 | (unsigned long) block, | 1482 | (unsigned long) block, |
1434 | (unsigned long) le32_to_cpu(ex->ee_block), | 1483 | (unsigned long) le32_to_cpu(ex->ee_block), |
1435 | (unsigned long) le16_to_cpu(ex->ee_len)); | 1484 | (unsigned long) le16_to_cpu(ex->ee_len)); |
1436 | } else if (block >= le32_to_cpu(ex->ee_block) | 1485 | } else if (block >= le32_to_cpu(ex->ee_block) |
1437 | + le16_to_cpu(ex->ee_len)) { | 1486 | + le16_to_cpu(ex->ee_len)) { |
1438 | lblock = le32_to_cpu(ex->ee_block) | 1487 | lblock = le32_to_cpu(ex->ee_block) |
1439 | + le16_to_cpu(ex->ee_len); | 1488 | + le16_to_cpu(ex->ee_len); |
1440 | len = ext4_ext_next_allocated_block(path); | 1489 | len = ext4_ext_next_allocated_block(path); |
1441 | ext_debug("cache gap(after): [%lu:%lu] %lu", | 1490 | ext_debug("cache gap(after): [%lu:%lu] %lu", |
1442 | (unsigned long) le32_to_cpu(ex->ee_block), | 1491 | (unsigned long) le32_to_cpu(ex->ee_block), |
1443 | (unsigned long) le16_to_cpu(ex->ee_len), | 1492 | (unsigned long) le16_to_cpu(ex->ee_len), |
1444 | (unsigned long) block); | 1493 | (unsigned long) block); |
1445 | BUG_ON(len == lblock); | 1494 | BUG_ON(len == lblock); |
1446 | len = len - lblock; | 1495 | len = len - lblock; |
@@ -1468,9 +1517,9 @@ ext4_ext_in_cache(struct inode *inode, unsigned long block, | |||
1468 | BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP && | 1517 | BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP && |
1469 | cex->ec_type != EXT4_EXT_CACHE_EXTENT); | 1518 | cex->ec_type != EXT4_EXT_CACHE_EXTENT); |
1470 | if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) { | 1519 | if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) { |
1471 | ex->ee_block = cpu_to_le32(cex->ec_block); | 1520 | ex->ee_block = cpu_to_le32(cex->ec_block); |
1472 | ext4_ext_store_pblock(ex, cex->ec_start); | 1521 | ext4_ext_store_pblock(ex, cex->ec_start); |
1473 | ex->ee_len = cpu_to_le16(cex->ec_len); | 1522 | ex->ee_len = cpu_to_le16(cex->ec_len); |
1474 | ext_debug("%lu cached by %lu:%lu:%llu\n", | 1523 | ext_debug("%lu cached by %lu:%lu:%llu\n", |
1475 | (unsigned long) block, | 1524 | (unsigned long) block, |
1476 | (unsigned long) cex->ec_block, | 1525 | (unsigned long) cex->ec_block, |
@@ -1956,9 +2005,9 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
1956 | /* we should allocate requested block */ | 2005 | /* we should allocate requested block */ |
1957 | } else if (goal == EXT4_EXT_CACHE_EXTENT) { | 2006 | } else if (goal == EXT4_EXT_CACHE_EXTENT) { |
1958 | /* block is already allocated */ | 2007 | /* block is already allocated */ |
1959 | newblock = iblock | 2008 | newblock = iblock |
1960 | - le32_to_cpu(newex.ee_block) | 2009 | - le32_to_cpu(newex.ee_block) |
1961 | + ext_pblock(&newex); | 2010 | + ext_pblock(&newex); |
1962 | /* number of remaining blocks in the extent */ | 2011 | /* number of remaining blocks in the extent */ |
1963 | allocated = le16_to_cpu(newex.ee_len) - | 2012 | allocated = le16_to_cpu(newex.ee_len) - |
1964 | (iblock - le32_to_cpu(newex.ee_block)); | 2013 | (iblock - le32_to_cpu(newex.ee_block)); |
@@ -1987,7 +2036,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
1987 | 2036 | ||
1988 | ex = path[depth].p_ext; | 2037 | ex = path[depth].p_ext; |
1989 | if (ex) { | 2038 | if (ex) { |
1990 | unsigned long ee_block = le32_to_cpu(ex->ee_block); | 2039 | unsigned long ee_block = le32_to_cpu(ex->ee_block); |
1991 | ext4_fsblk_t ee_start = ext_pblock(ex); | 2040 | ext4_fsblk_t ee_start = ext_pblock(ex); |
1992 | unsigned short ee_len = le16_to_cpu(ex->ee_len); | 2041 | unsigned short ee_len = le16_to_cpu(ex->ee_len); |
1993 | 2042 | ||
@@ -2000,7 +2049,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2000 | if (ee_len > EXT_MAX_LEN) | 2049 | if (ee_len > EXT_MAX_LEN) |
2001 | goto out2; | 2050 | goto out2; |
2002 | /* if found extent covers block, simply return it */ | 2051 | /* if found extent covers block, simply return it */ |
2003 | if (iblock >= ee_block && iblock < ee_block + ee_len) { | 2052 | if (iblock >= ee_block && iblock < ee_block + ee_len) { |
2004 | newblock = iblock - ee_block + ee_start; | 2053 | newblock = iblock - ee_block + ee_start; |
2005 | /* number of remaining blocks in the extent */ | 2054 | /* number of remaining blocks in the extent */ |
2006 | allocated = ee_len - (iblock - ee_block); | 2055 | allocated = ee_len - (iblock - ee_block); |
@@ -2031,7 +2080,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2031 | 2080 | ||
2032 | /* allocate new block */ | 2081 | /* allocate new block */ |
2033 | goal = ext4_ext_find_goal(inode, path, iblock); | 2082 | goal = ext4_ext_find_goal(inode, path, iblock); |
2034 | allocated = max_blocks; | 2083 | |
2084 | /* Check if we can really insert (iblock)::(iblock+max_blocks) extent */ | ||
2085 | newex.ee_block = cpu_to_le32(iblock); | ||
2086 | newex.ee_len = cpu_to_le16(max_blocks); | ||
2087 | err = ext4_ext_check_overlap(inode, &newex, path); | ||
2088 | if (err) | ||
2089 | allocated = le16_to_cpu(newex.ee_len); | ||
2090 | else | ||
2091 | allocated = max_blocks; | ||
2035 | newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err); | 2092 | newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err); |
2036 | if (!newblock) | 2093 | if (!newblock) |
2037 | goto out2; | 2094 | goto out2; |
@@ -2039,12 +2096,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2039 | goal, newblock, allocated); | 2096 | goal, newblock, allocated); |
2040 | 2097 | ||
2041 | /* try to insert new extent into found leaf and return */ | 2098 | /* try to insert new extent into found leaf and return */ |
2042 | newex.ee_block = cpu_to_le32(iblock); | ||
2043 | ext4_ext_store_pblock(&newex, newblock); | 2099 | ext4_ext_store_pblock(&newex, newblock); |
2044 | newex.ee_len = cpu_to_le16(allocated); | 2100 | newex.ee_len = cpu_to_le16(allocated); |
2045 | err = ext4_ext_insert_extent(handle, inode, path, &newex); | 2101 | err = ext4_ext_insert_extent(handle, inode, path, &newex); |
2046 | if (err) | 2102 | if (err) { |
2103 | /* free data blocks we just allocated */ | ||
2104 | ext4_free_blocks(handle, inode, ext_pblock(&newex), | ||
2105 | le16_to_cpu(newex.ee_len)); | ||
2047 | goto out2; | 2106 | goto out2; |
2107 | } | ||
2048 | 2108 | ||
2049 | if (extend_disksize && inode->i_size > EXT4_I(inode)->i_disksize) | 2109 | if (extend_disksize && inode->i_size > EXT4_I(inode)->i_disksize) |
2050 | EXT4_I(inode)->i_disksize = inode->i_size; | 2110 | EXT4_I(inode)->i_disksize = inode->i_size; |
@@ -2157,11 +2217,3 @@ int ext4_ext_writepage_trans_blocks(struct inode *inode, int num) | |||
2157 | 2217 | ||
2158 | return needed; | 2218 | return needed; |
2159 | } | 2219 | } |
2160 | |||
2161 | EXPORT_SYMBOL(ext4_mark_inode_dirty); | ||
2162 | EXPORT_SYMBOL(ext4_ext_invalidate_cache); | ||
2163 | EXPORT_SYMBOL(ext4_ext_insert_extent); | ||
2164 | EXPORT_SYMBOL(ext4_ext_walk_space); | ||
2165 | EXPORT_SYMBOL(ext4_ext_find_goal); | ||
2166 | EXPORT_SYMBOL(ext4_ext_calc_credits_for_insert); | ||
2167 | |||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b34182b6ee4d..0bcf62a750ff 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -255,8 +255,8 @@ static int verify_chain(Indirect *from, Indirect *to) | |||
255 | * @inode: inode in question (we are only interested in its superblock) | 255 | * @inode: inode in question (we are only interested in its superblock) |
256 | * @i_block: block number to be parsed | 256 | * @i_block: block number to be parsed |
257 | * @offsets: array to store the offsets in | 257 | * @offsets: array to store the offsets in |
258 | * @boundary: set this non-zero if the referred-to block is likely to be | 258 | * @boundary: set this non-zero if the referred-to block is likely to be |
259 | * followed (on disk) by an indirect block. | 259 | * followed (on disk) by an indirect block. |
260 | * | 260 | * |
261 | * To store the locations of file's data ext4 uses a data structure common | 261 | * To store the locations of file's data ext4 uses a data structure common |
262 | * for UNIX filesystems - tree of pointers anchored in the inode, with | 262 | * for UNIX filesystems - tree of pointers anchored in the inode, with |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 4ec57be5baf5..2811e5720ad0 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -46,7 +46,7 @@ | |||
46 | */ | 46 | */ |
47 | #define NAMEI_RA_CHUNKS 2 | 47 | #define NAMEI_RA_CHUNKS 2 |
48 | #define NAMEI_RA_BLOCKS 4 | 48 | #define NAMEI_RA_BLOCKS 4 |
49 | #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) | 49 | #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) |
50 | #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) | 50 | #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) |
51 | 51 | ||
52 | static struct buffer_head *ext4_append(handle_t *handle, | 52 | static struct buffer_head *ext4_append(handle_t *handle, |
@@ -241,7 +241,7 @@ static inline unsigned dx_node_limit (struct inode *dir) | |||
241 | static void dx_show_index (char * label, struct dx_entry *entries) | 241 | static void dx_show_index (char * label, struct dx_entry *entries) |
242 | { | 242 | { |
243 | int i, n = dx_get_count (entries); | 243 | int i, n = dx_get_count (entries); |
244 | printk("%s index ", label); | 244 | printk("%s index ", label); |
245 | for (i = 0; i < n; i++) { | 245 | for (i = 0; i < n; i++) { |
246 | printk("%x->%u ", i? dx_get_hash(entries + i) : | 246 | printk("%x->%u ", i? dx_get_hash(entries + i) : |
247 | 0, dx_get_block(entries + i)); | 247 | 0, dx_get_block(entries + i)); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index cb9afdd0e26e..175b68c60968 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1985,7 +1985,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb, | |||
1985 | 1985 | ||
1986 | if (bd_claim(bdev, sb)) { | 1986 | if (bd_claim(bdev, sb)) { |
1987 | printk(KERN_ERR | 1987 | printk(KERN_ERR |
1988 | "EXT4: failed to claim external journal device.\n"); | 1988 | "EXT4: failed to claim external journal device.\n"); |
1989 | blkdev_put(bdev); | 1989 | blkdev_put(bdev); |
1990 | return NULL; | 1990 | return NULL; |
1991 | } | 1991 | } |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8890eba1db52..bd5a772d8ccf 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -485,7 +485,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, | |||
485 | static int fuse_create(struct inode *dir, struct dentry *entry, int mode, | 485 | static int fuse_create(struct inode *dir, struct dentry *entry, int mode, |
486 | struct nameidata *nd) | 486 | struct nameidata *nd) |
487 | { | 487 | { |
488 | if (nd && (nd->flags & LOOKUP_CREATE)) { | 488 | if (nd && (nd->flags & LOOKUP_OPEN)) { |
489 | int err = fuse_create_open(dir, entry, mode, nd); | 489 | int err = fuse_create_open(dir, entry, mode, nd); |
490 | if (err != -ENOSYS) | 490 | if (err != -ENOSYS) |
491 | return err; | 491 | return err; |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index d0ed60bc3188..adf7995232b8 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -610,7 +610,9 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | |||
610 | ssize_t res; | 610 | ssize_t res; |
611 | /* Don't allow parallel writes to the same file */ | 611 | /* Don't allow parallel writes to the same file */ |
612 | mutex_lock(&inode->i_mutex); | 612 | mutex_lock(&inode->i_mutex); |
613 | res = fuse_direct_io(file, buf, count, ppos, 1); | 613 | res = generic_write_checks(file, ppos, &count, 0); |
614 | if (!res) | ||
615 | res = fuse_direct_io(file, buf, count, ppos, 1); | ||
614 | mutex_unlock(&inode->i_mutex); | 616 | mutex_unlock(&inode->i_mutex); |
615 | return res; | 617 | return res; |
616 | } | 618 | } |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 78f7a1dc90dd..9804c0cdcb42 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -454,6 +454,7 @@ static const struct super_operations fuse_super_operations = { | |||
454 | .destroy_inode = fuse_destroy_inode, | 454 | .destroy_inode = fuse_destroy_inode, |
455 | .read_inode = fuse_read_inode, | 455 | .read_inode = fuse_read_inode, |
456 | .clear_inode = fuse_clear_inode, | 456 | .clear_inode = fuse_clear_inode, |
457 | .drop_inode = generic_delete_inode, | ||
457 | .remount_fs = fuse_remount_fs, | 458 | .remount_fs = fuse_remount_fs, |
458 | .put_super = fuse_put_super, | 459 | .put_super = fuse_put_super, |
459 | .umount_begin = fuse_umount_begin, | 460 | .umount_begin = fuse_umount_begin, |
diff --git a/fs/ioctl.c b/fs/ioctl.c index 479c1038ed4a..8c90cbc903fa 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/security.h> | 13 | #include <linux/security.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/kallsyms.h> | ||
15 | 16 | ||
16 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
17 | #include <asm/ioctls.h> | 18 | #include <asm/ioctls.h> |
@@ -20,6 +21,7 @@ static long do_ioctl(struct file *filp, unsigned int cmd, | |||
20 | unsigned long arg) | 21 | unsigned long arg) |
21 | { | 22 | { |
22 | int error = -ENOTTY; | 23 | int error = -ENOTTY; |
24 | void *f; | ||
23 | 25 | ||
24 | if (!filp->f_op) | 26 | if (!filp->f_op) |
25 | goto out; | 27 | goto out; |
@@ -29,10 +31,16 @@ static long do_ioctl(struct file *filp, unsigned int cmd, | |||
29 | if (error == -ENOIOCTLCMD) | 31 | if (error == -ENOIOCTLCMD) |
30 | error = -EINVAL; | 32 | error = -EINVAL; |
31 | goto out; | 33 | goto out; |
32 | } else if (filp->f_op->ioctl) { | 34 | } else if ((f = filp->f_op->ioctl)) { |
33 | lock_kernel(); | 35 | lock_kernel(); |
34 | error = filp->f_op->ioctl(filp->f_path.dentry->d_inode, | 36 | if (!filp->f_op->ioctl) { |
35 | filp, cmd, arg); | 37 | printk("%s: ioctl %p disappeared\n", __FUNCTION__, f); |
38 | print_symbol("symbol: %s\n", (unsigned long)f); | ||
39 | dump_stack(); | ||
40 | } else { | ||
41 | error = filp->f_op->ioctl(filp->f_path.dentry->d_inode, | ||
42 | filp, cmd, arg); | ||
43 | } | ||
36 | unlock_kernel(); | 44 | unlock_kernel(); |
37 | } | 45 | } |
38 | 46 | ||
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 4884d5edfe65..12e83f67eee4 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
@@ -229,9 +229,16 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
229 | check anyway. */ | 229 | check anyway. */ |
230 | if (!tn->fn->size) { | 230 | if (!tn->fn->size) { |
231 | if (rii->mdata_tn) { | 231 | if (rii->mdata_tn) { |
232 | /* We had a candidate mdata node already */ | 232 | if (rii->mdata_tn->version < tn->version) { |
233 | dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version); | 233 | /* We had a candidate mdata node already */ |
234 | jffs2_kill_tn(c, rii->mdata_tn); | 234 | dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version); |
235 | jffs2_kill_tn(c, rii->mdata_tn); | ||
236 | } else { | ||
237 | dbg_readinode("kill new mdata with ver %d (older than existing %d\n", | ||
238 | tn->version, rii->mdata_tn->version); | ||
239 | jffs2_kill_tn(c, tn); | ||
240 | return 0; | ||
241 | } | ||
235 | } | 242 | } |
236 | rii->mdata_tn = tn; | 243 | rii->mdata_tn = tn; |
237 | dbg_readinode("keep new mdata with ver %d\n", tn->version); | 244 | dbg_readinode("keep new mdata with ver %d\n", tn->version); |
@@ -1044,7 +1051,8 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
1044 | 1051 | ||
1045 | case JFFS2_NODETYPE_DIRENT: | 1052 | case JFFS2_NODETYPE_DIRENT: |
1046 | 1053 | ||
1047 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { | 1054 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent) && |
1055 | len < sizeof(struct jffs2_raw_dirent)) { | ||
1048 | err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf); | 1056 | err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf); |
1049 | if (unlikely(err)) | 1057 | if (unlikely(err)) |
1050 | goto free_out; | 1058 | goto free_out; |
@@ -1058,7 +1066,8 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
1058 | 1066 | ||
1059 | case JFFS2_NODETYPE_INODE: | 1067 | case JFFS2_NODETYPE_INODE: |
1060 | 1068 | ||
1061 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { | 1069 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode) && |
1070 | len < sizeof(struct jffs2_raw_inode)) { | ||
1062 | err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf); | 1071 | err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf); |
1063 | if (unlikely(err)) | 1072 | if (unlikely(err)) |
1064 | goto free_out; | 1073 | goto free_out; |
@@ -1071,7 +1080,8 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
1071 | break; | 1080 | break; |
1072 | 1081 | ||
1073 | default: | 1082 | default: |
1074 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) { | 1083 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node) && |
1084 | len < sizeof(struct jffs2_unknown_node)) { | ||
1075 | err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf); | 1085 | err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf); |
1076 | if (unlikely(err)) | 1086 | if (unlikely(err)) |
1077 | goto free_out; | 1087 | goto free_out; |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 6488af43bc9b..e220d3bd610d 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <linux/jffs2.h> | 20 | #include <linux/jffs2.h> |
21 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
22 | #include <linux/mtd/mtd.h> | 22 | #include <linux/mtd/super.h> |
23 | #include <linux/ctype.h> | 23 | #include <linux/ctype.h> |
24 | #include <linux/namei.h> | 24 | #include <linux/namei.h> |
25 | #include "compr.h" | 25 | #include "compr.h" |
@@ -75,69 +75,27 @@ static const struct super_operations jffs2_super_operations = | |||
75 | .sync_fs = jffs2_sync_fs, | 75 | .sync_fs = jffs2_sync_fs, |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static int jffs2_sb_compare(struct super_block *sb, void *data) | 78 | /* |
79 | { | 79 | * fill in the superblock |
80 | struct jffs2_sb_info *p = data; | 80 | */ |
81 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 81 | static int jffs2_fill_super(struct super_block *sb, void *data, int silent) |
82 | |||
83 | /* The superblocks are considered to be equivalent if the underlying MTD | ||
84 | device is the same one */ | ||
85 | if (c->mtd == p->mtd) { | ||
86 | D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name)); | ||
87 | return 1; | ||
88 | } else { | ||
89 | D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n", | ||
90 | c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name)); | ||
91 | return 0; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static int jffs2_sb_set(struct super_block *sb, void *data) | ||
96 | { | ||
97 | struct jffs2_sb_info *p = data; | ||
98 | |||
99 | /* For persistence of NFS exports etc. we use the same s_dev | ||
100 | each time we mount the device, don't just use an anonymous | ||
101 | device */ | ||
102 | sb->s_fs_info = p; | ||
103 | p->os_priv = sb; | ||
104 | sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, p->mtd->index); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int jffs2_get_sb_mtd(struct file_system_type *fs_type, | ||
110 | int flags, const char *dev_name, | ||
111 | void *data, struct mtd_info *mtd, | ||
112 | struct vfsmount *mnt) | ||
113 | { | 82 | { |
114 | struct super_block *sb; | ||
115 | struct jffs2_sb_info *c; | 83 | struct jffs2_sb_info *c; |
116 | int ret; | 84 | |
85 | D1(printk(KERN_DEBUG "jffs2_get_sb_mtd():" | ||
86 | " New superblock for device %d (\"%s\")\n", | ||
87 | sb->s_mtd->index, sb->s_mtd->name)); | ||
117 | 88 | ||
118 | c = kzalloc(sizeof(*c), GFP_KERNEL); | 89 | c = kzalloc(sizeof(*c), GFP_KERNEL); |
119 | if (!c) | 90 | if (!c) |
120 | return -ENOMEM; | 91 | return -ENOMEM; |
121 | c->mtd = mtd; | ||
122 | |||
123 | sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); | ||
124 | |||
125 | if (IS_ERR(sb)) | ||
126 | goto out_error; | ||
127 | |||
128 | if (sb->s_root) { | ||
129 | /* New mountpoint for JFFS2 which is already mounted */ | ||
130 | D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", | ||
131 | mtd->index, mtd->name)); | ||
132 | ret = simple_set_mnt(mnt, sb); | ||
133 | goto out_put; | ||
134 | } | ||
135 | 92 | ||
136 | D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", | 93 | c->mtd = sb->s_mtd; |
137 | mtd->index, mtd->name)); | 94 | c->os_priv = sb; |
95 | sb->s_fs_info = c; | ||
138 | 96 | ||
139 | /* Initialize JFFS2 superblock locks, the further initialization will be | 97 | /* Initialize JFFS2 superblock locks, the further initialization will |
140 | * done later */ | 98 | * be done later */ |
141 | init_MUTEX(&c->alloc_sem); | 99 | init_MUTEX(&c->alloc_sem); |
142 | init_MUTEX(&c->erase_free_sem); | 100 | init_MUTEX(&c->erase_free_sem); |
143 | init_waitqueue_head(&c->erase_wait); | 101 | init_waitqueue_head(&c->erase_wait); |
@@ -146,133 +104,20 @@ static int jffs2_get_sb_mtd(struct file_system_type *fs_type, | |||
146 | spin_lock_init(&c->inocache_lock); | 104 | spin_lock_init(&c->inocache_lock); |
147 | 105 | ||
148 | sb->s_op = &jffs2_super_operations; | 106 | sb->s_op = &jffs2_super_operations; |
149 | sb->s_flags = flags | MS_NOATIME; | 107 | sb->s_flags = sb->s_flags | MS_NOATIME; |
150 | sb->s_xattr = jffs2_xattr_handlers; | 108 | sb->s_xattr = jffs2_xattr_handlers; |
151 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL | 109 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL |
152 | sb->s_flags |= MS_POSIXACL; | 110 | sb->s_flags |= MS_POSIXACL; |
153 | #endif | 111 | #endif |
154 | ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | 112 | return jffs2_do_fill_super(sb, data, silent); |
155 | |||
156 | if (ret) { | ||
157 | /* Failure case... */ | ||
158 | up_write(&sb->s_umount); | ||
159 | deactivate_super(sb); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | sb->s_flags |= MS_ACTIVE; | ||
164 | return simple_set_mnt(mnt, sb); | ||
165 | |||
166 | out_error: | ||
167 | ret = PTR_ERR(sb); | ||
168 | out_put: | ||
169 | kfree(c); | ||
170 | put_mtd_device(mtd); | ||
171 | |||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type, | ||
176 | int flags, const char *dev_name, | ||
177 | void *data, int mtdnr, | ||
178 | struct vfsmount *mnt) | ||
179 | { | ||
180 | struct mtd_info *mtd; | ||
181 | |||
182 | mtd = get_mtd_device(NULL, mtdnr); | ||
183 | if (IS_ERR(mtd)) { | ||
184 | D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); | ||
185 | return PTR_ERR(mtd); | ||
186 | } | ||
187 | |||
188 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); | ||
189 | } | 113 | } |
190 | 114 | ||
191 | static int jffs2_get_sb(struct file_system_type *fs_type, | 115 | static int jffs2_get_sb(struct file_system_type *fs_type, |
192 | int flags, const char *dev_name, | 116 | int flags, const char *dev_name, |
193 | void *data, struct vfsmount *mnt) | 117 | void *data, struct vfsmount *mnt) |
194 | { | 118 | { |
195 | int err; | 119 | return get_sb_mtd(fs_type, flags, dev_name, data, jffs2_fill_super, |
196 | struct nameidata nd; | 120 | mnt); |
197 | int mtdnr; | ||
198 | |||
199 | if (!dev_name) | ||
200 | return -EINVAL; | ||
201 | |||
202 | D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); | ||
203 | |||
204 | /* The preferred way of mounting in future; especially when | ||
205 | CONFIG_BLK_DEV is implemented - we specify the underlying | ||
206 | MTD device by number or by name, so that we don't require | ||
207 | block device support to be present in the kernel. */ | ||
208 | |||
209 | /* FIXME: How to do the root fs this way? */ | ||
210 | |||
211 | if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { | ||
212 | /* Probably mounting without the blkdev crap */ | ||
213 | if (dev_name[3] == ':') { | ||
214 | struct mtd_info *mtd; | ||
215 | |||
216 | /* Mount by MTD device name */ | ||
217 | D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); | ||
218 | for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { | ||
219 | mtd = get_mtd_device(NULL, mtdnr); | ||
220 | if (!IS_ERR(mtd)) { | ||
221 | if (!strcmp(mtd->name, dev_name+4)) | ||
222 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); | ||
223 | put_mtd_device(mtd); | ||
224 | } | ||
225 | } | ||
226 | printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4); | ||
227 | } else if (isdigit(dev_name[3])) { | ||
228 | /* Mount by MTD device number name */ | ||
229 | char *endptr; | ||
230 | |||
231 | mtdnr = simple_strtoul(dev_name+3, &endptr, 0); | ||
232 | if (!*endptr) { | ||
233 | /* It was a valid number */ | ||
234 | D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); | ||
235 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | /* Try the old way - the hack where we allowed users to mount | ||
241 | /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ | ||
242 | |||
243 | err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); | ||
244 | |||
245 | D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n", | ||
246 | err, nd.dentry->d_inode)); | ||
247 | |||
248 | if (err) | ||
249 | return err; | ||
250 | |||
251 | err = -EINVAL; | ||
252 | |||
253 | if (!S_ISBLK(nd.dentry->d_inode->i_mode)) | ||
254 | goto out; | ||
255 | |||
256 | if (nd.mnt->mnt_flags & MNT_NODEV) { | ||
257 | err = -EACCES; | ||
258 | goto out; | ||
259 | } | ||
260 | |||
261 | if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) { | ||
262 | if (!(flags & MS_SILENT)) | ||
263 | printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", | ||
264 | dev_name); | ||
265 | goto out; | ||
266 | } | ||
267 | |||
268 | mtdnr = iminor(nd.dentry->d_inode); | ||
269 | path_release(&nd); | ||
270 | |||
271 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); | ||
272 | |||
273 | out: | ||
274 | path_release(&nd); | ||
275 | return err; | ||
276 | } | 121 | } |
277 | 122 | ||
278 | static void jffs2_put_super (struct super_block *sb) | 123 | static void jffs2_put_super (struct super_block *sb) |
@@ -307,8 +152,7 @@ static void jffs2_kill_sb(struct super_block *sb) | |||
307 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 152 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
308 | if (!(sb->s_flags & MS_RDONLY)) | 153 | if (!(sb->s_flags & MS_RDONLY)) |
309 | jffs2_stop_garbage_collect_thread(c); | 154 | jffs2_stop_garbage_collect_thread(c); |
310 | generic_shutdown_super(sb); | 155 | kill_mtd_super(sb); |
311 | put_mtd_device(c->mtd); | ||
312 | kfree(c); | 156 | kfree(c); |
313 | } | 157 | } |
314 | 158 | ||
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 78fc08893a6c..e48665984cb3 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c | |||
@@ -754,6 +754,10 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) | |||
754 | list_del(&xd->xindex); | 754 | list_del(&xd->xindex); |
755 | jffs2_free_xattr_datum(xd); | 755 | jffs2_free_xattr_datum(xd); |
756 | } | 756 | } |
757 | list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { | ||
758 | list_del(&xd->xindex); | ||
759 | jffs2_free_xattr_datum(xd); | ||
760 | } | ||
757 | } | 761 | } |
758 | 762 | ||
759 | #define XREF_TMPHASH_SIZE (128) | 763 | #define XREF_TMPHASH_SIZE (128) |
@@ -825,7 +829,7 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) | |||
825 | ref->xd and ref->ic are not valid yet. */ | 829 | ref->xd and ref->ic are not valid yet. */ |
826 | xd = jffs2_find_xattr_datum(c, ref->xid); | 830 | xd = jffs2_find_xattr_datum(c, ref->xid); |
827 | ic = jffs2_get_ino_cache(c, ref->ino); | 831 | ic = jffs2_get_ino_cache(c, ref->ino); |
828 | if (!xd || !ic) { | 832 | if (!xd || !ic || !ic->nlink) { |
829 | dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n", | 833 | dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n", |
830 | ref->ino, ref->xid, ref->xseqno); | 834 | ref->ino, ref->xid, ref->xseqno); |
831 | ref->xseqno |= XREF_DELETE_MARKER; | 835 | ref->xseqno |= XREF_DELETE_MARKER; |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 345aa5c0f382..00eee87510fe 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -122,19 +122,25 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_ | |||
122 | return -EINVAL; | 122 | return -EINVAL; |
123 | } | 123 | } |
124 | 124 | ||
125 | static void nfs_direct_dirty_pages(struct page **pages, int npages) | 125 | static void nfs_direct_dirty_pages(struct page **pages, unsigned int pgbase, size_t count) |
126 | { | 126 | { |
127 | int i; | 127 | unsigned int npages; |
128 | unsigned int i; | ||
129 | |||
130 | if (count == 0) | ||
131 | return; | ||
132 | pages += (pgbase >> PAGE_SHIFT); | ||
133 | npages = (count + (pgbase & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
128 | for (i = 0; i < npages; i++) { | 134 | for (i = 0; i < npages; i++) { |
129 | struct page *page = pages[i]; | 135 | struct page *page = pages[i]; |
130 | if (!PageCompound(page)) | 136 | if (!PageCompound(page)) |
131 | set_page_dirty_lock(page); | 137 | set_page_dirty(page); |
132 | } | 138 | } |
133 | } | 139 | } |
134 | 140 | ||
135 | static void nfs_direct_release_pages(struct page **pages, int npages) | 141 | static void nfs_direct_release_pages(struct page **pages, unsigned int npages) |
136 | { | 142 | { |
137 | int i; | 143 | unsigned int i; |
138 | for (i = 0; i < npages; i++) | 144 | for (i = 0; i < npages; i++) |
139 | page_cache_release(pages[i]); | 145 | page_cache_release(pages[i]); |
140 | } | 146 | } |
@@ -162,7 +168,7 @@ static inline struct nfs_direct_req *nfs_direct_req_alloc(void) | |||
162 | return dreq; | 168 | return dreq; |
163 | } | 169 | } |
164 | 170 | ||
165 | static void nfs_direct_req_release(struct kref *kref) | 171 | static void nfs_direct_req_free(struct kref *kref) |
166 | { | 172 | { |
167 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); | 173 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); |
168 | 174 | ||
@@ -171,6 +177,11 @@ static void nfs_direct_req_release(struct kref *kref) | |||
171 | kmem_cache_free(nfs_direct_cachep, dreq); | 177 | kmem_cache_free(nfs_direct_cachep, dreq); |
172 | } | 178 | } |
173 | 179 | ||
180 | static void nfs_direct_req_release(struct nfs_direct_req *dreq) | ||
181 | { | ||
182 | kref_put(&dreq->kref, nfs_direct_req_free); | ||
183 | } | ||
184 | |||
174 | /* | 185 | /* |
175 | * Collects and returns the final error value/byte-count. | 186 | * Collects and returns the final error value/byte-count. |
176 | */ | 187 | */ |
@@ -190,7 +201,6 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) | |||
190 | result = dreq->count; | 201 | result = dreq->count; |
191 | 202 | ||
192 | out: | 203 | out: |
193 | kref_put(&dreq->kref, nfs_direct_req_release); | ||
194 | return (ssize_t) result; | 204 | return (ssize_t) result; |
195 | } | 205 | } |
196 | 206 | ||
@@ -208,7 +218,7 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq) | |||
208 | } | 218 | } |
209 | complete_all(&dreq->completion); | 219 | complete_all(&dreq->completion); |
210 | 220 | ||
211 | kref_put(&dreq->kref, nfs_direct_req_release); | 221 | nfs_direct_req_release(dreq); |
212 | } | 222 | } |
213 | 223 | ||
214 | /* | 224 | /* |
@@ -224,17 +234,18 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata) | |||
224 | if (nfs_readpage_result(task, data) != 0) | 234 | if (nfs_readpage_result(task, data) != 0) |
225 | return; | 235 | return; |
226 | 236 | ||
227 | nfs_direct_dirty_pages(data->pagevec, data->npages); | ||
228 | nfs_direct_release_pages(data->pagevec, data->npages); | ||
229 | |||
230 | spin_lock(&dreq->lock); | 237 | spin_lock(&dreq->lock); |
231 | 238 | if (unlikely(task->tk_status < 0)) { | |
232 | if (likely(task->tk_status >= 0)) | ||
233 | dreq->count += data->res.count; | ||
234 | else | ||
235 | dreq->error = task->tk_status; | 239 | dreq->error = task->tk_status; |
236 | 240 | spin_unlock(&dreq->lock); | |
237 | spin_unlock(&dreq->lock); | 241 | } else { |
242 | dreq->count += data->res.count; | ||
243 | spin_unlock(&dreq->lock); | ||
244 | nfs_direct_dirty_pages(data->pagevec, | ||
245 | data->args.pgbase, | ||
246 | data->res.count); | ||
247 | } | ||
248 | nfs_direct_release_pages(data->pagevec, data->npages); | ||
238 | 249 | ||
239 | if (put_dreq(dreq)) | 250 | if (put_dreq(dreq)) |
240 | nfs_direct_complete(dreq); | 251 | nfs_direct_complete(dreq); |
@@ -279,9 +290,12 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo | |||
279 | result = get_user_pages(current, current->mm, user_addr, | 290 | result = get_user_pages(current, current->mm, user_addr, |
280 | data->npages, 1, 0, data->pagevec, NULL); | 291 | data->npages, 1, 0, data->pagevec, NULL); |
281 | up_read(¤t->mm->mmap_sem); | 292 | up_read(¤t->mm->mmap_sem); |
282 | if (unlikely(result < data->npages)) { | 293 | if (result < 0) { |
283 | if (result > 0) | 294 | nfs_readdata_release(data); |
284 | nfs_direct_release_pages(data->pagevec, result); | 295 | break; |
296 | } | ||
297 | if ((unsigned)result < data->npages) { | ||
298 | nfs_direct_release_pages(data->pagevec, result); | ||
285 | nfs_readdata_release(data); | 299 | nfs_readdata_release(data); |
286 | break; | 300 | break; |
287 | } | 301 | } |
@@ -359,6 +373,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size | |||
359 | if (!result) | 373 | if (!result) |
360 | result = nfs_direct_wait(dreq); | 374 | result = nfs_direct_wait(dreq); |
361 | rpc_clnt_sigunmask(clnt, &oldset); | 375 | rpc_clnt_sigunmask(clnt, &oldset); |
376 | nfs_direct_req_release(dreq); | ||
362 | 377 | ||
363 | return result; | 378 | return result; |
364 | } | 379 | } |
@@ -610,9 +625,12 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l | |||
610 | result = get_user_pages(current, current->mm, user_addr, | 625 | result = get_user_pages(current, current->mm, user_addr, |
611 | data->npages, 0, 0, data->pagevec, NULL); | 626 | data->npages, 0, 0, data->pagevec, NULL); |
612 | up_read(¤t->mm->mmap_sem); | 627 | up_read(¤t->mm->mmap_sem); |
613 | if (unlikely(result < data->npages)) { | 628 | if (result < 0) { |
614 | if (result > 0) | 629 | nfs_writedata_release(data); |
615 | nfs_direct_release_pages(data->pagevec, result); | 630 | break; |
631 | } | ||
632 | if ((unsigned)result < data->npages) { | ||
633 | nfs_direct_release_pages(data->pagevec, result); | ||
616 | nfs_writedata_release(data); | 634 | nfs_writedata_release(data); |
617 | break; | 635 | break; |
618 | } | 636 | } |
@@ -703,6 +721,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz | |||
703 | if (!result) | 721 | if (!result) |
704 | result = nfs_direct_wait(dreq); | 722 | result = nfs_direct_wait(dreq); |
705 | rpc_clnt_sigunmask(clnt, &oldset); | 723 | rpc_clnt_sigunmask(clnt, &oldset); |
724 | nfs_direct_req_release(dreq); | ||
706 | 725 | ||
707 | return result; | 726 | return result; |
708 | } | 727 | } |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index cbdd1c6aaa94..c5bb51a29e80 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -355,6 +355,26 @@ void nfs_pageio_complete(struct nfs_pageio_descriptor *desc) | |||
355 | nfs_pageio_doio(desc); | 355 | nfs_pageio_doio(desc); |
356 | } | 356 | } |
357 | 357 | ||
358 | /** | ||
359 | * nfs_pageio_cond_complete - Conditional I/O completion | ||
360 | * @desc: pointer to io descriptor | ||
361 | * @index: page index | ||
362 | * | ||
363 | * It is important to ensure that processes don't try to take locks | ||
364 | * on non-contiguous ranges of pages as that might deadlock. This | ||
365 | * function should be called before attempting to wait on a locked | ||
366 | * nfs_page. It will complete the I/O if the page index 'index' | ||
367 | * is not contiguous with the existing list of pages in 'desc'. | ||
368 | */ | ||
369 | void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index) | ||
370 | { | ||
371 | if (!list_empty(&desc->pg_list)) { | ||
372 | struct nfs_page *prev = nfs_list_entry(desc->pg_list.prev); | ||
373 | if (index != prev->wb_index + 1) | ||
374 | nfs_pageio_doio(desc); | ||
375 | } | ||
376 | } | ||
377 | |||
358 | #define NFS_SCAN_MAXENTRIES 16 | 378 | #define NFS_SCAN_MAXENTRIES 16 |
359 | /** | 379 | /** |
360 | * nfs_scan_list - Scan a list for matching requests | 380 | * nfs_scan_list - Scan a list for matching requests |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index b084c03ce493..af344a158e01 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -273,8 +273,6 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
273 | * request as dirty (in which case we don't care). | 273 | * request as dirty (in which case we don't care). |
274 | */ | 274 | */ |
275 | spin_unlock(req_lock); | 275 | spin_unlock(req_lock); |
276 | /* Prevent deadlock! */ | ||
277 | nfs_pageio_complete(pgio); | ||
278 | ret = nfs_wait_on_request(req); | 276 | ret = nfs_wait_on_request(req); |
279 | nfs_release_request(req); | 277 | nfs_release_request(req); |
280 | if (ret != 0) | 278 | if (ret != 0) |
@@ -321,6 +319,8 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc | |||
321 | pgio = &mypgio; | 319 | pgio = &mypgio; |
322 | } | 320 | } |
323 | 321 | ||
322 | nfs_pageio_cond_complete(pgio, page->index); | ||
323 | |||
324 | err = nfs_page_async_flush(pgio, page); | 324 | err = nfs_page_async_flush(pgio, page); |
325 | if (err <= 0) | 325 | if (err <= 0) |
326 | goto out; | 326 | goto out; |
@@ -329,6 +329,8 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc | |||
329 | if (!offset) | 329 | if (!offset) |
330 | goto out; | 330 | goto out; |
331 | 331 | ||
332 | nfs_pageio_cond_complete(pgio, page->index); | ||
333 | |||
332 | ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE); | 334 | ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE); |
333 | if (ctx == NULL) { | 335 | if (ctx == NULL) { |
334 | err = -EBADF; | 336 | err = -EBADF; |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 074791ce4ab2..b532a730cec2 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -140,7 +140,7 @@ static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na) | |||
140 | if (!ni->name) | 140 | if (!ni->name) |
141 | return -ENOMEM; | 141 | return -ENOMEM; |
142 | memcpy(ni->name, na->name, i); | 142 | memcpy(ni->name, na->name, i); |
143 | ni->name[i] = 0; | 143 | ni->name[na->name_len] = 0; |
144 | } | 144 | } |
145 | return 0; | 145 | return 0; |
146 | } | 146 | } |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 8e7cafb5fc6c..a480b09c79b9 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -222,7 +222,10 @@ static int ocfs2_readpage(struct file *file, struct page *page) | |||
222 | goto out; | 222 | goto out; |
223 | } | 223 | } |
224 | 224 | ||
225 | down_read(&OCFS2_I(inode)->ip_alloc_sem); | 225 | if (down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem) == 0) { |
226 | ret = AOP_TRUNCATED_PAGE; | ||
227 | goto out_meta_unlock; | ||
228 | } | ||
226 | 229 | ||
227 | /* | 230 | /* |
228 | * i_size might have just been updated as we grabed the meta lock. We | 231 | * i_size might have just been updated as we grabed the meta lock. We |
@@ -235,10 +238,7 @@ static int ocfs2_readpage(struct file *file, struct page *page) | |||
235 | * XXX sys_readahead() seems to get that wrong? | 238 | * XXX sys_readahead() seems to get that wrong? |
236 | */ | 239 | */ |
237 | if (start >= i_size_read(inode)) { | 240 | if (start >= i_size_read(inode)) { |
238 | char *addr = kmap(page); | 241 | zero_user_page(page, 0, PAGE_SIZE, KM_USER0); |
239 | memset(addr, 0, PAGE_SIZE); | ||
240 | flush_dcache_page(page); | ||
241 | kunmap(page); | ||
242 | SetPageUptodate(page); | 242 | SetPageUptodate(page); |
243 | ret = 0; | 243 | ret = 0; |
244 | goto out_alloc; | 244 | goto out_alloc; |
@@ -258,6 +258,7 @@ static int ocfs2_readpage(struct file *file, struct page *page) | |||
258 | ocfs2_data_unlock(inode, 0); | 258 | ocfs2_data_unlock(inode, 0); |
259 | out_alloc: | 259 | out_alloc: |
260 | up_read(&OCFS2_I(inode)->ip_alloc_sem); | 260 | up_read(&OCFS2_I(inode)->ip_alloc_sem); |
261 | out_meta_unlock: | ||
261 | ocfs2_meta_unlock(inode, 0); | 262 | ocfs2_meta_unlock(inode, 0); |
262 | out: | 263 | out: |
263 | if (unlock) | 264 | if (unlock) |
@@ -797,6 +798,11 @@ int ocfs2_map_and_write_splice_data(struct inode *inode, | |||
797 | } | 798 | } |
798 | to = from + bytes; | 799 | to = from + bytes; |
799 | 800 | ||
801 | BUG_ON(from > PAGE_CACHE_SIZE); | ||
802 | BUG_ON(to > PAGE_CACHE_SIZE); | ||
803 | BUG_ON(from < cluster_start); | ||
804 | BUG_ON(to > cluster_end); | ||
805 | |||
800 | if (wc->w_this_page_new) | 806 | if (wc->w_this_page_new) |
801 | ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode, | 807 | ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode, |
802 | cluster_start, cluster_end, 1); | 808 | cluster_start, cluster_end, 1); |
@@ -808,11 +814,6 @@ int ocfs2_map_and_write_splice_data(struct inode *inode, | |||
808 | goto out; | 814 | goto out; |
809 | } | 815 | } |
810 | 816 | ||
811 | BUG_ON(from > PAGE_CACHE_SIZE); | ||
812 | BUG_ON(to > PAGE_CACHE_SIZE); | ||
813 | BUG_ON(from > osb->s_clustersize); | ||
814 | BUG_ON(to > osb->s_clustersize); | ||
815 | |||
816 | src = buf->ops->map(sp->s_pipe, buf, 1); | 817 | src = buf->ops->map(sp->s_pipe, buf, 1); |
817 | dst = kmap_atomic(wc->w_this_page, KM_USER1); | 818 | dst = kmap_atomic(wc->w_this_page, KM_USER1); |
818 | memcpy(dst + from, src + src_from, bytes); | 819 | memcpy(dst + from, src + src_from, bytes); |
@@ -889,6 +890,11 @@ int ocfs2_map_and_write_user_data(struct inode *inode, | |||
889 | 890 | ||
890 | to = from + bytes; | 891 | to = from + bytes; |
891 | 892 | ||
893 | BUG_ON(from > PAGE_CACHE_SIZE); | ||
894 | BUG_ON(to > PAGE_CACHE_SIZE); | ||
895 | BUG_ON(from < cluster_start); | ||
896 | BUG_ON(to > cluster_end); | ||
897 | |||
892 | if (wc->w_this_page_new) | 898 | if (wc->w_this_page_new) |
893 | ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode, | 899 | ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode, |
894 | cluster_start, cluster_end, 1); | 900 | cluster_start, cluster_end, 1); |
@@ -900,11 +906,6 @@ int ocfs2_map_and_write_user_data(struct inode *inode, | |||
900 | goto out; | 906 | goto out; |
901 | } | 907 | } |
902 | 908 | ||
903 | BUG_ON(from > PAGE_CACHE_SIZE); | ||
904 | BUG_ON(to > PAGE_CACHE_SIZE); | ||
905 | BUG_ON(from > osb->s_clustersize); | ||
906 | BUG_ON(to > osb->s_clustersize); | ||
907 | |||
908 | dst = kmap(wc->w_this_page); | 909 | dst = kmap(wc->w_this_page); |
909 | memcpy(dst + from, bp->b_src_buf + src_from, bytes); | 910 | memcpy(dst + from, bp->b_src_buf + src_from, bytes); |
910 | kunmap(wc->w_this_page); | 911 | kunmap(wc->w_this_page); |
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index a93620ce4aca..2b205f5d5790 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c | |||
@@ -144,8 +144,7 @@ static struct kobj_type mlog_ktype = { | |||
144 | }; | 144 | }; |
145 | 145 | ||
146 | static struct kset mlog_kset = { | 146 | static struct kset mlog_kset = { |
147 | .kobj = {.name = "logmask"}, | 147 | .kobj = {.name = "logmask", .ktype = &mlog_ktype}, |
148 | .ktype = &mlog_ktype | ||
149 | }; | 148 | }; |
150 | 149 | ||
151 | int mlog_sys_init(struct kset *o2cb_subsys) | 150 | int mlog_sys_init(struct kset *o2cb_subsys) |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 9395b4fa547d..ac6c96431bbc 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -326,6 +326,7 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
326 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 326 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
327 | (unsigned long long)new_i_size); | 327 | (unsigned long long)new_i_size); |
328 | 328 | ||
329 | unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1); | ||
329 | truncate_inode_pages(inode->i_mapping, new_i_size); | 330 | truncate_inode_pages(inode->i_mapping, new_i_size); |
330 | 331 | ||
331 | fe = (struct ocfs2_dinode *) di_bh->b_data; | 332 | fe = (struct ocfs2_dinode *) di_bh->b_data; |
@@ -1418,36 +1419,6 @@ out: | |||
1418 | return total ? total : ret; | 1419 | return total ? total : ret; |
1419 | } | 1420 | } |
1420 | 1421 | ||
1421 | static int ocfs2_check_iovec(const struct iovec *iov, size_t *counted, | ||
1422 | unsigned long *nr_segs) | ||
1423 | { | ||
1424 | size_t ocount; /* original count */ | ||
1425 | unsigned long seg; | ||
1426 | |||
1427 | ocount = 0; | ||
1428 | for (seg = 0; seg < *nr_segs; seg++) { | ||
1429 | const struct iovec *iv = &iov[seg]; | ||
1430 | |||
1431 | /* | ||
1432 | * If any segment has a negative length, or the cumulative | ||
1433 | * length ever wraps negative then return -EINVAL. | ||
1434 | */ | ||
1435 | ocount += iv->iov_len; | ||
1436 | if (unlikely((ssize_t)(ocount|iv->iov_len) < 0)) | ||
1437 | return -EINVAL; | ||
1438 | if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len)) | ||
1439 | continue; | ||
1440 | if (seg == 0) | ||
1441 | return -EFAULT; | ||
1442 | *nr_segs = seg; | ||
1443 | ocount -= iv->iov_len; /* This segment is no good */ | ||
1444 | break; | ||
1445 | } | ||
1446 | |||
1447 | *counted = ocount; | ||
1448 | return 0; | ||
1449 | } | ||
1450 | |||
1451 | static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, | 1422 | static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, |
1452 | const struct iovec *iov, | 1423 | const struct iovec *iov, |
1453 | unsigned long nr_segs, | 1424 | unsigned long nr_segs, |
@@ -1470,7 +1441,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, | |||
1470 | if (iocb->ki_left == 0) | 1441 | if (iocb->ki_left == 0) |
1471 | return 0; | 1442 | return 0; |
1472 | 1443 | ||
1473 | ret = ocfs2_check_iovec(iov, &ocount, &nr_segs); | 1444 | ret = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); |
1474 | if (ret) | 1445 | if (ret) |
1475 | return ret; | 1446 | return ret; |
1476 | 1447 | ||
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 4dedd9789108..545f7892cdf3 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
@@ -471,9 +471,6 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, | |||
471 | 471 | ||
472 | mutex_lock(&local_alloc_inode->i_mutex); | 472 | mutex_lock(&local_alloc_inode->i_mutex); |
473 | 473 | ||
474 | ac->ac_inode = local_alloc_inode; | ||
475 | ac->ac_which = OCFS2_AC_USE_LOCAL; | ||
476 | |||
477 | if (osb->local_alloc_state != OCFS2_LA_ENABLED) { | 474 | if (osb->local_alloc_state != OCFS2_LA_ENABLED) { |
478 | status = -ENOSPC; | 475 | status = -ENOSPC; |
479 | goto bail; | 476 | goto bail; |
@@ -511,10 +508,14 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, | |||
511 | } | 508 | } |
512 | } | 509 | } |
513 | 510 | ||
511 | ac->ac_inode = local_alloc_inode; | ||
512 | ac->ac_which = OCFS2_AC_USE_LOCAL; | ||
514 | get_bh(osb->local_alloc_bh); | 513 | get_bh(osb->local_alloc_bh); |
515 | ac->ac_bh = osb->local_alloc_bh; | 514 | ac->ac_bh = osb->local_alloc_bh; |
516 | status = 0; | 515 | status = 0; |
517 | bail: | 516 | bail: |
517 | if (status < 0 && local_alloc_inode) | ||
518 | iput(local_alloc_inode); | ||
518 | 519 | ||
519 | mlog_exit(status); | 520 | mlog_exit(status); |
520 | return status; | 521 | return status; |
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 3b481d557edb..5d258c40a2fd 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
@@ -179,7 +179,7 @@ static int ramfs_nommu_resize(struct inode *inode, loff_t newsize, loff_t size) | |||
179 | return ret; | 179 | return ret; |
180 | } | 180 | } |
181 | 181 | ||
182 | ret = vmtruncate(inode, size); | 182 | ret = vmtruncate(inode, newsize); |
183 | 183 | ||
184 | return ret; | 184 | return ret; |
185 | } | 185 | } |
@@ -195,6 +195,11 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia) | |||
195 | unsigned int old_ia_valid = ia->ia_valid; | 195 | unsigned int old_ia_valid = ia->ia_valid; |
196 | int ret = 0; | 196 | int ret = 0; |
197 | 197 | ||
198 | /* POSIX UID/GID verification for setting inode attributes */ | ||
199 | ret = inode_change_ok(inode, ia); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | |||
198 | /* by providing our own setattr() method, we skip this quotaism */ | 203 | /* by providing our own setattr() method, we skip this quotaism */ |
199 | if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) || | 204 | if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) || |
200 | (old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid)) | 205 | (old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid)) |
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index 9c23fee3bae9..ffbfc2caaf20 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c | |||
@@ -10,7 +10,7 @@ | |||
10 | #include <linux/buffer_head.h> | 10 | #include <linux/buffer_head.h> |
11 | #include <asm/uaccess.h> | 11 | #include <asm/uaccess.h> |
12 | 12 | ||
13 | extern struct reiserfs_key MIN_KEY; | 13 | extern const struct reiserfs_key MIN_KEY; |
14 | 14 | ||
15 | static int reiserfs_readdir(struct file *, void *, filldir_t); | 15 | static int reiserfs_readdir(struct file *, void *, filldir_t); |
16 | static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, | 16 | static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, |
diff --git a/fs/signalfd.c b/fs/signalfd.c index 7cfeab412b45..f1da89203a9a 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c | |||
@@ -11,6 +11,8 @@ | |||
11 | * Now using anonymous inode source. | 11 | * Now using anonymous inode source. |
12 | * Thanks to Oleg Nesterov for useful code review and suggestions. | 12 | * Thanks to Oleg Nesterov for useful code review and suggestions. |
13 | * More comments and suggestions from Arnd Bergmann. | 13 | * More comments and suggestions from Arnd Bergmann. |
14 | * Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br> | ||
15 | * Retrieve multiple signals with one read() call | ||
14 | */ | 16 | */ |
15 | 17 | ||
16 | #include <linux/file.h> | 18 | #include <linux/file.h> |
@@ -206,6 +208,59 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, | |||
206 | return err ? -EFAULT: sizeof(*uinfo); | 208 | return err ? -EFAULT: sizeof(*uinfo); |
207 | } | 209 | } |
208 | 210 | ||
211 | static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info, | ||
212 | int nonblock) | ||
213 | { | ||
214 | ssize_t ret; | ||
215 | struct signalfd_lockctx lk; | ||
216 | DECLARE_WAITQUEUE(wait, current); | ||
217 | |||
218 | if (!signalfd_lock(ctx, &lk)) | ||
219 | return 0; | ||
220 | |||
221 | ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); | ||
222 | switch (ret) { | ||
223 | case 0: | ||
224 | if (!nonblock) | ||
225 | break; | ||
226 | ret = -EAGAIN; | ||
227 | default: | ||
228 | signalfd_unlock(&lk); | ||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | add_wait_queue(&ctx->wqh, &wait); | ||
233 | for (;;) { | ||
234 | set_current_state(TASK_INTERRUPTIBLE); | ||
235 | ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); | ||
236 | signalfd_unlock(&lk); | ||
237 | if (ret != 0) | ||
238 | break; | ||
239 | if (signal_pending(current)) { | ||
240 | ret = -ERESTARTSYS; | ||
241 | break; | ||
242 | } | ||
243 | schedule(); | ||
244 | ret = signalfd_lock(ctx, &lk); | ||
245 | if (unlikely(!ret)) { | ||
246 | /* | ||
247 | * Let the caller read zero byte, ala socket | ||
248 | * recv() when the peer disconnect. This test | ||
249 | * must be done before doing a dequeue_signal(), | ||
250 | * because if the sighand has been orphaned, | ||
251 | * the dequeue_signal() call is going to crash | ||
252 | * because ->sighand will be long gone. | ||
253 | */ | ||
254 | break; | ||
255 | } | ||
256 | } | ||
257 | |||
258 | remove_wait_queue(&ctx->wqh, &wait); | ||
259 | __set_current_state(TASK_RUNNING); | ||
260 | |||
261 | return ret; | ||
262 | } | ||
263 | |||
209 | /* | 264 | /* |
210 | * Returns either the size of a "struct signalfd_siginfo", or zero if the | 265 | * Returns either the size of a "struct signalfd_siginfo", or zero if the |
211 | * sighand we are attached to, has been orphaned. The "count" parameter | 266 | * sighand we are attached to, has been orphaned. The "count" parameter |
@@ -215,55 +270,30 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, | |||
215 | loff_t *ppos) | 270 | loff_t *ppos) |
216 | { | 271 | { |
217 | struct signalfd_ctx *ctx = file->private_data; | 272 | struct signalfd_ctx *ctx = file->private_data; |
218 | ssize_t res = 0; | 273 | struct signalfd_siginfo __user *siginfo; |
219 | int locked, signo; | 274 | int nonblock = file->f_flags & O_NONBLOCK; |
275 | ssize_t ret, total = 0; | ||
220 | siginfo_t info; | 276 | siginfo_t info; |
221 | struct signalfd_lockctx lk; | ||
222 | DECLARE_WAITQUEUE(wait, current); | ||
223 | 277 | ||
224 | if (count < sizeof(struct signalfd_siginfo)) | 278 | count /= sizeof(struct signalfd_siginfo); |
279 | if (!count) | ||
225 | return -EINVAL; | 280 | return -EINVAL; |
226 | locked = signalfd_lock(ctx, &lk); | ||
227 | if (!locked) | ||
228 | return 0; | ||
229 | res = -EAGAIN; | ||
230 | signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info); | ||
231 | if (signo == 0 && !(file->f_flags & O_NONBLOCK)) { | ||
232 | add_wait_queue(&ctx->wqh, &wait); | ||
233 | for (;;) { | ||
234 | set_current_state(TASK_INTERRUPTIBLE); | ||
235 | signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info); | ||
236 | if (signo != 0) | ||
237 | break; | ||
238 | if (signal_pending(current)) { | ||
239 | res = -ERESTARTSYS; | ||
240 | break; | ||
241 | } | ||
242 | signalfd_unlock(&lk); | ||
243 | schedule(); | ||
244 | locked = signalfd_lock(ctx, &lk); | ||
245 | if (unlikely(!locked)) { | ||
246 | /* | ||
247 | * Let the caller read zero byte, ala socket | ||
248 | * recv() when the peer disconnect. This test | ||
249 | * must be done before doing a dequeue_signal(), | ||
250 | * because if the sighand has been orphaned, | ||
251 | * the dequeue_signal() call is going to crash. | ||
252 | */ | ||
253 | res = 0; | ||
254 | break; | ||
255 | } | ||
256 | } | ||
257 | remove_wait_queue(&ctx->wqh, &wait); | ||
258 | __set_current_state(TASK_RUNNING); | ||
259 | } | ||
260 | if (likely(locked)) | ||
261 | signalfd_unlock(&lk); | ||
262 | if (likely(signo)) | ||
263 | res = signalfd_copyinfo((struct signalfd_siginfo __user *) buf, | ||
264 | &info); | ||
265 | 281 | ||
266 | return res; | 282 | siginfo = (struct signalfd_siginfo __user *) buf; |
283 | |||
284 | do { | ||
285 | ret = signalfd_dequeue(ctx, &info, nonblock); | ||
286 | if (unlikely(ret <= 0)) | ||
287 | break; | ||
288 | ret = signalfd_copyinfo(siginfo, &info); | ||
289 | if (ret < 0) | ||
290 | break; | ||
291 | siginfo++; | ||
292 | total += ret; | ||
293 | nonblock = 1; | ||
294 | } while (--count); | ||
295 | |||
296 | return total ? total : ret; | ||
267 | } | 297 | } |
268 | 298 | ||
269 | static const struct file_operations signalfd_fops = { | 299 | static const struct file_operations signalfd_fops = { |
diff --git a/fs/splice.c b/fs/splice.c index 12f28281d2b1..cb211360273a 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -272,7 +272,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
272 | struct page *page; | 272 | struct page *page; |
273 | pgoff_t index, end_index; | 273 | pgoff_t index, end_index; |
274 | loff_t isize; | 274 | loff_t isize; |
275 | size_t total_len; | ||
276 | int error, page_nr; | 275 | int error, page_nr; |
277 | struct splice_pipe_desc spd = { | 276 | struct splice_pipe_desc spd = { |
278 | .pages = pages, | 277 | .pages = pages, |
@@ -298,7 +297,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
298 | * Now fill in the holes: | 297 | * Now fill in the holes: |
299 | */ | 298 | */ |
300 | error = 0; | 299 | error = 0; |
301 | total_len = 0; | ||
302 | 300 | ||
303 | /* | 301 | /* |
304 | * Lookup the (hopefully) full range of pages we need. | 302 | * Lookup the (hopefully) full range of pages we need. |
@@ -415,43 +413,47 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
415 | 413 | ||
416 | break; | 414 | break; |
417 | } | 415 | } |
416 | } | ||
417 | fill_it: | ||
418 | /* | ||
419 | * i_size must be checked after PageUptodate. | ||
420 | */ | ||
421 | isize = i_size_read(mapping->host); | ||
422 | end_index = (isize - 1) >> PAGE_CACHE_SHIFT; | ||
423 | if (unlikely(!isize || index > end_index)) | ||
424 | break; | ||
425 | |||
426 | /* | ||
427 | * if this is the last page, see if we need to shrink | ||
428 | * the length and stop | ||
429 | */ | ||
430 | if (end_index == index) { | ||
431 | unsigned int plen; | ||
418 | 432 | ||
419 | /* | 433 | /* |
420 | * i_size must be checked after ->readpage(). | 434 | * max good bytes in this page |
421 | */ | 435 | */ |
422 | isize = i_size_read(mapping->host); | 436 | plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1; |
423 | end_index = (isize - 1) >> PAGE_CACHE_SHIFT; | 437 | if (plen <= loff) |
424 | if (unlikely(!isize || index > end_index)) | ||
425 | break; | 438 | break; |
426 | 439 | ||
427 | /* | 440 | /* |
428 | * if this is the last page, see if we need to shrink | 441 | * force quit after adding this page |
429 | * the length and stop | ||
430 | */ | 442 | */ |
431 | if (end_index == index) { | 443 | this_len = min(this_len, plen - loff); |
432 | loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK); | 444 | len = this_len; |
433 | if (total_len + loff > isize) | ||
434 | break; | ||
435 | /* | ||
436 | * force quit after adding this page | ||
437 | */ | ||
438 | len = this_len; | ||
439 | this_len = min(this_len, loff); | ||
440 | loff = 0; | ||
441 | } | ||
442 | } | 445 | } |
443 | fill_it: | 446 | |
444 | partial[page_nr].offset = loff; | 447 | partial[page_nr].offset = loff; |
445 | partial[page_nr].len = this_len; | 448 | partial[page_nr].len = this_len; |
446 | len -= this_len; | 449 | len -= this_len; |
447 | total_len += this_len; | ||
448 | loff = 0; | 450 | loff = 0; |
449 | spd.nr_pages++; | 451 | spd.nr_pages++; |
450 | index++; | 452 | index++; |
451 | } | 453 | } |
452 | 454 | ||
453 | /* | 455 | /* |
454 | * Release any pages at the end, if we quit early. 'i' is how far | 456 | * Release any pages at the end, if we quit early. 'page_nr' is how far |
455 | * we got, 'nr_pages' is how many pages are in the map. | 457 | * we got, 'nr_pages' is how many pages are in the map. |
456 | */ | 458 | */ |
457 | while (page_nr < nr_pages) | 459 | while (page_nr < nr_pages) |
@@ -478,10 +480,18 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | |||
478 | { | 480 | { |
479 | ssize_t spliced; | 481 | ssize_t spliced; |
480 | int ret; | 482 | int ret; |
483 | loff_t isize, left; | ||
484 | |||
485 | isize = i_size_read(in->f_mapping->host); | ||
486 | if (unlikely(*ppos >= isize)) | ||
487 | return 0; | ||
488 | |||
489 | left = isize - *ppos; | ||
490 | if (unlikely(left < len)) | ||
491 | len = left; | ||
481 | 492 | ||
482 | ret = 0; | 493 | ret = 0; |
483 | spliced = 0; | 494 | spliced = 0; |
484 | |||
485 | while (len) { | 495 | while (len) { |
486 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); | 496 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); |
487 | 497 | ||
@@ -644,7 +654,6 @@ find_page: | |||
644 | * accessed, we are now done! | 654 | * accessed, we are now done! |
645 | */ | 655 | */ |
646 | mark_page_accessed(page); | 656 | mark_page_accessed(page); |
647 | balance_dirty_pages_ratelimited(mapping); | ||
648 | out: | 657 | out: |
649 | page_cache_release(page); | 658 | page_cache_release(page); |
650 | unlock_page(page); | 659 | unlock_page(page); |
@@ -815,6 +824,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, | |||
815 | if (err) | 824 | if (err) |
816 | ret = err; | 825 | ret = err; |
817 | } | 826 | } |
827 | balance_dirty_pages_ratelimited(mapping); | ||
818 | } | 828 | } |
819 | 829 | ||
820 | return ret; | 830 | return ret; |
@@ -868,6 +878,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
868 | if (err) | 878 | if (err) |
869 | ret = err; | 879 | ret = err; |
870 | } | 880 | } |
881 | balance_dirty_pages_ratelimited(mapping); | ||
871 | } | 882 | } |
872 | 883 | ||
873 | return ret; | 884 | return ret; |
@@ -922,7 +933,6 @@ static long do_splice_to(struct file *in, loff_t *ppos, | |||
922 | struct pipe_inode_info *pipe, size_t len, | 933 | struct pipe_inode_info *pipe, size_t len, |
923 | unsigned int flags) | 934 | unsigned int flags) |
924 | { | 935 | { |
925 | loff_t isize, left; | ||
926 | int ret; | 936 | int ret; |
927 | 937 | ||
928 | if (unlikely(!in->f_op || !in->f_op->splice_read)) | 938 | if (unlikely(!in->f_op || !in->f_op->splice_read)) |
@@ -935,14 +945,6 @@ static long do_splice_to(struct file *in, loff_t *ppos, | |||
935 | if (unlikely(ret < 0)) | 945 | if (unlikely(ret < 0)) |
936 | return ret; | 946 | return ret; |
937 | 947 | ||
938 | isize = i_size_read(in->f_mapping->host); | ||
939 | if (unlikely(*ppos >= isize)) | ||
940 | return 0; | ||
941 | |||
942 | left = isize - *ppos; | ||
943 | if (unlikely(left < len)) | ||
944 | len = left; | ||
945 | |||
946 | return in->f_op->splice_read(in, ppos, pipe, len, flags); | 948 | return in->f_op->splice_read(in, ppos, pipe, len, flags); |
947 | } | 949 | } |
948 | 950 | ||
@@ -1058,8 +1060,6 @@ out_release: | |||
1058 | return ret; | 1060 | return ret; |
1059 | } | 1061 | } |
1060 | 1062 | ||
1061 | EXPORT_SYMBOL(do_splice_direct); | ||
1062 | |||
1063 | /* | 1063 | /* |
1064 | * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same | 1064 | * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same |
1065 | * location, so checking ->i_pipe is not enough to verify that this is a | 1065 | * location, so checking ->i_pipe is not enough to verify that this is a |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index c8461551e108..1f0129405cf4 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -460,8 +460,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | |||
460 | kernel_long_ad laarr[EXTENT_MERGE_SIZE]; | 460 | kernel_long_ad laarr[EXTENT_MERGE_SIZE]; |
461 | struct extent_position prev_epos, cur_epos, next_epos; | 461 | struct extent_position prev_epos, cur_epos, next_epos; |
462 | int count = 0, startnum = 0, endnum = 0; | 462 | int count = 0, startnum = 0, endnum = 0; |
463 | uint32_t elen = 0; | 463 | uint32_t elen = 0, tmpelen; |
464 | kernel_lb_addr eloc; | 464 | kernel_lb_addr eloc, tmpeloc; |
465 | int c = 1; | 465 | int c = 1; |
466 | loff_t lbcount = 0, b_off = 0; | 466 | loff_t lbcount = 0, b_off = 0; |
467 | uint32_t newblocknum, newblock; | 467 | uint32_t newblocknum, newblock; |
@@ -520,8 +520,12 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | |||
520 | 520 | ||
521 | b_off -= lbcount; | 521 | b_off -= lbcount; |
522 | offset = b_off >> inode->i_sb->s_blocksize_bits; | 522 | offset = b_off >> inode->i_sb->s_blocksize_bits; |
523 | /* Move into indirect extent if we are at a pointer to it */ | 523 | /* |
524 | udf_next_aext(inode, &prev_epos, &eloc, &elen, 0); | 524 | * Move prev_epos and cur_epos into indirect extent if we are at |
525 | * the pointer to it | ||
526 | */ | ||
527 | udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0); | ||
528 | udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0); | ||
525 | 529 | ||
526 | /* if the extent is allocated and recorded, return the block | 530 | /* if the extent is allocated and recorded, return the block |
527 | if the extent is not a multiple of the blocksize, round up */ | 531 | if the extent is not a multiple of the blocksize, round up */ |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 3a743d854c17..6658afb41cc7 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -1351,7 +1351,7 @@ udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset) | |||
1351 | 1351 | ||
1352 | for (i=0; i<UDF_SB_NUMPARTS(sb); i++) | 1352 | for (i=0; i<UDF_SB_NUMPARTS(sb); i++) |
1353 | { | 1353 | { |
1354 | switch UDF_SB_PARTTYPE(sb, i) | 1354 | switch (UDF_SB_PARTTYPE(sb, i)) |
1355 | { | 1355 | { |
1356 | case UDF_VIRTUAL_MAP15: | 1356 | case UDF_VIRTUAL_MAP15: |
1357 | case UDF_VIRTUAL_MAP20: | 1357 | case UDF_VIRTUAL_MAP20: |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 4475588e973a..7361861e3aac 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -701,7 +701,7 @@ xfs_is_delayed_page( | |||
701 | else if (buffer_delay(bh)) | 701 | else if (buffer_delay(bh)) |
702 | acceptable = (type == IOMAP_DELAY); | 702 | acceptable = (type == IOMAP_DELAY); |
703 | else if (buffer_dirty(bh) && buffer_mapped(bh)) | 703 | else if (buffer_dirty(bh) && buffer_mapped(bh)) |
704 | acceptable = (type == 0); | 704 | acceptable = (type == IOMAP_NEW); |
705 | else | 705 | else |
706 | break; | 706 | break; |
707 | } while ((bh = bh->b_this_page) != head); | 707 | } while ((bh = bh->b_this_page) != head); |
@@ -810,7 +810,7 @@ xfs_convert_page( | |||
810 | page_dirty--; | 810 | page_dirty--; |
811 | count++; | 811 | count++; |
812 | } else { | 812 | } else { |
813 | type = 0; | 813 | type = IOMAP_NEW; |
814 | if (buffer_mapped(bh) && all_bh && startio) { | 814 | if (buffer_mapped(bh) && all_bh && startio) { |
815 | lock_buffer(bh); | 815 | lock_buffer(bh); |
816 | xfs_add_to_ioend(inode, bh, offset, | 816 | xfs_add_to_ioend(inode, bh, offset, |
@@ -968,8 +968,8 @@ xfs_page_state_convert( | |||
968 | 968 | ||
969 | bh = head = page_buffers(page); | 969 | bh = head = page_buffers(page); |
970 | offset = page_offset(page); | 970 | offset = page_offset(page); |
971 | flags = -1; | 971 | flags = BMAPI_READ; |
972 | type = IOMAP_READ; | 972 | type = IOMAP_NEW; |
973 | 973 | ||
974 | /* TODO: cleanup count and page_dirty */ | 974 | /* TODO: cleanup count and page_dirty */ |
975 | 975 | ||
@@ -999,14 +999,14 @@ xfs_page_state_convert( | |||
999 | * | 999 | * |
1000 | * Third case, an unmapped buffer was found, and we are | 1000 | * Third case, an unmapped buffer was found, and we are |
1001 | * in a path where we need to write the whole page out. | 1001 | * in a path where we need to write the whole page out. |
1002 | */ | 1002 | */ |
1003 | if (buffer_unwritten(bh) || buffer_delay(bh) || | 1003 | if (buffer_unwritten(bh) || buffer_delay(bh) || |
1004 | ((buffer_uptodate(bh) || PageUptodate(page)) && | 1004 | ((buffer_uptodate(bh) || PageUptodate(page)) && |
1005 | !buffer_mapped(bh) && (unmapped || startio))) { | 1005 | !buffer_mapped(bh) && (unmapped || startio))) { |
1006 | /* | 1006 | /* |
1007 | * Make sure we don't use a read-only iomap | 1007 | * Make sure we don't use a read-only iomap |
1008 | */ | 1008 | */ |
1009 | if (flags == BMAPI_READ) | 1009 | if (flags == BMAPI_READ) |
1010 | iomap_valid = 0; | 1010 | iomap_valid = 0; |
1011 | 1011 | ||
1012 | if (buffer_unwritten(bh)) { | 1012 | if (buffer_unwritten(bh)) { |
@@ -1055,7 +1055,7 @@ xfs_page_state_convert( | |||
1055 | * That means it must already have extents allocated | 1055 | * That means it must already have extents allocated |
1056 | * underneath it. Map the extent by reading it. | 1056 | * underneath it. Map the extent by reading it. |
1057 | */ | 1057 | */ |
1058 | if (!iomap_valid || type != IOMAP_READ) { | 1058 | if (!iomap_valid || flags != BMAPI_READ) { |
1059 | flags = BMAPI_READ; | 1059 | flags = BMAPI_READ; |
1060 | size = xfs_probe_cluster(inode, page, bh, | 1060 | size = xfs_probe_cluster(inode, page, bh, |
1061 | head, 1); | 1061 | head, 1); |
@@ -1066,7 +1066,15 @@ xfs_page_state_convert( | |||
1066 | iomap_valid = xfs_iomap_valid(&iomap, offset); | 1066 | iomap_valid = xfs_iomap_valid(&iomap, offset); |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | type = IOMAP_READ; | 1069 | /* |
1070 | * We set the type to IOMAP_NEW in case we are doing a | ||
1071 | * small write at EOF that is extending the file but | ||
1072 | * without needing an allocation. We need to update the | ||
1073 | * file size on I/O completion in this case so it is | ||
1074 | * the same case as having just allocated a new extent | ||
1075 | * that we are writing into for the first time. | ||
1076 | */ | ||
1077 | type = IOMAP_NEW; | ||
1070 | if (!test_and_set_bit(BH_Lock, &bh->b_state)) { | 1078 | if (!test_and_set_bit(BH_Lock, &bh->b_state)) { |
1071 | ASSERT(buffer_mapped(bh)); | 1079 | ASSERT(buffer_mapped(bh)); |
1072 | if (iomap_valid) | 1080 | if (iomap_valid) |