afs: Introduce afs_kill_pending()

Introduce a function that checks to see if the current kernel task has
a pending kill (e.g. SIGKILL) that will terminate the process when it
returns to userspace.

Add afs_kill_pending() that uses an osi level function,
osi_kill_pending() to determine if the process has a pending
termination. If the osi level function has not been implemented, just
return 0.

Add a Linux implementation of osi_kill_pending() that calls Linux's
fatal_signal_pending() (if it's available).

Update Linux's "filter_enoent()" function in osi_vnodeops.c to use
afs_kill_pending().

A future commit will expand the use of afs_kill_pending().

Fix minor white space in an adjacent lines.

Change-Id: Ib215639d36f4baa7a1dffda3cc314d2d447c6e96
Reviewed-on: https://gerrit.openafs.org/15746
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Michael Meffie <mmeffie@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
This commit is contained in:
Cheyenne Wills 2024-05-14 19:34:59 -06:00 committed by Andrew Deason
parent 9d34ceb2dc
commit 840cf3b628
5 changed files with 62 additions and 9 deletions

View File

@ -186,3 +186,20 @@ afs_start_thread(void (*proc)(void), char *name, int needs_glock)
kthread_run(afs_thread_wrapper, proc, "%s", name);
}
}
/*
* Check for a pending fatal signal
* Return 1 if a fatal signal is pending, otherwise return 0;
*/
int
osi_kill_pending(void)
{
#if defined(HAVE_LINUX_FATAL_SIGNAL_PENDING)
if (fatal_signal_pending(current)) {
return 1;
}
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
# error fatal_signal_pending not available, but it should be
#endif
return 0;
}

View File

@ -51,6 +51,7 @@ extern int osi_lookupname(char *aname, uio_seg_t seg, int followlink,
extern int osi_abspath(char *aname, char *buf, int buflen,
int followlink, char **pathp);
extern void afs_start_thread(void (*proc)(void), char *name, int needs_glock);
extern int osi_kill_pending(void);
/* osi_probe.c */
extern void *osi_find_syscall_table(int which);

View File

@ -1305,17 +1305,19 @@ parent_vcache_dv(struct inode *inode, cred_t *credp)
}
return hgetlo(pvcp->f.m.DataVersion);
}
/*
* Make sure we don't accidentally yield an ENOENT that's caused by internal
* errors instead of the requested filename actually not existing. This has been
* possible in the past because Linux returns errors for some low-level routines
* when the process is dying. Incorrect ENOENT errors can cause bogus negative
* dentries to exist, which is very bad, so make sure that doesn't happen.
*/
static inline int
filter_enoent(int code)
{
#ifdef HAVE_LINUX_FATAL_SIGNAL_PENDING
if (code == ENOENT && fatal_signal_pending(current)) {
return EINTR;
if (code == ENOENT && afs_kill_pending()) {
return EINTR;
}
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
# error fatal_signal_pending not available, but it should be
#endif
return code;
}

View File

@ -383,6 +383,38 @@ afs_PrintServerErrors(struct vrequest *areq, struct VenusFid *afid)
afs_warnuser("%s\n", term);
}
/*!
* \brief
* Determine if the current process is pending termination and will be
* killed when returning to userspace.
*
* \retval 1 if the process is dying
* \retval 0 if the process is not dying
*
* \note
* If the process is pending termination, there is no need to retry requests
* or wait for a server to return data, etc. as the process is going to die
* before it can process any data. However we will still need to ensure that
* we don't corrupt any locks, cache, etc., or any data that persists in other
* processes.
*
* \note
* On some platforms (Linux), a process will not sleep if it is pending
* termination. If we can detect that the process will be killed, it is better
* to not retry the requests, etc. to avoid spinning the CPU.
*/
int
afs_kill_pending(void)
{
#if defined(UKERNEL)
return 0;
#elif defined(AFS_LINUX_ENV)
return osi_kill_pending();
#else
return 0;
#endif /* UKERNEL */
}
/*!
* \brief
* Analyze the outcome of an RPC operation, taking whatever support

View File

@ -11,9 +11,10 @@
#define _AFS_PROTOTYPES_H_
/* afs_analyze.c */
extern int afs_kill_pending(void);
extern int afs_Analyze(struct afs_conn *aconn, struct rx_connection *rxconn,
afs_int32 acode, struct VenusFid *afid,
struct vrequest *areq,
afs_int32 acode, struct VenusFid *afid,
struct vrequest *areq,
int op, afs_int32 locktype, struct cell *cellp);
/* afs_axscache.c */