Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
Nathan Scott | 7b71876 | 2005-11-02 14:58:39 +1100 | [diff] [blame] | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. |
| 3 | * All Rights Reserved. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4 | * |
Nathan Scott | 7b71876 | 2005-11-02 14:58:39 +1100 | [diff] [blame] | 5 | * This program is free software; you can redistribute it and/or |
| 6 | * modify it under the terms of the GNU General Public License as |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7 | * published by the Free Software Foundation. |
| 8 | * |
Nathan Scott | 7b71876 | 2005-11-02 14:58:39 +1100 | [diff] [blame] | 9 | * This program is distributed in the hope that it would be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13 | * |
Nathan Scott | 7b71876 | 2005-11-02 14:58:39 +1100 | [diff] [blame] | 14 | * You should have received a copy of the GNU General Public License |
| 15 | * along with this program; if not, write the Free Software Foundation, |
| 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 17 | */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 18 | #ifndef __XFS_BUF_H__ |
| 19 | #define __XFS_BUF_H__ |
| 20 | |
| 21 | #include <linux/config.h> |
| 22 | #include <linux/list.h> |
| 23 | #include <linux/types.h> |
| 24 | #include <linux/spinlock.h> |
| 25 | #include <asm/system.h> |
| 26 | #include <linux/mm.h> |
| 27 | #include <linux/fs.h> |
| 28 | #include <linux/buffer_head.h> |
| 29 | #include <linux/uio.h> |
| 30 | |
| 31 | /* |
| 32 | * Base types |
| 33 | */ |
| 34 | |
| 35 | #define XFS_BUF_DADDR_NULL ((xfs_daddr_t) (-1LL)) |
| 36 | |
| 37 | #define page_buf_ctob(pp) ((pp) * PAGE_CACHE_SIZE) |
| 38 | #define page_buf_btoc(dd) (((dd) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) |
| 39 | #define page_buf_btoct(dd) ((dd) >> PAGE_CACHE_SHIFT) |
| 40 | #define page_buf_poff(aa) ((aa) & ~PAGE_CACHE_MASK) |
| 41 | |
| 42 | typedef enum page_buf_rw_e { |
| 43 | PBRW_READ = 1, /* transfer into target memory */ |
| 44 | PBRW_WRITE = 2, /* transfer from target memory */ |
| 45 | PBRW_ZERO = 3 /* Zero target memory */ |
| 46 | } page_buf_rw_t; |
| 47 | |
| 48 | |
| 49 | typedef enum page_buf_flags_e { /* pb_flags values */ |
| 50 | PBF_READ = (1 << 0), /* buffer intended for reading from device */ |
| 51 | PBF_WRITE = (1 << 1), /* buffer intended for writing to device */ |
| 52 | PBF_MAPPED = (1 << 2), /* buffer mapped (pb_addr valid) */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 53 | PBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ |
Christoph Hellwig | c86e711 | 2005-11-02 10:29:39 +1100 | [diff] [blame] | 54 | PBF_DONE = (1 << 5), /* all pages in the buffer uptodate */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 55 | PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ |
| 56 | PBF_STALE = (1 << 7), /* buffer has been staled, do not find it */ |
| 57 | PBF_FS_MANAGED = (1 << 8), /* filesystem controls freeing memory */ |
Christoph Hellwig | f538d4d | 2005-11-02 10:26:59 +1100 | [diff] [blame] | 58 | PBF_ORDERED = (1 << 11), /* use ordered writes */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 59 | PBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead */ |
| 60 | |
| 61 | /* flags used only as arguments to access routines */ |
| 62 | PBF_LOCK = (1 << 14), /* lock requested */ |
| 63 | PBF_TRYLOCK = (1 << 15), /* lock requested, but do not wait */ |
| 64 | PBF_DONT_BLOCK = (1 << 16), /* do not block in current thread */ |
| 65 | |
| 66 | /* flags used only internally */ |
| 67 | _PBF_PAGE_CACHE = (1 << 17),/* backed by pagecache */ |
| 68 | _PBF_KMEM_ALLOC = (1 << 18),/* backed by kmem_alloc() */ |
| 69 | _PBF_RUN_QUEUES = (1 << 19),/* run block device task queue */ |
David Chinner | 2f92658 | 2005-09-05 08:33:35 +1000 | [diff] [blame] | 70 | _PBF_DELWRI_Q = (1 << 21), /* buffer on delwri queue */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 71 | } page_buf_flags_t; |
| 72 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 73 | |
| 74 | typedef struct xfs_bufhash { |
| 75 | struct list_head bh_list; |
| 76 | spinlock_t bh_lock; |
| 77 | } xfs_bufhash_t; |
| 78 | |
| 79 | typedef struct xfs_buftarg { |
| 80 | dev_t pbr_dev; |
| 81 | struct block_device *pbr_bdev; |
| 82 | struct address_space *pbr_mapping; |
| 83 | unsigned int pbr_bsize; |
| 84 | unsigned int pbr_sshift; |
| 85 | size_t pbr_smask; |
| 86 | |
| 87 | /* per-device buffer hash table */ |
| 88 | uint bt_hashmask; |
| 89 | uint bt_hashshift; |
| 90 | xfs_bufhash_t *bt_hash; |
David Chinner | a6867a6 | 2006-01-11 15:37:58 +1100 | [diff] [blame^] | 91 | |
| 92 | /* per device delwri queue */ |
| 93 | struct task_struct *bt_task; |
| 94 | struct list_head bt_list; |
| 95 | struct list_head bt_delwrite_queue; |
| 96 | spinlock_t bt_delwrite_lock; |
| 97 | uint bt_flags; |
| 98 | #define BT_FORCE_SLEEP 1 |
| 99 | #define BT_FORCE_FLUSH 2 |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 100 | } xfs_buftarg_t; |
| 101 | |
| 102 | /* |
| 103 | * xfs_buf_t: Buffer structure for page cache-based buffers |
| 104 | * |
| 105 | * This buffer structure is used by the page cache buffer management routines |
| 106 | * to refer to an assembly of pages forming a logical buffer. The actual I/O |
| 107 | * is performed with buffer_head structures, as required by drivers. |
| 108 | * |
| 109 | * The buffer structure is used on temporary basis only, and discarded when |
| 110 | * released. The real data storage is recorded in the page cache. Metadata is |
| 111 | * hashed to the block device on which the file system resides. |
| 112 | */ |
| 113 | |
| 114 | struct xfs_buf; |
| 115 | |
| 116 | /* call-back function on I/O completion */ |
| 117 | typedef void (*page_buf_iodone_t)(struct xfs_buf *); |
| 118 | /* call-back function on I/O completion */ |
| 119 | typedef void (*page_buf_relse_t)(struct xfs_buf *); |
| 120 | /* pre-write function */ |
| 121 | typedef int (*page_buf_bdstrat_t)(struct xfs_buf *); |
| 122 | |
| 123 | #define PB_PAGES 2 |
| 124 | |
| 125 | typedef struct xfs_buf { |
| 126 | struct semaphore pb_sema; /* semaphore for lockables */ |
| 127 | unsigned long pb_queuetime; /* time buffer was queued */ |
| 128 | atomic_t pb_pin_count; /* pin count */ |
| 129 | wait_queue_head_t pb_waiters; /* unpin waiters */ |
| 130 | struct list_head pb_list; |
| 131 | page_buf_flags_t pb_flags; /* status flags */ |
| 132 | struct list_head pb_hash_list; /* hash table list */ |
| 133 | xfs_bufhash_t *pb_hash; /* hash table list start */ |
| 134 | xfs_buftarg_t *pb_target; /* buffer target (device) */ |
| 135 | atomic_t pb_hold; /* reference count */ |
| 136 | xfs_daddr_t pb_bn; /* block number for I/O */ |
| 137 | loff_t pb_file_offset; /* offset in file */ |
| 138 | size_t pb_buffer_length; /* size of buffer in bytes */ |
| 139 | size_t pb_count_desired; /* desired transfer size */ |
| 140 | void *pb_addr; /* virtual address of buffer */ |
| 141 | struct work_struct pb_iodone_work; |
| 142 | atomic_t pb_io_remaining;/* #outstanding I/O requests */ |
| 143 | page_buf_iodone_t pb_iodone; /* I/O completion function */ |
| 144 | page_buf_relse_t pb_relse; /* releasing function */ |
| 145 | page_buf_bdstrat_t pb_strat; /* pre-write function */ |
| 146 | struct semaphore pb_iodonesema; /* Semaphore for I/O waiters */ |
| 147 | void *pb_fspriv; |
| 148 | void *pb_fspriv2; |
| 149 | void *pb_fspriv3; |
| 150 | unsigned short pb_error; /* error code on I/O */ |
| 151 | unsigned short pb_locked; /* page array is locked */ |
| 152 | unsigned int pb_page_count; /* size of page array */ |
| 153 | unsigned int pb_offset; /* page offset in first page */ |
| 154 | struct page **pb_pages; /* array of page pointers */ |
| 155 | struct page *pb_page_array[PB_PAGES]; /* inline pages */ |
| 156 | #ifdef PAGEBUF_LOCK_TRACKING |
| 157 | int pb_last_holder; |
| 158 | #endif |
| 159 | } xfs_buf_t; |
| 160 | |
| 161 | |
| 162 | /* Finding and Reading Buffers */ |
| 163 | |
| 164 | extern xfs_buf_t *_pagebuf_find( /* find buffer for block if */ |
| 165 | /* the block is in memory */ |
| 166 | xfs_buftarg_t *, /* inode for block */ |
| 167 | loff_t, /* starting offset of range */ |
| 168 | size_t, /* length of range */ |
| 169 | page_buf_flags_t, /* PBF_LOCK */ |
| 170 | xfs_buf_t *); /* newly allocated buffer */ |
| 171 | |
| 172 | #define xfs_incore(buftarg,blkno,len,lockit) \ |
| 173 | _pagebuf_find(buftarg, blkno ,len, lockit, NULL) |
| 174 | |
| 175 | extern xfs_buf_t *xfs_buf_get_flags( /* allocate a buffer */ |
| 176 | xfs_buftarg_t *, /* inode for buffer */ |
| 177 | loff_t, /* starting offset of range */ |
| 178 | size_t, /* length of range */ |
| 179 | page_buf_flags_t); /* PBF_LOCK, PBF_READ, */ |
| 180 | /* PBF_ASYNC */ |
| 181 | |
| 182 | #define xfs_buf_get(target, blkno, len, flags) \ |
| 183 | xfs_buf_get_flags((target), (blkno), (len), PBF_LOCK | PBF_MAPPED) |
| 184 | |
| 185 | extern xfs_buf_t *xfs_buf_read_flags( /* allocate and read a buffer */ |
| 186 | xfs_buftarg_t *, /* inode for buffer */ |
| 187 | loff_t, /* starting offset of range */ |
| 188 | size_t, /* length of range */ |
| 189 | page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC */ |
| 190 | |
| 191 | #define xfs_buf_read(target, blkno, len, flags) \ |
| 192 | xfs_buf_read_flags((target), (blkno), (len), PBF_LOCK | PBF_MAPPED) |
| 193 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 194 | extern xfs_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */ |
| 195 | /* no memory or disk address */ |
| 196 | size_t len, |
| 197 | xfs_buftarg_t *); /* mount point "fake" inode */ |
| 198 | |
| 199 | extern xfs_buf_t *pagebuf_get_no_daddr(/* allocate pagebuf struct */ |
| 200 | /* without disk address */ |
| 201 | size_t len, |
| 202 | xfs_buftarg_t *); /* mount point "fake" inode */ |
| 203 | |
| 204 | extern int pagebuf_associate_memory( |
| 205 | xfs_buf_t *, |
| 206 | void *, |
| 207 | size_t); |
| 208 | |
| 209 | extern void pagebuf_hold( /* increment reference count */ |
| 210 | xfs_buf_t *); /* buffer to hold */ |
| 211 | |
| 212 | extern void pagebuf_readahead( /* read ahead into cache */ |
| 213 | xfs_buftarg_t *, /* target for buffer (or NULL) */ |
| 214 | loff_t, /* starting offset of range */ |
| 215 | size_t, /* length of range */ |
| 216 | page_buf_flags_t); /* additional read flags */ |
| 217 | |
| 218 | /* Releasing Buffers */ |
| 219 | |
| 220 | extern void pagebuf_free( /* deallocate a buffer */ |
| 221 | xfs_buf_t *); /* buffer to deallocate */ |
| 222 | |
| 223 | extern void pagebuf_rele( /* release hold on a buffer */ |
| 224 | xfs_buf_t *); /* buffer to release */ |
| 225 | |
| 226 | /* Locking and Unlocking Buffers */ |
| 227 | |
| 228 | extern int pagebuf_cond_lock( /* lock buffer, if not locked */ |
| 229 | /* (returns -EBUSY if locked) */ |
| 230 | xfs_buf_t *); /* buffer to lock */ |
| 231 | |
| 232 | extern int pagebuf_lock_value( /* return count on lock */ |
| 233 | xfs_buf_t *); /* buffer to check */ |
| 234 | |
| 235 | extern int pagebuf_lock( /* lock buffer */ |
| 236 | xfs_buf_t *); /* buffer to lock */ |
| 237 | |
| 238 | extern void pagebuf_unlock( /* unlock buffer */ |
| 239 | xfs_buf_t *); /* buffer to unlock */ |
| 240 | |
| 241 | /* Buffer Read and Write Routines */ |
| 242 | |
| 243 | extern void pagebuf_iodone( /* mark buffer I/O complete */ |
| 244 | xfs_buf_t *, /* buffer to mark */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 245 | int); /* run completion locally, or in |
| 246 | * a helper thread. */ |
| 247 | |
| 248 | extern void pagebuf_ioerror( /* mark buffer in error (or not) */ |
| 249 | xfs_buf_t *, /* buffer to mark */ |
| 250 | int); /* error to store (0 if none) */ |
| 251 | |
| 252 | extern int pagebuf_iostart( /* start I/O on a buffer */ |
| 253 | xfs_buf_t *, /* buffer to start */ |
| 254 | page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC, */ |
| 255 | /* PBF_READ, PBF_WRITE, */ |
| 256 | /* PBF_DELWRI */ |
| 257 | |
| 258 | extern int pagebuf_iorequest( /* start real I/O */ |
| 259 | xfs_buf_t *); /* buffer to convey to device */ |
| 260 | |
| 261 | extern int pagebuf_iowait( /* wait for buffer I/O done */ |
| 262 | xfs_buf_t *); /* buffer to wait on */ |
| 263 | |
| 264 | extern void pagebuf_iomove( /* move data in/out of pagebuf */ |
| 265 | xfs_buf_t *, /* buffer to manipulate */ |
| 266 | size_t, /* starting buffer offset */ |
| 267 | size_t, /* length in buffer */ |
| 268 | caddr_t, /* data pointer */ |
| 269 | page_buf_rw_t); /* direction */ |
| 270 | |
| 271 | static inline int pagebuf_iostrategy(xfs_buf_t *pb) |
| 272 | { |
| 273 | return pb->pb_strat ? pb->pb_strat(pb) : pagebuf_iorequest(pb); |
| 274 | } |
| 275 | |
| 276 | static inline int pagebuf_geterror(xfs_buf_t *pb) |
| 277 | { |
| 278 | return pb ? pb->pb_error : ENOMEM; |
| 279 | } |
| 280 | |
| 281 | /* Buffer Utility Routines */ |
| 282 | |
| 283 | extern caddr_t pagebuf_offset( /* pointer at offset in buffer */ |
| 284 | xfs_buf_t *, /* buffer to offset into */ |
| 285 | size_t); /* offset */ |
| 286 | |
| 287 | /* Pinning Buffer Storage in Memory */ |
| 288 | |
| 289 | extern void pagebuf_pin( /* pin buffer in memory */ |
| 290 | xfs_buf_t *); /* buffer to pin */ |
| 291 | |
| 292 | extern void pagebuf_unpin( /* unpin buffered data */ |
| 293 | xfs_buf_t *); /* buffer to unpin */ |
| 294 | |
| 295 | extern int pagebuf_ispin( /* check if buffer is pinned */ |
| 296 | xfs_buf_t *); /* buffer to check */ |
| 297 | |
| 298 | /* Delayed Write Buffer Routines */ |
| 299 | |
| 300 | extern void pagebuf_delwri_dequeue(xfs_buf_t *); |
| 301 | |
| 302 | /* Buffer Daemon Setup Routines */ |
| 303 | |
| 304 | extern int pagebuf_init(void); |
| 305 | extern void pagebuf_terminate(void); |
| 306 | |
| 307 | |
| 308 | #ifdef PAGEBUF_TRACE |
| 309 | extern ktrace_t *pagebuf_trace_buf; |
| 310 | extern void pagebuf_trace( |
| 311 | xfs_buf_t *, /* buffer being traced */ |
| 312 | char *, /* description of operation */ |
| 313 | void *, /* arbitrary diagnostic value */ |
| 314 | void *); /* return address */ |
| 315 | #else |
| 316 | # define pagebuf_trace(pb, id, ptr, ra) do { } while (0) |
| 317 | #endif |
| 318 | |
| 319 | #define pagebuf_target_name(target) \ |
| 320 | ({ char __b[BDEVNAME_SIZE]; bdevname((target)->pbr_bdev, __b); __b; }) |
| 321 | |
| 322 | |
| 323 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 324 | /* These are just for xfs_syncsub... it sets an internal variable |
| 325 | * then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t |
| 326 | */ |
| 327 | #define XFS_B_ASYNC PBF_ASYNC |
| 328 | #define XFS_B_DELWRI PBF_DELWRI |
| 329 | #define XFS_B_READ PBF_READ |
| 330 | #define XFS_B_WRITE PBF_WRITE |
| 331 | #define XFS_B_STALE PBF_STALE |
| 332 | |
| 333 | #define XFS_BUF_TRYLOCK PBF_TRYLOCK |
| 334 | #define XFS_INCORE_TRYLOCK PBF_TRYLOCK |
| 335 | #define XFS_BUF_LOCK PBF_LOCK |
| 336 | #define XFS_BUF_MAPPED PBF_MAPPED |
| 337 | |
| 338 | #define BUF_BUSY PBF_DONT_BLOCK |
| 339 | |
| 340 | #define XFS_BUF_BFLAGS(x) ((x)->pb_flags) |
| 341 | #define XFS_BUF_ZEROFLAGS(x) \ |
| 342 | ((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_DELWRI)) |
| 343 | |
| 344 | #define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE) |
| 345 | #define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE) |
| 346 | #define XFS_BUF_ISSTALE(x) ((x)->pb_flags & XFS_B_STALE) |
| 347 | #define XFS_BUF_SUPER_STALE(x) do { \ |
| 348 | XFS_BUF_STALE(x); \ |
| 349 | pagebuf_delwri_dequeue(x); \ |
| 350 | XFS_BUF_DONE(x); \ |
| 351 | } while (0) |
| 352 | |
| 353 | #define XFS_BUF_MANAGE PBF_FS_MANAGED |
| 354 | #define XFS_BUF_UNMANAGE(x) ((x)->pb_flags &= ~PBF_FS_MANAGED) |
| 355 | |
| 356 | #define XFS_BUF_DELAYWRITE(x) ((x)->pb_flags |= PBF_DELWRI) |
| 357 | #define XFS_BUF_UNDELAYWRITE(x) pagebuf_delwri_dequeue(x) |
| 358 | #define XFS_BUF_ISDELAYWRITE(x) ((x)->pb_flags & PBF_DELWRI) |
| 359 | |
| 360 | #define XFS_BUF_ERROR(x,no) pagebuf_ioerror(x,no) |
| 361 | #define XFS_BUF_GETERROR(x) pagebuf_geterror(x) |
| 362 | #define XFS_BUF_ISERROR(x) (pagebuf_geterror(x)?1:0) |
| 363 | |
Christoph Hellwig | c86e711 | 2005-11-02 10:29:39 +1100 | [diff] [blame] | 364 | #define XFS_BUF_DONE(x) ((x)->pb_flags |= PBF_DONE) |
| 365 | #define XFS_BUF_UNDONE(x) ((x)->pb_flags &= ~PBF_DONE) |
| 366 | #define XFS_BUF_ISDONE(x) ((x)->pb_flags & PBF_DONE) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 367 | |
Christoph Hellwig | 88741a9 | 2005-11-02 10:21:14 +1100 | [diff] [blame] | 368 | #define XFS_BUF_BUSY(x) do { } while (0) |
| 369 | #define XFS_BUF_UNBUSY(x) do { } while (0) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 370 | #define XFS_BUF_ISBUSY(x) (1) |
| 371 | |
| 372 | #define XFS_BUF_ASYNC(x) ((x)->pb_flags |= PBF_ASYNC) |
| 373 | #define XFS_BUF_UNASYNC(x) ((x)->pb_flags &= ~PBF_ASYNC) |
| 374 | #define XFS_BUF_ISASYNC(x) ((x)->pb_flags & PBF_ASYNC) |
| 375 | |
Christoph Hellwig | f538d4d | 2005-11-02 10:26:59 +1100 | [diff] [blame] | 376 | #define XFS_BUF_ORDERED(x) ((x)->pb_flags |= PBF_ORDERED) |
| 377 | #define XFS_BUF_UNORDERED(x) ((x)->pb_flags &= ~PBF_ORDERED) |
| 378 | #define XFS_BUF_ISORDERED(x) ((x)->pb_flags & PBF_ORDERED) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 379 | |
| 380 | #define XFS_BUF_SHUT(x) printk("XFS_BUF_SHUT not implemented yet\n") |
| 381 | #define XFS_BUF_UNSHUT(x) printk("XFS_BUF_UNSHUT not implemented yet\n") |
| 382 | #define XFS_BUF_ISSHUT(x) (0) |
| 383 | |
| 384 | #define XFS_BUF_HOLD(x) pagebuf_hold(x) |
| 385 | #define XFS_BUF_READ(x) ((x)->pb_flags |= PBF_READ) |
| 386 | #define XFS_BUF_UNREAD(x) ((x)->pb_flags &= ~PBF_READ) |
| 387 | #define XFS_BUF_ISREAD(x) ((x)->pb_flags & PBF_READ) |
| 388 | |
| 389 | #define XFS_BUF_WRITE(x) ((x)->pb_flags |= PBF_WRITE) |
| 390 | #define XFS_BUF_UNWRITE(x) ((x)->pb_flags &= ~PBF_WRITE) |
| 391 | #define XFS_BUF_ISWRITE(x) ((x)->pb_flags & PBF_WRITE) |
| 392 | |
| 393 | #define XFS_BUF_ISUNINITIAL(x) (0) |
| 394 | #define XFS_BUF_UNUNINITIAL(x) (0) |
| 395 | |
| 396 | #define XFS_BUF_BP_ISMAPPED(bp) 1 |
| 397 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 398 | #define XFS_BUF_IODONE_FUNC(buf) (buf)->pb_iodone |
| 399 | #define XFS_BUF_SET_IODONE_FUNC(buf, func) \ |
| 400 | (buf)->pb_iodone = (func) |
| 401 | #define XFS_BUF_CLR_IODONE_FUNC(buf) \ |
| 402 | (buf)->pb_iodone = NULL |
| 403 | #define XFS_BUF_SET_BDSTRAT_FUNC(buf, func) \ |
| 404 | (buf)->pb_strat = (func) |
| 405 | #define XFS_BUF_CLR_BDSTRAT_FUNC(buf) \ |
| 406 | (buf)->pb_strat = NULL |
| 407 | |
| 408 | #define XFS_BUF_FSPRIVATE(buf, type) \ |
| 409 | ((type)(buf)->pb_fspriv) |
| 410 | #define XFS_BUF_SET_FSPRIVATE(buf, value) \ |
| 411 | (buf)->pb_fspriv = (void *)(value) |
| 412 | #define XFS_BUF_FSPRIVATE2(buf, type) \ |
| 413 | ((type)(buf)->pb_fspriv2) |
| 414 | #define XFS_BUF_SET_FSPRIVATE2(buf, value) \ |
| 415 | (buf)->pb_fspriv2 = (void *)(value) |
| 416 | #define XFS_BUF_FSPRIVATE3(buf, type) \ |
| 417 | ((type)(buf)->pb_fspriv3) |
| 418 | #define XFS_BUF_SET_FSPRIVATE3(buf, value) \ |
| 419 | (buf)->pb_fspriv3 = (void *)(value) |
| 420 | #define XFS_BUF_SET_START(buf) |
| 421 | |
| 422 | #define XFS_BUF_SET_BRELSE_FUNC(buf, value) \ |
| 423 | (buf)->pb_relse = (value) |
| 424 | |
| 425 | #define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->pb_addr) |
| 426 | |
Christoph Hellwig | a3c476d | 2005-09-05 08:40:49 +1000 | [diff] [blame] | 427 | static inline xfs_caddr_t xfs_buf_offset(xfs_buf_t *bp, size_t offset) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 428 | { |
| 429 | if (bp->pb_flags & PBF_MAPPED) |
| 430 | return XFS_BUF_PTR(bp) + offset; |
| 431 | return (xfs_caddr_t) pagebuf_offset(bp, offset); |
| 432 | } |
| 433 | |
| 434 | #define XFS_BUF_SET_PTR(bp, val, count) \ |
| 435 | pagebuf_associate_memory(bp, val, count) |
| 436 | #define XFS_BUF_ADDR(bp) ((bp)->pb_bn) |
| 437 | #define XFS_BUF_SET_ADDR(bp, blk) \ |
| 438 | ((bp)->pb_bn = (xfs_daddr_t)(blk)) |
| 439 | #define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset) |
| 440 | #define XFS_BUF_SET_OFFSET(bp, off) \ |
| 441 | ((bp)->pb_file_offset = (off)) |
| 442 | #define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired) |
| 443 | #define XFS_BUF_SET_COUNT(bp, cnt) \ |
| 444 | ((bp)->pb_count_desired = (cnt)) |
| 445 | #define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length) |
| 446 | #define XFS_BUF_SET_SIZE(bp, cnt) \ |
| 447 | ((bp)->pb_buffer_length = (cnt)) |
| 448 | #define XFS_BUF_SET_VTYPE_REF(bp, type, ref) |
| 449 | #define XFS_BUF_SET_VTYPE(bp, type) |
| 450 | #define XFS_BUF_SET_REF(bp, ref) |
| 451 | |
| 452 | #define XFS_BUF_ISPINNED(bp) pagebuf_ispin(bp) |
| 453 | |
| 454 | #define XFS_BUF_VALUSEMA(bp) pagebuf_lock_value(bp) |
| 455 | #define XFS_BUF_CPSEMA(bp) (pagebuf_cond_lock(bp) == 0) |
| 456 | #define XFS_BUF_VSEMA(bp) pagebuf_unlock(bp) |
| 457 | #define XFS_BUF_PSEMA(bp,x) pagebuf_lock(bp) |
| 458 | #define XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iodonesema); |
| 459 | |
| 460 | /* setup the buffer target from a buftarg structure */ |
| 461 | #define XFS_BUF_SET_TARGET(bp, target) \ |
| 462 | (bp)->pb_target = (target) |
| 463 | #define XFS_BUF_TARGET(bp) ((bp)->pb_target) |
| 464 | #define XFS_BUFTARG_NAME(target) \ |
| 465 | pagebuf_target_name(target) |
| 466 | |
| 467 | #define XFS_BUF_SET_VTYPE_REF(bp, type, ref) |
| 468 | #define XFS_BUF_SET_VTYPE(bp, type) |
| 469 | #define XFS_BUF_SET_REF(bp, ref) |
| 470 | |
| 471 | static inline int xfs_bawrite(void *mp, xfs_buf_t *bp) |
| 472 | { |
| 473 | bp->pb_fspriv3 = mp; |
| 474 | bp->pb_strat = xfs_bdstrat_cb; |
| 475 | pagebuf_delwri_dequeue(bp); |
| 476 | return pagebuf_iostart(bp, PBF_WRITE | PBF_ASYNC | _PBF_RUN_QUEUES); |
| 477 | } |
| 478 | |
| 479 | static inline void xfs_buf_relse(xfs_buf_t *bp) |
| 480 | { |
| 481 | if (!bp->pb_relse) |
| 482 | pagebuf_unlock(bp); |
| 483 | pagebuf_rele(bp); |
| 484 | } |
| 485 | |
| 486 | #define xfs_bpin(bp) pagebuf_pin(bp) |
| 487 | #define xfs_bunpin(bp) pagebuf_unpin(bp) |
| 488 | |
| 489 | #define xfs_buftrace(id, bp) \ |
| 490 | pagebuf_trace(bp, id, NULL, (void *)__builtin_return_address(0)) |
| 491 | |
| 492 | #define xfs_biodone(pb) \ |
Christoph Hellwig | 88741a9 | 2005-11-02 10:21:14 +1100 | [diff] [blame] | 493 | pagebuf_iodone(pb, 0) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 494 | |
| 495 | #define xfs_biomove(pb, off, len, data, rw) \ |
| 496 | pagebuf_iomove((pb), (off), (len), (data), \ |
| 497 | ((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ) |
| 498 | |
| 499 | #define xfs_biozero(pb, off, len) \ |
| 500 | pagebuf_iomove((pb), (off), (len), NULL, PBRW_ZERO) |
| 501 | |
| 502 | |
| 503 | static inline int XFS_bwrite(xfs_buf_t *pb) |
| 504 | { |
| 505 | int iowait = (pb->pb_flags & PBF_ASYNC) == 0; |
| 506 | int error = 0; |
| 507 | |
| 508 | if (!iowait) |
| 509 | pb->pb_flags |= _PBF_RUN_QUEUES; |
| 510 | |
| 511 | pagebuf_delwri_dequeue(pb); |
| 512 | pagebuf_iostrategy(pb); |
| 513 | if (iowait) { |
| 514 | error = pagebuf_iowait(pb); |
| 515 | xfs_buf_relse(pb); |
| 516 | } |
| 517 | return error; |
| 518 | } |
| 519 | |
| 520 | #define XFS_bdwrite(pb) \ |
| 521 | pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC) |
| 522 | |
| 523 | static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp) |
| 524 | { |
| 525 | bp->pb_strat = xfs_bdstrat_cb; |
| 526 | bp->pb_fspriv3 = mp; |
| 527 | |
| 528 | return pagebuf_iostart(bp, PBF_DELWRI | PBF_ASYNC); |
| 529 | } |
| 530 | |
| 531 | #define XFS_bdstrat(bp) pagebuf_iorequest(bp) |
| 532 | |
| 533 | #define xfs_iowait(pb) pagebuf_iowait(pb) |
| 534 | |
| 535 | #define xfs_baread(target, rablkno, ralen) \ |
| 536 | pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK) |
| 537 | |
| 538 | #define xfs_buf_get_empty(len, target) pagebuf_get_empty((len), (target)) |
| 539 | #define xfs_buf_get_noaddr(len, target) pagebuf_get_no_daddr((len), (target)) |
| 540 | #define xfs_buf_free(bp) pagebuf_free(bp) |
| 541 | |
| 542 | |
| 543 | /* |
| 544 | * Handling of buftargs. |
| 545 | */ |
| 546 | |
| 547 | extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int); |
| 548 | extern void xfs_free_buftarg(xfs_buftarg_t *, int); |
| 549 | extern void xfs_wait_buftarg(xfs_buftarg_t *); |
| 550 | extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 551 | extern int xfs_flush_buftarg(xfs_buftarg_t *, int); |
| 552 | |
| 553 | #define xfs_getsize_buftarg(buftarg) \ |
| 554 | block_size((buftarg)->pbr_bdev) |
| 555 | #define xfs_readonly_buftarg(buftarg) \ |
| 556 | bdev_read_only((buftarg)->pbr_bdev) |
| 557 | #define xfs_binval(buftarg) \ |
| 558 | xfs_flush_buftarg(buftarg, 1) |
| 559 | #define XFS_bflush(buftarg) \ |
| 560 | xfs_flush_buftarg(buftarg, 1) |
| 561 | |
| 562 | #endif /* __XFS_BUF_H__ */ |