Marcelo,
This patch, which requires the previous BUG_ON part 1 patch, changes a
few uses of BUG -> BUG_ON in fast paths in the kernel, partly to
demonstrate readability, partly for the optimization, mostly to give a
reason to take part 1. ;)
Patch is against 2.4.19-pre5, please apply.
Robert Love
diff -urN linux-2.4.19-pre5/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- linux-2.4.19-pre5/arch/i386/kernel/smp.c Sat Mar 30 18:27:32 2002
+++ linux/arch/i386/kernel/smp.c Sat Mar 30 18:34:07 2002
@@ -301,8 +301,7 @@
*/
static void inline leave_mm (unsigned long cpu)
{
- if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
- BUG();
+ BUG_ON(cpu_tlbstate[cpu].state == TLBSTATE_OK);
clear_bit(cpu, &cpu_tlbstate[cpu].active_mm->cpu_vm_mask);
}
diff -urN linux-2.4.19-pre5/kernel/exit.c linux/kernel/exit.c
--- linux-2.4.19-pre5/kernel/exit.c Sat Mar 30 18:26:41 2002
+++ linux/kernel/exit.c Sat Mar 30 18:34:07 2002
@@ -316,7 +316,7 @@
mm_release();
if (mm) {
atomic_inc(&mm->mm_count);
- if (mm != tsk->active_mm) BUG();
+ BUG_ON(mm != tsk->active_mm);
/* more a memory barrier than a real lock */
task_lock(tsk);
tsk->mm = NULL;
diff -urN linux-2.4.19-pre5/kernel/fork.c linux/kernel/fork.c
--- linux-2.4.19-pre5/kernel/fork.c Sat Mar 30 18:26:41 2002
+++ linux/kernel/fork.c Sat Mar 30 18:34:07 2002
@@ -251,7 +251,7 @@
*/
inline void __mmdrop(struct mm_struct *mm)
{
- if (mm == &init_mm) BUG();
+ BUG_ON(mm == &init_mm);
pgd_free(mm->pgd);
destroy_context(mm);
free_mm(mm);
diff -urN linux-2.4.19-pre5/kernel/sched.c linux/kernel/sched.c
--- linux-2.4.19-pre5/kernel/sched.c Sat Mar 30 18:26:41 2002
+++ linux/kernel/sched.c Sat Mar 30 18:34:07 2002
@@ -556,7 +556,7 @@
spin_lock_prefetch(&runqueue_lock);
- if (!current->active_mm) BUG();
+ BUG_ON(!current->active_mm);
need_resched_back:
prev = current;
this_cpu = prev->processor;
@@ -675,12 +675,12 @@
struct mm_struct *mm = next->mm;
struct mm_struct *oldmm = prev->active_mm;
if (!mm) {
- if (next->active_mm) BUG();
+ BUG_ON(next->active_mm);
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next, this_cpu);
} else {
- if (next->active_mm != mm) BUG();
+ BUG_ON(next->active_mm != mm);
switch_mm(oldmm, mm, next, this_cpu);
}
diff -urN linux-2.4.19-pre5/mm/slab.c linux/mm/slab.c
--- linux-2.4.19-pre5/mm/slab.c Sat Mar 30 18:26:41 2002
+++ linux/mm/slab.c Sat Mar 30 18:34:07 2002
@@ -665,8 +665,7 @@
* Always checks flags, a caller might be expecting debug
* support which isn't available.
*/
- if (flags & ~CREATE_MASK)
- BUG();
+ BUG_ON(flags & ~CREATE_MASK);
/* Get cache's description obj. */
cachep = (kmem_cache_t *) kmem_cache_alloc(&cache_cache, SLAB_KERNEL);
diff -urN linux-2.4.19-pre5/mm/vmscan.c linux/mm/vmscan.c
--- linux-2.4.19-pre5/mm/vmscan.c Sat Mar 30 18:26:41 2002
+++ linux/mm/vmscan.c Sat Mar 30 18:34:07 2002
@@ -233,8 +233,7 @@
pgdir = pgd_offset(mm, address);
end = vma->vm_end;
- if (address >= end)
- BUG();
+ BUG_ON(address >= end);
do {
count = swap_out_pgd(mm, vma, pgdir, address, end, count, classzone);
if (!count)
@@ -353,10 +352,8 @@
page = list_entry(entry, struct page, lru);
- if (unlikely(!PageLRU(page)))
- BUG();
- if (unlikely(PageActive(page)))
- BUG();
+ BUG_ON(!PageLRU(page));
+ BUG_ON(PageActive(page));
list_del(entry);
list_add(entry, &inactive_list);
Marcelo,
This patch is against 2.4.19-pre5, please apply.
The following change would primarily interest people using linux on
embedded boards, but should be usable by any system.
This patch creates one new entry in the proc filesystem.
"/proc/net/bootpc" is now created and contains information if the
kernel received a bootp packet during bootup. The output format is
identical to the "bootpc" userspace program. On an embedded system,
this can save 10-15 seconds from boot time (if running 'bootpc' as one
of your init scripts). Also, this removes a possible point of failure
during bootup.
We think this patch would be useful to put in the 2.4.x stream.
But there's no reason it can't also go in 2.5.x as well. We also have
a 2.2.x version availble if there's any interest in that as well.
So what do people think? Should this go in 2.4 or 2.5?
Is this worthwhile to pursue putting this in (it's very useful to us,
so we figured others could use it)?
Should i send this to Linus for 2.5 inclusion as well?
Here's some sample output from the code:
bash-2.04$ cat /proc/net/bootpc
SERVER='10.40.4.101'
IPADDR='10.40.14.83'
BOOTFILE='/tftpboot/core_24work'
NETMASK='255.255.255.0'
GATEWAYS_1='10.40.14.1'
GATEWAYS='10.40.14.1'
YPDOMAIN='locoland'
HOSTNAME='somecard'
T129='configfile_1a'
NTPSRVS_1='10.40.4.101'
NTPSRVS='10.40.4.101'
Patch is below. Thanks.
--
Craig Arsenault.
+------------------------------------------------------+
http://www.wombat.ca Why? Why not.
http://www.washington.edu/pine/ Pine @ the U of Wash.
+-------------=*sent via Pine4.42*=--------------------+
diff -Nur linux-2.4.19-pre5/Documentation/Configure.help linux-2.4.19-pre5_NEW/Documentation/Configure.help
--- linux-2.4.19-pre5/Documentation/Configure.help Wed Apr 3 17:51:42 2002
+++ linux-2.4.19-pre5_NEW/Documentation/Configure.help Wed Apr 3 18:00:14 2002
@@ -5241,6 +5241,12 @@
want to use BOOTP, a BOOTP server must be operating on your network.
Read <file:Documentation/nfsroot.txt> for details.
+Provide bootpc style /proc file
+CONFIG_IP_BOOTP_PROC
+ If you say Y here, the file /proc/net/bootpc will output the bootp
+ record retrieved at boot time in a format identical to the bootpc
+ client program.
+
DHCP support
CONFIG_IP_PNP_DHCP
If you want your Linux box to mount its whole root file system (the
diff -Nur linux-2.4.19-pre5/net/ipv4/Config.in linux-2.4.19-pre5_NEW/net/ipv4/Config.in
--- linux-2.4.19-pre5/net/ipv4/Config.in Fri Dec 21 12:42:05 2001
+++ linux-2.4.19-pre5_NEW/net/ipv4/Config.in Wed Apr 3 18:00:14 2002
@@ -20,6 +20,9 @@
if [ "$CONFIG_IP_PNP" = "y" ]; then
bool ' IP: DHCP support' CONFIG_IP_PNP_DHCP
bool ' IP: BOOTP support' CONFIG_IP_PNP_BOOTP
+ if [ "$CONFIG_IP_PNP_BOOTP" = "y" ]; then
+ bool ' Provide bootpc style /proc file' CONFIG_IP_BOOTP_PROC
+ fi
bool ' IP: RARP support' CONFIG_IP_PNP_RARP
# not yet ready..
# bool ' IP: ARP support' CONFIG_IP_PNP_ARP
diff -Nur linux-2.4.19-pre5/net/ipv4/ipconfig.c linux-2.4.19-pre5_NEW/net/ipv4/ipconfig.c
--- linux-2.4.19-pre5/net/ipv4/ipconfig.c Mon Feb 25 14:38:14 2002
+++ linux-2.4.19-pre5_NEW/net/ipv4/ipconfig.c Wed Apr 3 18:00:14 2002
@@ -26,6 +26,10 @@
*
* Merged changes from 2.2.19 into 2.4.3
* -- Eric Biederman <[email protected]>, 22 April Aug 2001
+ *
+ * Added support for "/proc/net/bootpc" for bootp requests at boottime.
+ * -- Allan Snider <[email protected]>, 10 March 2002
+ *
*/
#include <linux/config.h>
@@ -525,6 +529,12 @@
func: ic_bootp_recv,
};
+#ifdef CONFIG_IP_BOOTP_PROC
+static char Bootp_vars[1024];
+static int Bootp_size;
+
+static void ic_bootp_vars( struct bootp_pkt* );
+#endif
/*
* Initialize DHCP/BOOTP extension fields in the request.
@@ -917,6 +927,10 @@
ic_nameserver = ic_servaddr;
ic_got_reply = IC_BOOTP;
+#ifdef CONFIG_IP_BOOTP_PROC
+ ic_bootp_vars( b );
+#endif
+
drop:
/* Show's over. Nothing to see here. */
spin_unlock(&ic_recv_lock);
@@ -1102,6 +1116,28 @@
return length;
}
+#ifdef CONFIG_IP_BOOTP_PROC
+static int
+bootpc_get_info( char *buffer, char **start, off_t offset, int length )
+ {
+ char *bv;
+
+ if( offset > Bootp_size )
+ offset = Bootp_size;
+
+ bv = Bootp_vars;
+ bv += offset;
+
+ if( offset + length > Bootp_size )
+ length = Bootp_size - offset;
+
+ strncpy( buffer, bv, length );
+ *start = buffer;
+
+ return( length );
+ }
+#endif
+
#endif /* CONFIG_PROC_FS */
/*
@@ -1115,6 +1151,10 @@
#ifdef CONFIG_PROC_FS
proc_net_create("pnp", 0, pnp_get_info);
+
+#ifdef CONFIG_IP_BOOTP_PROC
+ proc_net_create( "bootpc", 0, bootpc_get_info );
+#endif
#endif /* CONFIG_PROC_FS */
if (!ic_enable)
@@ -1368,3 +1408,392 @@
__setup("ip=", ip_auto_config_setup);
__setup("nfsaddrs=", nfsaddrs_config_setup);
+
+
+#ifdef CONFIG_IP_BOOTP_PROC
+
+/*
+ * ic_bootp_vars:
+ * Dump the bootp packet received to a static
+ * buffer using the same format as bootpc. Users can
+ * then retrieve this packet by reading:
+ *
+ * /proc/net/bootpc
+ */
+
+/* Vendor tags
+ *
+ * Please note: These tags came directly from
+ * the user-space program 'bootpc' code, which just did
+ * the work of extracting them from the RFC 1048.
+ * The orig author of that code follows (the only code
+ * from that file that was taken was the following #define's,
+ * which were modified from 'unsigned char' to 'u8'):
+ *
+ **
+ ** Last updated : Mon Sep 16 15:20:57 1996
+ ** Modified by JSP from code by Charles Hawkins <[email protected]>,
+ **
+ ** [email protected]
+ **
+ ** Copyright (c) University of Cambridge, 1993,1994,1995,1996
+ **
+ ** $Revision: 1.2 $
+ ** $Date: 1997/02/26 20:25:02 $
+ **
+ *
+ * */
+
+#define TAG_END ((u8) 255)
+#define TAG_PAD ((u8) 0)
+#define TAG_SUBNET_MASK ((u8) 1)
+#define TAG_TIME_OFFSET ((u8) 2)
+#define TAG_GATEWAY ((u8) 3)
+#define TAG_TIME_SERVER ((u8) 4)
+#define TAG_NAME_SERVER ((u8) 5)
+#define TAG_DOMAIN_SERVER ((u8) 6)
+#define TAG_LOG_SERVER ((u8) 7)
+#define TAG_COOKIE_SERVER ((u8) 8)
+#define TAG_LPR_SERVER ((u8) 9)
+#define TAG_IMPRESS_SERVER ((u8) 10)
+#define TAG_RLP_SERVER ((u8) 11)
+#define TAG_HOST_NAME ((u8) 12)
+#define TAG_BOOT_SIZE ((u8) 13)
+#define TAG_DUMP_FILE ((u8) 14)
+#define TAG_DOMAIN_NAME ((u8) 15)
+#define TAG_SWAP_SERVER ((u8) 16)
+#define TAG_ROOT_PATH ((u8) 17)
+#define TAG_EXTEN_FILE ((u8) 18)
+#define TAG_IP_FORWARD ((u8) 19)
+#define TAG_IP_NLSR ((u8) 20)
+#define TAG_IP_POLICY_FILTER ((u8) 21)
+#define TAG_IP_MAX_DRS ((u8) 22)
+#define TAG_IP_TTL ((u8) 23)
+#define TAG_IP_MTU_AGE ((u8) 24)
+#define TAG_IP_MTU_PLAT ((u8) 25)
+#define TAG_IP_MTU ((u8) 26)
+#define TAG_IP_SNARL ((u8) 27)
+#define TAG_IP_BROADCAST ((u8) 28)
+#define TAG_IP_SMASKDISC ((u8) 29)
+#define TAG_IP_SMASKSUPP ((u8) 30)
+#define TAG_IP_ROUTERDISC ((u8) 31)
+#define TAG_IP_ROUTER_SOL_ADDR ((u8) 32)
+#define TAG_IP_STATIC_ROUTES ((u8) 33)
+#define TAG_IP_TRAILER_ENC ((u8) 34)
+#define TAG_ARP_TIMEOUT ((u8) 35)
+#define TAG_ETHER_IEEE ((u8) 36)
+#define TAG_IP_TCP_TTL ((u8) 37)
+#define TAG_IP_TCP_KA_INT ((u8) 38)
+#define TAG_IP_TCP_KA_GARBAGE ((u8) 39)
+#define TAG_NIS_DOMAIN ((u8) 40)
+#define TAG_NIS_SERVER ((u8) 41)
+#define TAG_NTP_SERVER ((u8) 42)
+#define TAG_VEND_SPECIFIC ((u8) 43)
+#define TAG_NBNS_SERVER ((u8) 44)
+#define TAG_NBDD_SERVER ((u8) 45)
+#define TAG_NBOTCP_OTPION ((u8) 46)
+#define TAG_NB_SCOPE ((u8) 47)
+#define TAG_XFONT_SERVER ((u8) 48)
+#define TAG_XDISPLAY_SERVER ((u8) 49)
+
+typedef struct
+ {
+ char *buf; /* user buffer */
+ int len; /* size of buffer */
+ int n; /* current size */
+ } bootp_vars;
+
+static void ic_bootp_ext( bootp_vars*, struct bootp_pkt* );
+static void ic_oext( bootp_vars*, u8* );
+static void ic_oip( bootp_vars*, char*, u32 );
+static void ic_olist( bootp_vars*, char*, char*, int );
+static void ic_otag( bootp_vars*, int, char*, int );
+static void ic_ostr( bootp_vars*, char*, char*, int );
+
+
+/*
+ * ic_bootp_vars:
+ */
+
+static void
+ic_bootp_vars( struct bootp_pkt *b )
+ {
+ bootp_vars vars, *v;
+
+ v = &vars;
+ v->buf = Bootp_vars;
+ v->len = sizeof( Bootp_vars );
+ v->n = 0;
+
+ /* standard fields, SERVER, IPADDR, and BOOTFILE */
+ ic_oip( v, "SERVER", b->server_ip );
+ ic_oip( v, "IPADDR", b->your_ip );
+ ic_ostr( v, "BOOTFILE", b->boot_file, 128 );
+
+ /* extended vendor info */
+ if( !memcmp(b->exten,ic_bootp_cookie,4) )
+ ic_bootp_ext( v, b );
+
+ v->buf[v->n] = 0;
+ Bootp_size = v->n;
+ }
+
+
+/*
+ * ic_bootp_ext:
+ */
+
+static void
+ic_bootp_ext( bootp_vars *v, struct bootp_pkt *b )
+ {
+ u8 *end, *ext;
+
+ end = (u8*) b + ntohs( b->iph.tot_len );
+ ext = &b->exten[4];
+
+ if( ext >= end )
+ /* no extended data */
+ return;
+
+ while( *ext != TAG_END )
+ {
+ u8 *opt = ext++;
+ if( *opt == TAG_PAD )
+ continue;
+
+ ext += *ext + 1;
+ if( ext < end )
+ ic_oext( v, opt );
+ }
+ }
+
+
+/*
+ * ic_oext:
+ * Output extended vendor info.
+ */
+
+static void
+ic_oext( bootp_vars *v, u8 *opt )
+ {
+ u8 *tv, tn, tl;
+
+ /* tag number, tag length, tag value */
+ tn = *opt++;
+ tl = *opt++;
+ tv = opt;
+
+ switch( tn )
+ {
+ case TAG_SUBNET_MASK:
+ ic_oip( v, "NETMASK", *((u32*)tv) );
+ break;
+
+ case TAG_GATEWAY:
+ ic_olist( v, "GATEWAYS", tv, tl );
+ break;
+
+ case TAG_TIME_SERVER:
+ ic_olist( v, "TIMESRVS", tv, tl );
+ break;
+
+ case TAG_NAME_SERVER:
+ ic_olist( v, "IEN116SRVS", tv, tl );
+ break;
+
+ case TAG_DOMAIN_SERVER:
+ ic_olist( v, "DNSSRVS", tv, tl );
+ break;
+
+ case TAG_LOG_SERVER:
+ ic_olist( v, "LOGSRVS", tv, tl );
+ break;
+
+ case TAG_COOKIE_SERVER:
+ ic_olist( v, "QODSRVS", tv, tl );
+ break;
+
+ case TAG_LPR_SERVER:
+ ic_olist( v, "LPRSRVS", tv, tl );
+ break;
+
+ case TAG_IMPRESS_SERVER:
+ ic_olist( v, "IMPRESSSRVS", tv, tl );
+ break;
+
+ case TAG_RLP_SERVER:
+ ic_olist( v, "RLPSRVS", tv, tl );
+ break;
+
+ case TAG_HOST_NAME:
+ ic_ostr( v, "HOSTNAME", tv, tl );
+ break;
+
+ case TAG_DOMAIN_NAME:
+ ic_ostr( v, "DOMAIN", tv, tl );
+ break;
+
+ case TAG_SWAP_SERVER:
+ ic_olist( v, "SWAPSRVR", tv, tl );
+ break;
+
+ case TAG_ROOT_PATH:
+ ic_ostr( v, "ROOT_PATH", tv, tl );
+ break;
+
+ case TAG_EXTEN_FILE:
+ ic_ostr( v, "EXTEN_FILE", tv, tl );
+ break;
+
+ case TAG_NIS_DOMAIN:
+ ic_ostr( v, "YPDOMAIN", tv, tl );
+ break;
+
+ case TAG_NIS_SERVER:
+ ic_olist( v, "YPSRVR", tv, tl );
+ break;
+
+ case TAG_NTP_SERVER:
+ ic_olist( v, "NTPSRVS", tv, tl );
+ break;
+
+ default:
+ ic_otag( v, tn, tv, tl );
+ break;
+ }
+ }
+
+
+/*
+ * ic_oip:
+ * Output an IP address.
+ */
+
+static void
+ic_oip( bootp_vars *v, char *var, u32 val )
+ {
+ ic_ostr( v, var, in_ntoa(val), -1 );
+ }
+
+
+/*
+ * ic_olist:
+ * Output a list of IP addresses
+ * of the form:
+ *
+ * VAR='ip_1 ip_2 ... ip_n'
+ * VAR_1='ip_1'
+ * VAR_2='ip_2'
+ * ...
+ * VAR_n='ip_n'
+ *
+ * Process at most 10 IPs.
+ */
+
+static void
+ic_olist( bootp_vars *v, char *var, char *tv, int tl )
+ {
+ char buf[200], *b;
+ char vn[40], *ip;
+ u32 *t;
+ int n, i;
+
+ n = tl / 4;
+ if( n > 10 )
+ n = 10;
+
+ b = buf;
+ t = (u32*) tv;
+
+ for( i=0; i<n; i++, t++ )
+ {
+ sprintf( vn, "%s_%d", var, i+1 );
+
+ ip = in_ntoa( *t );
+ ic_ostr( v, vn, ip, -1 );
+
+ if( i )
+ *b++ = ' ';
+
+ while( *ip )
+ *b++ = *ip++;
+ }
+
+ *b = 0;
+ ic_ostr( v, var, buf, -1 );
+ }
+
+
+/*
+ * ic_otag:
+ * Output a generic tag value.
+ */
+
+static void
+ic_otag( bootp_vars *v, int tn, char *tv, int tl )
+ {
+ char var[10];
+
+ sprintf( var, "T%d", tn );
+ ic_ostr( v, var, tv, tl );
+ }
+
+
+/*
+ * ic_ostr:
+ * Output a variable and its value to the buffer
+ * of the form:
+ *
+ * var='val'\n
+ *
+ * Ensure that we do not overwrite the supplied buffer.
+ * If the given tag length (tl) is < 0, then we use
+ * strlen() to determine length.
+ */
+
+static void
+ic_ostr( bootp_vars *v, char *var, char *tv, int tl )
+ {
+ char *p;
+ int lv, l;
+ int t, i;
+
+ /* determine the lengths of var and val */
+ lv = strlen( var );
+ if( tl < 0 )
+ l = strlen( tv );
+ else
+ {
+ p = tv;
+ for( l=0; l<tl; l++ )
+ if( !*p++ )
+ break;
+ }
+
+ /* total length */
+ t = lv + l + 4;
+
+ /* room to add string? */
+ if( v->n + t >= v->len )
+ /* nope */
+ return;
+
+ /* add it */
+ p = v->buf + v->n;
+ while( *var )
+ *p++ = *var++;
+
+ *p++ = '=';
+
+ *p++ = '\'';
+ for( i=0; i<l; i++ )
+ *p++ = *tv++;
+ *p++ = '\'';
+
+ *p = '\n';
+
+ /* update buffer length */
+ v->n += t;
+ }
+
+#endif
Craig <[email protected]> writes:
> Marcelo,
> This patch is against 2.4.19-pre5, please apply.
This is unbelievable ugly. Can't you just save the packet as a binary
buffer, output it as binary in /proc and parse and format it in user space ?
Better would be to not use bootpc at all in kernel, but run it in initrd
(that is the long term plan anyways, removing dhcp/bootp completely
and only supporting them from initrd)
-Andi
> So what do people think? Should this go in 2.4 or 2.5?
> Is this worthwhile to pursue putting this in (it's very useful to us,
> so we figured others could use it)?
> Should i send this to Linus for 2.5 inclusion as well?
The longer term goal is to remove this stuff from the kernel and push it
into the initrd support. Instead of kernel hacks you use an initrd that
runs the real bootpc.
On 4 Apr 2002, Andi Kleen wrote:
> Craig <[email protected]> writes:
>
> > Marcelo,
> > This patch is against 2.4.19-pre5, please apply.
>
> This is unbelievable ugly. Can't you just save the packet as a binary
> buffer, output it as binary in /proc and parse and format it in user space ?
>
Sure, we *could* have done that. We chose not to because some of the user space
programs were having problems during bootup times. Instead, we did it in the
kernel for our specific application as that was the better place where we had
more control (for *our* application).
> Better would be to not use bootpc at all in kernel, but run it in initrd
> (that is the long term plan anyways, removing dhcp/bootp completely
> and only supporting them from initrd)
>
Yes, Alan mentions the same thing.
We didn't realize that was the long term plan. Is that documented anywhere, or
was it discussed on this list eons ago and 'decided'? ;)
--
Craig.
+------------------------------------------------------+
http://www.wombat.ca Why? Why not.
http://www.washington.edu/pine/ Pine @ the U of Wash.
+-------------=*sent via Pine4.42*=--------------------+
Craig <[email protected]> writes:
> Yes, Alan mentions the same thing.
> We didn't realize that was the long term plan. Is that documented anywhere, or
> was it discussed on this list eons ago and 'decided'? ;)
It has been discussed on this list several times. In fact every time
this has come up. There are a lot of policy decisions the in kernel
dhcp/bootpc code that are generally best left to user space.
Al Viro has gone so far as proposed moving a lot of other parts into
user space as well. But initramfs needs to be in the kernel for that.
Eric