7445 lines · 186.3 KB · C
RawDownload
 /*   rbd.c -- Export ceph rados objects as a Linux block device     based on drivers/block/osdblk.c:    Copyright 2009 Red Hat, Inc.    This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License 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 License   along with this program; see the file COPYING.  If not, write to   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.      For usage instructions, please refer to:                  Documentation/ABI/testing/sysfs-bus-rbd  */ #include <linux/ceph/libceph.h>#include <linux/ceph/osd_client.h>#include <linux/ceph/mon_client.h>#include <linux/ceph/cls_lock_client.h>#include <linux/ceph/striper.h>#include <linux/ceph/decode.h>#include <linux/fs_parser.h>#include <linux/bsearch.h> #include <linux/kernel.h>#include <linux/device.h>#include <linux/module.h>#include <linux/blk-mq.h>#include <linux/fs.h>#include <linux/blkdev.h>#include <linux/slab.h>#include <linux/idr.h>#include <linux/workqueue.h> #include "rbd_types.h" #define RBD_DEBUG	/* Activate rbd_assert() calls */ /* * Increment the given counter and return its updated value. * If the counter is already 0 it will not be incremented. * If the counter is already at its maximum value returns * -EINVAL without updating it. */static int atomic_inc_return_safe(atomic_t *v){	unsigned int counter; 	counter = (unsigned int)atomic_fetch_add_unless(v, 1, 0);	if (counter <= (unsigned int)INT_MAX)		return (int)counter; 	atomic_dec(v); 	return -EINVAL;} /* Decrement the counter.  Return the resulting value, or -EINVAL */static int atomic_dec_return_safe(atomic_t *v){	int counter; 	counter = atomic_dec_return(v);	if (counter >= 0)		return counter; 	atomic_inc(v); 	return -EINVAL;} #define RBD_DRV_NAME "rbd" #define RBD_MINORS_PER_MAJOR		256#define RBD_SINGLE_MAJOR_PART_SHIFT	4 #define RBD_MAX_PARENT_CHAIN_LEN	16 #define RBD_SNAP_DEV_NAME_PREFIX	"snap_"#define RBD_MAX_SNAP_NAME_LEN	\			(NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) #define RBD_MAX_SNAP_COUNT	510	/* allows max snapc to fit in 4KB */ #define RBD_SNAP_HEAD_NAME	"-" #define	BAD_SNAP_INDEX	U32_MAX		/* invalid index into snap array */ /* This allows a single page to hold an image name sent by OSD */#define RBD_IMAGE_NAME_LEN_MAX	(PAGE_SIZE - sizeof (__le32) - 1)#define RBD_IMAGE_ID_LEN_MAX	64 #define RBD_OBJ_PREFIX_LEN_MAX	64 #define RBD_NOTIFY_TIMEOUT	5	/* seconds */#define RBD_RETRY_DELAY		msecs_to_jiffies(1000) /* Feature bits */ #define RBD_FEATURE_LAYERING		(1ULL<<0)#define RBD_FEATURE_STRIPINGV2		(1ULL<<1)#define RBD_FEATURE_EXCLUSIVE_LOCK	(1ULL<<2)#define RBD_FEATURE_OBJECT_MAP		(1ULL<<3)#define RBD_FEATURE_FAST_DIFF		(1ULL<<4)#define RBD_FEATURE_DEEP_FLATTEN	(1ULL<<5)#define RBD_FEATURE_DATA_POOL		(1ULL<<7)#define RBD_FEATURE_OPERATIONS		(1ULL<<8) #define RBD_FEATURES_ALL	(RBD_FEATURE_LAYERING |		\				 RBD_FEATURE_STRIPINGV2 |	\				 RBD_FEATURE_EXCLUSIVE_LOCK |	\				 RBD_FEATURE_OBJECT_MAP |	\				 RBD_FEATURE_FAST_DIFF |	\				 RBD_FEATURE_DEEP_FLATTEN |	\				 RBD_FEATURE_DATA_POOL |	\				 RBD_FEATURE_OPERATIONS) /* Features supported by this (client software) implementation. */ #define RBD_FEATURES_SUPPORTED	(RBD_FEATURES_ALL) /* * An RBD device name will be "rbd#", where the "rbd" comes from * RBD_DRV_NAME above, and # is a unique integer identifier. */#define DEV_NAME_LEN		32 /* * block device image metadata (in-memory version) */struct rbd_image_header {	/* These six fields never change for a given rbd image */	char *object_prefix;	__u8 obj_order;	u64 stripe_unit;	u64 stripe_count;	s64 data_pool_id;	u64 features;		/* Might be changeable someday? */ 	/* The remaining fields need to be updated occasionally */	u64 image_size;	struct ceph_snap_context *snapc;	char *snap_names;	/* format 1 only */	u64 *snap_sizes;	/* format 1 only */}; /* * An rbd image specification. * * The tuple (pool_id, image_id, snap_id) is sufficient to uniquely * identify an image.  Each rbd_dev structure includes a pointer to * an rbd_spec structure that encapsulates this identity. * * Each of the id's in an rbd_spec has an associated name.  For a * user-mapped image, the names are supplied and the id's associated * with them are looked up.  For a layered image, a parent image is * defined by the tuple, and the names are looked up. * * An rbd_dev structure contains a parent_spec pointer which is * non-null if the image it represents is a child in a layered * image.  This pointer will refer to the rbd_spec structure used * by the parent rbd_dev for its own identity (i.e., the structure * is shared between the parent and child). * * Since these structures are populated once, during the discovery * phase of image construction, they are effectively immutable so * we make no effort to synchronize access to them. * * Note that code herein does not assume the image name is known (it * could be a null pointer). */struct rbd_spec {	u64		pool_id;	const char	*pool_name;	const char	*pool_ns;	/* NULL if default, never "" */ 	const char	*image_id;	const char	*image_name; 	u64		snap_id;	const char	*snap_name; 	struct kref	kref;}; /* * an instance of the client.  multiple devices may share an rbd client. */struct rbd_client {	struct ceph_client	*client;	struct kref		kref;	struct list_head	node;}; struct pending_result {	int			result;		/* first nonzero result */	int			num_pending;}; struct rbd_img_request; enum obj_request_type {	OBJ_REQUEST_NODATA = 1,	OBJ_REQUEST_BIO,	/* pointer into provided bio (list) */	OBJ_REQUEST_BVECS,	/* pointer into provided bio_vec array */	OBJ_REQUEST_OWN_BVECS,	/* private bio_vec array, doesn't own pages */}; enum obj_operation_type {	OBJ_OP_READ = 1,	OBJ_OP_WRITE,	OBJ_OP_DISCARD,	OBJ_OP_ZEROOUT,}; #define RBD_OBJ_FLAG_DELETION			(1U << 0)#define RBD_OBJ_FLAG_COPYUP_ENABLED		(1U << 1)#define RBD_OBJ_FLAG_COPYUP_ZEROS		(1U << 2)#define RBD_OBJ_FLAG_MAY_EXIST			(1U << 3)#define RBD_OBJ_FLAG_NOOP_FOR_NONEXISTENT	(1U << 4) enum rbd_obj_read_state {	RBD_OBJ_READ_START = 1,	RBD_OBJ_READ_OBJECT,	RBD_OBJ_READ_PARENT,}; /* * Writes go through the following state machine to deal with * layering: * *            . . . . . RBD_OBJ_WRITE_GUARD. . . . . . . . . . . . . . *            .                 |                                    . *            .                 v                                    . *            .    RBD_OBJ_WRITE_READ_FROM_PARENT. . .               . *            .                 |                    .               . *            .                 v                    v (deep-copyup  . *    (image  .   RBD_OBJ_WRITE_COPYUP_EMPTY_SNAPC   .  not needed)  . * flattened) v                 |                    .               . *            .                 v                    .               . *            . . . .RBD_OBJ_WRITE_COPYUP_OPS. . . . .      (copyup  . *                              |                        not needed) v *                              v                                    . *                            done . . . . . . . . . . . . . . . . . . *                              ^ *                              | *                     RBD_OBJ_WRITE_FLAT * * Writes start in RBD_OBJ_WRITE_GUARD or _FLAT, depending on whether * assert_exists guard is needed or not (in some cases it's not needed * even if there is a parent). */enum rbd_obj_write_state {	RBD_OBJ_WRITE_START = 1,	RBD_OBJ_WRITE_PRE_OBJECT_MAP,	RBD_OBJ_WRITE_OBJECT,	__RBD_OBJ_WRITE_COPYUP,	RBD_OBJ_WRITE_COPYUP,	RBD_OBJ_WRITE_POST_OBJECT_MAP,}; enum rbd_obj_copyup_state {	RBD_OBJ_COPYUP_START = 1,	RBD_OBJ_COPYUP_READ_PARENT,	__RBD_OBJ_COPYUP_OBJECT_MAPS,	RBD_OBJ_COPYUP_OBJECT_MAPS,	__RBD_OBJ_COPYUP_WRITE_OBJECT,	RBD_OBJ_COPYUP_WRITE_OBJECT,}; struct rbd_obj_request {	struct ceph_object_extent ex;	unsigned int		flags;	/* RBD_OBJ_FLAG_* */	union {		enum rbd_obj_read_state	 read_state;	/* for reads */		enum rbd_obj_write_state write_state;	/* for writes */	}; 	struct rbd_img_request	*img_request;	struct ceph_file_extent	*img_extents;	u32			num_img_extents; 	union {		struct ceph_bio_iter	bio_pos;		struct {			struct ceph_bvec_iter	bvec_pos;			u32			bvec_count;			u32			bvec_idx;		};	}; 	enum rbd_obj_copyup_state copyup_state;	struct bio_vec		*copyup_bvecs;	u32			copyup_bvec_count; 	struct list_head	osd_reqs;	/* w/ r_private_item */ 	struct mutex		state_mutex;	struct pending_result	pending;	struct kref		kref;}; enum img_req_flags {	IMG_REQ_CHILD,		/* initiator: block = 0, child image = 1 */	IMG_REQ_LAYERED,	/* ENOENT handling: normal = 0, layered = 1 */}; enum rbd_img_state {	RBD_IMG_START = 1,	RBD_IMG_EXCLUSIVE_LOCK,	__RBD_IMG_OBJECT_REQUESTS,	RBD_IMG_OBJECT_REQUESTS,}; struct rbd_img_request {	struct rbd_device	*rbd_dev;	enum obj_operation_type	op_type;	enum obj_request_type	data_type;	unsigned long		flags;	enum rbd_img_state	state;	union {		u64			snap_id;	/* for reads */		struct ceph_snap_context *snapc;	/* for writes */	};	struct rbd_obj_request	*obj_request;	/* obj req initiator */ 	struct list_head	lock_item;	struct list_head	object_extents;	/* obj_req.ex structs */ 	struct mutex		state_mutex;	struct pending_result	pending;	struct work_struct	work;	int			work_result;}; #define for_each_obj_request(ireq, oreq) \	list_for_each_entry(oreq, &(ireq)->object_extents, ex.oe_item)#define for_each_obj_request_safe(ireq, oreq, n) \	list_for_each_entry_safe(oreq, n, &(ireq)->object_extents, ex.oe_item) enum rbd_watch_state {	RBD_WATCH_STATE_UNREGISTERED,	RBD_WATCH_STATE_REGISTERED,	RBD_WATCH_STATE_ERROR,}; enum rbd_lock_state {	RBD_LOCK_STATE_UNLOCKED,	RBD_LOCK_STATE_LOCKED,	RBD_LOCK_STATE_QUIESCING,}; /* WatchNotify::ClientId */struct rbd_client_id {	u64 gid;	u64 handle;}; struct rbd_mapping {	u64                     size;}; /* * a single device */struct rbd_device {	int			dev_id;		/* blkdev unique id */ 	int			major;		/* blkdev assigned major */	int			minor;	struct gendisk		*disk;		/* blkdev's gendisk and rq */ 	u32			image_format;	/* Either 1 or 2 */	struct rbd_client	*rbd_client; 	char			name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */ 	spinlock_t		lock;		/* queue, flags, open_count */ 	struct rbd_image_header	header;	unsigned long		flags;		/* possibly lock protected */	struct rbd_spec		*spec;	struct rbd_options	*opts;	char			*config_info;	/* add{,_single_major} string */ 	struct ceph_object_id	header_oid;	struct ceph_object_locator header_oloc; 	struct ceph_file_layout	layout;		/* used for all rbd requests */ 	struct mutex		watch_mutex;	enum rbd_watch_state	watch_state;	struct ceph_osd_linger_request *watch_handle;	u64			watch_cookie;	struct delayed_work	watch_dwork; 	struct rw_semaphore	lock_rwsem;	enum rbd_lock_state	lock_state;	char			lock_cookie[32];	struct rbd_client_id	owner_cid;	struct work_struct	acquired_lock_work;	struct work_struct	released_lock_work;	struct delayed_work	lock_dwork;	struct work_struct	unlock_work;	spinlock_t		lock_lists_lock;	struct list_head	acquiring_list;	struct list_head	running_list;	struct completion	acquire_wait;	int			acquire_err;	struct completion	quiescing_wait; 	spinlock_t		object_map_lock;	u8			*object_map;	u64			object_map_size;	/* in objects */	u64			object_map_flags; 	struct workqueue_struct	*task_wq; 	struct rbd_spec		*parent_spec;	u64			parent_overlap;	atomic_t		parent_ref;	struct rbd_device	*parent; 	/* Block layer tags. */	struct blk_mq_tag_set	tag_set; 	/* protects updating the header */	struct rw_semaphore     header_rwsem; 	struct rbd_mapping	mapping; 	struct list_head	node; 	/* sysfs related */	struct device		dev;	unsigned long		open_count;	/* protected by lock */}; /* * Flag bits for rbd_dev->flags: * - REMOVING (which is coupled with rbd_dev->open_count) is protected *   by rbd_dev->lock */enum rbd_dev_flags {	RBD_DEV_FLAG_EXISTS,	/* rbd_dev_device_setup() ran */	RBD_DEV_FLAG_REMOVING,	/* this mapping is being removed */	RBD_DEV_FLAG_READONLY,  /* -o ro or snapshot */}; static DEFINE_MUTEX(client_mutex);	/* Serialize client creation */ static LIST_HEAD(rbd_dev_list);    /* devices */static DEFINE_SPINLOCK(rbd_dev_list_lock); static LIST_HEAD(rbd_client_list);		/* clients */static DEFINE_SPINLOCK(rbd_client_list_lock); /* Slab caches for frequently-allocated structures */ static struct kmem_cache	*rbd_img_request_cache;static struct kmem_cache	*rbd_obj_request_cache; static int rbd_major;static DEFINE_IDA(rbd_dev_id_ida); static struct workqueue_struct *rbd_wq; static struct ceph_snap_context rbd_empty_snapc = {	.nref = REFCOUNT_INIT(1),}; /* * single-major requires >= 0.75 version of userspace rbd utility. */static bool single_major = true;module_param(single_major, bool, 0444);MODULE_PARM_DESC(single_major, "Use a single major number for all rbd devices (default: true)"); static ssize_t add_store(const struct bus_type *bus, const char *buf, size_t count);static ssize_t remove_store(const struct bus_type *bus, const char *buf,			    size_t count);static ssize_t add_single_major_store(const struct bus_type *bus, const char *buf,				      size_t count);static ssize_t remove_single_major_store(const struct bus_type *bus, const char *buf,					 size_t count);

Lines 1–500 of 7445.