Home | History | Annotate | Download | only in nfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * general range tracking support
     28  *
     29  * This API is for keeping track of byte ranges.  Each byte in the range
     30  * is considered to be "set" or "cleared".  Only continous sub-ranges,
     31  * specified by offset and length, may be manipulated or queried; however,
     32  * the range itself may hold arbitrarily disjoint sub-ranges of set or
     33  * cleared bytes.
     34  */
     35 
     36 #ifndef _NFS_RANGE_H
     37 #define	_NFS_RANGE_H
     38 
     39 #include <sys/types.h>
     40 
     41 #ifdef	__cplusplus
     42 extern "C" {
     43 #endif
     44 
     45 /*
     46  * Creating / destroying ranges
     47  * ----------------------------
     48  *
     49  * nfs_range_create() - create a range container
     50  * nfs_range_destroy() - destroy a range container
     51  *
     52  * nfs_range_create() allocates and returns a range container.  Initially,
     53  * the entire range is clear.  To deallocate the range container, use
     54  * nfs_range_destroy().
     55  *
     56  * Example:
     57  * --------
     58  *
     59  * nfs_range_t *range;
     60  *
     61  * range = nfs_range_create();
     62  * . . .
     63  * nfs_range_destroy(range);
     64  *
     65  * Manipulating ranges
     66  * -------------------
     67  *
     68  * nfs_range_set() - set a sub-range of bytes
     69  * nfs_range_clear() - clear a sub-range of bytes
     70  *
     71  * nfs_range_set(range, offset, length, flags) sets the subrange,
     72  * specified by offset and length.  Returns the status of the entire
     73  * range as NFS_RANGE_ALL, NFS_RANGE_SOME, or NFS_RANGE_NONE, depending
     74  * on whether the entire range is now entirely set, partially set, or
     75  * entirely clear.
     76  *
     77  * nfs_range_clear(range, offset, length, flags) clears the subrange,
     78  * specified by offset and length.  Returns the status of the entire
     79  * range, the same as nfs_range_set().
     80  *
     81  * The "flags" field is reserved for future use.
     82  *
     83  * Example:
     84  * --------
     85  *
     86  * Set a sub-range consisting of the first 64k of the range
     87  *
     88  * nfs_range_set(range, 0, 65536);
     89  *
     90  * Since only the first 64k is set, NFS_RANGE_SOME is returned.
     91  *
     92  * Clear the 2nd 4k chunk of the range, splitting the sub-range that was
     93  * set above
     94  *
     95  * nfs_range_clear(range, 4096, 4096);
     96  *
     97  * At this point, [0, 4095] is set, and [8192, 65535] is set.
     98  * nfs_range_clear() returned NFS_RANGE_SOME, again because there were
     99  * some offsets in the entire range set, but not all.
    100  *
    101  * Querying ranges
    102  * ---------------
    103  *
    104  * nfs_range_is_set() - checks for a sub-range being set
    105  * nfs_range_is_clear() - checks for a sub-range being clear
    106  *
    107  * Return values:
    108  * NFS_RANGE_NONE - indicates that none of the sub-range meets the criteria
    109  * NFS_RANGE_SOME - indicates that some of the sub-range meets the criteria
    110  * NFS_RANGE_ALL - indicates that all of the sub-range meets the criteria
    111  *
    112  * nfs_range_is_set(range, offsetp, lengthp, flags) determines if a sub-range
    113  * is set.  It returns NFS_RANGE_NONE, NFS_RANGE_SOME, or NFS_RANGE_ALL,
    114  * depending on whether none, some, or all of the requested sub-range is set.
    115  * In the case that the initial offset is not set, NFS_RANGE_NONE will
    116  * be returned.
    117  *
    118  * The desired offset and length are passed by reference.  The values
    119  * indicated by offsetp and lengthp are modified, so that they fit
    120  * entirely within the area that is set, unless NFS_RANGE_NONE is
    121  * returned, in which case they are not modified at all.
    122  *
    123  * nfs_range_is_clear(range, offsetp, lengthp, flags) is just like
    124  * nfs_range_is_set(), except that the query or wait applies to the
    125  * sub-range being clear.  In the case that the initial offset is
    126  * not clear, NFS_RANGE_NONE will be returned.
    127  *
    128  * NFS_RANGE_NONE is guaranteed to be zero, so it may be used as a
    129  * generalized boolean.
    130  *
    131  * The "flags" field is reserved for future use.
    132  *
    133  * Example:
    134  * --------
    135  *
    136  * nfs_range_t *range;
    137  * uint64_t off, len;
    138  *
    139  * range = nfs_range_create();
    140  * nfs_range_set(range, 0, ULONG_MAX);
    141  * nfs_range_clear(range, 4096, 4096);
    142  *
    143  * off = 0;
    144  * len = 10;
    145  * ret = nfs_range_is_set(range, &off, &len, 0);
    146  *
    147  * ret is NFS_RANGE_ALL, off remains 0, len remains 10.
    148  *
    149  * off = 0;
    150  * len = 8192;
    151  * ret = nfs_range_is_set(range, &off, &len, 0);
    152  *
    153  * ret is NFS_RANGE_SOME, off is 0, len is 4096
    154  *
    155  * off = 1024;
    156  * len = 65536;
    157  * ret = nfs_range_is_set(range, &off, &len, 0);
    158  *
    159  * ret is NFS_RANGE_SOME, off is 0, len is 4096
    160  */
    161 
    162 typedef struct nfs_range nfs_range_t;
    163 
    164 nfs_range_t *nfs_range_create(void);
    165 void nfs_range_destroy(nfs_range_t *);
    166 
    167 typedef void *nfs_shared_range_t;
    168 
    169 typedef enum {
    170 	NFS_RANGE_NONE = 0,
    171 	NFS_RANGE_SOME,
    172 	NFS_RANGE_ALL
    173 } nfs_range_query_t;
    174 
    175 nfs_range_query_t nfs_range_set(nfs_range_t *, uint64_t, uint64_t);
    176 nfs_range_query_t nfs_range_clear(nfs_range_t *, uint64_t, uint64_t);
    177 
    178 nfs_range_query_t nfs_range_is_set(nfs_range_t *, uint64_t *, uint64_t *,
    179     uint32_t);
    180 nfs_range_query_t nfs_range_is_clear(nfs_range_t *, uint64_t *, uint64_t *,
    181     uint32_t);
    182 
    183 /*
    184  * These routines must be called when the kernel module is loaded or unloaded.
    185  */
    186 void nfs_range_init(void);
    187 void nfs_range_fini(void);
    188 
    189 #ifdef	__cplusplus
    190 }
    191 #endif
    192 
    193 #endif /* _NFS_RANGE_H */
    194