1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2007 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 # define EXPORT_SYMTAB
25 #define DEBUG_SUBSYSTEM S_SEC
28 #include <liblustre.h>
31 #include <obd_support.h>
32 #include <obd_class.h>
33 #include <lustre_net.h>
34 #include <lustre_sec.h>
36 #define SEC_GC_INTERVAL (30 * 60)
40 static DECLARE_MUTEX(sec_gc_mutex);
41 static LIST_HEAD(sec_gc_list);
42 static spinlock_t sec_gc_list_lock = SPIN_LOCK_UNLOCKED;
44 static struct ptlrpc_thread sec_gc_thread;
45 static atomic_t sec_gc_wait_del = ATOMIC_INIT(0);
47 void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec)
49 CWARN("add sec %p(%s)\n", sec, sec->ps_policy->sp_name);
50 if (!list_empty(&sec->ps_gc_list)) {
51 CERROR("sec %p(%s) already in gc list\n",
52 sec, sec->ps_policy->sp_name);
56 spin_lock(&sec_gc_list_lock);
57 list_add_tail(&sec_gc_list, &sec->ps_gc_list);
58 spin_unlock(&sec_gc_list_lock);
61 void sptlrpc_gc_del_sec(struct ptlrpc_sec *sec)
63 CWARN("del sec %p(%s)\n", sec, sec->ps_policy->sp_name);
64 if (list_empty(&sec->ps_gc_list))
69 spin_lock(&sec_gc_list_lock);
70 list_del_init(&sec->ps_gc_list);
71 spin_unlock(&sec_gc_list_lock);
74 atomic_inc(&sec_gc_wait_del);
75 mutex_down(&sec_gc_mutex);
76 mutex_up(&sec_gc_mutex);
77 atomic_dec(&sec_gc_wait_del);
80 static void sec_do_gc(struct ptlrpc_sec *sec)
82 cfs_time_t now = cfs_time_current_sec();
84 if (unlikely(sec->ps_gc_next == 0)) {
85 CWARN("sec %p(%s) has 0 gc time\n",
86 sec, sec->ps_policy->sp_name);
90 if (unlikely(sec->ps_policy->sp_cops->gc_ctx == NULL)) {
91 CWARN("sec %p(%s) is not prepared for gc\n",
92 sec, sec->ps_policy->sp_name);
96 CWARN("check on sec %p(%s)\n", sec, sec->ps_policy->sp_name);
97 if (time_after(sec->ps_gc_next, now))
100 sec->ps_policy->sp_cops->gc_ctx(sec);
101 sec->ps_gc_next = now + sec->ps_gc_interval;
104 static int sec_gc_main(void *arg)
106 struct ptlrpc_thread *thread = (struct ptlrpc_thread *) arg;
107 struct l_wait_info lwi;
109 cfs_daemonize("sptlrpc_ctx_gc");
111 /* Record that the thread is running */
112 thread->t_flags = SVC_RUNNING;
113 cfs_waitq_signal(&thread->t_ctl_waitq);
116 struct ptlrpc_sec *sec, *next;
119 mutex_down(&sec_gc_mutex);
120 list_for_each_entry_safe(sec, next, &sec_gc_list, ps_gc_list) {
122 * if someone is waiting to be deleted, let it
123 * proceed as soon as possible.
125 if (atomic_read(&sec_gc_wait_del)) {
126 CWARN("deletion pending, retry\n");
127 mutex_up(&sec_gc_mutex);
133 mutex_up(&sec_gc_mutex);
135 lwi = LWI_TIMEOUT(SEC_GC_INTERVAL * HZ, NULL, NULL);
136 l_wait_event(thread->t_ctl_waitq,
137 thread->t_flags & SVC_STOPPING,
140 if (thread->t_flags & SVC_STOPPING) {
141 thread->t_flags &= ~SVC_STOPPING;
146 thread->t_flags = SVC_STOPPED;
147 cfs_waitq_signal(&thread->t_ctl_waitq);
151 int sptlrpc_gc_start_thread(void)
153 struct l_wait_info lwi = { 0 };
156 /* initialize thread control */
157 memset(&sec_gc_thread, 0, sizeof(sec_gc_thread));
158 cfs_waitq_init(&sec_gc_thread.t_ctl_waitq);
160 rc = cfs_kernel_thread(sec_gc_main, &sec_gc_thread,
161 CLONE_VM | CLONE_FILES);
163 CERROR("can't start gc thread: %d\n", rc);
167 l_wait_event(sec_gc_thread.t_ctl_waitq,
168 sec_gc_thread.t_flags & SVC_RUNNING, &lwi);
172 void sptlrpc_gc_stop_thread(void)
174 struct l_wait_info lwi = { 0 };
176 sec_gc_thread.t_flags = SVC_STOPPING;
177 cfs_waitq_signal(&sec_gc_thread.t_ctl_waitq);
179 l_wait_event(sec_gc_thread.t_ctl_waitq,
180 sec_gc_thread.t_flags & SVC_STOPPED, &lwi);
183 #else /* !__KERNEL__ */
185 void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec)
188 void sptlrpc_gc_del_sec(struct ptlrpc_sec *sec)
191 int sptlrpc_gc_start_thread(void)
195 void sptlrpc_gc_stop_thread(void)
199 #endif /* __KERNEL__ */