How do ext2/3/4 filesystems deal with 64 bit time_t? - filesystems

I am working on small ext2 filesystem image manipulation tool (like listing directories, adding and extracting files without the need to mount it).
I've just came into a problem with Unix timestamp fields. They are all 32 bit in ext filesystems. As we know, 32 bit Unix timestamps won't work after year 2038 anymore. Most software can easily deal with this problem by just changing definition of time_t to 64 bit. But it is not that easy for filesystems. They need to be compatible with existing implementations yet they need to be updated from time to time. How exactly ext filesystems do that? Particularly fields like s_mtime, s_wtime, s_lastcheck, i_atime, i_ctime, i_mtime and i_dtime.

If you look at ext4's inode structure, you'll see:
struct ext4_inode {
...
__le32 i_ctime; /* Inode Change time */
...
__le32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
...
};
You won't find i_ctime_extra being used (*sigh*). Instead, you'll find:
#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
do { \
(inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \
if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) { \
ext4_decode_extra_time(&(inode)->xtime, \
raw_inode->xtime ## _extra); \
} \
else \
(inode)->xtime.tv_nsec = 0; \
} while (0)
#define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \
do { \
if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \
(einode)->xtime.tv_sec = \
(signed)le32_to_cpu((raw_inode)->xtime); \
else \
(einode)->xtime.tv_sec = 0; \
if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \
ext4_decode_extra_time(&(einode)->xtime, \
raw_inode->xtime ## _extra); \
else \
(einode)->xtime.tv_nsec = 0; \
} while (0)
And if you look at usages, you'll see that in-memory, a 64 bit integer is used, the separation only exists on disk.

Related

purpose of error injection macro in linux kernel

I have seen a macro ALLOW_ERROR_INJECTION which is used in SYSCALL_DEFINEx
#ifdef CONFIG_FUNCTION_ERROR_INJECTION
/*
* Whitelist ganerating macro. Specify functions which can be
* error-injectable using this macro.
*/
#define ALLOW_ERROR_INJECTION(fname, _etype) \
static struct error_injection_entry __used \
__attribute__((__section__("_error_injection_whitelist"))) \
_eil_addr_##fname = { \
.addr = (unsigned long)fname, \
.etype = EI_ETYPE_##_etype, \
};
#else
#define ALLOW_ERROR_INJECTION(fname, _etype)
#endif
#endif
Can anyone provide me enough documentation on this.
What is the use of it. What is whitelist

Any trick for simpler definition of multiline C macros?

I am trying to write some reusable generic type-safe code in C, using macros, similar to how klib works:
#define Fifo_define(TYPE) \
\
typedef struct { \
TYPE *head; \
TYPE *tail; \
size_t capacity; \
} Fifo_##TYPE, *pFifo_##TYPE; \
\
inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) { \
Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE)); \
TYPE * data = calloc(capacity, sizeof(TYPE)); \
fifo->head = data; \
fifo->tail = data; \
fifo->capacity = capacity; \
}
// define macros
#define Fifo(TYPE) Fifo_##TYPE
#define Fifo_init(TYPE, capacity) Fifo_##TYPE_init(capacity)
And then I just use it with any type parameter:
Fifo_define(int32_t);
...
Fifo(int32_t) *myFifo = Fifo_init(int32_t, 100);
However, writing this is rather convoluted and error prone, with no IDE editor support (IntelliSense), so I wondered if there are any tricks which might allow me to (perhaps) add a few defines and then include the file, without having to end each line with \?
Something like:
// no idea how to do this, just checking if similar concept is possible
#define FIFO_TYPE int
#define FIFO_NAME Fifo_int
#include <generic-fifo.h>
#undef FIFO_NAME
#undef FIFO_TYPE
And I would somehow get all the right structs and functions. The problem is that there is a lot of parameter concatenation in these macros, so I am not sure if this can be done in a simpler manner than the first snippet?
Not really recommended in this case, but you can do something like what you want to achieve with X-macros:
#define SUPPORTED_TYPES \
X(int) \
X(double) \
X(char)
#define X(TYPE) \
typedef struct { \
TYPE *head; \
TYPE *tail; \
size_t capacity; \
} Fifo_##TYPE, *pFifo_##TYPE;
SUPPORTED_TYPES
#undef X
#define X(TYPE) \
inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) \
{ \
Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE)); \
TYPE * data = calloc(capacity, sizeof(TYPE)); \
fifo->head = data; \
fifo->tail = data; \
fifo->capacity = capacity; \
}
SUPPORTED_TYPES
#undef X
But this didn't really improve the situation all that much. It got rid of the need for a single, ugly Fifo_define macro, so you can split up the code in several sections. But the macro mess remains.
I would recommend some completely different approach. Two suggestions:
Handle the type-generic things in the classic C way, in run-time. Use callbacks. Keep track of the used type with an enum, if needed.
C11 _Generic allows all kinds of type safety tricks and can be used to phase out such messy macros. Example that implements "functors". The macro itself is kept minimal and the different implementations for various types is typed out. (That's usually what you end up doing anyway, when you do type-generic programming.)
If you are using complex macros, consider using m4 instead of the C pre-processor. m4 is similar to the C pre-processor but is much more powerful and can do things like have multiple lines without a line continuation character.
Using code generators like m4 is called meta-programming.
Using m4 in C can be accomplished by treating it as a pre-pre-processor like this:
% grep -v '#include' file1 file2 | m4 > outfile
% m4 file1 file2 | cc
Since m4 works in a similar way to the C pre-processor at the basic level, it will generally convert any ordinary C macros correctly in addition to supporting its own advanced features.

Does hlist_for_each_entry_rcu need additional pointer to be passed into it?

LWN gives the following example on RCU:
Subscribing to an RCU-protected hlist is also similar to the circular
list:
1 rcu_read_lock();
2 hlist_for_each_entry_rcu(p, q, head, list) {
3 do_something_with(p->a, p->b, p->c);
4 }
5 rcu_read_unlock();
Quick Quiz 3: Why do we need to pass two pointers into hlist_for_each_entry_rcu() when only one is needed for
list_for_each_entry_rcu()?
Answer: Because in an hlist it is necessary to check for NULL rather than for encountering the head. (Try coding up a single-pointer
hlist_for_each_entry_rcu(). If you come up with a nice solution, it
would be a very good thing!)
I presume it must refer to an old version of hlist_for_each_entry_rcu() since current version (3.13.0) in rculist.h header actually presents the definition of hlist_for_each_entry_rcu taking 3 arguments, therefore eliminating the need for additional 4th pointer and doesn't seem to be very difficult to invent:
#define hlist_for_each_entry_rcu(pos, head, member) \
for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\
typeof(*(pos)), member); \
pos; \
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
&(pos)->member)), typeof(*(pos)), member))
Am I missing something or above version given in current rculist.h is such a very good thing?
We can see something subtle is going on in __rcu_dereference_check where additional pointer is created:
#define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*### needed? ###*/
#define rcu_dereference_check(p, c) \
__rcu_dereference_check((p), rcu_read_lock_held() || (c), __rcu)
#define __rcu_dereference_check(p, c, space) \
({ \
typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
rcu_lockdep_assert(c, "suspicious rcu_dereference_check()" \
" usage"); \
rcu_dereference_sparse(p, space); \
smp_read_barrier_depends(); \
((typeof(*p) __force __kernel *)(_________p1)); \
I wondered the same thing! Digging into the source, it seems like the the four argument version was replace by a three argument version somewhere between 3.8 (https://github.com/torvalds/linux/blob/v3.8/include/linux/rculist.h#L457) and 3.9 (https://github.com/torvalds/linux/blob/v3.9/include/linux/rculist.h#L456)
To compare the two macros, here's the older four argument version:
#define hlist_for_each_entry_rcu(tpos, pos, head, member) \
for (pos = rcu_dereference_raw(hlist_first_rcu(head)); \
pos && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
pos = rcu_dereference_raw(hlist_next_rcu(pos)))
And here's the new three-argument version:
#define hlist_for_each_entry_rcu(pos, head, member) \
for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\
typeof(*(pos)), member); \
pos; \
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
&(pos)->member)), typeof(*(pos)), member))
So it seems like the key difference is the hlist_entry_safe macro, which is basically ptr? ptr->member : NULL.
This is not obviously possible because hlist_entry_safe is a macro, so ptr might be an expression, and that expression should not be evaluated more than once. Ex, the obvious solution – #define hlist_entry_safe(ptr, member) ((ptr)? (ptr)->member : NULL) – will not work, because (ptr) will be evaluated twice.
Based on this answer, I assume the syntax that's being used in 3.9 – … ({ typeof(ptr) ____ptr = (ptr); … }) – is a GCC-only extension, which might explain why it wasn't possible at the time the article was written.

