In multi-thread applications, child can open a window but release FD will not be called upon its exit. NX Send window will be closed with release function. Parent thread will be closing it later upon its exit.
The parent can also send NX requests with this window and NX can generate page faults. After kernel handles the page fault, send signal to process by using PID if CRB is invalid. So parent thread will not receive signal since its PID is different from the one saved in vas_window. So use tgid in case if the task which has the same pid as in window is not running and sends signal to the parent. Signed-off-by: Haren Myneni <ha...@us.ibm.com> --- arch/powerpc/platforms/powernv/vas-fault.c | 14 ++++++++++++-- arch/powerpc/platforms/powernv/vas-window.c | 6 +++++- arch/powerpc/platforms/powernv/vas.h | 6 ++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c index 1ce85b5..98100c7 100644 --- a/arch/powerpc/platforms/powernv/vas-fault.c +++ b/arch/powerpc/platforms/powernv/vas-fault.c @@ -109,12 +109,14 @@ static void notify_process(pid_t pid, u64 fault_addr) * Remaining settings in the CSB are based on wait_for_csb() of * NX-GZIP. */ -static void update_csb(int pid, struct coprocessor_request_block *crb) +static void update_csb(struct vas_window *window, + struct coprocessor_request_block *crb) { int rc; void __user *csb_addr; struct task_struct *tsk; struct coprocessor_status_block csb; + pid_t pid = vas_window_pid(window); if (fault_in_csb(crb)) goto notify; @@ -137,6 +139,14 @@ static void update_csb(int pid, struct coprocessor_request_block *crb) rcu_read_lock(); tsk = find_task_by_vpid(pid); + + /* + * Thread may not exists, but does not close FD (means send window) + * upon exit. Expects parent (tgid) to use and close the window. + */ + if (!tsk && window->user_win) + tsk = find_task_by_vpid(vas_window_tgid(window)); + if (!tsk) { /* * vas_win_close() waits for any pending CRBs and pending @@ -270,7 +280,7 @@ static void process_fault_crbs(struct vas_instance *vinst) return; } - update_csb(vas_window_pid(window), crb); + update_csb(window, crb); } while (true); } diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c index 77871c1..2946dd6 100644 --- a/arch/powerpc/platforms/powernv/vas-window.c +++ b/arch/powerpc/platforms/powernv/vas-window.c @@ -886,8 +886,10 @@ struct vas_window *vas_rx_win_open(int vasid, enum vas_cop_type cop, rxwin->user_win = rxattr->user_win; rxwin->cop = cop; rxwin->wcreds_max = rxattr->wcreds_max ?: VAS_WCREDS_DEFAULT; - if (rxattr->user_win) + if (rxattr->user_win) { rxwin->pid = task_pid_vnr(current); + rxwin->tgid = task_tgid_vnr(current); + } init_winctx_for_rxwin(rxwin, rxattr, &winctx); init_winctx_regs(rxwin, &winctx); @@ -1033,6 +1035,8 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop, txwin->pid = attr->pid; txwin->user_win = attr->user_win; txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT; + if (attr->user_win) + txwin->tgid = task_tgid_vnr(current); init_winctx_for_txwin(txwin, attr, &winctx); diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h index be1aefa..1812c59 100644 --- a/arch/powerpc/platforms/powernv/vas.h +++ b/arch/powerpc/platforms/powernv/vas.h @@ -344,6 +344,7 @@ struct vas_window { void *hvwc_map; /* HV window context */ void *uwc_map; /* OS/User window context */ pid_t pid; /* Linux process id of owner */ + pid_t tgid; /* Thread group ID of owner */ int wcreds_max; /* Window credits */ char *dbgname; @@ -429,6 +430,11 @@ static inline int vas_window_pid(struct vas_window *window) return window->pid; } +static inline int vas_window_tgid(struct vas_window *window) +{ + return window->tgid; +} + static inline void vas_log_write(struct vas_window *win, char *name, void *regptr, u64 val) { -- 1.8.3.1