From 361edea4707254f4752ffd8c2db6c77a3ab9539c Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Wed, 19 Jul 2017 23:44:27 +0900 Subject: [PATCH] LU-9727 lustre: add uid/gid to Changelogs entries Add a new changelog extension named changelog_ext_uidgid to hold uid/gid information. uid/gid info is added to every Changelog entry type except MARK, in the form 'u=:': 5 01CREAT 15:44:32.385864793 2017.07.18 0x0 t=[0x200000402:0x3:0x0] ef=0x1 u=500:500 p=[0x200000402:0x2:0x0] file1 Signed-off-by: Sebastien Buisson Change-Id: Ie09e4cd146dea75985de00b1da58f75c2a5928f2 Reviewed-on: https://review.whamcloud.com/28114 Reviewed-by: Andreas Dilger Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Henri Doreau Reviewed-by: Olaf Weber --- lustre/include/lustre/lustreapi.h | 2 ++ lustre/include/uapi/linux/lustre/lustre_idl.h | 4 ++- lustre/include/uapi/linux/lustre/lustre_user.h | 48 ++++++++++++++++++++++++-- lustre/mdc/mdc_changelog.c | 3 +- lustre/mdd/mdd_dir.c | 22 +++++++++--- lustre/mdd/mdd_internal.h | 2 ++ lustre/mdd/mdd_object.c | 8 ++++- lustre/obdclass/llog_osd.c | 4 +++ lustre/utils/lfs.c | 16 +++++++++ lustre/utils/liblustreapi_chlg.c | 37 ++++++++++++++++++++ lustre/utils/lustre_rsync.c | 8 +++++ 11 files changed, 145 insertions(+), 9 deletions(-) diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index 165e1fe..80ba7aa 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -396,6 +396,8 @@ int llapi_changelog_get_fd(void *priv); /* Allow records up to endrec to be destroyed; requires registered id. */ int llapi_changelog_clear(const char *mdtname, const char *idstr, long long endrec); +extern int llapi_changelog_set_xflags(void *priv, + enum changelog_send_extra_flag extra_flags); /* HSM copytool interface. * priv is private state, managed internally by these functions diff --git a/lustre/include/uapi/linux/lustre/lustre_idl.h b/lustre/include/uapi/linux/lustre/lustre_idl.h index 52d0632..dfa345b 100644 --- a/lustre/include/uapi/linux/lustre/lustre_idl.h +++ b/lustre/include/uapi/linux/lustre/lustre_idl.h @@ -2836,12 +2836,14 @@ enum llog_flag { LLOG_F_EXT_JOBID = 0x8, LLOG_F_IS_FIXSIZE = 0x10, LLOG_F_EXT_EXTRA_FLAGS = 0x20, + LLOG_F_EXT_X_UIDGID = 0x40, /* Note: Flags covered by LLOG_F_EXT_MASK will be inherited from * catlog to plain log, so do not add LLOG_F_IS_FIXSIZE here, * because the catlog record is usually fixed size, but its plain * log record can be variable */ - LLOG_F_EXT_MASK = LLOG_F_EXT_JOBID | LLOG_F_EXT_EXTRA_FLAGS, + LLOG_F_EXT_MASK = LLOG_F_EXT_JOBID | LLOG_F_EXT_EXTRA_FLAGS | + LLOG_F_EXT_X_UIDGID, }; /* On-disk header structure of each log object, stored in little endian order */ diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index 111b732..6a2cacb 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -1090,8 +1090,9 @@ static inline void hsm_set_cl_error(int *flags, int error) } enum changelog_rec_extra_flags { - CLFE_INVALID = 0, /* No additional flags currently implemented */ - CLFE_SUPPORTED = CLFE_INVALID + CLFE_INVALID = 0, + CLFE_UIDGID = 0x0001, + CLFE_SUPPORTED = CLFE_UIDGID }; enum changelog_send_flag { @@ -1107,6 +1108,11 @@ enum changelog_send_flag { CHANGELOG_FLAG_EXTRA_FLAGS = 0x08, }; +enum changelog_send_extra_flag { + /* Pack uid/gid into the changelog record */ + CHANGELOG_EXTRA_FLAG_UIDGID = 0x01, +}; + #define CR_MAXSIZE cfs_size_round(2 * NAME_MAX + 2 + \ changelog_rec_offset(CLF_SUPPORTED, \ CLFE_SUPPORTED)) @@ -1151,6 +1157,12 @@ struct changelog_ext_extra_flags { __u64 cr_extra_flags; /* Additional CLFE_* flags */ }; +/* Changelog extra extension to include UID/GID. */ +struct changelog_ext_uidgid { + __u64 cr_uid; + __u64 cr_gid; +}; + static inline struct changelog_ext_extra_flags *changelog_rec_extra_flags( const struct changelog_rec *rec); @@ -1167,6 +1179,8 @@ static inline size_t changelog_rec_offset(enum changelog_rec_flags crf, if (crf & CLF_EXTRA_FLAGS) { size += sizeof(struct changelog_ext_extra_flags); + if (cref & CLFE_UIDGID) + size += sizeof(struct changelog_ext_uidgid); } return size; @@ -1222,6 +1236,19 @@ struct changelog_ext_extra_flags *changelog_rec_extra_flags( CLFE_INVALID)); } +/* The uid/gid is the first extra extension */ +static inline +struct changelog_ext_uidgid *changelog_rec_uidgid( + const struct changelog_rec *rec) +{ + enum changelog_rec_flags crf = rec->cr_flags & + (CLF_VERSION | CLF_RENAME | CLF_JOBID | CLF_EXTRA_FLAGS); + + return (struct changelog_ext_uidgid *)((char *)rec + + changelog_rec_offset(crf, + CLFE_INVALID)); +} + /* The name follows the rename, jobid and extra flags extns, if present */ static inline char *changelog_rec_name(const struct changelog_rec *rec) { @@ -1271,9 +1298,11 @@ static inline void changelog_remap_rec(struct changelog_rec *rec, enum changelog_rec_flags crf_wanted, enum changelog_rec_extra_flags cref_want) { + char *uidgid_mov = NULL; char *ef_mov; char *jid_mov; char *rnm_mov; + enum changelog_rec_extra_flags cref = CLFE_INVALID; crf_wanted &= CLF_SUPPORTED; cref_want &= CLFE_SUPPORTED; @@ -1292,6 +1321,13 @@ static inline void changelog_remap_rec(struct changelog_rec *rec, changelog_rec_name(rec), rec->cr_namelen); /* Locations of extensions in the remapped record */ + if (rec->cr_flags & CLF_EXTRA_FLAGS) { + uidgid_mov = (char *)rec + + changelog_rec_offset(crf_wanted & CLF_SUPPORTED, + CLFE_INVALID); + cref = changelog_rec_extra_flags(rec)->cr_extra_flags; + } + ef_mov = (char *)rec + changelog_rec_offset(crf_wanted & ~CLF_EXTRA_FLAGS, CLFE_INVALID); @@ -1309,6 +1345,10 @@ static inline void changelog_remap_rec(struct changelog_rec *rec, /* Move the extension fields to the desired positions */ if ((crf_wanted & CLF_EXTRA_FLAGS) && (rec->cr_flags & CLF_EXTRA_FLAGS)) { + if ((cref_want & CLFE_UIDGID) && (cref & CLFE_UIDGID)) + memmove(uidgid_mov, changelog_rec_uidgid(rec), + sizeof(struct changelog_ext_uidgid)); + memmove(ef_mov, changelog_rec_extra_flags(rec), sizeof(struct changelog_ext_extra_flags)); } @@ -1322,6 +1362,10 @@ static inline void changelog_remap_rec(struct changelog_rec *rec, sizeof(struct changelog_ext_rename)); /* Clear newly added fields */ + if (uidgid_mov && (cref_want & CLFE_UIDGID) && + !(cref & CLFE_UIDGID)) + memset(uidgid_mov, 0, sizeof(struct changelog_ext_uidgid)); + if ((crf_wanted & CLF_EXTRA_FLAGS) && !(rec->cr_flags & CLF_EXTRA_FLAGS)) memset(ef_mov, 0, sizeof(struct changelog_ext_extra_flags)); diff --git a/lustre/mdc/mdc_changelog.c b/lustre/mdc/mdc_changelog.c index cd50853..483d24d 100644 --- a/lustre/mdc/mdc_changelog.c +++ b/lustre/mdc/mdc_changelog.c @@ -217,7 +217,8 @@ static int chlg_load(void *args) rc = llog_init_handle(NULL, llh, LLOG_F_IS_CAT | LLOG_F_EXT_JOBID | - LLOG_F_EXT_EXTRA_FLAGS, + LLOG_F_EXT_EXTRA_FLAGS | + LLOG_F_EXT_X_UIDGID, NULL); if (rc) { CERROR("%s: fail to init llog handle: rc = %d\n", diff --git a/lustre/mdd/mdd_dir.c b/lustre/mdd/mdd_dir.c index b5baf1e..7cf63ed 100644 --- a/lustre/mdd/mdd_dir.c +++ b/lustre/mdd/mdd_dir.c @@ -736,7 +736,7 @@ static int mdd_llog_record_calc_size(const struct lu_env *env, { const struct lu_ucred *uc = lu_ucred(env); enum changelog_rec_flags crf = CLF_EXTRA_FLAGS; - enum changelog_rec_extra_flags crfe = CLFE_INVALID; + enum changelog_rec_extra_flags crfe = CLFE_UIDGID; if (sname != NULL) crf |= CLF_RENAME; @@ -845,8 +845,8 @@ static void mdd_changelog_rec_ext_rename(struct changelog_rec *rec, const struct lu_fid *spfid, const struct lu_name *sname) { - struct changelog_ext_rename *rnm = changelog_rec_rename(rec); - size_t extsize = sname->ln_namelen + 1; + struct changelog_ext_rename *rnm = changelog_rec_rename(rec); + size_t extsize = sname->ln_namelen + 1; LASSERT(sfid != NULL); LASSERT(spfid != NULL); @@ -862,7 +862,7 @@ static void mdd_changelog_rec_ext_rename(struct changelog_rec *rec, void mdd_changelog_rec_ext_jobid(struct changelog_rec *rec, const char *jobid) { - struct changelog_ext_jobid *jid = changelog_rec_jobid(rec); + struct changelog_ext_jobid *jid = changelog_rec_jobid(rec); if (jobid == NULL || jobid[0] == '\0') return; @@ -877,6 +877,15 @@ void mdd_changelog_rec_ext_extra_flags(struct changelog_rec *rec, __u64 eflags) ef->cr_extra_flags = eflags; } +void mdd_changelog_rec_extra_uidgid(struct changelog_rec *rec, + __u64 uid, __u64 gid) +{ + struct changelog_ext_uidgid *uidgid = changelog_rec_uidgid(rec); + + uidgid->cr_uid = uid; + uidgid->cr_gid = gid; +} + /** Store a namespace change changelog record * If this fails, we must fail the whole transaction; we don't * want the change to commit without the log entry. @@ -936,10 +945,15 @@ int mdd_changelog_ns_store(const struct lu_env *env, else crf |= CLF_VERSION; + xflags |= CLFE_UIDGID; + rec->cr.cr_flags = crf; if (crf & CLF_EXTRA_FLAGS) { mdd_changelog_rec_ext_extra_flags(&rec->cr, xflags); + if (xflags & CLFE_UIDGID) + mdd_changelog_rec_extra_uidgid(&rec->cr, + uc->uc_uid, uc->uc_gid); } rec->cr.cr_type = (__u32)type; diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index aeb0791..5a19769 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -279,6 +279,8 @@ int mdd_declare_changelog_store(const struct lu_env *env, struct thandle *handle); void mdd_changelog_rec_ext_jobid(struct changelog_rec *rec, const char *jobid); void mdd_changelog_rec_ext_extra_flags(struct changelog_rec *rec, __u64 eflags); +void mdd_changelog_rec_extra_uidgid(struct changelog_rec *rec, + __u64 uid, __u64 gid); int mdd_changelog_store(const struct lu_env *env, struct mdd_device *mdd, struct llog_changelog_rec *rec, struct thandle *th); int mdd_changelog_data_store(const struct lu_env *env, struct mdd_device *mdd, diff --git a/lustre/mdd/mdd_object.c b/lustre/mdd/mdd_object.c index 15a761d..e15141e 100644 --- a/lustre/mdd/mdd_object.c +++ b/lustre/mdd/mdd_object.c @@ -650,6 +650,8 @@ static int mdd_changelog_data_store_by_fid(const struct lu_env *env, if (uc != NULL && uc->uc_jobid[0] != '\0') flags |= CLF_JOBID; + xflags |= CLFE_UIDGID; + reclen = llog_data_len(LLOG_CHANGELOG_HDR_SZ + changelog_rec_offset(flags & CLF_SUPPORTED, xflags & CLFE_SUPPORTED)); @@ -667,8 +669,12 @@ static int mdd_changelog_data_store_by_fid(const struct lu_env *env, if (flags & CLF_JOBID) mdd_changelog_rec_ext_jobid(&rec->cr, uc->uc_jobid); - if (flags & CLF_EXTRA_FLAGS) + if (flags & CLF_EXTRA_FLAGS) { mdd_changelog_rec_ext_extra_flags(&rec->cr, xflags); + if (xflags & CLFE_UIDGID) + mdd_changelog_rec_extra_uidgid(&rec->cr, + uc->uc_uid, uc->uc_gid); + } rc = mdd_changelog_store(env, mdd, rec, handle); diff --git a/lustre/obdclass/llog_osd.c b/lustre/obdclass/llog_osd.c index 7ef7e9a..f1c4b22 100644 --- a/lustre/obdclass/llog_osd.c +++ b/lustre/obdclass/llog_osd.c @@ -975,6 +975,8 @@ static int llog_osd_next_block(const struct lu_env *env, /* Trim unsupported extensions for compat w/ older clients */ flags = CLF_SUPPORTED; xflags = CLFE_SUPPORTED; + if (!(loghandle->lgh_hdr->llh_flags & LLOG_F_EXT_X_UIDGID)) + xflags &= ~CLFE_UIDGID; if (!(loghandle->lgh_hdr->llh_flags & LLOG_F_EXT_EXTRA_FLAGS)) flags &= ~CLF_EXTRA_FLAGS; if (!(loghandle->lgh_hdr->llh_flags & LLOG_F_EXT_JOBID)) @@ -1119,6 +1121,8 @@ static int llog_osd_prev_block(const struct lu_env *env, /* Trim unsupported extensions for compat w/ older clients */ flags = CLF_SUPPORTED; xflags = CLFE_SUPPORTED; + if (!(loghandle->lgh_hdr->llh_flags & LLOG_F_EXT_X_UIDGID)) + xflags &= ~CLFE_UIDGID; if (!(loghandle->lgh_hdr->llh_flags & LLOG_F_EXT_EXTRA_FLAGS)) flags &= ~CLF_EXTRA_FLAGS; if (!(loghandle->lgh_hdr->llh_flags & LLOG_F_EXT_JOBID)) diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 3d278a02..9d3fd32 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -5174,6 +5174,14 @@ static int lfs_changelog(int argc, char **argv) return rc; } + rc = llapi_changelog_set_xflags(changelog_priv, + CHANGELOG_EXTRA_FLAG_UIDGID); + if (rc < 0) { + fprintf(stderr, "Can't set xflags for changelog: %s\n", + strerror(errno = -rc)); + return rc; + } + while ((rc = llapi_changelog_recv(changelog_priv, &rec)) == 0) { time_t secs; struct tm ts; @@ -5210,6 +5218,14 @@ static int lfs_changelog(int argc, char **argv) changelog_rec_extra_flags(rec); printf(" ef=0x%llx", ef->cr_extra_flags); + + if (ef->cr_extra_flags & CLFE_UIDGID) { + struct changelog_ext_uidgid *uidgid = + changelog_rec_uidgid(rec); + + printf(" u=%llu:%llu", + uidgid->cr_uid, uidgid->cr_gid); + } } if (rec->cr_namelen) diff --git a/lustre/utils/liblustreapi_chlg.c b/lustre/utils/liblustreapi_chlg.c index 15f334c..1389998 100644 --- a/lustre/utils/liblustreapi_chlg.c +++ b/lustre/utils/liblustreapi_chlg.c @@ -68,6 +68,8 @@ struct changelog_private { int clp_fd; /* Changelog delivery mode */ enum changelog_send_flag clp_send_flags; + /* Changelog extra flags */ + enum changelog_send_extra_flag clp_send_extra_flags; /* Available bytes in buffer */ size_t clp_buf_len; /* Current position in buffer */ @@ -243,6 +245,8 @@ int llapi_changelog_recv(void *priv, struct changelog_rec **rech) if (cp->clp_send_flags & CHANGELOG_FLAG_EXTRA_FLAGS) { rec_fmt |= CLF_EXTRA_FLAGS; + if (cp->clp_send_extra_flags & CHANGELOG_EXTRA_FLAG_UIDGID) + rec_extra_fmt |= CLFE_UIDGID; } if (cp->clp_buf + cp->clp_buf_len <= cp->clp_buf_pos) { @@ -328,3 +332,36 @@ out_close: close(fd); return rc; } + +/** + * Set extra flags for reading changelogs + * + * @param priv Opaque private control structure + * @param extra_flags Read extra flags (e.g. CHANGELOG_EXTRA_FLAG_UIDGID) + * + * Just call this function right after llapi_changelog_start(). + */ +int llapi_changelog_set_xflags(void *priv, + enum changelog_send_extra_flag extra_flags) +{ + struct changelog_private *cp = priv; + static bool warned_uidgid; + + if (!cp || cp->clp_magic != CHANGELOG_PRIV_MAGIC) + return -EINVAL; + + cp->clp_send_extra_flags = extra_flags; + + /* CHANGELOG_EXTRA_FLAG_UIDGID will eventually become mandatory. + * If it wasn't specified, display a warning here. + * Code elsewhere will remove the corresponding extension. + */ + if (!(extra_flags & CHANGELOG_EXTRA_FLAG_UIDGID) && !warned_uidgid) { + llapi_err_noerrno(LLAPI_MSG_WARN, + "warning: %s() called without CHANGELOG_EXTRA_FLAG_UIDGID", + __func__); + warned_uidgid = true; + } + + return 0; +} diff --git a/lustre/utils/lustre_rsync.c b/lustre/utils/lustre_rsync.c index 3974a70..7e97137 100644 --- a/lustre/utils/lustre_rsync.c +++ b/lustre/utils/lustre_rsync.c @@ -1551,6 +1551,14 @@ int lr_replicate() goto out; } + rc = llapi_changelog_set_xflags(changelog_priv, + CHANGELOG_EXTRA_FLAG_UIDGID); + if (rc < 0) { + fprintf(stderr, "Error setting xflag in changelog for fs %s.\n", + status->ls_source_fs); + goto out; + } + while (!quit && lr_parse_line(changelog_priv, info) == 0) { rc = 0; if (info->type == CL_RENAME && !info->is_extended) { -- 1.8.3.1