Commit 7a024f46 authored by Linus Torvalds's avatar Linus Torvalds

Pre-2.1.80..

 I just put a pre-2.1.80 on ftp.kernel.org that should fix the fat-related
problems. The reason I put it there is because I got several patches that
fixed the FAT problems _and_ something else, and they all obviously
clashed with each other so neither part got applied.

 So I'd ask people who sent me patches to maybe re-send the parts of the
patches that are still relevant,

                Linus
parent ae04feb3
......@@ -56,7 +56,7 @@ first_rule: sub_dirs
echo 'ifeq ($(strip $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@)),$$(strip $$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@)))' ; \
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
echo 'endif' \
) > .$@.flags
) > $(dir $@)/.$(notdir $@).flags
%.o: %.s
$(AS) $(ASFLAGS) $(EXTRA_CFLAGS) -o $@ $<
......@@ -82,7 +82,7 @@ endif
echo 'ifeq ($(strip $(EXTRA_LDFLAGS) $(ALL_O)),$$(strip $$(EXTRA_LDFLAGS) $$(ALL_O)))' ; \
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
echo 'endif' \
) > .$@.flags
) > $(dir $@)/.$(notdir $@).flags
endif # O_TARGET
#
......@@ -96,7 +96,7 @@ $(L_TARGET): $(LX_OBJS) $(L_OBJS)
echo 'ifeq ($(strip $(EXTRA_ARFLAGS) $(LX_OBJS) $(L_OBJS)),$$(strip $$(EXTRA_ARFLAGS) $$(LX_OBJS) $$(L_OBJS)))' ; \
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
echo 'endif' \
) > .$@.flags
) > $(dir $@)/.$(notdir $@).flags
endif
#
......@@ -218,7 +218,7 @@ $(SYMTAB_OBJS): $(TOPDIR)/include/linux/modversions.h $(SYMTAB_OBJS:.o=.c)
echo 'ifeq ($(strip $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -DEXPORT_SYMTAB),$$(strip $$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@) -DEXPORT_SYMTAB))' ; \
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
echo 'endif' \
) > .$@.flags
) > $(dir $@)/.$(notdir $@).flags
endif
endif # CONFIG_MODULES
......
......@@ -84,6 +84,7 @@ CONFIG_PACKET=y
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
......
......@@ -54,6 +54,7 @@ struct tunertype {
unchar UHF;
unchar config;
unchar I2C;
ushort IFPCoff;
};
#endif
......@@ -67,6 +67,7 @@ static inline void dentry_iput(struct dentry * dentry)
struct inode *inode = dentry->d_inode;
if (inode) {
dentry->d_inode = NULL;
list_del(&dentry->d_alias);
if (dentry->d_op && dentry->d_op->d_iput)
dentry->d_op->d_iput(dentry, inode);
else
......@@ -508,6 +509,7 @@ printk("d_alloc: %d unused, pruning dcache\n", dentry_stat.nr_unused);
INIT_LIST_HEAD(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_lru);
INIT_LIST_HEAD(&dentry->d_subdirs);
INIT_LIST_HEAD(&dentry->d_alias);
dentry->d_name.name = str;
dentry->d_name.len = name->len;
......@@ -529,6 +531,8 @@ printk("d_alloc: %d unused, pruning dcache\n", dentry_stat.nr_unused);
*/
void d_instantiate(struct dentry *entry, struct inode * inode)
{
if (inode)
list_add(&entry->d_alias, &inode->i_dentry);
entry->d_inode = inode;
}
......
......@@ -122,7 +122,7 @@ int fat_access(struct super_block *sb,int nr,int new_value)
}
void cache_init(void)
void fat_cache_init(void)
{
static int initialized = 0;
int count;
......@@ -138,7 +138,7 @@ void cache_init(void)
}
void cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu)
void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu)
{
struct fat_cache *walk;
......@@ -179,7 +179,7 @@ static void list_cache(void)
#endif
void cache_add(struct inode *inode,int f_clu,int d_clu)
void fat_cache_add(struct inode *inode,int f_clu,int d_clu)
{
struct fat_cache *walk,*last;
......@@ -252,12 +252,12 @@ int fat_get_cluster(struct inode *inode,int cluster)
if (!(nr = MSDOS_I(inode)->i_start)) return 0;
if (!cluster) return nr;
count = 0;
for (cache_lookup(inode,cluster,&count,&nr); count < cluster;
for (fat_cache_lookup(inode,cluster,&count,&nr); count < cluster;
count++) {
if ((nr = fat_access(inode->i_sb,nr,-1)) == -1) return 0;
if (!nr) return 0;
}
cache_add(inode,cluster,nr);
fat_cache_add(inode,cluster,nr);
return nr;
}
......
......@@ -237,6 +237,7 @@ int fat_readdirx(
char bufname[14];
char *ptname = bufname;
int dotoffset = 0;
int was_long = is_long;
if (is_long) {
unsigned char sum;
......@@ -247,6 +248,7 @@ int fat_readdirx(
if (sum != alias_checksum) {
PRINTK(("Checksums don't match %d != %d\n", sum, alias_checksum));
is_long = 0;
long_slots = 0;
}
if (utf8) {
long_len = utf8_wcstombs(longname, (__u16 *) unicode, sizeof(longname));
......@@ -290,7 +292,7 @@ int fat_readdirx(
if (both)
bufname[i+dotoffset] = '\0';
spos = oldpos;
if (is_long) {
if (was_long) {
spos = filp->f_pos - sizeof(struct msdos_dir_entry);
} else {
long_slots = 0;
......
......@@ -377,7 +377,7 @@ fat_read_super(struct super_block *sb, void *data, int silent)
/* N.B. we should parse directly into the sb structure */
memcpy(&(MSDOS_SB(sb)->options), &opts, sizeof(struct fat_mount_options));
cache_init();
fat_cache_init();
lock_super(sb);
if( blksize > 1024 )
{
......
......@@ -194,7 +194,7 @@ printk("set to %x\n",fat_access(sb,nr,-1));
*/
file_cluster = 0;
if ((curr = MSDOS_I(inode)->i_start) != 0) {
cache_lookup(inode,INT_MAX,&last,&curr);
fat_cache_lookup(inode,INT_MAX,&last,&curr);
file_cluster = last;
while (curr && curr != -1){
PRINTK (("."));
......@@ -242,7 +242,7 @@ if (last) printk("next set to %d\n",fat_access(sb,last,-1));
printk ("file_cluster badly computed!!! %d <> %ld\n"
,file_cluster,inode->i_blocks/cluster_size);
}else{
cache_add(inode,file_cluster,nr);
fat_cache_add(inode,file_cluster,nr);
}
inode->i_blocks += cluster_size;
if (S_ISDIR(inode->i_mode)) {
......
......@@ -118,11 +118,13 @@ int fat_mmap(struct file * file, struct vm_area_struct * vma)
}
int fat_readpage(struct inode * inode, struct page * page)
int fat_readpage(struct dentry * dentry, struct page * page)
{
struct inode * inode = dentry->d_inode;
if(MSDOS_SB(inode->i_sb)->cvf_format)
if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage)
return MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage(inode,page);
if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage)
return MSDOS_SB(inode->i_sb)->cvf_format
->cvf_readpage(inode,page);
printk("fat_readpage called with no handler (shouldn't happen)\n");
return -1;
......
......@@ -127,6 +127,7 @@ static inline void init_once(struct inode * inode)
memset(inode, 0, sizeof(*inode));
init_waitqueue(&inode->i_wait);
INIT_LIST_HEAD(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_dentry);
sema_init(&inode->i_sem, 1);
}
......
......@@ -43,11 +43,6 @@
#include <asm/segment.h>
/*
* If NFS_DEBUG is defined, you can toggle NFS debugging by causing
* a lookup of "__xyzzy__". Just cd to an NFS-mounted filesystem and type
* 'ls __xyzzy__' to turn on debugging.
*/
#ifdef NFS_DEBUG
# define NFSDBG_FACILITY NFSDBG_PROC
#endif
......@@ -90,10 +85,6 @@ nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,
int status;
dprintk("NFS call lookup %s\n", name);
#ifdef RPC_DEBUG
if (!strcmp(name, "__xyzzy__"))
nfs_debug = ~nfs_debug;
#endif
status = rpc_call(server->client, NFSPROC_LOOKUP, &arg, &res, 0);
dprintk("NFS reply lookup: %d\n", status);
return status;
......
......@@ -57,6 +57,38 @@ void vfat_read_inode(struct inode *inode);
static int vfat_valid_shortname(const char *,int, int, int);
static int vfat_format_name(const char *, int, char *, int, int);
static int vfat_valid_longname(const char *, int, int, int);
static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
static int vfat_hash(struct dentry *parent, struct qstr *qstr);
static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
static int vfat_revalidate(struct dentry *dentry);
static struct dentry_operations vfat_dentry_ops[4] = {
{
NULL, /* d_revalidate */
vfat_hashi,
vfat_cmpi,
NULL /* d_delete */
},
{
vfat_revalidate,
vfat_hashi,
vfat_cmpi,
NULL /* d_delete */
},
{
NULL, /* d_revalidate */
vfat_hash,
vfat_cmp,
NULL /* d_delete */
},
{
vfat_revalidate,
vfat_hash,
vfat_cmp,
NULL /* d_delete */
}
};
static int strnicmp(const char *s1, const char *s2, int len)
{
......@@ -80,6 +112,13 @@ void vfat_put_super(struct super_block *sb)
MOD_DEC_USE_COUNT;
}
static int vfat_revalidate(struct dentry *dentry)
{
if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
return 1;
}
return 0;
}
static struct super_operations vfat_sops = {
vfat_read_inode,
......@@ -165,6 +204,27 @@ static int parse_options(char *options, struct fat_mount_options *opts)
* return ENOENT or EINVAL as appropriate.
*/
static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
{
const char *name;
int len;
len = qstr->len;
name = qstr->name;
while (len && name[len-1] == '.')
len--;
qstr->hash = full_name_hash(name, len);
return 0;
}
/*
* Compute the hash for the vfat name corresponding to the dentry.
* Note: if the name is invalid, we leave the hash code unchanged so
* that the existing dentry can be used. The vfat fs routines will
* return ENOENT or EINVAL as appropriate.
*/
static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
{
const char *name;
int len;
......@@ -187,9 +247,9 @@ static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
}
/*
* Compare two vfat names.
* Case insensitive compare of two vfat names.
*/
static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
{
int alen, blen;
......@@ -200,18 +260,33 @@ static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
alen--;
while (blen && b->name[blen-1] == '.')
blen--;
if (alen != blen)
return 1;
return strnicmp(a->name, b->name, alen);
if (alen == blen) {
if (strnicmp(a->name, b->name, alen) == 0)
return 0;
}
return 1;
}
static struct dentry_operations vfat_dentry_operations = {
NULL, /* d_revalidate */
vfat_hash,
vfat_cmp,
NULL /* d_delete */
};
/*
* Case sensitive compare of two vfat names.
*/
static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
{
int alen, blen;
/* A filename cannot end in '.' or we treat it like it has none */
alen = a->len;
blen = b->len;
while (alen && a->name[alen-1] == '.')
alen--;
while (blen && b->name[blen-1] == '.')
blen--;
if (alen == blen) {
if (strncmp(a->name, b->name, alen) == 0)
return 0;
}
return 1;
}
struct super_block *vfat_read_super(struct super_block *sb,void *data,
int silent)
......@@ -235,7 +310,9 @@ struct super_block *vfat_read_super(struct super_block *sb,void *data,
} else {
MSDOS_SB(sb)->options.dotsOK = 0;
if (MSDOS_SB(sb)->options.name_check != 's') {
sb->s_root->d_op = &vfat_dentry_operations;
sb->s_root->d_op = &vfat_dentry_ops[0];
} else {
sb->s_root->d_op = &vfat_dentry_ops[2];
}
}
......@@ -321,7 +398,7 @@ static char replace_chars[] = "[];,+=";
static int vfat_find(struct inode *dir,struct qstr* name,
int find_long,int new_filename,int is_dir,
struct slot_info *sinfo_out);
struct vfat_slot_info *sinfo_out);
/* Checks the validity of a long MS-DOS filename */
/* Returns negative number on error, 0 for a normal
......@@ -519,7 +596,7 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
int res;
int spaces;
char buf[8];
struct slot_info sinfo;
struct vfat_slot_info sinfo;
const char *name_start;
struct qstr qname;
......@@ -778,7 +855,6 @@ xlate_to_uni(const char *name, int len, char *outname, int *outlen,
len--;
op = outname;
if (nls) {
/* XXX: i is incorrectly computed. */
for (i = 0, ip = name, op = outname, *outlen = 0;
i < len && *outlen <= 260; i++, *outlen += 1)
{
......@@ -992,7 +1068,7 @@ static int vfat_readdir_cb(
}
static int vfat_find(struct inode *dir,struct qstr* qname,
int find_long, int new_filename,int is_dir,struct slot_info *sinfo_out)
int find_long, int new_filename,int is_dir,struct vfat_slot_info *sinfo_out)
{
struct super_block *sb = dir->i_sb;
struct vfat_find_info vf;
......@@ -1118,37 +1194,36 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
int vfat_lookup(struct inode *dir,struct dentry *dentry)
{
int res;
struct slot_info sinfo;
struct vfat_slot_info sinfo;
struct inode *result;
int table;
PRINTK (("vfat_lookup: name=%s, len=%d\n",
dentry->d_name.name, dentry->d_name.len));
if (MSDOS_SB(dir->i_sb)->options.name_check != 's') {
dentry->d_op = &vfat_dentry_operations;
}
table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
dentry->d_op = &vfat_dentry_ops[table];
result = NULL;
if ((res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo)) < 0) {
d_add(dentry,NULL);
return 0;
result = NULL;
table++;
goto error;
}
PRINTK (("vfat_lookup 4.5\n"));
if (!(result = iget(dir->i_sb,sinfo.ino)))
return -EACCES;
PRINTK (("vfat_lookup 5\n"));
if (!result->i_sb ||
(result->i_sb->s_magic != MSDOS_SUPER_MAGIC)) {
/* crossed a mount point into a non-msdos fs */
d_add(dentry,NULL);
return 0;
}
if (MSDOS_I(result)->i_busy) { /* mkdir in progress */
iput(result);
d_add(dentry,NULL);
return 0;
result = NULL;
table++;
goto error;
}
PRINTK (("vfat_lookup 6\n"));
error:
dentry->d_op = &vfat_dentry_ops[table];
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_add(dentry,result);
return 0;
}
......@@ -1162,7 +1237,7 @@ static int vfat_create_entry(struct inode *dir,struct qstr* qname,
loff_t offset;
struct buffer_head *bh;
struct msdos_dir_entry *de;
struct slot_info sinfo;
struct vfat_slot_info sinfo;
*result=0;
PRINTK(("vfat_create_entry 1\n"));
......@@ -1210,6 +1285,7 @@ int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
if (res < 0) {
PRINTK(("vfat_create: unable to get new entry\n"));
} else {
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry,result);
}
return res;
......@@ -1388,7 +1464,7 @@ static int vfat_unlink_free_ino(struct inode *dir,struct buffer_head *bh,
return 0;
}
static int vfat_remove_entry(struct inode *dir,struct slot_info *sinfo,
static int vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
struct buffer_head **bh,struct dentry* dentry,
int is_dir,int nospc)
{
......@@ -1422,13 +1498,31 @@ static int vfat_remove_entry(struct inode *dir,struct slot_info *sinfo,
return 0;
}
static void vfat_delete_dentries(struct dentry *dentry)
{
struct list_head *head, *next, *tmp;
struct dentry *alias;
head = &dentry->d_inode->i_dentry;
if (dentry->d_inode) {
next = dentry->d_inode->i_dentry.next;
while (next != head) {
tmp = next;
next = tmp->next;
alias = list_entry(tmp, struct dentry, d_alias);
d_delete(alias);
}
} else {
d_delete(dentry);
}
}
static int vfat_rmdirx(struct inode *dir,struct dentry* dentry)
{
struct super_block *sb = dir->i_sb;
int res;
struct buffer_head *bh;
struct slot_info sinfo;
struct vfat_slot_info sinfo;
res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
......@@ -1450,7 +1544,7 @@ int vfat_rmdir(struct inode *dir,struct dentry* dentry)
int res;
res = vfat_rmdirx(dir, dentry);
if (res >= 0) {
d_delete(dentry);
vfat_delete_dentries(dentry);
}
return res;
}
......@@ -1463,7 +1557,7 @@ static int vfat_unlinkx(
struct super_block *sb = dir->i_sb;
int res;
struct buffer_head *bh;
struct slot_info sinfo;
struct vfat_slot_info sinfo;
bh = NULL;
res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
......@@ -1498,6 +1592,7 @@ int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
res = vfat_create_dotdirs(inode, dir);
fat_unlock_creation();
MSDOS_I(inode)->i_busy = 0;
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry,inode);
if (res < 0) {
if (vfat_rmdir(dir,dentry) < 0)
......@@ -1513,7 +1608,7 @@ int vfat_unlink(struct inode *dir,struct dentry* dentry)
res = vfat_unlinkx (dir,dentry,1);
if (res >= 0) {
d_delete(dentry);
vfat_delete_dentries(dentry);
}
return res;
}
......@@ -1540,7 +1635,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
struct dentry *walk;
int res, is_dir, i;
int locked = 0;
struct slot_info sinfo;
struct vfat_slot_info sinfo;
PRINTK(("vfat_rename 1\n"));
if (old_dir == new_dir &&
......
......@@ -124,6 +124,8 @@ extern void __put_user_1(void);
extern void __put_user_2(void);
extern void __put_user_4(void);
extern void __put_user_bad(void);
#define __put_user_x(size,ret,x,ptr) \
__asm__ __volatile__("call __put_user_" #size \
:"=a" (ret) \
......@@ -141,8 +143,89 @@ extern void __put_user_4(void);
__ret_pu; \
})
#define __get_user(x,ptr) get_user(x,ptr)
#define __put_user(x,ptr) put_user(x,ptr)
#define __get_user(x,ptr) \
__get_user_nocheck((x),(ptr),sizeof(*(ptr)))
#define __put_user(x,ptr) \
__put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
#define __put_user_nocheck(x,ptr,size) \
({ \
long __pu_err; \
__put_user_size((x),(ptr),(size),__pu_err); \
__pu_err; \
})
#define __put_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
switch (size) { \
case 1: __put_user_asm(x,ptr,retval,"b","b","iq"); break; \
case 2: __put_user_asm(x,ptr,retval,"w","w","ir"); break; \
case 4: __put_user_asm(x,ptr,retval,"l","","ir"); break; \
default: __put_user_bad(); \
} \
} while (0)
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
/*
* Tell gcc we read from memory instead of writing: this is because
* we do not write to any memory gcc knows about, so there are no
* aliasing issues.
*/
#define __put_user_asm(x, addr, err, itype, rtype, ltype) \
__asm__ __volatile__( \
"1: mov"itype" %"rtype"1,%2\n" \
"2:\n" \
".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" \
".previous" \
: "=r"(err) \
: ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err))
#define __get_user_nocheck(x,ptr,size) \
({ \
long __gu_err, __gu_val; \
__get_user_size(__gu_val,(ptr),(size),__gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
extern long __get_user_bad(void);
#define __get_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
switch (size) { \
case 1: __get_user_asm(x,ptr,retval,"b","b","=q"); break; \
case 2: __get_user_asm(x,ptr,retval,"w","w","=r"); break; \
case 4: __get_user_asm(x,ptr,retval,"l","","=r"); break; \
default: (x) = __get_user_bad(); \
} \
} while (0)
#define __get_user_asm(x, addr, err, itype, rtype, ltype) \
__asm__ __volatile__( \
"1: mov"itype" %2,%"rtype"1\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"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" \
".previous" \
: "=r"(err), ltype (x) \
: "m"(__m(addr)), "i"(-EFAULT), "0"(err))
/*
* The "xxx_ret" versions return constant specified in third argument, if
......
......@@ -61,6 +61,7 @@ struct dentry {
struct list_head d_lru; /* d_count = 0 LRU list */
struct list_head d_child; /* child of parent list */
struct list_head d_subdirs; /* our children */
struct list_head d_alias; /* inode alias list */
struct qstr d_name;
unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op;
......
......@@ -318,6 +318,7 @@ struct iattr {
struct inode {
struct list_head i_hash;
struct list_head i_list;
struct list_head i_dentry;
unsigned long i_ino;
kdev_t i_dev;
......
......@@ -163,7 +163,6 @@ struct msdos_dir_slot {
struct vfat_slot_info {
int is_long; /* was the found entry long */
int is_alias; /* was the found entry an alias */
int long_slots; /* number of long slots in filename */
int total_slots; /* total slots (long and short) */
loff_t longname_offset; /* dir offset for longname start */
......@@ -219,10 +218,10 @@ extern int fat_smap(struct inode *inode,int sector);
extern int fat_free(struct inode *inode,int skip);
void fat_cache_inval_inode(struct inode *inode);
void fat_cache_inval_dev(kdev_t device);
extern void cache_init(void);
void cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu);
void cache_add(struct inode *inode,int f_clu,int d_clu);
int get_cluster(struct inode *inode,int cluster);
extern void fat_cache_init(void);
void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu);
void fat_cache_add(struct inode *inode,int f_clu,int d_clu);
int fat_get_cluster(struct inode *inode,int cluster);
/* inode.c */
extern int fat_bmap(struct inode *inode,int block);
......@@ -256,7 +255,7 @@ extern void fat_truncate(struct inode *inode);
/* mmap.c */
extern int fat_mmap(struct file *, struct vm_area_struct *);
extern int fat_readpage(struct inode *, struct page *);
extern int fat_readpage(struct dentry *, struct page *);
/* vfat.c */
......
......@@ -119,6 +119,8 @@ EXPORT_SYMBOL(do_mmap);
EXPORT_SYMBOL(do_munmap);
EXPORT_SYMBOL(exit_mm);
EXPORT_SYMBOL(exit_files);
EXPORT_SYMBOL(exit_fs);
EXPORT_SYMBOL(exit_sighand);
/* internal kernel memory management */
EXPORT_SYMBOL(__get_free_pages);
......
......@@ -11,6 +11,7 @@ if [ "$CONFIG_NETLINK" = "y" ]; then
fi
bool 'Network firewalls' CONFIG_FIREWALL
bool 'Network aliasing' CONFIG_NET_ALIAS
bool 'Socket Filtering' CONFIG_FILTER
tristate 'Unix domain sockets' CONFIG_UNIX
bool 'TCP/IP networking' CONFIG_INET
if [ "$CONFIG_INET" = "y" ]; then
......
......@@ -16,6 +16,10 @@ ifeq ($(CONFIG_SYSCTL),y)
O_OBJS += sysctl_net_core.o
endif
ifdef CONFIG_FILTER
O_OBJS += filter.o
endif
ifdef CONFIG_NET
O_OBJS += dev.o dev_mcast.o
......
......@@ -123,6 +123,10 @@
#include <net/icmp.h>
#include <linux/ipsec.h>
#ifdef CONFIG_FILTER
#include <linux/filter.h>
#endif
#define min(a,b) ((a)<(b)?(a):(b))
/* Run time adjustable parameters. */
......@@ -148,6 +152,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
struct linger ling;
struct ifreq req;
int ret = 0;
#ifdef CONFIG_FILTER
struct sock_fprog fprog;
#endif
/*
* Options without arguments
......
......@@ -1468,6 +1468,14 @@ static inline struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb)
int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
{
#ifdef CONFIG_FILTER
if (sk->filter)
{
if (sk_filter(skb, sk->filter_data, sk->filter))
return -EPERM; /* Toss packet */
}
#endif /* CONFIG_FILTER */
skb_set_owner_r(skb, sk);
/*
......
......@@ -121,6 +121,10 @@ EXPORT_SYMBOL(net_families);
EXPORT_SYMBOL(sock_kmalloc);
EXPORT_SYMBOL(sock_kfree_s);
#ifdef CONFIG_FILTER
EXPORT_SYMBOL(sk_run_filter);
#endif
EXPORT_SYMBOL(neigh_table_init);
EXPORT_SYMBOL(neigh_table_clear);
EXPORT_SYMBOL(__neigh_lookup);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment