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