* refs/heads/tmp-719bdd9: Linux 4.9.180 drm: Wake up next in drm_read() chain if we are forced to putback the event ASoC: davinci-mcasp: Fix clang warning without CONFIG_PM spi: Fix zero length xfer bug spi: rspi: Fix sequencer reset during initialization spi : spi-topcliff-pch: Fix to handle empty DMA buffers scsi: lpfc: Fix SLI3 commands being issued on SLI4 devices media: saa7146: avoid high stack usage with clang scsi: lpfc: Fix FDMI manufacturer attribute value media: go7007: avoid clang frame overflow warning with KASAN media: m88ds3103: serialize reset messages in m88ds3103_set_frontend dmaengine: tegra210-adma: use devm_clk_*() helpers scsi: qla4xxx: avoid freeing unallocated dma memory usb: core: Add PM runtime calls to usb_hcd_platform_shutdown rcuperf: Fix cleanup path for invalid perf_type strings rcutorture: Fix cleanup path for invalid torture_type strings x86/mce: Fix machine_check_poll() tests for error types tty: ipwireless: fix missing checks for ioremap virtio_console: initialize vtermno value for ports media: wl128x: prevent two potential buffer overflows spi: tegra114: reset controller on probe cxgb3/l2t: Fix undefined behaviour ASoC: fsl_utils: fix a leaked reference by adding missing of_node_put ASoC: eukrea-tlv320: fix a leaked reference by adding missing of_node_put HID: core: move Usage Page concatenation to Main item chardev: add additional check for minor range overlap x86/ia32: Fix ia32_restore_sigcontext() AC leak x86/uaccess, signal: Fix AC=1 bloat arm64: cpu_ops: fix a leaked reference by adding missing of_node_put scsi: ufs: Avoid configuring regulator with undefined voltage range scsi: ufs: Fix regulator load and icc-level configuration brcmfmac: fix Oops when bringing up interface during USB disconnect brcmfmac: fix race during disconnect when USB completion is in progress brcmfmac: convert dev_init_lock mutex to completion b43: shut up clang -Wuninitialized variable warning brcmfmac: fix missing checks for kmemdup mwifiex: Fix mem leak in mwifiex_tm_cmd rtlwifi: fix a potential NULL pointer dereference iio: common: ssp_sensors: Initialize calculated_time in ssp_common_process_data iio: hmc5843: fix potential NULL pointer dereferences iio: ad_sigma_delta: Properly handle SPI bus locking vs CS assertion x86/build: Keep local relocations with ld.lld cpufreq: pmac32: fix possible object reference leak cpufreq/pasemi: fix possible object reference leak cpufreq: ppc_cbe: fix possible object reference leak s390: cio: fix cio_irb declaration extcon: arizona: Disable mic detect if running when driver is removed PM / core: Propagate dev->power.wakeup_path when no callbacks mmc: sdhci-of-esdhc: add erratum eSDHC-A001 and A-008358 support mmc: sdhci-of-esdhc: add erratum eSDHC5 support mmc_spi: add a status check for spi_sync_locked mmc: core: make pwrseq_emmc (partially) support sleepy GPIO controllers scsi: libsas: Do discovery on empty PHY to update PHY info hwmon: (f71805f) Use request_muxed_region for Super-IO accesses hwmon: (pc87427) Use request_muxed_region for Super-IO accesses hwmon: (smsc47b397) Use request_muxed_region for Super-IO accesses hwmon: (smsc47m1) Use request_muxed_region for Super-IO accesses hwmon: (vt1211) Use request_muxed_region for Super-IO accesses RDMA/cxgb4: Fix null pointer dereference on alloc_skb failure arm64: vdso: Fix clock_getres() for CLOCK_REALTIME i40e: don't allow changes to HW VLAN stripping on active port VLANs x86/irq/64: Limit IST stack overflow check to #DB stack USB: core: Don't unbind interfaces following device reset failure sched/core: Handle overflow in cpu_shares_write_u64 sched/core: Check quota and period overflow at usec to nsec conversion powerpc/numa: improve control of topology updates media: pvrusb2: Prevent a buffer overflow media: au0828: Fix NULL pointer dereference in au0828_analog_stream_enable() audit: fix a memory leak bug media: ov2659: make S_FMT succeed even if requested format doesn't match media: au0828: stop video streaming only when last user stops media: ov6650: Move v4l2_clk_get() to ov6650_video_probe() helper media: coda: clear error return value before picture run dmaengine: at_xdmac: remove BUG_ON macro in tasklet pinctrl: pistachio: fix leaked of_node references HID: logitech-hidpp: use RAP instead of FAP to get the protocol version mm/uaccess: Use 'unsigned long' to placate UBSAN warnings on older GCC versions x86/mm: Remove in_nmi() warning from 64-bit implementation of vmalloc_fault() smpboot: Place the __percpu annotation correctly x86/build: Move _etext to actual end of .text bcache: avoid clang -Wunintialized warning bcache: add failure check to run_cache_set() for journal replay bcache: fix failure in journal relplay bcache: return error immediately in bch_journal_replay() crypto: sun4i-ss - Fix invalid calculation of hash end net: cw1200: fix a NULL pointer dereference mwifiex: prevent an array overflow ASoC: fsl_sai: Update is_slave_mode with correct value mac80211/cfg80211: update bss channel on channel switch dmaengine: pl330: _stop: clear interrupt status w1: fix the resume command API rtc: 88pm860x: prevent use-after-free on device remove iwlwifi: pcie: don't crash on invalid RX interrupt scsi: qla2xxx: Fix a qla24xx_enable_msix() error path sched/cpufreq: Fix kobject memleak arm64: Fix compiler warning from pte_unmap() with -Wunused-but-set-variable ARM: vdso: Remove dependency with the arch_timer driver internals brcm80211: potential NULL dereference in brcmf_cfg80211_vndr_cmds_dcmd_handler() spi: pxa2xx: fix SCR (divisor) calculation ASoC: imx: fix fiq dependencies powerpc/boot: Fix missing check of lseek() return value ASoC: hdmi-codec: unlock the device on startup errors net: ena: gcc 8: fix compilation warning dmaengine: tegra210-dma: free dma controller in remove() mmc: core: Verify SD bus width cxgb4: Fix error path in cxgb4_init_module gfs2: Fix lru_count going negative Revert "btrfs: Honour FITRIM range constraints during free space trim" tools include: Adopt linux/bits.h perf tools: No need to include bitops.h in util.h at76c50x-usb: Don't register led_trigger if usb_register_driver failed ssb: Fix possible NULL pointer dereference in ssb_host_pcmcia_exit media: vivid: use vfree() instead of kfree() for dev->bitmap_cap media: cpia2: Fix use-after-free in cpia2_exit fbdev: fix WARNING in __alloc_pages_nodemask bug hugetlb: use same fault hash key for shared and private mappings fbdev: fix divide error in fb_var_to_videomode btrfs: sysfs: don't leak memory when failing add fsid Btrfs: fix race between ranged fsync and writeback of adjacent ranges Btrfs: do not abort transaction at btrfs_update_root() after failure to COW path gfs2: Fix sign extension bug in gfs2_update_stats arm64: Save and restore OSDLR_EL1 across suspend/resume libnvdimm/namespace: Fix label tracking error kvm: svm/avic: fix off-by-one in checking host APIC ID crypto: vmx - CTR: always increment IV as quadword Revert "scsi: sd: Keep disk read-only when re-reading partition" bio: fix improper use of smp_mb__before_atomic() KVM: x86: fix return value for reserved EFER ext4: do not delete unlinked inode from orphan list on failed truncate f2fs: link f2fs quota ops for sysfile Change-Id: Ief4e371f7f2377222f54fea237408c8bd5dda548 Signed-off-by: jianzhou <jianzhou@codeaurora.org>
814 lines
20 KiB
C
814 lines
20 KiB
C
/*
|
|
* Copyright (C) 2001 Jens Axboe <axboe@suse.de>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
*
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public Licens
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
|
|
*/
|
|
#ifndef __LINUX_BIO_H
|
|
#define __LINUX_BIO_H
|
|
|
|
#include <linux/highmem.h>
|
|
#include <linux/mempool.h>
|
|
#include <linux/ioprio.h>
|
|
#include <linux/bug.h>
|
|
|
|
#ifdef CONFIG_BLOCK
|
|
|
|
#include <asm/io.h>
|
|
|
|
/* struct bio, bio_vec and BIO_* flags are defined in blk_types.h */
|
|
#include <linux/blk_types.h>
|
|
|
|
#define BIO_DEBUG
|
|
|
|
#ifdef BIO_DEBUG
|
|
#define BIO_BUG_ON BUG_ON
|
|
#else
|
|
#define BIO_BUG_ON
|
|
#endif
|
|
|
|
#define BIO_MAX_PAGES 256
|
|
|
|
#define bio_prio(bio) (bio)->bi_ioprio
|
|
#define bio_set_prio(bio, prio) ((bio)->bi_ioprio = prio)
|
|
|
|
#define bio_iter_iovec(bio, iter) \
|
|
bvec_iter_bvec((bio)->bi_io_vec, (iter))
|
|
|
|
#define bio_iter_page(bio, iter) \
|
|
bvec_iter_page((bio)->bi_io_vec, (iter))
|
|
#define bio_iter_len(bio, iter) \
|
|
bvec_iter_len((bio)->bi_io_vec, (iter))
|
|
#define bio_iter_offset(bio, iter) \
|
|
bvec_iter_offset((bio)->bi_io_vec, (iter))
|
|
|
|
#define bio_page(bio) bio_iter_page((bio), (bio)->bi_iter)
|
|
#define bio_offset(bio) bio_iter_offset((bio), (bio)->bi_iter)
|
|
#define bio_iovec(bio) bio_iter_iovec((bio), (bio)->bi_iter)
|
|
|
|
#define bio_multiple_segments(bio) \
|
|
((bio)->bi_iter.bi_size != bio_iovec(bio).bv_len)
|
|
#define bio_sectors(bio) ((bio)->bi_iter.bi_size >> 9)
|
|
#define bio_end_sector(bio) ((bio)->bi_iter.bi_sector + bio_sectors((bio)))
|
|
#define bio_dun(bio) ((bio)->bi_iter.bi_dun)
|
|
#define bio_duns(bio) (bio_sectors(bio) >> 3) /* 4KB unit */
|
|
#define bio_end_dun(bio) (bio_dun(bio) + bio_duns(bio))
|
|
|
|
/*
|
|
* Check whether this bio carries any data or not. A NULL bio is allowed.
|
|
*/
|
|
static inline bool bio_has_data(struct bio *bio)
|
|
{
|
|
if (bio &&
|
|
bio->bi_iter.bi_size &&
|
|
bio_op(bio) != REQ_OP_DISCARD &&
|
|
bio_op(bio) != REQ_OP_SECURE_ERASE)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
static inline bool bio_no_advance_iter(struct bio *bio)
|
|
{
|
|
return bio_op(bio) == REQ_OP_DISCARD ||
|
|
bio_op(bio) == REQ_OP_SECURE_ERASE ||
|
|
bio_op(bio) == REQ_OP_WRITE_SAME;
|
|
}
|
|
|
|
static inline bool bio_is_rw(struct bio *bio)
|
|
{
|
|
if (!bio_has_data(bio))
|
|
return false;
|
|
|
|
if (bio_no_advance_iter(bio))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline bool bio_mergeable(struct bio *bio)
|
|
{
|
|
if (bio->bi_opf & REQ_NOMERGE_FLAGS)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline unsigned int bio_cur_bytes(struct bio *bio)
|
|
{
|
|
if (bio_has_data(bio))
|
|
return bio_iovec(bio).bv_len;
|
|
else /* dataless requests such as discard */
|
|
return bio->bi_iter.bi_size;
|
|
}
|
|
|
|
static inline void *bio_data(struct bio *bio)
|
|
{
|
|
if (bio_has_data(bio))
|
|
return page_address(bio_page(bio)) + bio_offset(bio);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* will die
|
|
*/
|
|
#define bio_to_phys(bio) (page_to_phys(bio_page((bio))) + (unsigned long) bio_offset((bio)))
|
|
#define bvec_to_phys(bv) (page_to_phys((bv)->bv_page) + (unsigned long) (bv)->bv_offset)
|
|
|
|
/*
|
|
* queues that have highmem support enabled may still need to revert to
|
|
* PIO transfers occasionally and thus map high pages temporarily. For
|
|
* permanent PIO fall back, user is probably better off disabling highmem
|
|
* I/O completely on that queue (see ide-dma for example)
|
|
*/
|
|
#define __bio_kmap_atomic(bio, iter) \
|
|
(kmap_atomic(bio_iter_iovec((bio), (iter)).bv_page) + \
|
|
bio_iter_iovec((bio), (iter)).bv_offset)
|
|
|
|
#define __bio_kunmap_atomic(addr) kunmap_atomic(addr)
|
|
|
|
/*
|
|
* merge helpers etc
|
|
*/
|
|
|
|
/* Default implementation of BIOVEC_PHYS_MERGEABLE */
|
|
#define __BIOVEC_PHYS_MERGEABLE(vec1, vec2) \
|
|
((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
|
|
|
|
/*
|
|
* allow arch override, for eg virtualized architectures (put in asm/io.h)
|
|
*/
|
|
#ifndef BIOVEC_PHYS_MERGEABLE
|
|
#define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \
|
|
__BIOVEC_PHYS_MERGEABLE(vec1, vec2)
|
|
#endif
|
|
|
|
#define __BIO_SEG_BOUNDARY(addr1, addr2, mask) \
|
|
(((addr1) | (mask)) == (((addr2) - 1) | (mask)))
|
|
#define BIOVEC_SEG_BOUNDARY(q, b1, b2) \
|
|
__BIO_SEG_BOUNDARY(bvec_to_phys((b1)), bvec_to_phys((b2)) + (b2)->bv_len, queue_segment_boundary((q)))
|
|
|
|
/*
|
|
* drivers should _never_ use the all version - the bio may have been split
|
|
* before it got to the driver and the driver won't own all of it
|
|
*/
|
|
#define bio_for_each_segment_all(bvl, bio, i) \
|
|
for (i = 0, bvl = (bio)->bi_io_vec; i < (bio)->bi_vcnt; i++, bvl++)
|
|
|
|
static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
|
|
unsigned bytes)
|
|
{
|
|
iter->bi_sector += bytes >> 9;
|
|
|
|
#ifdef CONFIG_PFK
|
|
if (iter->bi_dun)
|
|
iter->bi_dun += bytes >> 12;
|
|
#endif
|
|
|
|
if (bio_no_advance_iter(bio))
|
|
iter->bi_size -= bytes;
|
|
else
|
|
bvec_iter_advance(bio->bi_io_vec, iter, bytes);
|
|
}
|
|
|
|
#define __bio_for_each_segment(bvl, bio, iter, start) \
|
|
for (iter = (start); \
|
|
(iter).bi_size && \
|
|
((bvl = bio_iter_iovec((bio), (iter))), 1); \
|
|
bio_advance_iter((bio), &(iter), (bvl).bv_len))
|
|
|
|
#define bio_for_each_segment(bvl, bio, iter) \
|
|
__bio_for_each_segment(bvl, bio, iter, (bio)->bi_iter)
|
|
|
|
#define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len)
|
|
|
|
static inline unsigned bio_segments(struct bio *bio)
|
|
{
|
|
unsigned segs = 0;
|
|
struct bio_vec bv;
|
|
struct bvec_iter iter;
|
|
|
|
/*
|
|
* We special case discard/write same, because they interpret bi_size
|
|
* differently:
|
|
*/
|
|
|
|
if (bio_op(bio) == REQ_OP_DISCARD)
|
|
return 1;
|
|
|
|
if (bio_op(bio) == REQ_OP_SECURE_ERASE)
|
|
return 1;
|
|
|
|
if (bio_op(bio) == REQ_OP_WRITE_SAME)
|
|
return 1;
|
|
|
|
bio_for_each_segment(bv, bio, iter)
|
|
segs++;
|
|
|
|
return segs;
|
|
}
|
|
|
|
/*
|
|
* get a reference to a bio, so it won't disappear. the intended use is
|
|
* something like:
|
|
*
|
|
* bio_get(bio);
|
|
* submit_bio(rw, bio);
|
|
* if (bio->bi_flags ...)
|
|
* do_something
|
|
* bio_put(bio);
|
|
*
|
|
* without the bio_get(), it could potentially complete I/O before submit_bio
|
|
* returns. and then bio would be freed memory when if (bio->bi_flags ...)
|
|
* runs
|
|
*/
|
|
static inline void bio_get(struct bio *bio)
|
|
{
|
|
bio->bi_flags |= (1 << BIO_REFFED);
|
|
smp_mb__before_atomic();
|
|
atomic_inc(&bio->__bi_cnt);
|
|
}
|
|
|
|
static inline void bio_cnt_set(struct bio *bio, unsigned int count)
|
|
{
|
|
if (count != 1) {
|
|
bio->bi_flags |= (1 << BIO_REFFED);
|
|
smp_mb();
|
|
}
|
|
atomic_set(&bio->__bi_cnt, count);
|
|
}
|
|
|
|
static inline bool bio_flagged(struct bio *bio, unsigned int bit)
|
|
{
|
|
return (bio->bi_flags & (1U << bit)) != 0;
|
|
}
|
|
|
|
static inline void bio_set_flag(struct bio *bio, unsigned int bit)
|
|
{
|
|
bio->bi_flags |= (1U << bit);
|
|
}
|
|
|
|
static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
|
|
{
|
|
bio->bi_flags &= ~(1U << bit);
|
|
}
|
|
|
|
static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv)
|
|
{
|
|
*bv = bio_iovec(bio);
|
|
}
|
|
|
|
static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv)
|
|
{
|
|
struct bvec_iter iter = bio->bi_iter;
|
|
int idx;
|
|
|
|
if (unlikely(!bio_multiple_segments(bio))) {
|
|
*bv = bio_iovec(bio);
|
|
return;
|
|
}
|
|
|
|
bio_advance_iter(bio, &iter, iter.bi_size);
|
|
|
|
if (!iter.bi_bvec_done)
|
|
idx = iter.bi_idx - 1;
|
|
else /* in the middle of bvec */
|
|
idx = iter.bi_idx;
|
|
|
|
*bv = bio->bi_io_vec[idx];
|
|
|
|
/*
|
|
* iter.bi_bvec_done records actual length of the last bvec
|
|
* if this bio ends in the middle of one io vector
|
|
*/
|
|
if (iter.bi_bvec_done)
|
|
bv->bv_len = iter.bi_bvec_done;
|
|
}
|
|
|
|
enum bip_flags {
|
|
BIP_BLOCK_INTEGRITY = 1 << 0, /* block layer owns integrity data */
|
|
BIP_MAPPED_INTEGRITY = 1 << 1, /* ref tag has been remapped */
|
|
BIP_CTRL_NOCHECK = 1 << 2, /* disable HBA integrity checking */
|
|
BIP_DISK_NOCHECK = 1 << 3, /* disable disk integrity checking */
|
|
BIP_IP_CHECKSUM = 1 << 4, /* IP checksum */
|
|
};
|
|
|
|
/*
|
|
* bio integrity payload
|
|
*/
|
|
struct bio_integrity_payload {
|
|
struct bio *bip_bio; /* parent bio */
|
|
|
|
struct bvec_iter bip_iter;
|
|
|
|
bio_end_io_t *bip_end_io; /* saved I/O completion fn */
|
|
|
|
unsigned short bip_slab; /* slab the bip came from */
|
|
unsigned short bip_vcnt; /* # of integrity bio_vecs */
|
|
unsigned short bip_max_vcnt; /* integrity bio_vec slots */
|
|
unsigned short bip_flags; /* control flags */
|
|
|
|
struct work_struct bip_work; /* I/O completion */
|
|
|
|
struct bio_vec *bip_vec;
|
|
struct bio_vec bip_inline_vecs[0];/* embedded bvec array */
|
|
};
|
|
|
|
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
|
|
|
static inline struct bio_integrity_payload *bio_integrity(struct bio *bio)
|
|
{
|
|
if (bio->bi_opf & REQ_INTEGRITY)
|
|
return bio->bi_integrity;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static inline bool bio_integrity_flagged(struct bio *bio, enum bip_flags flag)
|
|
{
|
|
struct bio_integrity_payload *bip = bio_integrity(bio);
|
|
|
|
if (bip)
|
|
return bip->bip_flags & flag;
|
|
|
|
return false;
|
|
}
|
|
|
|
static inline sector_t bip_get_seed(struct bio_integrity_payload *bip)
|
|
{
|
|
return bip->bip_iter.bi_sector;
|
|
}
|
|
|
|
static inline void bip_set_seed(struct bio_integrity_payload *bip,
|
|
sector_t seed)
|
|
{
|
|
bip->bip_iter.bi_sector = seed;
|
|
}
|
|
|
|
#endif /* CONFIG_BLK_DEV_INTEGRITY */
|
|
|
|
extern void bio_trim(struct bio *bio, int offset, int size);
|
|
extern struct bio *bio_split(struct bio *bio, int sectors,
|
|
gfp_t gfp, struct bio_set *bs);
|
|
|
|
/**
|
|
* bio_next_split - get next @sectors from a bio, splitting if necessary
|
|
* @bio: bio to split
|
|
* @sectors: number of sectors to split from the front of @bio
|
|
* @gfp: gfp mask
|
|
* @bs: bio set to allocate from
|
|
*
|
|
* Returns a bio representing the next @sectors of @bio - if the bio is smaller
|
|
* than @sectors, returns the original bio unchanged.
|
|
*/
|
|
static inline struct bio *bio_next_split(struct bio *bio, int sectors,
|
|
gfp_t gfp, struct bio_set *bs)
|
|
{
|
|
if (sectors >= bio_sectors(bio))
|
|
return bio;
|
|
|
|
return bio_split(bio, sectors, gfp, bs);
|
|
}
|
|
|
|
extern struct bio_set *bioset_create(unsigned int, unsigned int);
|
|
extern struct bio_set *bioset_create_nobvec(unsigned int, unsigned int);
|
|
extern void bioset_free(struct bio_set *);
|
|
extern mempool_t *biovec_create_pool(int pool_entries);
|
|
|
|
extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *);
|
|
extern void bio_put(struct bio *);
|
|
|
|
extern void __bio_clone_fast(struct bio *, struct bio *);
|
|
extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *);
|
|
extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs);
|
|
|
|
extern struct bio_set *fs_bio_set;
|
|
|
|
static inline struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
|
|
{
|
|
return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
|
|
}
|
|
|
|
static inline struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
|
|
{
|
|
return bio_clone_bioset(bio, gfp_mask, fs_bio_set);
|
|
}
|
|
|
|
static inline struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs)
|
|
{
|
|
return bio_alloc_bioset(gfp_mask, nr_iovecs, NULL);
|
|
}
|
|
|
|
static inline struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask)
|
|
{
|
|
return bio_clone_bioset(bio, gfp_mask, NULL);
|
|
|
|
}
|
|
|
|
extern void bio_endio(struct bio *);
|
|
|
|
static inline void bio_io_error(struct bio *bio)
|
|
{
|
|
bio->bi_error = -EIO;
|
|
bio_endio(bio);
|
|
}
|
|
|
|
struct request_queue;
|
|
extern int bio_phys_segments(struct request_queue *, struct bio *);
|
|
|
|
extern int submit_bio_wait(struct bio *bio);
|
|
extern void bio_advance(struct bio *, unsigned);
|
|
|
|
extern void bio_init(struct bio *);
|
|
extern void bio_reset(struct bio *);
|
|
void bio_chain(struct bio *, struct bio *);
|
|
|
|
extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
|
|
extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
|
|
unsigned int, unsigned int);
|
|
struct rq_map_data;
|
|
extern struct bio *bio_map_user_iov(struct request_queue *,
|
|
const struct iov_iter *, gfp_t);
|
|
extern void bio_unmap_user(struct bio *);
|
|
extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
|
|
gfp_t);
|
|
extern struct bio *bio_copy_kern(struct request_queue *, void *, unsigned int,
|
|
gfp_t, int);
|
|
extern void bio_set_pages_dirty(struct bio *bio);
|
|
extern void bio_check_pages_dirty(struct bio *bio);
|
|
|
|
void generic_start_io_acct(int rw, unsigned long sectors,
|
|
struct hd_struct *part);
|
|
void generic_end_io_acct(int rw, struct hd_struct *part,
|
|
unsigned long start_time);
|
|
|
|
#ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
|
|
# error "You should define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE for your platform"
|
|
#endif
|
|
#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
|
|
extern void bio_flush_dcache_pages(struct bio *bi);
|
|
#else
|
|
static inline void bio_flush_dcache_pages(struct bio *bi)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
extern void bio_copy_data(struct bio *dst, struct bio *src);
|
|
extern int bio_alloc_pages(struct bio *bio, gfp_t gfp);
|
|
extern void bio_free_pages(struct bio *bio);
|
|
|
|
extern struct bio *bio_copy_user_iov(struct request_queue *,
|
|
struct rq_map_data *,
|
|
const struct iov_iter *,
|
|
gfp_t);
|
|
extern int bio_uncopy_user(struct bio *);
|
|
void zero_fill_bio(struct bio *bio);
|
|
extern struct bio_vec *bvec_alloc(gfp_t, int, unsigned long *, mempool_t *);
|
|
extern void bvec_free(mempool_t *, struct bio_vec *, unsigned int);
|
|
extern unsigned int bvec_nr_vecs(unsigned short idx);
|
|
|
|
#ifdef CONFIG_BLK_CGROUP
|
|
int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css);
|
|
int bio_associate_current(struct bio *bio);
|
|
void bio_disassociate_task(struct bio *bio);
|
|
void bio_clone_blkcg_association(struct bio *dst, struct bio *src);
|
|
#else /* CONFIG_BLK_CGROUP */
|
|
static inline int bio_associate_blkcg(struct bio *bio,
|
|
struct cgroup_subsys_state *blkcg_css) { return 0; }
|
|
static inline int bio_associate_current(struct bio *bio) { return -ENOENT; }
|
|
static inline void bio_disassociate_task(struct bio *bio) { }
|
|
static inline void bio_clone_blkcg_association(struct bio *dst,
|
|
struct bio *src) { }
|
|
#endif /* CONFIG_BLK_CGROUP */
|
|
|
|
#ifdef CONFIG_HIGHMEM
|
|
/*
|
|
* remember never ever reenable interrupts between a bvec_kmap_irq and
|
|
* bvec_kunmap_irq!
|
|
*/
|
|
static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
|
|
{
|
|
unsigned long addr;
|
|
|
|
/*
|
|
* might not be a highmem page, but the preempt/irq count
|
|
* balancing is a lot nicer this way
|
|
*/
|
|
local_irq_save(*flags);
|
|
addr = (unsigned long) kmap_atomic(bvec->bv_page);
|
|
|
|
BUG_ON(addr & ~PAGE_MASK);
|
|
|
|
return (char *) addr + bvec->bv_offset;
|
|
}
|
|
|
|
static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
|
|
{
|
|
unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
|
|
|
|
kunmap_atomic((void *) ptr);
|
|
local_irq_restore(*flags);
|
|
}
|
|
|
|
#else
|
|
static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
|
|
{
|
|
return page_address(bvec->bv_page) + bvec->bv_offset;
|
|
}
|
|
|
|
static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
|
|
{
|
|
*flags = 0;
|
|
}
|
|
#endif
|
|
|
|
static inline char *__bio_kmap_irq(struct bio *bio, struct bvec_iter iter,
|
|
unsigned long *flags)
|
|
{
|
|
return bvec_kmap_irq(&bio_iter_iovec(bio, iter), flags);
|
|
}
|
|
#define __bio_kunmap_irq(buf, flags) bvec_kunmap_irq(buf, flags)
|
|
|
|
#define bio_kmap_irq(bio, flags) \
|
|
__bio_kmap_irq((bio), (bio)->bi_iter, (flags))
|
|
#define bio_kunmap_irq(buf,flags) __bio_kunmap_irq(buf, flags)
|
|
|
|
/*
|
|
* BIO list management for use by remapping drivers (e.g. DM or MD) and loop.
|
|
*
|
|
* A bio_list anchors a singly-linked list of bios chained through the bi_next
|
|
* member of the bio. The bio_list also caches the last list member to allow
|
|
* fast access to the tail.
|
|
*/
|
|
struct bio_list {
|
|
struct bio *head;
|
|
struct bio *tail;
|
|
};
|
|
|
|
static inline int bio_list_empty(const struct bio_list *bl)
|
|
{
|
|
return bl->head == NULL;
|
|
}
|
|
|
|
static inline void bio_list_init(struct bio_list *bl)
|
|
{
|
|
bl->head = bl->tail = NULL;
|
|
}
|
|
|
|
#define BIO_EMPTY_LIST { NULL, NULL }
|
|
|
|
#define bio_list_for_each(bio, bl) \
|
|
for (bio = (bl)->head; bio; bio = bio->bi_next)
|
|
|
|
static inline unsigned bio_list_size(const struct bio_list *bl)
|
|
{
|
|
unsigned sz = 0;
|
|
struct bio *bio;
|
|
|
|
bio_list_for_each(bio, bl)
|
|
sz++;
|
|
|
|
return sz;
|
|
}
|
|
|
|
static inline void bio_list_add(struct bio_list *bl, struct bio *bio)
|
|
{
|
|
bio->bi_next = NULL;
|
|
|
|
if (bl->tail)
|
|
bl->tail->bi_next = bio;
|
|
else
|
|
bl->head = bio;
|
|
|
|
bl->tail = bio;
|
|
}
|
|
|
|
static inline void bio_list_add_head(struct bio_list *bl, struct bio *bio)
|
|
{
|
|
bio->bi_next = bl->head;
|
|
|
|
bl->head = bio;
|
|
|
|
if (!bl->tail)
|
|
bl->tail = bio;
|
|
}
|
|
|
|
static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2)
|
|
{
|
|
if (!bl2->head)
|
|
return;
|
|
|
|
if (bl->tail)
|
|
bl->tail->bi_next = bl2->head;
|
|
else
|
|
bl->head = bl2->head;
|
|
|
|
bl->tail = bl2->tail;
|
|
}
|
|
|
|
static inline void bio_list_merge_head(struct bio_list *bl,
|
|
struct bio_list *bl2)
|
|
{
|
|
if (!bl2->head)
|
|
return;
|
|
|
|
if (bl->head)
|
|
bl2->tail->bi_next = bl->head;
|
|
else
|
|
bl->tail = bl2->tail;
|
|
|
|
bl->head = bl2->head;
|
|
}
|
|
|
|
static inline struct bio *bio_list_peek(struct bio_list *bl)
|
|
{
|
|
return bl->head;
|
|
}
|
|
|
|
static inline struct bio *bio_list_pop(struct bio_list *bl)
|
|
{
|
|
struct bio *bio = bl->head;
|
|
|
|
if (bio) {
|
|
bl->head = bl->head->bi_next;
|
|
if (!bl->head)
|
|
bl->tail = NULL;
|
|
|
|
bio->bi_next = NULL;
|
|
}
|
|
|
|
return bio;
|
|
}
|
|
|
|
static inline struct bio *bio_list_get(struct bio_list *bl)
|
|
{
|
|
struct bio *bio = bl->head;
|
|
|
|
bl->head = bl->tail = NULL;
|
|
|
|
return bio;
|
|
}
|
|
|
|
/*
|
|
* Increment chain count for the bio. Make sure the CHAIN flag update
|
|
* is visible before the raised count.
|
|
*/
|
|
static inline void bio_inc_remaining(struct bio *bio)
|
|
{
|
|
bio_set_flag(bio, BIO_CHAIN);
|
|
smp_mb__before_atomic();
|
|
atomic_inc(&bio->__bi_remaining);
|
|
}
|
|
|
|
/*
|
|
* bio_set is used to allow other portions of the IO system to
|
|
* allocate their own private memory pools for bio and iovec structures.
|
|
* These memory pools in turn all allocate from the bio_slab
|
|
* and the bvec_slabs[].
|
|
*/
|
|
#define BIO_POOL_SIZE 2
|
|
|
|
struct bio_set {
|
|
struct kmem_cache *bio_slab;
|
|
unsigned int front_pad;
|
|
|
|
mempool_t *bio_pool;
|
|
mempool_t *bvec_pool;
|
|
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
|
mempool_t *bio_integrity_pool;
|
|
mempool_t *bvec_integrity_pool;
|
|
#endif
|
|
|
|
/*
|
|
* Deadlock avoidance for stacking block drivers: see comments in
|
|
* bio_alloc_bioset() for details
|
|
*/
|
|
spinlock_t rescue_lock;
|
|
struct bio_list rescue_list;
|
|
struct work_struct rescue_work;
|
|
struct workqueue_struct *rescue_workqueue;
|
|
};
|
|
|
|
struct biovec_slab {
|
|
int nr_vecs;
|
|
char *name;
|
|
struct kmem_cache *slab;
|
|
};
|
|
|
|
/*
|
|
* a small number of entries is fine, not going to be performance critical.
|
|
* basically we just need to survive
|
|
*/
|
|
#define BIO_SPLIT_ENTRIES 2
|
|
|
|
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
|
|
|
#define bip_for_each_vec(bvl, bip, iter) \
|
|
for_each_bvec(bvl, (bip)->bip_vec, iter, (bip)->bip_iter)
|
|
|
|
#define bio_for_each_integrity_vec(_bvl, _bio, _iter) \
|
|
for_each_bio(_bio) \
|
|
bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
|
|
|
|
extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
|
|
extern void bio_integrity_free(struct bio *);
|
|
extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
|
|
extern bool bio_integrity_enabled(struct bio *bio);
|
|
extern int bio_integrity_prep(struct bio *);
|
|
extern void bio_integrity_endio(struct bio *);
|
|
extern void bio_integrity_advance(struct bio *, unsigned int);
|
|
extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
|
|
extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t);
|
|
extern int bioset_integrity_create(struct bio_set *, int);
|
|
extern void bioset_integrity_free(struct bio_set *);
|
|
extern void bio_integrity_init(void);
|
|
|
|
#else /* CONFIG_BLK_DEV_INTEGRITY */
|
|
|
|
static inline void *bio_integrity(struct bio *bio)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline bool bio_integrity_enabled(struct bio *bio)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline int bioset_integrity_create(struct bio_set *bs, int pool_size)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void bioset_integrity_free (struct bio_set *bs)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static inline int bio_integrity_prep(struct bio *bio)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void bio_integrity_free(struct bio *bio)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
|
|
gfp_t gfp_mask)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void bio_integrity_advance(struct bio *bio,
|
|
unsigned int bytes_done)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static inline void bio_integrity_trim(struct bio *bio, unsigned int offset,
|
|
unsigned int sectors)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static inline void bio_integrity_init(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static inline bool bio_integrity_flagged(struct bio *bio, enum bip_flags flag)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline void *bio_integrity_alloc(struct bio * bio, gfp_t gfp,
|
|
unsigned int nr)
|
|
{
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
|
|
static inline int bio_integrity_add_page(struct bio *bio, struct page *page,
|
|
unsigned int len, unsigned int offset)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif /* CONFIG_BLK_DEV_INTEGRITY */
|
|
|
|
#endif /* CONFIG_BLOCK */
|
|
#endif /* __LINUX_BIO_H */
|