Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57bb5595 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: (23 commits)
  ceph: fix cap flush race reentrancy
  libceph: subscribe to osdmap when cluster is full
  libceph: handle new osdmap down/state change encoding
  rbd: handle online resize of underlying rbd image
  ceph: avoid inode lookup on nfs fh reconnect
  ceph: use LOOKUPINO to make unconnected nfs fh more reliable
  rbd: use snprintf for disk->disk_name
  rbd: cleanup: make kfree match kmalloc
  rbd: warn on update_snaps failure on notify
  ceph: check return value for start_request in writepages
  ceph: remove useless check
  libceph: add missing breaks in addr_set_port
  libceph: fix TAG_WAIT case
  ceph: fix broken comparison in readdir loop
  libceph: fix osdmap timestamp assignment
  ceph: fix rare potential cap leak
  libceph: use snprintf for unknown addrs
  libceph: use snprintf for formatting object name
  ceph: use snprintf for dirstat content
  libceph: fix uninitialized value when no get_authorizer method is set
  ...
parents 2a651c7f db354052
Loading
Loading
Loading
Loading
+18 −9
Original line number Diff line number Diff line
@@ -1191,14 +1191,19 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev,
static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
{
	struct rbd_device *dev = (struct rbd_device *)data;
	int rc;

	if (!dev)
		return;

	dout("rbd_watch_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name,
		notify_id, (int)opcode);
	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
	__rbd_update_snaps(dev);
	rc = __rbd_update_snaps(dev);
	mutex_unlock(&ctl_mutex);
	if (rc)
		pr_warning(DRV_NAME "%d got notification but failed to update"
			   " snaps: %d\n", dev->major, rc);

	rbd_req_sync_notify_ack(dev, ver, notify_id, dev->obj_md_name);
}
@@ -1597,7 +1602,7 @@ static int rbd_header_add_snap(struct rbd_device *dev,
	int name_len = strlen(snap_name);
	u64 new_snapid;
	int ret;
	void *data, *data_start, *data_end;
	void *data, *p, *e;
	u64 ver;

	/* we should create a snapshot only if we're pointing at the head */
@@ -1614,16 +1619,16 @@ static int rbd_header_add_snap(struct rbd_device *dev,
	if (!data)
		return -ENOMEM;

	data_start = data;
	data_end = data + name_len + 16;
	p = data;
	e = data + name_len + 16;

	ceph_encode_string_safe(&data, data_end, snap_name, name_len, bad);
	ceph_encode_64_safe(&data, data_end, new_snapid, bad);
	ceph_encode_string_safe(&p, e, snap_name, name_len, bad);
	ceph_encode_64_safe(&p, e, new_snapid, bad);

	ret = rbd_req_sync_exec(dev, dev->obj_md_name, "rbd", "snap_add",
				data_start, data - data_start, &ver);
				data, p - data, &ver);

	kfree(data_start);
	kfree(data);

	if (ret < 0)
		return ret;
@@ -1659,6 +1664,9 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev)
	if (ret < 0)
		return ret;

	/* resized? */
	set_capacity(rbd_dev->disk, h.image_size / 512ULL);

	down_write(&rbd_dev->header.snap_rwsem);

	snap_seq = rbd_dev->header.snapc->seq;
@@ -1716,7 +1724,8 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
	if (!disk)
		goto out;

	sprintf(disk->disk_name, DRV_NAME "%d", rbd_dev->id);
	snprintf(disk->disk_name, sizeof(disk->disk_name), DRV_NAME "%d",
		 rbd_dev->id);
	disk->major = rbd_dev->major;
	disk->first_minor = 0;
	disk->fops = &rbd_bd_ops;
+2 −3
Original line number Diff line number Diff line
@@ -848,7 +848,8 @@ get_more_pages:
		op->payload_len = cpu_to_le32(len);
		req->r_request->hdr.data_len = cpu_to_le32(len);

		ceph_osdc_start_request(&fsc->client->osdc, req, true);
		rc = ceph_osdc_start_request(&fsc->client->osdc, req, true);
		BUG_ON(rc);
		req = NULL;

		/* continue? */
@@ -880,8 +881,6 @@ release_pvec_pages:
out:
	if (req)
		ceph_osdc_put_request(req);
	if (rc > 0)
		rc = 0;  /* vfs expects us to return 0 */
	ceph_put_snap_context(snapc);
	dout("writepages done, rc = %d\n", rc);
	return rc;
+31 −30
Original line number Diff line number Diff line
@@ -569,7 +569,8 @@ retry:
		list_add_tail(&cap->session_caps, &session->s_caps);
		session->s_nr_caps++;
		spin_unlock(&session->s_cap_lock);
	}
	} else if (new_cap)
		ceph_put_cap(mdsc, new_cap);

	if (!ci->i_snap_realm) {
		/*
@@ -2634,6 +2635,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
			      struct ceph_mds_session *session,
			      int *open_target_sessions)
{
	struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
	struct ceph_inode_info *ci = ceph_inode(inode);
	int mds = session->s_mds;
	unsigned mseq = le32_to_cpu(ex->migrate_seq);
@@ -2670,6 +2672,19 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
			 * export targets, so that we get the matching IMPORT
			 */
			*open_target_sessions = 1;

			/*
			 * we can't flush dirty caps that we've seen the
			 * EXPORT but no IMPORT for
			 */
			spin_lock(&mdsc->cap_dirty_lock);
			if (!list_empty(&ci->i_dirty_item)) {
				dout(" moving %p to cap_dirty_migrating\n",
				     inode);
				list_move(&ci->i_dirty_item,
					  &mdsc->cap_dirty_migrating);
			}
			spin_unlock(&mdsc->cap_dirty_lock);
		}
		__ceph_remove_cap(cap);
	}
