The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [Patch]Fix spanned_pages is not updated at a case of memory hot-add take 2..
From: Yasunori Goto @ 2006-05-26  4:46 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Linux Kernel ML, Dave Hansen
In-Reply-To: <1148447148.8658.34.camel@localhost.localdomain>


I fixed redundant parentheses and tested this fix updating
spanned_pages patch.

Andrew-san.
Please apply.

------------------
If hot-added memory's address is smaller than old area,
spanned_pages will not be updated. It must be fixed.

example) Old zone_start_pfn = 0x60000, and spanned_pages = 0x10000
         Added new memory's start_pfn = 0x50000, and end_pfn = 0x60000

  new spanned_pages will be still 0x10000 by old code.
  (It should be updated to 0x20000.) Because old_zone_end_pfn will be
  0x70000, and end_pfn smaller than it. So, spanned_pages will not be
  updated.
  
In current code, spanned_pages is updated only when end_pfn is updated.
But, it should be updated by subtraction between bigger end_pfn and new
zone_start_pfn.

This is for 2.6.17-rc4-mm3.
I tested this patch on Tiger4 with my node emulation.

Signed-off-by: Yasunori Goto <y-goto@jp.fujitsu.com>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>

 mm/memory_hotplug.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

Index: pgdat15/mm/memory_hotplug.c
===================================================================
--- pgdat15.orig/mm/memory_hotplug.c	2006-05-25 12:22:54.000000000 +0900
+++ pgdat15/mm/memory_hotplug.c	2006-05-25 12:23:18.000000000 +0900
@@ -103,8 +103,8 @@ static void grow_zone_span(struct zone *
 	if (start_pfn < zone->zone_start_pfn)
 		zone->zone_start_pfn = start_pfn;
 
-	if (end_pfn > old_zone_end_pfn)
-		zone->spanned_pages = end_pfn - zone->zone_start_pfn;
+	zone->spanned_pages = max(old_zone_end_pfn, end_pfn) -
+				zone->zone_start_pfn;
 
 	zone_span_writeunlock(zone);
 }
@@ -118,8 +118,8 @@ static void grow_pgdat_span(struct pglis
 	if (start_pfn < pgdat->node_start_pfn)
 		pgdat->node_start_pfn = start_pfn;
 
-	if (end_pfn > old_pgdat_end_pfn)
-		pgdat->node_spanned_pages = end_pfn - pgdat->node_start_pfn;
+	pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) -
+					pgdat->node_start_pfn;
 }
 
 int online_pages(unsigned long pfn, unsigned long nr_pages)

-- 
Yasunori Goto 



^ permalink raw reply

* Re: [PATCH 1/2] request_firmware without a device
From: Shaohua Li @ 2006-05-26  4:41 UTC (permalink / raw)
  To: Greg KH; +Cc: Marcel Holtmann, lkml, Patrick Mochel, Andrew Morton
In-Reply-To: <20060526040613.GA5324@kroah.com>

