lkml.org 
[lkml]   [2017]   [Dec]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectStoring errors in the XArray
    On Mon, Dec 11, 2017 at 03:10:22PM -0800, Randy Dunlap wrote:
    > > +The XArray does not support storing :c:func:`IS_ERR` pointers; some
    > > +conflict with data values and others conflict with entries the XArray
    > > +uses for its own purposes. If you need to store special values which
    > > +cannot be confused with real kernel pointers, the values 4, 8, ... 4092
    > > +are available.
    >
    > or if I know that they values are errno-range values, I can just shift them
    > left by 2 to store them and then shift them right by 2 to use them?

    On further thought, I like this idea so much, it's worth writing helpers
    for this usage. And test-suite (also doubles as a demonstration of how
    to use it).

    diff --git a/include/linux/xarray.h b/include/linux/xarray.h
    index c616e9319c7c..53aa251df57a 100644
    --- a/include/linux/xarray.h
    +++ b/include/linux/xarray.h
    @@ -232,6 +232,39 @@ static inline bool xa_is_value(const void *entry)
    return (unsigned long)entry & 1;
    }

    +/**
    + * xa_mk_errno() - Create an XArray entry from an error number.
    + * @error: Error number to store in XArray.
    + *
    + * Return: An entry suitable for storing in the XArray.
    + */
    +static inline void *xa_mk_errno(long error)
    +{
    + return (void *)(error << 2);
    +}
    +
    +/**
    + * xa_to_errno() - Get error number stored in an XArray entry.
    + * @entry: XArray entry.
    + *
    + * Return: The error number stored in the XArray entry.
    + */
    +static inline unsigned long xa_to_errno(const void *entry)
    +{
    + return (long)entry >> 2;
    +}
    +
    +/**
    + * xa_is_errno() - Determine if an entry is an errno.
    + * @entry: XArray entry.
    + *
    + * Return: True if the entry is an errno, false if it is a pointer.
    + */
    +static inline bool xa_is_errno(const void *entry)
    +{
    + return (((unsigned long)entry & 3) == 0) && (entry > (void *)-4096);
    +}
    +
    /**
    * xa_is_internal() - Is the entry an internal entry?
    * @entry: Entry retrieved from the XArray
    diff --git a/tools/testing/radix-tree/xarray-test.c b/tools/testing/radix-tree/xarray-test.c
    index 43111786ebdd..b843cedf3988 100644
    --- a/tools/testing/radix-tree/xarray-test.c
    +++ b/tools/testing/radix-tree/xarray-test.c
    @@ -29,7 +29,13 @@ void check_xa_err(struct xarray *xa)
    assert(xa_err(xa_store(xa, 1, xa_mk_value(0), GFP_KERNEL)) == 0);
    assert(xa_err(xa_store(xa, 1, NULL, 0)) == 0);
    // kills the test-suite :-(
    -// assert(xa_err(xa_store(xa, 0, xa_mk_internal(0), 0)) == -EINVAL);
    +// assert(xa_err(xa_store(xa, 0, xa_mk_internal(0), 0)) == -EINVAL);
    +
    + assert(xa_err(xa_store(xa, 0, xa_mk_errno(-ENOMEM), GFP_KERNEL)) == 0);
    + assert(xa_err(xa_load(xa, 0)) == 0);
    + assert(xa_is_errno(xa_load(xa, 0)) == true);
    + assert(xa_to_errno(xa_load(xa, 0)) == -ENOMEM);
    + xa_erase(xa, 0);
    }

    void check_xa_tag(struct xarray *xa)
    \
     
     \ /
      Last update: 2017-12-15 18:11    [W:4.007 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site