linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
@ 2001-11-03 13:06 Telford002
  2001-11-03 13:36 ` Dave Jones
  2001-11-03 14:20 ` Tim Jansen
  0 siblings, 2 replies; 38+ messages in thread
From: Telford002 @ 2001-11-03 13:06 UTC (permalink / raw)
  To: tim, rusty; +Cc: linux-kernel

In a message dated 11/3/01 6:47:18 AM Eastern Standard Time, tim@tjansen.de 
writes:

> On Saturday 03 November 2001 00:31, you wrote:
>  > Hmm, I'd argue that a GUI tool would be fairly useless without knowing 
> what
>  > the values meant anwyay, to give help, in which case you might as well 
> know
>  > the types.
>  
>  Take, as an example, the compression module parameter of the PWC (Philips 
>  Webcam) driver. Currently you can specify a value between 0 for 
uncompressed 
> 
>  and 3 for high compression. If a GUI shows me that only values between 0 
and 
> 
>  3 are allowed I could guess that I have to enter "3" for high compression 
>  without searching for the documentation. It would be even better if I 
could 
>  select four strings, "none", "low", "medium" and "high". 
>  
>  I do see the advantages of using strings in proc, and maybe there is 
another 
> 
>  solution: keep the type information out of the proc filesystem and save it 
>  in a file similar to Configure.help, together with a description for a 
file. 
> 
>  I just don't know how to ensure that they are in sync. 
>  
It would always be possible to build a front end to the /proc file
system.

Joachim Martillo 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-03 13:06 [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit Telford002
@ 2001-11-03 13:36 ` Dave Jones
  2001-11-03 14:20 ` Tim Jansen
  1 sibling, 0 replies; 38+ messages in thread
From: Dave Jones @ 2001-11-03 13:36 UTC (permalink / raw)
  To: Telford002; +Cc: tim, rusty, linux-kernel

On Sat, 3 Nov 2001 Telford002@aol.com wrote:

> >  solution: keep the type information out of the proc filesystem and save it
> >  in a file similar to Configure.help, together with a description for a
> file.
> It would always be possible to build a front end to the /proc file
> system.

The approach taken by powertweak (http://www..powertweak.org) was to
use an XML description of /proc to define types etc. It's worked out
quite well, and has the added advantage of being buzzword compliant 8)

Dave.

-- 
| Dave Jones.        http://www.codemonkey.org.uk
| SuSE Labs


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-03 13:06 [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit Telford002
  2001-11-03 13:36 ` Dave Jones
@ 2001-11-03 14:20 ` Tim Jansen
  1 sibling, 0 replies; 38+ messages in thread
From: Tim Jansen @ 2001-11-03 14:20 UTC (permalink / raw)
  To: Telford002, rusty; +Cc: linux-kernel

On Saturday 03 November 2001 14:06, Telford002@aol.com wrote:
> >  I just don't know how to ensure that they are in sync.
> It would always be possible to build a front end to the /proc file
> system.

Yes, but we are talking about a file system that is used to configure ALL 
drivers. So these descriptions should be written by the authors and 
distributed with the kernel.  

bye...

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-05 22:48       ` Rusty Russell
  2001-11-06 10:25         ` Daniel Phillips
  2001-11-06 15:46         ` Theodore Tso
@ 2001-11-07 23:35         ` Rusty Russell
  2 siblings, 0 replies; 38+ messages in thread
From: Rusty Russell @ 2001-11-07 23:35 UTC (permalink / raw)
  To: Theodore Tso; +Cc: phillips, linux-kernel

On Tue, 6 Nov 2001 10:46:44 -0500
Theodore Tso <tytso@mit.edu> wrote:

> On Tue, Nov 06, 2001 at 09:48:52AM +1100, Rusty Russell wrote:
> > 
> > What concerns me most is the pain involved in writing a /proc or
> > sysctl interface in the kernel today.  Take kernel/module.c's
> > get_ksyms_list as a typical example: 45 lines of code to perform a
> > very trivial task.  And this code is sitting in your kernel whether
> > proc is enabled or not.  Now, I'm a huge Al Viro fan, but his proposed
> > improvements are in the wrong direction, IMHO.
> 
> I'm all for simplifying the internal kernel interfaces.  What I'm not
> at *all* convinced about is that it's worth it to make serious changes
> to the layout of /proc, /proc/sys, etc.  And the concept of being able
> to very rapidly and easily get at system configuration variables
> without needing to make sure that /proc is mounted is a very, very
> good thing.

As these threads show, this is a big argument, involving:
1) What should the in-kernel interface look like?
2) What should the userspace interface look like?
3) Should there be a sysctl interface overlap?

I'm trying to nail down (1).  Whether there is a new backwards
compatible sysctl() which takes a name instead of a number, and/or
whether the whole thing should be done in userspace, I am not going
to address.

Rusty.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-05 22:48       ` Rusty Russell
  2001-11-06 10:25         ` Daniel Phillips
@ 2001-11-06 15:46         ` Theodore Tso
  2001-11-07 23:35         ` Rusty Russell
  2 siblings, 0 replies; 38+ messages in thread
From: Theodore Tso @ 2001-11-06 15:46 UTC (permalink / raw)
  To: Rusty Russell; +Cc: Daniel Phillips, linux-kernel

On Tue, Nov 06, 2001 at 09:48:52AM +1100, Rusty Russell wrote:
> 
> What concerns me most is the pain involved in writing a /proc or
> sysctl interface in the kernel today.  Take kernel/module.c's
> get_ksyms_list as a typical example: 45 lines of code to perform a
> very trivial task.  And this code is sitting in your kernel whether
> proc is enabled or not.  Now, I'm a huge Al Viro fan, but his proposed
> improvements are in the wrong direction, IMHO.

I'm all for simplifying the internal kernel interfaces.  What I'm not
at *all* convinced about is that it's worth it to make serious changes
to the layout of /proc, /proc/sys, etc.  And the concept of being able
to very rapidly and easily get at system configuration variables
without needing to make sure that /proc is mounted is a very, very
good thing.  

While sysctl isn't the most compact way of doing things, it *is*
simpler than doing things using a raw /proc interfaces.  If you just
want sysctl to modify a single integer variable, it's basically just a
table entry and a call to register that table with sysctl.  If you
want to do more sophisticated things, then yes, it gets more
complicated faster than it probably should.  

But the bottom line is as far as I'm concerned is:

Baby.  Bathwater.  Let's not throw out the wrong thing....

						- Ted

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-05 22:48       ` Rusty Russell
@ 2001-11-06 10:25         ` Daniel Phillips
  2001-11-06 15:46         ` Theodore Tso
  2001-11-07 23:35         ` Rusty Russell
  2 siblings, 0 replies; 38+ messages in thread
From: Daniel Phillips @ 2001-11-06 10:25 UTC (permalink / raw)
  To: Rusty Russell; +Cc: linux-kernel

On November 5, 2001 11:48 pm, Rusty Russell wrote:
> In message <20011105033316Z16051-18972+45@humbolt.nl.linux.org> you write:
> > Yes, sold, if implementing the formatter is part of the plan.
> > 
> > Caveat: by profiling I've found that file ops on proc functions are already
> > eating a significant amount of cpu, going to one-value-per-file is going to 
> > make that worse.  But maybe this doesn't bother you.
> 
> What concerns me most is the pain involved in writing a /proc or
> sysctl interface in the kernel today.  Take kernel/module.c's
> get_ksyms_list as a typical example: 45 lines of code to perform a
> very trivial task.  And this code is sitting in your kernel whether
> proc is enabled or not.  Now, I'm a huge Al Viro fan, but his proposed
> improvements are in the wrong direction, IMHO.
> 
> My first priority is to have the most fool-proof possible inner kernel
> interface.  Second is trying to preserve some of the /proc features
> which actually work well when correctness isn't a huge issue (such as
> "give me everything in one table").  Efficiency of getting these
> things out of the kernel is a distant last (by see my previous comment
> on adapting sysctl(2)).
> 
> I'd like to see /proc (/proc/sys) FINALLY live up to its promise
> (rich, logical, complete) in 2.5.  We can do this by making it the
> simplest option for coders and users.

This is without a doubt the most levelheaded comment I've seen in the thread. 

I'm looking at all those 6+ parameter calls and thinking about cleaning that
up with a struct, which is really what it's trying to be.  I see lots of
proc reads ending with a boringly similar calc_metrics call, this is trying
to move out to the caller.  I'd hope this kind of cleanup, at least, is
noncontroversial.

--
Daniel

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-05 20:46       ` Tim Jansen
@ 2001-11-05 23:04         ` Greg KH
  2001-11-05 22:19           ` Tim Jansen
  0 siblings, 1 reply; 38+ messages in thread
From: Greg KH @ 2001-11-05 23:04 UTC (permalink / raw)
  To: Tim Jansen; +Cc: Jonathan Lundell, linux-kernel

On Mon, Nov 05, 2001 at 09:46:19PM +0100, Tim Jansen wrote:
> On Monday 05 November 2001 17:49, Jonathan Lundell wrote:
> > I think of the tagged list of n-tuples as a kind of ASCII
> > representation of a simple struct. One could of course create a
> > general ASCII representation of a C struct, and no doubt it's been
> > done innumerable times, but I don't think that helps in this
> > application.
> 
> But how can you represent references with those lists? Try to model the 
> content of /proc/bus/usb/devices with them.

The contents of /proc/bus/usb is the usbdevfs file system.  It does not
fit into the current /proc model, or discussion.

It's only mounted at that location, for lack of a better place :)

And no, "usbdevfs" has _nothing_ to do with "devfs", it was a bad name
choice, in hindsight.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-05  3:34     ` Daniel Phillips
@ 2001-11-05 22:48       ` Rusty Russell
  2001-11-06 10:25         ` Daniel Phillips
                           ` (2 more replies)
  0 siblings, 3 replies; 38+ messages in thread
From: Rusty Russell @ 2001-11-05 22:48 UTC (permalink / raw)
  To: Daniel Phillips; +Cc: linux-kernel

In message <20011105033316Z16051-18972+45@humbolt.nl.linux.org> you write:
> Yes, sold, if implementing the formatter is part of the plan.
> 
> Caveat: by profiling I've found that file ops on proc functions are already
> eating a significant amount of cpu, going to one-value-per-file is going to 
> make that worse.  But maybe this doesn't bother you.

What concerns me most is the pain involved in writing a /proc or
sysctl interface in the kernel today.  Take kernel/module.c's
get_ksyms_list as a typical example: 45 lines of code to perform a
very trivial task.  And this code is sitting in your kernel whether
proc is enabled or not.  Now, I'm a huge Al Viro fan, but his proposed
improvements are in the wrong direction, IMHO.

My first priority is to have the most fool-proof possible inner kernel
interface.  Second is trying to preserve some of the /proc features
which actually work well when correctness isn't a huge issue (such as
"give me everything in one table").  Efficiency of getting these
things out of the kernel is a distant last (by see my previous comment
on adapting sysctl(2)).

I'd like to see /proc (/proc/sys) FINALLY live up to its promise
(rich, logical, complete) in 2.5.  We can do this by making it the
simplest option for coders and users.

Rusty.
--
Premature optmztion is rt of all evl. --DK

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-05 23:04         ` Greg KH
@ 2001-11-05 22:19           ` Tim Jansen
  0 siblings, 0 replies; 38+ messages in thread
From: Tim Jansen @ 2001-11-05 22:19 UTC (permalink / raw)
  To: Greg KH; +Cc: Jonathan Lundell, linux-kernel

On Tuesday 06 November 2001 00:04, Greg KH wrote:
> The contents of /proc/bus/usb is the usbdevfs file system.  It does not
> fit into the current /proc model, or discussion.

It's just a example of a complex data structure that cannot easily be 
represented using the tagged-list form (I took it as an example because the 
first version of the devreg patch used tagged lists, too, and the complexity 
of representing this USB structure convinced me that tagged-lists are too 
limited). 
Whatever format is chosen for proc, it should be used for all data.

bye...



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-05 16:49     ` Jonathan Lundell
@ 2001-11-05 20:46       ` Tim Jansen
  2001-11-05 23:04         ` Greg KH
  0 siblings, 1 reply; 38+ messages in thread
From: Tim Jansen @ 2001-11-05 20:46 UTC (permalink / raw)
  To: Jonathan Lundell; +Cc: linux-kernel

On Monday 05 November 2001 17:49, Jonathan Lundell wrote:
> I think of the tagged list of n-tuples as a kind of ASCII
> representation of a simple struct. One could of course create a
> general ASCII representation of a C struct, and no doubt it's been
> done innumerable times, but I don't think that helps in this
> application.

But how can you represent references with those lists? Try to model the 
content of /proc/bus/usb/devices with them.

bye...

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-04  1:40   ` Daniel Phillips
  2001-11-04  2:08     ` Jakob Østergaard
@ 2001-11-05 16:49     ` Jonathan Lundell
  2001-11-05 20:46       ` Tim Jansen
  1 sibling, 1 reply; 38+ messages in thread
From: Jonathan Lundell @ 2001-11-05 16:49 UTC (permalink / raw)
  To: Rusty Russell, Daniel Phillips; +Cc: tim, linux-kernel

At 11:12 AM +1100 11/5/01, Rusty Russell wrote:
>Firstly, do not perpetuate the myth of /proc being "human readable".  (Hint:
>what language do humans speak?)  It supposed to be "admin readable" and
>"machine readable".

That's the key observation, seems to me. In our development, we've 
adopted a standard of tagged values, where a single-value file is 
tagged by its name, and multiple-value files have a tag:value per 
line (where value might be an n-tuple).

The result is easy to parse for userland code that needs the values 
and relatively easy (because ASCII and consistent) for admins to 
read. A pretty-printer provides an interface for mere humans.

I suppose one could add typing information as well, but it seems to 
me that a reader of /proc/stuff is either completely ignorant of the 
content (eg cat), and typing is irrelevant, or it knows what's there 
(eg ps) and typing is redundant, as long as there are unambiguous 
tags.

