chiark / gitweb /
Add ugly CMP_F_TYPE() macro
authorHarald Hoyer <harald@redhat.com>
Thu, 18 Apr 2013 05:34:25 +0000 (07:34 +0200)
committerHarald Hoyer <harald@redhat.com>
Thu, 18 Apr 2013 05:34:25 +0000 (07:34 +0200)
On some architectures (like s390x) the kernel has the type int for
f_type, but long in userspace.
Assigning the 32 bit magic constants from linux/magic.h to the 31 bit
signed f_type in the kernel, causes f_type to be negative for some
constants.
glibc extends the int to long for those architecures in 64 bit mode, so
the negative int becomes a negative long, which cannot be simply
compared to the original magic constant, because the compiler would
automatically cast the constant to long.
To workaround this issue, we also compare to the (int)MAGIC value in a
macro. Of course, we could do #ifdef with the architecure, but it has to
be maintained, and the magic constants are 32 bit anyway.

Someday, when the int is unsigned or long for all architectures, we can
remove this macro again. Until then, keep it as simple as it can be.

src/journal/sd-journal.c
src/readahead/readahead-collect.c
src/shared/macro.h
src/shared/util.c

index 88777cbcb967a481219c6ee43c12f9ff044c478d..e92f20b63b84b85b04a9ebec0cad2a44a8f7eeae 100644 (file)
@@ -1248,11 +1248,11 @@ static void check_network(sd_journal *j, int fd) {
                 return;
 
         j->on_network =
                 return;
 
         j->on_network =
-                (unsigned __SWORD_TYPE) sfs.f_type == CIFS_MAGIC_NUMBER ||
-                (unsigned __SWORD_TYPE) sfs.f_type == CODA_SUPER_MAGIC ||
-                (unsigned __SWORD_TYPE) sfs.f_type == NCP_SUPER_MAGIC ||
-                (unsigned __SWORD_TYPE) sfs.f_type == NFS_SUPER_MAGIC ||
-                (unsigned __SWORD_TYPE) sfs.f_type == SMB_SUPER_MAGIC;
+                CMP_F_TYPE(sfs.f_type, CIFS_MAGIC_NUMBER) ||
+                CMP_F_TYPE(sfs.f_type, CODA_SUPER_MAGIC) ||
+                CMP_F_TYPE(sfs.f_type, NCP_SUPER_MAGIC) ||
+                CMP_F_TYPE(sfs.f_type, NFS_SUPER_MAGIC) ||
+                CMP_F_TYPE(sfs.f_type, SMB_SUPER_MAGIC);
 }
 
 static int add_file(sd_journal *j, const char *prefix, const char *filename) {
 }
 
 static int add_file(sd_journal *j, const char *prefix, const char *filename) {
index fbfa8e786fdd16f4bd967ce807dbc87f2ad96ace..19703aa602a83654fb93533722948e41d2acfea8 100644 (file)
@@ -505,7 +505,7 @@ done:
         on_ssd = fs_on_ssd(root) > 0;
         log_debug("On SSD: %s", yes_no(on_ssd));
 
         on_ssd = fs_on_ssd(root) > 0;
         log_debug("On SSD: %s", yes_no(on_ssd));
 
-        on_btrfs = statfs(root, &sfs) >= 0 && (unsigned __SWORD_TYPE) sfs.f_type == BTRFS_SUPER_MAGIC;
+        on_btrfs = statfs(root, &sfs) >= 0 && CMP_F_TYPE(sfs.f_type, BTRFS_SUPER_MAGIC);
         log_debug("On btrfs: %s", yes_no(on_btrfs));
 
         if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) {
         log_debug("On btrfs: %s", yes_no(on_btrfs));
 
         if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) {
index 9bf81dc3cc541229bebe333d8d3ee31074ffe68b..f91f7de76956da0de546cf4bdba1b9c7c66650ca 100644 (file)
@@ -264,6 +264,23 @@ do {                                                                    \
         }                                                               \
 } while(false)
 
         }                                                               \
 } while(false)
 
+/* Remove this macro, when the kernel has f_type as unsigned int or long
+ * for every architecure. Currently some 64bit architecures (like s390x)
+ * have int in the kernel, but long in userspace for f_type, so glibc
+ * extends the int to long and carries over the sign. Negative numbers are
+ * caused by the 32bit magic constants in linux/magic.h stuffed into the
+ * signed int in the kernel and these negative numbers are extended to
+ * long, which cannot be simply compared to the magic constants anymore.
+ */
+#define CMP_F_TYPE(f, c)                                                \
+        __extension__ ({                                                \
+                        __SWORD_TYPE _f = (f);                          \
+                        const __SWORD_TYPE _c = (c);                    \
+                        const int _c32 = (c);                           \
+                        (_f == _c || _f == _c32 );                      \
+                })
+
+
 /* Returns the number of chars needed to format variables of the
  * specified type as a decimal string. Adds in extra space for a
  * negative '-' prefix. */
 /* Returns the number of chars needed to format variables of the
  * specified type as a decimal string. Adds in extra space for a
  * negative '-' prefix. */
index 386973b3fcc75ce70620d65dcfb2dec951dd297e..2a8046922bf539824f1a1f38d449d3d76c2f747a 100644 (file)
@@ -2779,8 +2779,9 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
 
 static int is_temporary_fs(struct statfs *s) {
         assert(s);
 
 static int is_temporary_fs(struct statfs *s) {
         assert(s);
-        return (unsigned __SWORD_TYPE) s->f_type == TMPFS_MAGIC ||
-                (unsigned __SWORD_TYPE) s->f_type == RAMFS_MAGIC;
+        return
+                CMP_F_TYPE(s->f_type, TMPFS_MAGIC) ||
+                CMP_F_TYPE(s->f_type, RAMFS_MAGIC);
 }
 
 int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
 }
 
 int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {