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 ...@@ -56,7 +56,7 @@ first_rule: sub_dirs
echo 'ifeq ($(strip $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@)),$$(strip $$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@)))' ; \ echo 'ifeq ($(strip $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@)),$$(strip $$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@)))' ; \
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
echo 'endif' \ echo 'endif' \
) > .$@.flags ) > $(dir $@)/.$(notdir $@).flags
%.o: %.s %.o: %.s
$(AS) $(ASFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(AS) $(ASFLAGS) $(EXTRA_CFLAGS) -o $@ $<
...@@ -82,7 +82,7 @@ endif ...@@ -82,7 +82,7 @@ endif
echo 'ifeq ($(strip $(EXTRA_LDFLAGS) $(ALL_O)),$$(strip $$(EXTRA_LDFLAGS) $$(ALL_O)))' ; \ echo 'ifeq ($(strip $(EXTRA_LDFLAGS) $(ALL_O)),$$(strip $$(EXTRA_LDFLAGS) $$(ALL_O)))' ; \
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
echo 'endif' \ echo 'endif' \
) > .$@.flags ) > $(dir $@)/.$(notdir $@).flags
endif # O_TARGET endif # O_TARGET
# #
...@@ -96,7 +96,7 @@ $(L_TARGET): $(LX_OBJS) $(L_OBJS) ...@@ -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 'ifeq ($(strip $(EXTRA_ARFLAGS) $(LX_OBJS) $(L_OBJS)),$$(strip $$(EXTRA_ARFLAGS) $$(LX_OBJS) $$(L_OBJS)))' ; \
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
echo 'endif' \ echo 'endif' \
) > .$@.flags ) > $(dir $@)/.$(notdir $@).flags
endif endif
# #
...@@ -218,7 +218,7 @@ $(SYMTAB_OBJS): $(TOPDIR)/include/linux/modversions.h $(SYMTAB_OBJS:.o=.c) ...@@ -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 'ifeq ($(strip $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -DEXPORT_SYMTAB),$$(strip $$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@) -DEXPORT_SYMTAB))' ; \
echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
echo 'endif' \ echo 'endif' \
) > .$@.flags ) > $(dir $@)/.$(notdir $@).flags
endif endif
endif # CONFIG_MODULES endif # CONFIG_MODULES
......
...@@ -84,6 +84,7 @@ CONFIG_PACKET=y ...@@ -84,6 +84,7 @@ CONFIG_PACKET=y
# CONFIG_NETLINK is not set # CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set # CONFIG_FIREWALL is not set
# CONFIG_NET_ALIAS is not set # CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y CONFIG_UNIX=y
CONFIG_INET=y CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set # CONFIG_IP_MULTICAST is not set
......
...@@ -54,6 +54,7 @@ struct tunertype { ...@@ -54,6 +54,7 @@ struct tunertype {
unchar UHF; unchar UHF;
unchar config; unchar config;
unchar I2C; unchar I2C;
ushort IFPCoff;
}; };
#endif #endif
...@@ -67,6 +67,7 @@ static inline void dentry_iput(struct dentry * dentry) ...@@ -67,6 +67,7 @@ static inline void dentry_iput(struct dentry * dentry)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
if (inode) { if (inode) {
dentry->d_inode = NULL; dentry->d_inode = NULL;
list_del(&dentry->d_alias);
if (dentry->d_op && dentry->d_op->d_iput) if (dentry->d_op && dentry->d_op->d_iput)
dentry->d_op->d_iput(dentry, inode); dentry->d_op->d_iput(dentry, inode);
else else
...@@ -508,6 +509,7 @@ printk("d_alloc: %d unused, pruning dcache\n", dentry_stat.nr_unused); ...@@ -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_hash);
INIT_LIST_HEAD(&dentry->d_lru); INIT_LIST_HEAD(&dentry->d_lru);
INIT_LIST_HEAD(&dentry->d_subdirs); INIT_LIST_HEAD(&dentry->d_subdirs);
INIT_LIST_HEAD(&dentry->d_alias);
dentry->d_name.name = str; dentry->d_name.name = str;
dentry->d_name.len = name->len; dentry->d_name.len = name->len;
...@@ -529,6 +531,8 @@ printk("d_alloc: %d unused, pruning dcache\n", dentry_stat.nr_unused); ...@@ -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) void d_instantiate(struct dentry *entry, struct inode * inode)
{ {
if (inode)
list_add(&entry->d_alias, &inode->i_dentry);
entry->d_inode = inode; entry->d_inode = inode;
} }
......
...@@ -122,7 +122,7 @@ int fat_access(struct super_block *sb,int nr,int new_value) ...@@ -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; static int initialized = 0;
int count; int count;
...@@ -138,7 +138,7 @@ void cache_init(void) ...@@ -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; struct fat_cache *walk;
...@@ -179,7 +179,7 @@ static void list_cache(void) ...@@ -179,7 +179,7 @@ static void list_cache(void)
#endif #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; struct fat_cache *walk,*last;
...@@ -252,12 +252,12 @@ int fat_get_cluster(struct inode *inode,int cluster) ...@@ -252,12 +252,12 @@ int fat_get_cluster(struct inode *inode,int cluster)
if (!(nr = MSDOS_I(inode)->i_start)) return 0; if (!(nr = MSDOS_I(inode)->i_start)) return 0;
if (!cluster) return nr; if (!cluster) return nr;
count = 0; count = 0;
for (cache_lookup(inode,cluster,&count,&nr); count < cluster; for (fat_cache_lookup(inode,cluster,&count,&nr); count < cluster;
count++) { count++) {
if ((nr = fat_access(inode->i_sb,nr,-1)) == -1) return 0; if ((nr = fat_access(inode->i_sb,nr,-1)) == -1) return 0;
if (!nr) return 0; if (!nr) return 0;
} }
cache_add(inode,cluster,nr); fat_cache_add(inode,cluster,nr);
return nr; return nr;
} }
......
...@@ -237,6 +237,7 @@ int fat_readdirx( ...@@ -237,6 +237,7 @@ int fat_readdirx(
char bufname[14]; char bufname[14];
char *ptname = bufname; char *ptname = bufname;
int dotoffset = 0; int dotoffset = 0;
int was_long = is_long;
if (is_long) { if (is_long) {
unsigned char sum; unsigned char sum;
...@@ -247,6 +248,7 @@ int fat_readdirx( ...@@ -247,6 +248,7 @@ int fat_readdirx(
if (sum != alias_checksum) { if (sum != alias_checksum) {
PRINTK(("Checksums don't match %d != %d\n", sum, alias_checksum)); PRINTK(("Checksums don't match %d != %d\n", sum, alias_checksum));
is_long = 0; is_long = 0;
long_slots = 0;
} }
if (utf8) { if (utf8) {
long_len = utf8_wcstombs(longname, (__u16 *) unicode, sizeof(longname)); long_len = utf8_wcstombs(longname, (__u16 *) unicode, sizeof(longname));
...@@ -290,7 +292,7 @@ int fat_readdirx( ...@@ -290,7 +292,7 @@ int fat_readdirx(
if (both) if (both)
bufname[i+dotoffset] = '\0'; bufname[i+dotoffset] = '\0';
spos = oldpos; spos = oldpos;
if (is_long) { if (was_long) {
spos = filp->f_pos - sizeof(struct msdos_dir_entry); spos = filp->f_pos - sizeof(struct msdos_dir_entry);
} else { } else {
long_slots = 0; long_slots = 0;
......
...@@ -377,7 +377,7 @@ fat_read_super(struct super_block *sb, void *data, int silent) ...@@ -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 */ /* N.B. we should parse directly into the sb structure */
memcpy(&(MSDOS_SB(sb)->options), &opts, sizeof(struct fat_mount_options)); memcpy(&(MSDOS_SB(sb)->options), &opts, sizeof(struct fat_mount_options));
cache_init(); fat_cache_init();
lock_super(sb); lock_super(sb);
if( blksize > 1024 ) if( blksize > 1024 )
{ {
......
...@@ -194,7 +194,7 @@ printk("set to %x\n",fat_access(sb,nr,-1)); ...@@ -194,7 +194,7 @@ printk("set to %x\n",fat_access(sb,nr,-1));
*/ */
file_cluster = 0; file_cluster = 0;
if ((curr = MSDOS_I(inode)->i_start) != 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; file_cluster = last;
while (curr && curr != -1){ while (curr && curr != -1){
PRINTK ((".")); PRINTK (("."));
...@@ -242,7 +242,7 @@ if (last) printk("next set to %d\n",fat_access(sb,last,-1)); ...@@ -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" printk ("file_cluster badly computed!!! %d <> %ld\n"
,file_cluster,inode->i_blocks/cluster_size); ,file_cluster,inode->i_blocks/cluster_size);
}else{ }else{
cache_add(inode,file_cluster,nr); fat_cache_add(inode,file_cluster,nr);
} }
inode->i_blocks += cluster_size; inode->i_blocks += cluster_size;
if (S_ISDIR(inode->i_mode)) { if (S_ISDIR(inode->i_mode)) {
......
...@@ -118,11 +118,13 @@ int fat_mmap(struct file * file, struct vm_area_struct * vma) ...@@ -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)
if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage) if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage)
return MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage(inode,page); return MSDOS_SB(inode->i_sb)->cvf_format
->cvf_readpage(inode,page);
printk("fat_readpage called with no handler (shouldn't happen)\n"); printk("fat_readpage called with no handler (shouldn't happen)\n");
return -1; return -1;
......
...@@ -127,6 +127,7 @@ static inline void init_once(struct inode * inode) ...@@ -127,6 +127,7 @@ static inline void init_once(struct inode * inode)
memset(inode, 0, sizeof(*inode)); memset(inode, 0, sizeof(*inode));
init_waitqueue(&inode->i_wait); init_waitqueue(&inode->i_wait);
INIT_LIST_HEAD(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_dentry);
sema_init(&inode->i_sem, 1); sema_init(&inode->i_sem, 1);
} }
......
...@@ -43,11 +43,6 @@ ...@@ -43,11 +43,6 @@
#include <asm/segment.h> #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 #ifdef NFS_DEBUG
# define NFSDBG_FACILITY NFSDBG_PROC # define NFSDBG_FACILITY NFSDBG_PROC
#endif #endif
...@@ -90,10 +85,6 @@ nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name, ...@@ -90,10 +85,6 @@ nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,
int status; int status;
dprintk("NFS call lookup %s\n", name); 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); status = rpc_call(server->client, NFSPROC_LOOKUP, &arg, &res, 0);
dprintk("NFS reply lookup: %d\n", status); dprintk("NFS reply lookup: %d\n", status);
return status; return status;
......
...@@ -57,6 +57,38 @@ void vfat_read_inode(struct inode *inode); ...@@ -57,6 +57,38 @@ void vfat_read_inode(struct inode *inode);
static int vfat_valid_shortname(const char *,int, int, int); static int vfat_valid_shortname(const char *,int, int, int);
static int vfat_format_name(const char *, int, char *, 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_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) static int strnicmp(const char *s1, const char *s2, int len)
{ {
...@@ -80,6 +112,13 @@ void vfat_put_super(struct super_block *sb) ...@@ -80,6 +112,13 @@ void vfat_put_super(struct super_block *sb)
MOD_DEC_USE_COUNT; 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 = { static struct super_operations vfat_sops = {
vfat_read_inode, vfat_read_inode,
...@@ -165,6 +204,27 @@ static int parse_options(char *options, struct fat_mount_options *opts) ...@@ -165,6 +204,27 @@ static int parse_options(char *options, struct fat_mount_options *opts)
* return ENOENT or EINVAL as appropriate. * return ENOENT or EINVAL as appropriate.
*/ */
static int vfat_hash(struct dentry *dentry, struct qstr *qstr) 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; const char *name;
int len; int len;
...@@ -187,9 +247,9 @@ static int vfat_hash(struct dentry *dentry, struct qstr *qstr) ...@@ -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; int alen, blen;
...@@ -200,18 +260,33 @@ static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) ...@@ -200,18 +260,33 @@ static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
alen--; alen--;
while (blen && b->name[blen-1] == '.') while (blen && b->name[blen-1] == '.')
blen--; blen--;
if (alen != blen) if (alen == blen) {
if (strnicmp(a->name, b->name, alen) == 0)
return 0;
}
return 1; return 1;
return strnicmp(a->name, b->name, alen);
} }
static struct dentry_operations vfat_dentry_operations = { /*
NULL, /* d_revalidate */ * Case sensitive compare of two vfat names.
vfat_hash, */
vfat_cmp, static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
NULL /* d_delete */ {
}; 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, struct super_block *vfat_read_super(struct super_block *sb,void *data,
int silent) int silent)
...@@ -235,7 +310,9 @@ struct super_block *vfat_read_super(struct super_block *sb,void *data, ...@@ -235,7 +310,9 @@ struct super_block *vfat_read_super(struct super_block *sb,void *data,
} else { } else {
MSDOS_SB(sb)->options.dotsOK = 0; MSDOS_SB(sb)->options.dotsOK = 0;
if (MSDOS_SB(sb)->options.name_check != 's') { 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[] = "[];,+="; ...@@ -321,7 +398,7 @@ static char replace_chars[] = "[];,+=";
static int vfat_find(struct inode *dir,struct qstr* name, static int vfat_find(struct inode *dir,struct qstr* name,
int find_long,int new_filename,int is_dir, 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 */ /* Checks the validity of a long MS-DOS filename */
/* Returns negative number on error, 0 for a normal /* Returns negative number on error, 0 for a normal
...@@ -519,7 +596,7 @@ static int vfat_create_shortname(struct inode *dir, const char *name, ...@@ -519,7 +596,7 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
int res; int res;
int spaces; int spaces;
char buf[8]; char buf[8];
struct slot_info sinfo; struct vfat_slot_info sinfo;
const char *name_start; const char *name_start;
struct qstr qname; struct qstr qname;
...@@ -778,7 +855,6 @@ xlate_to_uni(const char *name, int len, char *outname, int *outlen, ...@@ -778,7 +855,6 @@ xlate_to_uni(const char *name, int len, char *outname, int *outlen,
len--; len--;
op = outname; op = outname;
if (nls) { if (nls) {
/* XXX: i is incorrectly computed. */
for (i = 0, ip = name, op = outname, *outlen = 0; for (i = 0, ip = name, op = outname, *outlen = 0;
i < len && *outlen <= 260; i++, *outlen += 1) i < len && *outlen <= 260; i++, *outlen += 1)
{ {
...@@ -992,7 +1068,7 @@ static int vfat_readdir_cb( ...@@ -992,7 +1068,7 @@ static int vfat_readdir_cb(
} }
static int vfat_find(struct inode *dir,struct qstr* qname, 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 super_block *sb = dir->i_sb;
struct vfat_find_info vf; struct vfat_find_info vf;
...@@ -1118,37 +1194,36 @@ static int vfat_find(struct inode *dir,struct qstr* qname, ...@@ -1118,37 +1194,36 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
int vfat_lookup(struct inode *dir,struct dentry *dentry) int vfat_lookup(struct inode *dir,struct dentry *dentry)
{ {
int res; int res;
struct slot_info sinfo; struct vfat_slot_info sinfo;
struct inode *result; struct inode *result;
int table;
PRINTK (("vfat_lookup: name=%s, len=%d\n", PRINTK (("vfat_lookup: name=%s, len=%d\n",
dentry->d_name.name, dentry->d_name.len)); dentry->d_name.name, dentry->d_name.len));
if (MSDOS_SB(dir->i_sb)->options.name_check != 's') { table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
dentry->d_op = &vfat_dentry_operations; dentry->d_op = &vfat_dentry_ops[table];
}
result = NULL; result = NULL;
if ((res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo)) < 0) { if ((res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo)) < 0) {
d_add(dentry,NULL); result = NULL;
return 0; table++;
goto error;
} }
PRINTK (("vfat_lookup 4.5\n")); PRINTK (("vfat_lookup 4.5\n"));
if (!(result = iget(dir->i_sb,sinfo.ino))) if (!(result = iget(dir->i_sb,sinfo.ino)))
return -EACCES; return -EACCES;
PRINTK (("vfat_lookup 5\n")); 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 */ if (MSDOS_I(result)->i_busy) { /* mkdir in progress */
iput(result); iput(result);
d_add(dentry,NULL); result = NULL;
return 0; table++;
goto error;
} }
PRINTK (("vfat_lookup 6\n")); 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); d_add(dentry,result);
return 0; return 0;
} }
...@@ -1162,7 +1237,7 @@ static int vfat_create_entry(struct inode *dir,struct qstr* qname, ...@@ -1162,7 +1237,7 @@ static int vfat_create_entry(struct inode *dir,struct qstr* qname,
loff_t offset; loff_t offset;
struct buffer_head *bh; struct buffer_head *bh;
struct msdos_dir_entry *de; struct msdos_dir_entry *de;
struct slot_info sinfo; struct vfat_slot_info sinfo;
*result=0; *result=0;
PRINTK(("vfat_create_entry 1\n")); PRINTK(("vfat_create_entry 1\n"));
...@@ -1210,6 +1285,7 @@ int vfat_create(struct inode *dir,struct dentry* dentry,int mode) ...@@ -1210,6 +1285,7 @@ int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
if (res < 0) { if (res < 0) {
PRINTK(("vfat_create: unable to get new entry\n")); PRINTK(("vfat_create: unable to get new entry\n"));
} else { } else {
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry,result); d_instantiate(dentry,result);
} }
return res; return res;
...@@ -1388,7 +1464,7 @@ static int vfat_unlink_free_ino(struct inode *dir,struct buffer_head *bh, ...@@ -1388,7 +1464,7 @@ static int vfat_unlink_free_ino(struct inode *dir,struct buffer_head *bh,
return 0; 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, struct buffer_head **bh,struct dentry* dentry,
int is_dir,int nospc) int is_dir,int nospc)
{ {
...@@ -1422,13 +1498,31 @@ static int vfat_remove_entry(struct inode *dir,struct slot_info *sinfo, ...@@ -1422,13 +1498,31 @@ static int vfat_remove_entry(struct inode *dir,struct slot_info *sinfo,
return 0; 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) static int vfat_rmdirx(struct inode *dir,struct dentry* dentry)
{ {
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
int res; int res;
struct buffer_head *bh; struct buffer_head *bh;
struct slot_info sinfo; struct vfat_slot_info sinfo;
res = vfat_find(dir,&dentry->d_name,1,0,0,&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) ...@@ -1450,7 +1544,7 @@ int vfat_rmdir(struct inode *dir,struct dentry* dentry)
int res; int res;
res = vfat_rmdirx(dir, dentry); res = vfat_rmdirx(dir, dentry);
if (res >= 0) { if (res >= 0) {
d_delete(dentry); vfat_delete_dentries(dentry);
} }
return res; return res;
} }
...@@ -1463,7 +1557,7 @@ static int vfat_unlinkx( ...@@ -1463,7 +1557,7 @@ static int vfat_unlinkx(
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
int res; int res;
struct buffer_head *bh; struct buffer_head *bh;
struct slot_info sinfo; struct vfat_slot_info sinfo;
bh = NULL; bh = NULL;
res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo); 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) ...@@ -1498,6 +1592,7 @@ int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
res = vfat_create_dotdirs(inode, dir); res = vfat_create_dotdirs(inode, dir);
fat_unlock_creation(); fat_unlock_creation();
MSDOS_I(inode)->i_busy = 0; MSDOS_I(inode)->i_busy = 0;
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry,inode); d_instantiate(dentry,inode);
if (res < 0) { if (res < 0) {
if (vfat_rmdir(dir,dentry) < 0) if (vfat_rmdir(dir,dentry) < 0)
...@@ -1513,7 +1608,7 @@ int vfat_unlink(struct inode *dir,struct dentry* dentry) ...@@ -1513,7 +1608,7 @@ int vfat_unlink(struct inode *dir,struct dentry* dentry)
res = vfat_unlinkx (dir,dentry,1); res = vfat_unlinkx (dir,dentry,1);
if (res >= 0) { if (res >= 0) {
d_delete(dentry); vfat_delete_dentries(dentry);
} }
return res; return res;
} }
...@@ -1540,7 +1635,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry, ...@@ -1540,7 +1635,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
struct dentry *walk; struct dentry *walk;
int res, is_dir, i; int res, is_dir, i;
int locked = 0; int locked = 0;
struct slot_info sinfo; struct vfat_slot_info sinfo;
PRINTK(("vfat_rename 1\n")); PRINTK(("vfat_rename 1\n"));
if (old_dir == new_dir && if (old_dir == new_dir &&
......
...@@ -124,6 +124,8 @@ extern void __put_user_1(void); ...@@ -124,6 +124,8 @@ extern void __put_user_1(void);
extern void __put_user_2(void); extern void __put_user_2(void);
extern void __put_user_4(void); extern void __put_user_4(void);
extern void __put_user_bad(void);
#define __put_user_x(size,ret,x,ptr) \ #define __put_user_x(size,ret,x,ptr) \
__asm__ __volatile__("call __put_user_" #size \ __asm__ __volatile__("call __put_user_" #size \
:"=a" (ret) \ :"=a" (ret) \
...@@ -141,8 +143,89 @@ extern void __put_user_4(void); ...@@ -141,8 +143,89 @@ extern void __put_user_4(void);
__ret_pu; \ __ret_pu; \
}) })
#define __get_user(x,ptr) get_user(x,ptr) #define __get_user(x,ptr) \
#define __put_user(x,ptr) put_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 * The "xxx_ret" versions return constant specified in third argument, if
......
...@@ -61,6 +61,7 @@ struct dentry { ...@@ -61,6 +61,7 @@ struct dentry {
struct list_head d_lru; /* d_count = 0 LRU list */ struct list_head d_lru; /* d_count = 0 LRU list */
struct list_head d_child; /* child of parent list */ struct list_head d_child; /* child of parent list */
struct list_head d_subdirs; /* our children */ struct list_head d_subdirs; /* our children */
struct list_head d_alias; /* inode alias list */
struct qstr d_name; struct qstr d_name;
unsigned long d_time; /* used by d_revalidate */ unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op; struct dentry_operations *d_op;
......
...@@ -318,6 +318,7 @@ struct iattr { ...@@ -318,6 +318,7 @@ struct iattr {
struct inode { struct inode {
struct list_head i_hash; struct list_head i_hash;
struct list_head i_list; struct list_head i_list;
struct list_head i_dentry;
unsigned long i_ino; unsigned long i_ino;
kdev_t i_dev; kdev_t i_dev;
......
...@@ -163,7 +163,6 @@ struct msdos_dir_slot { ...@@ -163,7 +163,6 @@ struct msdos_dir_slot {
struct vfat_slot_info { struct vfat_slot_info {
int is_long; /* was the found entry long */ 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 long_slots; /* number of long slots in filename */
int total_slots; /* total slots (long and short) */ int total_slots; /* total slots (long and short) */
loff_t longname_offset; /* dir offset for longname start */ loff_t longname_offset; /* dir offset for longname start */
...@@ -219,10 +218,10 @@ extern int fat_smap(struct inode *inode,int sector); ...@@ -219,10 +218,10 @@ extern int fat_smap(struct inode *inode,int sector);
extern int fat_free(struct inode *inode,int skip); extern int fat_free(struct inode *inode,int skip);
void fat_cache_inval_inode(struct inode *inode); void fat_cache_inval_inode(struct inode *inode);
void fat_cache_inval_dev(kdev_t device); void fat_cache_inval_dev(kdev_t device);
extern void cache_init(void); extern void fat_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);
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);
int get_cluster(struct inode *inode,int cluster); int fat_get_cluster(struct inode *inode,int cluster);
/* inode.c */ /* inode.c */
extern int fat_bmap(struct inode *inode,int block); extern int fat_bmap(struct inode *inode,int block);
...@@ -256,7 +255,7 @@ extern void fat_truncate(struct inode *inode); ...@@ -256,7 +255,7 @@ extern void fat_truncate(struct inode *inode);
/* mmap.c */ /* mmap.c */
extern int fat_mmap(struct file *, struct vm_area_struct *); 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 */ /* vfat.c */
......
...@@ -119,6 +119,8 @@ EXPORT_SYMBOL(do_mmap); ...@@ -119,6 +119,8 @@ EXPORT_SYMBOL(do_mmap);
EXPORT_SYMBOL(do_munmap); EXPORT_SYMBOL(do_munmap);
EXPORT_SYMBOL(exit_mm); EXPORT_SYMBOL(exit_mm);
EXPORT_SYMBOL(exit_files); EXPORT_SYMBOL(exit_files);
EXPORT_SYMBOL(exit_fs);
EXPORT_SYMBOL(exit_sighand);
/* internal kernel memory management */ /* internal kernel memory management */
EXPORT_SYMBOL(__get_free_pages); EXPORT_SYMBOL(__get_free_pages);
......
...@@ -11,6 +11,7 @@ if [ "$CONFIG_NETLINK" = "y" ]; then ...@@ -11,6 +11,7 @@ if [ "$CONFIG_NETLINK" = "y" ]; then
fi fi
bool 'Network firewalls' CONFIG_FIREWALL bool 'Network firewalls' CONFIG_FIREWALL
bool 'Network aliasing' CONFIG_NET_ALIAS bool 'Network aliasing' CONFIG_NET_ALIAS
bool 'Socket Filtering' CONFIG_FILTER
tristate 'Unix domain sockets' CONFIG_UNIX tristate 'Unix domain sockets' CONFIG_UNIX
bool 'TCP/IP networking' CONFIG_INET bool 'TCP/IP networking' CONFIG_INET
if [ "$CONFIG_INET" = "y" ]; then if [ "$CONFIG_INET" = "y" ]; then
......
...@@ -16,6 +16,10 @@ ifeq ($(CONFIG_SYSCTL),y) ...@@ -16,6 +16,10 @@ ifeq ($(CONFIG_SYSCTL),y)
O_OBJS += sysctl_net_core.o O_OBJS += sysctl_net_core.o
endif endif
ifdef CONFIG_FILTER
O_OBJS += filter.o
endif
ifdef CONFIG_NET ifdef CONFIG_NET
O_OBJS += dev.o dev_mcast.o O_OBJS += dev.o dev_mcast.o
......
...@@ -123,6 +123,10 @@ ...@@ -123,6 +123,10 @@
#include <net/icmp.h> #include <net/icmp.h>
#include <linux/ipsec.h> #include <linux/ipsec.h>
#ifdef CONFIG_FILTER
#include <linux/filter.h>
#endif
#define min(a,b) ((a)<(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b))
/* Run time adjustable parameters. */ /* Run time adjustable parameters. */
...@@ -149,6 +153,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -149,6 +153,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
struct ifreq req; struct ifreq req;
int ret = 0; int ret = 0;
#ifdef CONFIG_FILTER
struct sock_fprog fprog;
#endif
/* /*
* Options without arguments * Options without arguments
*/ */
......
...@@ -1468,6 +1468,14 @@ static inline struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb) ...@@ -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) 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); skb_set_owner_r(skb, sk);
/* /*
......
...@@ -121,6 +121,10 @@ EXPORT_SYMBOL(net_families); ...@@ -121,6 +121,10 @@ EXPORT_SYMBOL(net_families);
EXPORT_SYMBOL(sock_kmalloc); EXPORT_SYMBOL(sock_kmalloc);
EXPORT_SYMBOL(sock_kfree_s); EXPORT_SYMBOL(sock_kfree_s);
#ifdef CONFIG_FILTER
EXPORT_SYMBOL(sk_run_filter);
#endif
EXPORT_SYMBOL(neigh_table_init); EXPORT_SYMBOL(neigh_table_init);
EXPORT_SYMBOL(neigh_table_clear); EXPORT_SYMBOL(neigh_table_clear);
EXPORT_SYMBOL(__neigh_lookup); 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