I think of the tagged list of n-tuples as a kind of ASCII 
representation of a simple struct. One could of course create a 
general ASCII representation of a C struct, and no doubt it's been 
done innumerable times, but I don't think that helps in this 
application.

Of course, one tagged value can be "version"....
-- 
/Jonathan Lundell.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-05  0:12   ` Rusty Russell
@ 2001-11-05  3:34     ` Daniel Phillips
  2001-11-05 22:48       ` Rusty Russell
  0 siblings, 1 reply; 38+ messages in thread
From: Daniel Phillips @ 2001-11-05  3:34 UTC (permalink / raw)
  To: Rusty Russell; +Cc: tim, linux-kernel

On November 5, 2001 01:12 am, Rusty Russell wrote:
> On Sun, 4 Nov 2001 02:40:51 +0100
> Daniel Phillips <phillips@bonn-fries.net> wrote:
> 
> > On November 2, 2001 03:20 am, Rusty Russell wrote:
> > > I agree with the "one file, one value" idea.
> > 
> > So cat /proc/partitions goes from being a nice, easy to read and use human 
> > interface to something other than that.  Lets not go overboard.
> 
> Firstly, do not perpetuate the myth of /proc being "human readable".  (Hint:
> what language do humans speak?)  It supposed to be "admin readable" and
> "machine readable".

You're letting me out as a human, fair enough ;-)

> Secondly, it is possible to implement a table formatter which kicks in
> when someone does a read() on a directory.  This is not a desirable format:
> look at /proc/mounts when you have a mount point with a space in it for a
> good example.

Yes, sold, if implementing the formatter is part of the plan.

Caveat: by profiling I've found that file ops on proc functions are already
eating a significant amount of cpu, going to one-value-per-file is going to 
make that worse.  But maybe this doesn't bother you.

--
Daniel

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02  2:20 ` Rusty Russell
  2001-11-02 13:59   ` Tim Jansen
  2001-11-04  1:40   ` Daniel Phillips
@ 2001-11-05  0:12   ` Rusty Russell
  2001-11-05  3:34     ` Daniel Phillips
  2 siblings, 1 reply; 38+ messages in thread
From: Rusty Russell @ 2001-11-05  0:12 UTC (permalink / raw)
  To: Daniel Phillips; +Cc: tim, linux-kernel

On Sun, 4 Nov 2001 02:40:51 +0100
Daniel Phillips <phillips@bonn-fries.net> wrote:

> On November 2, 2001 03:20 am, Rusty Russell wrote:
> > I agree with the "one file, one value" idea.
> 
> So cat /proc/partitions goes from being a nice, easy to read and use human 
> interface to something other than that.  Lets not go overboard.

Firstly, do not perpetuate the myth of /proc being "human readable".  (Hint:
what language do humans speak?)  It supposed to be "admin readable" and
"machine readable".

Secondly, it is possible to implement a table formatter which kicks in
when someone does a read() on a directory.  This is not a desirable format:
look at /proc/mounts when you have a mount point with a space in it for a
good example.

Thanks!
Rusty.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-04 13:36         ` Daniel Kobras
@ 2001-11-04 14:13           ` Tim Jansen
  0 siblings, 0 replies; 38+ messages in thread
From: Tim Jansen @ 2001-11-04 14:13 UTC (permalink / raw)
  To: Daniel Kobras; +Cc: linux-kernel

On Sunday 04 November 2001 14:36, Daniel Kobras wrote:
> Certainly you can further fields without breaking (well-written) apps.
> That's what the first line in /proc/partitions is for. When adding a new
> column, you also give it a new tag in the header. Ask RedHat how many apps
> broke when they started patching sard into their kernels.

The format won't help you when you have strings with whitespace or if you 
want to export a list for each partition. 

> Adding new fields is even easier with /proc/stat-style key:value pairs.
> Both styles are human- as well as machine readable. Problems only arise
> when someone changes the semantics of a certain field without changing the
> tag. But luckily these kinds of changes never happen in a stable kernel
> series...

I don't think that this format is very user friendly, and it has the same 
limitations as /proc/partitions. 

The problem is not that it is impossible to invent a new format for every 
file. The problem is that you need a different format for each file.

bye...

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-04 12:30       ` Tim Jansen
@ 2001-11-04 13:36         ` Daniel Kobras
  2001-11-04 14:13           ` Tim Jansen
  0 siblings, 1 reply; 38+ messages in thread
From: Daniel Kobras @ 2001-11-04 13:36 UTC (permalink / raw)
  To: linux-kernel

On Sun, Nov 04, 2001 at 01:30:06PM +0100, Tim Jansen wrote:
> The problem is that it is almost impossible to offer human-readable 
> interfaces that will be backward-compatible. As soon as you have a 
> well-formatted output, like /proc/partitions, you can not add a new field 
> without breaking user-space applications. 
> What you could do is to establish rules for files like /proc/partitions ("if 
> there are more than 4 space-separated alphanumeric strings per line in 
> /proc/partitions then ignore the additional fields"), but you won't find such 
> a rule that is useful for every file and still offers a nice human-readable 
> format.

Certainly you can further fields without breaking (well-written) apps. That's
what the first line in /proc/partitions is for. When adding a new column,
you also give it a new tag in the header. Ask RedHat how many apps broke
when they started patching sard into their kernels.

Adding new fields is even easier with /proc/stat-style key:value pairs. Both
styles are human- as well as machine readable. Problems only arise when
someone changes the semantics of a certain field without changing the tag.
But luckily these kinds of changes never happen in a stable kernel series...

Regards,

Daniel.


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-04  2:08     ` Jakob Østergaard
@ 2001-11-04 12:30       ` Tim Jansen
  2001-11-04 13:36         ` Daniel Kobras
  0 siblings, 1 reply; 38+ messages in thread
From: Tim Jansen @ 2001-11-04 12:30 UTC (permalink / raw)
  To: Jakob Østergaard , Daniel Phillips; +Cc: Rusty Russell, linux-kernel

On Sunday 04 November 2001 03:08, Jakob Østergaard wrote:
> Now, if established files in proc could just be stable, so that they would
> not change unless non-backwards-compatible information absolutely must be
> presented, that would be a major step in the right direction.  Further, if
> we could find some acceptable compromise between human- and machine-
> readability, as has happened in the past...

The problem is that it is almost impossible to offer human-readable 
interfaces that will be backward-compatible. As soon as you have a 
well-formatted output, like /proc/partitions, you can not add a new field 
without breaking user-space applications. 
What you could do is to establish rules for files like /proc/partitions ("if 
there are more than 4 space-separated alphanumeric strings per line in 
/proc/partitions then ignore the additional fields"), but you won't find such 
a rule that is useful for every file and still offers a nice human-readable 
format. And it will be quite hard to be sure that everybody really sticks to 
these rules. Alternatively you could use a semi-human-readable format like 
XML, which several people have proposed, but it seemed like almost nobody 
liked it.

IMHO there shouldn't be any 'presentation logic' in the kernel. If you need 
the things in a human-friendly format, write a 3 line shell script:

for I in `ls -d /proc/partitions/*` ; do
	echo `cat $I/major` `cat $I/minor` `cat $I/blocks` `cat $I/name`
done

bye...


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02 12:39     ` Martin Dalecki
  2001-11-02 11:57       ` Alexander Viro
  2001-11-02 13:55       ` Keith Owens
@ 2001-11-04  5:36       ` Albert D. Cahalan
  2 siblings, 0 replies; 38+ messages in thread
From: Albert D. Cahalan @ 2001-11-04  5:36 UTC (permalink / raw)
  To: dalecki; +Cc: Alexander Viro, Rusty Russell, Jeff Garzik, linux-kernel

Martin Dalecki writes:

> Bull shit. Standard policy is currently to keep crude old
> interfaces until no end of time. Here are some examples:
>
> /proc/meminfo
>         total:    used:    free:  shared: buffers:  cached:
> Mem:  196005888 60133376 135872512        0  3280896 31088640
> Swap: 410255360        0 410255360
> MemTotal:       191412 kB
> MemFree:        132688 kB
> MemShared:           0 kB
> Buffers:          3204 kB
>
> The first lines could have gone 2 years ago.

Kill them in the 2.5.0 kernel.

> /proc/ksyms - this is duplicating a system call (and making stuff
> easier for intrusors)

This is still used by procps.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-04  1:40   ` Daniel Phillips
@ 2001-11-04  2:08     ` Jakob Østergaard
  2001-11-04 12:30       ` Tim Jansen
  2001-11-05 16:49     ` Jonathan Lundell
  1 sibling, 1 reply; 38+ messages in thread
From: Jakob Østergaard @ 2001-11-04  2:08 UTC (permalink / raw)
  To: Daniel Phillips; +Cc: Rusty Russell, Tim Jansen, linux-kernel

On Sun, Nov 04, 2001 at 02:40:51AM +0100, Daniel Phillips wrote:
> On November 2, 2001 03:20 am, Rusty Russell wrote:
> > I agree with the "one file, one value" idea.
> 
> So cat /proc/partitions goes from being a nice, easy to read and use human 
> interface to something other than that.  Lets not go overboard.

/proc is usually a very nice interface that's both human- and machine-readable.
Some changes have gone in though (such as /proc/mdstat) that makes the proc
files implement something more like a pretty-printing user interface with
text-mode progress bars and what not.  That's a PITA to parse.

Now, if established files in proc could just be stable, so that they would not
change unless non-backwards-compatible information absolutely must be
presented, that would be a major step in the right direction.  Further, if we
could find some acceptable compromise between human- and machine- readability,
as has happened in the past...

Then, someone might just implement the equivalent of kstat (from Solaris) or
pstat (from HP-UX).   Under a license so that commercial players could actually
link to the library as well (unlike the gproc library).

So call me a dreamer   ;)

(For the record, it's not unlikely that I would be able to dedicate some
 time to that effort in a not too distant future - say, 2.5 ?)

-- 
................................................................
:   jakob@unthought.net   : And I see the elder races,         :
:.........................: putrid forms of man                :
:   Jakob Østergaard      : See him rise and claim the earth,  :
:        OZ9ABN           : his downfall is at hand.           :
:.........................:............{Konkhra}...............:

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02  2:20 ` Rusty Russell
  2001-11-02 13:59   ` Tim Jansen
@ 2001-11-04  1:40   ` Daniel Phillips
  2001-11-04  2:08     ` Jakob Østergaard
  2001-11-05 16:49     ` Jonathan Lundell
  2001-11-05  0:12   ` Rusty Russell
  2 siblings, 2 replies; 38+ messages in thread
From: Daniel Phillips @ 2001-11-04  1:40 UTC (permalink / raw)
  To: Rusty Russell, Tim Jansen; +Cc: linux-kernel

On November 2, 2001 03:20 am, Rusty Russell wrote:
> I agree with the "one file, one value" idea.

So cat /proc/partitions goes from being a nice, easy to read and use human 
interface to something other than that.  Lets not go overboard.

--
Daniel

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
       [not found]     ` <20011103103106.7eb6098b.rusty@rustcorp.com.au>
  2001-11-03 11:47       ` Tim Jansen
@ 2001-11-03 23:44       ` Rusty Russell
  1 sibling, 0 replies; 38+ messages in thread
From: Rusty Russell @ 2001-11-03 23:44 UTC (permalink / raw)
  To: Tim Jansen; +Cc: linux-kernel

On Sat, 3 Nov 2001 12:47:08 +0100
Tim Jansen <tim@tjansen.de> wrote:
> I do see the advantages of using strings in proc, and maybe there is another 
> solution: keep the type information out of the proc filesystem and save it 
> in a file similar to Configure.help, together with a description for a file. 
> I just don't know how to ensure that they are in sync. 

The same argument applies for module parameters when they become boot parameters
(handwave reference to my previous patch).  IMHO we should use a source-strainer
like the current Documentation/DocBook/ stuff does to extract these and consolidate
them.

Cheers,
Rusty.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
       [not found]     ` <20011103103106.7eb6098b.rusty@rustcorp.com.au>
@ 2001-11-03 11:47       ` Tim Jansen
  2001-11-03 23:44       ` Rusty Russell
  1 sibling, 0 replies; 38+ messages in thread
From: Tim Jansen @ 2001-11-03 11:47 UTC (permalink / raw)
  To: Rusty Russell; +Cc: linux-kernel

On Saturday 03 November 2001 00:31, you wrote:
> Hmm, I'd argue that a GUI tool would be fairly useless without knowing what
> the values meant anwyay, to give help, in which case you might as well know
> the types.

Take, as an example, the compression module parameter of the PWC (Philips 
Webcam) driver. Currently you can specify a value between 0 for uncompressed 
and 3 for high compression. If a GUI shows me that only values between 0 and 
3 are allowed I could guess that I have to enter "3" for high compression 
without searching for the documentation. It would be even better if I could 
select four strings, "none", "low", "medium" and "high". 

I do see the advantages of using strings in proc, and maybe there is another 
solution: keep the type information out of the proc filesystem and save it 
in a file similar to Configure.help, together with a description for a file. 
I just don't know how to ensure that they are in sync. 

bye...

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02 13:55       ` Keith Owens
@ 2001-11-02 15:08         ` Martin Dalecki
  0 siblings, 0 replies; 38+ messages in thread
From: Martin Dalecki @ 2001-11-02 15:08 UTC (permalink / raw)
  To: Keith Owens; +Cc: linux-kernel

Keith Owens wrote:
> 
> On Fri, 02 Nov 2001 13:39:29 +0100,
> Martin Dalecki <dalecki@evision-ventures.com> wrote:
> >Bull shit. Standard policy is currently to keep crude old
> >interfaces until no end of time. Here are some examples:
> >...
> >/proc/ksyms - this is duplicating a system call (and making stuff easier
> >for intrusors)
> 
> Anybody can issue syscall query_module.  Removing /proc/ksyms just
> forces users to run an executable or Perl syscall().  You have not
> improved security and you have made it harder to report and diagnose
> problems.

Talking about reality:

