Commit 2f111a6f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'ceph-for-5.15-rc7' of git://github.com/ceph/ceph-client

Pull ceph fixes from Ilya Dryomov:
 "Two important filesystem fixes, marked for stable.

  The blocklisted superblocks issue was particularly annoying because
  for unexperienced users it essentially exacted a reboot to establish a
  new functional mount in that scenario"

* tag 'ceph-for-5.15-rc7' of git://github.com/ceph/ceph-client:
  ceph: fix handling of "meta" errors
  ceph: skip existing superblocks that are blocklisted or shut down when mounting
parents 515dcc2e 1bd85aa6
Loading
Loading
Loading
Loading
+3 −9
Original line number Diff line number Diff line
@@ -2330,7 +2330,6 @@ static int unsafe_request_wait(struct inode *inode)

int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
	struct ceph_file_info *fi = file->private_data;
	struct inode *inode = file->f_mapping->host;
	struct ceph_inode_info *ci = ceph_inode(inode);
	u64 flush_tid;
@@ -2365,14 +2364,9 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
	if (err < 0)
		ret = err;

	if (errseq_check(&ci->i_meta_err, READ_ONCE(fi->meta_err))) {
		spin_lock(&file->f_lock);
		err = errseq_check_and_advance(&ci->i_meta_err,
					       &fi->meta_err);
		spin_unlock(&file->f_lock);
	err = file_check_and_advance_wb_err(file);
	if (err < 0)
		ret = err;
	}
out:
	dout("fsync %p%s result=%d\n", inode, datasync ? " datasync" : "", ret);
	return ret;
+0 −1
Original line number Diff line number Diff line
@@ -233,7 +233,6 @@ static int ceph_init_file_info(struct inode *inode, struct file *file,

	spin_lock_init(&fi->rw_contexts_lock);
	INIT_LIST_HEAD(&fi->rw_contexts);
	fi->meta_err = errseq_sample(&ci->i_meta_err);
	fi->filp_gen = READ_ONCE(ceph_inode_to_client(inode)->filp_gen);

	return 0;
+0 −2
Original line number Diff line number Diff line
@@ -541,8 +541,6 @@ struct inode *ceph_alloc_inode(struct super_block *sb)

	ceph_fscache_inode_init(ci);

	ci->i_meta_err = 0;

	return &ci->vfs_inode;
}

+5 −12
Original line number Diff line number Diff line
@@ -1493,7 +1493,6 @@ static void cleanup_session_requests(struct ceph_mds_client *mdsc,
{
	struct ceph_mds_request *req;
	struct rb_node *p;
	struct ceph_inode_info *ci;

	dout("cleanup_session_requests mds%d\n", session->s_mds);
	mutex_lock(&mdsc->mutex);
@@ -1502,16 +1501,10 @@ static void cleanup_session_requests(struct ceph_mds_client *mdsc,
				       struct ceph_mds_request, r_unsafe_item);
		pr_warn_ratelimited(" dropping unsafe request %llu\n",
				    req->r_tid);
		if (req->r_target_inode) {
			/* dropping unsafe change of inode's attributes */
			ci = ceph_inode(req->r_target_inode);
			errseq_set(&ci->i_meta_err, -EIO);
		}
		if (req->r_unsafe_dir) {
			/* dropping unsafe directory operation */
			ci = ceph_inode(req->r_unsafe_dir);
			errseq_set(&ci->i_meta_err, -EIO);
		}
		if (req->r_target_inode)
			mapping_set_error(req->r_target_inode->i_mapping, -EIO);
		if (req->r_unsafe_dir)
			mapping_set_error(req->r_unsafe_dir->i_mapping, -EIO);
		__unregister_request(mdsc, req);
	}
	/* zero r_attempts, so kick_requests() will re-send requests */
@@ -1678,7 +1671,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
		spin_unlock(&mdsc->cap_dirty_lock);

		if (dirty_dropped) {
			errseq_set(&ci->i_meta_err, -EIO);
			mapping_set_error(inode->i_mapping, -EIO);

			if (ci->i_wrbuffer_ref_head == 0 &&
			    ci->i_wr_ref == 0 &&
+14 −3
Original line number Diff line number Diff line
@@ -1002,16 +1002,16 @@ static int ceph_compare_super(struct super_block *sb, struct fs_context *fc)
	struct ceph_fs_client *new = fc->s_fs_info;
	struct ceph_mount_options *fsopt = new->mount_options;
	struct ceph_options *opt = new->client->options;
	struct ceph_fs_client *other = ceph_sb_to_client(sb);
	struct ceph_fs_client *fsc = ceph_sb_to_client(sb);

	dout("ceph_compare_super %p\n", sb);

	if (compare_mount_options(fsopt, opt, other)) {
	if (compare_mount_options(fsopt, opt, fsc)) {
		dout("monitor(s)/mount options don't match\n");
		return 0;
	}
	if ((opt->flags & CEPH_OPT_FSID) &&
	    ceph_fsid_compare(&opt->fsid, &other->client->fsid)) {
	    ceph_fsid_compare(&opt->fsid, &fsc->client->fsid)) {
		dout("fsid doesn't match\n");
		return 0;
	}
@@ -1019,6 +1019,17 @@ static int ceph_compare_super(struct super_block *sb, struct fs_context *fc)
		dout("flags differ\n");
		return 0;
	}

	if (fsc->blocklisted && !ceph_test_mount_opt(fsc, CLEANRECOVER)) {
		dout("client is blocklisted (and CLEANRECOVER is not set)\n");
		return 0;
	}

	if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) {
		dout("client has been forcibly unmounted\n");
		return 0;
	}

	return 1;
}

Loading