Subject: Re: [vserver] Problem with locks
From: Herbert Poetzl <herbert@13thfloor.at>
Date: Fri, 23 Mar 2012 18:56:13 +0100

On Fri, Mar 23, 2012 at 06:17:19PM +0100, PV wrote:
> El 23/03/12 15:30, Herbert Poetzl escribió:

>> I'd wrap the other processes, e.g. the pickup with an
>> strace shell wrapper, so that we get some information what
>> is requested and denied from the kernel side ...

> Really, I do not know how is possible that locks are not
> released after all programs kill (except sshd). With sshd
> problem do not appear.

Well, I had a look at the code involved (on 3.3) and
I can see a pathological case when a guest reaches
the given lock limit, because the code in question
(fcntl_setlk) first _allocates_ a file_lock structure
then inspects the userspace data (which basically is
the flock structure) which is fine in all cases where
a clock is created, but leads to an early reject for
calls where a lock should be unlocked ...

OTOH, this behaviour is completely identical to the
one you will get when the kernel runs out of memory
in the filelock_cache, so one could argue that this
is an upstream problem ...

I'm not sure this is what you are actually seeing,
probably a good way to verify it would be to remove
the lock limit on the guest and see what lock counts
you'll reach during normal operation (and if the
problem goes away :)

HTH,
Herbert

>> [root@mail ~]# ps aux
>> USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
>> root         1  0.0  0.1  10364   608 ?        SNs   2011   8:39 init [2]
>> root     24526  0.0  0.2 110212  1116 pts/12   R+    2011   0:00 ps aux
>> root     26049  0.0  0.2  64076  1104 ?        Ss    2011   0:00 
>> /usr/sbin/sshd
>> root     29638  0.0  0.7  95912  4120 ?        S     2011   0:00 sshd: 
>> root@pts/12
>> root     29662  0.0  0.3 110648  2020 pts/12   Ss    2011   0:00 -bash




>> [root@mail ~]# cat locks2.c
>> #include <stdlib.h>
>> #include <unistd.h>
>> #include <fcntl.h>
>> #include <errno.h>
>> #include <stdio.h>




>> int
>> lock (int fd)
>> {
>>  struct flock fl;
>>  /* Make a non-blocking request to place a write lock
>>     on bytes 100-109 of testfile */
>>  fl.l_type = F_WRLCK;
>>  fl.l_whence = SEEK_SET;
>>  fl.l_start = 100;
>>  fl.l_len = 10;

>>  if (fcntl (fd, F_SETLK, &fl) == -1)
>>    {
>>      if (errno == EACCES || errno == EAGAIN)
>>        {
>>          printf ("Already locked by another process\n");
>>          /* We can't get the lock at the moment */
>>        }
>>      else
>>        {
>>          /* Handle unexpected error */ ;
>>          printf("Error not listed %u\n",errno);
>>          //perror();
>>        }
>>    }else{
>>    printf("locked\n");
>>    }
>> }



>> int
>> unlock (int fd)
>> {
>>  struct flock fl;
>>  /* Perform I/O on bytes 100 to 109 of file */
>>  /* Unlock the locked bytes */
>>  fl.l_type = F_UNLCK;
>>  fl.l_whence = SEEK_SET;
>>  fl.l_start = 100;
>>  fl.l_len = 10;
>>  if (fcntl (fd, F_SETLK, &fl) == -1)
>>    {
>>      printf ("Can not unlock file\n");
>>    }else{
>>        printf("unlocked\n");
>>    }
>> }



>> int
>> main (int argc, char *argv[])
>> {
>>  register unsigned counter = 0;
>>  int fd;

>>  fd = open ("testfile", O_RDWR);
>>  if (fd == -1)
>>    {
>>      printf ("Can not open file\n");
>>    }


>>  for (counter = 0; counter < 5; counter++)
>>    {
>>    printf("cycle %u\n",counter);
>>      lock (fd);
>>      unlock (fd);
>>    }


>> /*malloc_test();

>>        char * buffer;
>>          printf ("How long do you want the string? ");
>>            scanf ("%d", &i);
>>              buffer = (char*) malloc (i+1);
>>                if (buffer==NULL) exit (1);
>>                            free (buffer);
>>    */


>>  exit (EXIT_SUCCESS);
>> }
>> /* main */



> [root@mail ~]# ./locks2
> cycle 0
> Error not listed 37
> Can not unlock file
> cycle 1
> Error not listed 37
> Can not unlock file
> cycle 2
> Error not listed 37
> Can not unlock file
> cycle 3
> Error not listed 37
> Can not unlock file
> cycle 4
> Error not listed 37
> Can not unlock file