Having perl on the box, or having to upload some special purpose
application on the box are both measures not that easy if you are
going to do a real breakin. (Read: write some buffer overflow stub)
But just echo sum stuff or therelike is
*much* easier. And then there is the capability stuff you could use
to prevent everybody from accessing the syscall interface.

You don't have much expierence with real break-ins. Don't you?

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02  2:20 ` Rusty Russell
@ 2001-11-02 13:59   ` Tim Jansen
       [not found]     ` <20011103103106.7eb6098b.rusty@rustcorp.com.au>
  2001-11-04  1:40   ` Daniel Phillips
  2001-11-05  0:12   ` Rusty Russell
  2 siblings, 1 reply; 38+ messages in thread
From: Tim Jansen @ 2001-11-02 13:59 UTC (permalink / raw)
  To: Rusty Russell; +Cc: linux-kernel

On Friday 02 November 2001 03:20, Rusty Russell wrote:
> 	I'm not sure about such explicit typing: see my patch (the existing types
> are only for convenience: you can trivially supply your own).  I agree with
> the "one file, one value" idea.  I also went for dynamic directories for
> those who don't want to continually register/deregister.

Explicit typing has a few advantages for the user. User-space apps could use 
a ioctl to get the type (and for enums the possible values, for integers 
maybe a value range). Then you can write some program that shows the user the 
possible values of each file, so you don't have to keep them in mind. And you 
can easily write a GUI administration tool that allows you to modify kernel 
and driver parameters. 
It would also make it possible to convert the content of the filesystem into 
another format, for example you could automatically generate a XML Schema 
definition. IMHO persistence is a desirable feature for the editable files.
 
bye...

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02 12:39     ` Martin Dalecki
  2001-11-02 11:57       ` Alexander Viro
@ 2001-11-02 13:55       ` Keith Owens
  2001-11-02 15:08         ` Martin Dalecki
  2001-11-04  5:36       ` Albert D. Cahalan
  2 siblings, 1 reply; 38+ messages in thread
From: Keith Owens @ 2001-11-02 13:55 UTC (permalink / raw)
  To: dalecki; +Cc: linux-kernel

On Fri, 02 Nov 2001 13:39:29 +0100, 
Martin Dalecki <dalecki@evision-ventures.com> wrote:
>Bull shit. Standard policy is currently to keep crude old
>interfaces until no end of time. Here are some examples:
>...
>/proc/ksyms - this is duplicating a system call (and making stuff easier
>for intrusors)

Anybody can issue syscall query_module.  Removing /proc/ksyms just
forces users to run an executable or Perl syscall().  You have not
improved security and you have made it harder to report and diagnose
problems.


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02  9:11   ` Alexander Viro
  2001-11-02 12:39     ` Martin Dalecki
@ 2001-11-02 12:46     ` Miquel van Smoorenburg
  1 sibling, 0 replies; 38+ messages in thread
From: Miquel van Smoorenburg @ 2001-11-02 12:46 UTC (permalink / raw)
  To: linux-kernel

In article <Pine.GSO.4.21.0111020359540.12621-100000@weyl.math.psu.edu>,
Alexander Viro  <viro@math.psu.edu> wrote:
>On Fri, 2 Nov 2001, Rusty Russell wrote:
>
>> On Thu, 01 Nov 2001 05:42:36 -0500
>> Jeff Garzik <jgarzik@mandrakesoft.com> wrote:
>> 
>> > Is this designed to replace sysctl?
>> 
>> Well, I'd suggest replacing *all* the non-process stuff in /proc.  Yes.
>
>Aha.  Like, say it, /proc/kcore.  Or /proc/mounts, yodda, yodda.

Well in 2.5 union mounts are going to go in right? Then you could
have a compatibility "proc-compat" filesystem that reads data from
/kernel and supplies it in backwards compatible formats such as
/proc/mounts, that you union-mount over /proc

And in 2.7, rm -rf linux/fs/proc-compat

Mike.
-- 
"Only two things are infinite, the universe and human stupidity,
 and I'm not sure about the former" -- Albert Einstein.


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02  9:11   ` Alexander Viro
@ 2001-11-02 12:39     ` Martin Dalecki
  2001-11-02 11:57       ` Alexander Viro
                         ` (2 more replies)
  2001-11-02 12:46     ` Miquel van Smoorenburg
  1 sibling, 3 replies; 38+ messages in thread
From: Martin Dalecki @ 2001-11-02 12:39 UTC (permalink / raw)
  To: Alexander Viro; +Cc: Rusty Russell, Jeff Garzik, linux-kernel

Alexander Viro wrote:
> 
> On Fri, 2 Nov 2001, Rusty Russell wrote:
> 
> > On Thu, 01 Nov 2001 05:42:36 -0500
> > Jeff Garzik <jgarzik@mandrakesoft.com> wrote:
> >
> > > Is this designed to replace sysctl?
> >
> > Well, I'd suggest replacing *all* the non-process stuff in /proc.  Yes.
> 
> Aha.  Like, say it, /proc/kcore.  Or /proc/mounts, yodda, yodda.
> 
>         Noble idea, but there is a little problem: random massive userland
> breakage.  E.g. changing /proc/mounts is going to hit getmntent(3), etc.
> 
>         If you are willing to audit all userland code - you are welcome.
> But keep in mind that standard policy is to keep obsolete API for at least
> one stable branch with warnings and remove it in the next one.  So we are
> talking about 2.8 here.  BTW, I'm less than sure that your variant is free
> of rmmod races, but that's a separate story...

Bull shit. Standard policy is currently to keep crude old
interfaces until no end of time. Here are some examples:

/proc/meminfo
        total:    used:    free:  shared: buffers:  cached:
Mem:  196005888 60133376 135872512        0  3280896 31088640
Swap: 410255360        0 410255360
MemTotal:       191412 kB
MemFree:        132688 kB
MemShared:           0 kB
Buffers:          3204 kB

The first lines could have gone 2 years ago.

/proc/ksyms - this is duplicating a system call (and making stuff easier
for intrusors)

/proc/modules - same as /proc/ksysms - entierly unneccessary and
obsolete,
since 3 years!

And so on and so on...

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02 12:39     ` Martin Dalecki
@ 2001-11-02 11:57       ` Alexander Viro
  2001-11-02 13:55       ` Keith Owens
  2001-11-04  5:36       ` Albert D. Cahalan
  2 siblings, 0 replies; 38+ messages in thread
From: Alexander Viro @ 2001-11-02 11:57 UTC (permalink / raw)
  To: dalecki; +Cc: Rusty Russell, Jeff Garzik, linux-kernel



On Fri, 2 Nov 2001, Martin Dalecki wrote:

> Bull shit. Standard policy is currently to keep crude old
> interfaces until no end of time. Here are some examples:

[snip]

Again, standard procedure for removal of user-visible API:
	* next devel and following stable branch - use of that API is
possible but produces a warning
	* devel branch after that - API removed.

The fact that nobody had even started that with procfs is a separate story.
But no matter what user-visible API changes we start now, the earliest point
when the old stuff can be removed is 2.7.


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02  1:56   ` Erik Andersen
@ 2001-11-02 11:44     ` Padraig Brady
  0 siblings, 0 replies; 38+ messages in thread
From: Padraig Brady @ 2001-11-02 11:44 UTC (permalink / raw)
  To: andersen; +Cc: Rusty Russell, linux-kernel

Erik Andersen wrote:

> On Fri Nov 02, 2001 at 12:42:52PM +1100, Rusty Russell wrote:
> 
>>On Thu, 01 Nov 2001 05:42:36 -0500
>>Jeff Garzik <jgarzik@mandrakesoft.com> wrote:
>>
>>
>>>Is this designed to replace sysctl?
>>>
>>Well, I'd suggest replacing *all* the non-process stuff in /proc.  Yes.
>>
> 
> As I've thought about this in the past, I realized that /proc 
> is serving two purposes.  It is exporting the list of processes,
> and it is also used to export kernel and driver information.
> 
> What we really need is for procfs to be just process stuff, and the
> creation of a separate kernelfs nodev filesystem though which
> the kernel can share all the gory details about the hardware,
> drivers, phase of the moon, etc.   Since these serve two
> fundamentally different tasks, doesn't it make sense to split
> them into two separate filesystems?
> 
>  -Erik

Well the way I look @ it is that /proc should be the
only interface between kernel and user space, and therefore
a better name would be /kernel. I know this is not going
to happen because of all the userspace dependencies and
also probably too Plan9esque, but it's the right direction IMHO.

The process information you refer to is KERNEL data and
therefore "other" kernel data should not be split from the /proc
hierarchy. However as said above a better name would be
/kernel and it should be organised better.

Padraig.


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02  1:42 ` Rusty Russell
  2001-11-02  1:56   ` Erik Andersen
@ 2001-11-02  9:11   ` Alexander Viro
  2001-11-02 12:39     ` Martin Dalecki
  2001-11-02 12:46     ` Miquel van Smoorenburg
  1 sibling, 2 replies; 38+ messages in thread
From: Alexander Viro @ 2001-11-02  9:11 UTC (permalink / raw)
  To: Rusty Russell; +Cc: Jeff Garzik, linux-kernel



On Fri, 2 Nov 2001, Rusty Russell wrote:

> On Thu, 01 Nov 2001 05:42:36 -0500
> Jeff Garzik <jgarzik@mandrakesoft.com> wrote:
> 
> > Is this designed to replace sysctl?
> 
> Well, I'd suggest replacing *all* the non-process stuff in /proc.  Yes.

Aha.  Like, say it, /proc/kcore.  Or /proc/mounts, yodda, yodda.

	Noble idea, but there is a little problem: random massive userland
breakage.  E.g. changing /proc/mounts is going to hit getmntent(3), etc.

	If you are willing to audit all userland code - you are welcome.
But keep in mind that standard policy is to keep obsolete API for at least
one stable branch with warnings and remove it in the next one.  So we are
talking about 2.8 here.  BTW, I'm less than sure that your variant is free
of rmmod races, but that's a separate story...


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-01 10:32 Rusty Russell
                   ` (2 preceding siblings ...)
  2001-11-02  1:42 ` Rusty Russell
@ 2001-11-02  2:20 ` Rusty Russell
  2001-11-02 13:59   ` Tim Jansen
                     ` (2 more replies)
  3 siblings, 3 replies; 38+ messages in thread
From: Rusty Russell @ 2001-11-02  2:20 UTC (permalink / raw)
  To: Tim Jansen; +Cc: linux-kernel

On Thu, 1 Nov 2001 13:06:00 +0100
Tim Jansen <tim@tjansen.de> wrote:

> On Thursday 01 November 2001 11:32, Rusty Russell wrote:
> > I believe that rewriting /proc (and /proc/sys should simply die) is a
> > better solution than extending the interface, or avoiding it
> > altogether by using a new filesystem.
> 
> I am currently working on something like this, too. It's using Patrick 
> Mochel's driverfs patch 
> (http://www.kernel.org/pub/linux/kernel/people/mochel/device/driverfs.diff-1030) 
> as a base and adds the functionality of the extensions that I did to proc fs 
> for my device registry patch 
> (http://www.tjansen.de/devreg/proc_ov-2.4.7.diff).

Hi Tim!

	Firstly: obviously, I think that work on /proc is a worthy and excellent
thing to be doing: everyone has been complaining about it since its introduction
(for good reason).

	I'm not sure about such explicit typing: see my patch (the existing types are
only for convenience: you can trivially supply your own).  I agree with the
"one file, one value" idea.  I also went for dynamic directories for those who
don't want to continually register/deregister.

I suggest you read my patch 8)
Rusty.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-02  1:42 ` Rusty Russell
@ 2001-11-02  1:56   ` Erik Andersen
  2001-11-02 11:44     ` Padraig Brady
  2001-11-02  9:11   ` Alexander Viro
  1 sibling, 1 reply; 38+ messages in thread
From: Erik Andersen @ 2001-11-02  1:56 UTC (permalink / raw)
  To: Rusty Russell; +Cc: linux-kernel

On Fri Nov 02, 2001 at 12:42:52PM +1100, Rusty Russell wrote:
> On Thu, 01 Nov 2001 05:42:36 -0500
> Jeff Garzik <jgarzik@mandrakesoft.com> wrote:
> 
> > Is this designed to replace sysctl?
> 
> Well, I'd suggest replacing *all* the non-process stuff in /proc.  Yes.

As I've thought about this in the past, I realized that /proc 
is serving two purposes.  It is exporting the list of processes,
and it is also used to export kernel and driver information.

What we really need is for procfs to be just process stuff, and the
creation of a separate kernelfs nodev filesystem though which
the kernel can share all the gory details about the hardware,
drivers, phase of the moon, etc.   Since these serve two
fundamentally different tasks, doesn't it make sense to split
them into two separate filesystems?

 -Erik

--
Erik B. Andersen             http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-01 10:32 Rusty Russell
  2001-11-01 10:42 ` Jeff Garzik
  2001-11-01 12:06 ` Tim Jansen
@ 2001-11-02  1:42 ` Rusty Russell
  2001-11-02  1:56   ` Erik Andersen
  2001-11-02  9:11   ` Alexander Viro
  2001-11-02  2:20 ` Rusty Russell
  3 siblings, 2 replies; 38+ messages in thread
From: Rusty Russell @ 2001-11-02  1:42 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linux-kernel

On Thu, 01 Nov 2001 05:42:36 -0500
Jeff Garzik <jgarzik@mandrakesoft.com> wrote:

> Is this designed to replace sysctl?

Well, I'd suggest replacing *all* the non-process stuff in /proc.  Yes.
 
> In general we want to support using sysctl and similar features WITHOUT
> procfs support at all (of any type).  Nice for embedded systems
> especially.

1) My example was implemented as a filesystem.  You could just as easily have
   a CONFIG_PROC_SYSCALL which implemented access as a syscall, ie. sysctl2().

2) It's not worth the hassle to save 7k of code (well, the final implementation
   will be larger than this, but OTOH, your replacement will be non-zero size).

> AFAICS your proposal, while nice and clean :), doesn't offer all the
> features that sysctl presently does.

You're right!  My code:

