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