From 0ae1c575448dbb0700bc45a88f964645c37a774c Mon Sep 17 00:00:00 2001 From: tappro Date: Sat, 6 Aug 2005 01:06:14 +0000 Subject: [PATCH] - b_hd_audit landing --- lustre/include/linux/Makefile.am | 3 +- lustre/include/linux/lustre_audit.h | 106 +++++ lustre/include/linux/lustre_cfg.h | 1 + lustre/include/linux/lustre_dlm.h | 2 +- lustre/include/linux/lustre_fsfilt.h | 34 +- lustre/include/linux/lustre_idl.h | 42 +- lustre/include/linux/lustre_lite.h | 1 + lustre/include/linux/lustre_mds.h | 4 + lustre/include/linux/lustre_smfs.h | 1 - lustre/include/linux/lvfs.h | 1 + lustre/include/linux/obd.h | 1 + lustre/include/lustre/lustre_user.h | 2 +- lustre/kernel_patches/patches/nid-2.6-fc3.patch | 12 + lustre/kernel_patches/series/2.6-fc3-uml.series | 2 + lustre/kernel_patches/series/2.6-fc3.series | 2 + lustre/ldlm/ldlm_lock.c | 2 +- lustre/llite/Makefile.in | 3 +- lustre/llite/dir.c | 3 + lustre/llite/file.c | 23 +- lustre/llite/llite_audit.c | 104 +++++ lustre/llite/llite_internal.h | 18 +- lustre/llite/llite_lib.c | 15 +- lustre/llite/llite_mmap.c | 11 +- lustre/llite/rw.c | 2 +- lustre/lmv/lmv_obd.c | 47 +- lustre/lov/lov_obd.c | 85 +++- lustre/lvfs/fsfilt_ext3.c | 11 + lustre/lvfs/lvfs_linux.c | 6 +- lustre/mdc/mdc_request.c | 39 +- lustre/mds/Makefile.in | 2 +- lustre/mds/handler.c | 293 ++++++++---- lustre/mds/mds_audit.c | 261 +++++++++++ lustre/mds/mds_audit_path.c | 584 ++++++++++++++++++++++++ lustre/mds/mds_fs.c | 22 +- lustre/mds/mds_internal.h | 20 +- lustre/mds/mds_lib.c | 23 +- lustre/mds/mds_open.c | 37 +- lustre/mds/mds_reint.c | 161 +++---- lustre/obdclass/llog_obd.c | 1 + lustre/obdclass/mea.c | 12 +- lustre/obdfilter/filter.c | 59 ++- lustre/obdfilter/filter_io.c | 31 +- lustre/osc/osc_request.c | 97 +++- lustre/ost/ost_handler.c | 14 + lustre/ptlrpc/lproc_ptlrpc.c | 1 + lustre/ptlrpc/pack_generic.c | 26 ++ lustre/ptlrpc/ptlrpc_module.c | 3 + lustre/smfs/Makefile.in | 1 + lustre/smfs/audit.c | 581 +++++++++++++++++++++++ lustre/smfs/audit_mds.c | 267 +++++++++++ lustre/smfs/audit_ost.c | 143 ++++++ lustre/smfs/audit_transfer.c | 357 +++++++++++++++ lustre/smfs/cache.c | 2 - lustre/smfs/cache_space.c | 60 ++- lustre/smfs/dir.c | 14 +- lustre/smfs/file.c | 30 +- lustre/smfs/fsfilt.c | 130 +++++- lustre/smfs/kml.c | 69 +-- lustre/smfs/smfs_api.h | 177 +++++-- lustre/smfs/smfs_internal.h | 10 +- lustre/smfs/smfs_lib.c | 58 ++- lustre/smfs/smfs_llog.c | 10 +- lustre/smfs/symlink.c | 22 +- lustre/tests/local.sh | 4 +- lustre/utils/lconf | 27 +- lustre/utils/lctl.c | 155 +++++++ lustre/utils/lustre_cfg.c | 2 + lustre/utils/obd.c | 1 + 68 files changed, 3890 insertions(+), 460 deletions(-) create mode 100644 lustre/include/linux/lustre_audit.h create mode 100644 lustre/kernel_patches/patches/nid-2.6-fc3.patch create mode 100644 lustre/llite/llite_audit.c create mode 100644 lustre/mds/mds_audit.c create mode 100644 lustre/mds/mds_audit_path.c create mode 100644 lustre/smfs/audit.c create mode 100644 lustre/smfs/audit_mds.c create mode 100644 lustre/smfs/audit_ost.c create mode 100644 lustre/smfs/audit_transfer.c diff --git a/lustre/include/linux/Makefile.am b/lustre/include/linux/Makefile.am index f04ba49..16e1aee4 100644 --- a/lustre/include/linux/Makefile.am +++ b/lustre/include/linux/Makefile.am @@ -16,4 +16,5 @@ EXTRA_DIST = lprocfs_status.h lustre_debug.h lustre_ha.h lustre_lib.h \ lustre_compat25.h lustre_fsfilt.h lustre_import.h lustre_mds.h obd.h \ lvfs.h lvfs_linux.h lustre_cfg.h lustre_lite.h lustre_idl.h lustre_smfs.h \ lustre_cmobd.h obd_lmv.h lustre_snap.h lustre_sec.h lustre_ucache.h \ - lustre_acl.h lustre_gs.h + lustre_acl.h lustre_audit.h lustre_gs.h + diff --git a/lustre/include/linux/lustre_audit.h b/lustre/include/linux/lustre_audit.h new file mode 100644 index 0000000..be74c17 --- /dev/null +++ b/lustre/include/linux/lustre_audit.h @@ -0,0 +1,106 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2001-2003 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * smfs data structures. + * See also lustre_idl.h for wire formats of requests. + * + */ + +#ifndef __LUSTRE_AUDIT_H +#define __LUSTRE_AUDIT_H + +/* Audit plugin stuff */ +#define AUDIT_MDS_NAME "audit_mds" +#define AUDIT_OST_NAME "audit_ost" +#define AUDIT_CLI_NAME "audit_client-" +#define AUDIT_ATTR_EA "audit" +#define AUDIT_ATTR_FILE "audit_setting" +//AUDIT OPCODES, also bit number in audit_setting mask + +typedef enum { + AUDIT_NONE = 0, + AUDIT_CREATE, + AUDIT_LINK, + AUDIT_UNLINK, + AUDIT_SYMLINK, + AUDIT_RENAME, + AUDIT_SETATTR, + AUDIT_WRITE, + AUDIT_READ, + AUDIT_OPEN, + AUDIT_STAT, + AUDIT_MMAP, + AUDIT_READLINK, + AUDIT_READDIR, + AUDIT_MAX, +} audit_op; + +#define AUDIT_FAIL AUDIT_MAX +#define AUDIT_DIR (AUDIT_MAX + 1) +#define AUDIT_FS (AUDIT_MAX + 2) + +#define AUD_BIT(a) (1 << a) + +#define AUDIT_ALL_OPS ((1 << AUDIT_MAX) - 1) +#define AUDIT_OFF 0 + +#define IS_AUDIT_OP(mask,op) (mask & (1<obd_fsops->fs_set_info) + return obd->obd_fsops->fs_set_info(sb, inode, + keylen, key, + valsize, val); + return 0; +} + +static inline int +fsfilt_get_info(struct obd_device *obd, struct super_block *sb, + struct inode * inode, __u32 keylen, void * key, + __u32 * valsize, void * val) { - if (obd->obd_fsops->fs_get_reint_log_ctxt) - return obd->obd_fsops->fs_get_reint_log_ctxt(sb, ctxt); + if (obd->obd_fsops->fs_get_info) + return obd->obd_fsops->fs_get_info(sb, inode, keylen, key, + valsize, val); return 0; } diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index 030199a..576186f 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -421,14 +421,16 @@ struct lov_mds_md_v0 { /* LOV EA mds/wire data (little-endian) */ #define OBD_MD_FLXATTRLIST (0x0000000200000000LL) /* user xattr list */ #define OBD_MD_FLACL (0x0000000400000000LL) /* acl */ #define OBD_MD_FLRMTACL (0x0000000800000000LL) /* remote acl */ -#define OBD_MD_FLKEY (0x0000001000000000LL) /* mds key extended attributes */ +#define OBD_MD_FLKEY (0x0000001000000000LL) /* mds key extended attributes */ +#define OBD_MD_FLAUDIT (0x0000002000000000LL) /* audit setting */ #define OBD_MD_FLNOTOBD (~(OBD_MD_FLBLOCKS | OBD_MD_LINKNAME | \ OBD_MD_FLEASIZE | OBD_MD_FLHANDLE | \ OBD_MD_FLCKSUM | OBD_MD_FLQOS | \ OBD_MD_FLOSCOPQ | OBD_MD_FLCOOKIE | \ OBD_MD_FLXATTR | OBD_MD_FLXATTRLIST | \ - OBD_MD_FLACL | OBD_MD_FLKEY | OBD_MD_MDS)) + OBD_MD_FLACL | OBD_MD_FLKEY | \ + OBD_MD_MDS | OBD_MD_FLAUDIT)) static inline struct lustre_handle *obdo_handle(struct obdo *oa) { @@ -561,6 +563,7 @@ typedef enum { MDS_SYNC = 44, MDS_DONE_WRITING = 45, MDS_ACCESS_CHECK = 46, + MDS_PARSE_ID = 47, MDS_LAST_OPC } mds_cmd_t; @@ -652,6 +655,38 @@ struct mds_status_req { __u32 repbuf; }; +struct parseid_pkg { + __u32 pp_type; + __u32 pp_rc; + struct lustre_id pp_id1; + struct lustre_id pp_id2; + __u8 pp_name[NAME_MAX + 1]; +}; + +struct audit_msg { + struct lustre_id id; + __u64 nid; + __u32 result; + __u32 uid; + __u32 gid; + __u32 code; +}; + +struct audit_attr_msg { + struct lustre_id id; + __u64 attr; +}; +#if 0 +extern void lustre_swab_lustre_id(struct lustre_id *id); +extern void lustre_swab_lustre_stc(struct lustre_stc *stc); +extern void lustre_swab_lustre_fid(struct lustre_fid *fid); +extern void lustre_swab_parseid_pkg(struct parseid_pkg *pkg); +extern void lustre_swab_mds_status_req (struct mds_status_req *r); +#endif +extern void lustre_swab_audit_msg (struct audit_msg *r); +extern void lustre_swab_audit_attr (struct audit_attr_msg *r); +extern void lustre_swab_parseid_pkg(struct parseid_pkg *pkg); + #define MDS_BFLAG_UNCOMMITTED_WRITES 0x1 #define MDS_BFLAG_CLOSE_EPOCH 0x2 #define MDS_BFLAG_DIRTY_EPOCH 0x4 @@ -664,6 +699,7 @@ struct mds_body { __u64 blocks; /* XID, in the case of MDS_READPAGE */ __u64 io_epoch; __u64 valid; + __u64 audit; __u32 mode; __u32 uid; __u32 gid; @@ -1034,6 +1070,8 @@ typedef enum { LLOG_LOGID_MAGIC = 0x1064553b, SMFS_UPDATE_REC = 0x10650000, CACHE_LRU_REC = 0x10660000, + SMFS_AUDIT_GEN_REC = 0x10670000, + SMFS_AUDIT_NAME_REC = 0x10680000, } llog_op_type; /* Log record header - stored in little endian order. diff --git a/lustre/include/linux/lustre_lite.h b/lustre/include/linux/lustre_lite.h index 66362f3..fa2887b 100644 --- a/lustre/include/linux/lustre_lite.h +++ b/lustre/include/linux/lustre_lite.h @@ -85,6 +85,7 @@ struct ll_inode_info { struct semaphore lli_size_sem; __u64 lli_maxbytes; __u64 lli_io_epoch; + __u64 lli_audit_mask; unsigned long lli_flags; /* this lock protects s_d_w and p_w_ll */ diff --git a/lustre/include/linux/lustre_mds.h b/lustre/include/linux/lustre_mds.h index 63730a9..290711e 100644 --- a/lustre/include/linux/lustre_mds.h +++ b/lustre/include/linux/lustre_mds.h @@ -377,6 +377,10 @@ int mdc_llog_process(struct obd_export *, char *, llog_cb_t, int mdc_done_writing(struct obd_export *, struct obdo *); +/* mds_audit_path.c */ +int mds_audit_id2name(struct obd_device *obd, char **name, int *namelen, + struct lustre_id *id); + /* ioctls for trying requests */ #define IOC_REQUEST_TYPE 'f' #define IOC_REQUEST_MIN_NR 30 diff --git a/lustre/include/linux/lustre_smfs.h b/lustre/include/linux/lustre_smfs.h index afc3367..e6d907c 100644 --- a/lustre/include/linux/lustre_smfs.h +++ b/lustre/include/linux/lustre_smfs.h @@ -496,7 +496,6 @@ static inline int smfs_do_cow(struct inode *inode) return 0; } - extern int smfs_write_extents(struct inode *dir, struct dentry *dentry, unsigned long from, unsigned long num); extern int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa); diff --git a/lustre/include/linux/lvfs.h b/lustre/include/linux/lvfs.h index 8f2189b..4c3c8e1 100644 --- a/lustre/include/linux/lvfs.h +++ b/lustre/include/linux/lvfs.h @@ -47,6 +47,7 @@ struct mds_grp_hash_entry; struct lvfs_ucred { struct lustre_sec_desc *luc_lsd; struct group_info *luc_ginfo; + __u64 luc_nid; __u32 luc_uid; __u32 luc_gid; __u32 luc_fsuid; diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index 5d1d006..fcc8d8d 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -625,6 +625,7 @@ enum llog_ctxt_id { LLOG_TEST_ORIG_CTXT = 10, LLOG_TEST_REPL_CTXT = 11, LLOG_REINT_ORIG_CTXT = 12, + LLOG_AUDIT_ORIG_CTXT = 13, LLOG_MAX_CTXTS }; diff --git a/lustre/include/lustre/lustre_user.h b/lustre/include/lustre/lustre_user.h index 2c1eadd..194c7e1 100644 --- a/lustre/include/lustre/lustre_user.h +++ b/lustre/include/lustre/lustre_user.h @@ -70,7 +70,7 @@ #define LL_IOC_KEY_TYPE _IOW ('f', 171, long) #define LL_IOC_DISABLE_CRYPTO _IOW ('f', 172, long) #define LL_IOC_ENABLE_CRYPTO _IOW ('f', 173, long) - +#define LL_IOC_AUDIT _IOW ('f', 174, __u64) #define O_LOV_DELAY_CREATE 0100000000 /* hopefully this does not conflict */ diff --git a/lustre/kernel_patches/patches/nid-2.6-fc3.patch b/lustre/kernel_patches/patches/nid-2.6-fc3.patch new file mode 100644 index 0000000..cbcbbca --- /dev/null +++ b/lustre/kernel_patches/patches/nid-2.6-fc3.patch @@ -0,0 +1,12 @@ +Index: linux-2.6.10/kernel/sched.c +=================================================================== +--- linux-2.6.10.orig/include/linux/sched.h 2005-04-06 15:38:35.000000000 +0000 ++++ linux-2.6.10/include/linux/sched.h 2005-07-06 15:06:06.000000000 +0000 +@@ -365,6 +376,7 @@ struct user_struct { + /* Hash table maintenance information */ + struct list_head uidhash_list; + uid_t uid; ++ __u64 nid; + }; + + extern struct user_struct *find_user(uid_t); diff --git a/lustre/kernel_patches/series/2.6-fc3-uml.series b/lustre/kernel_patches/series/2.6-fc3-uml.series index 6abe6cc..6dde515 100644 --- a/lustre/kernel_patches/series/2.6-fc3-uml.series +++ b/lustre/kernel_patches/series/2.6-fc3-uml.series @@ -25,4 +25,6 @@ jbd-2.6.10-jcberr.patch hostfs_readdir_large.patch vfs-intent_release_umount-vanilla-2.6.10-fc3.patch vfs-umount_lustre-vanilla-2.6.10-fc3.patch +nid-2.6-fc3.patch pag-basic-2.6.10-fc3.patch + diff --git a/lustre/kernel_patches/series/2.6-fc3.series b/lustre/kernel_patches/series/2.6-fc3.series index 1f7c36e..eca1d49 100644 --- a/lustre/kernel_patches/series/2.6-fc3.series +++ b/lustre/kernel_patches/series/2.6-fc3.series @@ -28,5 +28,7 @@ linux-2.6.10-fc3-lkcd.patch vfs-intent_release_umount-vanilla-2.6.10-fc3.patch vfs-umount_lustre-vanilla-2.6.10-fc3.patch export-show_task-2.6-vanilla.patch +nid-2.6-fc3.patch highmem-split-2.6.10-fc3.patch pag-basic-2.6.10-fc3.patch + diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index 300a3da..606ccc8 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -1008,7 +1008,7 @@ int ldlm_run_cp_ast_work(struct list_head *rpc_list) * will never call the local blocking_ast until we drop our * reader/writer reference, which we won't do until we get the * reply and finish enqueueing. */ - + list_for_each_safe(tmp, pos, rpc_list) { struct ldlm_lock *lock = list_entry(tmp, struct ldlm_lock, l_cp_ast); diff --git a/lustre/llite/Makefile.in b/lustre/llite/Makefile.in index fe89a59..9e91583 100644 --- a/lustre/llite/Makefile.in +++ b/lustre/llite/Makefile.in @@ -1,6 +1,7 @@ MODULES := llite llite-objs := dcache.o dir.o file.o llite_close.o llite_gns.o llite_lib.o llite_nfs.o -llite-objs += rw.o lproc_llite.o namei.o special.o symlink.o llite_mmap.o llite_gs.o +llite-objs += rw.o lproc_llite.o namei.o special.o symlink.o llite_mmap.o +llite-objs += llite_gs.o llite_audit.o ifeq ($(PATCHLEVEL),4) llite-objs += rw24.o super.o diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 2d144d7..bd74819 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include "llite_internal.h" @@ -906,6 +907,8 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file, } case LL_IOC_FLUSH_CRED: RETURN(ll_flush_cred(inode)); + case LL_IOC_AUDIT: + RETURN(ll_set_audit(inode, SET_AUDIT_OP(arg, AUDIT_DIR))); default: return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL, (void *)arg); diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 608606b..ae4c449 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -31,8 +31,9 @@ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) #include #endif -#include "llite_internal.h" #include +#include +#include "llite_internal.h" __u64 lov_merge_size(struct lov_stripe_md *lsm, int kms); __u64 lov_merge_blocks(struct lov_stripe_md *lsm); @@ -385,6 +386,7 @@ int ll_local_open(struct file *file, struct lookup_intent *it, file->private_data = fd; ll_readahead_init(file->f_dentry->d_inode, &fd->fd_ras); fd->fd_omode = it->it_flags; + RETURN(0); } @@ -547,6 +549,11 @@ int ll_file_open(struct inode *inode, struct file *file) file->f_flags &= ~O_LOV_DELAY_CREATE; GOTO(out, rc); out: + /* audit stuff if there was no RPC */ + if (LUSTRE_IT(it)->it_data == 0) { + ll_audit_log(inode, AUDIT_OPEN, rc); + } + req = LUSTRE_IT(it)->it_data; ll_intent_drop_lock(it); ll_intent_release(it); @@ -1040,7 +1047,7 @@ int ll_extent_lock(struct ll_file_data *fd, struct inode *inode, CDEBUG(D_DLMTRACE, "Locking inode %lu, start "LPU64" end "LPU64"\n", inode->i_ino, policy->l_extent.start, policy->l_extent.end); - do_gettimeofday(&start); + do_gettimeofday(&start); rc = obd_enqueue(sbi->ll_dt_exp, lsm, LDLM_EXTENT, policy, mode, &ast_flags, ll_extent_lock_callback, ldlm_completion_ast, ll_glimpse_callback, inode, @@ -1121,7 +1128,7 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count, LCK_PR); tree.lt_fd = file->private_data; - + rc = ll_tree_lock(&tree, node, inode, buf, count, file->f_flags & O_NONBLOCK ? LDLM_FL_BLOCK_NOWAIT :0); if (rc != 0) @@ -1143,7 +1150,7 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count, CDEBUG(D_INFO, "Read ino %lu, "LPSZ" bytes, offset %lld, i_size %llu\n", inode->i_ino, count, *ppos, inode->i_size); - + /* turn off the kernel's read-ahead */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) file->f_ramax = 0; @@ -1151,6 +1158,7 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count, file->f_ra.ra_pages = 0; #endif retval = generic_file_read(file, buf, count, ppos); + ll_audit_log(inode, AUDIT_READ, retval); out: ll_tree_unlock(&tree, inode); @@ -1198,7 +1206,7 @@ static ssize_t ll_file_write(struct file *file, const char *buf, RETURN(PTR_ERR(node)); tree.lt_fd = file->private_data; - + rc = ll_tree_lock(&tree, node, inode, buf, count, file->f_flags & O_NONBLOCK ? LDLM_FL_BLOCK_NOWAIT :0); if (rc != 0) @@ -1226,8 +1234,11 @@ static ssize_t ll_file_write(struct file *file, const char *buf, /* generic_file_write handles O_APPEND after getting i_sem */ retval = generic_file_write(file, buf, count, ppos); + EXIT; out: + ll_audit_log(inode, AUDIT_WRITE, retval); + ll_tree_unlock(&tree, inode); /* serialize with mmap/munmap/mremap */ lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, LPROC_LL_WRITE_BYTES, @@ -1565,6 +1576,8 @@ int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd, */ case LL_IOC_FLUSH_CRED: RETURN(ll_flush_cred(inode)); + case LL_IOC_AUDIT: + RETURN(ll_set_audit(inode, arg)); default: RETURN( obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL, (void *)arg) ); diff --git a/lustre/llite/llite_audit.c b/lustre/llite/llite_audit.c new file mode 100644 index 0000000..0c7cd9a --- /dev/null +++ b/lustre/llite/llite_audit.c @@ -0,0 +1,104 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (c) 2002, 2003 Cluster File Systems, Inc. + * + * osc_audit.c - audit code for client side. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define DEBUG_SUBSYSTEM S_LLITE +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "llite_internal.h" + +//audit is set via obd_set_info() on mds +int ll_set_audit(struct inode * inode, __u64 arg) +{ + struct audit_attr_msg msg; + struct obd_export * exp = ll_i2mdexp(inode); + int rc; + + msg.attr = arg; + msg.id = ll_i2info(inode)->lli_id; + //set audit on MDS (fs/dir/file) + rc = obd_set_info(exp, 5, "audit", sizeof(msg), &msg); + + //if fs audit is being set for fs then pass attr to all OSS + if (IS_AUDIT_OP(arg, AUDIT_FS)) { + exp = ll_i2dtexp(inode); + rc = obd_set_info(exp, 5, "audit", sizeof(msg), &msg); + } + return rc; +} + +int ll_check_audit(struct inode * inode, audit_op op, int ret) +{ + __u64 mask = 0; + + LASSERT(op < AUDIT_MAX); + //check fs audit + if (IS_AUDIT(ll_s2sbi(inode->i_sb)->ll_audit_mask)) { + mask = ll_s2sbi(inode->i_sb)->ll_audit_mask; + } + else if (IS_AUDIT(ll_i2info(inode)->lli_audit_mask)) { + mask = ll_i2info(inode)->lli_audit_mask; + } + else + return 0; + + //if audit is only for failures? + if (!ret && IS_AUDIT_OP(mask, AUDIT_FAIL)) + return 0; + + return (IS_AUDIT_OP(mask,op)); +} +/* + * this function send audit record data to selected OST + * obd_set_info() RPC is using for this with key "auditlog" + */ + +int ll_audit_log (struct inode * inode, audit_op code, int ret) +{ + struct audit_msg msg; + //struct lustre_id * id = &msg.id; + struct obd_export * exp = ll_i2dtexp(inode); + int rc = 0; + + if (ll_check_audit(inode, code, ret)) { + msg.id = ll_i2info(inode)->lli_id; + msg.code = code; + msg.result = ret; + msg.uid = current->fsuid; + msg.gid = current->fsgid; + msg.nid = 0xFEED; + + rc = obd_set_info(exp, 8, "auditlog", sizeof(msg), &msg); + } + + RETURN(rc); +} + diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 8a58404..d3cba8c 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -11,6 +11,7 @@ #define LLITE_INTERNAL_H #include +#include /* default to about 40meg of readahead on a given system. That much tied * up in 512k readahead requests serviced at 40ms each is about 1GB/s. */ @@ -56,7 +57,7 @@ struct ll_sb_info { struct lov_desc ll_dt_desc; struct proc_dir_entry *ll_proc_root; struct lustre_id ll_rootid; /* root lustre id */ - + struct lustre_mount_data *ll_lmd; char *ll_instance; @@ -74,7 +75,8 @@ struct ll_sb_info { struct ll_ra_info ll_ra_info; unsigned int ll_remote; /* remote client? */ - + + __u64 ll_audit_mask; /* times spent waiting for locks in each call site. These are * all protected by the ll_lock */ struct obd_service_time ll_read_stime; @@ -333,6 +335,8 @@ int ll_md_och_close(struct obd_export *md_exp, struct inode *inode, struct obd_client_handle *och, int dirty); void ll_och_fill(struct inode *inode, struct lookup_intent *it, struct obd_client_handle *och); +int ll_set_audit(struct inode *, __u64); +int ll_audit_log(struct inode *, audit_op, int); int ll_getxattr_internal(struct inode *inode, const char *name, void *value, size_t size, __u64 valid); @@ -450,7 +454,15 @@ typedef struct rb_root rb_root_t; typedef struct rb_node rb_node_t; #endif -struct ll_lock_tree_node; +struct ll_lock_tree_node { + rb_node_t lt_node; + struct list_head lt_locked_item; + __u64 lt_oid; + ldlm_policy_data_t lt_policy; + struct lustre_handle lt_lockh; + ldlm_mode_t lt_mode; +}; +//struct ll_lock_tree_node; struct ll_lock_tree { rb_root_t lt_root; struct list_head lt_locked_list; diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index ce919b7..96e5658 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include "llite_internal.h" @@ -94,7 +95,8 @@ struct ll_sb_info *lustre_init_sbi(struct super_block *sb) sbi->ll_gns_timer.data = (unsigned long)sbi; sbi->ll_gns_timer.function = ll_gns_timer_callback; init_timer(&sbi->ll_gns_timer); - + //audit mask + sbi->ll_audit_mask = AUDIT_OFF; ll_set_sbi(sb, sbi); generate_random_uuid(uuid); @@ -574,6 +576,7 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_mds_exec_och = NULL; lli->lli_open_fd_read_count = lli->lli_open_fd_write_count = 0; lli->lli_open_fd_exec_count = 0; + lli->lli_audit_mask = AUDIT_OFF; lli->lli_key_info = NULL; } @@ -618,6 +621,8 @@ out: OBD_FREE(mds_sec, strlen(mds_sec) + 1); if (oss_sec) OBD_FREE(oss_sec, strlen(oss_sec) + 1); + if (gkc) + OBD_FREE(gkc, strlen(gkc) + 1); return err; } /* ll_read_super */ @@ -2039,6 +2044,14 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) if (body->valid & OBD_MD_FLSIZE) set_bit(LLI_F_HAVE_MDS_SIZE_LOCK, &lli->lli_flags); + if (body->valid & OBD_MD_FLAUDIT) { + struct ll_sb_info * sbi = ll_s2sbi(inode->i_sb); + if (IS_AUDIT_OP(body->audit, AUDIT_FS)) + sbi->ll_audit_mask = body->audit; + else + lli->lli_audit_mask = body->audit; + } + if (mkey != NULL) { LASSERT(body->valid & OBD_MD_FLKEY); ll_crypto_init_inode_key(inode, mkey); diff --git a/lustre/llite/llite_mmap.c b/lustre/llite/llite_mmap.c index ec56b96..70dcf8a 100644 --- a/lustre/llite/llite_mmap.c +++ b/lustre/llite/llite_mmap.c @@ -48,10 +48,11 @@ #include #include +#include #include "llite_internal.h" #include - +/* struct ll_lock_tree_node { rb_node_t lt_node; struct list_head lt_locked_item; @@ -60,7 +61,7 @@ struct ll_lock_tree_node { struct lustre_handle lt_lockh; ldlm_mode_t lt_mode; }; - +*/ __u64 lov_merge_size(struct lov_stripe_md *lsm, int kms); int lt_get_mmap_locks(struct ll_lock_tree *tree, struct inode *inode, unsigned long addr, size_t count); @@ -568,6 +569,9 @@ static struct vm_operations_struct ll_file_vm_ops = { .close = ll_close_vma, }; +/* Audit functions */ +extern int ll_audit_log (struct inode *, audit_op, int); + int ll_file_mmap(struct file * file, struct vm_area_struct * vma) { int rc; @@ -577,10 +581,13 @@ int ll_file_mmap(struct file * file, struct vm_area_struct * vma) if (rc == 0) { struct ll_inode_info *lli = ll_i2info(file->f_dentry->d_inode); vma->vm_ops = &ll_file_vm_ops; + /* mark i/o epoch dirty */ if (vma->vm_flags & VM_SHARED) set_bit(LLI_F_DIRTY_HANDLE, &lli->lli_flags); } + + ll_audit_log(file->f_dentry->d_inode, AUDIT_MMAP, rc); RETURN(rc); } diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c index 634a454..7535447 100644 --- a/lustre/llite/rw.c +++ b/lustre/llite/rw.c @@ -366,7 +366,7 @@ void ll_inode_fill_obdo(struct inode *inode, int cmd, struct obdo *oa) oa->o_gr = lsm->lsm_object_gr; oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP; valid_flags = OBD_MD_FLTYPE | OBD_MD_FLATIME; - if (cmd == OBD_BRW_WRITE) { + if (cmd == OBD_BRW_WRITE || cmd == OBD_BRW_READ) { oa->o_valid |= OBD_MD_FLIFID | OBD_MD_FLEPOCH; *(obdo_id(oa)) = ll_i2info(inode)->lli_id; oa->o_easize = ll_i2info(inode)->lli_io_epoch; diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index 02198dc..79d2aff 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "lmv_internal.h" /* not defined for liblustre building */ @@ -2001,7 +2002,51 @@ int lmv_set_info(struct obd_export *exp, obd_count keylen, RETURN(rc); } - + if (keylen == 5 && strcmp(key, "audit") == 0) { + struct audit_attr_msg * msg = val; + int mds = id_group(&msg->id); + int i, rc = 0; + LASSERT(mds < lmv->desc.ld_tgt_count); + + if (IS_AUDIT_OP(msg->attr, AUDIT_FS)) { + //FS audit, send message to all mds + for (i = 0; i < lmv->desc.ld_tgt_count;i++) { + obd_set_info(lmv->tgts[i].ltd_exp, + keylen, key, vallen, val); + } + } + else if (IS_AUDIT_OP(msg->attr, AUDIT_DIR)) { + //audit for dir. + //if dir is splitted, send RPC to all mds involved + struct lmv_obj *obj; + struct lustre_id rid; + int i; + + obj = lmv_grab_obj(obd, &msg->id); + if (obj) { + lmv_lock_obj(obj); + for (i = 0; i < obj->objcount; i++) { + rid = obj->objs[i].id; + mds = id_group(&rid); + obd_set_info(lmv->tgts[mds].ltd_exp, + keylen, key, + vallen, val); + } + lmv_unlock_obj(obj); + lmv_put_obj(obj); + } + else { + rc = obd_set_info(lmv->tgts[mds].ltd_exp, + keylen, key, vallen, val); + } + } + else { + //set audit for file + rc = obd_set_info(lmv->tgts[mds].ltd_exp, + keylen, key, vallen, val); + } + RETURN(rc); + } if (((keylen == strlen("flush_cred") && strcmp(key, "flush_cred") == 0)) || ((keylen == strlen("crypto_type") && diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index 9cc2c6d..585d3bb 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -48,7 +48,7 @@ #include #include #include - +#include #include "lov_internal.h" /* obd methods */ @@ -2130,6 +2130,89 @@ static int lov_set_info(struct obd_export *exp, obd_count keylen, spin_unlock(&lov->lov_lock); RETURN(rc); + } else if (KEY_IS("auditlog")) { + ptl_nid_t nid = 0; + struct audit_msg * msg = val; + int i = 0, len = sizeof(nid); + struct obd_export * ost_exp; + //try to find client nid + for (i = 0; i < lov->desc.ld_tgt_count; i++) { + if (!lov->tgts[i].ltd_exp) + continue; + rc = obd_get_info(lov->tgts[i].ltd_exp, 10, + "client_nid", &len, &nid); + if (!rc) + break; + } + + i = (__u32)nid % lov->desc.ld_tgt_count; + + CDEBUG(D_INFO, "Select OST %i for nid %.8x\n",i, (__u32)nid); + + ost_exp = lov->tgts[i].ltd_exp; + if (!ost_exp) { + CERROR("can't send auditlog data," + "device %s is not attached?\n", + lov->tgts[i].uuid.uuid); + RETURN(-EFAULT); + } + msg->nid = nid; + rc = obd_set_info(ost_exp, keylen, key, vallen, val); + + RETURN(rc); + } else if (KEY_IS("audit_obj")) { + struct audit_lov_msg * msg = val; + int i = 0, index; + struct obd_export * ost_exp; + struct lov_oinfo *loi; + struct obdo *oa = NULL; + + oa = obdo_alloc(); + if (oa == NULL) + RETURN(-ENOMEM); + + //set audit for all objects of file + CDEBUG(D_INFO, "Set audit 0x%x for objects\n", (__u32)msg->mask); + //use o_fid to store audit mask + oa->o_fid = msg->mask; + oa->o_uid = msg->uid; + oa->o_gid = msg->gid; + //iterate over all objects and set audit for each + for (i = 0, loi = msg->lsm->lsm_oinfo; + i < msg->lsm->lsm_stripe_count; i++, loi++) { + index = loi->loi_ost_idx; + ost_exp = lov->tgts[index].ltd_exp; + if (!ost_exp) { + CERROR("can't send audit_obj data," + "device %s is not attached?\n", + lov->tgts[i].uuid.uuid); + continue; + } + oa->o_id = loi->loi_id; + oa->o_gr = loi->loi_gr; + + obd_set_info(ost_exp, keylen, key, sizeof(*oa), oa); + } + + obdo_free(oa); + RETURN(0); + } else if (KEY_IS("audit")) { + int i = 0; + struct obd_export * ost_exp; + + //set audit for whole fs on OSS + for (i = 0; i < lov->desc.ld_tgt_count; i++) { + ost_exp = lov->tgts[i].ltd_exp; + if (!ost_exp) { + CERROR("can't send audit_fs data," + "device %s is not attached?\n", + lov->tgts[i].uuid.uuid); + continue; + } + obd_set_info(ost_exp, keylen, key, vallen, val); + } + + RETURN(rc); } else if (KEY_IS("flush_cred") || KEY_IS("crypto_cb")) { struct lov_tgt_desc *tgt; int rc = 0, i; diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c index 52dde66..bdb6252 100644 --- a/lustre/lvfs/fsfilt_ext3.c +++ b/lustre/lvfs/fsfilt_ext3.c @@ -79,6 +79,7 @@ struct fsfilt_cb_data { #define XATTR_LUSTRE_MDS_MEA_EA "mea" #define XATTR_LUSTRE_MDS_MID_EA "mid" #define XATTR_LUSTRE_MDS_SID_EA "sid" +#define XATTR_LUSTRE_MDS_PID_EA "pid" #define XATTR_LUSTRE_MDS_KEY_EA "key" /* @@ -513,6 +514,11 @@ static int fsfilt_ext3_set_md(struct inode *inode, void *handle, XATTR_LUSTRE_MDS_MID_EA, lmm, lmm_size); break; + case EA_PID: + rc = fsfilt_ext3_set_xattr(inode, handle, + XATTR_LUSTRE_MDS_PID_EA, + lmm, lmm_size); + break; case EA_KEY: rc = fsfilt_ext3_set_xattr(inode, handle, XATTR_LUSTRE_MDS_KEY_EA, @@ -551,6 +557,11 @@ static int fsfilt_ext3_get_md(struct inode *inode, void *lmm, XATTR_LUSTRE_MDS_MID_EA, lmm, lmm_size); break; + case EA_PID: + rc = fsfilt_ext3_get_xattr(inode, + XATTR_LUSTRE_MDS_PID_EA, + lmm, lmm_size); + break; case EA_KEY: rc = fsfilt_ext3_get_xattr(inode, XATTR_LUSTRE_MDS_KEY_EA, diff --git a/lustre/lvfs/lvfs_linux.c b/lustre/lvfs/lvfs_linux.c index b4fb970..2db772c 100644 --- a/lustre/lvfs/lvfs_linux.c +++ b/lustre/lvfs/lvfs_linux.c @@ -153,12 +153,14 @@ void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx, save->luc.luc_fsuid = current->fsuid; save->luc.luc_fsgid = current->fsgid; save->luc.luc_cap = current->cap_effective; - + save->luc.luc_nid = current->user->nid; + current->uid = uc->luc_uid; current->gid = uc->luc_gid; current->fsuid = uc->luc_fsuid; current->fsgid = uc->luc_fsgid; current->cap_effective = uc->luc_cap; + current->user->nid = uc->luc_nid; push_group_info(save, uc->luc_ginfo); } @@ -216,7 +218,7 @@ void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx, current->fsuid = saved->luc.luc_fsuid; current->fsgid = saved->luc.luc_fsgid; current->cap_effective = saved->luc.luc_cap; - + current->user->nid = saved->luc.luc_nid; pop_group_info(saved, uc->luc_ginfo); } diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 8362bd8..8bed91e 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -935,6 +935,39 @@ int mdc_set_info(struct obd_export *exp, obd_count keylen, CDEBUG(D_HA, "%s: set async = %d\n", exp->exp_obd->obd_name, cl->cl_async); RETURN(0); + } else if (keylen == 5 && strcmp(key, "audit") == 0) { + struct ptlrpc_request *req; + char *bufs[2] = {key, val}; + int rc, size[2] = {keylen, vallen}; + + req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OBD_VERSION, + OST_SET_INFO, 2, size, bufs); + if (req == NULL) + RETURN(-ENOMEM); + + req->rq_replen = lustre_msg_size(0, NULL); + lustre_swab_reqbuf(req, 1, sizeof(struct audit_attr_msg), + lustre_swab_audit_attr); + rc = ptlrpc_queue_wait(req); + ptlrpc_req_finished(req); + + RETURN(rc); + } else if (keylen == strlen("ids") && memcmp(key, "ids", keylen) == 0) { + struct ptlrpc_request *req; + struct lustre_id *ids = (struct lustre_id *)val; + char *bufs[3] = {key, (char *)ids, (char *)(ids + 1)}; + int rc, size[3] = {keylen, sizeof(struct lustre_id), + sizeof(struct lustre_id)}; + + req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OBD_VERSION, + OST_SET_INFO, 3, size, bufs); + if (req == NULL) + RETURN(-ENOMEM); + + req->rq_replen = lustre_msg_size(0, NULL); + rc = ptlrpc_queue_wait(req); + ptlrpc_req_finished(req); + RETURN(rc); } RETURN(rc); } @@ -1317,7 +1350,8 @@ static int mdc_get_info(struct obd_export *exp, __u32 keylen, if ((keylen < strlen("mdsize") || strcmp(key, "mdsize") != 0) && (keylen < strlen("mdsnum") || strcmp(key, "mdsnum") != 0) && - (keylen < strlen("rootid") || strcmp(key, "rootid") != 0)) + (keylen < strlen("rootid") || strcmp(key, "rootid") != 0) && + (keylen < strlen("auditid") || strcmp(key, "auditid") != 0)) RETURN(-EPROTO); req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OBD_VERSION, @@ -1330,7 +1364,8 @@ static int mdc_get_info(struct obd_export *exp, __u32 keylen, if (rc) GOTO(out_req, rc); - if (keylen >= strlen("rootid") && !strcmp(key, "rootid")) { + if ((keylen >= strlen("rootid") && !strcmp(key, "rootid")) || + (keylen >= strlen("auditid") && !strcmp(key, "auditid"))) { struct lustre_id *reply; reply = lustre_swab_repbuf(req, 0, sizeof(*reply), diff --git a/lustre/mds/Makefile.in b/lustre/mds/Makefile.in index a7278e2..a3032e2 100644 --- a/lustre/mds/Makefile.in +++ b/lustre/mds/Makefile.in @@ -1,6 +1,6 @@ MODULES := mds mds-objs := mds_log.o mds_unlink_open.o mds_lov.o handler.o mds_reint.o mds-objs += mds_fs.o lproc_mds.o mds_open.o mds_lib.o mds_lmv.o mds_lsd.o -mds-objs += mds_acl.o +mds-objs += mds_audit_path.o mds_audit.o mds_acl.o @INCLUDE_RULES@ diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 41b73c5..622202b 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -59,6 +59,15 @@ #include #include "mds_internal.h" #include +#include + +extern int mds_audit_auth(struct ptlrpc_request *, struct lvfs_ucred *, + audit_op, struct lustre_id *, + char *, int); +extern int mds_audit_stat(struct ptlrpc_request *, struct lustre_id *, + struct dentry *, int); +extern int mds_audit_open(struct ptlrpc_request *, struct mds_update_record *, + int); static int mds_intent_policy(struct ldlm_namespace *ns, struct ldlm_lock **lockp, void *req_cookie, @@ -1224,7 +1233,9 @@ static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry, if (reqbody->valid & OBD_MD_FLKEY) { rc = mds_pack_gskey(obd, req->rq_repmsg, &offset, body, inode); - } + } + + mds_pack_audit(obd, inode, body); if (rc == 0) mds_body_do_reverse_map(med, body); @@ -1379,7 +1390,7 @@ int mds_check_mds_num(struct obd_device *obd, struct inode *inode, rc = mds_md_get_attr(obd, inode, &mea, &mea_size); if (rc) RETURN(rc); - if (mea != NULL) { + if (mea != NULL && mea->mea_count) { /* * dir is already splitted, check if requested filename should * live at this MDS or at another one. @@ -1486,6 +1497,9 @@ static int mds_getattr_lock(struct ptlrpc_request *req, int offset, rc = mds_init_ucred(&uc, req, rsd); if (rc) { + if (child_lockh->cookie == 0) + mds_audit_auth(req, &uc, AUDIT_STAT, &body->id1, + name, namesize); GOTO(cleanup, rc); } @@ -1648,6 +1662,10 @@ static int mds_getattr_lock(struct ptlrpc_request *req, int offset, #endif if (dparent) l_dput(dparent); + + /* audit stuff for getattr */ + if (dchild->d_inode) + mds_audit_stat(req, &body->id1, dchild, rc); } l_dput(dchild); case 1: @@ -1918,6 +1936,8 @@ static int mds_readpage(struct ptlrpc_request *req, int offset) rc = mds_init_ucred(&uc, req, rsd); if (rc) { + mds_audit_auth(req, &uc, AUDIT_READDIR, &body->id1, + NULL, 0); GOTO(out, rc); } @@ -2129,12 +2149,49 @@ int mds_reint(struct ptlrpc_request *req, int offset, rc = mds_init_ucred(&rec->ur_uc, req, rsd); if (rc) { + audit_op code = AUDIT_NONE; + char * au_name = NULL; + int au_len = 0; + switch (rec->ur_opcode) { + case REINT_SETATTR: + code = AUDIT_SETATTR; + break; + case REINT_CREATE: + code = AUDIT_CREATE; + au_name = rec->ur_name; + au_len = rec->ur_namelen; + break; + case REINT_LINK: + code = AUDIT_LINK; + break; + case REINT_UNLINK: + code = AUDIT_UNLINK; + break; + case REINT_RENAME: + code = AUDIT_RENAME; + break; + case REINT_OPEN: + au_name = rec->ur_name; + au_len = rec->ur_namelen; + code = AUDIT_OPEN; + break; + default: + CERROR("Wrong opcode in reint\n"); + LBUG(); + } + + mds_audit_auth(req, &rec->ur_uc, code, rec->ur_id1, + au_name, au_len); GOTO(out, rc); } /* rc will be used to interrupt a for loop over multiple records */ rc = mds_reint_rec(rec, offset, req, lockh); + /* audit stuff for OPEN */ + if (offset == 3 && rec->ur_opcode == REINT_OPEN) + mds_audit_open(req, rec, rc); + out: mds_exit_ucred(&rec->ur_uc); OBD_FREE(rec, sizeof(*rec)); @@ -2514,37 +2571,13 @@ repeat: if ((body->oa.o_flags & OBD_FL_RECREATE_OBJS) || lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) { - id_group(&id) = mds->mds_num; - - LASSERT(body->oa.o_fid != 0); - id_fid(&id) = body->oa.o_fid; - LASSERT(body->oa.o_id != 0); - id_ino(&id) = repbody->oa.o_id; - id_gen(&id) = repbody->oa.o_generation; - - down(&new->d_inode->i_sem); - rc = mds_update_inode_sid(obd, new->d_inode, handle, &id); - up(&new->d_inode->i_sem); - - /* - * make sure, that fid is up-to-date. - */ - mds_set_last_fid(obd, id_fid(&id)); - } else { - /* - * allocate new sid, as object is created from scratch - * and this is not replay. - */ - down(&new->d_inode->i_sem); - rc = mds_set_inode_sid(obd, new->d_inode, handle, &id, fid); - up(&new->d_inode->i_sem); - } - if (rc) { - CERROR("Can't update lustre ID for inode %lu, " - "error = %d\n", new->d_inode->i_ino, rc); - GOTO(cleanup, rc); + LASSERT(body->oa.o_fid != 0); } + + mds_inode2id(obd, &id, new->d_inode, fid); + mds_update_inode_ids(obd, new->d_inode, handle, &id, + obdo_id(&body->oa)); /* initializing o_fid after it is allocated. */ repbody->oa.o_fid = id_fid(&id); @@ -2580,8 +2613,10 @@ repeat: GOTO(cleanup, rc = -ENOMEM); mea->mea_magic = MEA_MAGIC_ALL_CHARS; - mea->mea_master = 0; + mea->mea_master = body->oa.o_mds; /* master mds num */ mea->mea_count = 0; + + obdo2id(&mea->mea_ids[body->oa.o_mds], &body->oa); down(&new->d_inode->i_sem); rc = fsfilt_set_md(obd, new->d_inode, handle, @@ -2703,7 +2738,47 @@ static int mds_set_info(struct obd_export *exp, __u32 keylen, rc = obd_set_info(mds->mds_dt_exp, strlen("mds_conn"), "mds_conn", valsize, &group); RETURN(rc); + } else if (keylen == 5 && memcmp(key, "audit", 5) == 0) { + rc = mds_set_audit(obd, val); + RETURN(rc); + } else if (keylen >= strlen("ids") && memcmp(key, "ids", keylen) == 0) { + struct lustre_id *ids = (struct lustre_id *)val; + struct dentry *de; + struct inode *inode; + void *handle; + int err; + + de = mds_id2dentry(obd, ids, NULL); + if (IS_ERR(de)) { + rc = PTR_ERR(de); + CERROR("lookup by an id error %d\n", rc); + RETURN(rc); + } + inode = de->d_inode; + if (inode == NULL) + GOTO(out_put, rc = -ENOENT); + + down(&inode->i_sem); + handle = fsfilt_start(obd, inode, FSFILT_OP_SETATTR, NULL); + if (IS_ERR(handle)) { + up(&inode->i_sem); + GOTO(out_put, rc = PTR_ERR(handle)); + } + + rc = mds_update_inode_ids(obd, inode, handle, NULL, ids + 1); + + err = fsfilt_commit(obd, mds->mds_sb, inode, handle, + exp->exp_sync); + if (err) { + CERROR("error committing transaction: %d\n", err); + if (!rc) rc = err; + } + up(&inode->i_sem); +out_put: + l_dput(de); + RETURN(rc); } + if (keylen >= strlen("crypto_type") && memcmp(key, "crypto_type", keylen) == 0) { rc = mds_set_crypto_type(obd, val, vallen); @@ -2718,7 +2793,7 @@ static int mdt_set_info(struct ptlrpc_request *req) { char *key, *val; struct obd_export *exp = req->rq_export; - int keylen, rc = 0, vallen; + int keylen, rc = 0, vallen = 0; ENTRY; key = lustre_msg_buf(req->rq_reqmsg, 0, 1); @@ -2742,7 +2817,42 @@ static int mdt_set_info(struct ptlrpc_request *req) rc = obd_set_info(exp, keylen, key, vallen, val); req->rq_repmsg->status = 0; RETURN(rc); + } else if (keylen == 5 && memcmp(key, "audit", 5) == 0) { + struct audit_attr_msg msg, *p; + int rc = 0; + + rc = lustre_pack_reply(req, 0, NULL, NULL); + if (rc) + RETURN(rc); + + p = lustre_swab_reqbuf(req, 1, sizeof(msg), + lustre_swab_audit_attr); + + msg = *p; + CDEBUG(D_INFO, "Get new audit setting 0x%x\n", (__u32)msg.attr); + rc = obd_set_info(exp, keylen, key, sizeof(msg), &msg); + + req->rq_repmsg->status = rc; + RETURN(rc); + } else if (keylen == strlen("ids") && + memcmp(key, "ids", keylen) == 0) { + struct lustre_id *id, ids[2]; + + rc = lustre_pack_reply(req, 0, NULL, NULL); + if (rc) + RETURN(rc); + id = lustre_swab_reqbuf(req, 1, sizeof(struct lustre_id), + lustre_swab_lustre_id); + ids[1] = *id; + id = lustre_swab_reqbuf(req, 2, sizeof(struct lustre_id), + lustre_swab_lustre_id); + ids[2] = *id; + + rc = obd_set_info(exp, keylen, key, vallen, ids); + req->rq_repmsg->status = rc; + RETURN(rc); } + CDEBUG(D_IOCTL, "invalid key\n"); RETURN(-EINVAL); } @@ -3105,7 +3215,10 @@ int mds_handle(struct ptlrpc_request *req) OBD_FAIL_RETURN(OBD_FAIL_MDS_SYNC_NET, 0); rc = mds_sync(req, MDS_REQ_REC_OFF); break; - + case MDS_PARSE_ID: + DEBUG_REQ(D_INODE, req, "parseid"); + rc = mds_parse_id(req); + break; case OBD_PING: DEBUG_REQ(D_INODE, req, "ping"); rc = target_handle_ping(req); @@ -3337,41 +3450,6 @@ __u64 mds_alloc_fid(struct obd_device *obd) return fid; } -/* - * update new lustre_id on passed @inode and saves it to inode EA. - */ -int mds_set_inode_sid(struct obd_device *obd, struct inode *inode, - void *handle, struct lustre_id *id, __u64 fid) -{ - struct mds_obd *mds = &obd->u.mds; - int alloc = 0, rc = 0; - ENTRY; - - LASSERT(obd != NULL); - LASSERT(inode != NULL); - - if (id == NULL) { - OBD_ALLOC(id, sizeof(*id)); - if (id == NULL) - RETURN(-ENOMEM); - alloc = 1; - } - id_group(id) = mds->mds_num; - id_fid(id) = fid; - id_ino(id) = inode->i_ino; - id_gen(id) = inode->i_generation; - id_type(id) = (S_IFMT & inode->i_mode); - - rc = mds_update_inode_sid(obd, inode, handle, id); - if (rc) { - CERROR("Can't update inode FID EA, " - "rc = %d\n", rc); - } - - if (alloc) - OBD_FREE(id, sizeof(*id)); - RETURN(rc); -} /* * reads inode self id from inode EA. Probably later this should be replaced by @@ -3399,26 +3477,56 @@ int mds_read_inode_sid(struct obd_device *obd, struct inode *inode, } else { rc = 0; } + id_ino(id) = inode->i_ino; + id_gen(id) = inode->i_generation; + id_type(id) = S_IFMT & inode->i_mode; + + RETURN(rc); +} + +int mds_read_inode_pid(struct obd_device *obd, struct inode *inode, + struct lustre_id *id) +{ + int rc; + ENTRY; + + LASSERT(inode && id); + + rc = fsfilt_get_md(obd, inode, id, sizeof(*id), EA_PID); + if (rc < 0) + CERROR("get parent id from EA failed, rc=%d\n", rc); + else if (!rc) + rc = -ENODATA; + else + rc = 0; RETURN(rc); } /* updates inode self id in EA. */ -int mds_update_inode_sid(struct obd_device *obd, struct inode *inode, - void *handle, struct lustre_id *id) +int mds_update_inode_ids(struct obd_device *obd, struct inode *inode, + void *handle, struct lustre_id *id, + struct lustre_id *pid) { int rc = 0; ENTRY; - - LASSERT(id != NULL); + + LASSERT(id || pid); + LASSERT(id == NULL || id_fid(id) != 0); + LASSERT(pid == NULL || id_fid(pid) != 0); LASSERT(obd != NULL); LASSERT(inode != NULL); - rc = fsfilt_set_md(obd, inode, handle, &id->li_fid, - sizeof(id->li_fid), EA_SID); - if (rc) { - CERROR("fsfilt_set_md() failed, rc = %d\n", rc); - RETURN(rc); + if (id) { + mds_set_last_fid(obd, id_fid(id)); + rc = fsfilt_set_md(obd, inode, handle, &id->li_fid, + sizeof(id->li_fid), EA_SID); + LASSERTF(rc == 0, "failed to update fid: %d\n", rc); + } + if (pid) { + rc = fsfilt_set_md(obd, inode, handle, pid, + sizeof(*pid), EA_PID); + LASSERTF(rc == 0, "failed to update parent fid: %d\n", rc); } RETURN(rc); @@ -3642,6 +3750,7 @@ static int mds_setup(struct obd_device *obd, obd_count len, void *buf) rc = mds_fs_setup_virtid(obd); if (rc) GOTO(err_fs, rc); + } ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL, @@ -3685,8 +3794,10 @@ static int mds_fs_post_setup(struct obd_device *obd) (int)PTR_ERR(dentry)); RETURN(PTR_ERR(dentry)); } - rc = fsfilt_post_setup(obd, dentry); + //set id2name function handler + fsfilt_set_info(obd, mds->mds_sb, NULL, 7, "id2name", + sizeof(mds_audit_id2name), mds_audit_id2name); l_dput(dentry); RETURN(rc); @@ -4134,7 +4245,7 @@ static int mds_intent_policy(struct ldlm_namespace *ns, fixup_handle_for_resent_req(req, MDS_REQ_INTENT_LOCKREQ_OFF, lock, NULL, lockh); rep->lock_policy_res2 = mds_reint(req, offset, lockh); - + if (rep->lock_policy_res2) { /* * mds_open() returns ENOLCK where it should return @@ -4389,6 +4500,7 @@ static int mds_get_info(struct obd_export *exp, __u32 keylen, { struct obd_device *obd; struct mds_obd *mds; + int rc = 0; ENTRY; obd = class_exp2obd(exp); @@ -4402,9 +4514,15 @@ static int mds_get_info(struct obd_export *exp, __u32 keylen, if (keylen >= strlen("reint_log") && memcmp(key, "reint_log", 9) == 0) { /* get log_context handle. */ + struct llog_ctxt *ctxt; unsigned long *llh_handle = val; *valsize = sizeof(unsigned long); - *llh_handle = (unsigned long)obd->obd_llog_ctxt[LLOG_REINT_ORIG_CTXT]; + ctxt = llog_get_context(&obd->obd_llogs, LLOG_REINT_ORIG_CTXT); + if (!ctxt) { + CERROR("Cannot get REINT llog context\n"); + RETURN(-ENOENT); + } + *llh_handle = (unsigned long)ctxt; RETURN(0); } if (keylen >= strlen("cache_sb") && memcmp(key, "cache_sb", 8) == 0) { @@ -4435,18 +4553,21 @@ static int mds_get_info(struct obd_export *exp, __u32 keylen, *rootid = mds->mds_rootid; RETURN(0); } - + if (keylen >= strlen("lovdesc") && strcmp(key, "lovdesc") == 0) { struct lov_desc *desc = val; *valsize = sizeof(*desc); *desc = mds->mds_dt_desc; RETURN(0); } - - CDEBUG(D_IOCTL, "invalid key\n"); - RETURN(-EINVAL); - + + rc = fsfilt_get_info(obd, mds->mds_sb, NULL, keylen, key, valsize, val); + if (rc) + CDEBUG(D_IOCTL, "invalid key\n"); + + RETURN(rc); } + struct lvfs_callback_ops mds_lvfs_ops = { l_id2dentry: mds_lvfs_id2dentry, }; diff --git a/lustre/mds/mds_audit.c b/lustre/mds/mds_audit.c new file mode 100644 index 0000000..71d1697 --- /dev/null +++ b/lustre/mds/mds_audit.c @@ -0,0 +1,261 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * lustre/mds/mds_audit.c + * Lustre Metadata Server (mds) audit stuff + * + * Copyright (c) 2001-2003 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif +#define DEBUG_SUBSYSTEM S_MDS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) +# include +# include +# include +# include +#else +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "mds_internal.h" + +int mds_audit_stat(struct ptlrpc_request *req, struct lustre_id * id, + struct dentry * dentry, int ret) +{ + struct obd_device *obd = req->rq_export->exp_obd; + struct inode * inode = dentry->d_inode; + ptl_nid_t nid = req->rq_peer.peer_id.nid; + struct audit_info info; + int rc = 0, len = sizeof(info); + ENTRY; + + LASSERT(inode); + LASSERT(id); + memcpy(&info.m.id, id, sizeof(*id)); + info.m.nid = nid; + info.m.uid = current->uid; + info.m.gid = current->gid; + info.m.result = ret; + info.m.code = AUDIT_STAT; + + //send info to local fs + fsfilt_set_info(obd, inode->i_sb, inode, + 10, "audit_info", len, (void*)&info); + + RETURN(rc); +} + +int mds_audit_open(struct ptlrpc_request *req, struct mds_update_record * rec, + int ret) +{ + struct obd_device *obd = req->rq_export->exp_obd; + struct inode * inode = NULL; + ptl_nid_t nid = req->rq_peer.peer_id.nid; + struct audit_info info; + int rc = 0, len = sizeof(info); + + struct dentry * dparent = NULL; + + dparent = mds_id2dentry(obd, rec->ur_id1, NULL); + if (IS_ERR(dparent)) { + rc = PTR_ERR(dparent); + RETURN(rc); + } + inode = dparent->d_inode; + + info.m.id = *(rec->ur_id1); + info.m.nid = nid; + info.m.uid = rec->ur_uc.luc_uid; + info.m.gid = rec->ur_uc.luc_gid; + info.m.result = ret; + info.m.code = AUDIT_OPEN; + info.name = rec->ur_name; + info.namelen = rec->ur_namelen; + + //send info to local fs + fsfilt_set_info(obd, inode->i_sb, inode, + 10, "audit_info", len, (void*)&info); + + l_dput(dparent); + + RETURN(rc); +} + +int mds_audit_auth(struct ptlrpc_request *req, struct lvfs_ucred * uc, + audit_op op, struct lustre_id * id, + char * name, int namelen) +{ + struct obd_device *obd = req->rq_export->exp_obd; + ptl_nid_t nid = req->rq_peer.peer_id.nid; + int rc = 0; + struct dentry * dparent; + struct inode * inode; + struct audit_info info; + + ENTRY; + + dparent = mds_id2dentry(obd, id, NULL); + if (IS_ERR(dparent)) { + rc = PTR_ERR(dparent); + GOTO(out, rc); + } + inode = dparent->d_inode; + + info.m.nid = nid; + info.m.uid = uc->luc_uid; + info.m.gid = uc->luc_gid; + info.m.id = (*id); + info.m.result = -EPERM; + info.m.code = op; + info.name = name; + info.namelen = namelen; + + fsfilt_set_info(obd, inode->i_sb, inode, + 10, "audit_info", sizeof(info), &info); + l_dput(dparent); + + EXIT; + out: + return rc; +} + +static int mds_set_obj_audit(struct obd_device * obd, struct inode * inode, + __u64 * mask) +{ + struct audit_lov_msg msg = { + .mask = *mask, + .lsm = NULL, + .uid = inode->i_uid, + .gid = inode->i_gid, + }; + int len, rc = 0; + void *lmm = NULL; + + down(&inode->i_sem); + len = fsfilt_get_md(obd, inode, NULL, 0, EA_LOV); + up(&inode->i_sem); + + if (len < 0) { + CERROR("error getting inode %lu LOV: %d\n", inode->i_ino, len); + GOTO(out, rc = len); + } else if (len == 0) { + CDEBUG(D_INODE, "no LOV in inode %lu\n", inode->i_ino); + GOTO(out, rc = 0); + } + + OBD_ALLOC(lmm, len); + if (lmm == NULL) { + CERROR("can't allocate memory\n"); + GOTO(out, rc = -ENOMEM); + } + + down(&inode->i_sem); + rc = fsfilt_get_md(obd, inode, lmm, len, EA_LOV); + up(&inode->i_sem); + + if (rc < 0) { + CERROR("error getting inode %lu MD: %d\n", inode->i_ino, rc); + GOTO(out, rc); + } + + rc = obd_unpackmd(obd->u.mds.mds_dt_exp, &msg.lsm, lmm, len); + if (rc < 0) { + CERROR("error unpacking inode %lu MD: %d\n", inode->i_ino, rc); + GOTO(out, rc); + } + + obd_set_info(obd->u.mds.mds_dt_exp, 9, "audit_obj", sizeof(msg), &msg); + +out: + if (msg.lsm != NULL) + obd_free_memmd(obd->u.mds.mds_dt_exp, &msg.lsm); + + if (lmm != NULL) + OBD_FREE(lmm, len); + + RETURN(rc); +} + +//set audit attributes for directory/file +int mds_set_audit(struct obd_device * obd, void * val) +{ + struct inode * inode = NULL; + struct dentry * dentry = NULL; + //struct lvfs_run_ctxt saved; + struct audit_attr_msg * msg = val; + + ENTRY; + + //push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + + dentry = mds_id2dentry(obd, &msg->id, NULL); + if (IS_ERR(dentry)) { + CERROR("Cannot get dentry\n"); + RETURN(PTR_ERR(dentry)); + } + + inode = dentry->d_inode; + fsfilt_set_info(obd, inode->i_sb, inode, + 5, "audit", sizeof(msg->attr), &msg->attr); + + if (S_ISREG(inode->i_mode) && !IS_AUDIT_OP(msg->attr, AUDIT_FS)) + mds_set_obj_audit(obd, inode, &msg->attr); + + l_dput(dentry); + + //pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + + RETURN(0); +} + +int mds_pack_audit(struct obd_device * obd, struct inode * inode, + struct mds_body * body) +{ + __u64 mask = 0; + int len = sizeof(mask); + int rc = 0; + + rc = fsfilt_get_info(obd, inode->i_sb, inode, + 5, "audit", &len, &mask); + if (!rc) { + body->audit = mask; + body->valid |= OBD_MD_FLAUDIT; + } + return rc; +} diff --git a/lustre/mds/mds_audit_path.c b/lustre/mds/mds_audit_path.c new file mode 100644 index 0000000..0dc21f6 --- /dev/null +++ b/lustre/mds/mds_audit_path.c @@ -0,0 +1,584 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * + * Copyright (C) 2001-2003 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif +#define DEBUG_SUBSYSTEM S_MDS + +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) +# include +# include +# include +# include +#else +# include +#endif +#include +#include "mds_internal.h" + + +#define PP_FILE 1 +#define PP_DIR 2 +#define PP_SPLIT_MASTER 3 +#define PP_SPLIT_SLAVE 4 +#define PP_CROSS_DIR 5 +#define PP_AUDIT_LOG 6 /* search id in audit log */ + +struct scan_dir_data { + int rc; + struct lustre_id *id; + char *name; +}; + +static int filldir(void *__buf, const char *name, int namlen, + loff_t offset, ino_t ino, unsigned int d_type) +{ + struct scan_dir_data *sd = __buf; + ENTRY; + + if (name[0] == '.' && + (namlen == 1 || (namlen == 2 && name[1] == '.'))) { + /* skip special entries */ + RETURN(0); + } + + LASSERT(sd != NULL); + + if (ino == id_ino(sd->id)) { + strncpy(sd->name, name, namlen); + sd->rc = 0; + RETURN(-EINTR); /* break the readdir loop */ + } + RETURN(0); +} + +int +scan_name_in_parent(struct lustre_id *pid, struct lustre_id *id, char *name) +{ + struct file * file; + char *pname; + struct scan_dir_data sd; + int len, rc = 0; + ENTRY; + + len = strlen("__iopen__/") + 10 + 1; + OBD_ALLOC(pname, len); + if (!pname) + RETURN(-ENOMEM); + + sprintf(pname, "__iopen__/0x%llx", id_ino(pid)); + + file = filp_open(pname, O_RDONLY, 0); + if (IS_ERR(file)) { + CERROR("can't open directory %s: %d\n", + pname, (int) PTR_ERR(file)); + GOTO(out, rc = PTR_ERR(file)); + } + + sd.id = id; + sd.name = name; + sd.rc = -ENOENT; + vfs_readdir(file, filldir, &sd); + + filp_close(file, 0); + rc = sd.rc; + +out: + OBD_FREE(pname, len); + RETURN(rc); + +} + +/* id2pid - given id, get parent id or master id. + * @obd: obd device + * @id: child id to be parsed + * @pid: parent id or master id + * @type: id type + */ +static int +id2pid(struct obd_device *obd, struct lustre_id *id, struct lustre_id *pid, + __u32 *type) +{ + struct dentry *dentry = NULL; + struct inode *inode = NULL; + struct mea *mea = NULL; + int mea_size, rc = 0; + ENTRY; + + dentry = mds_id2dentry(obd, id, NULL); + if (IS_ERR(dentry) || !dentry->d_inode) { + CERROR("can't find inode "LPU64"\n", id_ino(id)); + if (!IS_ERR(dentry)) l_dput(dentry); + RETURN(-ENOENT); + } + inode = dentry->d_inode; + + if (S_ISDIR(id_type(id))) { + LASSERT(S_ISDIR(inode->i_mode)); + rc = mds_md_get_attr(obd, inode, &mea, &mea_size); + if (rc) + GOTO(out, rc); + + if (!mea) { + *type = PP_DIR; + goto read_pid; + } else if (mea && mea->mea_count) { + *type = PP_SPLIT_MASTER; + goto read_pid; + } else { + *type = PP_SPLIT_SLAVE; + *pid = mea->mea_ids[mea->mea_master]; + } + + } else { + LASSERT(!S_ISDIR(inode->i_mode)); + *type = PP_FILE; +read_pid: + rc = mds_read_inode_pid(obd, inode, pid); + if (rc) { + CERROR("can't read parent ino(%lu) rc(%d).\n", + inode->i_ino, rc); + GOTO(out, rc); + } + } + + /* Well, if it's dir or master split, we have to check if it's + * a cross-ref dir */ + if ((*type == PP_DIR || *type == PP_SPLIT_MASTER) && + id_group(id) != id_group(pid)) + *type = PP_CROSS_DIR; +out: + if (mea) + OBD_FREE(mea, mea_size); + l_dput(dentry); + RETURN(rc); +} + +static int local_parse_id(struct obd_device *obd, struct parseid_pkg *pkg) +{ + struct lvfs_run_ctxt saved; + int rc = 0; + ENTRY; + + pkg->pp_rc = 0; + pkg->pp_type = 0; + memset(pkg->pp_name, 0, sizeof(pkg->pp_name)); + + LASSERT(obd->u.mds.mds_num == id_group(&pkg->pp_id1)); + + /* pp_id2 is present, which indicating we want to scan parent + * dir(pp_id2) to find the cross-ref entry(pp_id1) */ + if (id_fid(&pkg->pp_id2)) { + LASSERT(S_ISDIR(id_type(&pkg->pp_id1))); + LASSERT(S_ISDIR(id_type(&pkg->pp_id2))); + + pkg->pp_type = PP_DIR; + goto scan; + } + + rc = id2pid(obd, &pkg->pp_id1, &pkg->pp_id2, &pkg->pp_type); + if (rc) + GOTO(out, rc); +scan: + push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + + switch (pkg->pp_type) { + case PP_FILE: + case PP_DIR: + case PP_SPLIT_MASTER: + rc = scan_name_in_parent(&pkg->pp_id2, &pkg->pp_id1, + pkg->pp_name); + if (rc) + CERROR("scan "LPU64" in parent failed. rc=%d\n", + id_ino(&pkg->pp_id1), rc); + break; + case PP_SPLIT_SLAVE: + case PP_CROSS_DIR: + break; + default: + CERROR("invalid id\n"); + break; + } + + pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); +out: + pkg->pp_rc = rc; + RETURN(rc); +} + +static int +local_scan_audit_log(struct obd_device *obd, struct parseid_pkg *pkg); + +int mds_parse_id(struct ptlrpc_request *req) +{ + struct parseid_pkg *pkg, *reppkg; + struct obd_device *obd = req->rq_export->exp_obd; + int rc = 0, size = sizeof(*reppkg); + ENTRY; + + pkg = lustre_swab_reqbuf(req, 0, sizeof(*pkg), + lustre_swab_parseid_pkg); + if (pkg == NULL) + RETURN(-EPROTO); + + rc = lustre_pack_reply(req, 1, &size, NULL); + if (rc) + RETURN(rc); + + reppkg = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*reppkg)); + memcpy(reppkg, pkg, sizeof(*reppkg)); + + if (reppkg->pp_type == PP_AUDIT_LOG) + rc = local_scan_audit_log(obd, reppkg); + else + rc = local_parse_id(obd, reppkg); + + if (rc) + CERROR("local parseid failed. (rc:%d)\n", rc); + RETURN(0); /* we do need pack reply here */ +} + +static int parse_id(struct obd_device *obd, struct parseid_pkg *pkg) +{ + int rc = 0; + int mds_num = id_group(&pkg->pp_id1); + ENTRY; + + LASSERT(mds_num >= 0); + + if (mds_num == obd->u.mds.mds_num) { + rc = local_parse_id(obd, pkg); + } else { + struct ptlrpc_request *req; + struct lmv_obd *lmv = &obd->u.mds.mds_md_obd->u.lmv; + struct parseid_pkg *body; + int size = sizeof(*body); + struct obd_export *exp = lmv->tgts[mds_num].ltd_exp; + + req = ptlrpc_prep_req(class_exp2cliimp(exp), + LUSTRE_MDS_VERSION, MDS_PARSE_ID, 1, + &size, NULL); + if (!req) + RETURN(-ENOMEM); + + body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body)); + memcpy(body, pkg, sizeof(*body)); + + req->rq_replen = lustre_msg_size(1, &size); + + rc = ptlrpc_queue_wait(req); + if (rc) + GOTO(out, rc); + + body = lustre_swab_repbuf(req, 0, sizeof(*body), + lustre_swab_parseid_pkg); + if (body == NULL) { + CERROR("can't unpack parseid_pkg\n"); + GOTO(out, rc = -EPROTO); + } + memcpy(pkg, body, sizeof(*pkg)); +out: + ptlrpc_req_finished(req); + } + RETURN(rc); +} + +struct name_item { + struct list_head link; + char name[NAME_MAX + 1]; +}; + +int +mds_id2name(struct obd_device *obd, struct lustre_id *id, + struct lustre_id *rootid, struct list_head *list, + struct lustre_id *lastid) +{ + struct name_item *item; + struct parseid_pkg *pkg; + int rc = 0; + ENTRY; + + OBD_ALLOC(pkg, sizeof(*pkg)); + if (pkg == NULL) + RETURN(-ENOMEM); + + pkg->pp_id1 = *id; + while (!id_equal(&pkg->pp_id1, rootid)) { + + rc = parse_id(obd, pkg); + if (rc) { + CDEBUG(D_SEC, "parse id failed. rc=%d\n", rc); + *lastid = pkg->pp_id1; + break; + } + + switch (pkg->pp_type) { + case PP_FILE: + case PP_DIR: + case PP_SPLIT_MASTER: + OBD_ALLOC(item, sizeof(*item)); + if (item == NULL) + GOTO(out, rc = -ENOMEM); + + INIT_LIST_HEAD(&item->link); + list_add(&item->link, list); + memcpy(item->name, pkg->pp_name, sizeof(item->name)); + + case PP_SPLIT_SLAVE: + pkg->pp_id1 = pkg->pp_id2; + memset(&pkg->pp_id2, 0, sizeof(struct lustre_id)); + break; + case PP_CROSS_DIR: + break; + default: + LBUG(); + break; + } + + } +out: + OBD_FREE(pkg, sizeof(*pkg)); + RETURN(rc); +} + +static int +scan_audit_log_cb(struct llog_handle *llh, struct llog_rec_hdr *rec, void *data) +{ + struct parseid_pkg *pkg = (struct parseid_pkg *)data; + struct audit_record *ad_rec; + struct audit_id_record *cid_rec, *pid_rec; + struct audit_name_record *nm_rec; + ENTRY; + + if (!(le32_to_cpu(llh->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) { + CERROR("log is not plain\n"); + RETURN(-EINVAL); + } + if (rec->lrh_type != SMFS_AUDIT_NAME_REC && + rec->lrh_type != LLOG_GEN_REC) { + RETURN(0); + } + + ad_rec = (struct audit_record *)((char *)rec + sizeof(*rec)); + + if (ad_rec->result || + ad_rec->opcode != AUDIT_UNLINK || + ad_rec->opcode != AUDIT_RENAME) + RETURN(0); + + cid_rec = (struct audit_id_record *)((char *)ad_rec + sizeof(*ad_rec)); + pid_rec = cid_rec + 1; + nm_rec = (struct audit_name_record *) + ((char *)pid_rec + sizeof(*pid_rec)); + + if (cid_rec->au_num == id_ino(&pkg->pp_id1) && + cid_rec->au_gen == id_gen(&pkg->pp_id1)) { + /* get parent id */ + id_ino(&pkg->pp_id2) = pid_rec->au_num; + id_gen(&pkg->pp_id2) = pid_rec->au_gen; + id_type(&pkg->pp_id2) = pid_rec->au_type; + id_fid(&pkg->pp_id2) = pid_rec->au_fid; + id_group(&pkg->pp_id2) = pid_rec->au_mds; + /* get name */ + memcpy(pkg->pp_name, nm_rec->name, + le32_to_cpu(nm_rec->name_len)); + + RETURN(LLOG_PROC_BREAK); + } + RETURN(0); +} + +static int +local_scan_audit_log(struct obd_device *obd, struct parseid_pkg *pkg) +{ + struct llog_handle *llh = NULL; + struct llog_ctxt *ctxt = llog_get_context(&obd->obd_llogs, + LLOG_AUDIT_ORIG_CTXT); + int rc = 0; + ENTRY; + + if (ctxt) + llh = ctxt->loc_handle; + + if (llh == NULL) + RETURN(-ENOENT); + + rc = llog_cat_process(llh, (llog_cb_t)&scan_audit_log_cb, (void *)pkg); + if (rc != LLOG_PROC_BREAK) { + CWARN("process catalog log failed: rc(%d)\n", rc); + RETURN(-ENOENT); + } + RETURN(0); +} + +static int +scan_audit_log(struct obd_device *obd, struct lustre_id *cur_id, + struct list_head *list, struct lustre_id *parent_id) +{ + struct name_item *item = NULL; + int rc = 0, mds_num = id_group(cur_id); + struct parseid_pkg *pkg = NULL; + ENTRY; + + OBD_ALLOC(pkg, sizeof(*pkg)); + if (pkg == NULL) + RETURN(-ENOMEM); + + pkg->pp_type = PP_AUDIT_LOG; + pkg->pp_id1 = *cur_id; + + if (obd->u.mds.mds_num == mds_num) { + rc = local_scan_audit_log(obd, pkg); + } else { + struct ptlrpc_request *req; + struct lmv_obd *lmv = &obd->u.mds.mds_md_obd->u.lmv; + struct parseid_pkg *body; + int size = sizeof(*body); + struct obd_export *exp = lmv->tgts[mds_num].ltd_exp; + + req = ptlrpc_prep_req(class_exp2cliimp(exp), + LUSTRE_MDS_VERSION, MDS_PARSE_ID, 1, + &size, NULL); + if (!req) + RETURN(-ENOMEM); + + body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body)); + memcpy(body, pkg, sizeof(*body)); + + req->rq_replen = lustre_msg_size(1, &size); + + rc = ptlrpc_queue_wait(req); + if (rc) + GOTO(out_req, rc); + + body = lustre_swab_repbuf(req, 0, sizeof(*body), + lustre_swab_parseid_pkg); + if (body == NULL) { + CERROR("can't unpack parseid_pkg\n"); + GOTO(out, rc = -EPROTO); + } + memcpy(pkg, body, sizeof(*pkg)); +out_req: + ptlrpc_req_finished(req); + + } + + if (!rc) rc = pkg->pp_rc; + if (rc) + GOTO(out, rc); + + *parent_id = pkg->pp_id2; + + OBD_ALLOC(item, sizeof(*item)); + if (item == NULL) + GOTO(out, rc = -ENOMEM); + + INIT_LIST_HEAD(&item->link); + list_add(&item->link, list); + memcpy(item->name, pkg->pp_name, sizeof(item->name)); +out: + OBD_FREE(pkg, sizeof(*pkg)); + RETURN(rc); +} + +int +mds_audit_id2name(struct obd_device *obd, char **name, int *namelen, + struct lustre_id *id) +{ + int rc = 0; + struct list_head list, *pos, *n; + struct name_item *item; + struct lustre_id parent_id, cur_id, rootid; + ENTRY; + + *namelen = 0; + INIT_LIST_HEAD(&list); + + if (obd->u.mds.mds_num) { + int valsize = sizeof(rootid); + rc = obd_get_info(obd->u.mds.mds_md_exp, strlen("rootid"), + "rootid", &valsize, &rootid); + if (rc) { + CERROR("cann't get rootid!\n"); + RETURN(rc); + } + } else { + rootid = obd->u.mds.mds_rootid; + } + + cur_id = *id; + if (id_equal(&cur_id, &rootid)) + RETURN(0); +next: + memset(&parent_id, 0, sizeof(parent_id)); + + rc = mds_id2name(obd, &cur_id, &rootid, &list, &parent_id); + if (rc == -ENOENT) { + /* can't reconstruct name from id, turn to audit log */ + LASSERT(id_fid(&parent_id)); + cur_id = parent_id; + memset(&parent_id, 0, sizeof(parent_id)); + + rc = scan_audit_log(obd, &cur_id, &list, &parent_id); + if (rc) { + CERROR("scan id in audit log failed. (rc:%d)\n", rc); + GOTO(out, rc); + } + + LASSERT(id_fid(&parent_id)); + cur_id = parent_id; + goto next; + + } else if (rc) { + CERROR("reconstruct name from id failed. (rc:%d)\n", rc); + GOTO(out, rc); + } + + list_for_each_safe (pos, n, &list) { + item = list_entry(pos, struct name_item, link); + *namelen += strlen(item->name) + 1; + } + OBD_ALLOC(*name, *namelen); + if (*name == NULL) + rc = -ENOMEM; +out: + list_for_each_safe (pos, n, &list) { + item = list_entry(pos, struct name_item, link); + if (!rc) { + strcat(*name, "/"); + strcat(*name, item->name); + } + list_del_init(&item->link); + OBD_FREE(item, sizeof(*item)); + } + RETURN(rc); +} +EXPORT_SYMBOL(mds_audit_id2name); diff --git a/lustre/mds/mds_fs.c b/lustre/mds/mds_fs.c index f554b4c..59a5d98 100644 --- a/lustre/mds/mds_fs.c +++ b/lustre/mds/mds_fs.c @@ -440,7 +440,6 @@ int mds_fs_setup_rootid(struct obd_device *obd) struct inode *inode; struct dentry *dentry; struct mds_obd *mds = &obd->u.mds; - __u64 fid; ENTRY; /* getting root directory and setup its fid. */ @@ -479,14 +478,10 @@ int mds_fs_setup_rootid(struct obd_device *obd) GOTO(out_dentry, rc); } - fid = mds_alloc_fid(obd); - down(&inode->i_sem); - rc = mds_set_inode_sid(obd, inode, handle, &mds->mds_rootid, fid); - up(&inode->i_sem); - + mds_inode2id(obd, &mds->mds_rootid, inode, mds_alloc_fid(obd)); + rc = mds_update_inode_ids(obd, inode, handle, &mds->mds_rootid, NULL); if (rc) { - CERROR("mds_set_inode_sid() failed, rc = %d\n", - rc); + CERROR("mds_update_inode_ids() failed, rc = %d\n", rc); GOTO(out_dentry, rc); } @@ -585,13 +580,10 @@ int mds_fs_setup_virtid(struct obd_device *obd) id_gen(&sid) = inode->i_generation; id_type(&sid) = (S_IFMT & inode->i_mode); - down(&inode->i_sem); - rc = mds_update_inode_sid(obd, inode, handle, &sid); - up(&inode->i_sem); + rc = mds_update_inode_ids(obd, inode, handle, &sid, NULL); if (rc) { - CERROR("mds_update_inode_sid() failed, rc = %d\n", - rc); + CERROR("mds_update_inode_ids() failed, rc = %d\n", rc); RETURN(rc); } @@ -692,7 +684,7 @@ int mds_fs_setup(struct obd_device *obd, struct vfsmount *mnt) if (IS_ERR(dentry)) { rc = PTR_ERR(dentry); CERROR("cannot create UNNAMED directory: rc = %d\n", rc); - GOTO(err_unnamed, rc); + GOTO(err_id_dir, rc); } mds->mds_unnamed_dir = dentry; @@ -701,7 +693,7 @@ int mds_fs_setup(struct obd_device *obd, struct vfsmount *mnt) if (IS_ERR(file)) { rc = PTR_ERR(file); CERROR("cannot open/create %s file: rc = %d\n", LAST_RCVD, rc); - GOTO(err_id_dir, rc = PTR_ERR(file)); + GOTO(err_unnamed, rc = PTR_ERR(file)); } mds->mds_rcvd_filp = file; diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index 79c01d7..fd5eaec 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -230,15 +230,16 @@ int mds_fs_setup_virtid(struct obd_device *obd); __u64 mds_alloc_fid(struct obd_device *obd); -int mds_set_inode_sid(struct obd_device *, struct inode *, - void *, struct lustre_id *, __u64 fid); - -int mds_update_inode_sid(struct obd_device *, struct inode *, - void *, struct lustre_id *); - +void mds_inode2id(struct obd_device *obd, struct lustre_id *id, + struct inode *inode, __u64 fid); +int mds_update_inode_ids(struct obd_device *, struct inode *, + void *, struct lustre_id *, struct lustre_id *); int mds_read_inode_sid(struct obd_device *, struct inode *, struct lustre_id *); +int mds_read_inode_pid(struct obd_device *, struct inode *, + struct lustre_id *); + int mds_update_inode_mid(struct obd_device *, struct inode *, void *, struct lustre_id *); @@ -310,6 +311,13 @@ struct lustre_sec_desc * mds_get_lsd(__u32 uid); void mds_put_lsd(struct lustre_sec_desc *lsd); void mds_flush_lsd(__u32 id); +/* mds_audit_path.c */ +int mds_parse_id(struct ptlrpc_request *req); + +/* mds_audit.c */ +int mds_set_audit(struct obd_device * obd, void * val); +int mds_pack_audit(struct obd_device *, struct inode *, struct mds_body *); + /* mds_acl.c */ struct upcall_cache *__mds_get_global_rmtacl_upcall_cache(void); int mds_init_rmtacl_upcall_cache(void); diff --git a/lustre/mds/mds_lib.c b/lustre/mds/mds_lib.c index 0c1b854..6b4709a 100644 --- a/lustre/mds/mds_lib.c +++ b/lustre/mds/mds_lib.c @@ -217,6 +217,25 @@ int mds_pack_inode2id(struct obd_device *obd, RETURN(rc); } +void mds_inode2id(struct obd_device *obd, struct lustre_id *id, + struct inode *inode, __u64 fid) +{ + struct mds_obd *mds = &obd->u.mds; + ENTRY; + + LASSERT(inode != NULL); + LASSERT(id != NULL); + LASSERT(fid != 0); + + id_fid(id) = fid; + id_ino(id) = inode->i_ino; + id_group(id) = mds->mds_num; + id_gen(id) = inode->i_generation; + id_type(id) = (S_IFMT & inode->i_mode); + + EXIT; +} + int mds_pack_gskey(struct obd_device *obd, struct lustre_msg *repmsg, int *offset, struct mds_body *body, struct inode *inode) { @@ -342,7 +361,8 @@ int mds_set_crypto_type(struct obd_device *obd, void *val, __u32 vallen) CDEBUG(D_IOCTL, "invalid key\n"); RETURN(0); -} +} + /* Note that we can copy all of the fields, just some will not be "valid" */ void mds_pack_inode2body(struct obd_device *obd, struct mds_body *b, struct inode *inode, int fid) @@ -1172,6 +1192,7 @@ int mds_init_ucred(struct lvfs_ucred *ucred, rsd->rsd_cap &= ~CAP_FS_MASK; /* by now every fields other than groups in rsd have been granted */ + ucred->luc_nid = peernid; ucred->luc_uid = rsd->rsd_uid; ucred->luc_gid = rsd->rsd_gid; ucred->luc_fsuid = rsd->rsd_fsuid; diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c index baba9d1..4bf8e6e 100644 --- a/lustre/mds/mds_open.c +++ b/lustre/mds/mds_open.c @@ -925,6 +925,7 @@ int mds_open(struct mds_update_record *rec, int offset, struct mea *mea = NULL; int mea_size, update_mode; int child_mode = LCK_PR; + struct lustre_id sid; __u64 fid = 0; ENTRY; @@ -1023,12 +1024,19 @@ restart: cleanup_phase = 1; /* parent dentry and lock */ - /* try to retrieve MEA data for this dir */ + /* get parent id: ldlm lock on the parent protects ea */ + rc = mds_read_inode_sid(obd, dparent->d_inode, &sid); + if (rc) { + CERROR("can't read parent inode id. ino(%lu) rc(%d)\n", + dparent->d_inode->i_ino, rc); + GOTO(cleanup, rc); + } + /* try to retrieve MEA data for this dir */ rc = mds_md_get_attr(obd, dparent->d_inode, &mea, &mea_size); if (rc) GOTO(cleanup, rc); - if (mea != NULL) { + if (mea != NULL && mea->mea_count) { /* * dir is already splitted, check is requested filename should * * live at this MDS or at another one. @@ -1213,7 +1221,10 @@ got_child: else { MD_COUNTER_INCREMENT(obd, create); } - + + mds_inode2id(obd, &body->id1, inode, fid); + mds_update_inode_ids(obd, dchild->d_inode, handle, &body->id1, &sid); + if ((rec->ur_flags & MDS_OPEN_HAS_KEY) || mds->mds_crypto_type == MKS_TYPE) { rc = mds_set_gskey(obd, handle, dchild->d_inode, @@ -1223,26 +1234,6 @@ got_child: CERROR("error in set gs key rc %d\n", rc); } } - if (ino) { - rc = mds_update_inode_sid(obd, dchild->d_inode, - handle, rec->ur_id2); - if (rc) { - CERROR("mds_update_inode_sid() failed, " - "rc = %d\n", rc); - } - id_assign_fid(&body->id1, rec->ur_id2); - /* - * make sure, that fid is up-to-date. - */ - mds_set_last_fid(obd, id_fid(rec->ur_id2)); - } else { - rc = mds_set_inode_sid(obd, dchild->d_inode, - handle, &body->id1, fid); - if (rc) { - CERROR("mds_set_inode_sid() failed, " - "rc = %d\n", rc); - } - } if (!(rec->ur_flags & O_EXCL)) { /* bug 3313 */ rc = fsfilt_commit(obd, dchild->d_inode->i_sb, diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index dee71d8..52812f82 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -459,6 +459,8 @@ out: #define XATTR_LUSTRE_MDS_MEA_EA "mea" #define XATTR_LUSTRE_MDS_MID_EA "mid" #define XATTR_LUSTRE_MDS_SID_EA "sid" +#define XATTR_LUSTRE_MDS_PID_EA "pid" +#define XATTR_LUSTRE_MDS_KEY_EA "key" static int mds_get_md_type(char *name) { @@ -470,6 +472,11 @@ static int mds_get_md_type(char *name) RETURN(EA_MID); if (!strcmp(name, XATTR_LUSTRE_MDS_SID_EA)) RETURN(EA_SID); + if (!strcmp(name, XATTR_LUSTRE_MDS_PID_EA)) + RETURN(EA_PID); + if (!strcmp(name, XATTR_LUSTRE_MDS_KEY_EA)) + RETURN(EA_KEY); + RETURN(0); } @@ -804,6 +811,7 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, struct dentry *dparent = NULL; struct mds_obd *mds = mds_req2mds(req); struct obd_device *obd = req->rq_export->exp_obd; + struct mds_body *body = NULL; struct dentry *dchild = NULL; struct inode *dir = NULL; void *handle = NULL; @@ -814,6 +822,7 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, struct dentry_params dp; struct mea *mea = NULL; int mea_size; + struct lustre_id sid; __u64 fid; ENTRY; @@ -845,12 +854,20 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, ldlm_lock_dump_handle(D_OTHER, lockh); + /* get parent id: ldlm lock on the parent protects ea */ + rc = mds_read_inode_sid(obd, dir, &sid); + if (rc) { + CERROR("can't read parent id. ino(%lu) rc(%d)\n", + dir->i_ino, rc); + GOTO(cleanup, rc); + } + /* try to retrieve MEA data for this dir */ rc = mds_md_get_attr(obd, dparent->d_inode, &mea, &mea_size); if (rc) GOTO(cleanup, rc); - if (mea != NULL) { + if (mea != NULL && mea->mea_count) { /* * dir is already splitted, check is requested filename should * live at this MDS or at another one. @@ -913,6 +930,8 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, dp.p_fid = fid; dp.p_group = mds->mds_num; + body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body)); + switch (type) { case S_IFREG: { handle = fsfilt_start(obd, dir, FSFILT_OP_CREATE, NULL); @@ -955,32 +974,6 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, GOTO(cleanup, rc); } - down(&dchild->d_inode->i_sem); - if (dp.p_inum) { - rc = mds_update_inode_sid(obd, dchild->d_inode, - handle, rec->ur_id2); - if (rc) { - CERROR("mds_update_inode_sid() failed, inode %lu, " - "rc %d\n", dchild->d_inode->i_ino, rc); - } - - /* - * make sure, that fid is up-to-date. - */ - mds_set_last_fid(obd, id_fid(rec->ur_id2)); - } else { - rc = mds_set_inode_sid(obd, dchild->d_inode, - handle, NULL, fid); - if (rc) { - CERROR("mds_set_inode_sid() failed, inode %lu, " - "rc %d\n", dchild->d_inode->i_ino, rc); - } - } - up(&dchild->d_inode->i_sem); - - if (rc) - GOTO(cleanup, rc); - if (rec->ur_eadata) nstripes = *(u16 *)rec->ur_eadata; @@ -1006,7 +999,6 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, } else if (!DENTRY_VALID(dchild)) { /* inode will be created on another MDS */ struct obdo *oa = NULL; - struct mds_body *body; void *acl = NULL; int acl_size; @@ -1031,8 +1023,11 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, oa->o_uid = current->fsuid; oa->o_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; - oa->o_valid |= OBD_MD_FLTYPE|OBD_MD_FLUID|OBD_MD_FLGID; - + /* transfer parent id to remote inode */ + memcpy(obdo_id(oa), &sid, sizeof(sid)); + oa->o_valid |= OBD_MD_FLTYPE | OBD_MD_FLUID | + OBD_MD_FLGID | OBD_MD_FLIFID; + CDEBUG(D_OTHER, "%s: create dir on MDS %u\n", obd->obd_name, i); @@ -1102,8 +1097,6 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, } /* fill reply */ - body = lustre_msg_buf(req->rq_repmsg, - 0, sizeof(*body)); body->valid |= OBD_MD_FLID | OBD_MD_MDS | OBD_MD_FID; obdo2id(&body->id1, oa); @@ -1154,7 +1147,6 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, } else if (dchild->d_inode) { struct mds_export_data *med = &req->rq_export->u.eu_mds_data; struct iattr iattr; - struct mds_body *body; struct inode *inode = dchild->d_inode; created = 1; @@ -1174,67 +1166,12 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, if (id_ino(rec->ur_id2)) { LASSERT(id_ino(rec->ur_id2) == inode->i_ino); inode->i_generation = id_gen(rec->ur_id2); - - if (type != S_IFDIR) { - down(&inode->i_sem); - rc = mds_update_inode_sid(obd, inode, - handle, rec->ur_id2); - up(&inode->i_sem); - if (rc) { - CERROR("Can't update inode self id, " - "rc = %d.\n", rc); - } - - /* - * make sure, that fid is up-to-date. - */ - mds_set_last_fid(obd, id_fid(rec->ur_id2)); - } - /* dirtied and committed by the upcoming setattr. */ CDEBUG(D_INODE, "recreated ino %lu with gen %u\n", inode->i_ino, inode->i_generation); - } else { - struct lustre_handle child_ino_lockh; - - CDEBUG(D_INODE, "created ino %lu with gen %x\n", - inode->i_ino, inode->i_generation); - - if (type != S_IFDIR) { - /* - * allocate new id for @inode if it is not dir, - * because for dir it was already done. - */ - down(&inode->i_sem); - rc = mds_set_inode_sid(obd, inode, - handle, NULL, fid); - up(&inode->i_sem); - if (rc) { - CERROR("mds_set_inode_sid() failed, " - "inode %lu, rc %d\n", inode->i_ino, - rc); - } - } - - if (rc == 0) { - /* - * the inode we were allocated may have just - * been freed by an unlink operation. We take - * this lock to synchronize against the matching - * reply-ack-lock taken in unlink, to avoid - * replay problems if this reply makes it out to - * the client but the unlink's does not. See - * bug 2029 for more detail. - */ - rc = mds_lock_new_child(obd, inode, &child_ino_lockh); - if (rc != ELDLM_OK) { - CERROR("error locking for unlink/create sync: " - "%d\n", rc); - } else { - ldlm_lock_decref(&child_ino_lockh, LCK_EX); - } - } } + mds_inode2id(obd, &body->id1, dchild->d_inode, fid); + mds_update_inode_ids(obd, inode, handle, &body->id1, &sid); rc = fsfilt_setattr(obd, dchild, handle, &iattr, 0); if (rc) @@ -1266,7 +1203,6 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, } } - body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body)); mds_pack_inode2body(obd, body, inode, 1); mds_body_do_reverse_map(med, body); } @@ -1292,6 +1228,14 @@ cleanup: CERROR("unlink in error path: %d\n", err); break; } + } else if (created) { + /* The inode we were allocated may have just been freed + * by an unlink operation. We take this lock to + * synchronize against the matching reply-ack-lock taken + * in unlink, to avoid replay problems if this reply + * makes it out to the client but the unlink's does not. + * See bug 2029 for more detail.*/ + mds_lock_new_child(obd, dchild->d_inode, NULL); } else { rc = err; } @@ -3282,6 +3226,7 @@ static int mds_reint_rename_create_name(struct mds_update_record *rec, struct dentry *de_new = NULL; int cleanup_phase = 0; int update_mode, rc = 0; + struct lustre_id ids[2]; /* sid, pid */ ENTRY; /* @@ -3291,6 +3236,11 @@ static int mds_reint_rename_create_name(struct mds_update_record *rec, CDEBUG(D_OTHER, "%s: request to create name %s for "DLID4"\n", obd->obd_name, rec->ur_tgt, OLID4(rec->ur_id1)); + /* get parent id: ldlm lock on the parent protects ea */ + rc = mds_read_inode_sid(obd, de_tgtdir->d_inode, &ids[1]); + if (rc) + GOTO(cleanup, rc); + /* first, lookup the target */ rc = mds_get_parent_child_locked(obd, mds, rec->ur_id2, parent_lockh, &de_tgtdir, LCK_PW, MDS_INODELOCK_UPDATE, @@ -3308,7 +3258,14 @@ static int mds_reint_rename_create_name(struct mds_update_record *rec, rc = mds_add_local_dentry(rec, offset, req, rec->ur_id1, de_tgtdir, de_new); + if (rc) + GOTO(cleanup, rc); + ids[0] = *(rec->ur_id1); + rc = obd_set_info(mds->mds_md_obd->u.lmv.tgts[id_group(rec->ur_id1)].ltd_exp, + strlen("ids"), "ids", + sizeof(struct lustre_id) * 2, ids); + EXIT; cleanup: @@ -3447,6 +3404,7 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset, struct llog_create_locks *lcl = NULL; struct lov_mds_md *lmm = NULL; int rc = 0, cleanup_phase = 0; + struct lustre_id ids[2]; /* sid, pid */ void *handle = NULL; ENTRY; @@ -3565,6 +3523,11 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset, body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body)); LASSERT(body != NULL); + /* get new parent id: ldlm lock on the parent protects ea */ + rc = mds_read_inode_sid(obd, de_tgtdir->d_inode, &ids[1]); + if (rc) + GOTO(cleanup, rc); + /* child i_alloc_sem protects orphan_dec_test && is_orphan race */ if (new_inode) DOWN_READ_I_ALLOC_SEM(new_inode); @@ -3590,16 +3553,26 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset, if (de_old->d_flags & DCACHE_CROSS_REF) { struct lustre_id old_id; + struct obd_export *tgt_exp = + mds->mds_md_obd->u.lmv.tgts[de_old->d_mdsnum].ltd_exp; + mds_pack_dentry2id(obd, &old_id, de_old, 1); rc = mds_add_local_dentry(rec, offset, req, &old_id, de_tgtdir, de_new); if (rc) GOTO(cleanup, rc); - + rc = mds_del_local_dentry(rec, offset, req, de_srcdir, de_old); + if (rc) + GOTO(cleanup, rc); + + ids[0] = old_id; + rc = obd_set_info(tgt_exp, strlen("ids"), "ids", + sizeof(struct lustre_id) * 2, ids); + GOTO(cleanup, rc); } @@ -3645,6 +3618,10 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset, } } + if (rc == 0) + rc = mds_update_inode_ids(obd, de_old->d_inode, + handle, NULL, &ids[1]); + EXIT; cleanup: rc = mds_finish_transno(mds, (de_tgtdir ? de_tgtdir->d_inode : NULL), diff --git a/lustre/obdclass/llog_obd.c b/lustre/obdclass/llog_obd.c index fac3dd5..f0ccd0c 100644 --- a/lustre/obdclass/llog_obd.c +++ b/lustre/obdclass/llog_obd.c @@ -70,6 +70,7 @@ int obd_llog_setup(struct obd_device *obd, struct obd_llogs *llogs, rc = op->lop_setup(obd, llogs, index, disk_obd, count, logid); if (ctxt && rc) { obd->obd_llog_ctxt[index] = NULL; + llogs->llog_ctxt[index] = NULL; OBD_FREE(ctxt, sizeof(*ctxt)); } diff --git a/lustre/obdclass/mea.c b/lustre/obdclass/mea.c index 8dffec3..eae6027 100644 --- a/lustre/obdclass/mea.c +++ b/lustre/obdclass/mea.c @@ -80,16 +80,12 @@ int raw_name2idx(int hashtype, int count, const char *name, int namelen) int mea_name2idx(struct mea *mea, char *name, int namelen) { unsigned int c; - - /* just to simplify caller code */ - if (mea == NULL) - return 0; - - if (mea->mea_count == 0) - return 0; + + LASSERT(mea && mea->mea_count); c = raw_name2idx(mea->mea_magic, mea->mea_count, name, namelen); - LASSERT(c < mea->mea_count); + + LASSERT(c < mea->mea_count); return c; } diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index 1b13258..6da3b15 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -61,6 +61,7 @@ #include #include +#include #include "filter_internal.h" /* Group 0 is no longer a legal group, to catch uninitialized IDs */ @@ -2180,8 +2181,8 @@ int filter_setattr(struct obd_export *exp, struct obdo *oa, struct filter_obd *filter; struct ldlm_resource *res; struct dentry *dentry; - obd_uid uid; - obd_gid gid; + /*obd_uid uid;*/ + /*obd_gid gid;*/ int rc; ENTRY; @@ -2800,6 +2801,56 @@ static int filter_sync(struct obd_export *exp, struct obdo *oa, RETURN(rc); } +static int filter_set_info(struct obd_export *exp, __u32 keylen, + void *key, __u32 vallen, void *val) +{ + struct obd_device *obd; + int rc = -EINVAL; + ENTRY; + + obd = class_exp2obd(exp); + if (obd == NULL) { + CDEBUG(D_IOCTL, "invalid client cookie "LPX64"\n", + exp->exp_handle.h_cookie); + RETURN(-EINVAL); + } + + if (keylen == 8 && memcmp(key, "auditlog", 8) == 0) { + + rc = fsfilt_set_info(obd, obd->u.filter.fo_sb, NULL, + 8, "auditlog", vallen, val); + RETURN(rc); + } else if (keylen == 5 && strcmp(key, "audit") == 0) { + //set audit for whole FS on OSS + struct audit_attr_msg * msg = val; + + rc = fsfilt_set_info(obd, obd->u.filter.fo_sb, NULL, + 5, "audit", sizeof(msg->attr), &msg->attr); + RETURN(rc); + } else if (keylen == 9 && strcmp(key, "audit_obj") == 0) { + struct obdo * oa = val; + struct dentry * dentry; + __u64 mask = oa->o_fid; + + dentry = filter_crow_object(obd, oa); + if (IS_ERR(dentry)) + RETURN(PTR_ERR(dentry)); + + rc = fsfilt_set_info(obd, obd->u.filter.fo_sb, dentry->d_inode, + 5, "audit", sizeof(mask), &mask); + + f_dput(dentry); + + RETURN(rc); + } + + + if (rc) + CDEBUG(D_IOCTL, "invalid key\n"); + + RETURN(rc); +} + static int filter_get_info(struct obd_export *exp, __u32 keylen, void *key, __u32 *vallen, void *val) { @@ -2839,7 +2890,8 @@ static int filter_get_info(struct obd_export *exp, __u32 keylen, /*Get log_context handle*/ unsigned long *llh_handle = val; *vallen = sizeof(unsigned long); - *llh_handle = (unsigned long)obd->obd_llog_ctxt[LLOG_REINT_ORIG_CTXT]; + *llh_handle = (unsigned long)llog_get_context(&obd->obd_llogs, + LLOG_REINT_ORIG_CTXT); RETURN(0); } if (keylen >= strlen("cache_sb") && memcmp(key, "cache_sb", 8) == 0) { @@ -3069,6 +3121,7 @@ static struct obd_ops filter_obd_ops = { .o_owner = THIS_MODULE, .o_attach = filter_attach, .o_detach = filter_detach, + .o_set_info = filter_set_info, .o_get_info = filter_get_info, .o_setup = filter_setup, .o_precleanup = filter_precleanup, diff --git a/lustre/obdfilter/filter_io.c b/lustre/obdfilter/filter_io.c index 3d505ec..62beaa7 100644 --- a/lustre/obdfilter/filter_io.c +++ b/lustre/obdfilter/filter_io.c @@ -883,16 +883,29 @@ cleanup: int filter_commitrw(int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, int niocount, - struct niobuf_local *res, struct obd_trans_info *oti,int rc) + struct niobuf_local *res, struct obd_trans_info *oti,int ret) { - if (cmd == OBD_BRW_WRITE) - return filter_commitrw_write(exp, oa, objcount, obj, niocount, - res, oti, rc); - if (cmd == OBD_BRW_READ) - return filter_commitrw_read(exp, oa, objcount, obj, niocount, - res, oti, rc); - LBUG(); - return -EPROTO; + int rc = -EPROTO; + struct lustre_id *id = obdo_id(oa); + __u32 len = sizeof(*id); + struct inode * inode = res->dentry->d_inode; + struct super_block * sb = res->dentry->d_sb; + struct obd_device *obd = class_exp2obd(exp); + + if (cmd == OBD_BRW_WRITE) { + rc = filter_commitrw_write(exp, oa, objcount, obj, niocount, + res, oti, ret); + fsfilt_set_info(obd, sb, inode, 10, "file_write", len, (void*)id); + } + else if (cmd == OBD_BRW_READ) { + rc = filter_commitrw_read(exp, oa, objcount, obj, niocount, + res, oti, ret); + fsfilt_set_info(obd, sb, inode, 9, "file_read", len, (void*)id); + } + else + LBUG(); + + return rc; } int filter_brw(int cmd, struct obd_export *exp, struct obdo *oa, diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index 9794f8a..6fc5d02 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include "osc_internal.h" @@ -2546,31 +2547,7 @@ static int osc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm, } } - if (mode == LCK_PW) { - rc = ldlm_lock_match(obd->obd_namespace, 0, &res_id, type, - policy, LCK_PR, lockh); - if (rc == 1) { - rc = ldlm_cli_convert(lockh, mode, flags); - if (!rc) { - /* Update readers/writers accounting */ - ldlm_lock_addref(lockh, LCK_PW); - ldlm_lock_decref(lockh, LCK_PR); - osc_set_data_with_check(lockh, data); - RETURN(ELDLM_OK); - } - /* If the conversion failed, we need to drop refcount - on matched lock before we get new one */ - /* XXX Won't it save us some efforts if we cancel PR - lock here? We are going to take PW lock anyway and it - will invalidate PR lock */ - ldlm_lock_decref(lockh, LCK_PR); - if (rc != EDEADLOCK) { - RETURN(rc); - } - } - } - - no_match: +no_match: if (*flags & LDLM_FL_HAS_INTENT) { int size[2] = {0, sizeof(struct ldlm_request)}; @@ -2905,6 +2882,19 @@ static int osc_get_info(struct obd_export *exp, __u32 keylen, out: ptlrpc_req_finished(req); RETURN(rc); + } else if (keylen >= strlen("client_nid") && + strcmp(key, "client_nid") == 0) { + struct ptlrpc_connection * conn; + ptl_nid_t * nid = val; + *vallen = sizeof(*nid); + + conn = class_exp2cliimp(exp)->imp_connection; + if (!conn) + RETURN(-ENOTCONN); + + nid = &conn->c_peer.peer_id.nid; + + RETURN(0); } RETURN(-EPROTO); } @@ -2956,6 +2946,63 @@ static int osc_set_info(struct obd_export *exp, obd_count keylen, obd->obd_name, cl->cl_async); RETURN(0); } + + if (keylen == 5 && strcmp(key, "audit") == 0) { + struct ptlrpc_request *req; + char *bufs[2] = {key, val}; + int size[2] = {keylen, vallen}; + + req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OBD_VERSION, + OST_SET_INFO, 2, size, bufs); + if (req == NULL) + RETURN(-ENOMEM); + + req->rq_replen = lustre_msg_size(0, size); + lustre_swab_reqbuf(req, 1, sizeof(struct audit_attr_msg), + lustre_swab_audit_attr); + rc = ptlrpc_queue_wait(req); + + ptlrpc_req_finished(req); + RETURN(rc); + } + + if (keylen == 9 && strcmp(key, "audit_obj") == 0) { + struct ptlrpc_request *req; + char *bufs[2] = {key, val}; + int size[2] = {keylen, vallen}; + + req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OBD_VERSION, + OST_SET_INFO, 2, size, bufs); + if (req == NULL) + RETURN(-ENOMEM); + + req->rq_replen = lustre_msg_size(0, size); + lustre_swab_reqbuf(req, 1, sizeof(struct obdo), + lustre_swab_obdo); + rc = ptlrpc_queue_wait(req); + + ptlrpc_req_finished(req); + RETURN(rc); + } + + if (keylen == 8 && memcmp(key, "auditlog", 8) == 0) { + struct ptlrpc_request *req; + char *bufs[2] = {key, val}; + int size[2] = {keylen, vallen}; + + req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_OBD_VERSION, + OST_SET_INFO, 2, size, bufs); + if (req == NULL) + RETURN(-ENOMEM); + + req->rq_replen = lustre_msg_size(0, size); + lustre_swab_reqbuf(req, 1, sizeof(struct audit_msg), + lustre_swab_audit_msg); + rc = ptlrpc_queue_wait(req); + + ptlrpc_req_finished(req); + RETURN(rc); + } if (keylen == strlen("sec") && memcmp(key, "sec", keylen) == 0) { diff --git a/lustre/ost/ost_handler.c b/lustre/ost/ost_handler.c index 6c1493f..96481c7 100644 --- a/lustre/ost/ost_handler.c +++ b/lustre/ost/ost_handler.c @@ -45,6 +45,7 @@ #include #include #include +#include void oti_init(struct obd_trans_info *oti, struct ptlrpc_request *req) { @@ -878,6 +879,19 @@ static int ost_set_info(struct obd_export *exp, struct ptlrpc_request *req) RETURN(rc); val = lustre_msg_buf(req->rq_reqmsg, 1, 0); + + if (keylen == 8 && memcmp(key, "auditlog", 8) == 0) { + lustre_swab_reqbuf(req, 1, sizeof(struct audit_msg), + lustre_swab_audit_msg); + } + else if (keylen == 5 && strcmp(key, "audit") == 0) { + lustre_swab_reqbuf(req, 1, sizeof(struct audit_attr_msg), + lustre_swab_audit_attr); + } + else if (keylen == 9 && strcmp(key, "audit_obj") == 0) { + lustre_swab_reqbuf(req, 1, sizeof(struct obdo), + lustre_swab_obdo); + } rc = obd_set_info(exp, keylen, key, req->rq_reqmsg->buflens[1], val); req->rq_repmsg->status = 0; diff --git a/lustre/ptlrpc/lproc_ptlrpc.c b/lustre/ptlrpc/lproc_ptlrpc.c index 0bfcda2..995aec2 100644 --- a/lustre/ptlrpc/lproc_ptlrpc.c +++ b/lustre/ptlrpc/lproc_ptlrpc.c @@ -65,6 +65,7 @@ struct ll_rpc_opcode { { MDS_SYNC, "mds_sync" }, { MDS_DONE_WRITING, "mds_done_writing" }, { MDS_ACCESS_CHECK, "mds_access_check"}, + { MDS_PARSE_ID, "mds_parse_id" }, { LDLM_ENQUEUE, "ldlm_enqueue" }, { LDLM_CONVERT, "ldlm_convert" }, { LDLM_CANCEL, "ldlm_cancel" }, diff --git a/lustre/ptlrpc/pack_generic.c b/lustre/ptlrpc/pack_generic.c index 5db619a..2869561 100644 --- a/lustre/ptlrpc/pack_generic.c +++ b/lustre/ptlrpc/pack_generic.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -680,6 +681,14 @@ void lustre_swab_lustre_id(struct lustre_id *id) lustre_swab_lustre_fid(&id->li_fid); } +void lustre_swab_parseid_pkg (struct parseid_pkg *pkg) +{ + __swab32s(&pkg->pp_type); + __swab32s(&pkg->pp_rc); + lustre_swab_lustre_id(&pkg->pp_id1); + lustre_swab_lustre_id(&pkg->pp_id2); +} + void lustre_swab_mds_status_req(struct mds_status_req *r) { __swab32s(&r->flags); @@ -740,6 +749,7 @@ void lustre_swab_mds_body(struct mds_body *b) __swab64s(&b->size); __swab64s(&b->blocks); __swab64s(&b->valid); + __swab64s (&b->audit); __swab32s(&b->mode); __swab32s(&b->uid); __swab32s(&b->gid); @@ -894,6 +904,22 @@ void lustre_swab_remote_perm(struct mds_remote_perm *p) __swab16s(&p->mrp_perm); } +void lustre_swab_audit_msg (struct audit_msg *r) +{ + lustre_swab_lustre_id(&r->id); + __swab32s (&r->code); + __swab32s (&r->result); + __swab32s (&r->uid); + __swab32s (&r->gid); + __swab64s (&r->nid); +} + +void lustre_swab_audit_attr (struct audit_attr_msg *r) +{ + lustre_swab_lustre_id(&r->id); + __swab64s (&r->attr); +} + /* no one calls this */ int llog_log_swabbed(struct llog_log_hdr *hdr) { diff --git a/lustre/ptlrpc/ptlrpc_module.c b/lustre/ptlrpc/ptlrpc_module.c index d2056ac..5c5be86 100644 --- a/lustre/ptlrpc/ptlrpc_module.c +++ b/lustre/ptlrpc/ptlrpc_module.c @@ -176,6 +176,9 @@ EXPORT_SYMBOL(lustre_swab_generic_32s); EXPORT_SYMBOL(lustre_swab_lustre_id); EXPORT_SYMBOL(lustre_swab_lustre_stc); EXPORT_SYMBOL(lustre_swab_lustre_fid); +EXPORT_SYMBOL(lustre_swab_parseid_pkg); +EXPORT_SYMBOL(lustre_swab_audit_msg); +EXPORT_SYMBOL(lustre_swab_audit_attr); EXPORT_SYMBOL(lustre_swab_mds_status_req); EXPORT_SYMBOL(lustre_swab_mds_secdesc); EXPORT_SYMBOL(lustre_swab_remote_perm); diff --git a/lustre/smfs/Makefile.in b/lustre/smfs/Makefile.in index 28821e8..7e96ed1 100644 --- a/lustre/smfs/Makefile.in +++ b/lustre/smfs/Makefile.in @@ -2,5 +2,6 @@ MODULES := smfs smfs-objs := super.o inode.o cache.o dir.o fsfilt.o ioctl.o smfs-objs += sysctl.o file.o symlink.o smfs_lib.o smfs_llog.o smfs-objs += kml.o mds_kml.o ost_kml.o cache_space.o +smfs-objs += audit.o audit_mds.o audit_ost.o audit_transfer.o @SNAPFS_TRUE@smfs-objs += smfs_cow.o @INCLUDE_RULES@ diff --git a/lustre/smfs/audit.c b/lustre/smfs/audit.c new file mode 100644 index 0000000..93d4d3e --- /dev/null +++ b/lustre/smfs/audit.c @@ -0,0 +1,581 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * lustre/smfs/audit_mds.c + * Lustre filesystem audit part for MDS + * + * Copyright (C) 2004 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif + +#define DEBUG_SUBSYSTEM S_SM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "smfs_internal.h" + +static audit_op hook2audit(hook_op hook) +{ + audit_op opcode = AUDIT_NONE; + + switch (hook) + { + case HOOK_CREATE: + case HOOK_SYMLINK: + case HOOK_MKDIR: + case HOOK_MKNOD: + return AUDIT_CREATE; + + case HOOK_LINK: + return AUDIT_LINK; + + case HOOK_RMDIR: + case HOOK_UNLINK: + return AUDIT_UNLINK; + + case HOOK_READLINK: + return AUDIT_READLINK; + + case HOOK_RENAME: + return AUDIT_RENAME; + + case HOOK_SETATTR: + case HOOK_F_SETATTR: + return AUDIT_SETATTR; + + case HOOK_SI_WRITE: + return AUDIT_WRITE; + + case HOOK_SI_READ: + return AUDIT_READ; + + case HOOK_READDIR: + return AUDIT_READDIR; + + default: + return AUDIT_NONE; + } + + return opcode; +} + +struct inode * get_inode_from_hook(hook_op hook, void * msg) +{ + struct inode * inode; + + switch (hook) + { + case HOOK_LINK: + { + struct hook_link_msg * m = msg; + inode = m->dentry->d_inode; + break; + } + case HOOK_UNLINK: + case HOOK_RMDIR: + { + struct hook_unlink_msg * m = msg; + inode = m->dentry->d_inode; + break; + } + case HOOK_READLINK: + { + struct hook_symlink_msg * m = msg; + inode = m->dentry->d_inode; + break; + } + case HOOK_RENAME: + { + struct hook_rename_msg * m = msg; + inode = m->dentry->d_inode; + break; + } + default: + inode = NULL; + } + + return inode; +} + +int smfs_get_audit(struct super_block * sb, struct inode * parent, + struct inode * inode, __u64 * mask) +{ + struct smfs_super_info * smb = S2SMI(sb); + struct fsfilt_operations *fsfilt = smb->sm_fsfilt; + int rc; + struct audit_priv * priv = NULL; + + ENTRY; + + if (!SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT)) + RETURN(-EINVAL); + + priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT); + + //omit __iopen__ dir + if (parent->i_ino == SMFS_IOPEN_INO) + RETURN(-ENOENT); + + if (!priv) + RETURN(-ENOENT); + + if (IS_AUDIT(priv->a_mask)) { + (*mask) = priv->a_mask; + RETURN(0); + } + //get inode audit EA + rc = fsfilt->fs_get_xattr(parent, AUDIT_ATTR_EA, + mask, sizeof(*mask)); + if (rc <= 0) + RETURN(-ENODATA); + + //check if parent has audit + if (IS_AUDIT(*mask)) + RETURN(0); + + if (!inode) + RETURN(-ENOENT); + + rc = fsfilt->fs_get_xattr(inode, AUDIT_ATTR_EA, + mask, sizeof(*mask)); + if (rc <= 0) + RETURN(-ENODATA); + + if (IS_AUDIT(*mask)) + RETURN(0); + + RETURN(-ENODATA); +} + +int smfs_audit_check(struct inode * parent, hook_op hook, int ret, + struct audit_priv * priv, void * msg) +{ + audit_op code; + __u64 mask = 0; + int rc = 0; + + ENTRY; + + if (hook == HOOK_SPECIAL) { + struct audit_info * info = msg; + code = info->m.code; + } + else + code = hook2audit(hook); + + rc = smfs_get_audit(parent->i_sb, parent, + get_inode_from_hook(hook, msg), + &mask); + if (rc < 0) + RETURN(0); + //should only failures be audited? + if (!ret && IS_AUDIT_OP(mask, AUDIT_FAIL)) + RETURN(0); + + //check audit mask + RETURN(IS_AUDIT_OP(mask, code)); +} + +static int smfs_set_fs_audit (struct super_block * sb, __u64 *mask) +{ + struct smfs_super_info * smb = S2SMI(sb); + struct fsfilt_operations * fsfilt = smb->sm_fsfilt; + int rc = 0; + loff_t off = 0; + struct file * f = NULL; + struct audit_priv *priv; + struct lvfs_run_ctxt * ctxt, saved; + ENTRY; + + ctxt = &smb->smsi_exp->exp_obd->obd_lvfs_ctxt; + push_ctxt(&saved, ctxt, NULL); + priv = smfs_get_plg_priv(smb, SMFS_PLG_AUDIT); + if(!priv) { + CERROR("error updating audit setting: rc = %d\n", rc); + RETURN(-EINVAL); + } + + push_ctxt(&saved, ctxt, NULL); + + f = filp_open(AUDIT_ATTR_FILE, O_RDWR|O_CREAT, 0600); + if (IS_ERR(f)) { + CERROR("cannot get audit_setting file\n"); + rc = -EINVAL; + goto exit; + } + + rc = fsfilt->fs_write_record(f, mask, sizeof(*mask), &off, 1); + if (rc) { + CERROR("error writting audit setting: rc = %d\n", rc); + goto exit; + } + + priv->a_mask = (*mask); + +exit: + if (f) + filp_close(f, 0); + + pop_ctxt(&saved, ctxt, NULL); + + RETURN (rc); +} + +//set audit attributes for directory/file +int smfs_set_audit(struct super_block * sb, struct inode * inode, + __u64 * mask) +{ + void * handle = NULL; + struct fsfilt_operations * fsfilt = S2SMI(sb)->sm_fsfilt; + int rc = 0; + + ENTRY; + + if (IS_AUDIT_OP((*mask), AUDIT_FS)) + return smfs_set_fs_audit(sb, mask); + + LASSERT(inode); + + handle = fsfilt->fs_start(inode, FSFILT_OP_SETATTR, NULL, 0); + if (IS_ERR(handle)) + RETURN(PTR_ERR(handle)); + + if (fsfilt->fs_set_xattr) + rc = fsfilt->fs_set_xattr(inode, handle, AUDIT_ATTR_EA, + mask, sizeof(*mask)); + + fsfilt->fs_commit(inode->i_sb, inode, handle, 1); + RETURN(rc); + +} + +static int smfs_audit_post_op(hook_op code, struct inode * inode, void * msg, + int ret, void * arg) +{ + int rc = 0, len; + char * buffer = NULL; + struct audit_record * rec = NULL; + struct llog_rec_hdr * llh; + struct timeval cur_time; + struct audit_priv * priv = arg; + audit_get_op * handler = priv->audit_get_record; + + //check that we are in lustre ctxt + if (!SMFS_IS(I2SMI(inode)->smi_flags, SMFS_PLG_AUDIT)) + return 0; + + if (!handler || !handler[code]) + return 0; + + if (smfs_audit_check(inode, code, ret, priv, msg) == 0) + return 0; + + ENTRY; + + do_gettimeofday(&cur_time); + + OBD_ALLOC(buffer, PAGE_SIZE); + if (!buffer) + RETURN(-ENOMEM); + + llh = (void*)buffer; + //fill common fields + rec = (void*)(buffer + sizeof(*llh)); + + rec->result = ret; + rec->uid = current->uid; + rec->gid = current->gid; + rec->nid = current->user->nid; + rec->time = cur_time.tv_sec * USEC_PER_SEC + cur_time.tv_usec; + + + len = handler[code](inode, msg, priv, (char*)rec, + &llh->lrh_type); + + llh->lrh_len = size_round(len); + + rc = llog_cat_add_rec(priv->audit_ctxt->loc_handle, llh, NULL, + (void*)rec, NULL, NULL); + if (rc != 0) { + CERROR("Error adding audit record: %d\n", rc); + rc= -EINVAL; + } else { + audit_notify(priv->audit_ctxt->loc_handle, priv->au_id2name); + } + + OBD_FREE(buffer, PAGE_SIZE); + + RETURN(rc); +} + +/* Helpers */ +static int smfs_trans_audit (struct super_block *sb, void *arg, + struct audit_priv * priv) +{ + int size = 1; //one record in log per operation. + + return size; +} + +extern int mds_alloc_inode_ids(struct obd_device *, struct inode *, + void *, struct lustre_id *, struct lustre_id *); + +static int smfs_start_audit(struct super_block *sb, void *arg, + struct audit_priv * audit_p) +{ + struct smfs_super_info * smb = S2SMI(sb); + struct fsfilt_operations * fsfilt = smb->sm_fsfilt; + struct obd_device *obd = arg; + struct file * f; + int rc = 0; + + ENTRY; + + //is plugin already activated + if (SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT)) + RETURN(0); + + rc = audit_start_transferd(); + if (rc) { + CERROR("can't start audit transfer daemon. rc:%d\n", rc); + RETURN(rc); + } + + if (obd && obd->obd_type && obd->obd_type->typ_name) { + if (!strcmp(obd->obd_type->typ_name, "mds")) { + CDEBUG(D_INODE, "Setup MDS audit handler\n"); + audit_mds_setup(obd, sb, audit_p); + } + else if (!strcmp(obd->obd_type->typ_name, "obdfilter")) { + CDEBUG(D_INODE, "Setup OST audit handler\n"); + audit_ost_setup(obd, sb, audit_p); + } + else { + CDEBUG(D_INODE, "Unknown obd type %s\n", + obd->obd_type->typ_name); + RETURN(0); + } + } + //read fs audit settings if any + audit_p->a_mask = AUDIT_OFF; + + f = filp_open(AUDIT_ATTR_FILE, O_RDONLY, 0644); + if (!IS_ERR(f)) { + loff_t off = 0; + rc = fsfilt->fs_read_record(f, &audit_p->a_mask, + sizeof(audit_p->a_mask), &off); + if (rc) { + CERROR("error reading audit setting: rc = %d\n", rc); + } + filp_close(f, 0); + } + + SMFS_SET(smb->plg_flags, SMFS_PLG_AUDIT); + + RETURN(0); +} + +int smfs_stop_audit(struct super_block *sb, void *arg, + struct audit_priv * audit_p) +{ + struct smfs_super_info * smb = S2SMI(sb); + struct llog_ctxt *ctxt = audit_p->audit_ctxt; + ENTRY; + + if (!SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT)) + RETURN(0); + + audit_stop_transferd(); + + SMFS_CLEAR(smb->plg_flags, SMFS_PLG_AUDIT); + + if (ctxt->loc_llogs) + ctxt->loc_llogs->llog_ctxt[LLOG_AUDIT_ORIG_CTXT] = NULL; + + llog_catalog_cleanup(ctxt); + OBD_FREE(ctxt, sizeof(*ctxt)); + audit_p->audit_ctxt = NULL; + + RETURN(0); +} + +int smfs_audit_set_info(struct super_block *sb, void *arg, + struct audit_priv *priv) { + struct plg_info_msg * msg = arg; + if (KEY_IS(msg->key, "id2name")) { + priv->au_id2name = msg->val; + } + + return 0; +} + +typedef int (*audit_helper)(struct super_block * sb, void *msg, struct audit_priv *); +static audit_helper smfs_audit_helpers[PLG_HELPER_MAX] = { + [PLG_START] smfs_start_audit, + [PLG_STOP] smfs_stop_audit, + [PLG_TRANS_SIZE] smfs_trans_audit, + [PLG_TEST_INODE] NULL, + [PLG_SET_INODE] NULL, + [PLG_SET_INFO] smfs_audit_set_info, +}; + +static int smfs_audit_help_op(int code, struct super_block * sb, + void * arg, void * priv) +{ + int rc = 0; + + if (smfs_audit_helpers[code]) + rc = smfs_audit_helpers[code](sb, arg, (struct audit_priv *) priv); + return rc; +} + +static int smfs_exit_audit(struct super_block *sb, + void * arg) +{ + struct audit_priv * priv = arg; + struct smfs_plugin * plg; + ENTRY; + + plg = smfs_deregister_plugin(sb, SMFS_PLG_AUDIT); + if (plg) + OBD_FREE(plg, sizeof(*plg)); + else + CERROR("Cannot find AUDIT plugin while unregistering\n"); + + if (priv) + OBD_FREE(priv, sizeof(*priv)); + + RETURN(0); +} + +int smfs_init_audit(struct super_block *sb) +{ + int rc = 0; + struct audit_priv * priv = NULL; + struct smfs_plugin * plg = NULL; + + ENTRY; + + OBD_ALLOC(plg, sizeof(*plg)); + if (!plg) { + rc = -ENOMEM; + goto exit; + } + + plg->plg_type = SMFS_PLG_AUDIT; + plg->plg_post_op = &smfs_audit_post_op; + plg->plg_helper = &smfs_audit_help_op; + plg->plg_exit = &smfs_exit_audit; + + OBD_ALLOC(priv, sizeof(*priv)); + if (!priv) { + rc = -ENOMEM; + goto exit; + } + + plg->plg_private = priv; + rc = smfs_register_plugin(sb, plg); + if (!rc) + RETURN(0); +exit: + if (priv) + OBD_FREE(priv, sizeof(*priv)); + + if (plg) + OBD_FREE(plg, sizeof(*plg)); + + RETURN(rc); + +} + +int audit_client_log(struct super_block * sb, struct audit_msg * msg) +{ + struct smfs_super_info * smb = S2SMI(sb); + char *buffer = NULL, *pbuf = NULL; + struct audit_record * rec = NULL; + struct llog_rec_hdr * llh; + struct llog_handle * ll_handle = NULL; + int len = 0, rc = 0; + struct timeval cur_time; + //char name[32]; + struct audit_priv * priv; + + do_gettimeofday(&cur_time); + + priv = smfs_get_plg_priv(smb, SMFS_PLG_AUDIT); + if (!priv) + RETURN(-EINVAL); + + ll_handle = priv->audit_ctxt->loc_handle; + + OBD_ALLOC(buffer, PAGE_SIZE); + if (!buffer) + RETURN(-ENOMEM); + + llh = (void*)buffer; + llh->lrh_type = SMFS_AUDIT_GEN_REC; + pbuf = buffer + sizeof(*llh); + + //fill common fields + rec = (void*)(pbuf); + rec->opcode = msg->code; + rec->result = msg->result; + rec->uid = msg->uid; + rec->gid = msg->gid; + rec->nid = msg->nid; + rec->time = cur_time.tv_sec * USEC_PER_SEC + cur_time.tv_usec; + pbuf += sizeof(*rec); + + switch (msg->code) { + case AUDIT_READ: + case AUDIT_WRITE: + case AUDIT_MMAP: + case AUDIT_OPEN: + case AUDIT_STAT: + len = audit_rec_from_id(&pbuf, &msg->id); + break; + default: + CERROR("Unknown code %i in audit_msg\n", msg->code); + } + + llh->lrh_len = size_round(len); + + rc = llog_cat_add_rec(ll_handle, llh, NULL, (void*)rec, NULL, NULL); + if (rc != 0) { + CERROR("Error adding audit client record: %d\n", rc); + rc= -EINVAL; + } else { + audit_notify(ll_handle, priv->au_id2name); + } + + OBD_FREE(buffer, PAGE_SIZE); + return rc; +} + diff --git a/lustre/smfs/audit_mds.c b/lustre/smfs/audit_mds.c new file mode 100644 index 0000000..729ffc8 --- /dev/null +++ b/lustre/smfs/audit_mds.c @@ -0,0 +1,267 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * lustre/smfs/audit_mds.c + * Lustre filesystem audit part for MDS + * + * Copyright (C) 2004 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif + +#define DEBUG_SUBSYSTEM S_SM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "smfs_internal.h" + +int static audit_mds_create_rec(struct inode * parent, void * arg, + struct audit_priv * priv, char * buffer, + __u32 * type) +{ + struct hook_msg * msg = arg; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + struct inode * inode = msg->dentry->d_inode; + int len = sizeof(*rec); + + rec->opcode = AUDIT_CREATE; + if (priv->result == 0) { //successfull operation + len += audit_fill_id_rec(&pbuf, inode); + *type = SMFS_AUDIT_GEN_REC; + } + else { //failed operation + len += audit_fill_id_rec(&pbuf, parent); + len += audit_fill_name_rec(&pbuf, msg->dentry->d_name.name, + msg->dentry->d_name.len); + + *type = SMFS_AUDIT_NAME_REC; + } + return len; +} + +int static audit_mds_link_rec(struct inode * parent, void * arg, + struct audit_priv * priv, char * buffer, + __u32 *type) +{ + struct hook_link_msg * msg = arg; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + struct inode * inode = msg->dentry->d_inode; + int len = sizeof(*rec); + + rec->opcode = AUDIT_LINK; + + /* these things will be needed always */ + len += audit_fill_id_rec(&pbuf, inode); + len += audit_fill_id_rec(&pbuf, parent); + len += audit_fill_name_rec(&pbuf, msg->dentry->d_name.name, + msg->dentry->d_name.len); + *type = SMFS_AUDIT_NAME_REC; + + return len; +} + +int static audit_mds_unlink_rec(struct inode * parent, void * arg, + struct audit_priv * priv, char * buffer, + __u32 *type) +{ + struct hook_unlink_msg * msg = arg; + struct inode * inode = msg->dentry->d_inode; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + int len = sizeof(*rec); + + rec->opcode = AUDIT_UNLINK; + + + len += audit_fill_id_rec(&pbuf, inode); + len += audit_fill_id_rec(&pbuf, parent); + if (priv->result == 0) { + len += audit_fill_name_rec(&pbuf, msg->dentry->d_name.name, + msg->dentry->d_name.len); + *type = SMFS_AUDIT_NAME_REC; + } else { + //in case of failure name shouldn't be saved + *type = SMFS_AUDIT_GEN_REC; + } + + return len; +} + +int static audit_mds_rename_rec(struct inode * parent, void * arg, + struct audit_priv * priv, char * buffer, + __u32 *type) +{ + struct hook_rename_msg * msg = arg; + struct inode * inode = msg->dentry->d_inode; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + int len = sizeof(*rec); + + rec->opcode = AUDIT_RENAME; + + len += audit_fill_id_rec(&pbuf, inode); + if (priv->result == 0) { + len += audit_fill_id_rec(&pbuf, msg->old_dir); + len += audit_fill_name_rec(&pbuf, msg->dentry->d_name.name, + msg->dentry->d_name.len); + } else { + len += audit_fill_id_rec(&pbuf, msg->new_dir); + len += audit_fill_name_rec(&pbuf, msg->new_dentry->d_name.name, + msg->new_dentry->d_name.len); + } + + *type = SMFS_AUDIT_NAME_REC; + + return len; + +} + +int static audit_mds_setattr_rec(struct inode * inode, void * arg, + struct audit_priv * priv, char * buffer, + __u32 *type) +{ + //struct hook_attr_msg * msg = arg; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + int len = sizeof(*rec); + + rec->opcode = AUDIT_SETATTR; + len += audit_fill_id_rec(&pbuf, inode); + *type = SMFS_AUDIT_GEN_REC; + + return len; +} + +int static audit_mds_readlink_rec(struct inode * inode, void * arg, + struct audit_priv * priv, char * buffer, + __u32 *type) +{ + //struct hook_symlink_msg * msg = arg; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + int len = sizeof(*rec); + + rec->opcode = AUDIT_READLINK; + len += audit_fill_id_rec(&pbuf, inode); + *type = SMFS_AUDIT_GEN_REC; + + return len; +} + +int static audit_mds_readdir_rec(struct inode * inode, void * arg, + struct audit_priv * priv, char * buffer, + __u32 *type) +{ + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + int len = sizeof(*rec); + + rec->opcode = AUDIT_READDIR; + len += audit_fill_id_rec(&pbuf, inode); + *type = SMFS_AUDIT_GEN_REC; + + return len; +} + +/* for special records from failed auth and open/stat*/ +int audit_mds_special_rec(struct inode * inode, void * arg, + struct audit_priv * priv, char *buffer, + __u32 * type) +{ + struct audit_info * info = arg; + struct audit_msg * msg = &info->m; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + int len = sizeof(*rec); + + //rewrite some fields + rec->opcode = msg->code; + rec->result = msg->result; + rec->uid = msg->uid; + rec->gid = msg->gid; + rec->nid = msg->nid; + + len += audit_rec_from_id(&pbuf, &msg->id); + switch (rec->opcode) + { + case AUDIT_OPEN: + case AUDIT_CREATE: + if (info->name && info->namelen > 0) { + len += audit_fill_name_rec(&pbuf, + info->name, + info->namelen); + *type = SMFS_AUDIT_NAME_REC; + break; + } + default: + *type = SMFS_AUDIT_GEN_REC; + } + + return len; +} + +static audit_get_op audit_mds_record[HOOK_MAX] = { + [HOOK_CREATE] audit_mds_create_rec, + [HOOK_LINK] audit_mds_link_rec, + [HOOK_UNLINK] audit_mds_unlink_rec, + [HOOK_SYMLINK] audit_mds_create_rec, + [HOOK_READLINK] audit_mds_readlink_rec, + [HOOK_MKDIR] audit_mds_create_rec, + [HOOK_RMDIR] audit_mds_unlink_rec, + [HOOK_MKNOD] audit_mds_create_rec, + [HOOK_RENAME] audit_mds_rename_rec, + [HOOK_SETATTR] audit_mds_setattr_rec, + [HOOK_F_SETATTR] audit_mds_setattr_rec, + [HOOK_SPECIAL] audit_mds_special_rec, + [HOOK_READDIR] audit_mds_readdir_rec, +}; + +int audit_mds_setup(struct obd_device * obd, struct super_block *sb, + struct audit_priv *priv) +{ + int rc; + struct smfs_super_info * smb = S2SMI(sb); + struct llog_ctxt **ctxt = &priv->audit_ctxt; + + //this will do OBD_ALLOC() for ctxt + rc = llog_catalog_setup(ctxt, AUDIT_MDS_NAME, smb->smsi_exp, + smb->smsi_ctxt, smb->sm_fsfilt, + smb->smsi_logs_dir, smb->smsi_objects_dir); + + /* export audit llog ctxt */ + if (*ctxt) { + (*ctxt)->loc_idx = LLOG_AUDIT_ORIG_CTXT; + (*ctxt)->loc_obd = obd; + (*ctxt)->loc_llogs = &obd->obd_llogs; + (*ctxt)->loc_llogs->llog_ctxt[LLOG_AUDIT_ORIG_CTXT] = *ctxt; + } + priv->audit_get_record = &audit_mds_record; + return 0; +} diff --git a/lustre/smfs/audit_ost.c b/lustre/smfs/audit_ost.c new file mode 100644 index 0000000..7cb32a2 --- /dev/null +++ b/lustre/smfs/audit_ost.c @@ -0,0 +1,143 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * lustre/smfs/audit_mds.c + * Lustre filesystem audit part for MDS + * + * Copyright (C) 2004 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif + +#define DEBUG_SUBSYSTEM S_SM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "smfs_internal.h" + +static int audit_ost_create_rec(struct inode * parent, void * arg, + struct audit_priv * priv, char * buffer, + __u32 * type) +{ + struct hook_msg * msg = arg; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + struct inode * inode = msg->dentry->d_inode; + int len = sizeof(*rec); + + //TODO: useless until lustre inode id is in EA + rec->opcode = AUDIT_CREATE; + len += audit_fill_id_rec(&pbuf, inode); + *type = SMFS_AUDIT_GEN_REC; + return len; +} + +static int audit_ost_unlink_rec(struct inode * parent, void * arg, + struct audit_priv * priv, char * buffer, + __u32 *type) +{ + struct hook_unlink_msg * msg = arg; + struct inode * inode = msg->dentry->d_inode; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + int len = sizeof(*rec); + + //TODO: useless until lustre inode id is in EA + rec->opcode = AUDIT_UNLINK; + len += audit_fill_id_rec(&pbuf, inode); + len += audit_fill_id_rec(&pbuf, parent); + *type = SMFS_AUDIT_GEN_REC; + + return len; +} + +int static audit_ost_setattr_rec(struct inode * inode, void * arg, + struct audit_priv * priv, char * buffer, + __u32 *type) +{ + //struct hook_attr_msg * msg = arg; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + int len = sizeof(*rec); + + //TODO: useless until lustre inode id is in EA + rec->opcode = AUDIT_SETATTR; + len += audit_fill_id_rec(&pbuf, inode); + *type = SMFS_AUDIT_GEN_REC; + + return len; +} + +int static audit_ost_rw_rec(struct inode * inode, void * arg, + struct audit_priv * priv, char * buffer, + __u32 * type) +{ + struct hook_rw_msg * msg = arg; + struct audit_record * rec = (void*)buffer; + char * pbuf = buffer + sizeof(*rec); + int len = sizeof(*rec); + + rec->opcode = msg->write ? AUDIT_WRITE : AUDIT_READ; + len += audit_rec_from_id(&pbuf, msg->id); + *type = SMFS_AUDIT_GEN_REC; + + return len; +} + +static audit_get_op audit_ost_record[HOOK_MAX] = { + [HOOK_SI_READ] audit_ost_rw_rec, + [HOOK_SI_WRITE] audit_ost_rw_rec, + [HOOK_CREATE] audit_ost_create_rec, + [HOOK_UNLINK] audit_ost_unlink_rec, + [HOOK_SETATTR] audit_ost_setattr_rec, + [HOOK_F_SETATTR] audit_ost_setattr_rec +}; + +int audit_ost_setup(struct obd_device * obd, struct super_block *sb, + struct audit_priv *priv) +{ + int rc; + struct smfs_super_info * smb = S2SMI(sb); + struct llog_ctxt **ctxt = &priv->audit_ctxt; + + //this will do OBD_ALLOC() for ctxt + rc = llog_catalog_setup(ctxt, AUDIT_OST_NAME, smb->smsi_exp, + smb->smsi_ctxt, smb->sm_fsfilt, + smb->smsi_logs_dir, smb->smsi_objects_dir); + + /* export audit llog ctxt */ + if (*ctxt) { + (*ctxt)->loc_idx = LLOG_AUDIT_ORIG_CTXT; + (*ctxt)->loc_obd = obd; + (*ctxt)->loc_llogs = &obd->obd_llogs; + (*ctxt)->loc_llogs->llog_ctxt[LLOG_AUDIT_ORIG_CTXT] = *ctxt; + } + + priv->audit_get_record = audit_ost_record; + return 0; +} diff --git a/lustre/smfs/audit_transfer.c b/lustre/smfs/audit_transfer.c new file mode 100644 index 0000000..92a293f --- /dev/null +++ b/lustre/smfs/audit_transfer.c @@ -0,0 +1,357 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * lustre/smfs/audit_transfer.c + * + * Copyright (C) 2004 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif + +#define DEBUG_SUBSYSTEM S_SM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "smfs_internal.h" + +struct transfer_item { + struct llog_handle *ti_llh; + struct list_head ti_link; + void * id2name; +}; + +#define TRANSFERD_STOP 0 +struct transferd_ctl { + unsigned long tc_flags; + wait_queue_head_t tc_waitq; + struct completion tc_starting; + struct completion tc_stopping; + + struct list_head tc_list; + spinlock_t tc_lock; +}; + +static struct transferd_ctl transferd_tc; +static DECLARE_MUTEX(transferd_sem); +static int transferd_users = 0; +char *buf = NULL; + +int audit_notify(struct llog_handle *llh, void * arg) +{ + struct transfer_item *ti; + ENTRY; + + down(&transferd_sem); + if (transferd_users == 0) { + up(&transferd_sem); + RETURN(0); + } + up(&transferd_sem); + + if (test_bit(TRANSFERD_STOP, &transferd_tc.tc_flags)) { + CDEBUG(D_INFO, "transfer daemon stopped\n"); + RETURN(0); + } + + OBD_ALLOC(ti, sizeof(*ti)); + if (ti == NULL) + RETURN(-ENOMEM); + + INIT_LIST_HEAD(&ti->ti_link); + ti->ti_llh = llh; + ti->id2name = arg; + + spin_lock(&transferd_tc.tc_lock); + list_add_tail(&ti->ti_link, &transferd_tc.tc_list); + spin_unlock(&transferd_tc.tc_lock); + + wake_up(&transferd_tc.tc_waitq); + + RETURN(0); +} + +const char *opstr[AUDIT_MAX] = { + [AUDIT_NONE] "null", + [AUDIT_CREATE] "create", + [AUDIT_LINK] "link", + [AUDIT_UNLINK] "unlink", + [AUDIT_SYMLINK] "symlink", + [AUDIT_RENAME] "rename", + [AUDIT_SETATTR] "setattr", + [AUDIT_WRITE] "write", + [AUDIT_READ] "read", + [AUDIT_OPEN] "open", + [AUDIT_STAT] "stat", + [AUDIT_MMAP] "mmap", + [AUDIT_READLINK] "readlink", + [AUDIT_READDIR] "readdir", +}; + +#define construct_header(buf, size, rec) \ + snprintf(buf, size, \ + "AUDIT [%u] [nid: "LPU64" uid: %u gid: %u rc: %d] [%s] ", \ + rec->time, rec->nid, rec->uid, rec->gid, (__s16)rec->result, \ + opstr[rec->opcode]); + +#define REC2ID(rec, id) { \ + id_ino(id) = rec->au_num; \ + id_gen(id) = rec->au_gen; \ + id_type(id) = rec->au_type; \ + id_fid(id) = rec->au_fid; \ + id_group(id) = rec->au_mds; \ +} + +static int +transfer_record(struct obd_device *obd, struct audit_record *rec, int type, void * data) +{ + struct audit_id_record *id_rec = + (struct audit_id_record *)((char *)rec + sizeof(*rec)); + struct audit_name_record *name_rec = NULL; + int (*audit_id2name)(struct obd_device *obd, char **name, + int *namelen, struct lustre_id *id) = data; + + int n, rc = 0; + ENTRY; + + CDEBUG(D_INFO, "transfer %s\n", opstr[rec->opcode]); + + memset(buf, 0, PAGE_SIZE); + n = construct_header(buf, PAGE_SIZE, rec); + if (n < 0) + RETURN(n); + + switch (rec->opcode) + { + case AUDIT_UNLINK: + if (type != SMFS_AUDIT_NAME_REC) + break; + case AUDIT_LINK: + case AUDIT_RENAME: + id_rec++; + default: + break; + } + + if (audit_id2name) { + char *name = NULL; + struct lustre_id id; + int namelen = 0; + + REC2ID(id_rec, &id); + rc = audit_id2name(obd, &name, &namelen, &id); + if (rc < 0) { + strncat(buf, "unknown", PAGE_SIZE - n); + n += strlen("unknown"); + } else if (namelen == 0) { + //root itself + if (type != SMFS_AUDIT_NAME_REC) + strcat(buf, "/"); + } else { + strncat(buf, name, PAGE_SIZE - n); + n += namelen; + OBD_FREE(name, namelen); + } + } + + if (type == SMFS_AUDIT_NAME_REC) { + name_rec = (struct audit_name_record *)((char *)(++id_rec)); + strncat(buf, "/", 1); + n += 1; + strncat(buf, name_rec->name, PAGE_SIZE - n); + } + + CDEBUG(D_INFO, "%s\n", buf); + + printk("%s\n", buf); + + RETURN(rc); +} + +static int transfer_cb(struct llog_handle *llh, struct llog_rec_hdr *rec, + void *data) +{ + struct obd_device *obd = llh->lgh_ctxt->loc_obd; + struct audit_record *ad_rec; + int rc = 0; + ENTRY; + + if (!(le32_to_cpu(llh->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) { + CERROR("log is not plain\n"); + RETURN(-EINVAL); + } + if (rec->lrh_type != cpu_to_le32(SMFS_AUDIT_GEN_REC) && + rec->lrh_type != cpu_to_le32(SMFS_AUDIT_NAME_REC)) { + CERROR("log record type error\n"); + RETURN(-EINVAL); + } + + ad_rec = (struct audit_record *)((char *)rec + sizeof(*rec)); + + LASSERT(ad_rec->opcode < AUDIT_MAX); + + rc = transfer_record(obd, ad_rec, rec->lrh_type, data); + if (rc) + CERROR("transfer record failed! rc:%d\n", rc); + + RETURN(LLOG_DEL_RECORD); +} + +static int audit_transfer(struct transfer_item *ti) +{ + struct llog_handle *llh = ti->ti_llh; + int rc = 0; + ENTRY; + + rc = llog_cat_process(llh, (llog_cb_t)&transfer_cb, ti->id2name); + if (rc) + CERROR("process catalog log failed: rc(%d)\n", rc); + + RETURN(0); +} + +static int transferd_check(struct transferd_ctl *tc) +{ + int rc = 0; + ENTRY; + + if (test_bit(TRANSFERD_STOP, &tc->tc_flags)) + RETURN(1); + + spin_lock(&tc->tc_lock); + rc = list_empty(&tc->tc_list) ? 0 : 1; + spin_unlock(&tc->tc_lock); + + RETURN(rc); +} + +static int transferd(void *arg) +{ + struct transferd_ctl *tc = arg; + unsigned long flags; + struct list_head *pos, *tmp; + struct transfer_item *ti = NULL; + ENTRY; + + lock_kernel(); + + /* ptlrpc_daemonize() */ + exit_mm(current); + lustre_daemonize_helper(); + exit_files(current); + reparent_to_init(); + + SIGNAL_MASK_LOCK(current, flags); + sigfillset(¤t->blocked); + RECALC_SIGPENDING; + SIGNAL_MASK_UNLOCK(current, flags); + THREAD_NAME(current->comm, sizeof(current->comm) - 1, "%s", + "audit_transferd"); + unlock_kernel(); + + complete(&tc->tc_starting); + + LASSERT(buf == NULL); + OBD_ALLOC(buf, PAGE_SIZE); + LASSERT(buf != NULL); + + while (1) { + struct l_wait_info lwi = { 0 }; + + l_wait_event(tc->tc_waitq, transferd_check(tc), &lwi); + + if (test_bit(TRANSFERD_STOP, &tc->tc_flags)) + break; + + spin_lock(&tc->tc_lock); + LASSERT(!list_empty(&tc->tc_list)); + ti = list_entry(tc->tc_list.next, struct transfer_item, ti_link); + list_del_init(&ti->ti_link); + spin_unlock(&tc->tc_lock); + + audit_transfer(ti); + OBD_FREE(ti, sizeof(*ti)); + + } + + OBD_FREE(buf, PAGE_SIZE); + + spin_lock(&tc->tc_lock); + list_for_each_safe(pos, tmp, &tc->tc_list) { + ti = list_entry(pos, struct transfer_item, ti_link); + list_del_init(&ti->ti_link); + OBD_FREE(ti, sizeof(*ti)); + } + spin_unlock(&tc->tc_lock); + + complete(&tc->tc_stopping); + RETURN(0); +} + +int audit_start_transferd() +{ + int rc = 0; + ENTRY; + + down(&transferd_sem); + if (++transferd_users != 1) + GOTO(out, rc = 0); + + memset(&transferd_tc, 0, sizeof(transferd_tc)); + init_completion(&transferd_tc.tc_starting); + init_completion(&transferd_tc.tc_stopping); + init_waitqueue_head(&transferd_tc.tc_waitq); + transferd_tc.tc_flags = 0; + INIT_LIST_HEAD(&transferd_tc.tc_list); + spin_lock_init(&transferd_tc.tc_lock); + + if (kernel_thread(transferd, &transferd_tc, 0) < 0) { + transferd_users--; + GOTO(out, rc = -ECHILD); + } + + wait_for_completion(&transferd_tc.tc_starting); +out: + up(&transferd_sem); + RETURN(rc); +} + +int audit_stop_transferd(void) +{ + int rc = 0; + ENTRY; + + down(&transferd_sem); + if (--transferd_users > 0) + GOTO(out, rc = 0); + + set_bit(TRANSFERD_STOP, &transferd_tc.tc_flags); + wake_up(&transferd_tc.tc_waitq); + wait_for_completion(&transferd_tc.tc_stopping); +out: + up(&transferd_sem); + RETURN(rc); +} diff --git a/lustre/smfs/cache.c b/lustre/smfs/cache.c index 80c6b5d..cb8d900 100644 --- a/lustre/smfs/cache.c +++ b/lustre/smfs/cache.c @@ -205,8 +205,6 @@ static void setup_sm_special_ops(struct inode *inode) unlock_kernel(); } -#define SMFS_IOPEN_INO 1 - void sm_set_inode_ops(struct inode *inode) { struct smfs_super_info *smb = S2SMI(inode->i_sb); diff --git a/lustre/smfs/cache_space.c b/lustre/smfs/cache_space.c index 6b33b29..bbbdf0b 100644 --- a/lustre/smfs/cache_space.c +++ b/lustre/smfs/cache_space.c @@ -616,7 +616,7 @@ static post_lru_op smfs_lru_post[HOOK_MAX] = { [HOOK_READDIR] NULL, }; -static int smfs_lru_pre_op(int op, struct inode *inode, void * msg, int ret, +static int smfs_lru_pre_op(hook_op op, struct inode *inode, void * msg, int ret, void *priv) { int rc = 0; @@ -628,7 +628,7 @@ static int smfs_lru_pre_op(int op, struct inode *inode, void * msg, int ret, RETURN(rc); } -static int smfs_lru_post_op(int op, struct inode *inode, void *msg, int ret, +static int smfs_lru_post_op(hook_op op, struct inode *inode, void *msg, int ret, void *priv) { int rc = 0; @@ -644,16 +644,6 @@ static int smfs_lru_post_op(int op, struct inode *inode, void *msg, int ret, } /* Helpers */ -static int smfs_exit_lru(struct super_block *sb, void * arg, void * priv) -{ - ENTRY; - - smfs_deregister_plugin(sb, SMFS_PLG_LRU); - - EXIT; - return 0; -} - static int smfs_trans_lru (struct super_block *sb, void *arg, void * priv) { int size; @@ -734,7 +724,6 @@ static int smfs_stop_lru(struct super_block *sb, void *arg, void * priv) typedef int (*lru_helper)(struct super_block * sb, void *msg, void *); static lru_helper smfs_lru_helpers[PLG_HELPER_MAX] = { - [PLG_EXIT] smfs_exit_lru, [PLG_START] smfs_start_lru, [PLG_STOP] smfs_stop_lru, [PLG_TRANS_SIZE] smfs_trans_lru, @@ -751,20 +740,47 @@ static int smfs_lru_help_op(int code, struct super_block * sb, RETURN(0); } +static int smfs_exit_lru(struct super_block *sb, void * arg) +{ + struct smfs_plugin * plg; + + ENTRY; + + plg = smfs_deregister_plugin(sb, SMFS_PLG_LRU); + if (plg) + OBD_FREE(plg, sizeof(*plg)); + else + CERROR("Cannot find LRU plugin while unregistering\n"); + + EXIT; + return 0; +} + int smfs_init_lru(struct super_block *sb) { - struct smfs_plugin plg = { - .plg_type = SMFS_PLG_LRU, - .plg_pre_op = &smfs_lru_pre_op, - .plg_post_op = &smfs_lru_post_op, - .plg_helper = &smfs_lru_help_op, - .plg_private = NULL - }; + struct smfs_plugin * plg = NULL; int rc = 0; ENTRY; - - rc = smfs_register_plugin(sb, &plg); + + OBD_ALLOC(plg, sizeof(*plg)); + if (!plg) { + rc = -ENOMEM; + goto exit; + } + + plg->plg_type = SMFS_PLG_LRU; + plg->plg_pre_op = &smfs_lru_pre_op; + plg->plg_post_op = &smfs_lru_post_op; + plg->plg_helper = &smfs_lru_help_op; + plg->plg_exit = &smfs_exit_lru; + + rc = smfs_register_plugin(sb, plg); + if (!rc) + RETURN(0); +exit: + if (plg) + OBD_FREE(plg, sizeof(*plg)); RETURN(rc); } diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index 011dc60..c45b289 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -626,7 +626,7 @@ static int smfs_rmdir(struct inode *dir, struct dentry *dentry) rc = -ENOMEM; goto exit; } - + handle = smfs_trans_start(dir, FSFILT_OP_RMDIR, NULL); if (IS_ERR(handle) ) { rc = -ENOSPC; @@ -747,7 +747,8 @@ static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct hook_rename_msg msg = { .dentry = old_dentry, .new_dir = new_dir, - .new_dentry = new_dentry + .old_dir = old_dir, + .new_dentry = new_dentry, }; ENTRY; @@ -892,12 +893,6 @@ static int smfs_readdir(struct file *filp, void *dirent, filldir_t filldir) struct inode *cache_inode = NULL; struct smfs_file_info *sfi = NULL; int rc = 0; - struct hook_readdir_msg msg = { - .dentry = dentry, - .filp = filp, - .dirent = dirent, - .filldir = filldir - }; ENTRY; @@ -908,11 +903,8 @@ static int smfs_readdir(struct file *filp, void *dirent, filldir_t filldir) sfi = F2SMFI(filp); if (sfi->magic != SMFS_FILE_MAGIC) BUG(); - SMFS_PRE_HOOK(dentry->d_inode, HOOK_READDIR, &msg); - rc = cache_inode->i_fop->readdir(sfi->c_file, dirent, filldir); - SMFS_POST_HOOK(dentry->d_inode, HOOK_READDIR, &msg, rc); duplicate_file(filp, sfi->c_file); RETURN(rc); diff --git a/lustre/smfs/file.c b/lustre/smfs/file.c index 88e3931..49763fd 100644 --- a/lustre/smfs/file.c +++ b/lustre/smfs/file.c @@ -392,9 +392,9 @@ int smfs_setattr(struct dentry *dentry, struct iattr *attr) struct dentry *cache_dentry; void *handle = NULL; int rc = 0; - struct hook_setattr_msg msg = { + struct hook_attr_msg msg = { .dentry = dentry, - .attr = attr + .attr = attr, }; ENTRY; @@ -432,6 +432,9 @@ int smfs_setxattr(struct dentry *dentry, const char *name, const void *value, { struct inode *cache_inode = I2CI(dentry->d_inode); struct dentry *cache_dentry = NULL; + struct hook_xattr_msg msg = { + .name = (char*)name, + }; int rc = 0; ENTRY; @@ -444,9 +447,12 @@ int smfs_setxattr(struct dentry *dentry, const char *name, const void *value, RETURN(-ENOMEM); pre_smfs_inode(dentry->d_inode, cache_inode); + SMFS_PRE_HOOK(dentry->d_inode, HOOK_SETXATTR, &msg); rc = cache_inode->i_op->setxattr(cache_dentry, name, value, size, flags); + + SMFS_POST_HOOK(dentry->d_inode, HOOK_SETXATTR, &msg, rc); post_smfs_inode(dentry->d_inode, cache_inode); post_smfs_dentry(cache_dentry); @@ -459,6 +465,9 @@ int smfs_getxattr(struct dentry *dentry, const char *name, void *buffer, { struct inode *cache_inode = I2CI(dentry->d_inode); struct dentry *cache_dentry; + struct hook_xattr_msg msg = { + .name = (char*)name, + }; int rc = 0; ENTRY; @@ -471,10 +480,10 @@ int smfs_getxattr(struct dentry *dentry, const char *name, void *buffer, RETURN(-ENOMEM); pre_smfs_inode(dentry->d_inode, cache_inode); - + SMFS_PRE_HOOK(dentry->d_inode, HOOK_GETXATTR, &msg); rc = cache_inode->i_op->getxattr(cache_dentry, name, buffer, size); - + SMFS_POST_HOOK(dentry->d_inode, HOOK_GETXATTR, &msg, rc); post_smfs_inode(dentry->d_inode, cache_inode); post_smfs_dentry(cache_dentry); @@ -486,7 +495,10 @@ ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size) struct inode *cache_inode = I2CI(dentry->d_inode); struct dentry *cache_dentry; int rc = 0; - + struct hook_xattr_msg msg = { + .name = NULL, + }; + ENTRY; LASSERT(cache_inode); @@ -497,9 +509,11 @@ ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size) RETURN(-ENOMEM); pre_smfs_inode(dentry->d_inode, cache_inode); + SMFS_PRE_HOOK(dentry->d_inode, HOOK_LISTXATTR, &msg); rc = cache_inode->i_op->listxattr(cache_dentry, buffer, size); + SMFS_POST_HOOK(dentry->d_inode, HOOK_LISTXATTR, &msg, rc); post_smfs_inode(dentry->d_inode, cache_inode); post_smfs_dentry(cache_dentry); @@ -511,7 +525,9 @@ int smfs_removexattr(struct dentry *dentry, const char *name) struct inode *cache_inode = I2CI(dentry->d_inode); struct dentry *cache_dentry; int rc = 0; - + struct hook_xattr_msg msg = { + .name = (char*)name, + }; ENTRY; LASSERT(cache_inode); @@ -522,9 +538,11 @@ int smfs_removexattr(struct dentry *dentry, const char *name) RETURN(-ENOMEM); pre_smfs_inode(dentry->d_inode, cache_inode); + SMFS_PRE_HOOK(dentry->d_inode, HOOK_REMOVEXATTR, &msg); rc = cache_inode->i_op->removexattr(cache_dentry, name); + SMFS_POST_HOOK(dentry->d_inode, HOOK_REMOVEXATTR, &msg, rc); post_smfs_inode(dentry->d_inode, cache_inode); post_smfs_dentry(cache_dentry); diff --git a/lustre/smfs/fsfilt.c b/lustre/smfs/fsfilt.c index 977069b..752085e 100644 --- a/lustre/smfs/fsfilt.c +++ b/lustre/smfs/fsfilt.c @@ -269,6 +269,9 @@ static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf, loff_t tmp_ppos; loff_t *cache_ppos; ssize_t rc = -EIO; + struct hook_msg msg = { + .dentry = file->f_dentry, + }; ENTRY; @@ -291,6 +294,8 @@ static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf, *cache_ppos = *off; pre_smfs_inode(file->f_dentry->d_inode, cache_inode); + SMFS_PRE_HOOK(file->f_dentry->d_inode, HOOK_READDIR, &msg); + #if CONFIG_SNAPFS /*readdir page*/ if (smfs_dotsnap_inode(file->f_dentry->d_inode)) { @@ -312,6 +317,7 @@ static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf, cache_ppos); #endif + SMFS_POST_HOOK(file->f_dentry->d_inode, HOOK_READDIR, &msg, rc); *off = *cache_ppos; post_smfs_inode(file->f_dentry->d_inode, cache_inode); duplicate_file(file, sfi->c_file); @@ -381,7 +387,11 @@ int fsfilt_smfs_map_inode_pages(struct inode *inode, struct page **page, struct fsfilt_operations *cache_fsfilt = I2FOPS(inode); struct inode *cache_inode = NULL; int rc = -EIO; - + /* + struct hook_rw_msg msg = { + .write = create, + }; + */ ENTRY; if (!cache_fsfilt) @@ -396,9 +406,11 @@ int fsfilt_smfs_map_inode_pages(struct inode *inode, struct page **page, RETURN(-ENOSYS); down(&cache_inode->i_sem); + //SMFS_PRE_HOOK(inode, HOOK_MAP_PAGES, &msg); rc = cache_fsfilt->fs_map_inode_pages(cache_inode, page, pages, blocks, created, create, sem); + up(&cache_inode->i_sem); RETURN(rc); @@ -519,7 +531,7 @@ static int fsfilt_smfs_write_record(struct file *file, void *buf, int bufsize, } static int fsfilt_smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt, - struct dentry *root_dentry) + struct dentry *root_dentry)//, void *data) { struct super_block *sb = NULL; int rc = 0; @@ -529,15 +541,13 @@ static int fsfilt_smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt, if (mnt) { sb = mnt->mnt_sb; - if (obd) - S2SMI(sb)->smsi_exp = obd->obd_self_export; + LASSERT(obd); + S2SMI(sb)->smsi_exp = obd->obd_self_export; - rc = smfs_post_setup(obd, mnt, root_dentry); + rc = smfs_post_setup(obd, mnt, root_dentry);//, data); if (rc) { CERROR("post_setup fails in obd %p rc=%d", obd, rc); } - - } RETURN(rc); @@ -654,7 +664,7 @@ static int fsfilt_smfs_setattr(struct dentry *dentry, void *handle, struct dentry *cache_dentry = NULL; struct inode *cache_inode = I2CI(dentry->d_inode); struct smfs_super_info *sbi = S2SMI(dentry->d_inode->i_sb); - struct hook_setattr_msg msg = { + struct hook_attr_msg msg = { .dentry = dentry, .attr = iattr }; @@ -679,6 +689,7 @@ static int fsfilt_smfs_setattr(struct dentry *dentry, void *handle, * aggregated i_blocks from all OSTs -bzzz */ cache_inode->i_blocks = dentry->d_inode->i_blocks; } + rc = cache_fsfilt->fs_setattr(cache_dentry, handle, iattr, do_trunc); SMFS_POST_HOOK(dentry->d_inode, HOOK_F_SETATTR, &msg, rc); @@ -692,8 +703,7 @@ static int fsfilt_smfs_set_xattr(struct inode *inode, void *handle, char *name, { struct fsfilt_operations *cache_fsfilt = I2FOPS(inode); struct inode *cache_inode = NULL; - struct hook_setxattr_msg msg = { - .inode = inode, + struct hook_xattr_msg msg = { .name = name, .buffer = buffer, .buffer_size = buffer_size @@ -703,14 +713,13 @@ static int fsfilt_smfs_set_xattr(struct inode *inode, void *handle, char *name, ENTRY; if (!cache_fsfilt) - RETURN(rc); + RETURN(-EIO); cache_inode = I2CI(inode); if (!cache_inode) RETURN(rc); pre_smfs_inode(inode, cache_inode); - SMFS_PRE_HOOK(inode, HOOK_F_SETXATTR, &msg); if (cache_fsfilt->fs_set_xattr) rc = cache_fsfilt->fs_set_xattr(cache_inode, handle, name, @@ -737,7 +746,6 @@ static int fsfilt_smfs_get_xattr(struct inode *inode, char *name, RETURN(rc); pre_smfs_inode(inode, cache_inode); - if (cache_fsfilt->fs_get_xattr) rc = cache_fsfilt->fs_get_xattr(cache_inode, name, buffer, buffer_size); @@ -750,6 +758,7 @@ static int fsfilt_smfs_get_xattr(struct inode *inode, char *name, #define XATTR_LUSTRE_MDS_MEA_EA "mea" #define XATTR_LUSTRE_MDS_MID_EA "mid" #define XATTR_LUSTRE_MDS_SID_EA "sid" +#define XATTR_LUSTRE_MDS_PID_EA "pid" #define XATTR_LUSTRE_MDS_KEY_EA "key" static int fsfilt_smfs_set_md(struct inode *inode, void *handle, @@ -778,6 +787,11 @@ static int fsfilt_smfs_set_md(struct inode *inode, void *handle, XATTR_LUSTRE_MDS_MID_EA, lmm, lmm_size); break; + case EA_PID: + rc = fsfilt_smfs_set_xattr(inode, handle, + XATTR_LUSTRE_MDS_PID_EA, + lmm, lmm_size); + break; case EA_KEY: rc = fsfilt_smfs_set_xattr(inode, handle, XATTR_LUSTRE_MDS_KEY_EA, @@ -816,6 +830,16 @@ static int fsfilt_smfs_get_md(struct inode *inode, void *lmm, XATTR_LUSTRE_MDS_MID_EA, lmm, lmm_size); break; + case EA_PID: + rc = fsfilt_smfs_get_xattr(inode, + XATTR_LUSTRE_MDS_PID_EA, + lmm, lmm_size); + break; + case EA_KEY: + rc = fsfilt_smfs_get_xattr(inode, + XATTR_LUSTRE_MDS_KEY_EA, + lmm, lmm_size); + break; default: rc = -EINVAL; } @@ -1164,6 +1188,81 @@ exit: } +static int fsfilt_smfs_set_info (struct super_block *sb, struct inode * inode, + __u32 keylen, void *key, + __u32 valsize, void *val) +{ + int rc = 0; + struct plg_info_msg msg = { + .key = key, + .val = val, + }; + ENTRY; + + if (keylen >= 9 && memcmp(key, "file_read", 9) == 0) { + /* + * this key used to inform smfs on OST about incoming r/w + */ + struct lustre_id * id = val; + struct hook_rw_msg msg = { + .write = 0, + .id = id, + }; + if (inode) + SMFS_POST_HOOK(inode, HOOK_SI_READ, &msg, rc); + } + else if (keylen >= 10 && memcmp(key, "file_write", 10) == 0) { + /* + * this key used to inform smfs on OST about incoming r/w + */ + struct lustre_id * id = val; + struct hook_rw_msg msg = { + .write = 1, + .id = id, + }; + if (inode) + SMFS_POST_HOOK(inode, HOOK_SI_WRITE, &msg, rc); + } + else if (keylen >= 10 && memcmp(key, "audit_info", 10) == 0) { + /* this key used to pass audit data on MDS */ + struct audit_info * info = val; + + SMFS_POST_HOOK(inode, HOOK_SPECIAL, info, info->m.result); + } + else if (keylen >= 8 && memcmp(key, "auditlog", 8) == 0) { + /* + * this key used to inform smfs on OST about client audit data + */ + + audit_client_log(sb, val); + } + else if (keylen == 5 && memcmp(key, "audit", 5) == 0) { + rc = smfs_set_audit(sb, inode, (__u64 *)val); + } + else if (keylen == 7 && memcmp(key, "id2name", 7) == 0) { + rc = SMFS_PLG_HELP(sb, PLG_SET_INFO, &msg); + } + else + rc = -ENOENT; + + RETURN(rc); +} + +static int fsfilt_smfs_get_info (struct super_block *sb, struct inode * inode, + __u32 keylen, void *key, + __u32 *valsize, void *val) +{ + int rc = -ENOENT; + + ENTRY; + + if (keylen == 5 && strcmp(key, "audit") == 0) { + __u64 * mask = val; + rc = smfs_get_audit(sb, inode, NULL, mask); + } + + RETURN(rc); +} static struct fsfilt_operations fsfilt_smfs_ops = { .fs_type = "smfs", @@ -1209,10 +1308,11 @@ static struct fsfilt_operations fsfilt_smfs_ops = { .fs_set_ost_flags = fsfilt_smfs_set_ost_flags, .fs_set_mds_flags = fsfilt_smfs_set_mds_flags, .fs_precreate_rec = fsfilt_smfs_precreate_rec, - .fs_get_reint_log_ctxt = NULL, /*fsfilt_smfs_get_reint_log_ctxt,*/ + .fs_set_info = fsfilt_smfs_set_info, + .fs_get_info = fsfilt_smfs_get_info, .fs_set_snap_item = fsfilt_smfs_set_snap_item, .fs_do_write_cow = fsfilt_smfs_do_write_cow, - }; +}; struct fsfilt_operations *get_smfs_fs_ops(void) { diff --git a/lustre/smfs/kml.c b/lustre/smfs/kml.c index 33851b5..80996bf 100644 --- a/lustre/smfs/kml.c +++ b/lustre/smfs/kml.c @@ -561,7 +561,7 @@ exit: static int kml_setattr(struct inode *inode, void *arg, struct kml_priv *priv) { - struct hook_setattr_msg *msg = arg; + struct hook_attr_msg *msg = arg; int rc = 0, length = 0; char *buffer = NULL; ENTRY; @@ -597,7 +597,7 @@ exit: static int kml_setxattr(struct inode *inode, void *arg, struct kml_priv *priv) { - struct hook_setxattr_msg *msg = arg; + struct hook_xattr_msg *msg = arg; struct kml_buffer kbuf; int rc = 0, length = 0; char *buffer = NULL; @@ -610,7 +610,7 @@ static int kml_setxattr(struct inode *inode, void *arg, struct kml_priv *priv) kbuf.buf = msg->buffer; kbuf.buf_size = msg->buffer_size; - rc = priv->pack_fn(REINT_SETXATTR, buffer, NULL, msg->inode, msg->name, + rc = priv->pack_fn(REINT_SETXATTR, buffer, NULL, inode, msg->name, &kbuf); if (rc <= 0) GOTO(exit, rc); @@ -720,17 +720,21 @@ static post_kml_op smfs_kml_post[HOOK_MAX] = { [HOOK_F_SETXATTR] kml_setxattr, }; -static int smfs_kml_post_op(int code, struct inode * inode, +static int smfs_kml_post_op(hook_op code, struct inode * inode, void * msg, int ret, void * priv) { int rc = 0; ENTRY; - + + //check if inode has flag for KML + if (!SMFS_IS(I2SMI(inode)->smi_flags, SMFS_PLG_KML)) + RETURN(0); + //KML don't handle failed ops if (ret) RETURN(0); - + if (smfs_kml_post[code]) { CDEBUG(D_INODE,"KML: inode %lu, code: %u\n", inode->i_ino, code); rc = smfs_kml_post[code](inode, msg, priv); @@ -740,24 +744,6 @@ static int smfs_kml_post_op(int code, struct inode * inode, } /* Helpers */ -static int smfs_exit_kml(struct super_block *sb, void * arg, struct kml_priv * priv) -{ - struct smfs_plugin * plg = NULL; - ENTRY; - - plg = smfs_deregister_plugin(sb, SMFS_PLG_KML); - if (plg) - OBD_FREE(plg, sizeof(*plg)); - else - CERROR("Cannot find KLM plugin while unregistering\n"); - - if (priv) - OBD_FREE(priv, sizeof(*priv)); - - EXIT; - return 0; -} - static int smfs_trans_kml (struct super_block *sb, void *arg, struct kml_priv * priv) { @@ -803,7 +789,13 @@ static int smfs_start_kml(struct super_block *sb, void *arg, RETURN(rc); } - (*ctxt)->llog_proc_cb = NULL;//smfs_llog_process_rec_cb; + /* connect KML ctxt to obd */ + if (obd && smb->smsi_kml_log) { + smb->smsi_kml_log->loc_idx = LLOG_REINT_ORIG_CTXT; + smb->smsi_kml_log->loc_obd = obd; + smb->smsi_kml_log->loc_llogs = &obd->obd_llogs; + obd->obd_llogs.llog_ctxt[LLOG_REINT_ORIG_CTXT] = smb->smsi_kml_log; + } SMFS_SET(smb->plg_flags, SMFS_PLG_KML); @@ -815,6 +807,7 @@ int smfs_stop_kml(struct super_block *sb, void *arg, { struct smfs_super_info * smb = S2SMI(sb); struct llog_ctxt *ctxt = smb->smsi_kml_log; + struct obd_device * obd = ctxt->loc_obd; ENTRY; if (!SMFS_IS(smb->plg_flags, SMFS_PLG_KML)) @@ -823,6 +816,7 @@ int smfs_stop_kml(struct super_block *sb, void *arg, SMFS_CLEAR(smb->plg_flags, SMFS_PLG_KML); llog_catalog_cleanup(ctxt); + obd->obd_llogs.llog_ctxt[LLOG_REINT_ORIG_CTXT] = NULL; OBD_FREE(ctxt, sizeof(*ctxt)); RETURN(0); @@ -830,7 +824,6 @@ int smfs_stop_kml(struct super_block *sb, void *arg, typedef int (*kml_helper)(struct super_block * sb, void *msg, struct kml_priv *); static kml_helper smfs_kml_helpers[PLG_HELPER_MAX] = { - [PLG_EXIT] smfs_exit_kml, [PLG_START] smfs_start_kml, [PLG_STOP] smfs_stop_kml, [PLG_TRANS_SIZE] smfs_trans_kml, @@ -848,6 +841,25 @@ static int smfs_kml_help_op(int code, struct super_block * sb, return rc; } +static int smfs_exit_kml(struct super_block *sb, void * arg) +{ + struct smfs_plugin * plg = NULL; + struct kml_priv * priv = arg; + ENTRY; + + plg = smfs_deregister_plugin(sb, SMFS_PLG_KML); + if (plg) + OBD_FREE(plg, sizeof(*plg)); + else + CERROR("Cannot find KLM plugin while unregistering\n"); + + if (priv) + OBD_FREE(priv, sizeof(*priv)); + + EXIT; + return 0; +} + int smfs_init_kml(struct super_block *sb) { int rc = 0; @@ -863,8 +875,9 @@ int smfs_init_kml(struct super_block *sb) plg->plg_type = SMFS_PLG_KML; plg->plg_pre_op = NULL; - plg->plg_post_op = &smfs_kml_post_op; - plg->plg_helper = &smfs_kml_help_op; + plg->plg_post_op = smfs_kml_post_op; + plg->plg_helper = smfs_kml_help_op; + plg->plg_exit = smfs_exit_kml; OBD_ALLOC(priv, sizeof(*priv)); if (!priv) { diff --git a/lustre/smfs/smfs_api.h b/lustre/smfs/smfs_api.h index cd97c0f..112ecba 100644 --- a/lustre/smfs/smfs_api.h +++ b/lustre/smfs/smfs_api.h @@ -1,8 +1,39 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2001-2003 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * smfs data structures. + * See also lustre_idl.h for wire formats of requests. + * + */ + +#ifndef __SMFS_API_H +#define __SMFS_API_H + +#include + /* SMFS plugin stuff */ #define SMFS_PLG_KML 0x0001L #define SMFS_PLG_LRU 0x0004L #define SMFS_PLG_COW 0x0020L #define SMFS_PLG_UNDO 0x0100L +#define SMFS_PLG_AUDIT 0x0200L #define SMFS_PLG_DUMMY 0x1000L #define SMFS_PLG_ALL (~0L) @@ -10,7 +41,35 @@ #define SMFS_IS(flags, mask) (flags & mask) #define SMFS_CLEAR(flags, mask) (flags &= ~mask) -typedef int (*smfs_plg_hook)(int hook_code, struct inode *, +typedef enum { + HOOK_CREATE = 1, + HOOK_LOOKUP, + HOOK_LINK, + HOOK_UNLINK, + HOOK_SYMLINK, + HOOK_READLINK, + HOOK_MKDIR, + HOOK_RMDIR, + HOOK_MKNOD, + HOOK_RENAME, + HOOK_SETATTR, + HOOK_GETATTR, + HOOK_WRITE, + HOOK_READ, + HOOK_READDIR, + HOOK_F_SETATTR, + HOOK_SETXATTR, + HOOK_GETXATTR, + HOOK_REMOVEXATTR, + HOOK_LISTXATTR, + HOOK_F_SETXATTR, + HOOK_SI_READ, + HOOK_SI_WRITE, + HOOK_SPECIAL, + HOOK_MAX +} hook_op; + +typedef int (*smfs_plg_hook)(hook_op hook_code, struct inode *, void *arg, int rc, void * priv); typedef int (*smfs_plg_func)(int help_code, struct super_block *, void *arg, void * priv); @@ -23,8 +82,9 @@ struct smfs_plugin { smfs_plg_hook plg_post_op; smfs_plg_func plg_helper; void * plg_private; + int (* plg_exit)(struct super_block *, void *); }; - +/* KML plugin stuff */ #define KML_LOG_NAME "smfs_kml" struct kml_priv { @@ -33,27 +93,15 @@ struct kml_priv { struct inode *, void *, void *); }; -#define UNDO_LOG_NAME "smfs_undo" -struct undo_priv { - struct llog_ctxt *undo_ctxt; +struct audit_priv { + struct llog_ctxt *audit_ctxt; + void * audit_get_record; + void * au_id2name; + int result; + __u64 a_mask; }; - -#define HOOK_CREATE 1 -#define HOOK_LOOKUP 2 -#define HOOK_LINK 3 -#define HOOK_UNLINK 4 -#define HOOK_SYMLINK 5 -#define HOOK_MKDIR 6 -#define HOOK_RMDIR 7 -#define HOOK_MKNOD 8 -#define HOOK_RENAME 9 -#define HOOK_SETATTR 10 -#define HOOK_WRITE 11 -#define HOOK_READDIR 12 -#define HOOK_F_SETATTR 13 -#define HOOK_SETXATTR 14 -#define HOOK_F_SETXATTR 15 -#define HOOK_MAX 16 +typedef int (*audit_get_op)(struct inode *, void *, struct audit_priv *, + char *, __u32*); struct hook_msg { struct dentry * dentry; @@ -77,6 +125,7 @@ struct hook_symlink_msg { struct hook_rename_msg { struct dentry * dentry; + struct inode * old_dir; struct inode * new_dir; struct dentry * new_dentry; }; @@ -94,20 +143,24 @@ struct hook_write_msg { loff_t pos; }; -struct hook_setattr_msg { +struct hook_attr_msg { struct dentry * dentry; struct iattr *attr; }; -struct hook_setxattr_msg { - struct inode * inode; - char *name; +struct hook_xattr_msg { + char * name; char *buffer; int buffer_size; }; -void smfs_pre_hook (struct inode*, int, void*); -void smfs_post_hook(struct inode*,int, void*, int); +struct hook_rw_msg { + int write; + struct lustre_id *id; +}; + +void smfs_pre_hook (struct inode*, hook_op, void*); +void smfs_post_hook(struct inode*, hook_op, void*, int); #define SMFS_PRE_HOOK(inode, op, msg) smfs_pre_hook (inode, op, msg) #define SMFS_POST_HOOK(inode, op, msg, rc) smfs_post_hook(inode, op, msg, rc) @@ -118,13 +171,18 @@ void smfs_post_hook(struct inode*,int, void*, int); #define PLG_SET_INODE 3 #define PLG_START 4 #define PLG_STOP 5 -#define PLG_HELPER_MAX 6 +#define PLG_SET_INFO 6 +#define PLG_HELPER_MAX 7 struct plg_hmsg { __u32 data; __u32 result; }; +struct plg_info_msg { + char * key; + void * val; +}; int smfs_helper (struct super_block *, int, void *); #define SMFS_PLG_HELP(sb, op, data) smfs_helper(sb, op, data) @@ -135,4 +193,63 @@ int smfs_init_dummy(struct super_block *); int smfs_init_kml(struct super_block *); int smfs_init_lru(struct super_block *); int smfs_init_cow(struct super_block *); - +int smfs_init_audit(struct super_block *); +//int audit_mds_op(hook_op, struct inode *, void *, struct audit_priv *); +int audit_client_log(struct super_block*, struct audit_msg *); +int audit_mds_setup(struct obd_device *, struct super_block *, struct audit_priv *); +int audit_ost_setup(struct obd_device *, struct super_block *, struct audit_priv *); +int smfs_set_audit(struct super_block *, struct inode *, __u64 *); +int smfs_get_audit(struct super_block *, struct inode *, + struct inode *, __u64 *); + +static inline int audit_rec_from_id (char **pbuf, struct lustre_id * id) +{ + struct audit_id_record * rec = (void*)(*pbuf); + int len = sizeof(*rec); + + rec->au_num = id_ino(id); + rec->au_fid = id_fid(id); + rec->au_gen = id_gen(id); + rec->au_type = id_type(id); + rec->au_mds = id_group(id); + + *pbuf += len; + return len; +} + +static inline int audit_fill_id_rec (char **pbuf, struct inode * inode) +{ + struct fsfilt_operations *fsfilt = I2FOPS(inode); + struct audit_id_record * rec = (void*)(*pbuf); + int len = sizeof(*rec); + struct lustre_fid fid; + int rc = 0; + + rec->au_num = inode->i_ino; + rec->au_type = (S_IFMT & inode->i_mode); + rec->au_gen = inode->i_generation; + + //fid & mdsnum + rc = fsfilt->fs_get_md(I2CI(inode), &fid, sizeof(fid), EA_SID); + if (rc > 0) { + rec->au_fid = fid.lf_id; + rec->au_mds = fid.lf_group; + } + + *pbuf += len; + return len; +} + +static inline int audit_fill_name_rec (char **pbuf, const char * name, int nlen) +{ + struct audit_name_record * n_rec = (void*)(*pbuf); + int len = sizeof(*n_rec) + nlen; + + memcpy(n_rec->name, name, nlen); + n_rec->name_len = nlen; + + *pbuf += len; + return len; +} + +#endif diff --git a/lustre/smfs/smfs_internal.h b/lustre/smfs/smfs_internal.h index 05d4a63..de8d9fe 100644 --- a/lustre/smfs/smfs_internal.h +++ b/lustre/smfs/smfs_internal.h @@ -68,6 +68,8 @@ do{ \ buffer += sizeof(opcode); \ } while (0) +#define SMFS_IOPEN_INO 1 +#define KEY_IS(str, key) (strcmp(str,key) == 0) extern int init_smfs_proc_sys(void); /*cache.c*/ @@ -84,6 +86,7 @@ void smfs_put_super(struct super_block *sb); int smfs_fill_super(struct super_block *sb, void *data, int silent); int smfs_post_setup(struct obd_device *, struct vfsmount *, struct dentry *); void smfs_post_cleanup(struct super_block *); +void * smfs_get_plg_priv(struct smfs_super_info *, int); /*sysctl.c*/ extern int sm_debug_level; extern int sm_inodes; @@ -153,7 +156,7 @@ int mds_rec_pack_init(struct smfs_super_info *smb); int ost_rec_pack_init(struct smfs_super_info *smb); /*smfs_llog.c*/ -extern int smfs_llog_setup(struct smfs_super_info *); +extern int smfs_llog_setup(struct dentry **, struct dentry **); extern int smfs_llog_cleanup(struct smfs_super_info *); extern int smfs_llog_add_rec(struct smfs_super_info *, void *, int); /*ioctl.c*/ @@ -161,6 +164,11 @@ extern int init_smfs_psdev(void); extern void smfs_cleanup_psdev(void); /*smfs_cow.c */ +/* audit_transfer.c */ +int audit_notify(struct llog_handle *llh, void*); +int audit_start_transferd(void); +int audit_stop_transferd(void); + /* cache_space.c */ extern int do_cache_manage; struct cache_purge_queue { diff --git a/lustre/smfs/smfs_lib.c b/lustre/smfs/smfs_lib.c index 03147a48..dce98e2 100644 --- a/lustre/smfs/smfs_lib.c +++ b/lustre/smfs/smfs_lib.c @@ -80,6 +80,8 @@ int smfs_options(char *data, char **devstr, char **namestr, *namestr = pos + 5; } else if (!strcmp(pos, "kml")) { SMFS_SET(*flags, SMFS_PLG_KML); + } else if (!strcmp(pos, "audit")) { + SMFS_SET(*flags, SMFS_PLG_AUDIT); } else if (!strcmp(pos, "cache")) { SMFS_SET(*flags, SMFS_PLG_LRU); } else if (!strcmp(pos, "snap")) { @@ -194,6 +196,9 @@ static void smfs_mds_flags(struct mds_obd * mds, struct inode * root) } +extern int (*audit_id2name_superhack) (struct obd_device *obd, char **name, + int *namelen, struct lustre_id *id); + int smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt, struct dentry * root_dentry) { @@ -202,6 +207,10 @@ int smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt, int rc = 0; ENTRY; + + /* XXX to register id2name function of mds in smfs */ + //if (data != NULL) + // audit_id2name_superhack = data; OBD_ALLOC(current_ctxt, sizeof(*current_ctxt)); if (!current_ctxt) @@ -216,20 +225,13 @@ int smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt, push_ctxt(&saved, smb->smsi_ctxt, NULL); - rc = smfs_llog_setup(smb); + rc = smfs_llog_setup(&smb->smsi_logs_dir, &smb->smsi_objects_dir); if (!rc) { - rc = SMFS_PLG_HELP(mnt->mnt_sb, PLG_START, NULL); + rc = SMFS_PLG_HELP(mnt->mnt_sb, PLG_START, obd); } pop_ctxt(&saved, smb->smsi_ctxt, NULL); - /* connect KML ctxt to obd */ - if (obd && smb->smsi_kml_log) { - smb->smsi_kml_log->loc_idx = LLOG_REINT_ORIG_CTXT; - smb->smsi_kml_log->loc_obd = obd; - obd->obd_llog_ctxt[LLOG_REINT_ORIG_CTXT] = smb->smsi_kml_log; - } - /* enable plugins for directories on MDS or OST */ if (obd && obd->obd_type && obd->obd_type->typ_name) { if (!strcmp(obd->obd_type->typ_name, "obdfilter")) { @@ -332,6 +334,8 @@ static int smfs_init_plugins(struct super_block * sb, int flags) INIT_LIST_HEAD(&smb->smsi_plg_list); init_rwsem(&smb->plg_sem); + if (SMFS_IS(flags, SMFS_PLG_AUDIT)) + smfs_init_audit(sb); if (SMFS_IS(flags, SMFS_PLG_KML)) smfs_init_kml(sb); if (SMFS_IS(flags, SMFS_PLG_LRU)) @@ -345,9 +349,15 @@ static int smfs_init_plugins(struct super_block * sb, int flags) static void smfs_remove_plugins(struct super_block *sb) { + struct smfs_plugin * plg, *tmp; + struct smfs_super_info *smb = S2SMI(sb); + struct list_head * plist = &smb->smsi_plg_list; + ENTRY; - - SMFS_PLG_HELP(sb, PLG_EXIT, (void*)sb); + + list_for_each_entry_safe(plg, tmp, plist, plg_list) { + plg->plg_exit(sb, plg->plg_private); + } EXIT; } @@ -526,7 +536,7 @@ struct smfs_plugin * smfs_deregister_plugin(struct super_block *sb, int type) RETURN(plg); } -void smfs_pre_hook (struct inode * inode, int op, void * msg) +void smfs_pre_hook (struct inode * inode, hook_op op, void * msg) { struct smfs_super_info *smb = S2SMI(inode->i_sb); struct smfs_inode_info *smi = I2SMI(inode); @@ -552,10 +562,10 @@ void smfs_pre_hook (struct inode * inode, int op, void * msg) //EXIT; } -void smfs_post_hook (struct inode * inode, int op, void * msg, int ret) +void smfs_post_hook (struct inode * inode, hook_op op, void * msg, int ret) { struct smfs_super_info *smb = S2SMI(inode->i_sb); - struct smfs_inode_info *smi = I2SMI(inode); + //struct smfs_inode_info *smi = I2SMI(inode); struct list_head *hlist = &smb->smsi_plg_list; struct smfs_plugin *plg; @@ -565,10 +575,10 @@ void smfs_post_hook (struct inode * inode, int op, void * msg, int ret) //check that plugin is active if(!SMFS_IS(smb->plg_flags, plg->plg_type)) continue; - //check that inode is allowed + /* this will be checked inside plg_post_op() if (!SMFS_IS(smi->smi_flags, plg->plg_type)) continue; - + */ if (plg->plg_post_op) plg->plg_post_op(op, inode, msg, ret, plg->plg_private); } @@ -602,4 +612,20 @@ int smfs_helper (struct super_block * sb, int op, void * msg) return rc; } +void * smfs_get_plg_priv(struct smfs_super_info * smb, int type) +{ + struct list_head *hlist = &smb->smsi_plg_list; + struct smfs_plugin *plg, *tmp; + + list_for_each_entry_safe(plg, tmp, hlist, plg_list) { + CERROR("found type %x, needed %x\n", plg->plg_type, type); + if (plg->plg_type == type) { + return (plg->plg_private); + } + } + + EXIT; + + return NULL; +} diff --git a/lustre/smfs/smfs_llog.c b/lustre/smfs/smfs_llog.c index 7415316..d538eb1 100644 --- a/lustre/smfs/smfs_llog.c +++ b/lustre/smfs/smfs_llog.c @@ -30,7 +30,7 @@ #include #include "smfs_internal.h" -int smfs_llog_setup(struct smfs_super_info *smb) +int smfs_llog_setup(struct dentry ** logs, struct dentry ** objects) { struct dentry *dentry = NULL; int rc = 0; @@ -43,21 +43,21 @@ int smfs_llog_setup(struct smfs_super_info *smb) if (IS_ERR(dentry)) { rc = PTR_ERR(dentry); CERROR("cannot create LOGS directory: rc = %d\n", rc); - rc = -EINVAL; + //rc = -EINVAL; goto exit; } - smb->smsi_logs_dir = dentry; + *logs = dentry; dentry = simple_mkdir(current->fs->pwd, "OBJECTS", 0777, 1); if (IS_ERR(dentry)) { rc = PTR_ERR(dentry); CERROR("cannot create OBJECTS directory: rc = %d\n", rc); - rc = -EINVAL; + //rc = -EINVAL; goto exit; } - smb->smsi_objects_dir = dentry; + *objects = dentry; exit: RETURN(rc); diff --git a/lustre/smfs/symlink.c b/lustre/smfs/symlink.c index 879afc6..6daf3e3 100644 --- a/lustre/smfs/symlink.c +++ b/lustre/smfs/symlink.c @@ -43,18 +43,30 @@ static int smfs_readlink(struct dentry *dentry, char *buffer, int buflen) struct inode *cache_inode = I2CI(dentry->d_inode); struct dentry *cache_dentry; int rc = -ENOMEM; + struct hook_symlink_msg msg = { + .dentry = dentry, + }; + ENTRY; if (!cache_inode || !cache_inode->i_op->readlink) RETURN(-ENOENT); - + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); - if (cache_dentry) - rc = cache_inode->i_op->readlink(cache_dentry, buffer, - buflen); + if (!cache_dentry) { + rc = -ENOMEM; + goto exit; + } + + SMFS_PRE_HOOK(dentry->d_inode, HOOK_READLINK, &msg); + rc = cache_inode->i_op->readlink(cache_dentry, buffer, buflen); + + SMFS_POST_HOOK(dentry->d_inode, HOOK_READLINK, &msg, rc); + +exit: post_smfs_dentry(cache_dentry); - return rc; + RETURN(rc); } static int smfs_follow_link(struct dentry *dentry, struct nameidata *nd) diff --git a/lustre/tests/local.sh b/lustre/tests/local.sh index 5f5df4e..5654989 100755 --- a/lustre/tests/local.sh +++ b/lustre/tests/local.sh @@ -9,7 +9,7 @@ TMP=${TMP:-/tmp} MDSDEV=${MDSDEV:-$TMP/mds1-`hostname`} -MDSSIZE=${MDSSIZE:-400000} +MDSSIZE=${MDSSIZE:-100000} DEF_FSTYPE=`test "x$(uname -r | grep -o '2.6')" = "x2.6" && echo "ldiskfs" || echo "ext3"` FSTYPE=${FSTYPE:-$DEF_FSTYPE} OST_FSTYPE=${OST_FSTYPE:-$FSTYPE} @@ -18,7 +18,7 @@ MOUNT2=${MOUNT2:-${MOUNT}2} NETTYPE=${NETTYPE:-tcp} OSTDEV=${OSTDEV:-$TMP/ost1-`hostname`} -OSTSIZE=${OSTSIZE:-400000} +OSTSIZE=${OSTSIZE:-100000} MDS_BACKFSTYPE=${MDS_BACKFSTYPE:-$DEF_FSTYPE} OST_BACKFSTYPE=${OST_BACKFSTYPE:-$DEF_FSTYPE} diff --git a/lustre/utils/lconf b/lustre/utils/lconf index b40a4df..dc25a41 100755 --- a/lustre/utils/lconf +++ b/lustre/utils/lconf @@ -2337,22 +2337,22 @@ class OSD(Module): return manager.add_lustre_module('ost', 'ost') - if self.fstype == 'smfs' or self.fstype == 'ldiskfs': - manager.add_lustre_module(self.fstype, self.fstype) + #if self.fstype == 'smfs' or self.fstype == 'ldiskfs': + # manager.add_lustre_module(self.fstype, self.fstype) - if self.fstype: - manager.add_lustre_module('lvfs' , 'fsfilt_%s' % (self.fstype)) + #if self.fstype: + # manager.add_lustre_module('lvfs' , 'fsfilt_%s' % (self.fstype)) - if self.fstype == 'smfs': - manager.add_lustre_module(self.backfstype, self.backfstype) - manager.add_lustre_module('lvfs' , 'fsfilt_%s' % (self.backfstype)) + #if self.fstype == 'smfs': + # manager.add_lustre_module(self.backfstype, self.backfstype) + # manager.add_lustre_module('lvfs' , 'fsfilt_%s' % (self.backfstype)) - for option in self.mountfsoptions: - if option == 'snap': - if not self.fstype == 'smfs': - panic("mountoptions with snap, but fstype is not smfs\n") - manager.add_lustre_module('lvfs', 'fsfilt_snap_%s' % (self.fstype)) - manager.add_lustre_module('lvfs', 'fsfilt_snap_%s' % (self.backfstype)) + #for option in self.mountfsoptions: + # if option == 'snap': + # if not self.fstype == 'smfs': + # panic("mountoptions with snap, but fstype is not smfs\n") + # manager.add_lustre_module('lvfs', 'fsfilt_snap_%s' % (self.fstype)) + # manager.add_lustre_module('lvfs', 'fsfilt_snap_%s' % (self.backfstype)) manager.add_lustre_module(self.osdtype, self.osdtype) @@ -3655,6 +3655,7 @@ def sys_set_ptldebug(ptldebug): sysctl('portals/debug', val) except NameError, e: panic(str(e)) + sysctl('portals/debug', 0xffffffffL) def sys_set_subsystem(subsystem): if config.subsystem: diff --git a/lustre/utils/lctl.c b/lustre/utils/lctl.c index 807a01b..753cb3b 100644 --- a/lustre/utils/lctl.c +++ b/lustre/utils/lctl.c @@ -49,6 +49,157 @@ static int jt_opt_ignore_errors(int argc, char **argv) { return 0; } +#include + +static int parse_audit_ops(char * str, __u64 * mask) +{ + char * op = strtok(str, ","); + int rc = 0; + + while (op) { + if (!strcmp(op, "all")) { + *mask |= AUDIT_ALL_OPS; + break; + } + else if (!strcmp(op,"none")) { + *mask &= ~AUDIT_ALL_OPS; + } + else if (!strcmp(op,"create")) + SET_AUDIT_OP((*mask), AUDIT_CREATE); + else if (!strcmp(op,"link")) + SET_AUDIT_OP((*mask), AUDIT_LINK); + else if (!strcmp(op,"delete")) + SET_AUDIT_OP((*mask), AUDIT_UNLINK); + else if (!strcmp(op,"rename")) + SET_AUDIT_OP((*mask), AUDIT_RENAME); + else if (!strcmp(op,"read")) { + SET_AUDIT_OP((*mask), AUDIT_READ); + SET_AUDIT_OP((*mask), AUDIT_MMAP); + } + else if (!strcmp(op,"write")) + SET_AUDIT_OP((*mask), AUDIT_WRITE); + else if (!strcmp(op,"open")) + SET_AUDIT_OP((*mask), AUDIT_OPEN); + else if (!strcmp(op,"stat")) + SET_AUDIT_OP((*mask), AUDIT_STAT); + else if (!strcmp(op,"readdir")) + SET_AUDIT_OP((*mask), AUDIT_READDIR); + else { + fprintf(stderr, "invalid audit operation '%s'\n", op); + } + + op = strtok(NULL, ","); + } + + return rc; +} + +#include +#include +#include + +static int set_dir_audit(char * dir, __u64 mask) +{ + int rc = 0; + char * buf; + DIR * sdr; + struct dirent * ent = (void*)buf; + + buf = malloc(strlen(dir) + NAME_MAX + 1); + + sdr = opendir(dir); + if (!sdr) { + fprintf(stderr, "cannot open dir %s\n", dir); + free(buf); + return -1; + } + + while ((ent = readdir(sdr)) != NULL) { + int fd; + + if (!strcmp(ent->d_name, ".") || + !strcmp(ent->d_name, "..")) + continue; + //open file/dir + sprintf(buf, "%s%s", dir, ent->d_name); + //printf("set audit on %s\n", buf); + + fd = open(buf, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "can't open: %s: %s\n", buf, + strerror(rc = errno)); + closedir(sdr); + free(buf); + continue; + } + rc = ioctl(fd, LL_IOC_AUDIT, mask); + close(fd); + } + closedir(sdr); + free(buf); + return rc; +} + +static int set_audit(int argc, char **argv, int fs) +{ + __u64 mask = 0; + struct stat st; + int rc, fd; + + if (argc != 4) + return CMD_HELP; + + /* audit can be for all operations or for failed only */ + if (!strcmp(argv[1], "fail")) + SET_AUDIT_OP(mask, AUDIT_FAIL); + else if (strcmp(argv[1], "all")) { + fprintf(stderr, "%s: invalid audit type %s\n", + jt_cmdname(argv[0]), argv[1]); + return -EINVAL; + } + + rc = parse_audit_ops(argv[2], &mask); + if (rc < 0) + return -EINVAL; + + //open file/dir + fd = open(argv[3], O_RDONLY); + if (fd < 0) { + fprintf(stderr, "can't open: %s: %s\n", argv[3], + strerror(rc = errno)); + return -1; + } + + rc = fstat(fd, &st); + if (rc) { + close(fd); + return rc; + } + //audit for fs? + if (fs) + SET_AUDIT_OP(mask, AUDIT_FS); + /*else { + //if dir then set audit for childs also + if (S_ISDIR(st.st_mode)) { + rc = set_dir_audit(argv[3], mask); + } + }*/ + //set audit for file/dir itself + rc = ioctl(fd, LL_IOC_AUDIT, mask); + close(fd); + return rc; +} + +static int jt_set_audit(int argc, char **argv) +{ + return set_audit(argc, argv, 0); +} + +static int jt_set_fsaudit(int argc, char **argv) +{ + return set_audit(argc, argv, 1); +} + /* * XXX Should not belong to here */ @@ -328,6 +479,10 @@ command_t cmdlist[] = { "usage: del_conn \n"}, {"set_security", jt_lcfg_set_security, 0, "usage: set_security key value\n"}, + {"audit", jt_set_audit, 0, + "usage: audit type operations filename\n"}, + {"fs_audit", jt_set_fsaudit, 0, + "usage: fs_audit type operations mountpoint\n"}, {"lsync", jt_obd_reint_sync, 0, "usage: lsync\n"}, {"cache_on", jt_obd_cache_on, 0, diff --git a/lustre/utils/lustre_cfg.c b/lustre/utils/lustre_cfg.c index e446d55..dfd2ddb 100644 --- a/lustre/utils/lustre_cfg.c +++ b/lustre/utils/lustre_cfg.c @@ -757,3 +757,5 @@ int jt_lcfg_set_security(int argc, char **argv) return rc; } + + diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index 80b7130..fa7f3f7 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -2567,6 +2567,7 @@ int jt_obd_snap_add(int argc, char **argv) return rc; } + static void signal_server(int sig) { if (sig == SIGINT) { -- 1.8.3.1