diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-06-10 05:30:17 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-06-10 05:30:17 -0300 |
commit | d635711daa98be86d4c7fd01499c34f566b54ccb (patch) | |
tree | aa5cc3760a27c3d57146498cb82fa549547de06c /fs/dlm | |
parent | c91265cd0efb83778f015b4d4b1129bd2cfd075e (diff) |
Linux-libre 4.6.2-gnu
Diffstat (limited to 'fs/dlm')
-rw-r--r-- | fs/dlm/config.c | 41 | ||||
-rw-r--r-- | fs/dlm/lowcomms.c | 82 |
2 files changed, 74 insertions, 49 deletions
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 8e294fbba..1669f6291 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -343,24 +343,20 @@ static struct config_group *make_cluster(struct config_group *g, struct dlm_cluster *cl = NULL; struct dlm_spaces *sps = NULL; struct dlm_comms *cms = NULL; - void *gps = NULL; cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS); - gps = kcalloc(3, sizeof(struct config_group *), GFP_NOFS); sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS); cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS); - if (!cl || !gps || !sps || !cms) + if (!cl || !sps || !cms) goto fail; config_group_init_type_name(&cl->group, name, &cluster_type); config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type); config_group_init_type_name(&cms->cs_group, "comms", &comms_type); - cl->group.default_groups = gps; - cl->group.default_groups[0] = &sps->ss_group; - cl->group.default_groups[1] = &cms->cs_group; - cl->group.default_groups[2] = NULL; + configfs_add_default_group(&sps->ss_group, &cl->group); + configfs_add_default_group(&cms->cs_group, &cl->group); cl->cl_tcp_port = dlm_config.ci_tcp_port; cl->cl_buffer_size = dlm_config.ci_buffer_size; @@ -383,7 +379,6 @@ static struct config_group *make_cluster(struct config_group *g, fail: kfree(cl); - kfree(gps); kfree(sps); kfree(cms); return ERR_PTR(-ENOMEM); @@ -392,14 +387,8 @@ static struct config_group *make_cluster(struct config_group *g, static void drop_cluster(struct config_group *g, struct config_item *i) { struct dlm_cluster *cl = config_item_to_cluster(i); - struct config_item *tmp; - int j; - for (j = 0; cl->group.default_groups[j]; j++) { - tmp = &cl->group.default_groups[j]->cg_item; - cl->group.default_groups[j] = NULL; - config_item_put(tmp); - } + configfs_remove_default_groups(&cl->group); space_list = NULL; comm_list = NULL; @@ -410,7 +399,6 @@ static void drop_cluster(struct config_group *g, struct config_item *i) static void release_cluster(struct config_item *i) { struct dlm_cluster *cl = config_item_to_cluster(i); - kfree(cl->group.default_groups); kfree(cl); } @@ -418,21 +406,17 @@ static struct config_group *make_space(struct config_group *g, const char *name) { struct dlm_space *sp = NULL; struct dlm_nodes *nds = NULL; - void *gps = NULL; sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS); - gps = kcalloc(2, sizeof(struct config_group *), GFP_NOFS); nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS); - if (!sp || !gps || !nds) + if (!sp || !nds) goto fail; config_group_init_type_name(&sp->group, name, &space_type); - config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type); - sp->group.default_groups = gps; - sp->group.default_groups[0] = &nds->ns_group; - sp->group.default_groups[1] = NULL; + config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type); + configfs_add_default_group(&nds->ns_group, &sp->group); INIT_LIST_HEAD(&sp->members); mutex_init(&sp->members_lock); @@ -441,7 +425,6 @@ static struct config_group *make_space(struct config_group *g, const char *name) fail: kfree(sp); - kfree(gps); kfree(nds); return ERR_PTR(-ENOMEM); } @@ -449,24 +432,16 @@ static struct config_group *make_space(struct config_group *g, const char *name) static void drop_space(struct config_group *g, struct config_item *i) { struct dlm_space *sp = config_item_to_space(i); - struct config_item *tmp; - int j; /* assert list_empty(&sp->members) */ - for (j = 0; sp->group.default_groups[j]; j++) { - tmp = &sp->group.default_groups[j]->cg_item; - sp->group.default_groups[j] = NULL; - config_item_put(tmp); - } - + configfs_remove_default_groups(&sp->group); config_item_put(i); } static void release_space(struct config_item *i) { struct dlm_space *sp = config_item_to_space(i); - kfree(sp->group.default_groups); kfree(sp); } diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 3a37bd3f9..1ab012a27 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -124,7 +124,10 @@ struct connection { struct connection *othercon; struct work_struct rwork; /* Receive workqueue */ struct work_struct swork; /* Send workqueue */ - void (*orig_error_report)(struct sock *sk); + void (*orig_error_report)(struct sock *); + void (*orig_data_ready)(struct sock *); + void (*orig_state_change)(struct sock *); + void (*orig_write_space)(struct sock *); }; #define sock2con(x) ((struct connection *)(x)->sk_user_data) @@ -467,16 +470,24 @@ int dlm_lowcomms_connect_node(int nodeid) static void lowcomms_error_report(struct sock *sk) { - struct connection *con = sock2con(sk); + struct connection *con; struct sockaddr_storage saddr; + int buflen; + void (*orig_report)(struct sock *) = NULL; - if (nodeid_to_addr(con->nodeid, &saddr, NULL, false)) { + read_lock_bh(&sk->sk_callback_lock); + con = sock2con(sk); + if (con == NULL) + goto out; + + orig_report = con->orig_error_report; + if (con->sock == NULL || + kernel_getpeername(con->sock, (struct sockaddr *)&saddr, &buflen)) { printk_ratelimited(KERN_ERR "dlm: node %d: socket error " "sending to node %d, port %d, " "sk_err=%d/%d\n", dlm_our_nodeid(), con->nodeid, dlm_config.ci_tcp_port, sk->sk_err, sk->sk_err_soft); - return; } else if (saddr.ss_family == AF_INET) { struct sockaddr_in *sin4 = (struct sockaddr_in *)&saddr; @@ -499,22 +510,54 @@ static void lowcomms_error_report(struct sock *sk) dlm_config.ci_tcp_port, sk->sk_err, sk->sk_err_soft); } - con->orig_error_report(sk); +out: + read_unlock_bh(&sk->sk_callback_lock); + if (orig_report) + orig_report(sk); +} + +/* Note: sk_callback_lock must be locked before calling this function. */ +static void save_callbacks(struct connection *con, struct sock *sk) +{ + lock_sock(sk); + con->orig_data_ready = sk->sk_data_ready; + con->orig_state_change = sk->sk_state_change; + con->orig_write_space = sk->sk_write_space; + con->orig_error_report = sk->sk_error_report; + release_sock(sk); +} + +static void restore_callbacks(struct connection *con, struct sock *sk) +{ + write_lock_bh(&sk->sk_callback_lock); + lock_sock(sk); + sk->sk_user_data = NULL; + sk->sk_data_ready = con->orig_data_ready; + sk->sk_state_change = con->orig_state_change; + sk->sk_write_space = con->orig_write_space; + sk->sk_error_report = con->orig_error_report; + release_sock(sk); + write_unlock_bh(&sk->sk_callback_lock); } /* Make a socket active */ static void add_sock(struct socket *sock, struct connection *con) { + struct sock *sk = sock->sk; + + write_lock_bh(&sk->sk_callback_lock); con->sock = sock; + sk->sk_user_data = con; + if (!test_bit(CF_IS_OTHERCON, &con->flags)) + save_callbacks(con, sk); /* Install a data_ready callback */ - con->sock->sk->sk_data_ready = lowcomms_data_ready; - con->sock->sk->sk_write_space = lowcomms_write_space; - con->sock->sk->sk_state_change = lowcomms_state_change; - con->sock->sk->sk_user_data = con; - con->sock->sk->sk_allocation = GFP_NOFS; - con->orig_error_report = con->sock->sk->sk_error_report; - con->sock->sk->sk_error_report = lowcomms_error_report; + sk->sk_data_ready = lowcomms_data_ready; + sk->sk_write_space = lowcomms_write_space; + sk->sk_state_change = lowcomms_state_change; + sk->sk_allocation = GFP_NOFS; + sk->sk_error_report = lowcomms_error_report; + write_unlock_bh(&sk->sk_callback_lock); } /* Add the port number to an IPv6 or 4 sockaddr and return the address @@ -549,6 +592,8 @@ static void close_connection(struct connection *con, bool and_other, mutex_lock(&con->sock_mutex); if (con->sock) { + if (!test_bit(CF_IS_OTHERCON, &con->flags)) + restore_callbacks(con, con->sock->sk); sock_release(con->sock); con->sock = NULL; } @@ -595,7 +640,7 @@ static int receive_from_sock(struct connection *con) con->rx_page = alloc_page(GFP_ATOMIC); if (con->rx_page == NULL) goto out_resched; - cbuf_init(&con->cb, PAGE_CACHE_SIZE); + cbuf_init(&con->cb, PAGE_SIZE); } /* @@ -612,7 +657,7 @@ static int receive_from_sock(struct connection *con) * buffer and the start of the currently used section (cb.base) */ if (cbuf_data(&con->cb) >= con->cb.base) { - iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb); + iov[0].iov_len = PAGE_SIZE - cbuf_data(&con->cb); iov[1].iov_len = con->cb.base; iov[1].iov_base = page_address(con->rx_page); nvec = 2; @@ -630,7 +675,7 @@ static int receive_from_sock(struct connection *con) ret = dlm_process_incoming_buffer(con->nodeid, page_address(con->rx_page), con->cb.base, con->cb.len, - PAGE_CACHE_SIZE); + PAGE_SIZE); if (ret == -EBADMSG) { log_print("lowcomms: addr=%p, base=%u, len=%u, read=%d", page_address(con->rx_page), con->cb.base, @@ -1190,6 +1235,8 @@ static struct socket *tcp_create_listen_sock(struct connection *con, if (result < 0) { log_print("Failed to set SO_REUSEADDR on socket: %d", result); } + sock->sk->sk_user_data = con; + con->rx_action = tcp_accept_from_sock; con->connect_action = tcp_connect_to_sock; @@ -1271,6 +1318,7 @@ static int sctp_listen_for_all(void) if (result < 0) log_print("Could not set SCTP NODELAY error %d\n", result); + write_lock_bh(&sock->sk->sk_callback_lock); /* Init con struct */ sock->sk->sk_user_data = con; con->sock = sock; @@ -1278,6 +1326,8 @@ static int sctp_listen_for_all(void) con->rx_action = sctp_accept_from_sock; con->connect_action = sctp_connect_to_sock; + write_unlock_bh(&sock->sk->sk_callback_lock); + /* Bind to all addresses. */ if (sctp_bind_addrs(con, dlm_config.ci_tcp_port)) goto create_delsock; @@ -1366,7 +1416,7 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc) spin_lock(&con->writequeue_lock); e = list_entry(con->writequeue.prev, struct writequeue_entry, list); if ((&e->list == &con->writequeue) || - (PAGE_CACHE_SIZE - e->end < len)) { + (PAGE_SIZE - e->end < len)) { e = NULL; } else { offset = e->end; |