occlum/ngo

[BUG] Cannot update atime, mtime and ctime for inode

Bonjourz opened this issue · 0 comments

Describe the bug

Any inodes in Linux has typically these three timestamps:

  • atime: The time of last access of file data
  • mtime: Time of last modification of file data
  • ctime: The time of last status change of file status

(See more details at https://man7.org/linux/man-pages/man7/inode.7.html)

We can get such attributes from stat()(https://man7.org/linux/man-pages/man2/lstat.2.html).

I discover that in occlum and ngo, the atime, mtime and ctime remain unchanged when we read/write content from a file descriptor, or change its attributes (such as chmod, chown ...). Such behavior is different from Linux.

To reproduce

Here is the sample program:

// First we need to create a file at 'file_path' which has O_RDWR permission
static int test(const char *file_path) {
    int ret, fd;
    struct stat stat_buf;
    char c;
    const char *content = "abcde";

    fd = open(file_path, O_RDWR);
    ret = write(fd, content, strlen(content));
    if (ret != strlen(content))
        THROW_ERROR("cannot write, ret=%d\n", ret);

    ret = stat(file_path, &stat_buf);
    printf("atime: { %ld, %ld }, mtime { %ld, %ld }\n",
            stat_buf.st_atim.tv_sec, stat_buf.st_atim.tv_nsec,
            stat_buf.st_mtim.tv_sec, stat_buf.st_mtim.tv_nsec);
    nanosleep(&period_of_100ms, NULL);

    printf("just open: \n");
    fd = open(file_path, 0);
    close(fd);
    ret = stat(file_path, &stat_buf);
    printf("atime: { %ld, %ld }, mtime { %ld, %ld } ctime { %ld, %ld }\n",
            stat_buf.st_atim.tv_sec, stat_buf.st_atim.tv_nsec,
            stat_buf.st_mtim.tv_sec, stat_buf.st_mtim.tv_nsec,
            stat_buf.st_ctim.tv_sec, stat_buf.st_ctim.tv_nsec);
    nanosleep(&period_of_100ms, NULL);

    printf("Open and read: \n");
    fd = open(file_path, 0);
    ret = read(fd, &c, sizeof(c));
    if (ret != 1)
        THROW_ERROR("cannot read, ret=%d\n", ret);
    close(fd);
    ret = stat(file_path, &stat_buf);
    printf("read: %c\n", c);
    printf("atime: { %ld, %ld }, mtime { %ld, %ld } ctime { %ld, %ld }\n",
            stat_buf.st_atim.tv_sec, stat_buf.st_atim.tv_nsec,
            stat_buf.st_mtim.tv_sec, stat_buf.st_mtim.tv_nsec,
            stat_buf.st_ctim.tv_sec, stat_buf.st_ctim.tv_nsec);
    nanosleep(&period_of_100ms, NULL);

    printf("Open and write: \n");
    fd = open(file_path, O_RDWR);
    c = 'p';
    ret = write(fd, &c, sizeof(c));
    if (ret != 1)
        THROW_ERROR("cannot write, ret=%d\n", ret);
    close(fd);
    ret = stat(file_path, &stat_buf);
    printf("atime: { %ld, %ld }, mtime { %ld, %ld } ctime { %ld, %ld }\n",
            stat_buf.st_atim.tv_sec, stat_buf.st_atim.tv_nsec,
            stat_buf.st_mtim.tv_sec, stat_buf.st_mtim.tv_nsec,
            stat_buf.st_ctim.tv_sec, stat_buf.st_ctim.tv_nsec);
    nanosleep(&period_of_100ms, NULL);

    printf("change ctime: \n");
    utimes(file_path, NULL);
    ret = stat(file_path, &stat_buf);
    printf("atime: { %ld, %ld }, mtime { %ld, %ld } ctime { %ld, %ld }\n",
            stat_buf.st_atim.tv_sec, stat_buf.st_atim.tv_nsec,
            stat_buf.st_mtim.tv_sec, stat_buf.st_mtim.tv_nsec,
            stat_buf.st_ctim.tv_sec, stat_buf.st_ctim.tv_nsec);

    return SUCCESS;
}

Expected behavior and Current behavior

The output on Linux is:

atime: { 1648016324, 648673770 }, mtime { 1648016324, 648673770 }
just open:
atime: { 1648016324, 648673770 }, mtime { 1648016324, 648673770 } ctime { 1648016324, 648673770 }
Open and read:
read: a
atime: { 1648016324, 849993133 }, mtime { 1648016324, 648673770 } ctime { 1648016324, 648673770 }
Open and write:
atime: { 1648016324, 849993133 }, mtime { 1648016324, 954679202 } ctime { 1648016324, 954679202 }
change ctime:
atime: { 1648016325, 51280910 }, mtime { 1648016325, 51280910 } ctime { 1648016325, 51280910 }

Expected behavior:

The atime is updated after we read from the file (See Open and read:)
The mtime and ctime are updated after we write to the file (See Open and write:)
The ctime is updated after we modify atime and mtime by invoking utimes (See change ctime:)

Current behavior:

The output on ngo and occlum is:

atime: { 1648016417, 234385206 }, mtime { 1648016417, 234385206 }
just open:
atime: { 1648016417, 234385206 }, mtime { 1648016417, 234385206 } ctime { 1648016417, 234385206 }
Open and read:
read: a
atime: { 1648016417, 234385206 }, mtime { 1648016417, 234385206 } ctime { 1648016417, 234385206 }
Open and write:
atime: { 1648016417, 234385206 }, mtime { 1648016417, 234385206 } ctime { 1648016417, 234385206 }
change ctime:
atime: { 1648016417, 642904375 }, mtime { 1648016417, 642904375 } ctime { 1648016417, 234385206 }

The atime remains unchanged after we read from the file (See Open and read:)
The mtime and ctime remain unchanged after we write to the file (See Open and write:)
The ctime remains unchanged after we modify atime and mtime by invoking utimes (See change ctime:)

Environment

  • HW: [e.g. SGX1, SGX2]
  • OS: [Ubuntu20.04]
  • Occlum version: [0.27.0]

Additional context

None

Possible solution/Implementation

None