Today we discovered again a lock situation on one of our PIII SMP-boxes,

running SuSE 7.2 and kernel 2.4.18. The openafs-1.2.5 client has the
following patches included:
TryFlushDcacheChildren:
http://www.openafs.org/cgi-bin/wdelta/linux-newvcache-make-sure-we-dont-try-to-iterate-null-pointer-20020615

and the following patch from Chas Williams:

> Index: osi_sleep.c
> ===================================================================
> RCS file: /cvs/openafs/src/afs/LINUX/osi_sleep.c,v
> retrieving revision 1.6.4.4
> diff -u -d -b -w -r1.6.4.4 osi_sleep.c
> --- osi_sleep.c 2002/01/29 19:45:39     1.6.4.4
> +++ osi_sleep.c 2002/06/14 12:46:37
> @@ -17,52 +17,13 @@
>  #include "../afs/afs_stats.h"   /* afs statistics */
>
>
> -
> -#if defined(AFS_GLOBAL_SUNLOCK)
>  static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
> -#endif
> -
>  void afs_osi_Wakeup(char *event);
>  void afs_osi_Sleep(char *event);
>
>  static char waitV, dummyV;
>
> -#if ! defined(AFS_GLOBAL_SUNLOCK)
> -
> -/* call procedure aproc with arock as an argument, in ams
milliseconds */
> -static struct timer_list *afs_osi_CallProc(void *aproc, void *arock,
int ams)
> -{
> -    struct timer_list *timer = NULL;
> -
> -    timer = (struct timer_list*)osi_Alloc(sizeof(struct timer_list));

> -    if (timer) {
> -       init_timer(timer);
> -       timer->expires = (ams*afs_hz)/1000 + 1;
> -       timer->data = (unsigned long)arock;
> -       timer->function = aproc;
> -       add_timer(timer);
> -    }
> -    return timer;
> -}
> -
> -/* cancel a timeout, whether or not it has already occurred */
> -static int afs_osi_CancelProc(struct timer_list *timer)
> -{
> -    if (timer) {
> -       del_timer(timer);
> -       osi_Free(timer, sizeof(struct timer_list));
> -    }
> -    return 0;
> -}
> -
> -static AfsWaitHack()
> -{
> -    AFS_STATCNT(WaitHack);
> -    wakeup(&waitV);
> -}
>
> -#endif
> -
>  void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
>  {
>      AFS_STATCNT(osi_InitWaitHandle);
> @@ -96,25 +57,18 @@
>      if (ahandle)
>         ahandle->proc = (caddr_t) current;
>
> -    AFS_ASSERT_GLOCK();
>      do {
> -#if    defined(AFS_GLOBAL_SUNLOCK)
> -        code = osi_TimedSleep(&waitV, ams, 1);
> -        if (code == EINTR) {
> -                if (aintok)
> -                   return EINTR;
> -        }
> -#else
> -       timer = afs_osi_CallProc(AfsWaitHack, (char *) current, ams);
> -       afs_osi_Sleep(&waitV);
> -       afs_osi_CancelProc(timer);
> -#endif /* AFS_GLOBAL_SUNLOCK */
> +        AFS_ASSERT_GLOCK();
> +       code = 0;
> +        code = osi_TimedSleep(&waitV, ams, aintok);
> +
> +        if (code) break;
>         if (ahandle && (ahandle->proc == (caddr_t) 0)) {
>             /* we've been signalled */
> -           return EINTR;
> +           break;
>         }
>      } while (osi_Time() < endTime);
> -    return 0;
> +    return code;
>  }
>
>
> @@ -209,38 +163,40 @@
>  {
>      struct afs_event *evp;
>      int seq;
> +    sigset_t saved_set;
> +    DECLARE_WAITQUEUE(wait, current);
>
>      evp = afs_getevent(event);
>      if (!evp) {
> -       /* Can't block because allocating a new event would require
dropping
> -         * the GLOCK, which may cause us to miss the wakeup.  So call

the
> -         * allocator then return immediately.  We'll find the new
event next
> -         * time around without dropping the GLOCK. */
>          afs_addevent(event);
> -        return;
> +       evp = afs_getevent(event);
>      }
>
>      seq = evp->seq;
>
> -    while (seq == evp->seq) {
> -       sigset_t saved_set;
> -
> -       AFS_ASSERT_GLOCK();
> -       AFS_GUNLOCK();
>         spin_lock_irq(&current->sigmask_lock);
>         saved_set = current->blocked;
>         sigfillset(&current->blocked);
>         recalc_sigpending(current);
>         spin_unlock_irq(&current->sigmask_lock);
>
> -       interruptible_sleep_on(&evp->cond);
> +    add_wait_queue(&evp->cond, &wait);
> +    while (seq == evp->seq) {
> +        set_current_state(TASK_INTERRUPTIBLE);
> +       AFS_ASSERT_GLOCK();
> +       AFS_GUNLOCK();
> +       schedule();
> +       AFS_GLOCK();
> +    }
>
>         spin_lock_irq(&current->sigmask_lock);
>         current->blocked = saved_set;
>         recalc_sigpending(current);
>         spin_unlock_irq(&current->sigmask_lock);
> -       AFS_GLOCK();
> -    }
> +
> +    remove_wait_queue(&evp->cond, &wait);
> +    set_current_state(TASK_RUNNING);
> +
>      relevent(evp);
>  }
>
> @@ -256,29 +212,39 @@
>   */
>  static int osi_TimedSleep(char *event, afs_int32 ams, int aintok)
>  {
> -    long t = ams * HZ / 1000;
> +    int code = 0;
> +    long ticks = (ams * HZ / 1000) + 1;
>      struct afs_event *evp;
> +    DECLARE_WAITQUEUE(wait, current);
>
>      evp = afs_getevent(event);
>      if (!evp) {
> -        /* Can't block because allocating a new event would require
dropping
> -         * the GLOCK, which may cause us to miss the wakeup.  So call

the
> -         * allocator then return immediately.  We'll find the new
event next
> -         * time around without dropping the GLOCK. */
>          afs_addevent(event);
> -        return EAGAIN;
> +       evp = afs_getevent(event);
>      }
>
> +    if (aintok == 0) {
> +    }
> +
> +    add_wait_queue(&evp->cond, &wait);
> +    set_current_state(TASK_INTERRUPTIBLE);
> +               /* always sleep TASK_INTERRUPTIBLE to keep load
average
> +                  from artifically increasing. */
>      AFS_GUNLOCK();
> -    if (aintok)
> -       t = interruptible_sleep_on_timeout(&evp->cond, t);
> -    else
> -       t = sleep_on_timeout(&evp->cond, t);
> +
> +    if (aintok) {
> +        if (schedule_timeout(ticks))
> +            code = EINTR;
> +    } else
> +        schedule_timeout(ticks);
> +
>      AFS_GLOCK();
> +    remove_wait_queue(&evp->cond, &wait);
> +    set_current_state(TASK_RUNNING);
>
>      relevent(evp);
>
> -    return t ? EINTR : 0;
> +    return code;
>  }
>
>
> Index: osi_alloc.c
> ===================================================================
> RCS file: /cvs/openafs/src/afs/LINUX/osi_alloc.c,v
> retrieving revision 1.9.2.4
> diff -u -d -b -w -r1.9.2.4 osi_alloc.c
> --- osi_alloc.c 2002/04/23 03:32:36     1.9.2.4
> +++ osi_alloc.c 2002/06/14 12:46:48
> @@ -24,7 +24,7 @@
>  #include "../afs/afs_atomlist.h"
>  #include "../afs/afs_lhash.h"
>
> -#define MAX_KMALLOC_SIZE (131072-16) /* Max we can alloc in physmem
*/
> +#define MAX_KMALLOC_SIZE AFS_SMALLOCSIZ /* Max we should alloc with
kmalloc */
>  #define MAX_BUCKET_LEN 30 /* max. no. of entries per buckets we
expect to see */
>  #define STAT_INTERVAL 8192 /* we collect stats once every
STAT_INTERVAL allocs*/
>
> @@ -79,14 +79,12 @@
>  static void *linux_alloc(unsigned int asize)
>  {
>      void *new = NULL;
> -    int has_afs_glock = ISAFS_GLOCK();
> -
> -    /* if global lock has been held save this info and unlock it. */
> -    if (has_afs_glock)
> -        AFS_GUNLOCK();
> +    int max_retry = 10;
>
>      /*  if we can use kmalloc use it to allocate the required memory.

*/
> -    if (asize <  MAX_KMALLOC_SIZE) {
> +    while(!new && max_retry)
> +    {
> +        if (asize <=  MAX_KMALLOC_SIZE) {
>          new = (void *)(unsigned long)kmalloc(asize,
>  #ifdef GFP_NOFS
>                                              GFP_NOFS
> @@ -96,30 +94,31 @@
>                                              );
>          if (new) /* piggy back alloc type */
>              (unsigned long)new |= KM_TYPE;
> -    }
> -    if (!new) { /* otherwise use vmalloc  */
> -       int max_wait = 10;
> -        while (!(new = (void *)vmalloc(asize))) {
> -            if (--max_wait <=0) {
> -               break;
> +        } else {
> +            new = (void *)vmalloc(asize);
> +           if (new) /* piggy back alloc type */
> +               (unsigned long)new |= VM_TYPE;
>              }
> +
> +       if (!new) {
> +printk("god damn it -- need to retry alloc()...\n");
>  #ifdef set_current_state
>             set_current_state(TASK_INTERRUPTIBLE);
>  #else
>             current->state = TASK_INTERRUPTIBLE;
>  #endif
>             schedule_timeout(HZ);
> +#ifdef set_current_state
> +            set_current_state(TASK_RUNNING);
> +#else
> +            current->state = TASK_RUNNING;
> +#endif
> +            --max_retry;
>          }
> -       if (new) /* piggy back alloc type */
> -           (unsigned long)new |= VM_TYPE;
>      }
>      if (new)
>         memset(MEMADDR(new), 0, asize);
>
> -    /* if the global lock had been held, lock it again. */
> -    if (has_afs_glock)
> -        AFS_GLOCK();
> -
>      return new;
>  }
>
> @@ -287,21 +286,21 @@
>      void *new = NULL;
>      struct osi_linux_mem *lmem;
>
> +    new = linux_alloc(asize); /* get a chunk of memory of size asize
*/
> +
> +    if (!new) {
> +       printf("afs_osi_Alloc: Can't vmalloc %d bytes.\n", asize);
> +       return new;
> +    }
> +
>      down(&afs_linux_alloc_sem);
>
> -    if (allocator_init == 0) { /* allocator hasn't been initialized
yet */
> +    /* allocator hasn't been initialized yet */
> +    if (allocator_init == 0) {
>         if (linux_alloc_init() == 0) {
>             goto error;
>          }
>         allocator_init = 1; /* initialization complete */
> -    }
> -
> -    up(&afs_linux_alloc_sem);
> -    new = linux_alloc(asize); /* get a chunk of memory of size asize
*/
> -    down(&afs_linux_alloc_sem);
> -    if (!new) {
> -       printf("afs_osi_Alloc: Can't vmalloc %d bytes.\n", asize);
> -       goto error;
>      }
>
>      /* get an atom to store the pointer to the chunk */


Please find the analysis of the dump I've generated and the syslog file
containing the stack traces attached to this mail.

Regards

Herbert

Attachment: analysis.0.gz
Description: GNU Zip compressed data

Attachment: warn.lxsrv1.gz
Description: GNU Zip compressed data

begin:vcard 
n:Huber;Herbert
tel;work:089-289-28833
x-mozilla-html:FALSE
url:http:/www.lrz.de/
org:Leibniz-Rechenzentrum;Gruppe Hochleistungssysteme
adr:;;Leibniz-Rechenzentrum der Bayerischen Akademie der Wissenschafte;M�nchen;;D-80333;Germany
version:2.1
email;internet:[EMAIL PROTECTED]
title:Dr.
x-mozilla-cpt:;-12480
fn:Herbert Huber
end:vcard

Reply via email to