diff options
-rw-r--r-- | drivers/sound/Config.in | 284 | ||||
-rw-r--r-- | fs/Config.in | 3 | ||||
-rw-r--r-- | fs/Makefile | 8 | ||||
-rw-r--r-- | fs/efs/Makefile | 17 | ||||
-rw-r--r-- | fs/efs/dir.c | 132 | ||||
-rw-r--r-- | fs/efs/file.c | 218 | ||||
-rw-r--r-- | fs/efs/inode.c | 496 | ||||
-rw-r--r-- | fs/efs/namei.c | 143 | ||||
-rw-r--r-- | fs/efs/symlink.c | 136 | ||||
-rw-r--r-- | fs/filesystems.c | 5 | ||||
-rw-r--r-- | include/linux/fs.h | 4 |
11 files changed, 1435 insertions, 11 deletions
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index 310bf01bf..d14653d45 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -1,15 +1,277 @@ -# -# Sound driver configuration -# -#-------- -# There is another confic script which is compatible with rest of -# the kernel. It can be activated by running 'make mkscript' in this -# directory. Please note that this is an _experimental_ feature which -# doesn't work with all cards (PSS, SM Wave, AudioTriX Pro, Maui). -#-------- -# -$MAKE -C drivers/sound config || exit 1 +bool 'ProAudioSpectrum 16 support' CONFIG_PAS +bool '100%% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB +bool 'Generic OPL2/OPL3 FM synthesizer support' CONFIG_ADLIB +bool 'Gravis Ultrasound support' CONFIG_GUS +bool 'MPU-401 support (NOT for SB16)' CONFIG_MPU401 +bool 'PSS (ECHO-ADI2111) support' CONFIG_PSS +bool '16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_GUS16 +bool 'GUS MAX support' CONFIG_GUSMAX +bool 'Microsoft Sound System support' CONFIG_MSS +bool 'Ensoniq SoundScape support' CONFIG_SSCAPE +bool 'MediaTrix AudioTrix Pro support' CONFIG_TRIX +bool 'Support for MAD16 and/or Mozart based cards' CONFIG_MAD16 +bool 'Support for Crystal CS4232 based (PnP) cards' CONFIG_CS4232 +bool 'Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_MAUI +bool 'FM synthesizer (YM3812/OPL-3) support' CONFIG_YM3812 + +if [ "$CONFIG_AEDSP16" = "y" ]; then +hex 'I/O base for Audio Excel DSP 16 220 or 240' AEDSP16_BASE 220 +fi + +if [ "$CONFIG_SB" = "y" ]; then +hex 'I/O base for SB Check from manual of the card' SBC_BASE 220 +fi + +if [ "$CONFIG_SB" = "y" ]; then +int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7 +fi + +if [ "$CONFIG_SB" = "y" ]; then +int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1 +fi + +if [ "$CONFIG_SB" = "y" ]; then +int 'Sound Blaster 16 bit DMA (SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5 +fi + +if [ "$CONFIG_SB" = "y" ]; then +hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 330 +fi + + +if [ "$CONFIG_SB" = "y" ]; then +comment 'MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.' +fi + + +if [ "$CONFIG_SB" = "y" ]; then +comment 'Enter -1 to the following question if you have something else such as SB16/32.' +fi + +if [ "$CONFIG_SB" = "y" ]; then +int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' SB_MPU_IRQ -1 +fi + +if [ "$CONFIG_PAS" = "y" ]; then +int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10 +fi + +if [ "$CONFIG_PAS" = "y" ]; then +int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3 +fi + +if [ "$CONFIG_GUS" = "y" ]; then +hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220 +fi + +if [ "$CONFIG_GUS" = "y" ]; then +int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15 +fi + +if [ "$CONFIG_GUS" = "y" ]; then +int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6 +fi + +if [ "$CONFIG_GUS" = "y" ]; then +int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1 +fi + +if [ "$CONFIG_GUS16" = "y" ]; then +hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530 +fi + +if [ "$CONFIG_GUS16" = "y" ]; then +int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7 +fi + +if [ "$CONFIG_GUS16" = "y" ]; then +int 'GUS DMA 0, 1 or 3' GUS16_DMA 3 +fi + +if [ "$CONFIG_MPU401" = "y" ]; then +hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330 +fi + +if [ "$CONFIG_MPU401" = "y" ]; then +int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9 +fi + + +if [ "$CONFIG_MAUI" = "y" ]; then +comment 'ERROR! You have to use old sound configuration method with Maui.' +fi + +if [ "$CONFIG_MAUI" = "y" ]; then +hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330 +fi + +if [ "$CONFIG_MAUI" = "y" ]; then +int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9 +fi + +if [ "$CONFIG_UART6850" = "y" ]; then +hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0 +fi + +if [ "$CONFIG_UART6850" = "y" ]; then +int 'UART6850 IRQ (Unknown)' U6850_IRQ -1 +fi + + +if [ "$CONFIG_PSS" = "y" ]; then +comment 'ERROR! You have to use old sound configuration method with PSS cards.' +fi + +if [ "$CONFIG_PSS" = "y" ]; then +hex 'PSS I/O base 220 or 240' PSS_BASE 220 +fi + +if [ "$CONFIG_PSS" = "y" ]; then +hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530 +fi + +if [ "$CONFIG_PSS" = "y" ]; then +int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11 +fi + +if [ "$CONFIG_PSS" = "y" ]; then +int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3 +fi +if [ "$CONFIG_PSS" = "y" ]; then +hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330 +fi + +if [ "$CONFIG_PSS" = "y" ]; then +int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9 +fi + +if [ "$CONFIG_MSS" = "y" ]; then +hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530 +fi + +if [ "$CONFIG_MSS" = "y" ]; then +int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11 +fi + +if [ "$CONFIG_MSS" = "y" ]; then +int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3 +fi + +if [ "$CONFIG_MSS" = "y" ]; then +int 'MSS/WSS second DMA (if possible) 0, 1 or 3' MSS_DMA2 -1 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11 +fi + + +if [ "$CONFIG_TRIX" = "y" ]; then +comment 'ERROR! You have to use old sound configuration method with AudioTrix.' +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +hex 'AudioTrix audio I/O base 530, 604, E80 or F40' TRIX_BASE 530 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix audio DMA 0, 1 or 3' TRIX_DMA 0 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +hex 'AudioTrix MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +hex 'AudioTrix SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix SB DMA 1 or 3' TRIX_SB_DMA 1 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9 +fi +# +$MAKE -C drivers/sound kernelconfig || exit 1 bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then diff --git a/fs/Config.in b/fs/Config.in index bb5b843cc..5f53913ee 100644 --- a/fs/Config.in +++ b/fs/Config.in @@ -60,6 +60,9 @@ if [ "$CONFIG_UFS_FS" != "n" ]; then bool 'BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL fi +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'SGI EFS filesystem support' CONFIG_EFS_FS +fi bool 'Macintosh partition map support' CONFIG_MAC_PARTITION endmenu diff --git a/fs/Makefile b/fs/Makefile index fb9da7124..6061adad6 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -182,6 +182,14 @@ else endif endif +ifeq ($(CONFIG_EFS_FS),y) +SUB_DIRS += efs +else + ifeq ($(CONFIG_EFS_FS),m) + MOD_SUB_DIRS += efs + endif +endif + ifeq ($(CONFIG_BINFMT_ELF),y) BINFMTS += binfmt_elf.o else diff --git a/fs/efs/Makefile b/fs/efs/Makefile new file mode 100644 index 000000000..049456899 --- /dev/null +++ b/fs/efs/Makefile @@ -0,0 +1,17 @@ +# +# Makefile for the linux efs-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... + +# CFLAGS+=-g -DDEBUG_EFS + +O_TARGET := efs.o +O_OBJS := dir.o file.o inode.o namei.o \ + symlink.o +M_OBJS := $(O_TARGET) + +include $(TOPDIR)/Rules.make diff --git a/fs/efs/dir.c b/fs/efs/dir.c new file mode 100644 index 000000000..fa07a298f --- /dev/null +++ b/fs/efs/dir.c @@ -0,0 +1,132 @@ +/* dir.c + + directory inode operations for EFS filesystem + + (C)95,96 Christian Vogelgsang +*/ + +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/efs_fs.h> +#include <linux/efs_fs_i.h> +#include <linux/stat.h> +#include <asm/uaccess.h> + +static int efs_readdir(struct file *,void *,filldir_t); +extern int efs_lookup(struct inode *, struct dentry *); + +static struct file_operations efs_dir_ops = { + NULL, + NULL, + NULL, + efs_readdir, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +struct inode_operations efs_dir_in_ops = { + &efs_dir_ops, + NULL, + efs_lookup, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + efs_bmap, + NULL, + NULL +}; + + +/* ----- efs_readdir ----- + readdir inode operation: + read the next directory entry of a given dir file + + inode - pointer to inode struct of directory + filp - pointer to file struct of directory inode + dirent - pointer to dirent struct that has to be filled + filldir - function to store values in the directory + + return - 0 ok, <0 error +*/ +static int efs_readdir(struct file *filp, + void *dirent, filldir_t filldir) +{ + struct inode *inode = filp->f_dentry->d_inode; + struct efs_inode_info *ini = (struct efs_inode_info *)&inode->u.efs_i; + struct buffer_head *bh; + __u8 *rawdirblk; + __u32 iteminode; + __u16 namelen; + __u8 *nameptr; + __u32 numitems; + __u16 itemnum; + __u32 block; + __u16 rawdepos; + + /* some checks */ + if(!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) + return -EBADF; + + /* Warnings */ + if(ini->tot!=1) + printk("efs_readdir: More than one extent!\n"); + if(inode->i_size & (EFS_BLOCK_SIZE-1)) + printk("efs_readdir: dirsize != blocksize*n\n"); + + /* f_pos contains: dirblock<<BLOCK_SIZE | # of item in dirblock */ + block = filp->f_pos >> EFS_BLOCK_SIZE_BITS; + itemnum = filp->f_pos & 0xff; + + /* We found the last entry -> ready */ + if(block == (inode->i_size>>EFS_BLOCK_SIZE_BITS)) + return 0; + + /* get disc block number from dir block num: 0..i_size/BLOCK_SIZE */ + bh = bread(inode->i_dev,efs_bmap(inode,block),EFS_BLOCK_SIZE); + if(!bh) return 0; + + /* dirblock */ + rawdirblk = (__u8 *)bh->b_data; + /* number of entries stored in this dirblock */ + numitems = rawdirblk[EFS_DB_ENTRIES]; + /* offset in block of #off diritem */ + rawdepos = (__u16)rawdirblk[EFS_DB_FIRST+itemnum]<<1; + + /* diritem first contains the inode number, the namelen and the name */ + iteminode = ConvertLong(rawdirblk,rawdepos); + namelen = (__u16)rawdirblk[rawdepos+EFS_DI_NAMELEN]; + nameptr = rawdirblk + rawdepos + EFS_DI_NAME; + +#ifdef DEBUG + printk("efs: dir #%d @ %0#3x - inode %lx %s namelen %u\n",itemnum,rawdepos,iteminode,nameptr,namelen); +#endif + + /* copy filename and data in direntry */ + filldir(dirent,nameptr,namelen,filp->f_pos,iteminode); + + brelse(bh); + + /* store pos of next item */ + itemnum++; + if(itemnum==numitems) { + itemnum = 0; + block++; + } + filp->f_pos = (block<<EFS_BLOCK_SIZE_BITS) | itemnum; + UPDATE_ATIME(inode); + + return 0; +} + diff --git a/fs/efs/file.c b/fs/efs/file.c new file mode 100644 index 000000000..4c04616bb --- /dev/null +++ b/fs/efs/file.c @@ -0,0 +1,218 @@ +/* file.c + + read files on EFS filesystems + now replaced by generic functions of the kernel: + leaves only mapping of file block number -> disk block number in this file + + (C)95,96 Christian Vogelgsang +*/ + +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/efs_fs.h> +#include <linux/efs_fs_i.h> +#include <linux/efs_fs_sb.h> +#include <linux/stat.h> +#include <asm/uaccess.h> + +static struct file_operations efs_file_ops = { + NULL, + generic_file_read, + NULL, + NULL, + NULL, + NULL, + generic_file_mmap, + NULL, + NULL, + NULL +}; + +struct inode_operations efs_file_in_ops = { + &efs_file_ops, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + generic_readpage, + NULL, + efs_bmap, + NULL, + NULL +}; + +#define MIN(a,b) ((a)<(b)?(a):(b)) + +#define CHECK(num) \ + eblk = ini->extents[num].ex_bytes[0]; \ + epos = ini->extents[num].ex_bytes[1] & 0xffffff; \ + elen = ini->extents[num].ex_bytes[1] >> 24; \ + if((blk >= epos)&&(blk < (epos+elen))) \ + result = (blk - epos) + eblk + sbi->fs_start; + + +/* ----- efs_getblknum ----- + find the disc block number for a given logical file block number + + in - inode of file + blk - logical file block number + + return - 0 on error, or unmapped block number +*/ +static __u32 efs_getblk(struct inode *in,__u32 blk) +{ + struct efs_sb_info *sbi = &in->i_sb->u.efs_sb; + struct efs_inode_info *ini = &in->u.efs_i; + struct buffer_head *bh; + + __u32 result = 0; + __u32 eblk,epos,elen; + int num,extnum,readahead; + __u32 extblk; + __u16 extoff,pos,cur,tot; + union efs_extent *ptr; + + + /* first check the current extend */ + cur = ini->cur; + tot = ini->tot; + CHECK(cur) + if(result) + return result; + + /* if only one extent exists and we are here the test failed */ + if(tot==1) { + printk("efs: bmap failed on one extent!\n"); + return 0; + } + + /* check the stored extents in the inode */ + num = MIN(tot,EFS_MAX_EXTENTS); + for(pos=0;pos<num;pos++) { + /* don't check the current again! */ + if(pos==cur) + continue; + + CHECK(pos) + if(result) { + ini->cur = pos; + return result; + } + } + + /* If the inode has only direct extents, + the above tests must have found the block's extend! */ + if(tot<=EFS_MAX_EXTENTS) { + printk("efs: bmap failed for direct extents!\n"); + return 0; + } + + /* --- search in the indirect extensions list blocks --- */ +#ifdef DEBUG + printk("efs - indirect search for %lu\n",blk); +#endif + + /* calculate block and offset for begin of extent descr and read it */ + extblk = ini->extblk; + extoff = 0; + bh = bread(in->i_dev,extblk,EFS_BLOCK_SIZE); + if(!bh) { + printk("efs: read error in indirect extents\n"); + return 0; + } + ptr = (union efs_extent *)bh->b_data; + + pos = 0; /* number of extend store in the inode */ + extnum = 0; /* count the extents in the indirect blocks */ + readahead = 10; /* number of extents to read ahead */ + while(1) { + + /* skip last current extent store in the inode */ + if(pos==cur) pos++; + + /* read new extent in inode buffer */ + ini->extents[pos].ex_bytes[0] = efs_swab32(ptr[pos].ex_bytes[0]); + ini->extents[pos].ex_bytes[1] = efs_swab32(ptr[pos].ex_bytes[1]); + + /* we must still search */ + if(!result) { + CHECK(pos) + if(result) + ini->cur = pos; + } + /* we found it already and read ahead */ + else { + readahead--; + if(!readahead) + break; + } + + /* next storage place */ + pos++; + extnum++; + + /* last extent checked -> finished */ + if(extnum==tot) { + if(!result) + printk("efs: bmap on indirect failed!\n"); + break; + } + + extoff += 8; + /* need new block */ + if(extoff==EFS_BLOCK_SIZE) { + extoff = 0; + extblk++; + + brelse(bh); + bh = bread(in->i_dev,extblk,EFS_BLOCK_SIZE); + if(!bh) { + printk("efs: read error in indirect extents\n"); + return 0; + } + ptr = (union efs_extent *)bh->b_data; + } + } + brelse(bh); + + return result; +} + + +/* ----- efs_bmap ----- + bmap: map a file block number to a device block number + + in - inode owning the block + block - block number + + return - disk block +*/ +int efs_bmap(struct inode *in, int block) +{ + /* quickly reject invalid block numbers */ + if(block<0) { +#ifdef DEBUG + printk("efs_bmap: block < 0\n"); +#endif + return 0; + } + /* since the kernel wants to read a full page of data, i.e. 8 blocks + we must check if the block number is not too large */ + if(block>((in->i_size-1)>>EFS_BLOCK_SIZE_BITS)) { +#ifdef DEBUG + printk("efs_bmap: block %d > max %d == %d\n", + block,in->i_size>>EFS_BLOCK_SIZE_BITS,in->i_blocks); +#endif + return 0; + } + + return efs_getblk(in,block); +} diff --git a/fs/efs/inode.c b/fs/efs/inode.c new file mode 100644 index 000000000..b84231cd5 --- /dev/null +++ b/fs/efs/inode.c @@ -0,0 +1,496 @@ +/* inode.c + * + * Inode and Superblock handling for the EFS filesystem + * + * (C) 1995,96 Christian Vogelgsang + */ + +#include <linux/module.h> +#include <linux/init.h> /* __initfunc */ +#include <linux/fs.h> +#include <linux/efs_fs.h> +#include <linux/efs_fs_i.h> +#include <linux/efs_fs_sb.h> +#include <linux/locks.h> + +#include <asm/uaccess.h> + +/* ----- Define the operations for the Superblock ----- */ +void efs_read_inode(struct inode *); +void efs_put_super(struct super_block *); +int efs_statfs(struct super_block *, struct statfs *,int ); + +static struct super_operations efs_sops = { + efs_read_inode, + NULL, /* write_inode */ + NULL, /* put_inode */ + NULL, /* delete_inode */ + NULL, /* notify_change */ + efs_put_super, + NULL, /* write_super */ + efs_statfs, + NULL +}; + + +/* ----- Conversion utilities ----- + Get 16- and 32-bit unsigned values in big-endian format from a byte buffer +*/ +__u32 ConvertLong(__u8 *buf, int offset) +{ + return *((__u32 *)(buf + offset)); + /* return (__u32)buf[offset+3] | + ((__u32)buf[offset+2])<<8 | + ((__u32)buf[offset+1])<<16 | + ((__u32)buf[offset])<<24; + */ +} + +__u16 ConvertShort(__u8 *buf, int offset) +{ + return *((__u16 *)(buf + offset)); + /* + return (__u16)buf[offset+1] | + ((__u16)buf[offset])<<8; + */ +} + + +/* ----- Install/Remove Module ----- + These procedures are used to install/remove our filesystem + module in the linux kernel +*/ + +/* describe filesystem */ +struct super_block *efs_read_super(struct super_block *s, void *d, int sil); + +static struct file_system_type efs_fs_type = { + "efs", + FS_REQUIRES_DEV, + efs_read_super, + NULL +}; + +__initfunc(int init_efs_fs(void)) { + return register_filesystem(&efs_fs_type); +} + +#ifdef MODULE +EXPORT_NO_SYMBOLS; + +/* install module */ +int init_module(void) +{ + return init_efs_fs(); +} + +/* remove module */ +void cleanup_module(void) +{ + unregister_filesystem(&efs_fs_type); +} +#endif /* MODULE */ + +#ifdef DEBUG_EFS +void efs_dump_super(struct efs_super_block *sb) { + printk("efs_super_block @ 0x%p:\n", sb); + printk("size: %0#8lX firstcg: %0#8lX\n", sb->s_size, sb->s_firstcg); + printk("cgfsize: %0#8lX cgisize: %0#8hX\n", sb->s_cgfsize,sb->s_cgisize); + printk("sectors: %0#8hX heads: %0#8hX\n", sb->s_sectors, sb->s_heads); + printk("ncg: %0#8hX dirty: %0#8hX\n", sb->s_ncg, sb->s_dirty); + printk("time: %0#8lX magic: %0#8lX\n", sb->s_time, sb->s_magic); + printk("fname: %.6s fpack: %.6s\n", sb->s_fname, sb->s_fpack); + printk("bmsize: %0#8lX tfree: %0#8lX\n", sb->s_bmsize, sb->s_tfree); + printk("tinode: %0#8lX bmblock: %0#8lX\n", sb->s_tinode, sb->s_bmblock); + printk("replsb: %0#8lX lastiall: %0#8lX\n", sb->s_replsb, + sb->s_lastialloc); + printk("checksum: %0#8lX\n", sb->s_checksum); +} + +void efs_dump_inode(struct efs_disk_inode *di) { + printk("efs_disk_inode @ 0x%p: ", di); + printk("[%o %hd %hd %u %u %u %u %u #ext=%hd %u %u]\n", + di->di_mode, di->di_nlink, di->di_uid, di->di_gid, di->di_size, + di->di_atime, di->di_mtime, di->di_ctime, di->di_gen, + di->di_numextents, di->di_version); +} +#endif + +/* ----- efs_checkVolDesc ----- + Analyse the first block of a CD and check + if it's a valid efs volume descriptor + + blk - buffer with the data of first block + silent - 0 -> verbose + + return : 0 - error ; >0 - start block of filesystem +*/ +#if 0 +static __u32 efs_checkVolDesc(__u8 *blk,int silent) +{ + __u32 magic; + __u8 *ptr; + __u8 name[10]; + __u32 pos,len; + int i; + + /* is the magic cookie here? */ + magic = ConvertLong(blk,0); + if(magic!=0x0be5a941) { + printk("EFS: no magic on first block\n"); + return 0; + } + + /* Walk through the entries of the VD */ + /* Quite useless, but gives nice output ;-) */ + ptr = blk + EFS_VD_ENTRYFIRST; + name[8] = 0; + while(*ptr) { + for(i=0;i<8;i++) + name[i] = ptr[i]; + + /* start and length of entry */ + pos = ConvertLong(ptr,EFS_VD_ENTRYPOS); + len = ConvertLong(ptr,EFS_VD_ENTRYLEN); + + if(!silent) + printk("EFS: VolDesc: %8s blk: %08lx len: %08lx\n", + name,pos,len); + + ptr+=EFS_VD_ENTRYSIZE; + } + + pos = ConvertLong(blk,EFS_VD_FS_START); + printk("EFS: FS start: %08lx\n",pos); + return pos; +} +#endif + +/* ----- efs_checkSuper ----- + Check if the given block is a valid EFS-superblock + + sbi - my EFS superblock info + block - block that must be examined + + return - 0 ok, -1 error +*/ +static int efs_verify_super(struct efs_super_block *sb, + struct efs_sb_info *sbi, + int silent) +{ + __u32 magic; + + magic = sb->s_magic; + /* check if the magic cookie is here */ + if((magic!=EFS_MAGIC1)&&(magic!=EFS_MAGIC2)) { + printk("EFS: magic %#X doesn't match %#X or %#X!\n", + magic, EFS_MAGIC1, EFS_MAGIC2); + return -1; + } + + /* XXX should check csum */ + + sbi->total_blocks = sb->s_size; + sbi->first_block = sb->s_firstcg; + sbi->group_size = sb->s_cgfsize; + sbi->inode_blocks = sb->s_cgisize; + sbi->total_groups = sb->s_ncg; + + return 0; +} + + +/* ----- efs_read_super ----- + read_super: if the fs gets mounted this procedure is called to + check if the filesystem is valid and to fill the superblock struct + + s - superblock struct + d - options for fs (unused) + sil - flag to be silent + + return - filled s struct or NULL on error + */ + +struct super_block *efs_read_super(struct super_block *s, void *d, int silent) +{ + struct buffer_head *bh; + struct efs_sb_info *sb_info = (struct efs_sb_info *)&s->u.efs_sb; + struct efs_super_block *es; + int error = 0; + int dev = s->s_dev; + struct inode *root_inode = NULL; + + MOD_INC_USE_COUNT; + + /* say hello to my log file! */ +#ifdef EFS_DEBUG + if(!silent) + printk("EFS: --- Filesystem ---\n"); +#endif + /* set blocksize to 512 */ + set_blocksize(dev, EFS_BLOCK_SIZE); + + lock_super(s); + +#if 0 + /* Read first block of CD: the Volume Descriptor */ + bh = bread(dev, 0, EFS_BLOCK_SIZE); + if(bh) { + sb_info->fs_start = efs_checkVolDesc((__u8 *)bh->b_data,silent); + if(sb_info->fs_start==0) { + printk("EFS: failed checking Volume Descriptor\n"); + /* error++; */ + } + brelse(bh); + } else { + printk("EFS: cannot read the first block\n"); + error++; + } +#endif 0 + + /* Read the Superblock */ + if(!error) { +#ifdef DEBUG_EFS + if (!silent) + printk("EFS: reading superblock.\n"); +#endif + bh = bread(dev, EFS_BLK_SUPER, EFS_BLOCK_SIZE ); + if(bh) { + es = (struct efs_super_block *)(bh->b_data); +#ifdef DEBUG_EFS + if(!silent) + efs_dump_super(es); +#endif + if(efs_verify_super(es, sb_info, silent)) { + printk("EFS: failed checking Superblock\n"); + error++; + } + brelse(bh); + } else { + printk("EFS: cannot read the superblock\n"); + error++; + } + } + + if(!error) { + s->s_blocksize = EFS_BLOCK_SIZE; + s->s_blocksize_bits = EFS_BLOCK_SIZE_BITS; + + s->s_magic = EFS_SUPER_MAGIC; + s->s_flags = MS_RDONLY; + s->s_op = &efs_sops; + s->s_dev = dev; + root_inode = iget(s, EFS_ROOT_INODE); + s->s_root = d_alloc_root(root_inode, NULL); + if (!s->s_root) { + error++; + printk("EFS: couldn't allocate root inode!\n"); + } + } + + unlock_super(s); + + if(check_disk_change(s->s_dev)) { + printk("EFS: Device changed!\n"); + error++; + } + + /* We found errors -> say goodbye! */ + if(error) { + s->s_dev = 0; + d_delete(s->s_root); /* XXX is this enough? */ + printk("EFS: init failed with %d errors\n", error); + brelse(bh); + MOD_DEC_USE_COUNT; + return NULL; + } + + return s; +} + + +/* ----- efs_put_super ----- + put_super: remove the filesystem and the module use count + + s - superblock +*/ +void efs_put_super(struct super_block *s) +{ + lock_super(s); + s->s_dev = 0; + unlock_super(s); + MOD_DEC_USE_COUNT; +} + + +/* ----- efs_statfs ----- + statfs: get informatio on the filesystem + + s - superblock of fs + buf - statfs struct that has to be filled +*/ +int efs_statfs(struct super_block *s, struct statfs *buf,int bufsize) +{ + struct efs_sb_info *sbi = (struct efs_sb_info *)&s->u.generic_sbp; + struct statfs tmp; + + tmp.f_type = EFS_SUPER_MAGIC; + tmp.f_bsize = EFS_BLOCK_SIZE; + tmp.f_blocks = sbi->total_blocks; + tmp.f_bfree = 0; + tmp.f_bavail = 0; + tmp.f_files = 100; /* don't know how to calculate the correct value */ + tmp.f_ffree = 0; + tmp.f_namelen = NAME_MAX; + + return copy_to_user(buf,&tmp,bufsize) ? -EFAULT : 0; +} + + +/* ----- efs_read_inode ----- + read an inode specified by in->i_ino from disk, fill the inode + structure and install the correct handler for the file type + + in - inode struct +*/ +void efs_read_inode(struct inode *in) +{ + struct buffer_head *bh; + struct efs_sb_info *sbi = (struct efs_sb_info *)&in->i_sb->u.generic_sbp; + __u32 blk,off; + int error = 0; + + /* Calc the discblock and the offset for inode (4 Nodes fit in one block) */ + blk = in->i_ino >> 2; + blk = sbi->fs_start + sbi->first_block + + (sbi->group_size * (blk / sbi->inode_blocks)) + + (blk % sbi->inode_blocks); + off = (in->i_ino&3)<<7; + + /* Read the block with the inode from disk */ +#ifdef DEBUG_EFS + printk("EFS: looking for inode %#xl\n", in->i_ino); +#endif + bh = bread(in->i_dev,blk,EFS_BLOCK_SIZE); + if(bh) { + + struct efs_disk_inode *di = (struct efs_disk_inode *)(bh->b_data + off); + __u16 numext; + struct efs_inode_info *ini = &in->u.efs_i; + __u32 rdev; + int i; + + /* fill in standard inode infos */ + in->i_mtime = efs_swab32(di->di_mtime); + in->i_ctime = efs_swab32(di->di_ctime); + in->i_atime = efs_swab32(di->di_atime); + in->i_size = efs_swab32(di->di_size); + in->i_nlink = efs_swab16(di->di_nlink); + in->i_uid = efs_swab16(di->di_uid); + in->i_gid = efs_swab16(di->di_gid); + in->i_mode = efs_swab16(di->di_mode); + + /* Special files store their rdev value where the extends of + a regular file are found */ + /* rdev = ConvertLong(rawnode,EFS_IN_EXTENTS);*/ + /* XXX this isn't right */ + rdev = efs_swab32(*(__u32 *)&di->di_u.di_dev); + + /* ----------------------------------------------------------------- + The following values are stored in my private part of the Inode. + They are necessary for further operations with the file */ + + /* get the number of extends the inode posseses */ + numext = efs_swab16(di->di_numextents); + + /* if this inode has more than EFS_MAX_EXTENDS then the extends are + stored not directly in the inode but indirect on an extra block. + The address of the extends-block is stored in the inode */ + if(numext>EFS_MAX_EXTENTS) { + struct buffer_head *bh2; + printk("EFS: inode %#Xl has > EFS_MAX_EXTENTS (%ld)\n", + in->i_ino, numext); + + /* Store the discblock and offset of extend-list in Inode info */ + ini->extblk = sbi->fs_start + efs_swab32((__u32)(di->di_u.di_extents)); + + /* read INI_MAX_EXT extents from the indirect block */ + bh2 = bread(in->i_dev,ini->extblk,EFS_BLOCK_SIZE); + if(bh2) { + union efs_extent *ptr = (union efs_extent *)bh2->b_data; + for(i=0;i<EFS_MAX_EXTENTS;i++) { + ini->extents[i].ex_bytes[0] = efs_swab32(ptr[i].ex_bytes[0]); + ini->extents[i].ex_bytes[1] = efs_swab32(ptr[i].ex_bytes[1]); + } + brelse(bh2); + } else + printk("efs: failed reading indirect extends!\n"); + + } else { +#ifdef DEBUG_EFS + printk("EFS: inode %#Xl is direct (woohoo!)\n", + in->i_ino); +#endif + /* The extends are found in the inode block */ + ini->extblk = blk; + + /* copy extends directly from rawinode */ + for(i=0;i<numext;i++) { + ini->extents[i].ex_bytes[0] = efs_swab32(di->di_u.di_extents[i].ex_bytes[0]); + ini->extents[i].ex_bytes[1] = efs_swab32(di->di_u.di_extents[i].ex_bytes[1]); + } + } + ini->tot = numext; + ini->cur = 0; + + brelse(bh); + +#ifdef DEBUG_EFS + printk("%lx inode: blk %lx numext %x\n",in->i_ino,ini->extblk,numext); + efs_dump_inode(di); +#endif + + /* Install the filetype Handler */ + switch(in->i_mode & S_IFMT) { + case S_IFDIR: + in->i_op = &efs_dir_in_ops; + break; + case S_IFREG: + in->i_op = &efs_file_in_ops; + break; + case S_IFLNK: + in->i_op = &efs_symlink_in_ops; + break; + case S_IFCHR: + in->i_rdev = rdev; + in->i_op = &chrdev_inode_operations; + break; + case S_IFBLK: + in->i_rdev = rdev; + in->i_op = &blkdev_inode_operations; + break; + case S_IFIFO: + init_fifo(in); + break; + default: + printk("EFS: Unsupported inode Mode %o\n",(unsigned int)(in->i_mode)); + error++; + break; + } + + } else { + printk("EFS: Inode: failed bread!\n"); + error++; + } + + /* failed inode */ + if(error) { + printk("EFS: read inode failed with %d errors\n",error); + in->i_mtime = in->i_atime = in->i_ctime = 0; + in->i_size = 0; + in->i_nlink = 1; + in->i_uid = in->i_gid = 0; + in->i_mode = S_IFREG; + in->i_op = NULL; + } +} diff --git a/fs/efs/namei.c b/fs/efs/namei.c new file mode 100644 index 000000000..82086accd --- /dev/null +++ b/fs/efs/namei.c @@ -0,0 +1,143 @@ +/* namei.c + + name lookup for EFS filesystem + + (C)95,96 Christian Vogelgsang +*/ + +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/efs_fs.h> +#include <linux/efs_fs_i.h> +#include <linux/efs_fs_sb.h> +#include <linux/stat.h> +#include <asm/uaccess.h> + +/* ----- efs_find_entry ----- + search a raw efs dir entry for the given name + + dir - inode of directory + oname - name to search for + onamelen- length of name + + return - inode number of the found entry or 0 on error +*/ +static struct buffer_head * efs_find_entry(struct inode *dir, + const char *oname, + int onamelen, + struct efs_dir_entry *res_dir) +{ + struct efs_inode_info *ini = &dir->u.efs_i; + struct buffer_head *bh = NULL; + __u32 inode; + __u16 i; + __u8 *name; + __u16 namelen; + __u32 blknum,b; + struct efs_dirblk *db; + + /* Warnings */ + if(ini->tot!=1) + printk("efs_find: More than one extent!\n"); + if(dir->i_size & (EFS_BLOCK_SIZE-1)) + printk("efs_find: dirsize != blocklen * n\n"); + + /* Search in every dirblock */ + inode = 0; + blknum = dir->i_size >> EFS_BLOCK_SIZE_BITS; +#ifdef DEBUG_EFS + printk("EFS: directory with inode %#xd has %d blocks\n", + dir->i_ino, blknum); +#endif + for(b=0;b<blknum;b++) { + int db_offset; +#ifdef DEBUG_EFS + printk("EFS: trying block %d\n", b); +#endif + /* Read a raw dirblock */ + bh = bread(dir->i_dev,efs_bmap(dir,b),EFS_BLOCK_SIZE); + if(!bh) { + printk("EFS: efs_bmap returned NULL!\n"); + return 0; + } + + db = (struct efs_dirblk *)bh->b_data; + if (db->db_magic != EFS_DIRBLK_MAGIC) { + printk("EFS: dirblk has bad magic (%#xl)!\n", + db->db_magic); + return NULL; + } +#ifdef DEBUG_EFS + printk("EFS: db %d has %d entries, starting at offset %#x\n", + b, db->db_slots, (__u16)db->db_firstused << 1); +#endif + for(i = 0 ; i < db->db_slots ; i++) { + struct efs_dent * de; + int entry_inode; + db_offset = ((__u16)db->db_space[i] << 1) + - EFS_DIRBLK_HEADERSIZE; + de = (struct efs_dent *)(&db->db_space[db_offset]); + + /* inode, namelen and name of direntry */ + entry_inode = efs_swab32(de->ud_inum.l); + namelen = de->d_namelen; + name = de->d_name; +#ifdef DEBUG_EFS + printk("EFS: entry %d @ %#x has inode %#x, %s/%d\n", + i, db_offset, entry_inode, name, namelen); +#endif + /* we found the name! */ + if((namelen==onamelen)&& + (!memcmp(oname,name,onamelen))) { + res_dir->inode = entry_inode; +#ifdef DEBUG_EFS + printk("EFS: found inode %d\n", + entry_inode); +#endif + return bh; + } + } +#ifdef DEBUG_EFS + printk("EFS: efs_find_entry didn't find inode for \"%s\"!\n", + oname); +#endif + return NULL; + } + printk("EFS: Falling off the end of efs_find_entry! Bogus!\n"); + return NULL; + /* not reached */ +} + + +/* ----- efs_lookup ----- + lookup inode operation: + check if a given name is in the dir directory + + dir - pointer to inode of directory + name - name we must search for + len - length of name + result - pointer to inode struct if we found it or NULL on error + + return - 0 everything is ok or <0 on error +*/ +int efs_lookup(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = NULL; + struct buffer_head *bh; + struct efs_dir_entry de; + + bh = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); + if (bh) { + int ino = de.inode; + brelse(bh); + inode = iget(dir->i_sb, ino); + + if (!inode) + return -EACCES; + } + + d_add(dentry, inode); + return 0; +} diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c new file mode 100644 index 000000000..6197bb6f3 --- /dev/null +++ b/fs/efs/symlink.c @@ -0,0 +1,136 @@ +/* symlink.c + * + * Symbolic link handling for EFS + * + * (C)1995,96 Christian Vogelgsang + * + * Based on the symlink.c from minix-fs by Linus + */ + +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/efs_fs.h> +#include <linux/stat.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <asm/uaccess.h> + +static int efs_readlink(struct inode *, char *, int); +static struct dentry * efs_follow_link(struct inode *, struct dentry *); + +struct inode_operations efs_symlink_in_ops = { + NULL, /* no file-operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + efs_readlink, /* readlink */ + efs_follow_link, /* follow_link */ + NULL, + NULL, + NULL, /* bmap */ + NULL, /* truncate */ + NULL /* permission */ +}; + + +/* ----- efs_getlinktarget ----- + read the target of the link from the data zone of the file +*/ +static char *efs_getlinktarget(struct inode *in) +{ + struct buffer_head * bh; + char *name; + __u32 size = in->i_size; + __u32 block; + + /* link data longer than 1024 not supported */ + if(size>2*EFS_BLOCK_SIZE) { + printk("efs_getlinktarget: name too long: %lu\n",in->i_size); + return NULL; + } + + /* get some memory from the kernel to store the name */ + name = kmalloc(size+1,GFP_KERNEL); + if(!name) return NULL; + + /* read first 512 bytes of target */ + block = efs_bmap(in,0); + bh = bread(in->i_dev,block,EFS_BLOCK_SIZE); + if(!bh) { + kfree(name); + return NULL; + } + memcpy(name,bh->b_data,(size>EFS_BLOCK_SIZE)?EFS_BLOCK_SIZE:size); + brelse(bh); + + /* if the linktarget is long, read the next block */ + if(size>EFS_BLOCK_SIZE) { + bh = bread(in->i_dev,block+1,EFS_BLOCK_SIZE); + if(!bh) { + kfree(name); + return NULL; + } + memcpy(name+EFS_BLOCK_SIZE,bh->b_data,size-EFS_BLOCK_SIZE); + brelse(bh); + } + + /* terminate string and return it */ + name[size]=0; + return name; +} + + +/* ----- efs_follow_link ----- + get the inode of the link target +*/ +static struct dentry * efs_follow_link(struct inode * dir, struct dentry *base) +{ + struct buffer_head * bh; + __u32 block; + + block = efs_bmap(dir,0); + bh = bread(dir->i_dev,block,EFS_BLOCK_SIZE); + if (!bh) { + dput(base); + return ERR_PTR(-EIO); + } + UPDATE_ATIME(dir); + base = lookup_dentry(bh->b_data, base, 1); + brelse(bh); + return base; +} + +/* ----- efs_readlink ----- + read the target of a link and return the name +*/ +static int efs_readlink(struct inode * dir, char * buffer, int buflen) +{ + int i; + char c; + struct buffer_head * bh; + __u32 block; + + block = efs_bmap(dir,0); + if (buflen > 1023) + buflen = 1023; + bh = bread(dir->i_dev,block,EFS_BLOCK_SIZE); + if (!bh) + return 0; + + /* copy the link target to the given buffer */ + i = 0; + while (i<buflen && (c = bh->b_data[i])) { + i++; + put_user(c,buffer++); + } + + brelse(bh); + return i; +} diff --git a/fs/filesystems.c b/fs/filesystems.c index 74016aa67..348ad7bb7 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c @@ -24,6 +24,7 @@ #include <linux/ufs_fs.h> #include <linux/romfs_fs.h> #include <linux/auto_fs.h> +#include <linux/efs_fs.h> #include <linux/major.h> #include <linux/smp.h> #include <linux/smp_lock.h> @@ -116,6 +117,10 @@ __initfunc(static void do_sys_setup(void)) init_autofs_fs(); #endif +#ifdef CONFIG_EFS_FS + init_efs_fs(); +#endif + mount_root(); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 8dd814564..8380d0a67 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -251,6 +251,7 @@ static inline int buffer_protected(struct buffer_head * bh) #include <linux/ufs_fs_i.h> #include <linux/romfs_fs_i.h> #include <linux/smb_fs_i.h> +#include <linux/efs_fs_i.h> /* * Attribute flags. These should be or-ed together to figure out what @@ -350,6 +351,7 @@ struct inode { struct ufs_inode_info ufs_i; struct romfs_inode_info romfs_i; struct smb_inode_info smbfs_i; + struct efs_inode_info efs_i; struct socket socket_i; void *generic_ip; } u; @@ -481,6 +483,7 @@ extern int fasync_helper(struct inode *, struct file *, int, struct fasync_struc #include <linux/affs_fs_sb.h> #include <linux/ufs_fs_sb.h> #include <linux/romfs_fs_sb.h> +#include <linux/efs_fs_sb.h> #include <linux/smb_fs_sb.h> struct super_block { @@ -515,6 +518,7 @@ struct super_block { struct affs_sb_info affs_sb; struct ufs_sb_info ufs_sb; struct romfs_sb_info romfs_sb; + struct efs_sb_info efs_sb; struct smb_sb_info smbfs_sb; void *generic_sbp; } u; |