Commit 972b8494 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://gkernel.bkbits.net/misc-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 0b818f9d 7fc97e8d
......@@ -2667,7 +2667,7 @@ under /dev. These special filesystems provide kernel interfaces that
cannot be provided with standard device nodes.
/dev/pts devpts PTY slave filesystem
/dev/shm shmfs POSIX shared memory maintenance access
/dev/shm tmpfs POSIX shared memory maintenance access
**** TERMINAL DEVICES
......
......@@ -47,10 +47,9 @@ tmpfs has the following uses:
shared memory)
3) Some people (including me) find it very convenient to mount it
e.g. on /tmp and /var/tmp and have a big swap partition. But be
aware: loop mounts of tmpfs files do not work due to the internal
design. So mkinitrd shipped by most distributions will fail with a
tmpfs /tmp.
e.g. on /tmp and /var/tmp and have a big swap partition. And now
loop mounts of tmpfs files do work, so mkinitrd shipped by most
distributions should succeed with a tmpfs /tmp.
4) And probably a lot more I do not know about :-)
......@@ -90,13 +89,9 @@ TODOs:
size=50% the tmpfs instance should be able to grow to 50 percent of
RAM + swap. So the instance should adapt automatically if you add
or remove swap space.
2) loop mounts: This is difficult since loop.c relies on the readpage
operation. This operation gets a page from the caller to be filled
with the content of the file at that position. But tmpfs always has
the page and thus cannot copy the content to the given page. So it
cannot provide this operation. The VM had to be changed seriously
to achieve this.
3) Show the number of tmpfs RAM pages. (As shared?)
2) Show the number of tmpfs RAM pages. (As shared?)
Author:
Christoph Rohland <cr@sap.com>, 1.12.01
Updated:
Hugh Dickins <hugh@veritas.com>, 17 Oct 2002
......@@ -72,7 +72,9 @@ EXPORT_SYMBOL(pfn_to_nid);
#ifdef CONFIG_X86_NUMAQ
EXPORT_SYMBOL(xquad_portio);
#endif
#ifndef CONFIG_X86_WP_WORKS_OK
EXPORT_SYMBOL(__verify_write);
#endif
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(dump_extended_fpu);
......
......@@ -375,12 +375,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
break;
}
ret = 0;
if ( !child->used_math ) {
/* Simulate an empty FPU. */
set_fpu_cwd(child, 0x037f);
set_fpu_swd(child, 0x0000);
set_fpu_twd(child, 0xffff);
}
if (!child->used_math)
init_fpu(child);
get_fpregs((struct user_i387_struct *)data, child);
break;
}
......@@ -403,13 +399,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
break;
}
if ( !child->used_math ) {
/* Simulate an empty FPU. */
set_fpu_cwd(child, 0x037f);
set_fpu_swd(child, 0x0000);
set_fpu_twd(child, 0xffff);
set_fpu_mxcsr(child, 0x1f80);
}
if (!child->used_math)
init_fpu(child);
ret = get_fpxregs((struct user_fxsr_struct *)data, child);
break;
}
......
......@@ -54,10 +54,10 @@ static inline void save_processor_context (void)
/*
* descriptor tables
*/
asm volatile ("sgdt (%0)" : "=m" (saved_context.gdt_limit));
asm volatile ("sidt (%0)" : "=m" (saved_context.idt_limit));
asm volatile ("sldt (%0)" : "=m" (saved_context.ldt));
asm volatile ("str (%0)" : "=m" (saved_context.tr));
asm volatile ("sgdt %0" : "=m" (saved_context.gdt_limit));
asm volatile ("sidt %0" : "=m" (saved_context.idt_limit));
asm volatile ("sldt %0" : "=m" (saved_context.ldt));
asm volatile ("str %0" : "=m" (saved_context.tr));
/*
* save the general registers.
......@@ -67,22 +67,22 @@ static inline void save_processor_context (void)
* It's really not necessary, and kinda fishy (check the assembly output),
* so it's avoided.
*/
asm volatile ("movl %%esp, (%0)" : "=m" (saved_context.esp));
asm volatile ("movl %%eax, (%0)" : "=m" (saved_context.eax));
asm volatile ("movl %%ebx, (%0)" : "=m" (saved_context.ebx));
asm volatile ("movl %%ecx, (%0)" : "=m" (saved_context.ecx));
asm volatile ("movl %%edx, (%0)" : "=m" (saved_context.edx));
asm volatile ("movl %%ebp, (%0)" : "=m" (saved_context.ebp));
asm volatile ("movl %%esi, (%0)" : "=m" (saved_context.esi));
asm volatile ("movl %%edi, (%0)" : "=m" (saved_context.edi));
asm volatile ("movl %%esp, %0" : "=m" (saved_context.esp));
asm volatile ("movl %%eax, %0" : "=m" (saved_context.eax));
asm volatile ("movl %%ebx, %0" : "=m" (saved_context.ebx));
asm volatile ("movl %%ecx, %0" : "=m" (saved_context.ecx));
asm volatile ("movl %%edx, %0" : "=m" (saved_context.edx));
asm volatile ("movl %%ebp, %0" : "=m" (saved_context.ebp));
asm volatile ("movl %%esi, %0" : "=m" (saved_context.esi));
asm volatile ("movl %%edi, %0" : "=m" (saved_context.edi));
/* FIXME: Need to save XMM0..XMM15? */
/*
* segment registers
*/
asm volatile ("movw %%es, %0" : "=r" (saved_context.es));
asm volatile ("movw %%fs, %0" : "=r" (saved_context.fs));
asm volatile ("movw %%gs, %0" : "=r" (saved_context.gs));
asm volatile ("movw %%ss, %0" : "=r" (saved_context.ss));
asm volatile ("movw %%es, %0" : "=m" (saved_context.es));
asm volatile ("movw %%fs, %0" : "=m" (saved_context.fs));
asm volatile ("movw %%gs, %0" : "=m" (saved_context.gs));
asm volatile ("movw %%ss, %0" : "=m" (saved_context.ss));
/*
* control registers
......@@ -95,7 +95,7 @@ static inline void save_processor_context (void)
/*
* eflags
*/
asm volatile ("pushfl ; popl (%0)" : "=m" (saved_context.eflags));
asm volatile ("pushfl ; popl %0" : "=m" (saved_context.eflags));
}
static void
......@@ -125,9 +125,7 @@ static inline void restore_processor_context (void)
/*
* first restore %ds, so we can access our data properly
*/
asm volatile (".align 4");
asm volatile ("movw %0, %%ds" :: "r" ((u16)__KERNEL_DS));
asm volatile ("movw %0, %%ds" :: "r" (__KERNEL_DS));
/*
* control registers
......@@ -136,7 +134,7 @@ static inline void restore_processor_context (void)
asm volatile ("movl %0, %%cr3" :: "r" (saved_context.cr3));
asm volatile ("movl %0, %%cr2" :: "r" (saved_context.cr2));
asm volatile ("movl %0, %%cr0" :: "r" (saved_context.cr0));
/*
* segment registers
*/
......@@ -167,9 +165,9 @@ static inline void restore_processor_context (void)
* now restore the descriptor tables to their proper values
* ltr is done i fix_processor_context().
*/
asm volatile ("lgdt (%0)" :: "m" (saved_context.gdt_limit));
asm volatile ("lidt (%0)" :: "m" (saved_context.idt_limit));
asm volatile ("lldt (%0)" :: "m" (saved_context.ldt));
asm volatile ("lgdt %0" :: "m" (saved_context.gdt_limit));
asm volatile ("lidt %0" :: "m" (saved_context.idt_limit));
asm volatile ("lldt %0" :: "m" (saved_context.ldt));
fix_processor_context();
......
......@@ -30,17 +30,20 @@ extern void die(const char *,struct pt_regs *,long);
extern int console_loglevel;
#ifndef CONFIG_X86_WP_WORKS_OK
/*
* Ugly, ugly, but the goto's result in better assembly..
*/
int __verify_write(const void * addr, unsigned long size)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct * vma;
unsigned long start = (unsigned long) addr;
if (!size)
if (!size || segment_eq(get_fs(),KERNEL_DS))
return 1;
down_read(&mm->mmap_sem);
vma = find_vma(current->mm, start);
if (!vma)
goto bad_area;
......@@ -80,6 +83,13 @@ int __verify_write(const void * addr, unsigned long size)
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;;
}
/*
* We really need to hold mmap_sem over the whole access to
* userspace, else another thread could change permissions.
* This is unfixable, so don't use i386-class machines for
* critical servers.
*/
up_read(&mm->mmap_sem);
return 1;
check_stack:
......@@ -89,6 +99,7 @@ int __verify_write(const void * addr, unsigned long size)
goto good_area;
bad_area:
up_read(&mm->mmap_sem);
return 0;
out_of_memory:
......@@ -98,6 +109,7 @@ int __verify_write(const void * addr, unsigned long size)
}
goto bad_area;
}
#endif
/*
* Unlock any spinlocks which will prevent us from getting the
......
......@@ -378,15 +378,10 @@ void __init paging_init(void)
* This function cannot be __init, since exceptions don't work in that
* section.
*/
static int do_test_wp_bit(unsigned long vaddr);
static int do_test_wp_bit(void);
void __init test_wp_bit(void)
{
const unsigned long vaddr = PAGE_OFFSET;
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte, old_pte;
if (cpu_has_pse) {
/* Ok, all PSE-capable CPUs are definitely handling the WP bit right. */
boot_cpu_data.wp_works_ok = 1;
......@@ -395,17 +390,10 @@ void __init test_wp_bit(void)
printk("Checking if this processor honours the WP bit even in supervisor mode... ");
pgd = swapper_pg_dir + __pgd_offset(vaddr);
pmd = pmd_offset(pgd, vaddr);
pte = pte_offset_kernel(pmd, vaddr);
old_pte = *pte;
*pte = pfn_pte(0, PAGE_READONLY);
local_flush_tlb();
boot_cpu_data.wp_works_ok = do_test_wp_bit(vaddr);
*pte = old_pte;
local_flush_tlb();
/* Any page-aligned address will do, the test is non-destructive */
__set_fixmap(FIX_WP_TEST, __pa(&swapper_pg_dir), PAGE_READONLY);
boot_cpu_data.wp_works_ok = do_test_wp_bit();
clear_fixmap(FIX_WP_TEST);
if (!boot_cpu_data.wp_works_ok) {
printk("No.\n");
......@@ -550,7 +538,7 @@ void __init pgtable_cache_init(void)
#endif
/* Put this after the callers, so that it cannot be inlined */
static int do_test_wp_bit(unsigned long vaddr)
static int do_test_wp_bit(void)
{
char tmp_reg;
int flag;
......@@ -564,7 +552,7 @@ static int do_test_wp_bit(unsigned long vaddr)
" .align 4 \n"
" .long 1b,2b \n"
".previous \n"
:"=m" (*(char *) vaddr),
:"=m" (*(char *)fix_to_virt(FIX_WP_TEST)),
"=q" (tmp_reg),
"=r" (flag)
:"2" (1)
......
......@@ -289,7 +289,7 @@ void __init bt_iounmap(void *addr, unsigned long size)
idx = FIX_BTMAP_BEGIN;
while (nrpages > 0) {
__set_fixmap(idx, 0, __pgprot(0));
clear_fixmap(idx);
--idx;
--nrpages;
}
......
......@@ -29,58 +29,6 @@
extern void die(const char *,struct pt_regs *,long);
/*
* Ugly, ugly, but the goto's result in better assembly..
*/
int __verify_write(const void * addr, unsigned long size)
{
struct vm_area_struct * vma;
unsigned long start = (unsigned long) addr;
if (!size)
return 1;
vma = find_vma(current->mm, start);
if (!vma)
goto bad_area;
if (vma->vm_start > start)
goto check_stack;
good_area:
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
size--;
size += start & ~PAGE_MASK;
size >>= PAGE_SHIFT;
start &= PAGE_MASK;
for (;;) {
if (handle_mm_fault(current->mm, vma, start, 1) <= 0)
goto bad_area;
if (!size)
break;
size--;
start += PAGE_SIZE;
if (start < vma->vm_end)
continue;
vma = vma->vm_next;
if (!vma || vma->vm_start != start)
goto bad_area;
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;;
}
return 1;
check_stack:
if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
if (expand_stack(vma, start) == 0)
goto good_area;
bad_area:
return 0;
}
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
......
......@@ -432,7 +432,7 @@ static int __init rd_init (void)
disk->first_minor = i;
disk->fops = &rd_bd_op;
disk->queue = &rd_queue;
sprintf(disk->disk_name, "rd%d", i);
sprintf(disk->disk_name, "ram%d", i);
set_capacity(disk, rd_size * 2);
}
devfs_handle = devfs_mk_dir (NULL, "rd", NULL);
......
......@@ -1497,7 +1497,7 @@ int __init cm206_init(void)
goto out_disk;
disk->major = MAJOR_NR;
disk->first_minor = 0;
sprintf(disk->disk_name, "cm206");
sprintf(disk->disk_name, "cm206cd");
disk->fops = &cm206_bdops;
disk->flags = GENHD_FL_CD;
cm206_gendisk = disk;
......
......@@ -3287,13 +3287,13 @@ static int __init md_setup(char *str)
return 1;
}
extern kdev_t name_to_kdev_t(char *line) __init;
extern dev_t name_to_dev_t(char *line) __init;
void __init md_setup_drive(void)
{
int minor, i;
kdev_t dev;
dev_t dev;
mddev_t*mddev;
kdev_t devices[MD_SB_DISKS+1];
dev_t devices[MD_SB_DISKS+1];
for (minor = 0; minor < MAX_MD_DEVS; minor++) {
int err = 0;
......@@ -3312,16 +3312,17 @@ void __init md_setup_drive(void)
if (p)
*p++ = 0;
dev = name_to_kdev_t(devname);
handle = devfs_get_handle(NULL, devname, major(dev), minor(dev),
DEVFS_SPECIAL_BLK, 1);
dev = name_to_dev_t(devname);
handle = devfs_get_handle(NULL, devname,
MAJOR(dev), MINOR(dev),
DEVFS_SPECIAL_BLK, 1);
if (handle != 0) {
unsigned major, minor;
devfs_get_maj_min(handle, &major, &minor);
dev = mk_kdev(major, minor);
dev = MKDEV(major, minor);
devfs_put(handle);
}
if (kdev_none(dev)) {
if (!dev) {
printk(KERN_WARNING "md: Unknown device name: %s\n", devname);
break;
}
......@@ -3331,7 +3332,7 @@ void __init md_setup_drive(void)
devname = p;
}
devices[i] = to_kdev_t(0);
devices[i] = 0;
if (!md_setup_args.device_set[minor])
continue;
......@@ -3375,13 +3376,13 @@ void __init md_setup_drive(void)
err = set_array_info(mddev, &ainfo);
for (i = 0; !err && i <= MD_SB_DISKS; i++) {
dev = devices[i];
if (kdev_none(dev))
if (!dev)
break;
dinfo.number = i;
dinfo.raid_disk = i;
dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC);
dinfo.major = major(dev);
dinfo.minor = minor(dev);
dinfo.major = MAJOR(dev);
dinfo.minor = MINOR(dev);
mddev->raid_disks++;
err = add_new_disk (mddev, &dinfo);
}
......@@ -3389,10 +3390,10 @@ void __init md_setup_drive(void)
/* persistent */
for (i = 0; i <= MD_SB_DISKS; i++) {
dev = devices[i];
if (kdev_none(dev))
if (!dev)
break;
dinfo.major = major(dev);
dinfo.minor = minor(dev);
dinfo.major = MAJOR(dev);
dinfo.minor = MINOR(dev);
add_new_disk (mddev, &dinfo);
}
}
......
......@@ -1044,7 +1044,7 @@ static int __init calc_erase_regions(struct mtd_erase_region_info *info, size_t
}
extern kdev_t name_to_kdev_t(char *line) __init;
extern dev_t name_to_dev_t(char *line) __init;
/* Startup */
static int __init init_blkmtd(void)
......@@ -1059,7 +1059,7 @@ static int __init init_blkmtd(void)
loff_t size;
int readonly = 0;
int erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
kdev_t rdev;
dev_t rdev;
struct block_device *bdev;
int err;
int mode;
......@@ -1107,17 +1107,17 @@ static int __init init_blkmtd(void)
filp_close(file, NULL);
return 1;
}
rdev = inode->i_rdev;
rdev = inode->i_bdev->bd_dev;
filp_close(file, NULL);
#else
rdev = name_to_kdev_t(device);
rdev = name_to_dev_t(device);
#endif
maj = major(rdev);
min = minor(rdev);
maj = MAJOR(rdev);
min = MINOR(rdev);
DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n", maj, min);
if(kdev_none(rdev)) {
if(!rdev) {
printk("blkmtd: bad block device: `%s'\n", device);
return 1;
}
......
......@@ -1792,9 +1792,6 @@ xfs_alloc_buftarg(
case EVMS_MAJOR:
btp->pbr_flags = PBR_ALIGNED_ONLY;
break;
case LVM_BLK_MAJOR:
btp->pbr_flags = PBR_SECTOR_ONLY;
break;
}
return btp;
......
......@@ -27,7 +27,7 @@
* Here we define all the compile-time 'special' virtual
* addresses. The point is to have a constant address at
* compile time, but to set the physical address only
* in the boot process. We allocate these special addresses
* in the boot process. We allocate these special addresses
* from the end of virtual memory (0xfffff000) backwards.
* Also this lets us do fail-safe vmalloc(), we
* can guarantee that these special addresses and
......@@ -41,13 +41,6 @@
* TLB entries of such buffers will not be flushed across
* task switches.
*/
/*
* on UP currently we will have no trace of the fixmap mechanizm,
* no page table allocations, etc. This might change in the
* future, say framebuffers for the console driver(s) could be
* fix-mapped?
*/
enum fixed_addresses {
#ifdef CONFIG_X86_LOCAL_APIC
FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */
......@@ -81,6 +74,7 @@ enum fixed_addresses {
#define NR_FIX_BTMAPS 16
FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
FIX_WP_TEST,
__end_of_fixed_addresses
};
......@@ -94,6 +88,10 @@ extern void __set_fixmap (enum fixed_addresses idx,
*/
#define set_fixmap_nocache(idx, phys) \
__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
#define clear_fixmap(idx) \
__set_fixmap(idx, 0, __pgprot(0))
/*
* used by vmalloc.c.
*
......
......@@ -15,22 +15,22 @@ arch_prepare_suspend(void)
/* image of the saved processor state */
struct saved_context {
u32 eax, ebx, ecx, edx;
u32 esp, ebp, esi, edi;
u16 es, fs, gs, ss;
u32 cr0, cr2, cr3, cr4;
unsigned long eax, ebx, ecx, edx;
unsigned long esp, ebp, esi, edi;
u16 es, fs, gs, ss;
unsigned long cr0, cr2, cr3, cr4;
u16 gdt_pad;
u16 gdt_limit;
u32 gdt_base;
unsigned long gdt_base;
u16 idt_pad;
u16 idt_limit;
u32 idt_base;
unsigned long idt_base;
u16 ldt;
u16 tss;
u32 tr;
u32 safety;
u32 return_address;
u32 eflags;
unsigned long tr;
unsigned long safety;
unsigned long return_address;
unsigned long eflags;
} __attribute__((packed));
#define loaddebug(thread,register) \
......@@ -52,11 +52,11 @@ extern unsigned long saved_edi;
static inline void acpi_save_register_state(unsigned long return_point)
{
saved_eip = return_point;
asm volatile ("movl %%esp,(%0)" : "=m" (saved_esp));
asm volatile ("movl %%ebp,(%0)" : "=m" (saved_ebp));
asm volatile ("movl %%ebx,(%0)" : "=m" (saved_ebx));
asm volatile ("movl %%edi,(%0)" : "=m" (saved_edi));
asm volatile ("movl %%esi,(%0)" : "=m" (saved_esi));
asm volatile ("movl %%esp,%0" : "=m" (saved_esp));
asm volatile ("movl %%ebp,%0" : "=m" (saved_ebp));
asm volatile ("movl %%ebx,%0" : "=m" (saved_ebx));
asm volatile ("movl %%edi,%0" : "=m" (saved_edi));
asm volatile ("movl %%esi,%0" : "=m" (saved_esi));
}
#define acpi_restore_register_state() do {} while (0)
......
......@@ -64,7 +64,6 @@ int __verify_write(const void *, unsigned long);
#define access_ok(type,addr,size) ( (__range_ok(addr,size) == 0) && \
((type) == VERIFY_READ || boot_cpu_data.wp_works_ok || \
segment_eq(get_fs(),KERNEL_DS) || \
__verify_write((void *)(addr),(size))))
#endif
......
......@@ -39,6 +39,7 @@ extern void _clear_page(void *page);
#define clear_page(X) _clear_page((void *)(X))
struct page;
extern void clear_user_page(void *addr, unsigned long vaddr, struct page *page);
#define copy_page(X,Y) __memcpy((void *)(X), (void *)(Y), PAGE_SIZE)
extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *topage);
/* GROSS, defining this makes gcc pass these types as aggregates,
......
......@@ -1239,6 +1239,7 @@ extern int sb_min_blocksize(struct super_block *, int);
extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
extern ssize_t generic_file_aio_read(struct kiocb *, char *, size_t, loff_t);
......
......@@ -73,4 +73,15 @@ static inline void copy_user_highpage(struct page *to, struct page *from, unsign
kunmap_atomic(vto, KM_USER1);
}
static inline void copy_highpage(struct page *to, struct page *from)
{
char *vfrom, *vto;
vfrom = kmap_atomic(from, KM_USER0);
vto = kmap_atomic(to, KM_USER1);
copy_page(vto, vfrom);
kunmap_atomic(vfrom, KM_USER0);
kunmap_atomic(vto, KM_USER1);
}
#endif /* _LINUX_HIGHMEM_H */
......@@ -27,6 +27,7 @@ extern int get_filesystem_list(char * buf);
extern asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type,
unsigned long flags, void *data);
extern asmlinkage long sys_mkdir(const char *name, int mode);
extern asmlinkage long sys_rmdir(const char *name);
extern asmlinkage long sys_chdir(const char *name);
extern asmlinkage long sys_fchdir(int fd);
extern asmlinkage long sys_chroot(const char *name);
......@@ -55,6 +56,7 @@ int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */
int root_mountflags = MS_RDONLY | MS_VERBOSE;
static char root_device_name[64];
static char saved_root_name[64];
/* this is initialized in init/main.c */
dev_t ROOT_DEV;
......@@ -87,169 +89,135 @@ static int __init readwrite(char *str)
__setup("ro", readonly);
__setup("rw", readwrite);
static struct dev_name_struct {
const char *name;
const int num;
} root_dev_names[] __initdata = {
{ "nfs", 0x00ff },
{ "hda", 0x0300 },
{ "hdb", 0x0340 },
{ "loop", 0x0700 },
{ "hdc", 0x1600 },
{ "hdd", 0x1640 },
{ "hde", 0x2100 },
{ "hdf", 0x2140 },
{ "hdg", 0x2200 },
{ "hdh", 0x2240 },
{ "hdi", 0x3800 },
{ "hdj", 0x3840 },
{ "hdk", 0x3900 },
{ "hdl", 0x3940 },
{ "hdm", 0x5800 },
{ "hdn", 0x5840 },
{ "hdo", 0x5900 },
{ "hdp", 0x5940 },
{ "hdq", 0x5A00 },
{ "hdr", 0x5A40 },
{ "hds", 0x5B00 },
{ "hdt", 0x5B40 },
{ "sda", 0x0800 },
{ "sdb", 0x0810 },
{ "sdc", 0x0820 },
{ "sdd", 0x0830 },
{ "sde", 0x0840 },
{ "sdf", 0x0850 },
{ "sdg", 0x0860 },
{ "sdh", 0x0870 },
{ "sdi", 0x0880 },
{ "sdj", 0x0890 },
{ "sdk", 0x08a0 },
{ "sdl", 0x08b0 },
{ "sdm", 0x08c0 },
{ "sdn", 0x08d0 },
{ "sdo", 0x08e0 },
{ "sdp", 0x08f0 },
{ "ada", 0x1c00 },
{ "adb", 0x1c10 },
{ "adc", 0x1c20 },
{ "add", 0x1c30 },
{ "ade", 0x1c40 },
{ "fd", 0x0200 },
{ "md", 0x0900 },
{ "xda", 0x0d00 },
{ "xdb", 0x0d40 },
{ "ram", 0x0100 },
{ "scd", 0x0b00 },
{ "mcd", 0x1700 },
{ "cdu535", 0x1800 },
{ "sonycd", 0x1800 },
{ "aztcd", 0x1d00 },
{ "cm206cd", 0x2000 },
{ "gscd", 0x1000 },
{ "sbpcd", 0x1900 },
{ "eda", 0x2400 },
{ "edb", 0x2440 },
{ "pda", 0x2d00 },
{ "pdb", 0x2d10 },
{ "pdc", 0x2d20 },
{ "pdd", 0x2d30 },
{ "pcd", 0x2e00 },
{ "pf", 0x2f00 },
{ "apblock", APBLOCK_MAJOR << 8},
{ "ddv", DDV_MAJOR << 8},
{ "jsfd", JSFD_MAJOR << 8},
#if defined(CONFIG_ARCH_S390)
{ "dasda", (DASD_MAJOR << MINORBITS) },
{ "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
{ "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
{ "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
{ "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
{ "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
{ "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
{ "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
#endif
#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
{ "ida/c0d0p",0x4800 },
{ "ida/c0d1p",0x4810 },
{ "ida/c0d2p",0x4820 },
{ "ida/c0d3p",0x4830 },
{ "ida/c0d4p",0x4840 },
{ "ida/c0d5p",0x4850 },
{ "ida/c0d6p",0x4860 },
{ "ida/c0d7p",0x4870 },
{ "ida/c0d8p",0x4880 },
{ "ida/c0d9p",0x4890 },
{ "ida/c0d10p",0x48A0 },
{ "ida/c0d11p",0x48B0 },
{ "ida/c0d12p",0x48C0 },
{ "ida/c0d13p",0x48D0 },
{ "ida/c0d14p",0x48E0 },
{ "ida/c0d15p",0x48F0 },
#endif
#if defined(CONFIG_BLK_CPQ_CISS_DA) || defined(CONFIG_BLK_CPQ_CISS_DA_MODULE)
{ "cciss/c0d0p",0x6800 },
{ "cciss/c0d1p",0x6810 },
{ "cciss/c0d2p",0x6820 },
{ "cciss/c0d3p",0x6830 },
{ "cciss/c0d4p",0x6840 },
{ "cciss/c0d5p",0x6850 },
{ "cciss/c0d6p",0x6860 },
{ "cciss/c0d7p",0x6870 },
{ "cciss/c0d8p",0x6880 },
{ "cciss/c0d9p",0x6890 },
{ "cciss/c0d10p",0x68A0 },
{ "cciss/c0d11p",0x68B0 },
{ "cciss/c0d12p",0x68C0 },
{ "cciss/c0d13p",0x68D0 },
{ "cciss/c0d14p",0x68E0 },
{ "cciss/c0d15p",0x68F0 },
#endif
{ "nftla", 0x5d00 },
{ "nftlb", 0x5d10 },
{ "nftlc", 0x5d20 },
{ "nftld", 0x5d30 },
{ "ftla", 0x2c00 },
{ "ftlb", 0x2c08 },
{ "ftlc", 0x2c10 },
{ "ftld", 0x2c18 },
{ "mtdblock", 0x1f00 },
{ NULL, 0 }
};
kdev_t __init name_to_kdev_t(char *line)
{
int base = 0;
if (strncmp(line,"/dev/",5) == 0) {
struct dev_name_struct *dev = root_dev_names;
line += 5;
do {
int len = strlen(dev->name);
if (strncmp(line,dev->name,len) == 0) {
line += len;
base = dev->num;
break;
}
dev++;
} while (dev->name);
static __init dev_t try_name(char *name, int part)
{
char path[64];
char buf[32];
int range;
dev_t res;
char *s;
int len;
int fd;
/* read device number from .../dev */
sprintf(path, "/sys/bus/block/devices/%s/dev", name);
fd = open(path, 0, 0);
if (fd < 0)
goto fail;
len = read(fd, buf, 32);
close(fd);
if (len <= 0 || len == 32 || buf[len - 1] != '\n')
goto fail;
buf[len - 1] = '\0';
res = (dev_t) simple_strtoul(buf, &s, 16);
if (*s)
goto fail;
/* if it's there and we are not looking for a partition - that's it */
if (!part)
return res;
/* otherwise read range from .../range */
sprintf(path, "/sys/bus/block/devices/%s/range", name);
fd = open(path, 0, 0);
if (fd < 0)
goto fail;
len = read(fd, buf, 32);
close(fd);
if (len <= 0 || len == 32 || buf[len - 1] != '\n')
goto fail;
buf[len - 1] = '\0';
range = simple_strtoul(buf, &s, 10);
if (*s)
goto fail;
/* if partition is within range - we got it */
if (part < range)
return res + part;
fail:
return (dev_t) 0;
}
/*
* Convert a name into device number. We accept the following variants:
*
* 1) device number in hexadecimal represents itself
* 2) /dev/nfs represents Root_NFS (0xff)
* 3) /dev/<disk_name> represents the device number of disk
* 4) /dev/<disk_name><decimal> represents the device number
* of partition - device number of disk plus the partition number
* 5) /dev/<disk_name>p<decimal> - same as the above, that form is
* used when disk name of partitioned disk ends on a digit.
*
* If name doesn't have fall into the categories above, we return 0.
* Driverfs is used to check if something is a disk name - it has
* all known disks under bus/block/devices. If the disk name
* contains slashes, name of driverfs node has them replaced with
* dots. try_name() does the actual checks, assuming that driverfs
* is mounted on rootfs /sys.
*/
__init dev_t name_to_dev_t(char *name)
{
char s[32];
char *p;
dev_t res = 0;
int part;
sys_mkdir("/sys", 0700);
if (sys_mount("driverfs", "/sys", "driverfs", 0, NULL) < 0)
goto out;
if (strncmp(name, "/dev/", 5) != 0) {
res = (dev_t) simple_strtoul(name, &p, 16);
if (*p)
goto fail;
goto done;
}
return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
name += 5;
res = Root_NFS;
if (strcmp(name, "nfs") == 0)
goto done;
if (strlen(name) > 31)
goto fail;
strcpy(s, name);
for (p = s; *p; p++)
if (*p == '/')
*p = '.';
res = try_name(s, 0);
if (res)
goto done;
while (p > s && isdigit(p[-1]))
p--;
if (p == s || !*p || *p == '0')
goto fail;
part = simple_strtoul(p, NULL, 10);
*p = '\0';
res = try_name(s, part);
if (res)
goto done;
if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
goto fail;
p[-1] = '\0';
res = try_name(s, part);
done:
sys_umount("/sys", 0);
out:
sys_rmdir("/sys");
return res;
fail:
res = (dev_t) 0;
goto done;
}
static int __init root_dev_setup(char *line)
{
int i;
char ch;
ROOT_DEV = kdev_t_to_nr(name_to_kdev_t(line));
memset (root_device_name, 0, sizeof root_device_name);
if (strncmp (line, "/dev/", 5) == 0) line += 5;
for (i = 0; i < sizeof root_device_name - 1; ++i)
{
ch = line[i];
if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
root_device_name[i] = ch;
}
strncpy(saved_root_name, line, 64);
saved_root_name[63] = '\0';
return 1;
}
......@@ -768,6 +736,13 @@ static int __init initrd_load(void)
void prepare_namespace(void)
{
int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
if (saved_root_name[0]) {
char *p = saved_root_name;
ROOT_DEV = name_to_dev_t(p);
if (strncmp(p, "/dev/", 5) == 0)
p += 5;
strcpy(root_device_name, p);
}
#ifdef CONFIG_BLK_DEV_INITRD
if (!initrd_start)
mount_initrd = 0;
......
......@@ -57,12 +57,13 @@
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/buffer_head.h>
#include <linux/swapops.h>
#include <linux/bootmem.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <linux/swapops.h>
extern void signal_wake_up(struct task_struct *t);
extern int sys_sync(void);
......@@ -225,7 +226,7 @@ int freeze_processes(void)
todo++;
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
yield();
yield(); /* Yield is okay here */
if (time_after(jiffies, start_time + TIMEOUT)) {
printk( "\n" );
printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
......@@ -309,6 +310,9 @@ static void mark_swapfiles(swp_entry_t prev, int mode)
union diskpage *cur;
struct page *page;
if (root_swap == 0xFFFF) /* ignored */
return;
page = alloc_page(GFP_ATOMIC);
if (!page)
panic("Out of memory in mark_swapfiles");
......@@ -474,9 +478,9 @@ static int count_and_copy_data_pages(struct pbe *pagedir_p)
#ifdef CONFIG_DISCONTIGMEM
panic("Discontingmem not supported");
#else
BUG_ON (max_mapnr != num_physpages);
BUG_ON (max_pfn != num_physpages);
#endif
for (pfn = 0; pfn < max_mapnr; pfn++) {
for (pfn = 0; pfn < max_pfn; pfn++) {
page = pfn_to_page(pfn);
if (PageHighMem(page))
panic("Swsusp not supported on highmem boxes. Send 1GB of RAM to <pavel@ucw.cz> and try again ;-).");
......@@ -686,6 +690,7 @@ static int suspend_save_image(void)
if(nr_free_pages() < nr_needed_pages) {
printk(KERN_CRIT "%sCouldn't get enough free pages, on %d pages short\n",
name_suspend, nr_needed_pages-nr_free_pages());
root_swap = 0xFFFF;
spin_unlock_irq(&suspend_pagedir_lock);
return 1;
}
......@@ -1042,7 +1047,7 @@ static int bdev_write_page(struct block_device *bdev, long pos, void *buf)
return 0;
}
extern kdev_t __init name_to_kdev_t(const char *line);
extern dev_t __init name_to_dev_t(const char *line);
static int __read_suspend_image(struct block_device *bdev, union diskpage *cur, int noresume)
{
......@@ -1138,7 +1143,7 @@ static int read_suspend_image(const char * specialfile, int noresume)
unsigned long scratch_page = 0;
int error;
resume_device = name_to_kdev_t(specialfile);
resume_device = to_kdev_t(name_to_dev_t(specialfile));
scratch_page = get_zeroed_page(GFP_ATOMIC);
cur = (void *) scratch_page;
if (cur) {
......
......@@ -916,7 +916,7 @@ generic_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
return ret;
}
static int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
{
ssize_t written;
unsigned long count = desc->count;
......
This diff is collapsed.
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