LLAPI\_CHANGELOG\_RECV(3) Lustre Library Functions LLAPI\_CHANGELOG\_RECV(3)

# [NAME](#NAME)

llapi\_changelog\_recv, llapi\_changelog\_free - Read and free a changelog records

# [SYNOPSIS](#SYNOPSIS)

```
#include <lustre/lustreapi.h>
```

```
int llapi_changelog_recv(void *priv, struct changelog_rec **rech);
```

```
int llapi_changelog_free(struct changelog_rec **rech);
```

# [DESCRIPTION](#DESCRIPTION)

The function **llapi\_changelog\_recv()** allocates and reads the next changelog record *rech* from the changelog reader instance *priv*.

The function **llapi\_changelog\_free()** releases the allocated record *rech*.

# [NOTES](#NOTES)

If **llapi\_changelog\_start()** initializes *priv* with CHANGELOG\_FLAG\_FOLLOW flag, **llapi\_changelog\_recv()** can block waiting for new records.

## [Changelog record format](#Changelog_record_format)

**llapi\_changelog\_recv()** allocates a **struct changelog\_rec** structure and fills it with the next changelog record. The minimal changelog record struct has the following fields:

```
struct changelog_rec {


        __u16             cr_namelen;     /* entry name length in bytes */


        __u16             cr_flags;       /* enum changelog_rec_flags */


        __u32             cr_type;        /* enum changelog_rec_type */


        __u64             cr_index;       /* changelog record number */


        __u64             cr_prev;        /* last cr_index used by cr_tfid */


        __u64             cr_time;


        union {


            struct lu_fid cr_tfid;        /* target FID */


            __u32         cr_markerflags; /* CL_MARK flags */


        };


        struct lu_fid     cr_pfid;        /* parent FID */
} __attribute__ ((packed));
```

The changelog record name length **cr\_namelen** is the length of the directory entry name of the target file or directory. The name is stored in the record after the fixed-size fields.

The changelog record index **cr\_index** is always unique and monotonically increasing. However, a changelog consumer may not necessarily process all records, so may see gaps in the index sequence.

The changelog record timestamp **cr\_time** is a 64-bit value representing the time of the changelog record in nanoseconds since the Epoch. The top 34 bits represent the seconds since the Epoch, and the bottom 30 bits represent the nanoseconds.

The changelog target FID **cr\_tfid** is the FID of the file or directory that is the subject of the record. The parent FID **cr\_pfid** is the FID of the parent directory of the target FID, if applicable. The changelog record name is relative to the parent FID.

## [Changelog record flags](#Changelog_record_flags)

The high 4 bits of **cr\_flags** field can have the following values:

```
enum changelog_rec_flags {


    CLF_VERSION,     /* initial version record */


    CLF_RENAME,      /* rename in cr_sfid, cr_spfid */


    CLF_JOBID,       /* jobid in cr_jobid */


    CLF_EXTRA_FLAGS, /* extra flags in cr_extra_flags */


    CLF_FLAGMASK,    /* mask off per-record flags */


    CLF_VERMASK,
};
```

The low 12 bits of **cr\_flags** can be used for per-record flags. Currently defined per-record flags for **CL\_UNLINK** are:

```


    CLF_UNLINK_LAST,        /* Unlink of last hardlink */


    CLF_UNLINK_HSM_EXISTS,  /* File has something in HSM */
```

Currently defined per-record flags for **CL\_RENAME** are:

```


    CLF_RENAME_LAST,        /* rename unlink last link of target */


    CLF_RENAME_LAST_EXISTS, /* unlink last link of HSM target */
```

## [Changelog record types](#Changelog_record_types)

The changelog record **cr\_type** field describes the operation event type and can have the following values:

```
enum changelog_rec_type {


    CL_NONE,       /* no event */


    CL_MARK,       /* internal marker with initial version */


    CL_CREATE,     /* new file created */


    CL_MKDIR,      /* new directory created */


    CL_HARDLINK,   /* new hard link created */


    CL_SOFTLINK,   /* new symbolic link created */


    CL_MKNOD,      /* new device node created */


    CL_UNLINK,     /* file unlinked */


    CL_RMDIR,      /* directory removed */


    CL_RENAME,     /* file or directory renamed */


    CL_EXT,        /* namespace extended record (2nd half of rename) */


    CL_OPEN,       /* file opened */


    CL_CLOSE,      /* file closed */


    CL_LAYOUT,     /* file layout/striping modified */


    CL_TRUNC,      /* file truncated */


    CL_SETATTR,    /* file attributes changed, precedence over xTIME */


    CL_SETXATTR,   /* file extended attributes changed */


    CL_HSM,        /* HSM specific events, see flags */


    CL_MTIME,      /* mtime changed, precendence over CTIME, ATIME */


    CL_CTIME,      /* ctime changed, precendence over ATIME */


    CL_ATIME,      /* atime changed, but no other attributes */


    CL_MIGRATE,    /* file layout migrated */


    CL_FLRW,       /* FLR: file was firstly written */


    CL_RESYNC,     /* FLR: file was resync-ed */


    CL_GETXATTR,   /* file extended attributes read */


    CL_DN_OPEN,    /* file open denied */
};
```

