Re: [PATCH 1/2] [PATCH 1/2] Introduce new macros min_lt and max_lt for comparing with larger type

From: Dave Young
Date: Fri Mar 11 2016 - 02:55:41 EST


Hi, Jianyu

On 03/11/16 at 03:19pm, Jianyu Zhan wrote:
> On Fri, Mar 11, 2016 at 2:21 PM, <dyoung@xxxxxxxxxx> wrote:
> > A useful use case for min_t and max_t is comparing two values with larger
> > type. For example comparing an u64 and an u32, usually we do not want to
> > truncate the u64, so we need use min_t or max_t with u64.
> >
> > To simplify the usage introducing two more macros min_lt and max_lt,
> > 'lt' means larger type.
> >
> > Signed-off-by: Dave Young <dyoung@xxxxxxxxxx>
> > ---
> > include/linux/kernel.h | 13 +++++++++++++
> > 1 file changed, 13 insertions(+)
> >
> > --- linux.orig/include/linux/kernel.h
> > +++ linux/include/linux/kernel.h
> > @@ -798,6 +798,19 @@ static inline void ftrace_dump(enum ftra
> > type __max2 = (y); \
> > __max1 > __max2 ? __max1: __max2; })
> >
> > +/*
> > + * use type of larger size in min_lt and max_lt
> > + */
> > +#define min_lt(x, y) ({ \
> > + int sx = sizeof(typeof(x)); \
> > + int sy = sizeof(typeof(y)); \
> > + sx > sy ? min_t(typeof(x), x, y) : min_t(typeof(y), x, y); })
> > +
> > +#define max_lt(x, y) ({ \
> > + int sx = sizeof(typeof(x)); \
> > + int sy = sizeof(typeof(y)); \
> > + sx > sy ? max_t(typeof(x), x, y) : max_t(typeof(y), x, y); })
> > +
> > /**
> > * clamp_t - return a value clamped to a given range using a given type
> > * @type: the type of variable to use
> >
> >
>
> No no!
>
> C standard has defined "usual arithmetic conversions" rules[1], which
> decides the type promotion rules in binary operators.
>
> The interfaces in this patch just bluntly overrides this rule to
> choose the bigger type size
> for operation. Most of time it might work well, because most time the
> operands used in min_t()/max_t() in Linux kernel
> have same sign'ness and this rule works.
>
> But if two operands have same size type but have different different
> sign'ness, this interfaces will exhibit Undefind Behavior,
> i.e. you choose the typeof(y) as the final type to use in operation
> when they have the same type size, so it might be signed
> or unsigned, depending on the type of y.

Oops, brain dead, I obviously missed the case, it is definitely a problem.

>
> So, in this /proc/fs/vmcore case you should rather just explicit cast
> the operand to avoid truncation.

Sure, will resend a fix

Thanks
Dave