From 3132fdcb2d8590098732317f3dbe2718c3506cfd Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 20 Apr 2003 00:14:34 -0700 Subject: Interrupt handlers should return whether the interrupt was for them or not, so that the irq subsystem can properly handle screaming shared interrupts. So change the irq handlers to return a "irqretval_t", which is either IRQ_HANDLED or IRQ_NONE. --- include/linux/ide.h | 2 +- include/linux/interrupt.h | 27 +++++++++++++++++++++++++-- include/linux/irq.h | 1 - 3 files changed, 26 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/ide.h b/include/linux/ide.h index 1e678d06373b..a06f01033584 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1568,7 +1568,7 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); extern int ide_spin_wait_hwgroup(ide_drive_t *); extern void ide_timer_expiry(unsigned long); -extern void ide_intr(int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t ide_intr(int irq, void *dev_id, struct pt_regs *regs); extern void do_ide_request(request_queue_t *); extern void ide_init_subdrivers(void); diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 78969bb60521..0c489083d7c7 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -11,8 +11,30 @@ #include #include +/* + * For 2.4.x compatibility, 2.4.x can use + * + * typedef void irqreturn_t; + * #define IRQ_NONE + * #define IRQ_HANDLED + * #define IRQ_RETVAL(x) + * + * To mix old-style and new-style irq handler returns. + * + * IRQ_NONE means we didn't handle it. + * IRQ_HANDLED means that we did have a valid interrupt and handled it. + * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled) + */ +typedef struct irqreturn { + unsigned int val; +} irqreturn_t; + +#define IRQ_NONE ((struct irqreturn) { 0 }) +#define IRQ_HANDLED ((struct irqreturn) { 1 }) +#define IRQ_RETVAL(x) ((struct irqreturn) { (x) != 0 }) + struct irqaction { - void (*handler)(int, void *, struct pt_regs *); + irqreturn_t (*handler)(int, void *, struct pt_regs *); unsigned long flags; unsigned long mask; const char *name; @@ -20,8 +42,9 @@ struct irqaction { struct irqaction *next; }; +extern irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs); extern int request_irq(unsigned int, - void (*handler)(int, void *, struct pt_regs *), + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long, const char *, void *); extern void free_irq(unsigned int, void *); diff --git a/include/linux/irq.h b/include/linux/irq.h index 2791f0edbf57..c9bb7be100f3 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -72,7 +72,6 @@ extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); extern int setup_irq(unsigned int , struct irqaction * ); extern hw_irq_controller no_irq_type; /* needed in every arch ? */ -extern void no_action(int cpl, void *dev_id, struct pt_regs *regs); #endif -- cgit v1.2.3 From 0e3efbd1ebf9b6f6b16cd5b68465f02dbe72dff0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:26:14 -0700 Subject: [PATCH] Fix and clean up DCACHE_REFERENCED usage From: Maneesh Soni This patch changes the way DCACHE_REFERENCED flag is used. It got messed up in dcache_rcu iterations. I hope this will be ok now. The flag was meant to be advisory flag which is used while prune_dcache() so as not to free dentries which have recently entered d_lru list. At first pass in prune_dcache the dentries marked DCACHE_REFERENCED are left with the flag reset. and they are freed in the next pass. So, now we mark the dentry as DCACHE_REFERENCED when it is first entering the d_lru list in dput() and resetthe flag in prune_dcache(). If the flag remains reset in the next call to prune_dcache(), the dentry is then freed. Also I don't think any file system have to use this flag as it is taken care by the dcache layer. The patch removes such code from a few of file systems. Moreover these filesystems were anyway doing worng thing as they were changing the flag out of dcache_lock. Changes: o dput() marks dentry DCACHE_REFERENCED when it is added to the dentry_unused list o no need to set the flag in dget, dget_locked, d_lookup as these guys anyway increments the ref count. o check the ref count in prune_dcache and use DCACHE_REFERENCED flag just for two stage aging. o remove code for setting DACACHE_REFERENCED from reiserfs, fat, xfs and exportfs. --- fs/dcache.c | 20 ++++++++------------ fs/exportfs/expfs.c | 3 --- fs/fat/inode.c | 1 - fs/reiserfs/inode.c | 1 - fs/xfs/linux/xfs_super.c | 1 - include/linux/dcache.h | 1 - 6 files changed, 8 insertions(+), 19 deletions(-) (limited to 'include/linux') diff --git a/fs/dcache.c b/fs/dcache.c index 59480fedd61a..9eec20e0ab20 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -155,12 +155,11 @@ repeat: if (d_unhashed(dentry)) goto kill_it; if (list_empty(&dentry->d_lru)) { - dentry->d_vfs_flags &= ~DCACHE_REFERENCED; + dentry->d_vfs_flags |= DCACHE_REFERENCED; list_add(&dentry->d_lru, &dentry_unused); dentry_stat.nr_unused++; } spin_unlock(&dentry->d_lock); - dentry->d_vfs_flags |= DCACHE_REFERENCED; spin_unlock(&dcache_lock); return; @@ -250,7 +249,6 @@ int d_invalidate(struct dentry * dentry) static inline struct dentry * __dget_locked(struct dentry *dentry) { atomic_inc(&dentry->d_count); - dentry->d_vfs_flags |= DCACHE_REFERENCED; if (atomic_read(&dentry->d_count) == 1) { dentry_stat.nr_unused--; list_del_init(&dentry->d_lru); @@ -379,17 +377,16 @@ static void prune_dcache(int count) dentry = list_entry(tmp, struct dentry, d_lru); spin_lock(&dentry->d_lock); + /* leave inuse dentries */ + if (atomic_read(&dentry->d_count)) { + spin_unlock(&dentry->d_lock); + continue; + } /* If the dentry was recently referenced, don't free it. */ if (dentry->d_vfs_flags & DCACHE_REFERENCED) { dentry->d_vfs_flags &= ~DCACHE_REFERENCED; - - /* don't add non zero d_count dentries - * back to d_lru list - */ - if (!atomic_read(&dentry->d_count)) { - list_add(&dentry->d_lru, &dentry_unused); - dentry_stat.nr_unused++; - } + list_add(&dentry->d_lru, &dentry_unused); + dentry_stat.nr_unused++; spin_unlock(&dentry->d_lock); continue; } @@ -1027,7 +1024,6 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) if (likely(move_count == dentry->d_move_count)) { if (!d_unhashed(dentry)) { atomic_inc(&dentry->d_count); - dentry->d_vfs_flags |= DCACHE_REFERENCED; found = dentry; } } diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 7264433b25fd..aae953bb9572 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -91,7 +91,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, if (dentry != result && acceptable(context, dentry)) { dput(result); - dentry->d_vfs_flags |= DCACHE_REFERENCED; return dentry; } spin_lock(&dcache_lock); @@ -271,7 +270,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, if (dentry != result && acceptable(context, dentry)) { dput(result); - dentry->d_vfs_flags |= DCACHE_REFERENCED; return dentry; } spin_lock(&dcache_lock); @@ -434,7 +432,6 @@ static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u iput(inode); return ERR_PTR(-ENOMEM); } - result->d_vfs_flags |= DCACHE_REFERENCED; return result; } diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 67548b28113d..866edb62fad5 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -608,7 +608,6 @@ struct dentry *fat_get_dentry(struct super_block *sb, void *inump) return ERR_PTR(-ENOMEM); } result->d_op = sb->s_root->d_op; - result->d_vfs_flags |= DCACHE_REFERENCED; return result; } diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 0536716aa84e..fb7f27f1f532 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1260,7 +1260,6 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp) iput(inode); return ERR_PTR(-ENOMEM); } - result->d_vfs_flags |= DCACHE_REFERENCED; return result; } diff --git a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c index 662a43c90a1e..73ef4ec19e95 100644 --- a/fs/xfs/linux/xfs_super.c +++ b/fs/xfs/linux/xfs_super.c @@ -741,7 +741,6 @@ linvfs_get_dentry( iput(inode); return ERR_PTR(-ENOMEM); } - result->d_vfs_flags |= DCACHE_REFERENCED; return result; } diff --git a/include/linux/dcache.h b/include/linux/dcache.h index db979c3cf890..78fafd500123 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -270,7 +270,6 @@ static inline struct dentry *dget(struct dentry *dentry) if (!atomic_read(&dentry->d_count)) BUG(); atomic_inc(&dentry->d_count); - dentry->d_vfs_flags |= DCACHE_REFERENCED; } return dentry; } -- cgit v1.2.3 From 2f98681fa42f8971f09ca96ce6329fa3a3ff0740 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:26:21 -0700 Subject: [PATCH] Fix POSIX timers to give CLOCK_MONOTONIC full The POSIX CLOCK_MONOTONIC currently has only 1/HZ resolution. Further, it is tied to jiffies (i.e. is a restatment of jiffies) rather than "xtime" or the gettimeofday() clock. This patch changes CLOCK_MONOTONIC to be a restatment of gettimeofday() plus an offset to remove any clock setting activity from CLOCK_MONOTONIC. An offset is kept that represents the difference between CLOCK_MONOTONIC and gettimeofday(). This offset is updated when ever the gettimeofday() clock is set to back the clock setting change out of CLOCK_MONOTONIC (which by the standard, can not be set). With this change CLOCK_REALTIME (a direct restatement of gettimeofday()), CLOCK_MONOTONIC and gettimeofday() will all tick at the same time and with the same rate. And all will be affected by NTP adjustments (save those which actually set the time). --- arch/i386/kernel/time.c | 23 +++++- include/linux/time.h | 4 + kernel/posix-timers.c | 190 ++++++++++++++++++++++++++++-------------------- kernel/timer.c | 12 ++- 4 files changed, 146 insertions(+), 83 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index ab0f09bfe3d1..f5e9bf60dbb0 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -124,15 +124,28 @@ void do_settimeofday(struct timeval *tv) * made, and then undo it! */ tv->tv_usec -= timer->get_offset(); - tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); + tv->tv_usec -= (jiffies - wall_jiffies) * (USEC_PER_SEC / HZ); while (tv->tv_usec < 0) { - tv->tv_usec += 1000000; + tv->tv_usec += USEC_PER_SEC; tv->tv_sec--; } + tv->tv_usec *= NSEC_PER_USEC; + + wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec; + wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_usec; + + if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) { + wall_to_monotonic.tv_nsec -= NSEC_PER_SEC; + wall_to_monotonic.tv_sec++; + } + if (wall_to_monotonic.tv_nsec < 0) { + wall_to_monotonic.tv_nsec += NSEC_PER_SEC; + wall_to_monotonic.tv_sec--; + } xtime.tv_sec = tv->tv_sec; - xtime.tv_nsec = (tv->tv_usec * 1000); + xtime.tv_nsec = tv->tv_usec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; @@ -322,7 +335,9 @@ void __init time_init(void) { xtime.tv_sec = get_cmos_time(); - xtime.tv_nsec = 0; + wall_to_monotonic.tv_sec = -xtime.tv_sec + INITIAL_JIFFIES / HZ; + xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); + wall_to_monotonic.tv_nsec = 0; timer = select_timer(); diff --git a/include/linux/time.h b/include/linux/time.h index 4d7238025fe9..6fad88e1a37d 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -140,6 +140,7 @@ mktime (unsigned int year, unsigned int mon, } extern struct timespec xtime; +extern struct timespec wall_to_monotonic; extern seqlock_t xtime_lock; static inline unsigned long get_seconds(void) @@ -200,6 +201,9 @@ struct itimerval { #define CLOCK_MONOTONIC_HR 5 #define MAX_CLOCKS 6 +#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC | \ + CLOCK_REALTIME_HR | CLOCK_MONOTONIC_HR) +#define CLOCKS_MONO (CLOCK_MONOTONIC & CLOCK_MONOTONIC_HR) /* * The various flags for setting POSIX.1b interval timers. diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 54fe15f5c0b3..a0a972ec7742 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -48,7 +48,7 @@ * The idr_get_new *may* call slab for more memory so it must not be * called under a spin lock. Likewise idr_remore may release memory * (but it may be ok to do this under a lock...). - * idr_find is just a memory look up and is quite fast. A zero return + * idr_find is just a memory look up and is quite fast. A -1 return * indicates that the requested id does not exist. */ @@ -82,6 +82,7 @@ static spinlock_t idr_lock = SPIN_LOCK_UNLOCKED; * For some reason mips/mips64 define the SIGEV constants plus 128. * Here we define a mask to get rid of the common bits. The * optimizer should make this costless to all but mips. + * Note that no common bits (the non-mips case) will give 0xffffffff. */ #define MIPS_SIGEV ~(SIGEV_NONE & \ SIGEV_SIGNAL & \ @@ -93,7 +94,7 @@ static spinlock_t idr_lock = SPIN_LOCK_UNLOCKED; * The timer ID is turned into a timer address by idr_find(). * Verifying a valid ID consists of: * - * a) checking that idr_find() returns other than zero. + * a) checking that idr_find() returns other than -1. * b) checking that the timer id matches the one in the timer itself. * c) that the timer owner is in the callers thread group. */ @@ -162,6 +163,8 @@ static struct k_clock posix_clocks[MAX_CLOCKS]; void register_posix_clock(int clock_id, struct k_clock *new_clock); static int do_posix_gettime(struct k_clock *clock, struct timespec *tp); +static u64 do_posix_clock_monotonic_gettime_parts( + struct timespec *tp, struct timespec *mo); int do_posix_clock_monotonic_gettime(struct timespec *tp); int do_posix_clock_monotonic_settime(struct timespec *tp); static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags); @@ -192,7 +195,7 @@ __initcall(init_posix_timers); static void tstojiffie(struct timespec *tp, int res, u64 *jiff) { - unsigned long sec = tp->tv_sec; + long sec = tp->tv_sec; long nsec = tp->tv_nsec + res - 1; if (nsec > NSEC_PER_SEC) { @@ -210,7 +213,7 @@ static void tstojiffie(struct timespec *tp, int res, u64 *jiff) * below. Here it is enough to just discard the high order * bits. */ - *jiff = (u64)sec * HZ; + *jiff = (s64)sec * HZ; /* * Do the res thing. (Don't forget the add in the declaration of nsec) */ @@ -221,17 +224,6 @@ static void tstojiffie(struct timespec *tp, int res, u64 *jiff) *jiff += nsec / (NSEC_PER_SEC / HZ); } -static void tstotimer(struct itimerspec *time, struct k_itimer *timer) -{ - u64 result; - int res = posix_clocks[timer->it_clock].res; - - tstojiffie(&time->it_value, res, &result); - timer->it_timer.expires = (unsigned long)result; - tstojiffie(&time->it_interval, res, &result); - timer->it_incr = (unsigned long)result; -} - static void schedule_next_timer(struct k_itimer *timr) { struct now_struct now; @@ -690,57 +682,81 @@ sys_timer_getoverrun(timer_t timer_id) * If it is relative time, we need to add the current (CLOCK_MONOTONIC) * time to it to get the proper time for the timer. */ -static int adjust_abs_time(struct k_clock *clock, struct timespec *tp, int abs) +static int adjust_abs_time(struct k_clock *clock, struct timespec *tp, + int abs, u64 *exp) { struct timespec now; - struct timespec oc; - do_posix_clock_monotonic_gettime(&now); - - if (!abs || (posix_clocks[CLOCK_MONOTONIC].clock_get != - clock->clock_get)) { - if (abs) - do_posix_gettime(clock, &oc); - else - oc.tv_nsec = oc.tv_sec = 0; - - tp->tv_sec += now.tv_sec - oc.tv_sec; - tp->tv_nsec += now.tv_nsec - oc.tv_nsec; + struct timespec oc = *tp; + struct timespec wall_to_mono; + u64 jiffies_64_f; + int rtn =0; + if (abs) { + /* + * The mask pick up the 4 basic clocks + */ + if (!(clock - &posix_clocks[0]) & ~CLOCKS_MASK) { + jiffies_64_f = do_posix_clock_monotonic_gettime_parts( + &now, &wall_to_mono); + /* + * If we are doing a MONOTONIC clock + */ + if((clock - &posix_clocks[0]) & CLOCKS_MONO){ + now.tv_sec += wall_to_mono.tv_sec; + now.tv_nsec += wall_to_mono.tv_nsec; + } + } else { + /* + * Not one of the basic clocks + */ + do_posix_gettime(clock, &now); + jiffies_64_f = get_jiffies_64(); + } + /* + * Take away now to get delta + */ + oc.tv_sec -= now.tv_sec; + oc.tv_nsec -= now.tv_nsec; /* * Normalize... */ - if ((tp->tv_nsec - NSEC_PER_SEC) >= 0) { - tp->tv_nsec -= NSEC_PER_SEC; - tp->tv_sec++; + while ((oc.tv_nsec - NSEC_PER_SEC) >= 0) { + oc.tv_nsec -= NSEC_PER_SEC; + oc.tv_sec++; } - if ((tp->tv_nsec) < 0) { - tp->tv_nsec += NSEC_PER_SEC; - tp->tv_sec--; + while ((oc.tv_nsec) < 0) { + oc.tv_nsec += NSEC_PER_SEC; + oc.tv_sec--; } + }else{ + jiffies_64_f = get_jiffies_64(); } /* - * Check if the requested time is prior to now (if so set now) or - * is more than the timer code can handle (if so we error out). - * The (unsigned) catches the case of prior to "now" with the same - * test. Only on failure do we sort out what happened, and then - * we use the (unsigned) to error out negative seconds. + * Check if the requested time is prior to now (if so set now) */ - if ((unsigned) (tp->tv_sec - now.tv_sec) > (MAX_JIFFY_OFFSET / HZ)) { - if ((unsigned) tp->tv_sec < now.tv_sec) { - tp->tv_sec = now.tv_sec; - tp->tv_nsec = now.tv_nsec; - } else + if (oc.tv_sec < 0) + oc.tv_sec = oc.tv_nsec = 0; + tstojiffie(&oc, clock->res, exp); + + /* + * Check if the requested time is more than the timer code + * can handle (if so we error out but return the value too). + */ + if (*exp > ((u64)MAX_JIFFY_OFFSET)) /* * This is a considered response, not exactly in * line with the standard (in fact it is silent on - * possible overflows). We assume such a large + * possible overflows). We assume such a large * value is ALMOST always a programming error and * try not to compound it by setting a really dumb * value. */ - return -EINVAL; - } - return 0; + rtn = -EINVAL; + /* + * return the actual jiffies expire time, full 64 bits + */ + *exp += jiffies_64_f; + return rtn; } /* Set a POSIX.1b interval timer. */ @@ -750,6 +766,7 @@ do_timer_settime(struct k_itimer *timr, int flags, struct itimerspec *new_setting, struct itimerspec *old_setting) { struct k_clock *clock = &posix_clocks[timr->it_clock]; + u64 expire_64; if (old_setting) do_timer_gettime(timr, old_setting); @@ -788,14 +805,15 @@ do_timer_settime(struct k_itimer *timr, int flags, return 0; } - if ((flags & TIMER_ABSTIME) && - (clock->clock_get != do_posix_clock_monotonic_gettime)) - // FIXME: what is this? - ; if (adjust_abs_time(clock, - &new_setting->it_value, flags & TIMER_ABSTIME)) + &new_setting->it_value, flags & TIMER_ABSTIME, + &expire_64)) { return -EINVAL; - tstotimer(new_setting, timr); + } + timr->it_timer.expires = (unsigned long)expire_64; + tstojiffie(&new_setting->it_interval, clock->res, &expire_64); + timr->it_incr = (unsigned long)expire_64; + /* * For some reason the timer does not fire immediately if expires is @@ -964,30 +982,46 @@ static int do_posix_gettime(struct k_clock *clock, struct timespec *tp) * Note also that the while loop assures that the sub_jiff_offset * will be less than a jiffie, thus no need to normalize the result. * Well, not really, if called with ints off :( - * - * HELP, this code should make an attempt at resolution beyond the - * jiffie. Trouble is this is "arch" dependent... */ -int do_posix_clock_monotonic_gettime(struct timespec *tp) +static u64 do_posix_clock_monotonic_gettime_parts( + struct timespec *tp, struct timespec *mo) { - long sub_sec; - u64 jiffies_64_f; - -#if (BITS_PER_LONG > 32) - jiffies_64_f = jiffies_64; -#else + u64 jiff; + struct timeval tpv; unsigned int seq; do { seq = read_seqbegin(&xtime_lock); - jiffies_64_f = jiffies_64; + do_gettimeofday(&tpv); + *mo = wall_to_monotonic; + jiff = jiffies_64; - } while (read_seqretry(&xtime_lock, seq)); -#endif - tp->tv_sec = div_long_long_rem(jiffies_64_f, HZ, &sub_sec); - tp->tv_nsec = sub_sec * (NSEC_PER_SEC / HZ); + } while(read_seqretry(&xtime_lock, seq)); + /* + * Love to get this before it is converted to usec. + * It would save a div AND a mpy. + */ + tp->tv_sec = tpv.tv_sec; + tp->tv_nsec = tpv.tv_usec * NSEC_PER_USEC; + + return jiff; +} + +int do_posix_clock_monotonic_gettime(struct timespec *tp) +{ + struct timespec wall_to_mono; + + do_posix_clock_monotonic_gettime_parts(tp, &wall_to_mono); + + tp->tv_sec += wall_to_mono.tv_sec; + tp->tv_nsec += wall_to_mono.tv_nsec; + + if ((tp->tv_nsec - NSEC_PER_SEC) > 0) { + tp->tv_nsec -= NSEC_PER_SEC; + tp->tv_sec++; + } return 0; } @@ -1138,7 +1172,7 @@ do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave) struct timespec t; struct timer_list new_timer; DECLARE_WAITQUEUE(abs_wqueue, current); - u64 rq_time = 0; + u64 rq_time = (u64)0; s64 left; int abs; struct restart_block *restart_block = @@ -1163,7 +1197,7 @@ do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave) if (!rq_time) return -EINTR; left = rq_time - get_jiffies_64(); - if (left <= 0LL) + if (left <= (s64)0) return 0; /* Already passed */ } @@ -1174,14 +1208,14 @@ do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave) do { t = *tsave; if (abs || !rq_time) { - adjust_abs_time(&posix_clocks[which_clock], &t, abs); - tstojiffie(&t, posix_clocks[which_clock].res, &rq_time); + adjust_abs_time(&posix_clocks[which_clock], &t, abs, + &rq_time); } left = rq_time - get_jiffies_64(); - if (left >= MAX_JIFFY_OFFSET) - left = MAX_JIFFY_OFFSET; - if (left < 0) + if (left >= (s64)MAX_JIFFY_OFFSET) + left = (s64)MAX_JIFFY_OFFSET; + if (left < (s64)0) break; new_timer.expires = jiffies + left; @@ -1192,12 +1226,12 @@ do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave) del_timer_sync(&new_timer); left = rq_time - get_jiffies_64(); - } while (left > 0 && !test_thread_flag(TIF_SIGPENDING)); + } while (left > (s64)0 && !test_thread_flag(TIF_SIGPENDING)); if (abs_wqueue.task_list.next) finish_wait(&nanosleep_abs_wqueue, &abs_wqueue); - if (left > 0) { + if (left > (s64)0) { unsigned long rmd; /* diff --git a/kernel/timer.c b/kernel/timer.c index 4aaf025ee8ba..caa37716f860 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -441,8 +441,16 @@ repeat: unsigned long tick_usec = TICK_USEC; /* ACTHZ period (usec) */ unsigned long tick_nsec = TICK_NSEC(TICK_USEC); /* USER_HZ period (nsec) */ -/* The current time */ +/* + * The current time + * wall_to_monotonic is what we need to add to xtime (or xtime corrected + * for sub jiffie times) to get to monotonic time. Monotonic is pegged at zero + * at zero at system boot time, so wall_to_monotonic will be negative, + * however, we will ALWAYS keep the tv_nsec part positive so we can use + * the usual normalization. + */ struct timespec xtime __attribute__ ((aligned (16))); +struct timespec wall_to_monotonic __attribute__ ((aligned (16))); /* Don't completely fail for HZ > 500. */ int tickadj = 500/HZ ? : 1; /* microsecs */ @@ -508,6 +516,7 @@ static void second_overflow(void) case TIME_INS: if (xtime.tv_sec % 86400 == 0) { xtime.tv_sec--; + wall_to_monotonic.tv_sec++; time_state = TIME_OOP; clock_was_set(); printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n"); @@ -517,6 +526,7 @@ static void second_overflow(void) case TIME_DEL: if ((xtime.tv_sec + 1) % 86400 == 0) { xtime.tv_sec++; + wall_to_monotonic.tv_sec--; time_state = TIME_WAIT; clock_was_set(); printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n"); -- cgit v1.2.3 From 0ebcfd99e0a50c42248c5f4ee78d82d8cb65ab4a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:26:28 -0700 Subject: [PATCH] Fix jiffies_to_time[spec | val] and converse to use From: george anzinger In the current system (2.5.67) time_spec to jiffies, time_val to jiffies and the converse (jiffies to time_val and jiffies to time_spec) all use 1/HZ as the measure of a jiffie. Because of the inability of the PIT to actually generate an accurate 1/HZ interrupt, the wall clock is updated with a more accurate value (999848 nanoseconds per jiffie for HZ = 1000). This causes a 1/HZ interpretation of jiffies based timing to run faster than the wall clock, thus causing sleeps and timers to expire short of the requested time. Try, for example: time sleep 60 This patch changes the conversion routines to use the same value as the wall clock update code to do the conversions. The actual math is almost all done at compile time. The run time conversions require little if any more execution time. This patch must be applied after the patch I posted earlier today which fixed the CLOCK_MONOTONIC resolution issue. --- include/asm-i386/div64.h | 18 +++++++++++++ include/linux/time.h | 70 ++++++++++++++++++++++++++++++++++++++---------- include/linux/timex.h | 2 +- kernel/posix-timers.c | 43 +++++++++++++---------------- 4 files changed, 94 insertions(+), 39 deletions(-) (limited to 'include/linux') diff --git a/include/asm-i386/div64.h b/include/asm-i386/div64.h index ef915df700e4..bc8718a0b1ce 100644 --- a/include/asm-i386/div64.h +++ b/include/asm-i386/div64.h @@ -14,4 +14,22 @@ __mod; \ }) +/* + * (long)X = ((long long)divs) / (long)div + * (long)rem = ((long long)divs) % (long)div + * + * Warning, this will do an exception if X overflows. + */ +#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c) + +extern inline long +div_ll_X_l_rem(long long divs, long div, long *rem) +{ + long dum2; + __asm__("divl %2":"=a"(dum2), "=d"(*rem) + : "rm"(div), "A"(divs)); + + return dum2; + +} #endif diff --git a/include/linux/time.h b/include/linux/time.h index 6fad88e1a37d..fdab2abc43be 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -26,6 +26,16 @@ struct timezone { #include #include +#include +#include +#ifndef div_long_long_rem + +#define div_long_long_rem(dividend,divisor,remainder) ({ \ + u64 result = dividend; \ + *remainder = do_div(result,divisor); \ + result; }) + +#endif /* * Have the 32 bit jiffies value wrap 5 minutes after boot @@ -59,25 +69,52 @@ struct timezone { #ifndef NSEC_PER_USEC #define NSEC_PER_USEC (1000L) #endif +/* + * We want to do realistic conversions of time so we need to use the same + * values the update wall clock code uses as the jiffie size. This value + * is: TICK_NSEC(TICK_USEC) (both of which are defined in timex.h). This + * is a constant and is in nanoseconds. We will used scaled math and + * with a scales defined here as SEC_JIFFIE_SC, USEC_JIFFIE_SC and + * NSEC_JIFFIE_SC. Note that these defines contain nothing but + * constants and so are computed at compile time. SHIFT_HZ (computed in + * timex.h) adjusts the scaling for different HZ values. + */ +#define SEC_JIFFIE_SC (30 - SHIFT_HZ) +#define NSEC_JIFFIE_SC (SEC_JIFFIE_SC + 30) +#define USEC_JIFFIE_SC (SEC_JIFFIE_SC + 20) +#define SEC_CONVERSION ((unsigned long)(((u64)NSEC_PER_SEC << SEC_JIFFIE_SC) /\ + (u64)TICK_NSEC(TICK_USEC))) +#define NSEC_CONVERSION ((unsigned long)(((u64)1 << NSEC_JIFFIE_SC) / \ + (u64)TICK_NSEC(TICK_USEC))) +#define USEC_CONVERSION \ + ((unsigned long)(((u64)NSEC_PER_USEC << USEC_JIFFIE_SC)/ \ + (u64)TICK_NSEC(TICK_USEC))) +#define MAX_SEC_IN_JIFFIES \ + (u32)((u64)((u64)MAX_JIFFY_OFFSET * TICK_NSEC(TICK_USEC)) / NSEC_PER_SEC) static __inline__ unsigned long timespec_to_jiffies(struct timespec *value) { unsigned long sec = value->tv_sec; - long nsec = value->tv_nsec; + long nsec = value->tv_nsec + TICK_NSEC(TICK_USEC) - 1; - if (sec >= (MAX_JIFFY_OFFSET / HZ)) + if (sec >= MAX_SEC_IN_JIFFIES) return MAX_JIFFY_OFFSET; - nsec += 1000000000L / HZ - 1; - nsec /= 1000000000L / HZ; - return HZ * sec + nsec; + return (((u64)sec * SEC_CONVERSION) + + (((u64)nsec * NSEC_CONVERSION) >> + (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; + } static __inline__ void jiffies_to_timespec(unsigned long jiffies, struct timespec *value) { - value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ); - value->tv_sec = jiffies / HZ; + /* + * Convert jiffies to nanoseconds and seperate with + * one divide. + */ + u64 nsec = (u64)jiffies * TICK_NSEC(TICK_USEC); + value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_nsec); } /* Same for "timeval" */ @@ -85,20 +122,25 @@ static __inline__ unsigned long timeval_to_jiffies(struct timeval *value) { unsigned long sec = value->tv_sec; - long usec = value->tv_usec; + long usec = value->tv_usec + USEC_PER_SEC / HZ - 1; - if (sec >= (MAX_JIFFY_OFFSET / HZ)) + if (sec >= MAX_SEC_IN_JIFFIES) return MAX_JIFFY_OFFSET; - usec += 1000000L / HZ - 1; - usec /= 1000000L / HZ; - return HZ * sec + usec; + return (((u64)sec * SEC_CONVERSION) + + (((u64)usec * USEC_CONVERSION) >> + (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; } static __inline__ void jiffies_to_timeval(unsigned long jiffies, struct timeval *value) { - value->tv_usec = (jiffies % HZ) * (1000000L / HZ); - value->tv_sec = jiffies / HZ; + /* + * Convert jiffies to nanoseconds and seperate with + * one divide. + */ + u64 nsec = (u64)jiffies * TICK_NSEC(TICK_USEC); + value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec); + value->tv_usec /= NSEC_PER_USEC; } static __inline__ int timespec_equal(struct timespec *a, struct timespec *b) diff --git a/include/linux/timex.h b/include/linux/timex.h index 5b2b0ac18ae7..6c00606c6e33 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -51,7 +51,6 @@ #ifndef _LINUX_TIMEX_H #define _LINUX_TIMEX_H -#include #include /* @@ -177,6 +176,7 @@ /* a value TUSEC for TICK_USEC (can be set bij adjtimex) */ #define TICK_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8)) +#include /* * syscall interface - used (mainly by NTP daemon) * to discipline kernel clock oscillator diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index a0a972ec7742..bca12ba294e4 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -33,7 +33,12 @@ result; }) #endif +#define CLOCK_REALTIME_RES TICK_NSEC(TICK_USEC) // In nano seconds. +static inline u64 mpy_l_X_l_ll(unsigned long mpy1,unsigned long mpy2) +{ + return (u64)mpy1 * mpy2; +} /* * Management arrays for POSIX timers. Timers are kept in slab memory * Timer ids are allocated by an external routine that keeps track of the @@ -175,8 +180,8 @@ static inline void unlock_timer(struct k_itimer *timr, unsigned long flags); */ static __init int init_posix_timers(void) { - struct k_clock clock_realtime = {.res = NSEC_PER_SEC / HZ }; - struct k_clock clock_monotonic = {.res = NSEC_PER_SEC / HZ, + struct k_clock clock_realtime = {.res = CLOCK_REALTIME_RES }; + struct k_clock clock_monotonic = {.res = CLOCK_REALTIME_RES, .clock_get = do_posix_clock_monotonic_gettime, .clock_set = do_posix_clock_monotonic_settime }; @@ -204,24 +209,14 @@ static void tstojiffie(struct timespec *tp, int res, u64 *jiff) } /* - * A note on jiffy overflow: It is possible for the system to - * have been up long enough for the jiffies quanity to overflow. - * In order for correct timer evaluations we require that the - * specified time be somewhere between now and now + (max - * unsigned int/2). Times beyond this will be truncated back to - * this value. This is done in the absolute adjustment code, - * below. Here it is enough to just discard the high order - * bits. - */ - *jiff = (s64)sec * HZ; - /* - * Do the res thing. (Don't forget the add in the declaration of nsec) - */ - nsec -= nsec % res; - /* - * Split to jiffie and sub jiffie - */ - *jiff += nsec / (NSEC_PER_SEC / HZ); + * The scaling constants are defined in + * The difference between there and here is that we do the + * res rounding and compute a 64-bit result (well so does that + * but it then throws away the high bits). + */ + *jiff = (mpy_l_X_l_ll(sec, SEC_CONVERSION) + + (mpy_l_X_l_ll(nsec, NSEC_CONVERSION) >> + (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; } static void schedule_next_timer(struct k_itimer *timr) @@ -1232,7 +1227,6 @@ do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave) finish_wait(&nanosleep_abs_wqueue, &abs_wqueue); if (left > (s64)0) { - unsigned long rmd; /* * Always restart abs calls from scratch to pick up any @@ -1241,9 +1235,10 @@ do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave) if (abs) return -ERESTARTNOHAND; - tsave->tv_sec = div_long_long_rem(left, HZ, &rmd); - tsave->tv_nsec = rmd * (NSEC_PER_SEC / HZ); - + left *= TICK_NSEC(TICK_USEC); + tsave->tv_sec = div_long_long_rem(left, + NSEC_PER_SEC, + &tsave->tv_nsec); restart_block->fn = clock_nanosleep_restart; restart_block->arg0 = which_clock; restart_block->arg1 = (unsigned long)tsave; -- cgit v1.2.3 From 75908778d91e92ca3c9ed587c4550866f4c903fc Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:28:12 -0700 Subject: [PATCH] implement __GFP_REPEAT, __GFP_NOFAIL, __GFP_NORETRY This is a cleanup patch. There are quite a lot of places in the kernel which will infinitely retry a memory allocation. Generally, they get it wrong. Some do yield(), the semantics of which have changed over time. Some do schedule(), which can lock up if the caller is SCHED_FIFO/RR. Some do schedule_timeout(), etc. And often it is unnecessary, because the page allocator will do the retry internally anyway. But we cannot rely on that - this behaviour may change (-aa and -rmap kernels do not do this, for instance). So it is good to formalise and to centralise this operation. If an allocation specifies __GFP_REPEAT then the page allocator must infinitely retry the allocation. The semantics of __GFP_REPEAT are "try harder". The allocation _may_ fail (the 2.4 -aa and -rmap VM's do not retry infinitely by default). The semantics of __GFP_NOFAIL are "cannot fail". It is a no-op in this VM, but needs to be honoured (or fix up the callers) if the VM ischanged to not retry infinitely by default. The semantics of __GFP_NOREPEAT are "try once, don't loop". This isn't used at present (although perhaps it should be, in swapoff). It is mainly for completeness. --- include/linux/gfp.h | 15 ++++++++++++++- include/linux/slab.h | 2 +- mm/page_alloc.c | 18 +++++++++++++++--- mm/vmscan.c | 5 ++--- 4 files changed, 32 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gfp.h b/include/linux/gfp.h index c475f7b41e59..ade6d9e97475 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -11,13 +11,26 @@ #define __GFP_DMA 0x01 #define __GFP_HIGHMEM 0x02 -/* Action modifiers - doesn't change the zoning */ +/* + * Action modifiers - doesn't change the zoning + * + * __GFP_REPEAT: Try hard to allocate the memory, but the allocation attempt + * _might_ fail. This depends upon the particular VM implementation. + * + * __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller + * cannot handle allocation failures. + * + * __GFP_NORETRY: The VM implementation must not retry indefinitely. + */ #define __GFP_WAIT 0x10 /* Can wait and reschedule? */ #define __GFP_HIGH 0x20 /* Should access emergency pools? */ #define __GFP_IO 0x40 /* Can start physical IO? */ #define __GFP_FS 0x80 /* Can call down to low-level FS? */ #define __GFP_COLD 0x100 /* Cache-cold page required */ #define __GFP_NOWARN 0x200 /* Suppress page allocation failure warning */ +#define __GFP_REPEAT 0x400 /* Retry the allocation. Might fail */ +#define __GFP_NOFAIL 0x800 /* Retry for ever. Cannot fail */ +#define __GFP_NORETRY 0x1000 /* Do not retry. Might fail */ #define GFP_ATOMIC (__GFP_HIGH) #define GFP_NOIO (__GFP_WAIT) diff --git a/include/linux/slab.h b/include/linux/slab.h index bdc5256de12a..603748b9b349 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -22,7 +22,7 @@ typedef struct kmem_cache_s kmem_cache_t; #define SLAB_KERNEL GFP_KERNEL #define SLAB_DMA GFP_DMA -#define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS|__GFP_COLD|__GFP_NOWARN) +#define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS|__GFP_COLD|__GFP_NOWARN|__GFP_REPEAT|__GFP_NOFAIL|__GFP_NORETRY) #define SLAB_NO_GROW 0x00001000UL /* don't grow a cache */ /* flags to pass to kmem_cache_create(). diff --git a/mm/page_alloc.c b/mm/page_alloc.c index c9c7accac1f7..bff7db2296ae 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -536,6 +536,7 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, struct page *page; int i; int cold; + int do_retry; if (wait) might_sleep(); @@ -626,10 +627,21 @@ rebalance: } /* - * Don't let big-order allocations loop. Yield for kswapd, try again. + * Don't let big-order allocations loop unless the caller explicitly + * requests that. Wait for some write requests to complete then retry. + * + * In this implementation, __GFP_REPEAT means __GFP_NOFAIL, but that + * may not be true in other implementations. */ - if (order <= 3) { - yield(); + do_retry = 0; + if (!(gfp_mask & __GFP_NORETRY)) { + if ((order <= 3) || (gfp_mask & __GFP_REPEAT)) + do_retry = 1; + if (gfp_mask & __GFP_NOFAIL) + do_retry = 1; + } + if (do_retry) { + blk_congestion_wait(WRITE, HZ/50); goto rebalance; } diff --git a/mm/vmscan.c b/mm/vmscan.c index 291ce1136c6e..c1dffbdf2e41 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -805,8 +805,7 @@ shrink_caches(struct zone *classzone, int priority, int *total_scanned, * excessive rotation of the inactive list, which is _supposed_ to be an LRU, * yes? */ -int -try_to_free_pages(struct zone *classzone, +int try_to_free_pages(struct zone *classzone, unsigned int gfp_mask, unsigned int order) { int priority; @@ -838,7 +837,7 @@ try_to_free_pages(struct zone *classzone, blk_congestion_wait(WRITE, HZ/10); shrink_slab(total_scanned, gfp_mask); } - if (gfp_mask & __GFP_FS) + if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) out_of_memory(); return 0; } -- cgit v1.2.3 From 8db50e8b5efcdb7665443f750aef592871761978 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:28:19 -0700 Subject: [PATCH] make alloc_buffer_head take gfp_flags - alloc_buffer_head() should take the allocation mode as an arg, and not assume. - Use __GFP_NOFAIL in JBD's call to alloc_buffer_head(). - Remove all the retry code from jbd_kmalloc() - do it via page allocator controls. --- fs/buffer.c | 8 ++++---- fs/jbd/journal.c | 33 +++------------------------------ include/linux/buffer_head.h | 2 +- 3 files changed, 8 insertions(+), 35 deletions(-) (limited to 'include/linux') diff --git a/fs/buffer.c b/fs/buffer.c index c40bf36afc0b..47e2cf01f30c 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -995,7 +995,7 @@ try_again: head = NULL; offset = PAGE_SIZE; while ((offset -= size) >= 0) { - bh = alloc_buffer_head(); + bh = alloc_buffer_head(GFP_NOFS); if (!bh) goto no_grow; @@ -2346,7 +2346,7 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to, if (buffer_uptodate(&map_bh)) continue; /* reiserfs does this */ if (block_start < from || block_end > to) { - struct buffer_head *bh = alloc_buffer_head(); + struct buffer_head *bh = alloc_buffer_head(GFP_NOFS); if (!bh) { ret = -ENOMEM; @@ -2905,9 +2905,9 @@ static void recalc_bh_state(void) buffer_heads_over_limit = (tot > max_buffer_heads); } -struct buffer_head *alloc_buffer_head(void) +struct buffer_head *alloc_buffer_head(int gfp_flags) { - struct buffer_head *ret = kmem_cache_alloc(bh_cachep, GFP_NOFS); + struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags); if (ret) { preempt_disable(); __get_cpu_var(bh_accounting).nr++; diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index a429a2aa0ac5..96e1d0bf490f 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -457,14 +457,8 @@ int journal_write_metadata_buffer(transaction_t *transaction, /* * Right, time to make up the new buffer_head. */ - do { - new_bh = alloc_buffer_head(); - if (!new_bh) { - printk (KERN_NOTICE "%s: ENOMEM at alloc_buffer_head, " - "trying again.\n", __FUNCTION__); - yield(); - } - } while (!new_bh); + new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); + /* keep subsequent assertions sane */ new_bh->b_state = 0; init_buffer(new_bh, NULL, NULL); @@ -1613,28 +1607,7 @@ void shrink_journal_memory(void) */ void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry) { - void *p; - static unsigned long last_warning; - - while (1) { - p = kmalloc(size, flags); - if (p) - return p; - if (!retry) - return NULL; - /* Log every retry for debugging. Also log them to the - * syslog, but do rate-limiting on the non-debugging - * messages. */ - jbd_debug(1, "ENOMEM in %s, retrying.\n", where); - - if (time_after(jiffies, last_warning + 5*HZ)) { - printk(KERN_NOTICE - "ENOMEM in %s, retrying.\n", where); - last_warning = jiffies; - } - - yield(); - } + return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0)); } /* diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 64a70553d40c..26d71a5fb742 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -172,7 +172,7 @@ struct buffer_head * __getblk(struct block_device *, sector_t, int); void __brelse(struct buffer_head *); void __bforget(struct buffer_head *); struct buffer_head *__bread(struct block_device *, sector_t block, int size); -struct buffer_head *alloc_buffer_head(void); +struct buffer_head *alloc_buffer_head(int gfp_flags); void free_buffer_head(struct buffer_head * bh); void FASTCALL(unlock_buffer(struct buffer_head *bh)); void ll_rw_block(int, int, struct buffer_head * bh[]); -- cgit v1.2.3 From cca095e03401e4a1c6cd1a747d8e278986b9d6a4 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:28:52 -0700 Subject: [PATCH] oom-kill: preferentially kill swapoff From: Hugh Dickins The current behaviour is that once swapoff has filled memory, other tasks get OOMkilled one by one until swapoff completes, or more likely hangs. It is better that swapoff be the first choice for OOMkill. The patch changes the oom-killer so that it will kill off any currently-running swapoff instance before killing any other task. (Bit kludgy, couldn't think of a better way) --- include/linux/sched.h | 1 + mm/oom_kill.c | 2 ++ mm/swapfile.c | 2 ++ 3 files changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/sched.h b/include/linux/sched.h index c30c44f3cfcc..eee58c7354b4 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -465,6 +465,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PF_FROZEN 0x00010000 /* frozen for system suspend */ #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ #define PF_KSWAPD 0x00040000 /* I am kswapd */ +#define PF_SWAPOFF 0x00080000 /* I am in swapoff */ #if CONFIG_SMP extern void set_cpus_allowed(task_t *p, unsigned long new_mask); diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 34a3aeb50799..e537462aaf58 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -129,6 +129,8 @@ static struct task_struct * select_bad_process(void) chosen = p; maxpoints = points; } + if (p->flags & PF_SWAPOFF) + return p; } while_each_thread(g, p); return chosen; diff --git a/mm/swapfile.c b/mm/swapfile.c index 144915b74734..48ffb627914d 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1058,7 +1058,9 @@ asmlinkage long sys_swapoff(const char __user * specialfile) total_swap_pages -= p->pages; p->flags &= ~SWP_WRITEOK; swap_list_unlock(); + current->flags |= PF_SWAPOFF; err = try_to_unuse(type); + current->flags &= ~PF_SWAPOFF; if (err) { /* re-insert swap space back into swap_list */ swap_list_lock(); -- cgit v1.2.3 From 5fb58500eec7e5afab139a6b3825c55fbbeff48c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:29:12 -0700 Subject: [PATCH] Allocate hd_structs dynamically From: Badari Pulavarty Here is the patch to allocate hd_struct dynamically as we find partitions. There are 3 things I didn't like in the patch. 1) The patch allocates 15 pointers instead of 15 hd_structs. (incase of s= csi). I was really hoping to get rid of "15" and make it really dynamic. (In ca= se if we ever want to support more than 15 partitions per disk etc..).=20 I was thought about making it a linked list, but blk_partition_remap() needs to get to hd_struct for a given partition everytime we do IO. So linked list would be bad, we really need direct access to partition in= fo. 2) I had to add "partno" to hd_struct, since part_dev_read() used to calc= ulate partition number from the address before. 3) kmalloc() failure in add_partition() will be silently ignored. It saves 2048 bytes per disk. --- drivers/block/cciss.c | 9 ++++++--- drivers/block/genhd.c | 19 +++++++++++-------- drivers/block/ioctl.c | 11 ++++++++--- drivers/block/ll_rw_blk.c | 2 +- fs/block_dev.c | 4 ++-- fs/partitions/check.c | 17 ++++++++++++++--- include/linux/genhd.h | 4 ++-- 7 files changed, 44 insertions(+), 22 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 8987b67272cd..f566e20e2094 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -599,9 +599,12 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, luninfo.num_opens = drv->usage_count; luninfo.num_parts = 0; /* count partitions 1 to 15 with sizes > 0 */ - for(i=1; i part[i].nr_sects != 0) - luninfo.num_parts++; + for(i=1; i part[i]) + continue; + if (disk->part[i]->nr_sects != 0) + luninfo.num_parts++; + } if (copy_to_user((void *) arg, &luninfo, sizeof(LogvolInfo_struct))) return -EFAULT; diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index 032739646da9..af193deee80c 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -365,11 +365,13 @@ static int show_partition(struct seq_file *part, void *v) (unsigned long long)get_capacity(sgp) >> 1, disk_name(sgp, 0, buf)); for (n = 0; n < sgp->minors - 1; n++) { - if (sgp->part[n].nr_sects == 0) + if (!sgp->part[n]) + continue; + if (sgp->part[n]->nr_sects == 0) continue; seq_printf(part, "%4d %4d %10llu %s\n", sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n].nr_sects >> 1 , + (unsigned long long)sgp->part[n]->nr_sects >> 1 , disk_name(sgp, n + 1, buf)); } @@ -552,7 +554,7 @@ struct gendisk *alloc_disk(int minors) return NULL; } if (minors > 1) { - int size = (minors - 1) * sizeof(struct hd_struct); + int size = (minors - 1) * sizeof(struct hd_struct *); disk->part = kmalloc(size, GFP_KERNEL); if (!disk->part) { kfree(disk); @@ -604,8 +606,8 @@ void set_device_ro(struct block_device *bdev, int flag) struct gendisk *disk = bdev->bd_disk; if (bdev->bd_contains != bdev) { int part = bdev->bd_dev - MKDEV(disk->major, disk->first_minor); - struct hd_struct *p = &disk->part[part-1]; - p->policy = flag; + struct hd_struct *p = disk->part[part-1]; + if (p) p->policy = flag; } else disk->policy = flag; } @@ -615,7 +617,7 @@ void set_disk_ro(struct gendisk *disk, int flag) int i; disk->policy = flag; for (i = 0; i < disk->minors - 1; i++) - disk->part[i].policy = flag; + if (disk->part[i]) disk->part[i]->policy = flag; } int bdev_read_only(struct block_device *bdev) @@ -626,8 +628,9 @@ int bdev_read_only(struct block_device *bdev) disk = bdev->bd_disk; if (bdev->bd_contains != bdev) { int part = bdev->bd_dev - MKDEV(disk->major, disk->first_minor); - struct hd_struct *p = &disk->part[part-1]; - return p->policy; + struct hd_struct *p = disk->part[part-1]; + if (p) return p->policy; + return 0; } else return disk->policy; } diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c index 538c8a04a2d3..3dbd0824319b 100644 --- a/drivers/block/ioctl.c +++ b/drivers/block/ioctl.c @@ -41,11 +41,14 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg) return -EINVAL; } /* partition number in use? */ - if (disk->part[part - 1].nr_sects != 0) + if (disk->part[part - 1]) return -EBUSY; /* overlap? */ for (i = 0; i < disk->minors - 1; i++) { - struct hd_struct *s = &disk->part[i]; + struct hd_struct *s = disk->part[i]; + + if (!s) + continue; if (!(start+length <= s->start_sect || start >= s->start_sect + s->nr_sects)) return -EBUSY; @@ -54,7 +57,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg) add_partition(disk, part, start, length); return 0; case BLKPG_DEL_PARTITION: - if (disk->part[part - 1].nr_sects == 0) + if (!disk->part[part-1]) + return -ENXIO; + if (disk->part[part - 1]->nr_sects == 0) return -ENXIO; /* partition in use? Incomplete check for now. */ bdevp = bdget(MKDEV(disk->major, disk->first_minor) + part); diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index e14210308577..9e2fd26ce0ed 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -1841,7 +1841,7 @@ static inline void blk_partition_remap(struct bio *bio) if (bdev == bdev->bd_contains) return; - p = &disk->part[bdev->bd_dev-MKDEV(disk->major,disk->first_minor)-1]; + p = disk->part[bdev->bd_dev-MKDEV(disk->major,disk->first_minor)-1]; switch (bio->bi_rw) { case READ: p->read_sectors += bio_sectors(bio); diff --git a/fs/block_dev.c b/fs/block_dev.c index 948864b885b5..9a974170a10b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -559,10 +559,10 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file * bdev->bd_contains = whole; down(&whole->bd_sem); whole->bd_part_count++; - p = disk->part + part - 1; + p = disk->part[part - 1]; bdev->bd_inode->i_data.backing_dev_info = whole->bd_inode->i_data.backing_dev_info; - if (!(disk->flags & GENHD_FL_UP) || !p->nr_sects) { + if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { whole->bd_part_count--; up(&whole->bd_sem); ret = -ENXIO; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 647f0357e30c..aa0646e44598 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -182,7 +182,7 @@ static struct sysfs_ops part_sysfs_ops = { static ssize_t part_dev_read(struct hd_struct * p, char *page) { struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj); - int part = p - disk->part + 1; + int part = p->partno; dev_t base = MKDEV(disk->major, disk->first_minor); return sprintf(page, "%04x\n", (unsigned)(base + part)); } @@ -234,7 +234,9 @@ struct kobj_type ktype_part = { void delete_partition(struct gendisk *disk, int part) { - struct hd_struct *p = disk->part + part - 1; + struct hd_struct *p = disk->part[part-1]; + if (!p) + return; if (!p->nr_sects) return; p->start_sect = 0; @@ -242,14 +244,23 @@ void delete_partition(struct gendisk *disk, int part) p->reads = p->writes = p->read_sectors = p->write_sectors = 0; devfs_remove("%s/part%d", disk->devfs_name, part); kobject_unregister(&p->kobj); + disk->part[part-1] = NULL; + kfree(p); } void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) { - struct hd_struct *p = disk->part + part - 1; + struct hd_struct *p; + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return; + + memset(p, 0, sizeof(*p)); p->start_sect = start; p->nr_sects = len; + p->partno = part; + disk->part[part-1] = p; devfs_register_partition(disk, part); snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part); p->kobj.parent = &disk->kobj; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index c2432bd349e5..ac8fc9ef5bdb 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -64,7 +64,7 @@ struct hd_struct { sector_t nr_sects; struct kobject kobj; unsigned reads, read_sectors, writes, write_sectors; - int policy; + int policy, partno; }; #define GENHD_FL_REMOVABLE 1 @@ -89,7 +89,7 @@ struct gendisk { int minor_shift; /* number of times minor is shifted to get real minor */ char disk_name[16]; /* name of major driver */ - struct hd_struct *part; /* [indexed by minor] */ + struct hd_struct **part; /* [indexed by minor] */ struct block_device_operations *fops; struct request_queue *queue; void *private_data; -- cgit v1.2.3 From 4a6b60f25d68965452d60c2a77cccefffd8652b3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:29:19 -0700 Subject: [PATCH] fix CONFIG_NOMMU mismerges From: Christoph Hellwig we already have better stubs in nommu.c, the additional inlines in mm.h only cause compile failures. --- include/linux/mm.h | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mm.h b/include/linux/mm.h index ede6c5ff4181..6aa89d73f65b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -594,28 +594,10 @@ extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned lon extern unsigned int nr_used_zone_pages(void); -#ifdef CONFIG_MMU extern struct page * vmalloc_to_page(void *addr); extern struct page * follow_page(struct mm_struct *mm, unsigned long address, int write); extern int remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot); -#else -static inline struct page * vmalloc_to_page(void *addr) -{ - return NULL; -} -static inline struct page * follow_page(struct mm_struct *mm, - unsigned long address, int write) -{ - return NULL; -} -static inline int remap_page_range(struct vm_area_struct *vma, - unsigned long from, unsigned long to, - unsigned long size, pgprot_t prot) -{ - return -EPERM; -} -#endif /* CONFIG_MMU */ #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ -- cgit v1.2.3 From 2096040f5178cfc109cb8a529bd23dba77384f97 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:29:25 -0700 Subject: [PATCH] Extend map_vm_area()/get_vm_area() From: Christoph Hellwig and David M-T The ia64 port can use vmap(), but needs to be able to specify the protection flags and the resulting vma's vm_flags. The patch adds the two extra args to vmap(), updates the two callers and fixes some comment spellos. --- fs/xfs/pagebuf/page_buf.c | 3 ++- include/linux/vmalloc.h | 3 ++- mm/vmalloc.c | 29 ++++++++++++++++------------- sound/core/sgbuf.c | 2 +- 4 files changed, 21 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/fs/xfs/pagebuf/page_buf.c b/fs/xfs/pagebuf/page_buf.c index f50803bd2570..2230380e952f 100644 --- a/fs/xfs/pagebuf/page_buf.c +++ b/fs/xfs/pagebuf/page_buf.c @@ -554,7 +554,8 @@ mapit: } else if (flags & PBF_MAPPED) { if (as_list_len > 64) purge_addresses(); - pb->pb_addr = vmap(pb->pb_pages, page_count); + pb->pb_addr = vmap(pb->pb_pages, page_count, + VM_MAP, PAGE_KERNEL); if (pb->pb_addr == NULL) return -ENOMEM; pb->pb_addr += pb->pb_offset; diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index d90763253759..570778ddeae9 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -27,7 +27,8 @@ extern void *vmalloc_32(unsigned long size); extern void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot); extern void vfree(void *addr); -extern void *vmap(struct page **pages, unsigned int count); +extern void *vmap(struct page **pages, unsigned int count, + unsigned long flags, pgprot_t prot); extern void vunmap(void *addr); /* diff --git a/mm/vmalloc.c b/mm/vmalloc.c index a6423eebcd5d..f6ce2378b721 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -308,7 +308,7 @@ void __vunmap(void *addr, int deallocate_pages) * * @addr: memory base address * - * Free the virtually continguos memory area starting at @addr, as + * Free the virtually contiguous memory area starting at @addr, as * obtained from vmalloc(), vmalloc_32() or __vmalloc(). * * May not be called in interrupt context. @@ -324,7 +324,7 @@ void vfree(void *addr) * * @addr: memory base address * - * Free the virtually continguos memory area starting at @addr, + * Free the virtually contiguous memory area starting at @addr, * which was created from the page array passed to vmap(). * * May not be called in interrupt context. @@ -336,25 +336,28 @@ void vunmap(void *addr) } /** - * vmap - map an array of pages into virtually continguos space + * vmap - map an array of pages into virtually contiguous space * * @pages: array of page pointers * @count: number of pages to map + * @flags: vm_area->flags + * @prot: page protection for the mapping * - * Maps @count pages from @pages into continguos kernel virtual + * Maps @count pages from @pages into contiguous kernel virtual * space. */ -void *vmap(struct page **pages, unsigned int count) +void *vmap(struct page **pages, unsigned int count, + unsigned long flags, pgprot_t prot) { struct vm_struct *area; if (count > num_physpages) return NULL; - area = get_vm_area((count << PAGE_SHIFT), VM_MAP); + area = get_vm_area((count << PAGE_SHIFT), flags); if (!area) return NULL; - if (map_vm_area(area, PAGE_KERNEL, &pages)) { + if (map_vm_area(area, prot, &pages)) { vunmap(area->addr); return NULL; } @@ -363,14 +366,14 @@ void *vmap(struct page **pages, unsigned int count) } /** - * __vmalloc - allocate virtually continguos memory + * __vmalloc - allocate virtually contiguous memory * * @size: allocation size * @gfp_mask: flags for the page level allocator * @prot: protection mask for the allocated pages * * Allocate enough pages to cover @size from the page level - * allocator with @gfp_mask flags. Map them into continguos + * allocator with @gfp_mask flags. Map them into contiguous * kernel virtual space, using a pagetable protection of @prot. */ void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot) @@ -418,12 +421,12 @@ fail: } /** - * vmalloc - allocate virtually continguos memory + * vmalloc - allocate virtually contiguous memory * * @size: allocation size * * Allocate enough pages to cover @size from the page level - * allocator and map them into continguos kernel virtual space. + * allocator and map them into contiguous kernel virtual space. * * For tight cotrol over page level allocator and protection flags * use __vmalloc() instead. @@ -434,12 +437,12 @@ void *vmalloc(unsigned long size) } /** - * vmalloc_32 - allocate virtually continguos memory (32bit addressable) + * vmalloc_32 - allocate virtually contiguous memory (32bit addressable) * * @size: allocation size * * Allocate enough 32bit PA addressable pages to cover @size from the - * page level allocator and map them into continguos kernel virtual space. + * page level allocator and map them into contiguous kernel virtual space. */ void *vmalloc_32(unsigned long size) { diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index 84e79ebc5c80..4578d2b335bf 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -85,7 +85,7 @@ void *snd_malloc_sgbuf_pages(struct pci_dev *pci, size_t size, struct snd_dma_bu } sgbuf->size = size; - dmab->area = vmap(sgbuf->page_table, sgbuf->pages); + dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, PAGE_KERNEL); if (! dmab->area) goto _failed; return dmab->area; -- cgit v1.2.3 From 36ba76bb4499ed3d2735240369fbd371aa8dd11b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:29:55 -0700 Subject: [PATCH] Fix nfsctl for larger dev_t From: Andries.Brouwer@cwi.nl The old NFS control interface passes dev_t's in from userspace. This patch keeps it working when the size of dev_t changes. This is a deprecated interface - new nfs-utils uses an ascii representation in exportfs. Acked by Neil. --- arch/ia64/ia32/sys_ia32.c | 1 - arch/parisc/kernel/sys_parisc32.c | 2 +- arch/ppc64/kernel/sys_ppc32.c | 1 - arch/sparc64/kernel/sys_sparc32.c | 1 - arch/x86_64/ia32/sys_ia32.c | 1 - include/linux/nfsd/syscall.h | 3 +-- 6 files changed, 2 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 84d34a212ac2..570b03908dd5 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -3040,7 +3040,6 @@ struct nfsctl_arg32 { #define ca32_svc u.u32_svc #define ca32_client u.u32_client #define ca32_export u.u32_export -#define ca32_authd u.u32_authd #define ca32_debug u.u32_debug }; diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 63a85350d4ea..23a0afcf31a6 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -1131,7 +1131,7 @@ asmlinkage long sys32_msgrcv(int msqid, struct nfsctl_export32 { char ex_client[NFSCLNT_IDMAX+1]; char ex_path[NFS_MAXPATHLEN+1]; - __kernel_dev_t ex_dev; + __kernel_old_dev_t ex_dev; compat_ino_t ex_ino; int ex_flags; __kernel_uid_t ex_anon_uid; diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c index fba8c8254455..300a93c9c42e 100644 --- a/arch/ppc64/kernel/sys_ppc32.c +++ b/arch/ppc64/kernel/sys_ppc32.c @@ -910,7 +910,6 @@ struct nfsctl_arg32 { #define ca32_export u.u32_export #define ca32_getfd u.u32_getfd #define ca32_getfs u.u32_getfs -#define ca32_authd u.u32_authd }; union nfsctl_res32 { diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index b1194401deba..ff9c8ec19b16 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -2133,7 +2133,6 @@ struct nfsctl_arg32 { #define ca32_export u.u32_export #define ca32_getfd u.u32_getfd #define ca32_getfs u.u32_getfs -#define ca32_authd u.u32_authd }; union nfsctl_res32 { diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c index 292936f958f0..6712c9475d0b 100644 --- a/arch/x86_64/ia32/sys_ia32.c +++ b/arch/x86_64/ia32/sys_ia32.c @@ -1708,7 +1708,6 @@ struct nfsctl_arg32 { #define ca32_export u.u32_export #define ca32_getfd u.u32_getfd #define ca32_getfs u.u32_getfs -#define ca32_authd u.u32_authd }; union nfsctl_res32 { diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h index 37b8901433d6..b6fa4d1839e3 100644 --- a/include/linux/nfsd/syscall.h +++ b/include/linux/nfsd/syscall.h @@ -59,7 +59,7 @@ struct nfsctl_client { struct nfsctl_export { char ex_client[NFSCLNT_IDMAX+1]; char ex_path[NFS_MAXPATHLEN+1]; - __kernel_dev_t ex_dev; + __kernel_old_dev_t ex_dev; __kernel_ino_t ex_ino; int ex_flags; __kernel_uid_t ex_anon_uid; @@ -104,7 +104,6 @@ struct nfsctl_arg { #define ca_export u.u_export #define ca_getfd u.u_getfd #define ca_getfs u.u_getfs -#define ca_authd u.u_authd }; union nfsctl_res { -- cgit v1.2.3 From b009a1c6a6c0273f60d96eca2561bc79da3b6614 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 20 Apr 2003 00:34:45 -0700 Subject: [PATCH] fbdev build fix - fb_prepare_logo() is calling the undefined find_logo(). I think it wants fb_find_logo(). - fb_prepare_logo is not __init, therefore fb_find_logo() cannot be __init. --- drivers/video/fbmem.c | 3 ++- drivers/video/logo/logo.c | 2 +- include/linux/linux_logo.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 0f3182b1783a..75b47be36f22 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifdef CONFIG_KMOD #include @@ -655,7 +656,7 @@ int fb_prepare_logo(struct fb_info *info) } /* Return if no suitable logo was found */ - fb_logo.logo = find_logo(info->var.bits_per_pixel); + fb_logo.logo = fb_find_logo(info->var.bits_per_pixel); if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) { fb_logo.logo = NULL; diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c index daf9c360a2aa..3039664df313 100644 --- a/drivers/video/logo/logo.c +++ b/drivers/video/logo/logo.c @@ -33,7 +33,7 @@ extern const struct linux_logo logo_superh_vga16; extern const struct linux_logo logo_superh_clut224; -const struct linux_logo * __init find_logo(int depth) +const struct linux_logo *fb_find_logo(int depth) { const struct linux_logo *logo = 0; diff --git a/include/linux/linux_logo.h b/include/linux/linux_logo.h index ea05e16c2b16..9c01bde5bf1b 100644 --- a/include/linux/linux_logo.h +++ b/include/linux/linux_logo.h @@ -32,6 +32,6 @@ struct linux_logo { const unsigned char *data; }; -extern const struct linux_logo * __init find_logo(int depth); +extern const struct linux_logo *fb_find_logo(int depth); #endif /* _LINUX_LINUX_LOGO_H */ -- cgit v1.2.3 From 1c6099ba9a89e1287ff2198313dc7d2c2d6cac2a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Apr 2003 00:39:29 -0700 Subject: [PATCH] devfs: input Make sure input always uses devfs_remove. While at it I've also remove lots of code duplication - every upper input driver contained the code surrounding devfs_unregister in two identical copies. --- drivers/input/evdev.c | 27 +++++++++---------- drivers/input/input.c | 22 +++++---------- drivers/input/joydev.c | 29 ++++++++++---------- drivers/input/mousedev.c | 70 +++++++++++++++++++++++++----------------------- drivers/input/tsdev.c | 27 +++++++++---------- include/linux/input.h | 4 +-- 6 files changed, 85 insertions(+), 94 deletions(-) (limited to 'include/linux') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 9a70680b18f6..3e944fe20953 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -27,7 +27,6 @@ struct evdev{ char name[16]; struct input_handle handle; wait_queue_head_t wait; - devfs_handle_t devfs; struct list_head list; }; @@ -76,6 +75,13 @@ static int evdev_flush(struct file * file) return input_flush_device(&list->evdev->handle, file); } +static void evdev_free(struct evdev *evdev) +{ + devfs_remove("input/event%d", evdev->minor); + evdev_table[evdev->minor] = NULL; + kfree(evdev); +} + static int evdev_release(struct inode * inode, struct file * file) { struct evdev_list *list = file->private_data; @@ -84,17 +90,13 @@ static int evdev_release(struct inode * inode, struct file * file) list_del(&list->node); if (!--list->evdev->open) { - if (list->evdev->exist) { + if (list->evdev->exist) input_close_device(&list->evdev->handle); - } else { - input_unregister_minor(list->evdev->devfs); - evdev_table[list->evdev->minor] = NULL; - kfree(list->evdev); - } + else + evdev_free(list->evdev); } kfree(list); - return 0; } @@ -397,7 +399,7 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct sprintf(evdev->name, "event%d", minor); evdev_table[minor] = evdev; - evdev->devfs = input_register_minor("input/event%d", minor, EVDEV_MINOR_BASE); + input_register_minor("input/event%d", minor, EVDEV_MINOR_BASE); return &evdev->handle; } @@ -411,11 +413,8 @@ static void evdev_disconnect(struct input_handle *handle) if (evdev->open) { input_close_device(handle); wake_up_interruptible(&evdev->wait); - } else { - input_unregister_minor(evdev->devfs); - evdev_table[evdev->minor] = NULL; - kfree(evdev); - } + } else + evdev_free(evdev); } static struct input_device_id evdev_ids[] = { diff --git a/drivers/input/input.c b/drivers/input/input.c index bdf6020246e9..1989b14ea552 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -32,7 +32,6 @@ EXPORT_SYMBOL(input_unregister_device); EXPORT_SYMBOL(input_register_handler); EXPORT_SYMBOL(input_unregister_handler); EXPORT_SYMBOL(input_register_minor); -EXPORT_SYMBOL(input_unregister_minor); EXPORT_SYMBOL(input_open_device); EXPORT_SYMBOL(input_close_device); EXPORT_SYMBOL(input_accept_process); @@ -47,7 +46,6 @@ static LIST_HEAD(input_dev_list); static LIST_HEAD(input_handler_list); static struct input_handler *input_table[8]; -static devfs_handle_t input_devfs_handle; #ifdef CONFIG_PROC_FS static struct proc_dir_entry *proc_bus_input_dir; @@ -542,20 +540,13 @@ static struct file_operations input_fops = { .open = input_open_file, }; -devfs_handle_t input_register_minor(char *name, int minor, int minor_base) +void input_register_minor(char *name, int minor, int minor_base) { char devfs_name[16]; - sprintf(devfs_name, name, minor); - - return devfs_register(NULL, devfs_name, 0, - INPUT_MAJOR, minor + minor_base, - S_IFCHR|S_IRUGO|S_IWUSR, - &input_fops, NULL); -} -void input_unregister_minor(devfs_handle_t handle) -{ - devfs_unregister(handle); + sprintf(devfs_name, name, minor); + devfs_register(NULL, devfs_name, 0, INPUT_MAJOR, minor_base + minor, + S_IFCHR|S_IRUGO|S_IWUSR, &input_fops, NULL); } #ifdef CONFIG_PROC_FS @@ -699,8 +690,7 @@ static int __init input_init(void) return -EBUSY; } - input_devfs_handle = devfs_mk_dir("input"); - + devfs_mk_dir("input"); return 0; } @@ -711,7 +701,7 @@ static void __exit input_exit(void) remove_proc_entry("handlers", proc_bus_input_dir); remove_proc_entry("input", proc_bus); #endif - devfs_unregister(input_devfs_handle); + devfs_remove("input"); if (unregister_chrdev(INPUT_MAJOR, "input")) printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR); devclass_unregister(&input_devclass); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index f6dda351f1e4..5854c8c201aa 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -45,7 +45,6 @@ struct joydev { char name[16]; struct input_handle handle; wait_queue_head_t wait; - devfs_handle_t devfs; struct list_head list; struct js_corr corr[ABS_MAX]; struct JS_DATA_SAVE_TYPE glue; @@ -141,6 +140,13 @@ static int joydev_fasync(int fd, struct file *file, int on) return retval < 0 ? retval : 0; } +static void joydev_free(struct joydev *joydev) +{ + devfs_remove("js%d", joydev->minor); + joydev_table[joydev->minor] = NULL; + kfree(joydev); +} + static int joydev_release(struct inode * inode, struct file * file) { struct joydev_list *list = file->private_data; @@ -150,17 +156,13 @@ static int joydev_release(struct inode * inode, struct file * file) list_del(&list->node); if (!--list->joydev->open) { - if (list->joydev->exist) { + if (list->joydev->exist) input_close_device(&list->joydev->handle); - } else { - input_unregister_minor(list->joydev->devfs); - joydev_table[list->joydev->minor] = NULL; - kfree(list->joydev); - } + else + joydev_free(list->joydev); } kfree(list); - return 0; } @@ -442,7 +444,7 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct } joydev_table[minor] = joydev; - joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE); + input_register_minor("js%d", minor, JOYDEV_MINOR_BASE); return &joydev->handle; } @@ -453,13 +455,10 @@ static void joydev_disconnect(struct input_handle *handle) joydev->exist = 0; - if (joydev->open) { + if (joydev->open) input_close_device(handle); - } else { - input_unregister_minor(joydev->devfs); - joydev_table[joydev->minor] = NULL; - kfree(joydev); - } + else + joydev_free(joydev); } static struct input_device_id joydev_ids[] = { diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 57c6062a96d3..18d3a9c15a37 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -46,7 +46,6 @@ struct mousedev { wait_queue_head_t wait; struct list_head list; struct input_handle handle; - devfs_handle_t devfs; }; struct mousedev_list { @@ -171,45 +170,52 @@ static int mousedev_fasync(int fd, struct file *file, int on) return retval < 0 ? retval : 0; } +static void mousedev_free(struct mousedev *mousedev) +{ + devfs_remove("input/mouse%d", mousedev->minor); + mousedev_table[mousedev->minor] = NULL; + kfree(mousedev); +} + +static int mixdev_release(void) +{ + struct input_handle *handle; + + list_for_each_entry(handle, &mousedev_handler.h_list, h_node) { + struct mousedev *mousedev = handle->private; + + if (!mousedev->open) { + if (mousedev->exist) + input_close_device(&mousedev->handle); + else + mousedev_free(mousedev); + } + } + + return 0; +} + static int mousedev_release(struct inode * inode, struct file * file) { struct mousedev_list *list = file->private_data; - struct input_handle *handle; - struct mousedev *mousedev; mousedev_fasync(-1, file, 0); list_del(&list->node); if (!--list->mousedev->open) { - if (list->mousedev->minor == MOUSEDEV_MIX) { - list_for_each_entry(handle, &mousedev_handler.h_list, h_node) { - mousedev = handle->private; - if (!mousedev->open) { - if (mousedev->exist) { - input_close_device(&mousedev->handle); - } else { - input_unregister_minor(mousedev->devfs); - mousedev_table[mousedev->minor] = NULL; - kfree(mousedev); - } - } - } - } else { - if (!mousedev_mix.open) { - if (list->mousedev->exist) { - input_close_device(&list->mousedev->handle); - } else { - input_unregister_minor(list->mousedev->devfs); - mousedev_table[list->mousedev->minor] = NULL; - kfree(list->mousedev); - } - } + if (list->mousedev->minor == MOUSEDEV_MIX) + return mixdev_release(); + + if (!mousedev_mix.open) { + if (list->mousedev->exist) + input_close_device(&list->mousedev->handle); + else + mousedev_free(list->mousedev); } } kfree(list); - return 0; } @@ -425,7 +431,7 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru input_open_device(&mousedev->handle); mousedev_table[minor] = mousedev; - mousedev->devfs = input_register_minor("input/mouse%d", minor, MOUSEDEV_MINOR_BASE); + input_register_minor("input/mouse%d", minor, MOUSEDEV_MINOR_BASE); return &mousedev->handle; } @@ -441,9 +447,7 @@ static void mousedev_disconnect(struct input_handle *handle) } else { if (mousedev_mix.open) input_close_device(handle); - input_unregister_minor(mousedev->devfs); - mousedev_table[mousedev->minor] = NULL; - kfree(mousedev); + mousedev_free(mousedev); } } @@ -507,7 +511,7 @@ static int __init mousedev_init(void) mousedev_table[MOUSEDEV_MIX] = &mousedev_mix; mousedev_mix.exist = 1; mousedev_mix.minor = MOUSEDEV_MIX; - mousedev_mix.devfs = input_register_minor("input/mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE); + input_register_minor("input/mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE); #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX if (!(mousedev_mix.misc = !misc_register(&psaux_mouse))) @@ -525,7 +529,7 @@ static void __exit mousedev_exit(void) if (mousedev_mix.misc) misc_deregister(&psaux_mouse); #endif - input_unregister_minor(mousedev_mix.devfs); + devfs_remove("input/mice"); input_unregister_handler(&mousedev_handler); interface_unregister(&mousedev_intf); } diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index 3e7184548ee4..bc0314045969 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c @@ -57,7 +57,6 @@ struct tsdev { wait_queue_head_t wait; struct list_head list; struct input_handle handle; - devfs_handle_t devfs; }; /* From Compaq's Touch Screen Specification version 0.2 (draft) */ @@ -115,6 +114,13 @@ static int tsdev_open(struct inode *inode, struct file *file) return 0; } +static void tsdev_free(struct tsdev *tsdev) +{ + devfs_remove("input/ts%d", tsdev->minor); + tsdev_table[tsdev->minor] = NULL; + kfree(tsdev); +} + static int tsdev_release(struct inode *inode, struct file *file) { struct tsdev_list *list = file->private_data; @@ -123,13 +129,10 @@ static int tsdev_release(struct inode *inode, struct file *file) list_del(&list->node); if (!--list->tsdev->open) { - if (list->tsdev->exist) { + if (list->tsdev->exist) input_close_device(&list->tsdev->handle); - } else { - input_unregister_minor(list->tsdev->devfs); - tsdev_table[list->tsdev->minor] = NULL; - kfree(list->tsdev); - } + else + tsdev_free(list->tsdev); } kfree(list); return 0; @@ -325,8 +328,7 @@ static struct input_handle *tsdev_connect(struct input_handler *handler, tsdev->handle.private = tsdev; tsdev_table[minor] = tsdev; - tsdev->devfs = - input_register_minor("input/ts%d", minor, TSDEV_MINOR_BASE); + input_register_minor("input/ts%d", minor, TSDEV_MINOR_BASE); return &tsdev->handle; @@ -341,11 +343,8 @@ static void tsdev_disconnect(struct input_handle *handle) if (tsdev->open) { input_close_device(handle); wake_up_interruptible(&tsdev->wait); - } else { - input_unregister_minor(tsdev->devfs); - tsdev_table[tsdev->minor] = NULL; - kfree(tsdev); - } + } else + tsdev_free(tsdev); } static struct input_device_id tsdev_ids[] = { diff --git a/include/linux/input.h b/include/linux/input.h index 5991c97b45cc..ca2f6f6b2d1e 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -895,8 +895,8 @@ void input_close_device(struct input_handle *); int input_accept_process(struct input_handle *handle, struct file *file); int input_flush_device(struct input_handle* handle, struct file* file); -devfs_handle_t input_register_minor(char *name, int minor, int minor_base); -void input_unregister_minor(devfs_handle_t handle); +/* will go away once devfs_register gets sanitized */ +void input_register_minor(char *name, int minor, int minor_base); void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); -- cgit v1.2.3 From 4977d1c64d4bdd7cd5a4a684668b044b7eaeaa29 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Apr 2003 00:40:00 -0700 Subject: [PATCH] devfs: videodev --- drivers/media/video/videodev.c | 21 ++++++++++----------- include/linux/videodev.h | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index b5efe332355a..67a6ae6b4df9 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -375,7 +375,6 @@ int video_register_device(struct video_device *vfd, int type, int nr) int base; int end; char *name_base; - char name[16]; switch(type) { @@ -426,19 +425,19 @@ int video_register_device(struct video_device *vfd, int type, int nr) vfd->minor=i; up(&videodev_lock); - sprintf (name, "v4l/%s%d", name_base, i - base); - vfd->devfs_handle = - devfs_register (NULL, name, DEVFS_FL_DEFAULT, - VIDEO_MAJOR, vfd->minor, - S_IFCHR | S_IRUSR | S_IWUSR, - &video_fops, - NULL); + sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base); + devfs_register(NULL, vfd->devfs_name, 0, VIDEO_MAJOR, vfd->minor, + S_IFCHR | S_IRUSR | S_IWUSR, &video_fops, NULL); init_MUTEX(&vfd->lock); #ifdef CONFIG_VIDEO_PROC_FS - sprintf (name, "%s%d", name_base, i - base); - videodev_proc_create_dev (vfd, name); +{ + char name[16]; + sprintf(name, "%s%d", name_base, i - base); + videodev_proc_create_dev(vfd, name); +} #endif + return 0; } @@ -460,7 +459,7 @@ void video_unregister_device(struct video_device *vfd) videodev_proc_destroy_dev (vfd); #endif - devfs_unregister (vfd->devfs_handle); + devfs_remove(vfd->devfs_name); video_device[vfd->minor]=NULL; up(&videodev_lock); } diff --git a/include/linux/videodev.h b/include/linux/videodev.h index fc6d314ecfc1..6c684a84142b 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -39,7 +39,7 @@ struct video_device /* for videodev.c intenal usage -- don't touch */ int users; struct semaphore lock; - devfs_handle_t devfs_handle; + char devfs_name[64]; /* devfs */ }; #define VIDEO_MAJOR 81 -- cgit v1.2.3 From 2048d61cd6afcae590e1d09772cf1c08d7341e84 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Apr 2003 00:40:08 -0700 Subject: [PATCH] devfs: miscdev --- drivers/char/misc.c | 26 ++++++++++++++++---------- include/linux/miscdevice.h | 2 +- 2 files changed, 17 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/misc.c b/drivers/char/misc.c index a297f930f1f1..e7144be4ef79 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -167,7 +167,6 @@ static struct file_operations misc_fops = { int misc_register(struct miscdevice * misc) { struct miscdevice *c; - char buf[256]; if (misc->next || misc->prev) return -EBUSY; @@ -197,14 +196,21 @@ int misc_register(struct miscdevice * misc) misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); - /* yuck, yet another stupid special-casing. We should rather - add ->devfs_name to avoid this mess. */ - snprintf(buf, sizeof(buf), strchr(misc->name, '/') ? - "%s" : "misc/%s", misc->name); - misc->devfs_handle = devfs_register(NULL, buf, 0, - MISC_MAJOR, misc->minor, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - misc->fops, NULL); + /* + * please use it if you want to do fancy things with your + * name... + */ + if (misc->devfs_name[0] == '\0') { + /* yuck, yet another stupid special-casing. + whos actually using this? Please switch over + to ->devfs_name ASAP */ + snprintf(misc->devfs_name, sizeof(misc->devfs_name), + strchr(misc->name, '/') ? + "%s" : "misc/%s", misc->name); + } + + devfs_register(NULL, misc->devfs_name, 0, MISC_MAJOR, misc->minor, + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->fops, NULL); /* * Add it to the front, so that later devices can "override" @@ -238,7 +244,7 @@ int misc_deregister(struct miscdevice * misc) misc->next->prev = misc->prev; misc->next = NULL; misc->prev = NULL; - devfs_unregister (misc->devfs_handle); + devfs_remove(misc->devfs_name); if (i < DYNAMIC_MINORS && i>0) { misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); } diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index b7b3da409f8a..c8b70414ebf6 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -44,7 +44,7 @@ struct miscdevice const char *name; struct file_operations *fops; struct miscdevice * next, * prev; - devfs_handle_t devfs_handle; + char devfs_name[64]; }; extern int misc_register(struct miscdevice * misc); -- cgit v1.2.3 From d22af367d3c748b9c71f9327249e2edda30b41f9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Apr 2003 00:40:48 -0700 Subject: [PATCH] devfs: remove devfs_unregister --- fs/devfs/base.c | 27 +++++---------------------- include/linux/devfs_fs_kernel.h | 5 ----- 2 files changed, 5 insertions(+), 27 deletions(-) (limited to 'include/linux') diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 9a98b7555cf2..75f3d57850b0 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -1442,7 +1442,6 @@ static void devfsd_notify (struct devfs_entry *de,unsigned short type) * this to whatever you like, and change it once the file is opened (the next * file opened will not see this change). * - * Returns a handle which may later be used in a call to devfs_unregister(). * On failure %NULL is returned. */ @@ -1457,6 +1456,7 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, /* we don't accept any flags anymore. prototype will change soon. */ WARN_ON(flags); + WARN_ON(dir); if (name == NULL) { @@ -1578,24 +1578,6 @@ static void _devfs_unregister (struct devfs_entry *dir, struct devfs_entry *de) } } /* End Function _devfs_unregister */ - -/** - * devfs_unregister - Unregister a device entry. - * @de: A handle previously created by devfs_register() or returned from - * devfs_get_handle(). If this is %NULL the routine does nothing. - */ - -void devfs_unregister (devfs_handle_t de) -{ - VERIFY_ENTRY (de); - if ( (de == NULL) || (de->parent == NULL) ) return; - DPRINTK (DEBUG_UNREGISTER, "(%s): de: %p refcount: %d\n", - de->name, de, atomic_read (&de->refcount) ); - write_lock (&de->parent->u.dir.lock); - _devfs_unregister (de->parent, de); - devfs_put (de); -} /* End Function devfs_unregister */ - static int devfs_do_symlink (devfs_handle_t dir, const char *name, const char *link, devfs_handle_t *handle) { @@ -1678,7 +1660,6 @@ int devfs_mk_symlink(const char *from, const char *to) * Use of this function is optional. The devfs_register() function * will automatically create intermediate directories as needed. This function * is provided for efficiency reasons, as it provides a handle to a directory. - * Returns a handle which may later be used in a call to devfs_unregister(). * On failure %NULL is returned. */ @@ -1730,7 +1711,10 @@ void devfs_remove(const char *fmt, ...) n = vsnprintf(buf, 64, fmt, args); if (n < 64 && buf[0]) { devfs_handle_t de = _devfs_find_entry(NULL, buf, 0); - devfs_unregister(de); + + write_lock(&de->parent->u.dir.lock); + _devfs_unregister(de->parent, de); + devfs_put(de); devfs_put(de); } } @@ -1863,7 +1847,6 @@ __setup("devfs=", devfs_setup); EXPORT_SYMBOL(devfs_put); EXPORT_SYMBOL(devfs_register); -EXPORT_SYMBOL(devfs_unregister); EXPORT_SYMBOL(devfs_mk_symlink); EXPORT_SYMBOL(devfs_mk_dir); EXPORT_SYMBOL(devfs_remove); diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h index 84c0abc4b840..24ad37027b73 100644 --- a/include/linux/devfs_fs_kernel.h +++ b/include/linux/devfs_fs_kernel.h @@ -25,7 +25,6 @@ extern devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, unsigned int flags, unsigned int major, unsigned int minor, umode_t mode, void *ops, void *info); -extern void devfs_unregister (devfs_handle_t de); extern int devfs_mk_symlink (const char *name, const char *link); extern devfs_handle_t devfs_mk_dir(const char *fmt, ...) __attribute__((format (printf, 1, 2))); @@ -50,10 +49,6 @@ static inline devfs_handle_t devfs_register (devfs_handle_t dir, { return NULL; } -static inline void devfs_unregister (devfs_handle_t de) -{ - return; -} static inline int devfs_mk_symlink (const char *name, const char *link) { return 0; -- cgit v1.2.3 From 02da7e62d509ae482ef59bd16bbe745fae24ca93 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Apr 2003 00:41:20 -0700 Subject: [PATCH] devfs: introduce devfs_mk_bdev Replaces devfs_register for block devices. Note that we do NOT pass in an operaion vector here - it was unused in devfs_register already and our block device code fundamentally ties the operations to the gendisk. There will be only very few callers of this one anyway.. --- fs/devfs/base.c | 48 +++++++++++++++++++++++++++++++++++++++-- include/linux/devfs_fs_kernel.h | 6 ++++++ 2 files changed, 52 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 75f3d57850b0..fbdbecdcc315 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -763,7 +763,6 @@ struct directory_type struct bdev_type { - struct block_device_operations *ops; dev_t dev; }; @@ -1491,7 +1490,6 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, } else if (S_ISBLK (mode)) { de->u.bdev.dev = dev; de->u.cdev.autogen = devnum != 0; - de->u.bdev.ops = ops; } else { PRINTK ("(%s): illegal mode: %x\n", name, mode); devfs_put (de); @@ -1517,6 +1515,52 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, } /* End Function devfs_register */ +int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) +{ + struct devfs_entry *dir = NULL, *de; + char buf[64]; + va_list args; + int error, n; + + if (!S_ISBLK(mode)) { + printk(KERN_WARNING "%s: invalide mode (%u) for %s\n", + __FUNCTION__, mode, buf); + return -EINVAL; + } + + va_start(args, fmt); + n = vsnprintf(buf, 64, fmt, args); + if (n >= 64 || !buf[0]) { + printk(KERN_WARNING "%s: invalid format string\n", + __FUNCTION__); + return -EINVAL; + } + + de = _devfs_prepare_leaf(&dir, buf, mode); + if (!de) { + printk(KERN_WARNING "%s: could not prepare leaf for %s\n", + __FUNCTION__, buf); + return -ENOMEM; /* could be more accurate... */ + } + + de->u.bdev.dev = dev; + + error = _devfs_append_entry(dir, de, NULL); + if (error) { + printk(KERN_WARNING "%s: could not append to parent for %s\n", + __FUNCTION__, buf); + goto out; + } + + devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); + out: + devfs_put(dir); + return error; +} + +EXPORT_SYMBOL(devfs_mk_bdev); + + /** * _devfs_unhook - Unhook a device entry from its parents list * @de: The entry to unhook. diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h index 24ad37027b73..e19d6d1ec733 100644 --- a/include/linux/devfs_fs_kernel.h +++ b/include/linux/devfs_fs_kernel.h @@ -25,6 +25,8 @@ extern devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, unsigned int flags, unsigned int major, unsigned int minor, umode_t mode, void *ops, void *info); +extern int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) + __attribute__((format (printf, 3, 4))); extern int devfs_mk_symlink (const char *name, const char *link); extern devfs_handle_t devfs_mk_dir(const char *fmt, ...) __attribute__((format (printf, 1, 2))); @@ -49,6 +51,10 @@ static inline devfs_handle_t devfs_register (devfs_handle_t dir, { return NULL; } +static inline int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) +{ + return 0; +} static inline int devfs_mk_symlink (const char *name, const char *link) { return 0; -- cgit v1.2.3 From 995058f217a4091e22af5798a922e2ab25f842ae Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Apr 2003 00:41:28 -0700 Subject: [PATCH] devfs: gendisk.devfs_name updates Previously gendisk.devfs_name was used only for partitioned devices or CDroms, and for the latter it was slightly broken. Fix it to work genericly for all gendisks. --- drivers/ide/ide-cd.c | 3 +- drivers/scsi/sr.c | 3 +- fs/devfs/util.c | 149 ---------------------------------------- fs/partitions/Makefile | 1 + fs/partitions/check.c | 50 +++++++------- fs/partitions/devfs.c | 134 ++++++++++++++++++++++++++++++++++++ fs/partitions/devfs.h | 10 +++ include/linux/devfs_fs_kernel.h | 16 ----- 8 files changed, 174 insertions(+), 192 deletions(-) create mode 100644 fs/partitions/devfs.c create mode 100644 fs/partitions/devfs.h (limited to 'include/linux') diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 44303c540eb4..3e7a5888bcd9 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3366,7 +3366,8 @@ static int ide_cdrom_attach (ide_drive_t *drive) DRIVER(drive)->busy++; g->minors = 1; g->minor_shift = 0; - strcpy(g->devfs_name, drive->devfs_name); + snprintf(g->devfs_name, sizeof(g->devfs_name), + "%s/cd", drive->devfs_name); g->driverfs_dev = &drive->gendev; g->flags = GENHD_FL_CD; if (ide_cdrom_setup(drive)) { diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 069a260bd879..ffb4478bef1e 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -569,7 +569,8 @@ static int sr_attach(struct scsi_device *sdev) get_capabilities(cd); sr_vendor_init(cd); - strcpy(disk->devfs_name, sdev->devfs_name); + snprintf(disk->devfs_name, sizeof(disk->devfs_name), + "%s/cd", sdev->devfs_name); disk->driverfs_dev = &sdev->sdev_driverfs_dev; register_cdrom(&cd->cdi); set_capacity(disk, cd->capacity); diff --git a/fs/devfs/util.c b/fs/devfs/util.c index 3ce61ea5a042..823652cb61bb 100644 --- a/fs/devfs/util.c +++ b/fs/devfs/util.c @@ -74,8 +74,6 @@ #include #include "internal.h" -#define PRINTK(format, args...) \ - {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);} int devfs_register_tape(const char *name) { @@ -257,139 +255,6 @@ void devfs_dealloc_devnum(umode_t mode, dev_t devnum) up(&device_list_mutex); } -struct unique_numspace -{ - spinlock_t init_lock; - unsigned char sem_initialised; - unsigned int num_free; /* Num free in bits */ - unsigned int length; /* Array length in bytes */ - unsigned long *bits; - struct semaphore semaphore; -}; - -#define UNIQUE_NUMBERSPACE_INITIALISER {SPIN_LOCK_UNLOCKED, 0, 0, 0, NULL} - - -/** - * devfs_alloc_unique_number - Allocate a unique (positive) number. - * @space: The number space to allocate from. - * - * Returns the allocated unique number, else a negative error code. - * This routine is thread safe and may block. - */ - -int devfs_alloc_unique_number (struct unique_numspace *space) -{ - int number; - unsigned int length; - - /* Get around stupid lack of semaphore initialiser */ - spin_lock (&space->init_lock); - if (!space->sem_initialised) - { - sema_init (&space->semaphore, 1); - space->sem_initialised = 1; - } - spin_unlock (&space->init_lock); - down (&space->semaphore); - if (space->num_free < 1) - { - void *bits; - - if (space->length < 16) length = 16; - else length = space->length << 1; - if ( ( bits = vmalloc (length) ) == NULL ) - { - up (&space->semaphore); - return -ENOMEM; - } - if (space->bits != NULL) - { - memcpy (bits, space->bits, space->length); - vfree (space->bits); - } - space->num_free = (length - space->length) << 3; - space->bits = bits; - memset (bits + space->length, 0, length - space->length); - space->length = length; - } - number = find_first_zero_bit (space->bits, space->length << 3); - --space->num_free; - __set_bit (number, space->bits); - up (&space->semaphore); - return number; -} /* End Function devfs_alloc_unique_number */ -EXPORT_SYMBOL(devfs_alloc_unique_number); - - -/** - * devfs_dealloc_unique_number - Deallocate a unique (positive) number. - * @space: The number space to deallocate from. - * @number: The number to deallocate. - * - * This routine is thread safe and may block. - */ - -void devfs_dealloc_unique_number (struct unique_numspace *space, int number) -{ - int was_set; - - if (number < 0) return; - down (&space->semaphore); - was_set = __test_and_clear_bit (number, space->bits); - if (was_set) ++space->num_free; - up (&space->semaphore); - if (!was_set) PRINTK ("(): number %d was already free\n", number); -} /* End Function devfs_dealloc_unique_number */ -EXPORT_SYMBOL(devfs_dealloc_unique_number); - -static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER; -static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER; - -void devfs_create_partitions(struct gendisk *disk) -{ - char dirname[64], diskname[64], symlink[16]; - - if (!disk->devfs_name) - sprintf(disk->devfs_name, "%s/disc%d", disk->disk_name, - disk->first_minor >> disk->minor_shift); - - devfs_mk_dir(disk->devfs_name); - disk->number = devfs_alloc_unique_number(&disc_numspace); - - sprintf(diskname, "%s/disc", disk->devfs_name); - devfs_register(NULL, diskname, 0, - disk->major, disk->first_minor, - S_IFBLK | S_IRUSR | S_IWUSR, - disk->fops, NULL); - - sprintf(symlink, "discs/disc%d", disk->number); - sprintf(dirname, "../%s", disk->devfs_name); - devfs_mk_symlink(symlink, dirname); - -} - -void devfs_create_cdrom(struct gendisk *disk) -{ - char dirname[64], cdname[64], symlink[16]; - - if (!disk->devfs_name) - strcat(disk->devfs_name, disk->disk_name); - - devfs_mk_dir(disk->devfs_name); - disk->number = devfs_alloc_unique_number(&cdrom_numspace); - - sprintf(cdname, "%s/cd", disk->devfs_name); - devfs_register(NULL, cdname, 0, - disk->major, disk->first_minor, - S_IFBLK | S_IRUGO | S_IWUGO, - disk->fops, NULL); - - sprintf(symlink, "cdroms/cdrom%d", disk->number); - sprintf(dirname, "../%s", disk->devfs_name); - devfs_mk_symlink(symlink, dirname); -} - void devfs_register_partition(struct gendisk *dev, int part) { char devname[64]; @@ -400,17 +265,3 @@ void devfs_register_partition(struct gendisk *dev, int part) S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); } - -void devfs_remove_partitions(struct gendisk *disk) -{ - devfs_remove("discs/disc%d", disk->number); - devfs_remove(disk->devfs_name); - devfs_dealloc_unique_number(&disc_numspace, disk->number); -} - -void devfs_remove_cdrom(struct gendisk *disk) -{ - devfs_remove("cdroms/cdrom%d", disk->number); - devfs_remove(disk->devfs_name); - devfs_dealloc_unique_number(&cdrom_numspace, disk->number); -} diff --git a/fs/partitions/Makefile b/fs/partitions/Makefile index 4d9c91a4c33a..4c83c17969e1 100644 --- a/fs/partitions/Makefile +++ b/fs/partitions/Makefile @@ -4,6 +4,7 @@ obj-y := check.o +obj-$(CONFIG_DEVFS_FS) += devfs.o obj-$(CONFIG_ACORN_PARTITION) += acorn.o obj-$(CONFIG_AMIGA_PARTITION) += amiga.o obj-$(CONFIG_ATARI_PARTITION) += atari.o diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 647f0357e30c..ddd1b88d7819 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -19,8 +19,10 @@ #include #include #include +#include #include "check.h" +#include "devfs.h" #include "acorn.h" #include "amiga.h" @@ -94,25 +96,24 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) = char *disk_name(struct gendisk *hd, int part, char *buf) { - if (!part) { #ifdef CONFIG_DEVFS_FS - if (hd->devfs_name) - sprintf(buf, "%s/%s", hd->devfs_name, - (hd->flags & GENHD_FL_CD) ? "cd" : "disc"); - else -#endif - sprintf(buf, "%s", hd->disk_name); - } else { -#ifdef CONFIG_DEVFS_FS - if (hd->devfs_name) + if (hd->devfs_name[0] != '\0') { + if (part) sprintf(buf, "%s/part%d", hd->devfs_name, part); + else if (hd->minors != 1) + sprintf(buf, "%s/disc", hd->devfs_name); else -#endif - if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) - sprintf(buf, "%sp%d", hd->disk_name, part); - else - sprintf(buf, "%s%d", hd->disk_name, part); + sprintf(buf, "%s", hd->devfs_name); + return buf; } +#endif + + if (!part) + sprintf(buf, "%s", hd->disk_name); + else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) + sprintf(buf, "%sp%d", hd->disk_name, part); + else + sprintf(buf, "%s%d", hd->disk_name, part); return buf; } @@ -128,7 +129,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev) return NULL; #ifdef CONFIG_DEVFS_FS - if (hd->devfs_name) { + if (hd->devfs_name[0] != '\0') { printk(KERN_INFO " /dev/%s:", hd->devfs_name); sprintf(state->name, "p"); } @@ -284,12 +285,12 @@ void register_disk(struct gendisk *disk) return; disk_sysfs_symlinks(disk); - if (disk->flags & GENHD_FL_CD) - devfs_create_cdrom(disk); - /* No minors to use for partitions */ - if (disk->minors == 1) + if (disk->minors == 1) { + if (disk->devfs_name[0] != '\0') + devfs_add_disk(disk); return; + } /* No such device (e.g., media were just removed) */ if (!get_capacity(disk)) @@ -299,7 +300,7 @@ void register_disk(struct gendisk *disk) if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0) return; state = check_partition(disk, bdev); - devfs_create_partitions(disk); + devfs_add_partitioned(disk); if (state) { for (j = 1; j < state->limit; j++) { sector_t size = state->parts[j].size; @@ -392,10 +393,9 @@ void del_gendisk(struct gendisk *disk) unlink_gendisk(disk); disk_stat_set_all(disk, 0); disk->stamp = disk->stamp_idle = 0; - if (disk->flags & GENHD_FL_CD) - devfs_remove_cdrom(disk); - else - devfs_remove_partitions(disk); + + devfs_remove_disk(disk); + if (disk->driverfs_dev) { sysfs_remove_link(&disk->kobj, "device"); sysfs_remove_link(&disk->driverfs_dev->kobj, "block"); diff --git a/fs/partitions/devfs.c b/fs/partitions/devfs.c new file mode 100644 index 000000000000..67362483b4dc --- /dev/null +++ b/fs/partitions/devfs.c @@ -0,0 +1,134 @@ +/* + * This tries to keep block devices away from devfs as much as possible. + */ +#include +#include +#include +#include +#include +#include + + +struct unique_numspace { + u32 num_free; /* Num free in bits */ + u32 length; /* Array length in bytes */ + unsigned long *bits; + struct semaphore mutex; +}; + +static DECLARE_MUTEX(numspace_mutex); + +static int expand_numspace(struct unique_numspace *s) +{ + u32 length; + void *bits; + + if (s->length < 16) + length = 16; + else + length = s->length << 1; + + bits = vmalloc(length); + if (!bits) + return -ENOMEM; + if (s->bits) { + memcpy(bits, s->bits, s->length); + vfree(s->bits); + } + + s->num_free = (length - s->length) << 3; + s->bits = bits; + memset(bits + s->length, 0, length - s->length); + s->length = length; + + return 0; +} + +static int alloc_unique_number(struct unique_numspace *s) +{ + int rval = 0; + + down(&numspace_mutex); + if (s->num_free < 1) + rval = expand_numspace(s); + if (!rval) { + rval = find_first_zero_bit(s->bits, s->length << 3); + --s->num_free; + __set_bit(rval, s->bits); + } + up(&numspace_mutex); + + return rval; +} + +static void dealloc_unique_number(struct unique_numspace *s, int number) +{ + int old_val; + + if (number >= 0) { + down(&numspace_mutex); + old_val = __test_and_clear_bit(number, s->bits); + if (old_val) + ++s->num_free; + up(&numspace_mutex); + } +} + +static struct unique_numspace disc_numspace; +static struct unique_numspace cdrom_numspace; + +void devfs_add_partitioned(struct gendisk *disk) +{ + char dirname[64], symlink[16]; + + if (disk->devfs_name[0] != '\0') + sprintf(disk->devfs_name, "%s/disc%d", disk->disk_name, + disk->first_minor >> disk->minor_shift); + + devfs_mk_dir(disk->devfs_name); + devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), + S_IFBLK|S_IRUSR|S_IWUSR, + "%s/disc", disk->devfs_name); + + disk->number = alloc_unique_number(&disc_numspace); + + sprintf(symlink, "discs/disc%d", disk->number); + sprintf(dirname, "../%s", disk->devfs_name); + devfs_mk_symlink(symlink, dirname); + +} + +void devfs_add_disk(struct gendisk *disk) +{ + devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), + (disk->flags & GENHD_FL_CD) ? + S_IFBLK|S_IRUGO|S_IWUGO : + S_IFBLK|S_IRUSR|S_IWUSR, + "%s", disk->devfs_name); + + if (disk->flags & GENHD_FL_CD) { + char dirname[64], symlink[16]; + + disk->number = alloc_unique_number(&cdrom_numspace); + + sprintf(symlink, "cdroms/cdrom%d", disk->number); + sprintf(dirname, "../%s", disk->devfs_name); + devfs_mk_symlink(symlink, dirname); + } +} + +void devfs_remove_disk(struct gendisk *disk) +{ + if (disk->minors != 1) { + devfs_remove("discs/disc%d", disk->number); + dealloc_unique_number(&disc_numspace, disk->number); + devfs_remove("%s/disc", disk->devfs_name); + } + if (disk->flags & GENHD_FL_CD) { + devfs_remove("cdroms/cdrom%d", disk->number); + dealloc_unique_number(&cdrom_numspace, disk->number); + } + devfs_remove(disk->devfs_name); +} + + diff --git a/fs/partitions/devfs.h b/fs/partitions/devfs.h new file mode 100644 index 000000000000..176118b4e492 --- /dev/null +++ b/fs/partitions/devfs.h @@ -0,0 +1,10 @@ + +#ifdef CONFIG_DEVFS_FS +void devfs_add_disk(struct gendisk *dev); +void devfs_add_partitioned(struct gendisk *dev); +void devfs_remove_disk(struct gendisk *dev); +#else +# define devfs_add_disk(disk) do { } while (0) +# define devfs_add_partitioned(disk) do { } while (0) +# define devfs_remove_disk(disk) do { } while (0) +#endif diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h index e19d6d1ec733..a45a4060236d 100644 --- a/include/linux/devfs_fs_kernel.h +++ b/include/linux/devfs_fs_kernel.h @@ -34,10 +34,6 @@ extern void devfs_remove(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern int devfs_register_tape(const char *name); extern void devfs_unregister_tape(int num); -extern void devfs_create_partitions(struct gendisk *dev); -extern void devfs_create_cdrom(struct gendisk *dev); -extern void devfs_remove_partitions(struct gendisk *dev); -extern void devfs_remove_cdrom(struct gendisk *dev); extern void devfs_register_partition(struct gendisk *dev, int part); extern void mount_devfs_fs(void); #else /* CONFIG_DEVFS_FS */ @@ -73,18 +69,6 @@ static inline int devfs_register_tape (devfs_handle_t de) static inline void devfs_unregister_tape(int num) { } -static inline void devfs_create_partitions(struct gendisk *dev) -{ -} -static inline void devfs_create_cdrom(struct gendisk *dev) -{ -} -static inline void devfs_remove_partitions(struct gendisk *dev) -{ -} -static inline void devfs_remove_cdrom(struct gendisk *dev) -{ -} static inline void devfs_register_partition(struct gendisk *dev, int part) { } -- cgit v1.2.3 From 4b28bcb37986cf817cbfa38f1fd82f320df8f357 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Apr 2003 00:49:38 -0700 Subject: [PATCH] initrd.h split the initrd stuff out of blk.h, it's only needed in the boot code and the ramdisk driver. --- arch/alpha/kernel/core_irongate.c | 1 + arch/alpha/kernel/setup.c | 6 +----- arch/alpha/mm/numa.c | 4 +--- arch/arm/kernel/setup.c | 2 +- arch/arm/mach-clps711x/fortunet.c | 2 +- arch/arm/mm/init.c | 2 +- arch/i386/kernel/setup.c | 4 +--- arch/i386/mm/discontig.c | 4 +--- arch/ia64/kernel/setup.c | 5 +---- arch/m68k/kernel/setup.c | 5 +---- arch/mips/gt64120/momenco_ocelot/setup.c | 2 +- arch/mips/kernel/setup.c | 2 +- arch/mips64/mm/init.c | 4 +--- arch/parisc/kernel/setup.c | 2 +- arch/parisc/mm/init.c | 2 +- arch/ppc/kernel/setup.c | 2 +- arch/ppc/mm/init.c | 4 +--- arch/ppc/platforms/4xx/oak_setup.c | 2 +- arch/ppc/platforms/adir_setup.c | 2 +- arch/ppc/platforms/apus_setup.c | 2 +- arch/ppc/platforms/ev64260_setup.c | 2 +- arch/ppc/platforms/gemini_setup.c | 2 +- arch/ppc/platforms/k2_setup.c | 2 +- arch/ppc/platforms/lopec_setup.c | 2 +- arch/ppc/platforms/mcpn765_setup.c | 2 +- arch/ppc/platforms/menf1_setup.c | 2 +- arch/ppc/platforms/mvme5100_setup.c | 2 +- arch/ppc/platforms/pal4_setup.c | 2 +- arch/ppc/platforms/pcore_setup.c | 2 +- arch/ppc/platforms/pmac_setup.c | 2 +- arch/ppc/platforms/powerpmc250.c | 2 +- arch/ppc/platforms/pplus_setup.c | 2 +- arch/ppc/platforms/prep_setup.c | 2 +- arch/ppc/platforms/prpmc750_setup.c | 2 +- arch/ppc/platforms/prpmc800_setup.c | 2 +- arch/ppc/platforms/sandpoint_setup.c | 2 +- arch/ppc/platforms/spruce_setup.c | 2 +- arch/ppc/platforms/zx4500_setup.c | 2 +- arch/ppc/syslib/m8260_setup.c | 2 +- arch/ppc/syslib/m8xx_setup.c | 2 +- arch/ppc/syslib/ppc4xx_setup.c | 2 +- arch/ppc64/kernel/chrp_setup.c | 2 +- arch/ppc64/kernel/iSeries_setup.c | 2 +- arch/ppc64/kernel/setup.c | 2 +- arch/s390/kernel/setup.c | 4 +--- arch/sh/kernel/setup.c | 4 +--- arch/sparc/mm/init.c | 4 +--- arch/sparc64/mm/init.c | 2 +- arch/um/kernel/initrd_kern.c | 2 +- arch/x86_64/kernel/setup.c | 4 +--- drivers/block/rd.c | 6 +++++- include/linux/blk.h | 18 ------------------ include/linux/initrd.h | 16 ++++++++++++++++ init/do_mounts_rd.c | 1 + init/main.c | 1 + 55 files changed, 73 insertions(+), 96 deletions(-) create mode 100644 include/linux/initrd.h (limited to 'include/linux') diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c index 3ce8877195f6..b1bca4ad74df 100644 --- a/arch/alpha/kernel/core_irongate.c +++ b/arch/alpha/kernel/core_irongate.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 9ebcddc915f0..8ad279f3aae9 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -32,11 +32,7 @@ #include #include #include - -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif - +#include #ifdef CONFIG_MAGIC_SYSRQ #include #include diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c index b7618f261b89..5a7ad83d367c 100644 --- a/arch/alpha/mm/numa.c +++ b/arch/alpha/mm/numa.c @@ -12,9 +12,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif +#include #include #include diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 881e7ee4c89c..676630ca56f9 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c index 31ea65434883..864699216743 100644 --- a/arch/arm/mach-clps711x/fortunet.c +++ b/arch/arm/mach-clps711x/fortunet.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 8feead22ec00..b0aa4a9d087b 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 28b6d62a29db..332975cd16d8 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -29,9 +29,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif +#include #include #include #include diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c index 8a4175bebc52..382efc980923 100644 --- a/arch/i386/mm/discontig.c +++ b/arch/i386/mm/discontig.c @@ -27,9 +27,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif +#include #include #include diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 06981423d720..4b70c649a88f 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -42,10 +43,6 @@ #include #include -#ifdef CONFIG_BLK_DEV_RAM -# include -#endif - #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE) # error "struct cpuinfo_ia64 too big!" #endif diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index c8f2f7211eb5..349ffcc96dce 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -41,10 +42,6 @@ extern void sun_serial_setup(void); #endif -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif - unsigned long m68k_machtype; unsigned long m68k_cputype; unsigned long m68k_fputype; diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c index 57cf41a27114..23635c7e87fc 100644 --- a/arch/mips/gt64120/momenco_ocelot/setup.c +++ b/arch/mips/gt64120/momenco_ocelot/setup.c @@ -60,7 +60,7 @@ #include #include #include -#include +#include #include #include "ocelot_pld.h" diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 26a70f6d1a13..3dce39970712 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c index e194ab99c142..4f7fe2cf6726 100644 --- a/arch/mips64/mm/init.c +++ b/arch/mips64/mm/init.c @@ -21,9 +21,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif +#include #include #include diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index b08b901c6112..5dde472c50fc 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -29,7 +29,7 @@ #include #include -#include /* for initrd_start and initrd_end */ +#include #include #include #include diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 3b382ef901da..f976e13c36d0 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -15,7 +15,7 @@ #include #include #include /* for hppa_dma_ops and pcxl_dma_ops */ -#include /* for initrd_start and initrd_end */ +#include #include #include diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index e729d81d3aad..5408bc98bded 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 670bc174261b..9cf80494865a 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -28,9 +28,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include /* for initrd_* */ -#endif +#include #include #include diff --git a/arch/ppc/platforms/4xx/oak_setup.c b/arch/ppc/platforms/4xx/oak_setup.c index be4064dd676e..470361e356df 100644 --- a/arch/ppc/platforms/4xx/oak_setup.c +++ b/arch/ppc/platforms/4xx/oak_setup.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/ppc/platforms/adir_setup.c b/arch/ppc/platforms/adir_setup.c index bf65e2a56c76..d34d65c0cb64 100644 --- a/arch/ppc/platforms/adir_setup.c +++ b/arch/ppc/platforms/adir_setup.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c index cd1ac142249e..ac12e43585d9 100644 --- a/arch/ppc/platforms/apus_setup.c +++ b/arch/ppc/platforms/apus_setup.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include /* Needs INITSERIAL call in head.S! */ diff --git a/arch/ppc/platforms/ev64260_setup.c b/arch/ppc/platforms/ev64260_setup.c index eb090a3d7aaa..5ccbf7608967 100644 --- a/arch/ppc/platforms/ev64260_setup.c +++ b/arch/ppc/platforms/ev64260_setup.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c index dc976899f604..6e544e82961e 100644 --- a/arch/ppc/platforms/gemini_setup.c +++ b/arch/ppc/platforms/gemini_setup.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/k2_setup.c b/arch/ppc/platforms/k2_setup.c index fb62f99422ab..8d5946f54e2f 100644 --- a/arch/ppc/platforms/k2_setup.c +++ b/arch/ppc/platforms/k2_setup.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c index 2e96b741af31..786f4305db96 100644 --- a/arch/ppc/platforms/lopec_setup.c +++ b/arch/ppc/platforms/lopec_setup.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/ppc/platforms/mcpn765_setup.c b/arch/ppc/platforms/mcpn765_setup.c index 91b6971cc6a2..8199c1188863 100644 --- a/arch/ppc/platforms/mcpn765_setup.c +++ b/arch/ppc/platforms/mcpn765_setup.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/menf1_setup.c b/arch/ppc/platforms/menf1_setup.c index 3e8a75336a81..b202350a7657 100644 --- a/arch/ppc/platforms/menf1_setup.c +++ b/arch/ppc/platforms/menf1_setup.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/mvme5100_setup.c b/arch/ppc/platforms/mvme5100_setup.c index 9c5883ec7701..95c2911a7bbd 100644 --- a/arch/ppc/platforms/mvme5100_setup.c +++ b/arch/ppc/platforms/mvme5100_setup.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c index 48a3db47fc88..1a28f3d92f4c 100644 --- a/arch/ppc/platforms/pal4_setup.c +++ b/arch/ppc/platforms/pal4_setup.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/pcore_setup.c b/arch/ppc/platforms/pcore_setup.c index cf0503959265..b9588f08a008 100644 --- a/arch/ppc/platforms/pcore_setup.c +++ b/arch/ppc/platforms/pcore_setup.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c index 09162642a8fb..dad51708b8da 100644 --- a/arch/ppc/platforms/pmac_setup.c +++ b/arch/ppc/platforms/pmac_setup.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c index 9be3f52e6b1e..9a2125af6f66 100644 --- a/arch/ppc/platforms/powerpmc250.c +++ b/arch/ppc/platforms/powerpmc250.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/pplus_setup.c b/arch/ppc/platforms/pplus_setup.c index 751a06465e85..52c626fbe53a 100644 --- a/arch/ppc/platforms/pplus_setup.c +++ b/arch/ppc/platforms/pplus_setup.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index d5992324dd8b..71c42e9db752 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/prpmc750_setup.c b/arch/ppc/platforms/prpmc750_setup.c index 0857a1d13765..f4cfbd0c42e5 100644 --- a/arch/ppc/platforms/prpmc750_setup.c +++ b/arch/ppc/platforms/prpmc750_setup.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/prpmc800_setup.c b/arch/ppc/platforms/prpmc800_setup.c index 2ce1c3b1e6db..e41ac0aa2a34 100644 --- a/arch/ppc/platforms/prpmc800_setup.c +++ b/arch/ppc/platforms/prpmc800_setup.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/sandpoint_setup.c b/arch/ppc/platforms/sandpoint_setup.c index a99f22a8857e..e93a253a9317 100644 --- a/arch/ppc/platforms/sandpoint_setup.c +++ b/arch/ppc/platforms/sandpoint_setup.c @@ -64,7 +64,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/spruce_setup.c b/arch/ppc/platforms/spruce_setup.c index bbd0fa92a933..54a7bdf059b8 100644 --- a/arch/ppc/platforms/spruce_setup.c +++ b/arch/ppc/platforms/spruce_setup.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/platforms/zx4500_setup.c b/arch/ppc/platforms/zx4500_setup.c index 739bdc373b67..7fb5b8a5d1ad 100644 --- a/arch/ppc/platforms/zx4500_setup.c +++ b/arch/ppc/platforms/zx4500_setup.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c index 3d0148b4b787..f5f773beb324 100644 --- a/arch/ppc/syslib/m8260_setup.c +++ b/arch/ppc/syslib/m8260_setup.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index aea997fa5df4..15dc761f887e 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c index 803e707e8880..3fc259eb6817 100644 --- a/arch/ppc/syslib/ppc4xx_setup.c +++ b/arch/ppc/syslib/ppc4xx_setup.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c index 8b4fff8c7e13..2dfdd6c3b4e8 100644 --- a/arch/ppc64/kernel/chrp_setup.c +++ b/arch/ppc64/kernel/chrp_setup.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c index 15e621d5368b..7d26eabd42b4 100644 --- a/arch/ppc64/kernel/iSeries_setup.c +++ b/arch/ppc64/kernel/iSeries_setup.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index 2472fcc916e4..9681d815ad31 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index f25b904ecadd..1c43b3d40787 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -29,9 +29,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif +#include #include #include #include diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 6043bb426965..2b33c990517b 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -25,9 +25,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif +#include #include #include #include diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index 72ead972a5e2..b1692c1a21da 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -18,9 +18,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif +#include #include #include #include diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 8aeaf3e18259..773a8eaf2383 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/um/kernel/initrd_kern.c b/arch/um/kernel/initrd_kern.c index a8f7e70f1a17..fc568af468b9 100644 --- a/arch/um/kernel/initrd_kern.c +++ b/arch/um/kernel/initrd_kern.c @@ -5,7 +5,7 @@ #include "linux/init.h" #include "linux/bootmem.h" -#include "linux/blk.h" +#include "linux/initrd.h" #include "asm/types.h" #include "user_util.h" #include "kern_util.h" diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 18a5adfe572c..3f0a3e66aff6 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -28,9 +28,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif +#include #include #include #include diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 1692c41b5221..c72d687910e5 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -50,9 +50,13 @@ #include #include #include +#include +#include +#include +#include #include /* for invalidate_bdev() */ #include -#include +#include #include #include diff --git a/include/linux/blk.h b/include/linux/blk.h index a09126ffdacc..8523e8f841e3 100644 --- a/include/linux/blk.h +++ b/include/linux/blk.h @@ -12,24 +12,6 @@ extern void set_disk_ro(struct gendisk *disk, int flag); extern void add_disk_randomness(struct gendisk *disk); extern void rand_initialize_disk(struct gendisk *disk); -#ifdef CONFIG_BLK_DEV_RAM - -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ - -#ifdef CONFIG_BLK_DEV_INITRD - -#define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */ - -extern unsigned long initrd_start,initrd_end; -extern int initrd_below_start_ok; /* 1 if it is not an error if initrd_start < memory_start */ -void initrd_init(void); - -#endif /* CONFIG_BLK_DEV_INITRD */ - -#endif - /* * end_request() and friends. Must be called with the request queue spinlock * acquired. All functions called within end_request() _must_be_ atomic. diff --git a/include/linux/initrd.h b/include/linux/initrd.h new file mode 100644 index 000000000000..d1978c358b12 --- /dev/null +++ b/include/linux/initrd.h @@ -0,0 +1,16 @@ + +#define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */ + +/* 1 = load ramdisk, 0 = don't load */ +extern int rd_doload; + +/* 1 = prompt for ramdisk, 0 = don't prompt */ +extern int rd_prompt; + +/* starting block # of image */ +extern int rd_image_start; + +/* 1 if it is not an error if initrd_start < memory_start */ +extern int initrd_below_start_ok; + +extern unsigned long initrd_start, initrd_end; diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index be82c3fb89f1..0057b1c6f19b 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "do_mounts.h" diff --git a/init/main.c b/init/main.c index 8154b8b6ec35..edb701549dff 100644 --- a/init/main.c +++ b/init/main.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 5f390ed0436b7d1e27cdc9a8ec9ceffdd657cee9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Apr 2003 00:49:56 -0700 Subject: [PATCH] replace __blk_run_queue with blk_run_queue All callers of __blk_run_queue are of the form spin_lock_irqsave(q->queue_lock, flags); __blk_run_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); Replace it with a blk_run_queue that does the locking itself. --- drivers/block/ll_rw_blk.c | 8 ++++++-- drivers/scsi/scsi_error.c | 8 ++------ drivers/scsi/scsi_lib.c | 27 +++++++++------------------ include/linux/blkdev.h | 2 +- 4 files changed, 18 insertions(+), 27 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index e14210308577..c858bb4d7b81 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -1078,10 +1078,14 @@ void blk_stop_queue(request_queue_t *q) * blk_run_queue - run a single device queue * @q The queue to run */ -void __blk_run_queue(request_queue_t *q) +void blk_run_queue(struct request_queue *q) { + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); blk_remove_plug(q); q->request_fn(q); + spin_unlock_irqrestore(q->queue_lock, flags); } /** @@ -2267,5 +2271,5 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags); EXPORT_SYMBOL(blk_start_queue); EXPORT_SYMBOL(blk_stop_queue); EXPORT_SYMBOL(__blk_stop_queue); -EXPORT_SYMBOL(__blk_run_queue); +EXPORT_SYMBOL(blk_run_queue); EXPORT_SYMBOL(blk_run_queues); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index d22bbbc4d81e..a57c5aa6980c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1401,7 +1401,6 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) static void scsi_restart_operations(struct Scsi_Host *shost) { struct scsi_device *sdev; - unsigned long flags; /* * If the door was locked, we need to insert a door lock request @@ -1430,11 +1429,8 @@ static void scsi_restart_operations(struct Scsi_Host *shost) * now that error recovery is done, we will need to ensure that these * requests are started. */ - list_for_each_entry(sdev, &shost->my_devices, siblings) { - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - __blk_run_queue(sdev->request_queue); - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); - } + list_for_each_entry(sdev, &shost->my_devices, siblings) + blk_run_queue(sdev->request_queue); } /** diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 598c945ae33f..59b526ba0c72 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -328,7 +328,7 @@ void scsi_setup_cmd_retry(struct scsi_cmnd *cmd) /* * Called for single_lun devices on IO completion. Clear starget_sdev_user, - * and call __blk_run_queue for all the scsi_devices on the target - + * and call blk_run_queue for all the scsi_devices on the target - * including current_sdev first. * * Called with *no* scsi locks held. @@ -336,7 +336,7 @@ void scsi_setup_cmd_retry(struct scsi_cmnd *cmd) static void scsi_single_lun_run(struct scsi_device *current_sdev) { struct scsi_device *sdev; - unsigned long flags, flags2; + unsigned long flags; spin_lock_irqsave(current_sdev->host->host_lock, flags); WARN_ON(!current_sdev->sdev_target->starget_sdev_user); @@ -344,14 +344,12 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) spin_unlock_irqrestore(current_sdev->host->host_lock, flags); /* - * Call __blk_run_queue for all LUNs on the target, starting with + * Call blk_run_queue for all LUNs on the target, starting with * current_sdev. We race with others (to set starget_sdev_user), * but in most cases, we will be first. Ideally, each LU on the * target would get some limited time or requests on the target. */ - spin_lock_irqsave(current_sdev->request_queue->queue_lock, flags2); - __blk_run_queue(current_sdev->request_queue); - spin_unlock_irqrestore(current_sdev->request_queue->queue_lock, flags2); + blk_run_queue(current_sdev->request_queue); spin_lock_irqsave(current_sdev->host->host_lock, flags); if (current_sdev->sdev_target->starget_sdev_user) { @@ -366,11 +364,8 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) spin_unlock_irqrestore(current_sdev->host->host_lock, flags); list_for_each_entry(sdev, ¤t_sdev->same_target_siblings, - same_target_siblings) { - spin_lock_irqsave(sdev->request_queue->queue_lock, flags2); - __blk_run_queue(sdev->request_queue); - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags2); - } + same_target_siblings) + blk_run_queue(sdev->request_queue); } /* @@ -452,7 +447,7 @@ void scsi_queue_next_request(request_queue_t *q, struct scsi_cmnd *cmd) (shost->host_busy >= shost->can_queue))) { /* * As long as shost is accepting commands and we have - * starved queues, call __blk_run_queue. scsi_request_fn + * starved queues, call blk_run_queue. scsi_request_fn * drops the queue_lock and can add us back to the * starved_list. * @@ -465,9 +460,7 @@ void scsi_queue_next_request(request_queue_t *q, struct scsi_cmnd *cmd) list_del_init(&sdev->starved_entry); spin_unlock_irqrestore(shost->host_lock, flags); - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - __blk_run_queue(sdev->request_queue); - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); + blk_run_queue(sdev->request_queue); spin_lock_irqsave(shost->host_lock, flags); if (unlikely(!list_empty(&sdev->starved_entry))) @@ -480,9 +473,7 @@ void scsi_queue_next_request(request_queue_t *q, struct scsi_cmnd *cmd) } spin_unlock_irqrestore(shost->host_lock, flags); - spin_lock_irqsave(q->queue_lock, flags); - __blk_run_queue(q); - spin_unlock_irqrestore(q->queue_lock, flags); + blk_run_queue(q); } /* diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index ee3f66a5e60c..36741d178f34 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -341,7 +341,7 @@ extern int scsi_cmd_ioctl(struct block_device *, unsigned int, unsigned long); extern void blk_start_queue(request_queue_t *q); extern void blk_stop_queue(request_queue_t *q); extern void __blk_stop_queue(request_queue_t *q); -extern void __blk_run_queue(request_queue_t *q); +extern void blk_run_queue(request_queue_t *q); static inline request_queue_t *bdev_get_queue(struct block_device *bdev) { -- cgit v1.2.3