From 9b87a519169800ab6b9becbaf51051ffb006ddb9 Mon Sep 17 00:00:00 2001 From: Steven Cole Date: Mon, 12 May 2003 07:31:01 -0700 Subject: [PATCH] more potentially undefined preprocessor symbols Here are three more fixes which I missed in the previous patch. --- include/linux/smp_lock.h | 2 +- include/linux/tpqic02.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h index 5a0b83a677d9..80fbd56eb3e4 100644 --- a/include/linux/smp_lock.h +++ b/include/linux/smp_lock.h @@ -5,7 +5,7 @@ #include #include -#if CONFIG_SMP || CONFIG_PREEMPT +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) extern spinlock_t kernel_flag; diff --git a/include/linux/tpqic02.h b/include/linux/tpqic02.h index 2972cb2f827c..f980d4ff01fe 100644 --- a/include/linux/tpqic02.h +++ b/include/linux/tpqic02.h @@ -12,7 +12,7 @@ #include -#if CONFIG_QIC02_TAPE || CONFIG_QIC02_TAPE_MODULE +#if defined(CONFIG_QIC02_TAPE) || defined(CONFIG_QIC02_TAPE_MODULE) /* need to have QIC02_TAPE_DRIVE and QIC02_TAPE_IFC expand to something */ #include -- cgit v1.2.3 From b7df5197b4b05adfa66563a5908d29ef74c0fc64 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 12 May 2003 09:10:05 -0700 Subject: [PATCH] implement module_arch_cleanup() in all architectures From: Rusty Russell , David Mosberger The patch below updates the other platforms with module_arch_cleanup(). Also, I added more debug output to kernel/module.c since I found it useful to be able to see the final section layout. --- arch/alpha/kernel/module.c | 5 +++++ arch/arm/kernel/module.c | 5 +++++ arch/i386/kernel/module.c | 4 ++++ arch/parisc/kernel/module.c | 4 ++++ arch/ppc/kernel/module.c | 4 ++++ arch/ppc64/kernel/module.c | 4 ++++ arch/s390/kernel/module.c | 4 ++++ arch/sparc/kernel/module.c | 4 ++++ arch/sparc64/kernel/module.c | 4 ++++ arch/v850/kernel/module.c | 5 +++++ arch/x86_64/kernel/module.c | 4 ++++ include/linux/moduleloader.h | 3 +++ kernel/module.c | 5 +++++ 13 files changed, 55 insertions(+) (limited to 'include/linux') diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c index f444a94eb965..425928769c1d 100644 --- a/arch/alpha/kernel/module.c +++ b/arch/alpha/kernel/module.c @@ -300,3 +300,8 @@ module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, { return 0; } + +void +module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index c79822e3bb88..6d1f4a8d1426 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -159,3 +159,8 @@ module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, { return 0; } + +void +module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c index 463a2c7e0acc..e8258ad35860 100644 --- a/arch/i386/kernel/module.c +++ b/arch/i386/kernel/module.c @@ -123,3 +123,7 @@ int module_finalize(const Elf_Ehdr *hdr, } return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 703991db6276..936eba6c6b99 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -568,3 +568,7 @@ int module_finalize(const Elf_Ehdr *hdr, #endif return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/ppc/kernel/module.c b/arch/ppc/kernel/module.c index e9e586cb0718..d263eacc0625 100644 --- a/arch/ppc/kernel/module.c +++ b/arch/ppc/kernel/module.c @@ -269,3 +269,7 @@ int module_finalize(const Elf_Ehdr *hdr, { return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/ppc64/kernel/module.c b/arch/ppc64/kernel/module.c index 7b27cdd29fa0..8847feb93b1a 100644 --- a/arch/ppc64/kernel/module.c +++ b/arch/ppc64/kernel/module.c @@ -384,3 +384,7 @@ int module_finalize(const Elf_Ehdr *hdr, me->num_exentries); return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index d79e7345264e..913a21691c2f 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -386,3 +386,7 @@ int module_finalize(const Elf_Ehdr *hdr, kfree(me->arch.syminfo); return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index 99183d7f24bf..1bde20c52683 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c @@ -145,3 +145,7 @@ int module_finalize(const Elf_Ehdr *hdr, { return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c index 9918b76c6280..c24ee5aeaa27 100644 --- a/arch/sparc64/kernel/module.c +++ b/arch/sparc64/kernel/module.c @@ -273,3 +273,7 @@ int module_finalize(const Elf_Ehdr *hdr, { return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c index eedced8ddb19..64aeb3e37c52 100644 --- a/arch/v850/kernel/module.c +++ b/arch/v850/kernel/module.c @@ -230,3 +230,8 @@ int apply_relocate_add (Elf32_Shdr *sechdrs, const char *strtab, return 0; } + +void +module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c index 9236b4b59c26..a82e56875f50 100644 --- a/arch/x86_64/kernel/module.c +++ b/arch/x86_64/kernel/module.c @@ -231,3 +231,7 @@ int module_finalize(const Elf_Ehdr *hdr, { return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h index 0c9e9a69f8ba..eb1033957486 100644 --- a/include/linux/moduleloader.h +++ b/include/linux/moduleloader.h @@ -41,4 +41,7 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod); +/* Any cleanup needed when module leaves. */ +void module_arch_cleanup(struct module *mod); + #endif diff --git a/kernel/module.c b/kernel/module.c index 06ff9328b30b..4a01db569ac8 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -910,6 +910,9 @@ static void free_module(struct module *mod) list_del(&mod->list); spin_unlock_irq(&modlist_lock); + /* Arch-specific cleanup. */ + module_arch_cleanup(mod); + /* Module unload stuff */ module_unload_free(mod); @@ -1276,6 +1279,7 @@ static struct module *load_module(void __user *umod, mod->module_init = ptr; /* Transfer each section which specifies SHF_ALLOC */ + DEBUGP("final section addresses:\n"); for (i = 0; i < hdr->e_shnum; i++) { void *dest; @@ -1293,6 +1297,7 @@ static struct module *load_module(void __user *umod, sechdrs[i].sh_size); /* Update sh_addr to point to copy in image. */ sechdrs[i].sh_addr = (unsigned long)dest; + DEBUGP("\t0x%lx %s\n", sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name); } /* Module has been moved. */ mod = (void *)sechdrs[modindex].sh_addr; -- cgit v1.2.3 From fb7f7773c0d96957ca48b07915252615ef66989e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 12 May 2003 09:10:13 -0700 Subject: [PATCH] remove devfs_register From: Christoph Hellwig Whee! devfs_register isn't used anymore in the whole tree and with it some other devfs crap. Kill it for good. --- fs/devfs/base.c | 94 +---------------------------------------- include/linux/devfs_fs_kernel.h | 27 ------------ 2 files changed, 1 insertion(+), 120 deletions(-) (limited to 'include/linux') diff --git a/fs/devfs/base.c b/fs/devfs/base.c index fa63dc1820a5..6ca2544a5322 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -752,6 +752,7 @@ # define DPRINTK(flag, format, args...) #endif +typedef struct devfs_entry *devfs_handle_t; struct directory_type { @@ -1424,98 +1425,6 @@ static void devfsd_notify (struct devfs_entry *de,unsigned short type) current->egid, &fs_info); } - -/** - * devfs_register - Register a device entry. - * @dir: The handle to the parent devfs directory entry. If this is %NULL the - * new name is relative to the root of the devfs. - * @name: The name of the entry. - * @flags: Must be 0 - * @major: The major number. Not needed for regular files. - * @minor: The minor number. Not needed for regular files. - * @mode: The default file mode. - * @ops: The &file_operations or &block_device_operations structure. - * This must not be externally deallocated. - * @info: An arbitrary pointer which will be written to the @private_data - * field of the &file structure passed to the device driver. You can set - * this to whatever you like, and change it once the file is opened (the next - * file opened will not see this change). - * - * On failure %NULL is returned. - */ - -devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, - unsigned int flags, - unsigned int major, unsigned int minor, - umode_t mode, void *ops, void *info) -{ - int err; - dev_t devnum = 0, dev = MKDEV(major, minor); - struct devfs_entry *de; - - /* we don't accept any flags anymore. prototype will change soon. */ - WARN_ON(flags); - WARN_ON(dir); - WARN_ON(!S_ISCHR(mode)); - - if (name == NULL) - { - PRINTK ("(): NULL name pointer\n"); - return NULL; - } - if (ops == NULL) - { - PRINTK ("(%s): NULL ops pointer\n", name); - return NULL; - } - if ( S_ISDIR (mode) ) - { - PRINTK ("(%s): creating directories is not allowed\n", name); - return NULL; - } - if ( S_ISLNK (mode) ) - { - PRINTK ("(%s): creating symlinks is not allowed\n", name); - return NULL; - } - if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL ) - { - PRINTK ("(%s): could not prepare leaf\n", name); - if (devnum) devfs_dealloc_devnum (mode, devnum); - return NULL; - } - if (S_ISCHR (mode)) { - de->u.cdev.dev = dev; - de->u.cdev.autogen = devnum != 0; - de->u.cdev.ops = ops; - } else if (S_ISBLK (mode)) { - de->u.bdev.dev = dev; - de->u.cdev.autogen = devnum != 0; - } else { - PRINTK ("(%s): illegal mode: %x\n", name, mode); - devfs_put (de); - devfs_put (dir); - return (NULL); - } - de->info = info; - de->inode.uid = 0; - de->inode.gid = 0; - err = _devfs_append_entry(dir, de, NULL); - if (err) - { - PRINTK ("(%s): could not append to parent, err: %d\n", name, err); - devfs_put (dir); - if (devnum) devfs_dealloc_devnum (mode, devnum); - return NULL; - } - DPRINTK (DEBUG_REGISTER, "(%s): de: %p dir: %p \"%s\" pp: %p\n", - name, de, dir, dir->name, dir->parent); - devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED); - devfs_put (dir); - return de; -} /* End Function devfs_register */ - - int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) { struct devfs_entry *dir = NULL, *de; @@ -1935,7 +1844,6 @@ static int __init devfs_setup (char *str) __setup("devfs=", devfs_setup); EXPORT_SYMBOL(devfs_put); -EXPORT_SYMBOL(devfs_register); EXPORT_SYMBOL(devfs_mk_symlink); EXPORT_SYMBOL(devfs_mk_dir); EXPORT_SYMBOL(devfs_remove); diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h index 34ebe93c6194..f12addd1daeb 100644 --- a/include/linux/devfs_fs_kernel.h +++ b/include/linux/devfs_fs_kernel.h @@ -11,20 +11,7 @@ #define DEVFS_SUPER_MAGIC 0x1373 -#define DEVFS_FL_NONE 0x000 /* This helps to make code more readable - no, it doesn't --hch */ -#define DEVFS_FL_DEFAULT DEVFS_FL_NONE - - -typedef struct devfs_entry * devfs_handle_t; - -struct gendisk; - #ifdef CONFIG_DEVFS_FS -extern devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, - unsigned int flags, - unsigned int major, unsigned int minor, - umode_t mode, void *ops, void *info); extern int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) __attribute__((format (printf, 3, 4))); extern int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) @@ -36,19 +23,8 @@ extern void devfs_remove(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern int devfs_register_tape(const char *name); extern void devfs_unregister_tape(int num); -extern void devfs_register_partition(struct gendisk *dev, int part); extern void mount_devfs_fs(void); #else /* CONFIG_DEVFS_FS */ -static inline devfs_handle_t devfs_register (devfs_handle_t dir, - const char *name, - unsigned int flags, - unsigned int major, - unsigned int minor, - umode_t mode, - void *ops, void *info) -{ - return NULL; -} static inline int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) { return 0; @@ -75,9 +51,6 @@ static inline int devfs_register_tape (const char *name) static inline void devfs_unregister_tape(int num) { } -static inline void devfs_register_partition(struct gendisk *dev, int part) -{ -} static inline void mount_devfs_fs (void) { return; -- cgit v1.2.3 From a3db5a33a37367163b9ad7b45c7b8378f82e3fb8 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 12 May 2003 09:10:30 -0700 Subject: [PATCH] fat cluster search speedup From: Bjorn Stenberg OGAWA Hirofumi This simple patch makes the linux fat filesystem driver use the next_cluster field in the fat_boot_fsinfo structure. This field is a hint where to start looking for free clusters. Using this field makes a big difference for disks connected over slow links such as USB 1.1. Finding the first free cluster on a 40gig fat-formatted usb disk can today take several minutes. This patch cuts it down to a fraction of a second. Also, commit the next_cluster search hint toand from the superblock in write_super/fill_super. --- fs/fat/inode.c | 1 + fs/fat/misc.c | 17 +++++++++++------ include/linux/msdos_fs.h | 3 +-- 3 files changed, 13 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 866edb62fad5..282c0c22db6f 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -897,6 +897,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, sbi->fsinfo_sector); } else { sbi->free_clusters = CF_LE_L(fsinfo->free_clusters); + sbi->prev_free = CF_LE_L(fsinfo->next_cluster); } brelse(fsinfo_bh); diff --git a/fs/fat/misc.c b/fs/fat/misc.c index f7043d09f086..6e3e86c8899b 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -74,6 +74,7 @@ void fat_clusters_flush(struct super_block *sb) MSDOS_SB(sb)->fsinfo_sector); } else { fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters); + fsinfo->next_cluster = CF_LE_L(MSDOS_SB(sb)->prev_free); mark_buffer_dirty(bh); } brelse(bh); @@ -130,19 +131,23 @@ int fat_add_cluster(struct inode *inode) unlock_fat(sb); return -ENOSPC; } - limit = MSDOS_SB(sb)->clusters; - for (count = 0; count < limit; count++) { - nr = ((count + MSDOS_SB(sb)->prev_free) % limit) + 2; + + limit = MSDOS_SB(sb)->clusters + 2; + nr = MSDOS_SB(sb)->prev_free + 1; + for (count = 0; count < MSDOS_SB(sb)->clusters; count++, nr++) { + nr = nr % limit; + if (nr < 2) + nr = 2; if (fat_access(sb, nr, -1) == FAT_ENT_FREE) break; } - if (count >= limit) { + if (count >= MSDOS_SB(sb)->clusters) { MSDOS_SB(sb)->free_clusters = 0; unlock_fat(sb); return -ENOSPC; } - - MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit; + MSDOS_SB(sb)->prev_free = nr; + fat_access(sb, nr, FAT_ENT_EOF); if (MSDOS_SB(sb)->free_clusters != -1) MSDOS_SB(sb)->free_clusters--; diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 2945cb406b64..bd09a8135e79 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -146,8 +146,7 @@ struct fat_boot_fsinfo { __u32 reserved1[120]; /* Nothing as far as I can tell */ __u32 signature2; /* 0x61417272L */ __u32 free_clusters; /* Free cluster count. -1 if unknown */ - __u32 next_cluster; /* Most recently allocated cluster. - * Unused under Linux. */ + __u32 next_cluster; /* Most recently allocated cluster */ __u32 reserved2[4]; }; -- cgit v1.2.3 From 281df9b372d682a93f1fb4bdd9756d7601d50e0e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 12 May 2003 09:11:06 -0700 Subject: [PATCH] export cpufreq_driver to fix oops in proc interface From: Zwane Mwaikambo The proc interface has no way of telling wether there is an active cpufreq driver or not. This means that if you don't have a cpufreq supported processor, this will oops in various possible places. --- drivers/cpufreq/proc_intf.c | 3 +++ include/linux/cpufreq.h | 3 +++ kernel/cpufreq.c | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c index 5845e3404085..253dab930b06 100644 --- a/drivers/cpufreq/proc_intf.c +++ b/drivers/cpufreq/proc_intf.c @@ -209,6 +209,9 @@ static int __init cpufreq_proc_init (void) { struct proc_dir_entry *entry = NULL; + if (!cpufreq_driver) + return -ENODEV; + /* are these acceptable values? */ entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR, &proc_root); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index e99b9c3c1d01..3dc9062bd414 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -311,4 +311,7 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu); #endif /* CONFIG_CPU_FREQ_TABLE */ +/* Currently exported only for the proc interface, remove when that goes */ +extern struct cpufreq_driver *cpufreq_driver; + #endif /* _LINUX_CPUFREQ_H */ diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c index 913e6b0f56fb..589bf0bf2093 100644 --- a/kernel/cpufreq.c +++ b/kernel/cpufreq.c @@ -29,9 +29,11 @@ * level driver of CPUFreq support, and its locking mutex. * cpu_max_freq is in kHz. */ -static struct cpufreq_driver *cpufreq_driver; +struct cpufreq_driver *cpufreq_driver; static DECLARE_MUTEX (cpufreq_driver_sem); +/* required for the proc interface, remove when that goes away */ +EXPORT_SYMBOL_GPL(cpufreq_driver); /** * Two notifier lists: the "policy" list is involved in the -- cgit v1.2.3 From b5c385359e6452bd63971a35a022e3f71f5246fe Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 12 May 2003 09:11:41 -0700 Subject: [PATCH] exit_mmap() TASK_SIZE fix exit_mmap() currently assumes that the exitting task used virtual address span TASK_SIZE. But on some platforms, TASK_SIZE is variable, based on current->mm. But exit_mmap() can be called from (say) procfs's call to mmput. In which case current->mm has nothing to do with the mm which is being put in mmput(). So rather than assuming that the mm which is being put is current->mm, we need to calculate the virtual span of the mm. Add a new per-arch macro MM_VM_SIZE() for that. Some platforms can currently go BUG over this (where?). sparc64 is safe because our TASK_SIZE is constant. Platforms such as ia64 should stick the VM extent inside of mm_struct, I'd suggest adding it to mm_context_t. 1) TASK_SIZE means what is valid for mmap()'s in the processes address space 2) MM_VM_SIZE means where things might be mapped for a MM, including private implementation-specific areas created by the kernel which the user cannot access --- include/linux/mm.h | 5 +++++ mm/mmap.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mm.h b/include/linux/mm.h index 6aa89d73f65b..51f5377ec8fc 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -23,8 +23,13 @@ extern int page_cluster; #include #include +#include #include +#ifndef MM_VM_SIZE +#define MM_VM_SIZE(mm) TASK_SIZE +#endif + /* * Linux kernel virtual memory manager primitives. * The idea being to have a "virtual" mm in the same way diff --git a/mm/mmap.c b/mm/mmap.c index c0582bf2256f..f773d3d429b1 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1442,7 +1442,7 @@ void exit_mmap(struct mm_struct *mm) vm_unacct_memory(nr_accounted); BUG_ON(mm->map_count); /* This is just debugging */ clear_page_tables(tlb, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD); - tlb_finish_mmu(tlb, 0, TASK_SIZE); + tlb_finish_mmu(tlb, 0, MM_VM_SIZE(mm)); vma = mm->mmap; mm->mmap = mm->mmap_cache = NULL; -- cgit v1.2.3 From 699155e3a63c395c1769769a06ad0284db7a95dd Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 12 May 2003 09:13:18 -0700 Subject: [PATCH] htree nfs fix Patch from "Theodore Ts'o" We now use 0x7ffffff as the EOF cookie, because Linux NFS stupidly interprets the cookie (which is supposed to be a bag of bits without necessarily any semantic value) as a signed 64 bit integer, and then converts it to a unsigned integer, and then blows up if it cannot be expressed be expressed as a 32-bit value!! In order to do this, we have to fold the hash value 0x7ffffff into the hash value 0x7ffffffe. This is relatively safe; the only time we will lose if the directory contains filenames that hash to both 0x7ffffffe and 0x7fffffff (under the original hash), and the last directory entry which hashes to 0x7ffffffe is at the end of a leaf block, and the first directory entry which hashes to 0x7fffffff is at the beginning of a leaf block. --- fs/ext3/dir.c | 6 +++--- fs/ext3/hash.c | 5 ++++- include/linux/ext3_fs.h | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 4e73022d7637..2b387b5649e1 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -439,7 +439,7 @@ static int ext3_dx_readdir(struct file * filp, filp->private_data = info; } - if (filp->f_pos == -1) + if (filp->f_pos == EXT3_HTREE_EOF) return 0; /* EOF */ /* Some one has messed with f_pos; reset the world */ @@ -479,7 +479,7 @@ static int ext3_dx_readdir(struct file * filp, if (ret < 0) return ret; if (ret == 0) { - filp->f_pos = -1; + filp->f_pos = EXT3_HTREE_EOF; break; } info->curr_node = rb_first(&info->root); @@ -494,7 +494,7 @@ static int ext3_dx_readdir(struct file * filp, info->curr_node = rb_next(info->curr_node); if (!info->curr_node) { if (info->next_hash == ~0) { - filp->f_pos = -1; + filp->f_pos = EXT3_HTREE_EOF; break; } info->curr_hash = info->next_hash; diff --git a/fs/ext3/hash.c b/fs/ext3/hash.c index 2025354b85de..d00d658b1cfb 100644 --- a/fs/ext3/hash.c +++ b/fs/ext3/hash.c @@ -209,7 +209,10 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) hinfo->hash = 0; return -1; } - hinfo->hash = hash & ~1; + hash = hash & ~1; + if (hash == (EXT3_HTREE_EOF << 1)) + hash = (EXT3_HTREE_EOF-1) << 1; + hinfo->hash = hash; hinfo->minor_hash = minor_hash; return 0; } diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index b3da32479e13..c2f36c9d8022 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -625,6 +625,8 @@ struct dx_hash_info u32 *seed; }; +#define EXT3_HTREE_EOF 0x7fffffff + #ifdef __KERNEL__ /* * Control parameters used by ext3_htree_next_block -- cgit v1.2.3