Commit 70e39deb authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.44pre2

parent d5977cd7
......@@ -287,17 +287,19 @@ CONFIG_BLK_DEV_RZ1000
Linux. This may slow disk throughput by a few percent, but at least
things will operate 100% reliably. If unsure, say Y.
Intel 82371 PIIX (Triton I/II) DMA support
Intel 82371 PIIX (Triton I/II), VIA VP-1 DMA support
CONFIG_BLK_DEV_TRITON
If your PCI system uses an IDE harddrive (as opposed to SCSI, say)
and includes the Intel Triton I/II IDE interface chipset (i82371FB,
i82371SB or i82371AB), you will want to enable this option to allow
use of bus-mastering DMA data transfers. Read the comments at the
i82371SB or i82371AB), or the VIA VP-1 IDE interface chipset
(VT82C586), you will want to enable this option to allow use of
bus-mastering DMA data transfers. Read the comments at the
beginning of drivers/block/triton.c and Documentation/ide.txt.
You can get the latest version of the hdparm utility via
ftp (user: anonymous) from
sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/; it is
used to tune your harddisk. It is safe to say Y to this question.
used to tune your harddisk.
It is safe to say Y to this question.
Other IDE chipset support
CONFIG_IDE_CHIPSETS
......
VERSION = 2
PATCHLEVEL = 1
SUBLEVEL = 43
SUBLEVEL = 44
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
......
......@@ -2603,6 +2603,7 @@ __initfunc(static void probe_for_hwifs (void))
ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, &ide_init_triton, 0);
ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, &ide_init_triton, 0);
#endif /* CONFIG_BLK_DEV_TRITON */
ide_probe_pci (PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, &ide_init_triton, 0);
#ifdef CONFIG_BLK_DEV_OPTI621
ide_probe_pci (PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, &ide_init_opti621, 0);
#endif /* CONFIG_BLK_DEV_OPTI621 */
......
......@@ -298,7 +298,7 @@ typedef void (ide_selectproc_t) (ide_drive_t *);
typedef enum { ide_unknown, ide_generic, ide_triton,
ide_cmd640, ide_dtc2278, ide_ali14xx,
ide_qd6580, ide_umc8672, ide_ht6560b,
ide_promise }
ide_promise, ide_via }
hwif_chipset_t;
typedef struct hwif_s {
......
......@@ -122,15 +122,25 @@ static unsigned int piix_key;
#define PIIX_FLAGS_PREFETCH 4
#define PIIX_FLAGS_FAST_DMA 8
typedef struct {
unsigned d0_flags :4;
unsigned d1_flags :4;
unsigned recovery :2;
unsigned reserved :2;
unsigned sample :2;
unsigned sidetim_enabled:1;
unsigned ports_enabled :1;
} piix_timing_t;
union chip_en_reg_u {
struct {
unsigned d0_flags :4;
unsigned d1_flags :4;
unsigned recovery :2;
unsigned reserved :2;
unsigned sample :2;
unsigned sidetim_enabled:1;
unsigned ports_enabled :1;
} piix_s;
struct {
unsigned sec_en :1;
unsigned pri_en :1;
unsigned reserved :14;
} via_s;
};
typedef union chip_en_reg_u piix_timing_t;
typedef struct {
unsigned pri_recovery :2;
......@@ -269,16 +279,16 @@ static int piix_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
printk("%s: pcibios read failed\n", HWIF(drive)->name);
return 1;
}
dflags = drive->select.b.unit ? timing.d1_flags : timing.d0_flags;
dflags = drive->select.b.unit ? timing.piix_s.d1_flags : timing.piix_s.d0_flags;
if (dflags & PIIX_FLAGS_FAST_PIO) {
if (func == ide_dma_on && drive->media == ide_disk)
dflags |= PIIX_FLAGS_FAST_DMA;
else
dflags &= ~PIIX_FLAGS_FAST_DMA;
if (drive->select.b.unit == 0)
timing.d0_flags = dflags;
timing.piix_s.d0_flags = dflags;
else
timing.d1_flags = dflags;
timing.piix_s.d1_flags = dflags;
if (pcibios_write_config_word(piix_pci_bus, piix_pci_fn, reg, *(short *)&timing)) {
printk("%s: pcibios write failed\n", HWIF(drive)->name);
return 1;
......@@ -456,8 +466,14 @@ void ide_init_triton (byte bus, byte fn)
chipset = "PIIX4";
else if (devid == PCI_DEVICE_ID_INTEL_82371SB_1)
chipset = "PIIX3";
else
else if (devid == PCI_DEVICE_ID_INTEL_82371_1)
chipset = "PIIX";
else if (devid == PCI_DEVICE_ID_VIA_82C586_1)
chipset = "VP1";
else {
printk("Unknown PCI IDE interface 0x%x\n", devid);
goto quit;
}
printk("%s: bus-master IDE device on PCI bus %d function %d\n", chipset, bus, fn);
......@@ -470,13 +486,24 @@ void ide_init_triton (byte bus, byte fn)
printk("%s: IDE ports are not enabled (BIOS)\n", chipset);
goto quit;
}
if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0])))
goto quit;
if ((rc = pcibios_read_config_word(bus, fn, 0x42, (short *)&timings[1])))
goto quit;
if ((!timings[0].ports_enabled) && (!timings[1].ports_enabled)) {
printk("%s: neither IDE port is enabled\n", chipset);
goto quit;
if (devid == PCI_DEVICE_ID_VIA_82C586_1) {
/* pri and sec channel enables are in port 0x40 */
if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0])))
goto quit;
if ((!timings[0].via_s.pri_en && (!timings[0].via_s.sec_en))) {
printk("%s: neither IDE port is enabled\n", chipset);
goto quit;
}
}
else { /* INTEL piix */
if ((rc = pcibios_read_config_word(bus, fn, 0x40, (short *)&timings[0])))
goto quit;
if ((rc = pcibios_read_config_word(bus, fn, 0x42, (short *)&timings[1])))
goto quit;
if ((!timings[0].piix_s.ports_enabled) && (!timings[1].piix_s.ports_enabled)) {
printk("%s: neither IDE port is enabled\n", chipset);
goto quit;
}
}
/*
......@@ -526,10 +553,30 @@ void ide_init_triton (byte bus, byte fn)
case 0x170: pri_sec = 1; break;
default: continue;
}
if (devid == PCI_DEVICE_ID_VIA_82C586_1) {
timing = timings[0];
switch (h) {
case 0:
if (!timing.piix_s.ports_enabled) {
printk("port 0 DMA not enabled\n");
continue;
}
case 1:
if (!timing.piix_s.sidetim_enabled) {
printk("port 1 DMA not enabled\n");
continue;
}
}
hwif->chipset = ide_via;
}
else { /* PIIX */
timing = timings[pri_sec];
if (!timing.ports_enabled) /* interface disabled? */
if (!timing.piix_s.ports_enabled) /* interface disabled? */
continue;
hwif->chipset = ide_triton;
}
if (dma_enabled)
init_piix_dma(hwif, bmiba + (pri_sec ? 8 : 0));
#ifdef DISPLAY_PIIX_TIMINGS
......@@ -539,17 +586,32 @@ void ide_init_triton (byte bus, byte fn)
{
const char *slave;
piix_sidetim_t sidetim;
byte sample = 5 - timing.sample;
byte recovery = 4 - timing.recovery;
byte sample = 5 - timing.piix_s.sample;
byte recovery = 4 - timing.piix_s.recovery;
unsigned int drvtim;
if (devid == PCI_DEVICE_ID_VIA_82C586_1) {
pcibios_read_config_dword(bus, fn, 0x48, &drvtim);
if (pri_sec == 0) {
printk(" %s master: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+(drvtim>>28), 1+((drvtim & 0x0f000000)>>24));
printk(" %s slave: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf00000)>>20), 1+((drvtim & 0x0f0000)>>16));
continue;
} else {
printk(" %s master: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf000)>>12), 1+((drvtim & 0x0f00)>>8));
printk(" %s slave: active_pulse_CLKs=%d, recovery_CLKs=%d\n", hwif->name, 1+((drvtim & 0xf0)>>4), 1+(drvtim & 0x0f));
continue;
}
}
if ((devid == PCI_DEVICE_ID_INTEL_82371SB_1
|| devid == PCI_DEVICE_ID_INTEL_82371AB)
&& timing.sidetim_enabled
&& timing.piix_s.sidetim_enabled
&& !pcibios_read_config_byte(bus, fn, 0x44, (byte *) &sidetim))
slave = ""; /* PIIX3 and later */
else
slave = "/slave"; /* PIIX, or PIIX3 in compatibility mode */
printk(" %s master%s: sample_CLKs=%d, recovery_CLKs=%d\n", hwif->name, slave, sample, recovery);
print_piix_drive_flags ("master:", timing.d0_flags);
print_piix_drive_flags ("master:", timing.piix_s.d0_flags);
if (!*slave) {
if (pri_sec == 0) {
sample = 5 - sidetim.pri_sample;
......@@ -560,7 +622,7 @@ void ide_init_triton (byte bus, byte fn)
}
printk(" slave : sample_CLKs=%d, recovery_CLKs=%d\n", sample, recovery);
}
print_piix_drive_flags ("slave :", timing.d1_flags);
print_piix_drive_flags ("slave :", timing.piix_s.d1_flags);
}
#endif /* DISPLAY_PIIX_TIMINGS */
}
......
......@@ -180,7 +180,7 @@ static long rtc_read(struct inode *inode, struct file *file, char *buf,
data = rtc_irq_data;
rtc_irq_data = 0;
restore_flags(flags);
retval = put_user(data, (unsigned long *)buf)) ?: sizeof(unsigned long);
retval = put_user(data, (unsigned long *)buf) ?: sizeof(unsigned long);
}
current->state = TASK_RUNNING;
......
......@@ -143,12 +143,8 @@ if [ "$CONFIG_NET_RADIO" != "n" ]; then
bool 'Soundmodem support for 2400 baud AFSK modulation (8MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_8
bool 'Soundmodem support for 4800 baud HAPN-1 modulation' CONFIG_SOUNDMODEM_HAPN4800
bool 'Soundmodem support for 9600 baud FSK G3RUH modulation' CONFIG_SOUNDMODEM_FSK9600
if [ -f drivers/net/soundmodem/sm_afsk2666.c ]; then
bool 'Soundmodem support for 2666 baud AFSK modulation' CONFIG_SOUNDMODEM_AFSK2666
fi
if [ -f drivers/net/soundmodem/sm_psk4800.c ]; then
bool 'Soundmodem support for 4800 baud PSK modulation' CONFIG_SOUNDMODEM_PSK4800
fi
#bool 'Soundmodem support for 2666 baud AFSK modulation' CONFIG_SOUNDMODEM_AFSK2666
#bool 'Soundmodem support for 4800 baud PSK modulation' CONFIG_SOUNDMODEM_PSK4800
fi
fi
tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP
......
......@@ -204,7 +204,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( VIA, VIA_82C586_1, "VT 82C586 Apollo VP-1"),
DEVICE( VIA, VIA_82C576, "VT 82C576 3V"),
DEVICE( VIA, VIA_82C585, "VT 82C585VP Apollo VP-1"),
DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo VP-1"),
DEVICE( VIA, VIA_82C586, "VT 82C586 Apollo VP-1"),
DEVICE( VIA, VIA_82C416, "VT 82C416MV"),
DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"),
DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"),
......
......@@ -71,6 +71,7 @@
#include <linux/fs.h>
#include <linux/dalloc.h>
#include <linux/dlists.h>
#include <linux/malloc.h>
/* this should be removed after the beta phase */
/* #define DEBUG */
......@@ -90,33 +91,6 @@
#define D_RECURSIVE 4
#define D_NO_FREE 8
/* adjust these constants if you know a probability distribution ... */
#define D_SMALL 16
#define D_MEDIUM 64
#define D_LARGE 256
#define D_HUGE D_MAXLEN
#define BASE_DHEADER(x) (struct dheader*)((unsigned long)(x) & ~(PAGE_SIZE-1))
#define BYTE_ADD(x,n) (void*)((char*)(x) + (n))
#define BYTE_SUB(x,n) (void*)((char*)(x) - (n))
/* This is for global allocation of dentries. Remove this when
* converting to SLAB.
*/
struct dheader {
struct dentry * emptylist;
short free, maxfree;
struct dheader * next;
struct dheader * prev;
};
struct anchors {
struct dheader * free; /* each contains at least 1 empty dentry */
struct dheader * full; /* all the used up ones */
struct dheader * dir_free;
struct dheader * dir_full;
};
/* This is only used for directory dentries. Think of it as an extension
* of the dentry.
* It is defined as separate struct, so it uses up space only
......@@ -133,9 +107,6 @@ struct ddir {
unsigned short dd_negs; /* # of negative entries */
};
DEF_INSERT(header,struct dheader,next,prev)
DEF_REMOVE(header,struct dheader,next,prev)
DEF_INSERT(alias,struct dentry,d_next,d_prev)
DEF_REMOVE(alias,struct dentry,d_next,d_prev)
......@@ -145,13 +116,10 @@ DEF_REMOVE(hash,struct dentry,d_hash_next,d_hash_prev)
DEF_INSERT(basket,struct dentry,d_basket_next,d_basket_prev)
DEF_REMOVE(basket,struct dentry,d_basket_next,d_basket_prev)
static struct anchors anchors[4];
struct dentry * the_root = NULL;
unsigned long name_cache_init(unsigned long mem_start, unsigned long mem_end)
{
memset(anchors, 0, sizeof(anchors));
return mem_start;
}
......@@ -260,7 +228,7 @@ void printpath(struct dentry * entry)
{
if(!IS_ROOT(entry))
printpath(entry->d_parent);
printk("/%s", entry->d_name);
printk("/%s", entry->d_name.name);
}
static inline long has_sons(struct ddir * ddir)
......@@ -310,82 +278,42 @@ static void d_panic(void)
panic("VFS: dcache directory corruption");
}
/*
* IF this is a directory, the ddir has been allocated right
* after the dentry.
*/
static inline struct ddir * d_dir(struct dentry * entry)
{
struct ddir * res = BYTE_SUB(entry, sizeof(struct ddir));
if(!(entry->d_flag & D_DIR))
d_panic();
#ifdef DEBUG
if(!entry)
panic("entry NULL!");
if(BASE_DHEADER(res) != BASE_DHEADER(entry))
printk("Scheisse!!!\n");
#endif
return res;
return (struct ddir *) (entry+1);
}
static /*inline*/ struct dheader * dinit(int isdir, int size)
#define NAME_ALLOC_LEN(len) ((len+16) & ~15)
struct dentry * d_alloc(struct dentry * parent, int len, int isdir)
{
struct dheader * res = (struct dheader*)__get_free_page(GFP_KERNEL);
int restlen = PAGE_SIZE - sizeof(struct dheader);
struct dentry * ptr = BYTE_ADD(res, sizeof(struct dheader));
struct dentry *res;
int size = sizeof(struct dentry);
int flag = 0;
if(!res)
return NULL;
memset(res, 0, sizeof(struct dheader));
if(isdir) {
ptr = BYTE_ADD(ptr, sizeof(struct ddir));
if (isdir) {
size += sizeof(struct ddir);
flag = D_DIR;
}
if(BASE_DHEADER(ptr) != res)
panic("Bad kernel page alignment");
size += sizeof(struct dentry) - D_MAXLEN;
res->emptylist = NULL;
res->free = 0;
while(restlen >= size) {
#ifdef DEBUG
ins(ptr);
if(BASE_DHEADER(ptr) != res)
panic("Wrong dinit!");
#endif
ptr->d_next = res->emptylist;
res->emptylist = ptr;
ptr = BYTE_ADD(ptr, size);
res->free++;
restlen -= size;
}
res->maxfree = res->free;
return res;
}
res = kmalloc(size, GFP_KERNEL);
if (!res)
return NULL;
memset(res, 0, size);
res->d_flag = flag;
static /*inline*/ struct dentry * __dalloc(struct anchors * anchor,
struct dentry * parent, int isdir,
int len, int size)
{
struct dheader ** free = isdir ? &anchor->dir_free : &anchor->free;
struct dheader ** full = isdir ? &anchor->dir_full : &anchor->full;
struct dheader * base = *free;
struct dentry * res;
if(!base) {
base = dinit(isdir, size);
if(!base)
return NULL;
insert_header(free, base);
}
base->free--;
res = base->emptylist;
if(!(base->emptylist = res->d_next)) {
remove_header(free, base);
insert_header(full, base);
}
memset(res, 0, sizeof(struct dentry) - D_MAXLEN);
if(isdir) {
res->d_flag = D_DIR;
memset(d_dir(res), 0, sizeof(struct ddir));
res->d_name.name = kmalloc(NAME_ALLOC_LEN(len), GFP_KERNEL);
if (!res->d_name.name) {
kfree(res);
return NULL;
}
res->d_len = len;
res->d_name.len = len;
res->d_parent = parent;
if(parent) {
struct ddir * pdir = d_dir(parent);
......@@ -403,33 +331,6 @@ static /*inline*/ struct dentry * __dalloc(struct anchors * anchor,
return res;
}
struct dentry * d_alloc(struct dentry * parent, int len, int isdir)
{
int i, size;
#ifdef DEBUG
if(the_root)
recursive_test(the_root);
LOG("d_alloc", parent);
#endif
if(len >= D_MEDIUM) {
if(len >= D_LARGE) {
i = 3;
size = D_HUGE;
} else {
i = 2;
size = D_LARGE;
}
} else if(len >= D_SMALL) {
i = 1;
size = D_MEDIUM;
} else {
i = 0;
size = D_SMALL;
}
return __dalloc(&anchors[i], parent, isdir, len, size);
}
extern blocking struct dentry * d_alloc_root(struct inode * root_inode)
{
struct dentry * res = the_root;
......@@ -442,7 +343,7 @@ extern blocking struct dentry * d_alloc_root(struct inode * root_inode)
the_root = res = d_alloc(NULL, 0, 1);
LOG("d_alloc_root", res);
res->d_parent = res;
res->d_name[0]='\0';
res->d_name.name[0]='\0';
ddir = d_dir(res);
ddir->dd_alloced = 999; /* protect from deletion */
}
......@@ -460,8 +361,8 @@ static inline unsigned long d_hash(char first, char last)
static inline struct dentry ** d_base_entry(struct ddir * pdir, struct dentry * entry)
{
return &pdir->dd_hashtable[d_hash(entry->d_name[0],
entry->d_name[entry->d_len-1])];
return &pdir->dd_hashtable[d_hash(entry->d_name.name[0],
entry->d_name.name[entry->d_name.len-1])];
}
static inline struct dentry ** d_base_qstr(struct ddir * pdir,
......@@ -569,12 +470,8 @@ static /*inline*/ void _d_handle_zombie(struct dentry * entry,
}
static /*inline*/ blocking void _d_del(struct dentry * entry,
struct anchors * anchor,
int flags)
{
struct dheader ** free;
struct dheader ** full;
struct dheader * base = BASE_DHEADER(entry);
struct ddir * ddir = NULL;
struct ddir * pdir;
struct inode * inode = entry->d_flag & D_PRELIMINARY ? NULL : entry->u.d_inode;
......@@ -587,13 +484,6 @@ static /*inline*/ blocking void _d_del(struct dentry * entry,
printk("VFS: dcache parent is NULL\n");
return;
}
if(entry->d_flag & D_DIR) {
free = &anchor->dir_free;
full = &anchor->dir_full;
} else {
free = &anchor->free;
full = &anchor->full;
}
pdir = d_dir(entry->d_parent);
if(!IS_ROOT(entry))
_d_remove_from_parent(entry, pdir, inode, flags);
......@@ -636,50 +526,23 @@ static /*inline*/ blocking void _d_del(struct dentry * entry,
}
}
if(!(flags & D_NO_FREE) && !(entry->d_flag & D_ZOMBIE)) {
base->free++;
if(base->free == base->maxfree) {
#ifndef DEBUG
remove_header(free, base);
free_page((unsigned long)base);
goto done;
#endif
}
entry->d_next = base->emptylist;
base->emptylist = entry;
if(!entry->d_next) {
remove_header(full, base);
insert_header(free, base);
}
kfree(entry->d_name.name);
kfree(entry);
#ifdef DEBUG
x_freed++;
#endif
}
#ifndef DEBUG
done:
#else
#ifdef DEBUG
x_free++;
#endif
}
blocking void d_del(struct dentry * entry, int flags)
{
int i;
if(!entry)
return;
LOG("d_clear", entry);
if(entry->d_len >= D_MEDIUM) {
if(entry->d_len >= D_LARGE) {
i = 3;
} else {
i = 2;
}
} else if(entry->d_len >= D_SMALL) {
i = 1;
} else {
i = 0;
}
_d_del(entry, &anchors[i], flags);
_d_del(entry, flags);
}
static inline struct dentry * __dlookup(struct dentry ** base,
......@@ -694,10 +557,10 @@ static inline struct dentry * __dlookup(struct dentry ** base,
if(appendix)
totallen += appendix->len;
do {
if(tmp->d_len == totallen &&
if(tmp->d_name.len == totallen &&
!(tmp->d_flag & D_DUPLICATE) &&
!strncmp(tmp->d_name, name->name, name->len) &&
(!appendix || !strncmp(tmp->d_name+name->len,
!strncmp(tmp->d_name.name, name->name, name->len) &&
(!appendix || !strncmp(tmp->d_name.name+name->len,
appendix->name, appendix->len)))
return tmp;
tmp = tmp->d_hash_next;
......@@ -755,7 +618,7 @@ static /*inline*/ blocking void _d_insert_to_parent(struct dentry * entry,
if(inode && inode->i_dentry && (entry->d_flag & D_DIR)) {
struct dentry * tmp = inode->i_dentry;
printk("Auweia inode=%p entry=%p (%p %p %s)\n",
inode, entry, parent->u.d_inode, parent, parent->d_name);
inode, entry, parent->u.d_inode, parent, parent->d_name.name);
printk("entry path="); printpath(entry); printk("\n");
do {
TST("auweia",tmp);
......@@ -801,15 +664,15 @@ blocking void d_add(struct dentry * entry, struct inode * inode,
LOG("d_add", entry);
#endif
if(ininame) {
if(ininame->len != entry->d_len) {
if(ininame->len != entry->d_name.len) {
printk("VFS: d_add with wrong string length");
entry->d_len = ininame->len; /* kludge */
entry->d_name.len = ininame->len; /* kludge */
}
memcpy(entry->d_name, ininame->name, ininame->len);
entry->d_name[ininame->len] = '\0';
memcpy(entry->d_name.name, ininame->name, ininame->len);
entry->d_name.name[ininame->len] = '\0';
} else {
dummy.name = entry->d_name;
dummy.len = entry->d_len;
dummy.name = entry->d_name.name;
dummy.len = entry->d_name.len;
ininame = &dummy;
}
if(entry->d_flag & D_HASHED)
......@@ -871,11 +734,45 @@ blocking void d_entry_preliminary(struct dentry * parent,
}
}
static inline void alloc_new_name(struct dentry * entry, int len)
{
int alloc_len = NAME_ALLOC_LEN(len);
char *name;
if (alloc_len == NAME_ALLOC_LEN(entry->d_name.len))
return;
name = kmalloc(alloc_len, GFP_KERNEL);
if (!name)
printk("out of memory for dcache\n");
kfree(entry->d_name.name);
entry->d_name.name = name;
}
static inline void d_remove_old_parent(struct dentry * entry)
{
struct ddir * pdir;
struct inode * inode;
pdir = d_dir(entry->d_parent);
inode = entry->u.d_inode;
_d_remove_from_parent(entry, pdir, inode, D_NO_CLEAR_INODE);
}
static inline void d_add_new_parent(struct dentry * entry, struct inode * new_parent)
{
struct ddir * pdir;
struct inode * inode;
pdir = d_dir(entry->d_parent = new_parent->i_dentry);
inode = entry->u.d_inode;
_d_insert_to_parent(entry, pdir, inode, &entry->d_name, entry->d_flag);
}
blocking void d_move(struct dentry * entry, struct inode * newdir,
struct qstr * newname, struct qstr * newapp)
{
struct ddir tmp;
struct dentry * new;
struct inode * inode;
int len;
int flags;
......@@ -891,38 +788,29 @@ blocking void d_move(struct dentry * entry, struct inode * newdir,
return;
}
#if 0
printk("d_move %p '%s' -> '%s%s' dent_count=%d\n", inode, entry->d_name,
printk("d_move %p '%s' -> '%s%s' dent_count=%d\n", inode, entry->d_name.name,
newname->name, newapp ? newapp->name : "", inode->i_dent_count);
#endif
if(flags & D_ZOMBIE) {
printk("VFS: moving zombie entry\n");
}
if(flags & D_DIR) {
struct ddir * ddir = d_dir(entry);
memcpy(&tmp, ddir, sizeof(struct ddir));
d_remove_old_parent(entry);
/* Simulate empty dir for d_del(). */
memset(ddir, 0, sizeof(struct ddir));
}
len = newname->len;
if(newapp) {
len += newapp->len;
flags |= D_BASKET;
} else
flags &= ~D_BASKET;
new = d_alloc(newdir->i_dentry, len, flags & D_DIR);
memcpy(new->d_name, newname->name, newname->len);
alloc_new_name(entry, len);
memcpy(entry->d_name.name, newname->name, newname->len);
if(newapp)
memcpy(new->d_name+newname->len, newapp->name, newapp->len);
new->d_name[len] = '\0';
d_del(entry, D_NO_CLEAR_INODE);
d_add(new, inode, NULL, flags & (D_DIR|D_BASKET));
if(flags & D_DIR) {
struct ddir * ddir = d_dir(new);
memcpy(ddir, &tmp, sizeof(struct ddir));
}
memcpy(entry->d_name.name+newname->len, newapp->name, newapp->len);
entry->d_name.name[len] = '\0';
entry->d_name.len = len;
d_add_new_parent(entry, newdir);
}
int d_path(struct dentry * entry, struct inode * chroot, char * buf)
......@@ -939,8 +827,8 @@ int d_path(struct dentry * entry, struct inode * chroot, char * buf)
*buf++ = '/';
len++;
}
memcpy(buf, entry->d_name, entry->d_len);
return len + entry->d_len;
memcpy(buf, entry->d_name.name, entry->d_name.len);
return len + entry->d_name.len;
}
}
......@@ -966,7 +854,7 @@ blocking struct inode * d_inode(struct dentry ** changing_entry)
#ifdef CONFIG_DCACHE_PRELOAD
if(entry->d_flag & D_PRELIMINARY) {
struct qstr name = { entry->d_name, entry->d_len };
struct qstr name = { entry->d_name.name, entry->d_name.len };
struct ddir * pdir = d_dir(entry->d_parent);
struct dentry ** base = d_base_qstr(pdir, &name, NULL);
struct dentry * found;
......@@ -1014,7 +902,7 @@ blocking struct inode * d_inode(struct dentry ** changing_entry)
d_del(entry, D_NO_CLEAR_INODE);
*changing_entry = found;
} else if(S_ISDIR(inode->i_mode)) {
struct dentry * new = d_alloc(entry->d_parent, entry->d_len, 1);
struct dentry * new = d_alloc(entry->d_parent, entry->d_name.len, 1);
if(new)
d_add(new, inode, &name, D_DIR);
*changing_entry = new;
......
......@@ -951,7 +951,7 @@ static void basket_name(struct inode * dir, struct dentry * entry)
{
char prefix[32];
struct qstr prename = { prefix, 14 };
struct qstr entname = { entry->d_name, entry->d_len };
struct qstr entname = { entry->d_name.name, entry->d_name.len };
struct inode * inode;
struct dentry * old = entry; /* dummy */
int i;
......
......@@ -266,8 +266,8 @@ asmlinkage int sys_getdents(unsigned int fd, void * dirent, unsigned int count)
if(inode) {
nr++;
if(nr > (file->f_pos & ~BASKET_BIT)) {
int err = filldir(&buf, ptr->d_name,
ptr->d_len,
int err = filldir(&buf, ptr->d_name.name,
ptr->d_name.len,
file->f_pos,
inode->i_ino);
if(err)
......
......@@ -765,9 +765,9 @@ int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const cha
struct dentry * old = dir_i->i_dentry;
struct dentry * new;
vfs_lock();
new = d_alloc(old->d_parent, old->d_len, 1);
new = d_alloc(old->d_parent, old->d_name.len, 1);
if(new) {
struct qstr copy = { old->d_name, old->d_len };
struct qstr copy = { old->d_name.name, old->d_name.len };
d_add(new, sb->s_mounted, &copy, D_DUPLICATE);
vfs_unlock();
} else {
......
......@@ -9,7 +9,7 @@
* <schoebel@informatik.uni-stuttgart.de>.
*/
#define D_MAXLEN 1024
#define D_MAXLEN 1024
/* public flags for d_add() */
#define D_NORMAL 0
......@@ -26,6 +26,16 @@
#define IS_ROOT(x) ((x) == (x)->d_parent)
/* "quick string" -- I introduced this to shorten the parameter list
* of many routines. Think of it as a (str,stlen) pair.
* Storing the len instead of doing strlen() very often is performance
* critical.
*/
struct qstr {
char * name;
int len;
};
struct dentry {
union {
struct inode * d_inode; /* Where the name belongs to */
......@@ -38,19 +48,8 @@ struct dentry {
struct dentry * d_hash_prev;
struct dentry * d_basket_next;
struct dentry * d_basket_prev;
short d_len; /* set by dalloc() */
short d_flag;
char d_name[D_MAXLEN];
};
/* "quick string" -- I introduced this to shorten the parameter list
* of many routines. Think of it as a (str,stlen) pair.
* Storing the len instead of doing strlen() very often is performance
* critical.
*/
struct qstr {
const char * name;
int len;
struct qstr d_name;
unsigned int d_flag;
};
extern struct dentry * the_root;
......
......@@ -15,7 +15,9 @@
#include <linux/net.h>
#include <linux/kdev_t.h>
#include <linux/ioctl.h>
#include <asm/atomic.h>
#include <asm/bitops.h>
/* Prefixes for routines (having no effect), but indicate what
* the routine may do. This can greatly ease reasoning about routines...
......
......@@ -497,7 +497,7 @@
#define PCI_DEVICE_ID_VIA_82C586_1 0x0571
#define PCI_DEVICE_ID_VIA_82C576 0x0576
#define PCI_DEVICE_ID_VIA_82C585 0x0585
#define PCI_DEVICE_ID_VIA_82C586_0 0x0586
#define PCI_DEVICE_ID_VIA_82C586 0x0586
#define PCI_DEVICE_ID_VIA_82C416 0x1571
#define PCI_VENDOR_ID_VORTEX 0x1119
......
......@@ -31,6 +31,7 @@
// * Only resolves operands of jump and call instructions.
#include <fstream.h>
#include <strstream.h>
#include <iomanip.h>
#include <stdio.h>
#include <string.h>
......@@ -184,9 +185,23 @@ NameList::decode(unsigned char* code, long eip_addr)
char buf[1024];
int lines = 0;
int eip_seen = 0;
long offset;
while (fgets(buf, sizeof(buf), objdump_FILE)) {
if (eip_seen && buf[4] == ':') {
// assume objdump from binutils 2.8..., reformat to old style
offset = strtol(buf, 0, 16);
char newbuf[sizeof(buf)];
memset(newbuf, '\0', sizeof(newbuf));
ostrstream ost(newbuf, sizeof(newbuf));
ost.width(8);
ost << offset;
ost << " <_EIP+" << offset << ">: " << &buf[6] << ends;
strcpy(buf, newbuf);
}
if (!strnequ(&buf[9], "<_EIP", 5))
continue;
eip_seen = 1;
if (strstr(buf, " is out of bounds"))
break;
lines++;
......@@ -195,19 +210,28 @@ NameList::decode(unsigned char* code, long eip_addr)
cout << buf;
continue;
}
long offset = strtol(buf, 0, 16);
char* bp_0 = strchr(buf, '>') + 2;
offset = strtol(buf, 0, 16);
char* bp_0 = strchr(buf, '>');
KSym* ksym = find(eip_addr + offset);
if (bp_0)
bp_0 += 2;
else
bp_0 = strchr(buf, ':');
if (ksym)
cout << *ksym << ' ';
char* bp = bp_0;
char *bp_1 = strstr(bp_0, "\t"); // objdump from binutils 2.8...
if (bp_1)
++bp_1;
else
bp_1 = bp_0;
char *bp = bp_1;
while (!isspace(*bp))
bp++;
while (isspace(*bp))
bp++;
if (*bp != '0') {
if (!isxdigit(*bp)) {
cout << bp_0;
} else if (*bp_0 == 'j' || strnequ(bp_0, "call", 4)) { // a jump or call insn
} else if (*bp_1 == 'j' || strnequ(bp_1, "call", 4)) { // a jump or call insn
long rel_addr = strtol(bp, 0, 16);
ksym = find(eip_addr + rel_addr);
if (ksym) {
......
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