kernel - Enhance getcacheblk() (improve saturated write performance (3)).
[dragonfly.git] / sys / sys / buf.h
index c08afba..c09f235 100644 (file)
@@ -74,7 +74,7 @@ struct mount;
 struct vnode;
 struct xio;
 
-#define NBUF_BIO       4
+#define NBUF_BIO       6
 
 struct buf_rb_tree;
 struct buf_rb_hash;
@@ -162,8 +162,10 @@ struct buf {
        struct bio b_bio_array[NBUF_BIO]; /* BIO translation layers */ 
        u_int32_t b_flags;              /* B_* flags. */
        unsigned short b_qindex;        /* buffer queue index */
-       unsigned short b_unused01;
+       unsigned char b_act_count;      /* similar to vm_page act_count */
+       unsigned char b_unused01;
        struct lock b_lock;             /* Buffer lock */
+       void    *b_iosched;             /* I/O scheduler priv data */
        buf_cmd_t b_cmd;                /* I/O command */
        int     b_bufsize;              /* Allocated buffer size. */
        int     b_runningbufspace;      /* when I/O is running, pipelining */
@@ -175,6 +177,7 @@ struct buf {
        int     b_kvasize;              /* size of kva for buffer */
        int     b_dirtyoff;             /* Offset in buffer of dirty region. */
        int     b_dirtyend;             /* Offset of end of dirty region. */
+       int     b_refs;                 /* FINDBLK_REF / unrefblk() */
        struct  xio b_xio;              /* data buffer page list management */
        struct  bio_ops *b_ops;         /* bio_ops used w/ b_dep */
        struct  workhead b_dep;         /* List of filesystem dependencies. */
@@ -209,17 +212,13 @@ struct buf {
 
 #define FINDBLK_TEST   0x0010  /* test only, do not lock */
 #define FINDBLK_NBLOCK 0x0020  /* use non-blocking lock, can return NULL */
+#define FINDBLK_REF    0x0040  /* ref the buf to prevent reuse */
 
 /*
  * These flags are kept in b_flags.
  *
  * Notes:
  *
- *     B_ASYNC         VOP calls on bp's are usually async whether or not
- *                     B_ASYNC is set, but some subsystems, such as NFS, like 
- *                     to know what is best for the caller so they can
- *                     optimize the I/O.
- *
  *     B_PAGING        Indicates that bp is being used by the paging system or
  *                     some paging system and that the bp is not linked into
  *                     the b_vp's clean/dirty linked lists or ref counts.
@@ -279,32 +278,38 @@ struct buf {
  *     B_NOCACHE       Request that the buffer and backing store be
  *                     destroyed on completion.  If B_DELWRI is set and the
  *                     write fails, the buffer remains intact.
+ *
+ *     B_NOTMETA       May be set on block device buffers representing
+ *                     file data (i.e. which aren't really meta-data),
+ *                     which will cause the buffer cache to set PG_NOTMETA
+ *                     in the VM pages when releasing them and the
+ *                     swapcache to not try to cache them.
  */
 
 #define        B_AGE           0x00000001      /* Reuse more quickly */
 #define        B_NEEDCOMMIT    0x00000002      /* Append-write in progress. */
-#define        B_ASYNC         0x00000004      /* Start I/O, do not wait. */
+#define        B_NOTMETA       0x00000004      /* This really isn't metadata */
 #define        B_DIRECT        0x00000008      /* direct I/O flag (pls free vmio) */
 #define        B_DEFERRED      0x00000010      /* vfs-controlled deferment */
 #define        B_CACHE         0x00000020      /* Bread found us in the cache. */
 #define        B_HASHED        0x00000040      /* Indexed via v_rbhash_tree */
 #define        B_DELWRI        0x00000080      /* Delay I/O until buffer reused. */
 #define        B_BNOCLIP       0x00000100      /* EOF clipping b_bcount not allowed */
-#define        B_UNUSED0200    0x00000200
+#define        B_HASBOGUS      0x00000200      /* Contains bogus pages */
 #define        B_EINTR         0x00000400      /* I/O was interrupted */
 #define        B_ERROR         0x00000800      /* I/O error occurred. */
-#define        B_UNUSED1000    0x00001000      /* Unused */
+#define        B_IODEBUG       0x00001000      /* (Debugging only bread) */
 #define        B_INVAL         0x00002000      /* Does not contain valid info. */
 #define        B_LOCKED        0x00004000      /* Locked in core (not reusable). */
 #define        B_NOCACHE       0x00008000      /* Destroy buffer AND backing store */
 #define        B_MALLOC        0x00010000      /* malloced b_data */
 #define        B_CLUSTEROK     0x00020000      /* Pagein op, so swap() can count it. */
-#define        B_UNUSED40000   0x00040000
+#define        B_UNUSED18      0x00040000
 #define        B_RAW           0x00080000      /* Set by physio for raw transfers. */
 #define        B_HEAVY         0x00100000      /* Heavy-weight buffer */
 #define        B_DIRTY         0x00200000      /* Needs writing later. */
 #define        B_RELBUF        0x00400000      /* Release VMIO buffer. */
-#define        B_WANT          0x00800000      /* Used by vm_pager.c */
+#define        B_UNUSED23      0x00800000      /* Request wakeup on done */
 #define        B_VNCLEAN       0x01000000      /* On vnode clean list */
 #define        B_VNDIRTY       0x02000000      /* On vnode dirty list */
 #define        B_PAGING        0x04000000      /* volatile paging I/O -- bypass VMIO */
@@ -312,14 +317,14 @@ struct buf {
 #define B_RAM          0x10000000      /* Read ahead mark (flag) */
 #define B_VMIO         0x20000000      /* VMIO flag */
 #define B_CLUSTER      0x40000000      /* pagein op, so swap() can count it */
-#define B_UNUSED80000000 0x80000000
+#define B_VFSFLAG1     0x80000000      /* VFSs can set this flag */
 
 #define PRINT_BUF_FLAGS "\20"  \
        "\40unused31\37cluster\36vmio\35ram\34ordered" \
-       "\33paging\32vndirty\31vnclean\30want\27relbuf\26dirty" \
+       "\33paging\32vndirty\31vnclean\30unused23\27relbuf\26dirty" \
        "\25unused20\24raw\23unused18\22clusterok\21malloc\20nocache" \
        "\17locked\16inval\15unused12\14error\13eintr\12unused9\11bnoclip" \
-       "\10delwri\7hashed\6cache\5deferred\4direct\3async\2needcommit\1age"
+       "\10delwri\7hashed\6cache\5deferred\4direct\3unused2\2needcommit\1age"
 
 #define        NOOFFSET        (-1LL)          /* No buffer offset calculated yet */
 
@@ -334,9 +339,10 @@ extern char *buf_wmesg;                    /* Default buffer lock message */
 
 struct bio_queue_head {
        TAILQ_HEAD(bio_queue, bio) queue;
-       off_t   last_offset;
-       struct  bio *insert_point;
-       struct  bio *switch_point;
+       off_t   off_unused;
+       int     reorder;
+       struct  bio *transition;
+       struct  bio *bio_unused;
 };
 
 /*
@@ -369,10 +375,8 @@ struct cluster_save {
 
 #ifdef _KERNEL
 extern int     nbuf;                   /* The number of buffer headers */
-extern int     maxswzone;              /* Max KVA for swap structures */
-extern int     maxbcache;              /* Max KVA for buffer cache */
-extern int     runningbufspace;
-extern int     runningbufcount;
+extern long    maxswzone;              /* Max KVA for swap structures */
+extern long    maxbcache;              /* Max KVA for buffer cache */
 extern int     hidirtybufspace;
 extern int      buf_maxio;              /* nominal maximum I/O for buffer */
 extern struct buf *buf;                        /* The buffer headers. */
@@ -380,14 +384,22 @@ extern char       *buffers;               /* The buffer contents. */
 extern int     bufpages;               /* Number of memory pages in the buffer pool. */
 extern struct  buf *swbuf;             /* Swap I/O buffer headers. */
 extern int     nswbuf;                 /* Number of swap I/O buffer headers. */
+extern int     bioq_reorder_burst_interval;
+extern int     bioq_reorder_burst_bytes;
+extern int     bioq_reorder_minor_interval;
+extern int     bioq_reorder_minor_bytes;
 
 struct uio;
+struct devstat;
 
 void   bufinit (void);
 int    bd_heatup (void);
 void   bd_wait (int count);
+void   waitrunningbufspace(void);
 int    buf_dirty_count_severe (void);
+int    buf_runningbufspace_severe (void);
 void   initbufbio(struct buf *);
+void   uninitbufbio(struct buf *);
 void   reinitbufbio(struct buf *);
 void   clearbiocache(struct bio *);
 void   bremfree (struct buf *);
@@ -396,6 +408,7 @@ int breadn (struct vnode *, off_t, int, off_t *, int *, int,
            struct buf **);
 int    bwrite (struct buf *);
 void   bdwrite (struct buf *);
+void   buwrite (struct buf *);
 void   bawrite (struct buf *);
 void   bdirty (struct buf *);
 void   bheavy (struct buf *);
@@ -405,25 +418,29 @@ void      brelse (struct buf *);
 void   bqrelse (struct buf *);
 int    vfs_bio_awrite (struct buf *);
 struct buf *getpbuf (int *);
+struct buf *getpbuf_kva (int *);
 int    inmem (struct vnode *, off_t);
 struct buf *findblk (struct vnode *, off_t, int);
 struct buf *getblk (struct vnode *, off_t, int, int, int);
-struct buf *getcacheblk (struct vnode *, off_t);
+struct buf *getcacheblk (struct vnode *, off_t, int);
 struct buf *geteblk (int);
+void unrefblk(struct buf *bp);
 void regetblk(struct buf *bp);
 struct bio *push_bio(struct bio *);
 struct bio *pop_bio(struct bio *);
-int    biowait (struct buf *);
+int    biowait (struct bio *, const char *);
+int    biowait_timeout (struct bio *, const char *, int);
+void   bpdone (struct buf *, int);
 void   biodone (struct bio *);
+void   biodone_sync (struct bio *);
 
 void   cluster_append(struct bio *, struct buf *);
 int    cluster_read (struct vnode *, off_t, off_t, int,
-           int, int, struct buf **);
+           size_t, size_t, struct buf **);
 int    cluster_wbuild (struct vnode *, int, off_t, int);
 void   cluster_write (struct buf *, off_t, int, int);
 int    physread (struct dev_read_args *);
 int    physwrite (struct dev_write_args *);
-void   vfs_bio_set_validclean (struct buf *, int base, int size);
 void   vfs_bio_clrbuf (struct buf *);
 void   vfs_busy_pages (struct vnode *, struct buf *);
 void   vfs_unbusy_pages (struct buf *);
@@ -431,15 +448,21 @@ int       vmapbuf (struct buf *, caddr_t, int);
 void   vunmapbuf (struct buf *);
 void   relpbuf (struct buf *, int *);
 void   brelvp (struct buf *);
-int    bgetvp (struct vnode *, struct buf *);
+int    bgetvp (struct vnode *, struct buf *, int);
+void   bsetrunningbufspace(struct buf *, int);
 int    allocbuf (struct buf *bp, int size);
 int    scan_all_buffers (int (*)(struct buf *, void *), void *);
 void   reassignbuf (struct buf *);
 struct buf *trypbuf (int *);
+struct buf *trypbuf_kva (int *);
 void   bio_ops_sync(struct mount *mp);
 void   vm_hold_free_pages(struct buf *bp, vm_offset_t from, vm_offset_t to);
 void   vm_hold_load_pages(struct buf *bp, vm_offset_t from, vm_offset_t to);
-
+void   nestiobuf_done(struct bio *mbio, int donebytes, int error, struct devstat *stats);
+void   nestiobuf_init(struct bio *mbio);
+void   nestiobuf_add(struct bio *mbio, struct buf *bp, int off, size_t size, struct devstat *stats);
+void   nestiobuf_start(struct bio *mbio);
+void   nestiobuf_error(struct bio *mbio, int error);
 #endif /* _KERNEL */
 #endif /* _KERNEL || _KERNEL_STRUCTURES */
 #endif /* !_SYS_BUF_H_ */