Please mail me (Cort Dougan, cort@cs.nmt.edu) if you have questions,
comments or corrections.
-Last Change: 3.24.98
+Last Change: 6.16.99
This just covers sound on the PReP and CHRP systems for now and later
will contain information on the PowerMac's.
Midi is not supported since the cs4232 driver doesn't support midi yet.
-2. IBM PowerPersonal PReP machines and IBM LongTrail CHRP
+2. IBM PowerPersonal PReP machines
I've only tested sound on the Power Personal Series of IBM workstations
so if you try it on others please let me know the result. I'm especially
This setup does _NOT_ allow for recording yet.
Midi is not supported since the cs4232 driver doesn't support midi yet.
+
+2. IBM CHRP
+
+ I have only tested this on the 43P-150. Build the kernel with the cs4232
+ set as a module and load the module with irq=9 dma=1 dma2=2 io=0x550
W: http://www.dandelion.com/Linux/
S: Maintained
+CIRRUS LOGIC GENERIC FBDEV DRIVER
+P: Jeff Garzik
+M: jgarzik@pobox.com
+L: linux-fbdev@vuser.vu.union.edu
+S: Maintained
+
CONFIGURE, MENUCONFIG, XCONFIG
P: Michael Elizabeth Chastain
M: mec@shout.net
EXPORT_SYMBOL_NOVERS(__up_wakeup);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy);
+EXPORT_SYMBOL(csum_partial_copy_generic);
/* Delay loops */
EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(__delay);
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
return 0xffffffff;
}
- file = current->files->fd[elf_exec_fileno];
+ file = fget(elf_exec_fileno);
eppnt = elf_phdata;
for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
}
/* Now use mmap to map the library into memory. */
+ fput(file);
sys_close(elf_exec_fileno);
if(error < 0 && error > -1024) {
#ifdef DEBUG_ELF
unsigned int start_code, end_code, end_data, elf_stack;
int elf_exec_fileno, retval, has_interp, has_ephdr, size, i;
char *elf_interpreter;
+ struct file *file;
mm_segment_t old_fs;
load_addr = 0;
retval = read_exec(bprm->dentry, elf_ex.e_phoff,
(char *) elf_phdata, size, 1);
- if (retval < 0) {
- kfree (elf_phdata);
- return retval;
- }
+ if (retval < 0)
+ goto out_phdata;
#ifdef DEBUG_ELF
dump_phdrs(elf_phdata, elf_ex.e_phnum);
elf_bss = 0;
elf_brk = 0;
- elf_exec_fileno = open_dentry(bprm->dentry, O_RDONLY);
-
- if (elf_exec_fileno < 0) {
- kfree (elf_phdata);
- return elf_exec_fileno;
- }
+ retval = open_dentry(bprm->dentry, O_RDONLY);
+ if (retval < 0)
+ goto out_phdata;
+ file = fget(elf_exec_fileno = retval);
elf_stack = 0xffffffff;
elf_interpreter = NULL;
&interpreter_dentry,
&interp_elf_ex, elf_phdata, bprm,
elf_ex.e_phnum);
- if(retval) {
- kfree(elf_phdata);
- sys_close(elf_exec_fileno);
- return retval;
- }
+ if(retval)
+ goto out_file;
if(elf_interpreter) {
retval = verify_irix_interpreter(&interp_elf_ex);
- if(retval) {
- kfree(elf_interpreter);
- kfree(elf_phdata);
- sys_close(elf_exec_fileno);
- return retval;
- }
+ if(retval)
+ goto out_interp;
}
/* OK, we are done with that, now set up the arg stuff,
* and then start this sucker up.
*/
- if (!bprm->sh_bang) {
- if (!bprm->p) {
- if(elf_interpreter) {
- kfree(elf_interpreter);
- }
- kfree (elf_phdata);
- sys_close(elf_exec_fileno);
- return -E2BIG;
- }
- }
+ retval = -E2BIG;
+ if (!bprm->sh_bang && !bprm->p)
+ goto out_interp;
/* Flush all traces of the currently running executable */
retval = flush_old_exec(bprm);
if (retval)
- return retval;
+ goto out_interp;
/* OK, This is the point of no return */
current->mm->end_data = 0;
old_fs = get_fs();
set_fs(get_ds());
- map_executable(current->files->fd[elf_exec_fileno], elf_phdata,
- elf_ex.e_phnum, &elf_stack, &load_addr,
+ map_executable(file, elf_phdata, elf_ex.e_phnum, &elf_stack, &load_addr,
&start_code, &elf_bss, &end_code, &end_data, &elf_brk);
if(elf_interpreter) {
set_fs(old_fs);
kfree(elf_phdata);
+ fput(file);
sys_close(elf_exec_fileno);
current->personality = PER_IRIX32;
if (current->flags & PF_PTRACED)
send_sig(SIGTRAP, current, 0);
return 0;
+
+out_interp:
+ if(elf_interpreter) {
+ kfree(elf_interpreter);
+ }
+out_file:
+ fput(file);
+ sys_close(elf_exec_fileno);
+out_phdata:
+ kfree (elf_phdata);
+ return retval;
}
static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* This is really simpleminded and specialized - we are loading an
* a.out library that is given an ELF header.
*/
-static inline int do_load_irix_library(int fd)
+static inline int do_load_irix_library(struct file *file)
{
- struct file * file;
struct elfhdr elf_ex;
struct elf_phdr *elf_phdata = NULL;
struct dentry *dentry;
int i,j, k;
len = 0;
- file = current->files->fd[fd];
+ if (!file->f_op)
+ return -EACCES;
dentry = file->f_dentry;
inode = dentry->d_inode;
elf_bss = 0;
- if (!file || !file->f_op)
- return -EACCES;
-
/* Seek to the beginning of the file. */
if (file->f_op->llseek) {
if ((error = file->f_op->llseek(file, 0, 0)) != 0)
static int load_irix_library(int fd)
{
- int retval;
+ int retval = -EACCES;
+ struct file *file;
MOD_INC_USE_COUNT;
- retval = do_load_irix_library(fd);
+ file = fget(fd);
+ if (file) {
+ retval = do_load_irix_library(file);
+ fput(file);
+ }
MOD_DEC_USE_COUNT;
return retval;
}
return -ENOEXEC;
}
- filp = current->files->fd[fd];
- if(!filp || !filp->f_op) {
+ filp = fget(fd);
+ if (!filp)
+ return -EACCES;
+ if(!filp->f_op) {
printk("irix_mapelf: Bogon filp!\n");
+ fput(file);
return -EACCES;
}
if(retval != (hp->p_vaddr & 0xfffff000)) {
printk("irix_mapelf: do_mmap fails with %d!\n", retval);
+ fput(file);
return retval;
}
}
#ifdef DEBUG_ELF
printk("irix_mapelf: Success, returning %08lx\n", user_phdrp->p_vaddr);
#endif
+ fput(file);
return user_phdrp->p_vaddr;
}
LINKFLAGS = -T arch/ppc/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic
CFLAGSINC = -D__KERNEL__ -I$(TOPDIR)/include -D__powerpc__
CFLAGS := $(CFLAGS) -D__powerpc__ -fsigned-char -msoft-float -pipe \
- -fno-builtin -ffixed-r2 -Wno-uninitialized -mmultiple -mstring
+ -fno-builtin -ffixed-r2 -Wno-uninitialized -mmultiple \
+ -mstring
CPP = $(CC) -E $(CFLAGS)
ifdef CONFIG_8xx
endif
ifdef CONFIG_PPC64
-CFLAGS := $(CFLAGS) -Wa,-mppc64bridge #-Wa,-mppc64
-#CFLAGS := $(CFLAGS) -Wa,-mppc64 -mpowerpc64
+CFLAGS := $(CFLAGS) -Wa,-mppc64bridge #-mpowerpc64
endif
HEAD := arch/ppc/kernel/head.o
./mknote > note
$(OBJCOPY) $@ $@ --add-section=.note=note -R .comment
+mknote: mknote.c
+ $(HOSTCC) $(HOSTCFLAGS) -o $@ mknote.c
+
zImage.initrd: $(OBJS) initrd.o
$(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS)
#define RAM_START 0x00000000
#define RAM_END (8<<20)
-#define RAM_FREE (6<<20) /* after image of chrpboot */
+#define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF)
#define PROG_START 0x00010000
char *avail_ram;
char *end_avail;
+extern char _end[];
extern char image_data[];
extern int image_len;
extern char initrd_data[];
initrd_start = (RAM_END - initrd_size) & ~0xFFF;
a1 = initrd_start;
a2 = initrd_size;
- printf("initial ramdisk at 0x%x (%u bytes)\n\r", initrd_start,
- initrd_size);
+ printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n\r", initrd_start,
+ initrd_data,initrd_size);
memcpy((char *)initrd_start, initrd_data, initrd_size);
end_avail = (char *)initrd_start;
} else
im = image_data;
len = image_len;
dst = (void *) PROG_START;
-
if (im[0] == 0x1f && im[1] == 0x8b) {
avail_ram = (char *)RAM_FREE;
printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
#
# Paul Mackerras January 1997
-HOSTCC = gcc
HOSTCFLAGS = -O -I$(TOPDIR)/include
CC = $(CROSS_COMPILE)gcc
#
# Additional Block Devices
#
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
#
# CONFIG_IPX is not set
CONFIG_ATALK=m
+# CONFIG_DECNET is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_BRIDGE is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
CONFIG_SCSI_AIC7XXX=y
-# CONFIG_OVERRIDE_CMDS is not set
+# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
CONFIG_AIC7XXX_PROC_STATS=y
CONFIG_AIC7XXX_RESET_DELAY=15
# CONFIG_SCSI_ADVANSYS is not set
CONFIG_FB_MATROX=y
# CONFIG_FB_MATROX_MILLENIUM is not set
CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G100 is not set
+CONFIG_FB_MATROX_G100=y
# CONFIG_FB_MATROX_MULTIHEAD is not set
# CONFIG_FB_ATY is not set
# CONFIG_FB_VIRTUAL is not set
CONFIG_MAC_PARTITION=y
# CONFIG_SMD_DISKLABEL is not set
# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_SGI_DISKLABEL is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
CONFIG_NLS=y
#
CONFIG_SOUND=y
CONFIG_DMASOUND=y
+# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
# CONFIG_SOUND_SONICVIBES is not set
-# $Id: config.in,v 1.93 1999/05/14 22:36:58 cort Exp $
+# $Id: config.in,v 1.94 1999/06/25 11:00:07 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
endmenu
source drivers/char/Config.in
-source drivers/usb/Config.in
source fs/Config.in
mainmenu_option next_comment
#
# Additional Block Devices
#
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
#
# CONFIG_IPX is not set
CONFIG_ATALK=m
+# CONFIG_DECNET is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_BRIDGE is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
CONFIG_SCSI_AIC7XXX=y
-# CONFIG_OVERRIDE_CMDS is not set
+# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
CONFIG_AIC7XXX_PROC_STATS=y
CONFIG_AIC7XXX_RESET_DELAY=15
# CONFIG_SCSI_ADVANSYS is not set
CONFIG_FB_MATROX=y
# CONFIG_FB_MATROX_MILLENIUM is not set
CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G100 is not set
+CONFIG_FB_MATROX_G100=y
# CONFIG_FB_MATROX_MULTIHEAD is not set
# CONFIG_FB_ATY is not set
# CONFIG_FB_VIRTUAL is not set
CONFIG_MAC_PARTITION=y
# CONFIG_SMD_DISKLABEL is not set
# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_SGI_DISKLABEL is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
CONFIG_NLS=y
#
CONFIG_SOUND=y
CONFIG_DMASOUND=y
+# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
# CONFIG_SOUND_SONICVIBES is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
+CONFIG_SOUND_OSS=y
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+CONFIG_SOUND_CS4232=m
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
+
+#
+# Additional low level sound drivers
+#
+# CONFIG_LOWLEVEL_SOUND is not set
#
# Kernel hacking
$(TOPDIR)/include/asm/processor.h \
$(TOPDIR)/include/asm/pgtable.h \
$(TOPDIR)/include/asm/ptrace.h
- $(CC) ${CFLAGS} -S mk_defs.c
+ $(CC) $(CFLAGS) -S mk_defs.c
cp ppc_defs.head ppc_defs.h
grep '^#define' mk_defs.s >>ppc_defs.h
rm mk_defs.s
find_name : find_name.c
- $(HOSTCC) -o find_name find_name.c
+ $(HOSTCC) $(HOSTCFLAGS) -o find_name find_name.c
checks: checks.c
- $(HOSTCC) ${CFLAGS} -D__KERNEL__ -o checks checks.c
+ $(HOSTCC) $(HOSTCFLAGS) -D__KERNEL__ -o checks checks.c
./checks
include $(TOPDIR)/Rules.make
}
else
{
- if ( !strncmp("IBM,7043-150", get_property(find_path_device("/"), "name", NULL),12) )
+ if ( !strncmp("IBM,7043-150", get_property(find_path_device("/"), "name", NULL),12) ||
+ !strncmp("IBM,7046-155", get_property(find_path_device("/"), "name", NULL),12) )
{
pci_dram_offset = 0;
isa_mem_base = 0x80000000;
#include <asm/irq.h>
#include <asm/adb.h>
#include <asm/hydra.h>
+#include <asm/keyboard.h>
#include "time.h"
#include "local_irq.h"
unsigned long chrp_get_rtc_time(void);
int chrp_set_rtc_time(unsigned long nowtime);
-unsigned long rtas_event_scan_rate = 0, rtas_event_scan_ct = 0;
void chrp_calibrate_decr(void);
void chrp_time_init(void);
/*
* Fix the Super I/O configuration
*/
- /*sio_init();*/
+ sio_init();
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
struct property *p;
device = find_devices("rtas");
for ( p = device->properties;
- strncmp(p->name, "rtas-event-scan-rate", 20) && p ;
+ p && strncmp(p->name, "rtas-event-scan-rate", 20);
p = p->next )
/* nothing */ ;
if ( p && *(unsigned long *)p->value )
{
- rtas_event_scan_rate = (HZ/(*(unsigned long *)p->value)*30)-1;
- rtas_event_scan_ct = 1;
+ ppc_md.heartbeat = chrp_event_scan;
+ ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
+ ppc_md.heartbeat_count = 1;
printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
- *(unsigned long *)p->value, rtas_event_scan_rate );
+ *(unsigned long *)p->value, ppc_md.heartbeat_reset );
}
}
}
chrp_event_scan(void)
{
unsigned char log[1024];
- if ( rtas_event_scan_rate && (rtas_event_scan_ct-- <= 0) )
- {
- call_rtas( "event-scan", 4, 1, NULL, 0x0, 1, __pa(log), 1024 );
- rtas_event_scan_ct = rtas_event_scan_rate;
- }
+ call_rtas( "event-scan", 4, 1, NULL, 0x0, 1, __pa(log), 1024 );
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
}
void
chrp_power_off(void)
{
/* allow power on only with power button press */
-#define PWR_FIELD(x) (0x8000000000000000 >> ((x)-96))
+#define PWR_FIELD(x) (0x8000000000000000ULL >> ((x)-96))
printk("RTAS power-off returned %d\n",
call_rtas("power-off", 2, 1, NULL,
((PWR_FIELD(96)|PWR_FIELD(97))>>32)&0xffffffff,
ppc_md.kbd_leds = pckbd_leds;
ppc_md.kbd_init_hw = pckbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ SYSRQ_KEY = 0x54;
#endif
}
else
ppc_md.kbd_leds = mackbd_leds;
ppc_md.kbd_init_hw = mackbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.kbd_sysrq_xlate = mackbd_sysrq_xlate;
+ ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate;
+ SYSRQ_KEY = 0x69;
#endif
}
#else
ppc_md.kbd_leds = pckbd_leds;
ppc_md.kbd_init_hw = pckbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ SYSRQ_KEY = 0x54;
#endif
#endif
#endif
ppc_ide_md.outsw = chrp_ide_outsw;
ppc_ide_md.default_irq = chrp_ide_default_irq;
ppc_ide_md.default_io_base = chrp_ide_default_io_base;
- ppc_ide_md.check_region = chrp_ide_check_region;
- ppc_ide_md.request_region = chrp_ide_request_region;
- ppc_ide_md.release_region = chrp_ide_release_region;
+ ppc_ide_md.ide_check_region = chrp_ide_check_region;
+ ppc_ide_md.ide_request_region = chrp_ide_request_region;
+ ppc_ide_md.ide_release_region = chrp_ide_release_region;
ppc_ide_md.fix_driveid = chrp_ide_fix_driveid;
ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;
/*
- * $Id: idle.c,v 1.62 1999/05/24 05:43:18 cort Exp $
+ * $Id: idle.c,v 1.63 1999/06/10 22:55:35 geert Exp $
*
* Idle daemon for PowerPC. Idle daemon will handle any action
* that needs to be taken when the system becomes idle.
case 7: /* 603ev */
case 8: /* 750 */
save_flags(msr);
- cli();
+ __cli();
if (!current->need_resched) {
asm("mfspr %0,1008" : "=r" (hid0) :);
hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE);
/*
- * $Id: irq.c,v 1.106 1999/05/25 21:16:04 cort Exp $
+ * $Id: irq.c,v 1.107 1999/06/17 05:39:12 paulus Exp $
*
* arch/ppc/kernel/irq.c
*
request_irq(irq, NULL, 0, NULL, dev_id);
}
+/* XXX should implement irq disable depth like on intel */
+void disable_irq_nosync(unsigned int irq_nr)
+{
+ mask_irq(irq_nr);
+}
+
void disable_irq(unsigned int irq_nr)
{
mask_irq(irq_nr);
/*
- * $Id: mbx_setup.c,v 1.10 1999/05/14 07:24:19 davem Exp $
+ * $Id: mbx_setup.c,v 1.11 1999/06/28 17:59:43 cort Exp $
*
* linux/arch/ppc/kernel/setup.c
*
ppc_ide_md.outsw = mbx_ide_outsw;
ppc_ide_md.default_irq = mbx_ide_default_irq;
ppc_ide_md.default_io_base = mbx_ide_default_io_base;
- ppc_ide_md.check_region = mbx_ide_check_region;
- ppc_ide_md.request_region = mbx_ide_request_region;
- ppc_ide_md.release_region = mbx_ide_release_region;
+ ppc_ide_md.ide_check_region = mbx_ide_check_region;
+ ppc_ide_md.ide_request_region = mbx_ide_request_region;
+ ppc_ide_md.ide_release_region = mbx_ide_release_region;
ppc_ide_md.fix_driveid = mbx_ide_fix_driveid;
ppc_ide_md.ide_init_hwif = mbx_ide_init_hwif_ports;
/*
* Create a kernel thread
- * __kernel_thread(flags, fn, arg)
+ * kernel_thread(fn, arg, flags)
*/
-_GLOBAL(__kernel_thread)
+_GLOBAL(kernel_thread)
+ mr r6,r3 /* function */
+ ori r3,r5,CLONE_VM /* flags */
li r0,__NR_clone
sc
cmpi 0,r3,0 /* parent or child? */
bnelr /* return if parent */
li r0,0 /* clear out p->tss.regs */
stw r0,TSS+PT_REGS(r2) /* since we don't have user ctx */
- mtlr r4 /* fn addr in lr */
- mr r3,r5 /* load arg and call fn */
+ mtlr r6 /* fn addr in lr */
+ mr r3,r4 /* load arg and call fn */
blrl
li r0,__NR_exit /* exit after child exits */
li r3,0
.long sys_getresuid /* 165 */
.long sys_query_module
.long sys_poll
-#ifdef CONFIG_NFS
+#ifdef CONFIG_NFSD
.long sys_nfsservctl
#else
.long sys_ni_syscall
DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3));
DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
+ DEFINE(CLONE_VM, CLONE_VM);
return 0;
}
#include <linux/vt_kern.h>
#include <linux/console.h>
#include <linux/ide.h>
+#include <linux/pci.h>
#include <asm/prom.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/feature.h>
#include <asm/ide.h>
#include <asm/machdep.h>
+#include <asm/keyboard.h>
#include "time.h"
#include "local_irq.h"
extern void zs_kgdb_hook(int tty_num);
static void ohare_init(void);
+static void init_p2pbridge(void);
__pmac
int
ohare_init();
*memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+ init_p2pbridge();
/* Checks "l2cr-value" property in the registry */
if ( (_get_PVR() >> 16) == 8) {
ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
}
+/*
+ * Tweak the PCI-PCI bridge chip on the blue & white G3s.
+ */
+__initfunc(static void init_p2pbridge(void))
+{
+ struct device_node *p2pbridge;
+ unsigned char bus, devfn;
+ unsigned short val;
+
+ /* XXX it would be better here to identify the specific
+ PCI-PCI bridge chip we have. */
+ if ((p2pbridge = find_devices("pci-bridge")) == 0
+ || p2pbridge->parent == NULL
+ || strcmp(p2pbridge->parent->name, "pci") != 0)
+ return;
+
+ if (pci_device_loc(p2pbridge, &bus, &devfn) < 0)
+ return;
+
+ pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val);
+ val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
+ pcibios_write_config_word(bus, devfn, PCI_BRIDGE_CONTROL, val);
+ pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val);
+}
+
__initfunc(static void ohare_init(void))
{
/*
void
pmac_ide_insw(ide_ioreg_t port, void *buf, int ns)
{
- ide_insw(port, buf, ns);
+ _insw_ns(port+_IO_BASE, buf, ns);
}
void
pmac_ide_outsw(ide_ioreg_t port, void *buf, int ns)
{
- ide_outsw(port, buf, ns);
+ _outsw_ns(port+_IO_BASE, buf, ns);
}
int
ppc_md.kbd_leds = mackbd_leds;
ppc_md.kbd_init_hw = mackbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.kbd_sysrq_xlate = mackbd_sysrq_xlate;
+ ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate;
+ SYSRQ_KEY = 0x69;
#endif
#endif
ppc_ide_md.outsw = pmac_ide_outsw;
ppc_ide_md.default_irq = pmac_ide_default_irq;
ppc_ide_md.default_io_base = pmac_ide_default_io_base;
- ppc_ide_md.check_region = pmac_ide_check_region;
- ppc_ide_md.request_region = pmac_ide_request_region;
- ppc_ide_md.release_region = pmac_ide_release_region;
+ ppc_ide_md.ide_check_region = pmac_ide_check_region;
+ ppc_ide_md.ide_request_region = pmac_ide_request_region;
+ ppc_ide_md.ide_release_region = pmac_ide_release_region;
ppc_ide_md.fix_driveid = pmac_ide_fix_driveid;
ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
- ppc_ide_md.io_base = 0;
+ ppc_ide_md.io_base = _IO_BASE; /* actually too early for this :-( */
#endif
}
/*
- * $Id: ppc_htab.c,v 1.26 1998/12/10 00:24:23 cort Exp $
+ * $Id: ppc_htab.c,v 1.28 1999/06/27 10:53:32 davem Exp $
*
* PowerPC hash table management proc entry. Will show information
* about the current hash table and will allow changes to it.
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
#include <asm/dma.h>
#include <asm/machdep.h>
-#define __KERNEL_SYSCALLS__
-#include <linux/unistd.h>
+/* Tell string.h we don't want memcpy etc. as cpp defines */
+#define EXPORT_SYMTAB_STROPS
extern void transfer_to_handler(void);
extern void int_return(void);
extern void do_lost_interrupts(unsigned long);
extern int do_signal(sigset_t *, struct pt_regs *);
-asmlinkage long long __ashrdi3(long long, int);
asmlinkage int abs(int);
EXPORT_SYMBOL(clear_page);
EXPORT_SYMBOL(do_lost_interrupts);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(disable_irq_nosync);
EXPORT_SYMBOL(ppc_local_irq_count);
EXPORT_SYMBOL(ppc_local_bh_count);
EXPORT_SYMBOL(strspn);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(memcmp);
/* EXPORT_SYMBOL(csum_partial); already in net/netsyms.c */
EXPORT_SYMBOL(csum_partial_copy_generic);
EXPORT_SYMBOL(ide_insw);
EXPORT_SYMBOL(ide_outsw);
+EXPORT_SYMBOL(ppc_ide_md);
EXPORT_SYMBOL(start_thread);
-EXPORT_SYMBOL(__kernel_thread);
+EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(__cli);
EXPORT_SYMBOL(__sti);
EXPORT_SYMBOL(nvram_write_byte);
#endif /* CONFIG_PMAC */
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL_NOVERS(memcmp);
+
EXPORT_SYMBOL(abs);
EXPORT_SYMBOL(device_is_compatible);
-
-/* The following are special because they're not called
- explicitly (the C compiler generates them). Fortunately,
- their interface isn't gonna change any time soon now, so
- it's OK to leave it out of version control. */
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
#include <asm/mk48t59.h>
#include <asm/prep_nvram.h>
#include <asm/raven.h>
-
+#include <asm/keyboard.h>
#include "time.h"
#include "local_irq.h"
ppc_ide_md.outsw = prep_ide_outsw;
ppc_ide_md.default_irq = prep_ide_default_irq;
ppc_ide_md.default_io_base = prep_ide_default_io_base;
- ppc_ide_md.check_region = prep_ide_check_region;
- ppc_ide_md.request_region = prep_ide_request_region;
- ppc_ide_md.release_region = prep_ide_release_region;
+ ppc_ide_md.ide_check_region = prep_ide_check_region;
+ ppc_ide_md.ide_request_region = prep_ide_request_region;
+ ppc_ide_md.ide_release_region = prep_ide_release_region;
ppc_ide_md.fix_driveid = prep_ide_fix_driveid;
ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports;
#endif
ppc_md.kbd_leds = pckbd_leds;
ppc_md.kbd_init_hw = pckbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ SYSRQ_KEY = 0x54;
#endif
#endif
}
/*
- * $Id: process.c,v 1.85 1999/05/16 21:27:08 cort Exp $
+ * $Id: process.c,v 1.86 1999/06/17 21:53:46 cort Exp $
*
* linux/arch/ppc/kernel/process.c
*
p->tss.fpscr = current->tss.fpscr;
childregs->msr &= ~MSR_FP;
+ p->processor = 0;
#ifdef __SMP__
p->last_processor = NO_PROC_ID;
#endif /* __SMP__ */
/*
- * $Id: prom.c,v 1.60 1999/05/25 01:42:41 cort Exp $
+ * $Id: prom.c,v 1.61 1999/06/17 06:05:52 paulus Exp $
*
* Procedures for interfacing to the Open Firmware PROM on
* Power Macintosh computers.
*/
model = (char *) early_get_property
(r4 + bi->deviceTreeOffset, 4, RELOC("model"));
- if (model && strcmp(model, RELOC("iMac,1")) == 0) {
+ if (model
+ && (strcmp(model, RELOC("iMac,1")) == 0
+ || strcmp(model, RELOC("PowerMac1,1")) == 0)) {
out_le32((unsigned *)0x80880008, 1); /* XXX */
}
}
&& (imp = (struct pci_intr_map *)
get_property(np->parent, "interrupt-map", &ml)) != 0
&& (ip = (int *) get_property(np, "interrupts", &l)) != 0) {
- unsigned int busdevfn = pci_addrs[0].addr.a_hi & 0xffff00;
+ unsigned int devfn = pci_addrs[0].addr.a_hi & 0xff00;
np->n_intrs = 0;
np->intrs = (struct interrupt_info *) mem_start;
for (i = 0; (ml -= sizeof(struct pci_intr_map)) >= 0; ++i) {
- if (imp[i].addr.a_hi == busdevfn) {
+ if (imp[i].addr.a_hi == devfn) {
np->intrs[np->n_intrs].line = imp[i].intr;
np->intrs[np->n_intrs].sense = 0;
++np->n_intrs;
/*
- * $Id: setup.c,v 1.133 1999/05/14 07:24:30 davem Exp $
+ * $Id: setup.c,v 1.136 1999/06/18 07:11:35 cort Exp $
* Common prep/pmac/chrp boot and setup code.
*/
int have_of = 0;
int is_prep = 0;
int is_chrp = 0;
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned long SYSRQ_KEY;
+#endif /* CONFIG_MAGIC_SYSRQ */
/* For MTX/MVME boards.. with Raven/Falcon Chipset
Real close to CHRP, but boot like PReP (via PPCbug)
There's probably a nicer way to do this.. --Troy */
ppc_md.halt();
}
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-void ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
-{
- if (ppc_ide_md.ide_init_hwif != NULL) {
- ppc_ide_md.ide_init_hwif(hw, data_port, ctrl_port, irq);
- }
-}
-#endif
-
unsigned long cpu_temp(void)
{
unsigned char thres = 0;
else
{
_machine = _MACH_Pmac;
- is_prep = 1;
}
}
/*
* linux/arch/ppc/kernel/signal.c
*
- * $Id: signal.c,v 1.24 1999/04/03 11:25:16 paulus Exp $
+ * $Id: signal.c,v 1.25 1999/06/17 05:40:20 paulus Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
default:
lock_kernel();
sigaddset(¤t->signal, signr);
+ recalc_sigpending(current);
current->flags |= PF_SIGNALED;
do_exit(exit_code);
/* NOTREACHED */
/*
- * $Id: smp.c,v 1.52 1999/05/23 22:43:51 cort Exp $
+ * $Id: smp.c,v 1.54 1999/06/24 17:13:34 cort Exp $
*
* Smp support for ppc.
*
{
extern struct task_struct *current_set[NR_CPUS];
extern void __secondary_start_psurge(void);
- int i;
+ extern void __secondary_start_chrp(void);
+ int i, cpu_nr;
struct task_struct *p;
unsigned long a;
printk("Entering SMP Mode...\n");
/* let other processors know to not do certain initialization */
first_cpu_booted = 1;
+ smp_num_cpus = 1;
/*
* assume for now that the first cpu booted is
* cpu 0, the master -- Cort
*/
cpu_callin_map[0] = 1;
- cpu_callin_map[1] = 0;
smp_store_cpu_info(0);
active_kernel_processor = 0;
current->processor = 0;
{
case _MACH_Pmac:
/* assume powersurge board - 2 processors -- Cort */
- smp_num_cpus = 2;
+ cpu_nr = 2;
break;
case _MACH_chrp:
- smp_num_cpus = ((openpic_read(&OpenPIC->Global.Feature_Reporting0)
+ cpu_nr = ((openpic_read(&OpenPIC->Global.Feature_Reporting0)
& OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT)+1;
- /* get our processor # - we may not be cpu 0 */
- printk("SMP %d processors, boot CPU is %d (should be 0)\n",
- smp_num_cpus,
- 10/*openpic_read(&OpenPIC->Processor[0]._Who_Am_I)*/);
break;
}
* only check for cpus we know exist. We keep the callin map
* with cpus at the bottom -- Cort
*/
- for ( i = 1 ; i < smp_num_cpus; i++ )
+ for ( i = 1 ; i < cpu_nr; i++ )
{
int c;
case _MACH_chrp:
*(unsigned long *)KERNELBASE = i;
asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+#if 0
+ device = find_type_devices("cpu");
+ /* assume cpu device list is in order, find the ith cpu */
+ for ( a = i; device && a; device = device->next, a-- )
+ ;
+ if ( !device )
+ break;
+ printk( "Starting %s (%lu): ", device->full_name,
+ *(ulong *)get_property(device, "reg", NULL) );
+ call_rtas( "start-cpu", 3, 1, NULL,
+ *(ulong *)get_property(device, "reg", NULL),
+ __pa(__secondary_start_chrp), i);
+#endif
break;
}
/* this sync's the decr's -- Cort */
if ( _machine == _MACH_Pmac )
set_dec(decrementer_count);
+ smp_num_cpus++;
} else {
printk("Processor %d is stuck.\n", i);
}
void __init smp_commence(void)
{
- printk("SMP %d: smp_commence()\n",current->processor);
/*
* Lets the callin's below out of their loop.
*/
/* Activate a secondary processor. */
asmlinkage int __init start_secondary(void *unused)
{
- printk("SMP %d: start_secondary()\n",current->processor);
smp_callin();
return cpu_idle(NULL);
}
void __init smp_callin(void)
{
- int i;
-
- printk("SMP %d: smp_callin()\n",current->processor);
smp_store_cpu_info(current->processor);
set_dec(decrementer_count);
void __init smp_setup(char *str, int *ints)
{
- printk("SMP %d: smp_setup()\n",current->processor);
}
int __init setup_profiling_timer(unsigned int multiplier)
#include <linux/sys.h>
#include <linux/ipc.h>
#include <linux/utsname.h>
+#include <linux/file.h>
#include <asm/uaccess.h>
#include <asm/ipc.h>
/*
- * $Id: time.c,v 1.48 1999/05/22 19:35:57 cort Exp $
+ * $Id: time.c,v 1.50 1999/06/05 00:23:20 cort Exp $
* Common time routines among all ppc machines.
*
* Written by Cort Dougan (cort@cs.nmt.edu) to merge
smp_local_timer_interrupt(regs);
#endif
-#ifdef CONFIG_APUS
- {
- extern void apus_heartbeat (void);
- apus_heartbeat ();
- }
-#endif
-#if defined(CONFIG_ALL_PPC) || defined(CONFIG_CHRP)
- if ( _machine == _MACH_chrp )
- chrp_event_scan();
-#endif
-
+ if ( ppc_md.heartbeat && !ppc_md.heartbeat_count--)
+ ppc_md.heartbeat();
+
hardirq_exit(cpu);
}
/*
- * $Id: init.c,v 1.166 1999/05/22 18:18:30 cort Exp $
+ * $Id: init.c,v 1.169 1999/06/17 19:03:13 cort Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
#endif /* __SMP__ */
printk("\n");
for_each_task(p)
- {
+ {
printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ",
p->comm,p->pid,
- atomic_read(&p->mm->count),p->mm->context,
- p->mm->context<<4, p->tss.last_syscall,
- user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip,
+ (p->mm)?atomic_read(&p->mm->count):0,
+ (p->mm)?p->mm->context:0,
+ (p->mm)?(p->mm->context<<4):0,
+ p->tss.last_syscall,
+ (p->tss.regs)?user_mode(p->tss.regs) ? 'u' : 'k' : '?',
+ (p->tss.regs)?p->tss.regs->nip:0,
(ulong)p);
{
int iscur = 0;
iscur = 1;
printk("current");
}
-#else
+#else
if ( p == current )
{
iscur = 1;
p = addr & PAGE_MASK;
size = PAGE_ALIGN(addr + size) - p;
+ /*
+ * If the address lies within the first 16 MB, assume it's in ISA
+ * memory space
+ */
+ if (p < 16*1024*1024)
+ p += _ISA_MEM_BASE;
+
/*
* Don't allow anybody to remap normal RAM that we're using.
* mem_init() sets high_memory so only do the check after that.
* same virt address (and this is contiguous).
* -- Cort
*/
- if ( (v = p_mapped_by_bats(addr)) /*&& p_mapped_by_bats(addr+(size-1))*/ )
+ if ( (v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
goto out;
#endif /* CONFIG_8xx */
#ifdef CHRP_ESCC
unsigned long addr = 0xc1013020;
#else
- unsigned long addr = 0xf3013030;
+ unsigned long addr = 0xf3013020;
#endif
TXRDY = 4;
RXRDY = 1;
static char *help_string = "\
Commands:\n\
d dump bytes\n\
- dc dump characters\n\
di dump instructions\n\
df dump float values\n\
dd dump double values\n\
{
printf("vector: %x at pc = %x, msr = %x, sp = %x [%x]\n",
fp->trap, fp->nip, fp->msr, fp->gpr[1], fp);
- if ((fp->trap == 0x300) || (fp->trap == 0x600) || (fp->trap == 0x200))
+ if (fp->trap == 0x300 || fp->trap == 0x600)
printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
if (current)
printf("current = %x, pid = %d, comm = %s\n",
return c;
}
-#define isxdigit(c) ('0' <= (c) && (c) <= '9' || 'a' <= (c) && (c) <= 'f' \
- || 'A' <= (c) && (c) <= 'F')
+#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
+ || ('a' <= (c) && (c) <= 'f') \
+ || ('A' <= (c) && (c) <= 'F'))
void
dump()
{
int c;
c = inchar();
- if ((isxdigit(c) && (c != 'f') && (c != 'd')) || (c == '\n'))
+ if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
termch = c;
scanhex(&adrs);
if( termch != '\n')
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
return;
if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
return;
- /*
- * This block is from a device that we're about to stomp on.
- * So make sure nobody thinks this block is usable.
- */
- bh->b_state = 0;
if ((*(unsigned short *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
goto done;
hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
this_sector = first_sector + START_SECT(p) * sector_size;
dev = MKDEV(hd->major, current_minor);
- brelse(bh);
+
+ /* Use bforget(), as we have changed the disk geometry */
+ bforget(bh);
}
done:
- brelse(bh);
+ bforget(bh);
}
#ifdef CONFIG_SOLARIS_X86_PARTITION
if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
return;
- bh->b_state = 0;
l = (struct bsd_disklabel *) (bh->b_data+512);
if (l->d_magic != BSD_DISKMAGIC) {
brelse(bh);
if (p->p_fstype != BSD_FS_UNUSED)
check_and_add_bsd_partition(hd, p, dev);
}
- brelse(bh);
+
+ /* Use bforget(), as we have changed the disk setup */
+ bforget(bh);
}
#endif
if (!(bh = bread(dev, 14, get_ptable_blocksize(dev))))
return;
- bh->b_state = 0;
l = (struct unixware_disklabel *) (bh->b_data+512);
if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
}
p++;
}
- brelse(bh);
+ /* Use bforget, as we have changed the disk setup */
+ bforget(bh);
printk(" >");
}
#endif
return -1;
}
data = bh->b_data;
- /* In some cases we modify the geometry */
- /* of the drive (below), so ensure that */
- /* nobody else tries to re-use this data. */
- bh->b_state = 0;
#ifdef CONFIG_BLK_DEV_IDE
check_table:
#endif
+ /* Use bforget(), because we have potentially changed the disk geometry */
if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
- brelse(bh);
+ bforget(bh);
return 0;
}
p = (struct partition *) (0x1be + data);
* adjustments to fool fdisk/LILO and partition check.
*/
if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
- brelse(bh);
+ bforget(bh);
goto read_mbr; /* start over with new MBR */
}
} else if (sig <= 0x1ae &&
}
}
printk("\n");
- brelse(bh);
+ bforget(bh);
return 1;
}
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
return -ERESTARTSYS;
}
#endif
+ lock_kernel();
if (tty->ldisc.read)
i = (tty->ldisc.read)(tty,file,buf,count);
else
i = -EIO;
+ unlock_kernel();
if (i > 0)
inode->i_atime = CURRENT_TIME;
return i;
unsigned long size = PAGE_SIZE*2;
if (size > count)
size = count;
+ lock_kernel();
ret = write(tty, file, buf, size);
+ unlock_kernel();
if (ret <= 0)
break;
written += ret;
by <tymm@computer.org>
0.451 5-Nov-98 Fixed mca stuff cuz I'm a dummy. <tymm@computer.org>
0.5 14-Nov-98 Re-spin for 2.1.x kernels.
+ 0.51 27-Jun-99 Correct received packet length for CRC from
+ report by <worm@dkik.dk>
=========================================================================
*/
-static const char *version = "depca.c:v0.5 1998/11/14 davies@maniac.ultranet.com\n";
+static const char *version = "depca.c:v0.51 1999/6/27 davies@maniac.ultranet.com\n";
#include <linux/config.h>
#include <linux/module.h>
if (status & R_CRC) lp->stats.rx_crc_errors++;
if (status & R_BUFF) lp->stats.rx_fifo_errors++;
} else {
- short len, pkt_len = readw(&lp->rx_ring[entry].msg_length);
+ short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4;
struct sk_buff *skb;
skb = dev_alloc_skb(pkt_len+2);
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
/* 4/4/1999 added data toggle for interrupt pipes -keryan */
/* 5/16/1999 added global toggles for bulk and control */
+/* 6/25/1999 added fix for data toggles on bidirectional bulk endpoints */
#include <linux/config.h>
#include <linux/module.h>
if (uhci_debug) {
printk("Set toggle from %x rval %d\n", (unsigned int)tmp, rval ? *rval : 0);
}
- usb_settoggle(dev->usb, usb_pipeendpoint(tmp->info), (tmp->info >> 19) & 1);
+ usb_settoggle(dev->usb, usb_pipeendpoint(tmp->info), usb_pipeout(tmp->info), (tmp->info >> 19) & 1);
break;
} else {
if(rval)
td->link = 1;
td->status = status; /* In */
- td->info = destination | (7 << 21) | (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe)) << 19); /* 8 bytes of data */
+ td->info = destination | (7 << 21) | (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* 8 bytes of data */
td->buffer = virt_to_bus(dev->data);
td->first = td;
td->qh = interrupt_qh;
td->status = status; /* Status */
td->info = destination | ((pktsze-1) << 21) |
- (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe)) << 19); /* pktsze bytes of data */
+ (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */
td->buffer = virt_to_bus(data);
td->backptr = &prevtd->link;
td->first = first;
}
/* Alternate Data0/1 (start with Data0) */
- usb_dotoggle(usb_dev, usb_pipeendpoint(pipe));
+ usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
}
td->link = 1; /* Terminate */
td->status |= (1 << 24); /* IOC */
if (!(td->status & (1 << 25))) {
struct uhci_qh *interrupt_qh = td->qh;
- usb_dotoggle(td->dev, usb_pipeendpoint(td->info));
+ usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
td->info &= ~(1 << 19); /* clear data toggle */
- td->info |= usb_gettoggle(td->dev, usb_pipeendpoint(td->info)) << 19; /* toggle between data0 and data1 */
+ td->info |= usb_gettoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)) << 19; /* toggle between data0 and data1 */
td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24); /* active */
/* Remove then readd? Is that necessary */
struct uhci_qh *interrupt_qh = td->qh;
/* marked for removal */
td->inuse &= ~2;
- usb_dotoggle(td->dev, usb_pipeendpoint(td->info));
+ usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
uhci_remove_qh(interrupt_qh->skel, interrupt_qh);
uhci_qh_deallocate(interrupt_qh);
uhci_td_deallocate(td);
/* toggle is reset on clear */
- usb_settoggle(dev, endp & 0x0f, 0);
+ usb_settoggle(dev, endp & 0x0f, ((endp >> 7) & 1) ^ 1, 0);
return 0;
}
return -1;
dev->actconfig = cp;
- dev->toggle = 0;
+ dev->toggle[0] = 0;
+ dev->toggle[1] = 0;
usb_set_maxpacket(dev);
return 0;
}
int devnum; /* Device number on USB bus */
int slow; /* Slow device? */
int maxpacketsize; /* Maximum packet size */
- int toggle; /* one bit for each endpoint */
+ int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */
int halted; /* endpoint halts */
struct usb_config_descriptor *actconfig;/* the active configuration */
int epmaxpacket[16]; /* endpoint specific maximums */
#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
#define usb_pipedata(pipe) (((pipe) >> 19) & 1)
-#define usb_pipeout(pipe) (((pipe) & 0x80) == 0)
+#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1)
#define usb_pipeslow(pipe) (((pipe) >> 26) & 1)
#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff)
/* The D0/D1 toggle bits */
-#define usb_gettoggle(dev, ep) (((dev)->toggle >> ep) & 1)
-#define usb_dotoggle(dev, ep) ((dev)->toggle ^= (1 << ep))
-#define usb_settoggle(dev, ep, bit) ((dev)->toggle = ((dev)->toggle & ~(1 << ep)) | ((bit) << ep))
+#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1)
+#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep))
+#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << ep)) | ((bit) << ep))
/* Endpoint halt */
#define usb_endpoint_halt(dev, ep) ((dev)->halted |= (1 << (ep)))
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* read link */
NULL, /* follow link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* read page */
NULL, /* write page */
NULL, /* flush page */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- adfs_bmap, /* bmap */
+ adfs_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
affs_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- affs_bmap, /* bmap */
+ affs_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
affs_readlink, /* readlink */
affs_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
autofs_readlink, /* readlink */
autofs_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
coda_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
coda_readpage, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
coda_readlink, /* readlink */
coda_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL /* revalidate */
};
+extern int efs_get_block(struct inode *, long, struct buffer_head *, int);
+
struct inode_operations efs_dir_inode_operations = {
&efs_dir_operations, /* default directory file-ops */
NULL, /* create */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- efs_bmap, /* bmap */
+ efs_get_block, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
#include <linux/efs_fs.h>
+int efs_get_block(struct inode *inode, long iblock,
+ struct buffer_head *bh_result, int create)
+{
+ int error = -EROFS;
+ long phys;
+
+ if (create)
+ return error;
+ if (iblock >= inode->i_blocks) {
+#ifdef DEBUG
+ /*
+ * i have no idea why this happens as often as it does
+ */
+ printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n",
+ block,
+ inode->i_blocks,
+ inode->i_size);
+#endif
+ return 0;
+ }
+ phys = efs_map_block(inode, iblock);
+ if (phys) {
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = phys;
+ bh_result->b_state |= (1UL << BH_Mapped);
+ }
+ return 0;
+}
+
+int efs_bmap(struct inode *inode, efs_block_t block) {
+
+ if (block < 0) {
+ printk(KERN_WARNING "EFS: bmap(): block < 0\n");
+ return 0;
+ }
+
+ /* are we about to read past the end of a file ? */
+ if (!(block < inode->i_blocks)) {
+#ifdef DEBUG
+ /*
+ * i have no idea why this happens as often as it does
+ */
+ printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n",
+ block,
+ inode->i_blocks,
+ inode->i_size);
+#endif
+ return 0;
+ }
+
+ return efs_map_block(inode, block);
+}
+
static struct file_operations efs_file_operations = {
NULL, /* lseek */
generic_file_read, /* read */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- efs_bmap, /* bmap */
+ efs_get_block, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* smap */
NULL /* revalidate */
};
-
-int efs_bmap(struct inode *inode, efs_block_t block) {
-
- if (block < 0) {
- printk(KERN_WARNING "EFS: bmap(): block < 0\n");
- return 0;
- }
-
- /* are we about to read past the end of a file ? */
- if (!(block < inode->i_blocks)) {
-#ifdef DEBUG
- /*
- * i have no idea why this happens as often as it does
- */
- printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n",
- block,
- inode->i_blocks,
- inode->i_size);
-#endif
- return 0;
- }
-
- return efs_map_block(inode, block);
-}
-
NULL, /* rename */
efs_readlink, /* readlink */
efs_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- fat_bmap, /* bmap */
+ fat_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
fat_readpage, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
nr_free_files--;
new_one:
memset(f, 0, sizeof(*f));
- f->f_count = 1;
+ atomic_set(&f->f_count, 1);
f->f_version = ++event;
f->f_uid = current->fsuid;
f->f_gid = current->fsgid;
{
memset(filp, 0, sizeof(*filp));
filp->f_mode = mode;
- filp->f_count = 1;
+ atomic_set(&filp->f_count, 1);
filp->f_dentry = dentry;
filp->f_uid = current->fsuid;
filp->f_gid = current->fsgid;
void fput(struct file *file)
{
- int count = file->f_count-1;
-
- if (!count) {
+ if (atomic_dec_and_test(&file->f_count)) {
locks_remove_flock(file);
__fput(file);
- file->f_count = 0;
remove_filp(file);
insert_file_free(file);
- } else
- file->f_count = count;
+ }
}
void put_filp(struct file *file)
{
- if(--file->f_count == 0) {
+ if (atomic_dec_and_test(&file->f_count)) {
remove_filp(file);
insert_file_free(file);
}
hfs_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
dbl_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
hfs_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
nat_hdr_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- hfs_bmap, /* bmap */
+ hfs_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap - none */
+ NULL, /* get_block - none */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap - XXX: not available since
+ NULL, /* get_block - XXX: not available since
header part has no disk block */
NULL, /* readpage */
NULL, /* writepage */
anode = hpfs_map_anode(s, ano, &bh);
btree1 = &anode->btree;
} else btree1 = btree;
- for (i = 0; i < btree1->n_used_nodes; i++)
- if (btree1->u.internal[i].down == oano)
- if ((pos = i + 1) < btree1->n_used_nodes) goto go_down;
- else goto go_up;
- hpfs_error(s, "reference to anode %08x not found in anode %08x (probably bad up pointer)",
- oano, level ? ano : -1);
- if (level) brelse(bh);
+ for (i = 0; i < btree1->n_used_nodes; i++) {
+ if (btree1->u.internal[i].down == oano) {
+ if ((pos = i + 1) < btree1->n_used_nodes)
+ goto go_down;
+ else
+ goto go_up;
+ }
+ }
+ hpfs_error(s,
+ "reference to anode %08x not found in anode %08x "
+ "(probably bad up pointer)",
+ oano, level ? ano : -1);
+ if (level)
+ brelse(bh);
}
/* Just a wrapper around hpfs_bplus_lookup .. used for reading eas */
goto bail;
fnode->ea_anode = 0;
len++;
- }
- else if (!fnode->ea_anode)
- if (hpfs_alloc_if_possible(s, fnode->ea_secno + len)) len++;
- else {
+ } else if (!fnode->ea_anode) {
+ if (hpfs_alloc_if_possible(s, fnode->ea_secno + len)) {
+ len++;
+ } else {
/* Aargh... don't know how to create ea anodes :-( */
/*struct buffer_head *bh;
struct anode *anode;
fnode->ea_secno = new_sec;
len = (pos + 511) >> 9;
}
- if (fnode->ea_anode)
- if (hpfs_add_sector_to_btree(s, fnode->ea_secno, 0, len) != -1)
+ }
+ if (fnode->ea_anode) {
+ if (hpfs_add_sector_to_btree(s, fnode->ea_secno,
+ 0, len) != -1) {
len++;
- else goto bail;
+ } else {
+ goto bail;
+ }
+ }
}
h[0] = 0;
h[1] = strlen(key);
return buffer_uptodate(bh) ? 0 : -EIO;
}
-int hpfs_writepage(struct file *file, struct page *page)
-{
- return block_write_full_page(file, page, hpfs_get_block);
-}
-
-long hpfs_write_one_page (struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char *buf)
-{
- return block_write_partial_page(file, page, offset, bytes, buf, hpfs_get_block);
-}
-
-
ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
ssize_t retval;
- struct inode *inode = file->f_dentry->d_inode;
- retval = generic_file_write(file, buf, count, ppos, hpfs_write_one_page);
+
+ retval = generic_file_write(file, buf, count,
+ ppos, block_write_partial_page);
if (retval > 0) {
- /*remove_suid(inode);*/
+ struct inode *inode = file->f_dentry->d_inode;
inode->i_mtime = CURRENT_TIME;
inode->i_hpfs_dirty = 1;
}
NULL, /* readlink */
NULL, /* follow_link */
(int (*)(struct inode *, int))
- &hpfs_bmap, /* bmap */
+#warning Someone needs to code up hpfs_get_block properly... -DaveM
+ &hpfs_bmap, /* get_block */
block_read_full_page, /* readpage */
hpfs_writepage, /* writepage */
block_flushpage, /* flushpage */
hpfs_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
hpfs_readlink, /* readlink */
hpfs_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
return 1;
}
-static inline void hpfs_help()
+static inline void hpfs_help(void)
{
printk("\n\
HPFS filesystem options:\n\
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- isofs_bmap, /* bmap */
+ isofs_get_block, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
static int isofs_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
#endif
-void isofs_put_super(struct super_block *sb)
+static void isofs_put_super(struct super_block *sb)
{
#ifdef CONFIG_JOLIET
if (sb->u.isofs_sb.s_nls_iocharset) {
return;
}
+static void isofs_read_inode(struct inode *);
+static int isofs_statfs (struct super_block *, struct statfs *, int);
+
static struct super_operations isofs_sops = {
isofs_read_inode,
NULL, /* write_inode */
* Note: a check_disk_change() has been done immediately prior
* to this call, so we don't need to check again.
*/
-struct super_block *isofs_read_super(struct super_block *s, void *data,
- int silent)
+static struct super_block *isofs_read_super(struct super_block *s, void *data,
+ int silent)
{
kdev_t dev = s->s_dev;
struct buffer_head * bh = NULL, *pri_bh = NULL;
return NULL;
}
-int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
+static int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
{
struct statfs tmp;
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
-static int do_isofs_bmap(struct inode * inode,int block)
+/* Life is simpler than for other filesystem since we never
+ * have to create a new block, only find an existing one.
+ */
+int isofs_get_block(struct inode *inode, long iblock,
+ struct buffer_head *bh_result, int create)
{
- off_t b_off, offset, size;
- struct inode *ino;
+ off_t b_off, offset, sect_size;
unsigned int firstext;
unsigned long nextino;
- int i;
+ int i, err;
- if (block<0) {
- printk("_isofs_bmap: block<0");
- return 0;
- }
+ lock_kernel();
- b_off = block << ISOFS_BUFFER_BITS(inode);
+ err = -EROFS;
+ if (create)
+ goto abort_create_attempted;
- /*
- * If we are beyond the end of this file, don't give out any
+ err = -EIO;
+ if (iblock < 0)
+ goto abort_negative;
+
+ b_off = iblock << ISOFS_BUFFER_BITS(inode);
+
+ /* If we are beyond the end of this file, don't give out any
* blocks.
*/
- if( b_off > inode->i_size )
- {
- off_t max_legal_read_offset;
-
- /*
- * If we are *way* beyond the end of the file, print a message.
- * Access beyond the end of the file up to the next page boundary
- * is normal, however because of the way the page cache works.
- * In this case, we just return 0 so that we can properly fill
- * the page with useless information without generating any
- * I/O errors.
- */
- max_legal_read_offset = (inode->i_size + PAGE_SIZE - 1)
- & ~(PAGE_SIZE - 1);
- if( b_off >= max_legal_read_offset )
- {
-
- printk("_isofs_bmap: block>= EOF(%d, %ld)\n", block,
- inode->i_size);
- }
- return 0;
- }
+ if (b_off > inode->i_size) {
+ off_t max_legal_read_offset;
+
+ /* If we are *way* beyond the end of the file, print a message.
+ * Access beyond the end of the file up to the next page boundary
+ * is normal, however because of the way the page cache works.
+ * In this case, we just return 0 so that we can properly fill
+ * the page with useless information without generating any
+ * I/O errors.
+ */
+ max_legal_read_offset = (inode->i_size + PAGE_SIZE - 1)
+ & ~(PAGE_SIZE - 1);
+ if (b_off >= max_legal_read_offset)
+ goto abort_beyond_end;
+ }
+
+ offset = 0;
+ firstext = inode->u.isofs_i.i_first_extent;
+ sect_size = inode->u.isofs_i.i_section_size;
+ nextino = inode->u.isofs_i.i_next_section_ino;
- offset = 0;
- firstext = inode->u.isofs_i.i_first_extent;
- size = inode->u.isofs_i.i_section_size;
- nextino = inode->u.isofs_i.i_next_section_ino;
-#ifdef DEBUG
- printk("first inode: inode=%x nextino=%x firstext=%u size=%lu\n",
- inode->i_ino, nextino, firstext, size);
-#endif
i = 0;
if (nextino) {
- while(b_off >= offset + size) {
- offset += size;
-
- if(nextino == 0) return 0;
- ino = iget(inode->i_sb, nextino);
- if(!ino) return 0;
- firstext = ino->u.isofs_i.i_first_extent;
- size = ino->u.isofs_i.i_section_size;
-#ifdef DEBUG
- printk("read inode: inode=%lu ino=%lu nextino=%lu firstext=%u size=%lu\n",
- inode->i_ino, nextino, ino->u.isofs_i.i_next_section_ino, firstext, size);
-#endif
- nextino = ino->u.isofs_i.i_next_section_ino;
- iput(ino);
-
- if(++i > 100) {
- printk("isofs_bmap: More than 100 file sections ?!?, aborting...\n");
- printk("isofs_bmap: ino=%lu block=%d firstext=%u size=%u nextino=%lu\n",
- inode->i_ino, block, firstext, (unsigned)size, nextino);
- return 0;
- }
+ while (b_off >= (offset + sect_size)) {
+ struct inode *ninode;
+
+ offset += sect_size;
+ if (nextino == 0)
+ goto abort;
+ ninode = iget(inode->i_sb, nextino);
+ if (!ninode)
+ goto abort;
+ firstext = ninode->u.isofs_i.i_first_extent;
+ sect_size = ninode->u.isofs_i.i_section_size;
+ nextino = ninode->u.isofs_i.i_next_section_ino;
+ iput(ninode);
+
+ if (++i > 100)
+ goto abort_too_many_sections;
}
}
-#ifdef DEBUG
- printk("isofs_bmap: mapped inode:block %x:%d to block %lu\n",
- inode->i_ino, block, (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode));
-#endif
- return (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode);
-}
-int isofs_bmap(struct inode * inode,int block)
-{
- int retval;
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr =
+ (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode);
+ bh_result->b_state |= (1UL << BH_Mapped);
+ err = 0;
- lock_kernel();
- retval = do_isofs_bmap(inode, block);
+abort:
unlock_kernel();
- return retval;
+ return err;
+
+abort_create_attempted:
+ printk("_isofs_bmap: Kernel tries to allocate a block\n");
+ goto abort;
+
+abort_negative:
+ printk("_isofs_bmap: block < 0\n");
+ goto abort;
+
+abort_beyond_end:
+ printk("_isofs_bmap: block >= EOF (%ld, %ld)\n",
+ iblock, inode->i_size);
+ goto abort;
+
+abort_too_many_sections:
+ printk("isofs_bmap: More than 100 file sections ?!?, aborting...\n");
+ printk("isofs_bmap: ino=%lu block=%ld firstext=%u sect_size=%u nextino=%lu\n",
+ inode->i_ino, iblock, firstext, (unsigned) sect_size, nextino);
+ goto abort;
+}
+
+int isofs_bmap(struct inode *inode, int block)
+{
+ struct buffer_head dummy;
+ int error;
+
+ dummy.b_state = 0;
+ dummy.b_blocknr = -1000;
+ error = isofs_get_block(inode, block, &dummy, 0);
+ if (!error)
+ return dummy.b_blocknr;
+ return 0;
}
static void test_and_set_uid(uid_t *p, uid_t value)
goto out;
}
-void isofs_read_inode(struct inode * inode)
+static void isofs_read_inode(struct inode * inode)
{
struct super_block *sb = inode->i_sb;
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
NULL, /* rename */
isofs_readlink, /* readlink */
isofs_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
/* Candidates for mandatory locking have the setgid bit set
* but no group execute bit - an otherwise meaningless combination.
*/
- if (IS_MANDLOCK(inode) &&
- (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
- return (locks_mandatory_area(read_write, inode, filp, offset,
- count));
- return (0);
+ if (IS_MANDLOCK(inode) && (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) {
+ int retval;
+ lock_kernel();
+ retval = locks_mandatory_area(read_write, inode, filp, offset, count);
+ unlock_kernel();
+ return retval;
+ }
+ return 0;
}
int locks_mandatory_locked(struct inode *inode)
minix_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
#include <linux/fs.h>
#include <linux/minix_fs.h>
-static int minix_writepage(struct file *file, struct page *page)
-{
- return block_write_full_page(file, page, minix_getblk_block);
-}
-
-static long minix_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char *buf)
-{
- return block_write_partial_page(file, page, offset, bytes, buf, minix_getblk_block);
-}
-
/*
* Write to a file (through the page cache).
*/
static ssize_t
minix_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
- return generic_file_write(file, buf, count, ppos, minix_write_one_page);
+ return generic_file_write(file, buf, count,
+ ppos, block_write_partial_page);
}
/*
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- minix_bmap, /* bmap */
+ minix_get_block, /* get_block */
block_read_full_page, /* readpage */
- minix_writepage, /* writepage */
+ block_write_full_page, /* writepage */
block_flushpage, /* flushpage */
minix_truncate, /* truncate */
NULL, /* permission */
#include <linux/stat.h>
#include <linux/locks.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
return tmp;
}
-static int V1_minix_bmap(struct inode * inode,int block)
+static int V1_minix_block_map(struct inode * inode, long block)
{
- int i;
+ int i, ret;
- if (block<0) {
+ ret = 0;
+ lock_kernel();
+ if (block < 0) {
printk("minix_bmap: block<0");
- return 0;
+ goto out;
}
if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
printk("minix_bmap: block>big");
- return 0;
+ goto out;
+ }
+ if (block < 7) {
+ ret = V1_inode_bmap(inode,block);
+ goto out;
}
- if (block < 7)
- return V1_inode_bmap(inode,block);
block -= 7;
if (block < 512) {
i = V1_inode_bmap(inode,7);
if (!i)
- return 0;
- return V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
+ goto out;
+ ret = V1_block_bmap(bread(inode->i_dev, i,
+ BLOCK_SIZE), block);
+ goto out;
}
block -= 512;
i = V1_inode_bmap(inode,8);
if (!i)
- return 0;
+ goto out;
i = V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>9);
if (!i)
- return 0;
- return V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 511);
+ goto out;
+ ret = V1_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
+ block & 511);
+out:
+ unlock_kernel();
+ return ret;
}
/*
* The minix V2 fs bmap functions.
*/
-#define V2_inode_bmap(inode,nr) (((unsigned long *)(inode)->u.minix_i.u.i2_data)[(nr)])
+#define V2_inode_bmap(inode,nr) (((unsigned int *)(inode)->u.minix_i.u.i2_data)[(nr)])
static int V2_block_bmap(struct buffer_head * bh, int nr)
{
int tmp;
if (!bh)
return 0;
- tmp = ((unsigned long *) bh->b_data)[nr];
+ tmp = ((unsigned int *) bh->b_data)[nr];
brelse(bh);
return tmp;
}
-static int V2_minix_bmap(struct inode * inode, int block)
+static int V2_minix_block_map(struct inode * inode, int block)
{
- int i;
+ int i, ret;
- if (block<0) {
+ ret = 0;
+ lock_kernel();
+ if (block < 0) {
printk("minix_bmap: block<0");
- return 0;
+ goto out;
}
if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
printk("minix_bmap: block>big");
- return 0;
+ goto out;
+ }
+ if (block < 7) {
+ ret = V2_inode_bmap(inode,block);
+ goto out;
}
- if (block < 7)
- return V2_inode_bmap(inode,block);
block -= 7;
if (block < 256) {
- i = V2_inode_bmap(inode,7);
+ i = V2_inode_bmap(inode, 7);
if (!i)
- return 0;
- return V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
+ goto out;
+ ret = V2_block_bmap(bread(inode->i_dev, i,
+ BLOCK_SIZE), block);
+ goto out;
}
block -= 256;
- if (block < 256*256) {
- i = V2_inode_bmap(inode,8);
+ if (block < (256 * 256)) {
+ i = V2_inode_bmap(inode, 8);
if (!i)
- return 0;
- i = V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block >> 8);
+ goto out;
+ i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
+ block >> 8);
if (!i)
- return 0;
- return V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
+ goto out;
+ ret = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
+ block & 255);
+ goto out;
}
- block -= 256*256;
- i = V2_inode_bmap(inode,9);
+ block -= (256 * 256);
+ i = V2_inode_bmap(inode, 9);
if (!i)
- return 0;
- i = V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block >> 16);
+ goto out;
+ i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
+ block >> 16);
if (!i)
- return 0;
- i = V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block >> 8) & 255);
+ goto out;
+ i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
+ (block >> 8) & 255);
if (!i)
- return 0;
- return V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
-}
-
-/*
- * The global minix fs bmap function.
- */
-int minix_bmap(struct inode * inode, int block)
-{
- if (INODE_VERSION(inode) == MINIX_V1)
- return V1_minix_bmap(inode, block);
- else
- return V2_minix_bmap(inode, block);
+ goto out;
+ ret = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
+ block & 255);
+out:
+ unlock_kernel();
+ return ret;
}
/*
* The minix V1 fs getblk functions.
*/
-static struct buffer_head * V1_inode_getblk(struct inode * inode, int nr, int create,
- int metadata, int *phys_block, int *created)
+static struct buffer_head * V1_inode_getblk(struct inode * inode, int nr,
+ int new_block, int *err,
+ int metadata, int *phys, int *new)
{
int tmp;
unsigned short *p;
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
+ *phys = tmp;
return NULL;
}
}
- if (!create)
- return NULL;
+ *err = -EFBIG;
+
+ /* Check file limits.. */
+ {
+ unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= BLOCK_SIZE_BITS;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ *err = -EFBIG;
+ return NULL;
+ }
+ }
+ }
+
tmp = minix_new_block(inode->i_sb);
- if (!tmp)
+ if (!tmp) {
+ *err = -ENOSPC;
return NULL;
+ }
if (metadata) {
result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
if (*p) {
mark_buffer_dirty(result, 1);
} else {
if (*p) {
+ /*
+ * Nobody is allowed to change block allocation
+ * state from under us:
+ */
+ BUG();
minix_free_block(inode->i_sb, tmp);
goto repeat;
}
- *phys_block = tmp;
+ *phys = tmp;
result = NULL;
- *created = 1;
+ *err = 0;
+ *new = 1;
}
*p = tmp;
}
static struct buffer_head * V1_block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int create,
- int metadata, int *phys_block, int *created)
+ struct buffer_head * bh, int nr, int new_block, int *err,
+ int metadata, int *phys, int *new)
{
int tmp;
unsigned short *p;
struct buffer_head * result;
+ unsigned long limit;
+ result = NULL;
if (!bh)
- return NULL;
+ goto out;
if (!buffer_uptodate(bh)) {
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- return NULL;
- }
+ if (!buffer_uptodate(bh))
+ goto out;
}
p = nr + (unsigned short *) bh->b_data;
repeat:
if (tmp) {
if (metadata) {
result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (tmp == *p) {
- brelse(bh);
- return result;
- }
+ if (tmp == *p)
+ goto out;
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
- brelse(bh);
- return NULL;
+ *phys = tmp;
+ goto out;
}
}
- if (!create) {
- brelse(bh);
- return NULL;
+ *err = -EFBIG;
+
+ limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= BLOCK_SIZE_BITS;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ goto out;
+ }
}
+
tmp = minix_new_block(inode->i_sb);
- if (!tmp) {
- brelse(bh);
- return NULL;
- }
+ if (!tmp)
+ goto out;
if (metadata) {
result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
if (*p) {
mark_buffer_uptodate(result, 1);
mark_buffer_dirty(result, 1);
} else {
- if (*p) {
- minix_free_block(inode->i_sb, tmp);
- goto repeat;
- }
- *phys_block = tmp;
- result = NULL;
- *created = 1;
+ *phys = tmp;
+ *new = 1;
+ }
+ if (*p) {
+ minix_free_block(inode->i_sb, tmp);
+ brelse(result);
+ goto repeat;
}
*p = tmp;
mark_buffer_dirty(bh, 1);
+ *err = 0;
+out:
brelse(bh);
return result;
}
-int V1_getblk_block(struct inode * inode, long block, int create, int *err, int *created)
+static int V1_get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
{
- struct buffer_head *bh, *tmp;
- int phys_block;
+ int ret, err, new, phys, ptr;
+ struct buffer_head *bh;
- *err = -EIO;
- if (block < 0) {
- printk("minix_getblk: block<0");
- return 0;
- }
- if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE) {
- printk("minix_getblk: block>big");
+ if (!create) {
+ phys = V1_minix_block_map(inode, block);
+ if (phys) {
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = phys;
+ bh_result->b_state |= (1UL << BH_Mapped);
+ }
return 0;
}
- *created = 0;
- if (block < 7) {
- tmp = V1_inode_getblk(inode, block, create,
- 0, &phys_block, created);
+
+ err = -EIO;
+ new = 0;
+ ret = 0;
+ bh = NULL;
+
+ lock_kernel();
+ if (block < 0)
+ goto abort_negative;
+ if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)
+ goto abort_too_big;
+
+ err = 0;
+ ptr = block;
+ /*
+ * ok, these macros clean the logic up a bit and make
+ * it much more readable:
+ */
+#define GET_INODE_DATABLOCK(x) \
+ V1_inode_getblk(inode, x, block, &err, 0, &phys, &new)
+#define GET_INODE_PTR(x) \
+ V1_inode_getblk(inode, x, block, &err, 1, NULL, NULL)
+#define GET_INDIRECT_DATABLOCK(x) \
+ V1_block_getblk(inode, bh, x, block, &err, 0, &phys, &new)
+#define GET_INDIRECT_PTR(x) \
+ V1_block_getblk(inode, bh, x, block, &err, 1, NULL, NULL)
+
+ if (ptr < 7) {
+ bh = GET_INODE_DATABLOCK(ptr);
goto out;
}
- block -= 7;
- if (block < 512) {
- bh = V1_inode_getblk(inode, 7, create, 1, NULL, NULL);
- tmp = V1_block_getblk(inode, bh, block, create,
- 0, &phys_block, created);
- goto out;
+ ptr -= 7;
+ if (ptr < 512) {
+ bh = GET_INODE_PTR(7);
+ goto get_indirect;
}
- block -= 512;
- bh = V1_inode_getblk(inode, 8, create, 1, NULL, NULL);
- bh = V1_block_getblk(inode, bh, (block>>9) & 511, create, 1, NULL, NULL);
- tmp = V1_block_getblk(inode, bh, block & 511, create, 0, &phys_block, created);
+ ptr -= 512;
+ bh = GET_INODE_PTR(8);
+ bh = GET_INDIRECT_PTR((ptr >> 9) & 511);
+get_indirect:
+ bh = GET_INDIRECT_DATABLOCK(ptr & 511);
+
+#undef GET_INODE_DATABLOCK
+#undef GET_INODE_PTR
+#undef GET_INDIRECT_DATABLOCK
+#undef GET_INDIRECT_PTR
out:
- *err = 0;
- return phys_block;
+ if (err)
+ goto abort;
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = phys;
+ bh_result->b_state |= (1UL << BH_Mapped);
+ if (new)
+ bh_result->b_state |= (1UL << BH_New);
+abort:
+ unlock_kernel();
+ return err;
+
+abort_negative:
+ printk("minix_getblk: block<0");
+ goto abort;
+
+abort_too_big:
+ printk("minix_getblk: block>big");
+ goto abort;
}
/*
* The minix V2 fs getblk functions.
*/
-static struct buffer_head * V2_inode_getblk(struct inode * inode, int nr, int create,
- int metadata, int *phys_block, int *created)
+static struct buffer_head * V2_inode_getblk(struct inode * inode, int nr,
+ int new_block, int *err,
+ int metadata, int *phys, int *new)
{
int tmp;
- unsigned long *p;
+ unsigned int *p;
struct buffer_head * result;
- p = (unsigned long *) inode->u.minix_i.u.i2_data + nr;
+ p = (unsigned int *) inode->u.minix_i.u.i2_data + nr;
repeat:
tmp = *p;
if (tmp) {
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
+ *phys = tmp;
return NULL;
}
}
- if (!create)
- return NULL;
+ *err = -EFBIG;
+
+ /* Check file limits.. */
+ {
+ unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= BLOCK_SIZE_BITS;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ *err = -EFBIG;
+ return NULL;
+ }
+ }
+ }
+
tmp = minix_new_block(inode->i_sb);
- if (!tmp)
+ if (!tmp) {
+ *err = -ENOSPC;
return NULL;
+ }
if (metadata) {
result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
if (*p) {
mark_buffer_dirty(result, 1);
} else {
if (*p) {
+ /*
+ * Nobody is allowed to change block allocation
+ * state from under us:
+ */
+ BUG();
minix_free_block(inode->i_sb, tmp);
goto repeat;
}
- *phys_block = tmp;
+ *phys = tmp;
result = NULL;
- *created = 1;
+ *err = 0;
+ *new = 1;
}
*p = tmp;
}
static struct buffer_head * V2_block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int create,
- int metadata, int *phys_block, int *created)
+ struct buffer_head * bh, int nr, int new_block, int *err,
+ int metadata, int *phys, int *new)
{
int tmp;
- unsigned long *p;
+ unsigned int *p;
struct buffer_head * result;
+ unsigned long limit;
+ result = NULL;
if (!bh)
- return NULL;
+ goto out;
if (!buffer_uptodate(bh)) {
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- return NULL;
- }
+ if (!buffer_uptodate(bh))
+ goto out;
}
- p = nr + (unsigned long *) bh->b_data;
+ p = nr + (unsigned int *) bh->b_data;
repeat:
tmp = *p;
if (tmp) {
if (metadata) {
result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (tmp == *p) {
- brelse(bh);
- return result;
- }
+ if (tmp == *p)
+ goto out;
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
- brelse(bh);
- return NULL;
+ *phys = tmp;
+ goto out;
}
}
- if (!create) {
- brelse(bh);
- return NULL;
+ *err = -EFBIG;
+
+ limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= BLOCK_SIZE_BITS;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ goto out;
+ }
}
+
tmp = minix_new_block(inode->i_sb);
- if (!tmp) {
- brelse(bh);
- return NULL;
- }
+ if (!tmp)
+ goto out;
if (metadata) {
result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
if (*p) {
mark_buffer_uptodate(result, 1);
mark_buffer_dirty(result, 1);
} else {
- if (*p) {
- minix_free_block(inode->i_sb, tmp);
- goto repeat;
- }
- *phys_block = tmp;
- result = NULL;
- *created = 1;
+ *phys = tmp;
+ *new = 1;
+ }
+ if (*p) {
+ minix_free_block(inode->i_sb, tmp);
+ brelse(result);
+ goto repeat;
}
*p = tmp;
mark_buffer_dirty(bh, 1);
+ *err = 0;
+out:
brelse(bh);
return result;
}
-int V2_getblk_block(struct inode * inode, int block, int create, int *err, int *created)
+static int V2_get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
{
- struct buffer_head * bh, *tmp;
- int phys_block;
+ int ret, err, new, phys, ptr;
+ struct buffer_head * bh;
- *err = -EIO;
- if (block < 0) {
- printk("minix_getblk: block<0");
- return 0;
- }
- if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE) {
- printk("minix_getblk: block>big");
+ if (!create) {
+ phys = V2_minix_block_map(inode, block);
+ if (phys) {
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = phys;
+ bh_result->b_state |= (1UL << BH_Mapped);
+ }
return 0;
}
- *created = 0;
- if (block < 7) {
- tmp = V2_inode_getblk(inode, block, create,
- 0, &phys_block, created);
+
+ err = -EIO;
+ new = 0;
+ ret = 0;
+ bh = NULL;
+
+ lock_kernel();
+ if (block < 0)
+ goto abort_negative;
+ if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)
+ goto abort_too_big;
+
+ err = 0;
+ ptr = block;
+ /*
+ * ok, these macros clean the logic up a bit and make
+ * it much more readable:
+ */
+#define GET_INODE_DATABLOCK(x) \
+ V2_inode_getblk(inode, x, block, &err, 0, &phys, &new)
+#define GET_INODE_PTR(x) \
+ V2_inode_getblk(inode, x, block, &err, 1, NULL, NULL)
+#define GET_INDIRECT_DATABLOCK(x) \
+ V2_block_getblk(inode, bh, x, block, &err, 0, &phys, &new)
+#define GET_INDIRECT_PTR(x) \
+ V2_block_getblk(inode, bh, x, block, &err, 1, NULL, NULL)
+
+ if (ptr < 7) {
+ bh = GET_INODE_DATABLOCK(ptr);
goto out;
}
- block -= 7;
- if (block < 256) {
- bh = V2_inode_getblk(inode, 7, create, 1, NULL, NULL);
- tmp = V2_block_getblk(inode, bh, block, create,
- 0, &phys_block, created);
- goto out;
+ ptr -= 7;
+ if (ptr < 256) {
+ bh = GET_INODE_PTR(7);
+ goto get_indirect;
}
- block -= 256;
- if (block < 256*256) {
- bh = V2_inode_getblk(inode, 8, create, 1, NULL, NULL);
- bh = V2_block_getblk(inode, bh, (block>>8) & 255, create,
- 1, NULL, NULL);
- tmp = V2_block_getblk(inode, bh, block & 255, create,
- 0, &phys_block, created);
- goto out;
+ ptr -= 256;
+ if (ptr < 256*256) {
+ bh = GET_INODE_PTR(8);
+ goto get_double;
}
- block -= 256*256;
- bh = V2_inode_getblk(inode, 9, create, 1, NULL, NULL);
- bh = V2_block_getblk(inode, bh, (block >> 16) & 255, create, 1, NULL, NULL);
- bh = V2_block_getblk(inode, bh, (block >> 8) & 255, create, 1, NULL, NULL);
- tmp = V2_block_getblk(inode, bh, block & 255, create, 0, &phys_block, created);
+ ptr -= 256*256;
+ bh = GET_INODE_PTR(9);
+ bh = GET_INDIRECT_PTR((ptr >> 16) & 255);
+get_double:
+ bh = GET_INDIRECT_PTR((ptr >> 8) & 255);
+get_indirect:
+ bh = GET_INDIRECT_DATABLOCK(ptr & 255);
+
+#undef GET_INODE_DATABLOCK
+#undef GET_INODE_PTR
+#undef GET_INDIRECT_DATABLOCK
+#undef GET_INDIRECT_PTR
out:
- *err = 0;
- return phys_block;
+ if (err)
+ goto abort;
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = phys;
+ bh_result->b_state |= (1UL << BH_Mapped);
+ if (new)
+ bh_result->b_state |= (1UL << BH_New);
+abort:
+ unlock_kernel();
+ return err;
+
+abort_negative:
+ printk("minix_getblk: block<0");
+ goto abort;
+
+abort_too_big:
+ printk("minix_getblk: block>big");
+ goto abort;
}
-int minix_getblk_block (struct inode *inode, long block,
- int create, int *err, int *created)
+int minix_get_block(struct inode *inode, long block,
+ struct buffer_head *bh_result, int create)
{
if (INODE_VERSION(inode) == MINIX_V1)
- return V1_getblk_block(inode, block, create, err, created);
+ return V1_get_block(inode, block, bh_result, create);
else
- return V2_getblk_block(inode, block, create, err, created);
+ return V2_get_block(inode, block, bh_result, create);
}
/*
* the global minix fs getblk function.
*/
-struct buffer_head *minix_getblk (struct inode *inode, int block, int create)
+struct buffer_head *minix_getblk(struct inode *inode, int block, int create)
{
- struct buffer_head *tmp = NULL;
- int phys_block;
- int err, created;
-
- phys_block = minix_getblk_block(inode, block, create, &err, &created);
- if (phys_block) {
- tmp = getblk(inode->i_dev, phys_block, BLOCK_SIZE);
- if (created) {
- memset(tmp->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(tmp, 1);
- mark_buffer_dirty(tmp, 1);
+ struct buffer_head dummy;
+ int error;
+
+ dummy.b_state = 0;
+ dummy.b_blocknr = -1000;
+ error = minix_get_block(inode, block, &dummy, create);
+ if (!error && buffer_mapped(&dummy)) {
+ struct buffer_head *bh;
+ bh = getblk(dummy.b_dev, dummy.b_blocknr, BLOCK_SIZE);
+ if (buffer_new(&dummy)) {
+ memset(bh->b_data, 0, BLOCK_SIZE);
+ mark_buffer_uptodate(bh, 1);
+ mark_buffer_dirty(bh, 1);
}
+ return bh;
}
- return tmp;
+ return NULL;
}
struct buffer_head * minix_bread(struct inode * inode, int block, int create)
{
struct buffer_head * bh;
- bh = minix_getblk(inode,block,create);
+ bh = minix_getblk(inode, block, create);
if (!bh || buffer_uptodate(bh))
return bh;
ll_rw_block(READ, 1, &bh);
NULL, /* rename */
minix_readlink, /* readlink */
minix_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
msdos_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
ncp_rename, /* rename */
NULL, /* readlink */
NULL, /* follow link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
ncp_readlink, /* readlink */
ncp_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
* The IO completion will then free the page and the dentry.
*/
get_page(page);
- file->f_count++;
+ atomic_inc(&file->f_count);
/* Schedule request */
synchronous = schedule_write_request(req, synchronous);
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- ntfs_bmap,
- block_read_full_page,
+ ntfs_bmap, /* get_block */
+ block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* truncate */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
int retval;
struct dentry *dentry = filp->f_dentry;
- if (filp->f_count == 0) {
+ if (!atomic_read(&filp->f_count)) {
printk("VFS: Close: file count is 0\n");
return 0;
}
#include <linux/file.h>
#include <linux/poll.h>
#include <linux/malloc.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
/* in case of paging and multiple read/write on the same pipe. (FGC) */
-static ssize_t pipe_read(struct file * filp, char * buf,
- size_t count, loff_t *ppos)
+static ssize_t do_pipe_read(struct file * filp, char * buf, size_t count)
{
struct inode * inode = filp->f_dentry->d_inode;
ssize_t chars = 0, size = 0, read = 0;
char *pipebuf;
- if (ppos != &filp->f_pos)
- return -ESPIPE;
-
if (filp->f_flags & O_NONBLOCK) {
if (PIPE_LOCK(*inode))
return -EAGAIN;
return -EAGAIN;
return 0;
}
-
-static ssize_t pipe_write(struct file * filp, const char * buf,
- size_t count, loff_t *ppos)
+
+static ssize_t do_pipe_write(struct file * filp, const char * buf, size_t count)
{
struct inode * inode = filp->f_dentry->d_inode;
ssize_t chars = 0, free = 0, written = 0, err=0;
char *pipebuf;
- if (ppos != &filp->f_pos)
- return -ESPIPE;
-
if (!PIPE_READERS(*inode)) { /* no readers */
send_sig(SIGPIPE,current,0);
return -EPIPE;
return written ? written : err;
}
+static ssize_t pipe_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
+{
+ ssize_t retval;
+
+ if (ppos != &filp->f_pos)
+ return -ESPIPE;
+
+ lock_kernel();
+ retval = do_pipe_read(filp, buf, count);
+ unlock_kernel();
+ return retval;
+}
+
+static ssize_t pipe_write(struct file * filp, const char * buf, size_t count, loff_t *ppos)
+{
+ ssize_t retval;
+
+ if (ppos != &filp->f_pos)
+ return -ESPIPE;
+
+ lock_kernel();
+ retval = do_pipe_write(filp, buf, count);
+ unlock_kernel();
+ return retval;
+}
+
static long long pipe_lseek(struct file * file, long long offset, int orig)
{
return -ESPIPE;
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- qnx4_bmap, /* bmap */
+ qnx4_bmap, /* get_block */
qnx4_readpage, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
qnx4_readlink, /* readlink */
qnx4_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
{
ssize_t ret;
struct file * file;
- ssize_t (*read)(struct file *, char *, size_t, loff_t *);
-
- lock_kernel();
ret = -EBADF;
file = fget(fd);
- if (!file)
- goto bad_file;
- if (!(file->f_mode & FMODE_READ))
- goto out;
- ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,
- file, file->f_pos, count);
- if (ret)
- goto out;
- ret = -EINVAL;
- if (!file->f_op || !(read = file->f_op->read))
- goto out;
- ret = read(file, buf, count, &file->f_pos);
-out:
- fput(file);
-bad_file:
- unlock_kernel();
+ if (file) {
+ if (file->f_mode & FMODE_READ) {
+ ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,
+ file, file->f_pos, count);
+ if (!ret) {
+ ssize_t (*read)(struct file *, char *, size_t, loff_t *);
+ ret = -EINVAL;
+ if (file->f_op && (read = file->f_op->read) != NULL)
+ ret = read(file, buf, count, &file->f_pos);
+ }
+ }
+ fput(file);
+ }
return ret;
}
{
ssize_t ret;
struct file * file;
- struct inode * inode;
- ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
-
- lock_kernel();
ret = -EBADF;
file = fget(fd);
- if (!file)
- goto bad_file;
- if (!(file->f_mode & FMODE_WRITE))
- goto out;
- inode = file->f_dentry->d_inode;
- ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
+ if (file) {
+ if (file->f_mode & FMODE_WRITE) {
+ struct inode *inode = file->f_dentry->d_inode;
+ ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
file->f_pos, count);
- if (ret)
- goto out;
- ret = -EINVAL;
- if (!file->f_op || !(write = file->f_op->write))
- goto out;
-
- ret = write(file, buf, count, &file->f_pos);
-out:
- fput(file);
-bad_file:
- unlock_kernel();
+ if (!ret) {
+ ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
+ ret = -EINVAL;
+ if (file->f_op && (write = file->f_op->write) != NULL)
+ ret = write(file, buf, count, &file->f_pos);
+ }
+ }
+ fput(file);
+ }
return ret;
}
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap -- not really */
+ NULL, /* get_block -- not really */
romfs_readpage, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
romfs_readlink, /* readlink */
romfs_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
if (p->nr < __MAX_POLL_TABLE_ENTRIES) {
struct poll_table_entry * entry;
ok_table:
- entry = p->entry + p->nr;
- entry->filp = filp;
- filp->f_count++;
+ entry = p->entry + p->nr;
+ entry->filp = filp;
+ atomic_inc(&filp->f_count);
entry->wait_address = wait_address;
init_waitqueue_entry(&entry->wait, current);
add_wait_queue(wait_address,&entry->wait);
smb_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
smb_readpage, /* readpage */
smb_writepage, /* writepage */
NULL, /* flushpage */
sysv_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
#include <linux/fs.h>
#include <linux/sysv_fs.h>
-static int sysv_writepage (struct file * file, struct page * page)
-{
- return block_write_full_page(file, page, sysv_getblk_block);
-}
-
-static long sysv_write_one_page (struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
-{
- return block_write_partial_page(file, page, offset, bytes, buf, sysv_getblk_block);
-}
-
/*
* Write to a file (through the page cache).
*/
static ssize_t
sysv_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
- return generic_file_write(file, buf, count, ppos, sysv_write_one_page);
+ return generic_file_write(file, buf, count,
+ ppos, block_write_partial_page);
}
/*
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- sysv_bmap, /* bmap */
+ sysv_get_block, /* get_block */
block_read_full_page, /* readpage */
- sysv_writepage, /* writepage */
+ block_write_full_page, /* writepage */
block_flushpage, /* flushpage */
sysv_truncate, /* truncate */
NULL, /* permission */
#include <linux/string.h>
#include <linux/locks.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
sysv_free_inode(inode);
}
+static void sysv_put_super(struct super_block *);
+static void sysv_write_super(struct super_block *);
+static void sysv_read_inode(struct inode *);
+static int sysv_notify_change(struct dentry *, struct iattr *);
+static int sysv_statfs(struct super_block *, struct statfs *, int);
static struct super_operations sysv_sops = {
sysv_read_inode,
return sb;
}
-struct super_block *sysv_read_super(struct super_block *sb,void *data,
- int silent)
+static struct super_block *sysv_read_super(struct super_block *sb,
+ void *data, int silent)
{
struct buffer_head *bh;
const char *found;
}
/* This is only called on sync() and umount(), when s_dirt=1. */
-void sysv_write_super (struct super_block *sb)
+static void sysv_write_super(struct super_block *sb)
{
lock_super(sb);
if (buffer_dirty(sb->sv_bh1) || buffer_dirty(sb->sv_bh2)) {
unlock_super(sb);
}
-void sysv_put_super(struct super_block *sb)
+static void sysv_put_super(struct super_block *sb)
{
/* we can assume sysv_write_super() has already been called,
and that the superblock is locked */
MOD_DEC_USE_COUNT;
}
-int sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
struct statfs tmp;
return tmp + sb->sv_block_base;
}
-int sysv_bmap(struct inode * inode,int block_nr)
+static unsigned int sysv_block_map(struct inode *inode, unsigned int block)
{
- unsigned int block = block_nr;
- struct super_block * sb = inode->i_sb;
- int convert;
- int i;
- struct buffer_head * bh;
+ struct super_block *sb;
+ int i, ret, convert;
- if (block < 10)
- return inode_bmap(sb,inode,block);
+ ret = 0;
+ lock_kernel();
+ sb = inode->i_sb;
+ if (block < 10) {
+ ret = inode_bmap(sb, inode, block);
+ goto out;
+ }
block -= 10;
convert = sb->sv_convert;
if (block < sb->sv_ind_per_block) {
- i = inode_bmap(sb,inode,10);
+ i = inode_bmap(sb, inode, 10);
if (!i)
- return 0;
- bh = bread(inode->i_dev,i,sb->sv_block_size);
- return block_bmap(sb, bh, block, convert);
+ goto out;
+ ret = block_bmap(sb,
+ bread(inode->i_dev, i, sb->sv_block_size),
+ block, convert);
+ goto out;
}
block -= sb->sv_ind_per_block;
if (block < sb->sv_ind_per_block_2) {
- i = inode_bmap(sb,inode,11);
+ i = inode_bmap(sb, inode, 11);
if (!i)
- return 0;
- bh = bread(inode->i_dev,i,sb->sv_block_size);
- i = block_bmap(sb, bh, block >> sb->sv_ind_per_block_bits, convert);
+ goto out;
+ i = block_bmap(sb,
+ bread(inode->i_dev, i, sb->sv_block_size),
+ (block >> sb->sv_ind_per_block_bits), convert);
if (!i)
- return 0;
- bh = bread(inode->i_dev,i,sb->sv_block_size);
- return block_bmap(sb, bh, block & sb->sv_ind_per_block_1, convert);
+ goto out;
+ ret = block_bmap(sb,
+ bread(inode->i_dev, i, sb->sv_block_size),
+ (block & sb->sv_ind_per_block_1), convert);
+ goto out;
}
block -= sb->sv_ind_per_block_2;
if (block < sb->sv_ind_per_block_3) {
- i = inode_bmap(sb,inode,12);
+ i = inode_bmap(sb, inode, 12);
if (!i)
- return 0;
- bh = bread(inode->i_dev,i,sb->sv_block_size);
- i = block_bmap(sb, bh, block >> sb->sv_ind_per_block_2_bits, convert);
+ goto out;
+ i = block_bmap(sb,
+ bread(inode->i_dev, i, sb->sv_block_size),
+ (block >> sb->sv_ind_per_block_2_bits), convert);
if (!i)
- return 0;
- bh = bread(inode->i_dev,i,sb->sv_block_size);
- i = block_bmap(sb, bh, (block >> sb->sv_ind_per_block_bits) & sb->sv_ind_per_block_1,convert);
+ goto out;
+ ret = block_bmap(sb,
+ bread(inode->i_dev, i, sb->sv_block_size),
+ ((block >> sb->sv_ind_per_block_bits) &
+ sb->sv_ind_per_block_1), convert);
if (!i)
- return 0;
- bh = bread(inode->i_dev,i,sb->sv_block_size);
- return block_bmap(sb, bh, block & sb->sv_ind_per_block_1, convert);
- }
- if ((int)block<0) {
- printk("sysv_bmap: block<0");
- return 0;
+ goto out;
+ ret = block_bmap(sb,
+ bread(inode->i_dev, i, sb->sv_block_size),
+ (block & sb->sv_ind_per_block_1), convert);
+ goto out;
}
- printk("sysv_bmap: block>big");
- return 0;
+ if ((int)block < 0)
+ printk("sysv_block_map: block < 0\n");
+ else
+ printk("sysv_block_map: block > big\n");
+out:
+ unlock_kernel();
+ return ret;
}
/* End of bmap support. */
/* Access selected blocks of regular files (or directories) */
-static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create,
- int metadata, int *phys_block, int *created)
+static struct buffer_head *inode_getblk(struct inode *inode, int nr, int new_block,
+ int *err, int metadata, long *phys, int *new)
{
struct super_block *sb;
u32 tmp;
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
+ *phys = tmp;
return NULL;
}
}
- if (!create)
- return NULL;
+ *err = -EFBIG;
+
+ /* Check file limits.. */
+ {
+ unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= sb->sv_block_size_bits;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ *err = -EFBIG;
+ return NULL;
+ }
+ }
+ }
+
tmp = sysv_new_block(sb);
- if (!tmp)
+ if (!tmp) {
+ *err = -ENOSPC;
return NULL;
+ }
if (metadata) {
result = sv_getblk(sb, inode->i_dev, tmp);
if (*p) {
}
} else {
if (*p) {
+ /*
+ * Nobody is allowed to change block allocation
+ * state from under us:
+ */
+ BUG();
sysv_free_block(sb, tmp);
goto repeat;
}
- *phys_block = tmp;
+ *phys = tmp;
result = NULL;
- *created = 1;
+ *err = 0;
+ *new = 1;
}
*p = tmp;
return result;
}
-static struct buffer_head * block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int create,
- int metadata, int *phys_block, int *created)
+static struct buffer_head *block_getblk(struct inode *inode,
+ struct buffer_head *bh, int nr, int new_block, int *err,
+ int metadata, long *phys, int *new)
{
struct super_block *sb;
u32 tmp, block;
sysv_zone_t *p;
struct buffer_head * result;
+ unsigned long limit;
+ result = NULL;
if (!bh)
- return NULL;
+ goto out;
if (!buffer_uptodate(bh)) {
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- return NULL;
- }
+ if (!buffer_uptodate(bh))
+ goto out;
}
sb = inode->i_sb;
p = nr + (sysv_zone_t *) bh->b_data;
if (tmp) {
if (metadata) {
result = sv_getblk(sb, bh->b_dev, block);
- if (tmp == *p) {
- brelse(bh);
- return result;
- }
+ if (tmp == *p)
+ goto out;
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
- brelse(bh);
- return NULL;
+ *phys = tmp;
+ goto out;
}
}
- if (!create) {
- brelse(bh);
- return NULL;
+ *err = -EFBIG;
+
+ limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= sb->sv_block_size_bits;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ goto out;
+ }
}
+
block = sysv_new_block(sb);
- if (!block) {
- brelse(bh);
- return NULL;
- }
+ if (!block)
+ goto out;
if (metadata) {
result = sv_getblk(sb, bh->b_dev, block);
if (*p) {
- sysv_free_block(sb,block);
+ sysv_free_block(sb, block);
brelse(result);
goto repeat;
}
+ memset(result->b_data, 0, sb->sv_block_size);
+ mark_buffer_uptodate(result, 1);
+ mark_buffer_dirty(result, 1);
} else {
- *phys_block = tmp;
- result = NULL;
- *created = 1;
+ *phys = tmp;
+ *new = 1;
+ }
+ if (*p) {
+ sysv_free_block(sb, block);
+ brelse(result);
+ goto repeat;
}
*p = (sb->sv_convert ? to_coh_ulong(block) : block);
mark_buffer_dirty(bh, 1);
+ *err = 0;
+out:
brelse(bh);
return result;
}
-int sysv_getblk_block(struct inode *inode, long block, int create,
- int *err, int *created)
+int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
{
- struct super_block *sb = inode->i_sb;
- struct buffer_head *bh, *tmp;
- int phys_block;
+ struct super_block *sb;
+ int ret, err, new;
+ struct buffer_head *bh;
+ unsigned long ptr, phys;
- *err = -EIO;
- if (block < 0) {
- printk("sysv_getblk: block<0");
- return 0;
- }
- if (block > sb->sv_ind_per_block_3) {
- printk("sysv_getblk: block>big");
+ if (!create) {
+ phys = sysv_block_map(inode, iblock);
+ if (phys) {
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = phys;
+ bh_result->b_state |= (1UL << BH_Mapped);
+ }
return 0;
}
- if (block < 10) {
- tmp = inode_getblk(inode, block, create,
- 0, &phys_block, created);
+
+ err = -EIO;
+ new = 0;
+ ret = 0;
+ bh = NULL;
+
+ lock_kernel();
+ sb = inode->i_sb;
+ if (iblock < 0)
+ goto abort_negative;
+ if (iblock > sb->sv_ind_per_block_3)
+ goto abort_too_big;
+
+ err = 0;
+ ptr = iblock;
+
+ /*
+ * ok, these macros clean the logic up a bit and make
+ * it much more readable:
+ */
+#define GET_INODE_DATABLOCK(x) \
+ inode_getblk(inode, x, iblock, &err, 0, &phys, &new)
+#define GET_INODE_PTR(x) \
+ inode_getblk(inode, x, iblock, &err, 1, NULL, NULL)
+#define GET_INDIRECT_DATABLOCK(x) \
+ block_getblk (inode, bh, x, iblock, &err, 0, &phys, &new);
+#define GET_INDIRECT_PTR(x) \
+ block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL);
+
+ if (ptr < 10) {
+ bh = GET_INODE_DATABLOCK(ptr);
goto out;
}
- block -= 10;
- if (block < sb->sv_ind_per_block) {
- bh = inode_getblk(inode, 10, create, 1, NULL, NULL);
- tmp = block_getblk(inode, bh, block, create,
- 0, &phys_block, created);
- goto out;
+ ptr -= 10;
+ if (ptr < sb->sv_ind_per_block) {
+ bh = GET_INODE_PTR(10);
+ goto get_indirect;
}
- block -= sb->sv_ind_per_block;
- if (block < sb->sv_ind_per_block_2) {
- bh = inode_getblk(inode, 11, create, 1, NULL, NULL);
- bh = block_getblk(inode, bh, block >> sb->sv_ind_per_block_bits, create,
- 1, NULL, NULL);
- tmp = block_getblk(inode, bh, block & sb->sv_ind_per_block_1, create,
- 0, &phys_block, created);
- goto out;
+ ptr -= sb->sv_ind_per_block;
+ if (ptr < sb->sv_ind_per_block_2) {
+ bh = GET_INODE_PTR(11);
+ goto get_double;
}
- block -= sb->sv_ind_per_block_2;
- bh = inode_getblk(inode, 12, create, 1, NULL, NULL);
- bh = block_getblk(inode, bh, block >> sb->sv_ind_per_block_2_bits, create,
- 1, NULL, NULL);
- bh = block_getblk(inode, bh,
- (block >> sb->sv_ind_per_block_bits) & sb->sv_ind_per_block_1,
- create, 1, NULL, NULL);
- tmp = block_getblk(inode, bh, block & sb->sv_ind_per_block_1, create,
- 0, &phys_block, created);
+ ptr -= sb->sv_ind_per_block_2;
+ bh = GET_INODE_PTR(12);
+ bh = GET_INDIRECT_PTR(ptr >> sb->sv_ind_per_block_2_bits);
+get_double:
+ bh = GET_INDIRECT_PTR((ptr >> sb->sv_ind_per_block_bits) & sb->sv_ind_per_block_1);
+get_indirect:
+ bh = GET_INDIRECT_DATABLOCK(ptr & sb->sv_ind_per_block_1);
+
+#undef GET_INODE_DATABLOCK
+#undef GET_INODE_PTR
+#undef GET_INDIRECT_DATABLOCK
+#undef GET_INDIRECT_PTR
out:
- *err = 0;
- return phys_block;
+ if (err)
+ goto abort;
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = phys;
+ bh_result->b_state |= (1UL << BH_Mapped);
+ if (new)
+ bh_result->b_state |= (1UL << BH_New);
+abort:
+ unlock_kernel();
+ return err;
+
+abort_negative:
+ printk("sysv_getblk: block < 0\n");
+ goto abort;
+
+abort_too_big:
+ printk("sysv_getblk: block > big\n");
+ goto abort;
}
-struct buffer_head *sysv_getblk (struct inode *inode, unsigned int block, int create)
+struct buffer_head *sysv_getblk(struct inode *inode, unsigned int block, int create)
{
- struct buffer_head *tmp = NULL;
- int phys_block;
- int err, created;
-
- phys_block = sysv_getblk_block(inode, block, create, &err, &created);
- if (phys_block) {
- tmp = getblk(inode->i_dev, phys_block, BLOCK_SIZE);
- if (created) {
- memset(tmp->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(tmp, 1);
- mark_buffer_dirty(tmp, 1);
+ struct buffer_head dummy;
+ int error;
+
+ dummy.b_state = 0;
+ dummy.b_blocknr = -1000;
+ error = sysv_get_block(inode, block, &dummy, create);
+ if (!error && buffer_mapped(&dummy)) {
+ struct buffer_head *bh;
+ bh = getblk(dummy.b_dev, dummy.b_blocknr, BLOCK_SIZE);
+ if (buffer_new(&dummy)) {
+ memset(bh->b_data, 0, BLOCK_SIZE);
+ mark_buffer_uptodate(bh, 1);
+ mark_buffer_dirty(bh, 1);
}
+ return bh;
}
- return tmp;
+ return NULL;
}
-struct buffer_head * sysv_file_bread(struct inode * inode, int block, int create)
+struct buffer_head *sysv_file_bread(struct inode *inode, int block, int create)
{
- struct buffer_head * bh;
+ struct buffer_head *bh;
- bh = sysv_getblk(inode,block,create);
+ bh = sysv_getblk(inode, block, create);
if (!bh || buffer_uptodate(bh))
return bh;
ll_rw_block(READ, 1, &bh);
*(unsigned short *)(p+1) = (unsigned short) val;
}
-void sysv_read_inode(struct inode * inode)
+static void sysv_read_inode(struct inode *inode)
{
struct super_block * sb = inode->i_sb;
struct buffer_head * bh;
}
/* To avoid inconsistencies between inodes in memory and inodes on disk. */
-int sysv_notify_change(struct dentry *dentry, struct iattr *attr)
+static int sysv_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int error;
NULL, /* rename */
sysv_readlink, /* readlink */
sysv_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
while (!error && !stored && filp->f_pos < inode->i_size) {
lblk = (filp->f_pos) >> sb->s_blocksize_bits;
- /* XXX - ufs_bmap() call needs error checking */
- blk = ufs_bmap(inode, lblk);
- bh = bread (sb->s_dev, blk, sb->s_blocksize);
- if (!bh) {
+ blk = ufs_frag_map(inode, lblk);
+ if (!blk || !(bh = bread (sb->s_dev, blk, sb->s_blocksize))) {
/* XXX - error - skip to the next block */
printk("ufs_readdir: "
"dir inode %lu has a hole at offset %lu\n",
ufs_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
}
}
-static int ufs_writepage (struct file *file, struct page *page)
-{
- return block_write_full_page(file, page, ufs_getfrag_block);
-}
-
-static long ufs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char *buf)
-{
- return block_write_partial_page(file, page, offset, bytes, buf, ufs_getfrag_block);
-}
-
/*
* Write to a file (through the page cache).
*/
static ssize_t
ufs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
- ssize_t retval = generic_file_write(file, buf, count, ppos, ufs_write_one_page);
+ ssize_t retval;
+
+ retval = generic_file_write(file, buf, count,
+ ppos, block_write_partial_page);
if (retval > 0) {
struct inode *inode = file->f_dentry->d_inode;
remove_suid(inode);
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- ufs_bmap, /* bmap */
+ ufs_getfrag_block, /* get_block */
block_read_full_page, /* readpage */
- ufs_writepage, /* writepage */
+ block_write_full_page, /* writepage */
block_flushpage, /* flushpage */
ufs_truncate, /* truncate */
NULL, /* permission */
NULL, /* smap */
- NULL, /* revalidate */
+ NULL /* revalidate */
};
#include <linux/string.h>
#include <linux/locks.h>
#include <linux/mm.h>
+#include <linux/smp_lock.h>
#include "swab.h"
#include "util.h"
#define ufs_inode_bmap(inode, nr) \
(SWAB32((inode)->u.ufs_i.i_u1.i_data[(nr) >> uspi->s_fpbshift]) + ((nr) & uspi->s_fpbmask))
-static inline unsigned ufs_block_bmap (struct buffer_head * bh, unsigned nr,
+static inline unsigned int ufs_block_bmap (struct buffer_head * bh, unsigned nr,
struct ufs_sb_private_info * uspi, unsigned swab)
{
- unsigned tmp;
+ unsigned int tmp;
UFSD(("ENTER, nr %u\n", nr))
if (!bh)
return tmp;
}
-int ufs_bmap (struct inode * inode, int fragment)
+int ufs_frag_map(struct inode *inode, int frag)
{
- struct super_block * sb;
- struct ufs_sb_private_info * uspi;
- unsigned tmp;
- unsigned swab;
+ struct super_block *sb;
+ struct ufs_sb_private_info *uspi;
+ unsigned int swab;
+ int i, ret;
+
+ ret = 0;
+ lock_kernel();
sb = inode->i_sb;
uspi = sb->u.ufs_sb.s_uspi;
swab = sb->u.ufs_sb.s_swab;
-
- UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment))
-
- if (fragment >= ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb) << uspi->s_fpbshift)) {
- ufs_warning (sb, "ufs_bmap", "block > big");
- return 0;
+ if (frag < 0) {
+ ufs_warning(sb, "ufs_frag_map", "frag < 0");
+ goto out;
}
-
- /*
- * direct fragment
- */
- if (fragment < UFS_NDIR_FRAGMENT)
- return (uspi->s_sbbase + ufs_inode_bmap (inode, fragment));
-
- /*
- * indirect fragment
- */
- fragment -= UFS_NDIR_FRAGMENT;
- if (fragment < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) {
- tmp = ufs_inode_bmap (inode,
- UFS_IND_FRAGMENT + (fragment >> uspi->s_apbshift));
- if (!tmp)
- return 0;
- return (uspi->s_sbbase +
- ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
- fragment & uspi->s_apbmask, uspi, swab));
+ if (frag >=
+ ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb)
+ << uspi->s_fpbshift)) {
+ ufs_warning(sb, "ufs_frag_map", "frag > big");
+ goto out;
}
- /*
- * dindirect fragment
- */
- fragment -= 1 << (uspi->s_apbshift + uspi->s_fpbshift);
- if (fragment < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) {
- tmp = ufs_inode_bmap (inode,
- UFS_DIND_FRAGMENT + (fragment >> uspi->s_2apbshift));
- if (!tmp)
- return 0;
- tmp = ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
- (fragment >> uspi->s_apbshift) & uspi->s_apbmask, uspi, swab);
- if (!tmp)
- return 0;
- return (uspi->s_sbbase +
- ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
- fragment & uspi->s_apbmask, uspi, swab));
+ if (frag < UFS_NDIR_FRAGMENT) {
+ ret = uspi->s_sbbase + ufs_inode_bmap(inode, frag);
+ goto out;
}
- /*
- * tindirect fragment
- */
- fragment -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift);
- tmp = ufs_inode_bmap (inode,
- UFS_TIND_FRAGMENT + (fragment >> uspi->s_3apbshift));
- if (!tmp)
- return 0;
- tmp = ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
- (fragment >> uspi->s_2apbshift) & uspi->s_apbmask, uspi, swab);
- if (!tmp)
- return 0;
- tmp = ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
- (fragment >> uspi->s_apbshift) & uspi->s_apbmask, uspi, swab);
- if (!tmp)
- return 0;
- return (uspi->s_sbbase +
- ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
- fragment & uspi->s_apbmask, uspi, swab));
+ frag -= UFS_NDIR_FRAGMENT;
+ if (frag < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) {
+ i = ufs_inode_bmap(inode,
+ UFS_IND_FRAGMENT + (frag >> uspi->s_apbshift));
+ if (!i)
+ goto out;
+ ret = (uspi->s_sbbase +
+ ufs_block_bmap(bread(sb->s_dev, uspi->s_sbbase + i,
+ sb->s_blocksize),
+ frag & uspi->s_apbmask, uspi, swab));
+ }
+ frag -= 1 << (uspi->s_apbshift + uspi->s_fpbshift);
+ if (frag < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) {
+ i = ufs_inode_bmap (inode,
+ UFS_DIND_FRAGMENT + (frag >> uspi->s_2apbshift));
+ if (!i)
+ goto out;
+ i = ufs_block_bmap(bread(sb->s_dev, uspi->s_sbbase + i,
+ sb->s_blocksize),
+ (frag >> uspi->s_apbshift) & uspi->s_apbmask,
+ uspi, swab);
+ if (!i)
+ goto out;
+ ret = (uspi->s_sbbase +
+ ufs_block_bmap(bread(sb->s_dev, uspi->s_sbbase + i,
+ sb->s_blocksize),
+ (frag & uspi->s_apbmask), uspi, swab));
+ goto out;
+ }
+ frag -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift);
+ i = ufs_inode_bmap(inode,
+ UFS_TIND_FRAGMENT + (frag >> uspi->s_3apbshift));
+ if (!i)
+ goto out;
+ i = ufs_block_bmap(bread(sb->s_dev, uspi->s_sbbase + i, sb->s_blocksize),
+ (frag >> uspi->s_2apbshift) & uspi->s_apbmask,
+ uspi, swab);
+ if (!i)
+ goto out;
+ i = ufs_block_bmap(bread(sb->s_dev, uspi->s_sbbase + i, sb->s_blocksize),
+ (frag >> uspi->s_apbshift) & uspi->s_apbmask,
+ uspi, swab);
+ if (!i)
+ goto out;
+ ret = (uspi->s_sbbase +
+ ufs_block_bmap(bread(sb->s_dev, uspi->s_sbbase + i, sb->s_blocksize),
+ (frag & uspi->s_apbmask), uspi, swab));
+out:
+ unlock_kernel();
+ return ret;
}
-static struct buffer_head * ufs_inode_getfrag (struct inode * inode,
- unsigned fragment, unsigned new_fragment, int create,
- unsigned required, int *err, int metadata, int *phys_block, int *created)
+static struct buffer_head * ufs_inode_getfrag (struct inode *inode,
+ unsigned int fragment, unsigned int new_fragment,
+ unsigned int required, int *err, int metadata, long *phys, int *new)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
unsigned tmp, goal;
u32 * p, * p2;
- unsigned swab;
+ unsigned int swab;
UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
inode->i_ino, fragment, new_fragment, required))
sb->s_blocksize);
if (tmp == SWAB32(*p)) {
UFSD(("EXIT, result %u\n", tmp + blockoff))
- return result;
+ return result;
}
brelse (result);
goto repeat;
} else {
- *phys_block = tmp;
+ *phys = tmp;
return NULL;
}
}
*err = -EFBIG;
- if (!create)
- return NULL;
+
limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
if (limit < RLIM_INFINITY) {
limit >>= sb->s_blocksize_bits;
return NULL;
}
}
+
lastblock = ufs_fragstoblks (lastfrag);
lastblockoff = ufs_fragnum (lastfrag);
/*
}
if (!tmp) {
if ((!blockoff && SWAB32(*p)) ||
- (blockoff && lastfrag != inode->u.ufs_i.i_lastfrag))
+ (blockoff && lastfrag != inode->u.ufs_i.i_lastfrag))
goto repeat;
- else
- return NULL;
+ *err = -ENOSPC;
+ return NULL;
}
/* The nullification of framgents done in ufs/balloc.c is
if (metadata) {
result = getblk (inode->i_dev, tmp + blockoff, sb->s_blocksize);
} else {
- *phys_block = tmp;
+ *phys = tmp;
result = NULL;
*err = 0;
- *created = 1;
+ *new = 1;
}
inode->i_ctime = CURRENT_TIME;
return result;
}
-static struct buffer_head * ufs_block_getfrag (struct inode * inode,
- struct buffer_head * bh, unsigned fragment, unsigned new_fragment,
- int create, unsigned blocksize, int * err, int metadata, int *phys_block, int *created)
+static struct buffer_head * ufs_block_getfrag (struct inode *inode,
+ struct buffer_head *bh, unsigned int fragment, unsigned int new_fragment,
+ unsigned int blocksize, int * err, int metadata, long *phys, int *new)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
struct buffer_head * result;
unsigned tmp, goal, block, blockoff;
u32 * p;
- unsigned swab;
+ unsigned int swab;
sb = inode->i_sb;
swab = sb->u.ufs_sb.s_swab;
UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment))
+ result = NULL;
if (!bh)
- return NULL;
+ goto out;
if (!buffer_uptodate(bh)) {
ll_rw_block (READ, 1, &bh);
wait_on_buffer (bh);
- if (!buffer_uptodate(bh)) {
- brelse (bh);
- return NULL;
- }
+ if (!buffer_uptodate(bh))
+ goto out;
}
p = (u32 *) bh->b_data + block;
if (metadata) {
result = getblk (bh->b_dev, uspi->s_sbbase + tmp + blockoff,
sb->s_blocksize);
- if (tmp == SWAB32(*p)) {
- brelse (bh);
- UFSD(("EXIT, result %u\n", tmp + blockoff))
- return result;
- }
+ if (tmp == SWAB32(*p))
+ goto out;
brelse (result);
goto repeat;
} else {
- *phys_block = tmp;
- brelse (bh);
- return NULL;
+ *phys = tmp;
+ goto out;
}
}
*err = -EFBIG;
- if (!create) {
- brelse (bh);
- return NULL;
- } else {
+
+ {
unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
if (limit < RLIM_INFINITY) {
limit >>= sb->s_blocksize_bits;
goal = bh->b_blocknr + uspi->s_fpb;
tmp = ufs_new_fragments (inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err);
if (!tmp) {
- if (SWAB32(*p)) {
+ if (SWAB32(*p))
goto repeat;
- } else {
- brelse (bh);
- return NULL;
- }
+ goto out;
}
/* The nullification of framgents done in ufs/balloc.c is
if (metadata) {
result = getblk (bh->b_dev, tmp + blockoff, sb->s_blocksize);
} else {
- *phys_block = tmp;
- result = NULL;
- *err = 0;
- *created = 1;
+ *phys = tmp;
+ *new = 1;
}
mark_buffer_dirty(bh, 1);
}
inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
+out:
brelse (bh);
UFSD(("EXIT, result %u\n", tmp + blockoff))
return result;
}
-int ufs_getfrag_block (struct inode * inode, long fragment,
- int create, int * err, int *created)
+int ufs_getfrag_block (struct inode *inode, long fragment, struct buffer_head *bh_result, int create)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
- struct buffer_head * bh, * tmp;
- unsigned f;
- unsigned swab;
- int phys_block;
+ struct buffer_head * bh;
+ unsigned int swab;
+ int ret, err, new;
+ unsigned long ptr, phys;
sb = inode->i_sb;
uspi = sb->u.ufs_sb.s_uspi;
swab = sb->u.ufs_sb.s_swab;
- *err = -EIO;
- UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment))
- if (fragment < 0) {
- ufs_warning (sb, "ufs_getblk", "block < 0");
- return 0;
- }
- if (fragment > ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb) << uspi->s_fpbshift)) {
- ufs_warning (sb, "ufs_getblk", "block > big");
+ if (!create) {
+ phys = ufs_frag_map(inode, fragment);
+ if (phys) {
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = phys;
+ bh_result->b_state |= (1UL << BH_Mapped);
+ }
return 0;
}
- *err = -ENOSPC;
- f = fragment;
- *created = 0;
+ err = -EIO;
+ new = 0;
+ ret = 0;
+ bh = NULL;
+
+ lock_kernel();
+
+ UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment))
+ if (fragment < 0)
+ goto abort_negative;
+ if (fragment >
+ ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb)
+ << uspi->s_fpbshift))
+ goto abort_too_big;
+
+ err = 0;
+ ptr = fragment;
/*
- * Direct fragment
- */
- if (fragment < UFS_NDIR_FRAGMENT) {
- tmp = ufs_inode_getfrag (inode, fragment, fragment, create, 1,
- err, 0, &phys_block, created);
- goto out;
- }
- /*
- * Indirect fragment
- */
- fragment -= UFS_NDIR_FRAGMENT;
- if (fragment < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) {
- bh = ufs_inode_getfrag (inode,
- UFS_IND_FRAGMENT + (fragment >> uspi->s_apbshift),
- f, create, uspi->s_fpb, err, 1, NULL, NULL);
- tmp = ufs_block_getfrag (inode, bh,
- fragment & uspi->s_apbmask,
- f, create, sb->s_blocksize,
- err, 0, &phys_block, created);
- goto out;
- }
- /*
- * Dindirect fragment
+ * ok, these macros clean the logic up a bit and make
+ * it much more readable:
*/
- fragment -= 1 << (uspi->s_apbshift + uspi->s_fpbshift);
- if ( fragment < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) {
- bh = ufs_inode_getfrag (inode,
- UFS_DIND_FRAGMENT + (fragment >> uspi->s_2apbshift),
- f, create, uspi->s_fpb, err,
- 1, NULL, NULL);
- bh = ufs_block_getfrag (inode, bh,
- (fragment >> uspi->s_apbshift) & uspi->s_apbmask,
- f, create, sb->s_blocksize, err,
- 1, NULL, NULL);
- tmp = ufs_block_getfrag (inode, bh,
- fragment & uspi->s_apbmask,
- f, create, sb->s_blocksize, err,
- 0, &phys_block, created);
+#define GET_INODE_DATABLOCK(x) \
+ ufs_inode_getfrag(inode, x, fragment, 1, &err, 0, &phys, &new)
+#define GET_INODE_PTR(x) \
+ ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, 1, NULL, NULL)
+#define GET_INDIRECT_DATABLOCK(x) \
+ ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
+ &err, 0, &phys, &new);
+#define GET_INDIRECT_PTR(x) \
+ ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
+ &err, 1, NULL, NULL);
+
+ if (ptr < UFS_NDIR_FRAGMENT) {
+ bh = GET_INODE_DATABLOCK(ptr);
goto out;
}
- /*
- * Tindirect fragment
- */
- fragment -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift);
- bh = ufs_inode_getfrag (inode,
- UFS_TIND_FRAGMENT + (fragment >> uspi->s_3apbshift),
- f, create, uspi->s_fpb, err, 1, NULL, NULL);
- bh = ufs_block_getfrag (inode, bh,
- (fragment >> uspi->s_2apbshift) & uspi->s_apbmask,
- f, create, sb->s_blocksize, err, 1, NULL, NULL);
- bh = ufs_block_getfrag (inode, bh,
- (fragment >> uspi->s_apbshift) & uspi->s_apbmask,
- f, create, sb->s_blocksize, err, 1, NULL, NULL);
- tmp = ufs_block_getfrag (inode, bh,
- fragment & uspi->s_apbmask,
- f, create, sb->s_blocksize, err, 0, &phys_block, created);
+ ptr -= UFS_NDIR_FRAGMENT;
+ if (ptr < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) {
+ bh = GET_INODE_PTR(UFS_IND_FRAGMENT + (ptr >> uspi->s_apbshift));
+ goto get_indirect;
+ }
+ ptr -= 1 << (uspi->s_apbshift + uspi->s_fpbshift);
+ if (ptr < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) {
+ bh = GET_INODE_PTR(UFS_DIND_FRAGMENT + (ptr >> uspi->s_2apbshift));
+ goto get_double;
+ }
+ ptr -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift);
+ bh = GET_INODE_PTR(UFS_TIND_FRAGMENT + (ptr >> uspi->s_3apbshift));
+ bh = GET_INDIRECT_PTR((ptr >> uspi->s_2apbshift) & uspi->s_apbmask);
+get_double:
+ bh = GET_INDIRECT_PTR((ptr >> uspi->s_apbshift) & uspi->s_apbmask);
+get_indirect:
+ bh = GET_INDIRECT_DATABLOCK(ptr & uspi->s_apbmask);
+
+#undef GET_INODE_DATABLOCK
+#undef GET_INODE_PTR
+#undef GET_INDIRECT_DATABLOCK
+#undef GET_INDIRECT_PTR
out:
- if (!phys_block)
- return 0;
- if (*err)
- return 0;
- return phys_block;
+ if (err)
+ goto abort;
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = phys;
+ bh_result->b_state |= (1UL << BH_Mapped);
+ if (new)
+ bh_result->b_state |= (1UL << BH_New);
+abort:
+ unlock_kernel();
+ return err;
+
+abort_negative:
+ ufs_warning(sb, "ufs_get_block", "block < 0");
+ goto abort;
+
+abort_too_big:
+ ufs_warning(sb, "ufs_get_block", "block > big");
+ goto abort;
}
struct buffer_head *ufs_getfrag(struct inode *inode, unsigned int fragment,
int create, int *err)
{
- struct buffer_head *tmp = NULL;
- int phys_block, created;
-
- phys_block = ufs_getfrag_block(inode, fragment, create, err, &created);
- if (phys_block) {
- tmp = getblk(inode->i_dev, phys_block, inode->i_sb->s_blocksize);
- if (created) {
- memset(tmp->b_data, 0, inode->i_sb->s_blocksize);
- mark_buffer_uptodate(tmp, 1);
- mark_buffer_dirty(tmp, 1);
+ struct buffer_head dummy;
+ int error;
+
+ dummy.b_state = 0;
+ dummy.b_blocknr = -1000;
+ error = ufs_getfrag_block(inode, fragment, &dummy, create);
+ *err = error;
+ if (!error && buffer_mapped(&dummy)) {
+ struct buffer_head *bh;
+ bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
+ if (buffer_new(&dummy)) {
+ memset(bh->b_data, 0, inode->i_sb->s_blocksize);
+ mark_buffer_uptodate(bh, 1);
+ mark_buffer_dirty(bh, 1);
}
+ return bh;
}
- return tmp;
+ return NULL;
}
struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment,
NULL, /* rename */
ufs_readlink, /* readlink */
ufs_follow_link, /* follow_link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
UMSDOS_rename, /* rename */
NULL, /* readlink */
NULL, /* followlink */
- fat_bmap, /* bmap */
+ fat_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- fat_bmap, /* bmap */
+ fat_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow link */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow link */
- NULL, /* bmap */
+ NULL, /* get_block */
fat_readpage, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* followlink */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* truncate */
NULL, /* permission */
NULL, /* smap */
NULL, /* rename */
UMSDOS_readlink, /* readlink */
UMSDOS_followlink, /* followlink */
- fat_bmap, /* bmap */
+ fat_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
vfat_rename, /* rename */
NULL, /* readlink */
NULL, /* followlink */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* flushpage */
#ifndef __ASM_HARDIRQ_H
#define __ASM_HARDIRQ_H
+#include <asm/smp.h>
+
extern unsigned int ppc_local_irq_count[NR_CPUS];
/*
#define HYDRA_INT_VIA 9
#define HYDRA_INT_ADB 10
#define HYDRA_INT_ADB_NMI 11
-#define HYDRA_INT_EXT1 12
-#define HYDRA_INT_EXT2 13
-#define HYDRA_INT_EXT3 14
-#define HYDRA_INT_EXT4 15
-#define HYDRA_INT_EXT5 16
-#define HYDRA_INT_EXT6 17
-#define HYDRA_INT_EXT7 18
+#define HYDRA_INT_EXT1 12 /* PCI IRQW */
+#define HYDRA_INT_EXT2 13 /* PCI IRQX */
+#define HYDRA_INT_EXT3 14 /* PCI IRQY */
+#define HYDRA_INT_EXT4 15 /* PCI IRQZ */
+#define HYDRA_INT_EXT5 16 /* IDE Primay/Secondary */
+#define HYDRA_INT_EXT6 17 /* IDE Secondary */
+#define HYDRA_INT_EXT7 18 /* Power Off Request */
#define HYDRA_INT_SPARE 19
extern int hydra_init(void);
/*
* linux/include/asm-ppc/ide.h
*
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
+ * Copyright (C) 1994-1996 Linus Torvalds & authors */
/*
* This file contains the ppc architecture specific IDE code.
void (*outsw)(ide_ioreg_t port, void *buf, int ns);
int (*default_irq)(ide_ioreg_t base);
ide_ioreg_t (*default_io_base)(int index);
- int (*check_region)(ide_ioreg_t from, unsigned int extent);
- void (*request_region)(ide_ioreg_t from,
+ int (*ide_check_region)(ide_ioreg_t from, unsigned int extent);
+ void (*ide_request_region)(ide_ioreg_t from,
unsigned int extent,
const char *name);
- void (*release_region)(ide_ioreg_t from,
+ void (*ide_release_region)(ide_ioreg_t from,
unsigned int extent);
void (*fix_driveid)(struct hd_driveid *id);
void (*ide_init_hwif)(hw_regs_t *hw,
extern struct ide_machdep_calls ppc_ide_md;
-void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
void ide_insw(ide_ioreg_t port, void *buf, int ns);
void ide_outsw(ide_ioreg_t port, void *buf, int ns);
void ppc_generic_ide_fix_driveid(struct hd_driveid *id);
return -1;
}
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw,
+ ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq)
+{
+ if (ppc_ide_md.ide_init_hwif != NULL)
+ ppc_ide_md.ide_init_hwif(hw, data_port, ctrl_port, irq);
+}
+
static __inline__ void ide_init_default_hwifs(void)
{
#ifdef __DO_I_NEED_THIS
static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
{
- if ( ppc_ide_md.check_region )
- return ppc_ide_md.check_region(from, extent);
+ if ( ppc_ide_md.ide_check_region )
+ return ppc_ide_md.ide_check_region(from, extent);
else
return -1;
}
static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
{
- if ( ppc_ide_md.request_region )
- ppc_ide_md.request_region(from, extent, name);
+ if ( ppc_ide_md.ide_request_region )
+ ppc_ide_md.ide_request_region(from, extent, name);
}
static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
{
- if ( ppc_ide_md.release_region )
- ppc_ide_md.release_region(from, extent);
+ if ( ppc_ide_md.ide_release_region )
+ ppc_ide_md.ide_release_region(from, extent);
}
static __inline__ void ide_fix_driveid (struct hd_driveid *id)
ppc_ide_md.fix_driveid(id);
}
+#if 0 /* inb/outb from io.h is OK now -- paulus */
#undef inb
#define inb(port) in_8((unsigned char *)((port) + ppc_ide_md.io_base))
#undef inb_p
out_8((unsigned char *)((port) + ppc_ide_md.io_base), (val) )
#undef outb_p
#define outb_p(val, port) outb(val, port)
+#endif
typedef union {
unsigned all : 8; /* all of the bits together */
#include <asm/machdep.h> /* ppc_md */
extern void disable_irq(unsigned int);
+extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int);
#ifndef CONFIG_8xx
ppc_md.kbd_init_hw();
}
-#define kbd_sysrq_xlate (ppc_md.kbd_sysrq_xlate)
+#define kbd_sysrq_xlate (ppc_md.ppc_kbd_sysrq_xlate)
-#ifdef CONFIG_MAC_KEYBOARD
-# define SYSRQ_KEY 0x69
-#else
-# define SYSRQ_KEY 0x54
-#endif
+extern unsigned long SYSRQ_KEY;
#endif /* CONFIG_APUS */
unsigned long (*get_rtc_time)(void);
void (*calibrate_decr)(void);
+ void (*heartbeat)(void);
+ unsigned long heartbeat_reset;
+ unsigned long heartbeat_count;
+
unsigned char (*nvram_read_val)(int addr);
void (*nvram_write_val)(int addr, unsigned char val);
void (*kbd_leds)(unsigned char leds);
void (*kbd_init_hw)(void);
#ifdef CONFIG_MAGIC_SYSRQ
- unsigned char *kbd_sysrq_xlate;
+ unsigned char *ppc_kbd_sysrq_xlate;
#endif
/* PCI interfaces */
#ifndef _PPC_MMU_H_
#define _PPC_MMU_H_
-#include <linux/config.h>
-
#ifndef __ASSEMBLY__
/* Hardware Page Table Entry */
typedef struct _PTE {
#ifndef __ASSEMBLY__
#ifdef __KERNEL__
+#ifdef CONFIG_XMON
+#define BUG() do { \
+ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+ xmon(0); \
+} while (0)
+#else
+#define BUG() do { \
+ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+ __asm__ __volatile__(".long 0x0"); \
+}
+#endif
+#define PAGE_BUG(page) do { BUG(); } while (0)
+
#define STRICT_MM_TYPECHECKS
#ifdef STRICT_MM_TYPECHECKS
void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
void release_thread(struct task_struct *);
+/*
+ * Create a new kernel thread.
+ */
+extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
/*
* Bus types
*/
* the PT_* values below. This simplifies arch/ppc/kernel/ptrace.c.
*/
-#include <linux/config.h>
-
#ifndef __ASSEMBLY__
#ifdef CONFIG_PPC64
-#define REG unsigned long /*long*/
+#define PPC_REG unsigned long /*long*/
#else
-#define REG unsigned long
+#define PPC_REG unsigned long
#endif
struct pt_regs {
- REG gpr[32];
- REG nip;
- REG msr;
- REG orig_gpr3; /* Used for restarting system calls */
- REG ctr;
- REG link;
- REG xer;
- REG ccr;
- REG mq; /* 601 only (not used at present) */
- /* Used on APUS to hold IPL value. */
- REG trap; /* Reason for being here */
- REG dar; /* Fault registers */
- REG dsisr;
- REG result; /* Result of a system call */
+ PPC_REG gpr[32];
+ PPC_REG nip;
+ PPC_REG msr;
+ PPC_REG orig_gpr3; /* Used for restarting system calls */
+ PPC_REG ctr;
+ PPC_REG link;
+ PPC_REG xer;
+ PPC_REG ccr;
+ PPC_REG mq; /* 601 only (not used at present) */
+ /* Used on APUS to hold IPL value. */
+ PPC_REG trap; /* Reason for being here */
+ PPC_REG dar; /* Fault registers */
+ PPC_REG dsisr;
+ PPC_REG result; /* Result of a system call */
};
#endif
#include <asm/atomic.h>
#include <asm/hardirq.h>
-extern unsigned int ppc_local_bh_count[NR_CPUS];
-
#define get_active_bhs() (bh_mask & bh_active)
#define clear_active_bhs(x) atomic_clear_mask((x),&bh_active)
+extern unsigned int ppc_local_bh_count[NR_CPUS];
+
extern inline void init_bh(int nr, void (*routine)(void))
{
bh_base[nr] = routine;
{
bh_mask &= ~(1 << nr);
wmb();
- bh_base[nr] = NULL;
+ bh_base[nr] = 0;
}
extern inline void mark_bh(int nr)
static inline int softirq_trylock(int cpu)
{
if (!test_and_set_bit(0,&global_bh_count)) {
- if (atomic_read(&global_bh_lock) == 0) {
+ if (atomic_read(&global_bh_lock) &&
+ ppc_local_bh_count[cpu] == 0) {
++ppc_local_bh_count[cpu];
return 1;
}
#endif /* SMP */
+#define local_bh_disable() (ppc_local_bh_count[smp_processor_id()]++)
+#define local_bh_enable() (ppc_local_bh_count[smp_processor_id()]--)
+
/*
* These use a mask count to correctly handle
* nested disable/enable calls
#define __ASM_SPINLOCK_H
#ifndef __SMP__
-
/*
* Your basic spinlocks, allowing only a single CPU anywhere
*
#define spin_lock_init(lock) do { } while(0)
#define spin_lock(lock) do { } while(0)
-#define spin_trylock(lock) do { } while(0)
+#define spin_trylock(lock) (1)
#define spin_unlock_wait(lock) do { } while(0)
#define spin_unlock(lock) do { } while(0)
#define spin_lock_irq(lock) cli()
#define spin_unlock_irq(lock) sti()
-
+#define spin_lock_bh(lock) local_bh_disable()
+#define spin_unlock_bh(lock) local_bh_enable()
#define spin_lock_irqsave(lock, flags) \
do { save_flags(flags); cli(); } while (0)
+
#define spin_unlock_irqrestore(lock, flags) \
restore_flags(flags)
#define read_unlock_irq(lock) sti()
#define write_lock_irq(lock) cli()
#define write_unlock_irq(lock) sti()
+#define read_lock_bh(lock) local_bh_disable()
+#define read_unlock_bh(lock) local_bh_enable()
+#define write_lock_bh(lock) local_bh_disable()
+#define write_unlock_bh(lock) local_bh_enable()
#define read_lock_irqsave(lock, flags) \
do { save_flags(flags); cli(); } while (0)
#define spin_lock_irq(lock) \
do { __cli(); spin_lock(lock); } while (0)
+#define spin_lock_bh(___lk) do { local_bh_disable(); spin_lock(___lk); } while(0)
+
#define spin_unlock_irq(lock) \
do { spin_unlock(lock); __sti(); } while (0)
+#define spin_unlock_bh(___lk) do { spin_unlock(___lk); local_bh_enable(); } while(0)
#define spin_lock_irqsave(lock, flags) \
do { __save_flags(flags); __cli(); spin_lock(lock); } while (0)
#define read_unlock(rw) _read_unlock(rw)
#define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0)
+#define read_lock_bh(lock) do { local_bh_disable(); read_lock(lock); } while (0)
#define read_unlock_irq(lock) do { read_unlock(lock); __sti(); } while (0)
+#define read_unlock_bh(lock) do { read_unlock(lock); local_bh_enable(); } while (0)
#define write_lock_irq(lock) do { __cli(); write_lock(lock); } while (0)
+#define write_lock_bh(lock) do { local_bh_disable(); write_lock(lock); } while(0)
#define write_unlock_irq(lock) do { write_unlock(lock); __sti(); } while (0)
-
+#define write_unlock_bh(lock) do { write_unlock(lock); local_bh_enable(); } while(0)
#define read_lock_irqsave(lock, flags) \
do { __save_flags(flags); __cli(); read_lock(lock); } while (0)
#define read_unlock_irqrestore(lock, flags) \
#endif /* SMP */
#endif /* __ASM_SPINLOCK_H */
-
-
-
-
-
-
-
-
-
* the child.
*/
-/*
- * Create a new kernel thread.
- */
-extern long __kernel_thread(unsigned long, int (*)(void *), void *);
-
-static inline long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
- return __kernel_thread(flags | CLONE_VM, fn, arg);
-}
-
/*
* System call prototypes.
*/
extern inline struct file * fcheck(unsigned int fd)
{
struct file * file = NULL;
+ struct files_struct *files = current->files;
- if (fd < current->files->max_fds)
- file = current->files->fd[fd];
+ read_lock(&files->file_lock);
+ if (fd < files->max_fds)
+ file = files->fd[fd];
+ read_unlock(&files->file_lock);
return file;
}
extern inline struct file * fget(unsigned int fd)
{
- struct file * file = fcheck(fd);
+ struct file * file = NULL;
+ struct files_struct *files = current->files;
- if (file)
- file->f_count++;
+ read_lock(&files->file_lock);
+ if (fd < files->max_fds) {
+ file = files->fd[fd];
+ if (file)
+ atomic_inc(&file->f_count);
+ }
+ read_unlock(&files->file_lock);
return file;
}
*/
extern inline void fd_install(unsigned int fd, struct file * file)
{
- current->files->fd[fd] = file;
+ struct files_struct *files = current->files;
+
+ write_lock(&files->file_lock);
+ files->fd[fd] = file;
+ write_unlock(&files->file_lock);
}
/*
struct file *f_next, **f_pprev;
struct dentry *f_dentry;
struct file_operations *f_op;
+ atomic_t f_count;
+ unsigned int f_flags;
mode_t f_mode;
loff_t f_pos;
- unsigned int f_count, f_flags;
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
struct fown_struct f_owner;
unsigned int f_uid, f_gid;
int get_joliet_filename(struct iso_directory_record *, struct inode *, unsigned char *);
int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
-/* The stuff that follows may be totally unneeded. I have not checked to see
- which prototypes we are still using. */
-
-extern int isofs_open(struct inode * inode, struct file * filp);
-extern void isofs_release(struct inode * inode, struct file * filp);
-extern struct dentry *isofs_lookup(struct inode * dir, struct dentry *);
-extern unsigned long isofs_count_free_inodes(struct super_block *sb);
-extern int isofs_new_block(int dev);
-extern int isofs_free_block(int dev, int block);
-extern int isofs_bmap(struct inode *,int);
-
-extern void isofs_put_super(struct super_block *);
-extern struct super_block *isofs_read_super(struct super_block *,void *,int);
+extern struct dentry *isofs_lookup(struct inode *, struct dentry *);
+extern int isofs_get_block(struct inode *, long, struct buffer_head *, int);
+extern int isofs_bmap(struct inode *, int);
extern int init_iso9660_fs(void);
-extern void isofs_read_inode(struct inode *);
-extern void isofs_put_inode(struct inode *);
-extern int isofs_statfs(struct super_block *, struct statfs *, int);
-
-extern int isofs_lseek(struct inode *, struct file *, off_t, int);
-extern int isofs_read(struct inode *, struct file *, char *, int);
extern int isofs_lookup_grandparent(struct inode *, int);
extern struct inode_operations isofs_file_inode_operations;
extern int minix_bmap(struct inode *,int);
extern struct buffer_head * minix_getblk(struct inode *, int, int);
-extern int minix_getblk_block (struct inode *, long, int, int *, int *);
+extern int minix_get_block(struct inode *, long, struct buffer_head *, int);
extern struct buffer_head * minix_bread(struct inode *, int, int);
extern void minix_truncate(struct inode *);
*/
struct files_struct {
atomic_t count;
+ rwlock_t file_lock;
int max_fds;
struct file ** fd; /* current fd array */
fd_set close_on_exec;
#define INIT_FILES { \
ATOMIC_INIT(1), \
+ RW_LOCK_UNLOCKED, \
NR_OPEN, \
&init_fd_array[0], \
{ { 0, } }, \
extern void sysv_free_block(struct super_block * sb, unsigned int block);
extern unsigned long sysv_count_free_blocks(struct super_block *sb);
-extern int sysv_bmap(struct inode *,int);
-
extern struct buffer_head * sysv_getblk(struct inode *, unsigned int, int);
-extern int sysv_getblk_block(struct inode *, long, int, int *, int *);
+extern int sysv_get_block(struct inode *, long, struct buffer_head *, int);
extern struct buffer_head * sysv_file_bread(struct inode *, int, int);
-extern ssize_t sysv_file_read(struct file *, char *, size_t, loff_t *);
extern void sysv_truncate(struct inode *);
-extern void sysv_put_super(struct super_block *);
-extern struct super_block *sysv_read_super(struct super_block *,void *,int);
extern int init_sysv_fs(void);
-extern void sysv_write_super(struct super_block *);
-extern void sysv_read_inode(struct inode *);
-extern int sysv_notify_change(struct dentry *, struct iattr *);
extern void sysv_write_inode(struct inode *);
-extern int sysv_statfs(struct super_block *, struct statfs *, int);
extern int sysv_sync_inode(struct inode *);
extern int sysv_sync_file(struct file *, struct dentry *);
-extern int sysv_mmap(struct file *, struct vm_area_struct *);
extern struct inode_operations sysv_file_inode_operations;
extern struct inode_operations sysv_file_inode_operations_with_bmap;
timer->prev = NULL;
}
-extern inline int timer_pending(struct timer_list * timer)
+extern inline int timer_pending(const struct timer_list * timer)
{
return timer->prev != NULL;
}
extern struct inode * ufs_new_inode (const struct inode *, int, int *);
/* inode.c */
-extern int ufs_bmap (struct inode *, int);
+extern int ufs_frag_map (struct inode *, int);
extern void ufs_read_inode (struct inode *);
extern void ufs_put_inode (struct inode *);
extern void ufs_write_inode (struct inode *);
extern void ufs_write_inode (struct inode *);
extern void ufs_delete_inode (struct inode *);
extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
-extern int ufs_getfrag_block (struct inode *, long, int, int *, int *);
+extern int ufs_getfrag_block (struct inode *, long, struct buffer_head *, int);
extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
/* namei.c */
tmp->vm_next = NULL;
file = tmp->vm_file;
if (file) {
- file->f_count++;
+ atomic_inc(&file->f_count);
if (tmp->vm_flags & VM_DENYWRITE)
file->f_dentry->d_inode->i_writecount--;
if (!new_fds)
goto out_release;
+ newf->file_lock = RW_LOCK_UNLOCKED;
atomic_set(&newf->count, 1);
newf->max_fds = NR_OPEN;
newf->fd = new_fds;
struct file *f = *old_fds++;
*new_fds = f;
if (f)
- f->f_count++;
+ atomic_inc(&f->f_count);
new_fds++;
}
/* This is long word aligned thus could use a optimized version */
EXPORT_SYMBOL(ll_rw_block);
EXPORT_SYMBOL(__wait_on_buffer);
EXPORT_SYMBOL(add_blkdev_randomness);
+EXPORT_SYMBOL(block_read_full_page);
+EXPORT_SYMBOL(block_write_full_page);
+EXPORT_SYMBOL(block_flushpage);
EXPORT_SYMBOL(generic_file_read);
EXPORT_SYMBOL(generic_file_write);
EXPORT_SYMBOL(generic_file_mmap);
{
ssize_t retval;
- unlock_kernel();
retval = -EFAULT;
if (access_ok(VERIFY_WRITE, buf, count)) {
retval = 0;
retval = desc.error;
}
}
- lock_kernel();
return retval;
}
* If a task terminates while we're swapping the page, the vma and
* and file could be released ... increment the count to be safe.
*/
- file->f_count++;
+ atomic_inc(&file->f_count);
result = do_write_page(inode, file, (const char *) page, offset);
fput(file);
return result;
count = limit - pos;
}
- unlock_kernel();
-
while (count) {
unsigned long bytes, pgpos, offset;
/*
page_cache_free(page_cache);
err = written ? written : status;
- lock_kernel();
out:
return err;
}
vma->vm_offset += vma->vm_start - n->vm_start;
n->vm_flags = newflags;
if (n->vm_file)
- n->vm_file->f_count++;
+ atomic_inc(&n->vm_file->f_count);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
n->vm_offset += n->vm_start - vma->vm_start;
n->vm_flags = newflags;
if (n->vm_file)
- n->vm_file->f_count++;
+ atomic_inc(&n->vm_file->f_count);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
right->vm_offset += right->vm_start - left->vm_start;
vma->vm_flags = newflags;
if (vma->vm_file)
- vma->vm_file->f_count += 2;
+ atomic_add(2, &vma->vm_file->f_count);
if (vma->vm_ops && vma->vm_ops->open) {
vma->vm_ops->open(left);
if (error)
goto unmap_and_free_vma;
vma->vm_file = file;
- file->f_count++;
+ atomic_inc(&file->f_count);
}
/*
mpnt->vm_file = area->vm_file;
mpnt->vm_pte = area->vm_pte;
if (mpnt->vm_file)
- mpnt->vm_file->f_count++;
+ atomic_inc(&mpnt->vm_file->f_count);
if (mpnt->vm_ops && mpnt->vm_ops->open)
mpnt->vm_ops->open(mpnt);
area->vm_end = addr; /* Truncate area */
n->vm_flags = newflags;
n->vm_page_prot = prot;
if (n->vm_file)
- n->vm_file->f_count++;
+ atomic_inc(&n->vm_file->f_count);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
n->vm_flags = newflags;
n->vm_page_prot = prot;
if (n->vm_file)
- n->vm_file->f_count++;
+ atomic_inc(&n->vm_file->f_count);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
vma->vm_flags = newflags;
vma->vm_page_prot = prot;
if (vma->vm_file)
- vma->vm_file->f_count += 2;
+ atomic_add(2,&vma->vm_file->f_count);
if (vma->vm_ops && vma->vm_ops->open) {
vma->vm_ops->open(left);
vma->vm_ops->open(right);
new_vma->vm_offset = vma->vm_offset + (addr - vma->vm_start);
lock_kernel();
if (new_vma->vm_file)
- new_vma->vm_file->f_count++;
+ atomic_inc(&new_vma->vm_file->f_count);
if (new_vma->vm_ops && new_vma->vm_ops->open)
new_vma->vm_ops->open(new_vma);
insert_vm_struct(current->mm, new_vma);
break;
}
/* Bump the usage count and install the file. */
- fp[i]->f_count++;
+ atomic_inc(&fp[i]->f_count);
current->files->fd[new_fd] = fp[i];
}
memcpy(new_fpl, fpl, sizeof(*fpl));
for (i=fpl->count-1; i>=0; i--)
- fpl->fp[i]->f_count++;
+ atomic_inc(&fpl->fp[i]->f_count);
}
return new_fpl;
}
* Will cycle in MASQ_PORT boundaries.
*/
static __u16 masq_port = PORT_MASQ_BEGIN;
-#ifdef __SMP__
static spinlock_t masq_port_lock = SPIN_LOCK_UNLOCKED;
-#endif
/*
* free ports counters (UDP & TCP)
__u32 fwmark; /* key: firewall mark */
struct list_head hosts; /* list of forward-to hosts */
atomic_t nhosts; /* number of "" */
-#ifdef __SMP__
rwlock_t lock;
-#endif
};
static DECLARE_MUTEX(mfw_sema);
-#ifdef __SMP__
static rwlock_t mfw_lock = RW_LOCK_UNLOCKED;
-#endif
static struct ip_masq_mfw *ip_masq_mfw_table[IP_MASQ_MFW_HSIZE];
MOD_INC_USE_COUNT;
memset(mfw, 0, sizeof(*mfw));
mfw->fwmark = fwmark;
-#ifdef __SMP__
mfw->lock = (rwlock_t) RW_LOCK_UNLOCKED;
-#endif
INIT_LIST_HEAD(&mfw->hosts);
out:
EXPORT_SYMBOL(ip_masq_mod_lkp_link);
EXPORT_SYMBOL(ip_masq_mod_lkp_unlink);
-#ifdef __SMP__
static spinlock_t masq_mod_lock = SPIN_LOCK_UNLOCKED;
-#endif
/*
* Base pointer for registered modules
/*
* Lock
*/
-#ifdef __SMP__
static spinlock_t portfw_lock = SPIN_LOCK_UNLOCKED;
-#endif
static struct list_head portfw_list[2];
static __inline__ int portfw_idx(int protocol)
int mss_now;
int err, copied;
- unlock_kernel();
lock_sock(sk);
err = 0;
out:
tcp_push_pending_frames(sk, tp);
release_sock(sk);
- lock_kernel();
return err;
}
if (flags & MSG_WAITALL)
target=len;
- unlock_kernel();
add_wait_queue(sk->sleep, &wait);
lock_sock(sk);
/* Clean up data we have read: This will do ACK frames. */
cleanup_rbuf(sk, copied);
release_sock(sk);
- lock_kernel();
return copied;
}
#include <net/scm.h>
#include <linux/init.h>
#include <linux/poll.h>
+#include <linux/smp_lock.h>
#include <asm/checksum.h>
* Send AF_UNIX data.
*/
-static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
+static int do_unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct scm_cookie *scm)
{
struct sock *sk = sock->sk;
if (!unix_peer(sk))
unix_unlock(other);
+
return len;
out_unlock:
return err;
}
+static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
+ struct scm_cookie *scm)
+{
+ int retval;
+
+ lock_kernel();
+ retval = do_unix_dgram_sendmsg(sock, msg, len, scm);
+ unlock_kernel();
+ return retval;
+}
-static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, int len,
+static int do_unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct scm_cookie *scm)
{
struct sock *sk = sock->sk;
if (skb==NULL)
{
- if (sent)
- goto out;
- return err;
+ if (!sent)
+ sent = err;
+ goto out;
}
/*
if (memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) {
kfree_skb(skb);
- if (sent)
- goto out;
- return -EFAULT;
+ if (!sent)
+ sent = -EFAULT;
+ goto out;
}
other=unix_peer(sk);
goto out;
if (!(msg->msg_flags&MSG_NOSIGNAL))
send_sig(SIGPIPE,current,0);
- return -EPIPE;
+ sent = -EPIPE;
+ goto out;
}
skb_queue_tail(&other->receive_queue, skb);
return sent;
}
+static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, int len,
+ struct scm_cookie *scm)
+{
+ int retval;
+
+ lock_kernel();
+ retval = do_unix_stream_sendmsg(sock, msg, len, scm);
+ unlock_kernel();
+ return retval;
+}
+
/*
* Sleep until data has arrive. But check for races..
*/
}
}
-static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+static int do_unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, int size,
int flags, struct scm_cookie *scm)
{
struct sock *sk = sock->sk;
return err;
}
+static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+ int flags, struct scm_cookie *scm)
+{
+ int retval;
-static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+ lock_kernel();
+ retval = do_unix_dgram_recvmsg(sock, msg, size, flags, scm);
+ unlock_kernel();
+ return retval;
+}
+
+static int do_unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, int size,
int flags, struct scm_cookie *scm)
{
struct sock *sk = sock->sk;
return -EOPNOTSUPP;
if (flags&MSG_WAITALL)
target = size;
-
-
+
msg->msg_namelen = 0;
/* Lock the socket to prevent queue disordering
return copied;
}
+static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+ int flags, struct scm_cookie *scm)
+{
+ int retval;
+
+ lock_kernel();
+ retval = do_unix_stream_recvmsg(sock, msg, size, flags, scm);
+ unlock_kernel();
+ return retval;
+}
+
static int unix_shutdown(struct socket *sock, int mode)
{
struct sock *sk = sock->sk;
* in flight we are in use.
*/
if(s->socket && s->socket->file &&
- s->socket->file->f_count > s->protinfo.af_unix.inflight)
+ atomic_read(&s->socket->file->f_count) > s->protinfo.af_unix.inflight)
maybe_unmark_and_push(s);
}
NULL, /* readlink */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* truncate */
router_proc_perms
};
NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* bmap */
+ NULL, /* get_block */
NULL, /* truncate */
router_proc_perms
};