/****************************************************************************** ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. ** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions ** of the GNU General Public License v.2. ** ******************************************************************************* ******************************************************************************/ #include "dlm_internal.h" #include "lockspace.h" #include "member.h" #include "lowcomms.h" #include "midcomms.h" #include "rcom.h" #include "recover.h" #include "dir.h" #include "config.h" #include "memory.h" #include "lock.h" #include "util.h" static int rcom_response(struct dlm_ls *ls) { return test_bit(LSFL_RCOM_READY, &ls->ls_flags); } static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len, struct dlm_rcom **rc_ret, struct dlm_mhandle **mh_ret) { struct dlm_rcom *rc; struct dlm_mhandle *mh; char *mb; int mb_len = sizeof(struct dlm_rcom) + len; mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_NOFS, &mb); if (!mh) { log_print("create_rcom to %d type %d len %d ENOBUFS", to_nodeid, type, len); return -ENOBUFS; } memset(mb, 0, mb_len); rc = (struct dlm_rcom *) mb; rc->rc_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR); rc->rc_header.h_lockspace = ls->ls_global_id; rc->rc_header.h_nodeid = dlm_our_nodeid(); rc->rc_header.h_length = mb_len; rc->rc_header.h_cmd = DLM_RCOM; rc->rc_type = type; spin_lock(&ls->ls_recover_lock); rc->rc_seq = ls->ls_recover_seq; spin_unlock(&ls->ls_recover_lock); *mh_ret = mh; *rc_ret = rc; return 0; } static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh, struct dlm_rcom *rc) { dlm_rcom_out(rc); dlm_lowcomms_commit_buffer(mh); } static void set_rcom_status(struct dlm_ls *ls, struct rcom_status *rs, uint32_t flags) { rs->rs_flags = cpu_to_le32(flags); } /* When replying to a status request, a node also sends back its configuration values. The requesting node then checks that the remote node is configured the same way as itself. */ static void set_rcom_config(struct dlm_ls *ls, struct rcom_config *rf, uint32_t num_slots) { rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen); rf->rf_lsflags = cpu_to_le32(ls->ls_exflags); rf->rf_our_slot = cpu_to_le16(ls->ls_slot); rf->rf_num_slots = cpu_to_le16(num_slots); rf->rf_generation = cpu_to_le32(ls->ls_generation); } static int check_rcom_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) { struct rcom_config *rf = (struct rcom_config *) rc->rc_buf; if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) { log_error(ls, "version mismatch: %x nodeid %d: %x", DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid, rc->rc_header.h_version); return -EPROTO; } if (le32_to_cpu(rf->rf_lvblen) != ls->ls_lvblen || le32_to_cpu(rf->rf_lsflags) != ls->ls_exflags) { log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", ls->ls_lvblen, ls->ls_exflags, nodeid, le32_to_cpu(rf->rf_lvblen), le32_to_cpu(rf->rf_lsflags)); return -EPROTO; } return 0; } static void allow_sync_reply(struct dlm_ls *ls, uint64_t *new_seq) { spin_lock(&ls->ls_rcom_spin); *new_seq = ++ls->ls_rcom_seq; set_bit(LSFL_RCOM_WAIT, &ls->ls_flags); spin_unlock(&ls->ls_rcom_spin); } static void disallow_sync_reply(struct dlm_ls *ls) { spin_lock(&ls->ls_rcom_spin); clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags); clear_bit(LSFL_RCOM_READY, &ls->ls_flags); spin_unlock(&ls->ls_rcom_spin); } /* * low nodeid gathers one slot value at a time from each node. * it sets need_slots=0, and saves rf_our_slot returned from each * rcom_config. * * other nodes gather all slot values at once from the low nodeid. * they set need_slots=1, and ignore the rf_our_slot returned from each * rcom_config. they use the rf_num_slots returned from the low * node's rcom_config. */ int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags) { struct dlm_rcom *rc; struct dlm_mhandle *mh; int error = 0; ls->ls_recover_nodeid = nodeid; if (nodeid == dlm_our_nodeid()) { rc = ls->ls_recover_buf; rc->rc_result = dlm_recover_status(ls); goto out; } error = create_rcom(ls, nodeid, DLM_RCOM_STATUS, sizeof(struct rcom_status), &rc, &mh); if (error) goto out; set_rcom_status(ls, (struct rcom_status *)rc->rc_buf, status_flags); allow_sync_reply(ls, &rc->rc_id); memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size); send_rcom(ls, mh, rc); error = dlm_wait_function(ls, &rcom_response); disallow_sync_reply(ls); if (error) goto out; rc = ls->ls_recover_buf; if (rc->rc_result == -ESRCH) { /* we pretend the remote lockspace exists with 0 status */ log_debug(ls, "remote node %d no
/*
 * NET		Generic infrastructure for INET6 connection oriented protocols.
 *
 * Authors:	Many people, see the TCPv6 sources
 *
 * 		From code originally in TCPv6
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 */
#ifndef _INET6_CONNECTION_SOCK_H
#define _INET6_CONNECTION_SOCK_H

#include <linux/types.h>

struct in6_addr;
struct inet_bind_bucket;
struct request_sock;
struct sk_buff;
struct sock;
struct sockaddr;

int inet6_csk_bind_conflict(const struct sock *sk,
			    const struct inet_bind_bucket *tb, bool relax);

struct dst_entry *inet6_csk_route_req(const struct sock *sk, struct flowi6 *fl6<