Whamcloud - gitweb
- b_hd_audit landing
[fs/lustre-release.git] / lustre / smfs / audit_transfer.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/smfs/audit_transfer.c
5  *
6  *  Copyright (C) 2004 Cluster File Systems, Inc.
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23 #ifndef EXPORT_SYMTAB
24 # define EXPORT_SYMTAB
25 #endif
26
27 #define DEBUG_SUBSYSTEM S_SM
28
29 #include <linux/fs.h>
30 #include <linux/slab.h>
31 #include <linux/obd_class.h>
32 #include <linux/obd_support.h>
33 #include <linux/lustre_lib.h>
34 #include <linux/lustre_idl.h>
35 #include <linux/lustre_fsfilt.h>
36 #include <linux/lustre_smfs.h>
37 #include <linux/lustre_audit.h>
38 #include <linux/lustre_log.h>
39 #include "smfs_internal.h"
40
41 struct transfer_item {
42         struct llog_handle      *ti_llh;
43         struct list_head        ti_link;
44         void * id2name;
45 };
46
47 #define TRANSFERD_STOP          0
48 struct transferd_ctl {
49         unsigned long           tc_flags;
50         wait_queue_head_t       tc_waitq;
51         struct completion       tc_starting;
52         struct completion       tc_stopping;
53
54         struct list_head        tc_list;
55         spinlock_t              tc_lock;
56 };
57
58 static struct transferd_ctl transferd_tc;
59 static DECLARE_MUTEX(transferd_sem);
60 static int transferd_users = 0;
61 char *buf = NULL;
62
63 int audit_notify(struct llog_handle *llh, void * arg)
64 {
65         struct transfer_item *ti;
66         ENTRY;
67
68         down(&transferd_sem);
69         if (transferd_users == 0) {
70                 up(&transferd_sem);
71                 RETURN(0);
72         }
73         up(&transferd_sem);
74
75         if (test_bit(TRANSFERD_STOP, &transferd_tc.tc_flags)) {
76                 CDEBUG(D_INFO, "transfer daemon stopped\n");
77                 RETURN(0);
78         }
79
80         OBD_ALLOC(ti, sizeof(*ti));
81         if (ti == NULL)
82                 RETURN(-ENOMEM);
83         
84         INIT_LIST_HEAD(&ti->ti_link);
85         ti->ti_llh = llh;
86         ti->id2name = arg;
87
88         spin_lock(&transferd_tc.tc_lock);
89         list_add_tail(&ti->ti_link, &transferd_tc.tc_list);
90         spin_unlock(&transferd_tc.tc_lock);
91
92         wake_up(&transferd_tc.tc_waitq);
93
94         RETURN(0);
95 }
96                                                                                                                                                
97 const char *opstr[AUDIT_MAX] = {
98         [AUDIT_NONE]     "null",
99         [AUDIT_CREATE]   "create",
100         [AUDIT_LINK]     "link",
101         [AUDIT_UNLINK]   "unlink",
102         [AUDIT_SYMLINK]  "symlink",
103         [AUDIT_RENAME]   "rename",
104         [AUDIT_SETATTR]  "setattr",
105         [AUDIT_WRITE]    "write",
106         [AUDIT_READ]     "read",
107         [AUDIT_OPEN]     "open",
108         [AUDIT_STAT]     "stat",
109         [AUDIT_MMAP]     "mmap",
110         [AUDIT_READLINK] "readlink",
111         [AUDIT_READDIR]  "readdir",
112 };
113
114 #define construct_header(buf, size, rec)                                \
115         snprintf(buf, size,                                             \
116         "AUDIT [%u] [nid: "LPU64" uid: %u gid: %u rc: %d] [%s] ",       \
117         rec->time, rec->nid, rec->uid, rec->gid, (__s16)rec->result,      \
118         opstr[rec->opcode]);
119
120 #define REC2ID(rec, id) {                                       \
121         id_ino(id) = rec->au_num;                               \
122         id_gen(id) = rec->au_gen;                               \
123         id_type(id) = rec->au_type;                             \
124         id_fid(id) = rec->au_fid;                               \
125         id_group(id) = rec->au_mds;                             \
126 }
127
128 static int 
129 transfer_record(struct obd_device *obd, struct audit_record *rec, int type, void * data)
130 {
131         struct audit_id_record *id_rec = 
132                 (struct audit_id_record *)((char *)rec + sizeof(*rec));
133         struct audit_name_record *name_rec = NULL;
134         int (*audit_id2name)(struct obd_device *obd, char **name, 
135                      int *namelen, struct lustre_id *id) = data;
136
137         int n, rc = 0;
138         ENTRY;
139
140         CDEBUG(D_INFO, "transfer %s\n", opstr[rec->opcode]);
141
142         memset(buf, 0, PAGE_SIZE);
143         n = construct_header(buf, PAGE_SIZE, rec);
144         if (n < 0)
145                 RETURN(n);
146                 
147         switch (rec->opcode)
148         {
149                 case AUDIT_UNLINK:
150                         if (type != SMFS_AUDIT_NAME_REC)
151                                 break;
152                 case AUDIT_LINK:
153                 case AUDIT_RENAME:
154                         id_rec++;
155                 default:
156                         break;
157         }
158         
159         if (audit_id2name) {
160                 char *name = NULL;
161                 struct lustre_id id;
162                 int namelen = 0;
163         
164                 REC2ID(id_rec, &id);
165                 rc = audit_id2name(obd, &name, &namelen, &id);
166                 if (rc < 0) {
167                         strncat(buf, "unknown", PAGE_SIZE - n);
168                         n += strlen("unknown");
169                 } else if (namelen == 0) {
170                         //root itself
171                         if (type != SMFS_AUDIT_NAME_REC)
172                                 strcat(buf, "/");
173                 } else {
174                         strncat(buf, name, PAGE_SIZE - n);
175                         n += namelen;
176                         OBD_FREE(name, namelen);
177                 } 
178         }
179         
180         if (type == SMFS_AUDIT_NAME_REC) {
181                 name_rec = (struct audit_name_record *)((char *)(++id_rec));
182                 strncat(buf, "/", 1);
183                 n += 1;
184                 strncat(buf, name_rec->name, PAGE_SIZE - n);
185         }
186         
187         CDEBUG(D_INFO, "%s\n", buf);
188
189         printk("%s\n", buf);
190
191         RETURN(rc);
192 }
193
194 static int transfer_cb(struct llog_handle *llh, struct llog_rec_hdr *rec,
195                        void *data)
196 {
197         struct obd_device *obd = llh->lgh_ctxt->loc_obd;
198         struct audit_record *ad_rec;
199         int rc = 0;
200         ENTRY;
201         
202         if (!(le32_to_cpu(llh->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
203                 CERROR("log is not plain\n");
204                 RETURN(-EINVAL);
205         }
206         if (rec->lrh_type != cpu_to_le32(SMFS_AUDIT_GEN_REC) &&
207             rec->lrh_type != cpu_to_le32(SMFS_AUDIT_NAME_REC)) {
208                 CERROR("log record type error\n");
209                 RETURN(-EINVAL);
210         }
211
212         ad_rec = (struct audit_record *)((char *)rec + sizeof(*rec));
213         
214         LASSERT(ad_rec->opcode < AUDIT_MAX);
215
216         rc = transfer_record(obd, ad_rec, rec->lrh_type, data);
217         if (rc)
218                 CERROR("transfer record failed! rc:%d\n", rc);
219
220         RETURN(LLOG_DEL_RECORD);
221 }
222
223 static int audit_transfer(struct transfer_item *ti)
224 {
225         struct llog_handle *llh = ti->ti_llh;
226         int rc = 0;
227         ENTRY;
228
229         rc = llog_cat_process(llh, (llog_cb_t)&transfer_cb, ti->id2name);
230         if (rc)
231                 CERROR("process catalog log failed: rc(%d)\n", rc);
232
233         RETURN(0);
234 }
235
236 static int transferd_check(struct transferd_ctl *tc)
237 {
238         int rc = 0;
239         ENTRY;
240         
241         if (test_bit(TRANSFERD_STOP, &tc->tc_flags))
242                 RETURN(1);
243         
244         spin_lock(&tc->tc_lock);
245         rc = list_empty(&tc->tc_list) ? 0 : 1;
246         spin_unlock(&tc->tc_lock);
247         
248         RETURN(rc);
249 }
250                 
251 static int transferd(void *arg)
252 {
253         struct transferd_ctl *tc = arg;
254         unsigned long flags;
255         struct list_head *pos, *tmp;
256         struct transfer_item *ti = NULL;
257         ENTRY;
258
259         lock_kernel();
260         
261         /* ptlrpc_daemonize() */
262         exit_mm(current);
263         lustre_daemonize_helper();
264         exit_files(current);
265         reparent_to_init();
266         
267         SIGNAL_MASK_LOCK(current, flags);
268         sigfillset(&current->blocked);
269         RECALC_SIGPENDING;
270         SIGNAL_MASK_UNLOCK(current, flags);
271         THREAD_NAME(current->comm, sizeof(current->comm) - 1, "%s", 
272                     "audit_transferd");
273         unlock_kernel();
274
275         complete(&tc->tc_starting);
276
277         LASSERT(buf == NULL);
278         OBD_ALLOC(buf, PAGE_SIZE);
279         LASSERT(buf != NULL);
280
281         while (1) {
282                 struct l_wait_info lwi = { 0 };
283                 
284                 l_wait_event(tc->tc_waitq, transferd_check(tc), &lwi);
285                 
286                 if (test_bit(TRANSFERD_STOP, &tc->tc_flags))
287                         break;
288                 
289                 spin_lock(&tc->tc_lock);
290                 LASSERT(!list_empty(&tc->tc_list));
291                 ti = list_entry(tc->tc_list.next, struct transfer_item, ti_link);
292                 list_del_init(&ti->ti_link);
293                 spin_unlock(&tc->tc_lock);
294                 
295                 audit_transfer(ti);
296                 OBD_FREE(ti, sizeof(*ti));
297
298         }
299
300         OBD_FREE(buf, PAGE_SIZE);
301
302         spin_lock(&tc->tc_lock);
303         list_for_each_safe(pos, tmp, &tc->tc_list) {
304                 ti = list_entry(pos, struct transfer_item, ti_link);
305                 list_del_init(&ti->ti_link);
306                 OBD_FREE(ti, sizeof(*ti));
307         }
308         spin_unlock(&tc->tc_lock);
309
310         complete(&tc->tc_stopping);
311         RETURN(0);
312 }
313
314 int audit_start_transferd()
315 {
316         int rc = 0;
317         ENTRY;
318         
319         down(&transferd_sem);
320         if (++transferd_users != 1)
321                 GOTO(out, rc = 0);
322
323         memset(&transferd_tc, 0, sizeof(transferd_tc));
324         init_completion(&transferd_tc.tc_starting);
325         init_completion(&transferd_tc.tc_stopping);
326         init_waitqueue_head(&transferd_tc.tc_waitq);
327         transferd_tc.tc_flags = 0;
328         INIT_LIST_HEAD(&transferd_tc.tc_list);
329         spin_lock_init(&transferd_tc.tc_lock);
330         
331         if (kernel_thread(transferd, &transferd_tc, 0) < 0) {
332                 transferd_users--;
333                 GOTO(out, rc = -ECHILD);
334         }
335
336         wait_for_completion(&transferd_tc.tc_starting);
337 out:
338         up(&transferd_sem);
339         RETURN(rc);
340 }
341
342 int audit_stop_transferd(void)
343 {
344         int rc = 0;
345         ENTRY;
346
347         down(&transferd_sem);
348         if (--transferd_users > 0)
349                 GOTO(out, rc = 0);
350
351         set_bit(TRANSFERD_STOP, &transferd_tc.tc_flags);
352         wake_up(&transferd_tc.tc_waitq);
353         wait_for_completion(&transferd_tc.tc_stopping);
354 out:
355         up(&transferd_sem);
356         RETURN(rc);
357 }