From: Aaron Young Date: Thu, 2 Jun 2016 14:55:09 +0000 (-0400) Subject: SPARC64: UEK4 LDOMS DOMAIN SERVICES UPDATE 4 X-Git-Tag: v4.1.12-92~124^2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=4c23994bf12ddc9347733ee76f0da5cbd3fa3375;p=users%2Fjedix%2Flinux-maple.git SPARC64: UEK4 LDOMS DOMAIN SERVICES UPDATE 4 This update provides the following fixes for LDom domain services on UEK4. 1. DS service registration with major ver 0. 2. Kernel NULL pointer dereference in vlds driver at shutdown. Signed-off-by: Aaron Young Reviewed-by: Liam Merwick Orabug: 23292083,23504208 --- diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index 151f598ff60a..9dd2d125a3f6 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c @@ -2,7 +2,7 @@ * ds.c: Sun4v LDOMs Domain Services Driver * * Copyright (C) 2007, 2008 David S. Miller - * Copyright (C) 2015 Oracle. All rights reserved. + * Copyright (C) 2015, 2016 Oracle. All rights reserved. */ #include #include @@ -899,6 +899,7 @@ struct ds_callout_data_entry { struct ds_callout_reg_entry { struct ds_callout_entry_hdr hdr; u64 hdl; + ds_ver_t neg_vers; }; static struct ds_service_info *ds_callout_data_get_service( @@ -1116,7 +1117,7 @@ static void ds_do_callout_processing(void) reg_cb = svc_info->ops.ds_reg_cb; unreg_cb = svc_info->ops.ds_unreg_cb; cb_arg = svc_info->ops.cb_arg; - neg_vers = svc_info->neg_vers; + neg_vers = rentry->neg_vers; UNLOCK_DS_DEV(ds, ds_flags) @@ -1174,7 +1175,8 @@ static int ds_callout_thread(void *__unused) return 0; } -static int ds_submit_reg_cb(struct ds_dev *ds, u64 hdl, u8 type) +static int ds_submit_reg_cb(struct ds_dev *ds, u64 hdl, ds_ver_t *neg_vers, + u8 type) { struct ds_callout_reg_entry *rentry; gfp_t alloc_flags; @@ -1192,6 +1194,8 @@ static int ds_submit_reg_cb(struct ds_dev *ds, u64 hdl, u8 type) rentry->hdr.type = type; rentry->hdr.ds = ds; rentry->hdl = hdl; + if (neg_vers) + rentry->neg_vers = *neg_vers; list_add_tail(&rentry->hdr.list, &ds->callout_list); ds->co_ref_cnt++; @@ -2292,7 +2296,8 @@ static void ds_connect_service_client(struct ds_dev *ds, u64 handle, client_svc_info->is_connected = true; /* submit the register callback */ - (void) ds_submit_reg_cb(ds, client_svc_info->handle, DS_QTYPE_REG); + (void) ds_submit_reg_cb(ds, client_svc_info->handle, + &client_svc_info->neg_vers, DS_QTYPE_REG); } static void ds_disconnect_service_client(struct ds_dev *ds, @@ -2324,7 +2329,8 @@ static void ds_disconnect_service_client(struct ds_dev *ds, client_svc_info->svc_reg_timeout = ds_get_service_timeout(); /* submit the unregister callback */ - (void) ds_submit_reg_cb(ds, client_svc_info->handle, DS_QTYPE_UNREG); + (void) ds_submit_reg_cb(ds, client_svc_info->handle, NULL, + DS_QTYPE_UNREG); /* if it was a loopback connection, disconnect the peer */ if (peer_svc_info) @@ -2345,8 +2351,8 @@ static void ds_connect_service_provider(struct ds_dev *ds, u64 handle, provider_svc_info->is_connected = true; /* submit the register callback */ - (void) ds_submit_reg_cb(ds, provider_svc_info->handle, DS_QTYPE_REG); - + (void) ds_submit_reg_cb(ds, provider_svc_info->handle, + &provider_svc_info->neg_vers, DS_QTYPE_REG); } static void ds_disconnect_service_provider(struct ds_dev *ds, @@ -2378,7 +2384,8 @@ static void ds_disconnect_service_provider(struct ds_dev *ds, provider_svc_info->svc_reg_timeout = ds_get_service_timeout(); /* submit the unregister callback */ - (void) ds_submit_reg_cb(ds, provider_svc_info->handle, DS_QTYPE_UNREG); + (void) ds_submit_reg_cb(ds, provider_svc_info->handle, NULL, + DS_QTYPE_UNREG); /* if it was a loopback connection, disconnect the peer */ if (peer_svc_info) @@ -2420,8 +2427,10 @@ static int ds_connect_loopback_service(struct ds_dev *ds, peer_svc_info->is_connected = true; /* submit the register callbacks */ - (void) ds_submit_reg_cb(ds, svc_info->handle, DS_QTYPE_REG); - (void) ds_submit_reg_cb(ds, peer_svc_info->handle, DS_QTYPE_REG); + (void) ds_submit_reg_cb(ds, svc_info->handle, + &svc_info->neg_vers, DS_QTYPE_REG); + (void) ds_submit_reg_cb(ds, peer_svc_info->handle, + &peer_svc_info->neg_vers, DS_QTYPE_REG); return 0; } @@ -4536,7 +4545,7 @@ static int __init ds_init(void) { unsigned long hv_ret, major, minor; struct task_struct *callout_task; - int err; + int err; /* set the default ldoms debug level */ dsdbg_level = ldoms_debug_level; diff --git a/drivers/char/vlds.c b/drivers/char/vlds.c index 7f38f6e92b6a..cf0814767bfd 100644 --- a/drivers/char/vlds.c +++ b/drivers/char/vlds.c @@ -306,7 +306,7 @@ static int vlds_signal_event(pid_t tgid, int fd) /* Get the task struct */ utask = pid_task(find_vpid(tgid), PIDTYPE_PID); - if (!utask) { + if (!utask || !utask->files) { rcu_read_unlock(); return -EIO; } @@ -781,7 +781,6 @@ vlds_ds_reg_cb(ds_cb_arg_t arg, ds_svc_hdl_t hdl, ds_ver_t *ver) svc_info->neg_vers.vlds_minor, hdl); mutex_unlock(&vlds->vlds_mutex); - } static void @@ -818,7 +817,6 @@ vlds_ds_unreg_cb(ds_cb_arg_t arg, ds_svc_hdl_t hdl) vlds->int_name, svc_info->name, hdl); mutex_unlock(&vlds->vlds_mutex); - } static void @@ -859,7 +857,6 @@ vlds_ds_data_cb(ds_cb_arg_t arg, ds_svc_hdl_t hdl, void *buf, size_t buflen) vlds->int_name, svc_info->name, buflen, hdl); mutex_unlock(&vlds->vlds_mutex); - } static ds_ops_t vlds_ds_ops = {