N: Remy Card
E: Remy.Card@masi.ibp.fr
E: Remy.Card@linux.org
-D: Extended file system designer and developer
+D: Extended file system [defunct] designer and developer
D: Second extended file system designer and developer
S: Institut Blaise Pascal
S: 4 Place Jussieu
D: Debugging: SCSI code; Cyclades serial driver; APM driver
D: Debugging: XFree86 Mach 32 server, accelerated server code
+N: János Farkas
+E: chexum@shadow.banki.hu
+D: romfs, various (mostly networking) fixes
+P: 1024/F81FB2E1 41 B7 E4 E6 3E D4 A6 71 6D 9C F3 9F F2 BF DF 6E
+S: Madarász Viktor utca 25
+S: 1131 Budapest
+S: Hungary
+
N: Jürgen Fischer
E: fischer@et-inf.fho-emden.de (=?iso-8859-1?q?J=FCrgen?= Fischer)
D: Author of Adaptec AHA-152x scsi driver
N: Frank Xia
E: qx@math.columbia.edu
-D: Xiafs filesystem
+D: Xiafs filesystem [defunct]
S: 542 West 112th Street, 5N
S: New York, New York 10025
S: USA
generated by texinfo so a diff is useless anyway (though I can
incorporate one by hand if you insist upon sending it that way ;-).
-Last updated: December 13, 1996.
+Last updated: January 9, 1997.
Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
Current Minimal Requirements
Upgrade to at *least* these software revisions before thinking you've
encountered a bug!
-- Kernel modules 2.1.13
+- Kernel modules modutils-970104
- Gnu C 2.7.2.1
- Binutils 2.7.0.3
- Linux C Library 5.4.17
- Linux C++ Library 2.7.2.1
- Procps 1.01
- SysVinit 2.69
-- Sysklogd 1.3-3
- Mount 2.5p
- Net-tools 1.32-alpha
- Kbd 0.91
Modules
=======
- You need to upgrade to modules-2.1.13 for kernels 2.1.8 and later.
+ You need to upgrade to modutils-970104 for kernels 2.1.8 and later.
Gnu C
=====
Networking Changes
==================
- Please read Documentation/networking/routing.txt. People wanting to use
-all the new routing table features such as OSPF classes should also read
-Documentation/networking/policy-routing.txt.
+ Please read Documentation/networking/routing.txt and
+Documentation/networking/policy-routing.txt for more information about
+changes in routing code. OSPF classes have been added, and interface
+routes are generated automatically.
+
+ If for some reason you need to override this automatic default
+routing, you have to specify the complete route specification (netmask,
+device, etc.) for the kernel to accept it. Consequently, you need to
+either remove interface routes from your init scripts or add missing
+information to them if you need to replace the automatic routes.
+
+ Also note that some routes, such as loopback routes, do not show up
+in some standard tools. Check in /proc/net/rt_local to verify their
+presence.
SysVinit
========
To avoid an oops while shutting down or rebooting the computer,
upgrade to SysVinit 2.69.
+RPM
+===
+
+ If you run RedHat Linux or any other distribution that uses RPM, you
+need to upgrade RPM to version 2.2.7 or later.
+
+DOSEMU
+======
+
+ A new "stable" version of DOSEMU is available for 2.1.x kernels.
+Upgrade to 0.64.2 or later.
+
How to know the version of the installed programs
*************************************************
Gnu C: gcc -v or gcc --version
Libc: ls -l /lib/libc.so.*
Libc++: ls -l /usr/lib/libg++.so.*
+Ld.so: ldd-v
Binutils: ld -v
modules: insmod -V
procps: ps --version
-SysVinit: cat /proc/`cat /var/run/syslog.pid`/environ|strings|awk '$1 ~
+SysVinit: cat /proc/`cat /var/run/klogd.pid`/environ|strings|awk '$1 ~
/INIT_VERSION/ {print}'
+RPM: rpm --version
Where to get the files
**********************
Modules utilities
=================
-The 2.1.13 release:
-ftp://tsx-11.mit.edu/pub/linux/sources/system/v2.1/modules-2.1.13.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/kernel/v2.1/modules-2.1.13.tar.gz
+The 970104 release:
+ftp://ftp.redhat.com/pub/alphabits/modutils-970104.tar.gz
Procps utilities
================
ftp://tsx-11.mit.edu/pub/linux/sources/sbin/sysvinit-2.69.tar.gz
ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.69.tar.gz
+RPM utilities
+=============
+
+The 2.2.7 release for Intel:
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-2.2.7-1.i386.rpm
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-devel-2.2.7-1.i386.rpm
+The 2.2.7 release for Alpha:
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/axp/rpm-2.2.7-1.axp.rpm
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/axp/rpm-devel-2.2.7-1.axp.rpm
+The 2.2.7 release for SPARC:
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-2.2.7-1.sparc.rpm
+ftp://ftp.redhat.com/pub/redhat/redhat-4.0/updates/i386/rpm-devel-2.2.7-1.sparc.rpm
+
+DOSEMU
+======
+
+The 0.64.2 release:
+ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu0.64.2.tgz
+ftp://sunsite.unc.edu/pub/Linux/system/Emulators/dosemu0.64.2.tgz
+
Other Info
==========
Documentation/modules.txt. Note that the filesystem of your root
partition cannot be compiled as a module.
-Extended fs support
-CONFIG_EXT_FS
- This is the old Linux filesystem (= method to organize files on a
- harddisk partition or a floppy disk) and not in use anymore. It
- enlarges your kernel by about 25 kB. Let's all kill this beast. Say
- N.
-
Second extended fs support
CONFIG_EXT2_FS
This is the de facto standard Linux filesystem (= method to organize
sunsite.unc.edu:/pub/Linux/docs/faqs. This option will enlarge your
kernel by about 41 kB. Default is Y.
-xiafs filesystem support
-CONFIG_XIA_FS
- This is an old filesystem (= method to organize files on a harddisk
- partition or a floppy disk) and not in use anymore. This option
- would enlarge your kernel by about 28 kB. Let's all kill this beast:
- say N. If you want to compile this as a module ( = code which can
- be inserted in and removed from the running kernel whenever you
- want), say M here and read Documentation/modules.txt. Note that the
- filesystem of your root partition cannot be compiled as a module.
-
fat fs support
CONFIG_FAT_FS
If you want to use one of the FAT-based filesystems (the MS-DOS,
module, say M here and read Documentation/modules.txt.
If unsure, say N.
+ROMFS filesystem support (EXPERIMENTAL)
+CONFIG_ROMFS_FS
+ This is a special file system intended for installation disks or
+ otherwise prebuilt medias. It has very low overhead and low memory
+ requirements. However, it's read-only (one particular reason of the
+ smallness), so you need extra programs to prepare disks in this
+ format. If you are not sure, just say N, you don't need it.
+
Standard/generic serial support
CONFIG_SERIAL
This selects whether you want to include the driver for the standard
# LocalWords: TR Sony CDU caddyless cdu Mitsumi MCD cd mcd XA MultiSession CDA
# LocalWords: Matsushita Panasonic SBPCD Soundblaster Longshine sbpcd Aztech
# LocalWords: Okano Wearnes AZTCD CDD SE aztcd sonycd Goldstar GSCD Philips fs
-# LocalWords: LMS OPTCD Sanyo SJCD minix faqs xiafs XIA msdos harddrive mtools
+# LocalWords: LMS OPTCD Sanyo SJCD minix faqs msdos harddrive mtools
# LocalWords: std softlinks umssync NetworkFileSharing nfsd mountd CDs HPFS TI
# LocalWords: hpfs SYSV SCO intel iBCS Wyse WordPerfect tsx mit unixes sysv NR
# LocalWords: SMB WfW Cyclades async mux Logitech busmouse MouseSystem aka AST
- info and mount options for the OS/2 HPFS.
ncpfs.txt
- info on Novell Netware(tm) filesystem using NCP protocol.
+romfs.txt
+ - Description of the ROMFS filesystem.
smbfs.txt
- info on using filesystems with the SMB protocol (Win 3.11, Win NT)
sysv-fs.txt
--- /dev/null
+
+ROMFS - ROM FILE SYSTEM
+
+This is a quite dumb, read only filesystem, mainly for initial ram
+disks of installation disks. It has grown up by the need of having
+modules linked at boot time. Using this filesystem, you get a very
+similar feature, and even the possibility of a small kernel, with a
+file system which doesn't take up useful memory from the router
+functions in the basement of your office.
+
+For comparison, both the older minix and xiafs filesystems (compiled
+as module) need more than 20000 bytes, while romfs is less than a
+page, about 4000 bytes (assuming ix86 code). Under the same
+conditions, the msdos filesystem would need about 30K (and does not
+support device nodes or symlinks), while the nfs module with nfsroot
+is about 57K. Furthermore, as a bit unfair comparison, an actual
+rescue disk used up 3202 blocks with ext2, while with romfs, it needed
+3079 blocks.
+
+To create such a file system, you'll need a user program named
+genromfs. It is (or will be shortly) available via ftp on
+sunsite.unc.edu and its mirrors, in the /pub/Linux/system/Filesystems/
+directory.
+
+As the name suggests, romfs could be also used (space-efficiently) on
+various read-only medias, like (E)EPROM disks if someone will have the
+motivation.. :)
+
+However, the main purpose of romfs is to have a very small kernel,
+which has only this filesystem linked in, and then can load any module
+later, with the current module utilities. It can also be used to run
+some program to decide if you need SCSI devices, and even IDE or
+floppy drives can be loaded later if you use the "initrd" -- initial
+ram disk -- feature of the kernel. This would not be really news
+flash, but with romfs, you can even spare off your ext2 or minix or
+maybe even affs filesystem until you really know that you need it.
+
+For example, a distribution boot disk can contain only the cd disk
+drivers (and possibly the SCSI drivers), and the ISO filesystem
+module. The kernel can be small enough, since it doesn't have other
+filesystems, like the quite large ext2fs module, which can then be
+loaded off the CD at a later stage of the installation. Another use
+would be for a recovery disk, when you are reinstalling a workstation
+from the network, and you will have all the tools/modules available
+from a nearby server, so you don't want to carry two disks for this
+purpose, just because it won't fit into ext2.
+
+romfs operates on block devices as you can expect, and the underlying
+structure is very simple. Every accessible structure begins on 16
+byte boundaries for fast access. The minimum space a file will take
+is 32 bytes (this is an empty file, with a less than 16 character
+name). The maximum overhead for any non-empty file is the header, and
+the 16 byte padding for the name and the contents, also 16+14+15 = 45
+bytes. This is quite rare however, since most file names are longer
+than 3 bytes, and shorter than 15 bytes.
+
+The layout of the filesystem is the following:
+
+offset content
+
+ +---+---+---+---+
+ 0 | - | r | o | m | \
+ +---+---+---+---+ The ASCII representation of those bytes
+ 4 | 1 | f | s | - | / (i.e. "-rom1fs-"
+ +---+---+---+---+
+ 8 | full size | The number of accessible bytes in this fs.
+ +---+---+---+---+
+ 12 | checksum | The checksum of the FIRST 512 BYTES.
+ +---+---+---+---+
+ 16 | volume name | The zero terminated name of the volume,
+ : : padded to 16 byte boundary.
+ +---+---+---+---+
+ xx | file |
+ : headers :
+
+Every multi byte value (32 bit words, I'll use the longwords term from
+now on) must be in big endian order.
+
+The first eight bytes identify the filesystem, even for the casual
+reader. After that in the 3rd longword, it contains the number of
+bytes accessible from the start of this filesystem. The 4th longword
+is the checksum of the first 512 bytes (or the number of bytes
+accessible, whichever is smallest). The applied algorithm is the same
+as in the AFFS filesystem, namely a simple sum of the longwords
+(assuming bigendian quantities again). For details, please consult
+the source. This algorithm was chosen because although it's not quite
+reliable, it does not require any tables, and it is very simple.
+
+The following bytes are now part of the file system; each file header
+must begin on a 16 byte boundary.
+
+offset content
+
+ +---+---+---+---+
+ 0 | next filehdr|X| The offset of the next file header
+ +---+---+---+---+ (zero if no more files)
+ 4 | spec.info | Info for directories/hard links/devices
+ +---+---+---+---+
+ 8 | size | The size of this file in bytes
+ +---+---+---+---+
+ 12 | checksum | Covering the meta data, including the file
+ +---+---+---+---+ name, and padding
+ 16 | file name | The zero terminated name of the file,
+ : : padded to 16 byte boundary.
+ +---+---+---+---+
+ xx | file data |
+ : :
+
+Since the file headers begin always at a 16 byte boundary, the lowest
+4 bits would be always zero in the next filehdr pointer. These four
+bits are used for the mode information. Bits 0..2 specify the type of
+the file; while bit 4 shows if the file is executable or not. The
+permissions are assumed to be world readable, if this bit is not set,
+and world executable if it is; except the character and block devices,
+they are readable only for the owner. The owner of every file is user
+and group 0, this should never be a problem for the intended use. The
+mapping of the 8 possible values to file types is the following:
+
+ mapping spec.info means
+ 0 hard link link destination [file header]
+ 1 directory first file's header
+ 2 regular file unused, must be zero [MBZ]
+ 3 symbolic link unused, MBZ (file data is the link content)
+ 4 block device 16/16 bits major/minor number
+ 5 char device - " -
+ 6 socket unused, MBZ
+ 7 fifo unused, MBZ
+
+Note that hard links are specifically marked in this filesystem, but
+they will behave as you can expect (i.e. share the inode number).
+Note also that your responsibility to not create hard link loops, and
+creating all the . and .. links for directories. This is normally
+done correctly by the genromfs program. Please refrain from using the
+executable bits on the socket and fifo special files, they may have
+other uses in the future. Additionally, please remember that only
+regular files, and symlinks are supposed to have a nonzero size field;
+they contain the number of bytes available directly after the (padded)
+file name.
+
+Another thing to note is that romfs works on file headers and data
+aligned to 16 byte boundaries, but most hardware devices and the block
+device drivers are unable to cope with smaller than block-sized data.
+To overcome this limitation, the whole size of the file system must be
+padded to an 1024 byte boundary.
+
+If you have any problems or suggestions concerning this file system,
+please contact me. However, think twice before wanting me to add
+features and code, because the primary advantage of this file system
+is the small code.
+
+Have fun,
+Janos Farkas <chexum@shadow.banki.hu>
Here is a sample of the available modules included in the kernel sources:
- Most filesystems: minix, xiafs, msdos, umsdos, sysv, isofs, hpfs,
+ Most filesystems: minix, msdos, umsdos, sysv, isofs, hpfs,
smbfs, nfs
Mid-level SCSI support (required by top and low level scsi drivers).
VERSION = 2
PATCHLEVEL = 1
-SUBLEVEL = 20
+SUBLEVEL = 21
ARCH = i386
NM =$(CROSS_COMPILE)nm
STRIP =$(CROSS_COMPILE)strip
MAKE =make
+GENKSYMS=/sbin/genksyms
all: do-it-all
# standard CFLAGS
#
-CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce
+CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
ifdef CONFIG_CPP
CFLAGS := $(CFLAGS) -x c++
else
$(AR) rcs $@
endif
-endif
+endif # O_TARGET
#
# Rule to compile a set of .o files into one .a file
# Separate the object into "normal" objects and "exporting" objects
# Exporting objects are: all objects that define symbol tables
#
-ifdef CONFIG_MODVERSIONS
+ifdef CONFIG_MODULES
+
SYMTAB_OBJS = $(LX_OBJS) $(OX_OBJS) $(MX_OBJS)
+
+ifdef CONFIG_MODVERSIONS
ifneq "$(strip $(SYMTAB_OBJS))" ""
MODINCL = $(TOPDIR)/include/linux/modules
-# The -w option (enable warnings) for /bin/genksyms will return here in 2.1
+# The -w option (enable warnings) for genksyms will return here in 2.1
$(MODINCL)/%.ver: %.c
- @if [ ! -x /sbin/genksyms ]; then echo "Please read: Documentation/modules.txt"; fi
- $(CC) $(CFLAGS) -E -D__GENKSYMS__ $< | /sbin/genksyms $(MODINCL)
-
+ $(CC) $(CFLAGS) -E -D__GENKSYMS__ $<\
+ | $(GENKSYMS) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp
+ mv $@.tmp $@
+
$(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)): $(TOPDIR)/include/linux/autoconf.h
$(TOPDIR)/include/linux/modversions.h: $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver))
@echo updating $(TOPDIR)/include/linux/modversions.h
- @(echo "#ifdef MODVERSIONS";\
- echo "#undef CONFIG_MODVERSIONS";\
- echo "#define CONFIG_MODVERSIONS";\
- echo "#ifndef _set_ver";\
- echo "#define _set_ver(sym,vers) sym ## _R ## vers";\
- echo "#endif";\
- cd $(TOPDIR)/include/linux/modules; for f in *.ver;\
- do echo "#include <linux/modules/$${f}>"; done; \
- echo "#undef CONFIG_MODVERSIONS";\
- echo "#endif") \
- > $(TOPDIR)/include/linux/modversions.h
-
-$(MX_OBJS): $(TOPDIR)/include/linux/modversions.h
- $(CC) $(CFLAGS) -DEXPORT_SYMTAB -c $(@:.o=.c)
-
-$(LX_OBJS) $(OX_OBJS): $(TOPDIR)/include/linux/modversions.h
- $(CC) $(CFLAGS) -DMODVERSIONS -DEXPORT_SYMTAB -c $(@:.o=.c)
+ @(echo "#ifndef _LINUX_MODVERSIONS_H";\
+ echo "#define _LINUX_MODVERSIONS_H"; \
+ echo "#include <linux/modsetver.h>"; \
+ cd $(TOPDIR)/include/linux/modules; \
+ for f in *.ver; do \
+ if [ -f $$f ]; then echo "#include <linux/modules/$${f}>"; fi; \
+ done; \
+ echo "#endif"; \
+ ) > $@
dep fastdep: $(TOPDIR)/include/linux/modversions.h
-endif
+endif # SYMTAB_OBJS
+
$(M_OBJS): $(TOPDIR)/include/linux/modversions.h
ifdef MAKING_MODULES
$(O_OBJS) $(L_OBJS): $(TOPDIR)/include/linux/modversions.h
endif
-# This is needed to ensure proper dependency for multipart modules such as
-# fs/ext.o. (Otherwise, not all subobjects will be recompiled when
-# version information changes.)
else
$(TOPDIR)/include/linux/modversions.h:
- @touch $(TOPDIR)/include/linux/modversions.h
+ @echo "#include <linux/modsetver.h>" > $@
+endif # CONFIG_MODVERSIONS
+
+ifneq "$(strip $(SYMTAB_OBJS))" ""
+$(SYMTAB_OBJS): $(TOPDIR)/include/linux/modversions.h
+ $(CC) $(CFLAGS) -DEXPORT_SYMTAB -c $(@:.o=.c)
endif
+endif # CONFIG_MODULES
+
+
#
# include dependency files they exist
#
#
# CONFIG_QUOTA is not set
# CONFIG_MINIX_FS is not set
-# CONFIG_EXT_FS is not set
CONFIG_EXT2_FS=y
-# CONFIG_XIA_FS is not set
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_VFAT_FS is not set
O_TARGET := kernel.o
O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
- bios32.o ptrace.o time.o apecs.o lca.o cia.o ksyms.o
+ bios32.o ptrace.o time.o apecs.o lca.o cia.o
+OX_OBJS := alpha_ksyms.o
all: kernel.o head.o
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/ksyms.c
+ *
+ * Export the alpha-specific functions that are needed for loadable
+ * modules.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <asm/io.h>
+#include <asm/hwrpb.h>
+#include <asm/uaccess.h>
+
+
+extern void bcopy (const char *src, char *dst, int len);
+extern struct hwrpb_struct *hwrpb;
+extern long __kernel_thread(unsigned long, int (*)(void *), void *);
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
+
+/* these are C runtime functions with special calling conventions: */
+extern void __divl (void);
+extern void __reml (void);
+extern void __divq (void);
+extern void __remq (void);
+extern void __divlu (void);
+extern void __remlu (void);
+extern void __divqu (void);
+extern void __remqu (void);
+
+
+/* platform dependent support */
+EXPORT_SYMBOL(_inb);
+EXPORT_SYMBOL(_inw);
+EXPORT_SYMBOL(_inl);
+EXPORT_SYMBOL(_outb);
+EXPORT_SYMBOL(_outw);
+EXPORT_SYMBOL(_outl);
+EXPORT_SYMBOL(_readb);
+EXPORT_SYMBOL(_readw);
+EXPORT_SYMBOL(_readl);
+EXPORT_SYMBOL(_writeb);
+EXPORT_SYMBOL(_writew);
+EXPORT_SYMBOL(_writel);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(outsl);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(strtok);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(__memset);
+EXPORT_SYMBOL(__constant_c_memset);
+
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(hwrpb);
+EXPORT_SYMBOL(wrusp);
+EXPORT_SYMBOL(__kernel_thread);
+
+/*
+ * The following are specially called from the uaccess assembly stubs.
+ */
+EXPORT_SYMBOL_NOVERS(__copy_user);
+EXPORT_SYMBOL_NOVERS(__clear_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(__strlen_user);
+
+/*
+ * The following are special because they're not called
+ * explicitly (the C compiler or assembler generates them in
+ * response to division operations). Fortunately, their
+ * interface isn't gonna change any time soon now, so it's OK
+ * to leave it out of version control.
+ */
+# undef bcopy
+# undef memcpy
+# undef memset
+EXPORT_SYMBOL_NOVERS(__divl);
+EXPORT_SYMBOL_NOVERS(__divlu);
+EXPORT_SYMBOL_NOVERS(__divq);
+EXPORT_SYMBOL_NOVERS(__divqu);
+EXPORT_SYMBOL_NOVERS(__reml);
+EXPORT_SYMBOL_NOVERS(__remlu);
+EXPORT_SYMBOL_NOVERS(__remq);
+EXPORT_SYMBOL_NOVERS(__remqu);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memset);
+++ /dev/null
-/*
- * linux/arch/alpha/kernel/ksyms.c
- *
- * Export the alpha-specific functions that are needed for loadable
- * modules.
- */
-
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <asm/io.h>
-#include <asm/hwrpb.h>
-#include <asm/uaccess.h>
-
-extern void bcopy (const char *src, char *dst, int len);
-extern struct hwrpb_struct *hwrpb;
-
-/* these are C runtime functions with special calling conventions: */
-extern void __divl (void);
-extern void __reml (void);
-extern void __divq (void);
-extern void __remq (void);
-extern void __divlu (void);
-extern void __remlu (void);
-extern void __divqu (void);
-extern void __remqu (void);
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
-
-
-/* platform dependent support */
-EXPORT_SYMBOL(_inb);
-EXPORT_SYMBOL(_inw);
-EXPORT_SYMBOL(_inl);
-EXPORT_SYMBOL(_outb);
-EXPORT_SYMBOL(_outw);
-EXPORT_SYMBOL(_outl);
-EXPORT_SYMBOL(_readb);
-EXPORT_SYMBOL(_readw);
-EXPORT_SYMBOL(_readl);
-EXPORT_SYMBOL(_writeb);
-EXPORT_SYMBOL(_writew);
-EXPORT_SYMBOL(_writel);
-EXPORT_SYMBOL(insb);
-EXPORT_SYMBOL(insw);
-EXPORT_SYMBOL(insl);
-EXPORT_SYMBOL(outsb);
-EXPORT_SYMBOL(outsw);
-EXPORT_SYMBOL(outsl);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strtok);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(__memcpy);
-EXPORT_SYMBOL(__memset);
-EXPORT_SYMBOL(__constant_c_memset);
-
-EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(hwrpb);
-EXPORT_SYMBOL(wrusp);
-
-/*
- * The following are specially called from the uaccess assembly stubs.
- */
-EXPORT_SYMBOL_NOVERS(__copy_user);
-EXPORT_SYMBOL_NOVERS(__clear_user);
-EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(__strlen_user);
-
-/*
- * The following are special because they're not called
- * explicitly (the C compiler or assembler generates them in
- * response to division operations). Fortunately, their
- * interface isn't gonna change any time soon now, so it's OK
- * to leave it out of version control.
- */
-# undef bcopy
-# undef memcpy
-# undef memset
-EXPORT_SYMBOL_NOVERS(__divl);
-EXPORT_SYMBOL_NOVERS(__divlu);
-EXPORT_SYMBOL_NOVERS(__divq);
-EXPORT_SYMBOL_NOVERS(__divqu);
-EXPORT_SYMBOL_NOVERS(__reml);
-EXPORT_SYMBOL_NOVERS(__remlu);
-EXPORT_SYMBOL_NOVERS(__remq);
-EXPORT_SYMBOL_NOVERS(__remqu);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
" lda %1,3b-1b(%0)\n"
" .gprel32 2b\n"
" lda %2,3b-2b(%0)\n"
- ".text"
+ ".previous"
: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
: "r"(va), "0"(0));
if (error)
" lda %1,3b-1b(%0)\n"
" .gprel32 2b\n"
" lda %2,3b-2b(%0)\n"
- ".text"
+ ".previous"
: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
: "r"(va), "0"(0));
if (error)
" lda %1,3b-1b(%0)\n"
" .gprel32 2b\n"
" lda %2,3b-2b(%0)\n"
- ".text"
+ ".previous"
: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
: "r"(va), "0"(0));
if (error)
" lda $31,5b-3b(%0)\n"
" .gprel32 4b\n"
" lda $31,5b-4b(%0)\n"
- ".text"
+ ".previous"
: "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
"=&r"(tmp3), "=&r"(tmp4)
: "r"(va), "r"(una_reg(reg)), "0"(0));
" lda $31,5b-3b(%0)\n"
" .gprel32 4b\n"
" lda $31,5b-4b(%0)\n"
- ".text"
+ ".previous"
: "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
"=&r"(tmp3), "=&r"(tmp4)
: "r"(va), "r"(una_reg(reg)), "0"(0));
" lda $31,5b-3b(%0)\n"
" .gprel32 4b\n"
" lda $31,5b-4b(%0)\n"
- ".text"
+ ".previous"
: "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
"=&r"(tmp3), "=&r"(tmp4)
: "r"(va), "r"(una_reg(reg)), "0"(0));
.section __ex_table,"a"; \
.gprel32 99b; \
lda $31, $exception-99b($31); \
- .text
+ .previous
.set noat
.set noreorder
.section __ex_table,"a"; \
.gprel32 99b; \
lda $31, $exit-99b($31); \
- .text
+ .previous
.set noat
.align 3
.section __ex_table,"a"; \
.gprel32 99b; \
lda v0, $exception-99b(zero); \
- .text
+ .previous
.set noreorder
.section __ex_table,"a"; \
.gprel32 99b; \
lda $31, $exception-99b($0); \
- .text
+ .previous
.set noat
BZLINKFLAGS =-Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS)
LINKFLAGS =-Ttext $(IMAGE_OFFSET) $(LDFLAGS)
-CFLAGS := $(CFLAGS) -pipe
+CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce
ifdef CONFIG_M386
CFLAGS := $(CFLAGS) -m386 -DCPU=386
#
# CONFIG_QUOTA is not set
CONFIG_MINIX_FS=y
-# CONFIG_EXT_FS is not set
CONFIG_EXT2_FS=y
-# CONFIG_XIA_FS is not set
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_VFAT_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_AFFS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_UFS_FS is not set
#
O_TARGET := kernel.o
O_OBJS := process.o signal.o entry.o traps.o irq.o vm86.o bios32.o \
- ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o ksyms.o
+ ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o
+OX_OBJS := i386_ksyms.o
ifdef CONFIG_MCA
O_OBJS += mca.o
--- /dev/null
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <linux/mca.h>
+
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(elf_fpregset_t *);
+
+/* platform dependent support */
+EXPORT_SYMBOL(EISA_bus);
+EXPORT_SYMBOL(MCA_bus);
+EXPORT_SYMBOL(wp_works_ok);
+EXPORT_SYMBOL(__verify_write);
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL_NOVERS(__down_failed);
+EXPORT_SYMBOL_NOVERS(__up_wakeup);
+
+#ifdef __SMP__
+EXPORT_SYMBOL(apic_reg); /* Needed internally for the I386 inlines */
+EXPORT_SYMBOL(cpu_data);
+EXPORT_SYMBOL(syscall_count);
+EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(kernel_counter);
+EXPORT_SYMBOL(active_kernel_processor);
+EXPORT_SYMBOL(smp_invalidate_needed);
+#endif
+
+#ifdef CONFIG_MCA
+/* Adapter probing and info methods. */
+EXPORT_SYMBOL(mca_write_pos);
+EXPORT_SYMBOL(mca_read_pos);
+EXPORT_SYMBOL(mca_read_stored_pos);
+EXPORT_SYMBOL(mca_set_adapter_name);
+EXPORT_SYMBOL(mca_get_adapter_name);
+EXPORT_SYMBOL(mca_set_adapter_procfn);
+EXPORT_SYMBOL(mca_isenabled);
+EXPORT_SYMBOL(mca_isadapter);
+#endif
+++ /dev/null
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/smp.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/mca.h>
-
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(elf_fpregset_t *);
-
-/* platform dependent support */
-EXPORT_SYMBOL(EISA_bus);
-EXPORT_SYMBOL(MCA_bus);
-EXPORT_SYMBOL(wp_works_ok);
-EXPORT_SYMBOL(__verify_write);
-EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(ioremap);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
-
-#ifdef __SMP__
-EXPORT_SYMBOL(apic_reg); /* Needed internally for the I386 inlines */
-EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(syscall_count);
-EXPORT_SYMBOL(kernel_flag);
-EXPORT_SYMBOL(kernel_counter);
-EXPORT_SYMBOL(active_kernel_processor);
-EXPORT_SYMBOL(smp_invalidate_needed);
-#endif
-
-#ifdef CONFIG_MCA
-/* Adapter probing and info methods. */
-EXPORT_SYMBOL(mca_write_pos);
-EXPORT_SYMBOL(mca_read_pos);
-EXPORT_SYMBOL(mca_read_stored_pos);
-EXPORT_SYMBOL(mca_set_adapter_name);
-EXPORT_SYMBOL(mca_get_adapter_name);
-EXPORT_SYMBOL(mca_set_adapter_procfn);
-EXPORT_SYMBOL(mca_isenabled);
-EXPORT_SYMBOL(mca_isadapter);
-#endif
if(!reboot_thru_bios) {
sti();
/* rebooting needs to touch the page at absolute addr 0 */
- pg0[0] = 7;
- *((unsigned short *)0x472) = reboot_mode;
+ *((unsigned short *)__va(0x472)) = reboot_mode;
for (;;) {
int i;
for (i=0; i<100; i++) {
O_TARGET := amiga.o
O_OBJS := config.o amikeyb.o amiints.o cia.o \
- chipram.o amisound.o amifb.o zorro.o ksyms.o
+ chipram.o amisound.o amifb.o zorro.o
+OX_OBJS := amiga_ksyms.o
ifdef CONFIG_FB_CYBER
O_OBJS := $(O_OBJS) cyberfb.o
--- /dev/null
+#include <linux/types.h>
+#include <linux/module.h>
+#include <asm/zorro.h>
+#include <asm/amigahw.h>
+
+extern volatile u_short amiga_audio_min_period;
+extern u_short amiga_audio_period;
+
+/*
+ * Add things here when you find the need for it.
+ */
+EXPORT_SYMBOL(amiga_model);
+EXPORT_SYMBOL(amiga_hw_present);
+EXPORT_SYMBOL(amiga_eclock);
+EXPORT_SYMBOL(amiga_colorclock);
+EXPORT_SYMBOL(amiga_chip_alloc);
+EXPORT_SYMBOL(amiga_chip_free);
+EXPORT_SYMBOL(amiga_chip_avail);
+EXPORT_SYMBOL(amiga_audio_period);
+EXPORT_SYMBOL(amiga_audio_min_period);
+
+EXPORT_SYMBOL(zorro_find);
+EXPORT_SYMBOL(zorro_get_board);
+EXPORT_SYMBOL(zorro_config_board);
+EXPORT_SYMBOL(zorro_unconfig_board);
+EXPORT_SYMBOL(zorro_unused_z2ram);
+++ /dev/null
-#include <linux/types.h>
-#include <linux/module.h>
-#include <asm/zorro.h>
-#include <asm/amigahw.h>
-
-extern volatile u_short amiga_audio_min_period;
-extern u_short amiga_audio_period;
-
-/*
- * Add things here when you find the need for it.
- */
-EXPORT_SYMBOL(amiga_model);
-EXPORT_SYMBOL(amiga_hw_present);
-EXPORT_SYMBOL(amiga_eclock);
-EXPORT_SYMBOL(amiga_colorclock);
-EXPORT_SYMBOL(amiga_chip_alloc);
-EXPORT_SYMBOL(amiga_chip_free);
-EXPORT_SYMBOL(amiga_chip_avail);
-EXPORT_SYMBOL(amiga_audio_period);
-EXPORT_SYMBOL(amiga_audio_min_period);
-
-EXPORT_SYMBOL(zorro_find);
-EXPORT_SYMBOL(zorro_get_board);
-EXPORT_SYMBOL(zorro_config_board);
-EXPORT_SYMBOL(zorro_unconfig_board);
-EXPORT_SYMBOL(zorro_unused_z2ram);
O_TARGET := atari.o
O_OBJS := config.o atakeyb.o ataints.o \
- stdma.o atasound.o joystick.o stram.o atafb.o ksyms.o
+ stdma.o atasound.o joystick.o stram.o atafb.o
+OX_OBJS := atari_ksyms.o
include $(TOPDIR)/Rules.make
--- /dev/null
+#include <linux/module.h>
+#include <asm/ptrace.h>
+#include <asm/traps.h>
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/atarikb.h>
+#include <asm/atari_joystick.h>
+#include <asm/atari_stdma.h>
+
+extern void atari_microwire_cmd( int cmd );
+
+
+EXPORT_SYMBOL(atari_mch_cookie);
+EXPORT_SYMBOL(atari_hw_present);
+EXPORT_SYMBOL(is_medusa);
+EXPORT_SYMBOL(atari_register_vme_int);
+EXPORT_SYMBOL(atari_unregister_vme_int);
+EXPORT_SYMBOL(stdma_lock);
+EXPORT_SYMBOL(stdma_release);
+EXPORT_SYMBOL(stdma_others_waiting);
+EXPORT_SYMBOL(stdma_islocked);
+
+EXPORT_SYMBOL(atari_mouse_buttons);
+EXPORT_SYMBOL(atari_mouse_interrupt_hook);
+EXPORT_SYMBOL(atari_MIDI_interrupt_hook);
+EXPORT_SYMBOL(atari_mch_cookie);
+EXPORT_SYMBOL(ikbd_write);
+EXPORT_SYMBOL(ikbd_mouse_y0_top);
+EXPORT_SYMBOL(ikbd_mouse_thresh);
+EXPORT_SYMBOL(ikbd_mouse_rel_pos);
+EXPORT_SYMBOL(ikbd_mouse_disable);
+
+EXPORT_SYMBOL(atari_microwire_cmd);
+++ /dev/null
-#include <linux/module.h>
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atarikb.h>
-#include <asm/atari_joystick.h>
-#include <asm/atari_stdma.h>
-
-extern void atari_microwire_cmd( int cmd );
-
-
-EXPORT_SYMBOL(atari_mch_cookie);
-EXPORT_SYMBOL(atari_hw_present);
-EXPORT_SYMBOL(is_medusa);
-EXPORT_SYMBOL(atari_register_vme_int);
-EXPORT_SYMBOL(atari_unregister_vme_int);
-EXPORT_SYMBOL(stdma_lock);
-EXPORT_SYMBOL(stdma_release);
-EXPORT_SYMBOL(stdma_others_waiting);
-EXPORT_SYMBOL(stdma_islocked);
-
-EXPORT_SYMBOL(atari_mouse_buttons);
-EXPORT_SYMBOL(atari_mouse_interrupt_hook);
-EXPORT_SYMBOL(atari_MIDI_interrupt_hook);
-EXPORT_SYMBOL(atari_mch_cookie);
-EXPORT_SYMBOL(ikbd_write);
-EXPORT_SYMBOL(ikbd_mouse_y0_top);
-EXPORT_SYMBOL(ikbd_mouse_thresh);
-EXPORT_SYMBOL(ikbd_mouse_rel_pos);
-EXPORT_SYMBOL(ikbd_mouse_disable);
-
-EXPORT_SYMBOL(atari_microwire_cmd);
#
# CONFIG_QUOTA is not set
CONFIG_MINIX_FS=y
-# CONFIG_EXT_FS is not set
CONFIG_EXT2_FS=y
-# CONFIG_XIA_FS is not set
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_VFAT_FS is not set
all: kernel.o head.o
O_TARGET := kernel.o
O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \
- setup.o bios32.o sys_m68k.o console.o time.o ksyms.o
+ setup.o bios32.o sys_m68k.o console.o time.o
+OX_OBJS := m68k_ksyms.o
head.o: head.S
+++ /dev/null
-#include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-
-#include <asm/setup.h>
-#include <asm/machdep.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/semaphore.h>
-
-asmlinkage long long __ashrdi3 (long long, int);
-extern char m68k_debug_device[];
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(elf_fpregset_t *);
-
-/* platform dependent support */
-
-EXPORT_SYMBOLS(memcmp);
-EXPORT_SYMBOLS(m68k_machtype);
-EXPORT_SYMBOLS(m68k_cputype);
-EXPORT_SYMBOLS(m68k_is040or060);
-EXPORT_SYMBOLS(cache_push);
-EXPORT_SYMBOLS(cache_push_v);
-EXPORT_SYMBOLS(cache_clear);
-EXPORT_SYMBOLS(mm_vtop);
-EXPORT_SYMBOLS(mm_ptov);
-EXPORT_SYMBOLS(mm_end_of_chunk);
-EXPORT_SYMBOLS(m68k_debug_device);
-EXPORT_SYMBOLS(request_irq);
-EXPORT_SYMBOLS(free_irq);
-EXPORT_SYMBOLS(dump_fpu);
-EXPORT_SYMBOLS(dump_thread);
-EXPORT_SYMBOLS(strnlen);
-EXPORT_SYMBOLS(strrchr);
-EXPORT_SYMBOLS(strstr);
-
-/* 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_SYMBOLS_NOVERS(__ashrdi3);
-EXPORT_SYMBOLS_NOVERS(memcpy);
-EXPORT_SYMBOLS_NOVERS(memset);
-
-EXPORT_SYMBOLS_NOVERS(__down_failed);
-EXPORT_SYMBOLS_NOVERS(__up_wakeup);
--- /dev/null
+#include <linux/module.h>
+#include <linux/linkage.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+
+#include <asm/setup.h>
+#include <asm/machdep.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/semaphore.h>
+
+asmlinkage long long __ashrdi3 (long long, int);
+extern char m68k_debug_device[];
+
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(elf_fpregset_t *);
+
+/* platform dependent support */
+
+EXPORT_SYMBOLS(memcmp);
+EXPORT_SYMBOLS(m68k_machtype);
+EXPORT_SYMBOLS(m68k_cputype);
+EXPORT_SYMBOLS(m68k_is040or060);
+EXPORT_SYMBOLS(cache_push);
+EXPORT_SYMBOLS(cache_push_v);
+EXPORT_SYMBOLS(cache_clear);
+EXPORT_SYMBOLS(mm_vtop);
+EXPORT_SYMBOLS(mm_ptov);
+EXPORT_SYMBOLS(mm_end_of_chunk);
+EXPORT_SYMBOLS(m68k_debug_device);
+EXPORT_SYMBOLS(request_irq);
+EXPORT_SYMBOLS(free_irq);
+EXPORT_SYMBOLS(dump_fpu);
+EXPORT_SYMBOLS(dump_thread);
+EXPORT_SYMBOLS(strnlen);
+EXPORT_SYMBOLS(strrchr);
+EXPORT_SYMBOLS(strstr);
+
+/* 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_SYMBOLS_NOVERS(__ashrdi3);
+EXPORT_SYMBOLS_NOVERS(memcpy);
+EXPORT_SYMBOLS_NOVERS(memset);
+
+EXPORT_SYMBOLS_NOVERS(__down_failed);
+EXPORT_SYMBOLS_NOVERS(__up_wakeup);
if (context.sc_usp != fp+fsize)
current->flags &= ~PF_ONSIGSTK;
-
+
/* OK. Make room on the supervisor stack for the extra junk,
* if necessary.
*/
" .align 4\n"
" .long 2b,4b\n"
" .long 3b,4b\n"
- ".text"
+ ".previous"
: /* no outputs, it doesn't ever return */
: "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
"n" (frame_offset), "a" (fp)
/*
* OK, we're invoking a handler
- */
+ */
static inline void handle_signal(unsigned long signr, struct sigaction *sa,
unsigned long oldmask, struct pt_regs *regs)
{
continue;
current->state = TASK_STOPPED;
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
+ if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
notify_parent(current);
schedule();
".long 19b,7b\n"
".long 20b,7b\n"
".long 21b,7b\n"
- ".text"
+ ".previous"
: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
"=&d" (tmp1), "=&d" (tmp2)
: "0" (sum), "1" (len), "2" (src), "3" (dst)
# Filesystems
#
# CONFIG_MINIX_FS is not set
-# CONFIG_EXT_FS is not set
CONFIG_EXT2_FS=y
-# CONFIG_XIA_FS is not set
# CONFIG_MSDOS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_ISO9660_FS is not set
#
CONFIG_QUOTA=y
CONFIG_MINIX_FS=m
-CONFIG_EXT_FS=m
CONFIG_EXT2_FS=y
-CONFIG_XIA_FS=m
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
*/
#define EXPORT_SYMBOL_DOT(sym) \
-extern int __sparc_dot_ ## sym (int) __asm__("." ## #sym); \
-const struct module_symbol __export_dot_##sym \
-__attribute__((section("__ksymtab"))) = \
-{ (unsigned long) &__sparc_dot_ ## sym, "." ## #sym }
+extern int __sparc_dot_ ## sym (int) __asm__("." #sym); \
+__EXPORT_SYMBOL(__sparc_dot_ ## sym, "." #sym)
/* used by various drivers */
dev_fname = (char *) data;
} else if(strcmp(type, "minix") == 0) {
dev_fname = (char *) data;
- } else if(strcmp(type, "ext") == 0) {
- dev_fname = (char *) data;
- } else if(strcmp(type, "xiafs") == 0) {
- dev_fname = (char *) data;
} else if(strcmp(type, "nfs") == 0) {
return sunos_nfs_mount (dir, flags, data);
} else if(strcmp(type, "ufs") == 0) {
".word 14b, " #errh "\n\t" \
".word 15b, " #errh "\n\t" \
".word 16b, " #errh "\n\n\t" \
- ".text\n\t" \
+ ".previous\n\t" \
: : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed) \
: "l1", "l2", "g7", "g1"); \
})
-
+
#define store_common(dst_addr, size, src_val, errh) ({ \
__asm__ __volatile__ ( \
"ld [%2], %%l1\n" \
".word 15b, " #errh "\n\t" \
".word 16b, " #errh "\n\t" \
".word 17b, " #errh "\n\n\t" \
- ".text\n\t" \
+ ".previous\n\t" \
: : "r" (dst_addr), "r" (size), "r" (src_val) \
: "l1", "l2", "g7", "g1"); \
})
{
unsigned long g2 = regs->u_regs [UREG_G2];
unsigned long fixup = search_exception_table (regs->pc, &g2);
-
+
if (!fixup) {
unsigned long address = compute_effective_address(regs, insn);
if(address < PAGE_SIZE) {
printk("Unsupported unaligned load/store trap for kernel at <%08lx>.\n",
regs->pc);
unaligned_panic("Wheee. Kernel does fpu/atomic unaligned load/store.");
-
+
__asm__ __volatile__ ("\n"
"kernel_unaligned_trap_fault:\n\t"
"mov %0, %%o0\n\t"
" mov %1, %%o1\n\t"
: : "r" (regs), "r" (insn)
: "o0", "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g4", "g5", "g7");
-
+
return;
} else {
unsigned long addr = compute_effective_address(regs, insn);
#if 0 /* unsupported */
case both:
do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
- (unsigned long *) addr,
+ (unsigned long *) addr,
kernel_unaligned_trap_fault);
break;
#endif
" mov %1, %%o1\n\t"
: : "r" (regs), "r" (insn)
: "o0", "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g4", "g5", "g7");
-
+
return;
}
advance(regs);
#
CONFIG_QUOTA=y
CONFIG_MINIX_FS=y
-CONFIG_EXT_FS=y
CONFIG_EXT2_FS=y
-CONFIG_XIA_FS=y
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/ext2_fs.h>
+#include <linux/romfs_fs.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/string.h>
* We currently check for the following magic numbers:
* minix
* ext2
+ * romfs
* gzip
*/
int
const int size = 512;
struct minix_super_block *minixsb;
struct ext2_super_block *ext2sb;
+ struct romfs_super_block *romfsb;
int nblocks = -1;
int max_blocks;
unsigned char *buf;
minixsb = (struct minix_super_block *) buf;
ext2sb = (struct ext2_super_block *) buf;
+ romfsb = (struct romfs_super_block *) buf;
memset(buf, 0xe5, size);
/*
goto done;
}
+ /* romfs is at block zero too */
+ if (romfsb->word0 == ROMSB_WORD0 &&
+ romfsb->word1 == ROMSB_WORD1) {
+ printk(KERN_NOTICE
+ "RAMDISK: Romfs filesystem found at block %d\n",
+ start_block);
+ nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
+ goto done;
+ }
+
/*
* Read block 1 to test for minix and ext2 superblock
*/
nblocks = ext2sb->s_blocks_count;
goto done;
}
+
printk(KERN_NOTICE
"RAMDISK: Couldn't find valid ramdisk image starting at %d.\n",
start_block);
* int rs_open(struct tty_struct * tty, struct file * filp)
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
-#include <linux/config.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
}
state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size;
+ if (state->type == PORT_UNKNOWN) {
+ restore_flags(flags);
+ return;
+ }
+
request_region(info->port,8,"serial(auto)");
/*
state->port = req->port;
state->flags = req->flags;
- if (check_region(state->port,8)) {
- restore_flags(flags);
- printk("register_serial(): I/O region in use\n");
- return -1; /* Area in use */
- }
autoconfig(state);
if (state->type == PORT_UNKNOWN) {
restore_flags(flags);
/*****************************************************************************/
-#include <linux/module.h>
-
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/net.h>
#include <linux/in.h>
* released under the GNU General Public License Version 2.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
static int io[MAX_ULTRA_CARDS] = { 0, };
static int irq[MAX_ULTRA_CARDS] = { 0, };
-MODULE_PARM(io, "1-" __MODULE_PARM(MAX_ULTRA_CARDS) "i");
-MODULE_PARM(irq, "1-" __MODULE_PARM(MAX_ULTRA_CARDS) "i");
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
/* This is set up so that only a single autoprobe takes place per call.
ISA device autoprobes on a running machine are not recommended. */
+Sun Jan 12 12:00 1997 Gerard Roudier (groudier@club-internet.fr)
+ * ncr53c8xx.c - revision 1.16e
+ - Add support of PCI burst length control from boot setup command.
+ burst:0 disable burst
+ burst:255 get burst from initial settings (BIOS settings?)
+ burst:#x set burst transfers to 1<<#x
+ - Only check xfer direction for common op-codes.
+ For all device specific / vendor specific opcodes the driver
+ now uses the xfer direction decided by the target.
+
+Sun Jan 05 12:00 1997 Gerard Roudier (groudier@club-internet.fr)
+ * ncr53c8xx.c - revision 1.16d
+ - The driver is now able to process scsi commands without
+ knowledge of xfer data direction.
+ Stefan agreed with this change for Linux. This change is
+ not needed under FreeBSD since low-level drivers receive
+ the expected data direction for each scsi request.
+ - Save ctest5 features bits at start-up and restore them at
+ module release step.
+ Avoid side effects when a ncr driver which trusts bios
+ settings is reloaded (could be the ncr53c8xx itself).
+
+
+Wed Jan 01 23:30 1997 Gerard Roudier (groudier@club-internet.fr)
+ * ncr53c8xx.c - revision 1.16c
+ - Bad decision about 20MHz for 13 ns period factor.
+ Was wrong, so I restore the previous algorithm.
+ - Burst length 128 not correctly set in dmode.
+
Thu Dec 26 22:00 1996 Gerard Roudier (groudier@club-internet.fr)
* ncr53c8xx.c ncr53c8xx.h README.ncr53c8xx - revision 1.16b
- Remove useless code.
dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI
if [ "$CONFIG_SCSI_EATA" != "n" ]; then
bool ' enable tagged command queueing' CONFIG_SCSI_EATA_TAGGED_QUEUE
+ bool ' enable linked commands' CONFIG_SCSI_EATA_LINKED_COMMANDS
+ int ' maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16
fi
dep_tristate 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI
dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI
+ if [ "$CONFIG_SCSI_U14_34F" != "n" ]; then
+ bool ' enable linked commands' CONFIG_SCSI_U14_34F_LINKED_COMMANDS
+ int ' maximum number of queued commands' CONFIG_SCSI_U14_34F_MAX_TAGS 8
+ fi
dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI
#dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
endmenu
endif
ifeq ($(CONFIG_SCSI),y)
-L_OBJS += hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o
+ # We must attach scsi_syms.o to scsi.o, as otherwise there is nothing to
+ # pull the object file from the archive.
+ SCSI=scsi.o
+ ifeq ($(CONFIG_MODULES),y)
+ O_TARGET := scsi_n_syms.o
+ O_OBJS := scsi.o
+ OX_OBJS := scsi_syms.o
+ SCSI := $(O_TARGET)
+ endif
+ L_OBJS += $(SCSI) hosts.o scsi_ioctl.o constants.o scsicam.o
ifeq ($(CONFIG_PROC_FS),y)
L_OBJS += scsi_proc.o
endif
-LX_OBJS += scsi_syms.o
else
ifeq ($(CONFIG_SCSI),m)
MX_OBJS += scsi_syms.o
21 Rue Carnot
95170 DEUIL LA BARRE - FRANCE
-29 December 1996
+12 January 1997
===============================================================================
1. Introduction
This driver has been tested OK with linux/i386 and Linux/Alpha.
+Latest driver version and patches are available at:
+
+ ftp://linux.wauug.org/pub/roudier
+
I am not a native speaker of English and there are probably lots of
mistakes in this README file. Any help will be welcome.
DEBUG_FREEZE 0x800
DEBUG_RESTART 0x1000
-You can play safely with DEBUG_NEGO. However, some of these flags may
-generate bunches of syslog messages.
+ You can play safely with DEBUG_NEGO. However, some of these flags may
+ generate bunches of syslog messages.
+
+Burst max
+ burst:0 burst disabled
+ burst:255 get burst length from initial IO register settings.
+ burst:#x burst enabled (1<<#x burst transfers max)
+ #x is an integer value which is log base 2 of the burst transfers max.
+ The NCR53C875 and NCR53C825A support up to 128 burst transfers (#x = 7).
+ Other chips only support up to 16 (#x = 4).
+ This is a maximum value. The driver set the burst length according to chip
+ and revision ids. By default the driver uses the maximum value supported
+ by the chip.
+
10.3 Advised boot setup commands
The driver prints its actual setup when verbosity level is 2. You can try
"ncr53c8xx=verb:2" to get the "static" setup of the driver, or add "verb:2"
-to your boot setup command in order to check the actual setup the drive use.
+to your boot setup command in order to check the actual setup the driver is
+using.
11. Some constants and flags of the ncr53c8xx.h header file
/*
* eata.c - Low-level driver for EATA/DMA SCSI host adapters.
*
+ * 8 Jan 1997 rev. 2.50 for linux 2.1.20 and 2.0.27
+ * Added linked command support.
+ * Improved detection of PCI boards using ISA base addresses.
+ *
* 3 Dec 1996 rev. 2.40 for linux 2.1.14 and 2.0.27
* Added support for tagged commands and queue depth adjustment.
*
* This driver is based on the CAM (Common Access Method Committee)
* EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
*
- * Copyright (C) 1994, 1995, 1996 Dario Ballabio (dario@milano.europe.dg.com)
+ * Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that redistributions of source
* PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS
* v003.D0, firmware v07G.0).
*
+ * DPT SmartRAID boards support "Hardware Array" - a group of disk drives
+ * which are all members of the same RAID-1 or RAID-5 array implemented
+ * in host adapter hardware. Hardware Arrays are fully compatible with this
+ * driver, since they look to it as a single disk drive.
+ * By contrast RAID-0 are implemented as "Array Group", which does not
+ * seem to be supported correctly by the actual SCSI subsystem.
+ * To get RAID-0 functionality, the linux MD driver must be used instead of
+ * the DPT "Array Group" feature.
+ *
* Multiple ISA, EISA and PCI boards can be configured in the same system.
* It is suggested to put all the EISA boards on the same IRQ level, all
* the PCI boards on another IRQ level, while ISA boards cannot share
#undef FORCE_CONFIG
+#undef DEBUG_LINKED_COMMANDS
#undef DEBUG_DETECT
#undef DEBUG_INTERRUPT
#undef DEBUG_STATISTICS
#define LOCKED 2
#define IN_RESET 3
#define IGNORE 4
+#define READY 5
+#define ABORTING 6
#define NO_DMA 0xff
#define MAXLOOP 200000
#define REG_MID 4
#define REG_MSB 5
#define REGION_SIZE 9
-#define ISA_RANGE 0x0fff
-#define EISA_RANGE 0xfc88
+#define MAX_ISA_ADDR 0x03ff
+#define MIN_EISA_ADDR 0x1c88
+#define MAX_EISA_ADDR 0xfc88
#define BSY_ASSERTED 0x80
#define DRQ_ASSERTED 0x08
#define ABSY_ASSERTED 0x01
ulong sp_addr; /* Address where sp is DMA'ed when cp completes */
ulong sense_addr; /* Address where Sense Data is DMA'ed on error */
unsigned int index; /* cp index */
+ unsigned int link_id; /* reference cp for linked commands */
struct sg_list *sglist;
};
static int tagged_commands = FALSE;
#endif
+#if defined (CONFIG_SCSI_EATA_LINKED_COMMANDS)
+static int linked_commands = TRUE;
+#else
+static int linked_commands = FALSE;
+#endif
+
+#if defined CONFIG_SCSI_EATA_MAX_TAGS
+static int max_queue_depth = CONFIG_SCSI_EATA_MAX_TAGS;
+#else
+static int max_queue_depth = MAX_CMD_PER_LUN;
+#endif
+
static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
Scsi_Device *dev;
int j, ntag = 0, nuntag = 0, tqd, utqd;
tqd = (host->can_queue - utqd * nuntag) / (ntag + 1);
- if (tqd > MAX_TAGGED_CMD_PER_LUN) tqd = MAX_TAGGED_CMD_PER_LUN;
+ if (tqd > max_queue_depth) tqd = max_queue_depth;
if (tqd < MAX_CMD_PER_LUN) tqd = MAX_CMD_PER_LUN;
else
protocol_rev = 'C';
- irq = info.irq;
-
- if (port_base > ISA_RANGE) {
-
- if (!info.haaval || info.ata || info.drqvld) {
- printk("%s: unusable EISA/PCI board found (%d%d%d), detaching.\n",
- name, info.haaval, info.ata, info.drqvld);
- return FALSE;
- }
-
+ if (!setup_done && j > 0 && j <= MAX_PCI) {
+ bus_type = "PCI";
+ subversion = ESA;
+ }
+ else if (port_base > MAX_EISA_ADDR || (protocol_rev == 'C' && info.pci)) {
+ bus_type = "PCI";
+ subversion = ESA;
+ }
+ else if (port_base >= MIN_EISA_ADDR || (protocol_rev == 'C' && info.eisa)) {
+ bus_type = "EISA";
+ subversion = ESA;
+ }
+ else if (protocol_rev == 'C' && !info.eisa && !info.pci) {
+ bus_type = "ISA";
+ subversion = ISA;
+ }
+ else if (port_base > MAX_ISA_ADDR) {
+ bus_type = "PCI";
subversion = ESA;
- dma_channel = NO_DMA;
}
else {
+ bus_type = "ISA";
+ subversion = ISA;
+ }
- if (!info.haaval || info.ata || !info.drqvld) {
- printk("%s: unusable ISA board found (%d%d%d), detaching.\n",
- name, info.haaval, info.ata, info.drqvld);
- return FALSE;
- }
+ if (!info.haaval || info.ata) {
+ printk("%s: address 0x%03x, unusable %s board (%d%d), detaching.\n",
+ name, port_base, bus_type, info.haaval, info.ata);
+ return FALSE;
+ }
+
+ if (info.drqvld) {
+
+ if (subversion == ESA)
+ printk("%s: warning, weird %s board using DMA.\n", name, bus_type);
subversion = ISA;
dma_channel = dma_channel_table[3 - info.drqx];
}
+ else {
+
+ if (subversion == ISA)
+ printk("%s: warning, weird %s board not using DMA.\n", name, bus_type);
+
+ subversion = ESA;
+ dma_channel = NO_DMA;
+ }
if (!info.dmasup)
printk("%s: warning, DMA protocol support not asserted.\n", name);
+ irq = info.irq;
+
if (subversion == ESA && !info.irq_tr)
printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
name, irq);
sh[j]->max_lun = info.max_lun + 1;
}
- if (subversion == ESA && protocol_rev == 'C' && info.pci) bus_type = "PCI";
- else if (sh[j]->io_port > EISA_RANGE) bus_type = "PCI";
- else if (subversion == ESA) bus_type = "EISA";
- else bus_type = "ISA";
-
if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "NO DMA");
else sprintf(dma_name, "DMA %u", dma_channel);
return FALSE;
}
- printk("%s: rev. 2.0%c, %s, PORT 0x%03x, IRQ %u, %s, SG %d, "\
- "Mbox %d, TC %d.\n", BN(j), HD(j)->protocol_rev, bus_type,
- sh[j]->io_port, sh[j]->irq, dma_name, sh[j]->sg_tablesize,
- sh[j]->can_queue, tagged_commands);
+ if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
+ max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
+
+ if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
+
+ printk("%s: 2.0%c, %s 0x%03x, IRQ %u, %s, SG %d, MB %d, TC %d, LC %d, "\
+ "MQ %d.\n", BN(j), HD(j)->protocol_rev, bus_type, sh[j]->io_port,
+ sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue,
+ tagged_commands, linked_commands, max_queue_depth);
if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
}
if (j > 0)
- printk("EATA/DMA 2.0x: Copyright (C) 1994, 1995, 1996 Dario Ballabio.\n");
+ printk("EATA/DMA 2.0x: Copyright (C) 1994-1997 Dario Ballabio.\n");
restore_flags(flags);
return j;
memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+ if (linked_commands && SCpnt->device->tagged_supported
+ && !HD(j)->target_to[SCpnt->target][SCpnt->channel]
+ && !HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+
+ for (k = 0; k < sh[j]->can_queue; k++) {
+
+ if (HD(j)->cp_stat[k] != IN_USE) continue;
+
+ if ((&HD(j)->cp[k])->SCpnt->device != SCpnt->device) continue;
+
+ cpp->link_id = k;
+ HD(j)->cp_stat[i] = READY;
+
+#if defined (DEBUG_LINKED_COMMANDS)
+ printk("%s: qcomm, target %d.%d:%d, pid %ld, Mbox %d ready.\n",
+ BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
+ SCpnt->pid, i);
+#endif
+ restore_flags(flags);
+ return 0;
+ }
+
/* Send control packet to the board */
if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
SCpnt->result = DID_ERROR << 16;
restore_flags(flags);
return SCSI_ABORT_NOT_RUNNING;
}
+
+ if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+ SCarg->result = DID_ABORT << 16;
+ SCarg->host_scribble = NULL;
+ HD(j)->cp_stat[i] = FREE;
+ printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
+ BN(j), i, SCarg->pid);
+ SCarg->scsi_done(SCarg);
+ restore_flags(flags);
+ return SCSI_ABORT_SUCCESS;
+ }
+
restore_flags(flags);
panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
}
continue;
}
- SCpnt = HD(j)->cp[i].SCpnt;
- HD(j)->cp_stat[i] = IN_RESET;
- printk("%s: reset, mbox %d in reset, pid %ld.\n",
- BN(j), i, SCpnt->pid);
-
- if (SCpnt == NULL)
+ if (!(SCpnt = HD(j)->cp[i].SCpnt))
panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
+ if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+ HD(j)->cp_stat[i] = ABORTING;
+ printk("%s: reset, mbox %d aborting, pid %ld.\n",
+ BN(j), i, SCpnt->pid);
+ }
+
+ else {
+ HD(j)->cp_stat[i] = IN_RESET;
+ printk("%s: reset, mbox %d in reset, pid %ld.\n",
+ BN(j), i, SCpnt->pid);
+ }
+
if (SCpnt->host_scribble == NULL)
panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
for (i = 0; i < sh[j]->can_queue; i++) {
- /* Skip mailboxes already set free by interrupt */
- if (HD(j)->cp_stat[i] != IN_RESET) continue;
+ if (HD(j)->cp_stat[i] == IN_RESET) {
+ SCpnt = HD(j)->cp[i].SCpnt;
+ SCpnt->result = DID_RESET << 16;
+ SCpnt->host_scribble = NULL;
- SCpnt = HD(j)->cp[i].SCpnt;
- SCpnt->result = DID_RESET << 16;
- SCpnt->host_scribble = NULL;
+ /* This mailbox is still waiting for its interrupt */
+ HD(j)->cp_stat[i] = LOCKED;
- /* This mailbox is still waiting for its interrupt */
- HD(j)->cp_stat[i] = LOCKED;
+ printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
+ BN(j), i, SCpnt->pid);
+ }
+
+ else if (HD(j)->cp_stat[i] == ABORTING) {
+ SCpnt = HD(j)->cp[i].SCpnt;
+ SCpnt->result = DID_RESET << 16;
+ SCpnt->host_scribble = NULL;
+
+ /* This mailbox was never queued to the adapter */
+ HD(j)->cp_stat[i] = FREE;
+
+ printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
+ BN(j), i, SCpnt->pid);
+ }
+
+ else
+
+ /* Any other mailbox has already been set free by interrupt */
+ continue;
- printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
- BN(j), i, SCpnt->pid);
restore_flags(flags);
SCpnt->scsi_done(SCpnt);
cli();
}
}
+static inline void process_ready_list(unsigned int i, unsigned int j) {
+ Scsi_Cmnd *SCpnt;
+ unsigned int k, n_ready = 0;
+ struct mscp *cpp;
+
+ for (k = 0; k < sh[j]->can_queue; k++) {
+
+ if (HD(j)->cp_stat[k] != READY) continue;
+
+ cpp = &HD(j)->cp[k];
+
+ if (cpp->link_id != i) continue;
+
+ SCpnt = cpp->SCpnt;
+ n_ready++;
+
+ if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
+ printk("%s: ihdlr, target %d.%d:%d, pid %ld, Mbox %d, link_id %d, "\
+ "n_ready %d, adapter busy, will abort.\n", BN(j),
+ SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+ k, i, n_ready);
+ HD(j)->cp_stat[k] = ABORTING;
+ continue;
+ }
+
+ HD(j)->cp_stat[k] = IN_USE;
+
+#if defined (DEBUG_LINKED_COMMANDS)
+ printk("%s: ihdlr, target %d.%d:%d, pid %ld, Mbox %d in use, link_id %d,"
+ " n_ready %d.\n", BN(j), SCpnt->channel, SCpnt->target,
+ SCpnt->lun, SCpnt->pid, k, i, n_ready);
+#endif
+ }
+
+}
+
static void eata2x_interrupt_handler(int irq, void *dev_id,
struct pt_regs *regs) {
Scsi_Cmnd *SCpnt;
spp->eoc = FALSE;
+ if (linked_commands) process_ready_list(i, j);
+
if (HD(j)->cp_stat[i] == IGNORE) {
HD(j)->cp_stat[i] = FREE;
continue;
int eata2x_abort(Scsi_Cmnd *);
int eata2x_reset(Scsi_Cmnd *, unsigned int);
-#define EATA_VERSION "2.40.00"
+#define EATA_VERSION "2.50.00"
#define EATA { \
*/
/*
-** 26 December 1996, version 1.16b
+** 12 January 1997, version 1.16e
**
** Supported SCSI-II features:
** Synchronous negotiation
/*
** Transfer direction
**
-** The middle scsi driver of Linux does not provide the transfer
-** direction in the command structure.
-** FreeBsd ncr driver requires this information.
+** Low-level scsi drivers under Linux do not receive the expected
+** data transfer direction from upper scsi drivers.
+** The driver will only check actual data direction for common
+** scsi opcodes. Other ones may cause problem, since they may
+** depend on device type or be vendor specific.
+** I would prefer to never trust the device for data direction,
+** but that is not possible.
**
-** I spent some hours to read the scsi2 documentation to see if
-** it was possible to deduce the direction of transfer from the opcode
-** of the command. It seems that it's OK.
-** guess_xfer_direction() seems to work. If it's wrong we will
-** get a phase mismatch on some opcode.
+** The original driver requires the expected direction to be known.
+** The Linux version of the driver has been enhanced in order to
+** be able to transfer data in the direction choosen by the target.
*/
#define XferNone 0
unsigned default_tags;
unsigned default_sync;
unsigned debug;
+ unsigned burst_max;
} driver_setup = SCSI_NCR_DRIVER_SETUP;
/*
#define SIR_REJECT_SENT (10)
#define SIR_IGN_RESIDUE (11)
#define SIR_MISSING_SAVE (12)
-#define SIR_MAX (12)
+#define SIR_DATA_IO_IS_OUT (13)
+#define SIR_MAX (13)
/*==========================================================
**
*/
u_char tag;
+
+ /*
+ ** Number of segments of the scatter list.
+ ** Used for recalculation of savep/goalp/lastp on
+ ** SIR_DATA_IO_IS_OUT interrupt.
+ */
+
+ u_char segments;
};
#define CCB_PHYS(cp,lbl) (cp->p_ccb + offsetof(struct ccb, lbl))
u_char sv_dcntl;
u_char sv_ctest3;
u_char sv_ctest4;
+ u_char sv_ctest5;
u_char rv_dmode;
u_char rv_dcntl;
ncrcmd resel_tmp [ 5];
ncrcmd resel_lun [ 18];
ncrcmd resel_tag [ 24];
+ ncrcmd data_io [ 2]; /* MUST be just before data_in */
ncrcmd data_in [MAX_SCATTER * 4 + 7];
ncrcmd data_out [MAX_SCATTER * 4 + 7];
ncrcmd aborttag [ 4];
SCR_RETURN,
0,
+}/*-------------------------< DATA_IO >--------------------*/,{
+/*
+** Because Linux does not provide xfer data direction
+** to low-level scsi drivers, we must trust the target
+** for actual data direction when we cannot guess it.
+** The programmed interrupt patches savep, lastp, goalp,
+** etc.., and restarts the scsi script at data_out.
+*/
+ SCR_INT ^ IFTRUE (WHEN (SCR_DATA_OUT)),
+ SIR_DATA_IO_IS_OUT,
+
}/*-------------------------< DATA_IN >--------------------*/,{
/*
** Because the size depends on the
**----------------------------------------------------
*/
+ cp->segments = segments;
+
switch (xfer_direction) {
default:
+ case XferBoth:
+ cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_io);
+ cp->phys.header.goalp = cp->phys.header.savep +8 +20 +segments*16;
+ break;
case XferIn:
cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_in);
cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16;
OUTB(nc_dcntl, np->sv_dcntl);
OUTB(nc_ctest3, np->sv_ctest3);
OUTB(nc_ctest4, np->sv_ctest4);
+ OUTB(nc_ctest5, np->sv_ctest5);
if (np->uf_doubler) {
OUTB(nc_stest1, DBLEN); /* Enable clock doubler */
};
}
+/*===============================================================
+**
+** NCR chips allow burst lengths of 2, 4, 8, 16, 32, 64, 128
+** transfers. 32,64,128 are only supported by 875 chips.
+** We use log base 2 (burst length) as internal code, with
+** value 0 meaning "burst disabled".
+**
+**===============================================================
+*/
+
+/*
+ * Burst length from burst code.
+ */
+#define burst_length(bc) (!(bc))? 0 : 1 << (bc)
+
+/*
+ * Burst code from io register bits.
+ */
+#define burst_code(dmode, ctest4, ctest5) \
+ (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1
+
+/*
+ * Set initial io register bits from burst code.
+ */
+static void ncr_init_burst(ncb_p np, u_char bc)
+{
+ np->rv_ctest4 &= ~0x80;
+ np->rv_dmode &= ~(0x3 << 6);
+ np->rv_ctest5 &= ~0x4;
+
+ if (!bc) {
+ np->rv_ctest4 |= 0x80;
+ }
+ else {
+ --bc;
+ np->rv_dmode |= ((bc & 0x3) << 6);
+ np->rv_ctest5 |= (bc & 0x4);
+ }
+}
+
/*==========================================================
**
**
int i;
u_long usrsync;
u_char usrwide;
+ u_char burst_max;
/*
** Reset chip.
np->rv_dcntl = np->sv_dcntl;
np->rv_ctest3 = np->sv_ctest3;
np->rv_ctest4 = np->sv_ctest4;
+ np->rv_ctest5 = np->sv_ctest5;
+ burst_max = burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
#else
np->rv_dmode = 0;
np->rv_dcntl = 0;
np->rv_ctest3 = 0;
np->rv_ctest4 = 0;
+ burst_max = driver_setup.burst_max;
+ if (burst_max == 255)
+ burst_max = burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
+ if (burst_max > 7)
+ burst_max = 7;
/** NCR53C810 **/
if (ChipDevice == PCI_DEVICE_ID_NCR_53C810 && ChipVersion == 0) {
- np->rv_dmode = 0x80; /* burst length 8 */
+ burst_max = burst_max < 4 ? burst_max : 4;
}
else
/** NCR53C815 **/
if (ChipDevice == PCI_DEVICE_ID_NCR_53C815) {
- np->rv_dmode = 0x80; /* burst length 8 */
+ burst_max = burst_max < 4 ? burst_max : 4;
}
else
/** NCR53C825 **/
if (ChipDevice == PCI_DEVICE_ID_NCR_53C825 && ChipVersion == 0) {
- np->rv_dmode = 0x8a; /* burst length 8, burst opcode fetch */
+ burst_max = burst_max < 4 ? burst_max : 4;
+ np->rv_dmode = 0x0a; /* burst opcode fetch */
}
else
/** NCR53C810A or NCR53C860 **/
if ((ChipDevice == PCI_DEVICE_ID_NCR_53C810 && ChipVersion >= 0x10) ||
ChipDevice == PCI_DEVICE_ID_NCR_53C860) {
if (!driver_setup.special_features)
- np->rv_dmode = 0xc0; /* burst length 16 */
+ burst_max = burst_max < 4 ? burst_max : 4;
else {
- np->rv_dmode = 0xc0 | BOF | ERMP | ERL;
+ burst_max = burst_max < 4 ? burst_max : 4;
+ np->rv_dmode = BOF | ERMP | ERL;
/* burst op-code fetch, read multiple */
- /* read line, burst 16 */
+ /* read line */
np->rv_dcntl = PFEN | CLSE;
/* prefetch, cache line size */
np->rv_ctest3 = WRIE; /* write and invalidate */
- np->rv_ctest4 = 0x0; /* burst not disabled */
}
}
else
if ((ChipDevice == PCI_DEVICE_ID_NCR_53C825 && ChipVersion >= 0x10) ||
ChipDevice == PCI_DEVICE_ID_NCR_53C875) {
if (!driver_setup.special_features)
- np->rv_dmode = 0xc0; /* burst length 16 */
+ burst_max = burst_max < 4 ? burst_max : 4;
else {
- np->rv_dmode = 0xc0 | BOF | ERMP | ERL;
+ burst_max = burst_max < 7 ? burst_max : 7;
+ np->rv_dmode = BOF | ERMP | ERL;
/* burst op-code fetch, read multiple */
/* read line, burst 128 (ctest5&4) */
np->rv_dcntl = PFEN | CLSE;
/* prefetch, cache line size */
np->rv_ctest3 = WRIE; /* write and invalidate */
- np->rv_ctest4 = 0x0; /* burst not disabled */
- np->rv_ctest5 = 0x24; /* burst 128 (0x04) */
- /* dma fifo 536 (0x20) */
+ np->rv_ctest5 = 0x20; /* dma fifo 536 (0x20) */
}
}
/** OTHERS **/
else {
- np->rv_dmode = 0xc0; /* burst length 16 */
+ burst_max = burst_max < 4 ? burst_max : 4;
}
#endif /* SCSI_NCR_TRUST_BIOS_SETTING */
+ /*
+ * Prepare initial io register bits for burst length
+ */
+ ncr_init_burst(np, burst_max);
+
+ if (bootverbose > 1) {
+ printf ("%s: initial value of dmode/ctest4/ctest5 = 0x%02x/0x%02x/0x%02x\n",
+ ncr_name(np), np->sv_dmode, np->sv_ctest4, np->sv_ctest5);
+ }
+ if (bootverbose) {
+ printf ("%s: final value of dmode/ctest4/ctest5 = 0x%02x/0x%02x/0x%02x\n",
+ ncr_name(np), np->rv_dmode, np->rv_ctest4, np->rv_ctest5);
+ }
+
#if 0
- printf("%s: bios: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x\n",
- ncr_name(np), np->sv_dmode, np->sv_dcntl, np->sv_ctest3, np->sv_ctest4);
- printf("%s: used: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x\n",
- ncr_name(np), np->rv_dmode, np->rv_dcntl, np->rv_ctest3, np->rv_ctest4);
+ printf("%s: bios: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x, ctest5=0x%02x\n",
+ ncr_name(np), np->sv_dmode, np->sv_dcntl, np->sv_ctest3, np->sv_ctest4, np->sv_ctest5);
+ printf("%s: used: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x, ctest5=0x%02x\n",
+ ncr_name(np), np->rv_dmode, np->rv_dcntl, np->rv_ctest3, np->rv_ctest4, np->rv_ctest5);
#endif
OUTB (nc_istat, 0x00 ); /* Remove Reset, abort ... */
}
switch (num) {
+ case SIR_DATA_IO_IS_OUT:
+/*
+** We did not guess the direction of transfer. We assumed DATA IN,
+** but the the target drove DATA OUT.
+** We have to patch the script context with DATA OUT context and
+** restart processing at data out script address.
+*/
+ cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_out);
+ cp->phys.header.goalp = cp->phys.header.savep +20 +cp->segments*16;
+ cp->phys.header.lastp = cp->phys.header.savep;
+ np->header.savep = cp->phys.header.savep;
+ np->header.goalp = cp->phys.header.goalp;
+ np->header.lastp = cp->phys.header.lastp;
+ OUTL (nc_temp, np->header.savep);
+ OUTL (nc_dsp, np->header.savep);
+ return;
+ /* break; */
/*--------------------------------------------------------------------
**
/*
** Check against controller limits.
** --------------------------------
- ** per <= 13 special case, allow fast 20 MHz transfer.
- ** per < 25 fast 20
+ ** per < 25 fast20
** per < 50 fast
** per < 100 slow
** Use a value p2 twice the controller limit in order to
** not do wrong integer calculation for 80 MHz clock.
** (12.5x2 = 25ns).
- ** Compute scntl3&0xf0 sync clock divisor for 50 ns period.
+ ** Compute scntl3&0xf0 sync clock divisor for 50 ns period
+ ** from the async pre-scaler.
** Ajust it according to actual controller sync period.
** - 0x40 divides it by 4 -> 50/4 = 12.5ns
** - 0x20 divides it by 2 -> 50/2 = 25 ns
p2 = 100;
scntl3 = (np->rv_scntl3 & 0x07) << 4;
- if (per <= 13) {
- fak = 0;
+ if (per < 25) {
+ p2 = 25;
scntl3 = (scntl3 - 0x40) | 0x80;
}
- else {
- if (per < 25) {
- p2 = 25;
- scntl3 = (scntl3 - 0x40) | 0x80;
- }
- else if (per < 50) {
- p2 = 50;
- scntl3 = scntl3 - 0x20;
- }
+ else if (per < 50) {
+ p2 = 50;
+ scntl3 = scntl3 - 0x20;
+ }
- fak = (8 * per - 1) / p2 - 3;
- if (fak > 7) {
- chg = 1;
- ofs = 0;
- }
+ fak = (8 * per - 1) / p2 - 3;
+ if (fak > 7) {
+ chg = 1;
+ ofs = 0;
}
}
if (ofs == 0) {
** 0x04 enable read multiple
** 0x08 enable read line
** 0xc0 burst length 16/8/2
-** DCNTL 0xa0
+** DCNTL 0xa8
+** 0x08 totem pole irq
** 0x20 enable pre-fetch
** 0x80 enable cache line size
** CTEST3 0x01
** 0x01 set write and invalidate
** CTEST4 0x80
** 0x80 burst disabled
+** CTEST5 0x24
+** 0x20 dma fifo 536 (875 only)
+** 0x04 burst len 32/64/128 (875 only)
*/
static void ncr_save_bios_setting(ncb_p np)
{
np->sv_scntl3 = INB(nc_scntl3) & 0x07;
np->sv_dmode = INB(nc_dmode) & 0xce;
- np->sv_dcntl = INB(nc_dcntl) & 0xa0;
+ np->sv_dcntl = INB(nc_dcntl) & 0xa8;
np->sv_ctest3 = INB(nc_ctest3) & 0x01;
np->sv_ctest4 = INB(nc_ctest4) & 0x80;
+ np->sv_ctest5 = INB(nc_ctest5) & 0x24;
}
/*===================== LINUX ENTRY POINTS SECTION ==========================*/
driver_setup.verbose = val;
else if (!strncmp(cur, "debug:", 6))
driver_setup.debug = val;
+ else if (!strncmp(cur, "burst:", 6))
+ driver_setup.burst_max = val;
if ((cur = strchr(cur, ',')) != NULL)
++cur;
#define YesNo(y) y ? 'y' : 'n'
if (bootverbose >= 2) {
- printk("ncr53c8xx: setup=disc:%c,specf:%c,ultra:%c,tags:%d,sync:%d\n",
+ printk("ncr53c8xx: setup=disc:%c,specf:%c,ultra:%c,tags:%d,sync:%d,burst:%d\n",
YesNo(driver_setup.disconnection),
YesNo(driver_setup.special_features),
YesNo(driver_setup.ultra_scsi),
driver_setup.default_tags,
- driver_setup.default_sync/1000);
+ driver_setup.default_sync/1000,
+ driver_setup.burst_max);
printk("ncr53c8xx: setup=mpar:%c,spar:%c,fsn=%c,verb:%d,debug:0x%x\n",
YesNo(driver_setup.master_parity),
YesNo(driver_setup.scsi_parity),
#undef next_wcmd
/*
-** In order to patch the SCSI script for SAVE/RESTORE DATA POINTER,
-** we need the direction of transfer.
-** Linux middle-level scsi driver does not provide this information.
-** So we have to guess it.
-** My documentation about SCSI-II standard is old. Probably some opcode
-** are missing.
-** If I do'nt know the command code, I assume input transfer direction.
+** Returns data transfer direction for common op-codes.
*/
static int guess_xfer_direction(int opcode)
int d;
switch(opcode) {
- case 0x00: /* TEST UNIT READY 00 */
- case 0x08: /* READ(6) 08 */
case 0x12: /* INQUIRY 12 */
case 0x4D: /* LOG SENSE 4D */
case 0x5A: /* MODE SENSE(10) 5A */
case 0x1A: /* MODE SENSE(6) 1A */
- case 0x28: /* READ(10) 28 */
- case 0xA8: /* READ(12) A8 */
case 0x3C: /* READ BUFFER 3C */
case 0x1C: /* RECEIVE DIAGNOSTIC RESULTS 1C */
- case 0xB7: /* READ DEFECT DATA(12) B7 */
- case 0xB8: /* READ ELEMENT STATUS B8 */
- /* GET WINDOW 25 */
- case 0x25: /* READ CAPACITY 25 */
- case 0x29: /* READ GENERATION 29 */
- case 0x3E: /* READ LONG 3E */
- /* GET DATA BUFFER STATUS 34 */
- /* PRE-FETCH 34 */
- case 0x34: /* READ POSITION 34 */
case 0x03: /* REQUEST SENSE 03 */
- case 0x05: /* READ BLOCK LIMITS 05 */
- case 0x0F: /* READ REVERSE 0F */
- case 0x14: /* RECOVER BUFFERED DATA 14 */
- case 0x2D: /* READ UPDATED BLOCK 2D */
- case 0x37: /* READ DEFECT DATA(10) 37 */
- case 0x42: /* READ SUB-CHANNEL 42 */
- case 0x43: /* READ TOC 43 */
- case 0x44: /* READ HEADER 44 */
- case 0xC7: /* ??? ??? C7 */
d = XferIn;
break;
case 0x39: /* COMPARE 39 */
case 0x3A: /* COPY AND VERIFY 3A */
- /* PRINT 0A */
- /* SEND MESSAGE(6) 0A */
- case 0x0A: /* WRITE(6) 0A */
case 0x18: /* COPY 18 */
case 0x4C: /* LOG SELECT 4C */
case 0x55: /* MODE SELECT(10) 55 */
case 0x3B: /* WRITE BUFFER 3B */
case 0x1D: /* SEND DIAGNOSTIC 1D */
case 0x40: /* CHANGE DEFINITION 40 */
- /* SEND MESSAGE(12) AA */
- case 0xAA: /* WRITE(12) AA */
- case 0xB6: /* SEND VOLUME TAG B6 */
- case 0x3F: /* WRITE LONG 3F */
- case 0x04: /* FORMAT UNIT 04 */
- /* INITIALIZE ELEMENT STATUS 07 */
- case 0x07: /* REASSIGN BLOCKS 07 */
case 0x15: /* MODE SELECT(6) 15 */
- case 0x24: /* SET WINDOW 24 */
- case 0x2A: /* WRITE(10) 2A */
- case 0x2E: /* WRITE AND VERIFY(10) 2E */
- case 0xAE: /* WRITE AND VERIFY(12) AE */
- case 0xB0: /* SEARCH DATA HIGH(12) B0 */
- case 0xB1: /* SEARCH DATA EQUAL(12) B1 */
- case 0xB2: /* SEARCH DATA LOW(12) B2 */
- /* OBJECT POSITION 31 */
- case 0x30: /* SEARCH DATA HIGH(10) 30 */
- case 0x31: /* SEARCH DATA EQUAL(10) 31 */
- case 0x32: /* SEARCH DATA LOW(10) 32 */
- case 0x38: /* MEDIUM SCAN 38 */
- case 0x3D: /* UPDATE BLOCK 3D */
- case 0x41: /* WRITE SAME 41 */
- /* LOAD UNLOAD 1B */
- /* SCAN 1B */
- case 0x1B: /* START STOP UNIT 1B */
d = XferOut;
break;
- case 0x01: /* REZERO UNIT 01 */
- /* SEEK(6) 0B */
- case 0x0B: /* SLEW AND PRINT 0B */
- /* SYNCHRONIZE BUFFER 10 */
- case 0x10: /* WRITE FILEMARKS 10 */
- case 0x11: /* SPACE 11 */
- case 0x13: /* VERIFY 13 */
- case 0x16: /* RESERVE UNIT 16 */
- case 0x17: /* RELEASE UNIT 17 */
- case 0x19: /* ERASE 19 */
- /* LOCATE 2B */
- /* POSITION TO ELEMENT 2B */
- case 0x2B: /* SEEK(10) 2B */
- case 0x1E: /* PREVENT ALLOW MEDIUM REMOVAL 1E */
- case 0x2C: /* ERASE(10) 2C */
- case 0xAC: /* ERASE(12) AC */
- case 0x2F: /* VERIFY(10) 2F */
- case 0xAF: /* VERIFY(12) AF */
- case 0x33: /* SET LIMITS(10) 33 */
- case 0xB3: /* SET LIMITS(12) B3 */
- case 0x35: /* SYNCHRONIZE CACHE 35 */
- case 0x36: /* LOCK UNLOCK CACHE 36 */
- case 0x45: /* PLAY AUDIO(10) 45 */
- case 0x47: /* PLAY AUDIO MSF 47 */
- case 0x48: /* PLAY AUDIO TRACK/INDEX 48 */
- case 0x49: /* PLAY TRACK RELATIVE(10) 49 */
- case 0xA9: /* PLAY TRACK RELATIVE(12) A9 */
- case 0x4B: /* PAUSE/RESUME 4B */
- /* MOVE MEDIUM A5 */
- case 0xA5: /* PLAY AUDIO(12) A5 */
- case 0xA6: /* EXCHANGE MEDIUM A6 */
- case 0xB5: /* REQUEST VOLUME ELEMENT ADDRESS B5 */
+ case 0x00: /* TEST UNIT READY 00 */
d = XferNone;
break;
default:
- d = XferIn;
+ d = XferBoth;
break;
}
/*
** Name and revision of the driver
*/
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 1.16b"
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 1.16e"
/*
** If SCSI_NCR_SETUP_SPECIAL_FEATURES is defined,
1, \
SCSI_NCR_SETUP_DEFAULT_TAGS, \
SCSI_NCR_SETUP_DEFAULT_SYNC, \
- 0x00 \
+ 0x00, \
+ 7 \
}
* a module.
*/
#define __NO_VERSION__
-#include <linux/module.h>
#include <linux/config.h>
+#include <linux/module.h>
#ifdef CONFIG_MODULES
files and the file number status is retained. */
#define ST_FAST_MTEOM 0
+/* If ST_SYSV is non-zero, the tape behaves according to the SYS V semantics.
+ The default is BSD semantics. */
+#define ST_SYSV 0
+
#endif
/*
* u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
*
+ * 8 Jan 1997 rev. 2.50 for linux 2.1.20 and 2.0.27
+ * Added linked command support.
+ *
* 3 Dec 1996 rev. 2.40 for linux 2.1.14 and 2.0.27
* Added queue depth adjustment.
*
*
* Multiple U14F and/or U34F host adapters are supported.
*
- * Copyright (C) 1994, 1995, 1996 Dario Ballabio (dario@milano.europe.dg.com)
+ * Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that redistributions of source
*
* Here a sample configuration using two U14F boards:
*
- U14F0: PORT 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 32, Mbox 16, UC 1.
- U14F1: PORT 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 32, Mbox 16, UC 1.
+ U14F0: ISA 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 32, MB 16, UC 1, LC 1, MQ 8.
+ U14F1: ISA 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 32, MB 16, UC 1, LC 1, MQ 8.
*
* The boot controller must have its BIOS enabled, while other boards can
* have their BIOS disabled, or enabled to an higher address.
#include <asm/irq.h>
#include "u14-34f.h"
#include<linux/stat.h>
+#include<linux/config.h>
struct proc_dir_entry proc_scsi_u14_34f = {
PROC_SCSI_U14_34F, 6, "u14_34f",
#define HA_CMD_READ_BUFF 0x3
#define HA_CMD_WRITE_BUFF 0x4
+#undef DEBUG_LINKED_COMMANDS
#undef DEBUG_DETECT
#undef DEBUG_INTERRUPT
#undef DEBUG_STATISTICS
#define LOCKED 2
#define IN_RESET 3
#define IGNORE 4
+#define READY 5
+#define ABORTING 6
#define NO_DMA 0xff
#define MAXLOOP 200000
unsigned int data_address PACKED; /* transfer data pointer */
unsigned int data_len PACKED; /* length in bytes */
unsigned int link_address PACKED; /* for linking command chains */
- unsigned char link_id; /* identifies command in chain */
+ unsigned char clink_id; /* identifies command in chain */
unsigned char use_sg; /* (if sg is set) 8 bytes per list */
unsigned char sense_len;
unsigned char scsi_cdbs_len; /* 6, 10, or 12 */
unsigned int sense_addr PACKED;
Scsi_Cmnd *SCpnt;
unsigned int index; /* cp index */
+ unsigned int link_id; /* reference cp for linked commands */
struct sg_list *sglist;
};
static int do_trace = FALSE;
static int setup_done = FALSE;
+#if defined (CONFIG_SCSI_U14_34F_LINKED_COMMANDS)
+static int linked_commands = TRUE;
+#else
+static int linked_commands = FALSE;
+#endif
+
+#if defined CONFIG_SCSI_U14_34F_MAX_TAGS
+static int max_queue_depth = CONFIG_SCSI_U14_34F_MAX_TAGS;
+#else
+static int max_queue_depth = MAX_CMD_PER_LUN;
+#endif
+
static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
Scsi_Device *dev;
int j, ntag = 0, nuntag = 0, tqd, utqd;
tqd = (host->can_queue - utqd * nuntag) / (ntag + 1);
- if (tqd > MAX_TAGGED_CMD_PER_LUN) tqd = MAX_TAGGED_CMD_PER_LUN;
+ if (tqd > max_queue_depth) tqd = max_queue_depth;
if (tqd < MAX_CMD_PER_LUN) tqd = MAX_CMD_PER_LUN;
Scsi_Host_Template *tpnt) {
unsigned char irq, dma_channel, subversion, i;
unsigned char in_byte;
- char dma_name[16];
+ char *bus_type, dma_name[16];
/* Allowed BIOS base addresses (NULL indicates reserved) */
void *bios_segment_table[8] = {
sh[j]->dma_channel = NO_DMA;
sh[j]->unchecked_isa_dma = FALSE;
sprintf(BN(j), "U34F%d", j);
+ bus_type = "VESA";
}
else {
sh[j]->wish_block = TRUE;
clear_dma_ff(dma_channel);
set_dma_mode(dma_channel, DMA_MODE_CASCADE);
enable_dma(dma_channel);
+ bus_type = "ISA";
}
sh[j]->max_channel = MAX_CHANNEL - 1;
return FALSE;
}
- printk("%s: PORT 0x%03x, BIOS 0x%05x, IRQ %u, %s, SG %d, "\
- "Mbox %d, UC %d.\n", BN(j), sh[j]->io_port,
- (int)sh[j]->base, sh[j]->irq, dma_name, sh[j]->sg_tablesize,
- sh[j]->can_queue, sh[j]->hostt->use_clustering);
+ if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
+ max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
+
+ if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
+
+ printk("%s: %s 0x%03x, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, UC %d, "\
+ "LC %d, MQ %d.\n", BN(j), bus_type, sh[j]->io_port, (int)sh[j]->base,
+ sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue,
+ sh[j]->hostt->use_clustering, linked_commands, max_queue_depth);
if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++;
if (j > 0)
- printk("UltraStor 14F/34F: Copyright (C) 1994, 1995, 1996 Dario Ballabio.\n");
+ printk("UltraStor 14F/34F: Copyright (C) 1994-1997 Dario Ballabio.\n");
restore_flags(flags);
return j;
cpp->scsi_cdbs_len = SCpnt->cmd_len;
memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_len);
+ if (linked_commands && SCpnt->device->tagged_supported
+ && !HD(j)->target_to[SCpnt->target][SCpnt->channel]
+ && !HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+
+ for (k = 0; k < sh[j]->can_queue; k++) {
+
+ if (HD(j)->cp_stat[k] != IN_USE) continue;
+
+ if ((&HD(j)->cp[k])->SCpnt->device != SCpnt->device) continue;
+
+ cpp->link_id = k;
+ HD(j)->cp_stat[i] = READY;
+
+#if defined (DEBUG_LINKED_COMMANDS)
+ printk("%s: qcomm, target %d.%d:%d, pid %ld, Mbox %d ready.\n",
+ BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
+ SCpnt->pid, i);
+#endif
+ restore_flags(flags);
+ return 0;
+ }
+
if (wait_on_busy(sh[j]->io_port)) {
SCpnt->result = DID_ERROR << 16;
SCpnt->host_scribble = NULL;
restore_flags(flags);
return SCSI_ABORT_NOT_RUNNING;
}
+
+ if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+ SCarg->result = DID_ABORT << 16;
+ SCarg->host_scribble = NULL;
+ HD(j)->cp_stat[i] = FREE;
+ printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
+ BN(j), i, SCarg->pid);
+ SCarg->scsi_done(SCarg);
+ restore_flags(flags);
+ return SCSI_ABORT_SUCCESS;
+ }
+
restore_flags(flags);
panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
}
continue;
}
- SCpnt = HD(j)->cp[i].SCpnt;
- HD(j)->cp_stat[i] = IN_RESET;
- printk("%s: reset, mbox %d in reset, pid %ld.\n",
- BN(j), i, SCpnt->pid);
-
- if (SCpnt == NULL)
+ if (!(SCpnt = HD(j)->cp[i].SCpnt))
panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
+ if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+ HD(j)->cp_stat[i] = ABORTING;
+ printk("%s: reset, mbox %d aborting, pid %ld.\n",
+ BN(j), i, SCpnt->pid);
+ }
+
+ else {
+ HD(j)->cp_stat[i] = IN_RESET;
+ printk("%s: reset, mbox %d in reset, pid %ld.\n",
+ BN(j), i, SCpnt->pid);
+ }
+
if (SCpnt->host_scribble == NULL)
panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
for (i = 0; i < sh[j]->can_queue; i++) {
- /* Skip mailboxes already set free by interrupt */
- if (HD(j)->cp_stat[i] != IN_RESET) continue;
+ if (HD(j)->cp_stat[i] == IN_RESET) {
+ SCpnt = HD(j)->cp[i].SCpnt;
+ SCpnt->result = DID_RESET << 16;
+ SCpnt->host_scribble = NULL;
- SCpnt = HD(j)->cp[i].SCpnt;
- SCpnt->result = DID_RESET << 16;
- SCpnt->host_scribble = NULL;
+ /* This mailbox is still waiting for its interrupt */
+ HD(j)->cp_stat[i] = LOCKED;
+
+ printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
+ BN(j), i, SCpnt->pid);
+ }
+
+ else if (HD(j)->cp_stat[i] == ABORTING) {
+ SCpnt = HD(j)->cp[i].SCpnt;
+ SCpnt->result = DID_RESET << 16;
+ SCpnt->host_scribble = NULL;
+
+ /* This mailbox was never queued to the adapter */
+ HD(j)->cp_stat[i] = FREE;
+
+ printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
+ BN(j), i, SCpnt->pid);
+ }
- /* This mailbox is still waiting for its interrupt */
- HD(j)->cp_stat[i] = LOCKED;
+ else
+
+ /* Any other mailbox has already been set free by interrupt */
+ continue;
- printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
- BN(j), i, SCpnt->pid);
restore_flags(flags);
SCpnt->scsi_done(SCpnt);
cli();
return FALSE;
}
+static inline void process_ready_list(unsigned int i, unsigned int j) {
+ Scsi_Cmnd *SCpnt;
+ unsigned int k, n_ready = 0;
+ struct mscp *cpp;
+
+ for (k = 0; k < sh[j]->can_queue; k++) {
+
+ if (HD(j)->cp_stat[k] != READY) continue;
+
+ cpp = &HD(j)->cp[k];
+
+ if (cpp->link_id != i) continue;
+
+ SCpnt = cpp->SCpnt;
+ n_ready++;
+
+ if (wait_on_busy(sh[j]->io_port)) {
+ printk("%s: ihdlr, target %d.%d:%d, pid %ld, Mbox %d, link_id %d, "\
+ "n_ready %d, adapter busy, will abort.\n", BN(j),
+ SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+ k, i, n_ready);
+ HD(j)->cp_stat[k] = ABORTING;
+ continue;
+ }
+
+ outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
+ outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
+ HD(j)->cp_stat[k] = IN_USE;
+
+#if defined (DEBUG_LINKED_COMMANDS)
+ printk("%s: ihdlr, target %d.%d:%d, pid %ld, Mbox %d in use, link_id %d,"
+ " n_ready %d.\n", BN(j), SCpnt->channel, SCpnt->target,
+ SCpnt->lun, SCpnt->pid, k, i, n_ready);
+#endif
+ }
+
+}
+
static void u14_34f_interrupt_handler(int irq, void *dev_id,
struct pt_regs *regs) {
Scsi_Cmnd *SCpnt;
unsigned long flags;
- unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0;
+ unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0, ret;
struct mscp *spp;
save_flags(flags);
if (do_trace) printk("%s: ihdlr, start service, count %d.\n",
BN(j), HD(j)->iocount);
- spp = (struct mscp *)DEV2V(inl(sh[j]->io_port + REG_ICM));
+ spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
/* Clear interrupt pending flag */
outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
i = spp - HD(j)->cp;
- if (i >= sh[j]->can_queue)
- panic("%s: ihdlr, invalid mscp address.\n", BN(j));
+ if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
+ || i >= sh[j]->can_queue)
+ panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n",
+ BN(j), (void *)ret, HD(j)->cp);
+
+ if (linked_commands) process_ready_list(i, j);
if (HD(j)->cp_stat[i] == IGNORE) {
HD(j)->cp_stat[i] = FREE;
int u14_34f_reset(Scsi_Cmnd *, unsigned int);
int u14_34f_biosparam(Disk *, kdev_t, int *);
-#define U14_34F_VERSION "2.40.00"
+#define U14_34F_VERSION "2.50.00"
#define ULTRASTOR_14_34F { \
NULL, /* Ptr for modules */ \
bool 'Quota support' CONFIG_QUOTA
tristate 'Minix fs support' CONFIG_MINIX_FS
-tristate 'Extended fs support' CONFIG_EXT_FS
tristate 'Second extended fs support' CONFIG_EXT2_FS
-tristate 'xiafs filesystem support' CONFIG_XIA_FS
# msdos filesystems
tristate 'DOS FAT fs support' CONFIG_FAT_FS
tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS
tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
tristate 'Amiga FFS filesystem support' CONFIG_AFFS_FS
+tristate 'ROM filesystem support' CONFIG_ROMFS_FS
if [ "$CONFIG_AFFS_FS" != "n" ]; then
define_bool CONFIG_AMIGA_PARTITION y
fi
bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL
fi
endmenu
+
dcache.o $(BINFMTS)
MOD_LIST_NAME := FS_MODULES
-ALL_SUB_DIRS = minix ext ext2 fat msdos vfat proc isofs nfs xiafs umsdos \
- hpfs sysv smbfs ncpfs ufs affs
+ALL_SUB_DIRS = minix ext2 fat msdos vfat proc isofs nfs umsdos \
+ hpfs sysv smbfs ncpfs ufs affs romfs
ifeq ($(CONFIG_QUOTA),y)
O_OBJS += dquot.o
endif
endif
-ifeq ($(CONFIG_EXT_FS),y)
-SUB_DIRS += ext
-else
- ifeq ($(CONFIG_EXT_FS),m)
- MOD_SUB_DIRS += ext
- endif
-endif
-
ifeq ($(CONFIG_EXT2_FS),y)
SUB_DIRS += ext2
else
endif
endif
-ifeq ($(CONFIG_XIA_FS),y)
-SUB_DIRS += xiafs
-else
- ifeq ($(CONFIG_XIA_FS),m)
- MOD_SUB_DIRS += xiafs
- endif
-endif
-
ifeq ($(CONFIG_UMSDOS_FS),y)
SUB_DIRS += umsdos
else
endif
endif
+ifeq ($(CONFIG_ROMFS_FS),y)
+SUB_DIRS += romfs
+else
+ ifeq ($(CONFIG_ROMFS_FS),m)
+ MOD_SUB_DIRS += romfs
+ endif
+endif
+
ifeq ($(CONFIG_BINFMT_ELF),y)
BINFMTS += binfmt_elf.o
else
unsigned long addr = vma->vm_start;
unsigned long len = vma->vm_end - vma->vm_start;
+ i++;
if (!maydump(vma))
continue;
- i++;
#ifdef DEBUG
printk("elf_core_dump: writing %08lx %lx\n", addr, len);
#endif
#include <linux/major.h>
#include <linux/string.h>
#include <linux/sched.h>
-#include <linux/ext_fs.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/errno.h>
+++ /dev/null
-#
-# Makefile for the linux ext-filesystem routines.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
-
-O_TARGET := ext.o
-O_OBJS := freelists.o truncate.o namei.o inode.o file.o dir.o \
- symlink.o fsync.o
-M_OBJS := $(O_TARGET)
-
-include $(TOPDIR)/Rules.make
+++ /dev/null
-/*
- * linux/fs/ext/dir.c
- *
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/dir.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * ext directory handling functions
- */
-
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-
-static long ext_dir_read(struct inode * inode, struct file * filp,
- char * buf, unsigned long count)
-{
- return -EISDIR;
-}
-
-static int ext_readdir(struct inode *, struct file *, void *, filldir_t);
-
-static struct file_operations ext_dir_operations = {
- NULL, /* lseek - default */
- ext_dir_read, /* read */
- NULL, /* write - bad */
- ext_readdir, /* readdir */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special release code */
- file_fsync /* fsync */
-};
-
-/*
- * directories can handle most operations...
- */
-struct inode_operations ext_dir_inode_operations = {
- &ext_dir_operations, /* default directory file-ops */
- ext_create, /* create */
- ext_lookup, /* lookup */
- ext_link, /* link */
- ext_unlink, /* unlink */
- ext_symlink, /* symlink */
- ext_mkdir, /* mkdir */
- ext_rmdir, /* rmdir */
- ext_mknod, /* mknod */
- ext_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* bmap */
- ext_truncate, /* truncate */
- NULL /* permission */
-};
-
-static int ext_readdir(struct inode * inode, struct file * filp,
- void * dirent, filldir_t filldir)
-{
- int error;
- unsigned int i;
- off_t offset;
- struct buffer_head * bh;
- struct ext_dir_entry * de;
-
- if (!inode || !S_ISDIR(inode->i_mode))
- return -EBADF;
- if ((filp->f_pos & 7) != 0)
- return -EBADF;
- error = 0;
- while (!error && filp->f_pos < inode->i_size) {
- offset = filp->f_pos & 1023;
- bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
- if (!bh) {
- filp->f_pos += 1024-offset;
- continue;
- }
- for (i = 0; i < 1024 && i < offset; ) {
- de = (struct ext_dir_entry *) (bh->b_data + i);
- if (!de->rec_len)
- break;
- i += de->rec_len;
- }
- offset = i;
- de = (struct ext_dir_entry *) (offset + bh->b_data);
- while (offset < 1024 && filp->f_pos < inode->i_size) {
- if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
- de->rec_len < de->name_len + 8 ||
- (de->rec_len + (off_t) filp->f_pos - 1) / 1024 > ((off_t) filp->f_pos / 1024)) {
- printk ("ext_readdir: bad dir entry, skipping\n");
- printk ("dev=%s, dir=%ld, "
- "offset=%ld, rec_len=%d, name_len=%d\n",
- kdevname(inode->i_dev), inode->i_ino,
- offset, de->rec_len, de->name_len);
- filp->f_pos += 1024-offset;
- if (filp->f_pos > inode->i_size)
- filp->f_pos = inode->i_size;
- continue;
- }
- if (de->inode) {
- error = filldir(dirent, de->name, de->name_len, filp->f_pos, de->inode);
- if (error)
- break;
- }
- offset += de->rec_len;
- filp->f_pos += de->rec_len;
- ((char *) de) += de->rec_len;
- }
- brelse(bh);
- }
- return 0;
-}
+++ /dev/null
-/*
- * linux/fs/ext/file.c
- *
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/file.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * ext regular file handling primitives
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/pagemap.h>
-
-#define NBUF 32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-
-static long ext_file_read(struct inode *, struct file *, char *, unsigned long);
-static long ext_file_write(struct inode *, struct file *, const char *, unsigned long);
-
-/*
- * We have mostly NULL's here: the current defaults are ok for
- * the ext filesystem.
- */
-static struct file_operations ext_file_operations = {
- NULL, /* lseek - default */
- ext_file_read, /* read */
- ext_file_write, /* write */
- NULL, /* readdir - bad */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- generic_file_mmap, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* release */
- ext_sync_file /* fsync */
-};
-
-struct inode_operations ext_file_inode_operations = {
- &ext_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- generic_readpage, /* readpage */
- NULL, /* writepage */
- ext_bmap, /* bmap */
- ext_truncate, /* truncate */
- NULL /* permission */
-};
-
-static long ext_file_read(struct inode * inode, struct file * filp,
- char * buf, unsigned long count)
-{
- int read,left,chars;
- int block, blocks, offset;
- int bhrequest, uptodate;
- struct buffer_head ** bhb, ** bhe;
- struct buffer_head * bhreq[NBUF];
- struct buffer_head * buflist[NBUF];
- unsigned int size;
-
- if (!inode) {
- printk("ext_file_read: inode = NULL\n");
- return -EINVAL;
- }
- if (!S_ISREG(inode->i_mode)) {
- printk("ext_file_read: mode = %07o\n",inode->i_mode);
- return -EINVAL;
- }
- offset = filp->f_pos;
- size = inode->i_size;
- if (offset > size)
- left = 0;
- else
- left = size - offset;
- if (left > count)
- left = count;
- if (left <= 0)
- return 0;
- read = 0;
- block = offset >> BLOCK_SIZE_BITS;
- offset &= BLOCK_SIZE-1;
- size = (size + (BLOCK_SIZE-1)) >> BLOCK_SIZE_BITS;
- blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
- bhb = bhe = buflist;
- if (filp->f_reada) {
- if(blocks < read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9))
- blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
- if (block + blocks > size)
- blocks = size - block;
- }
-
- /* We do this in a two stage process. We first try to request
- as many blocks as we can, then we wait for the first one to
- complete, and then we try to wrap up as many as are actually
- done. This routine is rather generic, in that it can be used
- in a filesystem by substituting the appropriate function in
- for getblk.
-
- This routine is optimized to make maximum use of the various
- buffers and caches. */
-
- do {
- bhrequest = 0;
- uptodate = 1;
- while (blocks) {
- --blocks;
- *bhb = ext_getblk(inode, block++, 0);
- if (*bhb && !buffer_uptodate(*bhb)) {
- uptodate = 0;
- bhreq[bhrequest++] = *bhb;
- }
-
- if (++bhb == &buflist[NBUF])
- bhb = buflist;
-
- /* If the block we have on hand is uptodate, go ahead
- and complete processing. */
- if (uptodate)
- break;
- if (bhb == bhe)
- break;
- }
-
- /* Now request them all */
- if (bhrequest)
- ll_rw_block(READ, bhrequest, bhreq);
-
- do { /* Finish off all I/O that has actually completed */
- if (*bhe) {
- wait_on_buffer(*bhe);
- if (!buffer_uptodate(*bhe)) { /* read error? */
- brelse(*bhe);
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- left = 0;
- break;
- }
- }
- if (left < BLOCK_SIZE - offset)
- chars = left;
- else
- chars = BLOCK_SIZE - offset;
- filp->f_pos += chars;
- left -= chars;
- read += chars;
- if (*bhe) {
- copy_to_user(buf,offset+(*bhe)->b_data,chars);
- brelse(*bhe);
- buf += chars;
- } else {
- while (chars-->0)
- put_user(0,buf++);
- }
- offset = 0;
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
- } while (left > 0);
-
-/* Release the read-ahead blocks */
- while (bhe != bhb) {
- brelse(*bhe);
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- };
- if (!read)
- return -EIO;
- filp->f_reada = 1;
- if (!IS_RDONLY(inode)) {
- inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- }
- return read;
-}
-
-static long ext_file_write(struct inode * inode, struct file * filp,
- const char * buf, unsigned long count)
-{
- off_t pos;
- int written,c;
- struct buffer_head * bh;
- char * p;
-
- if (!inode) {
- printk("ext_file_write: inode = NULL\n");
- return -EINVAL;
- }
- if (!S_ISREG(inode->i_mode)) {
- printk("ext_file_write: mode = %07o\n",inode->i_mode);
- return -EINVAL;
- }
-/*
- * ok, append may not work when many processes are writing at the same time
- * but so what. That way leads to madness anyway.
- */
- if (filp->f_flags & O_APPEND)
- pos = inode->i_size;
- else
- pos = filp->f_pos;
- written = 0;
- while (written<count) {
- bh = ext_getblk(inode,pos/BLOCK_SIZE,1);
- if (!bh) {
- if (!written)
- written = -ENOSPC;
- break;
- }
- c = BLOCK_SIZE - (pos % BLOCK_SIZE);
- if (c > count-written)
- c = count-written;
- if (c != BLOCK_SIZE && !buffer_uptodate(bh)) {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- if (!written)
- written = -EIO;
- break;
- }
- }
- p = (pos % BLOCK_SIZE) + bh->b_data;
- copy_from_user(p,buf,c);
- update_vm_cache(inode, pos, p, c);
- pos += c;
- if (pos > inode->i_size) {
- inode->i_size = pos;
- inode->i_dirt = 1;
- }
- written += c;
- buf += c;
- mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh, 0);
- brelse(bh);
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- filp->f_pos = pos;
- inode->i_dirt = 1;
- return written;
-}
+++ /dev/null
-/*
- * linux/fs/ext/freelists.c
- *
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- */
-
-/* freelists.c contains the code that handles the inode and block free lists */
-
-
-/*
-
- The free blocks are managed by a linked list. The super block contains the
- number of the first free block. This block contains 254 numbers of other
- free blocks and the number of the next block in the list.
-
- When an ext fs is mounted, the number of the first free block is stored
- in s->u.ext_sb.s_firstfreeblocknumber and the block header is stored in
- s->u.ext_sb.s_firstfreeblock. u.ext_sb.s_freeblockscount contains the count
- of free blocks.
-
- The free inodes are also managed by a linked list in a similar way. The
- super block contains the number of the first free inode. This inode contains
- 14 numbers of other free inodes and the number of the next inode in the list.
-
- The number of the first free inode is stored in
- s->u.ext_sb.s_firstfreeinodenumber and the header of the block containing
- the inode is stored in s->u.ext_sb.s_firstfreeinodeblock.
- u.ext_sb.s_freeinodescount contains the count of free inodes.
-
-*/
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-
-void ext_free_block(struct super_block * sb, int block)
-{
- struct buffer_head * bh;
- struct ext_free_block * efb;
-
- if (!sb) {
- printk("trying to free block on non-existent device\n");
- return;
- }
- lock_super (sb);
- if (block < sb->u.ext_sb.s_firstdatazone ||
- block >= sb->u.ext_sb.s_nzones) {
- printk("trying to free block not in datazone\n");
- return;
- }
- bh = get_hash_table(sb->s_dev, block, sb->s_blocksize);
- if (bh)
- mark_buffer_clean(bh);
- brelse(bh);
- if (sb->u.ext_sb.s_firstfreeblock)
- efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
- if (!sb->u.ext_sb.s_firstfreeblock || efb->count == 254) {
-#ifdef EXTFS_DEBUG
-printk("ext_free_block: block full, skipping to %d\n", block);
-#endif
- if (sb->u.ext_sb.s_firstfreeblock)
- brelse (sb->u.ext_sb.s_firstfreeblock);
- if (!(sb->u.ext_sb.s_firstfreeblock = bread (sb->s_dev,
- block, sb->s_blocksize)))
- panic ("ext_free_block: unable to read block to free\n");
- efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
- efb->next = sb->u.ext_sb.s_firstfreeblocknumber;
- efb->count = 0;
- sb->u.ext_sb.s_firstfreeblocknumber = block;
- } else {
- efb->free[efb->count++] = block;
- }
- sb->u.ext_sb.s_freeblockscount ++;
- sb->s_dirt = 1;
- mark_buffer_dirty(sb->u.ext_sb.s_firstfreeblock, 1);
- unlock_super (sb);
- return;
-}
-
-int ext_new_block(struct super_block * sb)
-{
- struct buffer_head * bh;
- struct ext_free_block * efb;
- int j;
-
- if (!sb) {
- printk("trying to get new block from non-existent device\n");
- return 0;
- }
- if (!sb->u.ext_sb.s_firstfreeblock)
- return 0;
- lock_super (sb);
- efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
- if (efb->count) {
- j = efb->free[--efb->count];
- mark_buffer_dirty(sb->u.ext_sb.s_firstfreeblock, 1);
- } else {
-#ifdef EXTFS_DEBUG
-printk("ext_new_block: block empty, skipping to %d\n", efb->next);
-#endif
- j = sb->u.ext_sb.s_firstfreeblocknumber;
- sb->u.ext_sb.s_firstfreeblocknumber = efb->next;
- brelse (sb->u.ext_sb.s_firstfreeblock);
- if (!sb->u.ext_sb.s_firstfreeblocknumber) {
- sb->u.ext_sb.s_firstfreeblock = NULL;
- } else {
- if (!(sb->u.ext_sb.s_firstfreeblock = bread (sb->s_dev,
- sb->u.ext_sb.s_firstfreeblocknumber,
- sb->s_blocksize)))
- panic ("ext_new_block: unable to read next free block\n");
- }
- }
- if (j < sb->u.ext_sb.s_firstdatazone || j > sb->u.ext_sb.s_nzones) {
- printk ("ext_new_block: blk = %d\n", j);
- printk("allocating block not in data zone\n");
- return 0;
- }
- sb->u.ext_sb.s_freeblockscount --;
- sb->s_dirt = 1;
-
- if (!(bh=getblk(sb->s_dev, j, sb->s_blocksize))) {
- printk("new_block: cannot get block");
- return 0;
- }
- memset(bh->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh, 1);
- brelse(bh);
-#ifdef EXTFS_DEBUG
-printk("ext_new_block: allocating block %d\n", j);
-#endif
- unlock_super (sb);
- return j;
-}
-
-unsigned long ext_count_free_blocks(struct super_block *sb)
-{
-#ifdef EXTFS_DEBUG
- struct buffer_head * bh;
- struct ext_free_block * efb;
- unsigned long count, block;
-
- lock_super (sb);
- if (!sb->u.ext_sb.s_firstfreeblock)
- count = 0;
- else {
- efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
- count = efb->count + 1;
- block = efb->next;
- while (block) {
- if (!(bh = bread (sb->s_dev, block, sb->s_blocksize))) {
- printk ("ext_count_free: error while reading free blocks list\n");
- block = 0;
- } else {
- efb = (struct ext_free_block *) bh->b_data;
- count += efb->count + 1;
- block = efb->next;
- brelse (bh);
- }
- }
- }
-printk("ext_count_free_blocks: stored = %d, computed = %d\n",
- sb->u.ext_sb.s_freeblockscount, count);
- unlock_super (sb);
- return count;
-#else
- return sb->u.ext_sb.s_freeblockscount;
-#endif
-}
-
-void ext_free_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- struct ext_free_inode * efi;
- struct super_block * sb;
- unsigned long block;
- unsigned long ino;
- kdev_t dev;
-
- if (!inode)
- return;
- if (!inode->i_dev) {
- printk("free_inode: inode has no device\n");
- return;
- }
- if (inode->i_count != 1) {
- printk("free_inode: inode has count=%d\n",inode->i_count);
- return;
- }
- if (inode->i_nlink) {
- printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
- return;
- }
- if (!inode->i_sb) {
- printk("free_inode: inode on non-existent device\n");
- return;
- }
- sb = inode->i_sb;
- ino = inode->i_ino;
- dev = inode->i_dev;
- clear_inode(inode);
- lock_super (sb);
- if (ino < 1 || ino > sb->u.ext_sb.s_ninodes) {
- printk("free_inode: inode 0 or non-existent inode\n");
- unlock_super (sb);
- return;
- }
- if (sb->u.ext_sb.s_firstfreeinodeblock)
- efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
- (sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
- if (!sb->u.ext_sb.s_firstfreeinodeblock || efi->count == 14) {
-#ifdef EXTFS_DEBUG
-printk("ext_free_inode: inode full, skipping to %d\n", ino);
-#endif
- if (sb->u.ext_sb.s_firstfreeinodeblock)
- brelse (sb->u.ext_sb.s_firstfreeinodeblock);
- block = 2 + (ino - 1) / EXT_INODES_PER_BLOCK;
- if (!(bh = bread(dev, block, sb->s_blocksize)))
- panic("ext_free_inode: unable to read inode block\n");
- efi = ((struct ext_free_inode *) bh->b_data) +
- (ino - 1) % EXT_INODES_PER_BLOCK;
- efi->next = sb->u.ext_sb.s_firstfreeinodenumber;
- efi->count = 0;
- sb->u.ext_sb.s_firstfreeinodenumber = ino;
- sb->u.ext_sb.s_firstfreeinodeblock = bh;
- } else {
- efi->free[efi->count++] = ino;
- }
- sb->u.ext_sb.s_freeinodescount ++;
- sb->s_dirt = 1;
- mark_buffer_dirty(sb->u.ext_sb.s_firstfreeinodeblock, 1);
- unlock_super (sb);
-}
-
-struct inode * ext_new_inode(const struct inode * dir)
-{
- struct super_block * sb;
- struct inode * inode;
- struct ext_free_inode * efi;
- unsigned long block;
- int j;
-
- if (!dir || !(inode=get_empty_inode()))
- return NULL;
- sb = dir->i_sb;
- inode->i_sb = sb;
- inode->i_flags = sb->s_flags;
- if (!sb->u.ext_sb.s_firstfreeinodeblock)
- return 0;
- lock_super (sb);
- efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
- (sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
- if (efi->count) {
- j = efi->free[--efi->count];
- mark_buffer_dirty(sb->u.ext_sb.s_firstfreeinodeblock, 1);
- } else {
-#ifdef EXTFS_DEBUG
-printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
-#endif
- j = sb->u.ext_sb.s_firstfreeinodenumber;
- if (efi->next > sb->u.ext_sb.s_ninodes) {
- printk ("efi->next = %ld\n", efi->next);
- panic ("ext_new_inode: bad inode number in free list\n");
- }
- sb->u.ext_sb.s_firstfreeinodenumber = efi->next;
- block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK;
- brelse (sb->u.ext_sb.s_firstfreeinodeblock);
- if (!sb->u.ext_sb.s_firstfreeinodenumber) {
- sb->u.ext_sb.s_firstfreeinodeblock = NULL;
- } else {
- if (!(sb->u.ext_sb.s_firstfreeinodeblock =
- bread(sb->s_dev, block, sb->s_blocksize)))
- panic ("ext_new_inode: unable to read next free inode block\n");
- }
- }
- sb->u.ext_sb.s_freeinodescount --;
- sb->s_dirt = 1;
- inode->i_count = 1;
- inode->i_nlink = 1;
- inode->i_dev = sb->s_dev;
- inode->i_uid = current->fsuid;
- inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
- inode->i_dirt = 1;
- inode->i_ino = j;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- inode->i_op = NULL;
- inode->i_blocks = inode->i_blksize = 0;
- insert_inode_hash(inode);
-#ifdef EXTFS_DEBUG
-printk("ext_new_inode : allocating inode %d\n", inode->i_ino);
-#endif
- unlock_super (sb);
- return inode;
-}
-
-unsigned long ext_count_free_inodes(struct super_block *sb)
-{
-#ifdef EXTFS_DEBUG
- struct buffer_head * bh;
- struct ext_free_inode * efi;
- unsigned long count, block, ino;
-
- lock_super (sb);
- if (!sb->u.ext_sb.s_firstfreeinodeblock)
- count = 0;
- else {
- efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
- ((sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK);
- count = efi->count + 1;
- ino = efi->next;
- while (ino) {
- if (ino < 1 || ino > sb->u.ext_sb.s_ninodes) {
- printk ("u.ext_sb.s_firstfreeinodenumber = %d, ino = %d\n",
- (int) sb->u.ext_sb.s_firstfreeinodenumber,ino);
- panic ("ext_count_fre_inodes: bad inode number in free list\n");
- }
- block = 2 + ((ino - 1) / EXT_INODES_PER_BLOCK);
- if (!(bh = bread (sb->s_dev, block, sb->s_blocksize))) {
- printk ("ext_count_free_inodes: error while reading free inodes list\n");
- block = 0;
- } else {
- efi = ((struct ext_free_inode *) bh->b_data) +
- ((ino - 1) % EXT_INODES_PER_BLOCK);
- count += efi->count + 1;
- ino = efi->next;
- brelse (bh);
- }
- }
- }
-printk("ext_count_free_inodes: stored = %d, computed = %d\n",
- sb->u.ext_sb.s_freeinodescount, count);
- unlock_super (sb);
- return count;
-#else
- return sb->u.ext_sb.s_freeinodescount;
-#endif
-}
+++ /dev/null
-
-/*
- * linux/fs/ext/fsync.c
- *
- * Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
- * from
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- * from
- * linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds
- *
- * extfs fsync primitive
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/locks.h>
-
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-
-
-#define blocksize BLOCK_SIZE
-#define addr_per_block 256
-
-static int sync_block (struct inode * inode, unsigned long * block, int wait)
-{
- struct buffer_head * bh;
- int tmp;
-
- if (!*block)
- return 0;
- tmp = *block;
- bh = get_hash_table(inode->i_dev, *block, blocksize);
- if (!bh)
- return 0;
- if (*block != tmp) {
- brelse (bh);
- return 1;
- }
- if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- brelse(bh);
- return -1;
- }
- if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
- {
- brelse(bh);
- return 0;
- }
- ll_rw_block(WRITE, 1, &bh);
- bh->b_count--;
- return 0;
-}
-
-static int sync_iblock (struct inode * inode, unsigned long * iblock,
- struct buffer_head **bh, int wait)
-{
- int rc, tmp;
-
- *bh = NULL;
- tmp = *iblock;
- if (!tmp)
- return 0;
- rc = sync_block (inode, iblock, wait);
- if (rc)
- return rc;
- *bh = bread(inode->i_dev, tmp, blocksize);
- if (tmp != *iblock) {
- brelse(*bh);
- *bh = NULL;
- return 1;
- }
- if (!*bh)
- return -1;
- return 0;
-}
-
-
-static int sync_direct(struct inode *inode, int wait)
-{
- int i;
- int rc, err = 0;
-
- for (i = 0; i < 9; i++) {
- rc = sync_block (inode, inode->u.ext_i.i_data + i, wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- return err;
-}
-
-static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
-{
- int i;
- struct buffer_head * ind_bh;
- int rc, err = 0;
-
- rc = sync_iblock (inode, iblock, &ind_bh, wait);
- if (rc || !ind_bh)
- return rc;
-
- for (i = 0; i < addr_per_block; i++) {
- rc = sync_block (inode,
- ((unsigned long *) ind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(ind_bh);
- return err;
-}
-
-static int sync_dindirect(struct inode *inode, unsigned long *diblock,
- int wait)
-{
- int i;
- struct buffer_head * dind_bh;
- int rc, err = 0;
-
- rc = sync_iblock (inode, diblock, &dind_bh, wait);
- if (rc || !dind_bh)
- return rc;
-
- for (i = 0; i < addr_per_block; i++) {
- rc = sync_indirect (inode,
- ((unsigned long *) dind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(dind_bh);
- return err;
-}
-
-static int sync_tindirect(struct inode *inode, unsigned long *tiblock,
- int wait)
-{
- int i;
- struct buffer_head * tind_bh;
- int rc, err = 0;
-
- rc = sync_iblock (inode, tiblock, &tind_bh, wait);
- if (rc || !tind_bh)
- return rc;
-
- for (i = 0; i < addr_per_block; i++) {
- rc = sync_dindirect (inode,
- ((unsigned long *) tind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(tind_bh);
- return err;
-}
-
-int ext_sync_file(struct inode * inode, struct file *file)
-{
- int wait, err = 0;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return -EINVAL;
- for (wait=0; wait<=1; wait++)
- {
- err |= sync_direct(inode, wait);
- err |= sync_indirect(inode, inode->u.ext_i.i_data+9, wait);
- err |= sync_dindirect(inode, inode->u.ext_i.i_data+10, wait);
- err |= sync_tindirect(inode, inode->u.ext_i.i_data+11, wait);
- }
- err |= ext_sync_inode (inode);
- return (err < 0) ? -EIO : 0;
-}
+++ /dev/null
-/*
- * linux/fs/ext/inode.c
- *
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/inode.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-void ext_put_inode(struct inode *inode)
-{
- if (inode->i_nlink)
- return;
- inode->i_size = 0;
- ext_truncate(inode);
- ext_free_inode(inode);
-}
-
-void ext_put_super(struct super_block *sb)
-{
-
- lock_super(sb);
- sb->s_dev = 0;
- if (sb->u.ext_sb.s_firstfreeinodeblock)
- brelse (sb->u.ext_sb.s_firstfreeinodeblock);
- if (sb->u.ext_sb.s_firstfreeblock)
- brelse (sb->u.ext_sb.s_firstfreeblock);
- unlock_super(sb);
- MOD_DEC_USE_COUNT;
- return;
-}
-
-static struct super_operations ext_sops = {
- ext_read_inode,
- NULL,
- ext_write_inode,
- ext_put_inode,
- ext_put_super,
- ext_write_super,
- ext_statfs,
- NULL
-};
-
-struct super_block *ext_read_super(struct super_block *s,void *data,
- int silent)
-{
- struct buffer_head *bh;
- struct ext_super_block *es;
- kdev_t dev = s->s_dev;
- int block;
-
- MOD_INC_USE_COUNT;
- lock_super(s);
- set_blocksize(dev, BLOCK_SIZE);
- if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
- s->s_dev = 0;
- unlock_super(s);
- printk("EXT-fs: unable to read superblock\n");
- MOD_DEC_USE_COUNT;
- return NULL;
- }
- es = (struct ext_super_block *) bh->b_data;
- s->s_blocksize = 1024;
- s->s_blocksize_bits = 10;
- s->u.ext_sb.s_ninodes = es->s_ninodes;
- s->u.ext_sb.s_nzones = es->s_nzones;
- s->u.ext_sb.s_firstdatazone = es->s_firstdatazone;
- s->u.ext_sb.s_log_zone_size = es->s_log_zone_size;
- s->u.ext_sb.s_max_size = es->s_max_size;
- s->s_magic = es->s_magic;
- s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock;
- s->u.ext_sb.s_freeblockscount = es->s_freeblockscount;
- s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode;
- s->u.ext_sb.s_freeinodescount = es->s_freeinodescount;
- brelse(bh);
- if (s->s_magic != EXT_SUPER_MAGIC) {
- s->s_dev = 0;
- unlock_super(s);
- if (!silent)
- printk("VFS: Can't find an extfs filesystem on dev "
- "%s.\n", kdevname(dev));
- MOD_DEC_USE_COUNT;
- return NULL;
- }
- if (!s->u.ext_sb.s_firstfreeblocknumber)
- s->u.ext_sb.s_firstfreeblock = NULL;
- else
- if (!(s->u.ext_sb.s_firstfreeblock = bread(dev,
- s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) {
- printk("ext_read_super: unable to read first free block\n");
- s->s_dev = 0;
- unlock_super(s);
- MOD_DEC_USE_COUNT;
- return NULL;
- }
- if (!s->u.ext_sb.s_firstfreeinodenumber)
- s->u.ext_sb.s_firstfreeinodeblock = NULL;
- else {
- block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK;
- if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) {
- printk("ext_read_super: unable to read first free inode block\n");
- brelse(s->u.ext_sb.s_firstfreeblock);
- s->s_dev = 0;
- unlock_super (s);
- MOD_DEC_USE_COUNT;
- return NULL;
- }
- }
- unlock_super(s);
- /* set up enough so that it can read an inode */
- s->s_dev = dev;
- s->s_op = &ext_sops;
- if (!(s->s_mounted = iget(s,EXT_ROOT_INO))) {
- s->s_dev = 0;
- printk("EXT-fs: get root inode failed\n");
- MOD_DEC_USE_COUNT;
- return NULL;
- }
- return s;
-}
-
-void ext_write_super (struct super_block *sb)
-{
- struct buffer_head * bh;
- struct ext_super_block * es;
-
- if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) {
- printk ("ext_write_super: bread failed\n");
- return;
- }
- es = (struct ext_super_block *) bh->b_data;
- es->s_firstfreeblock = sb->u.ext_sb.s_firstfreeblocknumber;
- es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
- es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
- es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
- mark_buffer_dirty(bh, 1);
- brelse (bh);
- sb->s_dirt = 0;
-}
-
-void ext_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
-{
- struct statfs tmp;
-
- tmp.f_type = EXT_SUPER_MAGIC;
- tmp.f_bsize = 1024;
- tmp.f_blocks = sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size;
- tmp.f_bfree = ext_count_free_blocks(sb);
- tmp.f_bavail = tmp.f_bfree;
- tmp.f_files = sb->u.ext_sb.s_ninodes;
- tmp.f_ffree = ext_count_free_inodes(sb);
- tmp.f_namelen = EXT_NAME_LEN;
- copy_to_user(buf, &tmp, bufsiz);
-}
-
-#define inode_bmap(inode,nr) ((inode)->u.ext_i.i_data[(nr)])
-
-static inline int block_bmap(struct buffer_head * bh, int nr)
-{
- int tmp;
-
- if (!bh)
- return 0;
- tmp = ((unsigned long *) bh->b_data)[nr];
- brelse(bh);
- return tmp;
-}
-
-int ext_bmap(struct inode * inode,int block)
-{
- int i;
-
- if (block<0) {
- printk("ext_bmap: block<0");
- return 0;
- }
- if (block >= 9+256+256*256+256*256*256) {
- printk("ext_bmap: block>big");
- return 0;
- }
- if (block<9)
- return inode_bmap(inode,block);
- block -= 9;
- if (block<256) {
- i = inode_bmap(inode,9);
- if (!i)
- return 0;
- return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
- }
- block -= 256;
- if (block<256*256) {
- i = inode_bmap(inode,10);
- if (!i)
- return 0;
- i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>8);
- if (!i)
- return 0;
- return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
- }
- block -= 256*256;
- i = inode_bmap(inode,11);
- if (!i)
- return 0;
- i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>16);
- if (!i)
- return 0;
- i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block>>8) & 255);
- if (!i)
- return 0;
- return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
-}
-
-static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
-{
- int tmp;
- unsigned long * p;
- struct buffer_head * result;
-
- p = inode->u.ext_i.i_data + nr;
-repeat:
- tmp = *p;
- if (tmp) {
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp == *p)
- return result;
- brelse(result);
- goto repeat;
- }
- if (!create)
- return NULL;
- tmp = ext_new_block(inode->i_sb);
- if (!tmp)
- return NULL;
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (*p) {
- ext_free_block(inode->i_sb,tmp);
- brelse(result);
- goto repeat;
- }
- *p = tmp;
- inode->i_ctime = CURRENT_TIME;
- inode->i_dirt = 1;
- return result;
-}
-
-static struct buffer_head * block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int create)
-{
- int tmp;
- unsigned long * p;
- struct buffer_head * result;
-
- if (!bh)
- return NULL;
- if (!buffer_uptodate(bh)) {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- return NULL;
- }
- }
- p = nr + (unsigned long *) bh->b_data;
-repeat:
- tmp = *p;
- if (tmp) {
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (tmp == *p) {
- brelse(bh);
- return result;
- }
- brelse(result);
- goto repeat;
- }
- if (!create) {
- brelse(bh);
- return NULL;
- }
- tmp = ext_new_block(inode->i_sb);
- if (!tmp) {
- brelse(bh);
- return NULL;
- }
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (*p) {
- ext_free_block(inode->i_sb,tmp);
- brelse(result);
- goto repeat;
- }
- *p = tmp;
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- return result;
-}
-
-struct buffer_head * ext_getblk(struct inode * inode, int block, int create)
-{
- struct buffer_head * bh;
-
- if (block<0) {
- printk("ext_getblk: block<0\n");
- return NULL;
- }
- if (block >= 9+256+256*256+256*256*256) {
- printk("ext_getblk: block>big\n");
- return NULL;
- }
- if (block<9)
- return inode_getblk(inode,block,create);
- block -= 9;
- if (block<256) {
- bh = inode_getblk(inode,9,create);
- return block_getblk(inode,bh,block,create);
- }
- block -= 256;
- if (block<256*256) {
- bh = inode_getblk(inode,10,create);
- bh = block_getblk(inode,bh,block>>8,create);
- return block_getblk(inode,bh,block & 255,create);
- }
- block -= 256*256;
- bh = inode_getblk(inode,11,create);
- bh = block_getblk(inode,bh,block>>16,create);
- bh = block_getblk(inode,bh,(block>>8) & 255,create);
- return block_getblk(inode,bh,block & 255,create);
-}
-
-struct buffer_head * ext_bread(struct inode * inode, int block, int create)
-{
- struct buffer_head * bh;
-
- bh = ext_getblk(inode,block,create);
- if (!bh || buffer_uptodate(bh))
- return bh;
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (buffer_uptodate(bh))
- return bh;
- brelse(bh);
- return NULL;
-}
-
-void ext_read_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- struct ext_inode * raw_inode;
- int block;
-
- block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
- if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
- panic("unable to read i-node block");
- raw_inode = ((struct ext_inode *) bh->b_data) +
- (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
- inode->i_mode = raw_inode->i_mode;
- inode->i_uid = raw_inode->i_uid;
- inode->i_gid = raw_inode->i_gid;
- inode->i_nlink = raw_inode->i_nlinks;
- inode->i_size = raw_inode->i_size;
- inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
- inode->i_blocks = inode->i_blksize = 0;
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
- else for (block = 0; block < 12; block++)
- inode->u.ext_i.i_data[block] = raw_inode->i_zone[block];
- brelse(bh);
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &ext_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
- inode->i_op = &ext_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &ext_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
-}
-
-static struct buffer_head * ext_update_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- struct ext_inode * raw_inode;
- int block;
-
- block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
- if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
- panic("unable to read i-node block");
- raw_inode = ((struct ext_inode *)bh->b_data) +
- (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
- raw_inode->i_mode = inode->i_mode;
- raw_inode->i_uid = inode->i_uid;
- raw_inode->i_gid = inode->i_gid;
- raw_inode->i_nlinks = inode->i_nlink;
- raw_inode->i_size = inode->i_size;
- raw_inode->i_time = inode->i_mtime;
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
- else for (block = 0; block < 12; block++)
- raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
- mark_buffer_dirty(bh, 1);
- inode->i_dirt=0;
- return bh;
-}
-
-void ext_write_inode(struct inode * inode)
-{
- struct buffer_head *bh;
- bh = ext_update_inode (inode);
- brelse(bh);
-}
-
-int ext_sync_inode (struct inode *inode)
-{
- int err = 0;
- struct buffer_head *bh;
-
- bh = ext_update_inode(inode);
- if (bh && buffer_dirty(bh))
- {
- ll_rw_block(WRITE, 1, &bh);
- wait_on_buffer(bh);
- if (buffer_req(bh) && !buffer_uptodate(bh))
- {
- printk ("IO error syncing ext inode ["
- "%s:%08lx]\n",
- kdevname(inode->i_dev), inode->i_ino);
- err = -1;
- }
- }
- else if (!bh)
- err = -1;
- brelse (bh);
- return err;
-}
-
-
-static struct file_system_type ext_fs_type = {
- ext_read_super, "ext", 1, NULL
-};
-
-int init_ext_fs(void)
-{
- return register_filesystem(&ext_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
- return init_ext_fs();
-}
-
-void cleanup_module(void)
-{
- unregister_filesystem(&ext_fs_type);
-}
-
-#endif
+++ /dev/null
-/*
- * linux/fs/ext/namei.c
- *
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/namei.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-#include <asm/uaccess.h>
-
-/*
- * comment out this line if you want names > EXT_NAME_LEN chars to be
- * truncated. Else they will be disallowed.
- */
-/* #define NO_TRUNCATE */
-
-/*
- * EXT_DIR_PAD defines the directory entries boundaries
- *
- * NOTE: It must be a power of 2 and must be greater or equal than 8
- * because a directory entry needs 8 bytes for its fixed part
- * (4 bytes for the inode, 2 bytes for the entry length and 2 bytes
- * for the name length)
- */
-#define EXT_DIR_PAD 8
-
-/*
- *
- * EXT_DIR_MIN_SIZE is the minimal size of a directory entry
- *
- * During allocations, a directory entry is split into 2 ones
- * *ONLY* if the size of the unused part is greater than or
- * equal to EXT_DIR_MIN_SIZE
- */
-#define EXT_DIR_MIN_SIZE 12
-
-/*
- * ok, we cannot use strncmp, as the name is not in our data space.
- * Thus we'll have to use ext_match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, ext_match returns 1 for success, 0 for failure.
- */
-static int ext_match(int len,const char * name,struct ext_dir_entry * de)
-{
- if (!de || !de->inode || len > EXT_NAME_LEN)
- return 0;
- /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
- if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
- return 1;
- if (len != de->name_len)
- return 0;
- return !memcmp(name, de->name, len);
-}
-
-/*
- * ext_find_entry()
- *
- * finds an entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_dir). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
- *
- * addition for the ext file system : this function returns the previous
- * and next directory entries in the parameters prev_dir and next_dir
- */
-static struct buffer_head * ext_find_entry(struct inode * dir,
- const char * name, int namelen, struct ext_dir_entry ** res_dir,
- struct ext_dir_entry ** prev_dir, struct ext_dir_entry ** next_dir)
-{
- long offset;
- struct buffer_head * bh;
- struct ext_dir_entry * de;
-
- *res_dir = NULL;
- if (!dir)
- return NULL;
-#ifdef NO_TRUNCATE
- if (namelen > EXT_NAME_LEN)
- return NULL;
-#else
- if (namelen > EXT_NAME_LEN)
- namelen = EXT_NAME_LEN;
-#endif
- bh = ext_bread(dir,0,0);
- if (!bh)
- return NULL;
- if (prev_dir)
- *prev_dir = NULL;
- if (next_dir)
- *next_dir = NULL;
- offset = 0;
- de = (struct ext_dir_entry *) bh->b_data;
- while (offset < dir->i_size) {
- if ((char *)de >= BLOCK_SIZE+bh->b_data) {
- brelse(bh);
- bh = NULL;
- bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,0);
- if (!bh)
- continue;
- de = (struct ext_dir_entry *) bh->b_data;
- if (prev_dir)
- *prev_dir = NULL;
- }
- if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
- de->rec_len < de->name_len + 8 ||
- (((char *) de) + de->rec_len-1 >= BLOCK_SIZE+bh->b_data)) {
- printk ("ext_find_entry: bad dir entry\n");
- printk ("dev=%s, dir=%ld, offset=%ld, "
- "rec_len=%d, name_len=%d\n",
- kdevname(dir->i_dev), dir->i_ino, offset,
- de->rec_len, de->name_len);
- de = (struct ext_dir_entry *) (bh->b_data+BLOCK_SIZE);
- offset = ((offset / BLOCK_SIZE) + 1) * BLOCK_SIZE;
- continue;
-/* brelse (bh);
- return NULL; */
- }
- if (ext_match(namelen,name,de)) {
- *res_dir = de;
- if (next_dir)
- if (offset + de->rec_len < dir->i_size &&
- ((char *)de) + de->rec_len < BLOCK_SIZE+bh->b_data)
- *next_dir = (struct ext_dir_entry *)
- ((char *) de + de->rec_len);
- else
- *next_dir = NULL;
- return bh;
- }
- offset += de->rec_len;
- if (prev_dir)
- *prev_dir = de;
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- }
- brelse(bh);
- return NULL;
-}
-
-int ext_lookup(struct inode * dir,const char * name, int len,
- struct inode ** result)
-{
- int ino;
- struct ext_dir_entry * de;
- struct buffer_head * bh;
-
- *result = NULL;
- if (!dir)
- return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
- if (!(bh = ext_find_entry(dir,name,len,&de,NULL,NULL))) {
- iput(dir);
- return -ENOENT;
- }
- ino = de->inode;
- brelse(bh);
- if (!(*result = iget(dir->i_sb,ino))) {
- iput(dir);
- return -EACCES;
- }
- iput(dir);
- return 0;
-}
-
-/*
- * ext_add_entry()
- *
- * adds a file entry to the specified directory, using the same
- * semantics as ext_find_entry(). It returns NULL if it failed.
- *
- * NOTE!! The inode part of 'de' is left at 0 - which means you
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
-static struct buffer_head * ext_add_entry(struct inode * dir,
- const char * name, int namelen, struct ext_dir_entry ** res_dir)
-{
- int i;
- long offset;
- unsigned short rec_len;
- struct buffer_head * bh;
- struct ext_dir_entry * de, * de1;
-
- *res_dir = NULL;
- if (!dir)
- return NULL;
-#ifdef NO_TRUNCATE
- if (namelen > EXT_NAME_LEN)
- return NULL;
-#else
- if (namelen > EXT_NAME_LEN)
- namelen = EXT_NAME_LEN;
-#endif
- if (!namelen)
- return NULL;
- bh = ext_bread(dir,0,0);
- if (!bh)
- return NULL;
- rec_len = ((8 + namelen + EXT_DIR_PAD - 1) / EXT_DIR_PAD) * EXT_DIR_PAD;
- offset = 0;
- de = (struct ext_dir_entry *) bh->b_data;
- while (1) {
- if ((char *)de >= BLOCK_SIZE+bh->b_data && offset < dir->i_size) {
-#ifdef EXTFS_DEBUG
-printk ("ext_add_entry: skipping to next block\n");
-#endif
- brelse(bh);
- bh = NULL;
- bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,0);
- if (!bh)
- return NULL;
- de = (struct ext_dir_entry *) bh->b_data;
- }
- if (offset >= dir->i_size) {
- /* Check that the directory entry fits in the block */
- if (offset % BLOCK_SIZE == 0 ||
- (BLOCK_SIZE - (offset % BLOCK_SIZE)) < rec_len) {
- if ((offset % BLOCK_SIZE) != 0) {
- /* If the entry does not fit in the
- block, the remainder of the block
- becomes an unused entry */
- de->inode = 0;
- de->rec_len = BLOCK_SIZE
- - (offset & (BLOCK_SIZE - 1));
- de->name_len = 0;
- offset += de->rec_len;
- dir->i_size += de->rec_len;
- dir->i_dirt = 1;
-#if 0
- dir->i_ctime = CURRENT_TIME;
-#endif
- mark_buffer_dirty(bh, 1);
- }
- brelse (bh);
- bh = NULL;
-#ifdef EXTFS_DEBUG
-printk ("ext_add_entry : creating next block\n");
-#endif
- bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,1);
- if (!bh)
- return NULL; /* Other thing to do ??? */
- de = (struct ext_dir_entry *) bh->b_data;
- }
- /* Allocate the entry */
- de->inode=0;
- de->rec_len = rec_len;
- dir->i_size += de->rec_len;
- dir->i_dirt = 1;
-#if 0
- dir->i_ctime = CURRENT_TIME;
-#endif
- }
- if (de->rec_len < 8 || de->rec_len % 4 != 0 ||
- de->rec_len < de->name_len + 8 ||
- (((char *) de) + de->rec_len-1 >= BLOCK_SIZE+bh->b_data)) {
- printk ("ext_addr_entry: bad dir entry\n");
- printk ("dev=%s, dir=%ld, offset=%ld, "
- "rec_len=%d, name_len=%d\n",
- kdevname(dir->i_dev), dir->i_ino, offset,
- de->rec_len, de->name_len);
- brelse (bh);
- return NULL;
- }
- if (!de->inode && de->rec_len >= rec_len) {
- if (de->rec_len > rec_len
- && de->rec_len - rec_len >= EXT_DIR_MIN_SIZE) {
- /* The found entry is too big : it is split
- into 2 ones :
- - the 1st one will be used to hold the name,
- - the 2nd one is unused */
- de1 = (struct ext_dir_entry *) ((char *) de + rec_len);
- de1->inode = 0;
- de1->rec_len = de->rec_len - rec_len;
- de1->name_len = 0;
- de->rec_len = rec_len;
- }
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- dir->i_dirt = 1;
- de->name_len = namelen;
- for (i=0; i < namelen ; i++)
- de->name[i] = name[i];
- mark_buffer_dirty(bh, 1);
- *res_dir = de;
- return bh;
- }
- offset += de->rec_len;
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- }
- brelse(bh);
- return NULL;
-}
-
-int ext_create(struct inode * dir,const char * name, int len, int mode,
- struct inode ** result)
-{
- struct inode * inode;
- struct buffer_head * bh;
- struct ext_dir_entry * de;
-
- *result = NULL;
- if (!dir)
- return -ENOENT;
- inode = ext_new_inode(dir);
- if (!inode) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_op = &ext_file_inode_operations;
- inode->i_mode = mode;
- inode->i_dirt = 1;
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- iput(dir);
- return -ENOSPC;
- }
- de->inode = inode->i_ino;
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- iput(dir);
- *result = inode;
- return 0;
-}
-
-int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
-{
- struct inode * inode;
- struct buffer_head * bh;
- struct ext_dir_entry * de;
-
- if (!dir)
- return -ENOENT;
- bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- inode = ext_new_inode(dir);
- if (!inode) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_uid = current->fsuid;
- inode->i_mode = mode;
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &ext_file_inode_operations;
- else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &ext_dir_inode_operations;
- if (dir->i_mode & S_ISGID)
- inode->i_mode |= S_ISGID;
- }
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &ext_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
- if (S_ISBLK(mode) || S_ISCHR(mode))
- inode->i_rdev = to_kdev_t(rdev);
-#if 0
- inode->i_mtime = inode->i_atime = CURRENT_TIME;
-#endif
- inode->i_dirt = 1;
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- iput(dir);
- return -ENOSPC;
- }
- de->inode = inode->i_ino;
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- iput(dir);
- iput(inode);
- return 0;
-}
-
-int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
-{
- struct inode * inode;
- struct buffer_head * bh, *dir_block;
- struct ext_dir_entry * de;
-
- bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- inode = ext_new_inode(dir);
- if (!inode) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_op = &ext_dir_inode_operations;
- inode->i_size = 2 * 16; /* Each entry is coded on 16 bytes for "." and ".."
- - 4 bytes for the inode number,
- - 2 bytes for the record length
- - 2 bytes for the name length
- - 8 bytes for the name */
-#if 0
- inode->i_mtime = inode->i_atime = CURRENT_TIME;
-#endif
- dir_block = ext_bread(inode,0,1);
- if (!dir_block) {
- iput(dir);
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- return -ENOSPC;
- }
- de = (struct ext_dir_entry *) dir_block->b_data;
- de->inode=inode->i_ino;
- de->rec_len=16;
- de->name_len=1;
- strcpy(de->name,".");
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- de->inode = dir->i_ino;
- de->rec_len=16;
- de->name_len=2;
- strcpy(de->name,"..");
- inode->i_nlink = 2;
- mark_buffer_dirty(dir_block, 1);
- brelse(dir_block);
- inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
- if (dir->i_mode & S_ISGID)
- inode->i_mode |= S_ISGID;
- inode->i_dirt = 1;
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- iput(dir);
- inode->i_nlink=0;
- iput(inode);
- return -ENOSPC;
- }
- de->inode = inode->i_ino;
- mark_buffer_dirty(bh, 1);
- dir->i_nlink++;
- dir->i_dirt = 1;
- iput(dir);
- iput(inode);
- brelse(bh);
- return 0;
-}
-
-/*
- * routine to check that the specified directory is empty (for rmdir)
- */
-static int empty_dir(struct inode * inode)
-{
- unsigned long offset;
- struct buffer_head * bh;
- struct ext_dir_entry * de, * de1;
-
- if (inode->i_size < 2 * 12 || !(bh = ext_bread(inode,0,0))) {
- printk("warning - bad directory on dev %s\n",
- kdevname(inode->i_dev));
- return 1;
- }
- de = (struct ext_dir_entry *) bh->b_data;
- de1 = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- if (de->inode != inode->i_ino || !de1->inode ||
- strcmp(".",de->name) || strcmp("..",de1->name)) {
- printk("warning - bad directory on dev %s\n",
- kdevname(inode->i_dev));
- return 1;
- }
- offset = de->rec_len + de1->rec_len;
- de = (struct ext_dir_entry *) ((char *) de1 + de1->rec_len);
- while (offset < inode->i_size ) {
- if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
- brelse(bh);
- bh = ext_bread(inode, offset >> BLOCK_SIZE_BITS,1);
- if (!bh) {
- offset += BLOCK_SIZE;
- continue;
- }
- de = (struct ext_dir_entry *) bh->b_data;
- }
- if (de->rec_len < 8 || de->rec_len %4 != 0 ||
- de->rec_len < de->name_len + 8) {
- printk ("empty_dir: bad dir entry\n");
- printk ("dev=%s, dir=%ld, offset=%ld, "
- "rec_len=%d, name_len=%d\n",
- kdevname(inode->i_dev), inode->i_ino,
- offset, de->rec_len, de->name_len);
- brelse (bh);
- return 1;
- }
- if (de->inode) {
- brelse(bh);
- return 0;
- }
- offset += de->rec_len;
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
- }
- brelse(bh);
- return 1;
-}
-
-static inline void ext_merge_entries (struct ext_dir_entry * de,
- struct ext_dir_entry * pde, struct ext_dir_entry * nde)
-{
- if (nde && !nde->inode)
- de->rec_len += nde->rec_len;
- if (pde && !pde->inode)
- pde->rec_len += de->rec_len;
-}
-
-int ext_rmdir(struct inode * dir, const char * name, int len)
-{
- int retval;
- struct inode * inode;
- struct buffer_head * bh;
- struct ext_dir_entry * de, * pde, * nde;
-
- inode = NULL;
- bh = ext_find_entry(dir,name,len,&de,&pde,&nde);
- retval = -ENOENT;
- if (!bh)
- goto end_rmdir;
- retval = -EPERM;
- if (!(inode = iget(dir->i_sb, de->inode)))
- goto end_rmdir;
- if ((dir->i_mode & S_ISVTX) && !fsuser() &&
- current->fsuid != inode->i_uid &&
- current->fsuid != dir->i_uid)
- goto end_rmdir;
- if (inode->i_dev != dir->i_dev)
- goto end_rmdir;
- if (inode == dir) /* we may not delete ".", but "../dir" is ok */
- goto end_rmdir;
- if (!S_ISDIR(inode->i_mode)) {
- retval = -ENOTDIR;
- goto end_rmdir;
- }
- if (!empty_dir(inode)) {
- retval = -ENOTEMPTY;
- goto end_rmdir;
- }
- if (inode->i_count > 1) {
- retval = -EBUSY;
- goto end_rmdir;
- }
- if (inode->i_nlink != 2)
- printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
- de->inode = 0;
- de->name_len = 0;
- ext_merge_entries (de, pde, nde);
- mark_buffer_dirty(bh, 1);
- inode->i_nlink=0;
- inode->i_dirt=1;
- dir->i_nlink--;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->i_dirt=1;
- retval = 0;
-end_rmdir:
- iput(dir);
- iput(inode);
- brelse(bh);
- return retval;
-}
-
-int ext_unlink(struct inode * dir, const char * name, int len)
-{
- int retval;
- struct inode * inode;
- struct buffer_head * bh;
- struct ext_dir_entry * de, * pde, * nde;
-
- retval = -ENOENT;
- inode = NULL;
- bh = ext_find_entry(dir,name,len,&de,&pde,&nde);
- if (!bh)
- goto end_unlink;
- if (!(inode = iget(dir->i_sb, de->inode)))
- goto end_unlink;
- retval = -EPERM;
- if ((dir->i_mode & S_ISVTX) && !fsuser() &&
- current->fsuid != inode->i_uid &&
- current->fsuid != dir->i_uid)
- goto end_unlink;
- if (S_ISDIR(inode->i_mode))
- goto end_unlink;
- if (!inode->i_nlink) {
- printk("Deleting nonexistent file (%s:%ld), %d\n",
- kdevname(inode->i_dev), inode->i_ino,
- inode->i_nlink);
- inode->i_nlink=1;
- }
- de->inode = 0;
- de->name_len = 0;
- ext_merge_entries (de, pde, nde);
- mark_buffer_dirty(bh, 1);
- inode->i_nlink--;
- inode->i_dirt = 1;
- inode->i_ctime = CURRENT_TIME;
- dir->i_ctime = dir->i_mtime = inode->i_ctime;
- dir->i_dirt = 1;
- retval = 0;
-end_unlink:
- brelse(bh);
- iput(inode);
- iput(dir);
- return retval;
-}
-
-int ext_symlink(struct inode * dir, const char * name, int len, const char * symname)
-{
- struct ext_dir_entry * de;
- struct inode * inode = NULL;
- struct buffer_head * bh = NULL, * name_block = NULL;
- int i;
- char c;
-
- if (!(inode = ext_new_inode(dir))) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_mode = S_IFLNK | 0777;
- inode->i_op = &ext_symlink_inode_operations;
- name_block = ext_bread(inode,0,1);
- if (!name_block) {
- iput(dir);
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- return -ENOSPC;
- }
- i = 0;
- while (i < 1023 && (c = *(symname++)))
- name_block->b_data[i++] = c;
- name_block->b_data[i] = 0;
- mark_buffer_dirty(name_block, 1);
- brelse(name_block);
- inode->i_size = i;
- inode->i_dirt = 1;
- bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
- if (bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- iput(dir);
- return -ENOSPC;
- }
- de->inode = inode->i_ino;
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- iput(dir);
- iput(inode);
- return 0;
-}
-
-int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
-{
- struct ext_dir_entry * de;
- struct buffer_head * bh;
-
- if (S_ISDIR(oldinode->i_mode)) {
- iput(oldinode);
- iput(dir);
- return -EPERM;
- }
- if (oldinode->i_nlink > 32000) {
- iput(oldinode);
- iput(dir);
- return -EMLINK;
- }
- bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- iput(oldinode);
- return -EEXIST;
- }
- bh = ext_add_entry(dir,name,len,&de);
- if (!bh) {
- iput(dir);
- iput(oldinode);
- return -ENOSPC;
- }
- de->inode = oldinode->i_ino;
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- iput(dir);
- oldinode->i_nlink++;
- oldinode->i_ctime = CURRENT_TIME;
- oldinode->i_dirt = 1;
- iput(oldinode);
- return 0;
-}
-
-static int subdir(struct inode * new_inode, struct inode * old_inode)
-{
- int ino;
- int result;
-
- new_inode->i_count++;
- result = 0;
- for (;;) {
- if (new_inode == old_inode) {
- result = 1;
- break;
- }
- if (new_inode->i_dev != old_inode->i_dev)
- break;
- ino = new_inode->i_ino;
- if (ext_lookup(new_inode,"..",2,&new_inode))
- break;
- if (new_inode->i_ino == ino)
- break;
- }
- iput(new_inode);
- return result;
-}
-
-#define PARENT_INO(buffer) \
-((struct ext_dir_entry *) ((char *) buffer + \
-((struct ext_dir_entry *) buffer)->rec_len))->inode
-
-#define PARENT_NAME(buffer) \
-((struct ext_dir_entry *) ((char *) buffer + \
-((struct ext_dir_entry *) buffer)->rec_len))->name
-
-/*
- * rename uses retrying to avoid race-conditions: at least they should be minimal.
- * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
- * checks fail, it tries to restart itself again. Very practical - no changes
- * are done until we know everything works ok.. and then all the changes can be
- * done in one fell swoop when we have claimed all the buffers needed.
- *
- * Anybody can rename anything with this: the permission checks are left to the
- * higher-level routines.
- */
-static int do_ext_rename(struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len)
-{
- struct inode * old_inode, * new_inode;
- struct buffer_head * old_bh, * new_bh, * dir_bh;
- struct ext_dir_entry * old_de, * new_de, * pde, * nde;
- int retval;
-
- goto start_up;
-try_again:
- brelse(old_bh);
- brelse(new_bh);
- brelse(dir_bh);
- iput(old_inode);
- iput(new_inode);
- current->counter = 0;
- schedule();
-start_up:
- old_inode = new_inode = NULL;
- old_bh = new_bh = dir_bh = NULL;
- old_bh = ext_find_entry(old_dir,old_name,old_len,&old_de,&pde,&nde);
- retval = -ENOENT;
- if (!old_bh)
- goto end_rename;
- old_inode = __iget(old_dir->i_sb, old_de->inode,0); /* don't cross mnt-points */
- if (!old_inode)
- goto end_rename;
- retval = -EPERM;
- if ((old_dir->i_mode & S_ISVTX) &&
- current->fsuid != old_inode->i_uid &&
- current->fsuid != old_dir->i_uid && !fsuser())
- goto end_rename;
- new_bh = ext_find_entry(new_dir,new_name,new_len,&new_de,NULL,NULL);
- if (new_bh) {
- new_inode = __iget(new_dir->i_sb, new_de->inode,0); /* don't cross mnt-points */
- if (!new_inode) {
- brelse(new_bh);
- new_bh = NULL;
- }
- }
- if (new_inode == old_inode) {
- retval = 0;
- goto end_rename;
- }
- if (new_inode && S_ISDIR(new_inode->i_mode)) {
- retval = -EEXIST;
- goto end_rename;
- }
- retval = -EPERM;
- if (new_inode && (new_dir->i_mode & S_ISVTX) &&
- current->fsuid != new_inode->i_uid &&
- current->fsuid != new_dir->i_uid && !fsuser())
- goto end_rename;
- if (S_ISDIR(old_inode->i_mode)) {
- retval = -EEXIST;
- if (new_bh)
- goto end_rename;
- if ((retval = permission(old_inode, MAY_WRITE)) != 0)
- goto end_rename;
- retval = -EINVAL;
- if (subdir(new_dir, old_inode))
- goto end_rename;
- retval = -EIO;
- dir_bh = ext_bread(old_inode,0,0);
- if (!dir_bh)
- goto end_rename;
- if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
- goto end_rename;
- }
- if (!new_bh)
- new_bh = ext_add_entry(new_dir,new_name,new_len,&new_de);
- retval = -ENOSPC;
- if (!new_bh)
- goto end_rename;
-/* sanity checking before doing the rename - avoid races */
- if (new_inode && (new_de->inode != new_inode->i_ino))
- goto try_again;
- if (new_de->inode && !new_inode)
- goto try_again;
- if (old_de->inode != old_inode->i_ino)
- goto try_again;
-/* ok, that's it */
- old_de->inode = 0;
- old_de->name_len = 0;
- new_de->inode = old_inode->i_ino;
- ext_merge_entries (old_de, pde, nde);
- if (new_inode) {
- new_inode->i_nlink--;
- new_inode->i_dirt = 1;
- }
- mark_buffer_dirty(old_bh, 1);
- mark_buffer_dirty(new_bh, 1);
- if (dir_bh) {
- PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
- mark_buffer_dirty(dir_bh, 1);
- old_dir->i_nlink--;
- new_dir->i_nlink++;
- old_dir->i_dirt = 1;
- new_dir->i_dirt = 1;
- }
- retval = 0;
-end_rename:
- brelse(dir_bh);
- brelse(old_bh);
- brelse(new_bh);
- iput(old_inode);
- iput(new_inode);
- iput(old_dir);
- iput(new_dir);
- return retval;
-}
-
-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- */
-int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len,
- int must_be_dir)
-{
- static struct wait_queue * wait = NULL;
- static int lock = 0;
- int result;
-
- while (lock)
- sleep_on(&wait);
- lock = 1;
- result = do_ext_rename(old_dir, old_name, old_len,
- new_dir, new_name, new_len);
- lock = 0;
- wake_up(&wait);
- return result;
-}
+++ /dev/null
-/*
- * linux/fs/ext/symlink.c
- *
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/symlink.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * ext symlink handling code
- */
-
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-
-static int ext_readlink(struct inode *, char *, int);
-static int ext_follow_link(struct inode *, struct inode *, int, int, struct inode **);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations ext_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- ext_readlink, /* readlink */
- ext_follow_link, /* follow_link */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
-
-static int ext_follow_link(struct inode * dir, struct inode * inode,
- int flag, int mode, struct inode ** res_inode)
-{
- int error;
- struct buffer_head * bh;
-
- *res_inode = NULL;
- if (!dir) {
- dir = current->fs->root;
- dir->i_count++;
- }
- if (!inode) {
- iput(dir);
- return -ENOENT;
- }
- if (!S_ISLNK(inode->i_mode)) {
- iput(dir);
- *res_inode = inode;
- return 0;
- }
- if (current->link_count > 5) {
- iput(dir);
- iput(inode);
- return -ELOOP;
- }
- if (!(bh = ext_bread(inode, 0, 0))) {
- iput(inode);
- iput(dir);
- return -EIO;
- }
- iput(inode);
- current->link_count++;
- error = open_namei(bh->b_data,flag,mode,res_inode,dir);
- current->link_count--;
- brelse(bh);
- return error;
-}
-
-static int ext_readlink(struct inode * inode, char * buffer, int buflen)
-{
- struct buffer_head * bh;
- int i;
- char c;
-
- if (!S_ISLNK(inode->i_mode)) {
- iput(inode);
- return -EINVAL;
- }
- if (buflen > 1023)
- buflen = 1023;
- bh = ext_bread(inode, 0, 0);
- iput(inode);
- if (!bh)
- return 0;
- i = 0;
- while (i<buflen && (c = bh->b_data[i])) {
- i++;
- put_user(c,buffer++);
- }
- brelse(bh);
- return i;
-}
+++ /dev/null
-/*
- * linux/fs/ext/truncate.c
- *
- * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
- *
- * from
- *
- * linux/fs/minix/truncate.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-#include <linux/sched.h>
-#include <linux/ext_fs.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-/*
- * Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**. Especially as I don't do any locking...
- *
- * The code may look a bit weird, but that's just because I've tried to
- * handle things like file-size changes in a somewhat graceful manner.
- * Anyway, truncating a file at the same time somebody else writes to it
- * is likely to result in pretty weird behaviour...
- *
- * The new code handles normal truncates (size = 0) as well as the more
- * general case (size = XXX). I hope.
- */
-
-static int trunc_direct(struct inode * inode)
-{
- int i, tmp;
- unsigned long * p;
- struct buffer_head * bh;
- int retry = 0;
-#define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
-
-repeat:
- for (i = DIRECT_BLOCK ; i < 9 ; i++) {
- p = inode->u.ext_i.i_data+i;
- if (!(tmp = *p))
- continue;
- bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < DIRECT_BLOCK) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && bh->b_count != 1) || tmp != *p) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *p = 0;
- inode->i_dirt = 1;
- brelse(bh);
- ext_free_block(inode->i_sb,tmp);
- }
- return retry;
-}
-
-static int trunc_indirect(struct inode * inode, int offset, unsigned long * p)
-{
- int i, tmp;
- struct buffer_head * bh;
- struct buffer_head * ind_bh;
- unsigned long * ind;
- int retry = 0;
-#define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
-
- tmp = *p;
- if (!tmp)
- return 0;
- ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(ind_bh);
- return 1;
- }
- if (!ind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = INDIRECT_BLOCK ; i < 256 ; i++) {
- if (i < 0)
- i = 0;
- if (i < INDIRECT_BLOCK)
- goto repeat;
- ind = i+(unsigned long *) ind_bh->b_data;
- tmp = *ind;
- if (!tmp)
- continue;
- bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < INDIRECT_BLOCK) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && bh->b_count != 1) || tmp != *ind) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *ind = 0;
- mark_buffer_dirty(ind_bh, 1);
- brelse(bh);
- ext_free_block(inode->i_sb,tmp);
- }
- ind = (unsigned long *) ind_bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(ind++))
- break;
- if (i >= 256)
- if (ind_bh->b_count != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- inode->i_dirt = 1;
- ext_free_block(inode->i_sb,tmp);
- }
- brelse(ind_bh);
- return retry;
-}
-
-static int trunc_dindirect(struct inode * inode, int offset, unsigned long * p)
-{
- int i,tmp;
- struct buffer_head * dind_bh;
- unsigned long * dind;
- int retry = 0;
-#define DINDIRECT_BLOCK ((DIRECT_BLOCK-offset)>>8)
-
- tmp = *p;
- if (!tmp)
- return 0;
- dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(dind_bh);
- return 1;
- }
- if (!dind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = DINDIRECT_BLOCK ; i < 256 ; i ++) {
- if (i < 0)
- i = 0;
- if (i < DINDIRECT_BLOCK)
- goto repeat;
- dind = i+(unsigned long *) dind_bh->b_data;
- tmp = *dind;
- if (!tmp)
- continue;
- retry |= trunc_indirect(inode,offset+(i<<8),dind);
- mark_buffer_dirty(dind_bh, 1);
- }
- dind = (unsigned long *) dind_bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(dind++))
- break;
- if (i >= 256)
- if (dind_bh->b_count != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- inode->i_dirt = 1;
- ext_free_block(inode->i_sb,tmp);
- }
- brelse(dind_bh);
- return retry;
-}
-
-static int trunc_tindirect(struct inode * inode)
-{
- int i,tmp;
- struct buffer_head * tind_bh;
- unsigned long * tind, * p;
- int retry = 0;
-#define TINDIRECT_BLOCK ((DIRECT_BLOCK-(256*256+256+9))>>16)
-
- p = inode->u.ext_i.i_data+11;
- if (!(tmp = *p))
- return 0;
- tind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(tind_bh);
- return 1;
- }
- if (!tind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = TINDIRECT_BLOCK ; i < 256 ; i ++) {
- if (i < 0)
- i = 0;
- if (i < TINDIRECT_BLOCK)
- goto repeat;
- tind = i+(unsigned long *) tind_bh->b_data;
- retry |= trunc_dindirect(inode,9+256+256*256+(i<<16),tind);
- mark_buffer_dirty(tind_bh, 1);
- }
- tind = (unsigned long *) tind_bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(tind++))
- break;
- if (i >= 256)
- if (tind_bh->b_count != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- inode->i_dirt = 1;
- ext_free_block(inode->i_sb,tmp);
- }
- brelse(tind_bh);
- return retry;
-}
-
-void ext_truncate(struct inode * inode)
-{
- int retry;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
- while (1) {
- retry = trunc_direct(inode);
- retry |= trunc_indirect(inode,9,inode->u.ext_i.i_data+9);
- retry |= trunc_dindirect(inode,9+256,inode->u.ext_i.i_data+10);
- retry |= trunc_tindirect(inode);
- if (!retry)
- break;
- current->counter = 0;
- schedule();
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_dirt = 1;
-}
-
-/*
- * Called when an inode is released. Note that this is different
- * from ext_open: open gets called at every open, but release
- * gets called only when /all/ the files are closed.
- */
-void ext_release(struct inode * inode, struct file * filp)
-{
- printk("ext_release not implemented\n");
-}
* Exported kernel symbols for the low-level FAT-based fs support.
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/minix_fs.h>
-#include <linux/ext_fs.h>
#include <linux/ext2_fs.h>
-#include <linux/xia_fs.h>
#include <linux/msdos_fs.h>
#include <linux/umsdos_fs.h>
#include <linux/proc_fs.h>
#include <linux/ncp_fs.h>
#include <linux/affs_fs.h>
#include <linux/ufs_fs.h>
+#include <linux/romfs_fs.h>
#include <linux/major.h>
extern void device_setup(void);
binfmt_setup();
-#ifdef CONFIG_EXT_FS
- init_ext_fs();
-#endif
-
#ifdef CONFIG_EXT2_FS
init_ext2_fs();
#endif
-#ifdef CONFIG_XIA_FS
- init_xiafs_fs();
-#endif
-
#ifdef CONFIG_MINIX_FS
init_minix_fs();
#endif
init_ufs_fs();
#endif
+#ifdef CONFIG_ROMFS_FS
+ init_romfs_fs();
+#endif
+
mount_root();
return 0;
}
+
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/stat.h>
* These symbols are used by umsdos.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/mm.h>
*
*/
-#include <linux/module.h>
#include <linux/config.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/uaccess.h>
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
-#include <linux/module.h>
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
--- /dev/null
+#
+# Makefile for the linux romfs-filesystem routines.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := romfs.o
+O_OBJS := inode.o
+M_OBJS := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
--- /dev/null
+/*
+ * ROMFS file system, Linux implementation
+ *
+ * Copyright (C) 1997 Janos Farkas <chexum@shadow.banki.hu>
+ *
+ * Using parts of the minix filesystem
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * and parts of the affs filesystem additionally
+ * Copyright (C) 1993 Ray Burr
+ * Copyright (C) 1996 Hans-Joachim Widmaier
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Changes
+ * Changed for 2.1.19 modules
+ * Jan 1997 Initial release
+ */
+
+/* todo:
+ * use malloced memory for file names?
+ * considering write access...
+ * network (tftp) files?
+ */
+
+/*
+ * Sorry about some optimizations and for some goto's. I just wanted
+ * to squeeze some more bytes out of this code.. :)
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/romfs_fs.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
+
+#include <asm/uaccess.h>
+
+static int inline min(int a, int b)
+{
+ return a<b ? a : b;
+}
+
+static __s32
+romfs_checksum(void *data, int size)
+{
+ __s32 sum, *ptr;
+
+ sum = 0; ptr = data;
+ size>>=2;
+ while (size>0) {
+ sum += ntohl(*ptr++);
+ size--;
+ }
+ return sum;
+}
+
+static struct super_operations romfs_ops;
+
+static struct super_block *
+romfs_read_super(struct super_block *s, void *data, int silent)
+{
+ struct buffer_head *bh;
+ kdev_t dev = s->s_dev;
+ struct romfs_super_block *rsb;
+ int sz;
+
+ MOD_INC_USE_COUNT;
+
+ /* I would parse the options, but there are none.. :) */
+
+ lock_super(s);
+ set_blocksize(dev, ROMBSIZE);
+ s->s_blocksize = ROMBSIZE;
+ s->s_blocksize_bits = ROMBSBITS;
+ bh = bread(dev, 0, ROMBSIZE);
+ if (!bh) {
+ printk ("romfs: unable to read superblock\n");
+ goto outnobh;
+ }
+
+ rsb = (struct romfs_super_block *)bh->b_data;
+ sz = ntohl(rsb->size);
+ if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1
+ || sz < ROMFH_SIZE) {
+ if (!silent)
+ printk ("VFS: Can't find a romfs filesystem on dev "
+ "%s.\n", kdevname(dev));
+ goto out;
+ }
+ if (romfs_checksum(rsb, min(sz,512))) {
+ printk ("romfs: bad initial checksum on dev "
+ "%s.\n", kdevname(dev));
+ }
+
+ s->s_magic = ROMFS_MAGIC;
+ s->u.romfs_sb.s_maxsize = sz;
+
+ s->s_flags |= MS_RDONLY;
+
+ /* Find the start of the fs */
+ sz = (ROMFH_SIZE +
+ strnlen(rsb->name, ROMFS_MAXFN) + 1 + ROMFH_PAD)
+ & ROMFH_MASK;
+
+ brelse(bh);
+
+ s->s_op = &romfs_ops;
+
+ unlock_super(s);
+
+ if (!(s->s_mounted = iget(s, sz)))
+ goto outnobh;
+
+ /* Ehrhm; sorry.. :) And thanks to Hans-Joachim Widmaier :) */
+ if (0) {
+out:
+ brelse(bh);
+outnobh:
+ s->s_dev = 0;
+ unlock_super(s);
+ MOD_DEC_USE_COUNT;
+ s = NULL;
+ }
+
+ return s;
+}
+
+/* Nothing to do.. */
+
+static void
+romfs_put_super(struct super_block *sb)
+{
+ lock_super(sb);
+ sb->s_dev = 0;
+ unlock_super(sb);
+ MOD_DEC_USE_COUNT;
+ return;
+}
+
+
+/* That's simple too. */
+
+static void
+romfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+{
+ struct statfs tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.f_type = ROMFS_MAGIC;
+ tmp.f_bsize = ROMBSIZE;
+ tmp.f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS;
+ copy_to_user(buf, &tmp, bufsize);
+}
+
+static int
+romfs_strnlen(struct inode *i, unsigned long offset, unsigned long count)
+{
+ struct buffer_head *bh;
+ unsigned long avail, maxsize, res;
+
+ maxsize = i->i_sb->u.romfs_sb.s_maxsize;
+ if (offset >= maxsize)
+ return -1;
+
+ /* strnlen is almost always valid */
+ if (count > maxsize || offset+count > maxsize)
+ count = maxsize-offset;
+
+ bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE);
+ if (!bh)
+ return -1; /* error */
+
+ avail = ROMBSIZE - (offset & ROMBMASK);
+ maxsize = min(count, avail);
+ res = strnlen(((char *)bh->b_data)+(offset&ROMBMASK), maxsize);
+ brelse(bh);
+
+ if (res < maxsize)
+ return res; /* found all of it */
+
+ while (res < count) {
+ offset += maxsize;
+
+ bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE);
+ if (!bh)
+ return -1;
+ maxsize = min(count-res, ROMBSIZE);
+ avail = strnlen(bh->b_data, maxsize);
+ res += avail;
+ brelse(bh);
+ if (avail < maxsize)
+ return res;
+ }
+ return res;
+}
+
+static int
+romfs_copyfrom(struct inode *i, void *dest, unsigned long offset, unsigned long count)
+{
+ struct buffer_head *bh;
+ unsigned long avail, maxsize, res;
+
+ maxsize = i->i_sb->u.romfs_sb.s_maxsize;
+ if (offset >= maxsize || count > maxsize || offset+count>maxsize)
+ return -1;
+
+ bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE);
+ if (!bh)
+ return -1; /* error */
+
+ avail = ROMBSIZE - (offset & ROMBMASK);
+ maxsize = min(count, avail);
+ memcpy(dest, ((char *)bh->b_data) + (offset & ROMBMASK), maxsize);
+ brelse(bh);
+
+ res = maxsize; /* all of it */
+
+ while (res < count) {
+ offset += maxsize;
+ dest += maxsize;
+
+ bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE);
+ if (!bh)
+ return -1;
+ maxsize = min(count-res, ROMBSIZE);
+ memcpy(dest, bh->b_data, maxsize);
+ brelse(bh);
+ res += maxsize;
+ }
+ return res;
+}
+
+/* Directory operations */
+
+static int
+romfs_readdir(struct inode *i, struct file *filp, void *dirent, filldir_t filldir)
+{
+ struct romfs_inode ri;
+ unsigned long offset, maxoff;
+ int j, ino, nextfh;
+ int stored = 0;
+ char fsname[ROMFS_MAXFN]; /* XXX dynamic? */
+
+ if (!i || !S_ISDIR(i->i_mode))
+ return -EBADF;
+
+ maxoff = i->i_sb->u.romfs_sb.s_maxsize;
+
+ offset = filp->f_pos;
+ if (!offset) {
+ offset = i->i_ino & ROMFH_MASK;
+ if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0)
+ return stored;
+ offset = ntohl(ri.spec) & ROMFH_MASK;
+ }
+
+ /* Not really failsafe, but we are read-only... */
+ for(;;) {
+ if (!offset || offset >= maxoff) {
+ offset = 0xffffffff;
+ filp->f_pos = offset;
+ return stored;
+ }
+ filp->f_pos = offset;
+
+ /* Fetch inode info */
+ if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0)
+ return stored;
+
+ j = romfs_strnlen(i, offset+ROMFH_SIZE, sizeof(fsname)-1);
+ if (j < 0)
+ return stored;
+
+ fsname[j]=0;
+ romfs_copyfrom(i, fsname, offset+ROMFH_SIZE, j);
+
+ ino = offset;
+ nextfh = ntohl(ri.next);
+ if ((nextfh & ROMFH_TYPE) == ROMFH_HRD)
+ ino = ntohl(ri.spec);
+ if (filldir(dirent, fsname, j, offset, ino) < 0) {
+ return stored;
+ }
+ stored++;
+ offset = nextfh & ROMFH_MASK;
+ }
+}
+
+static int
+romfs_lookup(struct inode *dir, const char *name, int len, struct inode **result)
+{
+ unsigned long offset, maxoff;
+ int fslen, res;
+ char fsname[ROMFS_MAXFN]; /* XXX dynamic? */
+ struct romfs_inode ri;
+
+ *result = NULL;
+ if (!dir || !S_ISDIR(dir->i_mode)) {
+ res = -EBADF;
+ goto out;
+ }
+
+ offset = dir->i_ino & ROMFH_MASK;
+ if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) {
+ res = -ENOENT;
+ goto out;
+ }
+
+ maxoff = dir->i_sb->u.romfs_sb.s_maxsize;
+ offset = ntohl(ri.spec) & ROMFH_MASK;
+
+ for(;;) {
+ if (!offset || offset >= maxoff
+ || romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) {
+ res = -ENOENT;
+ goto out;
+ }
+
+ /* try to match the first 16 bytes of name */
+ fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE);
+ if (len < ROMFH_SIZE) {
+ if (len == fslen) {
+ /* both are shorter, and same size */
+ romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1);
+ if (strncmp (name, fsname, len) == 0)
+ break;
+ }
+ } else if (fslen >= ROMFH_SIZE) {
+ /* both are longer; XXX optimize max size */
+ fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, sizeof(fsname)-1);
+ if (len == fslen) {
+ romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1);
+ if (strncmp(name, fsname, len) == 0)
+ break;
+ }
+ }
+ /* next entry */
+ offset = ntohl(ri.next) & ROMFH_MASK;
+ }
+
+ /* Hard link handling */
+ if ((ntohl(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
+ offset = ntohl(ri.spec) & ROMFH_MASK;
+
+ res = 0;
+ if (!(*result = iget(dir->i_sb, offset)))
+ res = -EACCES;
+
+out:
+ iput(dir);
+ return res;
+}
+
+/*
+ * Ok, we do readpage, to be able to execute programs. Unfortunately,
+ * bmap is not applicable, since we have looser alignments.
+ *
+ * XXX I'm not quite sure that I need to muck around the PG_xx bits..
+ */
+
+static int
+romfs_readpage(struct inode * inode, struct page * page)
+{
+ unsigned long buf;
+ unsigned long offset, avail, readlen;
+ int result = -EIO;
+
+ buf = page_address(page);
+ page->count++;
+ offset = page->offset;
+ if (offset < inode->i_size) {
+ avail = inode->i_size-offset;
+ readlen = min(avail, PAGE_SIZE);
+ if (romfs_copyfrom(inode, (void *)buf, inode->u.romfs_i.i_dataoffset+offset, readlen) == readlen) {
+ if (readlen < PAGE_SIZE) {
+ memset((void *)(buf+readlen),0,PAGE_SIZE-readlen);
+ }
+ result = 0;
+ set_bit(PG_uptodate, &page->flags);
+ } else {
+ memset((void *)buf, 0, PAGE_SIZE);
+ }
+ }
+ free_page(buf);
+ return result;
+}
+
+static int
+romfs_readlink(struct inode *inode, char *buffer, int len)
+{
+ int mylen;
+ char buf[ROMFS_MAXFN]; /* XXX dynamic */
+
+ if (!inode || !S_ISLNK(inode->i_mode)) {
+ mylen = -EBADF;
+ goto out;
+ }
+
+ mylen = min(sizeof(buf), inode->i_size);
+
+ if (romfs_copyfrom(inode, buf, inode->u.romfs_i.i_dataoffset, mylen) <= 0) {
+ mylen = -EIO;
+ goto out;
+ }
+ copy_to_user(buffer, buf, mylen);
+
+out:
+ iput(inode);
+ return mylen;
+}
+
+static int
+romfs_follow_link(struct inode *dir, struct inode *inode,
+ int flag, int mode, struct inode **res_inode)
+{
+ int error, len;
+ char *buf;
+
+ *res_inode = NULL;
+ if (!dir) {
+ dir = current->fs->root;
+ dir->i_count++;
+ }
+
+ if (!inode) {
+ iput(dir);
+ return -ENOENT;
+ }
+ if (!S_ISLNK(inode->i_mode)) {
+ *res_inode = inode;
+ iput(dir);
+ return 0;
+ }
+ if (current->link_count > 5) {
+ iput(inode);
+ iput(dir);
+ return -ELOOP;
+ }
+
+ /* Eek. Short enough. */
+ len = inode->i_size;
+ if (!(buf = kmalloc(len+1, GFP_KERNEL))) {
+ iput(inode);
+ iput(dir);
+ /* correct? spin? */
+ return -EAGAIN;
+ }
+ error = romfs_copyfrom(inode, buf, inode->u.romfs_i.i_dataoffset, len);
+ if (error != len) {
+ iput(inode);
+ iput(dir);
+ error = -EIO;
+ } else {
+ iput(inode);
+ buf[len] = 0;
+ current->link_count++;
+ error = open_namei(buf, flag, mode, res_inode, dir);
+ current->link_count--;
+ }
+
+ kfree(buf);
+ return error;
+}
+
+/* Mapping from our types to the kernel */
+
+static struct file_operations romfs_file_operations = {
+ NULL, /* lseek - default */
+ generic_file_read, /* read */
+ NULL, /* write - bad */
+ NULL, /* readdir */
+ NULL, /* select - default */
+ NULL, /* ioctl */
+ generic_file_mmap, /* mmap */
+ NULL, /* open */
+ NULL, /* release */
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL /* revalidate */
+};
+
+static struct inode_operations romfs_file_inode_operations = {
+ &romfs_file_operations,
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ romfs_readpage, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap -- not really */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL, /* smap */
+};
+
+static struct file_operations romfs_dir_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read */
+ NULL, /* write - bad */
+ romfs_readdir, /* readdir */
+ NULL, /* select - default */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* open */
+ NULL, /* release */
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL /* revalidate */
+};
+
+/* Merged dir/symlink op table. readdir/lookup/readlink/follow_link
+ * will protect from type mismatch.
+ */
+
+static struct inode_operations romfs_dirlink_inode_operations = {
+ &romfs_dir_operations,
+ NULL, /* create */
+ romfs_lookup, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ romfs_readlink, /* readlink */
+ romfs_follow_link, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL, /* smap */
+};
+
+static mode_t romfs_modemap[] =
+{
+ 0, S_IFDIR, S_IFREG, S_IFLNK+0777,
+ S_IFBLK, S_IFCHR, S_IFSOCK, S_IFIFO
+};
+
+static struct inode_operations *romfs_inoops[] =
+{
+ NULL, /* hardlink, handled elsewhere */
+ &romfs_dirlink_inode_operations,
+ &romfs_file_inode_operations,
+ &romfs_dirlink_inode_operations,
+ &blkdev_inode_operations, /* standard handlers */
+ &chrdev_inode_operations,
+ NULL, /* socket */
+ NULL, /* fifo */
+};
+
+static void
+romfs_read_inode(struct inode *i)
+{
+ int nextfh, ino;
+ struct romfs_inode ri;
+
+ i->i_op = NULL;
+
+ ino = i->i_ino & ROMFH_MASK;
+
+ /* Loop for finding the real hard link */
+ for(;;) {
+ if (romfs_copyfrom(i, &ri, ino, ROMFH_SIZE) <= 0) {
+ printk("romfs: read error for inode 0x%x\n", ino);
+ return;
+ }
+ nextfh = ntohl(ri.next);
+ if ((nextfh & ROMFH_TYPE) != ROMFH_HRD)
+ break;
+
+ ino = ntohl(ri.spec) & ROMFH_MASK;
+ }
+
+ i->i_nlink = 1; /* Hard to decide.. */
+ i->i_size = ntohl(ri.size);
+ i->i_mtime = i->i_atime = i->i_ctime = 0;
+ i->i_uid = i->i_gid = 0;
+
+ i->i_op = romfs_inoops[nextfh & ROMFH_TYPE];
+
+ /* Precalculate the data offset */
+ ino = romfs_strnlen(i, ino+ROMFH_SIZE, ROMFS_MAXFN);
+ if (ino >= 0)
+ ino = ((ROMFH_SIZE+ino+1+ROMFH_PAD)&ROMFH_MASK);
+ else
+ ino = 0;
+ i->u.romfs_i.i_metasize = ino;
+ i->u.romfs_i.i_dataoffset = ino+(i->i_ino&ROMFH_MASK);
+
+ /* Compute permissions */
+ ino = S_IRUGO|S_IWUSR;
+ ino |= romfs_modemap[nextfh & ROMFH_TYPE];
+ if (nextfh & ROMFH_EXEC) {
+ ino |= S_IXUGO;
+ }
+ i->i_mode = ino;
+
+ if (S_ISFIFO(ino))
+ init_fifo(i);
+ else if (S_ISDIR(ino))
+ i->i_size = i->u.romfs_i.i_metasize;
+ else if (S_ISBLK(ino) || S_ISCHR(ino)) {
+ i->i_mode &= ~(S_IRWXG|S_IRWXO);
+ ino = ntohl(ri.spec);
+ i->i_rdev = MKDEV(ino>>16,ino&0xffff);
+ }
+}
+
+static struct super_operations romfs_ops = {
+ romfs_read_inode, /* read inode */
+ NULL, /* notify change */
+ NULL, /* write inode */
+ NULL, /* put inode */
+ romfs_put_super, /* put super */
+ NULL, /* write super */
+ romfs_statfs, /* statfs */
+ NULL /* remount */
+};
+
+static struct file_system_type romfs_fs_type = {
+ romfs_read_super, "romfs", 1, NULL
+};
+
+int
+init_romfs_fs(void)
+{
+ return register_filesystem(&romfs_fs_type);
+}
+
+#ifdef MODULE
+
+/* Yes, works even as a module... :) */
+
+EXPORT_NO_SYMBOLS;
+
+int
+init_module(void)
+{
+ return init_romfs_fs();
+}
+
+void
+cleanup_module(void)
+{
+ unregister_filesystem(&romfs_fs_type);
+}
+#endif
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
* the superblock.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
* Gertjan van Wingerde <gertjan@cs.vu.nl>
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
* the problem, send a script that demonstrates it.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
+++ /dev/null
-#
-# Makefile for the XIAFS filesystem routines.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
-
-O_TARGET := xiafs.o
-O_OBJS := bitmap.o truncate.o namei.o inode.o file.o dir.o symlink.o fsync.o
-M_OBJS := $(O_TARGET)
-
-include $(TOPDIR)/Rules.make
+++ /dev/null
-/*
- * linux/fs/xiafs/bitmap.c
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix/bitmap.c
- * Copyright (C) Linus Torvalds, 1991, 1992.
- *
- * This software may be redistributed per Linux Copyright.
- */
-
-/* bitmap.c contains the code that handles the inode and block bitmaps */
-
-#include <linux/sched.h>
-#include <linux/locks.h>
-#include <linux/xia_fs.h>
-#include <linux/stat.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include <asm/bitops.h>
-
-#include "xiafs_mac.h"
-
-
-char internal_error_message[]="XIA-FS: internal error %s %d\n";
-
-static int find_first_zero(struct buffer_head *bh, int start_bit, int end_bit)
-{
- /* This routine searches first 0 bit from (start_bit) to (end_bit-1).
- * If found the bit is set to 1 and the bit # is returned, otherwise,
- * -1 is returned. Race condition is avoid by using "btsl" and
- * "goto repeat". ---Frank.
- */
-
- int end, i, j, tmp;
- u_long *bmap;
-
- bmap=(u_long *)bh->b_data;
- end = end_bit >> 5;
-
-repeat:
- i=start_bit >> 5;
- if ( (tmp=(~bmap[i]) & (0xffffffff << (start_bit & 31))) )
- goto zone_found;
- while (++i < end)
- if (~bmap[i]) {
- tmp=~bmap[i];
- goto zone_found;
- }
- if ( !(tmp=~bmap[i] & ((1 << (end_bit & 31)) -1)) )
- return -1;
-zone_found:
- for (j=0; j < 32; j++)
- if (tmp & (1 << j))
- break;
- if (set_bit(j,bmap+i)) {
- start_bit=j + (i << 5) + 1;
- goto repeat;
- }
- mark_buffer_dirty(bh, 1);
- return j + (i << 5);
-}
-
-static void clear_buf(struct buffer_head * bh)
-{
- register int i;
- register long * lp;
-
- lp=(long *)bh->b_data;
- for (i= bh->b_size >> 2; i-- > 0; )
- *lp++=0;
-}
-
-static void que(struct buffer_head * bmap[], int bznr[], int pos)
-{
- struct buffer_head * tbh;
- int tmp;
- int i;
-
- tbh=bmap[pos];
- tmp=bznr[pos];
- for (i=pos; i > 0; i--) {
- bmap[i]=bmap[i-1];
- bznr[i]=bznr[i-1];
- }
- bmap[0]=tbh;
- bznr[0]=tmp;
-}
-
-#define get_imap_zone(sb, bit_nr, not_que) \
- get__map_zone((sb), (sb)->u.xiafs_sb.s_imap_buf, \
- (sb)->u.xiafs_sb.s_imap_iznr, \
- (sb)->u.xiafs_sb.s_imap_cached, 1, \
- (sb)->u.xiafs_sb.s_imap_zones, _XIAFS_IMAP_SLOTS, \
- bit_nr, not_que)
-
-#define get_zmap_zone(sb, bit_nr, not_que) \
- get__map_zone((sb), (sb)->u.xiafs_sb.s_zmap_buf, \
- (sb)->u.xiafs_sb.s_zmap_zznr, \
- (sb)->u.xiafs_sb.s_zmap_cached, \
- 1+(sb)->u.xiafs_sb.s_imap_zones, \
- (sb)->u.xiafs_sb.s_zmap_zones, _XIAFS_ZMAP_SLOTS, \
- bit_nr, not_que)
-
-static struct buffer_head *
-get__map_zone(struct super_block *sb, struct buffer_head * bmap_buf[],
- int bznr[], u_char cache, int first_zone,
- int bmap_zones, int slots, u_long bit_nr, int * not_que)
-{
- struct buffer_head * tmp_bh;
- int z_nr, i;
-
- z_nr = bit_nr >> XIAFS_BITS_PER_Z_BITS(sb);
- if (z_nr >= bmap_zones) {
- printk("XIA-FS: bad inode/zone number (%s %d)\n", WHERE_ERR);
- return NULL;
- }
- if (!cache)
- return bmap_buf[z_nr];
- lock_super(sb);
- for (i=0; i < slots; i++)
- if (bznr[i]==z_nr)
- break;
- if (i < slots) { /* cache hit */
- if (not_que) {
- *not_que=i;
- return bmap_buf[i];
- } else {
- que(bmap_buf, bznr, i);
- return bmap_buf[0];
- }
- }
- tmp_bh=bread(sb->s_dev, z_nr+first_zone, XIAFS_ZSIZE(sb)); /* cache not hit */
- if (!tmp_bh) {
- printk("XIA-FS: read bitmap failed (%s %d)\n", WHERE_ERR);
- unlock_super(sb);
- return NULL;
- }
- brelse(bmap_buf[slots-1]);
- bmap_buf[slots-1]=tmp_bh;
- bznr[slots-1]=z_nr;
- if (not_que)
- *not_que=slots-1;
- else
- que(bmap_buf, bznr, slots-1);
- return tmp_bh;
-}
-
-#define xiafs_unlock_super(sb, cache) if (cache) unlock_super(sb);
-
-#define get_free_ibit(sb, prev_bit) \
- get_free__bit(sb, sb->u.xiafs_sb.s_imap_buf, \
- sb->u.xiafs_sb.s_imap_iznr, \
- sb->u.xiafs_sb.s_imap_cached, \
- 1, sb->u.xiafs_sb.s_imap_zones, \
- _XIAFS_IMAP_SLOTS, prev_bit);
-
-#define get_free_zbit(sb, prev_bit) \
- get_free__bit(sb, sb->u.xiafs_sb.s_zmap_buf, \
- sb->u.xiafs_sb.s_zmap_zznr, \
- sb->u.xiafs_sb.s_zmap_cached, \
- 1 + sb->u.xiafs_sb.s_imap_zones, \
- sb->u.xiafs_sb.s_zmap_zones, \
- _XIAFS_ZMAP_SLOTS, prev_bit);
-
-static u_long
-get_free__bit(struct super_block *sb, struct buffer_head * bmap_buf[],
- int bznr[], u_char cache, int first_zone, int bmap_zones,
- int slots, u_long prev_bit)
-{
- struct buffer_head * bh;
- int not_done=0;
- u_long pos, start_bit, end_bit, total_bits;
- int z_nr, tmp;
-
- total_bits=bmap_zones << XIAFS_BITS_PER_Z_BITS(sb);
- if (prev_bit >= total_bits)
- prev_bit=0;
- pos=prev_bit+1;
- end_bit=XIAFS_BITS_PER_Z(sb);
-
- do {
- if (pos >= total_bits)
- pos=0;
- if (!not_done) { /* first time */
- not_done=1;
- start_bit= pos & (end_bit-1);
- } else
- start_bit=0;
- if ( pos < prev_bit && pos+end_bit >= prev_bit) { /* last time */
- not_done=0;
- end_bit=prev_bit & (end_bit-1); /* only here end_bit modified */
- }
- bh = get__map_zone(sb, bmap_buf, bznr, cache, first_zone,
- bmap_zones, slots, pos, &z_nr);
- if (!bh)
- return 0;
- tmp=find_first_zero(bh, start_bit, end_bit);
- if (tmp >= 0)
- break;
- xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached);
- pos=(pos & ~(end_bit-1))+end_bit;
- } while (not_done);
-
- if (tmp < 0)
- return 0;
- if (cache)
- que(bmap_buf, bznr, z_nr);
- xiafs_unlock_super(sb, cache);
- return (pos & ~(XIAFS_BITS_PER_Z(sb)-1))+tmp;
-}
-
-void xiafs_free_zone(struct super_block * sb, int d_addr)
-{
- struct buffer_head * bh;
- unsigned int bit, offset;
-
- if (!sb) {
- printk(INTERN_ERR);
- return;
- }
- if (d_addr < sb->u.xiafs_sb.s_firstdatazone ||
- d_addr >= sb->u.xiafs_sb.s_nzones) {
- printk("XIA-FS: bad zone number (%s %d)\n", WHERE_ERR);
- return;
- }
- bh = get_hash_table(sb->s_dev, d_addr, XIAFS_ZSIZE(sb));
- if (bh)
- mark_buffer_clean(bh);
- brelse(bh);
- bit=d_addr - sb->u.xiafs_sb.s_firstdatazone + 1;
- bh = get_zmap_zone(sb, bit, NULL);
- if (!bh)
- return;
- offset = bit & (XIAFS_BITS_PER_Z(sb) -1);
- if (!clear_bit(offset, bh->b_data))
- printk("XIA-FS: dev %s"
- " block bit %u (0x%x) already cleared (%s %d)\n",
- kdevname(sb->s_dev), bit, bit, WHERE_ERR);
- mark_buffer_dirty(bh, 1);
- xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached);
-}
-
-int xiafs_new_zone(struct super_block * sb, u_long prev_addr)
-{
- struct buffer_head * bh;
- int prev_znr, tmp;
-
- if (!sb) {
- printk(INTERN_ERR);
- return 0;
- }
- if (prev_addr < sb->u.xiafs_sb.s_firstdatazone ||
- prev_addr >= sb->u.xiafs_sb.s_nzones) {
- prev_addr=sb->u.xiafs_sb.s_firstdatazone;
- }
- prev_znr=prev_addr-sb->u.xiafs_sb.s_firstdatazone+1;
- tmp=get_free_zbit(sb, prev_znr);
- if (!tmp)
- return 0;
- tmp += sb->u.xiafs_sb.s_firstdatazone -1;
- if (!(bh = getblk(sb->s_dev, tmp, XIAFS_ZSIZE(sb)))) {
- printk("XIA-FS: I/O error (%s %d)\n", WHERE_ERR);
- return 0;
- }
- if (bh->b_count != 1) {
- printk(INTERN_ERR);
- return 0;
- }
- clear_buf(bh);
- mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- return tmp;
-}
-
-void xiafs_free_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- struct super_block * sb;
- unsigned long ino;
-
- if (!inode)
- return;
- if (!inode->i_dev || inode->i_count!=1
- || inode->i_nlink || !inode->i_sb || inode->i_ino < 3
- || inode->i_ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
- printk("XIA-FS: bad inode (%s %d)\n", WHERE_ERR);
- return;
- }
- sb = inode->i_sb;
- ino = inode->i_ino;
- bh = get_imap_zone(sb, ino, NULL);
- if (!bh)
- return;
- clear_inode(inode);
- if (!clear_bit(ino & (XIAFS_BITS_PER_Z(sb)-1), bh->b_data))
- printk("XIA-FS: dev %s"
- "inode bit %ld (0x%lx) already cleared (%s %d)\n",
- kdevname(inode->i_dev), ino, ino, WHERE_ERR);
- mark_buffer_dirty(bh, 1);
- xiafs_unlock_super(sb, sb->u.xiafs_sb.s_imap_cached);
-}
-
-struct inode * xiafs_new_inode(struct inode * dir)
-{
- struct super_block * sb;
- struct inode * inode;
- ino_t tmp;
-
- sb = dir->i_sb;
- if (!dir || !(inode = get_empty_inode()))
- return NULL;
- inode->i_sb = sb;
- inode->i_flags = inode->i_sb->s_flags;
-
- tmp=get_free_ibit(sb, dir->i_ino);
- if (!tmp) {
- iput(inode);
- return NULL;
- }
- inode->i_count = 1;
- inode->i_nlink = 1;
- inode->i_dev = sb->s_dev;
- inode->i_uid = current->fsuid;
- inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
- inode->i_dirt = 1;
- inode->i_ino = tmp;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- inode->i_op = NULL;
- inode->i_blocks = 0;
- inode->i_blksize = XIAFS_ZSIZE(inode->i_sb);
- insert_inode_hash(inode);
- return inode;
-}
-
-static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
-
-static u_long count_zone(struct buffer_head * bh)
-{
- int i, tmp;
- u_long sum;
-
- sum=0;
- for (i=bh->b_size; i-- > 0; ) {
- tmp=bh->b_data[i];
- sum += nibblemap[tmp & 0xf] + nibblemap[(tmp & 0xff) >> 4];
- }
- return sum;
-}
-
-unsigned long xiafs_count_free_inodes(struct super_block *sb)
-{
- struct buffer_head * bh;
- int izones, i, not_que;
- u_long sum;
-
- sum=0;
- izones=sb->u.xiafs_sb.s_imap_zones;
- for (i=0; i < izones; i++) {
- bh=get_imap_zone(sb, i << XIAFS_BITS_PER_Z_BITS(sb), ¬_que);
- if (bh) {
- sum += count_zone(bh);
- xiafs_unlock_super(sb, sb->u.xiafs_sb.s_imap_cached);
- }
- }
- i=izones << XIAFS_BITS_PER_Z_BITS(sb);
- return i - sum;
-}
-
-unsigned long xiafs_count_free_zones(struct super_block *sb)
-{
- struct buffer_head * bh;
- int zzones, i, not_que;
- u_long sum;
-
- sum=0;
- zzones=sb->u.xiafs_sb.s_zmap_zones;
- for (i=0; i < zzones; i++) {
- bh=get_zmap_zone(sb, i << XIAFS_BITS_PER_Z_BITS(sb), ¬_que);
- if (bh) {
- sum += count_zone(bh);
- xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached);
- }
- }
- i=zzones << XIAFS_BITS_PER_Z_BITS(sb);
- return i - sum;
-}
+++ /dev/null
-/*
- * linux/fs/xiafs/dir.c
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix/dir.c
- * Copyright (C) Linus Torvalds, 1991, 1992.
- *
- * This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/xia_fs.h>
-#include <linux/stat.h>
-
-#include <asm/uaccess.h>
-
-#include "xiafs_mac.h"
-
-static long xiafs_dir_read(struct inode *, struct file *, char *, unsigned long);
-static int xiafs_readdir(struct inode *, struct file *, void *, filldir_t);
-
-static struct file_operations xiafs_dir_operations = {
- NULL, /* lseek - default */
- xiafs_dir_read, /* read */
- NULL, /* write - bad */
- xiafs_readdir, /* readdir */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special release code */
- file_fsync /* default fsync */
-};
-
-/*
- * directories can handle most operations...
- */
-struct inode_operations xiafs_dir_inode_operations = {
- &xiafs_dir_operations, /* default directory file-ops */
- xiafs_create, /* create */
- xiafs_lookup, /* lookup */
- xiafs_link, /* link */
- xiafs_unlink, /* unlink */
- xiafs_symlink, /* symlink */
- xiafs_mkdir, /* mkdir */
- xiafs_rmdir, /* rmdir */
- xiafs_mknod, /* mknod */
- xiafs_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* bmap */
- xiafs_truncate, /* truncate */
- NULL /* permission */
-};
-
-static long xiafs_dir_read(struct inode * inode, struct file * filp,
- char * buf, unsigned long count)
-{
- return -EISDIR;
-}
-
-static int xiafs_readdir(struct inode * inode, struct file * filp,
- void * dirent, filldir_t filldir)
-{
- u_int offset, i;
- struct buffer_head * bh;
- struct xiafs_direct * de;
-
- if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode))
- return -EBADF;
- if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) )
- return -EBADF;
- while (filp->f_pos < inode->i_size) {
- offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1);
- bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0);
- if (!bh) {
- filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset;
- continue;
- }
- for (i = 0; i < XIAFS_ZSIZE(inode->i_sb) && i < offset; ) {
- de = (struct xiafs_direct *) (bh->b_data + i);
- if (!de->d_rec_len)
- break;
- i += de->d_rec_len;
- }
- offset = i;
- de = (struct xiafs_direct *) (offset + bh->b_data);
-
- while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
- if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
- de->d_rec_len < 12 ||
- (char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data ||
- de->d_name_len < 1 || de->d_name_len + 8 > de->d_rec_len ||
- de->d_name_len > _XIAFS_NAME_LEN ||
- de->d_name[de->d_name_len] ) {
- printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
- brelse(bh);
- return 0;
- }
- if (de->d_ino) {
- if (!IS_RDONLY (inode)) {
- inode->i_atime=CURRENT_TIME;
- inode->i_dirt=1;
- }
- if (filldir(dirent, de->d_name, de->d_name_len, filp->f_pos, de->d_ino) < 0) {
- brelse(bh);
- return 0;
- }
- }
- offset += de->d_rec_len;
- filp->f_pos += de->d_rec_len;
- de = (struct xiafs_direct *) (offset + bh->b_data);
- }
- brelse(bh);
- if (offset > XIAFS_ZSIZE(inode->i_sb)) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- return 0;
- }
- }
- if (!IS_RDONLY (inode)) {
- inode->i_atime=CURRENT_TIME;
- inode->i_dirt=1;
- }
- return 0;
-}
+++ /dev/null
-/*
- * linux/fs/xiafs/file.c
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix/file.c
- * Copyright (C) Linus Torvalds, 1991, 1992.
- *
- * This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/xia_fs.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/pagemap.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include "xiafs_mac.h"
-
-#define NBUF 32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-static long xiafs_file_read(struct inode *, struct file *, char *, unsigned long);
-static long xiafs_file_write(struct inode *, struct file *, const char *, unsigned long);
-
-/*
- * We have mostly NULL's here: the current defaults are ok for
- * the xiafs filesystem.
- */
-static struct file_operations xiafs_file_operations = {
- NULL, /* lseek - default */
- xiafs_file_read, /* read */
- xiafs_file_write, /* write */
- NULL, /* readdir - bad */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- generic_file_mmap, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* release */
- xiafs_sync_file /* fsync */
-};
-
-struct inode_operations xiafs_file_inode_operations = {
- &xiafs_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- generic_readpage, /* readpage */
- NULL, /* writepage */
- xiafs_bmap, /* bmap */
- xiafs_truncate, /* truncate */
- NULL /* permission */
-};
-
-static long
-xiafs_file_read(struct inode * inode, struct file * filp, char * buf, unsigned long count)
-{
- int read, left, chars;
- int zone_nr, zones, f_zones, offset;
- int bhrequest, uptodate;
- struct buffer_head ** bhb, ** bhe;
- struct buffer_head * bhreq[NBUF];
- struct buffer_head * buflist[NBUF];
-
- if (!inode) {
- printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
- return -EINVAL;
- }
- if (!S_ISREG(inode->i_mode)) {
- printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
- return -EINVAL;
- }
- offset = filp->f_pos;
- left = inode->i_size - offset;
- if (left > count)
- left = count;
- if (left <= 0)
- return 0;
- read = 0;
- zone_nr = offset >> XIAFS_ZSIZE_BITS(inode->i_sb);
- offset &= XIAFS_ZSIZE(inode->i_sb) -1 ;
- f_zones =(inode->i_size+XIAFS_ZSIZE(inode->i_sb)-1)>>XIAFS_ZSIZE_BITS(inode->i_sb);
- zones = (left+offset+XIAFS_ZSIZE(inode->i_sb)-1) >> XIAFS_ZSIZE_BITS(inode->i_sb);
- bhb = bhe = buflist;
- if (filp->f_reada) {
- if(zones < read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb)))
- zones = read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
- if (zone_nr + zones > f_zones)
- zones = f_zones - zone_nr;
- }
-
- /* We do this in a two stage process. We first try to request
- as many blocks as we can, then we wait for the first one to
- complete, and then we try to wrap up as many as are actually
- done. This routine is rather generic, in that it can be used
- in a filesystem by substituting the appropriate function in
- for getblk.
-
- This routine is optimized to make maximum use of the various
- buffers and caches. */
-
- do {
- bhrequest = 0;
- uptodate = 1;
- while (zones--) {
- *bhb = xiafs_getblk(inode, zone_nr++, 0);
- if (*bhb && !buffer_uptodate(*bhb)) {
- uptodate = 0;
- bhreq[bhrequest++] = *bhb;
- }
-
- if (++bhb == &buflist[NBUF])
- bhb = buflist;
-
- /* If the block we have on hand is uptodate, go ahead
- and complete processing. */
- if (uptodate)
- break;
- if (bhb == bhe)
- break;
- }
-
- /* Now request them all */
- if (bhrequest)
- ll_rw_block(READ, bhrequest, bhreq);
-
- do { /* Finish off all I/O that has actually completed */
- if (*bhe) {
- wait_on_buffer(*bhe);
- if (!buffer_uptodate(*bhe)) { /* read error? */
- brelse(*bhe);
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- left = 0;
- break;
- }
- }
- if (left < XIAFS_ZSIZE(inode->i_sb) - offset)
- chars = left;
- else
- chars = XIAFS_ZSIZE(inode->i_sb) - offset;
- filp->f_pos += chars;
- left -= chars;
- read += chars;
- if (*bhe) {
- copy_to_user(buf,offset+(*bhe)->b_data,chars);
- brelse(*bhe);
- buf += chars;
- } else {
- while (chars-->0)
- put_user(0,buf++);
- }
- offset = 0;
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
- } while (left > 0);
-
-/* Release the read-ahead blocks */
- while (bhe != bhb) {
- brelse(*bhe);
- if (++bhe == &buflist[NBUF])
- bhe = buflist;
- };
- if (!read)
- return -EIO;
- filp->f_reada = 1;
- if (!IS_RDONLY (inode)) {
- inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- }
- return read;
-}
-
-static long
-xiafs_file_write(struct inode * inode, struct file * filp, const char * buf, unsigned long count)
-{
- off_t pos;
- int written, c;
- struct buffer_head * bh;
- char * cp;
-
- if (!inode) {
- printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
- return -EINVAL;
- }
- if (!S_ISREG(inode->i_mode)) {
- printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
- return -EINVAL;
- }
-/*
- * ok, append may not work when many processes are writing at the same time
- * but so what. That way leads to madness anyway.
- */
- if (filp->f_flags & O_APPEND)
- pos = inode->i_size;
- else
- pos = filp->f_pos;
- written = 0;
- while (written < count) {
- bh = xiafs_getblk(inode, pos >> XIAFS_ZSIZE_BITS(inode->i_sb), 1);
- if (!bh) {
- if (!written)
- written = -ENOSPC;
- break;
- }
- c = XIAFS_ZSIZE(inode->i_sb) - (pos & (XIAFS_ZSIZE(inode->i_sb) - 1));
- if (c > count-written)
- c = count-written;
- if (c != XIAFS_ZSIZE(inode->i_sb) && !buffer_uptodate(bh)) {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- if (!written)
- written = -EIO;
- break;
- }
- }
- cp = (pos & (XIAFS_ZSIZE(inode->i_sb)-1)) + bh->b_data;
- copy_from_user(cp,buf,c);
- update_vm_cache(inode,pos,cp,c);
- pos += c;
- if (pos > inode->i_size) {
- inode->i_size = pos;
- inode->i_dirt = 1;
- }
- written += c;
- buf += c;
- mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh, 0);
- brelse(bh);
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- filp->f_pos = pos;
- inode->i_dirt = 1;
-
- return written;
-}
+++ /dev/null
-/*
- * linux/fs/xiafs/fsync.c
- *
- * Changes Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
- * from
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * xiafs fsync primitive
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/locks.h>
-
-#include <linux/fs.h>
-#include <linux/xia_fs.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include "xiafs_mac.h"
-
-
-#define blocksize (XIAFS_ZSIZE(inode->i_sb))
-#define addr_per_block (XIAFS_ADDRS_PER_Z(inode->i_sb))
-
-static int sync_block (struct inode * inode, unsigned long * block, int wait)
-{
- struct buffer_head * bh;
- int tmp;
-
- if (!*block)
- return 0;
- tmp = *block;
- bh = get_hash_table(inode->i_dev, *block, blocksize);
- if (!bh)
- return 0;
- if (*block != tmp) {
- brelse (bh);
- return 1;
- }
- if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- brelse(bh);
- return -1;
- }
- if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
- {
- brelse(bh);
- return 0;
- }
- ll_rw_block(WRITE, 1, &bh);
- bh->b_count--;
- return 0;
-}
-
-static int sync_iblock (struct inode * inode, unsigned long * iblock,
- struct buffer_head **bh, int wait)
-{
- int rc, tmp;
-
- *bh = NULL;
- tmp = *iblock;
- if (!tmp)
- return 0;
- rc = sync_block (inode, iblock, wait);
- if (rc)
- return rc;
- *bh = bread(inode->i_dev, tmp, blocksize);
- if (tmp != *iblock) {
- brelse(*bh);
- *bh = NULL;
- return 1;
- }
- if (!*bh)
- return -1;
- return 0;
-}
-
-
-static int sync_direct(struct inode *inode, int wait)
-{
- int i;
- int rc, err = 0;
-
- for (i = 0; i < 8; i++) {
- rc = sync_block (inode, inode->u.ext_i.i_data + i, wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- return err;
-}
-
-static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
-{
- int i;
- struct buffer_head * ind_bh;
- int rc, err = 0;
-
- rc = sync_iblock (inode, iblock, &ind_bh, wait);
- if (rc || !ind_bh)
- return rc;
-
- for (i = 0; i < addr_per_block; i++) {
- rc = sync_block (inode,
- ((unsigned long *) ind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(ind_bh);
- return err;
-}
-
-static int sync_dindirect(struct inode *inode, unsigned long *diblock,
- int wait)
-{
- int i;
- struct buffer_head * dind_bh;
- int rc, err = 0;
-
- rc = sync_iblock (inode, diblock, &dind_bh, wait);
- if (rc || !dind_bh)
- return rc;
-
- for (i = 0; i < addr_per_block; i++) {
- rc = sync_indirect (inode,
- ((unsigned long *) dind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(dind_bh);
- return err;
-}
-
-int xiafs_sync_file(struct inode * inode, struct file * file)
-{
- int wait, err = 0;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return -EINVAL;
- for (wait=0; wait<=1; wait++)
- {
- err |= sync_direct(inode, wait);
- err |= sync_indirect(inode, &inode->u.xiafs_i.i_ind_zone, wait);
- err |= sync_dindirect(inode, &inode->u.xiafs_i.i_dind_zone, wait);
- }
- err |= xiafs_sync_inode (inode);
- return (err < 0) ? -EIO : 0;
-}
+++ /dev/null
-/*
- * linux/fs/xiafs/inode.c
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix/inode.c
- * Copyright (C) Linus Torvalds, 1991, 1992.
- *
- * This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/xia_fs.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include "xiafs_mac.h"
-
-static u_long random_nr;
-
-void xiafs_put_inode(struct inode *inode)
-{
- if (inode->i_nlink)
- return;
- inode->i_size = 0;
- xiafs_truncate(inode);
- xiafs_free_inode(inode);
-}
-
-void xiafs_put_super(struct super_block *sb)
-{
- int i;
-
- lock_super(sb);
- sb->s_dev = 0;
- for(i = 0 ; i < _XIAFS_IMAP_SLOTS ; i++)
- brelse(sb->u.xiafs_sb.s_imap_buf[i]);
- for(i = 0 ; i < _XIAFS_ZMAP_SLOTS ; i++)
- brelse(sb->u.xiafs_sb.s_zmap_buf[i]);
- unlock_super(sb);
- MOD_DEC_USE_COUNT;
-}
-
-static struct super_operations xiafs_sops = {
- xiafs_read_inode,
- NULL,
- xiafs_write_inode,
- xiafs_put_inode,
- xiafs_put_super,
- NULL,
- xiafs_statfs,
- NULL
-};
-
-struct super_block *xiafs_read_super(struct super_block *s, void *data,
- int silent)
-{
- struct buffer_head *bh;
- struct xiafs_super_block *sp;
- int i, z;
- kdev_t dev;
-
- MOD_INC_USE_COUNT;
- dev = s->s_dev;
- lock_super(s);
-
- set_blocksize(dev, BLOCK_SIZE);
-
- if (!(bh = bread(dev, 0, BLOCK_SIZE))) {
- s->s_dev = 0;
- unlock_super(s);
- printk("XIA-FS: read super_block failed (%s %d)\n", WHERE_ERR);
- MOD_DEC_USE_COUNT;
- return NULL;
- }
- sp = (struct xiafs_super_block *) bh->b_data;
- s->s_magic = sp->s_magic;
- if (s->s_magic != _XIAFS_SUPER_MAGIC) {
- s->s_dev = 0;
- unlock_super(s);
- brelse(bh);
- if (!silent)
- printk("VFS: Can't find a xiafs filesystem on dev "
- "%s.\n", kdevname(dev));
- MOD_DEC_USE_COUNT;
- return NULL;
- }
- s->s_blocksize = sp->s_zone_size;
- s->s_blocksize_bits = 10 + sp->s_zone_shift;
- if (s->s_blocksize != BLOCK_SIZE &&
- (s->s_blocksize == 1024 || s->s_blocksize == 2048 ||
- s->s_blocksize == 4096)) {
- brelse(bh);
- set_blocksize(dev, s->s_blocksize);
- bh = bread (dev, 0, s->s_blocksize);
- if(!bh) {
- MOD_DEC_USE_COUNT;
- return NULL;
- }
- sp = (struct xiafs_super_block *) (((char *)bh->b_data) + BLOCK_SIZE) ;
- };
- s->u.xiafs_sb.s_nzones = sp->s_nzones;
- s->u.xiafs_sb.s_ninodes = sp->s_ninodes;
- s->u.xiafs_sb.s_ndatazones = sp->s_ndatazones;
- s->u.xiafs_sb.s_imap_zones = sp->s_imap_zones;
- s->u.xiafs_sb.s_zmap_zones = sp->s_zmap_zones;
- s->u.xiafs_sb.s_firstdatazone = sp->s_firstdatazone;
- s->u.xiafs_sb.s_zone_shift = sp->s_zone_shift;
- s->u.xiafs_sb.s_max_size = sp->s_max_size;
- brelse(bh);
- for (i=0;i < _XIAFS_IMAP_SLOTS;i++) {
- s->u.xiafs_sb.s_imap_buf[i] = NULL;
- s->u.xiafs_sb.s_imap_iznr[i] = -1;
- }
- for (i=0;i < _XIAFS_ZMAP_SLOTS;i++) {
- s->u.xiafs_sb.s_zmap_buf[i] = NULL;
- s->u.xiafs_sb.s_zmap_zznr[i] = -1;
- }
- z=1;
- if ( s->u.xiafs_sb.s_imap_zones > _XIAFS_IMAP_SLOTS )
- s->u.xiafs_sb.s_imap_cached=1;
- else {
- s->u.xiafs_sb.s_imap_cached=0;
- for (i=0 ; i < s->u.xiafs_sb.s_imap_zones ; i++) {
- if (!(s->u.xiafs_sb.s_imap_buf[i]=bread(dev, z++, XIAFS_ZSIZE(s))))
- goto xiafs_read_super_fail;
- s->u.xiafs_sb.s_imap_iznr[i]=i;
- }
- }
- if ( s->u.xiafs_sb.s_zmap_zones > _XIAFS_ZMAP_SLOTS )
- s->u.xiafs_sb.s_zmap_cached=1;
- else {
- s->u.xiafs_sb.s_zmap_cached=0;
- for (i=0 ; i < s->u.xiafs_sb.s_zmap_zones ; i++) {
- if (!(s->u.xiafs_sb.s_zmap_buf[i]=bread(dev, z++, XIAFS_ZSIZE(s))))
- goto xiafs_read_super_fail;
- s->u.xiafs_sb.s_zmap_zznr[i]=i;
- }
- }
- /* set up enough so that it can read an inode */
- s->s_dev = dev;
- s->s_op = &xiafs_sops;
- s->s_mounted = iget(s, _XIAFS_ROOT_INO);
- if (!s->s_mounted)
- goto xiafs_read_super_fail;
- unlock_super(s);
- random_nr=CURRENT_TIME;
- return s;
-
-xiafs_read_super_fail:
- for(i=0; i < _XIAFS_IMAP_SLOTS; i++)
- brelse(s->u.xiafs_sb.s_imap_buf[i]);
- for(i=0; i < _XIAFS_ZMAP_SLOTS; i++)
- brelse(s->u.xiafs_sb.s_zmap_buf[i]);
- s->s_dev = 0;
- unlock_super(s);
- printk("XIA-FS: read bitmaps failed (%s %d)\n", WHERE_ERR);
- MOD_DEC_USE_COUNT;
- return NULL;
-}
-
-void xiafs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
-{
- struct statfs tmp;
-
- tmp.f_type = _XIAFS_SUPER_MAGIC;
- tmp.f_bsize = XIAFS_ZSIZE(sb);
- tmp.f_blocks = sb->u.xiafs_sb.s_ndatazones;
- tmp.f_bfree = xiafs_count_free_zones(sb);
- tmp.f_bavail = tmp.f_bfree;
- tmp.f_files = sb->u.xiafs_sb.s_ninodes;
- tmp.f_ffree = xiafs_count_free_inodes(sb);
- tmp.f_namelen = _XIAFS_NAME_LEN;
- copy_to_user(buf, &tmp, bufsiz);
-}
-
-static int zone_bmap(struct buffer_head * bh, int nr)
-{
- int tmp;
-
- if (!bh)
- return 0;
- tmp = ((u_long *) bh->b_data)[nr];
- brelse(bh);
- return tmp;
-}
-
-int xiafs_bmap(struct inode * inode,int zone)
-{
- int i;
-
- if (zone < 0) {
- printk("XIA-FS: block < 0 (%s %d)\n", WHERE_ERR);
- return 0;
- }
- if (zone >= 8+(1+XIAFS_ADDRS_PER_Z(inode->i_sb))*XIAFS_ADDRS_PER_Z(inode->i_sb)) {
- printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR);
- return 0;
- }
- if (!IS_RDONLY (inode)) {
- inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- }
- if (zone < 8)
- return inode->u.xiafs_i.i_zone[zone];
- zone -= 8;
- if (zone < XIAFS_ADDRS_PER_Z(inode->i_sb)) {
- i = inode->u.xiafs_i.i_ind_zone;
- if (i)
- i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)), zone);
- return i;
- }
- zone -= XIAFS_ADDRS_PER_Z(inode->i_sb);
- i = inode->u.xiafs_i.i_dind_zone;
- if (i)
- i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)),
- zone >> XIAFS_ADDRS_PER_Z_BITS(inode->i_sb));
- if (i)
- i= zone_bmap(bread(inode->i_dev,i, XIAFS_ZSIZE(inode->i_sb)),
- zone & (XIAFS_ADDRS_PER_Z(inode->i_sb)-1));
- return i;
-}
-
-static u_long get_prev_addr(struct inode * inode, int zone)
-{
- u_long tmp;
-
- if (zone > 0)
- while (--zone >= 0) /* only files with holes suffer */
- if ((tmp=xiafs_bmap(inode, zone)))
- return tmp;
- random_nr=(random_nr+23)%inode->i_sb->u.xiafs_sb.s_ndatazones;
- return random_nr + inode->i_sb->u.xiafs_sb.s_firstdatazone;
-}
-
-static struct buffer_head *
-dt_getblk(struct inode * inode, u_long *lp, int create, u_long prev_addr)
-{
- int tmp;
- struct buffer_head * result;
-
-repeat:
- if ((tmp=*lp)) {
- result = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
- if (tmp == *lp)
- return result;
- brelse(result);
- goto repeat;
- }
- if (!create)
- return NULL;
- tmp = xiafs_new_zone(inode->i_sb, prev_addr);
- if (!tmp)
- return NULL;
- result = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
- if (*lp) {
- xiafs_free_zone(inode->i_sb, tmp);
- brelse(result);
- goto repeat;
- }
- *lp = tmp;
- inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
- return result;
-}
-
-static struct buffer_head *
-indt_getblk(struct inode * inode, struct buffer_head * bh,
- int nr, int create, u_long prev_addr)
-{
- int tmp;
- u_long *lp;
- struct buffer_head * result;
-
- if (!bh)
- return NULL;
- if (!buffer_uptodate(bh)) {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- return NULL;
- }
- }
- lp = nr + (u_long *) bh->b_data;
-repeat:
- if ((tmp=*lp)) {
- result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
- if (tmp == *lp) {
- brelse(bh);
- return result;
- }
- brelse(result);
- goto repeat;
- }
- if (!create) {
- brelse(bh);
- return NULL;
- }
- tmp = xiafs_new_zone(inode->i_sb, prev_addr);
- if (!tmp) {
- brelse(bh);
- return NULL;
- }
- result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
- if (*lp) {
- xiafs_free_zone(inode->i_sb, tmp);
- brelse(result);
- goto repeat;
- }
- *lp = tmp;
- inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- return result;
-}
-
-struct buffer_head * xiafs_getblk(struct inode * inode, int zone, int create)
-{
- struct buffer_head * bh;
- u_long prev_addr=0;
-
- if (zone<0) {
- printk("XIA-FS: zone < 0 (%s %d)\n", WHERE_ERR);
- return NULL;
- }
- if (zone >= 8+(1+XIAFS_ADDRS_PER_Z(inode->i_sb))*XIAFS_ADDRS_PER_Z(inode->i_sb)) {
- if (!create)
- printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR);
- return NULL;
- }
- if (create)
- prev_addr=get_prev_addr(inode, zone);
- if (zone < 8)
- return dt_getblk(inode, zone+inode->u.xiafs_i.i_zone, create, prev_addr);
- zone -= 8;
- if (zone < XIAFS_ADDRS_PER_Z(inode->i_sb)) {
- bh = dt_getblk(inode, &(inode->u.xiafs_i.i_ind_zone), create, prev_addr);
- bh = indt_getblk(inode, bh, zone, create, prev_addr);
- return bh;
- }
- zone -= XIAFS_ADDRS_PER_Z(inode->i_sb);
- bh = dt_getblk(inode, &(inode->u.xiafs_i.i_dind_zone), create, prev_addr);
- bh = indt_getblk(inode, bh, zone>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb),
- create, prev_addr);
- bh = indt_getblk(inode, bh, zone&(XIAFS_ADDRS_PER_Z(inode->i_sb)-1),
- create, prev_addr);
- return bh;
-}
-
-struct buffer_head * xiafs_bread(struct inode * inode, int zone, int create)
-{
- struct buffer_head * bh;
-
- bh = xiafs_getblk(inode, zone, create);
- if (!bh || buffer_uptodate(bh))
- return bh;
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (buffer_uptodate(bh))
- return bh;
- brelse(bh);
- return NULL;
-}
-
-void xiafs_read_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- struct xiafs_inode * raw_inode;
- int zone;
- ino_t ino;
-
- ino = inode->i_ino;
- inode->i_op = NULL;
- inode->i_mode=0;
- if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
- printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR);
- return;
- }
- zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones +
- inode->i_sb->u.xiafs_sb.s_zmap_zones +
- (ino-1)/ XIAFS_INODES_PER_Z(inode->i_sb);
- if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) {
- printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR);
- return;
- }
- raw_inode = ((struct xiafs_inode *) bh->b_data) +
- ((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) - 1));
- inode->i_mode = raw_inode->i_mode;
- inode->i_uid = raw_inode->i_uid;
- inode->i_gid = raw_inode->i_gid;
- inode->i_nlink = raw_inode->i_nlinks;
- inode->i_size = raw_inode->i_size;
- inode->i_mtime = raw_inode->i_mtime;
- inode->i_atime = raw_inode->i_atime;
- inode->i_ctime = raw_inode->i_ctime;
- inode->i_blksize = XIAFS_ZSIZE(inode->i_sb);
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
- inode->i_blocks=0;
- inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
- } else {
- XIAFS_GET_BLOCKS(raw_inode, inode->i_blocks);
- for (zone = 0; zone < 8; zone++)
- inode->u.xiafs_i.i_zone[zone] = raw_inode->i_zone[zone] & 0xffffff;
- inode->u.xiafs_i.i_ind_zone = raw_inode->i_ind_zone & 0xffffff;
- inode->u.xiafs_i.i_dind_zone = raw_inode->i_dind_zone & 0xffffff;
- }
- brelse(bh);
- if (S_ISREG(inode->i_mode))
- inode->i_op = &xiafs_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
- inode->i_op = &xiafs_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &xiafs_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
-}
-
-static struct buffer_head * xiafs_update_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- struct xiafs_inode * raw_inode;
- int zone;
- ino_t ino;
-
- if (IS_RDONLY (inode)) {
- printk("XIA-FS: write_inode on a read-only filesystem (%s %d)\n", WHERE_ERR);
- inode->i_dirt = 0;
- return 0;
- }
-
- ino = inode->i_ino;
- if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
- printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR);
- inode->i_dirt=0;
- return 0;
- }
- zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones +
- inode->i_sb->u.xiafs_sb.s_zmap_zones +
- (ino-1) / XIAFS_INODES_PER_Z(inode->i_sb);
- if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) {
- printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR);
- inode->i_dirt=0;
- return 0;
- }
- raw_inode = ((struct xiafs_inode *)bh->b_data) +
- ((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) -1));
- raw_inode->i_mode = inode->i_mode;
- raw_inode->i_uid = inode->i_uid;
- raw_inode->i_gid = inode->i_gid;
- raw_inode->i_nlinks = inode->i_nlink;
- raw_inode->i_size = inode->i_size;
- raw_inode->i_atime = inode->i_atime;
- raw_inode->i_ctime = inode->i_ctime;
- raw_inode->i_mtime = inode->i_mtime;
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
- else {
- XIAFS_PUT_BLOCKS(raw_inode, inode->i_blocks);
- for (zone = 0; zone < 8; zone++)
- raw_inode->i_zone[zone] = (raw_inode->i_zone[zone] & 0xff000000)
- | (inode->u.xiafs_i.i_zone[zone] & 0xffffff);
- raw_inode->i_ind_zone = (raw_inode->i_ind_zone & 0xff000000)
- | (inode->u.xiafs_i.i_ind_zone & 0xffffff);
- raw_inode->i_dind_zone = (raw_inode->i_dind_zone & 0xff000000)
- | (inode->u.xiafs_i.i_dind_zone & 0xffffff);
- }
- inode->i_dirt=0;
- mark_buffer_dirty(bh, 1);
- return bh;
-}
-
-
-void xiafs_write_inode(struct inode * inode)
-{
- struct buffer_head * bh;
- bh = xiafs_update_inode(inode);
- brelse (bh);
-}
-
-int xiafs_sync_inode (struct inode *inode)
-{
- int err = 0;
- struct buffer_head *bh;
-
- bh = xiafs_update_inode(inode);
- if (bh && buffer_dirty(bh))
- {
- ll_rw_block(WRITE, 1, &bh);
- wait_on_buffer(bh);
- if (buffer_req(bh) && !buffer_uptodate(bh))
- {
- printk ("IO error syncing xiafs inode [%s:%lu]\n",
- kdevname(inode->i_dev), inode->i_ino);
- err = -1;
- }
- }
- else if (!bh)
- err = -1;
- brelse (bh);
- return err;
-}
-
-/* Every kernel module contains stuff like this. */
-
-static struct file_system_type xiafs_fs_type = {
- xiafs_read_super, "xiafs", 1, NULL
-};
-
-int init_xiafs_fs(void)
-{
- return register_filesystem(&xiafs_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
- return init_xiafs_fs();
-}
-
-void cleanup_module(void)
-{
- unregister_filesystem(&xiafs_fs_type);
-}
-
-#endif
+++ /dev/null
-/*
- * Linux/fs/xiafs/namei.c
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix/namei.c
- * Copyright (C) Linus Torvalds, 1991, 1992.
- *
- * This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/sched.h>
-#include <linux/xia_fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-
-#include <asm/uaccess.h>
-
-#include "xiafs_mac.h"
-
-#define RNDUP4(x) ((3+(u_long)(x)) & ~3)
-/*
- * ok, we cannot use strncmp, as the name is not in our data space.
- * Thus we'll have to use xiafs_match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, xiafs_match returns 1 for success, 0 for failure.
- */
-static int xiafs_match(int len, const char * name, struct xiafs_direct * dep)
-{
- int i;
-
- if (!dep || !dep->d_ino || len > _XIAFS_NAME_LEN)
- return 0;
- /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
- if (!len && (dep->d_name[0]=='.') && (dep->d_name[1]=='\0'))
- return 1;
- if (len != dep->d_name_len)
- return 0;
- for (i=0; i < len; i++)
- if (*name++ != dep->d_name[i])
- return 0;
- return 1;
-}
-
-/*
- * xiafs_find_entry()
- *
- * finds an entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_dir). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
- */
-static struct buffer_head *
-xiafs_find_entry(struct inode * inode, const char * name, int namelen,
- struct xiafs_direct ** res_dir, struct xiafs_direct ** res_pre)
-{
- int i, zones, pos;
- struct buffer_head * bh;
- struct xiafs_direct * dep, * dep_pre;
-
- *res_dir = NULL;
- if (!inode)
- return NULL;
- if (namelen > _XIAFS_NAME_LEN)
- return NULL;
-
- if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1)) {
- printk("XIA-FS: bad dir size (%s %d)\n", WHERE_ERR);
- return NULL;
- }
- zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
- for (i=0; i < zones; i++ ) {
- bh = xiafs_bread(inode, i, 0);
- if (!bh)
- continue;
- dep_pre=dep=(struct xiafs_direct *)bh->b_data;
- if (!i && (dep->d_rec_len != 12 || !dep->d_ino ||
- dep->d_name_len != 1 || strcmp(dep->d_name, "."))) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- brelse(bh);
- return NULL;
- }
- pos = 0;
- while ( pos < XIAFS_ZSIZE(inode->i_sb) ) {
- if (dep->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
- dep->d_rec_len < 12 ||
- dep->d_rec_len+(char *)dep > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
- dep->d_name_len + 8 > dep->d_rec_len || dep->d_name_len <= 0 ||
- dep->d_name[dep->d_name_len] ) {
- brelse(bh);
- return NULL;
- }
- if (xiafs_match(namelen, name, dep)) {
- *res_dir=dep;
- if (res_pre)
- *res_pre=dep_pre;
- return bh;
- }
- pos += dep->d_rec_len;
- dep_pre=dep;
- dep=(struct xiafs_direct *)(bh->b_data + pos);
- }
- brelse(bh);
- if (pos > XIAFS_ZSIZE(inode->i_sb)) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- return NULL;
- }
- }
- return NULL;
-}
-
-int xiafs_lookup(struct inode * dir, const char * name, int len,
- struct inode ** result)
-{
- int ino;
- struct xiafs_direct * dep;
- struct buffer_head * bh;
-
- *result = NULL;
- if (!dir)
- return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
- if (!(bh = xiafs_find_entry(dir, name, len, &dep, NULL))) {
- iput(dir);
- return -ENOENT;
- }
- ino = dep->d_ino;
- brelse(bh);
- if (!(*result = iget(dir->i_sb, ino))) {
- iput(dir);
- return -EACCES;
- }
- iput(dir);
- return 0;
-}
-
-/*
- * xiafs_add_entry()
- *
- * adds a file entry to the specified directory, using the same
- * semantics as xiafs_find_entry(). It returns NULL if it failed.
- *
- * NOTE!! The inode part of 'de' is left at 0 - which means you
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
-static struct buffer_head * xiafs_add_entry(struct inode * dir,
- const char * name, int namelen, struct xiafs_direct ** res_dir,
- struct xiafs_direct ** res_pre)
-{
- int i, pos, offset;
- struct buffer_head * bh;
- struct xiafs_direct * de, * de_pre;
-
- *res_dir = NULL;
- if (!dir || !namelen || namelen > _XIAFS_NAME_LEN)
- return NULL;
-
- if (dir->i_size & (XIAFS_ZSIZE(dir->i_sb) - 1)) {
- printk("XIA-FS: bad dir size (%s %d)\n", WHERE_ERR);
- return NULL;
- }
- pos=0;
- for ( ; ; ) {
- bh = xiafs_bread(dir, pos >> XIAFS_ZSIZE_BITS(dir->i_sb), pos ? 1:0);
- if (!bh)
- return NULL;
- de_pre=de=(struct xiafs_direct *)bh->b_data;
- if (!pos) {
- if (de->d_rec_len != 12 || !de->d_ino || de->d_name_len != 1 ||
- strcmp(de->d_name, ".")) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- brelse(bh);
- return NULL;
- }
- offset = 12;
- de_pre=de=(struct xiafs_direct *)(bh->b_data+12);
- } else
- offset = 0;
- while (offset < XIAFS_ZSIZE(dir->i_sb)) {
- if (pos >= dir->i_size) {
- de->d_ino=0;
- de->d_name_len=0;
- de->d_name[0]=0;
- de->d_rec_len=XIAFS_ZSIZE(dir->i_sb);
- dir->i_size += XIAFS_ZSIZE(dir->i_sb);
- dir->i_dirt = 1;
- } else {
- if (de->d_ino > dir->i_sb->u.xiafs_sb.s_ninodes ||
- de->d_rec_len < 12 ||
- (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(dir->i_sb) ||
- de->d_name_len + 8 > de->d_rec_len ||
- de->d_name[de->d_name_len]) {
- printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
- brelse(bh);
- return NULL;
- }
- if (de->d_ino &&
- RNDUP4(de->d_name_len)+RNDUP4(namelen)+16<=de->d_rec_len) {
- i=RNDUP4(de->d_name_len)+8;
- de_pre=de;
- de=(struct xiafs_direct *)(i+(u_char *)de_pre);
- de->d_ino=0;
- de->d_rec_len=de_pre->d_rec_len-i;
- de_pre->d_rec_len=i;
- }
- }
- if (!de->d_ino && RNDUP4(namelen)+8 <= de->d_rec_len) {
- /*
- * XXX all times should be set by caller upon successful
- * completion.
- */
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->i_dirt = 1;
- memcpy(de->d_name, name, namelen);
- de->d_name[namelen]=0;
- de->d_name_len=namelen;
- mark_buffer_dirty(bh, 1);
- *res_dir = de;
- if (res_pre)
- *res_pre = de_pre;
- return bh;
- }
- offset+=de->d_rec_len;
- de_pre=de;
- de=(struct xiafs_direct *)(bh->b_data+offset);
- }
- brelse(bh);
- if (offset > XIAFS_ZSIZE(dir->i_sb)) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- return NULL;
- }
- pos+=XIAFS_ZSIZE(dir->i_sb);
- }
- return NULL;
-}
-
-int xiafs_create(struct inode * dir, const char * name, int len, int mode,
- struct inode ** result)
-{
- struct inode * inode;
- struct buffer_head * bh;
- struct xiafs_direct * de;
-
- *result = NULL;
- if (!dir)
- return -ENOENT;
- inode = xiafs_new_inode(dir);
- if (!inode) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_op = &xiafs_file_inode_operations;
- inode->i_mode = mode;
- inode->i_dirt = 1;
- bh = xiafs_add_entry(dir, name, len, &de, NULL);
- if (!bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- iput(dir);
- return -ENOSPC;
- }
- de->d_ino = inode->i_ino;
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- iput(dir);
- *result = inode;
- return 0;
-}
-
-int xiafs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev)
-{
- struct inode * inode;
- struct buffer_head * bh;
- struct xiafs_direct * de;
-
- if (!dir)
- return -ENOENT;
- bh = xiafs_find_entry(dir,name,len,&de, NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- inode = xiafs_new_inode(dir);
- if (!inode) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_uid = current->fsuid;
- inode->i_mode = mode;
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &xiafs_file_inode_operations;
- else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &xiafs_dir_inode_operations;
- if (dir->i_mode & S_ISGID)
- inode->i_mode |= S_ISGID;
- }
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &xiafs_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
- if (S_ISBLK(mode) || S_ISCHR(mode))
- inode->i_rdev = to_kdev_t(rdev);
- inode->i_atime = inode->i_ctime = inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- bh = xiafs_add_entry(dir, name, len, &de, NULL);
- if (!bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- iput(dir);
- return -ENOSPC;
- }
- de->d_ino = inode->i_ino;
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- iput(dir);
- iput(inode);
- return 0;
-}
-
-int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode)
-{
- struct inode * inode;
- struct buffer_head * bh, *dir_block;
- struct xiafs_direct * de;
-
- bh = xiafs_find_entry(dir,name,len,&de, NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- if (dir->i_nlink > 64000) {
- iput(dir);
- return -EMLINK;
- }
- inode = xiafs_new_inode(dir);
- if (!inode) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_op = &xiafs_dir_inode_operations;
- inode->i_size = XIAFS_ZSIZE(dir->i_sb);
- inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- inode->i_dirt = 1;
- dir_block = xiafs_bread(inode,0,1);
- if (!dir_block) {
- iput(dir);
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- return -ENOSPC;
- }
- de = (struct xiafs_direct *) dir_block->b_data;
- de->d_ino=inode->i_ino;
- strcpy(de->d_name,".");
- de->d_name_len=1;
- de->d_rec_len=12;
- de =(struct xiafs_direct *)(12 + dir_block->b_data);
- de->d_ino = dir->i_ino;
- strcpy(de->d_name,"..");
- de->d_name_len=2;
- de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12;
- inode->i_nlink = 2;
- mark_buffer_dirty(dir_block, 1);
- brelse(dir_block);
- inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->fs->umask);
- if (dir->i_mode & S_ISGID)
- inode->i_mode |= S_ISGID;
- inode->i_dirt = 1;
- bh = xiafs_add_entry(dir, name, len, &de, NULL);
- if (!bh) {
- iput(dir);
- inode->i_nlink=0;
- iput(inode);
- return -ENOSPC;
- }
- de->d_ino = inode->i_ino;
- mark_buffer_dirty(bh, 1);
- dir->i_nlink++;
- dir->i_dirt = 1;
- iput(dir);
- iput(inode);
- brelse(bh);
- return 0;
-}
-
-/*
- * routine to check that the specified directory is empty (for rmdir)
- */
-static int empty_dir(struct inode * inode)
-{
- int i, zones, offset;
- struct buffer_head * bh;
- struct xiafs_direct * de;
-
- if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb)-1) ) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- return 1;
- }
-
- zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
- for (i=0; i < zones; i++) {
- bh = xiafs_bread(inode, i, 0);
- if (!i) {
- if (!bh) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- return 1;
- }
- de=(struct xiafs_direct *)bh->b_data;
- if (de->d_ino != inode->i_ino || strcmp(".", de->d_name) ||
- de->d_rec_len != 12 ) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- brelse(bh);
- return 1;
- }
- de=(struct xiafs_direct *)(12 + bh->b_data);
- if (!de->d_ino || strcmp("..", de->d_name)) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- brelse(bh);
- return 1;
- }
- offset=de->d_rec_len+12;
- }
- else
- offset = 0;
- if (!bh)
- continue;
- while (offset < XIAFS_ZSIZE(inode->i_sb)) {
- de=(struct xiafs_direct *)(bh->b_data+offset);
- if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
- de->d_rec_len < 12 ||
- (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
- de->d_name_len + 8 > de->d_rec_len ||
- de->d_name[de->d_name_len]) {
- printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
- brelse(bh);
- return 1;
- }
- if (de->d_ino) {
- brelse(bh);
- return 0;
- }
- offset+=de->d_rec_len;
- }
- brelse(bh);
- }
- return 1;
-}
-
-static void xiafs_rm_entry(struct xiafs_direct *de, struct xiafs_direct * de_pre)
-{
- if (de==de_pre) {
- de->d_ino=0;
- return;
- }
- while (de_pre->d_rec_len+(u_char *)de_pre < (u_char *)de) {
- if (de_pre->d_rec_len < 12) {
- printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
- return;
- }
- de_pre=(struct xiafs_direct *)(de_pre->d_rec_len+(u_char *)de_pre);
- }
- if (de_pre->d_rec_len+(u_char *)de_pre > (u_char *)de) {
- printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
- return;
- }
- de_pre->d_rec_len+=de->d_rec_len;
-}
-
-int xiafs_rmdir(struct inode * dir, const char * name, int len)
-{
- int retval;
- struct inode * inode;
- struct buffer_head * bh;
- struct xiafs_direct * de, * de_pre;
-
- inode = NULL;
- bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
- retval = -ENOENT;
- if (!bh)
- goto end_rmdir;
- retval = -EPERM;
- if (!(inode = iget(dir->i_sb, de->d_ino)))
- goto end_rmdir;
- if ((dir->i_mode & S_ISVTX) && !fsuser() &&
- current->fsuid != inode->i_uid &&
- current->fsuid != dir->i_uid)
- goto end_rmdir;
- if (inode->i_dev != dir->i_dev)
- goto end_rmdir;
- if (inode == dir) /* we may not delete ".", but "../dir" is ok */
- goto end_rmdir;
- if (!S_ISDIR(inode->i_mode)) {
- retval = -ENOTDIR;
- goto end_rmdir;
- }
- if (!empty_dir(inode)) {
- retval = -ENOTEMPTY;
- goto end_rmdir;
- }
- if (inode->i_count > 1) {
- retval = -EBUSY;
- goto end_rmdir;
- }
- if (inode->i_nlink != 2)
- printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
- xiafs_rm_entry(de, de_pre);
- mark_buffer_dirty(bh, 1);
- inode->i_nlink=0;
- inode->i_dirt=1;
- dir->i_nlink--;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->i_dirt=1;
- retval = 0;
-end_rmdir:
- iput(dir);
- iput(inode);
- brelse(bh);
- return retval;
-}
-
-int xiafs_unlink(struct inode * dir, const char * name, int len)
-{
- int retval;
- struct inode * inode;
- struct buffer_head * bh;
- struct xiafs_direct * de, * de_pre;
-
-repeat:
- retval = -ENOENT;
- inode = NULL;
- bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
- if (!bh)
- goto end_unlink;
- if (!(inode = iget(dir->i_sb, de->d_ino)))
- goto end_unlink;
- retval = -EPERM;
- if (S_ISDIR(inode->i_mode))
- goto end_unlink;
- if (de->d_ino != inode->i_ino) {
- iput(inode);
- brelse(bh);
- current->counter = 0;
- schedule();
- goto repeat;
- }
- if ((dir->i_mode & S_ISVTX) && !fsuser() &&
- current->fsuid != inode->i_uid &&
- current->fsuid != dir->i_uid)
- goto end_unlink;
- if (!inode->i_nlink) {
- printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR);
- inode->i_nlink=1;
- }
- xiafs_rm_entry(de, de_pre);
- mark_buffer_dirty(bh, 1);
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->i_dirt = 1;
- inode->i_nlink--;
- inode->i_dirt = 1;
- retval = 0;
-end_unlink:
- brelse(bh);
- iput(inode);
- iput(dir);
- return retval;
-}
-
-int xiafs_symlink(struct inode * dir, const char * name,
- int len, const char * symname)
-{
- struct xiafs_direct * de;
- struct inode * inode = NULL;
- struct buffer_head * bh = NULL, * name_block = NULL;
- int i;
- char c;
-
- bh = xiafs_find_entry(dir,name,len, &de, NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- return -EEXIST;
- }
- if (!(inode = xiafs_new_inode(dir))) {
- iput(dir);
- return -ENOSPC;
- }
- inode->i_mode = S_IFLNK | S_IRWXUGO;
- inode->i_op = &xiafs_symlink_inode_operations;
- name_block = xiafs_bread(inode,0,1);
- if (!name_block) {
- iput(dir);
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- return -ENOSPC;
- }
- for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
- name_block->b_data[i] = c;
- name_block->b_data[i] = 0;
- mark_buffer_dirty(name_block, 1);
- brelse(name_block);
- inode->i_size = i;
- inode->i_dirt = 1;
- bh = xiafs_add_entry(dir, name, len, &de, NULL);
- if (!bh) {
- inode->i_nlink--;
- inode->i_dirt = 1;
- iput(inode);
- iput(dir);
- return -ENOSPC;
- }
- de->d_ino = inode->i_ino;
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- iput(dir);
- iput(inode);
- return 0;
-}
-
-int xiafs_link(struct inode * oldinode, struct inode * dir,
- const char * name, int len)
-{
- struct xiafs_direct * de;
- struct buffer_head * bh;
-
- if (S_ISDIR(oldinode->i_mode)) {
- iput(oldinode);
- iput(dir);
- return -EPERM;
- }
- if (oldinode->i_nlink > 64000) {
- iput(oldinode);
- iput(dir);
- return -EMLINK;
- }
- bh = xiafs_find_entry(dir, name, len, &de, NULL);
- if (bh) {
- brelse(bh);
- iput(dir);
- iput(oldinode);
- return -EEXIST;
- }
- bh = xiafs_add_entry(dir, name, len, &de, NULL);
- if (!bh) {
- iput(dir);
- iput(oldinode);
- return -ENOSPC;
- }
- de->d_ino = oldinode->i_ino;
- mark_buffer_dirty(bh, 1);
- brelse(bh);
- iput(dir);
- oldinode->i_nlink++;
- oldinode->i_ctime = CURRENT_TIME;
- oldinode->i_dirt = 1;
- iput(oldinode);
- return 0;
-}
-
-static int subdir(struct inode * new_inode, struct inode * old_inode)
-{
- int ino;
- int result;
-
- new_inode->i_count++;
- result = 0;
- for (;;) {
- if (new_inode == old_inode) {
- result = 1;
- break;
- }
- if (new_inode->i_dev != old_inode->i_dev)
- break;
- ino = new_inode->i_ino;
- if (xiafs_lookup(new_inode,"..",2,&new_inode))
- break;
- if (new_inode->i_ino == ino)
- break;
- }
- iput(new_inode);
- return result;
-}
-
-#define PARENT_INO(buffer) \
- (((struct xiafs_direct *) ((u_char *)(buffer) + 12))->d_ino)
-
-/*
- * rename uses retry to avoid race-conditions: at least they should be minimal.
- * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
- * checks fail, it tries to restart itself again. Very practical - no changes
- * are done until we know everything works ok.. and then all the changes can be
- * done in one fell swoop when we have claimed all the buffers needed.
- *
- * Anybody can rename anything with this: the permission checks are left to the
- * higher-level routines.
- */
-static int do_xiafs_rename(struct inode * old_dir, const char * old_name,
- int old_len, struct inode * new_dir,
- const char * new_name, int new_len,
- int must_be_dir)
-{
- struct inode * old_inode, * new_inode;
- struct buffer_head * old_bh, * new_bh, * dir_bh;
- struct xiafs_direct * old_de, * old_de_pre, * new_de, * new_de_pre;
- int retval;
-
-try_again:
- old_inode = new_inode = NULL;
- old_bh = new_bh = dir_bh = NULL;
- old_bh = xiafs_find_entry(old_dir, old_name, old_len, &old_de, &old_de_pre);
- retval = -ENOENT;
- if (!old_bh)
- goto end_rename;
- old_inode = __iget(old_dir->i_sb, old_de->d_ino, 0); /* don't cross mnt-points */
- if (!old_inode)
- goto end_rename;
- if (must_be_dir && !S_ISDIR(old_inode->i_mode))
- goto end_rename;
- retval = -EPERM;
- if ((old_dir->i_mode & S_ISVTX) &&
- current->fsuid != old_inode->i_uid &&
- current->fsuid != old_dir->i_uid && !fsuser())
- goto end_rename;
- new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL);
- if (new_bh) {
- new_inode = __iget(new_dir->i_sb, new_de->d_ino, 0);
- if (!new_inode) {
- brelse(new_bh);
- new_bh = NULL;
- }
- }
- if (new_inode == old_inode) {
- retval = 0;
- goto end_rename;
- }
- if (new_inode && S_ISDIR(new_inode->i_mode)) {
- retval = -EEXIST;
- goto end_rename;
- }
- retval = -EPERM;
- if (new_inode && (new_dir->i_mode & S_ISVTX) &&
- current->fsuid != new_inode->i_uid &&
- current->fsuid != new_dir->i_uid && !fsuser())
- goto end_rename;
- if (S_ISDIR(old_inode->i_mode)) {
- retval = -EEXIST;
- if (new_bh)
- goto end_rename;
- if ((retval = permission(old_inode, MAY_WRITE)) != 0)
- goto end_rename;
- retval = -EINVAL;
- if (subdir(new_dir, old_inode))
- goto end_rename;
- retval = -EIO;
- dir_bh = xiafs_bread(old_inode,0,0);
- if (!dir_bh)
- goto end_rename;
- if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
- goto end_rename;
- retval = -EMLINK;
- if (new_dir->i_nlink > 64000)
- goto end_rename;
- }
- if (!new_bh)
- new_bh = xiafs_add_entry(new_dir, new_name, new_len, &new_de, &new_de_pre);
- retval = -ENOSPC;
- if (!new_bh)
- goto end_rename;
- /* sanity checking */
- if ( (new_inode && (new_de->d_ino != new_inode->i_ino))
- || (new_de->d_ino && !new_inode)
- || (old_de->d_ino != old_inode->i_ino)) {
- xiafs_rm_entry(new_de, new_de_pre);
- brelse(old_bh);
- brelse(new_bh);
- brelse(dir_bh);
- iput(old_inode);
- iput(new_inode);
- current->counter=0;
- schedule();
- goto try_again;
- }
- xiafs_rm_entry(old_de, old_de_pre);
- new_de->d_ino = old_inode->i_ino;
- if (new_inode) {
- new_inode->i_nlink--;
- new_inode->i_dirt = 1;
- }
- mark_buffer_dirty(old_bh, 1);
- mark_buffer_dirty(new_bh, 1);
- if (dir_bh) {
- PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
- mark_buffer_dirty(dir_bh, 1);
- old_dir->i_nlink--;
- new_dir->i_nlink++;
- old_dir->i_dirt = 1;
- new_dir->i_dirt = 1;
- }
- retval = 0;
-end_rename:
- brelse(dir_bh);
- brelse(old_bh);
- brelse(new_bh);
- iput(old_inode);
- iput(new_inode);
- iput(old_dir);
- iput(new_dir);
- return retval;
-}
-
-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- */
-int xiafs_rename(struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len,
- int must_be_dir)
-{
- static struct wait_queue * wait = NULL;
- static int lock = 0;
- int result;
-
- while (lock)
- sleep_on(&wait);
- lock = 1;
- result = do_xiafs_rename(old_dir, old_name, old_len,
- new_dir, new_name, new_len,
- must_be_dir);
- lock = 0;
- wake_up(&wait);
- return result;
-}
+++ /dev/null
-/*
- * linux/fs/xiafs/symlink.c
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix/symlink.c
- * Copyright (C) Linus Torvalds, 1991, 1992.
- *
- * This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/xia_fs.h>
-#include <linux/stat.h>
-
-#include <asm/uaccess.h>
-
-static int
-xiafs_readlink(struct inode *, char *, int);
-
-static int
-xiafs_follow_link(struct inode *, struct inode *, int, int, struct inode **);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations xiafs_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- xiafs_readlink, /* readlink */
- xiafs_follow_link, /* follow_link */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
-};
-
-static int xiafs_readlink(struct inode * inode, char * buffer, int buflen)
-{
- struct buffer_head * bh;
- int i;
- char c;
-
- if (!S_ISLNK(inode->i_mode)) {
- iput(inode);
- return -EINVAL;
- }
- if (buflen > BLOCK_SIZE)
- buflen = BLOCK_SIZE;
- bh = xiafs_bread(inode, 0, 0);
- if (!IS_RDONLY (inode)) {
- inode->i_atime=CURRENT_TIME;
- inode->i_dirt=1;
- }
- iput(inode);
- if (!bh)
- return 0;
- for (i=0; i < buflen && (c=bh->b_data[i]); i++)
- put_user(c, buffer++);
- if (i < buflen-1)
- put_user('\0', buffer);
- brelse(bh);
- return i;
-}
-
-static int xiafs_follow_link(struct inode * dir, struct inode * inode,
- int flag, int mode, struct inode ** res_inode)
-{
- int error;
- struct buffer_head * bh;
-
- *res_inode = NULL;
- if (!dir) {
- dir = current->fs->root;
- dir->i_count++;
- }
- if (!inode) {
- iput(dir);
- return -ENOENT;
- }
- if (!S_ISLNK(inode->i_mode)) {
- iput(dir);
- *res_inode = inode;
- return 0;
- }
- if (!IS_RDONLY (inode)) {
- inode->i_atime=CURRENT_TIME;
- inode->i_dirt=1;
- }
- if (current->link_count > 5) {
- iput(inode);
- iput(dir);
- return -ELOOP;
- }
- if (!(bh = xiafs_bread(inode, 0, 0))) {
- iput(inode);
- iput(dir);
- return -EIO;
- }
- iput(inode);
- current->link_count++;
- error = open_namei(bh->b_data,flag,mode,res_inode,dir);
- current->link_count--;
- brelse(bh);
- return error;
-}
-
-
-
+++ /dev/null
-/*
- * linux/fs/xiafs/truncate.c
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix/truncate.c
- * Copyright (C) Linus Torvalds, 1991, 1992.
- *
- * This software may be redistributed per Linux Copyright.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/xia_fs.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-#include "xiafs_mac.h"
-
-/*
- * Linus' comment:
- *
- * Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**. Especially as I don't do any locking...
- *
- * The code may look a bit weird, but that's just because I've tried to
- * handle things like file-size changes in a somewhat graceful manner.
- * Anyway, truncating a file at the same time somebody else writes to it
- * is likely to result in pretty weird behaviour...
- *
- * The new code handles normal truncates (size = 0) as well as the more
- * general case (size = XXX). I hope.
- */
-
-#define DT_ZONE ((inode->i_size + XIAFS_ZSIZE(inode->i_sb) - 1) \
- >> XIAFS_ZSIZE_BITS(inode->i_sb) )
-
-static int trunc_direct(struct inode * inode)
-{
- u_long * lp;
- struct buffer_head * bh;
- int i, tmp;
- int retry = 0;
-
-repeat:
- for (i = DT_ZONE ; i < 8 ; i++) {
- if (i < DT_ZONE)
- goto repeat;
- lp=i + inode->u.xiafs_i.i_zone;
- if (!(tmp = *lp))
- continue;
- bh = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
- if (i < DT_ZONE) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && bh->b_count != 1) || tmp != *lp)
- retry = 1;
- else {
- *lp = 0;
- inode->i_dirt = 1;
- inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
- xiafs_free_zone(inode->i_sb, tmp);
- }
- brelse(bh);
- }
- return retry;
-}
-
-static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp)
-{
-
-#define INDT_ZONE (DT_ZONE - addr_off)
-
- struct buffer_head * bh, * ind_bh;
- int i, tmp;
- u_long * indp;
- int retry = 0;
-
- if ( !(tmp=*lp) )
- return 0;
- ind_bh = bread(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
- if (tmp != *lp) {
- brelse(ind_bh);
- return 1;
- }
- if (!ind_bh) {
- *lp = 0;
- return 0;
- }
-repeat:
- for (i = INDT_ZONE<0?0:INDT_ZONE; i < XIAFS_ADDRS_PER_Z(inode->i_sb); i++) {
- if (i < INDT_ZONE)
- goto repeat;
- indp = i+(u_long *) ind_bh->b_data;
- if (!(tmp=*indp))
- continue;
- bh = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
- if (i < INDT_ZONE) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && bh->b_count != 1) || tmp != *indp)
- retry = 1;
- else {
- *indp = 0;
- mark_buffer_dirty(ind_bh, 1);
- inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
- xiafs_free_zone(inode->i_sb, tmp);
- }
- brelse(bh);
- }
- indp = (u_long *) ind_bh->b_data;
- for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*indp++); i++) ;
- if (i >= XIAFS_ADDRS_PER_Z(inode->i_sb)) {
- if (ind_bh->b_count != 1)
- retry = 1;
- else {
- tmp = *lp;
- *lp = 0;
- inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
- xiafs_free_zone(inode->i_sb, tmp);
- }
- }
- brelse(ind_bh);
- return retry;
-}
-
-static int trunc_dindirect(struct inode * inode)
-{
-
-#define DINDT_ZONE \
- ((DT_ZONE-XIAFS_ADDRS_PER_Z(inode->i_sb)-8)>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb))
-
- int i, tmp;
- struct buffer_head * dind_bh;
- u_long * dindp, * lp;
- int retry = 0;
-
- lp = &(inode->u.xiafs_i.i_dind_zone);
- if (!(tmp = *lp))
- return 0;
- dind_bh = bread(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
- if (tmp != *lp) {
- brelse(dind_bh);
- return 1;
- }
- if (!dind_bh) {
- *lp = 0;
- return 0;
- }
-repeat:
- for (i=DINDT_ZONE<0?0:DINDT_ZONE ; i < XIAFS_ADDRS_PER_Z(inode->i_sb) ; i ++) {
- if (i < DINDT_ZONE)
- goto repeat;
- dindp = i+(u_long *) dind_bh->b_data;
- retry |= trunc_indirect(inode,
- 8+((1+i)<<XIAFS_ADDRS_PER_Z_BITS(inode->i_sb)),
- dindp);
- mark_buffer_dirty(dind_bh, 1);
- }
- dindp = (u_long *) dind_bh->b_data;
- for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*dindp++); i++);
- if (i >= XIAFS_ADDRS_PER_Z(inode->i_sb)) {
- if (dind_bh->b_count != 1)
- retry = 1;
- else {
- tmp = *lp;
- *lp = 0;
- inode->i_dirt = 1;
- inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
- xiafs_free_zone(inode->i_sb, tmp);
- }
- }
- brelse(dind_bh);
- return retry;
-}
-
-void xiafs_truncate(struct inode * inode)
-{
- int retry;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
- while (1) {
- retry = trunc_direct(inode);
- retry |= trunc_indirect(inode, 8, &(inode->u.xiafs_i.i_ind_zone));
- retry |= trunc_dindirect(inode);
- if (!retry)
- break;
- current->counter = 0;
- schedule();
- }
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- inode->i_dirt = 1;
-}
+++ /dev/null
-/*
- * linux/fs/xiafs/xiafs_mac.h
- *
- * Copyright (C) Q. Frank Xia, 1993.
- */
-
-extern char internal_error_message[];
-#define INTERN_ERR internal_error_message, __FILE__, __LINE__
-#define WHERE_ERR __FILE__, __LINE__
-
-#define XIAFS_ZSHIFT(sp) ((sp)->u.xiafs_sb.s_zone_shift)
-#define XIAFS_ZSIZE(sp) (BLOCK_SIZE << XIAFS_ZSHIFT(sp))
-#define XIAFS_ZSIZE_BITS(sp) (BLOCK_SIZE_BITS + XIAFS_ZSHIFT(sp))
-#define XIAFS_ADDRS_PER_Z(sp) (BLOCK_SIZE >> (2 - XIAFS_ZSHIFT(sp)))
-#define XIAFS_ADDRS_PER_Z_BITS(sp) (BLOCK_SIZE_BITS - 2 + XIAFS_ZSHIFT(sp))
-#define XIAFS_BITS_PER_Z(sp) (BLOCK_SIZE << (3 + XIAFS_ZSHIFT(sp)))
-#define XIAFS_BITS_PER_Z_BITS(sp) (BLOCK_SIZE_BITS + 3 + XIAFS_ZSHIFT(sp))
-#define XIAFS_INODES_PER_Z(sp) (_XIAFS_INODES_PER_BLOCK << XIAFS_ZSHIFT(sp))
-
-/* Use the most significant bytes of zone pointers to store block counter. */
-/* This is ugly, but it works. Note, We have another 7 bytes for "expansion". */
-
-#define XIAFS_GET_BLOCKS(row_ip, blocks) \
- blocks=((((row_ip)->i_zone[0] >> 24) & 0xff )|\
- (((row_ip)->i_zone[1] >> 16) & 0xff00 )|\
- (((row_ip)->i_zone[2] >> 8) & 0xff0000 ) )
-
-/* XIAFS_PUT_BLOCKS should be called before saving zone pointers */
-#define XIAFS_PUT_BLOCKS(row_ip, blocks) \
- (row_ip)->i_zone[2]=((blocks)<< 8) & 0xff000000;\
- (row_ip)->i_zone[1]=((blocks)<<16) & 0xff000000;\
- (row_ip)->i_zone[0]=((blocks)<<24) & 0xff000000
".section __ex_table,\"a\"\n" \
" .gprel32 1b\n" \
" lda %0, 2b-1b(%1)\n" \
- ".text" \
+ ".previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "m"(__m(addr)), "1"(__gu_err))
".section __ex_table,\"a\"\n" \
" .gprel32 1b\n" \
" lda %0, 2b-1b(%1)\n" \
- ".text" \
+ ".previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "m"(__m(addr)), "1"(__gu_err))
".section __ex_table,\"a\"\n" \
" .gprel32 1b\n" \
" lda %0, 2b-1b(%1)\n" \
- ".text" \
+ ".previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "m"(__m(addr)), "1"(__gu_err))
".section __ex_table,\"a\"\n" \
" .gprel32 1b\n" \
" lda %0, 2b-1b(%1)\n" \
- ".text" \
+ ".previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "m"(__m(addr)), "1"(__gu_err))
#else
" lda %0, 3b-1b(%2)\n" \
" .gprel32 2b\n" \
" lda %0, 2b-1b(%2)\n" \
- ".text" \
+ ".previous" \
: "=&r"(__gu_val), "=&r"(__gu_tmp), "=r"(__gu_err) \
: "r"(addr), "2"(__gu_err)); \
}
".section __ex_table,\"a\"\n" \
" .gprel32 1b\n" \
" lda %0, 2b-1b(%1)\n" \
- ".text" \
+ ".previous" \
: "=&r"(__gu_val), "=r"(__gu_err) \
: "r"(addr), "1"(__gu_err))
#endif
".section __ex_table,\"a\"\n" \
" .gprel32 1b\n" \
" lda $31,2b-1b(%0)\n" \
- ".text" \
+ ".previous" \
: "=r"(__pu_err) \
: "m" (__m(addr)), "rJ" (x), "0"(__pu_err))
".section __ex_table,\"a\"\n" \
" .gprel32 1b\n" \
" lda $31,2b-1b(%0)\n" \
- ".text" \
+ ".previous" \
: "=r"(__pu_err) \
: "m"(__m(addr)), "rJ"(x), "0"(__pu_err))
".section __ex_table,\"a\"\n" \
" .gprel32 1b\n" \
" lda $31,2b-1b(%0)\n" \
- ".text" \
+ ".previous" \
: "=r"(__pu_err) \
: "m"(__m(addr)), "rJ"(x), "0"(__pu_err))
".section __ex_table,\"a\"\n" \
" .gprel32 1b\n" \
" lda $31,2b-1b(%0)\n" \
- ".text" \
+ ".previous" \
: "=r"(__pu_err) \
: "m"(__m(addr)), "rJ"(x), "0"(__pu_err))
#else
" lda $31, 5b-3b(%0)\n" \
" .gprel32 4b\n" \
" lda $31, 5b-4b(%0)\n" \
- ".text" \
+ ".previous" \
: "=r"(__pu_err), "=&r"(__pu_tmp1), \
"=&r"(__pu_tmp2), "=&r"(__pu_tmp3), \
"=&r"(__pu_tmp4) \
" lda $31, 3b-1b(%0)\n" \
" .gprel32 2b\n" \
" lda $31, 3b-2b(%0)\n" \
- ".text" \
+ ".previous" \
: "=r"(__pu_err), \
"=&r"(__pu_tmp1), "=&r"(__pu_tmp2) \
: "r"((unsigned long)(x)), "r"(addr), "0"(__pu_err)); \
".section .fixup,\"ax\"\n" \
"3: movl %3,%0\n" \
" jmp 2b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 1b,3b\n" \
- ".text" \
+ ".previous" \
: "=r"(err) \
: ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err))
"3: movl %3,%0\n" \
" xor"itype" %"rtype"1,%"rtype"1\n" \
" jmp 2b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 1b,3b\n" \
- ".text" \
+ ".previous" \
: "=r"(err), ltype (x) \
: "m"(__m(addr)), "i"(-EFAULT), "0"(err))
".section .fixup,\"ax\"\n" \
"3: lea 0(%1,%0,4),%0\n" \
" jmp 2b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 0b,3b\n" \
" .long 1b,2b\n" \
- ".text" \
+ ".previous" \
: "=c"(size) \
: "r"(size & 3), "0"(size / 4), "D"(to), "S"(from) \
: "di", "si", "memory")
".section .fixup,\"ax\"\n" \
"2: shl $2,%0\n" \
" jmp 1b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 0b,2b\n" \
- ".text" \
+ ".previous" \
: "=c"(size) \
: "S"(from), "D"(to), "0"(size/4) \
: "di", "si", "memory"); \
"3: shl $2,%0\n" \
"4: incl %0\n" \
" jmp 2b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 0b,3b\n" \
" .long 1b,4b\n" \
- ".text" \
+ ".previous" \
: "=c"(size) \
: "S"(from), "D"(to), "0"(size/4) \
: "di", "si", "memory"); \
"3: shl $2,%0\n" \
"4: addl $2,%0\n" \
" jmp 2b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 0b,3b\n" \
" .long 1b,4b\n" \
- ".text" \
+ ".previous" \
: "=c"(size) \
: "S"(from), "D"(to), "0"(size/4) \
: "di", "si", "memory"); \
"5: addl $2,%0\n" \
"6: incl %0\n" \
" jmp 3b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 0b,4b\n" \
" .long 1b,5b\n" \
" .long 2b,6b\n" \
- ".text" \
+ ".previous" \
: "=c"(size) \
: "S"(from), "D"(to), "0"(size/4) \
: "di", "si", "memory"); \
".section .fixup,\"ax\"\n" \
"3: lea 0(%1,%0,4),%0\n" \
" jmp 2b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 0b,3b\n" \
" .long 1b,2b\n" \
- ".text" \
+ ".previous" \
: "=c"(size) \
: "r"(size & 3), "0"(size / 4), "D"(addr), "a"(0) \
: "di")
".section .fixup,\"ax\"\n" \
"3: movl %2,%0\n" \
" jmp 2b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 0b,3b\n" \
- ".text" \
+ ".previous" \
: "=d"(res), "=c"(count) \
: "i"(-EFAULT), "0"(count), "1"(count), "S"(src), "D"(dst) \
: "si", "di", "ax", "memory")
".section .fixup,\"ax\"\n"
"2: xorl %0,%0\n"
" jmp 1b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 0b,2b\n"
- ".text"
+ ".previous"
:"=c" (res), "=D" (s)
:"1" (s), "a" (0), "0" (-__addr_ok(s)));
return res & -__addr_ok(s);
" .even\n" \
"2: movel %3,%0\n" \
" jra 1b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 21b,2b\n" \
" .long 1b,2b\n" \
- ".text" \
+ ".previous" \
: "=d"(err) \
: "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
"3: movel %3,%0\n" \
" sub" #bwl " %1,%1\n" \
" jra 2b\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 1b,3b\n" \
- ".text" \
+ ".previous" \
: "=d"(err), reg(x) \
: "m"(*(ptr)), "i" (-EFAULT), "0"(0))
" jra 6b\n"
"9: addql #1,%2\n"
" jra 6b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,7b\n"
" .long 3b,8b\n"
" .long 5b,9b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
: "r"(n & 3), "0"(to), "1"(from), "2"(n/4)
: "d0", "memory");
" jra 5b\n"
"8: addql #1,%2\n"
" jra 5b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 22b,6b\n"
" .long 4b,7b\n"
" .long 25b,8b\n"
" .long 5b,8b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
: "r"(n & 3), "0"(to), "1"(from), "2"(n / 4));
return n;
"11: lsll #2,%2\n" \
fixup "\n" \
" jra 12f\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 10b,11b\n" \
- ".text\n" \
+ ".previous\n" \
copy "\n" \
- ".text\n" \
"12:" \
: "=a"(to), "=a"(from), "=d"(n) \
: "0"(to), "1"(from), "2"(n/4) \
" .even\n"
"3: addql #1,%2\n"
" jra 2b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
" .even\n"
"3: addql #2,%2\n"
" jra 2b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"4: addql #2,%2\n"
"5: addql #1,%2\n"
" jra 3b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,4b\n"
" .long 2b,5b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
" .even\n"
"3: addql #4,%2\n"
" jra 2b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"4: addql #4,%2\n"
"5: addql #4,%2\n"
" jra 3b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,4b\n"
" .long 2b,5b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"6: addql #4,%2\n"
"7: addql #4,%2\n"
" jra 4b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,5b\n"
" .long 2b,6b\n"
" .long 3b,7b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"8: addql #4,%2\n"
"9: addql #4,%2\n"
" jra 5b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,6b\n"
" .long 2b,7b\n"
" .long 3b,8b\n"
" .long 4b,9b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"2: movesb (%1)+,%%d0\n"
" moveb %%d0,(%0)+\n"
".section __ex_table,\"a\"\n"
- " .long 2b,1b");
+ " .long 2b,1b\n"
+ ".previous");
break;
case 2:
__copy_from_user_big(to, from, n,
"2: movesw (%1)+,%%d0\n"
" movew %%d0,(%0)+\n"
".section __ex_table,\"a\"\n"
- " .long 2b,1b");
+ " .long 2b,1b\n"
+ ".previous");
break;
case 3:
__copy_from_user_big(to, from, n,
" moveb %%d0,(%0)+\n"
".section __ex_table,\"a\"\n"
" .long 3b,1b\n"
- " .long 4b,2b");
+ " .long 4b,2b\n"
+ ".previous");
break;
}
break;
"12: lsll #2,%2\n" \
fixup "\n" \
" jra 13f\n" \
+ ".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 31b,12b\n" \
" .long 11b,12b\n" \
- ".text\n" \
+ ".previous\n" \
copy "\n" \
- ".text\n" \
"13:" \
: "=a"(to), "=a"(from), "=d"(n) \
: "0"(to), "1"(from), "2"(n/4) \
" .even\n"
"2: addql #1,%2\n"
" jra 1b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n "
" .long 21b,2b\n"
" .long 1b,2b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
" .even\n"
"2: addql #2,%2\n"
" jra 1b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 21b,2b\n"
" .long 1b,2b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"3: addql #2,%2\n"
"4: addql #1,%2\n"
" jra 2b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 21b,3b\n"
" .long 1b,3b\n"
" .long 22b,4b\n"
" .long 2b,4b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
" .even\n"
"2: addql #4,%2\n"
" jra 1b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 21b,2b\n"
" .long 1b,2b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"3: addql #4,%2\n"
"4: addql #4,%2\n"
" jra 2b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 21b,3b\n"
" .long 1b,3b\n"
" .long 22b,4b\n"
" .long 2b,4b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"5: addql #4,%2\n"
"6: addql #4,%2\n"
" jra 3b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 21b,4b\n"
" .long 2b,5b\n"
" .long 23b,6b\n"
" .long 3b,6b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"7: addql #4,%2\n"
"8: addql #4,%2\n"
" jra 4b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 21b,5b\n"
" .long 3b,7b\n"
" .long 24b,8b\n"
" .long 4b,8b\n"
- ".text"
+ ".previous"
: "=a"(to), "=a"(from), "=d"(n)
: "0"(to), "1"(from), "2"(0)
: "d0", "memory");
"2:"
".section __ex_table,\"a\"\n"
" .long 22b,1b\n"
- " .long 2b,1b");
+ " .long 2b,1b\n"
+ ".previous");
break;
case 2:
__copy_to_user_big(to, from, n,
"2:"
".section __ex_table,\"a\"\n"
" .long 22b,1b\n"
- " .long 2b,1b");
+ " .long 2b,1b\n"
+ ".previous");
break;
case 3:
__copy_to_user_big(to, from, n,
" .long 23b,1b\n"
" .long 3b,1b\n"
" .long 24b,2b\n"
- " .long 4b,2b");
+ " .long 4b,2b\n"
+ ".previous");
break;
}
break;
" .even\n"
"4: movel %4,%0\n"
" jra 3b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,4b\n"
" .long 12b,4b\n"
- ".text"
+ ".previous"
: "=d"(res), "=a"(dst), "=a"(src), "=d"(count)
: "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count)
: "d0", "memory");
" .even\n"
"3: moveq %2,%0\n"
" jra 2b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
" .long 12b,3b\n"
- ".text"
+ ".previous"
: "=d"(res), "=a"(src)
: "i"(0), "0"(res), "1"(src)
: "d0");
" jra 5b\n"
"8: addql #1,%1\n"
" jra 5b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,6b\n"
" .long 4b,7b\n"
" .long 25b,8b\n"
" .long 5b,8b\n"
- ".text"
+ ".previous"
: "=a"(to), "=d"(n)
: "r"(n & 3), "r"(0), "0"(to), "1"(n/4));
return n;
*
* There is a special way how to put a range of potentially faulting
* insns (like twenty ldd/std's with now intervening other instructions)
- * You specify address of first in insn and 0 in fixup and in the next
+ * You specify address of first in insn and 0 in fixup and in the next
* exception_table_entry you specify last potentially faulting insn + 1
* and in fixup the routine which should handle the fault.
* That fixup code will get
".align 4\n" \
"3:\n\t" \
"b 2b\n\t" \
- " mov %3, %0\n\n\t" \
+ " mov %3, %0\n\t" \
+ ".previous\n\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\t" \
- ".text\n\n\t" \
+ ".previous\n\n\t" \
: "=&r" (ret) : "r" (x), "r" (__m(addr)), \
"i" (-EFAULT))
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, __ret_efault\n\n\t" \
- ".text\n\n\t" \
+ ".previous\n\n\t" \
: "=r" (foo) : "r" (x), "r" (__m(addr))); \
else \
__asm__ __volatile( \
".align 4\n" \
"3:\n\t" \
"ret\n\t" \
- " restore %%g0, %3, %%o0\n\n\t" \
+ " restore %%g0, %3, %%o0\n\t" \
+ ".previous\n\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\n\t" \
- ".text\n\n\t" \
+ ".previous\n\n\t" \
: "=r" (foo) : "r" (x), "r" (__m(addr)), "i" (ret))
extern int __put_user_bad(void);
"clr %1\n\t" \
"b 2b\n\t" \
" mov %3, %0\n\n\t" \
+ ".previous\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\n\t" \
- ".text\n\t" \
+ ".previous\n\t" \
: "=&r" (ret), "=&r" (x) : "r" (__m(addr)), \
"i" (-EFAULT))
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b,__ret_efault\n\n\t" \
- ".text\n\t" \
+ ".previous\n\t" \
: "=&r" (x) : "r" (__m(addr))); \
else \
__asm__ __volatile__( \
"3:\n\t" \
"ret\n\t" \
" restore %%g0, %2, %%o0\n\n\t" \
+ ".previous\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\n\t" \
- ".text\n\t" \
+ ".previous\n\t" \
: "=&r" (x) : "r" (__m(addr)), "i" (retval))
extern int __get_user_bad(void);
*
* There is a special way how to put a range of potentially faulting
* insns (like twenty ldd/std's with now intervening other instructions)
- * You specify address of first in insn and 0 in fixup and in the next
+ * You specify address of first in insn and 0 in fixup and in the next
* exception_table_entry you specify last potentially faulting insn + 1
* and in fixup the routine which should handle the fault.
* That fixup code will get
"3:\n\t" \
"b 2b\n\t" \
" mov %3, %0\n\n\t" \
+ ".previous\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\t" \
- ".text\n\n\t" \
+ ".previous\n\n\t" \
: "=&r" (ret) : "r" (x), "r" (__m(addr)), \
"i" (-EFAULT))
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, __ret_efault\n\n\t" \
- ".text\n\n\t" \
+ ".previous\n\n\t" \
: "=r" (foo) : "r" (x), "r" (__m(addr))); \
else \
__asm__ __volatile( \
"3:\n\t" \
"ret\n\t" \
" restore %%g0, %3, %%o0\n\n\t" \
+ ".previous\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\n\t" \
- ".text\n\n\t" \
+ ".previous\n\n\t" \
: "=r" (foo) : "r" (x), "r" (__m(addr)), "i" (ret))
extern int __put_user_bad(void);
"clr %1\n\t" \
"b 2b\n\t" \
" mov %3, %0\n\n\t" \
+ ".previous\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\n\t" \
- ".text\n\t" \
+ ".previous\n\t" \
: "=&r" (ret), "=&r" (x) : "r" (__m(addr)), \
"i" (-EFAULT))
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b,__ret_efault\n\n\t" \
- ".text\n\t" \
+ ".previous\n\t" \
: "=&r" (x) : "r" (__m(addr))); \
else \
__asm__ __volatile__( \
"3:\n\t" \
"ret\n\t" \
" restore %%g0, %2, %%o0\n\n\t" \
+ ".previous\n\t" \
".section __ex_table,#alloc\n\t" \
".align 4\n\t" \
".word 1b, 3b\n\n\t" \
- ".text\n\t" \
+ ".previous\n\t" \
: "=&r" (x) : "r" (__m(addr)), "i" (retval))
extern int __get_user_bad(void);
+++ /dev/null
-#ifndef _LINUX_EXT_FS_H
-#define _LINUX_EXT_FS_H
-
-/*
- * The ext filesystem constants/structures
- */
-
-#define EXT_NAME_LEN 255
-#define EXT_ROOT_INO 1
-
-#define EXT_SUPER_MAGIC 0x137D
-
-#define EXT_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct ext_inode)))
-
-struct ext_inode {
- unsigned short i_mode;
- unsigned short i_uid;
- unsigned long i_size;
- unsigned long i_time;
- unsigned short i_gid;
- unsigned short i_nlinks;
- unsigned long i_zone[12];
-};
-
-struct ext_free_inode {
- unsigned long count;
- unsigned long free[14];
- unsigned long next;
-};
-
-struct ext_free_block {
- unsigned long count;
- unsigned long free[254];
- unsigned long next;
-};
-
-struct ext_super_block {
- unsigned long s_ninodes;
- unsigned long s_nzones;
- unsigned long s_firstfreeblock;
- unsigned long s_freeblockscount;
- unsigned long s_firstfreeinode;
- unsigned long s_freeinodescount;
- unsigned long s_firstdatazone;
- unsigned long s_log_zone_size;
- unsigned long s_max_size;
- unsigned long s_reserved1;
- unsigned long s_reserved2;
- unsigned long s_reserved3;
- unsigned long s_reserved4;
- unsigned long s_reserved5;
- unsigned short s_magic;
-};
-
-struct ext_dir_entry {
- unsigned long inode;
- unsigned short rec_len;
- unsigned short name_len;
- char name[EXT_NAME_LEN];
-};
-
-#ifdef __KERNEL__
-extern int ext_open(struct inode * inode, struct file * filp);
-extern void ext_release(struct inode * inode, struct file * filp);
-extern int ext_lookup(struct inode * dir,const char * name, int len,
- struct inode ** result);
-extern int ext_create(struct inode * dir,const char * name, int len, int mode,
- struct inode ** result);
-extern int ext_mkdir(struct inode * dir, const char * name, int len, int mode);
-extern int ext_rmdir(struct inode * dir, const char * name, int len);
-extern int ext_unlink(struct inode * dir, const char * name, int len);
-extern int ext_symlink(struct inode * inode, const char * name, int len,
- const char * symname);
-extern int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int len);
-extern int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
-extern int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len, int must_be_dir);
-extern struct inode * ext_new_inode(const struct inode * dir);
-extern void ext_free_inode(struct inode * inode);
-extern unsigned long ext_count_free_inodes(struct super_block *sb);
-extern int ext_new_block(struct super_block * sb);
-extern void ext_free_block(struct super_block * sb, int block);
-extern unsigned long ext_count_free_blocks(struct super_block *sb);
-
-extern int ext_bmap(struct inode *,int);
-
-extern struct buffer_head * ext_getblk(struct inode *, int, int);
-extern struct buffer_head * ext_bread(struct inode *, int, int);
-
-extern void ext_truncate(struct inode *);
-extern void ext_put_super(struct super_block *);
-extern void ext_write_super(struct super_block *);
-extern struct super_block *ext_read_super(struct super_block *,void *,int);
-extern int init_ext_fs(void);
-extern void ext_read_inode(struct inode *);
-extern void ext_write_inode(struct inode *);
-extern void ext_put_inode(struct inode *);
-extern void ext_statfs(struct super_block *, struct statfs *, int);
-extern int ext_sync_inode(struct inode *);
-extern int ext_sync_file(struct inode *, struct file *);
-
-extern int ext_lseek(struct inode *, struct file *, off_t, int);
-extern int ext_read(struct inode *, struct file *, char *, int);
-extern int ext_write(struct inode *, struct file *, char *, int);
-
-extern struct inode_operations ext_file_inode_operations;
-extern struct inode_operations ext_dir_inode_operations;
-extern struct inode_operations ext_symlink_inode_operations;
-
-#endif /*__KERNEL__ */
-#endif
+++ /dev/null
-#ifndef _EXT_FS_I
-#define _EXT_FS_I
-
-/*
- * extended file system inode data in memory
- */
-struct ext_inode_info {
- unsigned long i_data[16];
-};
-
-#endif
+++ /dev/null
-#ifndef _EXT_FS_SB
-#define _EXT_FS_SB
-
-/*
- * extended-fs super-block data in memory
- */
-struct ext_sb_info {
- unsigned long s_ninodes;
- unsigned long s_nzones;
- unsigned long s_firstdatazone;
- unsigned long s_log_zone_size;
- unsigned long s_max_size;
- unsigned long s_firstfreeblocknumber;
- unsigned long s_freeblockscount;
- struct buffer_head * s_firstfreeblock;
- unsigned long s_firstfreeinodenumber;
- unsigned long s_freeinodescount;
- struct buffer_head * s_firstfreeinodeblock;
-};
-
-#endif
#include <linux/pipe_fs_i.h>
#include <linux/minix_fs_i.h>
-#include <linux/ext_fs_i.h>
#include <linux/ext2_fs_i.h>
#include <linux/hpfs_fs_i.h>
#include <linux/msdos_fs_i.h>
#include <linux/umsdos_fs_i.h>
#include <linux/iso_fs_i.h>
#include <linux/nfs_fs_i.h>
-#include <linux/xia_fs_i.h>
#include <linux/sysv_fs_i.h>
#include <linux/affs_fs_i.h>
#include <linux/ufs_fs_i.h>
+#include <linux/romfs_fs_i.h>
/*
* Attribute flags. These should be or-ed together to figure out what
union {
struct pipe_inode_info pipe_i;
struct minix_inode_info minix_i;
- struct ext_inode_info ext_i;
struct ext2_inode_info ext2_i;
struct hpfs_inode_info hpfs_i;
struct msdos_inode_info msdos_i;
struct umsdos_inode_info umsdos_i;
struct iso_inode_info isofs_i;
struct nfs_inode_info nfs_i;
- struct xiafs_inode_info xiafs_i;
struct sysv_inode_info sysv_i;
struct affs_inode_info affs_i;
struct ufs_inode_info ufs_i;
+ struct romfs_inode_info romfs_i;
struct socket socket_i;
void * generic_ip;
} u;
extern int fasync_helper(struct inode *, struct file *, int, struct fasync_struct **);
#include <linux/minix_fs_sb.h>
-#include <linux/ext_fs_sb.h>
#include <linux/ext2_fs_sb.h>
#include <linux/hpfs_fs_sb.h>
#include <linux/msdos_fs_sb.h>
#include <linux/iso_fs_sb.h>
#include <linux/nfs_fs_sb.h>
-#include <linux/xia_fs_sb.h>
#include <linux/sysv_fs_sb.h>
#include <linux/affs_fs_sb.h>
#include <linux/ufs_fs_sb.h>
+#include <linux/romfs_fs_sb.h>
struct super_block {
kdev_t s_dev;
struct wait_queue * s_wait;
union {
struct minix_sb_info minix_sb;
- struct ext_sb_info ext_sb;
struct ext2_sb_info ext2_sb;
struct hpfs_sb_info hpfs_sb;
struct msdos_sb_info msdos_sb;
struct isofs_sb_info isofs_sb;
struct nfs_sb_info nfs_sb;
- struct xiafs_sb_info xiafs_sb;
struct sysv_sb_info sysv_sb;
struct affs_sb_info affs_sb;
struct ufs_sb_info ufs_sb;
+ struct romfs_sb_info romfs_sb;
void *generic_sbp;
} u;
};
#define IPV6_RXSRCRT 5
#define IPV6_PKTOPTIONS 6
#define IPV6_CHECKSUM 7
+#define IPV6_HOPLIMIT 8
/*
* Alternative names
--- /dev/null
+/* Symbol versioning nastiness. */
+
+#define __SYMBOL_VERSION(x) __ver_ ## x
+#define __VERSIONED_SYMBOL2(x,v) x ## _R ## v
+#define __VERSIONED_SYMBOL1(x,v) __VERSIONED_SYMBOL2(x,v)
+#define __VERSIONED_SYMBOL(x) __VERSIONED_SYMBOL1(x,__SYMBOL_VERSION(x))
+
+#ifndef _set_ver
+#define _set_ver(x) __VERSIONED_SYMBOL(x)
+#endif
#define _LINUX_MODULE_H
#ifdef __GENKSYMS__
-# undef MODVERSIONS
-# define MODVERSIONS
+# define _set_ver(sym) sym
+# undef MODVERSIONS
+# define MODVERSIONS
#else /* ! __GENKSYMS__ */
-# if defined(MODVERSIONS) && !defined(MODULE) && defined(EXPORT_SYMTAB)
+# if !defined(MODVERSIONS) && defined(EXPORT_SYMTAB)
+# define _set_ver(sym) sym
# include <linux/modversions.h>
# endif
#endif /* __GENKSYMS__ */
+
/* Don't need to bring in all of uaccess.h just for this decl. */
struct exception_table_entry;
struct module_ref *next_ref;
};
+/* TBD */
+struct module_persist;
+
struct module
{
unsigned long size_of_struct; /* == sizeof(module) */
#ifdef __alpha__
unsigned long gp;
#endif
+ /* Members past this point are extensions to the basic
+ module support and are optional. Use mod_opt_member()
+ to examine them. */
+ const struct module_persist *persist_start;
+ const struct module_persist *persist_end;
};
struct module_info
#define MOD_DELETED 2
#define MOD_AUTOCLEAN 4
#define MOD_VISITED 8
+#define MOD_USED_ONCE 16
/* Values for query_module's which. */
#define GET_USE_COUNT(module) ((module)->usecount)
+/* When the struct module is extended, new values must be examined using
+ this macro. It returns a pointer to the member if available, NULL
+ otherwise. */
+
+#define mod_opt_member(mod,member) \
+ ({ struct module *_mod = (mod); \
+ __typeof__(_mod->member) *_mem = &_mod->member; \
+ ((char *)(_mem+1) > (char *)_mod + _mod->size_of_struct \
+ ? (__typeof__(_mod->member) *)NULL : _mem); \
+ })
+
/* Indirect stringification. */
#define __MODULE_STRING_1(x) #x
#define __MODULE_STRING(x) __MODULE_STRING_1(x)
-#ifdef MODULE
+#if defined(MODULE) && !defined(__GENKSYMS__)
/* Embedded module documentation macros. */
const char __module_author[] __attribute__((section(".modinfo"))) = \
"author=" name
+#define MODULE_DESCRIPTION(desc) \
+const char __module_description[] __attribute__((section(".modinfo"))) = \
+"description=" desc
+
/* Could potentially be used by kerneld... */
#define MODULE_SUPPORTED_DEVICE(dev) \
__attribute__((section(".modinfo"))) = \
"parm_" __MODULE_STRING(var) "=" type
+#define MODULE_PARM_DESC(var,desc) \
+const char __module_parm_desc_##var[] \
+__attribute__((section(".modinfo"))) = \
+"parm_desc_" __MODULE_STRING(var) "=" desc
+
/* The attributes of a section are set the first time the section is
- seen; we want .modinfo to not be allocated. This header should be
- included before any functions or variables are defined. */
+ seen; we want .modinfo to not be allocated. */
-__asm__(".section .modinfo\n\t.text");
+__asm__(".section .modinfo\n\t.previous");
/* Define the module variable, and usage macros. */
extern struct module __this_module;
-#define MOD_INC_USE_COUNT \
- (__this_module.usecount++, __this_module.flags |= MOD_VISITED)
-#define MOD_DEC_USE_COUNT \
+#define MOD_INC_USE_COUNT \
+ (__this_module.usecount++, \
+ __this_module.flags |= MOD_VISITED|MOD_USED_ONCE)
+#define MOD_DEC_USE_COUNT \
(__this_module.usecount--, __this_module.flags |= MOD_VISITED)
-#define MOD_IN_USE \
+#define MOD_IN_USE \
(__this_module.usecount != 0)
#ifndef __NO_VERSION__
#include <linux/version.h>
const char __module_kernel_version[] __attribute__((section(".modinfo"))) =
"kernel_version=" UTS_RELEASE;
-#if defined(MODVERSIONS) && !defined(__GENKSYMS__)
+#ifdef MODVERSIONS
const char __module_using_checksums[] __attribute__((section(".modinfo"))) =
"using_checksums=1";
#endif
#else /* MODULE */
#define MODULE_AUTHOR(name)
+#define MODULE_DESCRIPTION(desc)
#define MODULE_SUPPORTED_DEVICE(name)
#define MODULE_PARM(var,type)
+#define MODULE_PARM_DESC(var,desc)
+
+#ifndef __GENKSYMS__
#define MOD_INC_USE_COUNT do { } while (0)
#define MOD_DEC_USE_COUNT do { } while (0)
extern struct module *module_list;
+#endif /* !__GENKSYMS__ */
+
#endif /* MODULE */
/* Export a symbol either from the kernel or a module.
/* We want the EXPORT_SYMBOL tag left intact for recognition. */
+#elif !defined(EXPORT_SYMTAB)
+
+#define __EXPORT_SYMBOL(sym,str) error EXPORT_SYMTAB_not_defined
+#define EXPORT_SYMBOL(var) error EXPORT_SYMTAB_not_defined
+#define EXPORT_SYMBOL_NOVERS(var) error EXPORT_SYMTAB_not_defined
+
+#elif !defined(AUTOCONF_INCLUDED)
+
+#define __EXPORT_SYMBOL(sym,str) error config_must_be_included_before_module
+#define EXPORT_SYMBOL(var) error config_must_be_included_before_module
+#define EXPORT_SYMBOL_NOVERS(var) error config_must_be_included_before_module
+
#elif !defined(CONFIG_MODULES)
+#define __EXPORT_SYMBOL(sym,str)
#define EXPORT_SYMBOL(var)
#define EXPORT_SYMBOL_NOVERS(var)
-#define EXPORT_NO_SYMBOLS
#else
-#define EXPORT_SYMBOL(var) \
-const struct module_symbol __export_##var \
-__attribute__((section("__ksymtab"))) = { \
- (unsigned long)&var, __MODULE_STRING(var) \
-} \
+#define __EXPORT_SYMBOL(sym, str) \
+const char __kstrtab_##sym[] \
+__attribute__((section(".kstrtab"))) = str; \
+const struct module_symbol __ksymtab_##sym \
+__attribute__((section("__ksymtab"))) = \
+{ (unsigned long)&sym, __kstrtab_##sym }
-#define EXPORT_SYMBOL_NOVERS(var) EXPORT_SYMBOL(var)
+#if defined(MODVERSIONS) || !defined(CONFIG_MODVERSIONS)
+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
+#else
+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
+#endif
+
+#define EXPORT_SYMBOL_NOVERS(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
+
+#endif /* __GENKSYMS__ */
#ifdef MODULE
/* Force a module to export no symbols. */
-#define EXPORT_NO_SYMBOLS \
-__asm__(".section __ksymtab\n.text")
+#define EXPORT_NO_SYMBOLS __asm__(".section __ksymtab\n.previous")
#else
#define EXPORT_NO_SYMBOLS
#endif /* MODULE */
-#endif
-
#endif /* _LINUX_MODULE_H */
--- /dev/null
+#ifndef __LINUX_ROMFS_FS_H
+#define __LINUX_ROMFS_FS_H
+
+/* The basic structures of the romfs filesystem */
+
+#define ROMBSIZE BLOCK_SIZE
+#define ROMBSBITS BLOCK_SIZE_BITS
+#define ROMBMASK (ROMBSIZE-1)
+#define ROMFS_MAGIC 0x7275
+
+#define ROMFS_MAXFN 128
+
+#define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff))
+#define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff))
+#define __mk4(a,b,c,d) htonl(__mkl(__mkw(a,b),__mkw(c,d)))
+#define ROMSB_WORD0 __mk4('-','r','o','m')
+#define ROMSB_WORD1 __mk4('1','f','s','-')
+
+/* On-disk "super block" */
+
+struct romfs_super_block {
+ __u32 word0;
+ __u32 word1;
+ __u32 size;
+ __u32 checksum;
+ char name[0]; /* volume name */
+};
+
+/* On disk inode */
+
+struct romfs_inode {
+ __u32 next; /* low 4 bits see ROMFH_ */
+ __u32 spec;
+ __u32 size;
+ __u32 checksum;
+ char name[0];
+};
+
+#define ROMFH_TYPE 7
+#define ROMFH_HRD 0
+#define ROMFH_DIR 1
+#define ROMFH_REG 2
+#define ROMFH_SYM 3
+#define ROMFH_BLK 4
+#define ROMFH_CHR 5
+#define ROMFH_SCK 6
+#define ROMFH_FIF 7
+#define ROMFH_EXEC 8
+
+/* Alignment */
+
+#define ROMFH_SIZE 16
+#define ROMFH_PAD (ROMFH_SIZE-1)
+#define ROMFH_MASK (~ROMFH_PAD)
+
+#ifdef __KERNEL__
+
+/* Not much now */
+extern int init_romfs_fs(void);
+
+#endif /* __KERNEL__ */
+#endif
--- /dev/null
+#ifndef __ROMFS_FS_I
+#define __ROMFS_FS_I
+
+/* inode in-kernel data */
+
+struct romfs_inode_info {
+ unsigned long i_metasize; /* size of non-data area */
+ unsigned long i_dataoffset; /* from the start of fs */
+};
+
+#endif
--- /dev/null
+#ifndef __ROMFS_FS_SB
+#define __ROMFS_FS_SB
+
+/* romfs superblock in-core data */
+
+struct romfs_sb_info {
+ unsigned long s_maxsize;
+};
+
+#endif
+++ /dev/null
-#ifndef _XIA_FS_H
-#define _XIA_FS_H
-
-/*
- * include/linux/xia_fs.h
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix_fs.h.
- * Copyright (C) Linus Torvalds, 1991, 1992.
- */
-
-#define _XIAFS_SUPER_MAGIC 0x012FD16D
-#define _XIAFS_ROOT_INO 1
-#define _XIAFS_BAD_INO 2
-
-#define _XIAFS_NAME_LEN 248
-
-#define _XIAFS_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof(struct xiafs_inode)))
-
-struct xiafs_inode { /* 64 bytes */
- mode_t i_mode;
- nlink_t i_nlinks;
- uid_t i_uid;
- gid_t i_gid;
- size_t i_size; /* 8 */
- time_t i_ctime;
- time_t i_atime;
- time_t i_mtime;
- daddr_t i_zone[8];
- daddr_t i_ind_zone;
- daddr_t i_dind_zone;
-};
-
-/*
- * linux super-block data on disk
- */
-struct xiafs_super_block {
- u_char s_boot_segment[512]; /* 1st sector reserved for boot */
- u_long s_zone_size; /* 0: the name says it */
- u_long s_nzones; /* 1: volume size, zone aligned */
- u_long s_ninodes; /* 2: # of inodes */
- u_long s_ndatazones; /* 3: # of data zones */
- u_long s_imap_zones; /* 4: # of imap zones */
- u_long s_zmap_zones; /* 5: # of zmap zones */
- u_long s_firstdatazone; /* 6: first data zone */
- u_long s_zone_shift; /* 7: z size = 1KB << z shift */
- u_long s_max_size; /* 8: max size of a single file */
- u_long s_reserved0; /* 9: reserved */
- u_long s_reserved1; /* 10: */
- u_long s_reserved2; /* 11: */
- u_long s_reserved3; /* 12: */
- u_long s_firstkernzone; /* 13: first kernel zone */
- u_long s_kernzones; /* 14: kernel size in zones */
- u_long s_magic; /* 15: magic number for xiafs */
-};
-
-struct xiafs_direct {
- ino_t d_ino;
- u_short d_rec_len;
- u_char d_name_len;
- char d_name[_XIAFS_NAME_LEN+1];
-};
-
-#ifdef __KERNEL__
-
-extern int xiafs_lookup(struct inode * dir,const char * name, int len,
- struct inode ** result);
-extern int xiafs_create(struct inode * dir,const char * name, int len, int mode,
- struct inode ** result);
-extern int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode);
-extern int xiafs_rmdir(struct inode * dir, const char * name, int len);
-extern int xiafs_unlink(struct inode * dir, const char * name, int len);
-extern int xiafs_symlink(struct inode * inode, const char * name, int len,
- const char * symname);
-extern int xiafs_link(struct inode * oldinode, struct inode * dir,
- const char * name, int len);
-extern int xiafs_mknod(struct inode * dir, const char * name, int len,
- int mode, int rdev);
-extern int xiafs_rename(struct inode * old_dir, const char * old_name,
- int old_len, struct inode * new_dir,
- const char * new_name, int new_len,
- int must_be_dir);
-extern struct inode * xiafs_new_inode(struct inode * dir);
-extern void xiafs_free_inode(struct inode * inode);
-extern unsigned long xiafs_count_free_inodes(struct super_block *sb);
-extern int xiafs_new_zone(struct super_block * sb, u_long prev_addr);
-extern void xiafs_free_zone(struct super_block * sb, int block);
-extern unsigned long xiafs_count_free_zones(struct super_block *sb);
-
-extern int xiafs_bmap(struct inode *,int);
-
-extern struct buffer_head * xiafs_getblk(struct inode *, int, int);
-extern struct buffer_head * xiafs_bread(struct inode *, int, int);
-
-extern void xiafs_truncate(struct inode *);
-extern void xiafs_put_super(struct super_block *);
-extern struct super_block *xiafs_read_super(struct super_block *,void *,int);
-extern int init_xiafs_fs(void);
-extern void xiafs_read_inode(struct inode *);
-extern void xiafs_write_inode(struct inode *);
-extern void xiafs_put_inode(struct inode *);
-extern void xiafs_statfs(struct super_block *, struct statfs *, int);
-extern int xiafs_sync_inode(struct inode *);
-extern int xiafs_sync_file(struct inode *, struct file *);
-
-extern struct inode_operations xiafs_file_inode_operations;
-extern struct inode_operations xiafs_dir_inode_operations;
-extern struct inode_operations xiafs_symlink_inode_operations;
-
-#endif /* __KERNEL__ */
-
-#endif /* _XIA_FS_H */
-
-
-
-
-
-
-
-
+++ /dev/null
-#ifndef _XIA_FS_I_H
-#define _XIA_FS_I_H
-
-/*
- * include/linux/xia_fs_i.h
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix_fs_i.h.
- * Copyright (C) Linus Torvalds, 1991, 1992.
- */
-
-struct xiafs_inode_info { /* for data zone pointers */
- unsigned long i_zone[8];
- unsigned long i_ind_zone;
- unsigned long i_dind_zone;
-};
-
-#endif /* _XIA_FS_I_H */
+++ /dev/null
-#ifndef _XIA_FS_SB_H
-#define _XIA_FS_SB_H
-
-/*
- * include/linux/xia_fs_sb.h
- *
- * Copyright (C) Q. Frank Xia, 1993.
- *
- * Based on Linus' minix_fs_sb.h.
- * Copyright (C) Linus Torvalds, 1991, 1992.
- */
-
-#define _XIAFS_IMAP_SLOTS 8
-#define _XIAFS_ZMAP_SLOTS 32
-
-struct xiafs_sb_info {
- u_long s_nzones;
- u_long s_ninodes;
- u_long s_ndatazones;
- u_long s_imap_zones;
- u_long s_zmap_zones;
- u_long s_firstdatazone;
- u_long s_zone_shift;
- u_long s_max_size; /* 32 bytes */
- struct buffer_head * s_imap_buf[_XIAFS_IMAP_SLOTS]; /* 32 bytes */
- struct buffer_head * s_zmap_buf[_XIAFS_ZMAP_SLOTS]; /* 128 bytes */
- int s_imap_iznr[_XIAFS_IMAP_SLOTS]; /* 32 bytes */
- int s_zmap_zznr[_XIAFS_ZMAP_SLOTS]; /* 128 bytes */
- u_char s_imap_cached; /* flag for cached imap */
- u_char s_zmap_cached; /* flag for cached imap */
-};
-
-#endif /* _XIA_FS_SB_H */
-
-
-
struct in6_addr * saddr,
struct device *dev,
struct ipv6_options *opt,
- int proto, int noblock);
+ int proto, int hlimit,
+ int noblock);
/*
* rcv function (called from netdevice level)
__u8 recvsrcrt:1,
rxinfo:1,
+ rxhlim:1,
+ hopopts:1,
+ dstopts:1,
mc_loop:1,
- unused:4;
+ unused:2;
/* device for outgoing mcast packets */
extern int datagram_send_ctl(struct msghdr *msg,
struct device **src_dev,
struct in6_addr **src_addr,
- struct ipv6_options *opt);
+ struct ipv6_options *opt,
+ int *hlimit);
#define LOOPBACK4_IPV6 __constant_htonl(0x7f000006)
* GK 2/5/95 - Changed to support mounting root fs via NFS
* Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
* Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
+ * Simplified starting of init: Michael A. Griffith <grif@acm.org>
*/
#define __KERNEL_SYSCALLS__
extern char _stext, _etext;
extern char *linux_banner;
-static char printbuf[1024];
-
extern int console_loglevel;
static int init(void *);
static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
-static char * argv_rc[] = { "/bin/sh", NULL };
-static char * envp_rc[] = { "HOME=/", "TERM=linux", NULL };
-
char *get_options(char *str, int *ints)
{
char *cur = str;
cpu_idle(NULL);
}
-static int printf(const char *fmt, ...)
-{
- va_list args;
- int i;
-
- va_start(args, fmt);
- write(1,printbuf,i=vsprintf(printbuf, fmt, args));
- va_end(args);
- return i;
-}
-
-static int do_rc(void * rc)
-{
- close(0);
- if (open(rc,O_RDONLY,0))
- return -1;
- return execve("/bin/sh", argv_rc, envp_rc);
-}
-
-static int do_shell(void * shell)
-{
- char *argv[2];
-
- close(0);close(1);close(2);
- setsid();
- (void) open("/dev/tty1",O_RDWR,0);
- (void) dup(0);
- (void) dup(0);
- argv[0] = shell;
- argv[1] = NULL;
- return execve(shell, argv, envp_rc);
-}
-
#ifdef CONFIG_BLK_DEV_INITRD
static int do_linuxrc(void * shell)
{
static int init(void * unused)
{
- int pid,i;
#ifdef CONFIG_BLK_DEV_INITRD
int real_root_mountflags;
#endif
(void) dup(0);
(void) dup(0);
+
+ /*
+ * We try each of these until one succeeds.
+ *
+ * The Bourne shell can be used instead of init if we are
+ * trying to recover a really broken machine.
+ */
- if (!execute_command) {
- execve("/etc/init",argv_init,envp_init);
- execve("/bin/init",argv_init,envp_init);
- execve("/sbin/init",argv_init,envp_init);
- /* if this fails, fall through to original stuff */
-
- pid = kernel_thread(do_rc, "/etc/rc", SIGCHLD);
- if (pid>0)
- while (pid != wait(&i))
- /* nothing */;
- }
-
- while (1) {
- pid = kernel_thread(do_shell,
- execute_command ? execute_command : "/bin/sh",
- SIGCHLD);
- if (pid < 0) {
- printf("Fork failed in init\n\r");
- continue;
- }
- while (1)
- if (pid == wait(&i))
- break;
- printf("\n\rchild %d died with code %04x\n\r",pid,i);
- sync();
- }
- return -1;
+ execve(execute_command,argv_init,envp_init);
+ execve("/etc/init",argv_init,envp_init);
+ execve("/bin/init",argv_init,envp_init);
+ execve("/sbin/init",argv_init,envp_init);
+ execve("/bin/sh",argv_init,envp_init);
+ panic("No init found. Try passing init= option to kernel.");
}
* by Bjorn Ekwall <bj0rn@blox.se>
*/
-#include <linux/module.h>
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/fs.h>
EXPORT_SYMBOL(___strtok);
EXPORT_SYMBOL(init_fifo);
EXPORT_SYMBOL(super_blocks);
-EXPORT_SYMBOL(reuse_list);
EXPORT_SYMBOL(fifo_inode_operations);
EXPORT_SYMBOL(chrdev_inode_operations);
EXPORT_SYMBOL(blkdev_inode_operations);
NULL, /* cleanup */
__start___ex_table, /* ex_table_start */
__stop___ex_table, /* ex_table_end */
-#ifdef __alpha__
- NULL, /* gp */
-#endif
+ /* Rest are NULL */
};
struct module *module_list = &kernel_module;
goto err1;
}
- /* In the future we can check for various known sizes, but for
- now there is only one. */
+ /* Check for legal module header sizes. */
if ((error = get_user(mod_user_size, &mod_user->size_of_struct)) != 0)
goto err1;
- if (mod_user_size != sizeof(struct module)) {
+ switch (mod_user_size) {
+ case sizeof(struct module):
+ case &((struct module *)0L)->persist_start:
+ break;
+ default:
printk(KERN_ERR "init_module: Invalid module header size.\n"
KERN_ERR "A new version of the modutils is likely "
"needed.\n");
next = mod->next;
if (mod->refs == NULL &&
mod->usecount == 0 &&
- ((mod->flags & (MOD_AUTOCLEAN|MOD_RUNNING|MOD_DELETED))
- == (MOD_AUTOCLEAN|MOD_RUNNING))) {
+ ((mod->flags
+ & (MOD_AUTOCLEAN|MOD_RUNNING|MOD_DELETED|MOD_USED_ONCE))
+ == (MOD_AUTOCLEAN|MOD_RUNNING|MOD_USED_ONCE))) {
if (mod->flags & MOD_VISITED)
mod->flags &= ~MOD_VISITED;
else
* 4 entries at most). The current demux assumes this.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
endif
endif
-L_TARGET := network.a
-L_OBJS := socket.o protocols.o sysctl_net.o $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
+# We must attach netsyms.o to socket.o, as otherwise there is nothing
+# to pull the object file from the archive.
+
+SOCK := socket.o
ifeq ($(CONFIG_NET),y)
ifeq ($(CONFIG_MODULES),y)
-LX_OBJS = netsyms.o
+O_TARGET := sock_n_syms.o
+O_OBJS := socket.o
+OX_OBJS := netsyms.o
+SOCK := $(O_TARGET)
endif
endif
+L_TARGET := network.a
+L_OBJS := $(SOCK) protocols.o sysctl_net.o $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
+
M_OBJS :=
CONFIG_NETLINK_BUILTIN :=
* much hacked by: Alan Cox
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/firewall.h>
tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o\
raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o ip_fw.o \
sysctl_net_ipv4.o fib.o ip_nat_dumb.o
+IPV4X_OBJS :=
MOD_LIST_NAME := IPV4_MODULES
M_OBJS :=
endif
ifeq ($(CONFIG_IP_MASQUERADE),y)
-IPV4_OBJS += ip_masq.o ip_masq_app.o
+IPV4X_OBJS += ip_masq.o ip_masq_app.o
M_OBJS += ip_masq_ftp.o ip_masq_irc.o ip_masq_raudio.o
endif
ifdef CONFIG_INET
O_OBJS := $(IPV4_OBJS)
+OX_OBJS := $(IPV4X_OBJS)
endif
include $(TOPDIR)/Rules.make
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <asm/system.h>
#include <linux/types.h>
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <asm/system.h>
#include <linux/types.h>
cmsg = (struct cmsghdr *)((u8*) cmsg + cmsg->cmsg_len);
}
+ if (np->rxhlim && (len >= sizeof(struct cmsghdr) + sizeof(int)))
+ {
+ int *hlim;
+
+ cmsg->cmsg_len = (sizeof(struct cmsghdr) + sizeof(int));
+ cmsg->cmsg_level = SOL_IPV6;
+ cmsg->cmsg_type = IPV6_HOPLIMIT;
+
+ hlim = (int *) cmsg->cmsg_data;
+ *hlim = skb->nh.ipv6h->hop_limit;
+
+ len -= cmsg->cmsg_len;
+ msg->msg_controllen += cmsg->cmsg_len;
+ cmsg = (struct cmsghdr *)((u8*) cmsg + cmsg->cmsg_len);
+ }
+
if (opt->srcrt)
{
int hdrlen = sizeof(struct rt0_hdr) + (opt->srcrt->hdrlen << 3);
int datagram_send_ctl(struct msghdr *msg, struct device **src_dev,
- struct in6_addr **src_addr, struct ipv6_options *opt)
+ struct in6_addr **src_addr, struct ipv6_options *opt,
+ int *hlimit)
{
struct inet6_dev *in6_dev = NULL;
struct in6_pktinfo *src_info;
struct cmsghdr *cmsg;
struct ipv6_rt_hdr *rthdr;
int len;
- int err = -EINVAL;
+ int err = 0;
for (cmsg = msg->msg_control; cmsg; cmsg = cmsg_nxthdr(msg, cmsg))
{
if (cmsg->cmsg_len < (sizeof(struct cmsghdr) +
sizeof(struct in6_pktinfo)))
{
+ err = -EINVAL;
goto exit_f;
}
in6_dev = ipv6_dev_by_index(src_info->ipi6_ifindex);
if (in6_dev == NULL)
{
+ err = -ENODEV;
goto exit_f;
}
if ( ifp == NULL)
{
+ err = -EINVAL;
goto exit_f;
}
*src_addr = &src_info->ipi6_addr;
- err = 0;
}
break;
/* validate option length */
if (len < sizeof(struct ipv6_rt_hdr))
{
+ err = -EINVAL;
goto exit_f;
}
*/
if (rthdr->type)
{
+ err = -EINVAL;
goto exit_f;
}
if (((rthdr->hdrlen + 1) << 3) < len)
- {
+ {
+ err = -EINVAL;
goto exit_f;
}
/* segments left must also match */
if ((rthdr->hdrlen >> 1) != rthdr->segments_left)
{
+ err = -EINVAL;
goto exit_f;
}
opt->opt_nflen += ((rthdr->hdrlen + 1) << 3);
opt->srcrt = rthdr;
- err = 0;
break;
+
+ case IPV6_HOPLIMIT:
+
+ len = cmsg->cmsg_len;
+ len -= sizeof(struct cmsghdr);
+
+ if (len < sizeof(int))
+ {
+ err = -EINVAL;
+ goto exit_f;
+ }
+
+ *hlimit = *((int *) cmsg->cmsg_data);
+ break;
+
default:
printk(KERN_DEBUG "invalid cmsg type: %d\n",
cmsg->cmsg_type);
+ err = -EINVAL;
break;
}
}
ipv6_build_xmit(sk, icmpv6_getfrag, &msg, &hdr->saddr, len,
- saddr, src_dev, NULL, IPPROTO_ICMPV6, 1);
+ saddr, src_dev, NULL, IPPROTO_ICMPV6, 0, 1);
}
static void icmpv6_echo_reply(struct sk_buff *skb)
msg.daddr = &hdr->saddr;
ipv6_build_xmit(sk, icmpv6_getfrag, &msg, &hdr->saddr, len, saddr,
- skb->dev, NULL, IPPROTO_ICMPV6, 1);
+ skb->dev, NULL, IPPROTO_ICMPV6, 0, 1);
}
static __inline__ int ipv6_ext_hdr(u8 nexthdr)
int ipv6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
struct in6_addr *dest, unsigned short int length,
struct in6_addr *saddr, struct device *dev,
- struct ipv6_options *opt, int proto,
+ struct ipv6_options *opt, int proto, int hlimit,
int noblock)
{
rt6_output_method_t output_method = default_output_method;
- int hlimit;
struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
struct dest_entry *dc = NULL;
struct in6_addr *daddr = dest;
}
addr_type = ipv6_addr_type(daddr);
- if (addr_type & IPV6_ADDR_MULTICAST)
+
+ if (hlimit < 1)
{
- hlimit = np->mcast_hops;
- if (dev == NULL)
+ if (addr_type & IPV6_ADDR_MULTICAST)
{
- dev = np->mc_if;
+ hlimit = np->mcast_hops;
+ if (dev == NULL)
+ {
+ dev = np->mc_if;
+ }
}
+ else
+ hlimit = np->hop_limit;
}
- else
- hlimit = np->hop_limit;
-
+
if (addr_type & (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_SITELOCAL |
IPV6_ADDR_MULTICAST))
{
retv = 0;
break;
+ case IPV6_HOPLIMIT:
+ np->rxhlim = val;
+ retv = 0;
+ break;
+
case IPV6_UNICAST_HOPS:
if (val > 255)
{
*addr_len = sizeof(struct sockaddr_in6);
}
- if (msg->msg_control)
+ if (msg->msg_controllen)
{
int err;
struct in6_addr *daddr;
struct raw6_opt *raw_opt;
u16 proto;
+ int hlimit = 0;
int err;
opt = &opt_space;
memset(opt, 0, sizeof(struct ipv6_options));
- err = datagram_send_ctl(msg, &dev, &saddr, opt);
+ err = datagram_send_ctl(msg, &dev, &saddr, opt, &hlimit);
if (err < 0)
{
printk(KERN_DEBUG "invalid msg_control\n");
}
err = ipv6_build_xmit(sk, rawv6_frag_cksum, &hdr, daddr, len,
- saddr, dev, opt, proto, msg->msg_flags&MSG_DONTWAIT);
+ saddr, dev, opt, proto, hlimit,
+ msg->msg_flags&MSG_DONTWAIT);
}
else
{
err = ipv6_build_xmit(sk, rawv6_getfrag, msg->msg_iov, daddr,
- len, saddr, dev, opt, proto,
+ len, saddr, dev, opt, proto, hlimit,
msg->msg_flags&MSG_DONTWAIT);
}
struct in6_addr *saddr = NULL;
int len = ulen + sizeof(struct udphdr);
int addr_type;
+ int hlimit = 0;
int err;
opt = &opt_space;
memset(opt, 0, sizeof(struct ipv6_options));
- err = datagram_send_ctl(msg, &dev, &saddr, opt);
+ err = datagram_send_ctl(msg, &dev, &saddr, opt, &hlimit);
if (err < 0)
{
printk(KERN_DEBUG "invalid msg_control\n");
udh.pl_len = len;
err = ipv6_build_xmit(sk, udpv6_getfrag, &udh, daddr, len,
- saddr, dev, opt, IPPROTO_UDP, msg->msg_flags&MSG_DONTWAIT);
+ saddr, dev, opt, IPPROTO_UDP, hlimit,
+ msg->msg_flags&MSG_DONTWAIT);
if (err < 0)
return err;
* "AS-IS" and at no charge.
*/
-#include <linux/module.h>
-
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
struct iovec *iov=iovstack;
struct msghdr msg_sys;
void * krn_msg_ctl = NULL;
+ void * usr_msg_ctl = NULL;
int err;
int total_len;
- int len;
+ int len = 0;
/* kernel mode address */
char addr[MAX_SOCK_ADDR];
if (msg_sys.msg_controllen)
{
+ /*
+ * FIXME:
+ * I'm assuming that the kernel may have to examine
+ * the acciliary control messages passed by the user.
+ * Find out what POSIX says about this...
+ */
krn_msg_ctl = kmalloc(msg_sys.msg_controllen, GFP_KERNEL);
if (!krn_msg_ctl)
err = copy_from_user(krn_msg_ctl, msg_sys.msg_control,
msg_sys.msg_controllen);
if (err)
+ {
+ err = -EFAULT;
goto flush_it;
+ }
+ usr_msg_ctl = msg_sys.msg_control;
msg_sys.msg_control = krn_msg_ctl;
}
{
err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr,
uaddr_len);
-
}
- if (!err && msg_sys.msg_controllen)
+ if (err >= 0 && msg_sys.msg_controllen)
{
- err = copy_to_user(msg_sys.msg_control, krn_msg_ctl,
+ err = copy_to_user(usr_msg_ctl, krn_msg_ctl,
msg_sys.msg_controllen);
}
kfree(krn_msg_ctl);
}
- if (err)
+ if (err < 0)
return err;
if (put_user(msg_sys.msg_flags, &msg->msg_flags))
echo "/*" > $CONFIG_H
echo " * Automatically generated C config: don't edit" >> $CONFIG_H
echo " */" >> $CONFIG_H
+echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H
DEFAULT=""
if [ "$1" = "-d" ] ; then
echo "/*" >$CONFIG_H
echo " * Automatically generated by make menuconfig: don't edit" >>$CONFIG_H
echo " */" >>$CONFIG_H
+ echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H
MAKE=: #To prevent sound Makefile from running.
#include <sys/mman.h>
char *filename, *command, __depname[256] = "\n\t@touch ";
-int needsconfig, hasconfig, hasdep;
+int needsconfig, hasconfig, hasmodules, hasdep;
#define depname (__depname+9)
int plen;
struct path_struct *path = path_array+type;
- if (len == 14 && !memcmp(name, "linux/config.h", len))
- hasconfig = 1;
+ if (len == 14)
+ if (!memcmp(name, "linux/config.h", len))
+ hasconfig = 1;
+ else if (!memcmp(name, "linux/module.h", len))
+ hasmodules = 1;
plen = path->len;
memcpy(path->buffer+plen, name, len);
command = "";
}
}
- needsconfig = hasconfig = hasdep = 0;
+ needsconfig = hasconfig = hasmodules = hasdep = 0;
do_depend();
- if (hasconfig && !needsconfig)
+ if (hasconfig && !hasmodules && !needsconfig)
fprintf(stderr, "%s doesn't need config\n", filename);
}
return 0;
printf("\tputs $autocfg \"/*\"\n");
printf("\tputs $autocfg \" * Automatically generated C config: don't edit\"\n");
printf("\tputs $autocfg \" */\"\n");
+ printf("\tputs $autocfg \"#define AUTOCONF_INCLUDED\"\n");
for(cfg = scfg; cfg != NULL; cfg = cfg->next)
{
switch (cfg->tok)