diff options
Diffstat (limited to 'fs')
42 files changed, 547 insertions, 259 deletions
diff --git a/fs/Makefile b/fs/Makefile index 9d53192236fc..3b2c76759ec9 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -10,7 +10,7 @@ obj-y := open.o read_write.o file_table.o super.o \ | |||
10 | ioctl.o readdir.o select.o fifo.o dcache.o inode.o \ | 10 | ioctl.o readdir.o select.o fifo.o dcache.o inode.o \ |
11 | attr.o bad_inode.o file.o filesystems.o namespace.o \ | 11 | attr.o bad_inode.o file.o filesystems.o namespace.o \ |
12 | seq_file.o xattr.o libfs.o fs-writeback.o \ | 12 | seq_file.o xattr.o libfs.o fs-writeback.o \ |
13 | pnode.o drop_caches.o splice.o sync.o utimes.o \ | 13 | pnode.o splice.o sync.o utimes.o \ |
14 | stack.o fs_struct.o statfs.o | 14 | stack.o fs_struct.o statfs.o |
15 | 15 | ||
16 | ifeq ($(CONFIG_BLOCK),y) | 16 | ifeq ($(CONFIG_BLOCK),y) |
@@ -49,6 +49,7 @@ obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o | |||
49 | obj-$(CONFIG_NFS_COMMON) += nfs_common/ | 49 | obj-$(CONFIG_NFS_COMMON) += nfs_common/ |
50 | obj-$(CONFIG_GENERIC_ACL) += generic_acl.o | 50 | obj-$(CONFIG_GENERIC_ACL) += generic_acl.o |
51 | obj-$(CONFIG_COREDUMP) += coredump.o | 51 | obj-$(CONFIG_COREDUMP) += coredump.o |
52 | obj-$(CONFIG_SYSCTL) += drop_caches.o | ||
52 | 53 | ||
53 | obj-$(CONFIG_FHANDLE) += fhandle.o | 54 | obj-$(CONFIG_FHANDLE) += fhandle.o |
54 | 55 | ||
@@ -1029,9 +1029,9 @@ static int aio_read_evt(struct kioctx *ioctx, struct io_event *ent) | |||
1029 | spin_unlock(&info->ring_lock); | 1029 | spin_unlock(&info->ring_lock); |
1030 | 1030 | ||
1031 | out: | 1031 | out: |
1032 | kunmap_atomic(ring); | ||
1033 | dprintk("leaving aio_read_evt: %d h%lu t%lu\n", ret, | 1032 | dprintk("leaving aio_read_evt: %d h%lu t%lu\n", ret, |
1034 | (unsigned long)ring->head, (unsigned long)ring->tail); | 1033 | (unsigned long)ring->head, (unsigned long)ring->tail); |
1034 | kunmap_atomic(ring); | ||
1035 | return ret; | 1035 | return ret; |
1036 | } | 1036 | } |
1037 | 1037 | ||
diff --git a/fs/befs/btree.c b/fs/befs/btree.c index a66c9b1136e0..74e397db0b8b 100644 --- a/fs/befs/btree.c +++ b/fs/befs/btree.c | |||
@@ -436,8 +436,7 @@ befs_btree_read(struct super_block *sb, befs_data_stream * ds, | |||
436 | goto error; | 436 | goto error; |
437 | } | 437 | } |
438 | 438 | ||
439 | if ((this_node = (befs_btree_node *) | 439 | if ((this_node = kmalloc(sizeof (befs_btree_node), GFP_NOFS)) == NULL) { |
440 | kmalloc(sizeof (befs_btree_node), GFP_NOFS)) == NULL) { | ||
441 | befs_error(sb, "befs_btree_read() failed to allocate %u " | 440 | befs_error(sb, "befs_btree_read() failed to allocate %u " |
442 | "bytes of memory", sizeof (befs_btree_node)); | 441 | "bytes of memory", sizeof (befs_btree_node)); |
443 | goto error; | 442 | goto error; |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 3939829f6c5c..86af964c2425 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1137,6 +1137,7 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, | |||
1137 | goto whole; | 1137 | goto whole; |
1138 | if (!(vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_PRIVATE)) | 1138 | if (!(vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_PRIVATE)) |
1139 | goto whole; | 1139 | goto whole; |
1140 | return 0; | ||
1140 | } | 1141 | } |
1141 | 1142 | ||
1142 | /* Do not dump I/O mapped devices or special mappings */ | 1143 | /* Do not dump I/O mapped devices or special mappings */ |
@@ -1428,8 +1428,6 @@ void bio_endio(struct bio *bio, int error) | |||
1428 | else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) | 1428 | else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) |
1429 | error = -EIO; | 1429 | error = -EIO; |
1430 | 1430 | ||
1431 | trace_block_bio_complete(bio, error); | ||
1432 | |||
1433 | if (bio->bi_end_io) | 1431 | if (bio->bi_end_io) |
1434 | bio->bi_end_io(bio, error); | 1432 | bio->bi_end_io(bio, error); |
1435 | } | 1433 | } |
diff --git a/fs/buffer.c b/fs/buffer.c index b4dcb34c9635..10ef81e10b20 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -865,8 +865,6 @@ try_again: | |||
865 | 865 | ||
866 | /* Link the buffer to its page */ | 866 | /* Link the buffer to its page */ |
867 | set_bh_page(bh, page, offset); | 867 | set_bh_page(bh, page, offset); |
868 | |||
869 | init_buffer(bh, NULL, NULL); | ||
870 | } | 868 | } |
871 | return head; | 869 | return head; |
872 | /* | 870 | /* |
@@ -2949,7 +2947,7 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh) | |||
2949 | } | 2947 | } |
2950 | } | 2948 | } |
2951 | 2949 | ||
2952 | int submit_bh(int rw, struct buffer_head * bh) | 2950 | int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags) |
2953 | { | 2951 | { |
2954 | struct bio *bio; | 2952 | struct bio *bio; |
2955 | int ret = 0; | 2953 | int ret = 0; |
@@ -2984,6 +2982,7 @@ int submit_bh(int rw, struct buffer_head * bh) | |||
2984 | 2982 | ||
2985 | bio->bi_end_io = end_bio_bh_io_sync; | 2983 | bio->bi_end_io = end_bio_bh_io_sync; |
2986 | bio->bi_private = bh; | 2984 | bio->bi_private = bh; |
2985 | bio->bi_flags |= bio_flags; | ||
2987 | 2986 | ||
2988 | /* Take care of bh's that straddle the end of the device */ | 2987 | /* Take care of bh's that straddle the end of the device */ |
2989 | guard_bh_eod(rw, bio, bh); | 2988 | guard_bh_eod(rw, bio, bh); |
@@ -2997,6 +2996,12 @@ int submit_bh(int rw, struct buffer_head * bh) | |||
2997 | bio_put(bio); | 2996 | bio_put(bio); |
2998 | return ret; | 2997 | return ret; |
2999 | } | 2998 | } |
2999 | EXPORT_SYMBOL_GPL(_submit_bh); | ||
3000 | |||
3001 | int submit_bh(int rw, struct buffer_head *bh) | ||
3002 | { | ||
3003 | return _submit_bh(rw, bh, 0); | ||
3004 | } | ||
3000 | EXPORT_SYMBOL(submit_bh); | 3005 | EXPORT_SYMBOL(submit_bh); |
3001 | 3006 | ||
3002 | /** | 3007 | /** |
diff --git a/fs/direct-io.c b/fs/direct-io.c index f853263cf74f..cfb816dc6d9f 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -672,12 +672,6 @@ static inline int dio_send_cur_page(struct dio *dio, struct dio_submit *sdio, | |||
672 | if (sdio->final_block_in_bio != sdio->cur_page_block || | 672 | if (sdio->final_block_in_bio != sdio->cur_page_block || |
673 | cur_offset != bio_next_offset) | 673 | cur_offset != bio_next_offset) |
674 | dio_bio_submit(dio, sdio); | 674 | dio_bio_submit(dio, sdio); |
675 | /* | ||
676 | * Submit now if the underlying fs is about to perform a | ||
677 | * metadata read | ||
678 | */ | ||
679 | else if (sdio->boundary) | ||
680 | dio_bio_submit(dio, sdio); | ||
681 | } | 675 | } |
682 | 676 | ||
683 | if (sdio->bio == NULL) { | 677 | if (sdio->bio == NULL) { |
@@ -737,16 +731,6 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, | |||
737 | sdio->cur_page_block + | 731 | sdio->cur_page_block + |
738 | (sdio->cur_page_len >> sdio->blkbits) == blocknr) { | 732 | (sdio->cur_page_len >> sdio->blkbits) == blocknr) { |
739 | sdio->cur_page_len += len; | 733 | sdio->cur_page_len += len; |
740 | |||
741 | /* | ||
742 | * If sdio->boundary then we want to schedule the IO now to | ||
743 | * avoid metadata seeks. | ||
744 | */ | ||
745 | if (sdio->boundary) { | ||
746 | ret = dio_send_cur_page(dio, sdio, map_bh); | ||
747 | page_cache_release(sdio->cur_page); | ||
748 | sdio->cur_page = NULL; | ||
749 | } | ||
750 | goto out; | 734 | goto out; |
751 | } | 735 | } |
752 | 736 | ||
@@ -758,7 +742,7 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, | |||
758 | page_cache_release(sdio->cur_page); | 742 | page_cache_release(sdio->cur_page); |
759 | sdio->cur_page = NULL; | 743 | sdio->cur_page = NULL; |
760 | if (ret) | 744 | if (ret) |
761 | goto out; | 745 | return ret; |
762 | } | 746 | } |
763 | 747 | ||
764 | page_cache_get(page); /* It is in dio */ | 748 | page_cache_get(page); /* It is in dio */ |
@@ -768,6 +752,16 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, | |||
768 | sdio->cur_page_block = blocknr; | 752 | sdio->cur_page_block = blocknr; |
769 | sdio->cur_page_fs_offset = sdio->block_in_file << sdio->blkbits; | 753 | sdio->cur_page_fs_offset = sdio->block_in_file << sdio->blkbits; |
770 | out: | 754 | out: |
755 | /* | ||
756 | * If sdio->boundary then we want to schedule the IO now to | ||
757 | * avoid metadata seeks. | ||
758 | */ | ||
759 | if (sdio->boundary) { | ||
760 | ret = dio_send_cur_page(dio, sdio, map_bh); | ||
761 | dio_bio_submit(dio, sdio); | ||
762 | page_cache_release(sdio->cur_page); | ||
763 | sdio->cur_page = NULL; | ||
764 | } | ||
771 | return ret; | 765 | return ret; |
772 | } | 766 | } |
773 | 767 | ||
@@ -969,7 +963,8 @@ do_holes: | |||
969 | this_chunk_bytes = this_chunk_blocks << blkbits; | 963 | this_chunk_bytes = this_chunk_blocks << blkbits; |
970 | BUG_ON(this_chunk_bytes == 0); | 964 | BUG_ON(this_chunk_bytes == 0); |
971 | 965 | ||
972 | sdio->boundary = buffer_boundary(map_bh); | 966 | if (this_chunk_blocks == sdio->blocks_available) |
967 | sdio->boundary = buffer_boundary(map_bh); | ||
973 | ret = submit_page_section(dio, sdio, page, | 968 | ret = submit_page_section(dio, sdio, page, |
974 | offset_in_page, | 969 | offset_in_page, |
975 | this_chunk_bytes, | 970 | this_chunk_bytes, |
@@ -613,7 +613,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
613 | * when the old and new regions overlap clear from new_end. | 613 | * when the old and new regions overlap clear from new_end. |
614 | */ | 614 | */ |
615 | free_pgd_range(&tlb, new_end, old_end, new_end, | 615 | free_pgd_range(&tlb, new_end, old_end, new_end, |
616 | vma->vm_next ? vma->vm_next->vm_start : 0); | 616 | vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING); |
617 | } else { | 617 | } else { |
618 | /* | 618 | /* |
619 | * otherwise, clean from old_start; this is done to not touch | 619 | * otherwise, clean from old_start; this is done to not touch |
@@ -622,7 +622,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
622 | * for the others its just a little faster. | 622 | * for the others its just a little faster. |
623 | */ | 623 | */ |
624 | free_pgd_range(&tlb, old_start, old_end, new_end, | 624 | free_pgd_range(&tlb, old_start, old_end, new_end, |
625 | vma->vm_next ? vma->vm_next->vm_start : 0); | 625 | vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING); |
626 | } | 626 | } |
627 | tlb_finish_mmu(&tlb, new_end, old_end); | 627 | tlb_finish_mmu(&tlb, new_end, old_end); |
628 | 628 | ||
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index fb5120a5505c..3dc48cc8b6eb 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -2067,7 +2067,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
2067 | test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal": | 2067 | test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal": |
2068 | test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": | 2068 | test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": |
2069 | "writeback"); | 2069 | "writeback"); |
2070 | sb->s_flags |= MS_SNAP_STABLE; | ||
2071 | 2070 | ||
2072 | return 0; | 2071 | return 0; |
2073 | 2072 | ||
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index cc2213afdcc7..201c8d3b0f86 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -137,7 +137,7 @@ struct extent_info { | |||
137 | rwlock_t ext_lock; /* rwlock for consistency */ | 137 | rwlock_t ext_lock; /* rwlock for consistency */ |
138 | unsigned int fofs; /* start offset in a file */ | 138 | unsigned int fofs; /* start offset in a file */ |
139 | u32 blk_addr; /* start block address of the extent */ | 139 | u32 blk_addr; /* start block address of the extent */ |
140 | unsigned int len; /* lenth of the extent */ | 140 | unsigned int len; /* length of the extent */ |
141 | }; | 141 | }; |
142 | 142 | ||
143 | /* | 143 | /* |
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 94b8a0c48453..2e3eb2d4fc30 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -222,7 +222,7 @@ static unsigned int get_gc_cost(struct f2fs_sb_info *sbi, unsigned int segno, | |||
222 | } | 222 | } |
223 | 223 | ||
224 | /* | 224 | /* |
225 | * This function is called from two pathes. | 225 | * This function is called from two paths. |
226 | * One is garbage collection and the other is SSR segment selection. | 226 | * One is garbage collection and the other is SSR segment selection. |
227 | * When it is called during GC, it just gets a victim segment | 227 | * When it is called during GC, it just gets a victim segment |
228 | * and it does not remove it from dirty seglist. | 228 | * and it does not remove it from dirty seglist. |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index fea6e582a2ed..62e017743af6 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -82,7 +82,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) | |||
82 | 82 | ||
83 | init_once((void *) fi); | 83 | init_once((void *) fi); |
84 | 84 | ||
85 | /* Initilize f2fs-specific inode info */ | 85 | /* Initialize f2fs-specific inode info */ |
86 | fi->vfs_inode.i_version = 1; | 86 | fi->vfs_inode.i_version = 1; |
87 | atomic_set(&fi->dirty_dents, 0); | 87 | atomic_set(&fi->dirty_dents, 0); |
88 | fi->i_current_depth = 1; | 88 | fi->i_current_depth = 1; |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 165012ef363a..7a6f02caf286 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
@@ -964,6 +964,29 @@ int fat_scan(struct inode *dir, const unsigned char *name, | |||
964 | } | 964 | } |
965 | EXPORT_SYMBOL_GPL(fat_scan); | 965 | EXPORT_SYMBOL_GPL(fat_scan); |
966 | 966 | ||
967 | /* | ||
968 | * Scans a directory for a given logstart. | ||
969 | * Returns an error code or zero. | ||
970 | */ | ||
971 | int fat_scan_logstart(struct inode *dir, int i_logstart, | ||
972 | struct fat_slot_info *sinfo) | ||
973 | { | ||
974 | struct super_block *sb = dir->i_sb; | ||
975 | |||
976 | sinfo->slot_off = 0; | ||
977 | sinfo->bh = NULL; | ||
978 | while (fat_get_short_entry(dir, &sinfo->slot_off, &sinfo->bh, | ||
979 | &sinfo->de) >= 0) { | ||
980 | if (fat_get_start(MSDOS_SB(sb), sinfo->de) == i_logstart) { | ||
981 | sinfo->slot_off -= sizeof(*sinfo->de); | ||
982 | sinfo->nr_slots = 1; | ||
983 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); | ||
984 | return 0; | ||
985 | } | ||
986 | } | ||
987 | return -ENOENT; | ||
988 | } | ||
989 | |||
967 | static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots) | 990 | static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots) |
968 | { | 991 | { |
969 | struct super_block *sb = dir->i_sb; | 992 | struct super_block *sb = dir->i_sb; |
diff --git a/fs/fat/fat.h b/fs/fat/fat.h index e9cc3f0d58e2..21664fcf3616 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h | |||
@@ -23,6 +23,9 @@ | |||
23 | #define FAT_ERRORS_PANIC 2 /* panic on error */ | 23 | #define FAT_ERRORS_PANIC 2 /* panic on error */ |
24 | #define FAT_ERRORS_RO 3 /* remount r/o on error */ | 24 | #define FAT_ERRORS_RO 3 /* remount r/o on error */ |
25 | 25 | ||
26 | #define FAT_NFS_STALE_RW 1 /* NFS RW support, can cause ESTALE */ | ||
27 | #define FAT_NFS_NOSTALE_RO 2 /* NFS RO support, no ESTALE issue */ | ||
28 | |||
26 | struct fat_mount_options { | 29 | struct fat_mount_options { |
27 | kuid_t fs_uid; | 30 | kuid_t fs_uid; |
28 | kgid_t fs_gid; | 31 | kgid_t fs_gid; |
@@ -34,6 +37,7 @@ struct fat_mount_options { | |||
34 | unsigned short shortname; /* flags for shortname display/create rule */ | 37 | unsigned short shortname; /* flags for shortname display/create rule */ |
35 | unsigned char name_check; /* r = relaxed, n = normal, s = strict */ | 38 | unsigned char name_check; /* r = relaxed, n = normal, s = strict */ |
36 | unsigned char errors; /* On error: continue, panic, remount-ro */ | 39 | unsigned char errors; /* On error: continue, panic, remount-ro */ |
40 | unsigned char nfs; /* NFS support: nostale_ro, stale_rw */ | ||
37 | unsigned short allow_utime;/* permission for setting the [am]time */ | 41 | unsigned short allow_utime;/* permission for setting the [am]time */ |
38 | unsigned quiet:1, /* set = fake successful chmods and chowns */ | 42 | unsigned quiet:1, /* set = fake successful chmods and chowns */ |
39 | showexec:1, /* set = only set x bit for com/exe/bat */ | 43 | showexec:1, /* set = only set x bit for com/exe/bat */ |
@@ -48,8 +52,7 @@ struct fat_mount_options { | |||
48 | usefree:1, /* Use free_clusters for FAT32 */ | 52 | usefree:1, /* Use free_clusters for FAT32 */ |
49 | tz_set:1, /* Filesystem timestamps' offset set */ | 53 | tz_set:1, /* Filesystem timestamps' offset set */ |
50 | rodir:1, /* allow ATTR_RO for directory */ | 54 | rodir:1, /* allow ATTR_RO for directory */ |
51 | discard:1, /* Issue discard requests on deletions */ | 55 | discard:1; /* Issue discard requests on deletions */ |
52 | nfs:1; /* Do extra work needed for NFS export */ | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | #define FAT_HASH_BITS 8 | 58 | #define FAT_HASH_BITS 8 |
@@ -72,6 +75,7 @@ struct msdos_sb_info { | |||
72 | unsigned long root_cluster; /* first cluster of the root directory */ | 75 | unsigned long root_cluster; /* first cluster of the root directory */ |
73 | unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ | 76 | unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ |
74 | struct mutex fat_lock; | 77 | struct mutex fat_lock; |
78 | struct mutex nfs_build_inode_lock; | ||
75 | struct mutex s_lock; | 79 | struct mutex s_lock; |
76 | unsigned int prev_free; /* previously allocated cluster number */ | 80 | unsigned int prev_free; /* previously allocated cluster number */ |
77 | unsigned int free_clusters; /* -1 if undefined */ | 81 | unsigned int free_clusters; /* -1 if undefined */ |
@@ -215,6 +219,27 @@ static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus) | |||
215 | + sbi->data_start; | 219 | + sbi->data_start; |
216 | } | 220 | } |
217 | 221 | ||
222 | static inline void fat_get_blknr_offset(struct msdos_sb_info *sbi, | ||
223 | loff_t i_pos, sector_t *blknr, int *offset) | ||
224 | { | ||
225 | *blknr = i_pos >> sbi->dir_per_block_bits; | ||
226 | *offset = i_pos & (sbi->dir_per_block - 1); | ||
227 | } | ||
228 | |||
229 | static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, | ||
230 | struct inode *inode) | ||
231 | { | ||
232 | loff_t i_pos; | ||
233 | #if BITS_PER_LONG == 32 | ||
234 | spin_lock(&sbi->inode_hash_lock); | ||
235 | #endif | ||
236 | i_pos = MSDOS_I(inode)->i_pos; | ||
237 | #if BITS_PER_LONG == 32 | ||
238 | spin_unlock(&sbi->inode_hash_lock); | ||
239 | #endif | ||
240 | return i_pos; | ||
241 | } | ||
242 | |||
218 | static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len) | 243 | static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len) |
219 | { | 244 | { |
220 | #ifdef __BIG_ENDIAN | 245 | #ifdef __BIG_ENDIAN |
@@ -271,6 +296,8 @@ extern int fat_dir_empty(struct inode *dir); | |||
271 | extern int fat_subdirs(struct inode *dir); | 296 | extern int fat_subdirs(struct inode *dir); |
272 | extern int fat_scan(struct inode *dir, const unsigned char *name, | 297 | extern int fat_scan(struct inode *dir, const unsigned char *name, |
273 | struct fat_slot_info *sinfo); | 298 | struct fat_slot_info *sinfo); |
299 | extern int fat_scan_logstart(struct inode *dir, int i_logstart, | ||
300 | struct fat_slot_info *sinfo); | ||
274 | extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, | 301 | extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, |
275 | struct msdos_dir_entry **de); | 302 | struct msdos_dir_entry **de); |
276 | extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); | 303 | extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); |
@@ -348,6 +375,7 @@ extern struct inode *fat_build_inode(struct super_block *sb, | |||
348 | extern int fat_sync_inode(struct inode *inode); | 375 | extern int fat_sync_inode(struct inode *inode); |
349 | extern int fat_fill_super(struct super_block *sb, void *data, int silent, | 376 | extern int fat_fill_super(struct super_block *sb, void *data, int silent, |
350 | int isvfat, void (*setup)(struct super_block *)); | 377 | int isvfat, void (*setup)(struct super_block *)); |
378 | extern int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de); | ||
351 | 379 | ||
352 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, | 380 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, |
353 | struct inode *i2); | 381 | struct inode *i2); |
@@ -382,12 +410,8 @@ int fat_cache_init(void); | |||
382 | void fat_cache_destroy(void); | 410 | void fat_cache_destroy(void); |
383 | 411 | ||
384 | /* fat/nfs.c */ | 412 | /* fat/nfs.c */ |
385 | struct fid; | 413 | extern const struct export_operations fat_export_ops; |
386 | extern struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid, | 414 | extern const struct export_operations fat_export_ops_nostale; |
387 | int fh_len, int fh_type); | ||
388 | extern struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
389 | int fh_len, int fh_type); | ||
390 | extern struct dentry *fat_get_parent(struct dentry *child_dir); | ||
391 | 415 | ||
392 | /* helper for printk */ | 416 | /* helper for printk */ |
393 | typedef unsigned long long llu; | 417 | typedef unsigned long long llu; |
diff --git a/fs/fat/file.c b/fs/fat/file.c index 3978f8ca1823..b0b632e50ddb 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -306,6 +306,11 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
306 | struct inode *inode = dentry->d_inode; | 306 | struct inode *inode = dentry->d_inode; |
307 | generic_fillattr(inode, stat); | 307 | generic_fillattr(inode, stat); |
308 | stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size; | 308 | stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size; |
309 | |||
310 | if (MSDOS_SB(inode->i_sb)->options.nfs == FAT_NFS_NOSTALE_RO) { | ||
311 | /* Use i_pos for ino. This is used as fileid of nfs. */ | ||
312 | stat->ino = fat_i_pos_read(MSDOS_SB(inode->i_sb), inode); | ||
313 | } | ||
309 | return 0; | 314 | return 0; |
310 | } | 315 | } |
311 | EXPORT_SYMBOL_GPL(fat_getattr); | 316 | EXPORT_SYMBOL_GPL(fat_getattr); |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index acf6e479b443..4ff901632b26 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
19 | #include <linux/mpage.h> | 19 | #include <linux/mpage.h> |
20 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
21 | #include <linux/exportfs.h> | ||
22 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
23 | #include <linux/vfs.h> | 22 | #include <linux/vfs.h> |
24 | #include <linux/parser.h> | 23 | #include <linux/parser.h> |
@@ -385,7 +384,7 @@ static int fat_calc_dir_size(struct inode *inode) | |||
385 | } | 384 | } |
386 | 385 | ||
387 | /* doesn't deal with root inode */ | 386 | /* doesn't deal with root inode */ |
388 | static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | 387 | int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) |
389 | { | 388 | { |
390 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | 389 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
391 | int error; | 390 | int error; |
@@ -444,12 +443,25 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
444 | return 0; | 443 | return 0; |
445 | } | 444 | } |
446 | 445 | ||
446 | static inline void fat_lock_build_inode(struct msdos_sb_info *sbi) | ||
447 | { | ||
448 | if (sbi->options.nfs == FAT_NFS_NOSTALE_RO) | ||
449 | mutex_lock(&sbi->nfs_build_inode_lock); | ||
450 | } | ||
451 | |||
452 | static inline void fat_unlock_build_inode(struct msdos_sb_info *sbi) | ||
453 | { | ||
454 | if (sbi->options.nfs == FAT_NFS_NOSTALE_RO) | ||
455 | mutex_unlock(&sbi->nfs_build_inode_lock); | ||
456 | } | ||
457 | |||
447 | struct inode *fat_build_inode(struct super_block *sb, | 458 | struct inode *fat_build_inode(struct super_block *sb, |
448 | struct msdos_dir_entry *de, loff_t i_pos) | 459 | struct msdos_dir_entry *de, loff_t i_pos) |
449 | { | 460 | { |
450 | struct inode *inode; | 461 | struct inode *inode; |
451 | int err; | 462 | int err; |
452 | 463 | ||
464 | fat_lock_build_inode(MSDOS_SB(sb)); | ||
453 | inode = fat_iget(sb, i_pos); | 465 | inode = fat_iget(sb, i_pos); |
454 | if (inode) | 466 | if (inode) |
455 | goto out; | 467 | goto out; |
@@ -469,6 +481,7 @@ struct inode *fat_build_inode(struct super_block *sb, | |||
469 | fat_attach(inode, i_pos); | 481 | fat_attach(inode, i_pos); |
470 | insert_inode_hash(inode); | 482 | insert_inode_hash(inode); |
471 | out: | 483 | out: |
484 | fat_unlock_build_inode(MSDOS_SB(sb)); | ||
472 | return inode; | 485 | return inode; |
473 | } | 486 | } |
474 | 487 | ||
@@ -655,20 +668,6 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
655 | return 0; | 668 | return 0; |
656 | } | 669 | } |
657 | 670 | ||
658 | static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, | ||
659 | struct inode *inode) | ||
660 | { | ||
661 | loff_t i_pos; | ||
662 | #if BITS_PER_LONG == 32 | ||
663 | spin_lock(&sbi->inode_hash_lock); | ||
664 | #endif | ||
665 | i_pos = MSDOS_I(inode)->i_pos; | ||
666 | #if BITS_PER_LONG == 32 | ||
667 | spin_unlock(&sbi->inode_hash_lock); | ||
668 | #endif | ||
669 | return i_pos; | ||
670 | } | ||
671 | |||
672 | static int __fat_write_inode(struct inode *inode, int wait) | 671 | static int __fat_write_inode(struct inode *inode, int wait) |
673 | { | 672 | { |
674 | struct super_block *sb = inode->i_sb; | 673 | struct super_block *sb = inode->i_sb; |
@@ -676,7 +675,8 @@ static int __fat_write_inode(struct inode *inode, int wait) | |||
676 | struct buffer_head *bh; | 675 | struct buffer_head *bh; |
677 | struct msdos_dir_entry *raw_entry; | 676 | struct msdos_dir_entry *raw_entry; |
678 | loff_t i_pos; | 677 | loff_t i_pos; |
679 | int err; | 678 | sector_t blocknr; |
679 | int err, offset; | ||
680 | 680 | ||
681 | if (inode->i_ino == MSDOS_ROOT_INO) | 681 | if (inode->i_ino == MSDOS_ROOT_INO) |
682 | return 0; | 682 | return 0; |
@@ -686,7 +686,8 @@ retry: | |||
686 | if (!i_pos) | 686 | if (!i_pos) |
687 | return 0; | 687 | return 0; |
688 | 688 | ||
689 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); | 689 | fat_get_blknr_offset(sbi, i_pos, &blocknr, &offset); |
690 | bh = sb_bread(sb, blocknr); | ||
690 | if (!bh) { | 691 | if (!bh) { |
691 | fat_msg(sb, KERN_ERR, "unable to read inode block " | 692 | fat_msg(sb, KERN_ERR, "unable to read inode block " |
692 | "for updating (i_pos %lld)", i_pos); | 693 | "for updating (i_pos %lld)", i_pos); |
@@ -699,8 +700,7 @@ retry: | |||
699 | goto retry; | 700 | goto retry; |
700 | } | 701 | } |
701 | 702 | ||
702 | raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) | 703 | raw_entry = &((struct msdos_dir_entry *) (bh->b_data))[offset]; |
703 | [i_pos & (sbi->dir_per_block - 1)]; | ||
704 | if (S_ISDIR(inode->i_mode)) | 704 | if (S_ISDIR(inode->i_mode)) |
705 | raw_entry->size = 0; | 705 | raw_entry->size = 0; |
706 | else | 706 | else |
@@ -761,12 +761,6 @@ static const struct super_operations fat_sops = { | |||
761 | .show_options = fat_show_options, | 761 | .show_options = fat_show_options, |
762 | }; | 762 | }; |
763 | 763 | ||
764 | static const struct export_operations fat_export_ops = { | ||
765 | .fh_to_dentry = fat_fh_to_dentry, | ||
766 | .fh_to_parent = fat_fh_to_parent, | ||
767 | .get_parent = fat_get_parent, | ||
768 | }; | ||
769 | |||
770 | static int fat_show_options(struct seq_file *m, struct dentry *root) | 764 | static int fat_show_options(struct seq_file *m, struct dentry *root) |
771 | { | 765 | { |
772 | struct msdos_sb_info *sbi = MSDOS_SB(root->d_sb); | 766 | struct msdos_sb_info *sbi = MSDOS_SB(root->d_sb); |
@@ -814,8 +808,6 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) | |||
814 | seq_puts(m, ",usefree"); | 808 | seq_puts(m, ",usefree"); |
815 | if (opts->quiet) | 809 | if (opts->quiet) |
816 | seq_puts(m, ",quiet"); | 810 | seq_puts(m, ",quiet"); |
817 | if (opts->nfs) | ||
818 | seq_puts(m, ",nfs"); | ||
819 | if (opts->showexec) | 811 | if (opts->showexec) |
820 | seq_puts(m, ",showexec"); | 812 | seq_puts(m, ",showexec"); |
821 | if (opts->sys_immutable) | 813 | if (opts->sys_immutable) |
@@ -849,6 +841,10 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) | |||
849 | seq_puts(m, ",errors=panic"); | 841 | seq_puts(m, ",errors=panic"); |
850 | else | 842 | else |
851 | seq_puts(m, ",errors=remount-ro"); | 843 | seq_puts(m, ",errors=remount-ro"); |
844 | if (opts->nfs == FAT_NFS_NOSTALE_RO) | ||
845 | seq_puts(m, ",nfs=nostale_ro"); | ||
846 | else if (opts->nfs) | ||
847 | seq_puts(m, ",nfs=stale_rw"); | ||
852 | if (opts->discard) | 848 | if (opts->discard) |
853 | seq_puts(m, ",discard"); | 849 | seq_puts(m, ",discard"); |
854 | 850 | ||
@@ -865,7 +861,7 @@ enum { | |||
865 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 861 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
866 | Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, | 862 | Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, |
867 | Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset, | 863 | Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset, |
868 | Opt_err, | 864 | Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err, |
869 | }; | 865 | }; |
870 | 866 | ||
871 | static const match_table_t fat_tokens = { | 867 | static const match_table_t fat_tokens = { |
@@ -895,7 +891,9 @@ static const match_table_t fat_tokens = { | |||
895 | {Opt_err_panic, "errors=panic"}, | 891 | {Opt_err_panic, "errors=panic"}, |
896 | {Opt_err_ro, "errors=remount-ro"}, | 892 | {Opt_err_ro, "errors=remount-ro"}, |
897 | {Opt_discard, "discard"}, | 893 | {Opt_discard, "discard"}, |
898 | {Opt_nfs, "nfs"}, | 894 | {Opt_nfs_stale_rw, "nfs"}, |
895 | {Opt_nfs_stale_rw, "nfs=stale_rw"}, | ||
896 | {Opt_nfs_nostale_ro, "nfs=nostale_ro"}, | ||
899 | {Opt_obsolete, "conv=binary"}, | 897 | {Opt_obsolete, "conv=binary"}, |
900 | {Opt_obsolete, "conv=text"}, | 898 | {Opt_obsolete, "conv=text"}, |
901 | {Opt_obsolete, "conv=auto"}, | 899 | {Opt_obsolete, "conv=auto"}, |
@@ -1092,6 +1090,12 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, | |||
1092 | case Opt_err_ro: | 1090 | case Opt_err_ro: |
1093 | opts->errors = FAT_ERRORS_RO; | 1091 | opts->errors = FAT_ERRORS_RO; |
1094 | break; | 1092 | break; |
1093 | case Opt_nfs_stale_rw: | ||
1094 | opts->nfs = FAT_NFS_STALE_RW; | ||
1095 | break; | ||
1096 | case Opt_nfs_nostale_ro: | ||
1097 | opts->nfs = FAT_NFS_NOSTALE_RO; | ||
1098 | break; | ||
1095 | 1099 | ||
1096 | /* msdos specific */ | 1100 | /* msdos specific */ |
1097 | case Opt_dots: | 1101 | case Opt_dots: |
@@ -1150,9 +1154,6 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, | |||
1150 | case Opt_discard: | 1154 | case Opt_discard: |
1151 | opts->discard = 1; | 1155 | opts->discard = 1; |
1152 | break; | 1156 | break; |
1153 | case Opt_nfs: | ||
1154 | opts->nfs = 1; | ||
1155 | break; | ||
1156 | 1157 | ||
1157 | /* obsolete mount options */ | 1158 | /* obsolete mount options */ |
1158 | case Opt_obsolete: | 1159 | case Opt_obsolete: |
@@ -1183,6 +1184,10 @@ out: | |||
1183 | opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); | 1184 | opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); |
1184 | if (opts->unicode_xlate) | 1185 | if (opts->unicode_xlate) |
1185 | opts->utf8 = 0; | 1186 | opts->utf8 = 0; |
1187 | if (opts->nfs == FAT_NFS_NOSTALE_RO) { | ||
1188 | sb->s_flags |= MS_RDONLY; | ||
1189 | sb->s_export_op = &fat_export_ops_nostale; | ||
1190 | } | ||
1186 | 1191 | ||
1187 | return 0; | 1192 | return 0; |
1188 | } | 1193 | } |
@@ -1193,7 +1198,7 @@ static int fat_read_root(struct inode *inode) | |||
1193 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 1198 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
1194 | int error; | 1199 | int error; |
1195 | 1200 | ||
1196 | MSDOS_I(inode)->i_pos = 0; | 1201 | MSDOS_I(inode)->i_pos = MSDOS_ROOT_INO; |
1197 | inode->i_uid = sbi->options.fs_uid; | 1202 | inode->i_uid = sbi->options.fs_uid; |
1198 | inode->i_gid = sbi->options.fs_gid; | 1203 | inode->i_gid = sbi->options.fs_gid; |
1199 | inode->i_version++; | 1204 | inode->i_version++; |
@@ -1256,6 +1261,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1256 | sb->s_magic = MSDOS_SUPER_MAGIC; | 1261 | sb->s_magic = MSDOS_SUPER_MAGIC; |
1257 | sb->s_op = &fat_sops; | 1262 | sb->s_op = &fat_sops; |
1258 | sb->s_export_op = &fat_export_ops; | 1263 | sb->s_export_op = &fat_export_ops; |
1264 | mutex_init(&sbi->nfs_build_inode_lock); | ||
1259 | ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, | 1265 | ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, |
1260 | DEFAULT_RATELIMIT_BURST); | 1266 | DEFAULT_RATELIMIT_BURST); |
1261 | 1267 | ||
diff --git a/fs/fat/nfs.c b/fs/fat/nfs.c index 499c10438ca2..93e14933dcb6 100644 --- a/fs/fat/nfs.c +++ b/fs/fat/nfs.c | |||
@@ -14,6 +14,18 @@ | |||
14 | #include <linux/exportfs.h> | 14 | #include <linux/exportfs.h> |
15 | #include "fat.h" | 15 | #include "fat.h" |
16 | 16 | ||
17 | struct fat_fid { | ||
18 | u32 i_gen; | ||
19 | u32 i_pos_low; | ||
20 | u16 i_pos_hi; | ||
21 | u16 parent_i_pos_hi; | ||
22 | u32 parent_i_pos_low; | ||
23 | u32 parent_i_gen; | ||
24 | }; | ||
25 | |||
26 | #define FAT_FID_SIZE_WITHOUT_PARENT 3 | ||
27 | #define FAT_FID_SIZE_WITH_PARENT (sizeof(struct fat_fid)/sizeof(u32)) | ||
28 | |||
17 | /** | 29 | /** |
18 | * Look up a directory inode given its starting cluster. | 30 | * Look up a directory inode given its starting cluster. |
19 | */ | 31 | */ |
@@ -38,63 +50,252 @@ static struct inode *fat_dget(struct super_block *sb, int i_logstart) | |||
38 | return inode; | 50 | return inode; |
39 | } | 51 | } |
40 | 52 | ||
41 | static struct inode *fat_nfs_get_inode(struct super_block *sb, | 53 | static struct inode *fat_ilookup(struct super_block *sb, u64 ino, loff_t i_pos) |
42 | u64 ino, u32 generation) | ||
43 | { | 54 | { |
44 | struct inode *inode; | 55 | if (MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO) |
56 | return fat_iget(sb, i_pos); | ||
45 | 57 | ||
46 | if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO)) | 58 | else { |
47 | return NULL; | 59 | if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO)) |
60 | return NULL; | ||
61 | return ilookup(sb, ino); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | static struct inode *__fat_nfs_get_inode(struct super_block *sb, | ||
66 | u64 ino, u32 generation, loff_t i_pos) | ||
67 | { | ||
68 | struct inode *inode = fat_ilookup(sb, ino, i_pos); | ||
48 | 69 | ||
49 | inode = ilookup(sb, ino); | ||
50 | if (inode && generation && (inode->i_generation != generation)) { | 70 | if (inode && generation && (inode->i_generation != generation)) { |
51 | iput(inode); | 71 | iput(inode); |
52 | inode = NULL; | 72 | inode = NULL; |
53 | } | 73 | } |
74 | if (inode == NULL && MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO) { | ||
75 | struct buffer_head *bh = NULL; | ||
76 | struct msdos_dir_entry *de ; | ||
77 | sector_t blocknr; | ||
78 | int offset; | ||
79 | fat_get_blknr_offset(MSDOS_SB(sb), i_pos, &blocknr, &offset); | ||
80 | bh = sb_bread(sb, blocknr); | ||
81 | if (!bh) { | ||
82 | fat_msg(sb, KERN_ERR, | ||
83 | "unable to read block(%llu) for building NFS inode", | ||
84 | (llu)blocknr); | ||
85 | return inode; | ||
86 | } | ||
87 | de = (struct msdos_dir_entry *)bh->b_data; | ||
88 | /* If a file is deleted on server and client is not updated | ||
89 | * yet, we must not build the inode upon a lookup call. | ||
90 | */ | ||
91 | if (IS_FREE(de[offset].name)) | ||
92 | inode = NULL; | ||
93 | else | ||
94 | inode = fat_build_inode(sb, &de[offset], i_pos); | ||
95 | brelse(bh); | ||
96 | } | ||
54 | 97 | ||
55 | return inode; | 98 | return inode; |
56 | } | 99 | } |
57 | 100 | ||
101 | static struct inode *fat_nfs_get_inode(struct super_block *sb, | ||
102 | u64 ino, u32 generation) | ||
103 | { | ||
104 | |||
105 | return __fat_nfs_get_inode(sb, ino, generation, 0); | ||
106 | } | ||
107 | |||
108 | static int | ||
109 | fat_encode_fh_nostale(struct inode *inode, __u32 *fh, int *lenp, | ||
110 | struct inode *parent) | ||
111 | { | ||
112 | int len = *lenp; | ||
113 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | ||
114 | struct fat_fid *fid = (struct fat_fid *) fh; | ||
115 | loff_t i_pos; | ||
116 | int type = FILEID_FAT_WITHOUT_PARENT; | ||
117 | |||
118 | if (parent) { | ||
119 | if (len < FAT_FID_SIZE_WITH_PARENT) { | ||
120 | *lenp = FAT_FID_SIZE_WITH_PARENT; | ||
121 | return FILEID_INVALID; | ||
122 | } | ||
123 | } else { | ||
124 | if (len < FAT_FID_SIZE_WITHOUT_PARENT) { | ||
125 | *lenp = FAT_FID_SIZE_WITHOUT_PARENT; | ||
126 | return FILEID_INVALID; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | i_pos = fat_i_pos_read(sbi, inode); | ||
131 | *lenp = FAT_FID_SIZE_WITHOUT_PARENT; | ||
132 | fid->i_gen = inode->i_generation; | ||
133 | fid->i_pos_low = i_pos & 0xFFFFFFFF; | ||
134 | fid->i_pos_hi = (i_pos >> 32) & 0xFFFF; | ||
135 | if (parent) { | ||
136 | i_pos = fat_i_pos_read(sbi, parent); | ||
137 | fid->parent_i_pos_hi = (i_pos >> 32) & 0xFFFF; | ||
138 | fid->parent_i_pos_low = i_pos & 0xFFFFFFFF; | ||
139 | fid->parent_i_gen = parent->i_generation; | ||
140 | type = FILEID_FAT_WITH_PARENT; | ||
141 | *lenp = FAT_FID_SIZE_WITH_PARENT; | ||
142 | } | ||
143 | |||
144 | return type; | ||
145 | } | ||
146 | |||
58 | /** | 147 | /** |
59 | * Map a NFS file handle to a corresponding dentry. | 148 | * Map a NFS file handle to a corresponding dentry. |
60 | * The dentry may or may not be connected to the filesystem root. | 149 | * The dentry may or may not be connected to the filesystem root. |
61 | */ | 150 | */ |
62 | struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid, | 151 | static struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid, |
63 | int fh_len, int fh_type) | 152 | int fh_len, int fh_type) |
64 | { | 153 | { |
65 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | 154 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, |
66 | fat_nfs_get_inode); | 155 | fat_nfs_get_inode); |
67 | } | 156 | } |
68 | 157 | ||
158 | static struct dentry *fat_fh_to_dentry_nostale(struct super_block *sb, | ||
159 | struct fid *fh, int fh_len, | ||
160 | int fh_type) | ||
161 | { | ||
162 | struct inode *inode = NULL; | ||
163 | struct fat_fid *fid = (struct fat_fid *)fh; | ||
164 | loff_t i_pos; | ||
165 | |||
166 | switch (fh_type) { | ||
167 | case FILEID_FAT_WITHOUT_PARENT: | ||
168 | if (fh_len < FAT_FID_SIZE_WITHOUT_PARENT) | ||
169 | return NULL; | ||
170 | break; | ||
171 | case FILEID_FAT_WITH_PARENT: | ||
172 | if (fh_len < FAT_FID_SIZE_WITH_PARENT) | ||
173 | return NULL; | ||
174 | break; | ||
175 | default: | ||
176 | return NULL; | ||
177 | } | ||
178 | i_pos = fid->i_pos_hi; | ||
179 | i_pos = (i_pos << 32) | (fid->i_pos_low); | ||
180 | inode = __fat_nfs_get_inode(sb, 0, fid->i_gen, i_pos); | ||
181 | |||
182 | return d_obtain_alias(inode); | ||
183 | } | ||
184 | |||
69 | /* | 185 | /* |
70 | * Find the parent for a file specified by NFS handle. | 186 | * Find the parent for a file specified by NFS handle. |
71 | * This requires that the handle contain the i_ino of the parent. | 187 | * This requires that the handle contain the i_ino of the parent. |
72 | */ | 188 | */ |
73 | struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid, | 189 | static struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid, |
74 | int fh_len, int fh_type) | 190 | int fh_len, int fh_type) |
75 | { | 191 | { |
76 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | 192 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, |
77 | fat_nfs_get_inode); | 193 | fat_nfs_get_inode); |
78 | } | 194 | } |
79 | 195 | ||
196 | static struct dentry *fat_fh_to_parent_nostale(struct super_block *sb, | ||
197 | struct fid *fh, int fh_len, | ||
198 | int fh_type) | ||
199 | { | ||
200 | struct inode *inode = NULL; | ||
201 | struct fat_fid *fid = (struct fat_fid *)fh; | ||
202 | loff_t i_pos; | ||
203 | |||
204 | if (fh_len < FAT_FID_SIZE_WITH_PARENT) | ||
205 | return NULL; | ||
206 | |||
207 | switch (fh_type) { | ||
208 | case FILEID_FAT_WITH_PARENT: | ||
209 | i_pos = fid->parent_i_pos_hi; | ||
210 | i_pos = (i_pos << 32) | (fid->parent_i_pos_low); | ||
211 | inode = __fat_nfs_get_inode(sb, 0, fid->parent_i_gen, i_pos); | ||
212 | break; | ||
213 | } | ||
214 | |||
215 | return d_obtain_alias(inode); | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * Rebuild the parent for a directory that is not connected | ||
220 | * to the filesystem root | ||
221 | */ | ||
222 | static | ||
223 | struct inode *fat_rebuild_parent(struct super_block *sb, int parent_logstart) | ||
224 | { | ||
225 | int search_clus, clus_to_match; | ||
226 | struct msdos_dir_entry *de; | ||
227 | struct inode *parent = NULL; | ||
228 | struct inode *dummy_grand_parent = NULL; | ||
229 | struct fat_slot_info sinfo; | ||
230 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | ||
231 | sector_t blknr = fat_clus_to_blknr(sbi, parent_logstart); | ||
232 | struct buffer_head *parent_bh = sb_bread(sb, blknr); | ||
233 | if (!parent_bh) { | ||
234 | fat_msg(sb, KERN_ERR, | ||
235 | "unable to read cluster of parent directory"); | ||
236 | return NULL; | ||
237 | } | ||
238 | |||
239 | de = (struct msdos_dir_entry *) parent_bh->b_data; | ||
240 | clus_to_match = fat_get_start(sbi, &de[0]); | ||
241 | search_clus = fat_get_start(sbi, &de[1]); | ||
242 | |||
243 | dummy_grand_parent = fat_dget(sb, search_clus); | ||
244 | if (!dummy_grand_parent) { | ||
245 | dummy_grand_parent = new_inode(sb); | ||
246 | if (!dummy_grand_parent) { | ||
247 | brelse(parent_bh); | ||
248 | return parent; | ||
249 | } | ||
250 | |||
251 | dummy_grand_parent->i_ino = iunique(sb, MSDOS_ROOT_INO); | ||
252 | fat_fill_inode(dummy_grand_parent, &de[1]); | ||
253 | MSDOS_I(dummy_grand_parent)->i_pos = -1; | ||
254 | } | ||
255 | |||
256 | if (!fat_scan_logstart(dummy_grand_parent, clus_to_match, &sinfo)) | ||
257 | parent = fat_build_inode(sb, sinfo.de, sinfo.i_pos); | ||
258 | |||
259 | brelse(parent_bh); | ||
260 | iput(dummy_grand_parent); | ||
261 | |||
262 | return parent; | ||
263 | } | ||
264 | |||
80 | /* | 265 | /* |
81 | * Find the parent for a directory that is not currently connected to | 266 | * Find the parent for a directory that is not currently connected to |
82 | * the filesystem root. | 267 | * the filesystem root. |
83 | * | 268 | * |
84 | * On entry, the caller holds child_dir->d_inode->i_mutex. | 269 | * On entry, the caller holds child_dir->d_inode->i_mutex. |
85 | */ | 270 | */ |
86 | struct dentry *fat_get_parent(struct dentry *child_dir) | 271 | static struct dentry *fat_get_parent(struct dentry *child_dir) |
87 | { | 272 | { |
88 | struct super_block *sb = child_dir->d_sb; | 273 | struct super_block *sb = child_dir->d_sb; |
89 | struct buffer_head *bh = NULL; | 274 | struct buffer_head *bh = NULL; |
90 | struct msdos_dir_entry *de; | 275 | struct msdos_dir_entry *de; |
91 | struct inode *parent_inode = NULL; | 276 | struct inode *parent_inode = NULL; |
277 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | ||
92 | 278 | ||
93 | if (!fat_get_dotdot_entry(child_dir->d_inode, &bh, &de)) { | 279 | if (!fat_get_dotdot_entry(child_dir->d_inode, &bh, &de)) { |
94 | int parent_logstart = fat_get_start(MSDOS_SB(sb), de); | 280 | int parent_logstart = fat_get_start(sbi, de); |
95 | parent_inode = fat_dget(sb, parent_logstart); | 281 | parent_inode = fat_dget(sb, parent_logstart); |
282 | if (!parent_inode && sbi->options.nfs == FAT_NFS_NOSTALE_RO) | ||
283 | parent_inode = fat_rebuild_parent(sb, parent_logstart); | ||
96 | } | 284 | } |
97 | brelse(bh); | 285 | brelse(bh); |
98 | 286 | ||
99 | return d_obtain_alias(parent_inode); | 287 | return d_obtain_alias(parent_inode); |
100 | } | 288 | } |
289 | |||
290 | const struct export_operations fat_export_ops = { | ||
291 | .fh_to_dentry = fat_fh_to_dentry, | ||
292 | .fh_to_parent = fat_fh_to_parent, | ||
293 | .get_parent = fat_get_parent, | ||
294 | }; | ||
295 | |||
296 | const struct export_operations fat_export_ops_nostale = { | ||
297 | .encode_fh = fat_encode_fh_nostale, | ||
298 | .fh_to_dentry = fat_fh_to_dentry_nostale, | ||
299 | .fh_to_parent = fat_fh_to_parent_nostale, | ||
300 | .get_parent = fat_get_parent, | ||
301 | }; | ||
diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c index 8179e8bc4a3d..40d13c70ef51 100644 --- a/fs/fscache/stats.c +++ b/fs/fscache/stats.c | |||
@@ -287,5 +287,5 @@ const struct file_operations fscache_stats_fops = { | |||
287 | .open = fscache_stats_open, | 287 | .open = fscache_stats_open, |
288 | .read = seq_read, | 288 | .read = seq_read, |
289 | .llseek = seq_lseek, | 289 | .llseek = seq_lseek, |
290 | .release = seq_release, | 290 | .release = single_release, |
291 | }; | 291 | }; |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index cf3515546739..bd8223595495 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -1017,11 +1017,11 @@ do_cancel: | |||
1017 | return; | 1017 | return; |
1018 | 1018 | ||
1019 | trap_recursive: | 1019 | trap_recursive: |
1020 | print_symbol(KERN_ERR "original: %s\n", gh2->gh_ip); | 1020 | printk(KERN_ERR "original: %pSR\n", (void *)gh2->gh_ip); |
1021 | printk(KERN_ERR "pid: %d\n", pid_nr(gh2->gh_owner_pid)); | 1021 | printk(KERN_ERR "pid: %d\n", pid_nr(gh2->gh_owner_pid)); |
1022 | printk(KERN_ERR "lock type: %d req lock state : %d\n", | 1022 | printk(KERN_ERR "lock type: %d req lock state : %d\n", |
1023 | gh2->gh_gl->gl_name.ln_type, gh2->gh_state); | 1023 | gh2->gh_gl->gl_name.ln_type, gh2->gh_state); |
1024 | print_symbol(KERN_ERR "new: %s\n", gh->gh_ip); | 1024 | printk(KERN_ERR "new: %pSR\n", (void *)gh->gh_ip); |
1025 | printk(KERN_ERR "pid: %d\n", pid_nr(gh->gh_owner_pid)); | 1025 | printk(KERN_ERR "pid: %d\n", pid_nr(gh->gh_owner_pid)); |
1026 | printk(KERN_ERR "lock type: %d req lock state : %d\n", | 1026 | printk(KERN_ERR "lock type: %d req lock state : %d\n", |
1027 | gh->gh_gl->gl_name.ln_type, gh->gh_state); | 1027 | gh->gh_gl->gl_name.ln_type, gh->gh_state); |
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 88162fae27a5..5bc023ea38ac 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c | |||
@@ -96,7 +96,8 @@ static void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) | |||
96 | 96 | ||
97 | static void gfs2_print_trans(const struct gfs2_trans *tr) | 97 | static void gfs2_print_trans(const struct gfs2_trans *tr) |
98 | { | 98 | { |
99 | print_symbol(KERN_WARNING "GFS2: Transaction created at: %s\n", tr->tr_ip); | 99 | printk(KERN_WARNING "GFS2: Transaction created at: %pSR\n", |
100 | (void *)tr->tr_ip); | ||
100 | printk(KERN_WARNING "GFS2: blocks=%u revokes=%u reserved=%u touched=%d\n", | 101 | printk(KERN_WARNING "GFS2: blocks=%u revokes=%u reserved=%u touched=%d\n", |
101 | tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, tr->tr_touched); | 102 | tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, tr->tr_touched); |
102 | printk(KERN_WARNING "GFS2: Buf %u/%u Databuf %u/%u Revoke %u/%u\n", | 103 | printk(KERN_WARNING "GFS2: Buf %u/%u Databuf %u/%u Revoke %u/%u\n", |
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index a94f0f779d5e..fe0a76213d9e 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c | |||
@@ -533,7 +533,7 @@ void hfsplus_file_truncate(struct inode *inode) | |||
533 | struct address_space *mapping = inode->i_mapping; | 533 | struct address_space *mapping = inode->i_mapping; |
534 | struct page *page; | 534 | struct page *page; |
535 | void *fsdata; | 535 | void *fsdata; |
536 | u32 size = inode->i_size; | 536 | loff_t size = inode->i_size; |
537 | 537 | ||
538 | res = pagecache_write_begin(NULL, mapping, size, 0, | 538 | res = pagecache_write_begin(NULL, mapping, size, 0, |
539 | AOP_FLAG_UNINTERRUPTIBLE, | 539 | AOP_FLAG_UNINTERRUPTIBLE, |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 84e3d856e91d..523464e62849 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -110,7 +110,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
110 | * way when do_mmap_pgoff unwinds (may be important on powerpc | 110 | * way when do_mmap_pgoff unwinds (may be important on powerpc |
111 | * and ia64). | 111 | * and ia64). |
112 | */ | 112 | */ |
113 | vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND | VM_DONTDUMP; | 113 | vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND; |
114 | vma->vm_ops = &hugetlb_vm_ops; | 114 | vma->vm_ops = &hugetlb_vm_ops; |
115 | 115 | ||
116 | if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT)) | 116 | if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT)) |
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 86b39b167c23..11bb11f48b3a 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
@@ -162,8 +162,17 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs, | |||
162 | 162 | ||
163 | for (i = 0; i < bufs; i++) { | 163 | for (i = 0; i < bufs; i++) { |
164 | wbuf[i]->b_end_io = end_buffer_write_sync; | 164 | wbuf[i]->b_end_io = end_buffer_write_sync; |
165 | /* We use-up our safety reference in submit_bh() */ | 165 | /* |
166 | submit_bh(write_op, wbuf[i]); | 166 | * Here we write back pagecache data that may be mmaped. Since |
167 | * we cannot afford to clean the page and set PageWriteback | ||
168 | * here due to lock ordering (page lock ranks above transaction | ||
169 | * start), the data can change while IO is in flight. Tell the | ||
170 | * block layer it should bounce the bio pages if stable data | ||
171 | * during write is required. | ||
172 | * | ||
173 | * We use up our safety reference in submit_bh(). | ||
174 | */ | ||
175 | _submit_bh(write_op, wbuf[i], 1 << BIO_SNAP_STABLE); | ||
167 | } | 176 | } |
168 | } | 177 | } |
169 | 178 | ||
@@ -667,7 +676,17 @@ start_journal_io: | |||
667 | clear_buffer_dirty(bh); | 676 | clear_buffer_dirty(bh); |
668 | set_buffer_uptodate(bh); | 677 | set_buffer_uptodate(bh); |
669 | bh->b_end_io = journal_end_buffer_io_sync; | 678 | bh->b_end_io = journal_end_buffer_io_sync; |
670 | submit_bh(write_op, bh); | 679 | /* |
680 | * In data=journal mode, here we can end up | ||
681 | * writing pagecache data that might be | ||
682 | * mmapped. Since we can't afford to clean the | ||
683 | * page and set PageWriteback (see the comment | ||
684 | * near the other use of _submit_bh()), the | ||
685 | * data can change while the write is in | ||
686 | * flight. Tell the block layer to bounce the | ||
687 | * bio pages if stable pages are required. | ||
688 | */ | ||
689 | _submit_bh(write_op, bh, 1 << BIO_SNAP_STABLE); | ||
671 | } | 690 | } |
672 | cond_resched(); | 691 | cond_resched(); |
673 | 692 | ||
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 81cc7eaff863..865c4308acb6 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -310,8 +310,6 @@ int journal_write_metadata_buffer(transaction_t *transaction, | |||
310 | 310 | ||
311 | new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); | 311 | new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); |
312 | /* keep subsequent assertions sane */ | 312 | /* keep subsequent assertions sane */ |
313 | new_bh->b_state = 0; | ||
314 | init_buffer(new_bh, NULL, NULL); | ||
315 | atomic_set(&new_bh->b_count, 1); | 313 | atomic_set(&new_bh->b_count, 1); |
316 | new_jh = journal_add_journal_head(new_bh); /* This sleeps */ | 314 | new_jh = journal_add_journal_head(new_bh); /* This sleeps */ |
317 | 315 | ||
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index ed10991ab006..8b220f1ab54f 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -367,8 +367,6 @@ retry_alloc: | |||
367 | } | 367 | } |
368 | 368 | ||
369 | /* keep subsequent assertions sane */ | 369 | /* keep subsequent assertions sane */ |
370 | new_bh->b_state = 0; | ||
371 | init_buffer(new_bh, NULL, NULL); | ||
372 | atomic_set(&new_bh->b_count, 1); | 370 | atomic_set(&new_bh->b_count, 1); |
373 | new_jh = jbd2_journal_add_journal_head(new_bh); /* This sleeps */ | 371 | new_jh = jbd2_journal_add_journal_head(new_bh); /* This sleeps */ |
374 | 372 | ||
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 88f9611a945c..5457745dd4f1 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -234,7 +234,7 @@ static int __alloc_objio_seg(unsigned numdevs, gfp_t gfp_flags, | |||
234 | 234 | ||
235 | lseg = kzalloc(lseg_size, gfp_flags); | 235 | lseg = kzalloc(lseg_size, gfp_flags); |
236 | if (unlikely(!lseg)) { | 236 | if (unlikely(!lseg)) { |
237 | dprintk("%s: Faild allocation numdevs=%d size=%zd\n", __func__, | 237 | dprintk("%s: Failed allocation numdevs=%d size=%zd\n", __func__, |
238 | numdevs, lseg_size); | 238 | numdevs, lseg_size); |
239 | return -ENOMEM; | 239 | return -ENOMEM; |
240 | } | 240 | } |
diff --git a/fs/nfs/objlayout/objlayout.h b/fs/nfs/objlayout/objlayout.h index 880ba086be94..87aa1dec6120 100644 --- a/fs/nfs/objlayout/objlayout.h +++ b/fs/nfs/objlayout/objlayout.h | |||
@@ -114,7 +114,7 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp, | |||
114 | gfp_t gfp_flags); | 114 | gfp_t gfp_flags); |
115 | extern void objio_free_lseg(struct pnfs_layout_segment *lseg); | 115 | extern void objio_free_lseg(struct pnfs_layout_segment *lseg); |
116 | 116 | ||
117 | /* objio_free_result will free these @oir structs recieved from | 117 | /* objio_free_result will free these @oir structs received from |
118 | * objlayout_{read,write}_done | 118 | * objlayout_{read,write}_done |
119 | */ | 119 | */ |
120 | extern void objio_free_result(struct objlayout_io_res *oir); | 120 | extern void objio_free_result(struct objlayout_io_res *oir); |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 2e27430b9070..417c84877742 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -234,7 +234,6 @@ static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct | |||
234 | kmem_cache *slab) | 234 | kmem_cache *slab) |
235 | { | 235 | { |
236 | struct idr *stateids = &cl->cl_stateids; | 236 | struct idr *stateids = &cl->cl_stateids; |
237 | static int min_stateid = 0; | ||
238 | struct nfs4_stid *stid; | 237 | struct nfs4_stid *stid; |
239 | int new_id; | 238 | int new_id; |
240 | 239 | ||
@@ -242,7 +241,7 @@ kmem_cache *slab) | |||
242 | if (!stid) | 241 | if (!stid) |
243 | return NULL; | 242 | return NULL; |
244 | 243 | ||
245 | new_id = idr_alloc(stateids, stid, min_stateid, 0, GFP_KERNEL); | 244 | new_id = idr_alloc_cyclic(stateids, stid, 0, 0, GFP_KERNEL); |
246 | if (new_id < 0) | 245 | if (new_id < 0) |
247 | goto out_free; | 246 | goto out_free; |
248 | stid->sc_client = cl; | 247 | stid->sc_client = cl; |
@@ -261,10 +260,6 @@ kmem_cache *slab) | |||
261 | * amount of time until an id is reused, by ensuring they always | 260 | * amount of time until an id is reused, by ensuring they always |
262 | * "increase" (mod INT_MAX): | 261 | * "increase" (mod INT_MAX): |
263 | */ | 262 | */ |
264 | |||
265 | min_stateid = new_id+1; | ||
266 | if (min_stateid == INT_MAX) | ||
267 | min_stateid = 0; | ||
268 | return stid; | 263 | return stid; |
269 | out_free: | 264 | out_free: |
270 | kfree(stid); | 265 | kfree(stid); |
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index e0f7c1241a6a..8562bd3af947 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
@@ -359,7 +359,6 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns | |||
359 | } | 359 | } |
360 | 360 | ||
361 | static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock, | 361 | static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock, |
362 | int *last_wd, | ||
363 | struct inotify_inode_mark *i_mark) | 362 | struct inotify_inode_mark *i_mark) |
364 | { | 363 | { |
365 | int ret; | 364 | int ret; |
@@ -367,11 +366,10 @@ static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock, | |||
367 | idr_preload(GFP_KERNEL); | 366 | idr_preload(GFP_KERNEL); |
368 | spin_lock(idr_lock); | 367 | spin_lock(idr_lock); |
369 | 368 | ||
370 | ret = idr_alloc(idr, i_mark, *last_wd + 1, 0, GFP_NOWAIT); | 369 | ret = idr_alloc_cyclic(idr, i_mark, 1, 0, GFP_NOWAIT); |
371 | if (ret >= 0) { | 370 | if (ret >= 0) { |
372 | /* we added the mark to the idr, take a reference */ | 371 | /* we added the mark to the idr, take a reference */ |
373 | i_mark->wd = ret; | 372 | i_mark->wd = ret; |
374 | *last_wd = i_mark->wd; | ||
375 | fsnotify_get_mark(&i_mark->fsn_mark); | 373 | fsnotify_get_mark(&i_mark->fsn_mark); |
376 | } | 374 | } |
377 | 375 | ||
@@ -638,8 +636,7 @@ static int inotify_new_watch(struct fsnotify_group *group, | |||
638 | if (atomic_read(&group->inotify_data.user->inotify_watches) >= inotify_max_user_watches) | 636 | if (atomic_read(&group->inotify_data.user->inotify_watches) >= inotify_max_user_watches) |
639 | goto out_err; | 637 | goto out_err; |
640 | 638 | ||
641 | ret = inotify_add_to_idr(idr, idr_lock, &group->inotify_data.last_wd, | 639 | ret = inotify_add_to_idr(idr, idr_lock, tmp_i_mark); |
642 | tmp_i_mark); | ||
643 | if (ret) | 640 | if (ret) |
644 | goto out_err; | 641 | goto out_err; |
645 | 642 | ||
@@ -697,7 +694,6 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events) | |||
697 | 694 | ||
698 | spin_lock_init(&group->inotify_data.idr_lock); | 695 | spin_lock_init(&group->inotify_data.idr_lock); |
699 | idr_init(&group->inotify_data.idr); | 696 | idr_init(&group->inotify_data.idr); |
700 | group->inotify_data.last_wd = 0; | ||
701 | group->inotify_data.user = get_current_user(); | 697 | group->inotify_data.user = get_current_user(); |
702 | 698 | ||
703 | if (atomic_inc_return(&group->inotify_data.user->inotify_devs) > | 699 | if (atomic_inc_return(&group->inotify_data.user->inotify_devs) > |
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index eeac97bb3bfa..b3fdd1a323d6 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c | |||
@@ -1498,10 +1498,8 @@ leave: | |||
1498 | 1498 | ||
1499 | dlm_put(dlm); | 1499 | dlm_put(dlm); |
1500 | if (ret < 0) { | 1500 | if (ret < 0) { |
1501 | if (buf) | 1501 | kfree(buf); |
1502 | kfree(buf); | 1502 | kfree(item); |
1503 | if (item) | ||
1504 | kfree(item); | ||
1505 | mlog_errno(ret); | 1503 | mlog_errno(ret); |
1506 | } | 1504 | } |
1507 | 1505 | ||
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 752f0b26221d..0c60ef2d8056 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c | |||
@@ -101,13 +101,6 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, | |||
101 | if (!S_ISDIR(inode->i_mode)) | 101 | if (!S_ISDIR(inode->i_mode)) |
102 | flags &= ~OCFS2_DIRSYNC_FL; | 102 | flags &= ~OCFS2_DIRSYNC_FL; |
103 | 103 | ||
104 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
105 | if (IS_ERR(handle)) { | ||
106 | status = PTR_ERR(handle); | ||
107 | mlog_errno(status); | ||
108 | goto bail_unlock; | ||
109 | } | ||
110 | |||
111 | oldflags = ocfs2_inode->ip_attr; | 104 | oldflags = ocfs2_inode->ip_attr; |
112 | flags = flags & mask; | 105 | flags = flags & mask; |
113 | flags |= oldflags & ~mask; | 106 | flags |= oldflags & ~mask; |
@@ -120,7 +113,14 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, | |||
120 | if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) & | 113 | if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) & |
121 | (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) { | 114 | (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) { |
122 | if (!capable(CAP_LINUX_IMMUTABLE)) | 115 | if (!capable(CAP_LINUX_IMMUTABLE)) |
123 | goto bail_commit; | 116 | goto bail_unlock; |
117 | } | ||
118 | |||
119 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
120 | if (IS_ERR(handle)) { | ||
121 | status = PTR_ERR(handle); | ||
122 | mlog_errno(status); | ||
123 | goto bail_unlock; | ||
124 | } | 124 | } |
125 | 125 | ||
126 | ocfs2_inode->ip_attr = flags; | 126 | ocfs2_inode->ip_attr = flags; |
@@ -130,8 +130,8 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, | |||
130 | if (status < 0) | 130 | if (status < 0) |
131 | mlog_errno(status); | 131 | mlog_errno(status); |
132 | 132 | ||
133 | bail_commit: | ||
134 | ocfs2_commit_trans(osb, handle); | 133 | ocfs2_commit_trans(osb, handle); |
134 | |||
135 | bail_unlock: | 135 | bail_unlock: |
136 | ocfs2_inode_unlock(inode, 1); | 136 | ocfs2_inode_unlock(inode, 1); |
137 | bail: | 137 | bail: |
@@ -706,8 +706,10 @@ int ocfs2_info_handle_freefrag(struct inode *inode, | |||
706 | 706 | ||
707 | o2info_set_request_filled(&oiff->iff_req); | 707 | o2info_set_request_filled(&oiff->iff_req); |
708 | 708 | ||
709 | if (o2info_to_user(*oiff, req)) | 709 | if (o2info_to_user(*oiff, req)) { |
710 | status = -EFAULT; | ||
710 | goto bail; | 711 | goto bail; |
712 | } | ||
711 | 713 | ||
712 | status = 0; | 714 | status = 0; |
713 | bail: | 715 | bail: |
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index 9f8dcadd9a50..f1fc172175b6 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c | |||
@@ -471,7 +471,7 @@ static int ocfs2_validate_and_adjust_move_goal(struct inode *inode, | |||
471 | int ret, goal_bit = 0; | 471 | int ret, goal_bit = 0; |
472 | 472 | ||
473 | struct buffer_head *gd_bh = NULL; | 473 | struct buffer_head *gd_bh = NULL; |
474 | struct ocfs2_group_desc *bg = NULL; | 474 | struct ocfs2_group_desc *bg; |
475 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 475 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
476 | int c_to_b = 1 << (osb->s_clustersize_bits - | 476 | int c_to_b = 1 << (osb->s_clustersize_bits - |
477 | inode->i_sb->s_blocksize_bits); | 477 | inode->i_sb->s_blocksize_bits); |
@@ -482,13 +482,6 @@ static int ocfs2_validate_and_adjust_move_goal(struct inode *inode, | |||
482 | range->me_goal = ocfs2_block_to_cluster_start(inode->i_sb, | 482 | range->me_goal = ocfs2_block_to_cluster_start(inode->i_sb, |
483 | range->me_goal); | 483 | range->me_goal); |
484 | /* | 484 | /* |
485 | * moving goal is not allowd to start with a group desc blok(#0 blk) | ||
486 | * let's compromise to the latter cluster. | ||
487 | */ | ||
488 | if (range->me_goal == le64_to_cpu(bg->bg_blkno)) | ||
489 | range->me_goal += c_to_b; | ||
490 | |||
491 | /* | ||
492 | * validate goal sits within global_bitmap, and return the victim | 485 | * validate goal sits within global_bitmap, and return the victim |
493 | * group desc | 486 | * group desc |
494 | */ | 487 | */ |
@@ -502,6 +495,13 @@ static int ocfs2_validate_and_adjust_move_goal(struct inode *inode, | |||
502 | bg = (struct ocfs2_group_desc *)gd_bh->b_data; | 495 | bg = (struct ocfs2_group_desc *)gd_bh->b_data; |
503 | 496 | ||
504 | /* | 497 | /* |
498 | * moving goal is not allowd to start with a group desc blok(#0 blk) | ||
499 | * let's compromise to the latter cluster. | ||
500 | */ | ||
501 | if (range->me_goal == le64_to_cpu(bg->bg_blkno)) | ||
502 | range->me_goal += c_to_b; | ||
503 | |||
504 | /* | ||
505 | * movement is not gonna cross two groups. | 505 | * movement is not gonna cross two groups. |
506 | */ | 506 | */ |
507 | if ((le16_to_cpu(bg->bg_bits) - goal_bit) * osb->s_clustersize < | 507 | if ((le16_to_cpu(bg->bg_bits) - goal_bit) * osb->s_clustersize < |
@@ -1057,42 +1057,40 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp) | |||
1057 | 1057 | ||
1058 | struct inode *inode = file_inode(filp); | 1058 | struct inode *inode = file_inode(filp); |
1059 | struct ocfs2_move_extents range; | 1059 | struct ocfs2_move_extents range; |
1060 | struct ocfs2_move_extents_context *context = NULL; | 1060 | struct ocfs2_move_extents_context *context; |
1061 | |||
1062 | if (!argp) | ||
1063 | return -EINVAL; | ||
1061 | 1064 | ||
1062 | status = mnt_want_write_file(filp); | 1065 | status = mnt_want_write_file(filp); |
1063 | if (status) | 1066 | if (status) |
1064 | return status; | 1067 | return status; |
1065 | 1068 | ||
1066 | if ((!S_ISREG(inode->i_mode)) || !(filp->f_mode & FMODE_WRITE)) | 1069 | if ((!S_ISREG(inode->i_mode)) || !(filp->f_mode & FMODE_WRITE)) |
1067 | goto out; | 1070 | goto out_drop; |
1068 | 1071 | ||
1069 | if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) { | 1072 | if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) { |
1070 | status = -EPERM; | 1073 | status = -EPERM; |
1071 | goto out; | 1074 | goto out_drop; |
1072 | } | 1075 | } |
1073 | 1076 | ||
1074 | context = kzalloc(sizeof(struct ocfs2_move_extents_context), GFP_NOFS); | 1077 | context = kzalloc(sizeof(struct ocfs2_move_extents_context), GFP_NOFS); |
1075 | if (!context) { | 1078 | if (!context) { |
1076 | status = -ENOMEM; | 1079 | status = -ENOMEM; |
1077 | mlog_errno(status); | 1080 | mlog_errno(status); |
1078 | goto out; | 1081 | goto out_drop; |
1079 | } | 1082 | } |
1080 | 1083 | ||
1081 | context->inode = inode; | 1084 | context->inode = inode; |
1082 | context->file = filp; | 1085 | context->file = filp; |
1083 | 1086 | ||
1084 | if (argp) { | 1087 | if (copy_from_user(&range, argp, sizeof(range))) { |
1085 | if (copy_from_user(&range, argp, sizeof(range))) { | 1088 | status = -EFAULT; |
1086 | status = -EFAULT; | 1089 | goto out_free; |
1087 | goto out; | ||
1088 | } | ||
1089 | } else { | ||
1090 | status = -EINVAL; | ||
1091 | goto out; | ||
1092 | } | 1090 | } |
1093 | 1091 | ||
1094 | if (range.me_start > i_size_read(inode)) | 1092 | if (range.me_start > i_size_read(inode)) |
1095 | goto out; | 1093 | goto out_free; |
1096 | 1094 | ||
1097 | if (range.me_start + range.me_len > i_size_read(inode)) | 1095 | if (range.me_start + range.me_len > i_size_read(inode)) |
1098 | range.me_len = i_size_read(inode) - range.me_start; | 1096 | range.me_len = i_size_read(inode) - range.me_start; |
@@ -1124,25 +1122,24 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp) | |||
1124 | 1122 | ||
1125 | status = ocfs2_validate_and_adjust_move_goal(inode, &range); | 1123 | status = ocfs2_validate_and_adjust_move_goal(inode, &range); |
1126 | if (status) | 1124 | if (status) |
1127 | goto out; | 1125 | goto out_copy; |
1128 | } | 1126 | } |
1129 | 1127 | ||
1130 | status = ocfs2_move_extents(context); | 1128 | status = ocfs2_move_extents(context); |
1131 | if (status) | 1129 | if (status) |
1132 | mlog_errno(status); | 1130 | mlog_errno(status); |
1133 | out: | 1131 | out_copy: |
1134 | /* | 1132 | /* |
1135 | * movement/defragmentation may end up being partially completed, | 1133 | * movement/defragmentation may end up being partially completed, |
1136 | * that's the reason why we need to return userspace the finished | 1134 | * that's the reason why we need to return userspace the finished |
1137 | * length and new_offset even if failure happens somewhere. | 1135 | * length and new_offset even if failure happens somewhere. |
1138 | */ | 1136 | */ |
1139 | if (argp) { | 1137 | if (copy_to_user(argp, &range, sizeof(range))) |
1140 | if (copy_to_user(argp, &range, sizeof(range))) | 1138 | status = -EFAULT; |
1141 | status = -EFAULT; | ||
1142 | } | ||
1143 | 1139 | ||
1140 | out_free: | ||
1144 | kfree(context); | 1141 | kfree(context); |
1145 | 1142 | out_drop: | |
1146 | mnt_drop_write_file(filp); | 1143 | mnt_drop_write_file(filp); |
1147 | 1144 | ||
1148 | return status; | 1145 | return status; |
diff --git a/fs/proc/Makefile b/fs/proc/Makefile index 712f24db9600..ab30716584f5 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | obj-y += proc.o | 5 | obj-y += proc.o |
6 | 6 | ||
7 | proc-y := nommu.o task_nommu.o | 7 | proc-y := nommu.o task_nommu.o |
8 | proc-$(CONFIG_MMU) := mmu.o task_mmu.o | 8 | proc-$(CONFIG_MMU) := task_mmu.o |
9 | 9 | ||
10 | proc-y += inode.o root.o base.o generic.o array.o \ | 10 | proc-y += inode.o root.o base.o generic.o array.o \ |
11 | fd.o | 11 | fd.o |
diff --git a/fs/proc/array.c b/fs/proc/array.c index f7ed9ee46eb9..cbd0f1b324b9 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -143,6 +143,7 @@ static const char * const task_state_array[] = { | |||
143 | "x (dead)", /* 64 */ | 143 | "x (dead)", /* 64 */ |
144 | "K (wakekill)", /* 128 */ | 144 | "K (wakekill)", /* 128 */ |
145 | "W (waking)", /* 256 */ | 145 | "W (waking)", /* 256 */ |
146 | "P (parked)", /* 512 */ | ||
146 | }; | 147 | }; |
147 | 148 | ||
148 | static inline const char *get_task_state(struct task_struct *tsk) | 149 | static inline const char *get_task_state(struct task_struct *tsk) |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 69078c7cef1f..a19308604145 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -86,6 +86,7 @@ | |||
86 | #include <linux/fs_struct.h> | 86 | #include <linux/fs_struct.h> |
87 | #include <linux/slab.h> | 87 | #include <linux/slab.h> |
88 | #include <linux/flex_array.h> | 88 | #include <linux/flex_array.h> |
89 | #include <linux/posix-timers.h> | ||
89 | #ifdef CONFIG_HARDWALL | 90 | #ifdef CONFIG_HARDWALL |
90 | #include <asm/hardwall.h> | 91 | #include <asm/hardwall.h> |
91 | #endif | 92 | #endif |
@@ -2013,6 +2014,102 @@ static const struct file_operations proc_map_files_operations = { | |||
2013 | .llseek = default_llseek, | 2014 | .llseek = default_llseek, |
2014 | }; | 2015 | }; |
2015 | 2016 | ||
2017 | struct timers_private { | ||
2018 | struct pid *pid; | ||
2019 | struct task_struct *task; | ||
2020 | struct sighand_struct *sighand; | ||
2021 | struct pid_namespace *ns; | ||
2022 | unsigned long flags; | ||
2023 | }; | ||
2024 | |||
2025 | static void *timers_start(struct seq_file *m, loff_t *pos) | ||
2026 | { | ||
2027 | struct timers_private *tp = m->private; | ||
2028 | |||
2029 | tp->task = get_pid_task(tp->pid, PIDTYPE_PID); | ||
2030 | if (!tp->task) | ||
2031 | return ERR_PTR(-ESRCH); | ||
2032 | |||
2033 | tp->sighand = lock_task_sighand(tp->task, &tp->flags); | ||
2034 | if (!tp->sighand) | ||
2035 | return ERR_PTR(-ESRCH); | ||
2036 | |||
2037 | return seq_list_start(&tp->task->signal->posix_timers, *pos); | ||
2038 | } | ||
2039 | |||
2040 | static void *timers_next(struct seq_file *m, void *v, loff_t *pos) | ||
2041 | { | ||
2042 | struct timers_private *tp = m->private; | ||
2043 | return seq_list_next(v, &tp->task->signal->posix_timers, pos); | ||
2044 | } | ||
2045 | |||
2046 | static void timers_stop(struct seq_file *m, void *v) | ||
2047 | { | ||
2048 | struct timers_private *tp = m->private; | ||
2049 | |||
2050 | if (tp->sighand) { | ||
2051 | unlock_task_sighand(tp->task, &tp->flags); | ||
2052 | tp->sighand = NULL; | ||
2053 | } | ||
2054 | |||
2055 | if (tp->task) { | ||
2056 | put_task_struct(tp->task); | ||
2057 | tp->task = NULL; | ||
2058 | } | ||
2059 | } | ||
2060 | |||
2061 | static int show_timer(struct seq_file *m, void *v) | ||
2062 | { | ||
2063 | struct k_itimer *timer; | ||
2064 | struct timers_private *tp = m->private; | ||
2065 | int notify; | ||
2066 | static char *nstr[] = { | ||
2067 | [SIGEV_SIGNAL] = "signal", | ||
2068 | [SIGEV_NONE] = "none", | ||
2069 | [SIGEV_THREAD] = "thread", | ||
2070 | }; | ||
2071 | |||
2072 | timer = list_entry((struct list_head *)v, struct k_itimer, list); | ||
2073 | notify = timer->it_sigev_notify; | ||
2074 | |||
2075 | seq_printf(m, "ID: %d\n", timer->it_id); | ||
2076 | seq_printf(m, "signal: %d/%p\n", timer->sigq->info.si_signo, | ||
2077 | timer->sigq->info.si_value.sival_ptr); | ||
2078 | seq_printf(m, "notify: %s/%s.%d\n", | ||
2079 | nstr[notify & ~SIGEV_THREAD_ID], | ||
2080 | (notify & SIGEV_THREAD_ID) ? "tid" : "pid", | ||
2081 | pid_nr_ns(timer->it_pid, tp->ns)); | ||
2082 | |||
2083 | return 0; | ||
2084 | } | ||
2085 | |||
2086 | static const struct seq_operations proc_timers_seq_ops = { | ||
2087 | .start = timers_start, | ||
2088 | .next = timers_next, | ||
2089 | .stop = timers_stop, | ||
2090 | .show = show_timer, | ||
2091 | }; | ||
2092 | |||
2093 | static int proc_timers_open(struct inode *inode, struct file *file) | ||
2094 | { | ||
2095 | struct timers_private *tp; | ||
2096 | |||
2097 | tp = __seq_open_private(file, &proc_timers_seq_ops, | ||
2098 | sizeof(struct timers_private)); | ||
2099 | if (!tp) | ||
2100 | return -ENOMEM; | ||
2101 | |||
2102 | tp->pid = proc_pid(inode); | ||
2103 | tp->ns = inode->i_sb->s_fs_info; | ||
2104 | return 0; | ||
2105 | } | ||
2106 | |||
2107 | static const struct file_operations proc_timers_operations = { | ||
2108 | .open = proc_timers_open, | ||
2109 | .read = seq_read, | ||
2110 | .llseek = seq_lseek, | ||
2111 | .release = seq_release_private, | ||
2112 | }; | ||
2016 | #endif /* CONFIG_CHECKPOINT_RESTORE */ | 2113 | #endif /* CONFIG_CHECKPOINT_RESTORE */ |
2017 | 2114 | ||
2018 | static struct dentry *proc_pident_instantiate(struct inode *dir, | 2115 | static struct dentry *proc_pident_instantiate(struct inode *dir, |
@@ -2583,6 +2680,9 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2583 | REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), | 2680 | REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), |
2584 | REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), | 2681 | REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), |
2585 | #endif | 2682 | #endif |
2683 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
2684 | REG("timers", S_IRUGO, proc_timers_operations), | ||
2685 | #endif | ||
2586 | }; | 2686 | }; |
2587 | 2687 | ||
2588 | static int proc_tgid_base_readdir(struct file * filp, | 2688 | static int proc_tgid_base_readdir(struct file * filp, |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 85ff3a4598b3..75710357a517 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -30,24 +30,6 @@ extern int proc_net_init(void); | |||
30 | static inline int proc_net_init(void) { return 0; } | 30 | static inline int proc_net_init(void) { return 0; } |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | struct vmalloc_info { | ||
34 | unsigned long used; | ||
35 | unsigned long largest_chunk; | ||
36 | }; | ||
37 | |||
38 | #ifdef CONFIG_MMU | ||
39 | #define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START) | ||
40 | extern void get_vmalloc_info(struct vmalloc_info *vmi); | ||
41 | #else | ||
42 | |||
43 | #define VMALLOC_TOTAL 0UL | ||
44 | #define get_vmalloc_info(vmi) \ | ||
45 | do { \ | ||
46 | (vmi)->used = 0; \ | ||
47 | (vmi)->largest_chunk = 0; \ | ||
48 | } while(0) | ||
49 | #endif | ||
50 | |||
51 | extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns, | 33 | extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns, |
52 | struct pid *pid, struct task_struct *task); | 34 | struct pid *pid, struct task_struct *task); |
53 | extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns, | 35 | extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns, |
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index eda6f017f272..f6a13f489e30 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/capability.h> | 15 | #include <linux/capability.h> |
16 | #include <linux/elf.h> | 16 | #include <linux/elf.h> |
17 | #include <linux/elfcore.h> | 17 | #include <linux/elfcore.h> |
18 | #include <linux/notifier.h> | ||
18 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
19 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
20 | #include <linux/printk.h> | 21 | #include <linux/printk.h> |
@@ -564,7 +565,6 @@ static const struct file_operations proc_kcore_operations = { | |||
564 | .llseek = default_llseek, | 565 | .llseek = default_llseek, |
565 | }; | 566 | }; |
566 | 567 | ||
567 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
568 | /* just remember that we have to update kcore */ | 568 | /* just remember that we have to update kcore */ |
569 | static int __meminit kcore_callback(struct notifier_block *self, | 569 | static int __meminit kcore_callback(struct notifier_block *self, |
570 | unsigned long action, void *arg) | 570 | unsigned long action, void *arg) |
@@ -578,8 +578,11 @@ static int __meminit kcore_callback(struct notifier_block *self, | |||
578 | } | 578 | } |
579 | return NOTIFY_OK; | 579 | return NOTIFY_OK; |
580 | } | 580 | } |
581 | #endif | ||
582 | 581 | ||
582 | static struct notifier_block kcore_callback_nb __meminitdata = { | ||
583 | .notifier_call = kcore_callback, | ||
584 | .priority = 0, | ||
585 | }; | ||
583 | 586 | ||
584 | static struct kcore_list kcore_vmalloc; | 587 | static struct kcore_list kcore_vmalloc; |
585 | 588 | ||
@@ -631,7 +634,7 @@ static int __init proc_kcore_init(void) | |||
631 | add_modules_range(); | 634 | add_modules_range(); |
632 | /* Store direct-map area from physical memory map */ | 635 | /* Store direct-map area from physical memory map */ |
633 | kcore_update_ram(); | 636 | kcore_update_ram(); |
634 | hotplug_memory_notifier(kcore_callback, 0); | 637 | register_hotmemory_notifier(&kcore_callback_nb); |
635 | 638 | ||
636 | return 0; | 639 | return 0; |
637 | } | 640 | } |
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 1efaaa19c4f3..5aa847a603c0 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/swap.h> | 11 | #include <linux/swap.h> |
12 | #include <linux/vmstat.h> | 12 | #include <linux/vmstat.h> |
13 | #include <linux/atomic.h> | 13 | #include <linux/atomic.h> |
14 | #include <linux/vmalloc.h> | ||
14 | #include <asm/page.h> | 15 | #include <asm/page.h> |
15 | #include <asm/pgtable.h> | 16 | #include <asm/pgtable.h> |
16 | #include "internal.h" | 17 | #include "internal.h" |
diff --git a/fs/proc/mmu.c b/fs/proc/mmu.c deleted file mode 100644 index 8ae221dfd010..000000000000 --- a/fs/proc/mmu.c +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | /* mmu.c: mmu memory info files | ||
2 | * | ||
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/spinlock.h> | ||
12 | #include <linux/vmalloc.h> | ||
13 | #include <linux/highmem.h> | ||
14 | #include <asm/pgtable.h> | ||
15 | #include "internal.h" | ||
16 | |||
17 | void get_vmalloc_info(struct vmalloc_info *vmi) | ||
18 | { | ||
19 | struct vm_struct *vma; | ||
20 | unsigned long free_area_size; | ||
21 | unsigned long prev_end; | ||
22 | |||
23 | vmi->used = 0; | ||
24 | |||
25 | if (!vmlist) { | ||
26 | vmi->largest_chunk = VMALLOC_TOTAL; | ||
27 | } | ||
28 | else { | ||
29 | vmi->largest_chunk = 0; | ||
30 | |||
31 | prev_end = VMALLOC_START; | ||
32 | |||
33 | read_lock(&vmlist_lock); | ||
34 | |||
35 | for (vma = vmlist; vma; vma = vma->next) { | ||
36 | unsigned long addr = (unsigned long) vma->addr; | ||
37 | |||
38 | /* | ||
39 | * Some archs keep another range for modules in vmlist | ||
40 | */ | ||
41 | if (addr < VMALLOC_START) | ||
42 | continue; | ||
43 | if (addr >= VMALLOC_END) | ||
44 | break; | ||
45 | |||
46 | vmi->used += vma->size; | ||
47 | |||
48 | free_area_size = addr - prev_end; | ||
49 | if (vmi->largest_chunk < free_area_size) | ||
50 | vmi->largest_chunk = free_area_size; | ||
51 | |||
52 | prev_end = vma->size + addr; | ||
53 | } | ||
54 | |||
55 | if (VMALLOC_END - prev_end > vmi->largest_chunk) | ||
56 | vmi->largest_chunk = VMALLOC_END - prev_end; | ||
57 | |||
58 | read_unlock(&vmlist_lock); | ||
59 | } | ||
60 | } | ||
diff --git a/fs/read_write.c b/fs/read_write.c index e6ddc8dceb96..7a648911246b 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -128,7 +128,7 @@ EXPORT_SYMBOL(generic_file_llseek_size); | |||
128 | * | 128 | * |
129 | * This is a generic implemenation of ->llseek useable for all normal local | 129 | * This is a generic implemenation of ->llseek useable for all normal local |
130 | * filesystems. It just updates the file offset to the value specified by | 130 | * filesystems. It just updates the file offset to the value specified by |
131 | * @offset and @whence under i_mutex. | 131 | * @offset and @whence. |
132 | */ | 132 | */ |
133 | loff_t generic_file_llseek(struct file *file, loff_t offset, int whence) | 133 | loff_t generic_file_llseek(struct file *file, loff_t offset, int whence) |
134 | { | 134 | { |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e14512678c9b..e8e0e71b29d5 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -165,21 +165,8 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | |||
165 | if (unlikely(!sd)) | 165 | if (unlikely(!sd)) |
166 | return NULL; | 166 | return NULL; |
167 | 167 | ||
168 | while (1) { | 168 | if (!atomic_inc_unless_negative(&sd->s_active)) |
169 | int v, t; | 169 | return NULL; |
170 | |||
171 | v = atomic_read(&sd->s_active); | ||
172 | if (unlikely(v < 0)) | ||
173 | return NULL; | ||
174 | |||
175 | t = atomic_cmpxchg(&sd->s_active, v, v + 1); | ||
176 | if (likely(t == v)) | ||
177 | break; | ||
178 | if (t < 0) | ||
179 | return NULL; | ||
180 | |||
181 | cpu_relax(); | ||
182 | } | ||
183 | 170 | ||
184 | if (likely(!ignore_lockdep(sd))) | 171 | if (likely(!ignore_lockdep(sd))) |
185 | rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_); | 172 | rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_); |
@@ -281,6 +268,10 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) | |||
281 | */ | 268 | */ |
282 | parent_sd = sd->s_parent; | 269 | parent_sd = sd->s_parent; |
283 | 270 | ||
271 | WARN(!(sd->s_flags & SYSFS_FLAG_REMOVED), | ||
272 | "sysfs: free using entry: %s/%s\n", | ||
273 | parent_sd ? parent_sd->s_name : "", sd->s_name); | ||
274 | |||
284 | if (sysfs_type(sd) == SYSFS_KOBJ_LINK) | 275 | if (sysfs_type(sd) == SYSFS_KOBJ_LINK) |
285 | sysfs_put(sd->s_symlink.target_sd); | 276 | sysfs_put(sd->s_symlink.target_sd); |
286 | if (sysfs_type(sd) & SYSFS_COPY_NAME) | 277 | if (sysfs_type(sd) & SYSFS_COPY_NAME) |
@@ -399,7 +390,7 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | |||
399 | 390 | ||
400 | sd->s_name = name; | 391 | sd->s_name = name; |
401 | sd->s_mode = mode; | 392 | sd->s_mode = mode; |
402 | sd->s_flags = type; | 393 | sd->s_flags = type | SYSFS_FLAG_REMOVED; |
403 | 394 | ||
404 | return sd; | 395 | return sd; |
405 | 396 | ||
@@ -479,6 +470,9 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
479 | ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; | 470 | ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; |
480 | } | 471 | } |
481 | 472 | ||
473 | /* Mark the entry added into directory tree */ | ||
474 | sd->s_flags &= ~SYSFS_FLAG_REMOVED; | ||
475 | |||
482 | return 0; | 476 | return 0; |
483 | } | 477 | } |
484 | 478 | ||
@@ -1012,6 +1006,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
1012 | enum kobj_ns_type type; | 1006 | enum kobj_ns_type type; |
1013 | const void *ns; | 1007 | const void *ns; |
1014 | ino_t ino; | 1008 | ino_t ino; |
1009 | loff_t off; | ||
1015 | 1010 | ||
1016 | type = sysfs_ns_type(parent_sd); | 1011 | type = sysfs_ns_type(parent_sd); |
1017 | ns = sysfs_info(dentry->d_sb)->ns[type]; | 1012 | ns = sysfs_info(dentry->d_sb)->ns[type]; |
@@ -1034,6 +1029,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
1034 | return 0; | 1029 | return 0; |
1035 | } | 1030 | } |
1036 | mutex_lock(&sysfs_mutex); | 1031 | mutex_lock(&sysfs_mutex); |
1032 | off = filp->f_pos; | ||
1037 | for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos); | 1033 | for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos); |
1038 | pos; | 1034 | pos; |
1039 | pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) { | 1035 | pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) { |
@@ -1045,19 +1041,24 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
1045 | len = strlen(name); | 1041 | len = strlen(name); |
1046 | ino = pos->s_ino; | 1042 | ino = pos->s_ino; |
1047 | type = dt_type(pos); | 1043 | type = dt_type(pos); |
1048 | filp->f_pos = pos->s_hash; | 1044 | off = filp->f_pos = pos->s_hash; |
1049 | filp->private_data = sysfs_get(pos); | 1045 | filp->private_data = sysfs_get(pos); |
1050 | 1046 | ||
1051 | mutex_unlock(&sysfs_mutex); | 1047 | mutex_unlock(&sysfs_mutex); |
1052 | ret = filldir(dirent, name, len, filp->f_pos, ino, type); | 1048 | ret = filldir(dirent, name, len, off, ino, type); |
1053 | mutex_lock(&sysfs_mutex); | 1049 | mutex_lock(&sysfs_mutex); |
1054 | if (ret < 0) | 1050 | if (ret < 0) |
1055 | break; | 1051 | break; |
1056 | } | 1052 | } |
1057 | mutex_unlock(&sysfs_mutex); | 1053 | mutex_unlock(&sysfs_mutex); |
1058 | if ((filp->f_pos > 1) && !pos) { /* EOF */ | 1054 | |
1059 | filp->f_pos = INT_MAX; | 1055 | /* don't reference last entry if its refcount is dropped */ |
1056 | if (!pos) { | ||
1060 | filp->private_data = NULL; | 1057 | filp->private_data = NULL; |
1058 | |||
1059 | /* EOF and not changed as 0 or 1 in read/write path */ | ||
1060 | if (off == filp->f_pos && off > 1) | ||
1061 | filp->f_pos = INT_MAX; | ||
1061 | } | 1062 | } |
1062 | return 0; | 1063 | return 0; |
1063 | } | 1064 | } |
diff --git a/fs/ufs/util.c b/fs/ufs/util.c index 95425b59ce0a..b6c2f94e041e 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c | |||
@@ -26,8 +26,7 @@ struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi, | |||
26 | count = size >> uspi->s_fshift; | 26 | count = size >> uspi->s_fshift; |
27 | if (count > UFS_MAXFRAG) | 27 | if (count > UFS_MAXFRAG) |
28 | return NULL; | 28 | return NULL; |
29 | ubh = (struct ufs_buffer_head *) | 29 | ubh = kmalloc (sizeof (struct ufs_buffer_head), GFP_NOFS); |
30 | kmalloc (sizeof (struct ufs_buffer_head), GFP_NOFS); | ||
31 | if (!ubh) | 30 | if (!ubh) |
32 | return NULL; | 31 | return NULL; |
33 | ubh->fragment = fragment; | 32 | ubh->fragment = fragment; |