1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * lustre/smfs/audit_transfer.c
6 * Copyright (C) 2004 Cluster File Systems, Inc.
8 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
24 # define EXPORT_SYMTAB
27 #define DEBUG_SUBSYSTEM S_SM
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"
46 struct transfer_item {
47 struct llog_handle *ti_llh;
48 struct list_head ti_link;
52 #define TRANSFERD_STOP 0
53 struct transferd_ctl {
54 unsigned long tc_flags;
55 wait_queue_head_t tc_waitq;
56 struct completion tc_starting;
57 struct completion tc_stopping;
59 struct list_head tc_list;
63 static struct transferd_ctl transferd_tc;
64 static DECLARE_MUTEX(transferd_sem);
65 static int transferd_users = 0;
68 static int transferd_check(struct transferd_ctl *tc)
73 if (test_bit(TRANSFERD_STOP, &tc->tc_flags))
76 spin_lock(&tc->tc_lock);
77 rc = list_empty(&tc->tc_list) ? 0 : 1;
78 spin_unlock(&tc->tc_lock);
83 int audit_notify(struct llog_handle *llh, void * arg, int null)
85 struct transfer_item *ti;
89 if (transferd_users == 0) {
95 if (test_bit(TRANSFERD_STOP, &transferd_tc.tc_flags)) {
96 CDEBUG(D_INFO, "transfer daemon stopped\n");
100 OBD_ALLOC(ti, sizeof(*ti));
104 INIT_LIST_HEAD(&ti->ti_link);
106 ti->priv.id2name = arg;
107 ti->priv.null = null;
109 spin_lock(&transferd_tc.tc_lock);
110 list_add_tail(&ti->ti_link, &transferd_tc.tc_list);
111 spin_unlock(&transferd_tc.tc_lock);
113 wake_up(&transferd_tc.tc_waitq);
115 if (llh == NULL) /* demand to flush list */
117 struct l_wait_info lwi = { 0 };
118 l_wait_event(transferd_tc.tc_waitq,
119 transferd_check(&transferd_tc), &lwi);
125 const char *opstr[AUDIT_MAX] = {
126 [AUDIT_UNKNOWN] "unknown",
127 [AUDIT_CREATE] "create",
129 [AUDIT_UNLINK] "unlink",
130 [AUDIT_RENAME] "rename",
131 [AUDIT_SETATTR] "setattr",
132 [AUDIT_WRITE] "write",
137 [AUDIT_READLINK] "readlink",
138 [AUDIT_READDIR] "readdir",
141 #define construct_header(buf, size, rec, id_rec) \
142 snprintf(buf, size, "AUDIT:"LPX64":%u/%u:%s:%d:"DLID4":", \
143 rec->nid, rec->uid, rec->gid, opstr[rec->opcode], (__s16)rec->result,\
144 (unsigned long)id_rec->au_fid, (unsigned long)id_rec->au_mds, \
145 (unsigned long)id_rec->au_num, (unsigned long)id_rec->au_gen);
147 #define REC2ID(rec, id) { \
148 id_ino(id) = rec->au_num; \
149 id_gen(id) = rec->au_gen; \
150 id_type(id) = rec->au_type; \
151 id_fid(id) = rec->au_fid; \
152 id_group(id) = rec->au_mds; \
156 transfer_record(struct obd_device *obd, struct audit_record *rec, int type, void * data)
158 struct audit_id_record *id_rec =
159 (struct audit_id_record *)(rec + 1);
160 struct audit_name_record *name_rec = NULL;
161 struct tr_priv * trp = data;
162 int (*audit_id2name)(struct obd_device *obd, char **name, int *namelen,
163 struct lustre_id *id) = trp->id2name;
168 CDEBUG(D_INFO, "transfer %s\n", opstr[rec->opcode]);
170 memset(buf, 0, PAGE_SIZE);
171 n = construct_header(buf, PAGE_SIZE, rec, id_rec);
174 /* let's use remaining space */
180 if (type != SMFS_AUDIT_NAME_REC)
196 //LASSERT(id_type(&id) & S_IFMT);
197 rc = audit_id2name(obd, &name, &namelen, &id);
199 strncat(buf, "unknown", n);
200 n -= strlen("unknown");
201 } else if (namelen == 0) {
203 if (type != SMFS_AUDIT_NAME_REC)
206 strncat(buf, name, n);
208 OBD_FREE(name, namelen);
212 if (type == SMFS_AUDIT_NAME_REC && n > 0) {
213 name_rec = (struct audit_name_record *)(++id_rec);
216 /* get minimum size to copy name with exact len */
217 if (n > name_rec->name_len)
218 n = name_rec->name_len;
219 strncat(buf, name_rec->name, n);
222 CDEBUG(D_INFO, "%s\n", buf);
230 static int transfer_cb(struct llog_handle *llh, struct llog_rec_hdr *rec,
233 struct obd_device *obd = llh->lgh_ctxt->loc_obd;
234 struct audit_record *ad_rec;
235 struct llog_cookie cookie;
238 if (!(le32_to_cpu(llh->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
239 CERROR("log is not plain\n");
242 if (rec->lrh_type != cpu_to_le32(SMFS_AUDIT_GEN_REC) &&
243 rec->lrh_type != cpu_to_le32(SMFS_AUDIT_NAME_REC)) {
244 CERROR("log record type error\n");
248 ad_rec = (struct audit_record *)((char *)rec + sizeof(*rec));
250 LASSERT(ad_rec->opcode < AUDIT_MAX);
252 cookie.lgc_lgl = llh->lgh_id;
253 cookie.lgc_subsys = LLOG_AUDIT_ORIG_CTXT;
254 cookie.lgc_index = le32_to_cpu(rec->lrh_index);
256 transfer_record(obd, ad_rec, rec->lrh_type, data);
258 llog_cancel(llh->lgh_ctxt, 1, &cookie, 0, NULL);
263 static int audit_transfer(struct transfer_item *ti)
265 struct llog_handle *llh = ti->ti_llh;
272 rc = llog_cat_process(llh, (llog_cb_t)&transfer_cb, &ti->priv);
274 CERROR("process catalog log failed: rc(%d)\n", rc);
279 static int transferd(void *arg)
281 struct transferd_ctl *tc = arg;
283 struct list_head *pos, *tmp;
284 struct transfer_item *ti = NULL;
289 /* ptlrpc_daemonize() */
291 lustre_daemonize_helper();
295 SIGNAL_MASK_LOCK(current, flags);
296 sigfillset(¤t->blocked);
298 SIGNAL_MASK_UNLOCK(current, flags);
299 THREAD_NAME(current->comm, sizeof(current->comm) - 1, "%s",
303 complete(&tc->tc_starting);
305 LASSERT(buf == NULL);
306 OBD_ALLOC(buf, PAGE_SIZE);
307 LASSERT(buf != NULL);
310 struct l_wait_info lwi = { 0 };
312 l_wait_event(tc->tc_waitq, transferd_check(tc), &lwi);
314 if (test_bit(TRANSFERD_STOP, &tc->tc_flags))
317 spin_lock(&tc->tc_lock);
318 LASSERT(!list_empty(&tc->tc_list));
319 ti = list_entry(tc->tc_list.next, struct transfer_item, ti_link);
320 list_del_init(&ti->ti_link);
321 spin_unlock(&tc->tc_lock);
324 OBD_FREE(ti, sizeof(*ti));
328 OBD_FREE(buf, PAGE_SIZE);
330 spin_lock(&tc->tc_lock);
331 list_for_each_safe(pos, tmp, &tc->tc_list) {
332 ti = list_entry(pos, struct transfer_item, ti_link);
333 list_del_init(&ti->ti_link);
334 OBD_FREE(ti, sizeof(*ti));
336 spin_unlock(&tc->tc_lock);
338 complete(&tc->tc_stopping);
342 int audit_start_transferd()
347 down(&transferd_sem);
348 if (++transferd_users != 1)
351 memset(&transferd_tc, 0, sizeof(transferd_tc));
352 init_completion(&transferd_tc.tc_starting);
353 init_completion(&transferd_tc.tc_stopping);
354 init_waitqueue_head(&transferd_tc.tc_waitq);
355 transferd_tc.tc_flags = 0;
356 INIT_LIST_HEAD(&transferd_tc.tc_list);
357 spin_lock_init(&transferd_tc.tc_lock);
359 if (kernel_thread(transferd, &transferd_tc, 0) < 0) {
361 GOTO(out, rc = -ECHILD);
364 wait_for_completion(&transferd_tc.tc_starting);
370 int audit_stop_transferd(void)
375 down(&transferd_sem);
376 if (--transferd_users > 0)
379 set_bit(TRANSFERD_STOP, &transferd_tc.tc_flags);
380 wake_up(&transferd_tc.tc_waitq);
381 wait_for_completion(&transferd_tc.tc_stopping);