@@ -2707,6 +2722,13 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
		ci->i_cap_exporting_issued = 0;
		ci->i_cap_exporting_mseq = 0;
		ci->i_cap_exporting_mds = -1;

		spin_lock(&mdsc->cap_dirty_lock);
		if (!list_empty(&ci->i_dirty_item)) {
			dout(" moving %p back to cap_dirty\n", inode);
			list_move(&ci->i_dirty_item, &mdsc->cap_dirty);
		}
		spin_unlock(&mdsc->cap_dirty_lock);
	} else {
		dout("handle_cap_import inode %p ci %p mds%d mseq %d\n",
		     inode, ci, mds, mseq);
@@ -2910,38 +2932,16 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
 */
void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc)
{
	struct ceph_inode_info *ci, *nci = NULL;
	struct inode *inode, *ninode = NULL;
	struct list_head *p, *n;
	struct ceph_inode_info *ci;
	struct inode *inode;

	dout("flush_dirty_caps\n");
	spin_lock(&mdsc->cap_dirty_lock);
	list_for_each_safe(p, n, &mdsc->cap_dirty) {
		if (nci) {
			ci = nci;
			inode = ninode;
			ci->i_ceph_flags &= ~CEPH_I_NOFLUSH;
			dout("flush_dirty_caps inode %p (was next inode)\n",
			     inode);
		} else {
			ci = list_entry(p, struct ceph_inode_info,
	while (!list_empty(&mdsc->cap_dirty)) {
		ci = list_first_entry(&mdsc->cap_dirty, struct ceph_inode_info,
				      i_dirty_item);
		inode = igrab(&ci->vfs_inode);
			BUG_ON(!inode);
			dout("flush_dirty_caps inode %p\n", inode);
		}
		if (n != &mdsc->cap_dirty) {
			nci = list_entry(n, struct ceph_inode_info,
					 i_dirty_item);
			ninode = igrab(&nci->vfs_inode);
			BUG_ON(!ninode);
			nci->i_ceph_flags |= CEPH_I_NOFLUSH;
			dout("flush_dirty_caps next inode %p, noflush\n",
			     ninode);
		} else {
			nci = NULL;
			ninode = NULL;
		}
		dout("flush_dirty_caps %p\n", inode);
		spin_unlock(&mdsc->cap_dirty_lock);
		if (inode) {
			ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH,
@@ -2951,6 +2951,7 @@ void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc)
		spin_lock(&mdsc->cap_dirty_lock);
	}
	spin_unlock(&mdsc->cap_dirty_lock);
	dout("flush_dirty_caps done\n");
}

/*
+4 −3
Original line number Diff line number Diff line
@@ -360,7 +360,7 @@ more:
	rinfo = &fi->last_readdir->r_reply_info;
	dout("readdir frag %x num %d off %d chunkoff %d\n", frag,
	     rinfo->dir_nr, off, fi->offset);
	while (off - fi->offset >= 0 && off - fi->offset < rinfo->dir_nr) {
	while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) {
		u64 pos = ceph_make_fpos(frag, off);
		struct ceph_mds_reply_inode *in =
			rinfo->dir_in[off - fi->offset].in;
@@ -1066,16 +1066,17 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
	struct inode *inode = file->f_dentry->d_inode;
	struct ceph_inode_info *ci = ceph_inode(inode);
	int left;
	const int bufsize = 1024;

	if (!ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT))
		return -EISDIR;

	if (!cf->dir_info) {
		cf->dir_info = kmalloc(1024, GFP_NOFS);
		cf->dir_info = kmalloc(bufsize, GFP_NOFS);
		if (!cf->dir_info)
			return -ENOMEM;
		cf->dir_info_len =
			sprintf(cf->dir_info,
			snprintf(cf->dir_info, bufsize,
				"entries:   %20lld\n"
				" files:    %20lld\n"
				" subdirs:  %20lld\n"
+22 −3
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
static struct dentry *__fh_to_dentry(struct super_block *sb,
				     struct ceph_nfs_fh *fh)
{
	struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
	struct inode *inode;
	struct dentry *dentry;
	struct ceph_vino vino;
@@ -95,8 +96,24 @@ static struct dentry *__fh_to_dentry(struct super_block *sb,
	vino.ino = fh->ino;
	vino.snap = CEPH_NOSNAP;
	inode = ceph_find_inode(sb, vino);
	if (!inode) {
		struct ceph_mds_request *req;

		req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPINO,
					       USE_ANY_MDS);
		if (IS_ERR(req))
			return ERR_CAST(req);

		req->r_ino1 = vino;
		req->r_num_caps = 1;
		err = ceph_mdsc_do_request(mdsc, NULL, req);
		inode = req->r_target_inode;
		if (inode)
			igrab(inode);
		ceph_mdsc_put_request(req);
		if (!inode)
			return ERR_PTR(-ESTALE);
	}

	dentry = d_obtain_alias(inode);
	if (IS_ERR(dentry)) {
@@ -148,8 +165,10 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb,
		snprintf(req->r_path2, 16, "%d", cfh->parent_name_hash);
		req->r_num_caps = 1;
		err = ceph_mdsc_do_request(mdsc, NULL, req);
		inode = req->r_target_inode;
		if (inode)
			igrab(inode);
		ceph_mdsc_put_request(req);
		inode = ceph_find_inode(sb, vino);
		if (!inode)
			return ERR_PTR(err ? err : -ESTALE);
	}
Loading