diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2005-10-31 05:06:46 -0500 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2005-10-31 05:06:46 -0500 |
commit | 1f04c0a24b2f3cfe89c802a24396263623e3512d (patch) | |
tree | d7e2216b6e65b833c0c2b79b478d13ce17dbf296 /fs | |
parent | 07b188ab773e183871e57b33ae37bf635c9f12ba (diff) | |
parent | e2f2e58e7968f8446b1078a20a18bf8ea12b4fbc (diff) |
Merge branch 'master' of /usr/src/ntfs-2.6/
Diffstat (limited to 'fs')
40 files changed, 283 insertions, 272 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 48f5422cb19a..01a295232f75 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -810,7 +810,7 @@ config TMPFS | |||
810 | 810 | ||
811 | config HUGETLBFS | 811 | config HUGETLBFS |
812 | bool "HugeTLB file system support" | 812 | bool "HugeTLB file system support" |
813 | depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || X86_64 || BROKEN | 813 | depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN |
814 | 814 | ||
815 | config HUGETLB_PAGE | 815 | config HUGETLB_PAGE |
816 | def_bool HUGETLBFS | 816 | def_bool HUGETLBFS |
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 434c19d076ac..175b2e8177c1 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt | |||
@@ -57,7 +57,7 @@ config BINFMT_SHARED_FLAT | |||
57 | 57 | ||
58 | config BINFMT_AOUT | 58 | config BINFMT_AOUT |
59 | tristate "Kernel support for a.out and ECOFF binaries" | 59 | tristate "Kernel support for a.out and ECOFF binaries" |
60 | depends on (X86 && !X86_64) || ALPHA || ARM || M68K || SPARC32 | 60 | depends on X86_32 || ALPHA || ARM || M68K || SPARC32 |
61 | ---help--- | 61 | ---help--- |
62 | A.out (Assembler.OUTput) is a set of formats for libraries and | 62 | A.out (Assembler.OUTput) is a set of formats for libraries and |
63 | executables used in the earliest versions of UNIX. Linux used | 63 | executables used in the earliest versions of UNIX. Linux used |
@@ -117,9 +117,6 @@ int notify_change(struct dentry * dentry, struct iattr * attr) | |||
117 | struct timespec now; | 117 | struct timespec now; |
118 | unsigned int ia_valid = attr->ia_valid; | 118 | unsigned int ia_valid = attr->ia_valid; |
119 | 119 | ||
120 | if (!inode) | ||
121 | BUG(); | ||
122 | |||
123 | mode = inode->i_mode; | 120 | mode = inode->i_mode; |
124 | now = current_fs_time(inode->i_sb); | 121 | now = current_fs_time(inode->i_sb); |
125 | 122 | ||
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 918ccc267e41..6fa6adc40972 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1502,9 +1502,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1502 | fill_psinfo(psinfo, current->group_leader, current->mm); | 1502 | fill_psinfo(psinfo, current->group_leader, current->mm); |
1503 | fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); | 1503 | fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); |
1504 | 1504 | ||
1505 | fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current); | 1505 | numnote = 2; |
1506 | |||
1507 | numnote = 3; | ||
1508 | 1506 | ||
1509 | auxv = (elf_addr_t *) current->mm->saved_auxv; | 1507 | auxv = (elf_addr_t *) current->mm->saved_auxv; |
1510 | 1508 | ||
diff --git a/fs/buffer.c b/fs/buffer.c index 2066e4cb700c..35fa34977e81 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -1478,8 +1478,10 @@ EXPORT_SYMBOL(__getblk); | |||
1478 | void __breadahead(struct block_device *bdev, sector_t block, int size) | 1478 | void __breadahead(struct block_device *bdev, sector_t block, int size) |
1479 | { | 1479 | { |
1480 | struct buffer_head *bh = __getblk(bdev, block, size); | 1480 | struct buffer_head *bh = __getblk(bdev, block, size); |
1481 | ll_rw_block(READA, 1, &bh); | 1481 | if (likely(bh)) { |
1482 | brelse(bh); | 1482 | ll_rw_block(READA, 1, &bh); |
1483 | brelse(bh); | ||
1484 | } | ||
1483 | } | 1485 | } |
1484 | EXPORT_SYMBOL(__breadahead); | 1486 | EXPORT_SYMBOL(__breadahead); |
1485 | 1487 | ||
@@ -1497,7 +1499,7 @@ __bread(struct block_device *bdev, sector_t block, int size) | |||
1497 | { | 1499 | { |
1498 | struct buffer_head *bh = __getblk(bdev, block, size); | 1500 | struct buffer_head *bh = __getblk(bdev, block, size); |
1499 | 1501 | ||
1500 | if (!buffer_uptodate(bh)) | 1502 | if (likely(bh) && !buffer_uptodate(bh)) |
1501 | bh = __bread_slow(bh); | 1503 | bh = __bread_slow(bh); |
1502 | return bh; | 1504 | return bh; |
1503 | } | 1505 | } |
@@ -1637,6 +1639,15 @@ out: | |||
1637 | } | 1639 | } |
1638 | EXPORT_SYMBOL(block_invalidatepage); | 1640 | EXPORT_SYMBOL(block_invalidatepage); |
1639 | 1641 | ||
1642 | int do_invalidatepage(struct page *page, unsigned long offset) | ||
1643 | { | ||
1644 | int (*invalidatepage)(struct page *, unsigned long); | ||
1645 | invalidatepage = page->mapping->a_ops->invalidatepage; | ||
1646 | if (invalidatepage == NULL) | ||
1647 | invalidatepage = block_invalidatepage; | ||
1648 | return (*invalidatepage)(page, offset); | ||
1649 | } | ||
1650 | |||
1640 | /* | 1651 | /* |
1641 | * We attach and possibly dirty the buffers atomically wrt | 1652 | * We attach and possibly dirty the buffers atomically wrt |
1642 | * __set_page_dirty_buffers() via private_lock. try_to_free_buffers | 1653 | * __set_page_dirty_buffers() via private_lock. try_to_free_buffers |
@@ -2696,7 +2707,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block, | |||
2696 | * they may have been added in ext3_writepage(). Make them | 2707 | * they may have been added in ext3_writepage(). Make them |
2697 | * freeable here, so the page does not leak. | 2708 | * freeable here, so the page does not leak. |
2698 | */ | 2709 | */ |
2699 | block_invalidatepage(page, 0); | 2710 | do_invalidatepage(page, 0); |
2700 | unlock_page(page); | 2711 | unlock_page(page); |
2701 | return 0; /* don't care */ | 2712 | return 0; /* don't care */ |
2702 | } | 2713 | } |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index a327e03753ac..43dbcb0b21eb 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -3046,6 +3046,10 @@ HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) | |||
3046 | /* Serial */ | 3046 | /* Serial */ |
3047 | HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) | 3047 | HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) |
3048 | HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) | 3048 | HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) |
3049 | #ifdef TIOCGLTC | ||
3050 | COMPATIBLE_IOCTL(TIOCGLTC) | ||
3051 | COMPATIBLE_IOCTL(TIOCSLTC) | ||
3052 | #endif | ||
3049 | /* Usbdevfs */ | 3053 | /* Usbdevfs */ |
3050 | HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) | 3054 | HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) |
3051 | HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) | 3055 | HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) |
diff --git a/fs/dquot.c b/fs/dquot.c index 05f3327d64a3..ea7644227a65 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -662,7 +662,7 @@ static void add_dquot_ref(struct super_block *sb, int type) | |||
662 | restart: | 662 | restart: |
663 | file_list_lock(); | 663 | file_list_lock(); |
664 | list_for_each(p, &sb->s_files) { | 664 | list_for_each(p, &sb->s_files) { |
665 | struct file *filp = list_entry(p, struct file, f_list); | 665 | struct file *filp = list_entry(p, struct file, f_u.fu_list); |
666 | struct inode *inode = filp->f_dentry->d_inode; | 666 | struct inode *inode = filp->f_dentry->d_inode; |
667 | if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { | 667 | if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { |
668 | struct dentry *dentry = dget(filp->f_dentry); | 668 | struct dentry *dentry = dget(filp->f_dentry); |
@@ -630,10 +630,9 @@ static inline int de_thread(struct task_struct *tsk) | |||
630 | /* | 630 | /* |
631 | * Account for the thread group leader hanging around: | 631 | * Account for the thread group leader hanging around: |
632 | */ | 632 | */ |
633 | count = 2; | 633 | count = 1; |
634 | if (thread_group_leader(current)) | 634 | if (!thread_group_leader(current)) { |
635 | count = 1; | 635 | count = 2; |
636 | else { | ||
637 | /* | 636 | /* |
638 | * The SIGALRM timer survives the exec, but needs to point | 637 | * The SIGALRM timer survives the exec, but needs to point |
639 | * at us as the new group leader now. We have a race with | 638 | * at us as the new group leader now. We have a race with |
@@ -642,8 +641,10 @@ static inline int de_thread(struct task_struct *tsk) | |||
642 | * before we can safely let the old group leader die. | 641 | * before we can safely let the old group leader die. |
643 | */ | 642 | */ |
644 | sig->real_timer.data = (unsigned long)current; | 643 | sig->real_timer.data = (unsigned long)current; |
644 | spin_unlock_irq(lock); | ||
645 | if (del_timer_sync(&sig->real_timer)) | 645 | if (del_timer_sync(&sig->real_timer)) |
646 | add_timer(&sig->real_timer); | 646 | add_timer(&sig->real_timer); |
647 | spin_lock_irq(lock); | ||
647 | } | 648 | } |
648 | while (atomic_read(&sig->count) > count) { | 649 | while (atomic_read(&sig->count) > count) { |
649 | sig->group_exit_task = current; | 650 | sig->group_exit_task = current; |
@@ -655,7 +656,6 @@ static inline int de_thread(struct task_struct *tsk) | |||
655 | } | 656 | } |
656 | sig->group_exit_task = NULL; | 657 | sig->group_exit_task = NULL; |
657 | sig->notify_count = 0; | 658 | sig->notify_count = 0; |
658 | sig->real_timer.data = (unsigned long)current; | ||
659 | spin_unlock_irq(lock); | 659 | spin_unlock_irq(lock); |
660 | 660 | ||
661 | /* | 661 | /* |
@@ -1417,19 +1417,16 @@ static void zap_threads (struct mm_struct *mm) | |||
1417 | static void coredump_wait(struct mm_struct *mm) | 1417 | static void coredump_wait(struct mm_struct *mm) |
1418 | { | 1418 | { |
1419 | DECLARE_COMPLETION(startup_done); | 1419 | DECLARE_COMPLETION(startup_done); |
1420 | int core_waiters; | ||
1420 | 1421 | ||
1421 | mm->core_waiters++; /* let other threads block */ | ||
1422 | mm->core_startup_done = &startup_done; | 1422 | mm->core_startup_done = &startup_done; |
1423 | 1423 | ||
1424 | /* give other threads a chance to run: */ | ||
1425 | yield(); | ||
1426 | |||
1427 | zap_threads(mm); | 1424 | zap_threads(mm); |
1428 | if (--mm->core_waiters) { | 1425 | core_waiters = mm->core_waiters; |
1429 | up_write(&mm->mmap_sem); | 1426 | up_write(&mm->mmap_sem); |
1427 | |||
1428 | if (core_waiters) | ||
1430 | wait_for_completion(&startup_done); | 1429 | wait_for_completion(&startup_done); |
1431 | } else | ||
1432 | up_write(&mm->mmap_sem); | ||
1433 | BUG_ON(mm->core_waiters); | 1430 | BUG_ON(mm->core_waiters); |
1434 | } | 1431 | } |
1435 | 1432 | ||
@@ -1463,11 +1460,21 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1463 | current->fsuid = 0; /* Dump root private */ | 1460 | current->fsuid = 0; /* Dump root private */ |
1464 | } | 1461 | } |
1465 | mm->dumpable = 0; | 1462 | mm->dumpable = 0; |
1466 | init_completion(&mm->core_done); | 1463 | |
1464 | retval = -EAGAIN; | ||
1467 | spin_lock_irq(¤t->sighand->siglock); | 1465 | spin_lock_irq(¤t->sighand->siglock); |
1468 | current->signal->flags = SIGNAL_GROUP_EXIT; | 1466 | if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { |
1469 | current->signal->group_exit_code = exit_code; | 1467 | current->signal->flags = SIGNAL_GROUP_EXIT; |
1468 | current->signal->group_exit_code = exit_code; | ||
1469 | retval = 0; | ||
1470 | } | ||
1470 | spin_unlock_irq(¤t->sighand->siglock); | 1471 | spin_unlock_irq(¤t->sighand->siglock); |
1472 | if (retval) { | ||
1473 | up_write(&mm->mmap_sem); | ||
1474 | goto fail; | ||
1475 | } | ||
1476 | |||
1477 | init_completion(&mm->core_done); | ||
1471 | coredump_wait(mm); | 1478 | coredump_wait(mm); |
1472 | 1479 | ||
1473 | /* | 1480 | /* |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index fdba4d1d3c60..e7d3f0522d01 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -440,6 +440,10 @@ static int ext2_alloc_branch(struct inode *inode, | |||
440 | * the pointer to new one, then send parent to disk. | 440 | * the pointer to new one, then send parent to disk. |
441 | */ | 441 | */ |
442 | bh = sb_getblk(inode->i_sb, parent); | 442 | bh = sb_getblk(inode->i_sb, parent); |
443 | if (!bh) { | ||
444 | err = -EIO; | ||
445 | break; | ||
446 | } | ||
443 | lock_buffer(bh); | 447 | lock_buffer(bh); |
444 | memset(bh->b_data, 0, blocksize); | 448 | memset(bh->b_data, 0, blocksize); |
445 | branch[n].bh = bh; | 449 | branch[n].bh = bh; |
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 0213db4911a2..7992d21e0e09 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/quotaops.h> | 20 | #include <linux/quotaops.h> |
21 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
22 | 22 | ||
23 | #include "bitmap.h" | ||
24 | |||
23 | /* | 25 | /* |
24 | * balloc.c contains the blocks allocation and deallocation routines | 26 | * balloc.c contains the blocks allocation and deallocation routines |
25 | */ | 27 | */ |
@@ -1010,7 +1012,7 @@ retry: | |||
1010 | * allocation within the reservation window. | 1012 | * allocation within the reservation window. |
1011 | * | 1013 | * |
1012 | * This will avoid keeping on searching the reservation list again and | 1014 | * This will avoid keeping on searching the reservation list again and |
1013 | * again when someboday is looking for a free block (without | 1015 | * again when somebody is looking for a free block (without |
1014 | * reservation), and there are lots of free blocks, but they are all | 1016 | * reservation), and there are lots of free blocks, but they are all |
1015 | * being reserved. | 1017 | * being reserved. |
1016 | * | 1018 | * |
@@ -1416,12 +1418,12 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) | |||
1416 | unsigned long bitmap_count, x; | 1418 | unsigned long bitmap_count, x; |
1417 | struct buffer_head *bitmap_bh = NULL; | 1419 | struct buffer_head *bitmap_bh = NULL; |
1418 | 1420 | ||
1419 | lock_super(sb); | ||
1420 | es = EXT3_SB(sb)->s_es; | 1421 | es = EXT3_SB(sb)->s_es; |
1421 | desc_count = 0; | 1422 | desc_count = 0; |
1422 | bitmap_count = 0; | 1423 | bitmap_count = 0; |
1423 | gdp = NULL; | 1424 | gdp = NULL; |
1424 | 1425 | ||
1426 | smp_rmb(); | ||
1425 | for (i = 0; i < ngroups; i++) { | 1427 | for (i = 0; i < ngroups; i++) { |
1426 | gdp = ext3_get_group_desc(sb, i, NULL); | 1428 | gdp = ext3_get_group_desc(sb, i, NULL); |
1427 | if (!gdp) | 1429 | if (!gdp) |
@@ -1440,7 +1442,6 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) | |||
1440 | brelse(bitmap_bh); | 1442 | brelse(bitmap_bh); |
1441 | printk("ext3_count_free_blocks: stored = %u, computed = %lu, %lu\n", | 1443 | printk("ext3_count_free_blocks: stored = %u, computed = %lu, %lu\n", |
1442 | le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count); | 1444 | le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count); |
1443 | unlock_super(sb); | ||
1444 | return bitmap_count; | 1445 | return bitmap_count; |
1445 | #else | 1446 | #else |
1446 | desc_count = 0; | 1447 | desc_count = 0; |
diff --git a/fs/ext3/bitmap.c b/fs/ext3/bitmap.c index 6c419b9ab0e8..5b4ba3e246e6 100644 --- a/fs/ext3/bitmap.c +++ b/fs/ext3/bitmap.c | |||
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/buffer_head.h> | 10 | #include <linux/buffer_head.h> |
11 | 11 | #include "bitmap.h" | |
12 | 12 | ||
13 | static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; | 13 | static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; |
14 | 14 | ||
diff --git a/fs/ext3/bitmap.h b/fs/ext3/bitmap.h new file mode 100644 index 000000000000..6ee503a6bb4e --- /dev/null +++ b/fs/ext3/bitmap.h | |||
@@ -0,0 +1,8 @@ | |||
1 | /* linux/fs/ext3/bitmap.c | ||
2 | * | ||
3 | * Copyright (C) 2005 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | extern unsigned long ext3_count_free (struct buffer_head *, unsigned int ); | ||
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 6549945f9ac1..df3f517c54ac 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <asm/byteorder.h> | 27 | #include <asm/byteorder.h> |
28 | 28 | ||
29 | #include "bitmap.h" | ||
29 | #include "xattr.h" | 30 | #include "xattr.h" |
30 | #include "acl.h" | 31 | #include "acl.h" |
31 | 32 | ||
@@ -704,7 +705,6 @@ unsigned long ext3_count_free_inodes (struct super_block * sb) | |||
704 | unsigned long bitmap_count, x; | 705 | unsigned long bitmap_count, x; |
705 | struct buffer_head *bitmap_bh = NULL; | 706 | struct buffer_head *bitmap_bh = NULL; |
706 | 707 | ||
707 | lock_super (sb); | ||
708 | es = EXT3_SB(sb)->s_es; | 708 | es = EXT3_SB(sb)->s_es; |
709 | desc_count = 0; | 709 | desc_count = 0; |
710 | bitmap_count = 0; | 710 | bitmap_count = 0; |
@@ -727,7 +727,6 @@ unsigned long ext3_count_free_inodes (struct super_block * sb) | |||
727 | brelse(bitmap_bh); | 727 | brelse(bitmap_bh); |
728 | printk("ext3_count_free_inodes: stored = %u, computed = %lu, %lu\n", | 728 | printk("ext3_count_free_inodes: stored = %u, computed = %lu, %lu\n", |
729 | le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count); | 729 | le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count); |
730 | unlock_super(sb); | ||
731 | return desc_count; | 730 | return desc_count; |
732 | #else | 731 | #else |
733 | desc_count = 0; | 732 | desc_count = 0; |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 8b38f2232796..5d9b00e28837 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -491,7 +491,7 @@ static unsigned long ext3_find_goal(struct inode *inode, long block, | |||
491 | * the same format as ext3_get_branch() would do. We are calling it after | 491 | * the same format as ext3_get_branch() would do. We are calling it after |
492 | * we had read the existing part of chain and partial points to the last | 492 | * we had read the existing part of chain and partial points to the last |
493 | * triple of that (one with zero ->key). Upon the exit we have the same | 493 | * triple of that (one with zero ->key). Upon the exit we have the same |
494 | * picture as after the successful ext3_get_block(), excpet that in one | 494 | * picture as after the successful ext3_get_block(), except that in one |
495 | * place chain is disconnected - *branch->p is still zero (we did not | 495 | * place chain is disconnected - *branch->p is still zero (we did not |
496 | * set the last link), but branch->key contains the number that should | 496 | * set the last link), but branch->key contains the number that should |
497 | * be placed into *branch->p to fill that gap. | 497 | * be placed into *branch->p to fill that gap. |
@@ -523,7 +523,6 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode, | |||
523 | if (!nr) | 523 | if (!nr) |
524 | break; | 524 | break; |
525 | branch[n].key = cpu_to_le32(nr); | 525 | branch[n].key = cpu_to_le32(nr); |
526 | keys = n+1; | ||
527 | 526 | ||
528 | /* | 527 | /* |
529 | * Get buffer_head for parent block, zero it out | 528 | * Get buffer_head for parent block, zero it out |
@@ -531,6 +530,9 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode, | |||
531 | * parent to disk. | 530 | * parent to disk. |
532 | */ | 531 | */ |
533 | bh = sb_getblk(inode->i_sb, parent); | 532 | bh = sb_getblk(inode->i_sb, parent); |
533 | if (!bh) | ||
534 | break; | ||
535 | keys = n+1; | ||
534 | branch[n].bh = bh; | 536 | branch[n].bh = bh; |
535 | lock_buffer(bh); | 537 | lock_buffer(bh); |
536 | BUFFER_TRACE(bh, "call get_create_access"); | 538 | BUFFER_TRACE(bh, "call get_create_access"); |
@@ -864,6 +866,10 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode, | |||
864 | if (!*errp && buffer_mapped(&dummy)) { | 866 | if (!*errp && buffer_mapped(&dummy)) { |
865 | struct buffer_head *bh; | 867 | struct buffer_head *bh; |
866 | bh = sb_getblk(inode->i_sb, dummy.b_blocknr); | 868 | bh = sb_getblk(inode->i_sb, dummy.b_blocknr); |
869 | if (!bh) { | ||
870 | *errp = -EIO; | ||
871 | goto err; | ||
872 | } | ||
867 | if (buffer_new(&dummy)) { | 873 | if (buffer_new(&dummy)) { |
868 | J_ASSERT(create != 0); | 874 | J_ASSERT(create != 0); |
869 | J_ASSERT(handle != 0); | 875 | J_ASSERT(handle != 0); |
@@ -896,6 +902,7 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode, | |||
896 | } | 902 | } |
897 | return bh; | 903 | return bh; |
898 | } | 904 | } |
905 | err: | ||
899 | return NULL; | 906 | return NULL; |
900 | } | 907 | } |
901 | 908 | ||
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 50378d8ff84b..b3c690a3b54a 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -36,6 +36,8 @@ | |||
36 | #include <linux/quotaops.h> | 36 | #include <linux/quotaops.h> |
37 | #include <linux/buffer_head.h> | 37 | #include <linux/buffer_head.h> |
38 | #include <linux/smp_lock.h> | 38 | #include <linux/smp_lock.h> |
39 | |||
40 | #include "namei.h" | ||
39 | #include "xattr.h" | 41 | #include "xattr.h" |
40 | #include "acl.h" | 42 | #include "acl.h" |
41 | 43 | ||
diff --git a/fs/ext3/namei.h b/fs/ext3/namei.h new file mode 100644 index 000000000000..f2ce2b0065c9 --- /dev/null +++ b/fs/ext3/namei.h | |||
@@ -0,0 +1,8 @@ | |||
1 | /* linux/fs/ext3/namei.h | ||
2 | * | ||
3 | * Copyright (C) 2005 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | extern struct dentry *ext3_get_parent(struct dentry *child); | ||
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 57f79106267d..1be78b4b4de9 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -118,6 +118,8 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb, | |||
118 | int err; | 118 | int err; |
119 | 119 | ||
120 | bh = sb_getblk(sb, blk); | 120 | bh = sb_getblk(sb, blk); |
121 | if (!bh) | ||
122 | return ERR_PTR(-EIO); | ||
121 | if ((err = ext3_journal_get_write_access(handle, bh))) { | 123 | if ((err = ext3_journal_get_write_access(handle, bh))) { |
122 | brelse(bh); | 124 | brelse(bh); |
123 | bh = ERR_PTR(err); | 125 | bh = ERR_PTR(err); |
@@ -202,6 +204,10 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
202 | ext3_debug("update backup group %#04lx (+%d)\n", block, bit); | 204 | ext3_debug("update backup group %#04lx (+%d)\n", block, bit); |
203 | 205 | ||
204 | gdb = sb_getblk(sb, block); | 206 | gdb = sb_getblk(sb, block); |
207 | if (!gdb) { | ||
208 | err = -EIO; | ||
209 | goto exit_bh; | ||
210 | } | ||
205 | if ((err = ext3_journal_get_write_access(handle, gdb))) { | 211 | if ((err = ext3_journal_get_write_access(handle, gdb))) { |
206 | brelse(gdb); | 212 | brelse(gdb); |
207 | goto exit_bh; | 213 | goto exit_bh; |
@@ -643,6 +649,10 @@ static void update_backups(struct super_block *sb, | |||
643 | break; | 649 | break; |
644 | 650 | ||
645 | bh = sb_getblk(sb, group * bpg + blk_off); | 651 | bh = sb_getblk(sb, group * bpg + blk_off); |
652 | if (!bh) { | ||
653 | err = -EIO; | ||
654 | break; | ||
655 | } | ||
646 | ext3_debug("update metadata backup %#04lx\n", | 656 | ext3_debug("update metadata backup %#04lx\n", |
647 | (unsigned long)bh->b_blocknr); | 657 | (unsigned long)bh->b_blocknr); |
648 | if ((err = ext3_journal_get_write_access(handle, bh))) | 658 | if ((err = ext3_journal_get_write_access(handle, bh))) |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 097383c11154..f594989ccb7a 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -36,9 +36,12 @@ | |||
36 | #include <linux/namei.h> | 36 | #include <linux/namei.h> |
37 | #include <linux/quotaops.h> | 37 | #include <linux/quotaops.h> |
38 | #include <linux/seq_file.h> | 38 | #include <linux/seq_file.h> |
39 | |||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
41 | |||
40 | #include "xattr.h" | 42 | #include "xattr.h" |
41 | #include "acl.h" | 43 | #include "acl.h" |
44 | #include "namei.h" | ||
42 | 45 | ||
43 | static int ext3_load_journal(struct super_block *, struct ext3_super_block *); | 46 | static int ext3_load_journal(struct super_block *, struct ext3_super_block *); |
44 | static int ext3_create_journal(struct super_block *, struct ext3_super_block *, | 47 | static int ext3_create_journal(struct super_block *, struct ext3_super_block *, |
@@ -615,7 +618,6 @@ static struct super_operations ext3_sops = { | |||
615 | #endif | 618 | #endif |
616 | }; | 619 | }; |
617 | 620 | ||
618 | struct dentry *ext3_get_parent(struct dentry *child); | ||
619 | static struct export_operations ext3_export_ops = { | 621 | static struct export_operations ext3_export_ops = { |
620 | .get_parent = ext3_get_parent, | 622 | .get_parent = ext3_get_parent, |
621 | }; | 623 | }; |
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 269c7b92db9a..430de9f63be3 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c | |||
@@ -210,7 +210,7 @@ ext3_xattr_find_entry(struct ext3_xattr_entry **pentry, int name_index, | |||
210 | return cmp ? -ENODATA : 0; | 210 | return cmp ? -ENODATA : 0; |
211 | } | 211 | } |
212 | 212 | ||
213 | int | 213 | static int |
214 | ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, | 214 | ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, |
215 | void *buffer, size_t buffer_size) | 215 | void *buffer, size_t buffer_size) |
216 | { | 216 | { |
@@ -354,7 +354,7 @@ ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry, | |||
354 | return buffer_size - rest; | 354 | return buffer_size - rest; |
355 | } | 355 | } |
356 | 356 | ||
357 | int | 357 | static int |
358 | ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) | 358 | ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) |
359 | { | 359 | { |
360 | struct buffer_head *bh = NULL; | 360 | struct buffer_head *bh = NULL; |
@@ -626,7 +626,7 @@ struct ext3_xattr_block_find { | |||
626 | struct buffer_head *bh; | 626 | struct buffer_head *bh; |
627 | }; | 627 | }; |
628 | 628 | ||
629 | int | 629 | static int |
630 | ext3_xattr_block_find(struct inode *inode, struct ext3_xattr_info *i, | 630 | ext3_xattr_block_find(struct inode *inode, struct ext3_xattr_info *i, |
631 | struct ext3_xattr_block_find *bs) | 631 | struct ext3_xattr_block_find *bs) |
632 | { | 632 | { |
@@ -859,7 +859,7 @@ struct ext3_xattr_ibody_find { | |||
859 | struct ext3_iloc iloc; | 859 | struct ext3_iloc iloc; |
860 | }; | 860 | }; |
861 | 861 | ||
862 | int | 862 | static int |
863 | ext3_xattr_ibody_find(struct inode *inode, struct ext3_xattr_info *i, | 863 | ext3_xattr_ibody_find(struct inode *inode, struct ext3_xattr_info *i, |
864 | struct ext3_xattr_ibody_find *is) | 864 | struct ext3_xattr_ibody_find *is) |
865 | { | 865 | { |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 895049b2ac9c..ba824964b9bb 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
@@ -222,6 +222,80 @@ fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size, | |||
222 | return len; | 222 | return len; |
223 | } | 223 | } |
224 | 224 | ||
225 | enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, }; | ||
226 | |||
227 | /** | ||
228 | * fat_parse_long - Parse extended directory entry. | ||
229 | * | ||
230 | * This function returns zero on success, negative value on error, or one of | ||
231 | * the following: | ||
232 | * | ||
233 | * %PARSE_INVALID - Directory entry is invalid. | ||
234 | * %PARSE_NOT_LONGNAME - Directory entry does not contain longname. | ||
235 | * %PARSE_EOF - Directory has no more entries. | ||
236 | */ | ||
237 | static int fat_parse_long(struct inode *dir, loff_t *pos, | ||
238 | struct buffer_head **bh, struct msdos_dir_entry **de, | ||
239 | wchar_t **unicode, unsigned char *nr_slots) | ||
240 | { | ||
241 | struct msdos_dir_slot *ds; | ||
242 | unsigned char id, slot, slots, alias_checksum; | ||
243 | |||
244 | if (!*unicode) { | ||
245 | *unicode = (wchar_t *)__get_free_page(GFP_KERNEL); | ||
246 | if (!*unicode) { | ||
247 | brelse(*bh); | ||
248 | return -ENOMEM; | ||
249 | } | ||
250 | } | ||
251 | parse_long: | ||
252 | slots = 0; | ||
253 | ds = (struct msdos_dir_slot *)*de; | ||
254 | id = ds->id; | ||
255 | if (!(id & 0x40)) | ||
256 | return PARSE_INVALID; | ||
257 | slots = id & ~0x40; | ||
258 | if (slots > 20 || !slots) /* ceil(256 * 2 / 26) */ | ||
259 | return PARSE_INVALID; | ||
260 | *nr_slots = slots; | ||
261 | alias_checksum = ds->alias_checksum; | ||
262 | |||
263 | slot = slots; | ||
264 | while (1) { | ||
265 | int offset; | ||
266 | |||
267 | slot--; | ||
268 | offset = slot * 13; | ||
269 | fat16_towchar(*unicode + offset, ds->name0_4, 5); | ||
270 | fat16_towchar(*unicode + offset + 5, ds->name5_10, 6); | ||
271 | fat16_towchar(*unicode + offset + 11, ds->name11_12, 2); | ||
272 | |||
273 | if (ds->id & 0x40) | ||
274 | (*unicode)[offset + 13] = 0; | ||
275 | if (fat_get_entry(dir, pos, bh, de) < 0) | ||
276 | return PARSE_EOF; | ||
277 | if (slot == 0) | ||
278 | break; | ||
279 | ds = (struct msdos_dir_slot *)*de; | ||
280 | if (ds->attr != ATTR_EXT) | ||
281 | return PARSE_NOT_LONGNAME; | ||
282 | if ((ds->id & ~0x40) != slot) | ||
283 | goto parse_long; | ||
284 | if (ds->alias_checksum != alias_checksum) | ||
285 | goto parse_long; | ||
286 | } | ||
287 | if ((*de)->name[0] == DELETED_FLAG) | ||
288 | return PARSE_INVALID; | ||
289 | if ((*de)->attr == ATTR_EXT) | ||
290 | goto parse_long; | ||
291 | if (IS_FREE((*de)->name) || ((*de)->attr & ATTR_VOLUME)) | ||
292 | return PARSE_INVALID; | ||
293 | if (fat_checksum((*de)->name) != alias_checksum) | ||
294 | *nr_slots = 0; | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
225 | /* | 299 | /* |
226 | * Return values: negative -> error, 0 -> not found, positive -> found, | 300 | * Return values: negative -> error, 0 -> not found, positive -> found, |
227 | * value is the total amount of slots, including the shortname entry. | 301 | * value is the total amount of slots, including the shortname entry. |
@@ -259,68 +333,16 @@ parse_record: | |||
259 | if (de->attr != ATTR_EXT && IS_FREE(de->name)) | 333 | if (de->attr != ATTR_EXT && IS_FREE(de->name)) |
260 | continue; | 334 | continue; |
261 | if (de->attr == ATTR_EXT) { | 335 | if (de->attr == ATTR_EXT) { |
262 | struct msdos_dir_slot *ds; | 336 | int status = fat_parse_long(inode, &cpos, &bh, &de, |
263 | unsigned char id; | 337 | &unicode, &nr_slots); |
264 | unsigned char slot; | 338 | if (status < 0) |
265 | unsigned char slots; | 339 | return status; |
266 | unsigned char sum; | 340 | else if (status == PARSE_INVALID) |
267 | unsigned char alias_checksum; | ||
268 | |||
269 | if (!unicode) { | ||
270 | unicode = (wchar_t *) | ||
271 | __get_free_page(GFP_KERNEL); | ||
272 | if (!unicode) { | ||
273 | brelse(bh); | ||
274 | return -ENOMEM; | ||
275 | } | ||
276 | } | ||
277 | parse_long: | ||
278 | slots = 0; | ||
279 | ds = (struct msdos_dir_slot *) de; | ||
280 | id = ds->id; | ||
281 | if (!(id & 0x40)) | ||
282 | continue; | ||
283 | slots = id & ~0x40; | ||
284 | if (slots > 20 || !slots) /* ceil(256 * 2 / 26) */ | ||
285 | continue; | ||
286 | nr_slots = slots; | ||
287 | alias_checksum = ds->alias_checksum; | ||
288 | |||
289 | slot = slots; | ||
290 | while (1) { | ||
291 | int offset; | ||
292 | |||
293 | slot--; | ||
294 | offset = slot * 13; | ||
295 | fat16_towchar(unicode + offset, ds->name0_4, 5); | ||
296 | fat16_towchar(unicode + offset + 5, ds->name5_10, 6); | ||
297 | fat16_towchar(unicode + offset + 11, ds->name11_12, 2); | ||
298 | |||
299 | if (ds->id & 0x40) { | ||
300 | unicode[offset + 13] = 0; | ||
301 | } | ||
302 | if (fat_get_entry(inode, &cpos, &bh, &de) < 0) | ||
303 | goto EODir; | ||
304 | if (slot == 0) | ||
305 | break; | ||
306 | ds = (struct msdos_dir_slot *) de; | ||
307 | if (ds->attr != ATTR_EXT) | ||
308 | goto parse_record; | ||
309 | if ((ds->id & ~0x40) != slot) | ||
310 | goto parse_long; | ||
311 | if (ds->alias_checksum != alias_checksum) | ||
312 | goto parse_long; | ||
313 | } | ||
314 | if (de->name[0] == DELETED_FLAG) | ||
315 | continue; | ||
316 | if (de->attr == ATTR_EXT) | ||
317 | goto parse_long; | ||
318 | if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME)) | ||
319 | continue; | 341 | continue; |
320 | for (sum = 0, i = 0; i < 11; i++) | 342 | else if (status == PARSE_NOT_LONGNAME) |
321 | sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i]; | 343 | goto parse_record; |
322 | if (sum != alias_checksum) | 344 | else if (status == PARSE_EOF) |
323 | nr_slots = 0; | 345 | goto EODir; |
324 | } | 346 | } |
325 | 347 | ||
326 | memcpy(work, de->name, sizeof(de->name)); | 348 | memcpy(work, de->name, sizeof(de->name)); |
@@ -408,8 +430,8 @@ struct fat_ioctl_filldir_callback { | |||
408 | int short_len; | 430 | int short_len; |
409 | }; | 431 | }; |
410 | 432 | ||
411 | static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent, | 433 | static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, |
412 | filldir_t filldir, int short_only, int both) | 434 | filldir_t filldir, int short_only, int both) |
413 | { | 435 | { |
414 | struct super_block *sb = inode->i_sb; | 436 | struct super_block *sb = inode->i_sb; |
415 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 437 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
@@ -458,9 +480,10 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent, | |||
458 | 480 | ||
459 | bh = NULL; | 481 | bh = NULL; |
460 | GetNew: | 482 | GetNew: |
461 | long_slots = 0; | ||
462 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) | 483 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) |
463 | goto EODir; | 484 | goto EODir; |
485 | parse_record: | ||
486 | long_slots = 0; | ||
464 | /* Check for long filename entry */ | 487 | /* Check for long filename entry */ |
465 | if (isvfat) { | 488 | if (isvfat) { |
466 | if (de->name[0] == DELETED_FLAG) | 489 | if (de->name[0] == DELETED_FLAG) |
@@ -475,69 +498,18 @@ GetNew: | |||
475 | } | 498 | } |
476 | 499 | ||
477 | if (isvfat && de->attr == ATTR_EXT) { | 500 | if (isvfat && de->attr == ATTR_EXT) { |
478 | struct msdos_dir_slot *ds; | 501 | int status = fat_parse_long(inode, &cpos, &bh, &de, |
479 | unsigned char id; | 502 | &unicode, &long_slots); |
480 | unsigned char slot; | 503 | if (status < 0) { |
481 | unsigned char slots; | 504 | filp->f_pos = cpos; |
482 | unsigned char sum; | 505 | ret = status; |
483 | unsigned char alias_checksum; | 506 | goto out; |
484 | 507 | } else if (status == PARSE_INVALID) | |
485 | if (!unicode) { | ||
486 | unicode = (wchar_t *)__get_free_page(GFP_KERNEL); | ||
487 | if (!unicode) { | ||
488 | filp->f_pos = cpos; | ||
489 | brelse(bh); | ||
490 | ret = -ENOMEM; | ||
491 | goto out; | ||
492 | } | ||
493 | } | ||
494 | ParseLong: | ||
495 | slots = 0; | ||
496 | ds = (struct msdos_dir_slot *) de; | ||
497 | id = ds->id; | ||
498 | if (!(id & 0x40)) | ||
499 | goto RecEnd; | ||
500 | slots = id & ~0x40; | ||
501 | if (slots > 20 || !slots) /* ceil(256 * 2 / 26) */ | ||
502 | goto RecEnd; | 508 | goto RecEnd; |
503 | long_slots = slots; | 509 | else if (status == PARSE_NOT_LONGNAME) |
504 | alias_checksum = ds->alias_checksum; | 510 | goto parse_record; |
505 | 511 | else if (status == PARSE_EOF) | |
506 | slot = slots; | 512 | goto EODir; |
507 | while (1) { | ||
508 | int offset; | ||
509 | |||
510 | slot--; | ||
511 | offset = slot * 13; | ||
512 | fat16_towchar(unicode + offset, ds->name0_4, 5); | ||
513 | fat16_towchar(unicode + offset + 5, ds->name5_10, 6); | ||
514 | fat16_towchar(unicode + offset + 11, ds->name11_12, 2); | ||
515 | |||
516 | if (ds->id & 0x40) { | ||
517 | unicode[offset + 13] = 0; | ||
518 | } | ||
519 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) | ||
520 | goto EODir; | ||
521 | if (slot == 0) | ||
522 | break; | ||
523 | ds = (struct msdos_dir_slot *) de; | ||
524 | if (ds->attr != ATTR_EXT) | ||
525 | goto RecEnd; /* XXX */ | ||
526 | if ((ds->id & ~0x40) != slot) | ||
527 | goto ParseLong; | ||
528 | if (ds->alias_checksum != alias_checksum) | ||
529 | goto ParseLong; | ||
530 | } | ||
531 | if (de->name[0] == DELETED_FLAG) | ||
532 | goto RecEnd; | ||
533 | if (de->attr == ATTR_EXT) | ||
534 | goto ParseLong; | ||
535 | if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME)) | ||
536 | goto RecEnd; | ||
537 | for (sum = 0, i = 0; i < 11; i++) | ||
538 | sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i]; | ||
539 | if (sum != alias_checksum) | ||
540 | long_slots = 0; | ||
541 | } | 513 | } |
542 | 514 | ||
543 | if (sbi->options.dotsOK) { | 515 | if (sbi->options.dotsOK) { |
@@ -671,7 +643,7 @@ out: | |||
671 | static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) | 643 | static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) |
672 | { | 644 | { |
673 | struct inode *inode = filp->f_dentry->d_inode; | 645 | struct inode *inode = filp->f_dentry->d_inode; |
674 | return fat_readdirx(inode, filp, dirent, filldir, 0, 0); | 646 | return __fat_readdir(inode, filp, dirent, filldir, 0, 0); |
675 | } | 647 | } |
676 | 648 | ||
677 | static int fat_ioctl_filldir(void *__buf, const char *name, int name_len, | 649 | static int fat_ioctl_filldir(void *__buf, const char *name, int name_len, |
@@ -760,8 +732,8 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp, | |||
760 | down(&inode->i_sem); | 732 | down(&inode->i_sem); |
761 | ret = -ENOENT; | 733 | ret = -ENOENT; |
762 | if (!IS_DEADDIR(inode)) { | 734 | if (!IS_DEADDIR(inode)) { |
763 | ret = fat_readdirx(inode, filp, &buf, fat_ioctl_filldir, | 735 | ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir, |
764 | short_only, both); | 736 | short_only, both); |
765 | } | 737 | } |
766 | up(&inode->i_sem); | 738 | up(&inode->i_sem); |
767 | if (ret >= 0) | 739 | if (ret >= 0) |
diff --git a/fs/file_table.c b/fs/file_table.c index 86ec8ae985b4..4dc205546547 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -56,13 +56,13 @@ void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags) | |||
56 | 56 | ||
57 | static inline void file_free_rcu(struct rcu_head *head) | 57 | static inline void file_free_rcu(struct rcu_head *head) |
58 | { | 58 | { |
59 | struct file *f = container_of(head, struct file, f_rcuhead); | 59 | struct file *f = container_of(head, struct file, f_u.fu_rcuhead); |
60 | kmem_cache_free(filp_cachep, f); | 60 | kmem_cache_free(filp_cachep, f); |
61 | } | 61 | } |
62 | 62 | ||
63 | static inline void file_free(struct file *f) | 63 | static inline void file_free(struct file *f) |
64 | { | 64 | { |
65 | call_rcu(&f->f_rcuhead, file_free_rcu); | 65 | call_rcu(&f->f_u.fu_rcuhead, file_free_rcu); |
66 | } | 66 | } |
67 | 67 | ||
68 | /* Find an unused file structure and return a pointer to it. | 68 | /* Find an unused file structure and return a pointer to it. |
@@ -95,7 +95,7 @@ struct file *get_empty_filp(void) | |||
95 | f->f_gid = current->fsgid; | 95 | f->f_gid = current->fsgid; |
96 | rwlock_init(&f->f_owner.lock); | 96 | rwlock_init(&f->f_owner.lock); |
97 | /* f->f_version: 0 */ | 97 | /* f->f_version: 0 */ |
98 | INIT_LIST_HEAD(&f->f_list); | 98 | INIT_LIST_HEAD(&f->f_u.fu_list); |
99 | return f; | 99 | return f; |
100 | 100 | ||
101 | over: | 101 | over: |
@@ -225,15 +225,15 @@ void file_move(struct file *file, struct list_head *list) | |||
225 | if (!list) | 225 | if (!list) |
226 | return; | 226 | return; |
227 | file_list_lock(); | 227 | file_list_lock(); |
228 | list_move(&file->f_list, list); | 228 | list_move(&file->f_u.fu_list, list); |
229 | file_list_unlock(); | 229 | file_list_unlock(); |
230 | } | 230 | } |
231 | 231 | ||
232 | void file_kill(struct file *file) | 232 | void file_kill(struct file *file) |
233 | { | 233 | { |
234 | if (!list_empty(&file->f_list)) { | 234 | if (!list_empty(&file->f_u.fu_list)) { |
235 | file_list_lock(); | 235 | file_list_lock(); |
236 | list_del_init(&file->f_list); | 236 | list_del_init(&file->f_u.fu_list); |
237 | file_list_unlock(); | 237 | file_list_unlock(); |
238 | } | 238 | } |
239 | } | 239 | } |
@@ -245,7 +245,7 @@ int fs_may_remount_ro(struct super_block *sb) | |||
245 | /* Check that no files are currently opened for writing. */ | 245 | /* Check that no files are currently opened for writing. */ |
246 | file_list_lock(); | 246 | file_list_lock(); |
247 | list_for_each(p, &sb->s_files) { | 247 | list_for_each(p, &sb->s_files) { |
248 | struct file *file = list_entry(p, struct file, f_list); | 248 | struct file *file = list_entry(p, struct file, f_u.fu_list); |
249 | struct inode *inode = file->f_dentry->d_inode; | 249 | struct inode *inode = file->f_dentry->d_inode; |
250 | 250 | ||
251 | /* File with pending delete? */ | 251 | /* File with pending delete? */ |
diff --git a/fs/filesystems.c b/fs/filesystems.c index 44082bfdfec9..9f1072836c8e 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/kmod.h> | 12 | #include <linux/kmod.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/sched.h> /* for 'current' */ | ||
15 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
16 | 17 | ||
17 | /* | 18 | /* |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index e94ab398b717..ffab4783ac64 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -230,7 +230,6 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
230 | * The inode is clean, unused | 230 | * The inode is clean, unused |
231 | */ | 231 | */ |
232 | list_move(&inode->i_list, &inode_unused); | 232 | list_move(&inode->i_list, &inode_unused); |
233 | inodes_stat.nr_unused++; | ||
234 | } | 233 | } |
235 | } | 234 | } |
236 | wake_up_inode(inode); | 235 | wake_up_inode(inode); |
@@ -238,14 +237,20 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
238 | } | 237 | } |
239 | 238 | ||
240 | /* | 239 | /* |
241 | * Write out an inode's dirty pages. Called under inode_lock. | 240 | * Write out an inode's dirty pages. Called under inode_lock. Either the |
241 | * caller has ref on the inode (either via __iget or via syscall against an fd) | ||
242 | * or the inode has I_WILL_FREE set (via generic_forget_inode) | ||
242 | */ | 243 | */ |
243 | static int | 244 | static int |
244 | __writeback_single_inode(struct inode *inode, | 245 | __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) |
245 | struct writeback_control *wbc) | ||
246 | { | 246 | { |
247 | wait_queue_head_t *wqh; | 247 | wait_queue_head_t *wqh; |
248 | 248 | ||
249 | if (!atomic_read(&inode->i_count)) | ||
250 | WARN_ON(!(inode->i_state & I_WILL_FREE)); | ||
251 | else | ||
252 | WARN_ON(inode->i_state & I_WILL_FREE); | ||
253 | |||
249 | if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) { | 254 | if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) { |
250 | list_move(&inode->i_list, &inode->i_sb->s_dirty); | 255 | list_move(&inode->i_list, &inode->i_sb->s_dirty); |
251 | return 0; | 256 | return 0; |
@@ -259,11 +264,9 @@ __writeback_single_inode(struct inode *inode, | |||
259 | 264 | ||
260 | wqh = bit_waitqueue(&inode->i_state, __I_LOCK); | 265 | wqh = bit_waitqueue(&inode->i_state, __I_LOCK); |
261 | do { | 266 | do { |
262 | __iget(inode); | ||
263 | spin_unlock(&inode_lock); | 267 | spin_unlock(&inode_lock); |
264 | __wait_on_bit(wqh, &wq, inode_wait, | 268 | __wait_on_bit(wqh, &wq, inode_wait, |
265 | TASK_UNINTERRUPTIBLE); | 269 | TASK_UNINTERRUPTIBLE); |
266 | iput(inode); | ||
267 | spin_lock(&inode_lock); | 270 | spin_lock(&inode_lock); |
268 | } while (inode->i_state & I_LOCK); | 271 | } while (inode->i_state & I_LOCK); |
269 | } | 272 | } |
@@ -541,14 +544,15 @@ void sync_inodes(int wait) | |||
541 | } | 544 | } |
542 | 545 | ||
543 | /** | 546 | /** |
544 | * write_inode_now - write an inode to disk | 547 | * write_inode_now - write an inode to disk |
545 | * @inode: inode to write to disk | 548 | * @inode: inode to write to disk |
546 | * @sync: whether the write should be synchronous or not | 549 | * @sync: whether the write should be synchronous or not |
550 | * | ||
551 | * This function commits an inode to disk immediately if it is dirty. This is | ||
552 | * primarily needed by knfsd. | ||
547 | * | 553 | * |
548 | * This function commits an inode to disk immediately if it is | 554 | * The caller must either have a ref on the inode or must have set I_WILL_FREE. |
549 | * dirty. This is primarily needed by knfsd. | ||
550 | */ | 555 | */ |
551 | |||
552 | int write_inode_now(struct inode *inode, int sync) | 556 | int write_inode_now(struct inode *inode, int sync) |
553 | { | 557 | { |
554 | int ret; | 558 | int ret; |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index d4c869c6d01b..a6f90a6c754a 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -151,9 +151,9 @@ void fuse_release_background(struct fuse_req *req) | |||
151 | /* | 151 | /* |
152 | * This function is called when a request is finished. Either a reply | 152 | * This function is called when a request is finished. Either a reply |
153 | * has arrived or it was interrupted (and not yet sent) or some error | 153 | * has arrived or it was interrupted (and not yet sent) or some error |
154 | * occured during communication with userspace, or the device file was | 154 | * occurred during communication with userspace, or the device file was |
155 | * closed. It decreases the referece count for the request. In case | 155 | * closed. It decreases the reference count for the request. In case |
156 | * of a background request the referece to the stored objects are | 156 | * of a background request the reference to the stored objects are |
157 | * released. The requester thread is woken up (if still waiting), and | 157 | * released. The requester thread is woken up (if still waiting), and |
158 | * finally the request is either freed or put on the unused_list | 158 | * finally the request is either freed or put on the unused_list |
159 | * | 159 | * |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 29f1e9f6e85c..70dba721acab 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -741,13 +741,14 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
741 | if (inode && S_ISDIR(inode->i_mode)) { | 741 | if (inode && S_ISDIR(inode->i_mode)) { |
742 | /* Don't allow creating an alias to a directory */ | 742 | /* Don't allow creating an alias to a directory */ |
743 | struct dentry *alias = d_find_alias(inode); | 743 | struct dentry *alias = d_find_alias(inode); |
744 | if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) { | 744 | if (alias) { |
745 | dput(alias); | 745 | dput(alias); |
746 | iput(inode); | 746 | iput(inode); |
747 | return ERR_PTR(-EIO); | 747 | return ERR_PTR(-EIO); |
748 | } | 748 | } |
749 | } | 749 | } |
750 | return d_splice_alias(inode, entry); | 750 | d_add(entry, inode); |
751 | return NULL; | ||
751 | } | 752 | } |
752 | 753 | ||
753 | static int fuse_setxattr(struct dentry *entry, const char *name, | 754 | static int fuse_setxattr(struct dentry *entry, const char *name, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 24d761518d86..5cb456f572c1 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -349,22 +349,22 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync, | |||
349 | int isdir); | 349 | int isdir); |
350 | 350 | ||
351 | /** | 351 | /** |
352 | * Initialise file operations on a regular file | 352 | * Initialize file operations on a regular file |
353 | */ | 353 | */ |
354 | void fuse_init_file_inode(struct inode *inode); | 354 | void fuse_init_file_inode(struct inode *inode); |
355 | 355 | ||
356 | /** | 356 | /** |
357 | * Initialise inode operations on regular files and special files | 357 | * Initialize inode operations on regular files and special files |
358 | */ | 358 | */ |
359 | void fuse_init_common(struct inode *inode); | 359 | void fuse_init_common(struct inode *inode); |
360 | 360 | ||
361 | /** | 361 | /** |
362 | * Initialise inode and file operations on a directory | 362 | * Initialize inode and file operations on a directory |
363 | */ | 363 | */ |
364 | void fuse_init_dir(struct inode *inode); | 364 | void fuse_init_dir(struct inode *inode); |
365 | 365 | ||
366 | /** | 366 | /** |
367 | * Initialise inode operations on a symlink | 367 | * Initialize inode operations on a symlink |
368 | */ | 368 | */ |
369 | void fuse_init_symlink(struct inode *inode); | 369 | void fuse_init_symlink(struct inode *inode); |
370 | 370 | ||
@@ -411,7 +411,7 @@ struct fuse_req *fuse_get_request(struct fuse_conn *fc); | |||
411 | 411 | ||
412 | /** | 412 | /** |
413 | * Decrement reference count of a request. If count goes to zero put | 413 | * Decrement reference count of a request. If count goes to zero put |
414 | * on unused list (preallocated) or free reqest (not preallocated). | 414 | * on unused list (preallocated) or free request (not preallocated). |
415 | */ | 415 | */ |
416 | void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); | 416 | void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); |
417 | 417 | ||
@@ -431,7 +431,7 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req); | |||
431 | void request_send_background(struct fuse_conn *fc, struct fuse_req *req); | 431 | void request_send_background(struct fuse_conn *fc, struct fuse_req *req); |
432 | 432 | ||
433 | /** | 433 | /** |
434 | * Release inodes and file assiciated with background request | 434 | * Release inodes and file associated with background request |
435 | */ | 435 | */ |
436 | void fuse_release_background(struct fuse_req *req); | 436 | void fuse_release_background(struct fuse_req *req); |
437 | 437 | ||
diff --git a/fs/inode.c b/fs/inode.c index 7d3316527767..d8d04bd72b59 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1088,6 +1088,7 @@ static void generic_forget_inode(struct inode *inode) | |||
1088 | if (inode->i_data.nrpages) | 1088 | if (inode->i_data.nrpages) |
1089 | truncate_inode_pages(&inode->i_data, 0); | 1089 | truncate_inode_pages(&inode->i_data, 0); |
1090 | clear_inode(inode); | 1090 | clear_inode(inode); |
1091 | wake_up_inode(inode); | ||
1091 | destroy_inode(inode); | 1092 | destroy_inode(inode); |
1092 | } | 1093 | } |
1093 | 1094 | ||
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 0f224384f176..8210ac16a368 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/jffs2.h> | 15 | #include <linux/jffs2.h> |
16 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
17 | #include <linux/completion.h> | 17 | #include <linux/completion.h> |
18 | #include <linux/sched.h> | ||
18 | #include "nodelist.h" | 19 | #include "nodelist.h" |
19 | 20 | ||
20 | 21 | ||
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 996d922e503e..316133c626b7 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/mtd/mtd.h> | 18 | #include <linux/mtd/mtd.h> |
19 | #include <linux/crc32.h> | 19 | #include <linux/crc32.h> |
20 | #include <linux/mtd/nand.h> | 20 | #include <linux/mtd/nand.h> |
21 | #include <linux/jiffies.h> | ||
22 | |||
21 | #include "nodelist.h" | 23 | #include "nodelist.h" |
22 | 24 | ||
23 | /* For testing write failures */ | 25 | /* For testing write failures */ |
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 154f511c7245..626a367bcd81 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c | |||
@@ -454,10 +454,10 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, | |||
454 | { | 454 | { |
455 | struct buffer_head *dotdot_bh; | 455 | struct buffer_head *dotdot_bh; |
456 | struct msdos_dir_entry *dotdot_de; | 456 | struct msdos_dir_entry *dotdot_de; |
457 | loff_t dotdot_i_pos; | ||
458 | struct inode *old_inode, *new_inode; | 457 | struct inode *old_inode, *new_inode; |
459 | struct fat_slot_info old_sinfo, sinfo; | 458 | struct fat_slot_info old_sinfo, sinfo; |
460 | struct timespec ts; | 459 | struct timespec ts; |
460 | loff_t dotdot_i_pos, new_i_pos; | ||
461 | int err, old_attrs, is_dir, update_dotdot, corrupt = 0; | 461 | int err, old_attrs, is_dir, update_dotdot, corrupt = 0; |
462 | 462 | ||
463 | old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; | 463 | old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; |
@@ -516,28 +516,24 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, | |||
516 | if (new_inode) { | 516 | if (new_inode) { |
517 | if (err) | 517 | if (err) |
518 | goto out; | 518 | goto out; |
519 | if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) { | ||
520 | /* WTF??? Cry and fail. */ | ||
521 | printk(KERN_WARNING "msdos_rename: fs corrupted\n"); | ||
522 | goto out; | ||
523 | } | ||
524 | |||
525 | if (is_dir) { | 519 | if (is_dir) { |
526 | err = fat_dir_empty(new_inode); | 520 | err = fat_dir_empty(new_inode); |
527 | if (err) | 521 | if (err) |
528 | goto out; | 522 | goto out; |
529 | } | 523 | } |
524 | new_i_pos = MSDOS_I(new_inode)->i_pos; | ||
530 | fat_detach(new_inode); | 525 | fat_detach(new_inode); |
531 | } else { | 526 | } else { |
532 | err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0, | 527 | err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0, |
533 | &ts, &sinfo); | 528 | &ts, &sinfo); |
534 | if (err) | 529 | if (err) |
535 | goto out; | 530 | goto out; |
531 | new_i_pos = sinfo.i_pos; | ||
536 | } | 532 | } |
537 | new_dir->i_version++; | 533 | new_dir->i_version++; |
538 | 534 | ||
539 | fat_detach(old_inode); | 535 | fat_detach(old_inode); |
540 | fat_attach(old_inode, sinfo.i_pos); | 536 | fat_attach(old_inode, new_i_pos); |
541 | if (is_hid) | 537 | if (is_hid) |
542 | MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; | 538 | MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; |
543 | else | 539 | else |
@@ -604,7 +600,7 @@ error_inode: | |||
604 | fat_attach(old_inode, old_sinfo.i_pos); | 600 | fat_attach(old_inode, old_sinfo.i_pos); |
605 | MSDOS_I(old_inode)->i_attrs = old_attrs; | 601 | MSDOS_I(old_inode)->i_attrs = old_attrs; |
606 | if (new_inode) { | 602 | if (new_inode) { |
607 | fat_attach(new_inode, sinfo.i_pos); | 603 | fat_attach(new_inode, new_i_pos); |
608 | if (corrupt) | 604 | if (corrupt) |
609 | corrupt |= fat_sync_inode(new_inode); | 605 | corrupt |= fat_sync_inode(new_inode); |
610 | } else { | 606 | } else { |
diff --git a/fs/namei.c b/fs/namei.c index aaaa81036234..c5769c4fcab1 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1311,9 +1311,6 @@ static inline int may_create(struct inode *dir, struct dentry *child, | |||
1311 | } | 1311 | } |
1312 | 1312 | ||
1313 | /* | 1313 | /* |
1314 | * Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security | ||
1315 | * reasons. | ||
1316 | * | ||
1317 | * O_DIRECTORY translates into forcing a directory lookup. | 1314 | * O_DIRECTORY translates into forcing a directory lookup. |
1318 | */ | 1315 | */ |
1319 | static inline int lookup_flags(unsigned int f) | 1316 | static inline int lookup_flags(unsigned int f) |
@@ -1323,9 +1320,6 @@ static inline int lookup_flags(unsigned int f) | |||
1323 | if (f & O_NOFOLLOW) | 1320 | if (f & O_NOFOLLOW) |
1324 | retval &= ~LOOKUP_FOLLOW; | 1321 | retval &= ~LOOKUP_FOLLOW; |
1325 | 1322 | ||
1326 | if ((f & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) | ||
1327 | retval &= ~LOOKUP_FOLLOW; | ||
1328 | |||
1329 | if (f & O_DIRECTORY) | 1323 | if (f & O_DIRECTORY) |
1330 | retval |= LOOKUP_DIRECTORY; | 1324 | retval |= LOOKUP_DIRECTORY; |
1331 | 1325 | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index f2781ca42761..fc0f12ba89cc 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -1274,14 +1274,12 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
1274 | } | 1274 | } |
1275 | 1275 | ||
1276 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) { | 1276 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) { |
1277 | spin_unlock(&inode->i_lock); | ||
1278 | return 0; | 1277 | return 0; |
1279 | } | 1278 | } |
1280 | 1279 | ||
1281 | /* Has the inode gone and changed behind our back? */ | 1280 | /* Has the inode gone and changed behind our back? */ |
1282 | if (nfsi->fileid != fattr->fileid | 1281 | if (nfsi->fileid != fattr->fileid |
1283 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { | 1282 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { |
1284 | spin_unlock(&inode->i_lock); | ||
1285 | return -EIO; | 1283 | return -EIO; |
1286 | } | 1284 | } |
1287 | 1285 | ||
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 8a8c34461d48..b638fb500743 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -533,7 +533,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de) | |||
533 | */ | 533 | */ |
534 | file_list_lock(); | 534 | file_list_lock(); |
535 | list_for_each(p, &sb->s_files) { | 535 | list_for_each(p, &sb->s_files) { |
536 | struct file * filp = list_entry(p, struct file, f_list); | 536 | struct file * filp = list_entry(p, struct file, f_u.fu_list); |
537 | struct dentry * dentry = filp->f_dentry; | 537 | struct dentry * dentry = filp->f_dentry; |
538 | struct inode * inode; | 538 | struct inode * inode; |
539 | struct file_operations *fops; | 539 | struct file_operations *fops; |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index effa6c0c467a..e6a818a93f3d 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -156,10 +156,13 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, | |||
156 | 156 | ||
157 | WARN_ON(de && de->deleted); | 157 | WARN_ON(de && de->deleted); |
158 | 158 | ||
159 | if (de != NULL && !try_module_get(de->owner)) | ||
160 | goto out_mod; | ||
161 | |||
159 | inode = iget(sb, ino); | 162 | inode = iget(sb, ino); |
160 | if (!inode) | 163 | if (!inode) |
161 | goto out_fail; | 164 | goto out_ino; |
162 | 165 | ||
163 | PROC_I(inode)->pde = de; | 166 | PROC_I(inode)->pde = de; |
164 | if (de) { | 167 | if (de) { |
165 | if (de->mode) { | 168 | if (de->mode) { |
@@ -171,20 +174,20 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, | |||
171 | inode->i_size = de->size; | 174 | inode->i_size = de->size; |
172 | if (de->nlink) | 175 | if (de->nlink) |
173 | inode->i_nlink = de->nlink; | 176 | inode->i_nlink = de->nlink; |
174 | if (!try_module_get(de->owner)) | ||
175 | goto out_fail; | ||
176 | if (de->proc_iops) | 177 | if (de->proc_iops) |
177 | inode->i_op = de->proc_iops; | 178 | inode->i_op = de->proc_iops; |
178 | if (de->proc_fops) | 179 | if (de->proc_fops) |
179 | inode->i_fop = de->proc_fops; | 180 | inode->i_fop = de->proc_fops; |
180 | } | 181 | } |
181 | 182 | ||
182 | out: | ||
183 | return inode; | 183 | return inode; |
184 | 184 | ||
185 | out_fail: | 185 | out_ino: |
186 | if (de != NULL) | ||
187 | module_put(de->owner); | ||
188 | out_mod: | ||
186 | de_put(de); | 189 | de_put(de); |
187 | goto out; | 190 | return NULL; |
188 | } | 191 | } |
189 | 192 | ||
190 | int proc_fill_super(struct super_block *s, void *data, int silent) | 193 | int proc_fill_super(struct super_block *s, void *data, int silent) |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index a3453555a94e..5b6b0b6038a7 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -629,12 +629,4 @@ void __init proc_misc_init(void) | |||
629 | if (entry) | 629 | if (entry) |
630 | entry->proc_fops = &proc_sysrq_trigger_operations; | 630 | entry->proc_fops = &proc_sysrq_trigger_operations; |
631 | #endif | 631 | #endif |
632 | #ifdef CONFIG_PPC32 | ||
633 | { | ||
634 | extern struct file_operations ppc_htab_operations; | ||
635 | entry = create_proc_entry("ppc_htab", S_IRUGO|S_IWUSR, NULL); | ||
636 | if (entry) | ||
637 | entry->proc_fops = &ppc_htab_operations; | ||
638 | } | ||
639 | #endif | ||
640 | } | 632 | } |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 44b02fc02ebe..42afb5bef111 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -1024,12 +1024,8 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin | |||
1024 | strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg); | 1024 | strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg); |
1025 | *mount_options |= 1 << REISERFS_QUOTA; | 1025 | *mount_options |= 1 << REISERFS_QUOTA; |
1026 | } else { | 1026 | } else { |
1027 | if (REISERFS_SB(s)->s_qf_names[qtype]) { | 1027 | kfree(REISERFS_SB(s)->s_qf_names[qtype]); |
1028 | kfree(REISERFS_SB(s)-> | 1028 | REISERFS_SB(s)->s_qf_names[qtype] = NULL; |
1029 | s_qf_names[qtype]); | ||
1030 | REISERFS_SB(s)->s_qf_names[qtype] = | ||
1031 | NULL; | ||
1032 | } | ||
1033 | } | 1029 | } |
1034 | } | 1030 | } |
1035 | if (c == 'f') { | 1031 | if (c == 'f') { |
@@ -1158,11 +1154,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
1158 | if (!reiserfs_parse_options | 1154 | if (!reiserfs_parse_options |
1159 | (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) { | 1155 | (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) { |
1160 | #ifdef CONFIG_QUOTA | 1156 | #ifdef CONFIG_QUOTA |
1161 | for (i = 0; i < MAXQUOTAS; i++) | 1157 | for (i = 0; i < MAXQUOTAS; i++) { |
1162 | if (REISERFS_SB(s)->s_qf_names[i]) { | 1158 | kfree(REISERFS_SB(s)->s_qf_names[i]); |
1163 | kfree(REISERFS_SB(s)->s_qf_names[i]); | 1159 | REISERFS_SB(s)->s_qf_names[i] = NULL; |
1164 | REISERFS_SB(s)->s_qf_names[i] = NULL; | 1160 | } |
1165 | } | ||
1166 | #endif | 1161 | #endif |
1167 | return -EINVAL; | 1162 | return -EINVAL; |
1168 | } | 1163 | } |
@@ -1940,13 +1935,11 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1940 | brelse(SB_BUFFER_WITH_SB(s)); | 1935 | brelse(SB_BUFFER_WITH_SB(s)); |
1941 | #ifdef CONFIG_QUOTA | 1936 | #ifdef CONFIG_QUOTA |
1942 | for (j = 0; j < MAXQUOTAS; j++) { | 1937 | for (j = 0; j < MAXQUOTAS; j++) { |
1943 | if (sbi->s_qf_names[j]) | 1938 | kfree(sbi->s_qf_names[j]); |
1944 | kfree(sbi->s_qf_names[j]); | 1939 | sbi->s_qf_names[j] = NULL; |
1945 | } | 1940 | } |
1946 | #endif | 1941 | #endif |
1947 | if (sbi != NULL) { | 1942 | kfree(sbi); |
1948 | kfree(sbi); | ||
1949 | } | ||
1950 | 1943 | ||
1951 | s->s_fs_info = NULL; | 1944 | s->s_fs_info = NULL; |
1952 | return errval; | 1945 | return errval; |
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 6703efa3c430..a47ac9aac8b2 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c | |||
@@ -296,8 +296,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
296 | } | 296 | } |
297 | } | 297 | } |
298 | 298 | ||
299 | if (value) | 299 | kfree(value); |
300 | kfree(value); | ||
301 | 300 | ||
302 | if (!error) { | 301 | if (!error) { |
303 | /* Release the old one */ | 302 | /* Release the old one */ |
diff --git a/fs/super.c b/fs/super.c index 6e57ee252e14..f60155ec7780 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -513,7 +513,7 @@ static void mark_files_ro(struct super_block *sb) | |||
513 | struct file *f; | 513 | struct file *f; |
514 | 514 | ||
515 | file_list_lock(); | 515 | file_list_lock(); |
516 | list_for_each_entry(f, &sb->s_files, f_list) { | 516 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { |
517 | if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f)) | 517 | if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f)) |
518 | f->f_mode &= ~FMODE_WRITE; | 518 | f->f_mode &= ~FMODE_WRITE; |
519 | } | 519 | } |
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 1c6f6b57ef1c..ef46939c0c1a 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c | |||
@@ -621,8 +621,7 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name, | |||
621 | } | 621 | } |
622 | 622 | ||
623 | /* build the entry of long file name */ | 623 | /* build the entry of long file name */ |
624 | for (cksum = i = 0; i < 11; i++) | 624 | cksum = fat_checksum(msdos_name); |
625 | cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i]; | ||
626 | 625 | ||
627 | *nr_slots = usize / 13; | 626 | *nr_slots = usize / 13; |
628 | for (ps = slots, i = *nr_slots; i > 0; i--, ps++) { | 627 | for (ps = slots, i = *nr_slots; i > 0; i--, ps++) { |
@@ -888,10 +887,10 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
888 | { | 887 | { |
889 | struct buffer_head *dotdot_bh; | 888 | struct buffer_head *dotdot_bh; |
890 | struct msdos_dir_entry *dotdot_de; | 889 | struct msdos_dir_entry *dotdot_de; |
891 | loff_t dotdot_i_pos; | ||
892 | struct inode *old_inode, *new_inode; | 890 | struct inode *old_inode, *new_inode; |
893 | struct fat_slot_info old_sinfo, sinfo; | 891 | struct fat_slot_info old_sinfo, sinfo; |
894 | struct timespec ts; | 892 | struct timespec ts; |
893 | loff_t dotdot_i_pos, new_i_pos; | ||
895 | int err, is_dir, update_dotdot, corrupt = 0; | 894 | int err, is_dir, update_dotdot, corrupt = 0; |
896 | 895 | ||
897 | old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; | 896 | old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; |
@@ -914,31 +913,24 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
914 | 913 | ||
915 | ts = CURRENT_TIME_SEC; | 914 | ts = CURRENT_TIME_SEC; |
916 | if (new_inode) { | 915 | if (new_inode) { |
917 | err = vfat_find(new_dir, &new_dentry->d_name, &sinfo); | ||
918 | if (err) | ||
919 | goto out; | ||
920 | if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) { | ||
921 | /* WTF??? Cry and fail. */ | ||
922 | printk(KERN_WARNING "vfat_rename: fs corrupted\n"); | ||
923 | goto out; | ||
924 | } | ||
925 | |||
926 | if (is_dir) { | 916 | if (is_dir) { |
927 | err = fat_dir_empty(new_inode); | 917 | err = fat_dir_empty(new_inode); |
928 | if (err) | 918 | if (err) |
929 | goto out; | 919 | goto out; |
930 | } | 920 | } |
921 | new_i_pos = MSDOS_I(new_inode)->i_pos; | ||
931 | fat_detach(new_inode); | 922 | fat_detach(new_inode); |
932 | } else { | 923 | } else { |
933 | err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0, | 924 | err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0, |
934 | &ts, &sinfo); | 925 | &ts, &sinfo); |
935 | if (err) | 926 | if (err) |
936 | goto out; | 927 | goto out; |
928 | new_i_pos = sinfo.i_pos; | ||
937 | } | 929 | } |
938 | new_dir->i_version++; | 930 | new_dir->i_version++; |
939 | 931 | ||
940 | fat_detach(old_inode); | 932 | fat_detach(old_inode); |
941 | fat_attach(old_inode, sinfo.i_pos); | 933 | fat_attach(old_inode, new_i_pos); |
942 | if (IS_DIRSYNC(new_dir)) { | 934 | if (IS_DIRSYNC(new_dir)) { |
943 | err = fat_sync_inode(old_inode); | 935 | err = fat_sync_inode(old_inode); |
944 | if (err) | 936 | if (err) |
@@ -1002,7 +994,7 @@ error_inode: | |||
1002 | fat_detach(old_inode); | 994 | fat_detach(old_inode); |
1003 | fat_attach(old_inode, old_sinfo.i_pos); | 995 | fat_attach(old_inode, old_sinfo.i_pos); |
1004 | if (new_inode) { | 996 | if (new_inode) { |
1005 | fat_attach(new_inode, sinfo.i_pos); | 997 | fat_attach(new_inode, new_i_pos); |
1006 | if (corrupt) | 998 | if (corrupt) |
1007 | corrupt |= fat_sync_inode(new_inode); | 999 | corrupt |= fat_sync_inode(new_inode); |
1008 | } else { | 1000 | } else { |
diff --git a/fs/xattr.c b/fs/xattr.c index 3f9c64bea151..f6e00c0e114f 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -143,7 +143,7 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) | |||
143 | if (size) { | 143 | if (size) { |
144 | if (size > XATTR_SIZE_MAX) | 144 | if (size > XATTR_SIZE_MAX) |
145 | size = XATTR_SIZE_MAX; | 145 | size = XATTR_SIZE_MAX; |
146 | kvalue = kmalloc(size, GFP_KERNEL); | 146 | kvalue = kzalloc(size, GFP_KERNEL); |
147 | if (!kvalue) | 147 | if (!kvalue) |
148 | return -ENOMEM; | 148 | return -ENOMEM; |
149 | } | 149 | } |
@@ -154,11 +154,15 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) | |||
154 | error = -EOPNOTSUPP; | 154 | error = -EOPNOTSUPP; |
155 | if (d->d_inode->i_op && d->d_inode->i_op->getxattr) | 155 | if (d->d_inode->i_op && d->d_inode->i_op->getxattr) |
156 | error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); | 156 | error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); |
157 | else if (!strncmp(kname, XATTR_SECURITY_PREFIX, | 157 | |
158 | sizeof XATTR_SECURITY_PREFIX - 1)) { | 158 | if (!strncmp(kname, XATTR_SECURITY_PREFIX, |
159 | sizeof XATTR_SECURITY_PREFIX - 1)) { | ||
159 | const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1; | 160 | const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1; |
160 | error = security_inode_getsecurity(d->d_inode, suffix, kvalue, | 161 | int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue, |
161 | size); | 162 | size, error); |
163 | /* Security module active: overwrite error value */ | ||
164 | if (rv != -EOPNOTSUPP) | ||
165 | error = rv; | ||
162 | } | 166 | } |
163 | if (error > 0) { | 167 | if (error > 0) { |
164 | if (size && copy_to_user(value, kvalue, error)) | 168 | if (size && copy_to_user(value, kvalue, error)) |