## [Changelog extended records](#Changelog_extended_records)

**struct changelog\_rec** can be extended with the following fields if corresponding flags are set:

```


        /* extension for RENME, when cr_flags & CLF_RENAME. */


        struct changelog_ext_rename {


                struct lu_fid    cr_sfid;   /* source fid, or zero */


                struct lu_fid    cr_spfid;  /* source parent fid, or zero */


        };


        /* extension for JOBID, when cr_flags & CLF_JOBID. */


        struct changelog_ext_jobid {


                char  cr_jobid[LUSTRE_JOBID_SIZE]; /* NUL-terminated string */


        };


        /* extension for additional flags, when cr_flags & CLF_EXTRA_FLAGS. */


        struct changelog_ext_extra_flags {


                __u64 cr_extra_flags; /* Additional CLFE_* flags */


        };
```

## [Changelog extra extensions](#Changelog_extra_extensions)

**struct changelog\_rec** can be extended with the following extra fields if corresponding flags are set in **struct changelog\_ext\_extra\_flags**. **cr\_extra\_flags** field can have the following values:

```


        CLFE_UIDGID,   /* changelog_ext_uidgid */


        CLFE_NID,      /* changelog_ext_nid */


        CLFE_OPEN,     /* changelog_ext_openmode */


        CLFE_XATTR,    /* changelog_ext_xattr */


        CLFE_NID_BE,   /* changelog_ext_nid is struct lnet_nid */
```

```


        /* extra extension for UID/GID, when cr_extra_flags & CLFE_UIDGID. */


        struct changelog_ext_uidgid {


                __u64     cr_uid;


                __u64     cr_gid;


        };


        /* extra extension for NID, when cr_extra_flags & CLFE_NID. */


        struct changelog_ext_nid {


                /* If CLFE_NID_BE is not set cr_nid is of the lnet_nid_t type.


                 * If CLFE_NID_BE is set then this is struct lnet_nid.


                 */


                __u64     cr_nid;


                __u64     extra;


                __u32     padding;


        };


        /* extra extension for low 32 bits of MDS_OPEN_* flags. */


        struct changelog_ext_openmode {


                __u32 cr_openflags; /* enum mds_open_flags */


        };


        /* extra extension to include xattr name */


        struct changelog_ext_xattr {


                char cr_xattr[XATTR_NAME_MAX + 1]; /* NUL-terminated string */


        };
```

# [RETURN VALUES](#RETURN_VALUES)

0

On success

1

End of records

-errno

On failure.

# [ERRORS](#ERRORS)

-ENOMEM

Insufficient memory to complete operation.

-EINVAL

One or more invalid arguments are given.

-EIO

Failed to read the changelog record on the MDT.

# [EXAMPLE](#EXAMPLE)

To process a sequence of changelog records:

```


        void *changelog_priv;


        struct changelog_rec *rec;


        char *mdtname = "testfs-MDT0000";


        char *consumer = "dirwatch";


        __u64 mask = 0; /* use mask registered for this user */


        long long startrec = 12345678;


        rc = llapi_changelog_start_user(&changelog_priv,


                        CHANGELOG_FLAG_BLOCK | CHANGELOG_FLAG_EXTRA_FLAGS |


                        CHANGELOG_FLAG_NID_BE | CHANGELOG_FLAG_JOBID |


                        CHANGELOG_FLAG_FOLLOW,


                        mdtname, consumer, mask, startrec);


        while ((rc = llapi_changelog_recv(changelog_priv, &rec)) == 0) {


                /* process 'rec' */


                llapi_changelog_free(&rec);


        }
```

# [AVAILABILITY](#AVAILABILITY)

**llapi\_changelog\_recv()** and **llapi\_changelog\_free()** are part of the [**lustre**(7)](/man/enterprise-packages/lustre/lustre.7) user application interface library since release 2.0.0.

# [SEE ALSO](#SEE_ALSO)

[**lfs-changelog**(1)](/man/enterprise-packages/lustre/lfs-changelog.1), [**llapi\_changelog\_clear**(3)](/man/enterprise-packages/lustre/llapi_changelog_clear.3), [**llapi\_changelog\_get\_fd**(3)](/man/enterprise-packages/lustre/llapi_changelog_get_fd.3), [**llapi\_changelog\_in\_buf**(3)](/man/enterprise-packages/lustre/llapi_changelog_in_buf.3), [**llapi\_changelog\_start**(3)](/man/enterprise-packages/lustre/llapi_changelog_start.3), [**llapi\_changelog\_start\_user**(3)](/man/enterprise-packages/lustre/llapi_changelog_start_user.3), [**lustreapi**(7)](/man/enterprise-packages/lustre/lustreapi.7)

2024-08-22 Lustre User API

---

Document: llapi_changelog_free(3) from lustre 2.17.60-r0 (Chainguard OS)
Source: https://github.com/lustre/lustre-release
