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(¤t->sigmask_lock);
> saved_set = current->blocked;
> sigfillset(¤t->blocked);
> recalc_sigpending(current);
> spin_unlock_irq(¤t->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(¤t->sigmask_lock);
> current->blocked = saved_set;
> recalc_sigpending(current);
> spin_unlock_irq(¤t->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
analysis.0.gz
Description: GNU Zip compressed data
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
