/* * Copyright (C) 2014-2015 Red Hat, Inc. * * This file is part of LVM2. * * 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 Lesser General Public License v.2.1. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _LVM_LVMPOLLD_DATA_UTILS_H #define _LVM_LVMPOLLD_DATA_UTILS_H #include struct buffer; struct lvmpolld_state; enum poll_type { PVMOVE = 0, CONVERT, MERGE, MERGE_THIN, POLL_TYPE_MAX }; struct lvmpolld_cmd_stat { int retcode; int signal; }; struct lvmpolld_store { pthread_mutex_t lock; void *store; const char *name; unsigned active_polling_count; }; struct lvmpolld_lv { /* * accessing following vars doesn't * require struct lvmpolld_lv lock */ struct lvmpolld_state *ls; const enum poll_type type; const char *lvid; const char *lvmpolld_id; const char *devicesfile; const char *lvname; /* full vg/lv name */ const unsigned pdtimeout; /* in seconds */ const char *sinterval; const char *lvm_system_dir_env; struct lvmpolld_store *pdst; const char **cmdargv; const char **cmdenvp; /* only used by write */ pid_t cmd_pid; pthread_t tid; pthread_mutex_t lock; /* block of shared variables protected by lock */ struct lvmpolld_cmd_stat cmd_state; unsigned init_rq_count; /* for debuging purposes only */ unsigned polling_finished:1; /* no more updates */ unsigned error:1; /* unrecoverable error occured in lvmpolld */ }; typedef void (*lvmpolld_parse_output_fn_t) (struct lvmpolld_lv *pdlv, const char *line); /* TODO: replace with configuration option */ #define MIN_POLLING_TIMEOUT 60 struct lvmpolld_lv_state { unsigned error:1; unsigned polling_finished:1; struct lvmpolld_cmd_stat cmd_state; }; struct lvmpolld_thread_data { char *line; size_t line_size; int outpipe[2]; int errpipe[2]; FILE *fout; FILE *ferr; char buf[1024]; struct lvmpolld_lv *pdlv; }; char *construct_id(const char *sysdir, const char *lvid); /* LVMPOLLD_LV_T section */ /* only call with appropriate struct lvmpolld_store lock held */ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id, const char *vgname, const char *lvname, const char *sysdir, enum poll_type type, const char *sinterval, unsigned pdtimeout, struct lvmpolld_store *pdst, const char *devicesfile); /* only call with appropriate struct lvmpolld_store lock held */ void pdlv_destroy(struct lvmpolld_lv *pdlv); static inline void pdlv_lock(struct lvmpolld_lv *pdlv) { pthread_mutex_lock(&pdlv->lock); } static inline void pdlv_unlock(struct lvmpolld_lv *pdlv) { pthread_mutex_unlock(&pdlv->lock); } /* * no struct lvmpolld_lv lock required section */ static inline int pdlv_is_type(const struct lvmpolld_lv *pdlv, enum poll_type type) { return pdlv->type == type; } static inline unsigned pdlv_get_timeout(const struct lvmpolld_lv *pdlv) { return pdlv->pdtimeout; } static inline enum poll_type pdlv_get_type(const struct lvmpolld_lv *pdlv) { return pdlv->type; } unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv); struct lvmpolld_lv_state pdlv_get_status(struct lvmpolld_lv *pdlv); void pdlv_set_cmd_state(struct lvmpolld_lv *pdlv, const struct lvmpolld_cmd_stat *cmd_state); void pdlv_set_error(struct lvmpolld_lv *pdlv, unsigned error); void pdlv_set_polling_finished(struct lvmpolld_lv *pdlv, unsigned finished); /* * struct lvmpolld_lv lock required section */ static inline struct lvmpolld_cmd_stat pdlv_locked_cmd_state(const struct lvmpolld_lv *pdlv) { return pdlv->cmd_state; } static inline int pdlv_locked_polling_finished(const struct lvmpolld_lv *pdlv) { return pdlv->polling_finished; } static inline unsigned pdlv_locked_error(const struct lvmpolld_lv *pdlv) { return pdlv->error; } /* struct lvmpolld_store manipulation routines */ struct lvmpolld_store *pdst_init(const char *name); void pdst_destroy(struct lvmpolld_store *pdst); void pdst_locked_dump(const struct lvmpolld_store *pdst, struct buffer *buff); void pdst_locked_lock_all_pdlvs(const struct lvmpolld_store *pdst); void pdst_locked_unlock_all_pdlvs(const struct lvmpolld_store *pdst); void pdst_locked_destroy_all_pdlvs(const struct lvmpolld_store *pdst); void pdst_locked_send_cancel(const struct lvmpolld_store *pdst); static inline void pdst_lock(struct lvmpolld_store *pdst) { pthread_mutex_lock(&pdst->lock); } static inline void pdst_unlock(struct lvmpolld_store *pdst) { pthread_mutex_unlock(&pdst->lock); } static inline void pdst_locked_inc(struct lvmpolld_store *pdst) { pdst->active_polling_count++; } static inline void pdst_locked_dec(struct lvmpolld_store *pdst) { pdst->active_polling_count--; } static inline unsigned pdst_locked_get_active_count(const struct lvmpolld_store *pdst) { return pdst->active_polling_count; } static inline int pdst_locked_insert(struct lvmpolld_store *pdst, const char *key, struct lvmpolld_lv *pdlv) { return dm_hash_insert(pdst->store, key, pdlv); } static inline struct lvmpolld_lv *pdst_locked_lookup(struct lvmpolld_store *pdst, const char *key) { return dm_hash_lookup(pdst->store, key); } static inline void pdst_locked_remove(struct lvmpolld_store *pdst, const char *key) { dm_hash_remove(pdst->store, key); } struct lvmpolld_thread_data *lvmpolld_thread_data_constructor(struct lvmpolld_lv *pdlv); void lvmpolld_thread_data_destroy(void *thread_private); #endif /* _LVM_LVMPOLLD_DATA_UTILS_H */