## Automatically generated incremental diff ## From: linux-2.5.70-bk1 ## To: linux-2.5.70-bk2 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.70-bk1/Documentation/filesystems/fat_cvf.txt linux-2.5.70-bk2/Documentation/filesystems/fat_cvf.txt --- linux-2.5.70-bk1/Documentation/filesystems/fat_cvf.txt 2003-05-26 18:00:44.000000000 -0700 +++ linux-2.5.70-bk2/Documentation/filesystems/fat_cvf.txt 1969-12-31 16:00:00.000000000 -0800 @@ -1,210 +0,0 @@ -This is the main documentation for the CVF-FAT filesystem extension. 18Nov1998 - - -Table of Contents: - -1. The idea of CVF-FAT -2. Restrictions -3. Mount options -4. Description of the CVF-FAT interface -5. CVF Modules - ------------------------------------------------------------------------------- - - -1. The idea of CVF-FAT ------------------------------------------------------------------------------- - -CVF-FAT is a FAT filesystem extension that provides a generic interface for -Compressed Volume Files in FAT partitions. Popular CVF software, for -example, are Microsoft's Doublespace/Drivespace and Stac's Stacker. -Using the CVF-FAT interface, it is possible to load a module that handles -all the low-level disk access that has to do with on-the-fly compression -and decompression. Any other part of FAT filesystem access is still handled -by the FAT, MSDOS or VFAT or even UMSDOS driver. - -CVF access works by redirecting certain low-level routines from the FAT -driver to a loadable, CVF-format specific module. This module must fake -a normal FAT filesystem to the FAT driver while doing all the extra stuff -like compression and decompression silently. - - -2. Restrictions ------------------------------------------------------------------------------- - -- BMAP problems - - CVF filesystems cannot do bmap. It's impossible in principle. Thus - all actions that require bmap do not work (swapping, writable mmapping). - Read-only mmapping works because the FAT driver has a hack for this - situation :) Well, writable mmapping should now work using the readpage - interface function which has been hacked into the FAT driver just for - CVF-FAT :) - -- attention, DOSEmu users - - You may have to unmount all CVF partitions before running DOSEmu depending - on your configuration. If DOSEmu is configured to use wholedisk or - partition access (this is often the case to let DOSEmu access - compressed partitions) there's a risk of destroying your compressed - partitions or crashing your system because of confused drivers. - - Note that it is always safe to redirect the compressed partitions with - lredir or emufs.sys. Refer to the DOSEmu documentation for details. - - -3. Mount options ------------------------------------------------------------------------------- - -The CVF-FAT extension currently adds the following options to the FAT -driver's standard options: - - cvf_format=xxx - Forces the driver to use the CVF module "xxx" instead of auto-detection. - Without this option, the CVF-FAT interface asks all currently loaded - CVF modules whether they recognize the CVF. Therefore, this option is - only necessary if the CVF format is not recognized correctly - because of bugs or incompatibilities in the CVF modules. (It skips - the detect_cvf call.) "xxx" may be the text "none" (without the quotes) - to inhibit using any of the loaded CVF modules, just in case a CVF - module insists on mounting plain FAT filesystems by misunderstanding. - "xxx" may also be the text "autoload", which has a special meaning for - a module loader, but does not skip auto-detection. - - If the kernel supports kmod, the cvf_format=xxx option also controls - on-demand CVF module loading. Without this option, nothing is loaded - on demand. With cvf_format=xxx, a module "xxx" is requested automatically - before mounting the compressed filesystem (unless "xxx" is "none"). In - case there is a difference between the CVF format name and the module - name, setup aliases in your modules configuration. If the string "xxx" - is "autoload", a non-existent module "cvf_autoload" is requested which - can be used together with a special modules configuration (alias and - pre-install statements) in order to load more than one CVF module, let - them detect automatically which kind of CVF is to be mounted, and only - keep the "right" module in memory. For examples please refer to the - dmsdos documentation (ftp and http addresses see below). - - cvf_options=yyy - Option string passed to the CVF module. I.e. only the "yyy" is passed - (without the quotes). The documentation for each CVF module should - explain it since it is interpreted only by the CVF module. Note that - the string must not contain a comma (",") - this would lead to - misinterpretation by the FAT driver, which would recognize the text - after a comma as a FAT driver option and might get confused or print - strange error messages. The documentation for the CVF module should - offer a different separation symbol, for example the dot "." or the - plus sign "+", which is only valid inside the string "yyy". - - -4. Description of the CVF-FAT interface ------------------------------------------------------------------------------- - -Assuming you want to write your own CVF module, you need to write a lot of -interface functions. Most of them are covered in the kernel documentation -you can find on the net, and thus won't be described here. They have been -marked with "[...]" :-) Take a look at include/linux/fat_cvf.h. - -struct cvf_format -{ int cvf_version; - char* cvf_version_text; - unsigned long int flags; - int (*detect_cvf) (struct super_block*sb); - int (*mount_cvf) (struct super_block*sb,char*options); - int (*unmount_cvf) (struct super_block*sb); - [...] - void (*zero_out_cluster) (struct inode*, int clusternr); -} - -This structure defines the capabilities of a CVF module. It must be filled -out completely by a CVF module. Consider it as a kind of form that is used -to introduce the module to the FAT/CVF-FAT driver. - -It contains... - - cvf_version: - A version id which must be unique. Choose one. - - cvf_version_text: - A human readable version string that should be one short word - describing the CVF format the module implements. This text is used - for the cvf_format option. This name must also be unique. - - flags: - Bit coded flags, currently only used for a readpage/mmap hack that - provides both mmap and readpage functionality. If CVF_USE_READPAGE - is set, mmap is set to generic_file_mmap and readpage is caught - and redirected to the cvf_readpage function. If it is not set, - readpage is set to generic_readpage and mmap is caught and redirected - to cvf_mmap. (If you want writable mmap use the readpage interface.) - - detect_cvf: - A function that is called to decide whether the filesystem is a CVF of - the type the module supports. The detect_cvf function must return 0 - for "NO, I DON'T KNOW THIS GARBAGE" or anything >0 for "YES, THIS IS - THE KIND OF CVF I SUPPORT". The function must maintain the module - usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning - and MOD_DEC_USE_COUNT at the end. The function *must not* assume that - successful recognition would lead to a call of the mount_cvf function - later. - - mount_cvf: - A function that sets up some values or initializes something additional - to what has to be done when a CVF is mounted. This is called at the - end of fat_read_super and must return 0 on success. Definitely, this - function must increment the module usage counter by MOD_INC_USE_COUNT. - This mount_cvf function is also responsible for interpreting a CVF - module specific option string (the "yyy" from the FAT mount option - "cvf_options=yyy") which cannot contain a comma (use for example the - dot "." as option separator symbol). - - unmount_cvf: - A function that is called when the filesystem is unmounted. Most likely - it only frees up some memory and calls MOD_DEC_USE_COUNT. The return - value might be ignored (it currently is ignored). - - [...]: - All other interface functions are "caught" FAT driver functions, i.e. - are executed by the FAT driver *instead* of the original FAT driver - functions. NULL means use the original FAT driver functions instead. - If you really want "no action", write a function that does nothing and - hang it in instead. - - zero_out_cluster: - The zero_out_cluster function is called when the fat driver wants to - zero out a (new) cluster. This is important for directories (mkdir). - If it is NULL, the FAT driver defaults to overwriting the whole - cluster with zeros. Note that clusternr is absolute, not relative - to the provided inode. - -Notes: - 1. The cvf_bmap function should be ignored. It really should never - get called from somewhere. I recommend redirecting it to a panic - or fatal error message so bugs show up immediately. - 2. The cvf_writepage function is ignored. This is because the fat - driver doesn't support it. This might change in future. I recommend - setting it to NULL (i.e use default). - -int register_cvf_format(struct cvf_format*cvf_format); - If you have just set up a variable containing the above structure, - call this function to introduce your CVF format to the FAT/CVF-FAT - driver. This is usually done in init_module. Be sure to check the - return value. Zero means success, everything else causes a kernel - message printed in the syslog describing the error that occurred. - Typical errors are: - - a module with the same version id is already registered or - - too many CVF formats. Hack fs/fat/cvf.c if you need more. - -int unregister_cvf_format(struct cvf_format*cvf_format); - This is usually called in cleanup_module. Return value =0 means - success. An error only occurs if you try to unregister a CVF format - that has not been previously registered. The code uses the version id - to distinguish the modules, so be sure to keep it unique. - -5. CVF Modules ------------------------------------------------------------------------------- - -Refer to the dmsdos module (the successor of the dmsdos filesystem) for a -sample implementation. It can currently be found at - - ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos/dmsdos-x.y.z.tgz - ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/dosfs/dmsdos-x.y.z.tgz - ftp://ftp.uni-stuttgart.de/pub/systems/linux/local/system/dmsdos-x.y.z.tgz - -(where x.y.z is to be replaced with the actual version number). Full -documentation about dmsdos is included in the dmsdos package, but can also -be found at - - http://fb9nt.uni-duisburg.de/mitarbeiter/gockel/software/dmsdos/index.html - http://www.yk.rim.or.jp/~takafumi/dmsdos/index.html (in Japanese). diff -urN linux-2.5.70-bk1/Makefile linux-2.5.70-bk2/Makefile --- linux-2.5.70-bk1/Makefile 2003-05-28 04:36:58.000000000 -0700 +++ linux-2.5.70-bk2/Makefile 2003-05-28 04:37:02.000000000 -0700 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 70 -EXTRAVERSION = -bk1 +EXTRAVERSION = -bk2 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -urN linux-2.5.70-bk1/arch/alpha/kernel/pci.c linux-2.5.70-bk2/arch/alpha/kernel/pci.c --- linux-2.5.70-bk1/arch/alpha/kernel/pci.c 2003-05-26 18:00:22.000000000 -0700 +++ linux-2.5.70-bk2/arch/alpha/kernel/pci.c 2003-05-28 04:37:02.000000000 -0700 @@ -102,7 +102,7 @@ { unsigned int class = dev->class >> 8; - if (class == PCI_CLASS_BRIDGE_ISA || class == PCI_CLASS_BRIDGE_ISA) { + if (class == PCI_CLASS_BRIDGE_ISA || class == PCI_CLASS_BRIDGE_EISA) { dev->dma_mask = MAX_ISA_DMA_ADDRESS - 1; isa_bridge = dev; } diff -urN linux-2.5.70-bk1/arch/alpha/kernel/ptrace.c linux-2.5.70-bk2/arch/alpha/kernel/ptrace.c --- linux-2.5.70-bk1/arch/alpha/kernel/ptrace.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.70-bk2/arch/alpha/kernel/ptrace.c 2003-05-28 04:37:02.000000000 -0700 @@ -366,8 +366,8 @@ ret = -EIO; if ((unsigned long) data > _NSIG) break; - /* Set single stepping. */ - ptrace_set_bpt(child); + /* Mark single stepping. */ + child->thread_info->bpt_nsaved = -1; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); wake_up_process(child); child->exit_code = data; diff -urN linux-2.5.70-bk1/arch/alpha/kernel/signal.c linux-2.5.70-bk2/arch/alpha/kernel/signal.c --- linux-2.5.70-bk1/arch/alpha/kernel/signal.c 2003-05-26 18:00:39.000000000 -0700 +++ linux-2.5.70-bk2/arch/alpha/kernel/signal.c 2003-05-28 04:37:02.000000000 -0700 @@ -619,7 +619,10 @@ if (!oldset) oldset = ¤t->blocked; + /* This lets the debugger run, ... */ signr = get_signal_to_deliver(&info, regs, NULL); + /* ... so re-check the single stepping. */ + single_stepping |= ptrace_cancel_bpt(current); if (signr > 0) { /* Whee! Actually deliver the signal. */ diff -urN linux-2.5.70-bk1/arch/alpha/kernel/smp.c linux-2.5.70-bk2/arch/alpha/kernel/smp.c --- linux-2.5.70-bk1/arch/alpha/kernel/smp.c 2003-05-26 18:00:27.000000000 -0700 +++ linux-2.5.70-bk2/arch/alpha/kernel/smp.c 2003-05-28 04:37:02.000000000 -0700 @@ -417,12 +417,7 @@ /* Don't care about the contents of regs since we'll never reschedule the forked task. */ struct pt_regs regs; - int pid; - pid = do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); - if (pid < 0) - return NULL; - - return find_task_by_pid (pid); + return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); } /* @@ -441,9 +436,11 @@ wish. We can't use kernel_thread since we must avoid rescheduling the child. */ idle = fork_by_hand(); - if (!idle) + if (IS_ERR(idle)) panic("failed fork for CPU %d", cpuid); + wake_up_forked_process(idle); + init_idle(idle, cpuid); unhash_process(idle); diff -urN linux-2.5.70-bk1/arch/m68knommu/platform/68VZ328/de2/config.c linux-2.5.70-bk2/arch/m68knommu/platform/68VZ328/de2/config.c --- linux-2.5.70-bk1/arch/m68knommu/platform/68VZ328/de2/config.c 2003-05-26 18:00:26.000000000 -0700 +++ linux-2.5.70-bk2/arch/m68knommu/platform/68VZ328/de2/config.c 2003-05-28 04:37:02.000000000 -0700 @@ -118,7 +118,7 @@ static void init_hardware(void) { -#if CONFIG_DIRECT_IO_ACCESS +#ifdef CONFIG_DIRECT_IO_ACCESS SCR = 0x10; /* allow user access to internal registers */ #endif diff -urN linux-2.5.70-bk1/arch/v850/as85ep1-rom.ld linux-2.5.70-bk2/arch/v850/as85ep1-rom.ld --- linux-2.5.70-bk1/arch/v850/as85ep1-rom.ld 2003-05-26 18:00:38.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/as85ep1-rom.ld 2003-05-28 04:37:02.000000000 -0700 @@ -1,9 +1,6 @@ /* Linker script for the NEC AS85EP1 V850E evaluation board (CONFIG_V850E_AS85EP1), with kernel in ROM (CONFIG_ROM_KERNEL). */ -/* Note, all symbols are prefixed with an extra `_' for compatibility with - the existing linux sources. */ - MEMORY { /* 4MB of flash ROM. */ ROM : ORIGIN = 0, LENGTH = 0x00400000 @@ -12,7 +9,7 @@ SRAM : ORIGIN = 0x00400000, LENGTH = 0x00100000 /* About 58MB of DRAM. This can actually be at one of two - positions, determined by jump JP3; we have to use the first + positions, determined by jumper JP3; we have to use the first position because the second is partially out of processor instruction addressing range (though in the second position there's actually 64MB available). */ diff -urN linux-2.5.70-bk1/arch/v850/kernel/entry.S linux-2.5.70-bk2/arch/v850/kernel/entry.S --- linux-2.5.70-bk1/arch/v850/kernel/entry.S 2003-05-26 18:00:57.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/entry.S 2003-05-28 04:37:02.000000000 -0700 @@ -29,28 +29,28 @@ #define CSYM C_SYMBOL_NAME -/* The offset of the struct pt_regs in a `state save frame' on the stack. */ +/* The offset of the struct pt_regs in a state-save-frame on the stack. */ #define PTO STATE_SAVE_PT_OFFSET -/* Save argument registers to the struct pt_regs pointed to by EP. */ +/* Save argument registers to the state-save-frame pointed to by EP. */ #define SAVE_ARG_REGS \ sst.w r6, PTO+PT_GPR(6)[ep]; \ sst.w r7, PTO+PT_GPR(7)[ep]; \ sst.w r8, PTO+PT_GPR(8)[ep]; \ sst.w r9, PTO+PT_GPR(9)[ep] -/* Restore argument registers from the struct pt_regs pointed to by EP. */ +/* Restore argument registers from the state-save-frame pointed to by EP. */ #define RESTORE_ARG_REGS \ sld.w PTO+PT_GPR(6)[ep], r6; \ sld.w PTO+PT_GPR(7)[ep], r7; \ sld.w PTO+PT_GPR(8)[ep], r8; \ sld.w PTO+PT_GPR(9)[ep], r9 -/* Save value return registers to the struct pt_regs pointed to by EP. */ +/* Save value return registers to the state-save-frame pointed to by EP. */ #define SAVE_RVAL_REGS \ sst.w r10, PTO+PT_GPR(10)[ep]; \ sst.w r11, PTO+PT_GPR(11)[ep] -/* Restore value return registers from the struct pt_regs pointed to by EP. */ +/* Restore value return registers from the state-save-frame pointed to by EP. */ #define RESTORE_RVAL_REGS \ sld.w PTO+PT_GPR(10)[ep], r10; \ sld.w PTO+PT_GPR(11)[ep], r11 @@ -81,13 +81,13 @@ sld.w PTO+PT_GPR(18)[ep], r18; \ sld.w PTO+PT_GPR(19)[ep], r19 -/* Save `call clobbered' registers to the struct pt_regs pointed to by EP. */ +/* Save `call clobbered' registers to the state-save-frame pointed to by EP. */ #define SAVE_CALL_CLOBBERED_REGS \ SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \ SAVE_ARG_REGS; \ SAVE_RVAL_REGS; \ SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL -/* Restore `call clobbered' registers from the struct pt_regs pointed to +/* Restore `call clobbered' registers from the state-save-frame pointed to by EP. */ #define RESTORE_CALL_CLOBBERED_REGS \ RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \ @@ -96,19 +96,19 @@ RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL /* Save `call clobbered' registers except for the return-value registers - to the struct pt_regs pointed to by EP. */ + to the state-save-frame pointed to by EP. */ #define SAVE_CALL_CLOBBERED_REGS_NO_RVAL \ SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \ SAVE_ARG_REGS; \ SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL /* Restore `call clobbered' registers except for the return-value registers - from the struct pt_regs pointed to by EP. */ + from the state-save-frame pointed to by EP. */ #define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL \ RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \ RESTORE_ARG_REGS; \ RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL -/* Save `call saved' registers to the struct pt_regs pointed to by EP. */ +/* Save `call saved' registers to the state-save-frame pointed to by EP. */ #define SAVE_CALL_SAVED_REGS \ sst.w r2, PTO+PT_GPR(2)[ep]; \ sst.w r20, PTO+PT_GPR(20)[ep]; \ @@ -121,7 +121,7 @@ sst.w r27, PTO+PT_GPR(27)[ep]; \ sst.w r28, PTO+PT_GPR(28)[ep]; \ sst.w r29, PTO+PT_GPR(29)[ep] -/* Restore `call saved' registers from the struct pt_regs pointed to by EP. */ +/* Restore `call saved' registers from the state-save-frame pointed to by EP. */ #define RESTORE_CALL_SAVED_REGS \ sld.w PTO+PT_GPR(2)[ep], r2; \ sld.w PTO+PT_GPR(20)[ep], r20; \ @@ -136,12 +136,12 @@ sld.w PTO+PT_GPR(29)[ep], r29 -/* Save the PC stored in the special register SAVEREG to the struct pt_regs +/* Save the PC stored in the special register SAVEREG to the state-save-frame pointed to by EP. r19 is clobbered. */ #define SAVE_PC(savereg) \ stsr SR_ ## savereg, r19; \ sst.w r19, PTO+PT_PC[ep] -/* Restore the PC from the struct pt_regs pointed to by EP, to the special +/* Restore the PC from the state-save-frame pointed to by EP, to the special register SAVEREG. LP is clobbered (it is used as a scratch register because the POP_STATE macro restores it, and this macro is usually used inside POP_STATE). */ @@ -149,11 +149,11 @@ sld.w PTO+PT_PC[ep], lp; \ ldsr lp, SR_ ## savereg /* Save the PSW register stored in the special register SAVREG to the - struct pt_regs pointed to by EP r19 is clobbered. */ + state-save-frame pointed to by EP. r19 is clobbered. */ #define SAVE_PSW(savereg) \ stsr SR_ ## savereg, r19; \ sst.w r19, PTO+PT_PSW[ep] -/* Restore the PSW register from the struct pt_regs pointed to by EP, to +/* Restore the PSW register from the state-save-frame pointed to by EP, to the special register SAVEREG. LP is clobbered (it is used as a scratch register because the POP_STATE macro restores it, and this macro is usually used inside POP_STATE). */ @@ -161,7 +161,7 @@ sld.w PTO+PT_PSW[ep], lp; \ ldsr lp, SR_ ## savereg -/* Save CTPC/CTPSW/CTBP registers to the struct pt_regs pointed to by REG. +/* Save CTPC/CTPSW/CTBP registers to the state-save-frame pointed to by REG. r19 is clobbered. */ #define SAVE_CT_REGS \ stsr SR_CTPC, r19; \ @@ -170,7 +170,7 @@ sst.w r19, PTO+PT_CTPSW[ep]; \ stsr SR_CTBP, r19; \ sst.w r19, PTO+PT_CTBP[ep] -/* Restore CTPC/CTPSW/CTBP registers from the struct pt_regs pointed to by EP. +/* Restore CTPC/CTPSW/CTBP registers from the state-save-frame pointed to by EP. LP is clobbered (it is used as a scratch register because the POP_STATE macro restores it, and this macro is usually used inside POP_STATE). */ #define RESTORE_CT_REGS \ @@ -182,10 +182,11 @@ ldsr lp, SR_CTBP -/* Push register state, except for the stack pointer, on the stack in the form - of a struct pt_regs, in preparation for a system call. This macro makes - sure that `special' registers, system registers; TYPE identifies the set of - extra registers to be saved as well. EP is clobbered. */ +/* Push register state, except for the stack pointer, on the stack in the + form of a state-save-frame (plus some extra padding), in preparation for + a system call. This macro makes sure that the EP, GP, and LP + registers are saved, and TYPE identifies the set of extra registers to + be saved as well. Also copies (the new value of) SP to EP. */ #define PUSH_STATE(type) \ addi -STATE_SAVE_SIZE, sp, sp; /* Make room on the stack. */ \ st.w ep, PTO+PT_GPR(GPR_EP)[sp]; \ @@ -193,8 +194,8 @@ sst.w gp, PTO+PT_GPR(GPR_GP)[ep]; \ sst.w lp, PTO+PT_GPR(GPR_LP)[ep]; \ type ## _STATE_SAVER -/* Pop a register state, except for the stack pointer, from the struct pt_regs - on the stack. */ +/* Pop a register state pushed by PUSH_STATE, except for the stack pointer, + from the the stack. */ #define POP_STATE(type) \ mov sp, ep; \ type ## _STATE_RESTORER; \ @@ -205,7 +206,7 @@ /* Switch to the kernel stack if necessary, and push register state on the - stack in the form of a struct pt_regs. Also load the current task + stack in the form of a state-save-frame. Also load the current task pointer if switching from user mode. The stack-pointer (r3) should have already been saved to the memory location SP_SAVE_LOC (the reason for this is that the interrupt vectors may be beyond a 22-bit signed offset @@ -234,25 +235,30 @@ sst.w syscall_num, PTO+PT_CUR_SYSCALL[ep] -/* Save register state not normally saved by PUSH_STATE for TYPE. */ +/* Save register state not normally saved by PUSH_STATE for TYPE, to the + state-save-frame on the stack; also copies SP to EP. r19 may be trashed. */ #define SAVE_EXTRA_STATE(type) \ - mov sp, ep; \ + mov sp, ep; \ type ## _EXTRA_STATE_SAVER -/* Restore register state not normally restored by POP_STATE for TYPE. */ +/* Restore register state not normally restored by POP_STATE for TYPE, + from the state-save-frame on the stack; also copies SP to EP. + r19 may be trashed. */ #define RESTORE_EXTRA_STATE(type) \ - mov sp, ep; \ + mov sp, ep; \ type ## _EXTRA_STATE_RESTORER -/* Save any call-clobbered registers not normally saved by PUSH_STATE - for TYPE. */ -#define SAVE_EXTRA_STATE_FOR_FUNCALL(type) \ - mov sp, ep; \ - type ## _FUNCALL_EXTRA_STATE_SAVER -/* Restore any call-clobbered registers not normally restored by POP_STATE for - TYPE. */ -#define RESTORE_EXTRA_STATE_FOR_FUNCALL(type) \ - mov sp, ep; \ - type ## _FUNCALL_EXTRA_STATE_RESTORER +/* Save any call-clobbered registers not normally saved by PUSH_STATE for + TYPE, to the state-save-frame on the stack. + EP may be trashed, but is not guaranteed to contain a copy of SP + (unlike after most SAVE_... macros). r19 may be trashed. */ +#define SAVE_EXTRA_STATE_FOR_SCHEDULE(type) \ + type ## _SCHEDULE_EXTRA_STATE_SAVER +/* Restore any call-clobbered registers not normally restored by + POP_STATE for TYPE, to the state-save-frame on the stack. + EP may be trashed, but is not guaranteed to contain a copy of SP + (unlike after most RESTORE_... macros). r19 may be trashed. */ +#define RESTORE_EXTRA_STATE_FOR_SCHEDULE(type) \ + type ## _SCHEDULE_EXTRA_STATE_RESTORER /* These are extra_state_saver/restorer values for a user trap. Note @@ -263,36 +269,48 @@ caller of the syscall function should have saved them. */ #define TRAP_RET reti -/* Traps don't save call-clobbered registers (but do still save arg regs). */ +/* Traps don't save call-clobbered registers (but do still save arg regs). + We preserve PSw to keep long-term state, namely interrupt status (for traps + from kernel-mode), and the single-step flag (for user traps). */ #define TRAP_STATE_SAVER \ SAVE_ARG_REGS; \ - SAVE_PC(EIPC) + SAVE_PC(EIPC); \ + SAVE_PSW(EIPSW) /* When traps return, they just leave call-clobbered registers (except for arg - regs) with whatever value they have from the kernel. */ + regs) with whatever value they have from the kernel. Traps don't preserve + the PSW, but we zero EIPSW to ensure it doesn't contain anything dangerous + (in particular, the single-step flag). */ #define TRAP_STATE_RESTORER \ RESTORE_ARG_REGS; \ - RESTORE_PC(EIPC) + RESTORE_PC(EIPC); \ + RESTORE_PSW(EIPSW) /* Save registers not normally saved by traps. We need to save r12, even though it's nominally call-clobbered, because it's used when restarting a system call (the signal-handling path uses SAVE_EXTRA_STATE, and - expects r12 to be restored when the trap returns). Similarly, we must - save the PSW, so that it's at least in a known state in the the pt_regs - structure. */ + expects r12 to be restored when the trap returns). */ #define TRAP_EXTRA_STATE_SAVER \ SAVE_RVAL_REGS; \ sst.w r12, PTO+PT_GPR(12)[ep]; \ SAVE_CALL_SAVED_REGS; \ - SAVE_PSW(EIPSW); \ SAVE_CT_REGS #define TRAP_EXTRA_STATE_RESTORER \ RESTORE_RVAL_REGS; \ sld.w PTO+PT_GPR(12)[ep], r12; \ RESTORE_CALL_SAVED_REGS; \ - RESTORE_PSW(EIPSW); \ RESTORE_CT_REGS -#define TRAP_FUNCALL_EXTRA_STATE_SAVER \ +/* Save registers prior to calling scheduler (just before trap returns). + We have to save the return-value registers to preserve the trap's return + value. Note that ..._SCHEDULE_EXTRA_STATE_SAVER, unlike most ..._SAVER + macros, is required to setup EP itself if EP is needed (this is because + in many cases, the macro is empty). */ +#define TRAP_SCHEDULE_EXTRA_STATE_SAVER \ + mov sp, ep; \ SAVE_RVAL_REGS -#define TRAP_FUNCALL_EXTRA_STATE_RESTORER \ +/* Note that ..._SCHEDULE_EXTRA_STATE_RESTORER, unlike most ..._RESTORER + macros, is required to setup EP itself if EP is needed (this is because + in many cases, the macro is empty). */ +#define TRAP_SCHEDULE_EXTRA_STATE_RESTORER \ + mov sp, ep; \ RESTORE_RVAL_REGS /* Register saving/restoring for maskable interrupts. */ @@ -311,8 +329,8 @@ #define IRQ_EXTRA_STATE_RESTORER \ RESTORE_CALL_SAVED_REGS; \ RESTORE_CT_REGS -#define IRQ_FUNCALL_EXTRA_STATE_SAVER /* nothing */ -#define IRQ_FUNCALL_EXTRA_STATE_RESTORER /* nothing */ +#define IRQ_SCHEDULE_EXTRA_STATE_SAVER /* nothing */ +#define IRQ_SCHEDULE_EXTRA_STATE_RESTORER /* nothing */ /* Register saving/restoring for non-maskable interrupts. */ #define NMI_RET reti @@ -330,8 +348,8 @@ #define NMI_EXTRA_STATE_RESTORER \ RESTORE_CALL_SAVED_REGS; \ RESTORE_CT_REGS -#define NMI_FUNCALL_EXTRA_STATE_SAVER /* nothing */ -#define NMI_FUNCALL_EXTRA_STATE_RESTORER /* nothing */ +#define NMI_SCHEDULE_EXTRA_STATE_SAVER /* nothing */ +#define NMI_SCHEDULE_EXTRA_STATE_RESTORER /* nothing */ /* Register saving/restoring for debug traps. */ #define DBTRAP_RET .long 0x014607E0 /* `dbret', but gas doesn't support it. */ @@ -349,8 +367,8 @@ #define DBTRAP_EXTRA_STATE_RESTORER \ RESTORE_CALL_SAVED_REGS; \ RESTORE_CT_REGS -#define DBTRAP_FUNCALL_EXTRA_STATE_SAVER /* nothing */ -#define DBTRAP_FUNCALL_EXTRA_STATE_RESTORER /* nothing */ +#define DBTRAP_SCHEDULE_EXTRA_STATE_SAVER /* nothing */ +#define DBTRAP_SCHEDULE_EXTRA_STATE_RESTORER /* nothing */ /* Register saving/restoring for a context switch. We don't need to save too many registers, because context-switching looks like a function call @@ -372,14 +390,14 @@ RESTORE_CT_REGS -/* Restore register state from the struct pt_regs on the stack, switch back +/* Restore register state from the state-save-frame on the stack, switch back to the user stack if necessary, and return from the trap/interrupt. EXTRA_STATE_RESTORER is a sequence of assembly language statements to restore anything not restored by this macro. Only registers not saved by the C compiler are restored (that is, R3(sp), R4(gp), R31(lp), and anything restored by EXTRA_STATE_RESTORER). */ #define RETURN(type) \ - ld.b PTO+PT_KERNEL_MODE[sp], r19; \ + ld.b PTO+PT_KERNEL_MODE[sp], r19; \ di; /* Disable interrupts */ \ cmp r19, r0; /* See if returning to kernel mode, */\ bne 2f; /* ... if so, skip resched &c. */ \ @@ -390,33 +408,34 @@ ld.w TI_FLAGS[r18], r19; \ andi _TIF_NEED_RESCHED, r19, r0; \ bnz 3f; /* Call the scheduler. */ \ - andi _TIF_SIGPENDING, r19, r0; \ - bnz 4f; /* Signals to handle, handle them */ \ +5: andi _TIF_SIGPENDING, r19, r18; \ + ld.w TASK_PTRACE[CURRENT_TASK], r19; /* ptrace flags */ \ + or r18, r19; /* see if either is non-zero */ \ + bnz 4f; /* if so, handle them */ \ \ -/* Return to user state. */ \ +/* Return to user state. */ \ 1: st.b r0, KM; /* Now officially in user state. */ \ \ /* Final return. The stack-pointer fiddling is not needed when returning \ to kernel-mode, but they don't hurt, and this way we can share the \ - (somtimes rather lengthy) POP_STATE macro. */ \ + (sometimes rather lengthy) POP_STATE macro. */ \ 2: POP_STATE(type); \ st.w sp, KSP; /* Save the kernel stack pointer. */ \ - ld.w PT_GPR(GPR_SP)-PT_SIZE[sp], sp; /* Restore stack pointer. */ \ + ld.w PT_GPR(GPR_SP)-PT_SIZE[sp], sp; /* Restore stack pointer. */ \ type ## _RET; /* Return from the trap/interrupt. */ \ \ /* Call the scheduler before returning from a syscall/trap. */ \ -3: SAVE_EXTRA_STATE_FOR_FUNCALL(type); /* Prepare for funcall. */ \ - jarl CSYM(schedule), lp; /* Call scheduler */ \ +3: SAVE_EXTRA_STATE_FOR_SCHEDULE(type); /* Prepare to call scheduler. */ \ + jarl call_scheduler, lp; /* Call scheduler */ \ di; /* The scheduler enables interrupts */\ - RESTORE_EXTRA_STATE_FOR_FUNCALL(type); \ + RESTORE_EXTRA_STATE_FOR_SCHEDULE(type); \ GET_CURRENT_THREAD(r18); \ ld.w TI_FLAGS[r18], r19; \ - andi _TIF_SIGPENDING, r19, r0; \ - bz 1b; /* No signals, return. */ \ - /* Signals to handle, fall through to handle them. */ \ + br 5b; /* Continue with return path. */ \ \ -/* Handle a signal return. */ \ -4: /* Not all registers are saved by the normal trap/interrupt entry \ +/* Handle a signal or ptraced process return. \ + r18 should be non-zero if there are pending signals. */ \ +4: /* Not all registers are saved by the normal trap/interrupt entry \ points (for instance, call-saved registers (because the normal \ C-compiler calling sequence in the kernel makes sure they're \ preserved), and call-clobbered registers in the case of \ @@ -424,12 +443,9 @@ complete register state. Here we save anything not saved by \ the normal entry sequence, so that it may be safely restored \ (in a possibly modified form) after do_signal returns. */ \ - SAVE_EXTRA_STATE(type); /* Save state not saved by entry. */ \ - movea PTO, sp, r6; /* Arg 1: struct pt_regs *regs */ \ - mov r0, r7; /* Arg 2: sigset_t *oldset */ \ - jarl CSYM(do_signal), lp; /* Handle any signals */ \ - di; /* sig handling enables interrupts */ \ - RESTORE_EXTRA_STATE(type); /* Restore extra regs. */ \ + SAVE_EXTRA_STATE(type); /* Save state not saved by entry. */ \ + jarl handle_signal_or_ptrace_return, lp; \ + RESTORE_EXTRA_STATE(type); /* Restore extra regs. */ \ br 1b @@ -471,7 +487,7 @@ * Return value in r10 */ G_ENTRY(trap): - SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers. + SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers. stsr SR_ECR, r19 // Find out which trap it was. ei // Enable interrupts. mov hilo(ret_from_trap), lp // where the trap should return @@ -481,12 +497,12 @@ // numbers into the (0-31) << 2 range we want, (3) set the flags. shl 27, r19 // chop off all high bits shr 25, r19 // scale back down and then << 2 - bnz 2f // See if not trap 0. + bnz 2f // See if not trap 0. - // Trap 0 is a `short' system call, skip general trap table. - MAKE_SYS_CALL // Jump to the syscall function. + // Trap 0 is a `short' system call, skip general trap table. + MAKE_SYS_CALL // Jump to the syscall function. -2: // For other traps, use a table lookup. +2: // For other traps, use a table lookup. mov hilo(CSYM(trap_table)), r18 add r19, r18 ld.w 0[r18], r18 @@ -505,6 +521,7 @@ RETURN(TRAP) END(ret_from_trap) + /* This the initial entry point for a new child thread, with an appropriate stack in place that makes it look the the child is in the middle of an syscall. This function is actually `returned to' from switch_thread @@ -538,7 +555,7 @@ mov hilo(ret_from_long_syscall), lp MAKE_SYS_CALL // Jump to the syscall function. -END(syscall_long) +END(syscall_long) /* Entry point used to return from a long syscall. Only needed to restore r13/r14 if the general trap mechanism doesnt' do so. */ @@ -554,11 +571,14 @@ L_ENTRY(sys_fork_wrapper): #ifdef CONFIG_MMU - addi SIGCHLD, r0, r6 // Arg 0: flags + addi SIGCHLD, r0, r6 // Arg 0: flags ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's) - movea PTO, sp, r8 // Arg 2: parent context - mov hilo(CSYM(fork_common)), r18// Where the real work gets done - br save_extra_state_tramp // Save state and go there + movea PTO, sp, r8 // Arg 2: parent context + mov r0, r9 // Arg 3/4/5: 0 + st.w r0, 16[sp] + st.w r0, 20[sp] + mov hilo(CSYM(do_fork)), r18 // Where the real work gets done + br save_extra_state_tramp // Save state and go there #else // fork almost works, enough to trick you into looking elsewhere :-( addi -EINVAL, r0, r10 @@ -569,18 +589,24 @@ L_ENTRY(sys_vfork_wrapper): addi CLONE_VFORK | CLONE_VM | SIGCHLD, r0, r6 // Arg 0: flags ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's) - movea PTO, sp, r8 // Arg 2: parent context - mov hilo(CSYM(fork_common)), r18// Where the real work gets done - br save_extra_state_tramp // Save state and go there + movea PTO, sp, r8 // Arg 2: parent context + mov r0, r9 // Arg 3/4/5: 0 + st.w r0, 16[sp] + st.w r0, 20[sp] + mov hilo(CSYM(do_fork)), r18 // Where the real work gets done + br save_extra_state_tramp // Save state and go there END(sys_vfork_wrapper) L_ENTRY(sys_clone_wrapper): - ld.w PTO+PT_GPR(GPR_SP)[sp], r19 // parent's stack pointer - cmp r7, r0 // See if child SP arg (arg 1) is 0. - cmov z, r19, r7, r7 // ... and use the parent's if so. - movea PTO, sp, r8 // Arg 2: parent context - mov hilo(CSYM(fork_common)), r18// Where the real work gets done - br save_extra_state_tramp // Save state and go there + ld.w PTO+PT_GPR(GPR_SP)[sp], r19// parent's stack pointer + cmp r7, r0 // See if child SP arg (arg 1) is 0. + cmov z, r19, r7, r7 // ... and use the parent's if so. + movea PTO, sp, r8 // Arg 2: parent context + mov r0, r9 // Arg 3/4/5: 0 + st.w r0, 16[sp] + st.w r0, 20[sp] + mov hilo(CSYM(do_fork)), r18 // Where the real work gets done + br save_extra_state_tramp // Save state and go there END(sys_clone_wrapper) @@ -598,8 +624,8 @@ END(sys_sigsuspend_wrapper) L_ENTRY(sys_rt_sigsuspend_wrapper): movea PTO, sp, r8 // add user context as 3rd arg - mov hilo(CSYM(sys_rt_sigsuspend)), r18 // syscall function - jarl save_extra_state_tramp, lp // Save state and do it + mov hilo(CSYM(sys_rt_sigsuspend)), r18 // syscall function + jarl save_extra_state_tramp, lp // Save state and do it br restore_extra_regs_and_ret_from_trap END(sys_rt_sigsuspend_wrapper) @@ -610,10 +636,9 @@ br restore_extra_regs_and_ret_from_trap END(sys_sigreturn_wrapper) L_ENTRY(sys_rt_sigreturn_wrapper): - SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry. movea PTO, sp, r6 // add user context as 1st arg - mov hilo(CSYM(sys_rt_sigreturn)), r18 // syscall function - jarl save_extra_state_tramp, lp // Save state and do it + mov hilo(CSYM(sys_rt_sigreturn)), r18// syscall function + jarl save_extra_state_tramp, lp // Save state and do it br restore_extra_regs_and_ret_from_trap END(sys_rt_sigreturn_wrapper) @@ -637,7 +662,7 @@ * indirect jump). */ G_ENTRY(irq): - SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers. + SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers. stsr SR_ECR, r6 // Find out which interrupt it was. movea PTO, sp, r7 // User regs are arg2 @@ -657,7 +682,7 @@ RETURN(IRQ) END(irq) - + /* * Debug trap / illegal-instruction exception * @@ -668,22 +693,50 @@ * indirect jump). */ G_ENTRY(dbtrap): - SAVE_STATE (DBTRAP, r0, ENTRY_SP)// Save registers. + SAVE_STATE (DBTRAP, r0, ENTRY_SP)// Save registers. + + /* First see if we came from kernel mode; if so, the dbtrap + instruction has a special meaning, to set the DIR (`debug + information register') register. This is because the DIR register + can _only_ be manipulated/read while in `debug mode,' and debug + mode is only active while we're inside the dbtrap handler. The + exact functionality is: { DIR = (DIR | r6) & ~r7; return DIR; }. */ + ld.b PTO+PT_KERNEL_MODE[sp], r19 + cmp r19, r0 + bz 1f + + stsr SR_DIR, r10 + or r6, r10 + not r7, r7 + and r7, r10 + ldsr r10, SR_DIR + stsr SR_DIR, r10 // Confirm the value we set + st.w r10, PTO+PT_GPR(10)[sp] // return it + br 3f + +1: ei // Enable interrupts. + + /* The default signal type we raise. */ + mov SIGTRAP, r6 + + /* See if it's a single-step trap. */ + stsr SR_DBPSW, r19 + andi 0x0800, r19, r19 + bnz 2f /* Look to see if the preceding instruction was is a dbtrap or not, to decide which signal we should use. */ stsr SR_DBPC, r19 // PC following trapping insn ld.hu -2[r19], r19 - mov SIGTRAP, r6 ori 0xf840, r0, r20 // DBTRAP insn cmp r19, r20 // Was this trap caused by DBTRAP? cmov ne, SIGILL, r6, r6 // Choose signal appropriately /* Raise the desired signal. */ - mov CURRENT_TASK, r7 // Arg 1: task - jarl CSYM(force_sig), lp // tail call +2: mov CURRENT_TASK, r7 // Arg 1: task + jarl CSYM(send_sig), lp // tail call - RETURN(DBTRAP) +3: RETURN(DBTRAP) END(dbtrap) @@ -725,9 +778,93 @@ /* + * Invoke the scheduler, called from the trap/irq kernel exit path. + * + * This basically just calls `schedule', but also arranges for extra + * registers to be saved for ptrace'd processes, so ptrace can modify them. + */ +L_ENTRY(call_scheduler): + ld.w TASK_PTRACE[CURRENT_TASK], r19 // See if task is ptrace'd + cmp r19, r0 + bnz 1f // ... yes, do special stuff + jr CSYM(schedule) // ... no, just tail-call scheduler + + // Save extra regs for ptrace'd task. We want to save anything + // that would otherwise only be `implicitly' saved by the normal + // compiler calling-convention. +1: mov sp, ep // Setup EP for SAVE_CALL_SAVED_REGS + SAVE_CALL_SAVED_REGS // Save call-saved registers to stack + mov lp, r20 // Save LP in a callee-saved register + + jarl CSYM(schedule), lp // Call scheduler + + mov r20, lp + mov sp, ep // We can't rely on EP after return + RESTORE_CALL_SAVED_REGS // Restore (possibly modified) regs + jmp [lp] // Return to the return path +END(call_scheduler) + + +/* + * This is an out-of-line handler for two special cases during the kernel + * trap/irq exit sequence: + * + * (1) If r18 is non-zero then a signal needs to be handled, which is + * done, and then the caller returned to. + * + * (2) If r18 is non-zero then we're returning to a ptraced process, which + * has several special cases -- single-stepping and trap tracing, both + * of which require using the `dbret' instruction to exit the kernel + * instead of the normal `reti' (this is because the CPU not correctly + * single-step after a reti). In this case, of course, this handler + * never returns to the caller. + * + * In either case, all registers should have been saved to the current + * state-save-frame on the stack, except for callee-saved registers. + * + * [These two different cases are combined merely to avoid bloating the + * macro-inlined code, not because they really make much sense together!] + */ +L_ENTRY(handle_signal_or_ptrace_return): + cmp r18, r0 // See if handling a signal + bz 1f // ... nope, go do ptrace return + + // Handle a signal + mov lp, r20 // Save link-pointer + mov r10, r21 // Save return-values (for trap) + mov r11, r22 + + movea PTO, sp, r6 // Arg 1: struct pt_regs *regs + mov r0, r7 // Arg 2: sigset_t *oldset + jarl CSYM(do_signal), lp // Handle the signal + di // sig handling enables interrupts + + mov r20, lp // Restore link-pointer + mov r21, r10 // Restore return-values (for trap) + mov r22, r11 + ld.w TASK_PTRACE[CURRENT_TASK], r19 // check ptrace flags too + cmp r19, r0 + bnz 1f // ... some set, so look more +2: jmp [lp] // ... none set, so return normally + + // ptrace return +1: ld.w PTO+PT_PSW[sp], r19 // Look at user-processes's flags + andi 0x0800, r19, r19 // See if single-step flag is set + bz 2b // ... nope, return normally + + // Return as if from a dbtrap insn + st.b r0, KM // Now officially in user state. + POP_STATE(DBTRAP) // Restore regs + st.w sp, KSP // Save the kernel stack pointer. + ld.w PT_GPR(GPR_SP)-PT_SIZE[sp], sp // Restore user stack pointer. + DBTRAP_RET // Return from the trap/interrupt. +END(handle_signal_or_ptrace_return) + + +/* * This is where we switch between two threads. The arguments are: * r6 -- pointer to the struct thread for the `current' process - * r7 -- pointer to the struct thread for the `new' process. + * r7 -- pointer to the struct thread for the `new' process. * when this function returns, it will return to the new thread. */ C_ENTRY(switch_thread): @@ -754,8 +891,8 @@ .align 4 C_DATA(trap_table): - .long bad_trap_wrapper // trap 0, doesn't use trap table. - .long syscall_long // trap 1, `long' syscall. + .long bad_trap_wrapper // trap 0, doesn't use trap table. + .long syscall_long // trap 1, `long' syscall. .long bad_trap_wrapper .long bad_trap_wrapper .long bad_trap_wrapper @@ -774,7 +911,7 @@ .section .rodata - + .align 4 C_DATA(sys_call_table): .long CSYM(sys_restart_syscall) // 0 @@ -835,7 +972,7 @@ .long CSYM(sys_fcntl) // 55 .long CSYM(sys_ni_syscall) // was: mpx .long CSYM(sys_setpgid) - .long CSYM(sys_ni_syscall) // was: ulimit + .long CSYM(sys_ni_syscall) // was: ulimit .long CSYM(sys_ni_syscall) .long CSYM(sys_umask) // 60 .long CSYM(sys_chroot) @@ -875,7 +1012,7 @@ .long CSYM(sys_fchown) // 95 .long CSYM(sys_getpriority) .long CSYM(sys_setpriority) - .long CSYM(sys_ni_syscall) // was: profil + .long CSYM(sys_ni_syscall) // was: profil .long CSYM(sys_statfs) .long CSYM(sys_fstatfs) // 100 .long CSYM(sys_ni_syscall) // i386: ioperm @@ -900,7 +1037,7 @@ .long sys_clone_wrapper // 120 .long CSYM(sys_setdomainname) .long CSYM(sys_newuname) - .long CSYM(sys_ni_syscall) // i386: modify_ldt, m68k: cacheflush + .long CSYM(sys_ni_syscall) // i386: modify_ldt, m68k: cacheflush .long CSYM(sys_adjtimex) .long CSYM(sys_ni_syscall) // 125 - sys_mprotect .long CSYM(sys_sigprocmask) @@ -937,7 +1074,7 @@ .long CSYM(sys_sched_getscheduler) .long CSYM(sys_sched_yield) .long CSYM(sys_sched_get_priority_max) - .long CSYM(sys_sched_get_priority_min) // 160 + .long CSYM(sys_sched_get_priority_min) // 160 .long CSYM(sys_sched_rr_get_interval) .long CSYM(sys_nanosleep) .long CSYM(sys_ni_syscall) // sys_mremap diff -urN linux-2.5.70-bk1/arch/v850/kernel/head.S linux-2.5.70-bk2/arch/v850/kernel/head.S --- linux-2.5.70-bk1/arch/v850/kernel/head.S 2003-05-26 18:00:23.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/head.S 2003-05-28 04:37:02.000000000 -0700 @@ -39,7 +39,7 @@ cmp r19, r20 bne 1f // Guard was not active - // If we get here, the reset guard was active. Load up some + // If we get here, the reset guard was active. Load up some // interesting values as arguments, and jump to the handler. st.w r0, RESET_GUARD // Allow further resets to succeed mov lp, r6 // Arg 0: return address @@ -53,7 +53,7 @@ 1: st.w r20, RESET_GUARD // Turn on reset guard #endif /* CONFIG_RESET_GUARD */ - + // Setup a temporary stack for doing pre-initialization function calls. // // We can't use the initial kernel stack, because (1) it may be diff -urN linux-2.5.70-bk1/arch/v850/kernel/irq.c linux-2.5.70-bk2/arch/v850/kernel/irq.c --- linux-2.5.70-bk1/arch/v850/kernel/irq.c 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/irq.c 2003-05-28 04:37:02.000000000 -0700 @@ -1,7 +1,7 @@ /* * arch/v850/kernel/irq.c -- High-level interrupt handling * - * Copyright (C) 2001,02,03 NEC Corporation + * Copyright (C) 2001,02,03 NEC Electronics Corporation * Copyright (C) 2001,02,03 Miles Bader * Copyright (C) 1994-2000 Ralf Baechle * Copyright (C) 1992 Linus Torvalds @@ -35,7 +35,7 @@ * Special irq handlers. */ -void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } +irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { } /* * Generic no controller code @@ -352,7 +352,7 @@ */ int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) diff -urN linux-2.5.70-bk1/arch/v850/kernel/ma.c linux-2.5.70-bk2/arch/v850/kernel/ma.c --- linux-2.5.70-bk1/arch/v850/kernel/ma.c 2003-05-26 18:00:24.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/ma.c 2003-05-28 04:37:02.000000000 -0700 @@ -1,8 +1,8 @@ /* * arch/v850/kernel/ma.c -- V850E/MA series of cpu chips * - * Copyright (C) 2001,02 NEC Corporation - * Copyright (C) 2001,02 Miles Bader + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this diff -urN linux-2.5.70-bk1/arch/v850/kernel/mach.h linux-2.5.70-bk2/arch/v850/kernel/mach.h --- linux-2.5.70-bk1/arch/v850/kernel/mach.h 2003-05-26 18:01:00.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/mach.h 2003-05-28 04:37:02.000000000 -0700 @@ -1,8 +1,8 @@ /* * arch/v850/kernel/mach.h -- Machine-dependent functions used by v850 port * - * Copyright (C) 2001,02 NEC Corporation - * Copyright (C) 2001,02 Miles Bader + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this diff -urN linux-2.5.70-bk1/arch/v850/kernel/process.c linux-2.5.70-bk2/arch/v850/kernel/process.c --- linux-2.5.70-bk1/arch/v850/kernel/process.c 2003-05-26 18:00:24.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/process.c 2003-05-28 04:37:02.000000000 -0700 @@ -1,7 +1,7 @@ /* * arch/v850/kernel/process.c -- Arch-dependent process handling * - * Copyright (C) 2001,02,03 NEC Corporation + * Copyright (C) 2001,02,03 NEC Electronics Corporation * Copyright (C) 2001,02,03 Miles Bader * * This file is subject to the terms and conditions of the GNU General @@ -200,14 +200,6 @@ return error; } -/* This is the common part of the various fork-like system calls (which - are in entry.S). */ -int fork_common (int flags, unsigned long new_sp, struct pt_regs *regs) -{ - struct task_struct *p = do_fork (flags, new_sp, regs, 0, 0, 0); - return IS_ERR (p) ? PTR_ERR (p) : p->pid; -} - /* * These bracket the sleeping functions.. diff -urN linux-2.5.70-bk1/arch/v850/kernel/ptrace.c linux-2.5.70-bk2/arch/v850/kernel/ptrace.c --- linux-2.5.70-bk1/arch/v850/kernel/ptrace.c 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/ptrace.c 2003-05-28 04:37:02.000000000 -0700 @@ -1,8 +1,8 @@ /* * arch/v850/kernel/ptrace.c -- `ptrace' system call * - * Copyright (C) 2002 NEC Corporation - * Copyright (C) 2002 Miles Bader + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader * * Derived from arch/mips/kernel/ptrace.c: * @@ -29,6 +29,89 @@ #include #include +/* Returns the address where the register at REG_OFFS in P is stashed away. */ +static v850_reg_t *reg_save_addr (unsigned reg_offs, struct task_struct *t) +{ + struct pt_regs *regs; + + /* Three basic cases: + + (1) A register normally saved before calling the scheduler, is + available in the kernel entry pt_regs structure at the top + of the kernel stack. The kernel trap/irq exit path takes + care to save/restore almost all registers for ptrace'd + processes. + + (2) A call-clobbered register, where the process P entered the + kernel via [syscall] trap, is not stored anywhere; that's + OK, because such registers are not expected to be preserved + when the trap returns anyway (so we don't actually bother to + test for this case). + + (3) A few registers not used at all by the kernel, and so + normally never saved except by context-switches, are in the + context switch state. */ + + if (reg_offs == PT_CTPC || reg_offs == PT_CTPSW || reg_offs == PT_CTBP) + /* Register saved during context switch. */ + regs = thread_saved_regs (t); + else + /* Register saved during kernel entry (or not available). */ + regs = task_regs (t); + + return (v850_reg_t *)((char *)regs + reg_offs); +} + +/* Set the bits SET and clear the bits CLEAR in the v850e DIR + (`debug information register'). Returns the new value of DIR. */ +static inline v850_reg_t set_dir (v850_reg_t set, v850_reg_t clear) +{ + register v850_reg_t rval asm ("r10"); + register v850_reg_t arg0 asm ("r6") = set; + register v850_reg_t arg1 asm ("r7") = clear; + + /* The dbtrap handler has exactly this functionality when called + from kernel mode. 0xf840 is a `dbtrap' insn. */ + asm (".short 0xf840" : "=r" (rval) : "r" (arg0), "r" (arg1)); + + return rval; +} + +/* Makes sure hardware single-stepping is (globally) enabled. + Returns true if successful. */ +static inline int enable_single_stepping (void) +{ + static int enabled = 0; /* Remember whether we already did it. */ + if (! enabled) { + /* Turn on the SE (`single-step enable') bit, 0x100, in the + DIR (`debug information register'). This may fail if a + processor doesn't support it or something. We also try + to clear bit 0x40 (`INI'), which is necessary to use the + debug stuff on the v850e2; on the v850e, clearing 0x40 + shouldn't cause any problem. */ + v850_reg_t dir = set_dir (0x100, 0x40); + /* Make sure it really got set. */ + if (dir & 0x100) + enabled = 1; + } + return enabled; +} + +/* Try to set CHILD's single-step flag to VAL. Returns true if successful. */ +static int set_single_step (struct task_struct *t, int val) +{ + v850_reg_t *psw_addr = reg_save_addr(PT_PSW, t); + if (val) { + /* Make sure single-stepping is enabled. */ + if (! enable_single_stepping ()) + return 0; + /* Set T's single-step flag. */ + *psw_addr |= 0x800; + } else + *psw_addr &= ~0x800; + return 1; +} + int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -36,12 +119,6 @@ lock_kernel(); -#if 0 - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif - if (request == PTRACE_TRACEME) { /* are we already being traced? */ if (current->ptrace & PT_PTRACED) { @@ -81,31 +158,15 @@ goto out_tsk; switch (request) { - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA:{ - unsigned long tmp; - int copied; + unsigned long val, copied; - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: + copied = access_process_vm(child, addr, &val, sizeof(val), 0); rval = -EIO; - if (copied != sizeof(tmp)) + if (copied != sizeof(val)) break; - rval = put_user(tmp,(unsigned long *) data); - - goto out; - } - - /* Read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: - if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) { - struct pt_regs *regs = task_regs (child); - unsigned long val = - *(unsigned long *)((char *)regs + addr); - rval = put_user (val, (unsigned long *)data); - } else { - rval = 0; - rval = -EIO; - } + rval = put_user(val, (unsigned long *)data); goto out; case PTRACE_POKETEXT: /* write the word at location addr. */ @@ -117,35 +178,62 @@ rval = -EIO; goto out; + /* Read/write the word at location ADDR in the registers. */ + case PTRACE_PEEKUSR: case PTRACE_POKEUSR: - if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) { - struct pt_regs *regs = task_regs (child); - unsigned long *loc = - (unsigned long *)((char *)regs + addr); - *loc = data; - } else { - rval = 0; - rval = -EIO; - } + rval = 0; + if (addr >= PT_SIZE && request == PTRACE_PEEKUSR) { + /* Special requests that don't actually correspond + to offsets in struct pt_regs. */ + if (addr == PT_TEXT_ADDR) + val = child->mm->start_code; + else if (addr == PT_DATA_ADDR) + val = child->mm->start_data; + else if (addr == PT_TEXT_LEN) + val = child->mm->end_code + - child->mm->start_code; + else + rval = -EIO; + } else if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) { + v850_reg_t *reg_addr = reg_save_addr(addr, child); + if (request == PTRACE_PEEKUSR) + val = *reg_addr; + else + *reg_addr = data; + } else + rval = -EIO; + + if (rval == 0 && request == PTRACE_PEEKUSR) + rval = put_user (val, (unsigned long *)data); goto out; - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: /* rvaltart after signal. */ + /* Continue and stop at next (return from) syscall */ + case PTRACE_SYSCALL: + /* Restart after a signal. */ + case PTRACE_CONT: + /* Execute a single instruction. */ + case PTRACE_SINGLESTEP: rval = -EIO; if ((unsigned long) data > _NSIG) break; + + /* Turn CHILD's single-step flag on or off. */ + if (! set_single_step (child, request == PTRACE_SINGLESTEP)) + break; + if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + child->exit_code = data; wake_up_process(child); rval = 0; break; /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to * exit. */ case PTRACE_KILL: @@ -157,6 +245,7 @@ break; case PTRACE_DETACH: /* detach a process that was attached. */ + set_single_step (child, 0); /* Clear single-step flag */ rval = ptrace_detach(child, data); break; @@ -181,7 +270,7 @@ /* The 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff -urN linux-2.5.70-bk1/arch/v850/kernel/rte_cb_leds.c linux-2.5.70-bk2/arch/v850/kernel/rte_cb_leds.c --- linux-2.5.70-bk1/arch/v850/kernel/rte_cb_leds.c 2003-05-26 18:00:23.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/rte_cb_leds.c 2003-05-28 04:37:02.000000000 -0700 @@ -1,8 +1,8 @@ /* * include/asm-v850/rte_cb_leds.c -- Midas lab RTE-CB board LED device support * - * Copyright (C) 2002 NEC Corporation - * Copyright (C) 2002 Miles Bader + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff -urN linux-2.5.70-bk1/arch/v850/kernel/rte_cb_multi.c linux-2.5.70-bk2/arch/v850/kernel/rte_cb_multi.c --- linux-2.5.70-bk1/arch/v850/kernel/rte_cb_multi.c 2003-05-26 18:00:28.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/rte_cb_multi.c 2003-05-28 04:37:02.000000000 -0700 @@ -2,7 +2,7 @@ * include/asm-v850/rte_multi.c -- Support for Multi debugger monitor ROM * on Midas lab RTE-CB series of evaluation boards * - * Copyright (C) 2001,02,03 NEC Corporation + * Copyright (C) 2001,02,03 NEC Electronics Corporation * Copyright (C) 2001,02,03 Miles Bader * * This file is subject to the terms and conditions of the GNU General diff -urN linux-2.5.70-bk1/arch/v850/kernel/rte_ma1_cb.c linux-2.5.70-bk2/arch/v850/kernel/rte_ma1_cb.c --- linux-2.5.70-bk1/arch/v850/kernel/rte_ma1_cb.c 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/kernel/rte_ma1_cb.c 2003-05-28 04:37:02.000000000 -0700 @@ -1,7 +1,7 @@ /* * arch/v850/kernel/rte_ma1_cb.c -- Midas labs RTE-V850E/MA1-CB board * - * Copyright (C) 2001,02,03 NEC Corporation + * Copyright (C) 2001,02,03 NEC Electronics Corporation * Copyright (C) 2001,02,03 Miles Bader * * This file is subject to the terms and conditions of the GNU General diff -urN linux-2.5.70-bk1/arch/v850/vmlinux.lds.S linux-2.5.70-bk2/arch/v850/vmlinux.lds.S --- linux-2.5.70-bk1/arch/v850/vmlinux.lds.S 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.70-bk2/arch/v850/vmlinux.lds.S 2003-05-28 04:37:02.000000000 -0700 @@ -105,9 +105,9 @@ #define RAMK_INIT_CONTENTS_NO_END \ . = ALIGN (4096) ; \ __init_start = . ; \ - _sinittext = .; \ + __sinittext = .; \ *(.init.text) /* 2.5 convention */ \ - _einittext = .; \ + __einittext = .; \ *(.init.data) \ *(.text.init) /* 2.4 convention */ \ *(.data.init) \ diff -urN linux-2.5.70-bk1/arch/x86_64/kernel/reboot.c linux-2.5.70-bk2/arch/x86_64/kernel/reboot.c --- linux-2.5.70-bk1/arch/x86_64/kernel/reboot.c 2003-05-26 18:00:47.000000000 -0700 +++ linux-2.5.70-bk2/arch/x86_64/kernel/reboot.c 2003-05-28 04:37:02.000000000 -0700 @@ -124,7 +124,7 @@ { int i; -#if CONFIG_SMP +#ifdef CONFIG_SMP smp_halt(); #endif diff -urN linux-2.5.70-bk1/crypto/sha512.c linux-2.5.70-bk2/crypto/sha512.c --- linux-2.5.70-bk1/crypto/sha512.c 2003-05-26 18:00:58.000000000 -0700 +++ linux-2.5.70-bk2/crypto/sha512.c 2003-05-28 04:37:02.000000000 -0700 @@ -48,33 +48,33 @@ } const u64 sha512_K[80] = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, - 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, - 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, - 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, - 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, - 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, - 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, - 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, - 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, - 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, - 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, - 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, - 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, - 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, - 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, - 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, - 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, - 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, - 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, - 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, - 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, }; #define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) @@ -83,24 +83,24 @@ #define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) /* H* initial state for SHA-512 */ -#define H0 0x6a09e667f3bcc908 -#define H1 0xbb67ae8584caa73b -#define H2 0x3c6ef372fe94f82b -#define H3 0xa54ff53a5f1d36f1 -#define H4 0x510e527fade682d1 -#define H5 0x9b05688c2b3e6c1f -#define H6 0x1f83d9abfb41bd6b -#define H7 0x5be0cd19137e2179 +#define H0 0x6a09e667f3bcc908ULL +#define H1 0xbb67ae8584caa73bULL +#define H2 0x3c6ef372fe94f82bULL +#define H3 0xa54ff53a5f1d36f1ULL +#define H4 0x510e527fade682d1ULL +#define H5 0x9b05688c2b3e6c1fULL +#define H6 0x1f83d9abfb41bd6bULL +#define H7 0x5be0cd19137e2179ULL /* H'* initial state for SHA-384 */ -#define HP0 0xcbbb9d5dc1059ed8 -#define HP1 0x629a292a367cd507 -#define HP2 0x9159015a3070dd17 -#define HP3 0x152fecd8f70e5939 -#define HP4 0x67332667ffc00b31 -#define HP5 0x8eb44a8768581511 -#define HP6 0xdb0c2e0d64f98fa7 -#define HP7 0x47b5481dbefa4fa4 +#define HP0 0xcbbb9d5dc1059ed8ULL +#define HP1 0x629a292a367cd507ULL +#define HP2 0x9159015a3070dd17ULL +#define HP3 0x152fecd8f70e5939ULL +#define HP4 0x67332667ffc00b31ULL +#define HP5 0x8eb44a8768581511ULL +#define HP6 0xdb0c2e0d64f98fa7ULL +#define HP7 0x47b5481dbefa4fa4ULL static inline void LOAD_OP(int I, u64 *W, const u8 *input) { diff -urN linux-2.5.70-bk1/drivers/block/ll_rw_blk.c linux-2.5.70-bk2/drivers/block/ll_rw_blk.c --- linux-2.5.70-bk1/drivers/block/ll_rw_blk.c 2003-05-26 18:00:23.000000000 -0700 +++ linux-2.5.70-bk2/drivers/block/ll_rw_blk.c 2003-05-28 04:37:02.000000000 -0700 @@ -413,11 +413,12 @@ { struct blk_queue_tag *bqt = q->queue_tags; - if (unlikely(bqt == NULL || bqt->max_depth < tag)) + if (unlikely(bqt == NULL || tag >= bqt->real_max_depth)) return NULL; return bqt->tag_index[tag]; } + /** * blk_queue_free_tags - release tag maintenance info * @q: the request queue for the device @@ -448,39 +449,28 @@ q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED); } -/** - * blk_queue_init_tags - initialize the queue tag info - * @q: the request queue for the device - * @depth: the maximum queue depth supported - **/ -int blk_queue_init_tags(request_queue_t *q, int depth) +static int init_tag_map(struct blk_queue_tag *tags, int depth) { - struct blk_queue_tag *tags; int bits, i; if (depth > (queue_nr_requests*2)) { depth = (queue_nr_requests*2); - printk("blk_queue_init_tags: adjusted depth to %d\n", depth); + printk(KERN_ERR "%s: adjusted depth to %d\n", __FUNCTION__, depth); } - tags = kmalloc(sizeof(struct blk_queue_tag),GFP_ATOMIC); - if (!tags) - goto fail; - tags->tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC); if (!tags->tag_index) - goto fail_index; + goto fail; bits = (depth / BLK_TAGS_PER_LONG) + 1; tags->tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC); if (!tags->tag_map) - goto fail_map; + goto fail; memset(tags->tag_index, 0, depth * sizeof(struct request *)); memset(tags->tag_map, 0, bits * sizeof(unsigned long)); - INIT_LIST_HEAD(&tags->busy_list); - tags->busy = 0; tags->max_depth = depth; + tags->real_max_depth = bits * BITS_PER_LONG; /* * set the upper bits if the depth isn't a multiple of the word size @@ -488,22 +478,89 @@ for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++) __set_bit(i, tags->tag_map); + return 0; +fail: + kfree(tags->tag_index); + return -ENOMEM; +} + + +/** + * blk_queue_init_tags - initialize the queue tag info + * @q: the request queue for the device + * @depth: the maximum queue depth supported + **/ +int blk_queue_init_tags(request_queue_t *q, int depth) +{ + struct blk_queue_tag *tags; + + tags = kmalloc(sizeof(struct blk_queue_tag),GFP_ATOMIC); + if (!tags) + goto fail; + + if (init_tag_map(tags, depth)) + goto fail; + + INIT_LIST_HEAD(&tags->busy_list); + tags->busy = 0; + /* * assign it, all done */ q->queue_tags = tags; q->queue_flags |= (1 << QUEUE_FLAG_QUEUED); return 0; - -fail_map: - kfree(tags->tag_index); -fail_index: - kfree(tags); fail: + kfree(tags); return -ENOMEM; } /** + * blk_queue_resize_tags - change the queueing depth + * @q: the request queue for the device + * @new_depth: the new max command queueing depth + * + * Notes: + * Must be called with the queue lock held. + **/ +int blk_queue_resize_tags(request_queue_t *q, int new_depth) +{ + struct blk_queue_tag *bqt = q->queue_tags; + struct request **tag_index; + unsigned long *tag_map; + int bits, max_depth; + + if (!bqt) + return -ENXIO; + + /* + * don't bother sizing down + */ + if (new_depth <= bqt->real_max_depth) { + bqt->max_depth = new_depth; + return 0; + } + + /* + * save the old state info, so we can copy it back + */ + tag_index = bqt->tag_index; + tag_map = bqt->tag_map; + max_depth = bqt->real_max_depth; + + if (init_tag_map(bqt, new_depth)) + return -ENOMEM; + + memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *)); + bits = max_depth / BLK_TAGS_PER_LONG; + memcpy(bqt->tag_map, bqt->tag_map, bits * sizeof(unsigned long)); + + kfree(tag_index); + kfree(tag_map); + return 0; +} + +/** * blk_queue_end_tag - end tag operations for a request * @q: the request queue for the device * @tag: the tag that has completed @@ -524,7 +581,7 @@ BUG_ON(tag == -1); - if (unlikely(tag >= bqt->max_depth)) + if (unlikely(tag >= bqt->real_max_depth)) return; if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) { diff -urN linux-2.5.70-bk1/drivers/ide/ide-cd.c linux-2.5.70-bk2/drivers/ide/ide-cd.c --- linux-2.5.70-bk1/drivers/ide/ide-cd.c 2003-05-26 18:00:39.000000000 -0700 +++ linux-2.5.70-bk2/drivers/ide/ide-cd.c 2003-05-28 04:37:02.000000000 -0700 @@ -2993,12 +2993,6 @@ long block = (long)rq->hard_sector / (hard_sect >> 9); unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9); - BUG_ON(sizeof(rq->hard_sector) > 4 && (rq->hard_sector >> 32)); - - if (rq->hard_nr_sectors != rq->nr_sectors) { - printk(KERN_ERR "ide-cd: hard_nr_sectors differs from nr_sectors! %lu %lu\n", - rq->nr_sectors, rq->hard_nr_sectors); - } memset(rq->cmd, 0, sizeof(rq->cmd)); if (rq_data_dir(rq) == READ) diff -urN linux-2.5.70-bk1/drivers/net/setup.c linux-2.5.70-bk2/drivers/net/setup.c --- linux-2.5.70-bk1/drivers/net/setup.c 2003-05-26 18:00:58.000000000 -0700 +++ linux-2.5.70-bk2/drivers/net/setup.c 2003-05-28 04:37:02.000000000 -0700 @@ -15,7 +15,6 @@ extern int fec_enet_init(void); extern int sdla_setup(void); extern int sdla_c_setup(void); -extern int lmc_setup(void); /* * Devices in this list must do new style probing. That is they must @@ -45,9 +44,6 @@ #if defined(CONFIG_FEC_ENET) {fec_enet_init, 0}, #endif -#if defined(CONFIG_LANMEDIA) - {lmc_setup, 0}, -#endif {NULL, 0}, }; diff -urN linux-2.5.70-bk1/drivers/net/sunqe.c linux-2.5.70-bk2/drivers/net/sunqe.c --- linux-2.5.70-bk1/drivers/net/sunqe.c 2003-05-26 18:00:38.000000000 -0700 +++ linux-2.5.70-bk2/drivers/net/sunqe.c 2003-05-28 04:37:02.000000000 -0700 @@ -124,7 +124,6 @@ qb->qe_rxd[i].rx_flags = (RXD_OWN | ((RXD_PKT_SZ) & RXD_LENGTH)); } - return IRQ_HANDLED; } static int qe_init(struct sunqe *qep, int from_irq) diff -urN linux-2.5.70-bk1/drivers/net/wan/lmc/lmc_main.c linux-2.5.70-bk2/drivers/net/wan/lmc/lmc_main.c --- linux-2.5.70-bk1/drivers/net/wan/lmc/lmc_main.c 2003-05-28 04:36:58.000000000 -0700 +++ linux-2.5.70-bk2/drivers/net/wan/lmc/lmc_main.c 2003-05-28 04:37:02.000000000 -0700 @@ -1876,9 +1876,7 @@ return (struct net_device_stats *) &sc->stats; } -#ifdef MODULE - -int init_module (void) /*fold00*/ +static int __init init_lmc(void) { printk ("lmc: module loaded\n"); @@ -1889,7 +1887,7 @@ return 0; } -void cleanup_module (void) /*fold00*/ +static void __exit exit_lmc(void) { struct net_device *dev, *next; lmc_softc_t *sc; @@ -1931,7 +1929,9 @@ Lmc_root_dev = NULL; printk ("lmc module unloaded\n"); } -#endif + +module_init(init_lmc); +module_exit(exit_lmc); unsigned lmc_mii_readreg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno) /*fold00*/ { diff -urN linux-2.5.70-bk1/drivers/usb/media/pwc-if.c linux-2.5.70-bk2/drivers/usb/media/pwc-if.c --- linux-2.5.70-bk1/drivers/usb/media/pwc-if.c 2003-05-26 18:00:45.000000000 -0700 +++ linux-2.5.70-bk2/drivers/usb/media/pwc-if.c 2003-05-28 04:37:02.000000000 -0700 @@ -1804,7 +1804,7 @@ } memcpy(vdev, &pwc_template, sizeof(pwc_template)); strcpy(vdev->name, name); - SET_MODULE_OWNER(vdev); + vdev->owner = THIS_MODULE; pdev->vdev = vdev; vdev->priv = pdev; diff -urN linux-2.5.70-bk1/drivers/video/i810/i810.h linux-2.5.70-bk2/drivers/video/i810/i810.h --- linux-2.5.70-bk1/drivers/video/i810/i810.h 2003-05-26 18:00:57.000000000 -0700 +++ linux-2.5.70-bk2/drivers/video/i810/i810.h 2003-05-28 04:37:02.000000000 -0700 @@ -203,8 +203,8 @@ #define LOCKUP 8 struct gtt_data { - agp_memory *i810_fb_memory; - agp_memory *i810_cursor_memory; + struct agp_memory *i810_fb_memory; + struct agp_memory *i810_cursor_memory; }; struct mode_registers { diff -urN linux-2.5.70-bk1/drivers/video/i810/i810_main.c linux-2.5.70-bk2/drivers/video/i810/i810_main.c --- linux-2.5.70-bk1/drivers/video/i810/i810_main.c 2003-05-26 18:00:28.000000000 -0700 +++ linux-2.5.70-bk2/drivers/video/i810/i810_main.c 2003-05-28 04:37:02.000000000 -0700 @@ -1926,11 +1926,6 @@ #ifndef MODULE int __init i810fb_init(void) { - if (agp_init()) { - printk("i810fb_init: cannot initialize agpgart\n"); - return -ENODEV; - } - if (agp_intel_init()) { printk("i810fb_init: cannot initialize intel agpgart\n"); return -ENODEV; diff -urN linux-2.5.70-bk1/drivers/video/i810/i810_main.h linux-2.5.70-bk2/drivers/video/i810/i810_main.h --- linux-2.5.70-bk1/drivers/video/i810/i810_main.h 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.70-bk2/drivers/video/i810/i810_main.h 2003-05-28 04:37:02.000000000 -0700 @@ -111,7 +111,6 @@ /* Initialization */ static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par); extern int __init agp_intel_init(void); -extern int __init agp_init(void); /* Video Timings */ diff -urN linux-2.5.70-bk1/drivers/video/sis/sis_main.c linux-2.5.70-bk2/drivers/video/sis/sis_main.c --- linux-2.5.70-bk1/drivers/video/sis/sis_main.c 2003-05-26 18:00:43.000000000 -0700 +++ linux-2.5.70-bk2/drivers/video/sis/sis_main.c 2003-05-28 04:37:02.000000000 -0700 @@ -2868,8 +2868,8 @@ unsigned long *write_port = 0; SIS_CMDTYPE cmd_type; #ifndef AGPOFF - agp_kern_info *agp_info; - agp_memory *agp; + struct agp_kern_info *agp_info; + struct agp_memory *agp; u32 agp_phys; #endif #endif @@ -2946,8 +2946,8 @@ #ifndef AGPOFF if (sisfb_queuemode == AGP_CMD_QUEUE) { - agp_info = vmalloc(sizeof(agp_kern_info)); - memset((void*)agp_info, 0x00, sizeof(agp_kern_info)); + agp_info = vmalloc(sizeof(*agp_info)); + memset((void*)agp_info, 0x00, sizeof(*agp_info)); agp_copy_info(agp_info); agp_backend_acquire(); diff -urN linux-2.5.70-bk1/fs/char_dev.c linux-2.5.70-bk2/fs/char_dev.c --- linux-2.5.70-bk1/fs/char_dev.c 2003-05-26 18:00:28.000000000 -0700 +++ linux-2.5.70-bk2/fs/char_dev.c 2003-05-28 04:37:02.000000000 -0700 @@ -89,6 +89,8 @@ if (cd == NULL) return ERR_PTR(-ENOMEM); + memset(cd, 0, sizeof(struct char_device_struct)); + write_lock_irq(&chrdevs_lock); /* temporary */ diff -urN linux-2.5.70-bk1/fs/cifs/cifsfs.c linux-2.5.70-bk2/fs/cifs/cifsfs.c --- linux-2.5.70-bk1/fs/cifs/cifsfs.c 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.70-bk2/fs/cifs/cifsfs.c 2003-05-28 04:37:02.000000000 -0700 @@ -94,13 +94,17 @@ sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ inode = iget(sb, ROOT_I); - if (!inode) + if (!inode) { + rc = -ENOMEM; goto out_no_root; + } sb->s_root = d_alloc_root(inode); - if (!sb->s_root) + if (!sb->s_root) { + rc = -ENOMEM; goto out_no_root; + } return 0; @@ -114,7 +118,7 @@ unload_nls(cifs_sb->local_nls); if(cifs_sb) kfree(cifs_sb); - return -EINVAL; + return rc; } void @@ -332,7 +336,7 @@ .release = cifs_close, .lock = cifs_lock, .fsync = cifs_fsync, - .flush = cifs_flush, + .flush = cifs_flush, .mmap = cifs_file_mmap, .sendfile = generic_file_sendfile, }; diff -urN linux-2.5.70-bk1/fs/cifs/connect.c linux-2.5.70-bk2/fs/cifs/connect.c --- linux-2.5.70-bk1/fs/cifs/connect.c 2003-05-26 18:00:57.000000000 -0700 +++ linux-2.5.70-bk2/fs/cifs/connect.c 2003-05-28 04:37:02.000000000 -0700 @@ -346,6 +346,7 @@ { char *value; char *data; + int temp_len; memset(vol,0,sizeof(struct smb_vol)); vol->linux_uid = current->uid; /* current->euid instead? */ @@ -398,8 +399,9 @@ "CIFS: invalid path to network resource\n"); return 1; /* needs_arg; */ } - if (strnlen(value, 300) < 300) { - vol->UNC = value; + if ((temp_len = strnlen(value, 300)) < 300) { + vol->UNC = kmalloc(GFP_KERNEL, temp_len); + strcpy(vol->UNC,value); if (strncmp(vol->UNC, "//", 2) == 0) { vol->UNC[0] = '\\'; vol->UNC[1] = '\\'; @@ -472,8 +474,9 @@ printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n"); return 1; } - if (strnlen(devname, 300) < 300) { - vol->UNC = devname; + if ((temp_len = strnlen(devname, 300)) < 300) { + vol->UNC = kmalloc(GFP_KERNEL, temp_len); + strcpy(vol->UNC,devname); if (strncmp(vol->UNC, "//", 2) == 0) { vol->UNC[0] = '\\'; vol->UNC[1] = '\\'; @@ -812,6 +815,8 @@ cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); if (parse_mount_options(mount_data, devname, &volume_info)) { + if(volume_info.UNC) + kfree(volume_info.UNC); FreeXid(xid); return -EINVAL; } @@ -852,6 +857,8 @@ ("Error connecting to IPv4 socket. Aborting operation")); if(csocket != NULL) sock_release(csocket); + if(volume_info.UNC) + kfree(volume_info.UNC); FreeXid(xid); return rc; } @@ -860,6 +867,8 @@ if (srvTcp == NULL) { rc = -ENOMEM; sock_release(csocket); + if(volume_info.UNC) + kfree(volume_info.UNC); FreeXid(xid); return rc; } else { @@ -943,6 +952,8 @@ "", cifs_sb-> local_nls); + if(volume_info.UNC) + kfree(volume_info.UNC); FreeXid(xid); return -ENODEV; } else { @@ -995,7 +1006,8 @@ if (tcon->ses->capabilities & CAP_UNIX) CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls); } - + if(volume_info.UNC) + kfree(volume_info.UNC); FreeXid(xid); return rc; } @@ -2293,7 +2305,7 @@ length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); /* skip service field (NB: this field is always ASCII) */ bcc_ptr += length + 1; - strncpy(tcon->treeName, tree, MAX_TREE_SIZE); + strncpy(tcon->treeName, tree, MAX_TREE_SIZE); if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) { length = UniStrnlen((wchar_t *) bcc_ptr, 512); if (((long) bcc_ptr + (2 * length)) - diff -urN linux-2.5.70-bk1/fs/cifs/netmisc.c linux-2.5.70-bk2/fs/cifs/netmisc.c --- linux-2.5.70-bk1/fs/cifs/netmisc.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.70-bk2/fs/cifs/netmisc.c 2003-05-28 04:37:02.000000000 -0700 @@ -46,7 +46,7 @@ const struct smb_to_posix_error mapping_table_ERRDOS[] = { {ERRbadfunc, -EINVAL}, {ERRbadfile, -ENOENT}, - {ERRbadpath, -ENOENT}, + {ERRbadpath, -ENOTDIR}, {ERRnofids, -EMFILE}, {ERRnoaccess, -EACCES}, {ERRbadfid, -EBADF}, @@ -63,26 +63,29 @@ {ERRnofiles, -ENOENT}, {ERRbadshare, -ETXTBSY}, {ERRlock, -EACCES}, - {ERRfilexists, -EINVAL}, + {ERRunsup, -EINVAL}, + {ERRnosuchshare,-ENXIO}, + {ERRfilexists, -EEXIST}, {ERRinvparm, -EINVAL}, {ERRdiskfull, -ENOSPC}, - {ERRinvnum, -EINVAL}, + {ERRinvname, -ENOENT}, {ERRdirnotempty, -ENOTEMPTY}, {ERRnotlocked, -ENOLCK}, {ERRalreadyexists, -EEXIST}, {ERRmoredata, -EOVERFLOW}, {ErrQuota, -EDQUOT}, {ErrNotALink, -ENOLINK}, + {ERRnetlogonNotStarted,-ENOPROTOOPT}, {0, 0} }; const struct smb_to_posix_error mapping_table_ERRSRV[] = { {ERRerror, -EIO}, - {ERRbadpw, -EACCES}, + {ERRbadpw, -EPERM}, {ERRbadtype, -EREMOTE}, {ERRaccess, -EACCES}, {ERRinvtid, -ENXIO}, - {ERRinvnetname, -ENOENT}, + {ERRinvnetname, -ENODEV}, {ERRinvdevice, -ENXIO}, {ERRqfull, -ENOSPC}, {ERRqtoobig, -ENOSPC}, @@ -617,7 +620,7 @@ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, { ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, { ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, { - ERRDOS, 2455, NT_STATUS_NETLOGON_NOT_STARTED}, { + ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, { ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, { ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, { ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, { diff -urN linux-2.5.70-bk1/fs/cifs/smberr.h linux-2.5.70-bk2/fs/cifs/smberr.h --- linux-2.5.70-bk1/fs/cifs/smberr.h 2003-05-26 18:00:42.000000000 -0700 +++ linux-2.5.70-bk2/fs/cifs/smberr.h 2003-05-28 04:37:02.000000000 -0700 @@ -59,7 +59,7 @@ #define ERRfilexists 80 /* The file named in the request already exists. */ #define ERRinvparm 87 #define ERRdiskfull 112 -#define ERRinvnum 123 +#define ERRinvname 123 #define ERRdirnotempty 145 #define ERRnotlocked 158 #define ERRalreadyexists 183 @@ -109,4 +109,5 @@ #define ERRbadclient 2240 #define ERRbadLogonTime 2241 #define ERRpasswordExpired 2242 +#define ERRnetlogonNotStarted 2455 #define ERRnosupport 0xFFFF diff -urN linux-2.5.70-bk1/fs/fat/cache.c linux-2.5.70-bk2/fs/fat/cache.c --- linux-2.5.70-bk1/fs/fat/cache.c 2003-05-26 18:00:47.000000000 -0700 +++ linux-2.5.70-bk2/fs/fat/cache.c 2003-05-28 04:37:02.000000000 -0700 @@ -12,9 +12,6 @@ #include #include -static struct fat_cache *fat_cache,cache[FAT_CACHE]; -static spinlock_t fat_cache_lock = SPIN_LOCK_UNLOCKED; - int __fat_access(struct super_block *sb, int nr, int new_value) { struct msdos_sb_info *sbi = MSDOS_SB(sb); @@ -133,148 +130,163 @@ return next; } -void fat_cache_init(void) +void fat_cache_init(struct super_block *sb) { - static int initialized; + struct msdos_sb_info *sbi = MSDOS_SB(sb); int count; - spin_lock(&fat_cache_lock); - if (initialized) { - spin_unlock(&fat_cache_lock); - return; - } - fat_cache = &cache[0]; - for (count = 0; count < FAT_CACHE; count++) { - cache[count].sb = NULL; - cache[count].next = count == FAT_CACHE-1 ? NULL : - &cache[count+1]; + spin_lock_init(&sbi->cache_lock); + + for (count = 0; count < FAT_CACHE_NR - 1; count++) { + sbi->cache_array[count].start_cluster = 0; + sbi->cache_array[count].next = &sbi->cache_array[count + 1]; } - initialized = 1; - spin_unlock(&fat_cache_lock); + sbi->cache_array[count].start_cluster = 0; + sbi->cache_array[count].next = NULL; + sbi->cache = sbi->cache_array; } - -void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu) +void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu) { + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); struct fat_cache *walk; - int first = MSDOS_I(inode)->i_start; + int first; + BUG_ON(cluster == 0); + + first = MSDOS_I(inode)->i_start; if (!first) return; - spin_lock(&fat_cache_lock); - for (walk = fat_cache; walk; walk = walk->next) - if (inode->i_sb == walk->sb - && walk->start_cluster == first + + spin_lock(&sbi->cache_lock); + + if (MSDOS_I(inode)->disk_cluster && + MSDOS_I(inode)->file_cluster <= cluster) { + *d_clu = MSDOS_I(inode)->disk_cluster; + *f_clu = MSDOS_I(inode)->file_cluster; + } + + for (walk = sbi->cache; walk; walk = walk->next) { + if (walk->start_cluster == first && walk->file_cluster <= cluster && walk->file_cluster > *f_clu) { *d_clu = walk->disk_cluster; + *f_clu = walk->file_cluster; #ifdef DEBUG -printk("cache hit: %d (%d)\n",walk->file_cluster,*d_clu); + printk("cache hit: %d (%d)\n", *f_clu, *d_clu); #endif - if ((*f_clu = walk->file_cluster) == cluster) { - spin_unlock(&fat_cache_lock); - return; - } + if (*f_clu == cluster) + goto out; } - spin_unlock(&fat_cache_lock); + } #ifdef DEBUG -printk("cache miss\n"); + printk("cache miss\n"); #endif +out: + spin_unlock(&sbi->cache_lock); } - #ifdef DEBUG -static void list_cache(void) +static void list_cache(struct super_block *sb) { + struct msdos_sb_info *sbi = MSDOS_SB(sb); struct fat_cache *walk; - for (walk = fat_cache; walk; walk = walk->next) { - if (walk->sb) - printk("<%s,%d>(%d,%d) ", walk->sb->s_id, + for (walk = sbi->cache; walk; walk = walk->next) { + if (walk->start_cluster) + printk("<%s,%d>(%d,%d) ", sb->s_id, walk->start_cluster, walk->file_cluster, walk->disk_cluster); - else printk("-- "); + else + printk("-- "); } printk("\n"); } #endif - -void fat_cache_add(struct inode *inode,int f_clu,int d_clu) +/* + * Cache invalidation occurs rarely, thus the LRU chain is not updated. It + * fixes itself after a while. + */ +static void __fat_cache_inval_inode(struct inode *inode) { - struct fat_cache *walk,*last; + struct fat_cache *walk; int first = MSDOS_I(inode)->i_start; + MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0; + for (walk = MSDOS_SB(inode->i_sb)->cache; walk; walk = walk->next) + if (walk->start_cluster == first) + walk->start_cluster = 0; +} + +void fat_cache_inval_inode(struct inode *inode) +{ + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); + spin_lock(&sbi->cache_lock); + __fat_cache_inval_inode(inode); + spin_unlock(&sbi->cache_lock); +} + +void fat_cache_add(struct inode *inode, int f_clu, int d_clu) +{ + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); + struct fat_cache *walk, *last; + int first, prev_f_clu, prev_d_clu; + + first = MSDOS_I(inode)->i_start; + if (!first) + return; last = NULL; - spin_lock(&fat_cache_lock); - for (walk = fat_cache; walk->next; walk = (last = walk)->next) - if (inode->i_sb == walk->sb - && walk->start_cluster == first - && walk->file_cluster == f_clu) { + spin_lock(&sbi->cache_lock); + + if (MSDOS_I(inode)->file_cluster == f_clu) + goto out; + else { + prev_f_clu = MSDOS_I(inode)->file_cluster; + prev_d_clu = MSDOS_I(inode)->disk_cluster; + MSDOS_I(inode)->file_cluster = f_clu; + MSDOS_I(inode)->disk_cluster = d_clu; + if (prev_f_clu == 0) + goto out; + f_clu = prev_f_clu; + d_clu = prev_d_clu; + } + + for (walk = sbi->cache; walk->next; walk = (last = walk)->next) { + if (walk->start_cluster == first && + walk->file_cluster == f_clu) { if (walk->disk_cluster != d_clu) { printk(KERN_ERR "FAT: cache corruption" " (ino %lu)\n", inode->i_ino); - spin_unlock(&fat_cache_lock); - fat_cache_inval_inode(inode); - return; + __fat_cache_inval_inode(inode); + goto out; } + if (last == NULL) + goto out; + /* update LRU */ - if (last == NULL) { - spin_unlock(&fat_cache_lock); - return; - } last->next = walk->next; - walk->next = fat_cache; - fat_cache = walk; + walk->next = sbi->cache; + sbi->cache = walk; #ifdef DEBUG -list_cache(); + list_cache(); #endif - spin_unlock(&fat_cache_lock); - return; + goto out; } - walk->sb = inode->i_sb; + } walk->start_cluster = first; walk->file_cluster = f_clu; walk->disk_cluster = d_clu; last->next = NULL; - walk->next = fat_cache; - fat_cache = walk; - spin_unlock(&fat_cache_lock); + walk->next = sbi->cache; + sbi->cache = walk; #ifdef DEBUG -list_cache(); + list_cache(); #endif +out: + spin_unlock(&sbi->cache_lock); } - -/* Cache invalidation occurs rarely, thus the LRU chain is not updated. It - fixes itself after a while. */ - -void fat_cache_inval_inode(struct inode *inode) -{ - struct fat_cache *walk; - int first = MSDOS_I(inode)->i_start; - - spin_lock(&fat_cache_lock); - for (walk = fat_cache; walk; walk = walk->next) - if (walk->sb == inode->i_sb - && walk->start_cluster == first) - walk->sb = NULL; - spin_unlock(&fat_cache_lock); -} - - -void fat_cache_inval_dev(struct super_block *sb) -{ - struct fat_cache *walk; - - spin_lock(&fat_cache_lock); - for (walk = fat_cache; walk; walk = walk->next) - if (walk->sb == sb) - walk->sb = 0; - spin_unlock(&fat_cache_lock); -} - - static int fat_get_cluster(struct inode *inode, int cluster) { struct super_block *sb = inode->i_sb; @@ -302,32 +314,36 @@ return nr; } -int fat_bmap(struct inode *inode, int sector) +int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys) { struct super_block *sb = inode->i_sb; struct msdos_sb_info *sbi = MSDOS_SB(sb); - int cluster, offset, last_block; + sector_t last_block; + int cluster, offset; + *phys = 0; if ((sbi->fat_bits != 32) && (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) && !MSDOS_I(inode)->i_start))) { - if (sector >= sbi->dir_entries >> sbi->dir_per_block_bits) - return 0; - return sector + sbi->dir_start; + if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits)) + *phys = sector + sbi->dir_start; + return 0; } last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1)) >> sb->s_blocksize_bits; if (sector >= last_block) return 0; - cluster = sector / sbi->cluster_size; - offset = sector % sbi->cluster_size; + cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits); + offset = sector & (sbi->cluster_size - 1); cluster = fat_get_cluster(inode, cluster); if (cluster < 0) return cluster; - else if (!cluster) - return 0; - return (cluster - 2) * sbi->cluster_size + sbi->data_start + offset; + else if (cluster) { + *phys = ((sector_t)cluster - 2) * sbi->cluster_size + + sbi->data_start + offset; + } + return 0; } diff -urN linux-2.5.70-bk1/fs/fat/dir.c linux-2.5.70-bk2/fs/fat/dir.c --- linux-2.5.70-bk1/fs/fat/dir.c 2003-05-26 18:00:21.000000000 -0700 +++ linux-2.5.70-bk2/fs/fat/dir.c 2003-05-28 04:37:02.000000000 -0700 @@ -191,11 +191,11 @@ int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate; int utf8 = MSDOS_SB(sb)->options.utf8; unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname; - int ino, chl, i, j, last_u, res = 0; - loff_t cpos = 0; + int chl, i, j, last_u, res = 0; + loff_t i_pos, cpos = 0; while(1) { - if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1) + if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1) goto EODir; parse_record: long_slots = 0; @@ -246,7 +246,7 @@ if (ds->id & 0x40) { unicode[offset + 13] = 0; } - if (fat_get_entry(inode,&cpos,&bh,&de,&ino)<0) + if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos)<0) goto EODir; if (slot == 0) break; @@ -358,14 +358,15 @@ int utf8 = MSDOS_SB(sb)->options.utf8; int nocase = MSDOS_SB(sb)->options.nocase; unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname; - int ino, inum, chi, chl, i, i2, j, last, last_u, dotoffset = 0; - loff_t cpos; + unsigned long inum; + int chi, chl, i, i2, j, last, last_u, dotoffset = 0; + loff_t i_pos, cpos; int ret = 0; lock_kernel(); cpos = filp->f_pos; -/* Fake . and .. for the root directory. */ + /* Fake . and .. for the root directory. */ if (inode->i_ino == MSDOS_ROOT_INO) { while (cpos < 2) { if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO, DT_DIR) < 0) @@ -387,7 +388,7 @@ bh = NULL; GetNew: long_slots = 0; - if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1) + if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1) goto EODir; /* Check for long filename entry */ if (isvfat) { @@ -445,7 +446,7 @@ if (ds->id & 0x40) { unicode[offset + 13] = 0; } - if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1) + if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1) goto EODir; if (slot == 0) break; @@ -533,7 +534,7 @@ else if (!memcmp(de->name,MSDOS_DOTDOT,11)) { inum = parent_ino(filp->f_dentry); } else { - struct inode *tmp = fat_iget(sb, ino); + struct inode *tmp = fat_iget(sb, i_pos); if (tmp) { inum = tmp->i_ino; iput(tmp); @@ -591,23 +592,23 @@ return fat_readdirx(inode, filp, dirent, filldir, 0, 0); } -static int vfat_ioctl_fill( - void * buf, - const char * name, - int name_len, - loff_t offset, - ino_t ino, - unsigned int d_type) +struct fat_ioctl_filldir_callback { + struct dirent __user *dirent; + int result; +}; + +static int fat_ioctl_filldir(void *__buf, const char * name, int name_len, + loff_t offset, ino_t ino, unsigned int d_type) { - struct dirent *d1 = (struct dirent *)buf; - struct dirent *d2 = d1 + 1; + struct fat_ioctl_filldir_callback *buf = __buf; + struct dirent __user *d1 = buf->dirent; + struct dirent __user *d2 = d1 + 1; int len, slen; int dotdir; - get_user(len, &d1->d_reclen); - if (len != 0) { - return -1; - } + if (buf->result) + return -EINVAL; + buf->result++; if ((name_len == 1 && name[0] == '.') || (name_len == 2 && name[0] == '.' && name[1] == '.')) { @@ -618,73 +619,79 @@ len = strlen(name); } if (len != name_len) { - copy_to_user(d2->d_name, name, len); - put_user(0, d2->d_name + len); - put_user(len, &d2->d_reclen); - put_user(ino, &d2->d_ino); - put_user(offset, &d2->d_off); slen = name_len - len; - copy_to_user(d1->d_name, name+len+1, slen); - put_user(0, d1->d_name+slen); - put_user(slen, &d1->d_reclen); + if (copy_to_user(d2->d_name, name, len) || + put_user(0, d2->d_name + len) || + put_user(len, &d2->d_reclen) || + put_user(ino, &d2->d_ino) || + put_user(offset, &d2->d_off) || + copy_to_user(d1->d_name, name+len+1, slen) || + put_user(0, d1->d_name+slen) || + put_user(slen, &d1->d_reclen)) + goto efault; } else { - put_user(0, d2->d_name); - put_user(0, &d2->d_reclen); - copy_to_user(d1->d_name, name, len); - put_user(0, d1->d_name+len); - put_user(len, &d1->d_reclen); + if (put_user(0, d2->d_name) || + put_user(0, &d2->d_reclen) || + copy_to_user(d1->d_name, name, len) || + put_user(0, d1->d_name+len) || + put_user(len, &d1->d_reclen)) + goto efault; } - return 0; +efault: + buf->result = -EFAULT; + return -EFAULT; } int fat_dir_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { - int err; + struct fat_ioctl_filldir_callback buf; + struct dirent __user *d1 = (struct dirent *)arg; + int ret, shortname, both; + + if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2]))) + return -EFAULT; /* - * We want to provide an interface for Samba to be able - * to get the short filename for a given long filename. - * Samba should use this ioctl instead of readdir() to - * get the information it needs. + * Yes, we don't need this put_user() absolutely. However old + * code didn't return the right value. So, app use this value, + * in order to check whether it is EOF. */ + if (put_user(0, &d1->d_reclen)) + return -EFAULT; + + buf.dirent = d1; + buf.result = 0; switch (cmd) { - case VFAT_IOCTL_READDIR_BOTH: { - struct dirent *d1 = (struct dirent *)arg; - err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2])); - if (err) - return err; - put_user(0, &d1->d_reclen); - return fat_readdirx(inode,filp,(void *)arg, - vfat_ioctl_fill, 0, 1); - } - case VFAT_IOCTL_READDIR_SHORT: { - struct dirent *d1 = (struct dirent *)arg; - put_user(0, &d1->d_reclen); - err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2])); - if (err) - return err; - return fat_readdirx(inode,filp,(void *)arg, - vfat_ioctl_fill, 1, 1); - } + case VFAT_IOCTL_READDIR_SHORT: + shortname = 1; + both = 1; + break; + case VFAT_IOCTL_READDIR_BOTH: + shortname = 0; + both = 1; + break; default: return -EINVAL; } - - return 0; + ret = fat_readdirx(inode, filp, &buf, fat_ioctl_filldir, + shortname, both); + if (ret >= 0) + ret = buf.result; + return ret; } /***** See if directory is empty */ int fat_dir_empty(struct inode *dir) { - loff_t pos; + loff_t pos, i_pos; struct buffer_head *bh; struct msdos_dir_entry *de; - int ino,result = 0; + int result = 0; pos = 0; bh = NULL; - while (fat_get_entry(dir,&pos,&bh,&de,&ino) > -1) { + while (fat_get_entry(dir,&pos,&bh,&de,&i_pos) > -1) { /* Ignore vfat longname entries */ if (de->attr == ATTR_EXT) continue; @@ -703,7 +710,7 @@ /* This assumes that size of cluster is above the 32*slots */ int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh, - struct msdos_dir_entry **de, int *ino) + struct msdos_dir_entry **de, loff_t *i_pos) { struct super_block *sb = dir->i_sb; loff_t offset, curr; @@ -713,7 +720,7 @@ offset = curr = 0; *bh = NULL; row = 0; - while (fat_get_entry(dir, &curr, bh, de, ino) > -1) { + while (fat_get_entry(dir, &curr, bh, de, i_pos) > -1) { /* check the maximum size of directory */ if (curr >= FAT_MAX_DIR_SIZE) { brelse(*bh); @@ -735,7 +742,7 @@ return PTR_ERR(new_bh); brelse(new_bh); do { - fat_get_entry(dir, &curr, bh, de, ino); + fat_get_entry(dir, &curr, bh, de, i_pos); } while (++row < slots); return offset; diff -urN linux-2.5.70-bk1/fs/fat/file.c linux-2.5.70-bk2/fs/fat/file.c --- linux-2.5.70-bk1/fs/fat/file.c 2003-05-26 18:00:26.000000000 -0700 +++ linux-2.5.70-bk2/fs/fat/file.c 2003-05-28 04:37:02.000000000 -0700 @@ -32,11 +32,12 @@ struct buffer_head *bh_result, int create) { struct super_block *sb = inode->i_sb; - unsigned long phys; + sector_t phys; + int err; - phys = fat_bmap(inode, iblock); - if (phys < 0) - return phys; + err = fat_bmap(inode, iblock, &phys); + if (err) + return err; if (phys) { map_bh(bh_result, sb, phys); return 0; @@ -55,9 +56,9 @@ return error; } MSDOS_I(inode)->mmu_private += sb->s_blocksize; - phys = fat_bmap(inode, iblock); - if (phys < 0) - return phys; + err = fat_bmap(inode, iblock, &phys); + if (err) + return err; if (!phys) BUG(); set_buffer_new(bh_result); diff -urN linux-2.5.70-bk1/fs/fat/inode.c linux-2.5.70-bk2/fs/fat/inode.c --- linux-2.5.70-bk1/fs/fat/inode.c 2003-05-26 18:00:39.000000000 -0700 +++ linux-2.5.70-bk2/fs/fat/inode.c 2003-05-28 04:37:02.000000000 -0700 @@ -60,17 +60,17 @@ } } -static inline unsigned long fat_hash(struct super_block *sb, int i_pos) +static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) { unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb; tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2); return tmp & FAT_HASH_MASK; } -void fat_attach(struct inode *inode, int i_pos) +void fat_attach(struct inode *inode, loff_t i_pos) { spin_lock(&fat_inode_lock); - MSDOS_I(inode)->i_location = i_pos; + MSDOS_I(inode)->i_pos = i_pos; list_add(&MSDOS_I(inode)->i_fat_hash, fat_inode_hashtable + fat_hash(inode->i_sb, i_pos)); spin_unlock(&fat_inode_lock); @@ -79,12 +79,12 @@ void fat_detach(struct inode *inode) { spin_lock(&fat_inode_lock); - MSDOS_I(inode)->i_location = 0; + MSDOS_I(inode)->i_pos = 0; list_del_init(&MSDOS_I(inode)->i_fat_hash); spin_unlock(&fat_inode_lock); } -struct inode *fat_iget(struct super_block *sb, int i_pos) +struct inode *fat_iget(struct super_block *sb, loff_t i_pos) { struct list_head *p = fat_inode_hashtable + fat_hash(sb, i_pos); struct list_head *walk; @@ -96,7 +96,7 @@ i = list_entry(walk, struct msdos_inode_info, i_fat_hash); if (i->vfs_inode.i_sb != sb) continue; - if (i->i_location != i_pos) + if (i->i_pos != i_pos) continue; inode = igrab(&i->vfs_inode); if (inode) @@ -109,11 +109,11 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de); struct inode *fat_build_inode(struct super_block *sb, - struct msdos_dir_entry *de, int ino, int *res) + struct msdos_dir_entry *de, loff_t i_pos, int *res) { struct inode *inode; *res = 0; - inode = fat_iget(sb, ino); + inode = fat_iget(sb, i_pos); if (inode) goto out; inode = new_inode(sb); @@ -128,7 +128,7 @@ inode = NULL; goto out; } - fat_attach(inode, ino); + fat_attach(inode, i_pos); insert_inode_hash(inode); out: return inode; @@ -160,7 +160,6 @@ struct msdos_sb_info *sbi = MSDOS_SB(sb); fat_clusters_flush(sb); - fat_cache_inval_dev(sb); if (sbi->nls_disk) { unload_nls(sbi->nls_disk); sbi->nls_disk = NULL; @@ -500,7 +499,7 @@ struct msdos_sb_info *sbi = MSDOS_SB(sb); int error; - MSDOS_I(inode)->i_location = 0; + MSDOS_I(inode)->i_pos = 0; inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; inode->i_version++; @@ -537,9 +536,10 @@ * 0/ i_ino - for fast, reliable lookup if still in the cache * 1/ i_generation - to see if i_ino is still valid * bit 0 == 0 iff directory - * 2/ i_location - if ino has changed, but still in cache - * 3/ i_logstart - to semi-verify inode found at i_location - * 4/ parent->i_logstart - maybe used to hunt for the file on disc + * 2/ i_pos - if ino has changed, but still in cache (hi) + * 3/ i_pos - if ino has changed, but still in cache (low) + * 4/ i_logstart - to semi-verify inode found at i_location + * 5/ parent->i_logstart - maybe used to hunt for the file on disc * */ @@ -551,7 +551,7 @@ if (fhtype != 3) return ERR_PTR(-ESTALE); - if (len < 5) + if (len < 6) return ERR_PTR(-ESTALE); return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context); @@ -570,13 +570,15 @@ inode = NULL; } if (!inode) { - /* try 2 - see if i_location is in F-d-c + loff_t i_pos = ((loff_t)fh[2] << 32) | fh[3]; + + /* try 2 - see if i_pos is in F-d-c * require i_logstart to be the same * Will fail if you truncate and then re-write */ - inode = fat_iget(sb, fh[2]); - if (inode && MSDOS_I(inode)->i_logstart != fh[3]) { + inode = fat_iget(sb, i_pos); + if (inode && MSDOS_I(inode)->i_logstart != fh[4]) { iput(inode); inode = NULL; } @@ -616,15 +618,16 @@ int len = *lenp; struct inode *inode = de->d_inode; - if (len < 5) + if (len < 6) return 255; /* no room */ - *lenp = 5; + *lenp = 6; fh[0] = inode->i_ino; fh[1] = inode->i_generation; - fh[2] = MSDOS_I(inode)->i_location; - fh[3] = MSDOS_I(inode)->i_logstart; + fh[2] = (__u32)(MSDOS_I(inode)->i_pos >> 32); + fh[3] = (__u32)MSDOS_I(inode)->i_pos; + fh[4] = MSDOS_I(inode)->i_logstart; spin_lock(&de->d_lock); - fh[4] = MSDOS_I(de->d_parent->d_inode)->i_logstart; + fh[5] = MSDOS_I(de->d_parent->d_inode)->i_logstart; spin_unlock(&de->d_lock); return 3; } @@ -635,15 +638,15 @@ struct msdos_dir_entry *de = NULL; struct dentry *parent = NULL; int res; - int ino = 0; + loff_t i_pos = 0; struct inode *inode; lock_kernel(); - res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &ino); + res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &i_pos); if (res < 0) goto out; - inode = fat_build_inode(child->d_sb, de, ino, &res); + inode = fat_build_inode(child->d_sb, de, i_pos, &res); if (res) goto out; if (!inode) @@ -762,7 +765,7 @@ if (!parse_options(data, isvfat, &debug, &sbi->options)) goto out_fail; - fat_cache_init(); + fat_cache_init(sb); /* set up enough so that it can read an inode */ init_MUTEX(&sbi->fat_lock); @@ -1098,7 +1101,8 @@ struct msdos_sb_info *sbi = MSDOS_SB(sb); int error; - MSDOS_I(inode)->i_location = 0; + MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0; + MSDOS_I(inode)->i_pos = 0; inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; inode->i_version++; @@ -1112,10 +1116,9 @@ inode->i_fop = &fat_dir_operations; MSDOS_I(inode)->i_start = CF_LE_W(de->start); - if (sbi->fat_bits == 32) { - MSDOS_I(inode)->i_start |= - (CF_LE_W(de->starthi) << 16); - } + if (sbi->fat_bits == 32) + MSDOS_I(inode)->i_start |= (CF_LE_W(de->starthi) << 16); + MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; error = fat_calc_dir_size(inode); if (error < 0) @@ -1131,10 +1134,9 @@ ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~sbi->options.fs_fmask) | S_IFREG; MSDOS_I(inode)->i_start = CF_LE_W(de->start); - if (sbi->fat_bits == 32) { - MSDOS_I(inode)->i_start |= - (CF_LE_W(de->starthi) << 16); - } + if (sbi->fat_bits == 32) + MSDOS_I(inode)->i_start |= (CF_LE_W(de->starthi) << 16); + MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; inode->i_size = CF_LE_L(de->size); inode->i_op = &fat_file_inode_operations; @@ -1168,22 +1170,22 @@ struct super_block *sb = inode->i_sb; struct buffer_head *bh; struct msdos_dir_entry *raw_entry; - unsigned int i_pos; + loff_t i_pos; retry: - i_pos = MSDOS_I(inode)->i_location; + i_pos = MSDOS_I(inode)->i_pos; if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) { return; } lock_kernel(); if (!(bh = sb_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) { - fat_fs_panic(sb, "unable to read i-node block (ino %lu)", + fat_fs_panic(sb, "unable to read i-node block (i_pos %llu)", i_pos); unlock_kernel(); return; } spin_lock(&fat_inode_lock); - if (i_pos != MSDOS_I(inode)->i_location) { + if (i_pos != MSDOS_I(inode)->i_pos) { spin_unlock(&fat_inode_lock); brelse(bh); unlock_kernel(); diff -urN linux-2.5.70-bk1/fs/fat/misc.c linux-2.5.70-bk2/fs/fat/misc.c --- linux-2.5.70-bk1/fs/fat/misc.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.70-bk2/fs/fat/misc.c 2003-05-28 04:37:02.000000000 -0700 @@ -178,9 +178,9 @@ struct buffer_head *fat_extend_dir(struct inode *inode) { struct super_block *sb = inode->i_sb; - int nr, sector, last_sector; struct buffer_head *bh, *res = NULL; - int cluster_size = MSDOS_SB(sb)->cluster_size; + int nr, cluster_size = MSDOS_SB(sb)->cluster_size; + sector_t sector, last_sector; if (MSDOS_SB(sb)->fat_bits != 32) { if (inode->i_ino == MSDOS_ROOT_INO) @@ -191,7 +191,7 @@ if (nr < 0) return ERR_PTR(nr); - sector = MSDOS_SB(sb)->data_start + (nr - 2) * cluster_size; + sector = ((sector_t)nr - 2) * cluster_size + MSDOS_SB(sb)->data_start; last_sector = sector + cluster_size; for ( ; sector < last_sector; sector++) { if ((bh = sb_getblk(sb, sector))) { @@ -289,11 +289,13 @@ */ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh, - struct msdos_dir_entry **de, int *ino) + struct msdos_dir_entry **de, loff_t *i_pos) { struct super_block *sb = dir->i_sb; struct msdos_sb_info *sbi = MSDOS_SB(sb); - int sector, offset, iblock; + sector_t phys, iblock; + loff_t offset; + int err; next: offset = *pos; @@ -302,14 +304,14 @@ *bh = NULL; iblock = *pos >> sb->s_blocksize_bits; - sector = fat_bmap(dir, iblock); - if (sector <= 0) + err = fat_bmap(dir, iblock, &phys); + if (err || !phys) return -1; /* beyond EOF or error */ - *bh = sb_bread(sb, sector); + *bh = sb_bread(sb, phys); if (*bh == NULL) { - printk(KERN_ERR "FAT: Directory bread(block %d) failed\n", - sector); + printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n", + phys); /* skip this block */ *pos = (iblock + 1) << sb->s_blocksize_bits; goto next; @@ -318,7 +320,7 @@ offset &= sb->s_blocksize - 1; *pos += sizeof(struct msdos_dir_entry); *de = (struct msdos_dir_entry *)((*bh)->b_data + offset); - *ino = (sector << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS); + *i_pos = ((loff_t)phys << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS); return 0; } @@ -357,7 +359,7 @@ done = !IS_FREE(data[entry].name) \ && ( \ ( \ - (MSDOS_SB(sb)->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \ + (sbi->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \ ) \ | CF_LE_W(data[entry].start) \ ) == *number; @@ -374,35 +376,38 @@ (*number)++; \ } -static int raw_scan_sector(struct super_block *sb,int sector,const char *name, - int *number,int *ino,struct buffer_head **res_bh, - struct msdos_dir_entry **res_de) +static int raw_scan_sector(struct super_block *sb, sector_t sector, + const char *name, int *number, loff_t *i_pos, + struct buffer_head **res_bh, + struct msdos_dir_entry **res_de) { + struct msdos_sb_info *sbi = MSDOS_SB(sb); struct buffer_head *bh; struct msdos_dir_entry *data; int entry,start,done; - if (!(bh = sb_bread(sb,sector))) + if (!(bh = sb_bread(sb, sector))) return -EIO; data = (struct msdos_dir_entry *) bh->b_data; - for (entry = 0; entry < MSDOS_SB(sb)->dir_per_block; entry++) { + for (entry = 0; entry < sbi->dir_per_block; entry++) { /* RSS_COUNT: if (data[entry].name == name) done=true else done=false. */ if (name) { RSS_NAME } else { - if (!ino) RSS_COUNT + if (!i_pos) RSS_COUNT else { if (number) RSS_START else RSS_FREE } } if (done) { - if (ino) - *ino = sector * MSDOS_SB(sb)->dir_per_block + entry; + if (i_pos) { + *i_pos = ((loff_t)sector << sbi->dir_per_block_bits) + entry; + } start = CF_LE_W(data[entry].start); - if (MSDOS_SB(sb)->fat_bits == 32) { + if (sbi->fat_bits == 32) start |= (CF_LE_W(data[entry].starthi) << 16); - } + if (!res_bh) brelse(bh); else { @@ -422,16 +427,19 @@ * requested entry is found or the end of the directory is reached. */ -static int raw_scan_root(struct super_block *sb,const char *name,int *number,int *ino, - struct buffer_head **res_bh,struct msdos_dir_entry **res_de) +static int raw_scan_root(struct super_block *sb, const char *name, + int *number, loff_t *i_pos, + struct buffer_head **res_bh, + struct msdos_dir_entry **res_de) { int count,cluster; for (count = 0; count < MSDOS_SB(sb)->dir_entries / MSDOS_SB(sb)->dir_per_block; count++) { - if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count, - name,number,ino,res_bh,res_de)) >= 0) + cluster = raw_scan_sector(sb, MSDOS_SB(sb)->dir_start + count, + name, number, i_pos, res_bh, res_de); + if (cluster >= 0) return cluster; } return -ENOENT; @@ -443,24 +451,29 @@ * requested entry is found or the end of the directory is reached. */ -static int raw_scan_nonroot(struct super_block *sb,int start,const char *name, - int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry - **res_de) +static int raw_scan_nonroot(struct super_block *sb, int start, const char *name, + int *number, loff_t *i_pos, + struct buffer_head **res_bh, + struct msdos_dir_entry **res_de) { + struct msdos_sb_info *sbi = MSDOS_SB(sb); int count, cluster; unsigned long dir_size = 0; + sector_t sector; #ifdef DEBUG printk("raw_scan_nonroot: start=%d\n",start); #endif do { - for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) { - if ((cluster = raw_scan_sector(sb,(start-2)* - MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+ - count,name,number,ino,res_bh,res_de)) >= 0) + for (count = 0; count < sbi->cluster_size; count++) { + sector = ((sector_t)start - 2) * sbi->cluster_size + + count + sbi->data_start; + cluster = raw_scan_sector(sb, sector, name, number, + i_pos, res_bh, res_de); + if (cluster >= 0) return cluster; } - dir_size += 1 << MSDOS_SB(sb)->cluster_bits; + dir_size += 1 << sbi->cluster_bits; if (dir_size > FAT_MAX_DIR_SIZE) { fat_fs_panic(sb, "Directory %d: " "exceeded the maximum size of directory", @@ -492,13 +505,13 @@ */ static int raw_scan(struct super_block *sb, int start, const char *name, - int *number, int *ino, struct buffer_head **res_bh, - struct msdos_dir_entry **res_de) + loff_t *i_pos, struct buffer_head **res_bh, + struct msdos_dir_entry **res_de) { if (start) - return raw_scan_nonroot(sb,start,name,number,ino,res_bh,res_de); + return raw_scan_nonroot(sb,start,name,NULL,i_pos,res_bh,res_de); else - return raw_scan_root(sb,name,number,ino,res_bh,res_de); + return raw_scan_root(sb,name,NULL,i_pos,res_bh,res_de); } /* @@ -507,19 +520,21 @@ */ int fat_subdirs(struct inode *dir) { - int count; + struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb); + int number; - count = 0; - if ((dir->i_ino == MSDOS_ROOT_INO) && - (MSDOS_SB(dir->i_sb)->fat_bits != 32)) { - (void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL); - } else { - if ((dir->i_ino != MSDOS_ROOT_INO) && - !MSDOS_I(dir)->i_start) return 0; /* in mkdir */ - else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start, - NULL,&count,NULL,NULL,NULL); + number = 0; + if ((dir->i_ino == MSDOS_ROOT_INO) && (sbi->fat_bits != 32)) + raw_scan_root(dir->i_sb, NULL, &number, NULL, NULL, NULL); + else { + if ((dir->i_ino != MSDOS_ROOT_INO) && !MSDOS_I(dir)->i_start) + return 0; /* in mkdir */ + else { + raw_scan_nonroot(dir->i_sb, MSDOS_I(dir)->i_start, + NULL, &number, NULL, NULL, NULL); + } } - return count; + return number; } @@ -528,12 +543,12 @@ * for an empty directory slot (name is NULL). Returns an error code or zero. */ -int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh, - struct msdos_dir_entry **res_de,int *ino) +int fat_scan(struct inode *dir, const char *name, struct buffer_head **res_bh, + struct msdos_dir_entry **res_de, loff_t *i_pos) { int res; - res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start, - name, NULL, ino, res_bh, res_de); - return res<0 ? res : 0; + res = raw_scan(dir->i_sb, MSDOS_I(dir)->i_start, name, i_pos, + res_bh, res_de); + return (res < 0) ? res : 0; } diff -urN linux-2.5.70-bk1/fs/msdos/namei.c linux-2.5.70-bk2/fs/msdos/namei.c --- linux-2.5.70-bk1/fs/msdos/namei.c 2003-05-26 18:01:03.000000000 -0700 +++ linux-2.5.70-bk2/fs/msdos/namei.c 2003-05-28 04:37:02.000000000 -0700 @@ -112,8 +112,9 @@ } /***** Locates a directory entry. Uses unformatted name. */ -static int msdos_find(struct inode *dir,const char *name,int len, - struct buffer_head **bh,struct msdos_dir_entry **de,int *ino) +static int msdos_find(struct inode *dir, const char *name, int len, + struct buffer_head **bh, struct msdos_dir_entry **de, + loff_t *i_pos) { int res; char dotsOK; @@ -123,7 +124,7 @@ res = msdos_format_name(name,len, msdos_name,&MSDOS_SB(dir->i_sb)->options); if (res < 0) return -ENOENT; - res = fat_scan(dir,msdos_name,bh,de,ino); + res = fat_scan(dir, msdos_name, bh, de, i_pos); if (!res && dotsOK) { if (name[0]=='.') { if (!((*de)->attr & ATTR_HIDDEN)) @@ -134,7 +135,6 @@ } } return res; - } /* @@ -199,19 +199,19 @@ struct inode *inode = NULL; struct msdos_dir_entry *de; struct buffer_head *bh = NULL; - int ino,res; + loff_t i_pos; + int res; dentry->d_op = &msdos_dentry_operations; lock_kernel(); res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &bh, - &de, &ino); - + &de, &i_pos); if (res == -ENOENT) goto add; if (res < 0) goto out; - inode = fat_build_inode(sb, de, ino, &res); + inode = fat_build_inode(sb, de, i_pos, &res); if (res) goto out; add: @@ -231,12 +231,11 @@ static int msdos_add_entry(struct inode *dir, const char *name, struct buffer_head **bh, struct msdos_dir_entry **de, - int *ino, - int is_dir, int is_hid) + loff_t *i_pos, int is_dir, int is_hid) { int res; - res = fat_add_entries(dir, 1, bh, de, ino); + res = fat_add_entries(dir, 1, bh, de, i_pos); if (res < 0) return res; @@ -268,7 +267,8 @@ struct buffer_head *bh; struct msdos_dir_entry *de; struct inode *inode; - int ino,res,is_hid; + loff_t i_pos; + int res, is_hid; char msdos_name[MSDOS_NAME]; lock_kernel(); @@ -280,18 +280,18 @@ } is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.'); /* Have to do it due to foo vs. .foo conflicts */ - if (fat_scan(dir,msdos_name,&bh,&de,&ino) >= 0) { + if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0) { brelse(bh); unlock_kernel(); return -EINVAL; } inode = NULL; - res = msdos_add_entry(dir, msdos_name, &bh, &de, &ino, 0, is_hid); + res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 0, is_hid); if (res) { unlock_kernel(); return res; } - inode = fat_build_inode(dir->i_sb, de, ino, &res); + inode = fat_build_inode(dir->i_sb, de, i_pos, &res); brelse(bh); if (!inode) { unlock_kernel(); @@ -308,14 +308,15 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; - int res,ino; + loff_t i_pos; + int res; struct buffer_head *bh; struct msdos_dir_entry *de; bh = NULL; lock_kernel(); res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, - &bh, &de, &ino); + &bh, &de, &i_pos); if (res < 0) goto rmdir_done; /* @@ -351,7 +352,7 @@ struct inode *inode; int res,is_hid; char msdos_name[MSDOS_NAME]; - int ino; + loff_t i_pos; lock_kernel(); res = msdos_format_name(dentry->d_name.name,dentry->d_name.len, @@ -362,13 +363,13 @@ } is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.'); /* foo vs .foo situation */ - if (fat_scan(dir,msdos_name,&bh,&de,&ino) >= 0) + if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0) goto out_exist; - res = msdos_add_entry(dir, msdos_name, &bh, &de, &ino, 1, is_hid); + res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 1, is_hid); if (res) goto out_unlock; - inode = fat_build_inode(dir->i_sb, de, ino, &res); + inode = fat_build_inode(dir->i_sb, de, i_pos, &res); if (!inode) { brelse(bh); goto out_unlock; @@ -414,14 +415,15 @@ int msdos_unlink( struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; - int res,ino; + loff_t i_pos; + int res; struct buffer_head *bh; struct msdos_dir_entry *de; bh = NULL; lock_kernel(); res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, - &bh, &de, &ino); + &bh, &de, &i_pos); if (res < 0) goto unlink_done; @@ -443,12 +445,12 @@ struct dentry *old_dentry, struct inode *new_dir,char *new_name, struct dentry *new_dentry, struct buffer_head *old_bh, - struct msdos_dir_entry *old_de, int old_ino, int is_hid) + struct msdos_dir_entry *old_de, loff_t old_i_pos, int is_hid) { struct buffer_head *new_bh=NULL,*dotdot_bh=NULL; struct msdos_dir_entry *new_de,*dotdot_de; struct inode *old_inode,*new_inode; - int new_ino,dotdot_ino; + loff_t new_i_pos, dotdot_i_pos; int error; int is_dir; @@ -456,7 +458,8 @@ new_inode = new_dentry->d_inode; is_dir = S_ISDIR(old_inode->i_mode); - if (fat_scan(new_dir,new_name,&new_bh,&new_de,&new_ino)>=0 &&!new_inode) + if (fat_scan(new_dir, new_name, &new_bh, &new_de, &new_i_pos) >= 0 + && !new_inode) goto degenerate_case; if (is_dir) { if (new_inode) { @@ -465,7 +468,7 @@ goto out; } error = fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh, - &dotdot_de, &dotdot_ino); + &dotdot_de, &dotdot_i_pos); if (error < 0) { printk(KERN_WARNING "MSDOS: %s/%s, get dotdot failed, ret=%d\n", @@ -476,7 +479,7 @@ } if (!new_bh) { error = msdos_add_entry(new_dir, new_name, &new_bh, &new_de, - &new_ino, is_dir, is_hid); + &new_i_pos, is_dir, is_hid); if (error) goto out; } @@ -489,7 +492,7 @@ old_de->name[0] = DELETED_FLAG; mark_buffer_dirty(old_bh); fat_detach(old_inode); - fat_attach(old_inode, new_ino); + fat_attach(old_inode, new_i_pos); if (is_hid) MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; else @@ -544,8 +547,8 @@ { struct buffer_head *old_bh; struct msdos_dir_entry *old_de; - int old_ino, error; - int is_hid,old_hid; /* if new file and old file are hidden */ + loff_t old_i_pos; + int error, is_hid, old_hid; /* if new file and old file are hidden */ char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME]; lock_kernel(); @@ -562,13 +565,13 @@ is_hid = (new_dentry->d_name.name[0]=='.') && (new_msdos_name[0]!='.'); old_hid = (old_dentry->d_name.name[0]=='.') && (old_msdos_name[0]!='.'); - error = fat_scan(old_dir, old_msdos_name, &old_bh, &old_de, &old_ino); + error = fat_scan(old_dir, old_msdos_name, &old_bh, &old_de, &old_i_pos); if (error < 0) goto rename_done; error = do_msdos_rename(old_dir, old_msdos_name, old_dentry, new_dir, new_msdos_name, new_dentry, - old_bh, old_de, (ino_t)old_ino, is_hid); + old_bh, old_de, old_i_pos, is_hid); brelse(old_bh); rename_done: diff -urN linux-2.5.70-bk1/fs/proc/inode.c linux-2.5.70-bk2/fs/proc/inode.c --- linux-2.5.70-bk1/fs/proc/inode.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.70-bk2/fs/proc/inode.c 2003-05-28 04:37:02.000000000 -0700 @@ -61,8 +61,6 @@ struct proc_dir_entry *de; struct task_struct *tsk; - inode->i_state = I_CLEAR; - /* Let go of any associated process */ tsk = PROC_I(inode)->task; if (tsk) @@ -75,6 +73,7 @@ module_put(de->owner); de_put(de); } + clear_inode(inode); } struct vfsmount *proc_mnt; diff -urN linux-2.5.70-bk1/fs/vfat/namei.c linux-2.5.70-bk2/fs/vfat/namei.c --- linux-2.5.70-bk1/fs/vfat/namei.c 2003-05-26 18:00:42.000000000 -0700 +++ linux-2.5.70-bk2/fs/vfat/namei.c 2003-05-28 04:37:02.000000000 -0700 @@ -317,9 +317,10 @@ { struct msdos_dir_entry *de; struct buffer_head *bh = NULL; - int ino,res; + loff_t i_pos; + int res; - res = fat_scan(dir,name,&bh,&de,&ino); + res = fat_scan(dir, name, &bh, &de, &i_pos); brelse(bh); if (res < 0) return -ENOENT; @@ -781,7 +782,7 @@ int res, len; struct msdos_dir_entry *dummy_de; struct buffer_head *dummy_bh; - int dummy_ino; + loff_t dummy_i_pos; dir_slots = (struct msdos_dir_slot *) kmalloc(sizeof(struct msdos_dir_slot) * MSDOS_SLOTS, GFP_KERNEL); @@ -797,7 +798,7 @@ goto cleanup; /* build the empty directory entry of number of slots */ - offset = fat_add_entries(dir, slots, &dummy_bh, &dummy_de, &dummy_ino); + offset = fat_add_entries(dir, slots, &dummy_bh, &dummy_de, &dummy_i_pos); if (offset < 0) { res = offset; goto cleanup; @@ -807,7 +808,7 @@ /* Now create the new entry */ *bh = NULL; for (slot = 0; slot < slots; slot++) { - if (fat_get_entry(dir, &offset, bh, de, &sinfo_out->ino) < 0) { + if (fat_get_entry(dir, &offset, bh, de, &sinfo_out->i_pos) < 0) { res = -EIO; goto cleanup; } @@ -852,7 +853,7 @@ &offset,&sinfo->longname_offset); if (res>0) { sinfo->long_slots = res-1; - if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->ino)>=0) + if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->i_pos)>=0) return 0; res = -EIO; } @@ -882,7 +883,7 @@ table++; goto error; } - inode = fat_build_inode(dir->i_sb, de, sinfo.ino, &res); + inode = fat_build_inode(dir->i_sb, de, sinfo.i_pos, &res); brelse(bh); if (res) { unlock_kernel(); @@ -926,7 +927,7 @@ unlock_kernel(); return res; } - inode = fat_build_inode(sb, de, sinfo.ino, &res); + inode = fat_build_inode(sb, de, sinfo.i_pos, &res); brelse(bh); if (!inode) { unlock_kernel(); @@ -945,8 +946,8 @@ static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo, struct buffer_head *bh, struct msdos_dir_entry *de) { - loff_t offset; - int i,ino; + loff_t offset, i_pos; + int i; /* remove the shortname */ dir->i_mtime = CURRENT_TIME; @@ -958,7 +959,7 @@ /* remove the longname */ offset = sinfo->longname_offset; de = NULL; for (i = sinfo->long_slots; i > 0; --i) { - if (fat_get_entry(dir, &offset, &bh, &de, &ino) < 0) + if (fat_get_entry(dir, &offset, &bh, &de, &i_pos) < 0) continue; de->name[0] = DELETED_FLAG; de->attr = ATTR_NONE; @@ -1040,7 +1041,7 @@ unlock_kernel(); return res; } - inode = fat_build_inode(sb, de, sinfo.ino, &res); + inode = fat_build_inode(sb, de, sinfo.i_pos, &res); if (!inode) goto out; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; @@ -1078,7 +1079,7 @@ { struct buffer_head *old_bh,*new_bh,*dotdot_bh; struct msdos_dir_entry *old_de,*new_de,*dotdot_de; - int dotdot_ino; + loff_t dotdot_i_pos; struct inode *old_inode, *new_inode; int res, is_dir; struct vfat_slot_info old_sinfo,sinfo; @@ -1094,13 +1095,13 @@ is_dir = S_ISDIR(old_inode->i_mode); if (is_dir && (res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh, - &dotdot_de,&dotdot_ino)) < 0) + &dotdot_de,&dotdot_i_pos)) < 0) goto rename_done; if (new_dentry->d_inode) { res = vfat_find(new_dir,&new_dentry->d_name,&sinfo,&new_bh, &new_de); - if (res < 0 || MSDOS_I(new_inode)->i_location != sinfo.ino) { + if (res < 0 || MSDOS_I(new_inode)->i_pos != sinfo.i_pos) { /* WTF??? Cry and fail. */ printk(KERN_WARNING "vfat_rename: fs corrupted\n"); goto rename_done; @@ -1124,7 +1125,7 @@ vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de); old_bh=NULL; fat_detach(old_inode); - fat_attach(old_inode, sinfo.ino); + fat_attach(old_inode, sinfo.i_pos); mark_inode_dirty(old_inode); old_dir->i_version++; diff -urN linux-2.5.70-bk1/include/asm-alpha/bitops.h linux-2.5.70-bk2/include/asm-alpha/bitops.h --- linux-2.5.70-bk1/include/asm-alpha/bitops.h 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.70-bk2/include/asm-alpha/bitops.h 2003-05-28 04:37:02.000000000 -0700 @@ -233,7 +233,7 @@ } static inline int -test_bit(int nr, volatile void * addr) +test_bit(int nr, const volatile void * addr) { return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL; } diff -urN linux-2.5.70-bk1/include/asm-v850/bitops.h linux-2.5.70-bk2/include/asm-v850/bitops.h --- linux-2.5.70-bk1/include/asm-v850/bitops.h 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.70-bk2/include/asm-v850/bitops.h 2003-05-28 04:37:02.000000000 -0700 @@ -1,8 +1,8 @@ /* * include/asm-v850/bitops.h -- Bit operations * - * Copyright (C) 2001,02 NEC Corporation - * Copyright (C) 2001,02 Miles Bader + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader * Copyright (C) 1992 Linus Torvalds. * * This file is subject to the terms and conditions of the GNU General @@ -133,7 +133,7 @@ "m" (*((const char *)(addr) + ((nr) >> 3)))); \ __test_bit_res; \ }) -extern __inline__ int __test_bit (int nr, void *addr) +extern __inline__ int __test_bit (int nr, const void *addr) { int res; __asm__ ("tst1 %1, [%2]; setf nz, %0" diff -urN linux-2.5.70-bk1/include/asm-v850/nb85e_cache.h linux-2.5.70-bk2/include/asm-v850/nb85e_cache.h --- linux-2.5.70-bk1/include/asm-v850/nb85e_cache.h 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.70-bk2/include/asm-v850/nb85e_cache.h 2003-05-28 04:37:02.000000000 -0700 @@ -35,7 +35,7 @@ #define L1_CACHE_BYTES NB85E_CACHE_LINE_SIZE -#ifndef __ASSEMBLY__ +#if defined(__KERNEL__) && !defined(__ASSEMBLY__) /* Set caching params via the BHC and DCC registers. */ void nb85e_cache_enable (u16 bhc, u16 dcc); @@ -73,6 +73,6 @@ #define flush_icache_user_range nb85e_cache_flush_icache_user_range #define flush_cache_sigtramp nb85e_cache_flush_sigtramp -#endif /* !__ASSEMBLY__ */ +#endif /* __KERNEL__ && !__ASSEMBLY__ */ #endif /* __V850_NB85E_CACHE_H__ */ diff -urN linux-2.5.70-bk1/include/asm-v850/sim.h linux-2.5.70-bk2/include/asm-v850/sim.h --- linux-2.5.70-bk1/include/asm-v850/sim.h 2003-05-26 18:00:25.000000000 -0700 +++ linux-2.5.70-bk2/include/asm-v850/sim.h 2003-05-28 04:37:02.000000000 -0700 @@ -1,8 +1,8 @@ /* * include/asm-v850/sim.h -- Machine-dependent defs for GDB v850e simulator * - * Copyright (C) 2001,02 NEC Corporation - * Copyright (C) 2001,02 Miles Bader + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this diff -urN linux-2.5.70-bk1/include/linux/blkdev.h linux-2.5.70-bk2/include/linux/blkdev.h --- linux-2.5.70-bk1/include/linux/blkdev.h 2003-05-26 18:00:26.000000000 -0700 +++ linux-2.5.70-bk2/include/linux/blkdev.h 2003-05-28 04:37:02.000000000 -0700 @@ -179,7 +179,8 @@ unsigned long *tag_map; /* bit map of free/busy tags */ struct list_head busy_list; /* fifo list of busy tags */ int busy; /* current depth */ - int max_depth; + int max_depth; /* what we will send to device */ + int real_max_depth; /* what the array can hold */ }; struct request_queue @@ -452,6 +453,7 @@ extern void blk_queue_end_tag(request_queue_t *, struct request *); extern int blk_queue_init_tags(request_queue_t *, int); extern void blk_queue_free_tags(request_queue_t *); +extern int blk_queue_resize_tags(request_queue_t *, int); extern void blk_queue_invalidate_tags(request_queue_t *); extern void blk_congestion_wait(int rw, long timeout); diff -urN linux-2.5.70-bk1/include/linux/msdos_fs.h linux-2.5.70-bk2/include/linux/msdos_fs.h --- linux-2.5.70-bk1/include/linux/msdos_fs.h 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.70-bk2/include/linux/msdos_fs.h 2003-05-28 04:37:02.000000000 -0700 @@ -27,8 +27,6 @@ #define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ -#define FAT_CACHE 8 /* FAT cache size */ - #define ATTR_NONE 0 /* no attribute bits */ #define ATTR_RO 1 /* read-only */ #define ATTR_HIDDEN 2 /* hidden */ @@ -178,7 +176,7 @@ struct vfat_slot_info { int long_slots; /* number of long slots in filename */ loff_t longname_offset; /* dir offset for longname start */ - int ino; /* ino for the file */ + loff_t i_pos; /* on-disk position of directory entry */ }; /* Convert attribute bits and a mask to the UNIX mode. */ @@ -204,14 +202,6 @@ return container_of(inode, struct msdos_inode_info, vfs_inode); } -struct fat_cache { - struct super_block *sb; /* fs in question. NULL means unused */ - int start_cluster; /* first cluster of the chain. */ - int file_cluster; /* cluster number in the file. */ - int disk_cluster; /* cluster number on disk. */ - struct fat_cache *next; /* next cache entry */ -}; - static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len) { #ifdef __BIG_ENDIAN @@ -241,13 +231,12 @@ /* fat/cache.c */ extern int fat_access(struct super_block *sb, int nr, int new_value); extern int __fat_access(struct super_block *sb, int nr, int new_value); -extern int fat_bmap(struct inode *inode, int sector); -extern void fat_cache_init(void); +extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys); +extern void fat_cache_init(struct super_block *sb); extern void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu); extern void fat_cache_add(struct inode *inode, int f_clu, int d_clu); extern void fat_cache_inval_inode(struct inode *inode); -extern void fat_cache_inval_dev(struct super_block *sb); extern int fat_free(struct inode *inode, int skip); /* fat/dir.c */ @@ -259,7 +248,7 @@ unsigned int cmd, unsigned long arg); extern int fat_dir_empty(struct inode *dir); extern int fat_add_entries(struct inode *dir, int slots, struct buffer_head **bh, - struct msdos_dir_entry **de, int *ino); + struct msdos_dir_entry **de, loff_t *i_pos); extern int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat); /* fat/file.c */ @@ -271,11 +260,11 @@ /* fat/inode.c */ extern void fat_hash_init(void); -extern void fat_attach(struct inode *inode, int i_pos); +extern void fat_attach(struct inode *inode, loff_t i_pos); extern void fat_detach(struct inode *inode); -extern struct inode *fat_iget(struct super_block *sb, int i_pos); +extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); extern struct inode *fat_build_inode(struct super_block *sb, - struct msdos_dir_entry *de, int ino, int *res); + struct msdos_dir_entry *de, loff_t i_pos, int *res); extern void fat_delete_inode(struct inode *inode); extern void fat_clear_inode(struct inode *inode); extern void fat_put_super(struct super_block *sb); @@ -295,26 +284,27 @@ extern int date_dos2unix(unsigned short time, unsigned short date); extern void fat_date_unix2dos(int unix_date, unsigned short *time, unsigned short *date); -extern int fat__get_entry(struct inode *dir, loff_t *pos, struct buffer_head **bh, - struct msdos_dir_entry **de, int *ino); +extern int fat__get_entry(struct inode *dir, loff_t *pos, + struct buffer_head **bh, + struct msdos_dir_entry **de, loff_t *i_pos); static __inline__ int fat_get_entry(struct inode *dir, loff_t *pos, struct buffer_head **bh, - struct msdos_dir_entry **de, int *ino) + struct msdos_dir_entry **de, loff_t *i_pos) { /* Fast stuff first */ if (*bh && *de && (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) { *pos += sizeof(struct msdos_dir_entry); (*de)++; - (*ino)++; + (*i_pos)++; return 0; } - return fat__get_entry(dir,pos,bh,de,ino); + return fat__get_entry(dir, pos, bh, de, i_pos); } extern int fat_subdirs(struct inode *dir); extern int fat_scan(struct inode *dir, const char *name, struct buffer_head **res_bh, - struct msdos_dir_entry **res_de, int *ino); + struct msdos_dir_entry **res_de, loff_t *i_pos); /* msdos/namei.c - these are for Umsdos */ extern struct dentry *msdos_lookup(struct inode *dir, struct dentry *); diff -urN linux-2.5.70-bk1/include/linux/msdos_fs_i.h linux-2.5.70-bk2/include/linux/msdos_fs_i.h --- linux-2.5.70-bk1/include/linux/msdos_fs_i.h 2003-05-26 18:01:00.000000000 -0700 +++ linux-2.5.70-bk2/include/linux/msdos_fs_i.h 2003-05-28 04:37:02.000000000 -0700 @@ -8,12 +8,16 @@ */ struct msdos_inode_info { + /* cache of lastest accessed cluster */ + int file_cluster; /* cluster number in the file. */ + int disk_cluster; /* cluster number on disk. */ + loff_t mmu_private; int i_start; /* first cluster or 0 */ int i_logstart; /* logical first cluster */ int i_attrs; /* unused attribute bits */ int i_ctime_ms; /* unused change time in milliseconds */ - int i_location; /* on-disk position of directory entry or 0 */ + loff_t i_pos; /* on-disk position of directory entry or 0 */ struct list_head i_fat_hash; /* hash by i_location */ struct inode vfs_inode; }; diff -urN linux-2.5.70-bk1/include/linux/msdos_fs_sb.h linux-2.5.70-bk2/include/linux/msdos_fs_sb.h --- linux-2.5.70-bk1/include/linux/msdos_fs_sb.h 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.70-bk2/include/linux/msdos_fs_sb.h 2003-05-28 04:37:02.000000000 -0700 @@ -26,6 +26,15 @@ nocase:1; /* Does this need case conversion? 0=need case conversion*/ }; +#define FAT_CACHE_NR 8 /* number of FAT cache */ + +struct fat_cache { + int start_cluster; /* first cluster of the chain. */ + int file_cluster; /* cluster number in the file. */ + int disk_cluster; /* cluster number on disk. */ + struct fat_cache *next; /* next cache entry */ +}; + struct msdos_sb_info { unsigned short cluster_size; /* sectors/cluster */ unsigned short cluster_bits; /* sectors/cluster */ @@ -47,6 +56,9 @@ void *dir_ops; /* Opaque; default directory operations */ int dir_per_block; /* dir entries per block */ int dir_per_block_bits; /* log2(dir_per_block) */ + + spinlock_t cache_lock; + struct fat_cache cache_array[FAT_CACHE_NR], *cache; }; #endif diff -urN linux-2.5.70-bk1/include/linux/wanrouter.h linux-2.5.70-bk2/include/linux/wanrouter.h --- linux-2.5.70-bk1/include/linux/wanrouter.h 2003-05-26 18:00:27.000000000 -0700 +++ linux-2.5.70-bk2/include/linux/wanrouter.h 2003-05-28 04:37:03.000000000 -0700 @@ -534,7 +534,8 @@ /* Public Data */ -extern struct wan_device *router_devlist; /* list of registered devices */ +/* list of registered devices */ +extern struct wan_device *wanrouter_router_devlist; #endif /* __KERNEL__ */ #endif /* _ROUTER_H */ diff -urN linux-2.5.70-bk1/kernel/sched.c linux-2.5.70-bk2/kernel/sched.c --- linux-2.5.70-bk1/kernel/sched.c 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.70-bk2/kernel/sched.c 2003-05-28 04:37:03.000000000 -0700 @@ -501,7 +501,7 @@ } success = 1; } -#if CONFIG_SMP +#ifdef CONFIG_SMP else if (unlikely(kick) && task_running(rq, p) && (p->thread_info->cpu != smp_processor_id())) smp_send_reschedule(p->thread_info->cpu); diff -urN linux-2.5.70-bk1/net/ipv4/esp.c linux-2.5.70-bk2/net/ipv4/esp.c --- linux-2.5.70-bk1/net/ipv4/esp.c 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.70-bk2/net/ipv4/esp.c 2003-05-28 04:37:03.000000000 -0700 @@ -567,7 +567,7 @@ .no_policy = 1, }; -int __init esp4_init(void) +static int __init esp4_init(void) { struct xfrm_decap_state decap; @@ -578,7 +578,6 @@ decap_data_too_small(); } - esp_type.owner = THIS_MODULE; if (xfrm_register_type(&esp_type, AF_INET) < 0) { printk(KERN_INFO "ip esp init: can't add xfrm type\n"); return -EAGAIN; diff -urN linux-2.5.70-bk1/net/ipv4/ipcomp.c linux-2.5.70-bk2/net/ipv4/ipcomp.c --- linux-2.5.70-bk1/net/ipv4/ipcomp.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.70-bk2/net/ipv4/ipcomp.c 2003-05-28 04:37:03.000000000 -0700 @@ -382,9 +382,9 @@ goto out; } -static struct xfrm_type ipcomp_type = -{ +static struct xfrm_type ipcomp_type = { .description = "IPCOMP4", + .owner = THIS_MODULE, .proto = IPPROTO_COMP, .init_state = ipcomp_init_state, .destructor = ipcomp_destroy, @@ -400,7 +400,6 @@ static int __init ipcomp4_init(void) { - ipcomp_type.owner = THIS_MODULE; if (xfrm_register_type(&ipcomp_type, AF_INET) < 0) { printk(KERN_INFO "ipcomp init: can't add xfrm type\n"); return -EAGAIN; diff -urN linux-2.5.70-bk1/net/ipv4/xfrm4_tunnel.c linux-2.5.70-bk2/net/ipv4/xfrm4_tunnel.c --- linux-2.5.70-bk1/net/ipv4/xfrm4_tunnel.c 2003-05-26 18:00:23.000000000 -0700 +++ linux-2.5.70-bk2/net/ipv4/xfrm4_tunnel.c 2003-05-28 04:37:03.000000000 -0700 @@ -215,6 +215,7 @@ static struct xfrm_type ipip_type = { .description = "IPIP", + .owner = THIS_MODULE, .proto = IPPROTO_IPIP, .init_state = ipip_init_state, .destructor = ipip_destroy, @@ -229,7 +230,6 @@ static int __init ipip_init(void) { - ipip_type.owner = THIS_MODULE; if (xfrm_register_type(&ipip_type, AF_INET) < 0) { printk(KERN_INFO "ipip init: can't add xfrm type\n"); return -EAGAIN; diff -urN linux-2.5.70-bk1/net/ipv6/addrconf.c linux-2.5.70-bk2/net/ipv6/addrconf.c --- linux-2.5.70-bk1/net/ipv6/addrconf.c 2003-05-26 18:00:58.000000000 -0700 +++ linux-2.5.70-bk2/net/ipv6/addrconf.c 2003-05-28 04:37:03.000000000 -0700 @@ -33,6 +33,8 @@ * Yuji SEKIYA @USAGI : Don't assign a same IPv6 * address on a same interface. * YOSHIFUJI Hideaki @USAGI : ARCnet support + * YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to + * seq_file. */ #include @@ -76,6 +78,9 @@ #include +#include +#include + #define IPV6_MAX_ADDRESSES 16 /* Set to 3 to get tracing... */ @@ -2090,57 +2095,141 @@ } #ifdef CONFIG_PROC_FS -static int iface_proc_info(char *buffer, char **start, off_t offset, - int length) +struct if6_iter_state { + int bucket; +}; + +static inline struct inet6_ifaddr *if6_get_bucket(struct seq_file *seq, loff_t *pos) { - struct inet6_ifaddr *ifp; int i; - int len = 0; - off_t pos=0; - off_t begin=0; + struct inet6_ifaddr *ifa = NULL; + loff_t l = *pos; + struct if6_iter_state *state = seq->private; + + for (; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) + for (i = 0, ifa = inet6_addr_lst[state->bucket]; ifa; ++i, ifa=ifa->lst_next) { + if (l--) + continue; + *pos = i; + goto out; + } +out: + return ifa; +} - for (i=0; i < IN6_ADDR_HSIZE; i++) { - read_lock_bh(&addrconf_hash_lock); - for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) { - int j; +static void *if6_seq_start(struct seq_file *seq, loff_t *pos) +{ + read_lock_bh(&addrconf_hash_lock); + return *pos ? if6_get_bucket(seq, pos) : (void *)1; +} - for (j=0; j<16; j++) { - sprintf(buffer + len, "%02x", - ifp->addr.s6_addr[j]); - len += 2; - } +static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct inet6_ifaddr *ifa; + struct if6_iter_state *state; - len += sprintf(buffer + len, - " %02x %02x %02x %02x %8s\n", - ifp->idev->dev->ifindex, - ifp->prefix_len, - ifp->scope, - ifp->flags, - ifp->idev->dev->name); - pos=begin+len; - if(posoffset+length) { - read_unlock_bh(&addrconf_hash_lock); - goto done; - } - } - read_unlock_bh(&addrconf_hash_lock); + if (v == (void *)1) { + ifa = if6_get_bucket(seq, pos); + goto out; } -done: + state = seq->private; + + ifa = v; + ifa = ifa->lst_next; + if (ifa) + goto out; + + if (++state->bucket >= IN6_ADDR_HSIZE) + goto out; + + *pos = 0; + ifa = if6_get_bucket(seq, pos); +out: + ++*pos; + return ifa; +} + +static inline void if6_iface_seq_show(struct seq_file *seq, struct inet6_ifaddr *ifp) +{ + seq_printf(seq, + "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n", + NIP6(ifp->addr), + ifp->idev->dev->ifindex, + ifp->prefix_len, + ifp->scope, + ifp->flags, + ifp->idev->dev->name); +} + +static int if6_seq_show(struct seq_file *seq, void *v) +{ + if (v == (void *)1) + return 0; + else + if6_iface_seq_show(seq, v); + return 0; +} + +static void if6_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock_bh(&addrconf_hash_lock); +} + +static struct seq_operations if6_seq_ops = { + .start = if6_seq_start, + .next = if6_seq_next, + .show = if6_seq_show, + .stop = if6_seq_stop, +}; + +static int if6_seq_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int rc = -ENOMEM; + struct if6_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); + + if (!s) + goto out; + memset(s, 0, sizeof(*s)); - *start=buffer+(offset-begin); - len-=(offset-begin); - if(len>length) - len=length; - if(len<0) - len=0; - return len; + rc = seq_open(file, &if6_seq_ops); + if (rc) + goto out_kfree; + + seq = file->private_data; + seq->private = s; +out: + return rc; +out_kfree: + kfree(s); + goto out; } +static struct file_operations if6_fops = { + .owner = THIS_MODULE, + .open = if6_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +int __init if6_proc_init(void) +{ + struct proc_dir_entry *p; + int rc = 0; + + p = create_proc_entry("if_inet6", S_IRUGO, proc_net); + if (p) + p->proc_fops = &if6_fops; + else + rc = -ENOMEM; + return rc; +} +void if6_proc_exit(void) +{ + proc_net_remove("if_inet6"); +} #endif /* CONFIG_PROC_FS */ /* @@ -2727,10 +2816,6 @@ rtnl_unlock(); #endif -#ifdef CONFIG_PROC_FS - proc_net_create("if_inet6", 0, iface_proc_info); -#endif - addrconf_verify(0); rtnetlink_links[PF_INET6] = inet6_rtnetlink_table; #ifdef CONFIG_SYSCTL diff -urN linux-2.5.70-bk1/net/ipv6/af_inet6.c linux-2.5.70-bk2/net/ipv6/af_inet6.c --- linux-2.5.70-bk1/net/ipv6/af_inet6.c 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.70-bk2/net/ipv6/af_inet6.c 2003-05-28 04:37:03.000000000 -0700 @@ -75,18 +75,16 @@ #ifdef CONFIG_PROC_FS extern int raw6_proc_init(void); -extern int raw6_proc_exit(void); - +extern void raw6_proc_exit(void); extern int tcp6_proc_init(void); extern void tcp6_proc_exit(void); - extern int udp6_proc_init(void); extern void udp6_proc_exit(void); - extern int ipv6_misc_proc_init(void); -extern int ipv6_misc_proc_exit(void); - +extern void ipv6_misc_proc_exit(void); extern int anycast6_get_info(char *, char **, off_t, int); +extern int if6_proc_init(void); +extern void if6_proc_exit(void); #endif #ifdef CONFIG_SYSCTL @@ -799,6 +797,8 @@ if (!proc_net_create("anycast6", 0, anycast6_get_info)) goto proc_anycast6_fail; + if (if6_proc_init()) + goto proc_if6_fail; #endif ipv6_netdev_notif_init(); ipv6_packet_init(); @@ -820,6 +820,8 @@ return 0; #ifdef CONFIG_PROC_FS +proc_if6_fail: + proc_net_remove("anycast6"); proc_anycast6_fail: ipv6_misc_proc_exit(); proc_misc6_fail: @@ -852,11 +854,12 @@ /* First of all disallow new sockets creation. */ sock_unregister(PF_INET6); #ifdef CONFIG_PROC_FS - raw6_proc_exit(); - proc_net_remove("tcp6"); - proc_net_remove("udp6"); - ipv6_misc_proc_exit(); - proc_net_remove("anycast6"); + if6_proc_exit(); + proc_net_remove("anycast6"); + ipv6_misc_proc_exit(); + udp6_proc_exit(); + tcp6_proc_exit(); + raw6_proc_exit(); #endif /* Cleanup code parts. */ sit_cleanup(); diff -urN linux-2.5.70-bk1/net/ipv6/icmp.c linux-2.5.70-bk2/net/ipv6/icmp.c --- linux-2.5.70-bk1/net/ipv6/icmp.c 2003-05-26 18:00:27.000000000 -0700 +++ linux-2.5.70-bk2/net/ipv6/icmp.c 2003-05-28 04:37:03.000000000 -0700 @@ -263,7 +263,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, struct net_device *dev) { - struct inet6_dev *idev; + struct inet6_dev *idev = NULL; struct ipv6hdr *hdr = skb->nh.ipv6h; struct sock *sk = icmpv6_socket->sk; struct ipv6_pinfo *np = inet6_sk(sk); @@ -384,7 +384,7 @@ hlimit, NULL, &fl, (struct rt6_info*)dst, MSG_DONTWAIT); if (err) { ip6_flush_pending_frames(sk); - goto out; + goto out_put; } err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr)); __skb_push(skb, plen); @@ -393,6 +393,7 @@ ICMP6_INC_STATS_OFFSET_BH(idev, Icmp6OutDestUnreachs, type - ICMPV6_DEST_UNREACH); ICMP6_INC_STATS_BH(idev, Icmp6OutMsgs); +out_put: if (likely(idev != NULL)) in6_dev_put(idev); out: @@ -455,13 +456,14 @@ if (err) { ip6_flush_pending_frames(sk); - goto out; + goto out_put; } err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr)); ICMP6_INC_STATS_BH(idev, Icmp6OutEchoReplies); ICMP6_INC_STATS_BH(idev, Icmp6OutMsgs); +out_put: if (likely(idev != NULL)) in6_dev_put(idev); out: diff -urN linux-2.5.70-bk1/net/ipv6/ndisc.c linux-2.5.70-bk2/net/ipv6/ndisc.c --- linux-2.5.70-bk1/net/ipv6/ndisc.c 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.70-bk2/net/ipv6/ndisc.c 2003-05-28 04:37:03.000000000 -0700 @@ -431,23 +431,21 @@ len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); - rt = ip6_dst_alloc(); - if (!rt) - return; - /* for anycast or proxy, solicited_addr != src_addr */ ifp = ipv6_get_ifaddr(solicited_addr, dev); if (ifp) { src_addr = solicited_addr; in6_ifa_put(ifp); } else { - if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr, 0)) { - dst_free(dst); + if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr, 0)) return; - } src_addr = &tmpaddr; } + rt = ip6_dst_alloc(); + if (!rt) + return; + ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr); ndisc_rt_init(rt, dev, neigh); diff -urN linux-2.5.70-bk1/net/ipv6/proc.c linux-2.5.70-bk2/net/ipv6/proc.c --- linux-2.5.70-bk1/net/ipv6/proc.c 2003-05-26 18:00:38.000000000 -0700 +++ linux-2.5.70-bk2/net/ipv6/proc.c 2003-05-28 04:37:03.000000000 -0700 @@ -299,11 +299,10 @@ goto out; } -int ipv6_misc_proc_exit(void) +void ipv6_misc_proc_exit(void) { proc_net_remove("sockstat6"); proc_net_remove("dev_snmp6"); proc_net_remove("snmp6"); - return 0; } diff -urN linux-2.5.70-bk1/net/wanrouter/wanproc.c linux-2.5.70-bk2/net/wanrouter/wanproc.c --- linux-2.5.70-bk1/net/wanrouter/wanproc.c 2003-05-26 18:00:39.000000000 -0700 +++ linux-2.5.70-bk2/net/wanrouter/wanproc.c 2003-05-28 04:37:03.000000000 -0700 @@ -87,7 +87,8 @@ lock_kernel(); if (!l--) return (void *)1; - for (wandev = router_devlist; l-- && wandev; wandev = wandev->next) + for (wandev = wanrouter_router_devlist; l-- && wandev; + wandev = wandev->next) ; return wandev; } @@ -96,7 +97,7 @@ { struct wan_device *wandev = v; (*pos)++; - return (v == (void *)1) ? router_devlist : wandev->next; + return (v == (void *)1) ? wanrouter_router_devlist : wandev->next; } static void r_stop(struct seq_file *m, void *v)