On Thu, 2006-05-25 at 21:06 -0700, Greg KH wrote:
> On Fri, May 26, 2006 at 11:40:39AM +0800, Shaohua Li wrote:
> > On Thu, 2006-05-25 at 12:24 +0200, Marcel Holtmann wrote:
> > > Hi Greg,
> > > 
> > > > > The patch allows calling request_firmware without a 'struct device'.
> > > > > It appears we just need a name here from 'struct device'. I changed it
> > > > > to use a kobject as Patrick suggested.
> > > > > Next patch will use the new API to request firmware (microcode) for a CPU.
> > > > 
> > > > But a cpu does have a struct device.  Why not just use that?
> > > > 
> > > > > +fw_setup_class_device_id(struct class_device *class_dev, struct kobject *kobj)
> > > > >  {
> > > > >  	/* XXX warning we should watch out for name collisions */
> > > > > -	strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
> > > > > +	strlcpy(class_dev->class_id, kobj->k_name, BUS_ID_SIZE);
> > > > 
> > > > There's a function for this, kobject_name(), please never touch k_name
> > > > directly.
> > > > 
> > > > > +EXPORT_SYMBOL(request_firmware_kobj);
> > > > 
> > > > Ick, if you really want to do this, just fix up all callers of
> > > > request_firmware(), there aren't that many of them.
> > > > 
> > > > But I don't recommend it anyway.
> > > 
> > > I also disagree with this change at all. The callers of request_firmware
> > > should not fiddle around with kobject's to make this work. All of them
> > > have their struct device and they should use it.
> > So why we need a 'struct device'? I didn't see any point we need it. We
> > just need a 'name'.
> 
> You need a kobject, as ideally we would have a symlink back to the
> "real" kobject.  So far, only "devices" need firmware, that's why it is
> that way.
> > > So I would propose that we fix the caller and the not request_firmware
> > > code. However one option would be calling it with NULL as device
> > > argument and it registers itself a dummy device for the operation.
> > This doesn't work, as we need a 'name'.
> > 
> > do we really need to differentiate between sysdev and device anymore. I
> > > recall a plan to unify all devices, but I might be wrong.
> > I'd like this idea. But it means many works. In addition, a sysdev could
> > have multiple drivers, and a 'device' can't to me.
> 
> Today a sysdev can have that?  Ick.  Any examples of ones that really
> do?
At least cpu sysdev has two drivers currently. one is mtrr driver the
other is cpurfreq.

Thanks,
Shaohua

^ permalink raw reply

* Re: uclinux 2.4.32 panic
From: Willy Tarreau @ 2006-05-26  4:32 UTC (permalink / raw)
  To: Stephen Clark
  Cc: Steve Clark, Steve Clark, linux-kernel, uClinux development list
In-Reply-To: <447642F6.5030807@seclark.us>

On Thu, May 25, 2006 at 07:51:18PM -0400, Stephen Clark wrote:
> Thanks Willy,
> 
> I tracked down the problem it was in the receive_chars(). Whoever did 
> this had an #if 0
> that removed the test of the flip buffer count exceeding the flip buffer 
> size, so under
> stress the buffer would overflow and zero the pointer stored in 
> driver_data field.

Fine. Once your code works OK after the various cleanups, be sure to
send the patches back to the uclinux maintainers (including the fixes
for the rs_write() code we talked about in the first mail).

> Steve

Regards,
Willy


^ permalink raw reply

* Re: Fwd: [RFC] New netfilter match
From: Randy.Dunlap @ 2006-05-26  4:40 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: alex14641, linux-kernel
In-Reply-To: <20060526042550.GW11191@w.ods.org>

On Fri, 26 May 2006 06:25:51 +0200 Willy Tarreau wrote:

> On Thu, May 25, 2006 at 09:18:03PM -0700, Alex Davis wrote:
> > I posted this to netfilter-devel@lists.netfilter.org 5 hours ago and it hasn't 
> > appeared on that list yet.
> > 
> > 
> > --- Alex Davis <alex14641@yahoo.com> wrote:
> > 
> > > 
> > > This is a proposal for a new netfilter module. 
> > > Please read and furnish comments.
> > > 
> > > http://linux.ace-technologies.biz:81/ipisforif.html
> 
> Nobody will take the time to click on your link. And there are people in
> big companies who will not have an easy access to HTTP on a port other
> than 80. You should post your code right here in a mail so that competent
> people can discuss it (and don't worry if they use harsh words).

I suggest a network-related mailing list instead of lkml.

---
~Randy

^ permalink raw reply

* Re: [ANNOUNCE] Linux Device Driver Kit available
From: Willy Tarreau @ 2006-05-26  4:28 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel
In-Reply-To: <20060524232900.GA18408@kroah.com>

On Wed, May 24, 2006 at 04:29:00PM -0700, Greg KH wrote:
(...)
> In coordination with the FreedomHEC[1] conference this week in Seattle,
> WA, USA, I'm proud to announce the first release of the Linux Device
> Driver Kit.
> 
> It is a cd image that contains everything that a Linux device driver
> author would need in order to create Linux drivers, including a full
> copy of the O'Reilly book, "Linux Device Drivers, third edition" and
> pre-built copies of all of the in-kernel docbook documentation for easy
> browsing.  It even has a copy of the Linux source code that you can
> directly build external kernel modules against.
> 
> It can be downloaded for free at:
>    kernel.org/pub/linux/kernel/people/gregkh/ddk/
(...)

Got it. Thanks a lot Greg, that's an excellent initiative ! I hope it
will encourage hardware makers to provide GPL drivers.

Regards,
Willy


^ permalink raw reply

* Re: Fwd: [RFC] New netfilter match
From: Willy Tarreau @ 2006-05-26  4:25 UTC (permalink / raw)
  To: Alex Davis; +Cc: linux-kernel
In-Reply-To: <20060526041803.46181.qmail@web50209.mail.yahoo.com>

On Thu, May 25, 2006 at 09:18:03PM -0700, Alex Davis wrote:
> I posted this to netfilter-devel@lists.netfilter.org 5 hours ago and it hasn't 
> appeared on that list yet.
> 
> 
> --- Alex Davis <alex14641@yahoo.com> wrote:
> 
> > 
> > This is a proposal for a new netfilter module. 
> > Please read and furnish comments.
> > 
> > http://linux.ace-technologies.biz:81/ipisforif.html

Nobody will take the time to click on your link. And there are people in
big companies who will not have an easy access to HTTP on a port other
than 80. You should post your code right here in a mail so that competent
people can discuss it (and don't worry if they use harsh words).

Willy


^ permalink raw reply

* Re: why svc_export_lookup() has no implementation?
From: Neil Brown @ 2006-05-26  4:34 UTC (permalink / raw)
  To: Xin Zhao; +Cc: linux-kernel, linux-fsdevel
In-Reply-To: <4ae3c140605252115n7b040a99l6633ba387ce48358@mail.gmail.com>

On Friday May 26, uszhaoxin@gmail.com wrote:
> I noticed that functions like exp_get_by_name() calls function
> svc_export_lookup(). But I cannot find the implementation of
> svc_export_lookup(). I can only find the function definition. HOw can
> this happen?
> 
> Can someone give me a hand?

Look at and understand DefineCacheLookup (in
include/linux/sunrpc/cache.h).

Then look for places that it is used.

But if you find you cannot stomach that, but assured that you aren't
alone and have a look in something newer than 2.6.16.  There-in, and
Randy has suggest, it will be easy to find the definition.

NeilBrown

^ permalink raw reply

* Re: How to check if kernel sources are installed on a system?
From: Willy Tarreau @ 2006-05-26  4:23 UTC (permalink / raw)
  To: Olivier Galibert, linux-kernel, Dave Jones, Jeff Garzik
In-Reply-To: <20060525225222.GA14552@dspnet.fr.eu.org>

Hi,

On Fri, May 26, 2006 at 12:52:22AM +0200, Olivier Galibert wrote:
> On Thu, May 25, 2006 at 05:44:13PM -0400, Dave Jones wrote:
> > Following /lib/modules/`uname -r`/build is the only way this can work.
> > (And that should be true on any distro)
> 
> On one side it's a reasonably nice way, on the other it makes it hard
> to build modules for a different kernel than the running one.  I have
> a uname version in a corner that allows overriding the -r return with
> an environment variable just for that reason, I should probably send
> the path upstream.

I agree with Olivier here.

The trick above should only be a hint to propose to the user what has
been found. If he doesn't know, it's certainly OK. Otherwise, he must
have the ability to use anything else (often needed for packaging or
for cross-building).

Regards,
Willy


^ permalink raw reply

* Re: [OOPS] amrestore dies in kmem_cache_free 2.6.16.18 - cannot restore backups!
From: Chuck Ebbert @ 2006-05-26  4:27 UTC (permalink / raw)
  To: James Lamanna; +Cc: linux-kernel, Pekka Enberg, James Bottomley, Mike Christie

In-Reply-To: <aa4c40ff0605231824j55c998c3oe427dec2404afba0@mail.gmail.com>

On Tue, 23 May 2006 18:24:14 -0700, James Lamanna wrote:

> So I was able to recreate this problem on a vanilla 2.6.16.18 with the
> following oops..
> I'd say this is a serious regression since I cannot restore backups
> anymore (I could with 2.6.14.x, but that kernel series had other
> issues...)

> Unable to handle kernel paging request at ffff82bc81000030 RIP: <ffffffff801657d9>{kmem_cache_free+82}
> PGD 0
> Oops: 0000 [1] SMP
> CPU 1
> Modules linked in:
> Pid: 5814, comm: amrestore Not tainted 2.6.16.18 #2
> RIP: 0010:[<ffffffff801657d9>] <ffffffff801657d9>{kmem_cache_free+82}
> RSP: 0018:ffff81007d4afcd8  EFLAGS: 00010086
> RAX: ffff82bc81000000 RBX: ffff81004119d800 RCX: 000000000000001e
> RDX: ffff81000000c000 RSI: 0000000000000000 RDI: 00000007f0000000
> RBP: ffff81007ff0c800 R08: 0000000000000000 R09: 0000000000000400
> R10: 0000000000000000 R11: ffffffff8014b3d6 R12: ffff810041311480
> R13: 0000000000000400 R14: 0000000000000400 R15: ffff81007e676748
> FS:  00002b7f39708020(0000) GS:ffff810041173bc0(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> CR2: ffff82bc81000030 CR3: 000000007de09000 CR4: 00000000000006e0
> Process amrestore (pid: 5814, threadinfo ffff81007d4ae000, task ffff81007e2f8ae0)
> Stack: 0000000000000000 0000000000000246 ffff8100413c9bc0 ffff81007ff0c800
>        ffff8100413c9bc0 ffffffff8016dfdc ffff8100413c9bc0 ffff81007fe25408
>        00000000ffffffea ffffffff803187e7
> Call Trace: <ffffffff8016dfdc>{bio_free+48} <ffffffff803187e7>{scsi_execute_async+640}
>        <ffffffff8035d8d2>{st_do_scsi+422} <ffffffff8035d6e2>{st_sleep_done+0}
>        <ffffffff80362950>{st_read+855} <ffffffff8013e1ca>{autoremove_wake_function+0}
>        <ffffffff80169d7c>{vfs_read+171} <ffffffff8016a0af>{sys_read+69}
>        <ffffffff8010a93e>{system_call+126}
> 
> Code: 48 8b 48 30 0f b7 51 28 65 8b 04 25 30 00 00 00 39 c2 0f 84
> RIP <ffffffff801657d9>{kmem_cache_free+82} RSP <ffff81007d4afcd8>
> CR2: ffff82bc81000030

First of all, to really see what is happening you need to recompile your kernel
after adding some debug options:

Kernel Hacking --->
   [*] Kernel debugging
   [*]   Debug memory allocations
   [*]   Compile the kernel with frame pointers

(Frame pointers won't give an exact trace but they'll prevent the tail merging
that makes it so hard to follow.)

Then reproduce the error and send the oops and any new error messages you see.
Don't send the whole boot log and .config again -- we have them already.

The bug is happening here, in __cache_free, in code that's only included
on NUMA machines:

static inline void __cache_free(struct kmem_cache *cachep, void *objp)
{
        struct array_cache *ac = cpu_cache_get(cachep);

        check_irq_off();
        objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));

        /* Make sure we are not freeing a object from another
         * node to the array cache on this cpu.
         */
#ifdef CONFIG_NUMA
        {
                struct slab *slabp;
                slabp = virt_to_slab(objp);                      <==== OOPS
                if (unlikely(slabp->nodeid != numa_node_id())) {
                        struct array_cache *alien = NULL;
                        int nodeid = slabp->nodeid;


Tracing through the nested inline functions, we have:

static inline struct slab *virt_to_slab(const void *obj)
{
        struct page *page = virt_to_page(obj);
        return page_get_slab(page);                              <==== OOPS
}

static inline struct slab *page_get_slab(struct page *page)
{
        return (struct slab *)page->lru.prev;                    <==== OOPS
}


virt_to_page() returned a struct page * that pointed to unmapped memory.


This all came from scsi_execute_async, possibly through this path:

scsi_execute_async
    scsi_rq_map_sg: some kind of error occurred?
        bio_endio
            bio->bi_end_io ==> scsi_bi_end_io
                bio_put
                    bio->bi_destructor ==> bio_fs_destructor
                        bio_free
                            mempool_free
                                kmem_cache_free

scsi_execute_async and scsi_rq_map_sg were rewritten last December, so may have
new bugs.


-- 
Chuck

^ permalink raw reply

* Re: [USB disks] FAT: invalid media value (0x01)
From: Chuck Ebbert @ 2006-05-26  4:27 UTC (permalink / raw)
  To: Pawel Sikora; +Cc: linux-kernel

In-Reply-To: <200605252310.00568.pluto@agmk.net>

(Sorry if I got your name wrong, the last letter came through as '?'.)

On Thu, 25 May 2006 23:10:00 +0200, Pawe? Sikora wrote:

> sdc: assuming drive cache: write through
>  sdc: sdc1
> sd 11:0:0:0: Attached scsi removable disk sdc
> usb-storage: device scan complete
> FAT: invalid media value (0x01)
> VFS: Can't find a valid FAT filesystem on dev sdc.
                                                ^^^

Shouldn't it be looking on sdc1 for the filesystem?

This could be some kind of hal/udev screwup.


-- 
Chuck

^ permalink raw reply

* [RFC 5/5] sched: Add procfs interface for CPU rate hard caps
From: Peter Williams @ 2006-05-26  4:21 UTC (permalink / raw)
  To: Mike Galbraith
  Cc: Con Kolivas, Peter Williams, Linux Kernel, Kingsley Cheung,
	Ingo Molnar, Rene Herman
In-Reply-To: <20060526042021.2886.4957.sendpatchset@heathwren.pw.nest>

This patch implements a procfs interface for hard CPU rate caps.

Signed-off-by: Peter Williams <pwil3058@bigpond.com.au>
 fs/proc/base.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

Index: MM-2.6.17-rc4-mm3/fs/proc/base.c
===================================================================
--- MM-2.6.17-rc4-mm3.orig/fs/proc/base.c	2006-05-26 13:50:57.000000000 +1000
+++ MM-2.6.17-rc4-mm3/fs/proc/base.c	2006-05-26 13:51:01.000000000 +1000
@@ -170,6 +170,9 @@ enum pid_directory_inos {
 #ifdef CONFIG_CPU_RATE_CAPS
 	PROC_TID_CPU_RATE_CAP,
 #endif
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	PROC_TID_CPU_RATE_HARD_CAP,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TID_ATTR,
 	PROC_TID_ATTR_CURRENT,
@@ -286,6 +289,9 @@ static struct pid_entry tid_base_stuff[]
 #ifdef CONFIG_CPU_RATE_CAPS
 	E(PROC_TID_CPU_RATE_CAP,  "cpu_rate_cap",   S_IFREG|S_IRUGO|S_IWUSR),
 #endif
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	E(PROC_TID_CPU_RATE_HARD_CAP,  "cpu_rate_hard_cap",   S_IFREG|S_IRUGO|S_IWUSR),
+#endif
 	{0,0,NULL,0}
 };
 
@@ -1090,6 +1096,54 @@ struct file_operations proc_cpu_rate_cap
 };
 #endif
 
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+static ssize_t cpu_rate_hard_cap_read(struct file * file, char * buf,
+			size_t count, loff_t *ppos)
+{
+	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+	char buffer[64];
+	size_t len;
+	unsigned int cppt = get_cpu_rate_hard_cap(task);
+
+	if (*ppos)
+		return 0;
+	*ppos = len = sprintf(buffer, "%u\n", cppt);
+	if (copy_to_user(buf, buffer, len))
+		return -EFAULT;
+
+	return len;
+}
+
+static ssize_t cpu_rate_hard_cap_write(struct file * file, const char * buf,
+			 size_t count, loff_t *ppos)
+{
+	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+	char buffer[128] = "";
+	char *endptr = NULL;
+	unsigned long hcppt;
+	int res;
+
+
+	if ((count > 63) || *ppos)
+		return -EFBIG;
+	if (copy_from_user(buffer, buf, count))
+		return -EFAULT;
+	hcppt = simple_strtoul(buffer, &endptr, 0);
+	if ((endptr == buffer) || (hcppt == ULONG_MAX))
+		return -EINVAL;
+
+	if ((res = set_cpu_rate_hard_cap(task, hcppt)) != 0)
+		return res;
+
+	return count;
+}
+
+struct file_operations proc_cpu_rate_hard_cap_operations = {
+	read:		cpu_rate_hard_cap_read,
+	write:		cpu_rate_hard_cap_write,
+};
+#endif
+
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
@@ -1855,6 +1909,11 @@ static struct dentry *proc_pident_lookup
 			inode->i_fop = &proc_cpu_rate_cap_operations;
 			break;
 #endif
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+		case PROC_TID_CPU_RATE_HARD_CAP:
+			inode->i_fop = &proc_cpu_rate_hard_cap_operations;
+			break;
+#endif
 		default:
 			printk("procfs: impossible type (%d)",p->type);
 			iput(inode);

-- 
Peter Williams                                   pwil3058@bigpond.net.au

"Learning, n. The kind of ignorance distinguishing the studious."
 -- Ambrose Bierce

^ permalink raw reply

* [RFC 4/5] sched: Add procfs interface for CPU rate soft caps
From: Peter Williams @ 2006-05-26  4:21 UTC (permalink / raw)
  To: Mike Galbraith
  Cc: Con Kolivas, Peter Williams, Linux Kernel, Kingsley Cheung,
	Ingo Molnar, Rene Herman
In-Reply-To: <20060526042021.2886.4957.sendpatchset@heathwren.pw.nest>

This patch implements a procfs interface for soft CPU rate caps.

Signed-off-by: Peter Williams <pwil3058@bigpond.com.au>
 fs/proc/base.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

Index: MM-2.6.17-rc4-mm3/fs/proc/base.c
===================================================================
--- MM-2.6.17-rc4-mm3.orig/fs/proc/base.c	2006-05-26 13:46:40.000000000 +1000
+++ MM-2.6.17-rc4-mm3/fs/proc/base.c	2006-05-26 13:50:57.000000000 +1000
@@ -167,6 +167,9 @@ enum pid_directory_inos {
 #ifdef CONFIG_CPUSETS
 	PROC_TID_CPUSET,
 #endif
+#ifdef CONFIG_CPU_RATE_CAPS
+	PROC_TID_CPU_RATE_CAP,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TID_ATTR,
 	PROC_TID_ATTR_CURRENT,
@@ -280,6 +283,9 @@ static struct pid_entry tid_base_stuff[]
 #ifdef CONFIG_AUDITSYSCALL
 	E(PROC_TID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
 #endif
+#ifdef CONFIG_CPU_RATE_CAPS
+	E(PROC_TID_CPU_RATE_CAP,  "cpu_rate_cap",   S_IFREG|S_IRUGO|S_IWUSR),
+#endif
 	{0,0,NULL,0}
 };
 
@@ -1036,6 +1042,54 @@ static struct file_operations proc_secco
 };
 #endif /* CONFIG_SECCOMP */
 
+#ifdef CONFIG_CPU_RATE_CAPS
+static ssize_t cpu_rate_cap_read(struct file * file, char * buf,
+			size_t count, loff_t *ppos)
+{
+	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+	char buffer[64];
+	size_t len;
+	unsigned int cppt = get_cpu_rate_cap(task);
+
+	if (*ppos)
+		return 0;
+	*ppos = len = sprintf(buffer, "%u\n", cppt);
+	if (copy_to_user(buf, buffer, len))
+		return -EFAULT;
+
+	return len;
+}
+
+static ssize_t cpu_rate_cap_write(struct file * file, const char * buf,
+			 size_t count, loff_t *ppos)
+{
+	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+	char buffer[128] = "";
+	char *endptr = NULL;
+	unsigned long hcppt;
+	int res;
+
+
+	if ((count > 63) || *ppos)
+		return -EFBIG;
+	if (copy_from_user(buffer, buf, count))
+		return -EFAULT;
+	hcppt = simple_strtoul(buffer, &endptr, 0);
+	if ((endptr == buffer) || (hcppt == ULONG_MAX))
+		return -EINVAL;
+
+	if ((res = set_cpu_rate_cap(task, hcppt)) != 0)
+		return res;
+
+	return count;
+}
+
+struct file_operations proc_cpu_rate_cap_operations = {
+	read:		cpu_rate_cap_read,
+	write:		cpu_rate_cap_write,
+};
+#endif
+
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
@@ -1796,6 +1850,11 @@ static struct dentry *proc_pident_lookup
 			inode->i_fop = &proc_loginuid_operations;
 			break;
 #endif
+#ifdef CONFIG_CPU_RATE_CAPS
+		case PROC_TID_CPU_RATE_CAP:
+			inode->i_fop = &proc_cpu_rate_cap_operations;
+			break;
+#endif
 		default:
 			printk("procfs: impossible type (%d)",p->type);
 			iput(inode);

-- 
Peter Williams                                   pwil3058@bigpond.net.au

"Learning, n. The kind of ignorance distinguishing the studious."
 -- Ambrose Bierce

^ permalink raw reply

* Re: why svc_export_lookup() has no implementation?
From: Randy.Dunlap @ 2006-05-26  4:23 UTC (permalink / raw)
  To: Xin Zhao; +Cc: linux-kernel, linux-fsdevel
In-Reply-To: <4ae3c140605252115n7b040a99l6633ba387ce48358@mail.gmail.com>

On Fri, 26 May 2006 00:15:32 -0400 Xin Zhao wrote:

> I noticed that functions like exp_get_by_name() calls function
> svc_export_lookup(). But I cannot find the implementation of
> svc_export_lookup(). I can only find the function definition. HOw can
> this happen?
> 
> Can someone give me a hand?

Sounds like you need better tools or get them to search like
you mean for them to search.

seee fs/nfsd/export.c

---
~Randy

^ permalink raw reply

* [RFC 3/5] sched: Add CPU rate hard caps
From: Peter Williams @ 2006-05-26  4:20 UTC (permalink / raw)
  To: Mike Galbraith
  Cc: Con Kolivas, Peter Williams, Linux Kernel, Kingsley Cheung,
	Ingo Molnar, Rene Herman
In-Reply-To: <20060526042021.2886.4957.sendpatchset@heathwren.pw.nest>

This patch implements hard CPU rate caps per task as a proportion of a
single CPU's capacity expressed in parts per thousand.

Signed-off-by: Peter Williams <pwil3058@bigpond.com.au>
 include/linux/sched.h |    8 ++
 kernel/Kconfig.caps   |   14 +++-
 kernel/sched.c        |  154 ++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 168 insertions(+), 8 deletions(-)

Index: MM-2.6.17-rc4-mm3/include/linux/sched.h
===================================================================
--- MM-2.6.17-rc4-mm3.orig/include/linux/sched.h	2006-05-26 10:46:35.000000000 +1000
+++ MM-2.6.17-rc4-mm3/include/linux/sched.h	2006-05-26 11:00:07.000000000 +1000
@@ -796,6 +796,10 @@ struct task_struct {
 #ifdef CONFIG_CPU_RATE_CAPS
 	unsigned long long avg_cpu_per_cycle, avg_cycle_length;
 	unsigned int cpu_rate_cap;
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	unsigned int cpu_rate_hard_cap;
+	struct timer_list sinbin_timer;
+#endif
 #endif
 	enum sleep_type sleep_type;
 
@@ -994,6 +998,10 @@ struct task_struct {
 #ifdef CONFIG_CPU_RATE_CAPS
 unsigned int get_cpu_rate_cap(const struct task_struct *);
 int set_cpu_rate_cap(struct task_struct *, unsigned int);
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+unsigned int get_cpu_rate_hard_cap(const struct task_struct *);
+int set_cpu_rate_hard_cap(struct task_struct *, unsigned int);
+#endif
 #endif
 
 static inline pid_t process_group(struct task_struct *tsk)
Index: MM-2.6.17-rc4-mm3/kernel/Kconfig.caps
===================================================================
--- MM-2.6.17-rc4-mm3.orig/kernel/Kconfig.caps	2006-05-26 10:45:26.000000000 +1000
+++ MM-2.6.17-rc4-mm3/kernel/Kconfig.caps	2006-05-26 11:00:07.000000000 +1000
@@ -3,11 +3,21 @@
 #
 
 config CPU_RATE_CAPS
-	bool "Support (soft) CPU rate caps"
+	bool "Support CPU rate caps"
 	default n
 	---help---
-	  Say y here if you wish to be able to put a (soft) upper limit on
+	  Say y here if you wish to be able to put a soft upper limit on
 	  the rate of CPU usage by individual tasks.  A task which has been
 	  allocated a soft CPU rate cap will be limited to that rate of CPU
 	  usage unless there is spare CPU resources available after the needs
 	  of uncapped tasks are met.
+
+config CPU_RATE_HARD_CAPS
+	bool "Support CPU rate hard caps"
+	depends on CPU_RATE_CAPS
+	default n
+	---help---
+	  Say y here if you wish to be able to put a hard upper limit on
+	  the rate of CPU usage by individual tasks.  A task which has been
+	  allocated a hard CPU rate cap will be limited to that rate of CPU
+	  usage regardless of whether there is spare CPU resources available.
Index: MM-2.6.17-rc4-mm3/kernel/sched.c
===================================================================
--- MM-2.6.17-rc4-mm3.orig/kernel/sched.c	2006-05-26 11:00:02.000000000 +1000
+++ MM-2.6.17-rc4-mm3/kernel/sched.c	2006-05-26 13:50:11.000000000 +1000
@@ -201,21 +201,33 @@ static inline unsigned int task_timeslic
 
 #ifdef CONFIG_CPU_RATE_CAPS
 #define CAP_STATS_OFFSET 8
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+static void sinbin_release_fn(unsigned long arg);
+#define min_cpu_rate_cap(p) min((p)->cpu_rate_cap, (p)->cpu_rate_hard_cap)
+#else
+#define min_cpu_rate_cap(p) (p)->cpu_rate_cap
+#endif
 #define task_has_cap(p) unlikely((p)->flags & PF_HAS_CAP)
 /* this assumes that p is not a real time task */
 #define task_is_background(p) unlikely((p)->cpu_rate_cap == 0)
 #define task_being_capped(p) unlikely((p)->prio >= CAPPED_PRIO)
-#define cap_load_weight(p) (((p)->cpu_rate_cap * SCHED_LOAD_SCALE) / 1000)
+#define cap_load_weight(p) ((min_cpu_rate_cap(p) * SCHED_LOAD_SCALE) / 1000)
 
 static void init_cpu_rate_caps(task_t *p)
 {
 	p->cpu_rate_cap = 1000;
 	p->flags &= ~PF_HAS_CAP;
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	p->cpu_rate_hard_cap = 1000;
+	init_timer(&p->sinbin_timer);
+	p->sinbin_timer.function = sinbin_release_fn;
+	p->sinbin_timer.data = (unsigned long) p;
+#endif
 }
 
 static inline void set_cap_flag(task_t *p)
 {
-	if (p->cpu_rate_cap < 1000 && !has_rt_policy(p))
+	if (min_cpu_rate_cap(p) < 1000 && !has_rt_policy(p))
 		p->flags |= PF_HAS_CAP;
 	else
 		p->flags &= ~PF_HAS_CAP;
@@ -223,7 +235,7 @@ static inline void set_cap_flag(task_t *
 
 static inline int task_exceeding_cap(const task_t *p)
 {
-	return (p->avg_cpu_per_cycle * 1000) > (p->avg_cycle_length * p->cpu_rate_cap);
+	return (p->avg_cpu_per_cycle * 1000) > (p->avg_cycle_length * min_cpu_rate_cap(p));
 }
 
 #ifdef CONFIG_SCHED_SMT
@@ -257,7 +269,7 @@ static int task_exceeding_cap_now(const 
 
 	delta = (now > p->timestamp) ? (now - p->timestamp) : 0;
 	lhs = (p->avg_cpu_per_cycle + delta) * 1000;
-	rhs = (p->avg_cycle_length + delta) * p->cpu_rate_cap;
+	rhs = (p->avg_cycle_length + delta) * min_cpu_rate_cap(p);
 
 	return lhs > rhs;
 }
@@ -266,6 +278,10 @@ static inline void init_cap_stats(task_t
 {
 	p->avg_cpu_per_cycle = 0;
 	p->avg_cycle_length = 0;
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	init_timer(&p->sinbin_timer);
+	p->sinbin_timer.data = (unsigned long) p;
+#endif
 }
 
 static inline void inc_cap_stats_cycle(task_t *p, unsigned long long now)
@@ -1213,6 +1229,64 @@ static void deactivate_task(struct task_
 	p->array = NULL;
 }
 
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+#define task_has_hard_cap(p) unlikely((p)->cpu_rate_hard_cap < 1000)
+
+/*
+ * Release a task from the sinbin
+ */
+static void sinbin_release_fn(unsigned long arg)
+{
+	unsigned long flags;
+	struct task_struct *p = (struct task_struct*)arg;
+	struct runqueue *rq = task_rq_lock(p, &flags);
+
+	p->prio = effective_prio(p);
+
+	__activate_task(p, rq);
+
+	task_rq_unlock(rq, &flags);
+}
+
+static unsigned long reqd_sinbin_ticks(const task_t *p)
+{
+	unsigned long long res;
+
+	res = p->avg_cpu_per_cycle * 1000;
+
+	if (res > p->avg_cycle_length * p->cpu_rate_hard_cap) {
+		(void)do_div(res, p->cpu_rate_hard_cap);
+		res -= p->avg_cpu_per_cycle;
+		/*
+		 * IF it was available we'd also subtract
+		 * the average sleep per cycle here
+		 */
+		res >>= CAP_STATS_OFFSET;
+		(void)do_div(res, (1000000000 / HZ));
+
+		return res ? : 1;
+	}
+
+	return 0;
+}
+
+static void sinbin_task(task_t *p, unsigned long durn)
+{
+	if (durn == 0)
+		return;
+	deactivate_task(p, task_rq(p));
+	p->sinbin_timer.expires = jiffies + durn;
+	add_timer(&p->sinbin_timer);
+}
+#else
+#define task_has_hard_cap(p) 0
+#define reqd_sinbin_ticks(p) 0
+
+static inline void sinbin_task(task_t *p, unsigned long durn)
+{
+}
+#endif
+
 /*
  * resched_task - mark a task 'to be rescheduled now'.
  *
@@ -3508,9 +3582,16 @@ need_resched_nonpreemptible:
 		}
 	}
 
-	/* do this now so that stats are correct for SMT code */
-	if (task_has_cap(prev))
+	if (task_has_cap(prev)) {
 		inc_cap_stats_both(prev, now);
+		if (task_has_hard_cap(prev) && !prev->state &&
+		    !rt_task(prev) && !signal_pending(prev)) {
+			unsigned long sinbin_ticks = reqd_sinbin_ticks(prev);
+
+			if (sinbin_ticks)
+				sinbin_task(prev, sinbin_ticks);
+		}
+	}
 
 	cpu = smp_processor_id();
 	if (unlikely(!rq->nr_running)) {
@@ -4539,6 +4620,67 @@ out:
 }
 
 EXPORT_SYMBOL(set_cpu_rate_cap);
+
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+unsigned int get_cpu_rate_hard_cap(const struct task_struct *p)
+{
+	return p->cpu_rate_hard_cap;
+}
+
+EXPORT_SYMBOL(get_cpu_rate_hard_cap);
+
+/*
+ * Require: 1 <= new_cap <= 1000
+ */
+int set_cpu_rate_hard_cap(struct task_struct *p, unsigned int new_cap)
+{
+	int is_allowed;
+	unsigned long flags;
+	struct runqueue *rq;
+	int delta;
+
+	if (new_cap > 1000 && new_cap > 0)
+		return -EINVAL;
+	is_allowed = capable(CAP_SYS_NICE);
+	/*
+	 * We have to be careful, if called from /proc code,
+	 * the task might be in the middle of scheduling on another CPU.
+	 */
+	rq = task_rq_lock(p, &flags);
+	delta = new_cap - p->cpu_rate_hard_cap;
+	if (!is_allowed) {
+		/*
+		 * Ordinary users can set/change caps on their own tasks
+		 * provided that the new setting is MORE constraining
+		 */
+		if (((current->euid != p->uid) && (current->uid != p->uid)) || (delta > 0)) {
+			task_rq_unlock(rq, &flags);
+			return -EPERM;
+		}
+	}
+	/*
+	 * The RT tasks don't have caps, but we still allow the caps to be
+	 * set - but as expected it wont have any effect on scheduling until
+	 * the task becomes SCHED_NORMAL/SCHED_BATCH:
+	 */
+	p->cpu_rate_hard_cap = new_cap;
+
+	if (has_rt_policy(p))
+		goto out;
+
+	if (p->array)
+		dec_raw_weighted_load(rq, p);
+	set_load_weight(p);
+	if (p->array)
+		inc_raw_weighted_load(rq, p);
+out:
+	task_rq_unlock(rq, &flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(set_cpu_rate_hard_cap);
+#endif
 #endif
 
 long sched_setaffinity(pid_t pid, cpumask_t new_mask)

-- 
Peter Williams                                   pwil3058@bigpond.net.au

"Learning, n. The kind of ignorance distinguishing the studious."
 -- Ambrose Bierce

^ permalink raw reply

* [RFC 2/5] sched: Add CPU rate soft caps
From: Peter Williams @ 2006-05-26  4:20 UTC (permalink / raw)
  To: Mike Galbraith
  Cc: Con Kolivas, Peter Williams, Linux Kernel, Kingsley Cheung,
	Ingo Molnar, Rene Herman
In-Reply-To: <20060526042021.2886.4957.sendpatchset@heathwren.pw.nest>

This patch implements (soft) CPU rate caps per task as a proportion of a
single CPU's capacity expressed in parts per thousand.  The CPU usage
of capped tasks is determined by using Kalman filters to calculate the
(recent) average lengths of the task's scheduling cycle and the time
spent on the CPU each cycle and taking the ratio of the latter to the
former.  To minimize overhead associated with uncapped tasks these
statistics are not kept for them.

Notes:

1. To minimize the overhead incurred when testing to skip caps processing for
uncapped tasks a new flag PF_HAS_CAP has been added to flags.

2. The implementation involves the addition of two priority slots to the
run queue priority arrays and this means that MAX_PRIO no longer
represents the scheduling priority of the idle process and can't be used to
test whether priority values are in the valid range.  To alleviate this
problem a new function sched_idle_prio() has been provided.

3. Enforcement of caps is not as strict as it could be in order to
reduce the possibility of a task being starved of CPU while holding
an important system resource with resultant overall performance
degradation.  In effect, all runnable capped tasks will get some amount
of CPU access every active/expired swap cycle.  This will be most
apparent for small or zero soft caps.

Signed-off-by: Peter Williams <pwil3058@bigpond.com.au>

 include/linux/sched.h  |   16 ++
 init/Kconfig           |    2 
 kernel/Kconfig.caps    |   13 +
 kernel/rtmutex-debug.c |    4 
 kernel/sched.c         |  362 ++++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 375 insertions(+), 22 deletions(-)

Index: MM-2.6.17-rc4-mm3/include/linux/sched.h
===================================================================
--- MM-2.6.17-rc4-mm3.orig/include/linux/sched.h	2006-05-26 10:43:21.000000000 +1000
+++ MM-2.6.17-rc4-mm3/include/linux/sched.h	2006-05-26 10:46:35.000000000 +1000
@@ -494,6 +494,12 @@ struct signal_struct {
 #define has_rt_policy(p) \
 	unlikely((p)->policy != SCHED_NORMAL && (p)->policy != SCHED_BATCH)
 
+#ifdef CONFIG_CPU_RATE_CAPS
+int sched_idle_prio(void);
+#else
+#define sched_idle_prio()	MAX_PRIO
+#endif
+
 /*
  * Some day this will be a full-fledged user tracking system..
  */
@@ -787,6 +793,10 @@ struct task_struct {
 	unsigned long sleep_avg;
 	unsigned long long timestamp, last_ran;
 	unsigned long long sched_time; /* sched_clock time spent running */
+#ifdef CONFIG_CPU_RATE_CAPS
+	unsigned long long avg_cpu_per_cycle, avg_cycle_length;
+	unsigned int cpu_rate_cap;
+#endif
 	enum sleep_type sleep_type;
 
 	unsigned long policy;
@@ -981,6 +991,11 @@ struct task_struct {
 #endif
 };
 
+#ifdef CONFIG_CPU_RATE_CAPS
+unsigned int get_cpu_rate_cap(const struct task_struct *);
+int set_cpu_rate_cap(struct task_struct *, unsigned int);
+#endif
+
 static inline pid_t process_group(struct task_struct *tsk)
 {
 	return tsk->signal->pgrp;
@@ -1040,6 +1055,7 @@ static inline void put_task_struct(struc
 #define PF_SPREAD_SLAB	0x08000000	/* Spread some slab caches over cpuset */
 #define PF_MEMPOLICY	0x10000000	/* Non-default NUMA mempolicy */
 #define PF_MUTEX_TESTER	0x02000000	/* Thread belongs to the rt mutex tester */
+#define PF_HAS_CAP	0x20000000	/* Has a CPU rate cap */
 
 /*
  * Only the _current_ task can read/write to tsk->flags, but other
Index: MM-2.6.17-rc4-mm3/init/Kconfig
===================================================================
--- MM-2.6.17-rc4-mm3.orig/init/Kconfig	2006-05-26 10:39:59.000000000 +1000
+++ MM-2.6.17-rc4-mm3/init/Kconfig	2006-05-26 10:45:26.000000000 +1000
@@ -286,6 +286,8 @@ config RELAY
 
 	  If unsure, say N.
 
+source "kernel/Kconfig.caps"
+
 source "usr/Kconfig"
 
 config UID16
Index: MM-2.6.17-rc4-mm3/kernel/Kconfig.caps
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ MM-2.6.17-rc4-mm3/kernel/Kconfig.caps	2006-05-26 10:45:26.000000000 +1000
@@ -0,0 +1,13 @@
+#
+# CPU Rate Caps Configuration
+#
+
+config CPU_RATE_CAPS
+	bool "Support (soft) CPU rate caps"
+	default n
+	---help---
+	  Say y here if you wish to be able to put a (soft) upper limit on
+	  the rate of CPU usage by individual tasks.  A task which has been
+	  allocated a soft CPU rate cap will be limited to that rate of CPU
+	  usage unless there is spare CPU resources available after the needs
+	  of uncapped tasks are met.
Index: MM-2.6.17-rc4-mm3/kernel/sched.c
===================================================================
--- MM-2.6.17-rc4-mm3.orig/kernel/sched.c	2006-05-26 10:44:51.000000000 +1000
+++ MM-2.6.17-rc4-mm3/kernel/sched.c	2006-05-26 11:00:02.000000000 +1000
@@ -57,6 +57,19 @@
 
 #include <asm/unistd.h>
 
+#ifdef CONFIG_CPU_RATE_CAPS
+#define IDLE_PRIO	(MAX_PRIO + 2)
+#else
+#define IDLE_PRIO	MAX_PRIO
+#endif
+#define BGND_PRIO	(IDLE_PRIO - 1)
+#define CAPPED_PRIO	(IDLE_PRIO - 2)
+
+int sched_idle_prio(void)
+{
+	return IDLE_PRIO;
+}
+
 /*
  * Convert user-nice values [ -20 ... 0 ... 19 ]
  * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
@@ -186,6 +199,149 @@ static inline unsigned int task_timeslic
 	return static_prio_timeslice(p->static_prio);
 }
 
+#ifdef CONFIG_CPU_RATE_CAPS
+#define CAP_STATS_OFFSET 8
+#define task_has_cap(p) unlikely((p)->flags & PF_HAS_CAP)
+/* this assumes that p is not a real time task */
+#define task_is_background(p) unlikely((p)->cpu_rate_cap == 0)
+#define task_being_capped(p) unlikely((p)->prio >= CAPPED_PRIO)
+#define cap_load_weight(p) (((p)->cpu_rate_cap * SCHED_LOAD_SCALE) / 1000)
+
+static void init_cpu_rate_caps(task_t *p)
+{
+	p->cpu_rate_cap = 1000;
+	p->flags &= ~PF_HAS_CAP;
+}
+
+static inline void set_cap_flag(task_t *p)
+{
+	if (p->cpu_rate_cap < 1000 && !has_rt_policy(p))
+		p->flags |= PF_HAS_CAP;
+	else
+		p->flags &= ~PF_HAS_CAP;
+}
+
+static inline int task_exceeding_cap(const task_t *p)
+{
+	return (p->avg_cpu_per_cycle * 1000) > (p->avg_cycle_length * p->cpu_rate_cap);
+}
+
+#ifdef CONFIG_SCHED_SMT
+static unsigned int smt_timeslice(task_t *p)
+{
+	if (task_has_cap(p) && task_being_capped(p))
+		return 0;
+
+	return task_timeslice(p);
+}
+
+static int task_priority_gt(const task_t *thisp, const task_t *thatp)
+{
+	if (task_has_cap(thisp) && (task_being_capped(thisp)))
+	    return 0;
+
+	if (task_has_cap(thatp) && (task_being_capped(thatp)))
+	    return 1;
+
+	return thisp->static_prio < thatp->static_prio;
+}
+#endif
+
+/*
+ * Update usage stats to "now" before making comparison
+ * Assume: task is actually on a CPU
+ */
+static int task_exceeding_cap_now(const task_t *p, unsigned long long now)
+{
+	unsigned long long delta, lhs, rhs;
+
+	delta = (now > p->timestamp) ? (now - p->timestamp) : 0;
+	lhs = (p->avg_cpu_per_cycle + delta) * 1000;
+	rhs = (p->avg_cycle_length + delta) * p->cpu_rate_cap;
+
+	return lhs > rhs;
+}
+
+static inline void init_cap_stats(task_t *p)
+{
+	p->avg_cpu_per_cycle = 0;
+	p->avg_cycle_length = 0;
+}
+
+static inline void inc_cap_stats_cycle(task_t *p, unsigned long long now)
+{
+	unsigned long long delta;
+
+	delta = (now > p->timestamp) ? (now - p->timestamp) : 0;
+	p->avg_cycle_length += delta;
+}
+
+static inline void inc_cap_stats_both(task_t *p, unsigned long long now)
+{
+	unsigned long long delta;
+
+	delta = (now > p->timestamp) ? (now - p->timestamp) : 0;
+	p->avg_cycle_length += delta;
+	p->avg_cpu_per_cycle += delta;
+}
+
+static inline void decay_cap_stats(task_t *p)
+{
+	p->avg_cycle_length *= ((1 << CAP_STATS_OFFSET) - 1);
+	p->avg_cycle_length >>= CAP_STATS_OFFSET;
+	p->avg_cpu_per_cycle *= ((1 << CAP_STATS_OFFSET) - 1);
+	p->avg_cpu_per_cycle >>= CAP_STATS_OFFSET;
+}
+#else
+#define task_has_cap(p) 0
+#define task_is_background(p) 0
+#define task_being_capped(p) 0
+#define cap_load_weight(p) SCHED_LOAD_SCALE
+
+static inline void init_cpu_rate_caps(task_t *p)
+{
+}
+
+static inline void set_cap_flag(task_t *p)
+{
+}
+
+static inline int task_exceeding_cap(const task_t *p)
+{
+	return 0;
+}
+
+#ifdef CONFIG_SCHED_SMT
+#define smt_timeslice(p) task_timeslice(p)
+
+static inline int task_priority_gt(const task_t *thisp, const task_t *thatp)
+{
+	return thisp->static_prio < thatp->static_prio;
+}
+#endif
+
+static inline int task_exceeding_cap_now(const task_t *p, unsigned long long now)
+{
+	return 0;
+}
+
+static inline void init_cap_stats(task_t *p)
+{
+}
+
+static inline void inc_cap_stats_cycle(task_t *p, unsigned long long now)
+{
+}
+
+static inline void inc_cap_stats_both(task_t *p, unsigned long long now)
+{
+}
+
+static inline void decay_cap_stats(task_t *p)
+{
+}
+#endif
+
 #define task_hot(p, now, sd) ((long long) ((now) - (p)->last_ran)	\
 				< (long long) (sd)->cache_hot_time)
 
@@ -197,8 +353,8 @@ typedef struct runqueue runqueue_t;
 
 struct prio_array {
 	unsigned int nr_active;
-	DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
-	struct list_head queue[MAX_PRIO];
+	DECLARE_BITMAP(bitmap, IDLE_PRIO+1); /* include 1 bit for delimiter */
+	struct list_head queue[IDLE_PRIO];
 };
 
 /*
@@ -710,6 +866,10 @@ static inline int __normal_prio(task_t *
 {
 	int bonus, prio;
 
+	/* Ensure that background tasks stay at BGND_PRIO */
+	if (task_is_background(p))
+		return BGND_PRIO;
+
 	bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
 
 	prio = p->static_prio - bonus;
@@ -786,6 +946,8 @@ static inline int expired_starving(runqu
 
 static void set_load_weight(task_t *p)
 {
+	set_cap_flag(p);
+
 	if (has_rt_policy(p)) {
 #ifdef CONFIG_SMP
 		if (p == task_rq(p)->migration_thread)
@@ -798,8 +960,22 @@ static void set_load_weight(task_t *p)
 		else
 #endif
 			p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
-	} else
+	} else {
 		p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);
+
+		/*
+		 * Reduce the probability of a task escaping its CPU rate cap
+		 * due to load balancing leaving it on a lighly used CPU
+		 * This will be optimized away if rate caps aren't configured
+		 */
+		if (task_has_cap(p)) {
+			unsigned int clw; /* load weight based on cap */
+
+			clw = cap_load_weight(p);
+			if (clw < p->load_weight)
+				p->load_weight = clw;
+		}
+	}
 }
 
 static inline void inc_raw_weighted_load(runqueue_t *rq, const task_t *p)
@@ -869,7 +1045,8 @@ static void __activate_task(task_t *p, r
 {
 	prio_array_t *target = rq->active;
 
-	if (unlikely(batch_task(p) || (expired_starving(rq) && !rt_task(p))))
+	if (unlikely(batch_task(p) || (expired_starving(rq) && !rt_task(p)) ||
+			task_being_capped(p)))
 		target = rq->expired;
 	enqueue_task(p, target);
 	inc_nr_running(p, rq);
@@ -975,8 +1152,30 @@ static void activate_task(task_t *p, run
 #endif
 
 	if (!rt_task(p))
+		/*
+		 * We want to do the recalculation even if we're exceeding
+		 * a cap so that everything still works when we stop
+		 * exceeding our cap.
+		 */
 		p->prio = recalc_task_prio(p, now);
 
+	if (task_has_cap(p)) {
+		inc_cap_stats_cycle(p, now);
+		/* Background tasks are handled in effective_prio()
+		 * in order to ensure that they stay at BGND_PRIO
+		 * but we need to be careful that we don't override
+		 * it here
+		 */
+		if (task_exceeding_cap(p) && !task_is_background(p)) {
+			p->normal_prio = CAPPED_PRIO;
+			/*
+			 * Don't undo any priority ineheritance
+			 */
+			if (!rt_task(p))
+				p->prio = CAPPED_PRIO;
+		}
+	}
+
 	/*
 	 * This checks to make sure it's not an uninterruptible task
 	 * that is now waking up.
@@ -1566,6 +1765,7 @@ void fastcall sched_fork(task_t *p, int 
 #endif
 	set_task_cpu(p, cpu);
 
+	init_cap_stats(p);
 	/*
 	 * We mark the process as running here, but have not actually
 	 * inserted it onto the runqueue yet. This guarantees that
@@ -2040,7 +2240,7 @@ void pull_task(runqueue_t *src_rq, prio_
 	p->timestamp = (p->timestamp - src_rq->timestamp_last_tick)
 				+ this_rq->timestamp_last_tick;
 	/*
-	 * Note that idle threads have a prio of MAX_PRIO, for this test
+	 * Note that idle threads have a prio of IDLE_PRIO, for this test
 	 * to be always true for them.
 	 */
 	if (TASK_PREEMPTS_CURR(p, this_rq))
@@ -2140,8 +2340,8 @@ skip_bitmap:
 	if (!idx)
 		idx = sched_find_first_bit(array->bitmap);
 	else
-		idx = find_next_bit(array->bitmap, MAX_PRIO, idx);
-	if (idx >= MAX_PRIO) {
+		idx = find_next_bit(array->bitmap, IDLE_PRIO, idx);
+	if (idx >= IDLE_PRIO) {
 		if (array == busiest->expired && busiest->active->nr_active) {
 			array = busiest->active;
 			dst_array = this_rq->active;
@@ -2931,15 +3131,58 @@ void scheduler_tick(void)
 		}
 		goto out_unlock;
 	}
+	/* Only check for task exceeding cap if it's worthwhile */
+	if (task_has_cap(p)) {
+		/*
+		 * Do this even if there's only one task on the queue as
+		 * we want to set the priority low so that any waking tasks
+		 * can preempt.
+		 */
+		if (task_being_capped(p)) {
+			/*
+			 * Tasks whose cap is currently being enforced will be
+			 * at CAPPED_PRIO or BGND_PRIO priority and preemption
+			 * should be enough to keep them in check provided we
+			 * don't let them adversely effect tasks on the expired
+			 * array
+			 */
+			if (!task_is_background(p) && !task_exceeding_cap_now(p, now)) {
+				dequeue_task(p, rq->active);
+				p->prio = effective_prio(p);
+				enqueue_task(p, rq->active);
+			} else if (rq->expired->nr_active && rq->best_expired_prio < p->prio) {
+				dequeue_task(p, rq->active);
+				enqueue_task(p, rq->expired);
+				set_tsk_need_resched(p);
+				goto out_unlock;
+			}
+		} else if (task_exceeding_cap_now(p, now)) {
+			dequeue_task(p, rq->active);
+			p->prio = CAPPED_PRIO;
+			enqueue_task(p, rq->expired);
+			/*
+			 * think about making this conditional to reduce
+			 * context switch rate
+			 */
+			set_tsk_need_resched(p);
+			goto out_unlock;
+		}
+	}
 	if (!--p->time_slice) {
 		dequeue_task(p, rq->active);
 		set_tsk_need_resched(p);
-		p->prio = effective_prio(p);
+		if (!task_being_capped(p))
+			p->prio = effective_prio(p);
 		p->time_slice = task_timeslice(p);
 		p->first_time_slice = 0;
 
 		if (!rq->expired_timestamp)
 			rq->expired_timestamp = jiffies;
+		/*
+		 * No need to do anything special for capped tasks as here
+		 * TASK_INTERACTIVE() should fail when they're exceeding
+		 * their caps.
+		 */
 		if (!TASK_INTERACTIVE(p) || expired_starving(rq)) {
 			enqueue_task(p, rq->expired);
 			if (p->static_prio < rq->best_expired_prio)
@@ -3104,9 +3347,9 @@ static int dependent_sleeper(int this_cp
 				(sd->per_cpu_gain * DEF_TIMESLICE / 100))
 					ret = 1;
 		} else
-			if (smt_curr->static_prio < p->static_prio &&
+			if (task_priority_gt(smt_curr, p) &&
 				!TASK_PREEMPTS_CURR(p, smt_rq) &&
-				smt_slice(smt_curr, sd) > task_timeslice(p))
+				smt_slice(smt_curr, sd) > smt_timeslice(p))
 					ret = 1;
 
 check_smt_task:
@@ -3129,7 +3372,7 @@ check_smt_task:
 					resched_task(smt_curr);
 		} else {
 			if (TASK_PREEMPTS_CURR(p, smt_rq) &&
-				smt_slice(p, sd) > task_timeslice(smt_curr))
+				smt_slice(p, sd) > smt_timeslice(smt_curr))
 					resched_task(smt_curr);
 			else
 				wakeup_busy_runqueue(smt_rq);
@@ -3265,6 +3508,10 @@ need_resched_nonpreemptible:
 		}
 	}
 
+	/* do this now so that stats are correct for SMT code */
+	if (task_has_cap(prev))
+		inc_cap_stats_both(prev, now);
+
 	cpu = smp_processor_id();
 	if (unlikely(!rq->nr_running)) {
 go_idle:
@@ -3305,7 +3552,7 @@ go_idle:
 		rq->expired = array;
 		array = rq->active;
 		rq->expired_timestamp = 0;
-		rq->best_expired_prio = MAX_PRIO;
+		rq->best_expired_prio = IDLE_PRIO;
 	}
 
 	idx = sched_find_first_bit(array->bitmap);
@@ -3323,7 +3570,7 @@ go_idle:
 		array = next->array;
 		new_prio = recalc_task_prio(next, next->timestamp + delta);
 
-		if (unlikely(next->prio != new_prio)) {
+		if (unlikely(next->prio != new_prio && !task_being_capped(next))) {
 			dequeue_task(next, array);
 			next->prio = new_prio;
 			enqueue_task(next, array);
@@ -3347,6 +3594,10 @@ switch_tasks:
 
 	sched_info_switch(prev, next);
 	if (likely(prev != next)) {
+		if (task_has_cap(next)) {
+			decay_cap_stats(next);
+			inc_cap_stats_cycle(next, now);
+		}
 		next->timestamp = now;
 		rq->nr_switches++;
 		rq->curr = next;
@@ -3792,7 +4043,7 @@ void rt_mutex_setprio(task_t *p, int pri
 	runqueue_t *rq;
 	int oldprio;
 
-	BUG_ON(prio < 0 || prio > MAX_PRIO);
+	BUG_ON(prio < 0 || prio > IDLE_PRIO);
 
 	rq = task_rq_lock(p, &flags);
 
@@ -4220,6 +4471,76 @@ out_unlock:
 	return retval;
 }
 
+#ifdef CONFIG_CPU_RATE_CAPS
+unsigned int get_cpu_rate_cap(const struct task_struct *p)
+{
+	return p->cpu_rate_cap;
+}
+
+EXPORT_SYMBOL(get_cpu_rate_cap);
+
+/*
+ * Require: 0 <= new_cap <= 1000
+ */
+int set_cpu_rate_cap(struct task_struct *p, unsigned int new_cap)
+{
+	int is_allowed;
+	unsigned long flags;
+	struct runqueue *rq;
+	prio_array_t *array;
+	int delta;
+
+	if (new_cap > 1000)
+		return -EINVAL;
+	is_allowed = capable(CAP_SYS_NICE);
+	/*
+	 * We have to be careful, if called from /proc code,
+	 * the task might be in the middle of scheduling on another CPU.
+	 */
+	rq = task_rq_lock(p, &flags);
+	delta = new_cap - p->cpu_rate_cap;
+	if (!is_allowed) {
+		/*
+		 * Ordinary users can set/change caps on their own tasks
+		 * provided that the new setting is MORE constraining
+		 */
+		if (((current->euid != p->uid) && (current->uid != p->uid)) || (delta > 0)) {
+			task_rq_unlock(rq, &flags);
+			return -EPERM;
+		}
+	}
+	/*
+	 * The RT tasks don't have caps, but we still allow the caps to be
+	 * set - but as expected it wont have any effect on scheduling until
+	 * the task becomes SCHED_NORMAL/SCHED_BATCH:
+	 */
+	p->cpu_rate_cap = new_cap;
+
+	if (has_rt_policy(p))
+		goto out;
+
+	array = p->array;
+	if (array) {
+		dec_raw_weighted_load(rq, p);
+		dequeue_task(p, array);
+	}
+
+	set_load_weight(p);
+	p->prio = effective_prio(p);
+
+	if (array) {
+		enqueue_task(p, array);
+		inc_raw_weighted_load(rq, p);
+	}
+out:
+	task_rq_unlock(rq, &flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(set_cpu_rate_cap);
+#endif
+
 long sched_setaffinity(pid_t pid, cpumask_t new_mask)
 {
 	task_t *p;
@@ -4733,7 +5054,7 @@ void __devinit init_idle(task_t *idle, i
 	idle->timestamp = sched_clock();
 	idle->sleep_avg = 0;
 	idle->array = NULL;
-	idle->prio = idle->normal_prio = MAX_PRIO;
+	idle->prio = idle->normal_prio = IDLE_PRIO;
 	idle->state = TASK_RUNNING;
 	idle->cpus_allowed = cpumask_of_cpu(cpu);
 	set_task_cpu(idle, cpu);
@@ -5074,7 +5395,7 @@ static void migrate_dead_tasks(unsigned 
 	struct runqueue *rq = cpu_rq(dead_cpu);
 
 	for (arr = 0; arr < 2; arr++) {
-		for (i = 0; i < MAX_PRIO; i++) {
+		for (i = 0; i < IDLE_PRIO; i++) {
 			struct list_head *list = &rq->arrays[arr].queue[i];
 			while (!list_empty(list))
 				migrate_dead(dead_cpu,
@@ -5244,7 +5565,7 @@ static int migration_call(struct notifie
 		/* Idle task back to normal (off runqueue, low prio) */
 		rq = task_rq_lock(rq->idle, &flags);
 		deactivate_task(rq->idle, rq);
-		rq->idle->static_prio = MAX_PRIO;
+		rq->idle->static_prio = IDLE_PRIO;
 		__setscheduler(rq->idle, SCHED_NORMAL, 0);
 		migrate_dead_tasks(cpu);
 		task_rq_unlock(rq, &flags);
@@ -6657,7 +6978,7 @@ void __init sched_init(void)
 		rq->nr_running = 0;
 		rq->active = rq->arrays;
 		rq->expired = rq->arrays + 1;
-		rq->best_expired_prio = MAX_PRIO;
+		rq->best_expired_prio = IDLE_PRIO;
 
 #ifdef CONFIG_SMP
 		rq->sd = NULL;
@@ -6673,15 +6994,16 @@ void __init sched_init(void)
 
 		for (j = 0; j < 2; j++) {
 			array = rq->arrays + j;
-			for (k = 0; k < MAX_PRIO; k++) {
+			for (k = 0; k < IDLE_PRIO; k++) {
 				INIT_LIST_HEAD(array->queue + k);
 				__clear_bit(k, array->bitmap);
 			}
 			// delimiter for bitsearch
-			__set_bit(MAX_PRIO, array->bitmap);
+			__set_bit(IDLE_PRIO, array->bitmap);
 		}
 	}
 
+	init_cpu_rate_caps(&init_task);
 	set_load_weight(&init_task);
 	/*
 	 * The boot idle thread does lazy MMU switching as well:
Index: MM-2.6.17-rc4-mm3/kernel/rtmutex-debug.c
===================================================================
--- MM-2.6.17-rc4-mm3.orig/kernel/rtmutex-debug.c	2006-05-26 10:39:59.000000000 +1000
+++ MM-2.6.17-rc4-mm3/kernel/rtmutex-debug.c	2006-05-26 10:45:26.000000000 +1000
@@ -479,8 +479,8 @@ void debug_rt_mutex_proxy_unlock(struct 
 void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter)
 {
 	memset(waiter, 0x11, sizeof(*waiter));
-	plist_node_init(&waiter->list_entry, MAX_PRIO);
-	plist_node_init(&waiter->pi_list_entry, MAX_PRIO);
+	plist_node_init(&waiter->list_entry, sched_idle_prio());
+	plist_node_init(&waiter->pi_list_entry, sched_idle_prio());
 }
 
 void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)

-- 
Peter Williams                                   pwil3058@bigpond.net.au

"Learning, n. The kind of ignorance distinguishing the studious."
 -- Ambrose Bierce

^ permalink raw reply

* [RFC 1/5] sched: Fix priority inheritence before CPU rate soft caps
From: Peter Williams @ 2006-05-26  4:20 UTC (permalink / raw)
  To: Mike Galbraith
  Cc: Con Kolivas, Peter Williams, Linux Kernel, Kingsley Cheung,
	Ingo Molnar, Rene Herman
In-Reply-To: <20060526042021.2886.4957.sendpatchset@heathwren.pw.nest>

Problem:

The advent of priority inheritance (PI) (in -mm kernels) means that the
prio field for non real time tasks can no longer be guaranteed to be
greater than or equal to MAX_RT_PRIO.  This, in turn, means that the
rt_task() macro is no longer a reliable test for determining if the
scheduler policy of a task is one of the real time policies.

Redefining rt_task() is not a good solution as the majority places
where it is used within sched.c the current definition is what is
required. However, this is not the case in the functions
set_load_weight() and set_user_nice() (and perhaps elsewhere in the
kernel).

Solution:

Define a new macro, has_rt_policy(), that returns true if the task given
as an argument has a policy of SCHED_RR or SCHED_FIFO and use this
inside set_load_weight() and set_user_nice().  The definition is made in
sched.h so that it is generally available should it be needed elsewhere
in the kernel.

Signed-off-by: Peter Williams <pwil3058@bigpond.com.au>
 include/linux/sched.h |    2 ++
 kernel/sched.c        |   15 +++++++--------
 2 files changed, 9 insertions(+), 8 deletions(-)

Index: MM-2.6.17-rc4-mm3/include/linux/sched.h
===================================================================
--- MM-2.6.17-rc4-mm3.orig/include/linux/sched.h	2006-05-26 10:39:59.000000000 +1000
+++ MM-2.6.17-rc4-mm3/include/linux/sched.h	2006-05-26 10:43:21.000000000 +1000
@@ -491,6 +491,8 @@ struct signal_struct {
 #define rt_prio(prio)		unlikely((prio) < MAX_RT_PRIO)
 #define rt_task(p)		rt_prio((p)->prio)
 #define batch_task(p)		(unlikely((p)->policy == SCHED_BATCH))
+#define has_rt_policy(p) \
+	unlikely((p)->policy != SCHED_NORMAL && (p)->policy != SCHED_BATCH)
 
 /*
  * Some day this will be a full-fledged user tracking system..
Index: MM-2.6.17-rc4-mm3/kernel/sched.c
===================================================================
--- MM-2.6.17-rc4-mm3.orig/kernel/sched.c	2006-05-26 10:39:59.000000000 +1000
+++ MM-2.6.17-rc4-mm3/kernel/sched.c	2006-05-26 10:44:51.000000000 +1000
@@ -786,7 +786,7 @@ static inline int expired_starving(runqu
 
 static void set_load_weight(task_t *p)
 {
-	if (rt_task(p)) {
+	if (has_rt_policy(p)) {
 #ifdef CONFIG_SMP
 		if (p == task_rq(p)->migration_thread)
 			/*
@@ -835,7 +835,7 @@ static inline int normal_prio(task_t *p)
 {
 	int prio;
 
-	if (p->policy != SCHED_NORMAL && p->policy != SCHED_BATCH)
+	if (has_rt_policy(p))
 		prio = MAX_RT_PRIO-1 - p->rt_priority;
 	else
 		prio = __normal_prio(p);
@@ -3831,7 +3831,7 @@ void set_user_nice(task_t *p, long nice)
 	unsigned long flags;
 	prio_array_t *array;
 	runqueue_t *rq;
-	int old_prio, new_prio, delta;
+	int old_prio, delta;
 
 	if (TASK_NICE(p) == nice || nice < -20 || nice > 19)
 		return;
@@ -3846,7 +3846,7 @@ void set_user_nice(task_t *p, long nice)
 	 * it wont have any effect on scheduling until the task is
 	 * not SCHED_NORMAL/SCHED_BATCH:
 	 */
-	if (rt_task(p)) {
+	if (has_rt_policy(p)) {
 		p->static_prio = NICE_TO_PRIO(nice);
 		goto out_unlock;
 	}
@@ -3856,12 +3856,11 @@ void set_user_nice(task_t *p, long nice)
 		dec_raw_weighted_load(rq, p);
 	}
 
-	old_prio = p->prio;
-	new_prio = NICE_TO_PRIO(nice);
-	delta = new_prio - old_prio;
 	p->static_prio = NICE_TO_PRIO(nice);
 	set_load_weight(p);
-	p->prio += delta;
+	old_prio = p->prio;
+	p->prio = effective_prio(p);
+	delta = p->prio - old_prio;
 
 	if (array) {
 		enqueue_task(p, array);

-- 
Peter Williams                                   pwil3058@bigpond.net.au

"Learning, n. The kind of ignorance distinguishing the studious."
 -- Ambrose Bierce

^ permalink raw reply

* [RFC 0/5] sched: Add CPU rate caps
From: Peter Williams @ 2006-05-26  4:20 UTC (permalink / raw)
  To: Mike Galbraith
  Cc: Con Kolivas, Peter Williams, Linux Kernel, Kingsley Cheung,
	Ingo Molnar, Rene Herman

These patches implement CPU usage rate limits for tasks.

Although the rlimit mechanism already has a CPU usage limit (RLIMIT_CPU)
it is a total usage limit and therefore (to my mind) not very useful.
These patches provide an alternative whereby the (recent) average CPU
usage rate of a task can be limited to a (per task) specified proportion
of a single CPU's capacity.  The limits are specified in parts per
thousand and come in two varieties -- hard and soft.  The difference
between the two is that the system tries to enforce hard caps regardless
of the other demand for CPU resources but allows soft caps to be
exceeded if there are spare CPU resources available.  By default, tasks
will have both caps set to 1000 (i.e. no limit) but newly forked tasks
will inherit any caps that have been imposed on their parent from the
parent.  The mimimim soft cap allowed is 0 (which effectively puts the
task in the background) and the minimim hard cap allowed is 1.

Care has been taken to minimize the overhead inflicted on tasks that
have no caps and my tests using kernbench indicate that it is hidden in
the noise.

Note:

The first patch in this series fixes some problems with priority
inheritance that are present in 2.6.17-rc4-mm3 but will be fixed in
the next -mm kernel.

Signed-off-by: Peter Williams <pwil3058@bigpond.com.au>


-- 
Peter Williams                                   pwil3058@bigpond.net.au

"Learning, n. The kind of ignorance distinguishing the studious."
 -- Ambrose Bierce

^ permalink raw reply

* Re: [PATCH 1/2] request_firmware without a device
From: Greg KH @ 2006-05-26  4:06 UTC (permalink / raw)
  To: Shaohua Li; +Cc: Marcel Holtmann, lkml, Patrick Mochel, Andrew Morton
In-Reply-To: <1148614839.32046.143.camel@sli10-desk.sh.intel.com>

On Fri, May 26, 2006 at 11:40:39AM +0800, Shaohua Li wrote:
> On Thu, 2006-05-25 at 12:24 +0200, Marcel Holtmann wrote:
> > Hi Greg,
> > 
> > > > The patch allows calling request_firmware without a 'struct device'.
> > > > It appears we just need a name here from 'struct device'. I changed it
> > > > to use a kobject as Patrick suggested.
> > > > Next patch will use the new API to request firmware (microcode) for a CPU.
> > > 
> > > But a cpu does have a struct device.  Why not just use that?
> > > 
> > > > +fw_setup_class_device_id(struct class_device *class_dev, struct kobject *kobj)
> > > >  {
> > > >  	/* XXX warning we should watch out for name collisions */
> > > > -	strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
> > > > +	strlcpy(class_dev->class_id, kobj->k_name, BUS_ID_SIZE);
> > > 
> > > There's a function for this, kobject_name(), please never touch k_name
> > > directly.
> > > 
> > > > +EXPORT_SYMBOL(request_firmware_kobj);
> > > 
> > > Ick, if you really want to do this, just fix up all callers of
> > > request_firmware(), there aren't that many of them.
> > > 
> > > But I don't recommend it anyway.
> > 
> > I also disagree with this change at all. The callers of request_firmware
> > should not fiddle around with kobject's to make this work. All of them
> > have their struct device and they should use it.
> So why we need a 'struct device'? I didn't see any point we need it. We
> just need a 'name'.

You need a kobject, as ideally we would have a symlink back to the
"real" kobject.  So far, only "devices" need firmware, that's why it is
that way.

> > So I would propose that we fix the caller and the not request_firmware
> > code. However one option would be calling it with NULL as device
> > argument and it registers itself a dummy device for the operation.
> This doesn't work, as we need a 'name'.
> 
> do we really need to differentiate between sysdev and device anymore. I
> > recall a plan to unify all devices, but I might be wrong.
> I'd like this idea. But it means many works. In addition, a sysdev could
> have multiple drivers, and a 'device' can't to me.

Today a sysdev can have that?  Ick.  Any examples of ones that really
do?

thanks,

greg k-h

^ permalink raw reply

* Re: [ANNOUNCE] Linux Device Driver Kit available
From: Greg KH @ 2006-05-26  4:09 UTC (permalink / raw)
  To: Tim Bird; +Cc: linux-kernel
In-Reply-To: <44760C89.4070904@am.sony.com>

On Thu, May 25, 2006 at 12:59:05PM -0700, Tim Bird wrote:
> If Jonathon thinks it's OK, I think the Kernel content from LWN would
> be a great addition to the CD: http://lwn.net/Kernel/
> 
> (especially: http://lwn.net/Kernel/Index/ and children).

A number of people have asked for this already.  I'll talk with them
about it, as they own the copyright for that material.

thanks,

greg k-h

^ permalink raw reply

* Fwd: [RFC] New netfilter match
From: Alex Davis @ 2006-05-26  4:18 UTC (permalink / raw)
  To: linux-kernel

I posted this to netfilter-devel@lists.netfilter.org 5 hours ago and it hasn't 
appeared on that list yet.


--- Alex Davis <alex14641@yahoo.com> wrote:

> 
> This is a proposal for a new netfilter module. 
> Please read and furnish comments.
> 
> http://linux.ace-technologies.biz:81/ipisforif.html
> 
>  
> Thanks
> 
> -Alex

I code, therefore I am

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

^ permalink raw reply

* why svc_export_lookup() has no implementation?
From: Xin Zhao @ 2006-05-26  4:15 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-fsdevel

I noticed that functions like exp_get_by_name() calls function
svc_export_lookup(). But I cannot find the implementation of
svc_export_lookup(). I can only find the function definition. HOw can
this happen?

Can someone give me a hand?

Thanks!

-x

^ permalink raw reply

* Re: Linux Kernel Source Compression
From: Bruce Guenter @ 2006-05-26  4:11 UTC (permalink / raw)
  To: linux-kernel
In-Reply-To: <Pine.LNX.4.64.0605211028100.4037@p34>

[-- Attachment #1: Type: text/plain, Size: 615 bytes --]

On Sun, May 21, 2006 at 10:35:00AM -0400, Justin Piszcz wrote:
> Was curious as to which utilities would offer the best compression ratio 
> for the kernel source, I thought it'd be bzip2 or rar but lzma wins, 
> roughly 6 MiB smaller than bzip2.
> 
> $ du -sk * | sort -n
> 33520   linux-2.6.16.17.tar.lzma

Since it was requested by somebody:

$ du -sk linux-2.6.16.17.*
32904	linux-2.6.16.17.7z
39919	linux-2.6.16.17.tar.bz2

This was done with: 7z -mx=9
-- 
Bruce Guenter <bruce@untroubled.org> http://untroubled.org/
OpenPGP key: 699980E8 / D0B7 C8DD 365D A395 29DA  2E2A E96F B2DC 6999 80E8

[-- Attachment #2: Type: application/pgp-signature, Size: 191 bytes --]

^ permalink raw reply

* Re: [UPDATE][0/24]extend file size and filesystem size
From: sho @ 2006-05-26  4:05 UTC (permalink / raw)
  To: cmm; +Cc: adilger, jitendra, ext2-devel, linux-kernel

Hi Mingming,

On May 26, 2006, Mingming wrote:
> As we have discussed before, it's saner to define ext3 fs blocks type
> and group block type and then fix the kernel ext3 block variable type
> bugs....So above patches from me are going to be replaced by a new
> set of ext3 filesystem blocks patches, I have sent out a RFC to the
> ext2-devel list in the last few weeks:

I agree.  But the aim of this fix is to keep as much compatibility as
possible by making only >2TB file incompatible(RO).  So I didn't add
typedef for ext3 block type.

Now I'm working on changing the type of variables related to block,
including ext3_fileblk_t.  I'll send the update patches later.


Cheer, sho



^ permalink raw reply

* Re: [PATCH]  Per-superblock unused dentry LRU lists V3
From: David Chinner @ 2006-05-26  3:49 UTC (permalink / raw)
  To: Andrew Morton; +Cc: balbir, linux-kernel, linux-fsdevel
In-Reply-To: <20060525200100.142b2124.akpm@osdl.org>

On Thu, May 25, 2006 at 08:01:00PM -0700, Andrew Morton wrote:
> David Chinner <dgc@sgi.com> wrote:
> >
> > Per superblock dentry LRU lists.
> > 
> > ...
> >
> > +/*
> > + * Shrink the dentry LRU on a given superblock.
> > + *
> > + * If flags is non-zero, we need to do special processing based on
> > + * which flags are set. This means we don't need to maintain multiple
> > + * similar copies of this loop.
> > + */
> > +static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags)
> > +{

....

> > +		/*
> > +		 * If we are honouring the DCACHE_REFERENCED flag and the
> > +		 * dentry has this flag set, don't free it. Clear the flag
> > +		 * and put it back on the LRU
> > +		 */
> > +		if ((flags & DCACHE_REFERENCED) &&
> > +		    (dentry->d_flags & DCACHE_REFERENCED)) {
> > +			dentry->d_flags &= ~DCACHE_REFERENCED;
> > +			dentry_lru_add(dentry);
> > +			spin_unlock(&dentry->d_lock);
> > +			continue;
> 
> Here we put the dentry back onto the list which we're currently scanning. 
> So if `cnt' exceeds the number of dentries on this superblock we end up
> scanning some of them more than once.

Good point. Should be easy to fix because we know exactly how
many dentries are on the list before we start scanning...

> Seems odd.
> 
> > -static void prune_dcache(int count, struct super_block *sb)
> > +static void prune_dcache(int count)
> >  {
> >
> > ...
> >
> > +	struct super_block *sb;
> > +	static struct super_block *sb_hand = NULL;
> > +	int work_done = 0;
> > +
> > +	spin_lock(&sb_lock);
> > +	if (sb_hand == NULL)
> > +		sb_hand = sb_entry(super_blocks.next);
> > +restart:
> > +	list_for_each_entry(sb, &super_blocks, s_list) {
> > +		if (sb != sb_hand)
> >  			continue;
> > -		}
> >  		/*
> > -		 * If the dentry is not DCACHED_REFERENCED, it is time
> > -		 * to remove it from the dcache, provided the super block is
> > -		 * NULL (which means we are trying to reclaim memory)
> > -		 * or this dentry belongs to the same super block that
> > -		 * we want to shrink.
> > +		 * Found the next superblock to work on.  Move the hand
> > +		 * forwards so that parallel pruners work on a different sb
> >  		 */
> > +		work_done++;
> > +		sb_hand = sb_entry(sb->s_list.next);
> > +		sb->s_count++;
> > +		spin_unlock(&sb_lock);
> 
> Now sb_hand points at a superblock against which we have no reference.  How
> can we use sb_hand safely next time we call in here?  It could point at a
> now-freed superblock?

Yes, it could. but we don't use what sb_hand points at unless it
matches something in the list. Therefore it only gets used when it is
valid.

If sb_hand is not valid, then it won't match with any of the  sb's in the
list, we exist the loop, work_done is zero, and we restart after setting
sb_hand back to the first entry in the list.

> A better approach might be to rotate the super_blocks list as we walk
> through it, so the search always starts at super_blocks.next - that way,
> there's no need to introduce a new global to record where we're up to.

hmm, that'll stuff up other threads walking the superblock list. If we
rotate the head while they are in the middle of walking the list, then
we'll need more logic in __put_super_and_need_restart() to handle
the list head changing while traversals are occuring. It also makes
it difficult to give parallel shrinkers different superblocks to
work on because we can't rotate the head until we've traversed
the entire list or count is exhausted in prune_dcache....

> >  		/*
> > -		 * If this dentry is for "my" filesystem, then I can prune it
> > -		 * without taking the s_umount lock (I already hold it).
> > +		 * We need to be sure this filesystem isn't being unmounted,
> > +		 * otherwise we could race with generic_shutdown_super(), and
> > +		 * end up holding a reference to an inode while the filesystem
> > +		 * is unmounted.  So we try to get s_umount, and make sure
> > +		 * s_root isn't NULL.
> >  		 */
> > -		if (sb && dentry->d_sb == sb) {
> > -			prune_one_dentry(dentry);
> > -			continue;
> > +		if (down_read_trylock(&sb->s_umount)) {
> > +			if ((sb->s_root != NULL) &&
> > +			    (!list_empty(&sb->s_dentry_lru))) {
> > +				__shrink_dcache_sb(sb, &count,
> > +						DCACHE_REFERENCED);
> 
> um.  If `count' is 10000 and we have 100 superblocks each with 1000
> dentries, we end up scanning the first five to ten (depending upon
> DCACHE_REFERENCED density) superblocks to exhaustion and the rest not at
> all.  I think.

Yes, given the bug you pointed out above, then yes, that is probably correct.
However, given that prune_dcache() only has one caller now - the shrinker -
count is only ever going to be SHRINK_BATCH (128), this is not a big
problem right now because each new call into prune_dcache will start
on a different superblock...

> If so, I'd have thought that we'd be better off putting some balancing
> arithmetic in here.
> 
> number of dentries to scan on this sb =
> 	count * (number of dentries on this sb /
> 		number of dentries in the machine)

Agreed, and as I pointed out in the thread following the first version
of the patch I've been concerned with fixing the bug first. now that it
appears that I've fixed the bug, I'm looking at how to make this fairer.
The above is basically what I was thinking of doing.

It's a bit more complex than that, though. The above will always result
in zero due to the integer division. Turning it around as (count * nr_sb) /
nr_unused will lead to 32bit integer overflow with more than 20 million
dentries on a superblock (which we already exceed quite easily)....

So I'm thinking that the dentry stats need to be converted to longs
from ints as the only platforms where 32bit overflow will be a problem
are 64bit platforms...

Thoughts?

Cheers,

Dave.
-- 
Dave Chinner
R&D Software Enginner
SGI Australian Software Group

^ permalink raw reply

* [PATCH] POSIX-hostname up to 255 characters
From: Randy.Dunlap @ 2006-05-26  3:45 UTC (permalink / raw)
  To: lkml, drepper; +Cc: akpm, serue, sam, ebiederm, clg, dev


This patch is against 2.6.17-rc5, for review/comments, please.
It won't apply to -mm since Andrew has merged the uts-namespace patches.
I'll see about merging it with those patches next.
---

From: Randy Dunlap <rdunlap@xenotime.net>

Implement POSIX-defined length for 'hostname' so that hostnames
can be longer than 64 characters (max. 255 characters plus
terminating NULL character).

Adds sys_gethostname_long() and sys_sethostname_long().
Tested on i386 and x86_64.
Builds on powerpc(64).
Test program is at http://www.xenotime.net/linux/src/hostnamelong.c .

Consolidates many open-coded copiers of system_utsname into
functions in lib/utsname.c::put_oldold_uname(), put_old_uname(),
put_new_uname(). and put_long_uname().

gethostname:
http://www.opengroup.org/onlinepubs/009695399/functions/gethostname.html
sysconf:
http://www.opengroup.org/onlinepubs/009695399/functions/sysconf.html
unistd.h:
http://www.opengroup.org/onlinepubs/009695399/basedefs/unistd.h.html
limits.h:
http://www.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html


Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
---
 arch/i386/kernel/sys_i386.c      |   37 +------
 arch/i386/kernel/syscall_table.S |    3 
 arch/m32r/kernel/sys_m32r.c      |   12 --
 arch/mips/kernel/linux32.c       |    4 
 arch/mips/kernel/syscall.c       |   25 -----
 arch/powerpc/kernel/syscalls.c   |   37 +------
 arch/sh/kernel/sys_sh.c          |   11 --
 arch/sh64/kernel/sys_sh64.c      |   11 --
 arch/um/kernel/syscall_kern.c    |    9 -
 arch/x86_64/ia32/ia32entry.S     |    4 
 arch/x86_64/ia32/sys_ia32.c      |   39 +-------
 arch/x86_64/kernel/sys_x86_64.c  |    8 -
 arch/xtensa/kernel/syscalls.c    |    8 -
 drivers/char/random.c            |    2 
 include/asm-i386/unistd.h        |    6 +
 include/asm-m32r/unistd.h        |    1 
 include/asm-mips/unistd.h        |    3 
 include/asm-powerpc/unistd.h     |    2 
 include/asm-sh/unistd.h          |    1 
 include/asm-sh64/unistd.h        |    1 
 include/asm-um/unistd.h          |    2 
 include/asm-x86_64/unistd.h      |    8 +
 include/asm-xtensa/unistd.h      |    1 
 include/linux/syscalls.h         |    2 
 include/linux/utsname.h          |   21 ++++
 init/version.c                   |    3 
 kernel/power/power.h             |    2 
 kernel/sys.c                     |   42 ++++++++
 lib/Makefile                     |    2 
 lib/utsname.c                    |  188 +++++++++++++++++++++++++++++++++++++++
 net/ipv4/ipconfig.c              |    3 
 31 files changed, 334 insertions(+), 164 deletions(-)

--- linux-2617-rc5.orig/include/asm-i386/unistd.h
+++ linux-2617-rc5/include/asm-i386/unistd.h
@@ -322,8 +322,10 @@
 #define __NR_sync_file_range	314
 #define __NR_tee		315
 #define __NR_vmsplice		316
+#define __NR_gethostname_long	317
+#define __NR_sethostname_long	318
 
-#define NR_syscalls 317
+#define NR_syscalls 319
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
@@ -429,6 +431,8 @@ __syscall_return(type,__res); \
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_OLD_UNAME
+#define __ARCH_WANT_OLDOLD_UNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
--- linux-2617-rc5.orig/include/linux/utsname.h
+++ linux-2617-rc5/include/linux/utsname.h
@@ -30,7 +30,26 @@ struct new_utsname {
 	char domainname[65];
 };
 
-extern struct new_utsname system_utsname;
+/* for (POSIX) IEEE Std. 1003.1, 2004 edition */
+#define __POSIX_HOST_NAME_MAX	255	/* not including terminating NUL char */
 
+struct long_utsname {
+	char sysname[__NEW_UTS_LEN + 1];	/* O/S name */
+	char nodename[__POSIX_HOST_NAME_MAX + 1]; /* hostname, but keep field
+					* name same as other structs here */
+	char release[__NEW_UTS_LEN + 1];	/* O/S release level */
+	char version[__NEW_UTS_LEN + 1];	/* version level of release */
+	char machine[__NEW_UTS_LEN + 1];	/* machine hardware type */
+	char domainname[__NEW_UTS_LEN + 1];
+};
+
+extern struct long_utsname system_utsname;
 extern struct rw_semaphore uts_sem;
+
+int put_oldold_uname(struct oldold_utsname __user *name);
+int __put_oldold_uname(struct oldold_utsname __user *name);
+int put_old_uname(struct old_utsname __user *name);
+int __put_old_uname(struct old_utsname __user *name);
+int put_new_uname(struct new_utsname __user *name);
+int __put_new_uname(struct new_utsname __user *name);
 #endif
--- linux-2617-rc5.orig/include/linux/syscalls.h
+++ linux-2617-rc5/include/linux/syscalls.h
@@ -432,7 +432,9 @@ asmlinkage long sys_epoll_ctl(int epfd, 
 asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
 				int maxevents, int timeout);
 asmlinkage long sys_gethostname(char __user *name, int len);
+asmlinkage long sys_gethostname_long(char __user *name, int len);
 asmlinkage long sys_sethostname(char __user *name, int len);
+asmlinkage long sys_sethostname_long(char __user *name, int len);
 asmlinkage long sys_setdomainname(char __user *name, int len);
 asmlinkage long sys_newuname(struct new_utsname __user *name);
 
--- linux-2617-rc5.orig/init/version.c
+++ linux-2617-rc5/init/version.c
@@ -17,7 +17,7 @@
 
 int version_string(LINUX_VERSION_CODE);
 
-struct new_utsname system_utsname = {
+struct long_utsname system_utsname = {
 	.sysname	= UTS_SYSNAME,
 	.nodename	= UTS_NODENAME,
 	.release	= UTS_RELEASE,
@@ -25,7 +25,6 @@ struct new_utsname system_utsname = {
 	.machine	= UTS_MACHINE,
 	.domainname	= UTS_DOMAINNAME,
 };
-
 EXPORT_SYMBOL(system_utsname);
 
 const char linux_banner[] =
--- linux-2617-rc5.orig/kernel/sys.c
+++ linux-2617-rc5/kernel/sys.c
@@ -1666,14 +1666,13 @@ DECLARE_RWSEM(uts_sem);
 
 EXPORT_SYMBOL(uts_sem);
 
+/* TBD: may also need a sys_uname_long() */
 asmlinkage long sys_newuname(struct new_utsname __user * name)
 {
 	int errno = 0;
 
-	down_read(&uts_sem);
-	if (copy_to_user(name,&system_utsname,sizeof *name))
+	if (put_new_uname(name))
 		errno = -EFAULT;
-	up_read(&uts_sem);
 	return errno;
 }
 
@@ -1697,6 +1696,26 @@ asmlinkage long sys_sethostname(char __u
 	return errno;
 }
 
+asmlinkage long sys_sethostname_long(char __user *name, int len)
+{
+	int errno;
+	char tmp[__POSIX_HOST_NAME_MAX + 1];
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (len < 0 || len > __POSIX_HOST_NAME_MAX)
+		return -EINVAL;
+	down_write(&uts_sem);
+	errno = -EFAULT;
+	if (!copy_from_user(tmp, name, len)) {
+		memcpy(system_utsname.nodename, tmp, len);
+		system_utsname.nodename[len] = 0;
+		errno = 0;
+	}
+	up_write(&uts_sem);
+	return errno;
+}
+
 #ifdef __ARCH_WANT_SYS_GETHOSTNAME
 
 asmlinkage long sys_gethostname(char __user *name, int len)
@@ -1718,6 +1737,23 @@ asmlinkage long sys_gethostname(char __u
 
 #endif
 
+asmlinkage long sys_gethostname_long(char __user *name, int len)
+{
+	int i, errno;
+
+	if (len < 0)
+		return -EINVAL;
+	down_read(&uts_sem);
+	i = 1 + strlen(system_utsname.nodename);
+	if (i > len)
+		i = len;
+	errno = 0;
+	if (copy_to_user(name, system_utsname.nodename, i))
+		errno = -EFAULT;
+	up_read(&uts_sem);
+	return errno;
+}
+
 /*
  * Only setdomainname; getdomainname can be implemented by calling
  * uname()
--- linux-2617-rc5.orig/kernel/power/power.h
+++ linux-2617-rc5/kernel/power/power.h
@@ -2,7 +2,7 @@
 #include <linux/utsname.h>
 
 struct swsusp_info {
-	struct new_utsname	uts;
+	struct long_utsname	uts;
 	u32			version_code;
 	unsigned long		num_physpages;
 	int			cpus;
--- linux-2617-rc5.orig/net/ipv4/ipconfig.c
+++ linux-2617-rc5/net/ipv4/ipconfig.c
@@ -806,7 +806,8 @@ static void __init ic_do_bootp_ext(u8 *e
 			}
 			break;
 		case 12:	/* Host name */
-			ic_bootp_string(system_utsname.nodename, ext+1, *ext, __NEW_UTS_LEN);
+			ic_bootp_string(system_utsname.nodename, ext+1, *ext,
+				sizeof(system_utsname.nodename));
 			ic_host_name_set = 1;
 			break;
 		case 15:	/* Domain name (DNS) */
--- linux-2617-rc5.orig/arch/mips/kernel/syscall.c
+++ linux-2617-rc5/arch/mips/kernel/syscall.c
@@ -232,9 +232,9 @@ out:
  */
 asmlinkage int sys_uname(struct old_utsname __user * name)
 {
-	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
-		return 0;
-	return -EFAULT;
+	if (put_old_uname(name))
+		return -EFAULT;
+	return 0;
 }
 
 /*
@@ -242,24 +242,7 @@ asmlinkage int sys_uname(struct old_utsn
  */
 asmlinkage int sys_olduname(struct oldold_utsname __user * name)
 {
-	int error;
-
-	if (!name)
-		return -EFAULT;
-	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
-		return -EFAULT;
-
-	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-	error -= __put_user(0,name->release+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-	error -= __put_user(0,name->version+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
-	error = __put_user(0,name->machine+__OLD_UTS_LEN);
-	error = error ? -EFAULT : 0;
+	int error = put_oldold_uname(name);
 
 	return error;
 }
--- /dev/null
+++ linux-2617-rc5/lib/utsname.c
@@ -0,0 +1,188 @@
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/rwsem.h>
+#include <linux/utsname.h>
+#include <asm/uaccess.h>
+
+#ifdef __ARCH_WANT_OLDOLD_UNAME
+
+int __put_oldold_uname(struct oldold_utsname __user *name)
+{
+	int error;
+
+	if (!name)
+		return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
+		return -EFAULT;
+
+	error = __copy_to_user(&name->sysname, &system_utsname.sysname,
+				__OLD_UTS_LEN);
+	error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
+	error |= __copy_to_user(&name->nodename, &system_utsname.nodename,
+				__OLD_UTS_LEN);
+	error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
+	error |= __copy_to_user(&name->release, &system_utsname.release,
+				__OLD_UTS_LEN);
+	error |= __put_user(0, name->release + __OLD_UTS_LEN);
+	error |= __copy_to_user(&name->version, &system_utsname.version,
+				__OLD_UTS_LEN);
+	error |= __put_user(0, name->version + __OLD_UTS_LEN);
+	error |= __copy_to_user(&name->machine, &system_utsname.machine,
+				__OLD_UTS_LEN);
+	error |= __put_user(0, name->machine + __OLD_UTS_LEN);
+
+	return error;
+}
+EXPORT_SYMBOL(__put_oldold_uname);
+
+int put_oldold_uname(struct oldold_utsname __user *name)
+{
+	int error;
+
+	down_read(&uts_sem);
+	error = __put_oldold_uname(name);
+	up_read(&uts_sem);
+
+	error = error ? -EFAULT : 0;
+	return error;
+}
+EXPORT_SYMBOL(put_oldold_uname);
+
+#endif
+
+#ifdef __ARCH_WANT_OLD_UNAME
+
+int __put_old_uname(struct old_utsname __user *name)
+{
+	int error;
+
+	if (!name)
+		return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, name, sizeof(struct old_utsname)))
+		return -EFAULT;
+
+	error = __copy_to_user(&name->sysname, &system_utsname.sysname,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->sysname + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->nodename, &system_utsname.nodename,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->nodename + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->release, &system_utsname.release,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->release + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->version, &system_utsname.version,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->version + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->machine, &system_utsname.machine,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->machine + __NEW_UTS_LEN);
+
+	return error;
+}
+EXPORT_SYMBOL(__put_old_uname);
+
+int put_old_uname(struct old_utsname __user *name)
+{
+	int error;
+
+	down_read(&uts_sem);
+	error = __put_old_uname(name);
+	up_read(&uts_sem);
+
+	error = error ? -EFAULT : 0;
+	return error;
+}
+EXPORT_SYMBOL(put_old_uname);
+
+#endif
+
+int __put_new_uname(struct new_utsname __user *name)
+{
+	int error;
+
+	if (!name)
+		return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, name, sizeof(struct new_utsname)))
+		return -EFAULT;
+
+	error = __copy_to_user(&name->sysname, &system_utsname.sysname,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->sysname + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->nodename, &system_utsname.nodename,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->nodename + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->release, &system_utsname.release,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->release + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->version, &system_utsname.version,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->version + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->machine, &system_utsname.machine,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->machine + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->domainname, &system_utsname.domainname,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->domainname + __NEW_UTS_LEN);
+
+	return error;
+}
+EXPORT_SYMBOL(__put_new_uname);
+
+int put_new_uname(struct new_utsname __user *name)
+{
+	int error;
+
+	down_read(&uts_sem);
+	error = __put_new_uname(name);
+	up_read(&uts_sem);
+
+	error = error ? -EFAULT : 0;
+	return error;
+}
+EXPORT_SYMBOL(put_new_uname);
+
+int __put_long_uname(struct long_utsname __user *name)
+{
+	int error;
+
+	if (!name)
+		return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, name, sizeof(struct new_utsname)))
+		return -EFAULT;
+
+	error = __copy_to_user(&name->sysname, &system_utsname.sysname,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->sysname + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->nodename, &system_utsname.nodename,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->nodename + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->release, &system_utsname.release,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->release + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->version, &system_utsname.version,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->version + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->machine, &system_utsname.machine,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->machine + __NEW_UTS_LEN);
+	error |= __copy_to_user(&name->domainname, &system_utsname.domainname,
+				__NEW_UTS_LEN);
+	error |= __put_user(0, name->domainname + __NEW_UTS_LEN);
+
+	return error;
+}
+EXPORT_SYMBOL(__put_long_uname);
+
+int put_long_uname(struct long_utsname __user *name)
+{
+	int error;
+
+	down_read(&uts_sem);
+	error = __put_long_uname(name);
+	up_read(&uts_sem);
+
+	error = error ? -EFAULT : 0;
+	return error;
+}
+EXPORT_SYMBOL(put_long_uname);
--- linux-2617-rc5.orig/arch/powerpc/kernel/syscalls.c
+++ linux-2617-rc5/arch/powerpc/kernel/syscalls.c
@@ -255,14 +255,13 @@ static inline int override_machine(char 
 	return 0;
 }
 
-long ppc_newuname(struct new_utsname __user * name)
+long ppc_newuname(struct new_utsname __user *name)
 {
-	int err = 0;
+	int err;
 
-	down_read(&uts_sem);
-	if (copy_to_user(name, &system_utsname, sizeof(*name)))
+	err = put_new_uname(name);
+	if (err)
 		err = -EFAULT;
-	up_read(&uts_sem);
 	if (!err)
 		err = override_machine(name->machine);
 	return err;
@@ -270,12 +269,10 @@ long ppc_newuname(struct new_utsname __u
 
 int sys_uname(struct old_utsname __user *name)
 {
-	int err = 0;
+	int err;
 	
-	down_read(&uts_sem);
-	if (copy_to_user(name, &system_utsname, sizeof(*name)))
+	err = put_old_uname(name);
 		err = -EFAULT;
-	up_read(&uts_sem);
 	if (!err)
 		err = override_machine(name->machine);
 	return err;
@@ -285,28 +282,10 @@ int sys_olduname(struct oldold_utsname _
 {
 	int error;
 
-	if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
-		return -EFAULT;
-  
-	down_read(&uts_sem);
-	error = __copy_to_user(&name->sysname, &system_utsname.sysname,
-			       __OLD_UTS_LEN);
-	error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->nodename, &system_utsname.nodename,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->release, &system_utsname.release,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->release + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->version, &system_utsname.version,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->version + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->machine, &system_utsname.machine,
-				__OLD_UTS_LEN);
+	error = put_oldold_uname(name);
 	error |= override_machine(name->machine);
-	up_read(&uts_sem);
 
-	return error? -EFAULT: 0;
+	return error ? -EFAULT : 0;
 }
 
 long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
--- linux-2617-rc5.orig/include/asm-mips/unistd.h
+++ linux-2617-rc5/include/asm-mips/unistd.h
@@ -1176,6 +1176,9 @@ type name (atype a,btype b,ctype c,dtype
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_OLDOLD_UNAME
+#define __ARCH_WANT_OLD_UNAME
+#define __ARCH_WANT_NEW_UNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_UTIME
--- linux-2617-rc5.orig/include/asm-powerpc/unistd.h
+++ linux-2617-rc5/include/asm-powerpc/unistd.h
@@ -454,6 +454,8 @@ type name(type1 arg1, type2 arg2, type3 
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_OLDOLD_UNAME
+#define __ARCH_WANT_NEW_UNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
--- linux-2617-rc5.orig/arch/mips/kernel/linux32.c
+++ linux-2617-rc5/arch/mips/kernel/linux32.c
@@ -1039,10 +1039,8 @@ asmlinkage long sys32_newuname(struct ne
 {
 	int ret = 0;
 
-	down_read(&uts_sem);
-	if (copy_to_user(name,&system_utsname,sizeof *name))
+	if (put_new_uname(name))
 		ret = -EFAULT;
-	up_read(&uts_sem);
 
 	if (current->personality == PER_LINUX32 && !ret)
 		if (copy_to_user(name->machine, "mips\0\0\0", 8))
--- linux-2617-rc5.orig/lib/Makefile
+++ linux-2617-rc5/lib/Makefile
@@ -5,7 +5,7 @@
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
 	 idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
-	 sha1.o
+	 sha1.o utsname.o
 
 lib-$(CONFIG_SMP) += cpumask.o
 
--- linux-2617-rc5.orig/include/asm-m32r/unistd.h
+++ linux-2617-rc5/include/asm-m32r/unistd.h
@@ -410,6 +410,7 @@ __syscall_return(type,__res); \
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define	__ARCH_WANT_OLD_UNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_TIME
 #define __ARCH_WANT_SYS_UTIME
--- linux-2617-rc5.orig/arch/m32r/kernel/sys_m32r.c
+++ linux-2617-rc5/arch/m32r/kernel/sys_m32r.c
@@ -200,15 +200,11 @@ asmlinkage int sys_ipc(uint call, int fi
 	}
 }
 
-asmlinkage int sys_uname(struct old_utsname * name)
+asmlinkage int sys_uname(struct old_utsname *name)
 {
-	int err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err=copy_to_user(name, &system_utsname, sizeof (*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
+	int err = put_old_uname(name);
+
+	return err ? -EFAULT : 0;
 }
 
 asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
--- linux-2617-rc5.orig/arch/xtensa/kernel/syscalls.c
+++ linux-2617-rc5/arch/xtensa/kernel/syscalls.c
@@ -127,11 +127,11 @@ out:
 	return error;
 }
 
-int sys_uname(struct old_utsname * name)
+int sys_uname(struct old_utsname *name)
 {
-	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
-		return 0;
-	return -EFAULT;
+	if (put_old_uname(name))
+		return -EFAULT;
+	return 0;
 }
 
 /*
--- linux-2617-rc5.orig/include/asm-xtensa/unistd.h
+++ linux-2617-rc5/include/asm-xtensa/unistd.h
@@ -434,6 +434,7 @@ static __inline__ _syscall3(int,execve,c
 #define __ARCH_WANT_SYS_UTIME
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_OLD_UNAME
 #endif
 
 #endif	/* _XTENSA_UNISTD_H */
--- linux-2617-rc5.orig/arch/um/kernel/syscall_kern.c
+++ linux-2617-rc5/arch/um/kernel/syscall_kern.c
@@ -107,12 +107,9 @@ long sys_pipe(unsigned long __user * fil
 long sys_uname(struct old_utsname __user * name)
 {
 	long err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err=copy_to_user(name, &system_utsname, sizeof (*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
+
+	err = put_old_uname(name);
+	return err ? -EFAULT : 0;
 }
 
 long sys_olduname(struct oldold_utsname __user * name)
--- linux-2617-rc5.orig/include/asm-um/unistd.h
+++ linux-2617-rc5/include/asm-um/unistd.h
@@ -18,6 +18,8 @@ extern int um_execve(const char *file, c
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_OLD_UNAME
+#define __ARCH_WANT_NEW_UNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
--- linux-2617-rc5.orig/include/asm-sh/unistd.h
+++ linux-2617-rc5/include/asm-sh/unistd.h
@@ -427,6 +427,7 @@ __syscall_return(type,__sc0); \
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_OLD_UNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
--- linux-2617-rc5.orig/include/asm-sh64/unistd.h
+++ linux-2617-rc5/include/asm-sh64/unistd.h
@@ -493,6 +493,7 @@ __syscall_return(type,__sc0); 						    
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_OLD_UNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
--- linux-2617-rc5.orig/arch/sh/kernel/sys_sh.c
+++ linux-2617-rc5/arch/sh/kernel/sys_sh.c
@@ -261,15 +261,12 @@ asmlinkage int sys_ipc(uint call, int fi
 	return -EINVAL;
 }
 
-asmlinkage int sys_uname(struct old_utsname * name)
+asmlinkage int sys_uname(struct old_utsname *name)
 {
 	int err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err=copy_to_user(name, &system_utsname, sizeof (*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
+
+	err = put_old_uname(name);
+	return err ? -EFAULT : 0;
 }
 
 asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char * buf,
--- linux-2617-rc5.orig/arch/sh64/kernel/sys_sh64.c
+++ linux-2617-rc5/arch/sh64/kernel/sys_sh64.c
@@ -273,13 +273,10 @@ asmlinkage int sys_ipc(uint call, int fi
 	return -EINVAL;
 }
 
-asmlinkage int sys_uname(struct old_utsname * name)
+asmlinkage int sys_uname(struct old_utsname *name)
 {
 	int err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err=copy_to_user(name, &system_utsname, sizeof (*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
+
+	err = put_old_uname(name);
+	return err ? -EFAULT : 0;
 }
--- linux-2617-rc5.orig/arch/x86_64/kernel/sys_x86_64.c
+++ linux-2617-rc5/arch/x86_64/kernel/sys_x86_64.c
@@ -144,12 +144,10 @@ full_search:
 	}
 }
 
-asmlinkage long sys_uname(struct new_utsname __user * name)
+asmlinkage long sys_uname(struct new_utsname __user *name)
 {
-	int err;
-	down_read(&uts_sem);
-	err = copy_to_user(name, &system_utsname, sizeof (*name));
-	up_read(&uts_sem);
+	int err = put_new_uname(name);
+
 	if (personality(current->personality) == PER_LINUX32) 
 		err |= copy_to_user(&name->machine, "i686", 5); 		
 	return err ? -EFAULT : 0;
--- linux-2617-rc5.orig/include/asm-x86_64/unistd.h
+++ linux-2617-rc5/include/asm-x86_64/unistd.h
@@ -617,8 +617,12 @@ __SYSCALL(__NR_tee, sys_tee)
 __SYSCALL(__NR_sync_file_range, sys_sync_file_range)
 #define __NR_vmsplice		278
 __SYSCALL(__NR_vmsplice, sys_vmsplice)
+#define __NR_gethostname_long	279
+__SYSCALL(__NR_gethostname_long, sys_gethostname_long)
+#define __NR_sethostname_long	280
+__SYSCALL(__NR_sethostname_long, sys_sethostname_long)
 
-#define __NR_syscall_max __NR_vmsplice
+#define __NR_syscall_max __NR_sethostname_long
 
 #ifndef __NO_STUBS
 
@@ -640,6 +644,8 @@ do { \
 #define __ARCH_WANT_OLD_STAT
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_OLDOLD_UNAME
+#define __ARCH_WANT_NEW_UNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
--- linux-2617-rc5.orig/arch/x86_64/ia32/sys_ia32.c
+++ linux-2617-rc5/arch/x86_64/ia32/sys_ia32.c
@@ -790,38 +790,17 @@ asmlinkage long sys32_mmap2(unsigned lon
 	return error;
 }
 
-asmlinkage long sys32_olduname(struct oldold_utsname __user * name)
+asmlinkage long sys32_olduname(struct oldold_utsname __user *name)
 {
-	int error;
+	int error = put_oldold_uname(name);
+	char *arch = "x86_64";
 
-	if (!name)
-		return -EFAULT;
-	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
-		return -EFAULT;
-  
-  	down_read(&uts_sem);
-	
-	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-	 __put_user(0,name->sysname+__OLD_UTS_LEN);
-	 __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-	 __put_user(0,name->nodename+__OLD_UTS_LEN);
-	 __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-	 __put_user(0,name->release+__OLD_UTS_LEN);
-	 __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-	 __put_user(0,name->version+__OLD_UTS_LEN);
-	 { 
-		 char *arch = "x86_64";
-		 if (personality(current->personality) == PER_LINUX32)
-			 arch = "i686";
-		 
-		 __copy_to_user(&name->machine,arch,strlen(arch)+1);
-	 }
-	
-	 up_read(&uts_sem);
-	 
-	 error = error ? -EFAULT : 0;
-	 
-	 return error;
+	if (personality(current->personality) == PER_LINUX32)
+		arch = "i686";
+	__copy_to_user(&name->machine, arch, strlen(arch)+1);
+
+	error = error ? -EFAULT : 0;
+	return error;
 }
 
 long sys32_uname(struct old_utsname __user * name)
--- linux-2617-rc5.orig/arch/i386/kernel/sys_i386.c
+++ linux-2617-rc5/arch/i386/kernel/sys_i386.c
@@ -204,42 +204,17 @@ asmlinkage int sys_ipc (uint call, int f
 /*
  * Old cruft
  */
-asmlinkage int sys_uname(struct old_utsname __user * name)
+asmlinkage int sys_uname(struct old_utsname __user *name)
 {
-	int err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err=copy_to_user(name, &system_utsname, sizeof (*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
+	int err = put_old_uname(name);
+
+	return err ? -EFAULT : 0;
 }
 
-asmlinkage int sys_olduname(struct oldold_utsname __user * name)
+asmlinkage int sys_olduname(struct oldold_utsname __user *name)
 {
-	int error;
-
-	if (!name)
-		return -EFAULT;
-	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
-		return -EFAULT;
-  
-  	down_read(&uts_sem);
-	
-	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-	error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-	error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-	error |= __put_user(0,name->release+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-	error |= __put_user(0,name->version+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
-	error |= __put_user(0,name->machine+__OLD_UTS_LEN);
-	
-	up_read(&uts_sem);
+	int error = put_oldold_uname(name);
 	
 	error = error ? -EFAULT : 0;
-
 	return error;
 }
--- linux-2617-rc5.orig/drivers/char/random.c
+++ linux-2617-rc5/drivers/char/random.c
@@ -223,7 +223,6 @@
  * Eastlake, Steve Crocker, and Jeff Schiller.
  */
 
-#include <linux/utsname.h>
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -240,6 +239,7 @@
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
 #include <linux/cryptohash.h>
+#include <linux/utsname.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
--- linux-2617-rc5.orig/arch/i386/kernel/syscall_table.S
+++ linux-2617-rc5/arch/i386/kernel/syscall_table.S
@@ -315,3 +315,6 @@ ENTRY(sys_call_table)
 	.long sys_splice
 	.long sys_sync_file_range
 	.long sys_tee			/* 315 */
+	.long sys_ni_syscall		/* vmsplice */
+	.long sys_gethostname_long
+	.long sys_sethostname_long
--- linux-2617-rc5.orig/arch/x86_64/ia32/ia32entry.S
+++ linux-2617-rc5/arch/x86_64/ia32/ia32entry.S
@@ -694,6 +694,8 @@ ia32_sys_call_table:
 	.quad compat_sys_get_robust_list
 	.quad sys_splice
 	.quad sys_sync_file_range
-	.quad sys_tee
+	.quad sys_tee			/* 315 */
 	.quad compat_sys_vmsplice
+	.quad sys_gethostname
+	.quad sys_sethostname
 ia32_syscall_end:		

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox