Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix compatibility with AARCH64 #101

Merged
merged 3 commits into from May 11, 2017
Merged

Conversation

etehtsea
Copy link
Contributor

@etehtsea etehtsea commented May 10, 2017

I added/,odified Linux stat64 struct layouts according to pahole output:

xtest.c

#define _LARGEFILE_SOURCE 1

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
        struct stat sb;

        if (argc < 2)
        {
                fprintf(stderr, "Usage: %s: file ...\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        for (int i = 1; i < argc; i++)
        {
                if (-1 == __xstat64(0, argv[i], &sb))
                {
                        perror("stat()");
                        exit(EXIT_FAILURE);
                }

                printf("%s:\n", argv[i]);
                printf("\tdev: %u\n", sb.st_dev);
                printf("\tinode: %u\n", sb.st_ino);
                printf("\tmode: %o\n", sb.st_mode);
                printf("\tlinks: %d\n", sb.st_nlink);
                printf("\towner: %u\n", sb.st_uid);
                printf("\tgroup: %u\n", sb.st_gid);
                printf("\trdev: %u\n", sb.st_rdev);
                printf("\tsize: %ld\n", sb.st_size);
                printf("\tblksize: %d\n", sb.st_blksize);
                printf("\tblkcnt: %ld\n", sb.st_blocks);
                printf("\tatime: %s", ctime(&sb.st_atim.tv_sec));
                printf("\tmtime: %s", ctime(&sb.st_mtim.tv_sec));
                printf("\tctime: %s", ctime(&sb.st_ctim.tv_sec));
                printf("\n");
        }

        return 0;
}

On AARCH64:

struct stat {
        __dev_t                    st_dev;               /*     0     8 */
        __ino_t                    st_ino;               /*     8     8 */
        __mode_t                   st_mode;              /*    16     4 */
        __nlink_t                  st_nlink;             /*    20     4 */
        __uid_t                    st_uid;               /*    24     4 */
        __gid_t                    st_gid;               /*    28     4 */
        __dev_t                    st_rdev;              /*    32     8 */
        __dev_t                    __pad1;               /*    40     8 */
        __off_t                    st_size;              /*    48     8 */
        __blksize_t                st_blksize;           /*    56     4 */
        int                        __pad2;               /*    60     4 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        __blkcnt_t                 st_blocks;            /*    64     8 */
        struct timespec            st_atim;              /*    72    16 */
        struct timespec            st_mtim;              /*    88    16 */
        struct timespec            st_ctim;              /*   104    16 */
        int                        __glibc_reserved[2];  /*   120     8 */
        /* --- cacheline 2 boundary (128 bytes) --- */

        /* size: 128, cachelines: 2, members: 16 */
};

On X86_64:

struct stat {
	__dev_t                    st_dev;               /*     0     8 */
	__ino_t                    st_ino;               /*     8     8 */
	__nlink_t                  st_nlink;             /*    16     8 */
	__mode_t                   st_mode;              /*    24     4 */
	__uid_t                    st_uid;               /*    28     4 */
	__gid_t                    st_gid;               /*    32     4 */
	int                        __pad0;               /*    36     4 */
	__dev_t                    st_rdev;              /*    40     8 */
	__off_t                    st_size;              /*    48     8 */
	__blksize_t                st_blksize;           /*    56     8 */
	/* --- cacheline 1 boundary (64 bytes) --- */
	__blkcnt_t                 st_blocks;            /*    64     8 */
	struct timespec            st_atim;              /*    72    16 */
	struct timespec            st_mtim;              /*    88    16 */
	struct timespec            st_ctim;              /*   104    16 */
	__syscall_slong_t          __glibc_reserved[3];  /*   120    24 */
	/* --- cacheline 2 boundary (128 bytes) was 16 bytes ago --- */

	/* size: 144, cachelines: 3, members: 15 */
	/* last cacheline: 16 bytes */
};

This PR fixes jruby/jruby#4600

public final Unsigned32 st_mode = new Unsigned32();
public final Unsigned32 st_uid = new Unsigned32();
public final Unsigned32 st_gid = new Unsigned32();
public final Signed32 __pad0 = new Signed32();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@etehtsea Is __pad0 missing from all 64 bit Linux systems? This seems like everything would be way off here if this were the case. Assuming it was ever tested against any other 64 bit linux.

Copy link
Contributor Author

@etehtsea etehtsea May 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally I tried on Debian 8.8 / cc (Debian 4.9.2-10) 4.9.2 / Xeon E5620. At the moment I rechecked on CentOS 7.3.1611/ cc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11) / i7-4770HQ.

And also using clang on CentOS (clang version 3.4.2 (tags/RELEASE_34/dot2-final)) and got the same result everywhere.

P.S. I'm not sure but one C dev who I know said that this should be guaranteed by C ABI (https://en.m.wikipedia.org/wiki/Application_binary_interface).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@etehtsea yeah I guess I am mostly asking because by ABI then this should have never worked until this PR. So that makes me wonder if some Linux variants are actually missing a field that the system you tested have (which might just be a literal pad).

Unfortunately, this structure since the very beginning has not had that extra 32 bit pad. We can probably land this as-is and write off the old code as a mistake but I will poke around and see if I can understand why there is a pad (or more importantly why we committed something without the pad).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like these pads are in for word alignment purposes. Our .java files are pretty old. I wonder if they corrected alignment of stat in the last 10 years and ours are out of date with newer linuxes. I see in FC25 the same pads. I wish history was documented better in software.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made sure that StructLayout handles padding automatically so I updated PR.

ioprioThreadedTest(jnr.posix.LinuxPOSIXTest)  Time elapsed: 0.038 sec  <<< ERROR!
java.lang.IllegalStateException: ioprio_set is not implemented in jnr-posix
        at jnr.posix.util.DefaultPOSIXHandler.unimplementedError(DefaultPOSIXHandler.java:28)
        at jnr.posix.LinuxPOSIX.ioprio_set(LinuxPOSIX.java:254)
        at jnr.posix.LinuxPOSIXTest.ioprioThreadedTest(LinuxPOSIXTest.java:44)
@enebo enebo merged commit 6335c46 into jnr:master May 11, 2017
@etehtsea etehtsea deleted the linux-file-stat64 branch May 11, 2017 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dir.tmpdir fails with error on AARCH64
3 participants