upcall_cache.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 519 行 · 第 1/2 页
C
519 行
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Supplementary groups cache. * * Copyright (c) 2004 Cluster File Systems, Inc. * * This file is part of Lustre, http://www.lustre.org. * * Lustre is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * Lustre is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Lustre; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#define DEBUG_SUBSYSTEM S_SEC#ifndef AUTOCONF_INCLUDED#include <linux/config.h>#endif#include <linux/module.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/kmod.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/errno.h>#include <linux/version.h>#include <linux/unistd.h>#include <asm/system.h>#include <asm/uaccess.h>#include <linux/fs.h>#include <linux/stat.h>#include <asm/uaccess.h>#include <linux/slab.h>#include <obd_support.h>#include <lustre_lib.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4)struct group_info *groups_alloc(int ngroups){ struct group_info *ginfo; LASSERT(ngroups <= NGROUPS_SMALL); OBD_ALLOC(ginfo, sizeof(*ginfo) + 1 * sizeof(gid_t *)); if (!ginfo) return NULL; ginfo->ngroups = ngroups; ginfo->nblocks = 1; ginfo->blocks[0] = ginfo->small_block; atomic_set(&ginfo->usage, 1); return ginfo;}void groups_free(struct group_info *ginfo){ LASSERT(ginfo->ngroups <= NGROUPS_SMALL); LASSERT(ginfo->nblocks == 1); LASSERT(ginfo->blocks[0] == ginfo->small_block); OBD_FREE(ginfo, sizeof(*ginfo) + 1 * sizeof(gid_t *));}#endifstatic struct upcall_cache_entry *alloc_entry(__u64 key){ struct upcall_cache_entry *entry; OBD_ALLOC(entry, sizeof(*entry)); if (!entry) return NULL; UC_CACHE_SET_NEW(entry); INIT_LIST_HEAD(&entry->ue_hash); entry->ue_key = key; atomic_set(&entry->ue_refcount, 0); init_waitqueue_head(&entry->ue_waitq); return entry;}/* protected by hash lock */static void free_entry(struct upcall_cache_entry *entry){ if (entry->ue_group_info) groups_free(entry->ue_group_info); list_del(&entry->ue_hash); CDEBUG(D_OTHER, "destroy cache entry %p for key "LPU64"\n", entry, entry->ue_key); OBD_FREE(entry, sizeof(*entry));}static void get_entry(struct upcall_cache_entry *entry){ atomic_inc(&entry->ue_refcount);}static void put_entry(struct upcall_cache_entry *entry){ if (atomic_dec_and_test(&entry->ue_refcount) && (UC_CACHE_IS_INVALID(entry) || UC_CACHE_IS_EXPIRED(entry))) { free_entry(entry); }}static int check_unlink_entry(struct upcall_cache_entry *entry){ if (UC_CACHE_IS_VALID(entry) && time_before(jiffies, entry->ue_expire)) return 0; if (UC_CACHE_IS_ACQUIRING(entry)) { if (time_before(jiffies, entry->ue_acquire_expire)) return 0; UC_CACHE_SET_EXPIRED(entry); wake_up_all(&entry->ue_waitq); } else if (!UC_CACHE_IS_INVALID(entry)) { UC_CACHE_SET_EXPIRED(entry); } list_del_init(&entry->ue_hash); if (!atomic_read(&entry->ue_refcount)) free_entry(entry); return 1;}static int refresh_entry(struct upcall_cache *hash, struct upcall_cache_entry *entry){ char *argv[4]; char *envp[3]; char keystr[16]; int rc; ENTRY; snprintf(keystr, 16, LPU64, entry->ue_key); CDEBUG(D_INFO, "The groups upcall is: %s \n", hash->uc_upcall); argv[0] = hash->uc_upcall; argv[1] = hash->uc_name; argv[2] = keystr; argv[3] = NULL; envp[0] = "HOME=/"; envp[1] = "PATH=/sbin:/usr/sbin"; envp[2] = NULL; rc = USERMODEHELPER(argv[0], argv, envp); if (rc < 0) { CERROR("%s: error invoking getgroups upcall %s %s %s: rc %d; " "check /proc/fs/lustre/mds/%s/group_upcall\n", hash->uc_name, argv[0], argv[1], argv[2], rc, argv[1]); } else { CDEBUG(D_HA, "%s: invoked upcall %s %s %s\n", hash->uc_name, argv[0], argv[1], argv[2]); rc = 0; } RETURN(rc);}static int entry_set_group_info(struct upcall_cache_entry *entry, __u32 primary, __u32 ngroups, __u32 *groups){ struct group_info *ginfo; int i, j; ENTRY;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) if (ngroups > NGROUPS) ngroups = NGROUPS;#endif if (ngroups > NGROUPS_MAX) { CERROR("using first %d supplementary groups for uid "LPU64"\n", NGROUPS_MAX, entry->ue_key); ngroups = NGROUPS_MAX; } ginfo = groups_alloc(ngroups); if (!ginfo) { CERROR("uid "LPU64" update can't alloc ginfo for %d groups\n", entry->ue_key, ngroups); RETURN(-ENOMEM); } entry->ue_group_info = ginfo; entry->ue_primary = primary; for (i = 0; i < ginfo->nblocks; i++) { int cp_count = min(NGROUPS_PER_BLOCK, (int)ngroups); int off = i * NGROUPS_PER_BLOCK; for (j = 0; j < cp_count; j++) ginfo->blocks[i][j] = groups[off + j]; ngroups -= cp_count; } RETURN(0);}struct upcall_cache_entry *upcall_cache_get_entry(struct upcall_cache *hash, __u64 key, __u32 primary, __u32 ngroups, __u32 *groups){ struct upcall_cache_entry *entry = NULL, *new = NULL, *next; struct list_head *head; wait_queue_t wait; int rc, found; ENTRY; LASSERT(hash); if (strcmp(hash->uc_upcall, "NONE") == 0) { new = alloc_entry(key); if (!new) { CERROR("fail to alloc entry\n"); RETURN(NULL); } get_entry(new); /* We have to sort the groups for 2.6 kernels */ LASSERT(ngroups <= 2); if (ngroups == 2 && groups[1] == -1) ngroups--;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,4) /* 2.6 needs groups array sorted */ if (ngroups == 2 && groups[0] > groups[1]) { __u32 tmp = groups[1]; groups[1] = groups[0]; groups[0] = tmp; }#endif if (ngroups > 0 && groups[0] == -1) { groups[0] = groups[1]; ngroups--; } rc = entry_set_group_info(new, primary, ngroups, groups); /* We can't cache this entry as it only has a subset of * the user's groups, as sent in suppgid1, suppgid2. */ UC_CACHE_SET_EXPIRED(new); RETURN(new); } head = &hash->uc_hashtable[UC_CACHE_HASH_INDEX(key)];find_again: found = 0; spin_lock(&hash->uc_lock);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?