Samba NIS problem and solution

Gerald Carter gcarter at valinux.com
Wed Oct 18 15:49:00 GMT 2000


Brian M Hoy wrote:
> 
> Hi Jerry,
> 
> We have recently upgraded from Samba 2.0.5a to 2.0.7 (both 
> using Solaris 2.6 on an Ultra-1). Everything was fine, 
> except that our NIS server was now idling at between 
> 5-10%, instead of the prior 0.3-0.5%.
> 
> Anyway, to cut a long story short, when Samba checks to see 
> if a user is in a group  (lib/username.c:user_in_group_list) 
> it iterates through every group (think setgrent, 
> getgrent, endgrent) looking for the group in question.  
> When you have lots of users and 320+ groups, and 
> regularly perform this _linear_ search and wrap each iteration 
> up in RPC calls to NIS you are going to take a CPU hit.

Uugghhh...I just checked 2.0.7 and you are correct.  That's
a horrible way to do it!  

> The solution to this problem is conveniently located in 
> the old 2.0.5a code! Simply call getgrnam() once - one RPC 
> call and the NIS server can search efficiently (think 
> hashes), and suddenly the loading on ypserv drops fifteen
> fold.
> 
> There are no hints in the release notes or source code 
> about this change.  I am puzzled as to why the change was 
> made.  Any ideas?  Perhaps getgrnam() does not work on 
> some platforms?
> 
> Perhaps the developers might like to reinstate the old 
> code unless they now of a good reason for keeping it.
> 
> BTW I note that Samba 2.2 alpha 0 has the same 
> user_in_group_list() code as 2.0.7 (ie. not very NIS 
> friendly), with one exception!  It is missing the setgrent() 
> before the getgrent()s and endgrent().  This looks like a 
> bug to me. Comments anyone.

Although it is in 2.2alpha0, it is not in the 
SAMBA_2_2 CVS tree.  From lib/username.c (I 
removed the DEBUG statements)

{
  	check to see if the group is the user's 
		primary group;
	if yes then return true;

	check to see if the group is one of the user's
		secondary groups;
	if yes then return true;

	return false;
}

......................
static BOOL user_in_unix_group_list(char *user,char *gname)
{
	struct group *gptr;
	char **member;  
	struct passwd *pass = Get_Pwnam(user,False);

 	/*
 	 * We need to check the users primary group as this
 	 * group is implicit and often not listed in the 
	 * group database.
 	 */
 
 	if (pass) {
 		gptr = getgrgid(pass->pw_gid);
 		if (gptr && strequal(gptr->gr_name,gname)) {
 			return True;
 		}
 	}
 
 	if ((gptr = (struct group *)getgrnam(gname)) == NULL) {
 		return False;
 	}
 
 	member = gptr->gr_mem;
  	while (member && *member) {
  		if (strequal(*member,user)) {
  			return(True);
  		}
		member++;
	}

	return False;
}	      





----------------------------------------------------------------------
   /\  Gerald (Jerry) Carter                     Professional Services
 \/    http://www.valinux.com/  VA Linux Systems   gcarter at valinux.com
       http://www.samba.org/       SAMBA Team          jerry at samba.org
       http://www.plainjoe.org/                     jerry at plainjoe.org

       "...a hundred billion castaways looking for a home."
                                - Sting "Message in a Bottle" ( 1979 )




More information about the samba-ntdom mailing list