mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
zfetch: Don't issue new streams when old have not completed
The current dmu_zfetch code implicitly assumes that I/Os complete within min_sec_reap seconds. With async dmu and a readonly workload (and thus no exponential backoff in operations from the "write throttle") such as L2ARC rebuild it is possible to saturate the drives with I/O requests. These are then effectively compounded with prefetch requests. This change reference counts streams and prevents them from being recycled after their min_sec_reap timeout if they still have outstanding I/Os. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Matt Macy <mmacy@FreeBSD.org> Closes #10900
This commit is contained in:
+6
-1
@@ -309,6 +309,8 @@ typedef struct dbuf_hash_table {
|
||||
kmutex_t hash_mutexes[DBUF_MUTEXES];
|
||||
} dbuf_hash_table_t;
|
||||
|
||||
typedef void (*dbuf_prefetch_fn)(void *, boolean_t);
|
||||
|
||||
uint64_t dbuf_whichblock(const struct dnode *di, const int64_t level,
|
||||
const uint64_t offset);
|
||||
|
||||
@@ -324,7 +326,10 @@ int dbuf_hold_impl(struct dnode *dn, uint8_t level, uint64_t blkid,
|
||||
boolean_t fail_sparse, boolean_t fail_uncached,
|
||||
void *tag, dmu_buf_impl_t **dbp);
|
||||
|
||||
void dbuf_prefetch(struct dnode *dn, int64_t level, uint64_t blkid,
|
||||
int dbuf_prefetch_impl(struct dnode *dn, int64_t level, uint64_t blkid,
|
||||
zio_priority_t prio, arc_flags_t aflags, dbuf_prefetch_fn cb,
|
||||
void *arg);
|
||||
int dbuf_prefetch(struct dnode *dn, int64_t level, uint64_t blkid,
|
||||
zio_priority_t prio, arc_flags_t aflags);
|
||||
|
||||
void dbuf_add_ref(dmu_buf_impl_t *db, void *tag);
|
||||
|
||||
@@ -40,6 +40,13 @@ extern unsigned long zfetch_array_rd_sz;
|
||||
|
||||
struct dnode; /* so we can reference dnode */
|
||||
|
||||
typedef struct zfetch {
|
||||
kmutex_t zf_lock; /* protects zfetch structure */
|
||||
list_t zf_stream; /* list of zstream_t's */
|
||||
struct dnode *zf_dnode; /* dnode that owns this zfetch */
|
||||
int zf_numstreams; /* number of zstream_t's */
|
||||
} zfetch_t;
|
||||
|
||||
typedef struct zstream {
|
||||
uint64_t zs_blkid; /* expect next access at this blkid */
|
||||
uint64_t zs_pf_blkid; /* next block to prefetch */
|
||||
@@ -52,15 +59,12 @@ typedef struct zstream {
|
||||
|
||||
kmutex_t zs_lock; /* protects stream */
|
||||
hrtime_t zs_atime; /* time last prefetch issued */
|
||||
hrtime_t zs_start_time; /* start of last prefetch */
|
||||
list_node_t zs_node; /* link for zf_stream */
|
||||
zfetch_t *zs_fetch; /* parent fetch */
|
||||
zfs_refcount_t zs_blocks; /* number of pending blocks in the stream */
|
||||
} zstream_t;
|
||||
|
||||
typedef struct zfetch {
|
||||
kmutex_t zf_lock; /* protects zfetch structure */
|
||||
list_t zf_stream; /* list of zstream_t's */
|
||||
struct dnode *zf_dnode; /* dnode that owns this zfetch */
|
||||
} zfetch_t;
|
||||
|
||||
void zfetch_init(void);
|
||||
void zfetch_fini(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user