Description
It would be more efficient to have a Changelog interface similar to llapi_changelog_recv() that is returning multiple records to the caller at once.
A proposed interface would be like the following:
int llapi_changelog_recv_many(void *priv, struct changelog_rec **rech, int *numrec) int llapi_changelog_free_many(struct changelog_rec **rech, int numrec)
where recv_many allocates and returns an array of struct changelog_rec * pointers that reference numrec changelog records, and free_many frees the corresponding number of records (it would be undefined if free_many were called with a different numrec than returned by recv_many).
Instead of returning an array of pointers to each struct changelog_rec (plus packed extensions), an alternative would be that this returns a pointer to the packed array of struct changelog_rec, but this would be very complex to process because it may have multiple extension records and each one would need to be processed and skipped even if the contents are not of interest.
A better alternative would be to have a more comprehensive structure for changelog events to make this easier to process, and return an array pointers to these structures, like:
struct changelog_record {
__u16 cr_namelen;
__u16 cr_flags; /* enum changelog_rec_flags, CLF_* */
__u32 cr_type; /* enum changelog_rec_type */
__u64 cr_index; /* changelog record number */
__u64 cr_prev; /* last cr_index for this cr_tfid */
__u64 cr_time;
union {
struct lu_fid cr_tfid; /* target fid */
__u32 cr_markerflags; /* CL_MARK flags */ };
__u64 cr_extra_flags; /* Additional CLFE_* flags */
struct lu_fid cr_pfid; /* parent fid */
struct changelog_ext_rename cre_rename; /* if cr_flags & CLF_RENAME */
struct changelog_ext_jobid cre_jobid; /* if cr_flags & CLF_JOBID */
struct changelog_ext_uidgid cre_uidgid; /* if cr_extra_flags & CLFE_UIDGID */
struct changelog_ext_nid cre_nid; /* if cr_extra_flags & CLFE_NID */
struct changelog_ext_openmode cre_openmode; /* if cr_extra_flags & CLFE_OPENMODE */
struct changelog_ext_xattr cre_xattr; /* if cr_extra_flags & CLFE_XATTR */
};
The unused extension records would be unpopulated if the corresponding flag is not set. This would provide a balance between simplifying access to the changelog records, while minimizing the overhead of reprocessing and reformatting every record before it is returned.
It would be possible that the cre_* extension records would be pointers to those fields in a larger buffer, and NULL if they are not present, but in most cases the size of the pointer is similar in size as the record itself, so there would not be much space savings.