1) Doesn't have the feature of requiring #ifdef CONFIG_SYSCTL in every file
   that uses it properly (ie. checks error returns).
2) Doesn't have the feature that compiling without CONFIG_PROC/CONFIG_SYSCTL 
   wastes kernel memory unless surrounded by above #ifdefs.
3) Doesn't have the feature that it takes over 90 lines to implement a working
   read & write.
4) Doesn't have the feature that it's hard to create dynamic directories.
5) Doesn't have the feature that it's inherently racy against module unload.

What was I thinking????
Rusty.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-01 12:06 ` Tim Jansen
@ 2001-11-01 18:34   ` James Simmons
  0 siblings, 0 replies; 38+ messages in thread
From: James Simmons @ 2001-11-01 18:34 UTC (permalink / raw)
  To: Tim Jansen; +Cc: Rusty Russell, linux-kernel


> I am currently working on something like this, too. It's using Patrick 
> Mochel's driverfs patch 
> (http://www.kernel.org/pub/linux/kernel/people/mochel/device/driverfs.diff-1030) 
> as a base and adds the functionality of the extensions that I did to proc fs 
> for my device registry patch 
> (http://www.tjansen.de/devreg/proc_ov-2.4.7.diff). 

Hm. Sounds like everyone wants the same thing. Some kind of device filesystem. 
Perhaps a projects somewhere should be started.


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-01 10:42 ` Jeff Garzik
  2001-11-01 16:49   ` Martin Dalecki
@ 2001-11-01 17:06   ` Gábor Lénárt
  1 sibling, 0 replies; 38+ messages in thread
From: Gábor Lénárt @ 2001-11-01 17:06 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linux-kernel

On Thu, Nov 01, 2001 at 05:42:36AM -0500, Jeff Garzik wrote:
> >         proc(KBUILD_OBJECT, "foo", my_foo, int, 0644);
> > 
> > And with my previous parameter patch:
> >         PARAM(foo, int, 0444);
> 
> Is this designed to replace sysctl?
> 
> In general we want to support using sysctl and similar features WITHOUT
> procfs support at all (of any type).  Nice for embedded systems
> especially.

Agreed. It would be nice to have always 1:1 relation between sysctl and
procfs interface, so you can do EVERYTHING with both of sysctl and via
/proc ... Maybe the code should be partly common as much as possible as well.

- Gabor

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-01 10:42 ` Jeff Garzik
@ 2001-11-01 16:49   ` Martin Dalecki
  2001-11-01 17:06   ` Gábor Lénárt
  1 sibling, 0 replies; 38+ messages in thread
From: Martin Dalecki @ 2001-11-01 16:49 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Rusty Russell, linux-kernel

Jeff Garzik wrote:
> 
> > No kernel-formatted tables: use a directory.  (eg. kernel symbols
> > become a directory of symbol names, each containing the symbol value).
> >
> > For cases when you don't want to take the overhead of creating a new
> > proc entry (eg. tcp socket creation), you can create directories on
> > demand when a user reads them using:
> >
> >         proc_dir("net", "subdir", dirfunc, NULL);
> >         unproc_dir("net", "subdir");
> >
> > Note that with kbuild 2.5, you can do something like:
> >
> >         proc(KBUILD_OBJECT, "foo", my_foo, int, 0644);
> >
> > And with my previous parameter patch:
> >         PARAM(foo, int, 0444);
> 
> Is this designed to replace sysctl?
> 
> In general we want to support using sysctl and similar features WITHOUT
> procfs support at all (of any type).  Nice for embedded systems
> especially.
> 
> sysctl may be ugly but it provides for a standard way of manipulating
> kernel variables... sysctl(2) or via procfs or via /etc/sysctl.conf.
> 
> AFAICS your proposal, while nice and clean :), doesn't offer all the
> features that sysctl presently does.
> 
>         Jeff

sysctl IS NOT UGLY. Not the sysctl I know from Solaris or BSD. Both are
far more pleasant solutions then the proliferation of ad-hoc,
undocumented
ever changing, redunand, slow, overcomplex in implementation,
(insert a list of random invectives here) interfaces shown under /proc.
And yes I don't give a shit about "cool features" like:

echo "bull shit" >
/proc/this/is/some/random/peace/of/crappy/interface/design

BTW.> /proc/sys is indeed silly, since it's a "second order" interface
to something you can gat your gip on far easier already. And redundant
system
intrefaces are not a nice design.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-01 10:32 Rusty Russell
  2001-11-01 10:42 ` Jeff Garzik
@ 2001-11-01 12:06 ` Tim Jansen
  2001-11-01 18:34   ` James Simmons
  2001-11-02  1:42 ` Rusty Russell
  2001-11-02  2:20 ` Rusty Russell
  3 siblings, 1 reply; 38+ messages in thread
From: Tim Jansen @ 2001-11-01 12:06 UTC (permalink / raw)
  To: Rusty Russell, linux-kernel

On Thursday 01 November 2001 11:32, Rusty Russell wrote:
> I believe that rewriting /proc (and /proc/sys should simply die) is a
> better solution than extending the interface, or avoiding it
> altogether by using a new filesystem.

I am currently working on something like this, too. It's using Patrick 
Mochel's driverfs patch 
(http://www.kernel.org/pub/linux/kernel/people/mochel/device/driverfs.diff-1030) 
as a base and adds the functionality of the extensions that I did to proc fs 
for my device registry patch 
(http://www.tjansen.de/devreg/proc_ov-2.4.7.diff). 

You can get an idea of the API in the proc_ov patch: every file in the 
filesystem is typed and either a string, integer, unsigned long or an enum. 
The intention is that you have a single value per file, like in /proc/sys, 
and not more. The API does not even allow you to have more complex files (I 
plan to add a blob type though).  
Unlike comparable APIs it also supports 'dynamic directories'. So you can, 
for example, create a directory for each device without registering a 
directory for each device. You only need a single dynamic directory with a 
couple of callbacks that specify the number of directories, their names and 
their contexts. Contexts are void pointers that are given to the callbacks of 
the content files, in this example you would probably use the pointer to the 
device's struct device as context. 

bye...
 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
  2001-11-01 10:32 Rusty Russell
@ 2001-11-01 10:42 ` Jeff Garzik
  2001-11-01 16:49   ` Martin Dalecki
  2001-11-01 17:06   ` Gábor Lénárt
  2001-11-01 12:06 ` Tim Jansen
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 38+ messages in thread
From: Jeff Garzik @ 2001-11-01 10:42 UTC (permalink / raw)
  To: Rusty Russell; +Cc: linux-kernel

> No kernel-formatted tables: use a directory.  (eg. kernel symbols
> become a directory of symbol names, each containing the symbol value).
> 
> For cases when you don't want to take the overhead of creating a new
> proc entry (eg. tcp socket creation), you can create directories on
> demand when a user reads them using:
> 
>         proc_dir("net", "subdir", dirfunc, NULL);
>         unproc_dir("net", "subdir");
> 
> Note that with kbuild 2.5, you can do something like:
> 
>         proc(KBUILD_OBJECT, "foo", my_foo, int, 0644);
> 
> And with my previous parameter patch:
>         PARAM(foo, int, 0444);

Is this designed to replace sysctl?

In general we want to support using sysctl and similar features WITHOUT
procfs support at all (of any type).  Nice for embedded systems
especially.

sysctl may be ugly but it provides for a standard way of manipulating
kernel variables... sysctl(2) or via procfs or via /etc/sysctl.conf.

AFAICS your proposal, while nice and clean :), doesn't offer all the
features that sysctl presently does.

	Jeff



-- 
Jeff Garzik      | Only so many songs can be sung
Building 1024    | with two lips, two lungs, and one tongue.
MandrakeSoft     |         - nomeansno


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit.
@ 2001-11-01 10:32 Rusty Russell
  2001-11-01 10:42 ` Jeff Garzik
                   ` (3 more replies)
  0 siblings, 4 replies; 38+ messages in thread
From: Rusty Russell @ 2001-11-01 10:32 UTC (permalink / raw)
  To: linux-kernel

[Sorry: been wanting to use that phrase here for the longest time]

	This proof-of-concept implementation is pretty poor but the
principle (and interface) is simple:

	int my_foo;

	static int __init initfn(void)
	{
		return proc("net", "foo", my_foo, int, 0644);
	}

	static void __exit exitfn(void)
	{
		unproc("net", "foo");
	}

No kernel-formatted tables: use a directory.  (eg. kernel symbols
become a directory of symbol names, each containing the symbol value).

For cases when you don't want to take the overhead of creating a new
proc entry (eg. tcp socket creation), you can create directories on
demand when a user reads them using:

	proc_dir("net", "subdir", dirfunc, NULL);
	unproc_dir("net", "subdir");

Note that with kbuild 2.5, you can do something like:

	proc(KBUILD_OBJECT, "foo", my_foo, int, 0644);

And with my previous parameter patch:
	PARAM(foo, int, 0444);

declares a boot time parameter "KBUILD_OBJECT.foo=", or a module
parameter "foo=", and places it as readable in
/proc/KBUILD_OBJECT/foo.

I believe that rewriting /proc (and /proc/sys should simply die) is a
better solution than extending the interface, or avoiding it
altogether by using a new filesystem.

Of course, I don't care if it's *NOT* under /proc...
Rusty.
--
Premature optmztion is rt of all evl. --DK

diff -urN -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.4.13-uml/include/linux/simpleproc.h working-2.4.13-uml-proc/include/linux/simpleproc.h
--- linux-2.4.13-uml/include/linux/simpleproc.h	Thu Jan  1 10:00:00 1970
+++ working-2.4.13-uml-proc/include/linux/simpleproc.h	Thu Nov  1 20:17:42 2001
@@ -0,0 +1,206 @@
+/* Dynamic proc filesystem that doesn't suck.  (C) 2001 Rusty Russell. */
+#ifndef _LINUX_SIMPLE_PROC_H
+#define _LINUX_SIMPLE_PROC_H
+#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+
+/* Commit the contents of this (NUL-terminated) buffer if possible.
+   -errno indicates error. */
+typedef int (proc_commitfn_t)(const char *dirname,
+			      const char *filename,
+			      const char *buffer,
+			      unsigned int size,
+			      void *arg);
+/* Fetch the contents into buffer: return size used (or needed), or
+   -errno. */
+typedef int (proc_fetchfn_t)(const char *dirname,
+			     const char *filename,
+			     char *buffer,
+			     unsigned int size,
+			     void *arg);
+
+/* If we're a dynamic directory, this routine gets dir contents:
+   returns size used (or needed), or -errno. */
+struct proc_dircontents;
+typedef int (proc_dirfn_t)(const char *dirname,
+			   const char *filename,
+			   struct proc_dircontents *buffer,
+			   unsigned int maxlen,
+			   void *arg);
+
+/* Register a proc entry of the given type. */
+#define proc(dir, fname, var, type, perms)				 \
+	__proc(dir, fname, S_IFREG|(perms),				 \
+	       __new_proc(&var,						 \
+			  ((perms)&S_IRUGO) ? proc_fetch_##type : NULL,	 \
+			  ((perms)&S_IWUGO) ? proc_commit_##type : NULL, \
+			  NULL))
+
+/* Register a proc entry protected by a spinlock. */
+#define proc_spinlock(dir, fname, var, type, lock, p)			   \
+	__proc(dir, fname, S_IFREG|(p),					   \
+	       __new_proc_lock(&var, lock,				   \
+			       ((p)&S_IRUGO) ? proc_fetch_##type : NULL,   \
+			       ((p)&S_IWUGO) ? proc_commit_##type : NULL))
+
+/* Register a proc entry protected by a semaphore. */
+#define proc_sem(dir, fname, var, type, sem, p)				  \
+	__proc(dir, fname, S_IFREG|(p),					  \
+	       __new_proc_sem(&var, sem,				  \
+			      ((p)&S_IRUGO) ? proc_fetch_##type : NULL,	  \
+			      ((p)&S_IWUGO) ? proc_commit_##type : NULL))
+
+/* These exist, believe me */
+struct semaphore;
+struct proc_data;
+
+#ifdef CONFIG_SIMPLE_PROC_FS
+/* Low level functions */
+int __proc(const char *dirname, const char *fname, int mode,
+	   struct proc_data *pdata);
+struct proc_data *__new_proc(void *arg, proc_fetchfn_t *, proc_commitfn_t *,
+			     proc_dirfn_t *);
+struct proc_data *__new_proc_lock(void *arg, spinlock_t *lock,
+				  proc_fetchfn_t *, proc_commitfn_t *);
+struct proc_data *__new_proc_sem(void *arg, struct semaphore *sem,
+				 proc_fetchfn_t *, proc_commitfn_t *);
+
+/* Register a whole dynamic directory */
+static inline int proc_dir(const char *dir, const char *dirname,
+			   proc_dirfn_t *dirfunc, void *arg)
+{
+	return __proc(dir, dirname, S_IFDIR|0555, 
+		      __new_proc(arg, NULL, NULL, dirfunc));
+}
+
+/* Release a dynamic proc directory */
+void unproc_dir(const char *dir, const char *fname);
+
+/* Release a proc entry */
+void unproc(const char *dir, const char *fname);
+
+#else
+static inline int proc_dir(const char *dir, const char *dirname,
+			   proc_dirfn_t *dirfunc, void *arg)
+{
+	return 0;
+}
+
+static inline void unproc(const char *dir, const char *fname)
+{
+}
+
+static inline void unproc_dir(const char *dir, const char *fname)
+{
+}
+
+static inline int __proc(const char *dirname, const char *fname, int mode,
+			 struct proc_data *pdata)
+{
+	return 0;
+}
+
+struct proc_data *__new_proc(void *arg,
+			     proc_fetchfn_t *fetch,
+			     proc_commitfn_t *commit,
+			     proc_dirfn_t *dir)
+{
+	return (struct proc_data *)-1;
+}
+struct proc_data *__new_proc_lock(void *arg, spinlock_t *lock,
+				  proc_fetchfn_t *fetch,
+				  proc_commitfn_t *commit)
+{
+	return (struct proc_data *)-1;
+}
+struct proc_data *__new_proc_sem(void *arg, struct semaphore *sem,
+				 proc_fetchfn_t *fetch,
+				 proc_commitfn_t *commit)
+{
+	return (struct proc_data *)-1;
+}
+#endif /*CONFIG_PROC_FS*/
+
+/* Helper parsing routines.  You can write your own, too. */
+proc_fetchfn_t proc_fetch_short;
+proc_fetchfn_t proc_fetch_ushort;
+proc_fetchfn_t proc_fetch_int;
+proc_fetchfn_t proc_fetch_uint;
+proc_fetchfn_t proc_fetch_long;
+proc_fetchfn_t proc_fetch_ulong;
+proc_fetchfn_t proc_fetch_bool;
+
+proc_commitfn_t proc_commit_short;
+proc_commitfn_t proc_commit_ushort;
+proc_commitfn_t proc_commit_int;
+proc_commitfn_t proc_commit_uint;
+proc_commitfn_t proc_commit_long;
+proc_commitfn_t proc_commit_ulong;
+proc_commitfn_t proc_commit_bool;
+
+/* Filled in by dir functions */
+struct proc_dircontents
+{
+	/* Mode of file.  0 terminates list. */
+	int mode;
+
+	/* Fetch, commit and dir functions for entry. */
+	proc_fetchfn_t *fetch;
+	proc_commitfn_t *commit;
+	proc_dirfn_t *dir;
+
+	/* Arg */
+	void *arg;
+
+	/* Name is nul-terminated, and padded to alignof this struct */
+	char name[0];
+};
+
+/* Helper to add another dircontents to the list, return updated "used" */
+static inline unsigned int proc_add_dircontents(struct proc_dircontents *pd,
+						unsigned int used,
+						unsigned int maxlen,
+						int mode,
+						proc_fetchfn_t *fetch,
+						proc_commitfn_t *commit,
+						proc_dirfn_t *dir,
+						void *arg,
+						const char *name)
+{
+	unsigned int thislen;
+
+	thislen = sizeof(*pd) + strlen(name) + 1;
+	thislen = (thislen + __alignof__(*pd) - 1) & ~(__alignof__(*pd) - 1);
+	if (used + thislen <= maxlen) {
+		pd = (void *)pd + used;
+		pd->mode = mode;
+		pd->fetch = fetch;
+		pd->commit = commit;
+		pd->dir = dir;
+		pd->arg = arg;
+		strcpy(pd->name, name);
+	}
+	return used + thislen;
+}
+
+static inline unsigned int proc_end_dircontents(struct proc_dircontents *pd,
+						unsigned int used,
+						unsigned int maxlen)
+{
+	return proc_add_dircontents(pd, used, maxlen, 0,
+				    NULL, NULL, NULL, NULL, "");
+}
+
+/* Internal use */
+struct proc_data
+{
+	/* User-defined argument for routines */
+	void *arg;
+
+	proc_dirfn_t *dir;
+	proc_commitfn_t *commit;
+	proc_fetchfn_t *fetch;
+};
+#endif /* _LINUX_SIMPLE_PROC_H */
diff -urN -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.4.13-uml/fs/Config.in working-2.4.13-uml-proc/fs/Config.in
--- linux-2.4.13-uml/fs/Config.in	Thu Oct 25 11:29:49 2001
+++ working-2.4.13-uml-proc/fs/Config.in	Tue Oct 30 12:47:11 2001
@@ -50,7 +50,10 @@
 
 tristate 'OS/2 HPFS file system support' CONFIG_HPFS_FS
 
-bool '/proc file system support' CONFIG_PROC_FS
+bool 'Simple /proc file system support (EXPERIMENTAL)' CONFIG_SIMPLE_PROC_FS
+if [ "$CONFIG_SIMPLE_PROC_FS" != y ]; then
+   bool '/proc file system support' CONFIG_PROC_FS
+fi
 
 dep_bool '/dev file system support (EXPERIMENTAL)' CONFIG_DEVFS_FS $CONFIG_EXPERIMENTAL
 dep_bool '  Automatically mount at boot' CONFIG_DEVFS_MOUNT $CONFIG_DEVFS_FS
diff -urN -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.4.13-uml/fs/Makefile working-2.4.13-uml-proc/fs/Makefile
--- linux-2.4.13-uml/fs/Makefile	Thu Oct 25 11:29:49 2001
+++ working-2.4.13-uml-proc/fs/Makefile	Tue Oct 30 12:47:11 2001
@@ -23,6 +23,7 @@
 endif
 
 subdir-$(CONFIG_PROC_FS)	+= proc
+subdir-$(CONFIG_SIMPLE_PROC_FS)	+= simpleproc
 subdir-y			+= partitions
 
 # Do not add any filesystems before this line
diff -urN -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.4.13-uml/fs/proc/simple_proc.c working-2.4.13-uml-proc/fs/proc/simple_proc.c
--- linux-2.4.13-uml/fs/proc/simple_proc.c	Thu Jan  1 10:00:00 1970
+++ working-2.4.13-uml-proc/fs/proc/simple_proc.c	Tue Oct 30 12:47:11 2001
@@ -0,0 +1,517 @@
+/* Those of you who read this, give quiet thanks that you did not
+   suffer the endless frustration of dealing with the old /proc
+   interface.
+
+   Copyright (C) 2001 Rusty Russell.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <linux/proc.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+/* Simplistic approach: semaphore protects all proc accesses. */
+static DECLARE_MUTEX(simple_proc_sem);
+
+/* FIXME: Use reference counts and "dead" marker to return -ENOENT if
+   unregistered while open -RR */
+struct proc_data
+{
+	void *arg;
+	int (*get)(void *, char *, int);
+	int (*set)(void *, const char *);
+
+	/* FIXME: Belongs in struct file --RR */
+	int readlen, maxreadlen, writelen, maxwritelen;
+	char *readdata, *writedata;
+};
+
+static int fill_buffer(char **buffer,
+			int *maxlen,
+			struct proc_data *pdata)
+{
+	int len;
+
+	for (;;) {
+		len = pdata->get(pdata->arg, *buffer, *maxlen);
+		/* Need more room? */
+		if (len > *maxlen) {
+			/* We need some restriction here, to avoid
+			   DoS.  fs/proc/generic.c wants this, but we
+			   should make one or two pages eventually. */
+			if (len > PAGE_SIZE - 1024)
+				BUG();
+			kfree(*buffer);
+			*buffer = kmalloc(len, GFP_KERNEL);
+			if (!*buffer) return -ENOMEM;
+			*maxlen = len;
+		} else
+			return len;
+	}
+}
+
+/* FIXME: Get the struct file, and we can use ->private_data to store
+   this per file descriptor, rather than per file --RR */
+static int simple_read(char *page, char **start, off_t off, int count, 
+		       int *eof, void *data)
+{
+	struct proc_data *pdata = data;
+	int ret;
+
+	/* Start of read?  Get fresh buffer */
+	if (off == 0) {
+		int readlen, maxreadlen;
+		char *buffer;
+
+		maxreadlen = pdata->maxreadlen;
+		buffer = kmalloc(maxreadlen, GFP_KERNEL);
+		if (!buffer) {
+			*eof = 1;
+			return -ENOMEM;
+		}
+		readlen = fill_buffer(&buffer, &maxreadlen, pdata);
+		if (readlen < 0) {
+			*eof = 1;
+			kfree(buffer);
+			return readlen;
+		}
+
+		/* Substitute buffer */
+		if (down_interruptible(&simple_proc_sem) != 0) {
+			*eof = 1;
+			kfree(buffer);
+			return -EINTR;
+		}
+		kfree(pdata->readdata);
+		pdata->maxreadlen = maxreadlen;
+		pdata->readlen = readlen;
+		pdata->readdata = buffer;
+		up(&simple_proc_sem);
+	}
+
+	/* Serve from buffer */
+	if (down_interruptible(&simple_proc_sem) != 0) {
+		*eof = 1;
+		return -EINTR;
+	}
+
+	if (off <= pdata->readlen) {
+		ret = pdata->readlen - off;
+		memcpy(page + off, pdata->readdata + off, ret);
+	} else {
+		*eof = 1;
+		ret = 0;
+	}
+	up(&simple_proc_sem);
+
+	return ret;
+}
+
+/* FIXME: Don't share the write buffer: use file->private_data */
+static int simple_write(struct file *file,
+			const char *userbuffer,
+			unsigned long count, 
+			void *data)
+{
+	struct proc_data *pdata = data;
+
+	/* FIXME: commit the write(s) on close or seek.  We don't have
+	   that control under the current proc system, so simply
+	   terminate on \n. --RR */
+	if (file->f_pos + count > pdata->maxwritelen) {
+		char *newbuffer;
+		int newmax = file->f_pos + count;
+
+		/* As in read, we need some limit, and this is from
+                   fs/proc/generic.c */
+		if (newmax > PAGE_SIZE - 1024)
+			return -ENOSPC;
+
+		newbuffer = kmalloc(newmax, GFP_KERNEL);
+		if (!newbuffer)
+			return -ENOMEM;
+
+		/* Substitute buffer */
+		if (down_interruptible(&simple_proc_sem) != 0) {
+			kfree(newbuffer);
+			return -EINTR;
+		}
+		memcpy(newbuffer, pdata->writedata, pdata->writelen);
+		kfree(pdata->writedata);
+		pdata->maxwritelen = newmax;
+		pdata->writedata = newbuffer;
+		up(&simple_proc_sem);
+	}
+
+	/* Copy into buffer */
+	if (down_interruptible(&simple_proc_sem) != 0)
+		return -EINTR;
+
+	if (copy_from_user(pdata->writedata+file->f_pos, userbuffer, count)
+	    != 0) {
+		up(&simple_proc_sem);
+		return -EFAULT;
+	}
+
+	file->f_pos += count;
+
+	/* If there is now a '\n' at the end of the buffer, commit */
+	if (file->f_pos > 0 && pdata->writedata[file->f_pos-1] == '\n') {
+		int set;
+		pdata->writedata[file->f_pos-1] = '\0';
+		set = pdata->set(pdata->arg, pdata->writedata);
+
+		if (set < 0) {
+			up(&simple_proc_sem);
+			return set;
+		}
+	}
+	up(&simple_proc_sem);
+	return count;
+}
+
+/* This implementation serves only as a demonstration. --RR */
+static int do_register(const char *dir,
+		       const char *fname,
+		       int perms,
+		       struct proc_data *pdata)
+{
+	struct proc_dir_entry *entry;
+	char fullpath[strlen(dir) + 1 + strlen(fname) + 1];
+
+	sprintf(fullpath, "%s/%s", dir, fname);
+	entry = create_proc_entry(fullpath, perms, NULL);
+	if (!entry) return -EINVAL; /* -ERANDOM */
+
+	/* Populate data */
+	entry->data = pdata;
+
+	/* Set up read and write callbacks */
+	if (pdata->set) entry->read_proc = &simple_read;
+	if (pdata->get) entry->write_proc = &simple_write;
+	return 0;
+}
+
+int __register_proc(const char *dir,
+		    const char *fname,
+		    void *arg,
+		    unsigned int perms,
+		    int (*get)(void *arg, char *, int),
+		    int (*set)(void *arg, const char *))
+{
+	struct proc_data *pdata;
+	int ret;
+
+	pdata = kmalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+	
+	pdata->arg = arg;
+	pdata->get = get;
+	pdata->set = set;
+	pdata->writelen = pdata->readlen = 0;
+	pdata->readdata = pdata->writedata = NULL;
+
+	ret = do_register(dir, fname, perms, pdata);
+	if (ret < 0)
+		kfree(pdata);
+	return ret;
+}
+
+/* Wrapper for user's real proc functions */
+struct pdata_wrapper
+{
+	struct proc_data pdata;
+	int (*get)(void *, char *, int);
+	int (*set)(void *, const char *);
+	void *lock;
+	void *userarg;
+};
+
+static struct pdata_wrapper *
+new_pdata_wrapper(void *arg,
+		  int (*userget)(void *, char *, int),
+		  int (*userset)(void *, const char *),
+		  int (*wrapperget)(void *, char *, int),
+		  int (*wrapperset)(void *, const char *),
+		  void *lock)
+{
+	struct pdata_wrapper *pwrap;
+
+	pwrap = kmalloc(sizeof(*pwrap), GFP_KERNEL);
+	if (pwrap) {
+		pwrap->pdata.arg = pwrap;
+		pwrap->pdata.writelen = pwrap->pdata.readlen = 0;
+		pwrap->pdata.readdata = pwrap->pdata.writedata = NULL;
+		pwrap->pdata.get = wrapperget;
+		pwrap->pdata.set = wrapperset;
+		pwrap->lock = lock;
+		pwrap->userarg = arg;
+		pwrap->get = userget;
+		pwrap->set = userset;
+	}
+	return pwrap;
+}
+
+static int do_register_wrap(const char *dir,
+			    const char *fname,
+			    int perms,
+			    void *arg,
+			    int (*userget)(void *, char *, int),
+			    int (*userset)(void *, const char *),
+			    int (*wrapperget)(void *, char *, int),
+			    int (*wrapperset)(void *, const char *),
+			    void *lock)
+{
+	struct pdata_wrapper *pwrap;
+	int ret;
+
+	pwrap = new_pdata_wrapper(arg, userget, userset, wrapperget,
+				  wrapperset, lock);
+	if (!pwrap)
+		return -ENOMEM;
+	ret = do_register(dir, fname, perms, &pwrap->pdata);
+	if (ret < 0)
+		kfree(pwrap);
+	return ret;
+}
+
+static int spinlock_get(void *arg, char *buffer, int size)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	spin_lock_irq(pwrap->lock);
+	ret = pwrap->get(pwrap->userarg, buffer, size);
+	spin_unlock_irq(pwrap->lock);
+
+	return ret;
+}
+
+static int spinlock_set(void *arg, const char *buffer)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	spin_lock_irq(pwrap->lock);
+	ret = pwrap->set(pwrap->userarg, buffer);
+	spin_unlock_irq(pwrap->lock);
+
+	return ret;
+}
+
+int __register_proc_spinlock(const char *dir,
+			     const char *fname,
+			     void *arg,
+			     unsigned int perms,
+			     spinlock_t *lock,
+			     int (*get)(void *arg, char *, int),
+			     int (*set)(void *arg, const char *))
+{
+	return do_register_wrap(dir, fname, perms, arg, get, set,
+				spinlock_get, spinlock_set, lock);
+}
+
+static int rwlock_get(void *arg, char *buffer, int size)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	read_lock_irq(pwrap->lock);
+	ret = pwrap->get(pwrap->userarg, buffer, size);
+	read_unlock_irq(pwrap->lock);
+
+	return ret;
+}
+
+static int rwlock_set(void *arg, const char *buffer)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	write_lock_irq(pwrap->lock);
+	ret = pwrap->set(pwrap->userarg, buffer);
+	write_unlock_irq(pwrap->lock);
+
+	return ret;
+}
+
+int __register_proc_rwlock(const char *dir,
+			   const char *fname,
+			   void *arg,
+			   unsigned int perms,
+			   rwlock_t *lock,
+			   int (*get)(void *arg, char *, int),
+			   int (*set)(void *arg, const char *))
+{
+	return do_register_wrap(dir, fname, perms, arg, get, set,
+				rwlock_get, rwlock_set, lock);
+}
+
+static int semaphore_get(void *arg, char *buffer, int size)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	if (down_interruptible(pwrap->lock) != 0)
+		return -EINTR;
+	ret = pwrap->get(pwrap->userarg, buffer, size);
+	up(pwrap->lock);
+
+	return ret;
+}
+
+static int semaphore_set(void *arg, const char *buffer)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	if (down_interruptible(pwrap->lock) != 0)
+		return -EINTR;
+	ret = pwrap->set(pwrap->userarg, buffer);
+	up(pwrap->lock);
+
+	return ret;
+}
+
+int __register_proc_semaphore(const char *dir,
+			      const char *fname,
+			      void *arg,
+			      unsigned int perms,
+			      struct semaphore *lock,
+			      int (*get)(void *arg, char *, int),
+			      int (*set)(void *arg, const char *))
+{
+	return do_register_wrap(dir, fname, perms, arg, get, set,
+				semaphore_get, semaphore_set, lock);
+}
+	
+static int rwsemaphore_get(void *arg, char *buffer, int size)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	down_read(pwrap->lock);
+	ret = pwrap->get(pwrap->userarg, buffer, size);
+	up_read(pwrap->lock);
+
+	return ret;
+}
+
+static int rwsemaphore_set(void *arg, const char *buffer)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	down_write(pwrap->lock);
+	ret = pwrap->set(pwrap->userarg, buffer);
+	up_write(pwrap->lock);
+
+	return ret;
+}
+
+int __register_proc_rwsemaphore(const char *dir,
+				const char *fname,
+				void *arg,
+				unsigned int perms,
+				struct rw_semaphore *lock,
+				int (*get)(void *arg, char *, int),
+				int (*set)(void *arg, const char *))
+{
+	return do_register_wrap(dir, fname, perms, arg, get, set,
+				rwsemaphore_get, rwsemaphore_set, lock);
+}
+
+int __proc_read_short(void *shortp, char *outbuf, int len)
+{
+	return snprintf(outbuf, len, "%hi", *(short *)shortp);
+}
+
+int __proc_write_short(void *shortp, const char *inbuf)
+{
+	if (sscanf(inbuf, "%hi", (short *)shortp) != 1) return -EINVAL;
+	return 0;
+}
+
+int __proc_read_ushort(void *ushortp, char *outbuf, int len)
+{
+	return snprintf(outbuf, len, "%hu", *(unsigned short *)ushortp);
+}
+
+int __proc_write_ushort(void *ushortp, const char *inbuf)
+{
+	if (sscanf(inbuf, "%hu", (unsigned short *)ushortp) != 1)
+		return -EINVAL;
+	return 0;
+}
+
+int __proc_read_int(void *intp, char *outbuf, int len)
+{
+	return snprintf(outbuf, len, "%i", *(int *)intp);
+}
+
+int __proc_write_int(void *intp, const char *inbuf)
+{
+	if (sscanf(inbuf, "%i", (int *)intp) != 1) return -EINVAL;
+	return 0;
+}
+
+int __proc_read_uint(void *uintp, char *outbuf, int len)
+{
+	return snprintf(outbuf, len, "%u", *(unsigned int *)uintp);
+}
+
+int __proc_write_uint(void *uintp, const char *inbuf)
+{
+	if (sscanf(inbuf, "%u", (unsigned int *)uintp) != 1) return -EINVAL;
+	return 0;
+}
+
+int __proc_read_long(void *longp, char *outbuf, int len)
+{
+	return snprintf(outbuf, len, "%li", *(long *)longp);
+}
+
+int __proc_write_long(void *longp, const char *inbuf)
+{
+	if (sscanf(inbuf, "%li", (long *)longp) != 1) return -EINVAL;
+	return 0;
+}
+
+int __proc_read_ulong(void *ulongp, char *outbuf, int len)
+{
+	return snprintf(outbuf, len, "%lu", *(long *)ulongp);
+}
+
+int __proc_write_ulong(void *ulongp, const char *inbuf)
+{
+	if (sscanf(inbuf, "%lu", (unsigned long *)ulongp) != 1) return -EINVAL;
+	return 0;
+}
+
+int __proc_read_bool(void *boolp, char *outbuf, int len)
+{
+	if (*(int *)boolp) return snprintf(outbuf, len, "y");
+	else return snprintf(outbuf, len, "n");
+}
+
+int __proc_write_bool(void *boolp, const char *inbuf)
+{
+	if (inbuf[0] == 'y' || inbuf[0] == 'Y')
+		*(int *)boolp = 1;
+	else if (inbuf[0] == 'n' || inbuf[0] == 'N')
+		*(int *)boolp = 0;
+	else return __proc_write_int(boolp, inbuf);
+	return 0;
+}
diff -urN -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.4.13-uml/fs/simpleproc/Makefile working-2.4.13-uml-proc/fs/simpleproc/Makefile
--- linux-2.4.13-uml/fs/simpleproc/Makefile	Thu Jan  1 10:00:00 1970
+++ working-2.4.13-uml-proc/fs/simpleproc/Makefile	Tue Oct 30 12:47:11 2001
@@ -0,0 +1,14 @@
+#
+# Makefile for the Linux proc filesystem routines.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile.
+
+O_TARGET := simpleproc.o
+
+obj-y    := inode.o helper.o
+
+include $(TOPDIR)/Rules.make
diff -urN -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.4.13-uml/fs/simpleproc/helper.c working-2.4.13-uml-proc/fs/simpleproc/helper.c
--- linux-2.4.13-uml/fs/simpleproc/helper.c	Thu Jan  1 10:00:00 1970
+++ working-2.4.13-uml-proc/fs/simpleproc/helper.c	Thu Nov  1 20:58:13 2001
@@ -0,0 +1,277 @@
+/* Those of you who read this, give quiet thanks that you did not
+   suffer the endless frustration of dealing with the old /proc
+   interface.
+
+   Copyright (C) 2001 Rusty Russell.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <linux/simpleproc.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/dcache.h>
+#include <linux/init.h>
+
+/* Wrapper for user's real proc functions */
+struct pdata_wrapper
+{
+	struct proc_data pdata;
+	proc_fetchfn_t *fetch;
+	proc_commitfn_t *commit;
+	void *lock;
+	void *userarg;
+};
+
+static struct proc_data *new_wrapper(proc_fetchfn_t *userfetch,
+				     proc_commitfn_t *usercommit,
+				     void *userarg,
+				     proc_fetchfn_t *wrapfetch,
+				     proc_commitfn_t *wrapcommit,
+				     void *lock)
+{
+	struct pdata_wrapper *pwrap;
+
+	pwrap = kmalloc(sizeof(*pwrap), GFP_KERNEL);
+	if (pwrap) {
+		pwrap->pdata.arg = pwrap;
+		pwrap->pdata.fetch = wrapfetch;
+		pwrap->pdata.commit = wrapcommit;
+		pwrap->pdata.dir = NULL;
+		pwrap->fetch = userfetch;
+		pwrap->commit = usercommit;
+		pwrap->lock = lock;
+		pwrap->userarg = userarg;
+	}
+	return &pwrap->pdata;
+}
+
+static int lock_fetch(const char *dirname, const char *fname,
+		      char *buffer, unsigned int size, void *arg)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	spin_lock_irq(pwrap->lock);
+	ret = pwrap->fetch(dirname, fname, pwrap->userarg, size, buffer);
+	spin_unlock_irq(pwrap->lock);
+
+	return ret;
+}
+
+static int lock_commit(const char *dirname, const char *fname,
+		       const char *buffer, unsigned int size, void *arg)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	spin_lock_irq(pwrap->lock);
+	ret = pwrap->commit(dirname, fname, buffer, size, pwrap->userarg);
+	spin_unlock_irq(pwrap->lock);
+
+	return ret;
+}
+
+struct proc_data *__new_proc_lock(void *arg, spinlock_t *lock,
+				  proc_fetchfn_t *fetch,
+				  proc_commitfn_t *commit)
+{
+	return new_wrapper(fetch, commit, arg, lock_fetch, lock_commit, lock);
+}
+
+static int sem_fetch(const char *dirname, const char *fname,
+		     char *buffer, unsigned int size, void *arg)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	if (down_interruptible(pwrap->lock) != 0)
+		return -EINTR;
+	ret = pwrap->fetch(dirname, fname, pwrap->userarg, size, buffer);
+	up(pwrap->lock);
+
+	return ret;
+}
+
+static int sem_commit(const char *dirname, const char *fname,
+		      const char *buffer, unsigned int size, void *arg)
+{
+	struct pdata_wrapper *pwrap = arg;
+	int ret;
+
+	if (down_interruptible(pwrap->lock) != 0)
+		return -EINTR;
+	ret = pwrap->commit(dirname, fname, buffer, size, pwrap->userarg);
+	up(pwrap->lock);
+
+	return ret;
+}
+
+struct proc_data *__new_proc_sem(void *arg, struct semaphore *sem,
+				 proc_fetchfn_t *fetch,
+				 proc_commitfn_t *commit)
+{
+	return new_wrapper(fetch, commit, arg, sem_fetch, sem_commit, sem);
+}
+
+int proc_fetch_short(const char *dir, const char *fname,
+		     char *outbuf, unsigned int size, void *shortp)
+{
+	return snprintf(outbuf, size, "%hi\n", *(short *)shortp);
+}
+
+int proc_commit_short(const char *dir, const char *fname,
+		      const char *inbuf, unsigned int size, void *shortp)
+{
+	if (sscanf(inbuf, "%hi", (short *)shortp) != 1) return -EINVAL;
+	return 0;
+}
+
+int proc_fetch_ushort(const char *dir, const char *fname,
+		      char *outbuf, unsigned int size, void *ushortp)
+{
+	return snprintf(outbuf, size, "%hu\n", *(unsigned short *)ushortp);
+}
+
+int proc_commit_ushort(const char *dir, const char *fname,
+		       const char *inbuf, unsigned int size, void *ushortp)
+{
+	if (sscanf(inbuf, "%hu", (unsigned short *)ushortp) != 1)
+		return -EINVAL;
+	return 0;
+}
+
+int proc_fetch_int(const char *dir, const char *fname,
+		    char *outbuf, unsigned int size, void *intp)
+{
+	return snprintf(outbuf, size, "%i\n", *(int *)intp);
+}
+
+int proc_commit_int(const char *dir, const char *fname,
+		    const char *inbuf, unsigned int size, void *intp)
+{
+	if (sscanf(inbuf, "%i", (int *)intp) != 1) return -EINVAL;
+	return 0;
+}
+
+int proc_fetch_uint(const char *dir, const char *fname,
+		    char *outbuf, unsigned int size, void *uintp)
+{
+	return snprintf(outbuf, size, "%u\n", *(unsigned int *)uintp);
+}
+
+int proc_commit_uint(const char *dir, const char *fname,
+		     const char *inbuf, unsigned int size, void *uintp)
+{
+	if (sscanf(inbuf, "%u", (unsigned int *)uintp) != 1) return -EINVAL;
+	return 0;
+}
+
+int proc_fetch_long(const char *dir, const char *fname,
+		    char *outbuf, unsigned int size, void *longp)
+{
+	return snprintf(outbuf, size, "%li\n", *(long *)longp);
+}
+
+int proc_commit_long(const char *dir, const char *fname,
+		     const char *inbuf, unsigned int size, void *longp)
+{
+	if (sscanf(inbuf, "%li", (long *)longp) != 1) return -EINVAL;
+	return 0;
+}
+
+int proc_fetch_ulong(const char *dir, const char *fname,
+		     char *outbuf, unsigned int size, void *ulongp)
+{
+	return snprintf(outbuf, size, "%lu\n", *(long *)ulongp);
+}
+
+int proc_commit_ulong(const char *dir, const char *fname,
+		      const char *inbuf, unsigned int size, void *ulongp)
+{
+	if (sscanf(inbuf, "%lu", (unsigned long *)ulongp) != 1) return -EINVAL;
+	return 0;
+}
+
+int proc_fetch_bool(const char *dir, const char *fname,
+		    char *outbuf, unsigned int size, void *boolp)
+{
+	if (*(int *)boolp) return snprintf(outbuf, size, "y\n");
+	else return snprintf(outbuf, size, "n\n");
+}
+
+int proc_commit_bool(const char *dir, const char *fname,
+		     const char *inbuf, unsigned int size, void *boolp)
+{
+	if (inbuf[0] == 'y' || inbuf[0] == 'Y')
+		*(int *)boolp = 1;
+	else if (inbuf[0] == 'n' || inbuf[0] == 'N')
+		*(int *)boolp = 0;
+	else return proc_commit_int(dir, fname, inbuf, size, boolp);
+	return 0;
+}
+
+/* Test code: delete me */
+static int number = 7;
+
+static int testfetch(const char *dirname,
+		     const char *filename,
+		     char *buffer,
+		     unsigned int size,
+		     void *arg)
+{
+	/* As an example, each one holds its own name */
+	return snprintf(buffer, size, "%s/%s\n", dirname, filename);
+}
+
+static int dirfunc(const char *dirname,
+		   const char *filename,
+		   struct proc_dircontents *buffer,
+		   unsigned int maxlen,
+		   void *arg)
+{
+	unsigned int used = 0;
+	char name[100];
+	unsigned int i;
+
+	for (i = 0; i < 10; i++) {
+		sprintf(name, "file-%u", i);
+		used = proc_add_dircontents(buffer, used, maxlen,
+					    S_IFREG|0400, testfetch,
+					    NULL, NULL, NULL, name);
+	}
+	/* And one infinite subdirectory example */
+	used = proc_add_dircontents(buffer, used, maxlen,
+				    S_IFDIR|0555, NULL, NULL, dirfunc, NULL,
+				    "subdir");
+	return proc_end_dircontents(buffer, used, maxlen);
+}
+
+static int __init init_test(void)
+{
+	int ret;
+	ret = proc("testdir", "number", number, int, 0644);
+	if (ret)
+		printk("Proc registration failed: %i\n", ret);
+	proc_dir("testdir", "subdir", dirfunc, NULL);
+	return 0;
+}
+
+static void __exit exit_test(void)
+{
+	unproc("testdir", "number");
+	unproc_dir("testdir", "subdir");
+}
+
+module_init(init_test);
+module_exit(exit_test);
diff -urN -I \$.*\$ --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.4.13-uml/fs/simpleproc/inode.c working-2.4.13-uml-proc/fs/simpleproc/inode.c
--- linux-2.4.13-uml/fs/simpleproc/inode.c	Thu Jan  1 10:00:00 1970
+++ working-2.4.13-uml-proc/fs/simpleproc/inode.c	Thu Nov  1 21:29:14 2001
@@ -0,0 +1,790 @@
+/*
+ * Simple /proc filesystem for Linux.
+ *
+ * Conceptually, there are two types of directories here: static
+ * (entries are created and deleted using
+ * register_proc/unregister_proc), and dynamic (contents are created
+ * on demand using a callback).
+ *
+ *   Copyright (C) 2001 Rusty Russell.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/simpleproc.h>
+#include <asm/semaphore.h>
+
+#include <asm/uaccess.h>
+
+/* Proc mount point */
+struct vfsmount *proc_mnt;
+
+/* Serialize insert/delete and mounts */
+static DECLARE_MUTEX(proc_semaphore);
+
+#define SIMPLE_PROCFS_MAGIC	0x62121174
+
+/* Start with this many bytes allocated for file read */
+#define PROCFS_START_FILE	64
+/* Start with this many bytes allocated for directory read */
+#define PROCFS_START_DIR	PAGE_SIZE
+/* Approximate upper ceiling for memory usage per fs */
+#define PROCFS_MAX_SIZE		PAGE_SIZE
+
+/* Pre-decls for assigning */
+static struct inode_operations proc_punt_inodeops;
+static struct file_operations proc_helper_fileops;
+static struct file_operations proc_helper_dirops;
+static struct file_operations proc_punt_dirops;
+static struct inode_operations proc_helper_inodeops;
+static struct super_operations proc_ops;
+static struct dentry_operations proc_dentry_ops;
+
+struct proc_buffer
+{
+	unsigned int maxlen;
+	unsigned int len;
+	/* One is for the nul terminator */
+	char buffer[1];
+};
+
+struct proc_data *__new_proc(void *arg,
+			     proc_fetchfn_t *fetch,
+			     proc_commitfn_t *commit,
+			     proc_dirfn_t *dir)
+{
+	struct proc_data *pdata;
+
+	pdata = kmalloc(sizeof(*pdata), GFP_KERNEL);
+	if (pdata) {
+		pdata->arg = arg;
+		pdata->fetch = fetch;
+		pdata->commit = commit;
+		pdata->dir = dir;
+	}
+	return pdata;
+}
+
+/* FIXME: I have no idea what all this does: stolen from old /proc --RR */
+static int proc_statfs(struct super_block *sb, struct statfs *buf)
+{
+	buf->f_type = SIMPLE_PROCFS_MAGIC;
+	buf->f_bsize = PAGE_SIZE/sizeof(long);
+	buf->f_bfree = 0;
+	buf->f_bavail = 0;
+	buf->f_ffree = 0;
+	buf->f_namelen = NAME_MAX;
+	return 0;
+}
+
+/* Convenience routine to make an inode */
+static struct inode *
+new_proc_inode(struct super_block *sb, int mode, int is_dynamic)
+{
+	struct inode * inode = new_inode(sb);
+
+	if (!inode)
+		return NULL;
+
+	inode->i_mode = mode;
+	inode->i_uid = 0;
+	inode->i_gid = 0;
+	inode->i_blksize = PAGE_CACHE_SIZE;
+	inode->i_blocks = 0;
+	inode->i_rdev = NODEV;
+	inode->i_mapping->a_ops = NULL;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	switch (mode & S_IFMT) {
+	case S_IFREG:
+		inode->i_fop = &proc_helper_fileops;
+		break;
+	case S_IFDIR:
+		if (is_dynamic) {
+			inode->i_fop = &proc_punt_dirops;
+			inode->i_op = &proc_punt_inodeops;
+		} else {
+			inode->i_fop = &proc_helper_dirops;
+			inode->i_op = &proc_helper_inodeops;
+		}
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	return inode;
+}
+
+/* Make a new proc entry in this directory: must be holding proc_semapore */
+static int make_proc_entry(struct dentry *dir,
+			   const char *fname,
+			   int mode,
+			   struct proc_data *pdata,
+			   int is_dynamic)
+{
+	struct inode *inode;
+	struct dentry *dentry;
+	struct qstr qstr;
+
+	/* Create qstr for this entry */
+	qstr.name = fname;
+	qstr.len = strlen(fname);
+	qstr.hash = full_name_hash(qstr.name, qstr.len);
+
+	/* You can't put a static proc entry in a dynamic dir */
+	if (dir->d_inode->i_op == &proc_punt_inodeops)
+		BUG();
+
+	/* Does it already exist? */
+	dentry = d_lookup(dir, &qstr);
+	if (dentry) {
+		dput(dentry);
+		return -EEXIST;
+	}
+
+	/* Doesn't exist: create inode */
+	inode = new_proc_inode(dir->d_sb, mode, is_dynamic);
+	if (!inode)
+		return -ENOMEM;
+
+	/* Create dentry */
+	dentry = d_alloc(dir, &qstr);
+	if (!dentry) {
+		iput(inode);
+		return -ENOMEM;
+	}
+	dentry->d_op = &proc_dentry_ops;
+	dentry->d_fsdata = pdata;
+	d_add(dentry, inode);
+
+	/* Pin the dentry here, so it doesn't get pruned */
+	dget(dentry);
+	return 0;
+}
+
+/* Create (static) proc directory if neccessary. */
+/* FIXME: Keep refcnt, so we can delete when no more users */
+static struct dentry *get_proc_dir(const char *dirname)
+{
+	struct dentry *dentry;
+	struct qstr qstr;
+	const char *delim;
+
+	/* FIXME: Definitely need a better way --RR */
+	dentry = dget(proc_mnt->mnt_sb->s_root);
+	delim = dirname;
+
+	for (;;) {
+		struct dentry *newdentry;
+
+		/* Ignore multiple slashes */ 
+		while (*delim == '/') delim++;
+		qstr.name = delim;
+		delim = strchr(qstr.name, '/');
+		if (!delim) delim = qstr.name + strlen(qstr.name);
+		qstr.len = delim-(char *)qstr.name;
+		qstr.hash = full_name_hash(qstr.name, qstr.len);
+
+		if (qstr.len == 0)
+			break;
+
+		/* If entry doesn't exist, create it */
+		while (!(newdentry = d_lookup(dentry, &qstr))) {
+			char fname[qstr.len+1];
+			int ret;
+
+			strncpy(fname, qstr.name, qstr.len);
+			fname[qstr.len] = '\0';
+			down(&proc_semaphore);
+			ret = make_proc_entry(dentry, fname, S_IFDIR|0555,
+					       NULL, 0);
+			up(&proc_semaphore);
+
+			if (ret < 0) {
+				dput(dentry);
+				return ERR_PTR(ret);
+			}
+		}
+		dput(dentry);
+		dentry = newdentry;
+	}
+	return dentry;
+}
+
+/* Actually add a proc file or dynamic directory */
+int __proc(const char *dirname, const char *fname, int mode,
+	   struct proc_data *pdata)
+{
+	struct dentry *dir;
+	int ret;
+
+	if (!pdata)
+		return -ENOMEM;
+
+	dir = get_proc_dir(dirname);
+	if (IS_ERR(dir))
+		return PTR_ERR(dir);
+
+	ret = make_proc_entry(dir, fname, mode, pdata, S_ISDIR(mode) ? 1 : 0);
+	dput(dir);
+	return ret;
+}
+
+static int proc_nofetch(const char *dirname, const char *fname,
+			char *outbuf, unsigned int len, void *arg)
+{
+	return -ENOENT;
+}
+
+static int proc_nocommit(const char *dirname, const char *fname,
+			 const char *inbuf, unsigned int len, void *arg)
+{
+	return -ENOENT;
+}
+
+static int proc_nodir(const char *dirname,
+		      const char *filename,
+		      struct proc_dircontents *buffer,
+		      unsigned int size,
+		      void *arg)
+{
+	return -ENOENT;
+}
+
+/* Release a proc entry */
+void unproc(const char *dir, const char *fname)
+{
+	struct dentry *dentry;
+	const char *delim;
+	struct qstr qstr;
+	struct proc_data *pdata;
+
+	/* FIXME: There's a better way, right? --RR */
+	dentry = dget(proc_mnt->mnt_sb->s_root);
+
+	delim = dir;
+	for (;;) {
+		/* Ignore multiple slashes */ 
+		while (*delim == '/') delim++;
+		qstr.name = delim;
+		delim = strchr(qstr.name, '/');
+		if (!delim) delim = qstr.name + strlen(qstr.name);
+		qstr.len = delim-(char *)qstr.name;
+		qstr.hash = full_name_hash(qstr.name, qstr.len);
+
+		if (qstr.len == 0)
+			break;
+
+		dentry = d_lookup(dentry, &qstr);
+		if (!dentry)
+			BUG();
+		dput(dentry->d_parent);
+	}
+
+	qstr.name = fname;
+	qstr.len = strlen(fname);
+	qstr.hash = full_name_hash(qstr.name, qstr.len);
+	dentry = d_lookup(dentry, &qstr);
+	if (!dentry)
+		BUG();
+	dput(dentry->d_parent);
+
+	/* We have the dentry: change the private area so it doesn't
+           enter the caller any more. */
+	pdata = dentry->d_fsdata;
+	pdata->commit = proc_nocommit;
+	pdata->fetch = proc_nofetch;
+	pdata->dir = proc_nodir;
+
+	/* This will probably free the dentry immediately, but if not,
+           too bad. */
+	dput(dentry);
+	dput(dentry);
+}
+
+void unproc_dir(const char *dir, const char *fname)
+{
+	unproc(dir, fname);
+}
+
+/* See if /proc entry exists (entries registered in directory). */
+static struct dentry *proc_lookup(struct inode *dir,
+					 struct dentry *dentry)
+{
+	/* Since we place new staticn entries in the dcache, if we get
+	   here, we know the entry does not exist.  Create a negative
+	   dentry, and return NULL */
+	d_add(dentry, NULL);
+	return NULL;
+}
+
+/* Call callback to get directory contents */
+static struct proc_dircontents *get_dir_contents(const char *dirname,
+						 const char *filename,
+						 struct proc_data *pdata)
+{
+	struct proc_dircontents *ret;
+	unsigned int size = PROCFS_START_DIR;
+
+	ret = kmalloc(size, GFP_KERNEL);
+	while (ret) {
+		int used;
+		used = pdata->dir(dirname, filename, ret, size, pdata->arg);
+		if (used < 0) {
+			kfree(ret);
+			return ERR_PTR(used);
+		}
+		if (used <= size)
+			return ret;
+
+		/* Realloc larger and loop */
+		kfree(ret);
+		size = used;
+		ret = kmalloc(size, GFP_KERNEL);
+	}
+	return ERR_PTR(-ENOMEM);
+}
+
+/* Incrementing is a little tricky: round up to alignment */
+static struct proc_dircontents *next_dcont(struct proc_dircontents *dcontents)
+{
+	unsigned int len;
+
+	len = ((sizeof(*dcontents) + strlen(dcontents->name) + 1
+		+ __alignof__(*dcontents) - 1)
+	       & ~(__alignof__(*dcontents) - 1));
+	return (void *)dcontents + len;
+}
+
+/* Search results from callback for this name, and if found create inode */
+static struct proc_dircontents *
+find_dcontents(struct proc_dircontents *dir_contents,
+	       struct dentry *dentry)
+{
+	while (dir_contents->mode) {
+		if (strcmp(dentry->d_name.name, dir_contents->name) == 0)
+			return dir_contents;
+		dir_contents = next_dcont(dir_contents);
+	}
+	/* Not found... */
+	return NULL;
+}
+
+/* Since there are no hard links in this filesystem, we can simply map
+   inodes to dentries.  This is not possibly in general! */
+static struct dentry *inode_to_dentry(struct inode *inode)
+{
+	if (inode->i_dentry.next->next != &inode->i_dentry)
+		BUG();
+	return list_entry(inode->i_dentry.next, struct dentry, d_alias);
+}
+
+/* See if /proc entry exists (user controls contents of directory). */
+static struct dentry *proc_punt_lookup(struct inode *dir,
+				       struct dentry *dentry)
+{
+	/* We do the whole callback on every lookup. */
+	struct proc_data *pdata;
+	struct proc_dircontents *dir_contents, *dc;
+	struct inode *inode;
+	struct dentry *parent;
+
+	/* Since we know the inode is a directory, there is only one
+           inode in the dentry alias list, so mapping inode -> dentry
+           is easy */
+	parent = inode_to_dentry(dir);
+	dir_contents = get_dir_contents(parent->d_name.name,
+					dentry->d_name.name,
+					parent->d_fsdata);
+	if (!dir_contents || IS_ERR(dir_contents))
+		return (struct dentry *)dir_contents;
+
+	/* Looks through callback-supplied list for this dentry */ 
+	dc = find_dcontents(dir_contents, dentry);
+	if (!dc) {
+		kfree(dir_contents);
+		return NULL;
+	}
+	inode = new_proc_inode(dentry->d_sb, dc->mode, 1);
+	if (!inode) {
+		kfree(dir_contents);
+		return ERR_PTR(-ENOMEM);
+	}
+	pdata = __new_proc(dc->arg, dc->fetch, dc->commit, dc->dir);
+	if (!pdata) {
+		iput(inode);
+		kfree(dir_contents);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dentry->d_op = &proc_dentry_ops;
+	dentry->d_fsdata = pdata;
+	d_add(dentry, inode);
+	kfree(dir_contents);
+	return NULL;
+}
+
+/* On open, we grab contents if we're readable... */
+static int proc_file_snapshot(struct inode *inode, struct file *filp)
+{
+	unsigned int size;
+	struct proc_buffer *buf;
+	struct proc_data *pdata;
+	char *dirname;
+	unsigned long page;
+
+	pdata = filp->f_dentry->d_fsdata;
+	/* Start at this, and work up */
+	size = PROCFS_START_FILE;
+
+	if (!(filp->f_mode & FMODE_READ)) {
+		/* Allocate write buffer: */
+		buf = kmalloc(sizeof(*buf) + size, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+		buf->maxlen = size;
+		buf->len = 0;
+		filp->private_data = buf;
+		return 0;
+	}
+
+	/* For the moment, you can't open for read & write.  Later,
+           when seek resets snapshot/commit, we should allow this. */
+	if (filp->f_mode & FMODE_WRITE)
+		return -EINVAL;
+
+	page = __get_free_page(GFP_USER);
+	if (!page)
+		return -ENOMEM;
+
+	/* FIXME: This is not right: the callbacks don't care what the
+	   process's idea of root is, it only wants path after proc/. */
+	dirname = d_path(filp->f_dentry, filp->f_vfsmnt,
+			 (char *)page, PAGE_SIZE);
+	if (dirname < (char *)page)
+		BUG();
+
+	/* buf[0] holds the size */
+	buf = kmalloc(sizeof(*buf)+size, GFP_KERNEL);
+	while (buf) {
+		int used;
+		used = pdata->fetch(dirname, filp->f_dentry->d_name.name,
+				    buf->buffer, size, pdata->arg);
+		if (used < 0) {
+			kfree(buf);
+			free_page(page);
+			/* FIXME: if used == -ENOENT, destroy dcache entry */
+			return used;
+		}
+		if (used <= size) {
+			free_page(page);
+			filp->private_data = buf;
+			/* Nul terminate and save size */
+			buf->maxlen = size;
+			buf->len = used;
+			buf->buffer[used] = '\0';
+			return 0;
+		}
+
+		/* Realloc larger and loop */
+		kfree(buf);
+		size = used;
+		if (size > PROCFS_MAX_SIZE)
+			break;
+		buf = kmalloc(sizeof(*buf)+size, GFP_KERNEL);
+	}
+	free_page(page);
+	return -ENOMEM;
+}
+
+/* On close, we commit contents if we've been written to... */
+static int proc_file_commit(struct inode *inode, struct file *filp)
+{
+	int ret;
+	struct proc_data *pdata;
+	struct proc_buffer *buf;
+	char *dirname;
+	unsigned long page;
+
+	pdata = filp->f_dentry->d_fsdata;
+	if (!(filp->f_mode & FMODE_WRITE)) {
+		kfree(filp->private_data);
+		return 0;
+	}
+
+	page = __get_free_page(GFP_USER);
+	if (!page) {
+		kfree(filp->private_data);
+		return -ENOMEM;
+	}
+
+	/* FIXME: This is not right: the callbacks don't care what the
+	   process's idea of root is, it only wants path after proc/. */
+	dirname = d_path(filp->f_dentry, filp->f_vfsmnt,
+			 (char *)page, PAGE_SIZE);
+	if (dirname < (char *)page)
+		BUG();
+
+	/* nul-terminate buffer */
+	buf = filp->private_data;
+	buf->buffer[buf->len] = '\0';
+	ret = pdata->commit(dirname, filp->f_dentry->d_name.name,
+			    buf->buffer, buf->len, pdata->arg);
+	
+	kfree(filp->private_data);
+	free_page(page);
+	return ret;
+}
+
+/* Copy from buffer */
+static ssize_t proc_file_read(struct file *filp, char *ubuf, size_t size,
+			      loff_t *off)
+{
+	struct proc_buffer *buf;
+	struct inode *inode;
+
+	/* Use inode semaphore to serialize against writes. */
+	inode = filp->f_dentry->d_inode;
+	if (down_interruptible(&inode->i_sem) != 0)
+		return -EINTR;
+
+	buf = filp->private_data;
+	if (size + *off > buf->len)
+		size = buf->len - *off;
+
+	/* Copy from static buffer */
+	if (copy_to_user(ubuf, buf->buffer, size) != 0) {
+		up(&inode->i_sem);
+		return -EFAULT;
+	}
+	up(&inode->i_sem);
+
+	*off += size;
+	return (ssize_t)size;
+}
+
+/* Copy to buffer */
+static ssize_t proc_file_write(struct file *filp,
+			       const char *ubuf,
+			       size_t size,
+			       loff_t *off)
+{
+	struct inode *inode;
+	struct proc_buffer *buf;
+	struct proc_data *pdata;
+
+	pdata = filp->f_dentry->d_fsdata;
+
+	/* Use inode semaphore to serialize writes & reads. */
+	inode = filp->f_dentry->d_inode;
+	if (down_interruptible(&inode->i_sem) != 0)
+		return -EINTR;
+
+	buf = filp->private_data;
+	if (*off + size > buf->maxlen) {
+		struct proc_buffer *newbuffer;
+		/* Prevent them using too much memory */
+		if (*off + size > PROCFS_MAX_SIZE) {
+			up(&inode->i_sem);
+			return -ENOSPC;
+		}
+		/* Room for count at head */
+		newbuffer = kmalloc(sizeof(*newbuffer) + *off + size,
+				    GFP_USER);
+		if (!newbuffer) {
+			up(&inode->i_sem);
+			return -ENOMEM;
+		}
+		memcpy(newbuffer, buf, sizeof(*buf) + buf->len);
+		kfree(filp->private_data);
+		filp->private_data = buf = newbuffer;
+	}
+
+	/* Do actual copy */
+	if (copy_from_user(buf->buffer + *off, ubuf, size) != 0) {
+		up(&inode->i_sem);
+		return -EFAULT;
+	}
+	up(&inode->i_sem);
+	buf->len += size;
+	*off += size;
+
+	return size;
+}
+
+/* Call the user's callback to get contents of this directory.
+   Generate . and .. automagically. */
+static int proc_dynamic_readdir(struct file *filp,
+				void *dirent,
+				filldir_t filldir)
+{
+	int i;
+	struct proc_dircontents *dcontents, *dp;
+	char *dirname;
+	unsigned long page;
+	struct proc_data *pdata;
+	struct dentry *dentry = filp->f_dentry;
+
+	pdata = filp->f_dentry->d_fsdata;
+
+	i = filp->f_pos;
+	switch (i) {
+	case 0:
+		if (filldir(dirent, ".", 1, 0, dentry->d_inode->i_ino, DT_DIR)
+		    < 0)
+			break;
+		i++;
+		filp->f_pos++;
+		/* fallthrough */
+	case 1:
+		if (filldir(dirent, "..", 2, 0,
+			    dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
+			break;
+		i++;
+		filp->f_pos++;
+	}
+
+	page = __get_free_page(GFP_USER);
+	if (!page) return -ENOMEM;
+
+	/* FIXME: This is not right: the callbacks don't care what the
+	   process's idea of root is, it only wants path after proc/. */
+	dirname = d_path(filp->f_dentry, filp->f_vfsmnt,
+			 (char *)page, PAGE_SIZE);
+	if (dirname < (char *)page)
+		BUG();
+
+	/* Call user callback to get directory */
+	dcontents = get_dir_contents(dirname,
+				     dentry->d_name.name,
+				     pdata);
+	if (IS_ERR(dcontents)) {
+		free_page(page);
+		return PTR_ERR(dcontents);
+	}
+
+	/* Skip any already-read entries... */
+	for (dp = dcontents, i -= 2; dp->mode && i; dp = next_dcont(dp), i++);
+
+	for (; dp->mode; dp = next_dcont(dp)) {
+		/* FIXME: Use non-zero inode numbers */
+		if (filldir(dirent, dp->name, strlen(dp->name),
+			    filp->f_pos,
+			    filp->f_pos,
+			    S_ISDIR(dp->mode) ? DT_DIR : DT_REG) < 0)
+			break;
+		filp->f_pos++;
+	}
+	free_page(page);
+	kfree(dcontents);
+	return 0;
+}
+
+/* Free the private area when dentry is freed. */
+static void proc_release(struct dentry *dentry)
+{
+	kfree(dentry->d_fsdata);
+}
+
+static struct super_block *proc_read_super(struct super_block *s,
+					   void *data, 
+					   int silent)
+{
+	struct inode * root_inode;
+
+	s->s_blocksize = 1024;
+	s->s_blocksize_bits = 10;
+	s->s_magic = SIMPLE_PROCFS_MAGIC;
+	s->s_op = &proc_ops;
+
+	root_inode = new_proc_inode(s, S_IFDIR|0555, 0);
+	if (!root_inode) return NULL;
+
+	/* Block concurrent mounts */
+	down(&proc_semaphore);
+
+	s->s_root = d_alloc_root(root_inode);
+	if (!s->s_root) {
+		iput(root_inode);
+		up(&proc_semaphore);
+		return NULL;
+	}
+	up(&proc_semaphore);
+	return s;
+}
+
+/* Proc files use these wrappers */
+static struct file_operations proc_helper_fileops = {
+	open:		proc_file_snapshot,
+	release:	proc_file_commit,
+	read:		proc_file_read,
+	write:		proc_file_write,
+};
+
+/* Directories which use normal registration mechanism, which sit in
+   the dcache */
+static struct file_operations proc_helper_dirops = {
+	read:		generic_read_dir,
+	readdir:	dcache_readdir,
+};
+
+/* Directories which have their own dynamic content */
+static struct file_operations proc_punt_dirops = {
+	read:		generic_read_dir,
+	readdir:	proc_dynamic_readdir,
+};
+
+/* You can only do lookups through these dirs: dynamic ones do callbacks... */
+static struct inode_operations proc_punt_inodeops = {
+	lookup:		proc_punt_lookup,
+};
+
+/* ... static ones look up registrations */
+static struct inode_operations proc_helper_inodeops = {
+	lookup:		proc_lookup,
+};
+
+static struct super_operations proc_ops = {
+	statfs:		proc_statfs,
+	put_inode:	force_delete,
+};
+
+static struct dentry_operations proc_dentry_ops = {
+	d_release:	proc_release,
+};
+
+static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, FS_SINGLE);
+
+static int __init init_proc_fs(void)
+{
+	register_filesystem(&proc_fs_type);
+	proc_mnt = kern_mount(&proc_fs_type);
+	return 0;
+}
+
+static void __exit exit_proc_fs(void)
+{
+	unregister_filesystem(&proc_fs_type);
+}
+
+module_init(init_proc_fs);
+module_exit(exit_proc_fs);
+

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2001-11-08  1:35 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-11-03 13:06 [PATCH] 2.5 PROPOSAL: Replacement for current /proc of shit Telford002
2001-11-03 13:36 ` Dave Jones
2001-11-03 14:20 ` Tim Jansen
  -- strict thread matches above, loose matches on Subject: below --
2001-11-01 10:32 Rusty Russell
2001-11-01 10:42 ` Jeff Garzik
2001-11-01 16:49   ` Martin Dalecki
2001-11-01 17:06   ` Gábor Lénárt
2001-11-01 12:06 ` Tim Jansen
2001-11-01 18:34   ` James Simmons
2001-11-02  1:42 ` Rusty Russell
2001-11-02  1:56   ` Erik Andersen
2001-11-02 11:44     ` Padraig Brady
2001-11-02  9:11   ` Alexander Viro
2001-11-02 12:39     ` Martin Dalecki
2001-11-02 11:57       ` Alexander Viro
2001-11-02 13:55       ` Keith Owens
2001-11-02 15:08         ` Martin Dalecki
2001-11-04  5:36       ` Albert D. Cahalan
2001-11-02 12:46     ` Miquel van Smoorenburg
2001-11-02  2:20 ` Rusty Russell
2001-11-02 13:59   ` Tim Jansen
     [not found]     ` <20011103103106.7eb6098b.rusty@rustcorp.com.au>
2001-11-03 11:47       ` Tim Jansen
2001-11-03 23:44       ` Rusty Russell
2001-11-04  1:40   ` Daniel Phillips
2001-11-04  2:08     ` Jakob Østergaard
2001-11-04 12:30       ` Tim Jansen
2001-11-04 13:36         ` Daniel Kobras
2001-11-04 14:13           ` Tim Jansen
2001-11-05 16:49     ` Jonathan Lundell
2001-11-05 20:46       ` Tim Jansen
2001-11-05 23:04         ` Greg KH
2001-11-05 22:19           ` Tim Jansen
2001-11-05  0:12   ` Rusty Russell
2001-11-05  3:34     ` Daniel Phillips
2001-11-05 22:48       ` Rusty Russell
2001-11-06 10:25         ` Daniel Phillips
2001-11-06 15:46         ` Theodore Tso
2001-11-07 23:35         ` Rusty Russell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).