comments in c macro definition

There is not much information about this. Is this the one and only way to do comment in C macro definition? Or can I make add comment using another way?
#define TEST(a, b) \
{ \
bool aGb = false;\
bool bGc = false;\
/* comment is here */ \
if (a > b) \
{\
... \
}\
}
You can do this:
#define DOC(ignored)
And combine like so:
#define TEST(a, b) \
{ \
bool aGb = false; \
bool bGc = false; \
DOC((This is a comment, hello world!)) \
if (a > b) \
{ \
... \
} \
}
Naturally you can't use the C99 comment style with //, since it would ignore the rest of the line and prevent you from creating a multi-line macro.
I would personally suggest just getting used to /* comment */ style. For a start, people using syntax-highlighting IDEs with your code won't see the highlighting if you use this DOC macro above.
The only limitation which adds to those already present when commenting "real" C sources is, that you may not add anything on a macro's "source" line after the final backslash.

How to eliminate a redundant macro parameter

A while ago, I wrote a set of X-macros for a largish project. I needed to maintain coherent lists of both strings and enumerated references/hash values/callback functions etc. Here is what the function callback looks like
#define LREF_LOOKUP_TABLE_TEXT_SIZE 32
#define _LREF_ENUM_LIST(_prefix,_ref,...) _prefix ## _ ## _ref,
#define _LREF_BASE_STRUCT_ENTRY(_prefix,_ref) .text= #_ref "\0", .position= _LREF_ENUM_LIST(_prefix, _ref)
#define _LREF_FUNCTION_STRUCT_LIST(_prefix,_ref,...) {_LREF_BASE_STRUCT_ENTRY(_prefix,_ref) _prefix ## _ ## _ref ## _callback},
#define _LREF_ENUM_TYPEDEF(_prefix) \
typedef enum _prefix \
{ \
_ ## _prefix ## s(_prefix,_LREF_ENUM_LIST) \
_LREF_ENUM_LIST(_prefix,tblEnd) \
} e_ ## _prefix
#define _LREF_LOOKUP_TABLE_TYPEDEF(_prefix, _extras) \
typedef struct _prefix ## _lookup \
{ \
const char text[LREF_LOOKUP_TABLE_TEXT_SIZE]; \
e_ ## _prefix position; \
_extras \
} _prefix ##_lookup_t
#define LREF_GENERIC_LOOKUP_TABLE(_prefix, _type, _tabledef, _listdef, _extras) \
_LREF_ENUM_TYPEDEF(_prefix); \
_LREF_LOOKUP_TABLE_TYPEDEF(_prefix,_tabledef); \
_extras \
_LREF_LOOKUP_TABLE_DECLARATION(_prefix,_listdef, _type)
#define LREF_FUNCTION_LOOKUP_TABLE(_prefix, _type) \
_ ## _prefix ## s(_prefix, _LREF_FUNCTION_DEF ) \
LREF_GENERIC_LOOKUP_TABLE( _prefix, \
_type, \
void* (*function) (void*);, \
_LREF_FUNCTION_STRUCT_LIST, )
This sits in a header file and allows me to write things like:
#define _cl_tags(x,_) \
_(x, command_list) \
_(x, command) \
_(x, parameter) \
_(x, fixed_parameter) \
_(x, parameter_group) \
_(x, group) \
_(x, map) \
_(x, transform)
LREF_FUNCTION_LOOKUP_TABLE(cl_tag, static);
This keeps processing routines short. For example, loading a configuration file with the above tags is simply:
for (node_tag = cl_tag_lookup_table; node_tag->position != cl_tag_tblEnd; node_tag++)
{
if (strcasecmp(test_string, node_tag->text) == 0)
{
func_return = node_tag->function((void*)m_parser);
}
}
My question is this: I hate that I have to include the second parameter in my #define. I want to be able to write #define _cl_tags(_) instead of #define _cl_tags(x,_). As you can see, the x is only used to pass the prefix (cl_tag) down. But this is superfluous as the prefix is a parameter to the initial macro.
The solution to this would be easy if my preprocessor would expand the outer-most macros first. Unfortunately, GCC's preprocessor works through the inner-most macros, i.e. parameter values, before expanding the outermost macro.
I am using gcc 4.4.5
Clarification
By C89 (and C99) standard, the following definitions
#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))
with the invocation
plus(plus(a,b),c)
should yield
plus(plus(a,b),c)
add(c,plus(a,b))
((c)+(plus(a,b))
((c)+(add(b,a))
((c)+(((b)+(a))))
gcc 4.4.5 gives
plus(plus(a,b),c)
plus(add(b,a),c)
plus(((b)+(a)),c)
add(c,((b)+(a)))
((c)+(((b)+(a))))
Here's what I would do (have done similarly):
Put these in a utility header file:
/*
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define PPCAT_NX(A, B) A ## B
/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
*/
#define PPCAT(A, B) PPCAT_NX(A, B)
Then define this before including your LREF macro header file:
#define LREF_TAG cl_tag
Then, in your LREF macro header file,
#define LREF_PFX(x) PPCAT(LREF_TAG, x)
#define LREF_SFX(x) PPCAT(x, LREF_TAG)
Then replace every instance of _prefix ## foo with LREF_PFX(foo) and foo ## _prefix with LREF_SFX(foo).
(When pasting more than two tokens together, just use nested PPCAT's.)
Your invocation would become
#define LREF_TAG cl_tag
#define _cl_tags(_) \
_(command_list) \
_(command) \
_(parameter) \
_(fixed_parameter) \
_(parameter_group) \
_(group) \
_(map) \
_(transform)
LREF_FUNCTION_LOOKUP_TABLE(static);
This answer just addresses the 'clarification'. Here is the correct behaviour:
#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))
Initial: plus(plus(a,b),c)
Pass 1a: plus(add(b,a),c)
Pass 1b: add(c,add(b,a))
Pass 2a: add(c,((b)+(a)))
Pass 2b: ((c)+(((b)+(a))))
The rules are that each macro is replaced once non-recursively (starting from the inner-most when they are nested); and then a new pass (aka. "rescan") happens repeating the same procedure, this continues until a pass performs no replacement.
I'm not sure what point you were trying to make though, as you give the same final conclusion for both GCC and what you expected to happen.

Resources