afs: afs_pag_wait() makes process unkillable 60/12260/7
authorMarcio Barbosa <mbarbosa@sinenomine.net>
Thu, 7 Nov 2019 03:10:12 +0000 (00:10 -0300)
committerBenjamin Kaduk <kaduk@mit.edu>
Thu, 28 Nov 2019 07:18:32 +0000 (02:18 -0500)
To enforce a maximum average rate of one PAG allocation per second,
afs_pag_wait(), called by afs_setpag*(), sleeps until the difference
between the current time and pag_epoch gets greater than pagCounter.
Unfortunately, this function ignores the code returned by afs_osi_Wait().
As a result, it is not possible to kill the process that requested the
new pag while afs_pag_wait() is sleeping.

To fix this problem, do not ignore the code returned by afs_osi_Wait().

Change-Id: I6be11a569edcafa6ecdf716e5315fc75f5a128e8
Reviewed-on: https://gerrit.openafs.org/12260
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>

src/afs/afs_osi_pag.c

index 6b9ae1f..22167f0 100644 (file)
@@ -162,6 +162,8 @@ afs_pag_sleep(afs_ucred_t **acred)
 static int
 afs_pag_wait(afs_ucred_t **acred)
 {
+    int code = 0;
+
     if (afs_pag_sleep(acred)) {
        if (!afs_pag_sleepcnt) {
            afs_warn("%s() PAG throttling triggered, pid %d... sleeping.  sleepcnt %d\n",
@@ -171,14 +173,13 @@ afs_pag_wait(afs_ucred_t **acred)
        afs_pag_sleepcnt++;
 
        do {
-           /* XXX spins on EINTR */
-           afs_osi_Wait(1000, (struct afs_osi_WaitHandle *)0, 0);
-       } while (afs_pag_sleep(acred));
+           code = afs_osi_Wait(1000, (struct afs_osi_WaitHandle *)0, 0);
+       } while (!code && afs_pag_sleep(acred));
 
        afs_pag_sleepcnt--;
     }
 
-    return 0;
+    return code;
 }
 
 int
@@ -212,7 +213,10 @@ afs_setpag(void)
 
     AFS_STATCNT(afs_setpag);
 
-    afs_pag_wait(acred);
+    code = afs_pag_wait(acred);
+    if (code) {
+       goto done;
+    }
 
 
 #if    defined(AFS_SUN5_ENV)
@@ -271,6 +275,7 @@ afs_setpag(void)
     code = AddPag(genpag(), &u.u_cred);
 #endif
 
+  done:
     afs_Trace1(afs_iclSetp, CM_TRACE_SETPAG, ICL_TYPE_INT32, code);
 
 #if defined(KERNEL_HAVE_UERROR)
@@ -322,7 +327,10 @@ afs_setpag_val(int pagval)
 
     AFS_STATCNT(afs_setpag);
 
-    afs_pag_wait(acred);
+    code = afs_pag_wait(acred);
+    if (code) {
+       goto done;
+    }
 
 #if    defined(AFS_SUN5_ENV)
     code = AddPag(pagval, credpp);
@@ -372,6 +380,7 @@ afs_setpag_val(int pagval)
     code = AddPag(pagval, &u.u_cred);
 #endif
 
+  done:
     afs_Trace1(afs_iclSetp, CM_TRACE_SETPAG, ICL_TYPE_INT32, code);
 #if defined(KERNEL_HAVE_UERROR)
     if (!getuerror())