Subject: Re: implementing closeall via a syscall
To: None <tech-kern@netbsd.org>
From: Matt Thomas <matt@3am-software.com>
List: tech-kern
Date: 01/04/2004 16:01:52
At 02:44 PM 1/4/2004, mouss wrote:
>I have implemented a syscall to close all descriptors from some value to
>the max open, that is:
> closem(k) will close descriptors k, k+1, ..., max_open_fd
>
>[rationale]
>dameons (and other apps) sometimes need to close almost all descriptors.
>The primary method to do this was to call close on fds from k to N, where
>N is either a fixed value or the result of a function (SOPEN_MAX,
>getrlimit, getdtablesize, ...). Unfortunately, this has two problems:
> * a program may lower its limits while having a lot of fds open,
> so the return value of getrlimit, sysconf, ... do not necessarily match
> the number of open files inherited from a parent.
> * there are too many useless syscalls
>
>An alternative is the use of /proc/ and close each open fd. This gets the
>open fds right, but still consumes many syscalls. While this may be
>acceptable, procfs is not necessarily the right place (kernfs maybe?).
>
>AIX has a F_CLOSEM cmd to fcntl to do just that. I originally intended to
>implement this, but fcntl code checks that the fd arg is valid, which is
>not relevant for the closem() function. Also, I got comments (a very long
>time ago) that this would change the semantics of fcntl (which up so far
>acts on a single fd and doesn't touch other fds), which seems a reasonable
>counter-arg. Also, I'm not aware of any unix that followed the aix path,
>so chances are this won't happen, so compatibility is not critical.
I'd prefer to follow prior art so i think the AIX fcntl FCLOSEM is
preferrable to me. It's not that hard to make fcntl to not check the fd
for validity.
An alternative might be add an F_MAXFD to fcntl which would return the
highest opened fd.
The following loop is wrong:
+ for (i=fdp->fd_lastfile; i>=fd; i--) {
+ fdrelease(p, i);
+ }
It should be:
while (fdp->fd_lastfile >= fd)
fdrelease(p, fdp->fd_lastfile);
The changes to kern_descrip.c would look something life:
Index: kern_descrip.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_descrip.c,v
retrieving revision 1.121
diff -c -3 -p -r1.121 kern_descrip.c
*** kern_descrip.c 30 Nov 2003 18:16:45 -0000 1.121
--- kern_descrip.c 5 Jan 2004 00:01:23 -0000
*************** sys_fcntl(struct lwp *l, void *v, regist
*** 339,355 ****
p = l->l_proc;
fd = SCARG(uap, fd);
fdp = p->p_fd;
error = 0;
flg = F_POSIX;
restart:
if ((fp = fd_getfile(fdp, fd)) == NULL)
return (EBADF);
FILE_USE(fp);
- cmd = SCARG(uap, cmd);
if ((cmd & F_FSCTL)) {
error = fcntl_forfs(fd, p, cmd, SCARG(uap, arg));
goto out;
--- 339,366 ----
p = l->l_proc;
fd = SCARG(uap, fd);
+ cmd = SCARG(uap, cmd);
fdp = p->p_fd;
error = 0;
flg = F_POSIX;
+ switch (cmd) {
+ case F_CLOSEM:
+ if (fd < 0)
+ return (EBADF);
+ while (fdp->fd_lastfile >= fd)
+ fdrelease(p, fdp->fd_lastfile);
+ return (0);
+ case F_MAXFD:
+ return (fdp->fd_lastfile);
+ }
+
restart:
if ((fp = fd_getfile(fdp, fd)) == NULL)
return (EBADF);
FILE_USE(fp);
if ((cmd & F_FSCTL)) {
error = fcntl_forfs(fd, p, cmd, SCARG(uap, arg));
goto out;
--
Matt Thomas email: matt@3am-software.com
3am Software Foundry www: http://3am-software.com/bio/matt/
Cupertino, CA disclaimer: I avow all knowledge of this message.