Commit f3d104a9 authored by Anton Altaparmakov's avatar Anton Altaparmakov

Merge cantab.net:/usr/src/bklinux-2.5 into cantab.net:/usr/src/tng

parents 98a58fbe 75eead62
...@@ -3,11 +3,13 @@ Changes since 2.5.0: ...@@ -3,11 +3,13 @@ Changes since 2.5.0:
--- ---
[recommended] [recommended]
New helpers: sb_bread(), sb_getblk(), sb_get_hash_table(), set_bh(), New helpers: sb_bread(), sb_getblk(), sb_find_get_block(), set_bh(),
sb_set_blocksize() and sb_min_blocksize(). sb_set_blocksize() and sb_min_blocksize().
Use them. Use them.
(sb_find_get_block() replaces 2.4's get_hash_table())
--- ---
[recommended] [recommended]
...@@ -228,3 +230,21 @@ anything from oops to silent memory corruption. ...@@ -228,3 +230,21 @@ anything from oops to silent memory corruption.
Use bdev_read_only(bdev) instead of is_read_only(kdev). The latter Use bdev_read_only(bdev) instead of is_read_only(kdev). The latter
is still alive, but only because of the mess in drivers/s390/block/dasd.c. is still alive, but only because of the mess in drivers/s390/block/dasd.c.
As soon as it gets fixed is_read_only() will die. As soon as it gets fixed is_read_only() will die.
---
[mandatory]
is_read_only() is gone; use bdev_read_only() instead.
---
[mandatory]
destroy_buffers() is gone; use invalidate_bdev().
---
[mandatory]
fsync_dev() is gone; use fsync_bdev(). NOTE: lvm breakage is
deliberate; as soon as struct block_device * is propagated in a reasonable
way by that code fixing will become trivial; until then nothing can be
done.
...@@ -56,12 +56,16 @@ int __verify_write(const void * addr, unsigned long size) ...@@ -56,12 +56,16 @@ int __verify_write(const void * addr, unsigned long size)
for (;;) { for (;;) {
survive: survive:
{ switch (handle_mm_fault(current->mm, vma, start, 1)) {
int fault = handle_mm_fault(current->mm, vma, start, 1); case VM_FAULT_SIGBUS:
if (!fault)
goto bad_area; goto bad_area;
if (fault < 0) case VM_FAULT_OOM:
goto out_of_memory; goto out_of_memory;
case VM_FAULT_MINOR:
case VM_FAULT_MAJOR:
break;
default:
BUG();
} }
if (!size) if (!size)
break; break;
...@@ -239,16 +243,18 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -239,16 +243,18 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
* the fault. * the fault.
*/ */
switch (handle_mm_fault(mm, vma, address, write)) { switch (handle_mm_fault(mm, vma, address, write)) {
case 1: case VM_FAULT_MINOR:
tsk->min_flt++; tsk->min_flt++;
break; break;
case 2: case VM_FAULT_MAJOR:
tsk->maj_flt++; tsk->maj_flt++;
break; break;
case 0: case VM_FAULT_SIGBUS:
goto do_sigbus; goto do_sigbus;
default: case VM_FAULT_OOM:
goto out_of_memory; goto out_of_memory;
default:
BUG();
} }
/* /*
......
...@@ -1090,7 +1090,7 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, ...@@ -1090,7 +1090,7 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
#ifdef DEBUG_SIGNALS_MAPS #ifdef DEBUG_SIGNALS_MAPS
#define MAPS_LINE_FORMAT "%08lx-%08lx %s %08lx %s %lu " #define MAPS_LINE_FORMAT "%08lx-%08lx %s %08lx %02x:%02x %lu "
static inline void read_maps (void) static inline void read_maps (void)
{ {
...@@ -1107,7 +1107,7 @@ static inline void read_maps (void) ...@@ -1107,7 +1107,7 @@ static inline void read_maps (void)
char *line; char *line;
char str[5], *cp = str; char str[5], *cp = str;
int flags; int flags;
kdev_t dev; dev_t dev;
unsigned long ino; unsigned long ino;
/* /*
...@@ -1132,7 +1132,7 @@ static inline void read_maps (void) ...@@ -1132,7 +1132,7 @@ static inline void read_maps (void)
buffer, PAGE_SIZE); buffer, PAGE_SIZE);
} }
printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT,
kdevname(dev), ino); MAJOR(dev), MINOR(dev), ino);
if (map->vm_file != NULL) if (map->vm_file != NULL)
printk("%s\n", line); printk("%s\n", line);
else else
......
...@@ -633,7 +633,7 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, ...@@ -633,7 +633,7 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
#ifdef DEBUG_SIGNALS_MAPS #ifdef DEBUG_SIGNALS_MAPS
#define MAPS_LINE_FORMAT "%016lx-%016lx %s %016lx %s %lu " #define MAPS_LINE_FORMAT "%016lx-%016lx %s %016lx %02x:%02x %lu "
static inline void read_maps (void) static inline void read_maps (void)
{ {
...@@ -650,7 +650,7 @@ static inline void read_maps (void) ...@@ -650,7 +650,7 @@ static inline void read_maps (void)
char *line; char *line;
char str[5], *cp = str; char str[5], *cp = str;
int flags; int flags;
kdev_t dev; dev_t dev;
unsigned long ino; unsigned long ino;
/* /*
...@@ -675,7 +675,7 @@ static inline void read_maps (void) ...@@ -675,7 +675,7 @@ static inline void read_maps (void)
buffer, PAGE_SIZE); buffer, PAGE_SIZE);
} }
printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT,
kdevname(dev), ino); MAJOR(dev), MINOR(dev), ino);
if (map->vm_file != NULL) if (map->vm_file != NULL)
printk("%s\n", line); printk("%s\n", line);
else else
......
...@@ -1319,7 +1319,7 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs ...@@ -1319,7 +1319,7 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
#ifdef DEBUG_SIGNALS_MAPS #ifdef DEBUG_SIGNALS_MAPS
#define MAPS_LINE_FORMAT "%016lx-%016lx %s %016lx %s %lu " #define MAPS_LINE_FORMAT "%016lx-%016lx %s %016lx %02x:%02x %lu "
static inline void read_maps (void) static inline void read_maps (void)
{ {
...@@ -1336,7 +1336,7 @@ static inline void read_maps (void) ...@@ -1336,7 +1336,7 @@ static inline void read_maps (void)
char *line; char *line;
char str[5], *cp = str; char str[5], *cp = str;
int flags; int flags;
kdev_t dev; dev_t dev;
unsigned long ino; unsigned long ino;
/* /*
...@@ -1361,7 +1361,7 @@ static inline void read_maps (void) ...@@ -1361,7 +1361,7 @@ static inline void read_maps (void)
buffer, PAGE_SIZE); buffer, PAGE_SIZE);
} }
printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT,
kdevname(dev), ino); MAJOR(dev), MINOR(dev), ino);
if (map->vm_file != NULL) if (map->vm_file != NULL)
printk("%s\n", line); printk("%s\n", line);
else else
......
...@@ -964,8 +964,7 @@ void blk_run_queues(void) ...@@ -964,8 +964,7 @@ void blk_run_queues(void)
return; return;
} }
list_splice(&blk_plug_list, &local_plug_list); list_splice_init(&blk_plug_list, &local_plug_list);
INIT_LIST_HEAD(&blk_plug_list);
spin_unlock_irq(&blk_plug_lock); spin_unlock_irq(&blk_plug_lock);
while (!list_empty(&local_plug_list)) { while (!list_empty(&local_plug_list)) {
...@@ -1212,21 +1211,19 @@ void blk_put_request(struct request *rq) ...@@ -1212,21 +1211,19 @@ void blk_put_request(struct request *rq)
static long ro_bits[MAX_BLKDEV][8]; static long ro_bits[MAX_BLKDEV][8];
int is_read_only(kdev_t dev) int bdev_read_only(struct block_device *bdev)
{ {
int minor,major; int minor,major;
major = major(dev); if (!bdev)
minor = minor(dev); return 0;
if (major < 0 || major >= MAX_BLKDEV) return 0; major = MAJOR(bdev->bd_dev);
minor = MINOR(bdev->bd_dev);
if (major < 0 || major >= MAX_BLKDEV)
return 0;
return ro_bits[major][minor >> 5] & (1 << (minor & 31)); return ro_bits[major][minor >> 5] & (1 << (minor & 31));
} }
int bdev_read_only(struct block_device *bdev)
{
return bdev && is_read_only(to_kdev_t(bdev->bd_dev));
}
void set_device_ro(kdev_t dev,int flag) void set_device_ro(kdev_t dev,int flag)
{ {
int minor,major; int minor,major;
......
...@@ -318,8 +318,9 @@ static void sanitize_format(union cdrom_addr *addr, ...@@ -318,8 +318,9 @@ static void sanitize_format(union cdrom_addr *addr,
static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
unsigned long arg); unsigned long arg);
int cdrom_get_last_written(kdev_t dev, long *last_written); int cdrom_get_last_written(struct cdrom_device_info *, long *);
int cdrom_get_next_writable(kdev_t dev, long *next_writable); static int cdrom_get_next_writable(struct cdrom_device_info *, long *);
static void cdrom_count_tracks(struct cdrom_device_info *, tracktype*);
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
static void cdrom_sysctl_register(void); static void cdrom_sysctl_register(void);
...@@ -441,7 +442,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg) ...@@ -441,7 +442,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
return 0; return 0;
} }
struct cdrom_device_info *cdrom_find_device(kdev_t dev) static struct cdrom_device_info *cdrom_find_device(kdev_t dev)
{ {
struct cdrom_device_info *cdi; struct cdrom_device_info *cdi;
...@@ -780,7 +781,7 @@ static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot) ...@@ -780,7 +781,7 @@ static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot)
return cdi->ops->generic_packet(cdi, &cgc); return cdi->ops->generic_packet(cdi, &cgc);
} }
int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
{ {
struct cdrom_changer_info info; struct cdrom_changer_info info;
int curslot; int curslot;
...@@ -864,7 +865,7 @@ int cdrom_media_changed(kdev_t dev) ...@@ -864,7 +865,7 @@ int cdrom_media_changed(kdev_t dev)
} }
/* badly broken, I know. Is due for a fixup anytime. */ /* badly broken, I know. Is due for a fixup anytime. */
void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks) static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
{ {
struct cdrom_tochdr header; struct cdrom_tochdr header;
struct cdrom_tocentry entry; struct cdrom_tocentry entry;
...@@ -1926,7 +1927,6 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, ...@@ -1926,7 +1927,6 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
{ {
struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_device_ops *cdo = cdi->ops;
struct cdrom_generic_command cgc; struct cdrom_generic_command cgc;
kdev_t dev = cdi->dev;
char buffer[32]; char buffer[32];
int ret = 0; int ret = 0;
...@@ -2198,7 +2198,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, ...@@ -2198,7 +2198,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
case CDROM_NEXT_WRITABLE: { case CDROM_NEXT_WRITABLE: {
long next = 0; long next = 0;
cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n");
if ((ret = cdrom_get_next_writable(dev, &next))) if ((ret = cdrom_get_next_writable(cdi, &next)))
return ret; return ret;
IOCTL_OUT(arg, long, next); IOCTL_OUT(arg, long, next);
return 0; return 0;
...@@ -2206,7 +2206,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, ...@@ -2206,7 +2206,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
case CDROM_LAST_WRITTEN: { case CDROM_LAST_WRITTEN: {
long last = 0; long last = 0;
cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n");
if ((ret = cdrom_get_last_written(dev, &last))) if ((ret = cdrom_get_last_written(cdi, &last)))
return ret; return ret;
IOCTL_OUT(arg, long, last); IOCTL_OUT(arg, long, last);
return 0; return 0;
...@@ -2216,10 +2216,9 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, ...@@ -2216,10 +2216,9 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
return -ENOTTY; return -ENOTTY;
} }
int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type, static int cdrom_get_track_info(struct cdrom_device_info *cdi, __u16 track, __u8 type,
track_information *ti) track_information *ti)
{ {
struct cdrom_device_info *cdi = cdrom_find_device(dev);
struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_device_ops *cdo = cdi->ops;
struct cdrom_generic_command cgc; struct cdrom_generic_command cgc;
int ret; int ret;
...@@ -2246,9 +2245,8 @@ int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type, ...@@ -2246,9 +2245,8 @@ int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type,
} }
/* requires CD R/RW */ /* requires CD R/RW */
int cdrom_get_disc_info(kdev_t dev, disc_information *di) static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di)
{ {
struct cdrom_device_info *cdi = cdrom_find_device(dev);
struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_device_ops *cdo = cdi->ops;
struct cdrom_generic_command cgc; struct cdrom_generic_command cgc;
int ret; int ret;
...@@ -2278,9 +2276,8 @@ int cdrom_get_disc_info(kdev_t dev, disc_information *di) ...@@ -2278,9 +2276,8 @@ int cdrom_get_disc_info(kdev_t dev, disc_information *di)
/* return the last written block on the CD-R media. this is for the udf /* return the last written block on the CD-R media. this is for the udf
file system. */ file system. */
int cdrom_get_last_written(kdev_t dev, long *last_written) int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written)
{ {
struct cdrom_device_info *cdi = cdrom_find_device(dev);
struct cdrom_tocentry toc; struct cdrom_tocentry toc;
disc_information di; disc_information di;
track_information ti; track_information ti;
...@@ -2290,17 +2287,17 @@ int cdrom_get_last_written(kdev_t dev, long *last_written) ...@@ -2290,17 +2287,17 @@ int cdrom_get_last_written(kdev_t dev, long *last_written)
if (!CDROM_CAN(CDC_GENERIC_PACKET)) if (!CDROM_CAN(CDC_GENERIC_PACKET))
goto use_toc; goto use_toc;
if ((ret = cdrom_get_disc_info(dev, &di))) if ((ret = cdrom_get_disc_info(cdi, &di)))
goto use_toc; goto use_toc;
last_track = (di.last_track_msb << 8) | di.last_track_lsb; last_track = (di.last_track_msb << 8) | di.last_track_lsb;
if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti))) if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
goto use_toc; goto use_toc;
/* if this track is blank, try the previous. */ /* if this track is blank, try the previous. */
if (ti.blank) { if (ti.blank) {
last_track--; last_track--;
if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti))) if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
goto use_toc; goto use_toc;
} }
...@@ -2330,9 +2327,8 @@ int cdrom_get_last_written(kdev_t dev, long *last_written) ...@@ -2330,9 +2327,8 @@ int cdrom_get_last_written(kdev_t dev, long *last_written)
} }
/* return the next writable block. also for udf file system. */ /* return the next writable block. also for udf file system. */
int cdrom_get_next_writable(kdev_t dev, long *next_writable) static int cdrom_get_next_writable(struct cdrom_device_info *cdi, long *next_writable)
{ {
struct cdrom_device_info *cdi = cdrom_find_device(dev);
disc_information di; disc_information di;
track_information ti; track_information ti;
__u16 last_track; __u16 last_track;
...@@ -2341,17 +2337,17 @@ int cdrom_get_next_writable(kdev_t dev, long *next_writable) ...@@ -2341,17 +2337,17 @@ int cdrom_get_next_writable(kdev_t dev, long *next_writable)
if (!CDROM_CAN(CDC_GENERIC_PACKET)) if (!CDROM_CAN(CDC_GENERIC_PACKET))
goto use_last_written; goto use_last_written;
if ((ret = cdrom_get_disc_info(dev, &di))) if ((ret = cdrom_get_disc_info(cdi, &di)))
goto use_last_written; goto use_last_written;
last_track = (di.last_track_msb << 8) | di.last_track_lsb; last_track = (di.last_track_msb << 8) | di.last_track_lsb;
if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti))) if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
goto use_last_written; goto use_last_written;
/* if this track is blank, try the previous. */ /* if this track is blank, try the previous. */
if (ti.blank) { if (ti.blank) {
last_track--; last_track--;
if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti))) if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
goto use_last_written; goto use_last_written;
} }
...@@ -2364,7 +2360,7 @@ int cdrom_get_next_writable(kdev_t dev, long *next_writable) ...@@ -2364,7 +2360,7 @@ int cdrom_get_next_writable(kdev_t dev, long *next_writable)
return 0; return 0;
use_last_written: use_last_written:
if ((ret = cdrom_get_last_written(dev, next_writable))) { if ((ret = cdrom_get_last_written(cdi, next_writable))) {
*next_writable = 0; *next_writable = 0;
return ret; return ret;
} else { } else {
...@@ -2373,11 +2369,7 @@ int cdrom_get_next_writable(kdev_t dev, long *next_writable) ...@@ -2373,11 +2369,7 @@ int cdrom_get_next_writable(kdev_t dev, long *next_writable)
} }
} }
EXPORT_SYMBOL(cdrom_get_disc_info);
EXPORT_SYMBOL(cdrom_get_track_info);
EXPORT_SYMBOL(cdrom_get_next_writable);
EXPORT_SYMBOL(cdrom_get_last_written); EXPORT_SYMBOL(cdrom_get_last_written);
EXPORT_SYMBOL(cdrom_count_tracks);
EXPORT_SYMBOL(register_cdrom); EXPORT_SYMBOL(register_cdrom);
EXPORT_SYMBOL(unregister_cdrom); EXPORT_SYMBOL(unregister_cdrom);
EXPORT_SYMBOL(cdrom_open); EXPORT_SYMBOL(cdrom_open);
...@@ -2385,11 +2377,9 @@ EXPORT_SYMBOL(cdrom_release); ...@@ -2385,11 +2377,9 @@ EXPORT_SYMBOL(cdrom_release);
EXPORT_SYMBOL(cdrom_ioctl); EXPORT_SYMBOL(cdrom_ioctl);
EXPORT_SYMBOL(cdrom_media_changed); EXPORT_SYMBOL(cdrom_media_changed);
EXPORT_SYMBOL(cdrom_number_of_slots); EXPORT_SYMBOL(cdrom_number_of_slots);
EXPORT_SYMBOL(cdrom_select_disc);
EXPORT_SYMBOL(cdrom_mode_select); EXPORT_SYMBOL(cdrom_mode_select);
EXPORT_SYMBOL(cdrom_mode_sense); EXPORT_SYMBOL(cdrom_mode_sense);
EXPORT_SYMBOL(init_cdrom_command); EXPORT_SYMBOL(init_cdrom_command);
EXPORT_SYMBOL(cdrom_find_device);
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
......
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#define BUILDING_PTY_C 1
#include <linux/devpts_fs.h> #include <linux/devpts_fs.h>
struct pty_struct { struct pty_struct {
......
...@@ -1336,7 +1336,7 @@ static int tty_open(struct inode * inode, struct file * filp) ...@@ -1336,7 +1336,7 @@ static int tty_open(struct inode * inode, struct file * filp)
ptmx_found: ptmx_found:
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
minor -= driver->minor_start; minor -= driver->minor_start;
devpts_pty_new(driver->other->name_base + minor, mk_kdev(driver->other->major, minor + driver->other->minor_start)); devpts_pty_new(driver->other->name_base + minor, MKDEV(driver->other->major, minor + driver->other->minor_start));
tty_register_devfs(&pts_driver[major], DEVFS_FL_DEFAULT, tty_register_devfs(&pts_driver[major], DEVFS_FL_DEFAULT,
pts_driver[major].minor_start + minor); pts_driver[major].minor_start + minor);
noctty = 1; noctty = 1;
......
...@@ -1937,9 +1937,9 @@ static int cdrom_read_tocentry(struct ata_device *drive, int trackno, int msf_fl ...@@ -1937,9 +1937,9 @@ static int cdrom_read_tocentry(struct ata_device *drive, int trackno, int msf_fl
/* Try to read the entire TOC for the disk into our internal buffer. */ /* Try to read the entire TOC for the disk into our internal buffer. */
static int cdrom_read_toc(struct ata_device *drive, struct request_sense *sense) static int cdrom_read_toc(struct ata_device *drive, struct request_sense *sense)
{ {
int minor, stat, ntracks, i; int stat, ntracks, i;
kdev_t dev;
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
struct atapi_toc *toc = info->toc; struct atapi_toc *toc = info->toc;
struct { struct {
struct atapi_toc_header hdr; struct atapi_toc_header hdr;
...@@ -2071,10 +2071,8 @@ static int cdrom_read_toc(struct ata_device *drive, struct request_sense *sense) ...@@ -2071,10 +2071,8 @@ static int cdrom_read_toc(struct ata_device *drive, struct request_sense *sense)
toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
/* Now try to get the total cdrom capacity. */ /* Now try to get the total cdrom capacity. */
minor = (drive->select.b.unit) << PARTN_BITS;
dev = mk_kdev(drive->channel->major, minor);
/* FIXME: This is making worng assumptions about register layout. */ /* FIXME: This is making worng assumptions about register layout. */
stat = cdrom_get_last_written(dev, (unsigned long *) &toc->capacity); stat = cdrom_get_last_written(cdi, (unsigned long *) &toc->capacity);
if (stat) if (stat)
stat = cdrom_read_capacity(drive, &toc->capacity, sense); stat = cdrom_read_capacity(drive, &toc->capacity, sense);
if (stat) if (stat)
......
...@@ -740,8 +740,7 @@ void abort_requests(struct hpsb_host *host) ...@@ -740,8 +740,7 @@ void abort_requests(struct hpsb_host *host)
host->ops->devctl(host, CANCEL_REQUESTS, 0); host->ops->devctl(host, CANCEL_REQUESTS, 0);
spin_lock_irqsave(&host->pending_pkt_lock, flags); spin_lock_irqsave(&host->pending_pkt_lock, flags);
list_splice(&host->pending_packets, &llist); list_splice_init(&host->pending_packets, &llist);
INIT_LIST_HEAD(&host->pending_packets);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags); spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
list_for_each(lh, &llist) { list_for_each(lh, &llist) {
......
...@@ -60,7 +60,6 @@ static int linear_run (mddev_t *mddev) ...@@ -60,7 +60,6 @@ static int linear_run (mddev_t *mddev)
goto out; goto out;
} }
disk->dev = rdev->dev;
disk->bdev = rdev->bdev; disk->bdev = rdev->bdev;
atomic_inc(&rdev->bdev->bd_count); atomic_inc(&rdev->bdev->bd_count);
disk->size = rdev->size; disk->size = rdev->size;
...@@ -163,7 +162,7 @@ static int linear_make_request (request_queue_t *q, struct bio *bio) ...@@ -163,7 +162,7 @@ static int linear_make_request (request_queue_t *q, struct bio *bio)
if (block >= (tmp_dev->size + tmp_dev->offset) if (block >= (tmp_dev->size + tmp_dev->offset)
|| block < tmp_dev->offset) { || block < tmp_dev->offset) {
printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset); printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, bdevname(tmp_dev->bdev), tmp_dev->size, tmp_dev->offset);
bio_io_error(bio); bio_io_error(bio);
return 0; return 0;
} }
...@@ -186,11 +185,11 @@ static int linear_status (char *page, mddev_t *mddev) ...@@ -186,11 +185,11 @@ static int linear_status (char *page, mddev_t *mddev)
for (j = 0; j < conf->nr_zones; j++) for (j = 0; j < conf->nr_zones; j++)
{ {
sz += sprintf(page+sz, "[%s", sz += sprintf(page+sz, "[%s",
partition_name(conf->hash_table[j].dev0->dev)); bdev_partition_name(conf->hash_table[j].dev0->bdev));
if (conf->hash_table[j].dev1) if (conf->hash_table[j].dev1)
sz += sprintf(page+sz, "/%s] ", sz += sprintf(page+sz, "/%s] ",
partition_name(conf->hash_table[j].dev1->dev)); bdev_partition_name(conf->hash_table[j].dev1->bdev));
else else
sz += sprintf(page+sz, "] "); sz += sprintf(page+sz, "] ");
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -174,6 +174,10 @@ ...@@ -174,6 +174,10 @@
- Add `global_options' as default for options[]. Ditto global_enable_wol, - Add `global_options' as default for options[]. Ditto global_enable_wol,
global_full_duplex. global_full_duplex.
LK1.1.18 01Jul02 akpm
- Fix for undocumented transceiver power-up bit on some 3c566B's
(Donald Becker, Rahul Karnik)
- See http://www.zip.com.au/~akpm/linux/#3c59x-2.3 for more details. - See http://www.zip.com.au/~akpm/linux/#3c59x-2.3 for more details.
- Also see Documentation/networking/vortex.txt - Also see Documentation/networking/vortex.txt
*/ */
...@@ -189,8 +193,8 @@ ...@@ -189,8 +193,8 @@
#define DRV_NAME "3c59x" #define DRV_NAME "3c59x"
#define DRV_VERSION "LK1.1.17" #define DRV_VERSION "LK1.1.18"
#define DRV_RELDATE "18 Dec 2001" #define DRV_RELDATE "1 Jul 2002"
...@@ -414,7 +418,7 @@ enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8, ...@@ -414,7 +418,7 @@ enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8,
EEPROM_8BIT=0x10, /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */ EEPROM_8BIT=0x10, /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */
HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100, HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100,
INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800, INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800,
EEPROM_OFFSET=0x1000, HAS_HWCKSM=0x2000 }; EEPROM_OFFSET=0x1000, HAS_HWCKSM=0x2000, WNO_XCVR_PWR=0x4000 };
enum vortex_chips { enum vortex_chips {
CH_3C590 = 0, CH_3C590 = 0,
...@@ -522,7 +526,7 @@ static struct vortex_chip_info { ...@@ -522,7 +526,7 @@ static struct vortex_chip_info {
HAS_HWCKSM, 128, }, HAS_HWCKSM, 128, },
{"3c556B Laptop Hurricane", {"3c556B Laptop Hurricane",
PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR| PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR|
HAS_HWCKSM, 128, }, WNO_XCVR_PWR|HAS_HWCKSM, 128, },
{"3c575 [Megahertz] 10/100 LAN CardBus", {"3c575 [Megahertz] 10/100 LAN CardBus",
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
...@@ -1222,6 +1226,10 @@ static int __devinit vortex_probe1(struct pci_dev *pdev, ...@@ -1222,6 +1226,10 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
if (vp->drv_flags & INVERT_MII_PWR) if (vp->drv_flags & INVERT_MII_PWR)
n |= 0x4000; n |= 0x4000;
outw(n, ioaddr + Wn2_ResetOptions); outw(n, ioaddr + Wn2_ResetOptions);
if (vp->drv_flags & WNO_XCVR_PWR) {
EL3WINDOW(0);
outw(0x0800, ioaddr);
}
} }
/* Extract our information from the EEPROM data. */ /* Extract our information from the EEPROM data. */
......
...@@ -1031,14 +1031,6 @@ extern unsigned char e100_selftest(struct e100_private *bdp, u32 *st_timeout, ...@@ -1031,14 +1031,6 @@ extern unsigned char e100_selftest(struct e100_private *bdp, u32 *st_timeout,
extern unsigned char e100_get_link_state(struct e100_private *bdp); extern unsigned char e100_get_link_state(struct e100_private *bdp);
extern unsigned char e100_wait_scb(struct e100_private *bdp); extern unsigned char e100_wait_scb(struct e100_private *bdp);
#ifndef yield
#define yield() \
do { \
current->policy |= SCHED_YIELD; \
schedule(); \
} while (0)
#endif
extern void e100_deisolate_driver(struct e100_private *bdp, extern void e100_deisolate_driver(struct e100_private *bdp,
u8 recover, u8 full_reset); u8 recover, u8 full_reset);
extern unsigned char e100_hw_reset_recover(struct e100_private *bdp, extern unsigned char e100_hw_reset_recover(struct e100_private *bdp,
......
...@@ -303,15 +303,15 @@ pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma) ...@@ -303,15 +303,15 @@ pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
#ifdef CONFIG_DEBUG_SLAB #ifdef CONFIG_DEBUG_SLAB
if (((dma - page->dma) + (void *)page->vaddr) != vaddr) { if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n", printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%Lx\n",
pool->dev ? pool->dev->slot_name : NULL, pool->dev ? pool->dev->slot_name : NULL,
pool->name, vaddr, (unsigned long) dma); pool->name, vaddr, (unsigned long long) dma);
return; return;
} }
if (page->bitmap [map] & (1UL << block)) { if (page->bitmap [map] & (1UL << block)) {
printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n", printk (KERN_ERR "pci_pool_free %s/%s, dma %Lx already free\n",
pool->dev ? pool->dev->slot_name : NULL, pool->dev ? pool->dev->slot_name : NULL,
pool->name, dma); pool->name, (unsigned long long)dma);
return; return;
} }
memset (vaddr, POOL_POISON_BYTE, pool->size); memset (vaddr, POOL_POISON_BYTE, pool->size);
......
...@@ -2467,7 +2467,9 @@ struct scatterlist *scsi_alloc_sgtable(Scsi_Cmnd *SCpnt, int gfp_mask) ...@@ -2467,7 +2467,9 @@ struct scatterlist *scsi_alloc_sgtable(Scsi_Cmnd *SCpnt, int gfp_mask)
sgp = scsi_sg_pools + SCpnt->sglist_len; sgp = scsi_sg_pools + SCpnt->sglist_len;
current->flags |= PF_NOWARN;
sgl = mempool_alloc(sgp->pool, gfp_mask); sgl = mempool_alloc(sgp->pool, gfp_mask);
current->flags &= ~PF_NOWARN;
if (sgl) { if (sgl) {
memset(sgl, 0, sgp->size); memset(sgl, 0, sgp->size);
return sgl; return sgl;
......
...@@ -74,8 +74,10 @@ int scsi_init_io(Scsi_Cmnd *SCpnt) ...@@ -74,8 +74,10 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
SCpnt->use_sg = count; SCpnt->use_sg = count;
gfp_mask = GFP_NOIO; gfp_mask = GFP_NOIO;
if (in_interrupt()) if (in_interrupt()) {
gfp_mask &= ~__GFP_WAIT; gfp_mask &= ~__GFP_WAIT;
gfp_mask |= __GFP_HIGH;
}
/* /*
* if sg table allocation fails, requeue request later. * if sg table allocation fails, requeue request later.
......
...@@ -522,8 +522,8 @@ void get_sectorsize(int i) ...@@ -522,8 +522,8 @@ void get_sectorsize(int i)
SCp->needs_sector_size = 1; SCp->needs_sector_size = 1;
} else { } else {
#if 0 #if 0
if (cdrom_get_last_written(mkdev(MAJOR_NR, i), if (cdrom_get_last_written(&SCp->cdi,
&scsi_CDs[i].capacity)) &SCp->capacity))
#endif #endif
SCp->capacity = 1 + ((buffer[0] << 24) | SCp->capacity = 1 + ((buffer[0] << 24) |
(buffer[1] << 16) | (buffer[1] << 16) |
......
...@@ -40,6 +40,7 @@ obj-$(CONFIG_QUOTACTL) += quota.o ...@@ -40,6 +40,7 @@ obj-$(CONFIG_QUOTACTL) += quota.o
obj-$(CONFIG_PROC_FS) += proc/ obj-$(CONFIG_PROC_FS) += proc/
obj-y += partitions/ obj-y += partitions/
obj-y += driverfs/ obj-y += driverfs/
obj-y += devpts/
# Do not add any filesystems before this line # Do not add any filesystems before this line
obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3 obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3
...@@ -81,7 +82,6 @@ obj-$(CONFIG_AUTOFS_FS) += autofs/ ...@@ -81,7 +82,6 @@ obj-$(CONFIG_AUTOFS_FS) += autofs/
obj-$(CONFIG_AUTOFS4_FS) += autofs4/ obj-$(CONFIG_AUTOFS4_FS) += autofs4/
obj-$(CONFIG_ADFS_FS) += adfs/ obj-$(CONFIG_ADFS_FS) += adfs/
obj-$(CONFIG_REISERFS_FS) += reiserfs/ obj-$(CONFIG_REISERFS_FS) += reiserfs/
obj-$(CONFIG_DEVPTS_FS) += devpts/
obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
obj-$(CONFIG_JFS_FS) += jfs/ obj-$(CONFIG_JFS_FS) += jfs/
......
...@@ -135,21 +135,26 @@ inline void bio_init(struct bio *bio) ...@@ -135,21 +135,26 @@ inline void bio_init(struct bio *bio)
**/ **/
struct bio *bio_alloc(int gfp_mask, int nr_iovecs) struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
{ {
struct bio *bio = mempool_alloc(bio_pool, gfp_mask); struct bio *bio;
struct bio_vec *bvl = NULL; struct bio_vec *bvl = NULL;
current->flags |= PF_NOWARN;
bio = mempool_alloc(bio_pool, gfp_mask);
if (unlikely(!bio)) if (unlikely(!bio))
return NULL; goto out;
if (!nr_iovecs || (bvl = bvec_alloc(gfp_mask,nr_iovecs,&bio->bi_max))) { if (!nr_iovecs || (bvl = bvec_alloc(gfp_mask,nr_iovecs,&bio->bi_max))) {
bio_init(bio); bio_init(bio);
bio->bi_destructor = bio_destructor; bio->bi_destructor = bio_destructor;
bio->bi_io_vec = bvl; bio->bi_io_vec = bvl;
return bio; goto out;
} }
mempool_free(bio, bio_pool); mempool_free(bio, bio_pool);
return NULL; bio = NULL;
out:
current->flags &= ~PF_NOWARN;
return bio;
} }
/** /**
......
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512)
static unsigned long max_block(struct block_device *bdev) static unsigned long max_block(struct block_device *bdev)
{ {
unsigned int retval = ~0U; unsigned int retval = ~0U;
...@@ -299,7 +297,6 @@ struct block_device *bdget(dev_t dev) ...@@ -299,7 +297,6 @@ struct block_device *bdget(dev_t dev)
new_bdev->bd_inode = inode; new_bdev->bd_inode = inode;
inode->i_mode = S_IFBLK; inode->i_mode = S_IFBLK;
inode->i_rdev = kdev; inode->i_rdev = kdev;
inode->i_dev = kdev;
inode->i_bdev = new_bdev; inode->i_bdev = new_bdev;
inode->i_data.a_ops = &def_blk_aops; inode->i_data.a_ops = &def_blk_aops;
inode->i_data.gfp_mask = GFP_USER; inode->i_data.gfp_mask = GFP_USER;
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <asm/bitops.h> #include <asm/bitops.h>
static void invalidate_bh_lrus(void);
#define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers) #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
/* /*
...@@ -243,22 +245,6 @@ int fsync_bdev(struct block_device *bdev) ...@@ -243,22 +245,6 @@ int fsync_bdev(struct block_device *bdev)
return sync_blockdev(bdev); return sync_blockdev(bdev);
} }
/*
* Write out and wait upon all dirty data associated with this
* kdev_t. Filesystem data as well as the underlying block
* device. Takes the superblock lock.
*/
int fsync_dev(kdev_t dev)
{
struct block_device *bdev = bdget(kdev_t_to_nr(dev));
if (bdev) {
int res = fsync_bdev(bdev);
bdput(bdev);
return res;
}
return 0;
}
/* /*
* sync everything. * sync everything.
*/ */
...@@ -389,7 +375,7 @@ asmlinkage long sys_fdatasync(unsigned int fd) ...@@ -389,7 +375,7 @@ asmlinkage long sys_fdatasync(unsigned int fd)
* private_lock is contended then so is mapping->page_lock). * private_lock is contended then so is mapping->page_lock).
*/ */
struct buffer_head * struct buffer_head *
__find_get_block(struct block_device *bdev, sector_t block, int unused) __find_get_block_slow(struct block_device *bdev, sector_t block, int unused)
{ {
struct inode *bd_inode = bdev->bd_inode; struct inode *bd_inode = bdev->bd_inode;
struct address_space *bd_mapping = bd_inode->i_mapping; struct address_space *bd_mapping = bd_inode->i_mapping;
...@@ -459,12 +445,15 @@ __find_get_block(struct block_device *bdev, sector_t block, int unused) ...@@ -459,12 +445,15 @@ __find_get_block(struct block_device *bdev, sector_t block, int unused)
pass does the actual I/O. */ pass does the actual I/O. */
void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
{ {
invalidate_bh_lrus();
/* /*
* FIXME: what about destroy_dirty_buffers? * FIXME: what about destroy_dirty_buffers?
* We really want to use invalidate_inode_pages2() for * We really want to use invalidate_inode_pages2() for
* that, but not until that's cleaned up. * that, but not until that's cleaned up.
*/ */
current->flags |= PF_INVALIDATE;
invalidate_inode_pages(bdev->bd_inode); invalidate_inode_pages(bdev->bd_inode);
current->flags &= ~PF_INVALIDATE;
} }
void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers) void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
...@@ -489,7 +478,6 @@ static void free_more_memory(void) ...@@ -489,7 +478,6 @@ static void free_more_memory(void)
wakeup_bdflush(); wakeup_bdflush();
try_to_free_pages(zone, GFP_NOFS, 0); try_to_free_pages(zone, GFP_NOFS, 0);
blk_run_queues(); blk_run_queues();
__set_current_state(TASK_RUNNING);
yield(); yield();
} }
...@@ -961,7 +949,9 @@ create_buffers(struct page * page, unsigned long size, int retry) ...@@ -961,7 +949,9 @@ create_buffers(struct page * page, unsigned long size, int retry)
head = NULL; head = NULL;
offset = PAGE_SIZE; offset = PAGE_SIZE;
while ((offset -= size) >= 0) { while ((offset -= size) >= 0) {
current->flags |= PF_NOWARN;
bh = alloc_buffer_head(); bh = alloc_buffer_head();
current->flags &= ~PF_NOWARN;
if (!bh) if (!bh)
goto no_grow; goto no_grow;
...@@ -1159,7 +1149,7 @@ grow_buffers(struct block_device *bdev, unsigned long block, int size) ...@@ -1159,7 +1149,7 @@ grow_buffers(struct block_device *bdev, unsigned long block, int size)
* attempt is failing. FIXME, perhaps? * attempt is failing. FIXME, perhaps?
*/ */
struct buffer_head * struct buffer_head *
__getblk(struct block_device *bdev, sector_t block, int size) __getblk_slow(struct block_device *bdev, sector_t block, int size)
{ {
for (;;) { for (;;) {
struct buffer_head * bh; struct buffer_head * bh;
...@@ -1259,7 +1249,8 @@ void __bforget(struct buffer_head *bh) ...@@ -1259,7 +1249,8 @@ void __bforget(struct buffer_head *bh)
* Reads a specified block, and returns buffer head that contains it. * Reads a specified block, and returns buffer head that contains it.
* It returns NULL if the block was unreadable. * It returns NULL if the block was unreadable.
*/ */
struct buffer_head * __bread(struct block_device *bdev, int block, int size) struct buffer_head *
__bread_slow(struct block_device *bdev, sector_t block, int size)
{ {
struct buffer_head *bh = __getblk(bdev, block, size); struct buffer_head *bh = __getblk(bdev, block, size);
...@@ -1283,6 +1274,165 @@ struct buffer_head * __bread(struct block_device *bdev, int block, int size) ...@@ -1283,6 +1274,165 @@ struct buffer_head * __bread(struct block_device *bdev, int block, int size)
return NULL; return NULL;
} }
/*
* Per-cpu buffer LRU implementation. To reduce the cost of __find_get_block().
* The bhs[] array is sorted - newest buffer is at bhs[0]. Buffers have their
* refcount elevated by one when they're in an LRU. A buffer can only appear
* once in a particular CPU's LRU. A single buffer can be present in multiple
* CPU's LRUs at the same time.
*
* This is a transparent caching front-end to sb_bread(), sb_getblk() and
* sb_find_get_block().
*/
#define BH_LRU_SIZE 7
static struct bh_lru {
spinlock_t lock;
struct buffer_head *bhs[BH_LRU_SIZE];
} ____cacheline_aligned_in_smp bh_lrus[NR_CPUS];
/*
* The LRU management algorithm is dopey-but-simple. Sorry.
*/
static void bh_lru_install(struct buffer_head *bh)
{
struct buffer_head *evictee = NULL;
struct bh_lru *lru;
if (bh == NULL)
return;
lru = &bh_lrus[get_cpu()];
spin_lock(&lru->lock);
if (lru->bhs[0] != bh) {
struct buffer_head *bhs[BH_LRU_SIZE];
int in;
int out = 0;
get_bh(bh);
bhs[out++] = bh;
for (in = 0; in < BH_LRU_SIZE; in++) {
struct buffer_head *bh2 = lru->bhs[in];
if (bh2 == bh) {
__brelse(bh2);
} else {
if (out >= BH_LRU_SIZE) {
BUG_ON(evictee != NULL);
evictee = bh2;
} else {
bhs[out++] = bh2;
}
}
}
while (out < BH_LRU_SIZE)
bhs[out++] = NULL;
memcpy(lru->bhs, bhs, sizeof(bhs));
}
spin_unlock(&lru->lock);
put_cpu();
if (evictee) {
touch_buffer(evictee);
__brelse(evictee);
}
}
static inline struct buffer_head *
lookup_bh(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *ret = NULL;
struct bh_lru *lru;
int i;
lru = &bh_lrus[get_cpu()];
spin_lock(&lru->lock);
for (i = 0; i < BH_LRU_SIZE; i++) {
struct buffer_head *bh = lru->bhs[i];
if (bh && bh->b_bdev == bdev &&
bh->b_blocknr == block && bh->b_size == size) {
if (i) {
while (i) {
lru->bhs[i] = lru->bhs[i - 1];
i--;
}
lru->bhs[0] = bh;
}
get_bh(bh);
ret = bh;
break;
}
}
spin_unlock(&lru->lock);
put_cpu();
return ret;
}
struct buffer_head *
__find_get_block(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *bh = lookup_bh(bdev, block, size);
if (bh == NULL) {
bh = __find_get_block_slow(bdev, block, size);
bh_lru_install(bh);
}
return bh;
}
EXPORT_SYMBOL(__find_get_block);
struct buffer_head *
__getblk(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *bh = __find_get_block(bdev, block, size);
if (bh == NULL) {
bh = __getblk_slow(bdev, block, size);
bh_lru_install(bh);
}
return bh;
}
EXPORT_SYMBOL(__getblk);
struct buffer_head *
__bread(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *bh = __getblk(bdev, block, size);
if (bh) {
if (buffer_uptodate(bh))
return bh;
__brelse(bh);
}
bh = __bread_slow(bdev, block, size);
bh_lru_install(bh);
return bh;
}
EXPORT_SYMBOL(__bread);
/*
* This is called rarely - at unmount.
*/
static void invalidate_bh_lrus(void)
{
int cpu_idx;
for (cpu_idx = 0; cpu_idx < NR_CPUS; cpu_idx++)
spin_lock(&bh_lrus[cpu_idx].lock);
for (cpu_idx = 0; cpu_idx < NR_CPUS; cpu_idx++) {
int i;
for (i = 0; i < BH_LRU_SIZE; i++) {
brelse(bh_lrus[cpu_idx].bhs[i]);
bh_lrus[cpu_idx].bhs[i] = NULL;
}
}
for (cpu_idx = 0; cpu_idx < NR_CPUS; cpu_idx++)
spin_unlock(&bh_lrus[cpu_idx].lock);
}
void set_bh_page(struct buffer_head *bh, void set_bh_page(struct buffer_head *bh,
struct page *page, unsigned long offset) struct page *page, unsigned long offset)
{ {
...@@ -2306,7 +2456,8 @@ static inline int buffer_busy(struct buffer_head *bh) ...@@ -2306,7 +2456,8 @@ static inline int buffer_busy(struct buffer_head *bh)
(bh->b_state & ((1 << BH_Dirty) | (1 << BH_Lock))); (bh->b_state & ((1 << BH_Dirty) | (1 << BH_Lock)));
} }
static /*inline*/ int drop_buffers(struct page *page) static inline int
drop_buffers(struct page *page, struct buffer_head **buffers_to_free)
{ {
struct buffer_head *head = page_buffers(page); struct buffer_head *head = page_buffers(page);
struct buffer_head *bh; struct buffer_head *bh;
...@@ -2330,9 +2481,9 @@ static /*inline*/ int drop_buffers(struct page *page) ...@@ -2330,9 +2481,9 @@ static /*inline*/ int drop_buffers(struct page *page)
if (!list_empty(&bh->b_assoc_buffers)) if (!list_empty(&bh->b_assoc_buffers))
__remove_assoc_queue(bh); __remove_assoc_queue(bh);
free_buffer_head(bh);
bh = next; bh = next;
} while (bh != head); } while (bh != head);
*buffers_to_free = head;
__clear_page_buffers(page); __clear_page_buffers(page);
return 1; return 1;
failed: failed:
...@@ -2342,17 +2493,20 @@ static /*inline*/ int drop_buffers(struct page *page) ...@@ -2342,17 +2493,20 @@ static /*inline*/ int drop_buffers(struct page *page)
int try_to_free_buffers(struct page *page) int try_to_free_buffers(struct page *page)
{ {
struct address_space * const mapping = page->mapping; struct address_space * const mapping = page->mapping;
struct buffer_head *buffers_to_free = NULL;
int ret = 0; int ret = 0;
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
if (PageWriteback(page)) if (PageWriteback(page))
return 0; return 0;
if (mapping == NULL) /* swapped-in anon page */ if (mapping == NULL) { /* swapped-in anon page */
return drop_buffers(page); ret = drop_buffers(page, &buffers_to_free);
goto out;
}
spin_lock(&mapping->private_lock); spin_lock(&mapping->private_lock);
ret = drop_buffers(page); ret = drop_buffers(page, &buffers_to_free);
if (ret && !PageSwapCache(page)) { if (ret && !PageSwapCache(page)) {
/* /*
* If the filesystem writes its buffers by hand (eg ext3) * If the filesystem writes its buffers by hand (eg ext3)
...@@ -2365,6 +2519,16 @@ int try_to_free_buffers(struct page *page) ...@@ -2365,6 +2519,16 @@ int try_to_free_buffers(struct page *page)
ClearPageDirty(page); ClearPageDirty(page);
} }
spin_unlock(&mapping->private_lock); spin_unlock(&mapping->private_lock);
out:
if (buffers_to_free) {
struct buffer_head *bh = buffers_to_free;
do {
struct buffer_head *next = bh->b_this_page;
free_buffer_head(bh);
bh = next;
} while (bh != buffers_to_free);
}
return ret; return ret;
} }
EXPORT_SYMBOL(try_to_free_buffers); EXPORT_SYMBOL(try_to_free_buffers);
...@@ -2435,6 +2599,9 @@ void __init buffer_init(void) ...@@ -2435,6 +2599,9 @@ void __init buffer_init(void)
{ {
int i; int i;
for (i = 0; i < NR_CPUS; i++)
spin_lock_init(&bh_lrus[i].lock);
bh_cachep = kmem_cache_create("buffer_head", bh_cachep = kmem_cache_create("buffer_head",
sizeof(struct buffer_head), 0, sizeof(struct buffer_head), 0,
SLAB_HWCACHE_ALIGN, init_buffer_head, NULL); SLAB_HWCACHE_ALIGN, init_buffer_head, NULL);
......
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
obj-$(CONFIG_DEVPTS_FS) += devpts.o obj-$(CONFIG_DEVPTS_FS) += devpts.o
devpts-objs := root.o inode.o devpts-objs := inode.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
/* -*- linux-c -*- --------------------------------------------------------- *
*
* linux/fs/devpts/devpts_i.h
*
* Copyright 1998 H. Peter Anvin -- All Rights Reserved
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
* option, any later version, incorporated herein by reference.
*
* ------------------------------------------------------------------------- */
#include <linux/fs.h>
#include <linux/tty.h>
#include <linux/types.h>
#define BUILDING_DEVPTS 1
#include <linux/devpts_fs.h>
struct devpts_sb_info {
u32 magic;
int setuid;
int setgid;
uid_t uid;
gid_t gid;
umode_t mode;
unsigned int max_ptys;
struct inode **inodes;
};
#define DEVPTS_SUPER_MAGIC 0x1cd1
#define DEVPTS_SBI_MAGIC 0x01da1d02
extern inline struct devpts_sb_info *SBI(struct super_block *sb)
{
return (struct devpts_sb_info *)(sb->u.generic_sbp);
}
extern struct inode_operations devpts_root_inode_operations;
extern struct file_operations devpts_root_operations;
...@@ -11,135 +11,70 @@ ...@@ -11,135 +11,70 @@
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kdev_t.h> #include <linux/fs.h>
#include <linux/kernel.h> #include <linux/sched.h>
#include <linux/major.h> #include <linux/namei.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/tty.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include "devpts_i.h" #define DEVPTS_SUPER_MAGIC 0x1cd1
static struct vfsmount *devpts_mnt; static struct vfsmount *devpts_mnt;
static struct dentry *devpts_root;
static void devpts_put_super(struct super_block *sb) static struct {
{ int setuid;
struct devpts_sb_info *sbi = SBI(sb); int setgid;
struct inode *inode; uid_t uid;
int i; gid_t gid;
umode_t mode;
} config = {mode: 0600};
for ( i = 0 ; i < sbi->max_ptys ; i++ ) { static int devpts_remount(struct super_block *sb, int *flags, char *data)
if ( (inode = sbi->inodes[i]) ) {
if ( atomic_read(&inode->i_count) != 1 )
printk("devpts_put_super: badness: entry %d count %d\n",
i, atomic_read(&inode->i_count));
inode->i_nlink--;
iput(inode);
}
}
kfree(sbi->inodes);
kfree(sbi);
}
static int devpts_remount (struct super_block * sb, int * flags, char * data);
static struct super_operations devpts_sops = {
put_super: devpts_put_super,
statfs: simple_statfs,
remount_fs: devpts_remount,
};
static int devpts_parse_options(char *options, struct devpts_sb_info *sbi)
{ {
int setuid = 0; int setuid = 0;
int setgid = 0; int setgid = 0;
uid_t uid = 0; uid_t uid = 0;
gid_t gid = 0; gid_t gid = 0;
umode_t mode = 0600; umode_t mode = 0600;
char *this_char, *value; char *this_char;
this_char = NULL; this_char = NULL;
while ((this_char = strsep(&options, ",")) != NULL) { while ((this_char = strsep(&data, ",")) != NULL) {
int n;
char dummy;
if (!*this_char) if (!*this_char)
continue; continue;
if ((value = strchr(this_char,'=')) != NULL) if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) {
*value++ = 0;
if (!strcmp(this_char,"uid")) {
if (!value || !*value)
return 1;
uid = simple_strtoul(value,&value,0);
if (*value)
return 1;
setuid = 1; setuid = 1;
} uid = n;
else if (!strcmp(this_char,"gid")) { } else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) {
if (!value || !*value)
return 1;
gid = simple_strtoul(value,&value,0);
if (*value)
return 1;
setgid = 1; setgid = 1;
gid = n;
} else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1)
mode = n & ~S_IFMT;
else {
printk("devpts: called with bogus options\n");
return -EINVAL;
} }
else if (!strcmp(this_char,"mode")) {
if (!value || !*value)
return 1;
mode = simple_strtoul(value,&value,8);
if (*value)
return 1;
}
else
return 1;
} }
sbi->setuid = setuid; config.setuid = setuid;
sbi->setgid = setgid; config.setgid = setgid;
sbi->uid = uid; config.uid = uid;
sbi->gid = gid; config.gid = gid;
sbi->mode = mode & ~S_IFMT; config.mode = mode;
return 0; return 0;
} }
static int devpts_remount(struct super_block * sb, int * flags, char * data) static struct super_operations devpts_sops = {
{ statfs: simple_statfs,
struct devpts_sb_info *sbi = sb->u.generic_sbp; remount_fs: devpts_remount,
int res = devpts_parse_options(data,sbi); };
if (res) {
printk("devpts: called with bogus options\n");
return -EINVAL;
}
return 0;
}
static int devpts_fill_super(struct super_block *s, void *data, int silent) static int devpts_fill_super(struct super_block *s, void *data, int silent)
{ {
int error = -ENOMEM;
struct inode * inode; struct inode * inode;
struct devpts_sb_info *sbi;
sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
if ( !sbi )
goto fail;
memset(sbi, 0, sizeof(*sbi));
sbi->magic = DEVPTS_SBI_MAGIC;
sbi->max_ptys = unix98_max_ptys;
sbi->inodes = kmalloc(sizeof(struct inode *) * sbi->max_ptys, GFP_KERNEL);
if ( !sbi->inodes )
goto fail_free;
memset(sbi->inodes, 0, sizeof(struct inode *) * sbi->max_ptys);
if ( devpts_parse_options(data,sbi) && !silent) {
error = -EINVAL;
printk("devpts: called with bogus options\n");
goto fail_free;
}
s->u.generic_sbp = (void *) sbi;
s->s_blocksize = 1024; s->s_blocksize = 1024;
s->s_blocksize_bits = 10; s->s_blocksize_bits = 10;
s->s_magic = DEVPTS_SUPER_MAGIC; s->s_magic = DEVPTS_SUPER_MAGIC;
...@@ -147,27 +82,25 @@ static int devpts_fill_super(struct super_block *s, void *data, int silent) ...@@ -147,27 +82,25 @@ static int devpts_fill_super(struct super_block *s, void *data, int silent)
inode = new_inode(s); inode = new_inode(s);
if (!inode) if (!inode)
goto fail_free; goto fail;
inode->i_ino = 1; inode->i_ino = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = 0; inode->i_blocks = 0;
inode->i_blksize = 1024; inode->i_blksize = 1024;
inode->i_uid = inode->i_gid = 0; inode->i_uid = inode->i_gid = 0;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &devpts_root_inode_operations; inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &devpts_root_operations; inode->i_fop = &simple_dir_operations;
inode->i_nlink = 2; inode->i_nlink = 2;
s->s_root = d_alloc_root(inode); devpts_root = s->s_root = d_alloc_root(inode);
if (s->s_root) if (s->s_root)
return 0; return 0;
printk("devpts: get root dentry failed\n"); printk("devpts: get root dentry failed\n");
iput(inode); iput(inode);
fail_free:
kfree(sbi);
fail: fail:
return error; return -ENOMEM;
} }
static struct super_block *devpts_get_sb(struct file_system_type *fs_type, static struct super_block *devpts_get_sb(struct file_system_type *fs_type,
...@@ -183,44 +116,52 @@ static struct file_system_type devpts_fs_type = { ...@@ -183,44 +116,52 @@ static struct file_system_type devpts_fs_type = {
kill_sb: kill_anon_super, kill_sb: kill_anon_super,
}; };
void devpts_pty_new(int number, kdev_t device) /*
* The normal naming convention is simply /dev/pts/<number>; this conforms
* to the System V naming convention
*/
static struct dentry *get_node(int num)
{ {
struct super_block *sb = devpts_mnt->mnt_sb; char s[10];
struct devpts_sb_info *sbi = SBI(sb); struct dentry *root = devpts_root;
struct inode *inode; down(&root->d_inode->i_sem);
return lookup_one_len(s, root, sprintf(s, "%d", num));
if ( sbi->inodes[number] ) }
return; /* Already registered, this does happen */
void devpts_pty_new(int number, dev_t device)
inode = new_inode(sb); {
struct dentry *dentry;
struct inode *inode = new_inode(devpts_mnt->mnt_sb);
if (!inode) if (!inode)
return; return;
inode->i_ino = number+2; inode->i_ino = number+2;
inode->i_blocks = 0;
inode->i_blksize = 1024; inode->i_blksize = 1024;
inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid; inode->i_uid = config.setuid ? config.uid : current->fsuid;
inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid; inode->i_gid = config.setgid ? config.gid : current->fsgid;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
init_special_inode(inode, S_IFCHR|sbi->mode, kdev_t_to_nr(device)); init_special_inode(inode, S_IFCHR|config.mode, device);
if ( sbi->inodes[number] ) { dentry = get_node(number);
iput(inode); if (!IS_ERR(dentry) && !dentry->d_inode)
return; d_instantiate(dentry, inode);
} up(&devpts_root->d_inode->i_sem);
sbi->inodes[number] = inode;
} }
void devpts_pty_kill(int number) void devpts_pty_kill(int number)
{ {
struct super_block *sb = devpts_mnt->mnt_sb; struct dentry *dentry = get_node(number);
struct devpts_sb_info *sbi = SBI(sb);
struct inode *inode = sbi->inodes[number];
if ( inode ) { if (!IS_ERR(dentry)) {
sbi->inodes[number] = NULL; struct inode *inode = dentry->d_inode;
inode->i_nlink--; if (inode) {
iput(inode); inode->i_nlink--;
d_delete(dentry);
dput(dentry);
}
dput(dentry);
} }
up(&devpts_root->d_inode->i_sem);
} }
static int __init init_devpts_fs(void) static int __init init_devpts_fs(void)
...@@ -231,22 +172,12 @@ static int __init init_devpts_fs(void) ...@@ -231,22 +172,12 @@ static int __init init_devpts_fs(void)
err = PTR_ERR(devpts_mnt); err = PTR_ERR(devpts_mnt);
if (!IS_ERR(devpts_mnt)) if (!IS_ERR(devpts_mnt))
err = 0; err = 0;
#ifdef MODULE
if ( !err ) {
devpts_upcall_new = devpts_pty_new;
devpts_upcall_kill = devpts_pty_kill;
}
#endif
} }
return err; return err;
} }
static void __exit exit_devpts_fs(void) static void __exit exit_devpts_fs(void)
{ {
#ifdef MODULE
devpts_upcall_new = NULL;
devpts_upcall_kill = NULL;
#endif
unregister_filesystem(&devpts_fs_type); unregister_filesystem(&devpts_fs_type);
kern_umount(devpts_mnt); kern_umount(devpts_mnt);
} }
...@@ -254,4 +185,3 @@ static void __exit exit_devpts_fs(void) ...@@ -254,4 +185,3 @@ static void __exit exit_devpts_fs(void)
module_init(init_devpts_fs) module_init(init_devpts_fs)
module_exit(exit_devpts_fs) module_exit(exit_devpts_fs)
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* -*- linux-c -*- --------------------------------------------------------- *
*
* linux/fs/devpts/root.c
*
* Copyright 1998 H. Peter Anvin -- All Rights Reserved
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
* option, any later version, incorporated herein by reference.
*
* ------------------------------------------------------------------------- */
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
#include "devpts_i.h"
static int devpts_root_readdir(struct file *,void *,filldir_t);
static struct dentry *devpts_root_lookup(struct inode *,struct dentry *);
static int devpts_revalidate(struct dentry *, int);
struct file_operations devpts_root_operations = {
read: generic_read_dir,
readdir: devpts_root_readdir,
};
struct inode_operations devpts_root_inode_operations = {
lookup: devpts_root_lookup,
};
static struct dentry_operations devpts_dentry_operations = {
d_revalidate: devpts_revalidate,
};
/*
* The normal naming convention is simply /dev/pts/<number>; this conforms
* to the System V naming convention
*/
#define genptsname(buf,num) sprintf(buf, "%d", num)
static int devpts_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct inode * inode = filp->f_dentry->d_inode;
struct devpts_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
off_t nr;
char numbuf[16];
lock_kernel();
nr = filp->f_pos;
switch(nr)
{
case 0:
if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
goto out;
filp->f_pos = ++nr;
/* fall through */
case 1:
if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
goto out;
filp->f_pos = ++nr;
/* fall through */
default:
while ( nr - 2 < sbi->max_ptys ) {
int ptynr = nr - 2;
if ( sbi->inodes[ptynr] ) {
genptsname(numbuf, ptynr);
if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_CHR) < 0 )
goto out;
}
filp->f_pos = ++nr;
}
break;
}
out:
unlock_kernel();
return 0;
}
/*
* Revalidate is called on every cache lookup. We use it to check that
* the pty really does still exist. Never revalidate negative dentries;
* for simplicity (fix later?)
*/
static int devpts_revalidate(struct dentry * dentry, int flags)
{
struct devpts_sb_info *sbi;
if ( !dentry->d_inode )
return 0;
sbi = SBI(dentry->d_inode->i_sb);
return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode );
}
static struct dentry *devpts_root_lookup(struct inode * dir, struct dentry * dentry)
{
struct devpts_sb_info *sbi = SBI(dir->i_sb);
unsigned int entry;
int i;
const char *p;
dentry->d_op = &devpts_dentry_operations;
if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) {
entry = 0;
} else if ( dentry->d_name.len < 1 ) {
return NULL;
} else {
p = dentry->d_name.name;
if ( *p < '1' || *p > '9' )
return NULL;
entry = *p++ - '0';
for ( i = dentry->d_name.len-1 ; i ; i-- ) {
unsigned int nentry = *p++ - '0';
if ( nentry > 9 )
return NULL;
if ( entry >= ~0U/10 )
return NULL;
entry = nentry + entry * 10;
}
}
if ( entry >= sbi->max_ptys )
return NULL;
lock_kernel();
if ( sbi->inodes[entry] )
atomic_inc(&sbi->inodes[entry]->i_count);
d_add(dentry, sbi->inodes[entry]);
unlock_kernel();
return NULL;
}
This diff is collapsed.
...@@ -30,8 +30,7 @@ ...@@ -30,8 +30,7 @@
* *
* The file system contains group descriptors which are located after the * The file system contains group descriptors which are located after the
* super block. Each descriptor contains the number of the bitmap block and * super block. Each descriptor contains the number of the bitmap block and
* the free blocks count in the block. The descriptors are loaded in memory * the free blocks count in the block.
* when a file system is mounted (see ext2_read_super).
*/ */
...@@ -41,8 +40,8 @@ ...@@ -41,8 +40,8 @@
* *
* Return buffer_head of bitmap on success or NULL. * Return buffer_head of bitmap on success or NULL.
*/ */
static struct buffer_head *read_inode_bitmap (struct super_block * sb, static struct buffer_head *
unsigned long block_group) read_inode_bitmap(struct super_block * sb, unsigned long block_group)
{ {
struct ext2_group_desc *desc; struct ext2_group_desc *desc;
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
...@@ -53,7 +52,7 @@ static struct buffer_head *read_inode_bitmap (struct super_block * sb, ...@@ -53,7 +52,7 @@ static struct buffer_head *read_inode_bitmap (struct super_block * sb,
bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap)); bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap));
if (!bh) if (!bh)
ext2_error (sb, "read_inode_bitmap", ext2_error(sb, "read_inode_bitmap",
"Cannot read inode bitmap - " "Cannot read inode bitmap - "
"block_group = %lu, inode_bitmap = %lu", "block_group = %lu, inode_bitmap = %lu",
block_group, (unsigned long) desc->bg_inode_bitmap); block_group, (unsigned long) desc->bg_inode_bitmap);
...@@ -61,75 +60,6 @@ static struct buffer_head *read_inode_bitmap (struct super_block * sb, ...@@ -61,75 +60,6 @@ static struct buffer_head *read_inode_bitmap (struct super_block * sb,
return bh; return bh;
} }
/*
* load_inode_bitmap loads the inode bitmap for a blocks group
*
* It maintains a cache for the last bitmaps loaded. This cache is managed
* with a LRU algorithm.
*
* Notes:
* 1/ There is one cache per mounted file system.
* 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
* this function reads the bitmap without maintaining a LRU cache.
*
* Return the buffer_head of the bitmap or the ERR_PTR(error)
*/
static struct buffer_head *load_inode_bitmap (struct super_block * sb,
unsigned int block_group)
{
int i, slot = 0;
struct ext2_sb_info *sbi = EXT2_SB(sb);
struct buffer_head *bh = sbi->s_inode_bitmap[0];
if (block_group >= sbi->s_groups_count)
ext2_panic (sb, "load_inode_bitmap",
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
block_group, sbi->s_groups_count);
if (sbi->s_loaded_inode_bitmaps > 0 &&
sbi->s_inode_bitmap_number[0] == block_group && bh)
goto found;
if (sbi->s_groups_count <= EXT2_MAX_GROUP_LOADED) {
slot = block_group;
bh = sbi->s_inode_bitmap[slot];
if (!bh)
goto read_it;
if (sbi->s_inode_bitmap_number[slot] == slot)
goto found;
ext2_panic (sb, "load_inode_bitmap",
"block_group != inode_bitmap_number");
}
bh = NULL;
for (i = 0; i < sbi->s_loaded_inode_bitmaps &&
sbi->s_inode_bitmap_number[i] != block_group;
i++)
;
if (i < sbi->s_loaded_inode_bitmaps)
bh = sbi->s_inode_bitmap[i];
else if (sbi->s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
sbi->s_loaded_inode_bitmaps++;
else
brelse (sbi->s_inode_bitmap[--i]);
while (i--) {
sbi->s_inode_bitmap_number[i+1] = sbi->s_inode_bitmap_number[i];
sbi->s_inode_bitmap[i+1] = sbi->s_inode_bitmap[i];
}
read_it:
if (!bh)
bh = read_inode_bitmap (sb, block_group);
sbi->s_inode_bitmap_number[slot] = block_group;
sbi->s_inode_bitmap[slot] = bh;
if (!bh)
return ERR_PTR(-EIO);
found:
return bh;
}
/* /*
* NOTE! When we get the inode, we're the only people * NOTE! When we get the inode, we're the only people
* that have access to it, and as such there are no * that have access to it, and as such there are no
...@@ -151,8 +81,8 @@ void ext2_free_inode (struct inode * inode) ...@@ -151,8 +81,8 @@ void ext2_free_inode (struct inode * inode)
struct super_block * sb = inode->i_sb; struct super_block * sb = inode->i_sb;
int is_directory; int is_directory;
unsigned long ino; unsigned long ino;
struct buffer_head * bh; struct buffer_head *bitmap_bh = NULL;
struct buffer_head * bh2; struct buffer_head *bh2;
unsigned long block_group; unsigned long block_group;
unsigned long bit; unsigned long bit;
struct ext2_group_desc * desc; struct ext2_group_desc * desc;
...@@ -186,12 +116,13 @@ void ext2_free_inode (struct inode * inode) ...@@ -186,12 +116,13 @@ void ext2_free_inode (struct inode * inode)
} }
block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb); block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb); bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb);
bh = load_inode_bitmap (sb, block_group); brelse(bitmap_bh);
if (IS_ERR(bh)) bitmap_bh = read_inode_bitmap(sb, block_group);
if (!bitmap_bh)
goto error_return; goto error_return;
/* Ok, now we can actually update the inode bitmaps.. */ /* Ok, now we can actually update the inode bitmaps.. */
if (!ext2_clear_bit (bit, bh->b_data)) if (!ext2_clear_bit(bit, bitmap_bh->b_data))
ext2_error (sb, "ext2_free_inode", ext2_error (sb, "ext2_free_inode",
"bit already cleared for inode %lu", ino); "bit already cleared for inode %lu", ino);
else { else {
...@@ -208,13 +139,14 @@ void ext2_free_inode (struct inode * inode) ...@@ -208,13 +139,14 @@ void ext2_free_inode (struct inode * inode)
cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1); cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
mark_buffer_dirty(EXT2_SB(sb)->s_sbh); mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
} }
mark_buffer_dirty(bh); mark_buffer_dirty(bitmap_bh);
if (sb->s_flags & MS_SYNCHRONOUS) { if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh); ll_rw_block(WRITE, 1, &bitmap_bh);
wait_on_buffer (bh); wait_on_buffer(bitmap_bh);
} }
sb->s_dirt = 1; sb->s_dirt = 1;
error_return: error_return:
brelse(bitmap_bh);
unlock_super (sb); unlock_super (sb);
} }
...@@ -351,9 +283,9 @@ static int find_group_other(struct super_block *sb, int parent_group) ...@@ -351,9 +283,9 @@ static int find_group_other(struct super_block *sb, int parent_group)
struct inode * ext2_new_inode(struct inode * dir, int mode) struct inode * ext2_new_inode(struct inode * dir, int mode)
{ {
struct super_block * sb; struct super_block *sb;
struct buffer_head * bh; struct buffer_head *bitmap_bh = NULL;
struct buffer_head * bh2; struct buffer_head *bh2;
int group, i; int group, i;
ino_t ino; ino_t ino;
struct inode * inode; struct inode * inode;
...@@ -361,6 +293,7 @@ struct inode * ext2_new_inode(struct inode * dir, int mode) ...@@ -361,6 +293,7 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
struct ext2_super_block * es; struct ext2_super_block * es;
struct ext2_inode_info *ei; struct ext2_inode_info *ei;
int err; int err;
struct inode *ret;
sb = dir->i_sb; sb = dir->i_sb;
inode = new_inode(sb); inode = new_inode(sb);
...@@ -381,20 +314,21 @@ struct inode * ext2_new_inode(struct inode * dir, int mode) ...@@ -381,20 +314,21 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
goto fail; goto fail;
err = -EIO; err = -EIO;
bh = load_inode_bitmap (sb, group); brelse(bitmap_bh);
if (IS_ERR(bh)) bitmap_bh = read_inode_bitmap(sb, group);
if (!bitmap_bh)
goto fail2; goto fail2;
i = ext2_find_first_zero_bit ((unsigned long *) bh->b_data, i = ext2_find_first_zero_bit((unsigned long *)bitmap_bh->b_data,
EXT2_INODES_PER_GROUP(sb)); EXT2_INODES_PER_GROUP(sb));
if (i >= EXT2_INODES_PER_GROUP(sb)) if (i >= EXT2_INODES_PER_GROUP(sb))
goto bad_count; goto bad_count;
ext2_set_bit (i, bh->b_data); ext2_set_bit(i, bitmap_bh->b_data);
mark_buffer_dirty(bh); mark_buffer_dirty(bitmap_bh);
if (sb->s_flags & MS_SYNCHRONOUS) { if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh); ll_rw_block(WRITE, 1, &bitmap_bh);
wait_on_buffer (bh); wait_on_buffer(bitmap_bh);
} }
ino = group * EXT2_INODES_PER_GROUP(sb) + i + 1; ino = group * EXT2_INODES_PER_GROUP(sb) + i + 1;
...@@ -452,17 +386,19 @@ struct inode * ext2_new_inode(struct inode * dir, int mode) ...@@ -452,17 +386,19 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
insert_inode_hash(inode); insert_inode_hash(inode);
mark_inode_dirty(inode); mark_inode_dirty(inode);
unlock_super (sb); unlock_super(sb);
ret = inode;
if(DQUOT_ALLOC_INODE(inode)) { if(DQUOT_ALLOC_INODE(inode)) {
DQUOT_DROP(inode); DQUOT_DROP(inode);
inode->i_flags |= S_NOQUOTA; inode->i_flags |= S_NOQUOTA;
inode->i_nlink = 0; inode->i_nlink = 0;
iput(inode); iput(inode);
return ERR_PTR(-EDQUOT); ret = ERR_PTR(-EDQUOT);
} else {
ext2_debug("allocating inode %lu\n", inode->i_ino);
ext2_preread_inode(inode);
} }
ext2_debug ("allocating inode %lu\n", inode->i_ino); goto out;
ext2_preread_inode(inode);
return inode;
fail2: fail2:
desc = ext2_get_group_desc (sb, group, &bh2); desc = ext2_get_group_desc (sb, group, &bh2);
...@@ -476,7 +412,8 @@ struct inode * ext2_new_inode(struct inode * dir, int mode) ...@@ -476,7 +412,8 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
unlock_super(sb); unlock_super(sb);
make_bad_inode(inode); make_bad_inode(inode);
iput(inode); iput(inode);
return ERR_PTR(err); ret = ERR_PTR(err);
goto out;
bad_count: bad_count:
ext2_error (sb, "ext2_new_inode", ext2_error (sb, "ext2_new_inode",
...@@ -491,6 +428,9 @@ struct inode * ext2_new_inode(struct inode * dir, int mode) ...@@ -491,6 +428,9 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
desc->bg_free_inodes_count = 0; desc->bg_free_inodes_count = 0;
mark_buffer_dirty(bh2); mark_buffer_dirty(bh2);
goto repeat; goto repeat;
out:
brelse(bitmap_bh);
return ret;
} }
unsigned long ext2_count_free_inodes (struct super_block * sb) unsigned long ext2_count_free_inodes (struct super_block * sb)
...@@ -498,30 +438,33 @@ unsigned long ext2_count_free_inodes (struct super_block * sb) ...@@ -498,30 +438,33 @@ unsigned long ext2_count_free_inodes (struct super_block * sb)
#ifdef EXT2FS_DEBUG #ifdef EXT2FS_DEBUG
struct ext2_super_block * es; struct ext2_super_block * es;
unsigned long desc_count = 0, bitmap_count = 0; unsigned long desc_count = 0, bitmap_count = 0;
struct buffer_head *bitmap_bh = NULL;
int i; int i;
lock_super (sb); lock_super (sb);
es = EXT2_SB(sb)->s_es; es = EXT2_SB(sb)->s_es;
for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) { for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {
struct ext2_group_desc *desc = ext2_get_group_desc (sb, i, NULL); struct ext2_group_desc *desc;
struct buffer_head *bh;
unsigned x; unsigned x;
desc = ext2_get_group_desc (sb, i, NULL);
if (!desc) if (!desc)
continue; continue;
desc_count += le16_to_cpu(desc->bg_free_inodes_count); desc_count += le16_to_cpu(desc->bg_free_inodes_count);
bh = load_inode_bitmap (sb, i); brelse(bitmap_bh);
if (IS_ERR(bh)) bitmap_bh = read_inode_bitmap(sb, i);
if (!bitmap_bh)
continue; continue;
x = ext2_count_free (bh, EXT2_INODES_PER_GROUP(sb) / 8); x = ext2_count_free(bitmap_bh, EXT2_INODES_PER_GROUP(sb) / 8);
printk ("group %d: stored = %d, counted = %lu\n", printk ("group %d: stored = %d, counted = %lu\n",
i, le16_to_cpu(desc->bg_free_inodes_count), x); i, le16_to_cpu(desc->bg_free_inodes_count), x);
bitmap_count += x; bitmap_count += x;
} }
brelse(bitmap_bh);
printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n", printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count); le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
unlock_super (sb); unlock_super(sb);
return desc_count; return desc_count;
#else #else
return le32_to_cpu(EXT2_SB(sb)->s_es->s_free_inodes_count); return le32_to_cpu(EXT2_SB(sb)->s_es->s_free_inodes_count);
...@@ -534,21 +477,23 @@ void ext2_check_inodes_bitmap (struct super_block * sb) ...@@ -534,21 +477,23 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
{ {
struct ext2_super_block * es = EXT2_SB(sb)->s_es; struct ext2_super_block * es = EXT2_SB(sb)->s_es;
unsigned long desc_count = 0, bitmap_count = 0; unsigned long desc_count = 0, bitmap_count = 0;
struct buffer_head *bitmap_bh = NULL;
int i; int i;
for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) { for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {
struct ext2_group_desc *desc = ext2_get_group_desc(sb, i, NULL); struct ext2_group_desc *desc;
struct buffer_head *bh;
unsigned x; unsigned x;
desc = ext2_get_group_desc(sb, i, NULL);
if (!desc) if (!desc)
continue; continue;
desc_count += le16_to_cpu(desc->bg_free_inodes_count); desc_count += le16_to_cpu(desc->bg_free_inodes_count);
bh = load_inode_bitmap (sb, i); brelse(bitmap_bh);
if (IS_ERR(bh)) bitmap_bh = read_inode_bitmap(sb, i);
if (!bitmap_bh)
continue; continue;
x = ext2_count_free (bh, EXT2_INODES_PER_GROUP(sb) / 8); x = ext2_count_free(bitmap_bh, EXT2_INODES_PER_GROUP(sb) / 8);
if (le16_to_cpu(desc->bg_free_inodes_count) != x) if (le16_to_cpu(desc->bg_free_inodes_count) != x)
ext2_error (sb, "ext2_check_inodes_bitmap", ext2_error (sb, "ext2_check_inodes_bitmap",
"Wrong free inodes count in group %d, " "Wrong free inodes count in group %d, "
...@@ -556,8 +501,9 @@ void ext2_check_inodes_bitmap (struct super_block * sb) ...@@ -556,8 +501,9 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
le16_to_cpu(desc->bg_free_inodes_count), x); le16_to_cpu(desc->bg_free_inodes_count), x);
bitmap_count += x; bitmap_count += x;
} }
brelse(bitmap_bh);
if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count) if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count)
ext2_error (sb, "ext2_check_inodes_bitmap", ext2_error(sb, "ext2_check_inodes_bitmap",
"Wrong free inodes count in super block, " "Wrong free inodes count in super block, "
"stored = %lu, counted = %lu", "stored = %lu, counted = %lu",
(unsigned long)le32_to_cpu(es->s_free_inodes_count), (unsigned long)le32_to_cpu(es->s_free_inodes_count),
......
...@@ -142,12 +142,6 @@ static void ext2_put_super (struct super_block * sb) ...@@ -142,12 +142,6 @@ static void ext2_put_super (struct super_block * sb)
if (sbi->s_group_desc[i]) if (sbi->s_group_desc[i])
brelse (sbi->s_group_desc[i]); brelse (sbi->s_group_desc[i]);
kfree(sbi->s_group_desc); kfree(sbi->s_group_desc);
for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
if (sbi->s_inode_bitmap[i])
brelse (sbi->s_inode_bitmap[i]);
for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
if (sbi->s_block_bitmap[i])
brelse (sbi->s_block_bitmap[i]);
brelse (sbi->s_sbh); brelse (sbi->s_sbh);
sb->u.generic_sbp = NULL; sb->u.generic_sbp = NULL;
kfree(sbi); kfree(sbi);
...@@ -686,14 +680,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) ...@@ -686,14 +680,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
db_count = i; db_count = i;
goto failed_mount2; goto failed_mount2;
} }
for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
sbi->s_inode_bitmap_number[i] = 0;
sbi->s_inode_bitmap[i] = NULL;
sbi->s_block_bitmap_number[i] = 0;
sbi->s_block_bitmap[i] = NULL;
}
sbi->s_loaded_inode_bitmaps = 0;
sbi->s_loaded_block_bitmaps = 0;
sbi->s_gdb_count = db_count; sbi->s_gdb_count = db_count;
get_random_bytes(&sbi->s_next_generation, sizeof(u32)); get_random_bytes(&sbi->s_next_generation, sizeof(u32));
/* /*
......
This diff is collapsed.
This diff is collapsed.
...@@ -1632,8 +1632,10 @@ ext3_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh, ...@@ -1632,8 +1632,10 @@ ext3_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh,
} }
ext3_mark_inode_dirty(handle, inode); ext3_mark_inode_dirty(handle, inode);
ext3_journal_test_restart(handle, inode); ext3_journal_test_restart(handle, inode);
BUFFER_TRACE(bh, "get_write_access"); if (bh) {
ext3_journal_get_write_access(handle, bh); BUFFER_TRACE(bh, "retaking write access");
ext3_journal_get_write_access(handle, bh);
}
} }
/* /*
......
...@@ -417,10 +417,6 @@ void ext3_put_super (struct super_block * sb) ...@@ -417,10 +417,6 @@ void ext3_put_super (struct super_block * sb)
for (i = 0; i < sbi->s_gdb_count; i++) for (i = 0; i < sbi->s_gdb_count; i++)
brelse(sbi->s_group_desc[i]); brelse(sbi->s_group_desc[i]);
kfree(sbi->s_group_desc); kfree(sbi->s_group_desc);
for (i = 0; i < EXT3_MAX_GROUP_LOADED; i++)
brelse(sbi->s_inode_bitmap[i]);
for (i = 0; i < EXT3_MAX_GROUP_LOADED; i++)
brelse(sbi->s_block_bitmap[i]);
brelse(sbi->s_sbh); brelse(sbi->s_sbh);
/* Debugging code just in case the in-memory inode orphan list /* Debugging code just in case the in-memory inode orphan list
...@@ -1150,14 +1146,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -1150,14 +1146,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
printk (KERN_ERR "EXT3-fs: group descriptors corrupted !\n"); printk (KERN_ERR "EXT3-fs: group descriptors corrupted !\n");
goto failed_mount2; goto failed_mount2;
} }
for (i = 0; i < EXT3_MAX_GROUP_LOADED; i++) {
sbi->s_inode_bitmap_number[i] = 0;
sbi->s_inode_bitmap[i] = NULL;
sbi->s_block_bitmap_number[i] = 0;
sbi->s_block_bitmap[i] = NULL;
}
sbi->s_loaded_inode_bitmaps = 0;
sbi->s_loaded_block_bitmaps = 0;
sbi->s_gdb_count = db_count; sbi->s_gdb_count = db_count;
/* /*
* set up enough so that it can read an inode * set up enough so that it can read an inode
......
...@@ -245,6 +245,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) ...@@ -245,6 +245,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
} }
if (arg & O_DIRECT) { if (arg & O_DIRECT) {
if (inode->i_mapping && inode->i_mapping->a_ops) {
if (!inode->i_mapping->a_ops->direct_IO)
return -EINVAL;
}
/* /*
* alloc_kiovec() can sleep and we are only serialized by * alloc_kiovec() can sleep and we are only serialized by
* the big kernel lock here, so abuse the i_sem to serialize * the big kernel lock here, so abuse the i_sem to serialize
......
This diff is collapsed.
...@@ -101,7 +101,7 @@ static struct inode *alloc_inode(struct super_block *sb) ...@@ -101,7 +101,7 @@ static struct inode *alloc_inode(struct super_block *sb)
struct address_space * const mapping = &inode->i_data; struct address_space * const mapping = &inode->i_data;
inode->i_sb = sb; inode->i_sb = sb;
inode->i_dev = to_kdev_t(sb->s_dev); inode->i_dev = sb->s_dev;
inode->i_blkbits = sb->s_blocksize_bits; inode->i_blkbits = sb->s_blocksize_bits;
inode->i_flags = 0; inode->i_flags = 0;
atomic_set(&inode->i_count, 1); atomic_set(&inode->i_count, 1);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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