diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-15 00:46:01 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-15 00:46:01 -0400 |
| commit | 6b0490816671b2f4126a99998c9bf3c8c0472de2 (patch) | |
| tree | 016543455c2bdbe47b422fed6a3b4ffb991c97d6 /drivers/block | |
| parent | ce9d7f7b45930ed16c512aabcfe651d44f1c8619 (diff) | |
| parent | 0bc62284ee3f2a228c64902ed818b6ba8e04159b (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull Ceph updates from Sage Weil:
"There is the long-awaited discard support for RBD (Guangliang Zhao,
Josh Durgin), a pile of RBD bug fixes that didn't belong in late -rc's
(Ilya Dryomov, Li RongQing), a pile of fs/ceph bug fixes and
performance and debugging improvements (Yan, Zheng, John Spray), and a
smattering of cleanups (Chao Yu, Fabian Frederick, Joe Perches)"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: (40 commits)
ceph: fix divide-by-zero in __validate_layout()
rbd: rbd workqueues need a resque worker
libceph: ceph-msgr workqueue needs a resque worker
ceph: fix bool assignments
libceph: separate multiple ops with commas in debugfs output
libceph: sync osd op definitions in rados.h
libceph: remove redundant declaration
ceph: additional debugfs output
ceph: export ceph_session_state_name function
ceph: include the initial ACL in create/mkdir/mknod MDS requests
ceph: use pagelist to present MDS request data
libceph: reference counting pagelist
ceph: fix llistxattr on symlink
ceph: send client metadata to MDS
ceph: remove redundant code for max file size verification
ceph: remove redundant io_iter_advance()
ceph: move ceph_find_inode() outside the s_mutex
ceph: request xattrs if xattr_version is zero
rbd: set the remaining discard properties to enable support
rbd: use helpers to handle discard for layered images correctly
...
Diffstat (limited to 'drivers/block')
| -rw-r--r-- | drivers/block/rbd.c | 396 |
1 files changed, 276 insertions, 120 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 4b97baf8afa3..0a54c588e433 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
| @@ -210,6 +210,12 @@ enum obj_request_type { | |||
| 210 | OBJ_REQUEST_NODATA, OBJ_REQUEST_BIO, OBJ_REQUEST_PAGES | 210 | OBJ_REQUEST_NODATA, OBJ_REQUEST_BIO, OBJ_REQUEST_PAGES |
| 211 | }; | 211 | }; |
| 212 | 212 | ||
| 213 | enum obj_operation_type { | ||
| 214 | OBJ_OP_WRITE, | ||
| 215 | OBJ_OP_READ, | ||
| 216 | OBJ_OP_DISCARD, | ||
| 217 | }; | ||
| 218 | |||
| 213 | enum obj_req_flags { | 219 | enum obj_req_flags { |
| 214 | OBJ_REQ_DONE, /* completion flag: not done = 0, done = 1 */ | 220 | OBJ_REQ_DONE, /* completion flag: not done = 0, done = 1 */ |
| 215 | OBJ_REQ_IMG_DATA, /* object usage: standalone = 0, image = 1 */ | 221 | OBJ_REQ_IMG_DATA, /* object usage: standalone = 0, image = 1 */ |
| @@ -276,6 +282,7 @@ enum img_req_flags { | |||
| 276 | IMG_REQ_WRITE, /* I/O direction: read = 0, write = 1 */ | 282 | IMG_REQ_WRITE, /* I/O direction: read = 0, write = 1 */ |
| 277 | IMG_REQ_CHILD, /* initiator: block = 0, child image = 1 */ | 283 | IMG_REQ_CHILD, /* initiator: block = 0, child image = 1 */ |
| 278 | IMG_REQ_LAYERED, /* ENOENT handling: normal = 0, layered = 1 */ | 284 | IMG_REQ_LAYERED, /* ENOENT handling: normal = 0, layered = 1 */ |
| 285 | IMG_REQ_DISCARD, /* discard: normal = 0, discard request = 1 */ | ||
| 279 | }; | 286 | }; |
| 280 | 287 | ||
| 281 | struct rbd_img_request { | 288 | struct rbd_img_request { |
| @@ -785,6 +792,20 @@ static int parse_rbd_opts_token(char *c, void *private) | |||
| 785 | return 0; | 792 | return 0; |
| 786 | } | 793 | } |
| 787 | 794 | ||
| 795 | static char* obj_op_name(enum obj_operation_type op_type) | ||
| 796 | { | ||
| 797 | switch (op_type) { | ||
| 798 | case OBJ_OP_READ: | ||
| 799 | return "read"; | ||
| 800 | case OBJ_OP_WRITE: | ||
| 801 | return "write"; | ||
| 802 | case OBJ_OP_DISCARD: | ||
| 803 | return "discard"; | ||
| 804 | default: | ||
| 805 | return "???"; | ||
| 806 | } | ||
| 807 | } | ||
| 808 | |||
| 788 | /* | 809 | /* |
| 789 | * Get a ceph client with specific addr and configuration, if one does | 810 | * Get a ceph client with specific addr and configuration, if one does |
| 790 | * not exist create it. Either way, ceph_opts is consumed by this | 811 | * not exist create it. Either way, ceph_opts is consumed by this |
| @@ -1600,6 +1621,21 @@ static bool img_request_write_test(struct rbd_img_request *img_request) | |||
| 1600 | return test_bit(IMG_REQ_WRITE, &img_request->flags) != 0; | 1621 | return test_bit(IMG_REQ_WRITE, &img_request->flags) != 0; |
| 1601 | } | 1622 | } |
| 1602 | 1623 | ||
| 1624 | /* | ||
| 1625 | * Set the discard flag when the img_request is an discard request | ||
| 1626 | */ | ||
| 1627 | static void img_request_discard_set(struct rbd_img_request *img_request) | ||
| 1628 | { | ||
| 1629 | set_bit(IMG_REQ_DISCARD, &img_request->flags); | ||
| 1630 | smp_mb(); | ||
| 1631 | } | ||
| 1632 | |||
| 1633 | static bool img_request_discard_test(struct rbd_img_request *img_request) | ||
| 1634 | { | ||
| 1635 | smp_mb(); | ||
| 1636 | return test_bit(IMG_REQ_DISCARD, &img_request->flags) != 0; | ||
| 1637 | } | ||
| 1638 | |||
| 1603 | static void img_request_child_set(struct rbd_img_request *img_request) | 1639 | static void img_request_child_set(struct rbd_img_request *img_request) |
| 1604 | { | 1640 | { |
| 1605 | set_bit(IMG_REQ_CHILD, &img_request->flags); | 1641 | set_bit(IMG_REQ_CHILD, &img_request->flags); |
| @@ -1636,6 +1672,17 @@ static bool img_request_layered_test(struct rbd_img_request *img_request) | |||
| 1636 | return test_bit(IMG_REQ_LAYERED, &img_request->flags) != 0; | 1672 | return test_bit(IMG_REQ_LAYERED, &img_request->flags) != 0; |
| 1637 | } | 1673 | } |
| 1638 | 1674 | ||
| 1675 | static enum obj_operation_type | ||
| 1676 | rbd_img_request_op_type(struct rbd_img_request *img_request) | ||
| 1677 | { | ||
| 1678 | if (img_request_write_test(img_request)) | ||
| 1679 | return OBJ_OP_WRITE; | ||
| 1680 | else if (img_request_discard_test(img_request)) | ||
| 1681 | return OBJ_OP_DISCARD; | ||
| 1682 | else | ||
| 1683 | return OBJ_OP_READ; | ||
| 1684 | } | ||
| 1685 | |||
| 1639 | static void | 1686 | static void |
| 1640 | rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request) | 1687 | rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request) |
| 1641 | { | 1688 | { |
| @@ -1722,6 +1769,21 @@ static void rbd_osd_write_callback(struct rbd_obj_request *obj_request) | |||
| 1722 | obj_request_done_set(obj_request); | 1769 | obj_request_done_set(obj_request); |
| 1723 | } | 1770 | } |
| 1724 | 1771 | ||
| 1772 | static void rbd_osd_discard_callback(struct rbd_obj_request *obj_request) | ||
| 1773 | { | ||
| 1774 | dout("%s: obj %p result %d %llu\n", __func__, obj_request, | ||
| 1775 | obj_request->result, obj_request->length); | ||
| 1776 | /* | ||
| 1777 | * There is no such thing as a successful short discard. Set | ||
| 1778 | * it to our originally-requested length. | ||
| 1779 | */ | ||
| 1780 | obj_request->xferred = obj_request->length; | ||
| 1781 | /* discarding a non-existent object is not a problem */ | ||
| 1782 | if (obj_request->result == -ENOENT) | ||
| 1783 | obj_request->result = 0; | ||
| 1784 | obj_request_done_set(obj_request); | ||
| 1785 | } | ||
| 1786 | |||
| 1725 | /* | 1787 | /* |
| 1726 | * For a simple stat call there's nothing to do. We'll do more if | 1788 | * For a simple stat call there's nothing to do. We'll do more if |
| 1727 | * this is part of a write sequence for a layered image. | 1789 | * this is part of a write sequence for a layered image. |
| @@ -1773,6 +1835,11 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, | |||
| 1773 | case CEPH_OSD_OP_STAT: | 1835 | case CEPH_OSD_OP_STAT: |
| 1774 | rbd_osd_stat_callback(obj_request); | 1836 | rbd_osd_stat_callback(obj_request); |
| 1775 | break; | 1837 | break; |
| 1838 | case CEPH_OSD_OP_DELETE: | ||
| 1839 | case CEPH_OSD_OP_TRUNCATE: | ||
| 1840 | case CEPH_OSD_OP_ZERO: | ||
| 1841 | rbd_osd_discard_callback(obj_request); | ||
| 1842 | break; | ||
| 1776 | case CEPH_OSD_OP_CALL: | 1843 | case CEPH_OSD_OP_CALL: |
| 1777 | case CEPH_OSD_OP_NOTIFY_ACK: | 1844 | case CEPH_OSD_OP_NOTIFY_ACK: |
| 1778 | case CEPH_OSD_OP_WATCH: | 1845 | case CEPH_OSD_OP_WATCH: |
| @@ -1823,7 +1890,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request) | |||
| 1823 | */ | 1890 | */ |
| 1824 | static struct ceph_osd_request *rbd_osd_req_create( | 1891 | static struct ceph_osd_request *rbd_osd_req_create( |
| 1825 | struct rbd_device *rbd_dev, | 1892 | struct rbd_device *rbd_dev, |
| 1826 | bool write_request, | 1893 | enum obj_operation_type op_type, |
| 1827 | unsigned int num_ops, | 1894 | unsigned int num_ops, |
| 1828 | struct rbd_obj_request *obj_request) | 1895 | struct rbd_obj_request *obj_request) |
| 1829 | { | 1896 | { |
| @@ -1831,16 +1898,18 @@ static struct ceph_osd_request *rbd_osd_req_create( | |||
| 1831 | struct ceph_osd_client *osdc; | 1898 | struct ceph_osd_client *osdc; |
| 1832 | struct ceph_osd_request *osd_req; | 1899 | struct ceph_osd_request *osd_req; |
| 1833 | 1900 | ||
| 1834 | if (obj_request_img_data_test(obj_request)) { | 1901 | if (obj_request_img_data_test(obj_request) && |
| 1902 | (op_type == OBJ_OP_DISCARD || op_type == OBJ_OP_WRITE)) { | ||
| 1835 | struct rbd_img_request *img_request = obj_request->img_request; | 1903 | struct rbd_img_request *img_request = obj_request->img_request; |
| 1836 | 1904 | if (op_type == OBJ_OP_WRITE) { | |
| 1837 | rbd_assert(write_request == | 1905 | rbd_assert(img_request_write_test(img_request)); |
| 1838 | img_request_write_test(img_request)); | 1906 | } else { |
| 1839 | if (write_request) | 1907 | rbd_assert(img_request_discard_test(img_request)); |
| 1840 | snapc = img_request->snapc; | 1908 | } |
| 1909 | snapc = img_request->snapc; | ||
| 1841 | } | 1910 | } |
| 1842 | 1911 | ||
| 1843 | rbd_assert(num_ops == 1 || (write_request && num_ops == 2)); | 1912 | rbd_assert(num_ops == 1 || ((op_type == OBJ_OP_WRITE) && num_ops == 2)); |
| 1844 | 1913 | ||
| 1845 | /* Allocate and initialize the request, for the num_ops ops */ | 1914 | /* Allocate and initialize the request, for the num_ops ops */ |
| 1846 | 1915 | ||
| @@ -1850,7 +1919,7 @@ static struct ceph_osd_request *rbd_osd_req_create( | |||
| 1850 | if (!osd_req) | 1919 | if (!osd_req) |
| 1851 | return NULL; /* ENOMEM */ | 1920 | return NULL; /* ENOMEM */ |
| 1852 | 1921 | ||
| 1853 | if (write_request) | 1922 | if (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD) |
| 1854 | osd_req->r_flags = CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK; | 1923 | osd_req->r_flags = CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK; |
| 1855 | else | 1924 | else |
| 1856 | osd_req->r_flags = CEPH_OSD_FLAG_READ; | 1925 | osd_req->r_flags = CEPH_OSD_FLAG_READ; |
| @@ -1865,9 +1934,10 @@ static struct ceph_osd_request *rbd_osd_req_create( | |||
| 1865 | } | 1934 | } |
| 1866 | 1935 | ||
