1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Copyright (C) 2001-2003 Cluster File Systems, Inc.
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 # define EXPORT_SYMTAB
26 #define DEBUG_SUBSYSTEM S_MDS
28 #include <linux/module.h>
29 #include <linux/lustre_mds.h>
30 #include <linux/lustre_dlm.h>
31 #include <linux/lustre_fsfilt.h>
32 #include <linux/init.h>
33 #include <linux/obd_class.h>
35 #include <linux/namei.h>
36 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
37 # include <linux/smp_lock.h>
38 # include <linux/buffer_head.h>
39 # include <linux/workqueue.h>
40 # include <linux/mount.h>
42 # include <linux/locks.h>
44 #include <linux/lustre_audit.h>
45 #include "mds_internal.h"
50 #define PP_SPLIT_MASTER 3
51 #define PP_SPLIT_SLAVE 4
52 #define PP_CROSS_DIR 5
53 #define PP_AUDIT_LOG 6 /* search id in audit log */
55 struct scan_dir_data {
62 static int filldir(void *__buf, const char *name, int namlen,
63 loff_t offset, ino_t ino, unsigned int d_type)
65 struct scan_dir_data *sd = __buf;
69 (namlen == 1 || (namlen == 2 && name[1] == '.'))) {
70 /* skip special entries */
76 /* skip non-cross_ref entries if we need cross-ref */
77 if (sd->cross_ref && !(d_type & 128))
80 if (ino == sd->i_num) {
81 strncpy(sd->name, name, namlen);
83 RETURN(-EINTR); /* break the readdir loop */
88 static int scan_name_in_parent(struct lustre_id *pid, struct lustre_id *id,
93 struct scan_dir_data sd;
97 len = strlen("__iopen__/") + 10 + 1;
98 OBD_ALLOC(pname, len);
102 sprintf(pname, "__iopen__/0x%llx", id_ino(pid));
104 file = filp_open(pname, O_RDONLY, 0);
106 CERROR("can't open directory %s: %d\n",
107 pname, (int) PTR_ERR(file));
108 GOTO(out, rc = PTR_ERR(file));
111 sd.i_num = id_ino(id);
115 rc = vfs_readdir(file, filldir, &sd);
122 OBD_FREE(pname, len);
127 /* id2pid - given id, get parent id or master id.
129 * @id: child id to be parsed
130 * @pid: parent id or master id
134 id2pid(struct obd_device *obd, struct lustre_id *id, struct lustre_id *pid,
137 struct dentry *dentry = NULL;
138 struct inode *inode = NULL;
139 struct mea *mea = NULL;
140 int mea_size, rc = 0;
143 dentry = mds_id2dentry(obd, id, NULL);
144 if (IS_ERR(dentry) || !dentry->d_inode) {
145 CERROR("can't find inode "LPU64"\n", id_ino(id));
146 if (!IS_ERR(dentry)) l_dput(dentry);
149 inode = dentry->d_inode;
151 if (S_ISDIR(inode->i_mode)) {
152 //LASSERT(S_ISDIR(id_type(id)));
153 rc = mds_md_get_attr(obd, inode, &mea, &mea_size);
160 } else if (mea && mea->mea_count) {
161 *type = PP_SPLIT_MASTER;
164 *type = PP_SPLIT_SLAVE;
165 *pid = mea->mea_ids[mea->mea_master];
166 LASSERT(id_fid(pid));
170 //LASSERT(!S_ISDIR(id_type(id)));
173 rc = mds_read_inode_pid(obd, inode, pid);
175 CERROR("can't read parent ino(%lu) rc(%d).\n",
181 /* Well, if it's dir or master split, we have to check if it's
183 if ((*type == PP_DIR || *type == PP_SPLIT_MASTER) &&
184 id_group(id) != id_group(pid))
185 *type = PP_CROSS_DIR;
188 OBD_FREE(mea, mea_size);
193 static int local_parse_id(struct obd_device *obd, struct parseid_pkg *pkg)
195 struct lvfs_run_ctxt saved;
196 int rc = 0, cross_ref = 0;
201 memset(pkg->pp_name, 0, sizeof(pkg->pp_name));
203 /* pp_id2 is present, which indicating we want to scan parent
204 * dir(pp_id2) to find the cross-ref entry(pp_id1) */
205 if (id_fid(&pkg->pp_id2)) {
206 LASSERT(obd->u.mds.mds_num == id_group(&pkg->pp_id2));
207 pkg->pp_type = PP_DIR;
210 LASSERT(obd->u.mds.mds_num == id_group(&pkg->pp_id1));
211 rc = id2pid(obd, &pkg->pp_id1, &pkg->pp_id2, &pkg->pp_type);
216 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
218 switch (pkg->pp_type) {
221 case PP_SPLIT_MASTER:
222 rc = scan_name_in_parent(&pkg->pp_id2, &pkg->pp_id1,
223 pkg->pp_name, cross_ref);
225 CERROR("scan "LPU64" in parent failed. rc=%d\n",
226 id_ino(&pkg->pp_id1), rc);
232 CERROR("invalid id\n");
236 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
243 local_scan_audit_log(struct obd_device *obd, struct parseid_pkg *pkg);
245 int mds_parse_id(struct ptlrpc_request *req)
247 struct parseid_pkg *pkg, *reppkg;
248 struct obd_device *obd = req->rq_export->exp_obd;
249 int rc = 0, size = sizeof(*reppkg);
252 pkg = lustre_swab_reqbuf(req, 0, sizeof(*pkg),
253 lustre_swab_parseid_pkg);
257 rc = lustre_pack_reply(req, 1, &size, NULL);
261 reppkg = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*reppkg));
262 memcpy(reppkg, pkg, sizeof(*reppkg));
264 if (reppkg->pp_type == PP_AUDIT_LOG)
265 rc = local_scan_audit_log(obd, reppkg);
267 rc = local_parse_id(obd, reppkg);
270 CERROR("local parseid failed. (rc:%d)\n", rc);
271 RETURN(0); /* we do need pack reply here */
274 static int parse_id(struct obd_device *obd, struct parseid_pkg *pkg)
277 int mds_num = id_group(&pkg->pp_id1);
280 //for cross-ref dir we should send request to parent's MDS
281 if (pkg->pp_type == PP_CROSS_DIR)
282 mds_num = id_group(&pkg->pp_id2);
284 LASSERT(mds_num >= 0);
286 if (mds_num == obd->u.mds.mds_num) {
287 rc = local_parse_id(obd, pkg);
289 struct ptlrpc_request *req;
290 struct lmv_obd *lmv = &obd->u.mds.mds_md_obd->u.lmv;
291 struct parseid_pkg *body;
292 int size = sizeof(*body);
293 struct obd_export *exp;
295 /* make sure connection established */
296 rc = obd_set_info(obd->u.mds.mds_md_exp, strlen("chkconnect"),
297 "chkconnect", 0, NULL);
301 exp = lmv->tgts[mds_num].ltd_exp;
302 LASSERTF(exp, "No export for MDS #%i\n", mds_num);
304 req = ptlrpc_prep_req(class_exp2cliimp(exp),
305 LUSTRE_MDS_VERSION, MDS_PARSE_ID, 1,
310 body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body));
311 memcpy(body, pkg, sizeof(*body));
313 req->rq_replen = lustre_msg_size(1, &size);
315 rc = ptlrpc_queue_wait(req);
319 body = lustre_swab_repbuf(req, 0, sizeof(*body),
320 lustre_swab_parseid_pkg);
322 CERROR("can't unpack parseid_pkg\n");
323 GOTO(out, rc = -EPROTO);
325 memcpy(pkg, body, sizeof(*pkg));
327 ptlrpc_req_finished(req);
334 struct list_head link;
335 char name[NAME_MAX + 1];
339 mds_id2name(struct obd_device *obd, struct lustre_id *id,
340 struct list_head *list, struct lustre_id *lastid)
342 struct name_item *item;
343 struct parseid_pkg *pkg;
347 OBD_ALLOC(pkg, sizeof(*pkg));
352 while (id_fid(&pkg->pp_id1) != ROOT_FID) {
354 rc = parse_id(obd, pkg);
356 CDEBUG(D_SEC, "parse id failed. rc=%d\n", rc);
357 *lastid = pkg->pp_id1;
361 switch (pkg->pp_type) {
364 case PP_SPLIT_MASTER:
365 OBD_ALLOC(item, sizeof(*item));
367 GOTO(out, rc = -ENOMEM);
369 INIT_LIST_HEAD(&item->link);
370 list_add(&item->link, list);
371 memcpy(item->name, pkg->pp_name, sizeof(item->name));
374 pkg->pp_id1 = pkg->pp_id2;
375 memset(&pkg->pp_id2, 0, sizeof(struct lustre_id));
379 CERROR("Wrong id = %i\n", pkg->pp_type);
385 OBD_FREE(pkg, sizeof(*pkg));
390 scan_audit_log_cb(struct llog_handle *llh, struct llog_rec_hdr *rec, void *data)
392 struct parseid_pkg *pkg = (struct parseid_pkg *)data;
393 struct audit_record *ad_rec;
394 struct audit_id_record *cid_rec, *pid_rec;
395 struct audit_name_record *nm_rec;
398 if (!(le32_to_cpu(llh->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
399 CERROR("log is not plain\n");
403 if (rec->lrh_type != SMFS_AUDIT_NAME_REC)
406 ad_rec = (struct audit_record *)(rec + 1);
407 if (ad_rec->result ||
408 (ad_rec->opcode != AUDIT_UNLINK &&
409 ad_rec->opcode != AUDIT_RENAME))
412 cid_rec = (struct audit_id_record *)(ad_rec + 1);
413 pid_rec = cid_rec + 1;
414 nm_rec = (struct audit_name_record *)(pid_rec + 1);
416 if (cid_rec->au_num == id_ino(&pkg->pp_id1) &&
417 cid_rec->au_gen == id_gen(&pkg->pp_id1)) {
418 LASSERT(pid_rec->au_fid);
420 id_ino(&pkg->pp_id2) = pid_rec->au_num;
421 id_gen(&pkg->pp_id2) = pid_rec->au_gen;
422 id_type(&pkg->pp_id2) = pid_rec->au_type;
423 id_fid(&pkg->pp_id2) = pid_rec->au_fid;
424 id_group(&pkg->pp_id2) = pid_rec->au_mds;
426 memcpy(pkg->pp_name, nm_rec->name,
427 le32_to_cpu(nm_rec->name_len));
428 RETURN(LLOG_PROC_BREAK);
434 local_scan_audit_log(struct obd_device *obd, struct parseid_pkg *pkg)
436 struct llog_handle *llh = NULL;
437 struct llog_ctxt *ctxt = llog_get_context(&obd->obd_llogs,
438 LLOG_AUDIT_ORIG_CTXT);
444 llh = ctxt->loc_handle;
447 GOTO(out, rc = -ENOENT);
449 rc = llog_cat_process(llh, (llog_cb_t)&scan_audit_log_cb, (void *)pkg);
450 if (rc != LLOG_PROC_BREAK) {
451 CWARN("process catalog log failed: rc(%d)\n", rc);
460 scan_audit_log(struct obd_device *obd, struct lustre_id *cur_id,
461 struct list_head *list, struct lustre_id *parent_id)
463 struct name_item *item = NULL;
464 int rc = 0, mds_num = id_group(cur_id);
465 struct parseid_pkg *pkg = NULL;
468 OBD_ALLOC(pkg, sizeof(*pkg));
472 pkg->pp_type = PP_AUDIT_LOG;
473 pkg->pp_id1 = *cur_id;
475 if (obd->u.mds.mds_num == mds_num) {
476 rc = local_scan_audit_log(obd, pkg);
478 struct ptlrpc_request *req;
479 struct lmv_obd *lmv = &obd->u.mds.mds_md_obd->u.lmv;
480 struct parseid_pkg *body;
481 int size = sizeof(*body);
482 struct obd_export *exp;
484 /* make sure connection established */
485 rc = obd_set_info(obd->u.mds.mds_md_exp, strlen("chkconnect"),
486 "chkconnect", 0, NULL);
490 exp = lmv->tgts[mds_num].ltd_exp;
491 LASSERTF(exp, "No export for MDS #%i\n", mds_num);
493 req = ptlrpc_prep_req(class_exp2cliimp(exp),
494 LUSTRE_MDS_VERSION, MDS_PARSE_ID, 1,
499 body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body));
500 memcpy(body, pkg, sizeof(*body));
502 req->rq_replen = lustre_msg_size(1, &size);
504 rc = ptlrpc_queue_wait(req);
508 body = lustre_swab_repbuf(req, 0, sizeof(*body),
509 lustre_swab_parseid_pkg);
511 CERROR("can't unpack parseid_pkg\n");
512 GOTO(out, rc = -EPROTO);
514 memcpy(pkg, body, sizeof(*pkg));
516 ptlrpc_req_finished(req);
520 if (!rc) rc = pkg->pp_rc;
524 *parent_id = pkg->pp_id2;
526 OBD_ALLOC(item, sizeof(*item));
528 GOTO(out, rc = -ENOMEM);
530 INIT_LIST_HEAD(&item->link);
531 list_add(&item->link, list);
532 memcpy(item->name, pkg->pp_name, sizeof(item->name));
534 OBD_FREE(pkg, sizeof(*pkg));
539 mds_audit_id2name(struct obd_device *obd, char **name, int *namelen,
540 struct lustre_id *id)
543 struct list_head list, *pos, *n;
544 struct name_item *item;
545 struct lustre_id parent_id, cur_id;
549 INIT_LIST_HEAD(&list);
552 if (!id_fid(&cur_id)) {
553 CERROR("Invalid id!\n");
556 if (id_fid(&cur_id) == ROOT_FID)
560 memset(&parent_id, 0, sizeof(parent_id));
561 rc = mds_id2name(obd, &cur_id, &list, &parent_id);
563 /* can't reconstruct name from id, turn to audit log */
564 LASSERT(id_fid(&parent_id));
566 memset(&parent_id, 0, sizeof(parent_id));
568 rc = scan_audit_log(obd, &cur_id, &list, &parent_id);
570 CERROR("scan id in audit log failed. (rc:%d)\n", rc);
574 LASSERT(id_fid(&parent_id));
579 CERROR("reconstruct name from id failed. (rc:%d)\n", rc);
583 list_for_each_safe (pos, n, &list) {
584 item = list_entry(pos, struct name_item, link);
585 *namelen += strlen(item->name) + 1;
588 (*namelen)++; /* for the ending '\0' of string */
589 OBD_ALLOC(*name, *namelen);
593 list_for_each_safe (pos, n, &list) {
594 item = list_entry(pos, struct name_item, link);
598 strcat(*name, item->name);
600 list_del_init(&item->link);
601 OBD_FREE(item, sizeof(*item));
602 LASSERT(strlen(*name) < *namelen);
606 EXPORT_SYMBOL(mds_audit_id2name);