1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#define DEBUG_SUBSYSTEM S_SEC
42
43#include "../../include/linux/libcfs/libcfs.h"
44
45#include "../include/obd_support.h"
46#include "../include/obd_class.h"
47#include "../include/lustre_net.h"
48#include "../include/lustre_sec.h"
49
50#include "ptlrpc_internal.h"
51
52#define SEC_GC_INTERVAL (30 * 60)
53
54static struct mutex sec_gc_mutex;
55static LIST_HEAD(sec_gc_list);
56static spinlock_t sec_gc_list_lock;
57
58static LIST_HEAD(sec_gc_ctx_list);
59static spinlock_t sec_gc_ctx_list_lock;
60
61static struct ptlrpc_thread sec_gc_thread;
62static atomic_t sec_gc_wait_del = ATOMIC_INIT(0);
63
64void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec)
65{
66 LASSERT(sec->ps_policy->sp_cops->gc_ctx);
67 LASSERT(sec->ps_gc_interval > 0);
68 LASSERT(list_empty(&sec->ps_gc_list));
69
70 sec->ps_gc_next = ktime_get_real_seconds() + sec->ps_gc_interval;
71
72 spin_lock(&sec_gc_list_lock);
73 list_add_tail(&sec_gc_list, &sec->ps_gc_list);
74 spin_unlock(&sec_gc_list_lock);
75
76 CDEBUG(D_SEC, "added sec %p(%s)\n", sec, sec->ps_policy->sp_name);
77}
78EXPORT_SYMBOL(sptlrpc_gc_add_sec);
79
80void sptlrpc_gc_del_sec(struct ptlrpc_sec *sec)
81{
82 if (list_empty(&sec->ps_gc_list))
83 return;
84
85 might_sleep();
86
87
88 atomic_inc(&sec_gc_wait_del);
89
90 spin_lock(&sec_gc_list_lock);
91 list_del_init(&sec->ps_gc_list);
92 spin_unlock(&sec_gc_list_lock);
93
94
95 mutex_lock(&sec_gc_mutex);
96 mutex_unlock(&sec_gc_mutex);
97
98 atomic_dec(&sec_gc_wait_del);
99
100 CDEBUG(D_SEC, "del sec %p(%s)\n", sec, sec->ps_policy->sp_name);
101}
102EXPORT_SYMBOL(sptlrpc_gc_del_sec);
103
104static void sec_process_ctx_list(void)
105{
106 struct ptlrpc_cli_ctx *ctx;
107
108 spin_lock(&sec_gc_ctx_list_lock);
109
110 while (!list_empty(&sec_gc_ctx_list)) {
111 ctx = list_entry(sec_gc_ctx_list.next,
112 struct ptlrpc_cli_ctx, cc_gc_chain);
113 list_del_init(&ctx->cc_gc_chain);
114 spin_unlock(&sec_gc_ctx_list_lock);
115
116 LASSERT(ctx->cc_sec);
117 LASSERT(atomic_read(&ctx->cc_refcount) == 1);
118 CDEBUG(D_SEC, "gc pick up ctx %p(%u->%s)\n",
119 ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
120 sptlrpc_cli_ctx_put(ctx, 1);
121
122 spin_lock(&sec_gc_ctx_list_lock);
123 }
124
125 spin_unlock(&sec_gc_ctx_list_lock);
126}
127
128static void sec_do_gc(struct ptlrpc_sec *sec)
129{
130 LASSERT(sec->ps_policy->sp_cops->gc_ctx);
131
132 if (unlikely(sec->ps_gc_next == 0)) {
133 CDEBUG(D_SEC, "sec %p(%s) has 0 gc time\n",
134 sec, sec->ps_policy->sp_name);
135 return;
136 }
137
138 CDEBUG(D_SEC, "check on sec %p(%s)\n", sec, sec->ps_policy->sp_name);
139
140 if (sec->ps_gc_next > ktime_get_real_seconds())
141 return;
142
143 sec->ps_policy->sp_cops->gc_ctx(sec);
144 sec->ps_gc_next = ktime_get_real_seconds() + sec->ps_gc_interval;
145}
146
147static int sec_gc_main(void *arg)
148{
149 struct ptlrpc_thread *thread = arg;
150 struct l_wait_info lwi;
151
152 unshare_fs_struct();
153
154
155 thread_set_flags(thread, SVC_RUNNING);
156 wake_up(&thread->t_ctl_waitq);
157
158 while (1) {
159 struct ptlrpc_sec *sec;
160
161 thread_clear_flags(thread, SVC_SIGNAL);
162 sec_process_ctx_list();
163again:
164
165
166
167
168
169
170
171 mutex_lock(&sec_gc_mutex);
172 list_for_each_entry(sec, &sec_gc_list, ps_gc_list) {
173
174
175
176 if (atomic_read(&sec_gc_wait_del)) {
177 CDEBUG(D_SEC, "deletion pending, start over\n");
178 mutex_unlock(&sec_gc_mutex);
179 goto again;
180 }
181
182 sec_do_gc(sec);
183 }
184 mutex_unlock(&sec_gc_mutex);
185
186
187 sec_process_ctx_list();
188
189 lwi = LWI_TIMEOUT(SEC_GC_INTERVAL * HZ, NULL, NULL);
190 l_wait_event(thread->t_ctl_waitq,
191 thread_is_stopping(thread) ||
192 thread_is_signal(thread),
193 &lwi);
194
195 if (thread_test_and_clear_flags(thread, SVC_STOPPING))
196 break;
197 }
198
199 thread_set_flags(thread, SVC_STOPPED);
200 wake_up(&thread->t_ctl_waitq);
201 return 0;
202}
203
204int sptlrpc_gc_init(void)
205{
206 struct l_wait_info lwi = { 0 };
207 struct task_struct *task;
208
209 mutex_init(&sec_gc_mutex);
210 spin_lock_init(&sec_gc_list_lock);
211 spin_lock_init(&sec_gc_ctx_list_lock);
212
213
214 memset(&sec_gc_thread, 0, sizeof(sec_gc_thread));
215 init_waitqueue_head(&sec_gc_thread.t_ctl_waitq);
216
217 task = kthread_run(sec_gc_main, &sec_gc_thread, "sptlrpc_gc");
218 if (IS_ERR(task)) {
219 CERROR("can't start gc thread: %ld\n", PTR_ERR(task));
220 return PTR_ERR(task);
221 }
222
223 l_wait_event(sec_gc_thread.t_ctl_waitq,
224 thread_is_running(&sec_gc_thread), &lwi);
225 return 0;
226}
227
228void sptlrpc_gc_fini(void)
229{
230 struct l_wait_info lwi = { 0 };
231
232 thread_set_flags(&sec_gc_thread, SVC_STOPPING);
233 wake_up(&sec_gc_thread.t_ctl_waitq);
234
235 l_wait_event(sec_gc_thread.t_ctl_waitq,
236 thread_is_stopped(&sec_gc_thread), &lwi);
237}
238