X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=libcfs%2Flibcfs%2Fkernel_user_comm.c;h=fc92e2f736758ddb8817c106f03d4e07bd2224d7;hb=df1d59429cbfd1ea2464e863458b6a4a268e516b;hp=7ac1f9e74f2ae314314fe93307bb46c77b1eedcf;hpb=d70db3335f52cc49f5e01858d27b0ccd61036c62;p=fs%2Flustre-release.git diff --git a/libcfs/libcfs/kernel_user_comm.c b/libcfs/libcfs/kernel_user_comm.c index 7ac1f9e..fc92e2f 100644 --- a/libcfs/libcfs/kernel_user_comm.c +++ b/libcfs/libcfs/kernel_user_comm.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,8 +24,10 @@ * GPL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2012, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -40,7 +40,7 @@ */ #define DEBUG_SUBSYSTEM S_CLASS -#define D_KUC 0 +#define D_KUC D_OTHER #include @@ -54,23 +54,30 @@ */ int libcfs_ukuc_start(lustre_kernelcomm *link, int group) { - int pfd[2]; + int pfd[2]; - if (pipe(pfd) < 0) - return -errno; + link->lk_rfd = link->lk_wfd = LK_NOFD; - link->lk_rfd = pfd[0]; - link->lk_wfd = pfd[1]; - link->lk_group = group; - link->lk_uid = getpid(); - return 0; + if (pipe(pfd) < 0) + return -errno; + + memset(link, 0, sizeof(*link)); + link->lk_rfd = pfd[0]; + link->lk_wfd = pfd[1]; + link->lk_group = group; + link->lk_uid = getpid(); + return 0; } int libcfs_ukuc_stop(lustre_kernelcomm *link) { - if (link->lk_wfd > 0) - close(link->lk_wfd); - return close(link->lk_rfd); + int rc; + + if (link->lk_wfd != LK_NOFD) + close(link->lk_wfd); + rc = close(link->lk_rfd); + link->lk_rfd = link->lk_wfd = LK_NOFD; + return rc; } #define lhsz sizeof(*kuch) @@ -79,7 +86,7 @@ int libcfs_ukuc_stop(lustre_kernelcomm *link) * Allocates memory, returns handle * * @param link Private descriptor for pipe/socket. - * @param buf Buffer to read into + * @param buf Buffer to read into, must include size for kuc_hdr * @param maxsize Maximum message size allowed * @param transport Only listen to messages on this transport * (and the generic transport) @@ -104,7 +111,7 @@ int libcfs_ukuc_msg_get(lustre_kernelcomm *link, char *buf, int maxsize, } kuch = (struct kuc_hdr *)buf; - CDEBUG(D_KUC, " Received message mg=%x t=%d m=%d l=%d\n", + CDEBUG(D_KUC, "Received message mg=%x t=%d m=%d l=%d\n", kuch->kuc_magic, kuch->kuc_transport, kuch->kuc_msgtype, kuch->kuc_msglen); @@ -151,7 +158,7 @@ int libcfs_ukuc_msg_get(lustre_kernelcomm *link, char *buf, int maxsize, * @param payload Payload data. First field of payload is always * struct kuc_hdr */ -int libcfs_kkuc_msg_put(cfs_file_t *filp, void *payload) +int libcfs_kkuc_msg_put(struct file *filp, void *payload) { struct kuc_hdr *kuch = (struct kuc_hdr *)payload; int rc = -ENOSYS; @@ -165,7 +172,11 @@ int libcfs_kkuc_msg_put(cfs_file_t *filp, void *payload) } #ifdef __KERNEL__ - rc = cfs_user_write(filp, (char *)payload, kuch->kuc_msglen, 0); + { + loff_t offset = 0; + rc = filp_user_write(filp, payload, kuch->kuc_msglen, + &offset); + } #endif if (rc < 0) @@ -175,27 +186,30 @@ int libcfs_kkuc_msg_put(cfs_file_t *filp, void *payload) return rc; } -CFS_EXPORT_SYMBOL(libcfs_kkuc_msg_put); +EXPORT_SYMBOL(libcfs_kkuc_msg_put); /* Broadcast groups are global across all mounted filesystems; * i.e. registering for a group on 1 fs will get messages for that * group from any fs */ -/** A single group reigstration has a uid and a file pointer */ +/** A single group registration has a uid and a file pointer */ struct kkuc_reg { - cfs_list_t kr_chain; - int kr_uid; - cfs_file_t *kr_fp; + struct list_head kr_chain; + int kr_uid; + struct file *kr_fp; + void *kr_data; }; -static cfs_list_t kkuc_groups[KUC_GRP_MAX+1] = {}; + +static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; /* Protect message sending against remove and adds */ -static CFS_DECLARE_RWSEM(kg_sem); +static DECLARE_RWSEM(kg_sem); /** Add a receiver to a broadcast group * @param filp pipe to write into - * @param uid identidier for this receiver + * @param uid identifier for this receiver * @param group group number + * @param data user data */ -int libcfs_kkuc_group_add(cfs_file_t *filp, int uid, int group) +int libcfs_kkuc_group_add(struct file *filp, int uid, int group, void *data) { struct kkuc_reg *reg; @@ -209,26 +223,27 @@ int libcfs_kkuc_group_add(cfs_file_t *filp, int uid, int group) return -EBADF; /* freed in group_rem */ - reg = cfs_alloc(sizeof(*reg), 0); + reg = kmalloc(sizeof(*reg), 0); if (reg == NULL) return -ENOMEM; reg->kr_fp = filp; reg->kr_uid = uid; + reg->kr_data = data; - cfs_down_write(&kg_sem); - if (kkuc_groups[group].next == NULL) - CFS_INIT_LIST_HEAD(&kkuc_groups[group]); - cfs_list_add(®->kr_chain, &kkuc_groups[group]); - cfs_up_write(&kg_sem); + down_write(&kg_sem); + if (kkuc_groups[group].next == NULL) + INIT_LIST_HEAD(&kkuc_groups[group]); + list_add(®->kr_chain, &kkuc_groups[group]); + up_write(&kg_sem); - CDEBUG(D_KUC, "Added uid=%d fp=%p to group %d\n", uid, filp, group); + CDEBUG(D_KUC, "Added uid=%d fp=%p to group %d\n", uid, filp, group); - return 0; + return 0; } -CFS_EXPORT_SYMBOL(libcfs_kkuc_group_add); +EXPORT_SYMBOL(libcfs_kkuc_group_add); -int libcfs_kkuc_group_rem(int uid, int group) +int libcfs_kkuc_group_rem(int uid, int group, void **pdata) { struct kkuc_reg *reg, *next; ENTRY; @@ -247,37 +262,88 @@ int libcfs_kkuc_group_rem(int uid, int group) libcfs_kkuc_group_put(group, &lh); } - cfs_down_write(&kg_sem); - cfs_list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) { - if ((uid == 0) || (uid == reg->kr_uid)) { - cfs_list_del(®->kr_chain); - CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", - reg->kr_uid, reg->kr_fp, group); - cfs_put_file(reg->kr_fp); - cfs_free(reg); - } - } - cfs_up_write(&kg_sem); - - RETURN(0); + down_write(&kg_sem); + list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) { + if ((uid == 0) || (uid == reg->kr_uid)) { + list_del(®->kr_chain); + CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", + reg->kr_uid, reg->kr_fp, group); + if (reg->kr_fp != NULL) + fput(reg->kr_fp); + if (pdata != NULL) + *pdata = reg->kr_data; + kfree(reg); + } + } + up_write(&kg_sem); + + RETURN(0); } -CFS_EXPORT_SYMBOL(libcfs_kkuc_group_rem); +EXPORT_SYMBOL(libcfs_kkuc_group_rem); int libcfs_kkuc_group_put(int group, void *payload) { - struct kkuc_reg *reg; - int rc = 0; - ENTRY; - - cfs_down_read(&kg_sem); - cfs_list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { - rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); - } - cfs_up_read(&kg_sem); + struct kkuc_reg *reg; + int rc = 0; + int one_success = 0; + ENTRY; + + down_read(&kg_sem); + list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { + if (reg->kr_fp != NULL) { + rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); + if (rc == 0) + one_success = 1; + else if (rc == -EPIPE) { + fput(reg->kr_fp); + reg->kr_fp = NULL; + } + } + } + up_read(&kg_sem); + + /* don't return an error if the message has been delivered + * at least to one agent */ + if (one_success) + rc = 0; + + RETURN(rc); +} +EXPORT_SYMBOL(libcfs_kkuc_group_put); - RETURN(rc); +/** + * Calls a callback function for each link of the given kuc group. + * @param group the group to call the function on. + * @param cb_func the function to be called. + * @param cb_arg extra argument to be passed to the callback function. + */ +int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, + void *cb_arg) +{ + struct kkuc_reg *reg; + int rc = 0; + ENTRY; + + if (group > KUC_GRP_MAX) { + CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); + RETURN(-EINVAL); + } + + /* no link for this group */ + if (kkuc_groups[group].next == NULL) + RETURN(0); + + down_read(&kg_sem); + list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { + if (reg->kr_fp != NULL) { + rc = cb_func(reg->kr_data, cb_arg); + } + } + up_read(&kg_sem); + + RETURN(rc); } -CFS_EXPORT_SYMBOL(libcfs_kkuc_group_put); +EXPORT_SYMBOL(libcfs_kkuc_group_foreach); #endif /* LUSTRE_UTILS */