CLF_VERSION = 0x1000,
CLF_RENAME = 0x2000,
CLF_JOBID = 0x4000,
- CLF_SUPPORTED = CLF_VERSION | CLF_RENAME | CLF_JOBID
+ CLF_EXTRA_FLAGS = 0x8000,
+ CLF_SUPPORTED = CLF_VERSION | CLF_RENAME | CLF_JOBID | CLF_EXTRA_FLAGS
};
*flags |= (error << CLF_HSM_ERR_L);
}
+enum changelog_rec_extra_flags {
+ CLFE_INVALID = 0, /* No additional flags currently implemented */
+ CLFE_SUPPORTED = CLFE_INVALID
+};
+
enum changelog_send_flag {
/* Not yet implemented */
- CHANGELOG_FLAG_FOLLOW = 0x01,
+ CHANGELOG_FLAG_FOLLOW = 0x01,
/* Blocking IO makes sense in case of slow user parsing of the records,
* but it also prevents us from cleaning up if the records are not
* consumed. */
- CHANGELOG_FLAG_BLOCK = 0x02,
+ CHANGELOG_FLAG_BLOCK = 0x02,
/* Pack jobid into the changelog records if available. */
- CHANGELOG_FLAG_JOBID = 0x04,
+ CHANGELOG_FLAG_JOBID = 0x04,
+ /* Pack additional flag bits into the changelog record */
+ CHANGELOG_FLAG_EXTRA_FLAGS = 0x08,
};
#define CR_MAXSIZE cfs_size_round(2 * NAME_MAX + 2 + \
- changelog_rec_offset(CLF_SUPPORTED))
+ changelog_rec_offset(CLF_SUPPORTED, \
+ CLFE_SUPPORTED))
/* 31 usable bytes string + null terminator. */
#define LUSTRE_JOBID_SIZE 32
/* This is the minimal changelog record. It can contain extensions
* such as rename fields or process jobid. Its exact content is described
- * by the cr_flags.
+ * by the cr_flags and cr_extra_flags.
*
- * Extensions are packed in the same order as their corresponding flags.
+ * Extensions are packed in the same order as their corresponding flags,
+ * then in the same order as their corresponding extra flags.
*/
struct changelog_rec {
__u16 cr_namelen;
char cr_jobid[LUSTRE_JOBID_SIZE]; /**< zero-terminated string. */
};
+/* Changelog extension to include additional flags. */
+struct changelog_ext_extra_flags {
+ __u64 cr_extra_flags; /* Additional CLFE_* flags */
+};
+
+static inline struct changelog_ext_extra_flags *changelog_rec_extra_flags(
+ const struct changelog_rec *rec);
-static inline size_t changelog_rec_offset(enum changelog_rec_flags crf)
+static inline size_t changelog_rec_offset(enum changelog_rec_flags crf,
+ enum changelog_rec_extra_flags cref)
{
size_t size = sizeof(struct changelog_rec);
if (crf & CLF_JOBID)
size += sizeof(struct changelog_ext_jobid);
+ if (crf & CLF_EXTRA_FLAGS) {
+ size += sizeof(struct changelog_ext_extra_flags);
+ }
+
return size;
}
static inline size_t changelog_rec_size(const struct changelog_rec *rec)
{
- return changelog_rec_offset(rec->cr_flags);
+ enum changelog_rec_extra_flags cref = CLFE_INVALID;
+
+ if (rec->cr_flags & CLF_EXTRA_FLAGS)
+ cref = changelog_rec_extra_flags(rec)->cr_extra_flags;
+
+ return changelog_rec_offset(rec->cr_flags, cref);
}
static inline size_t changelog_rec_varsize(const struct changelog_rec *rec)
enum changelog_rec_flags crf = rec->cr_flags & CLF_VERSION;
return (struct changelog_ext_rename *)((char *)rec +
- changelog_rec_offset(crf));
+ changelog_rec_offset(crf,
+ CLFE_INVALID));
}
/* The jobid follows the rename extension, if present */
(CLF_VERSION | CLF_RENAME);
return (struct changelog_ext_jobid *)((char *)rec +
- changelog_rec_offset(crf));
+ changelog_rec_offset(crf,
+ CLFE_INVALID));
}
-/* The name follows the rename and jobid extensions, if present */
+/* The additional flags follow the rename and jobid extensions, if present */
+static inline
+struct changelog_ext_extra_flags *changelog_rec_extra_flags(
+ const struct changelog_rec *rec)
+{
+ enum changelog_rec_flags crf = rec->cr_flags &
+ (CLF_VERSION | CLF_RENAME | CLF_JOBID);
+
+ return (struct changelog_ext_extra_flags *)((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)
{
- return (char *)rec + changelog_rec_offset(rec->cr_flags &
- CLF_SUPPORTED);
+ enum changelog_rec_extra_flags cref = CLFE_INVALID;
+
+ if (rec->cr_flags & CLF_EXTRA_FLAGS)
+ cref = changelog_rec_extra_flags(rec)->cr_extra_flags;
+
+ return (char *)rec + changelog_rec_offset(rec->cr_flags & CLF_SUPPORTED,
+ cref & CLFE_SUPPORTED);
}
static inline size_t changelog_rec_snamelen(const struct changelog_rec *rec)
* The following assumptions are being made:
* - CLF_RENAME will not be removed
* - CLF_JOBID will not be added without CLF_RENAME being added too
+ * - CLF_EXTRA_FLAGS will not be added without CLF_JOBID being added too
*
* @param[in,out] rec The record to remap.
* @param[in] crf_wanted Flags describing the desired extensions.
+ * @param[in] cref_want Flags describing the desired extra extensions.
*/
static inline void changelog_remap_rec(struct changelog_rec *rec,
- enum changelog_rec_flags crf_wanted)
+ enum changelog_rec_flags crf_wanted,
+ enum changelog_rec_extra_flags cref_want)
{
+ char *ef_mov;
char *jid_mov;
char *rnm_mov;
crf_wanted &= CLF_SUPPORTED;
-
- if ((rec->cr_flags & CLF_SUPPORTED) == crf_wanted)
- return;
+ cref_want &= CLFE_SUPPORTED;
+
+ if ((rec->cr_flags & CLF_SUPPORTED) == crf_wanted) {
+ if (!(rec->cr_flags & CLF_EXTRA_FLAGS) ||
+ (rec->cr_flags & CLF_EXTRA_FLAGS &&
+ (changelog_rec_extra_flags(rec)->cr_extra_flags &
+ CLFE_SUPPORTED) ==
+ cref_want))
+ return;
+ }
/* First move the variable-length name field */
- memmove((char *)rec + changelog_rec_offset(crf_wanted),
+ memmove((char *)rec + changelog_rec_offset(crf_wanted, cref_want),
changelog_rec_name(rec), rec->cr_namelen);
- /* Locations of jobid and rename extensions in the remapped record */
+ /* Locations of extensions in the remapped record */
+ ef_mov = (char *)rec +
+ changelog_rec_offset(crf_wanted & ~CLF_EXTRA_FLAGS,
+ CLFE_INVALID);
jid_mov = (char *)rec +
- changelog_rec_offset(crf_wanted & ~CLF_JOBID);
+ changelog_rec_offset(crf_wanted &
+ ~(CLF_EXTRA_FLAGS | CLF_JOBID),
+ CLFE_INVALID);
rnm_mov = (char *)rec +
- changelog_rec_offset(crf_wanted & ~(CLF_JOBID | CLF_RENAME));
+ changelog_rec_offset(crf_wanted &
+ ~(CLF_EXTRA_FLAGS |
+ CLF_JOBID |
+ CLF_RENAME),
+ CLFE_INVALID);
/* Move the extension fields to the desired positions */
+ if ((crf_wanted & CLF_EXTRA_FLAGS) &&
+ (rec->cr_flags & CLF_EXTRA_FLAGS)) {
+ memmove(ef_mov, changelog_rec_extra_flags(rec),
+ sizeof(struct changelog_ext_extra_flags));
+ }
+
if ((crf_wanted & CLF_JOBID) && (rec->cr_flags & CLF_JOBID))
memmove(jid_mov, changelog_rec_jobid(rec),
sizeof(struct changelog_ext_jobid));
sizeof(struct changelog_ext_rename));
/* Clear newly added fields */
+ if ((crf_wanted & CLF_EXTRA_FLAGS) &&
+ !(rec->cr_flags & CLF_EXTRA_FLAGS))
+ memset(ef_mov, 0, sizeof(struct changelog_ext_extra_flags));
+
if ((crf_wanted & CLF_JOBID) && !(rec->cr_flags & CLF_JOBID))
memset(jid_mov, 0, sizeof(struct changelog_ext_jobid));
/* Update the record's flags accordingly */
rec->cr_flags = (rec->cr_flags & CLF_FLAGMASK) | crf_wanted;
+ if (rec->cr_flags & CLF_EXTRA_FLAGS)
+ changelog_rec_extra_flags(rec)->cr_extra_flags =
+ changelog_rec_extra_flags(rec)->cr_extra_flags |
+ cref_want;
}
enum changelog_message_type {