RE: [PATCH] mdadm: close parent file descriptors when starting mdmon.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: NeilBrown [mailto:neilb@xxxxxxx]
> Sent: Tuesday, August 30, 2011 1:32 AM
> To: Patelczyk, Maciej
> Cc: linux-raid@xxxxxxxxxxxxxxx
> Subject: Re: [PATCH] mdadm: close parent file descriptors when starting
> mdmon.
> 
> On Mon, 29 Aug 2011 17:49:49 +0200 Maciej Patelczyk
> <maciej.patelczyk@xxxxxxxxx> wrote:
> 
> > When mdadm is invoked by fork-and-exec it inherits all open file
> > descriptors and when mdadm forks to exec mdmon those file descriptors
> > are passed to mdmon. Mdmon closes only first 97 fd and that in some
> > cases is not enough.
> 
> Can you describe and actual can when it is not enough?  Maybe there is
> some
> other problem where mdadm is not closing things as it should.
 
There is one:
CIM Server (Sfcbd - Small Footprint CIM Broker) -> registered provider 
-> intermediate library -> mdadm -> mdmon

We register provider in Sfcbd which brings some functionality to cim server.
It uses our library which calls mdadm (popen). Later mdadm is calling mdmon
(fork&exec).

The problem is that Sfcbd is a server and it has more than 100 files opened.
Open files handles are passed down to mdadm (popen behavior) and here we have
a problem.



> > This commit adds function which looks at the '/proc/<pid>/fd'
> directory
> > and closes all inherited file descriptors except the standard ones
> (0-2).
> 
> I'm not thrilled by this approach.
> For a start, the loop could close the fd that is being used to
> read /proc/<pid>/fd, so subsequent fds won't get seen or closed.
> 

That's a bug. There is a 'dirfd()' function but it depends on 
_BSD_SOURCE || _SVID_SOURCE flags so I don't know if this is acceptable.
There could be additional check to skip dir fd.



> I would much rather do as the comment suggests and use O_CLOEXEC on all
> opens
> so that everything gets closed when we do an exec.

So do I. But we cannot control scenarios in which mdadm is used.
O_CLOEXEC is nice but that gives you nothing in scenario like I presented.
It looks like Sfcbd is not using O_CLOEXEC.
Optional parameter to popen/exec in my opinion would be better.
But this is not the case.


> 
> About the most I  would be willing to do in closing more fds before the
> exec
> is to keep closing until we get too many failures.
> e.g.
>   fd = 3;
>   failed = 0;
>   while (failed < 20) {
>       if (close(fd) < 0)
>           failed ++;
>       else
>           failed = 0;
>       fd++;
>   }
> 

Imagine:
1. Open 100 files (user #1 action)
2. Open 100 files (user #2 action)
3. Close 43 files from #1 (user #1 action)
4. call mdadm (user #3 action)
...

It's not 'most likely' but possible.



maciej



> NeilBrown
> 
> 
> >
> > Signed-off-by: Maciej Patelczyk <maciej.patelczyk@xxxxxxxxx>
> > ---
> >  util.c |   41 +++++++++++++++++++++++++++++++++++++----
> >  1 files changed, 37 insertions(+), 4 deletions(-)
> >
> > diff --git a/util.c b/util.c
> > index ce03239..b844447 100644
> > --- a/util.c
> > +++ b/util.c
> > @@ -30,7 +30,12 @@
> >  #include	<sys/un.h>
> >  #include	<ctype.h>
> >  #include	<dirent.h>
> > +#include	<sys/types.h>
> >  #include	<signal.h>
> > +#include	<stdlib.h>
> > +#include	<string.h>
> > +#include	<errno.h>
> > +#include	<unistd.h>
> >
> >  /*
> >   * following taken from linux/blkpg.h because they aren't
> > @@ -1571,11 +1576,41 @@ int mdmon_running(int devnum)
> >  	return 0;
> >  }
> >
> > +static void close_parent_fds(void)
> > +{
> > +	pid_t pid;
> > +	char buf[128];
> > +	DIR *dirp;
> > +	struct dirent *d_entry;
> > +	int fd;
> > +
> > +	pid = getpid();
> > +	if (snprintf(buf, sizeof(buf), "/proc/%d/fd", (int)pid) < 0)
> > +		return;
> > +
> > +	dirp = opendir((const char *)buf);
> > +	if (!dirp)
> > +		return;
> > +
> > +	while((d_entry = readdir(dirp)) != NULL) {
> > +		if (!strcmp(d_entry->d_name, ".") ||
> > +		    !strcmp(d_entry->d_name, ".."))
> > +			continue;
> > +		errno = 0;
> > +		fd = (int)strtol(d_entry->d_name, NULL, 10);
> > +		if (errno)
> > +			continue;
> > +		if (fd > 2)
> > +			close(fd);
> > +	}
> > +	closedir(dirp);
> > +}
> > +
> >  int start_mdmon(int devnum)
> >  {
> >  	int i;
> >  	int len;
> > -	pid_t pid;
> > +	pid_t pid;
> >  	int status;
> >  	char pathbuf[1024];
> >  	char *paths[4] = {
> > @@ -1603,9 +1638,7 @@ int start_mdmon(int devnum)
> >
> >  	switch(fork()) {
> >  	case 0:
> > -		/* FIXME yuk. CLOSE_EXEC?? */
> > -		for (i=3; i < 100; i++)
> > -			close(i);
> > +		close_parent_fds();
> >  		for (i=0; paths[i]; i++)
> >  			if (paths[i][0])
> >  				execl(paths[i], "mdmon",

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux