ldlm_resource.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,062 行 · 第 1/3 页
C
1,062 行
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Copyright (C) 2002, 2003 Cluster File Systems, Inc. * Author: Phil Schwan <phil@clusterfs.com> * Author: Peter Braam <braam@clusterfs.com> * * This file is part of the Lustre file system, http://www.lustre.org * Lustre is a trademark of Cluster File Systems, Inc. * * You may have signed or agreed to another license before downloading * this software. If so, you are bound by the terms and conditions * of that agreement, and the following does not apply to you. See the * LICENSE file included with this distribution for more information. * * If you did not agree to a different license, then this copy of Lustre * is open source 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. * * In either case, 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 * license text for more details. */#define DEBUG_SUBSYSTEM S_LDLM#ifdef __KERNEL__# include <lustre_dlm.h>#else# include <liblustre.h>#endif#include <obd_class.h>#include "ldlm_internal.h"cfs_mem_cache_t *ldlm_resource_slab, *ldlm_lock_slab;atomic_t ldlm_srv_namespace_nr = ATOMIC_INIT(0);atomic_t ldlm_cli_namespace_nr = ATOMIC_INIT(0);struct semaphore ldlm_srv_namespace_lock;struct list_head ldlm_srv_namespace_list = CFS_LIST_HEAD_INIT(ldlm_srv_namespace_list);struct semaphore ldlm_cli_namespace_lock;struct list_head ldlm_cli_namespace_list = CFS_LIST_HEAD_INIT(ldlm_cli_namespace_list);cfs_proc_dir_entry_t *ldlm_type_proc_dir = NULL;cfs_proc_dir_entry_t *ldlm_ns_proc_dir = NULL;cfs_proc_dir_entry_t *ldlm_svc_proc_dir = NULL;#ifdef LPROCFSstatic int ldlm_proc_dump_ns(struct file *file, const char *buffer, unsigned long count, void *data){ ldlm_dump_all_namespaces(LDLM_NAMESPACE_SERVER, D_DLMTRACE); ldlm_dump_all_namespaces(LDLM_NAMESPACE_CLIENT, D_DLMTRACE); RETURN(count);}int ldlm_proc_setup(void){ int rc; struct lprocfs_vars list[] = { { "dump_namespaces", NULL, ldlm_proc_dump_ns, NULL }, { NULL }}; ENTRY; LASSERT(ldlm_ns_proc_dir == NULL); ldlm_type_proc_dir = lprocfs_register(OBD_LDLM_DEVICENAME, proc_lustre_root, NULL, NULL); if (IS_ERR(ldlm_type_proc_dir)) { CERROR("LProcFS failed in ldlm-init\n"); rc = PTR_ERR(ldlm_type_proc_dir); GOTO(err, rc); } ldlm_ns_proc_dir = lprocfs_register("namespaces", ldlm_type_proc_dir, NULL, NULL); if (IS_ERR(ldlm_ns_proc_dir)) { CERROR("LProcFS failed in ldlm-init\n"); rc = PTR_ERR(ldlm_ns_proc_dir); GOTO(err_type, rc); } ldlm_svc_proc_dir = lprocfs_register("services", ldlm_type_proc_dir, NULL, NULL); if (IS_ERR(ldlm_svc_proc_dir)) { CERROR("LProcFS failed in ldlm-init\n"); rc = PTR_ERR(ldlm_svc_proc_dir); GOTO(err_ns, rc); } rc = lprocfs_add_vars(ldlm_type_proc_dir, list, NULL); RETURN(0);err_ns: lprocfs_remove(&ldlm_ns_proc_dir);err_type: lprocfs_remove(&ldlm_type_proc_dir);err: ldlm_svc_proc_dir = NULL; RETURN(rc);}void ldlm_proc_cleanup(void){ if (ldlm_svc_proc_dir) lprocfs_remove(&ldlm_svc_proc_dir); if (ldlm_ns_proc_dir) lprocfs_remove(&ldlm_ns_proc_dir); if (ldlm_type_proc_dir) lprocfs_remove(&ldlm_type_proc_dir);}static int lprocfs_rd_lru_size(char *page, char **start, off_t off, int count, int *eof, void *data){ struct ldlm_namespace *ns = data; __u32 *nr = &ns->ns_max_unused; if (ns_connect_lru_resize(ns)) nr = &ns->ns_nr_unused; return lprocfs_rd_uint(page, start, off, count, eof, nr);}static int lprocfs_wr_lru_size(struct file *file, const char *buffer, unsigned long count, void *data){ struct ldlm_namespace *ns = data; char dummy[MAX_STRING_SIZE + 1], *end; unsigned long tmp; int lru_resize; dummy[MAX_STRING_SIZE] = '\0'; if (copy_from_user(dummy, buffer, MAX_STRING_SIZE)) return -EFAULT; if (count == 6 && memcmp(dummy, "clear", 5) == 0) { CDEBUG(D_DLMTRACE, "dropping all unused locks from namespace %s\n", ns->ns_name); if (ns_connect_lru_resize(ns)) { int canceled, unused = ns->ns_nr_unused; /* Try to cancel all @ns_nr_unused locks. */ canceled = ldlm_cancel_lru(ns, unused, LDLM_SYNC, LDLM_CANCEL_PASSED); if (canceled < unused) { CERROR("not all requested locks are canceled, " "requested: %d, canceled: %d\n", unused, canceled); return -EINVAL; } } else { tmp = ns->ns_max_unused; ns->ns_max_unused = 0; ldlm_cancel_lru(ns, 0, LDLM_SYNC, LDLM_CANCEL_PASSED); ns->ns_max_unused = tmp; } return count; } tmp = simple_strtoul(dummy, &end, 0); if (dummy == end) { CERROR("invalid value written\n"); return -EINVAL; } lru_resize = (tmp == 0); if (ns_connect_lru_resize(ns)) { if (!lru_resize) ns->ns_max_unused = (unsigned int)tmp; if (tmp > ns->ns_nr_unused) tmp = ns->ns_nr_unused; tmp = ns->ns_nr_unused - tmp; CDEBUG(D_DLMTRACE, "changing namespace %s unused locks from %u to %u\n", ns->ns_name, ns->ns_nr_unused, (unsigned int)tmp); ldlm_cancel_lru(ns, (unsigned int)tmp, LDLM_ASYNC, LDLM_CANCEL_PASSED); if (!lru_resize) { CDEBUG(D_DLMTRACE, "disable lru_resize for namespace %s\n", ns->ns_name); ns->ns_connect_flags &= ~OBD_CONNECT_LRU_RESIZE; } } else { CDEBUG(D_DLMTRACE, "changing namespace %s max_unused from %u to %u\n", ns->ns_name, ns->ns_max_unused, (unsigned int)tmp); ns->ns_max_unused = (unsigned int)tmp; ldlm_cancel_lru(ns, 0, LDLM_ASYNC, LDLM_CANCEL_PASSED); /* Make sure that originally lru resize was supported before * turning it on here. */ if (lru_resize && (ns->ns_orig_connect_flags & OBD_CONNECT_LRU_RESIZE)) { CDEBUG(D_DLMTRACE, "enable lru_resize for namespace %s\n", ns->ns_name); ns->ns_connect_flags |= OBD_CONNECT_LRU_RESIZE; } } return count;}void ldlm_proc_namespace(struct ldlm_namespace *ns){ struct lprocfs_vars lock_vars[2]; char lock_name[MAX_STRING_SIZE + 1]; LASSERT(ns != NULL); LASSERT(ns->ns_name != NULL); lock_name[MAX_STRING_SIZE] = '\0'; memset(lock_vars, 0, sizeof(lock_vars)); lock_vars[0].name = lock_name; snprintf(lock_name, MAX_STRING_SIZE, "%s/resource_count", ns->ns_name); lock_vars[0].data = &ns->ns_refcount; lock_vars[0].read_fptr = lprocfs_rd_atomic; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); snprintf(lock_name, MAX_STRING_SIZE, "%s/lock_count", ns->ns_name); lock_vars[0].data = &ns->ns_locks; lock_vars[0].read_fptr = lprocfs_rd_atomic; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); if (ns_is_client(ns)) { snprintf(lock_name, MAX_STRING_SIZE, "%s/lock_unused_count", ns->ns_name); lock_vars[0].data = &ns->ns_nr_unused; lock_vars[0].read_fptr = lprocfs_rd_uint; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); snprintf(lock_name, MAX_STRING_SIZE, "%s/lru_size", ns->ns_name); lock_vars[0].data = ns; lock_vars[0].read_fptr = lprocfs_rd_lru_size; lock_vars[0].write_fptr = lprocfs_wr_lru_size; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); snprintf(lock_name, MAX_STRING_SIZE, "%s/shrink_thumb", ns->ns_name); lock_vars[0].data = ns; lock_vars[0].read_fptr = lprocfs_rd_uint; lock_vars[0].write_fptr = lprocfs_wr_uint; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); snprintf(lock_name, MAX_STRING_SIZE, "%s/lru_max_age", ns->ns_name); lock_vars[0].data = &ns->ns_max_age; lock_vars[0].read_fptr = lprocfs_rd_uint; lock_vars[0].write_fptr = lprocfs_wr_uint; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); } else { snprintf(lock_name, MAX_STRING_SIZE, "%s/max_nolock_bytes", ns->ns_name); lock_vars[0].data = &ns->ns_max_nolock_size; lock_vars[0].read_fptr = lprocfs_rd_uint; lock_vars[0].write_fptr = lprocfs_wr_uint; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); snprintf(lock_name, MAX_STRING_SIZE, "%s/contention_seconds", ns->ns_name); lock_vars[0].data = &ns->ns_contention_time; lock_vars[0].read_fptr = lprocfs_rd_uint; lock_vars[0].write_fptr = lprocfs_wr_uint; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); snprintf(lock_name, MAX_STRING_SIZE, "%s/contended_locks", ns->ns_name); lock_vars[0].data = &ns->ns_contended_locks; lock_vars[0].read_fptr = lprocfs_rd_uint; lock_vars[0].write_fptr = lprocfs_wr_uint; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); }}#undef MAX_STRING_SIZE#else#define ldlm_proc_namespace(ns) do {} while (0)#endif /* LPROCFS */struct ldlm_namespace *ldlm_namespace_new(char *name, ldlm_side_t client, ldlm_appetite_t apt){ struct ldlm_namespace *ns = NULL; struct list_head *bucket; int rc, idx, namelen; ENTRY; rc = ldlm_get_ref(); if (rc) { CERROR("ldlm_get_ref failed: %d\n", rc); RETURN(NULL); } OBD_ALLOC_PTR(ns); if (!ns) GOTO(out_ref, NULL); OBD_VMALLOC(ns->ns_hash, sizeof(*ns->ns_hash) * RES_HASH_SIZE); if (!ns->ns_hash) GOTO(out_ns, NULL); namelen = strlen(name); OBD_ALLOC(ns->ns_name, namelen + 1); if (!ns->ns_name) GOTO(out_hash, NULL); ns->ns_shrink_thumb = LDLM_LOCK_SHRINK_THUMB; ns->ns_appetite = apt; strcpy(ns->ns_name, name); CFS_INIT_LIST_HEAD(&ns->ns_root_list); ns->ns_refcount = 0; ns->ns_client = client; spin_lock_init(&ns->ns_hash_lock); atomic_set(&ns->ns_locks, 0); ns->ns_resources = 0; cfs_waitq_init(&ns->ns_waitq); ns->ns_max_nolock_size = NS_DEFAULT_MAX_NOLOCK_BYTES; ns->ns_contention_time = NS_DEFAULT_CONTENTION_SECONDS; ns->ns_contended_locks = NS_DEFAULT_CONTENDED_LOCKS; for (bucket = ns->ns_hash + RES_HASH_SIZE - 1; bucket >= ns->ns_hash; bucket--) CFS_INIT_LIST_HEAD(bucket); CFS_INIT_LIST_HEAD(&ns->ns_unused_list); ns->ns_nr_unused = 0; ns->ns_max_unused = LDLM_DEFAULT_LRU_SIZE; ns->ns_max_age = LDLM_DEFAULT_MAX_ALIVE; spin_lock_init(&ns->ns_unused_lock); ns->ns_orig_connect_flags = 0; ns->ns_connect_flags = 0; ldlm_proc_namespace(ns); idx = atomic_read(ldlm_namespace_nr(client)); rc = ldlm_pool_init(&ns->ns_pool, ns, idx, client); if (rc) { CERROR("Can't initialize lock pool, rc %d\n", rc); GOTO(out_proc, rc); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?