[systemd-devel] [PATCH 2/5] Add a machine_id_commit call to commit on disk a, transient machine-id

Didier Roche didrocks at ubuntu.com
Tue Dec 2 02:43:21 PST 2014


Le 01/12/2014 18:37, Lennart Poettering a écrit :
> On Mon, 24.11.14 12:35, Didier Roche (didrocks at ubuntu.com) wrote:
>
>>   
>> +static int is_on_temporary_fs(int fd) {
>> +        struct statfs s;
>> +
>> +        if (fstatfs(fd, &s) < 0)
>> +                return -errno;
>> +
>> +        return F_TYPE_EQUAL(s.f_type, TMPFS_MAGIC) ||
>> +               F_TYPE_EQUAL(s.f_type, RAMFS_MAGIC);
>> +}
> This should really move to util.[ch] I figure, and reuse
> is_temporary_fs() that we already have there.

Thanks for your feedback.
I did introduce is_fd_on_temporary_fs() in utils.[ch] and reused 
is_temporary_fs there.
>
>> +
>> +int machine_id_commit(const char *root) {
>> +        const char *etc_machine_id;
>> +        _cleanup_close_ int fd = -1;
>> +        _cleanup_close_ int initial_mntns_fd = -1;
>> +        struct stat st;
>> +        char id[34]; /* 32 + \n + \0 */
>> +        int r;
>> +
>> +        if (isempty(root))
>> +                etc_machine_id = "/etc/machine-id";
>> +        else {
>> +                etc_machine_id = strappenda(root, "/etc/machine-id");
>> +                path_kill_slashes((char*) etc_machine_id);
>> +        }
>> +
>> +        r = path_is_mount_point(etc_machine_id, false);
>> +        if (r <= 0) {
>> +                log_error("We expected that %s was an independent mount.", etc_machine_id);
>> +                return r < 0 ? r : -ENOENT;
>> +        }
> I think this should really work in idempotent style, i.e. so that you
> exit cleanly if the thing is already a proper file.

Making sense. I downgraded the error messaging to debug and always 
returns 0. I tried other various use case and I think the functions 
(hence, the binary) is idempotent now.

>
>> +
>> +        /* read existing machine-id */
>> +        fd = open(etc_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY);
>> +        if (fd < 0) {
>> +                log_error("Cannot open %s: %m", etc_machine_id);
>> +                return -errno;
>> +        }
>> +        if (fstat(fd, &st) < 0) {
>> +                log_error("fstat() failed: %m");
>> +                return -errno;
>> +        }
>> +        if (!S_ISREG(st.st_mode)) {
>> +                log_error("We expected %s to be a regular file.", etc_machine_id);
>> +                return -EISDIR;
>> +        }
>> +        r = get_valid_machine_id(fd, id);
>> +        if (r < 0) {
>> +                log_error("We didn't find a valid machine-id.");
>> +                return r;
>> +        }
>> +
>> +        r = is_on_temporary_fs(fd);
>> +        if (r <= 0) {
>> +                log_error("We expected %s to be a temporary file system.", etc_machine_id);
>> +                return r;
>> +        }
>> +
>> +        fd = safe_close(fd);
>> +
>> +        /* store current mount namespace */
>> +        r = namespace_open(0, NULL, &initial_mntns_fd, NULL, NULL);
>> +        if (r < 0) {
>> +                log_error("Can't fetch current mount namespace: %s", strerror(r));
>> +                return r;
>> +        }
>> +
>> +        /* switch to a new mount namespace, isolate ourself and unmount etc_machine_id in our new namespace */
>> +        if (unshare(CLONE_NEWNS) == -1) {
>> +                 log_error("Not enough privilege to switch to another namespace.");
>> +                 return EPERM;
>> +        }
>> +
>> +        if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
>> +                 log_error("Couldn't make-rslave / mountpoint in our private namespace.");
>> +                 return EPERM;
>> +        }
>> +
>> +        r = umount(etc_machine_id);
>> +        if (r < 0) {
>> +                log_error("Failed to unmount transient %s file in our private namespace: %m", etc_machine_id);
>> +                return -errno;
>> +        }
>> +
>> +        /* update a persistent version of etc_machine_id */
>> +        fd = open(etc_machine_id, O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444);
>> +        if (fd < 0) {
>> +                log_error("Cannot open for writing %s. This is mandatory to get a persistent machine-id: %m",
>> +                          etc_machine_id);
>> +                return -errno;
>> +        }
>> +        if (fstat(fd, &st) < 0) {
>> +                log_error("fstat() failed: %m");
>> +                return -errno;
>> +        }
>> +        if (!S_ISREG(st.st_mode)) {
>> +                log_error("We expected %s to be a regular file.", etc_machine_id);
>> +                return -EISDIR;
>> +        }
>> +
>> +        r = write_machine_id(fd, id);
>> +        if (r < 0) {
>> +                log_error("Cannot write %s: %s", etc_machine_id, strerror(r));
>> +                return r;
>> +        }
> Since you prepared the original patch, we improved the loggic logic of
> systemd. It would be great if you would update the patch to make use
> of it. In particular, this means avoiding strerror() for cases like
> the above (because it is not thread-safe to use). Instead use the new
> log_error_errno() that takes the error value as first parameter, and
> then makes sure that %m actually evaluates to the error string for
> that error. Also it will then return the error, so that you can
> simplify the four lines above into:
>
> if (r < 0)
>          return log_error_errno(r, "Cannot write %s: %m",
>          etc_machine_id);

Nice feature! I replaced it in some other places as well.
>
>> +        fd = safe_close(fd);
>> +
>> +        /* return to initial namespace and proceed a lazy tmpfs unmount */
>> +        r = namespace_enter(-1, initial_mntns_fd, -1, -1);
>> +        if (r < 0) {
>> +                log_warning("Failed to switch back to initial mount namespace. We'll keep transient %s file until next reboot.", etc_machine_id);
>> +        } else {
> No {} for single-line if-blocks please.
>
> Also, please print the error cause, use log_Warning_errno() for this,
> and use %m...

Done (here and on the next statement as well)!
>
>> +                r = umount2(etc_machine_id, MNT_DETACH);
>> +                if (r < 0)
>> +                        log_warning("Failed to unmount transient %s file. We keep that mount until next reboot: %m", etc_machine_id);
>> +        }
>> +
>> +        return 0;
>> +}
>> +
>>   int machine_id_setup(const char *root) {
> Otherwise looks great.

Thanks! Here is the new version with the above suggestion.

Cheers,
Didier
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-Add-a-machine_id_commit-call-to-commit-on-disk-a-tra.patch
Type: text/x-diff
Size: 6769 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/systemd-devel/attachments/20141202/9ea5b066/attachment.patch>


More information about the systemd-devel mailing list