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

Commit 63c70a0d 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:
  ceph: try to send partial cap release on cap message on missing inode
  ceph: release cap on import if we don't have the inode
  ceph: fix misleading/incorrect debug message
  ceph: fix atomic64_t initialization on ia64
  ceph: fix lease revocation when seq doesn't match
  ceph: fix f_namelen reported by statfs
  ceph: fix memory leak in statfs
  ceph: fix d_subdirs ordering problem
parents 10823452 2b2300d6
Loading
Loading
Loading
Loading
+57 −36
Original line number Original line Diff line number Diff line
@@ -981,19 +981,10 @@ static int send_cap_msg(struct ceph_mds_session *session,
	return 0;
	return 0;
}
}


/*
static void __queue_cap_release(struct ceph_mds_session *session,
 * Queue cap releases when an inode is dropped from our cache.  Since
				u64 ino, u64 cap_id, u32 migrate_seq,
 * inode is about to be destroyed, there is no need for i_lock.
				u32 issue_seq)
 */
void ceph_queue_caps_release(struct inode *inode)
{
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	struct rb_node *p;

	p = rb_first(&ci->i_caps);
	while (p) {
		struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
		struct ceph_mds_session *session = cap->session;
	struct ceph_msg *msg;
	struct ceph_msg *msg;
	struct ceph_mds_cap_release *head;
	struct ceph_mds_cap_release *head;
	struct ceph_mds_cap_item *item;
	struct ceph_mds_cap_item *item;
@@ -1003,25 +994,24 @@ void ceph_queue_caps_release(struct inode *inode)
	msg = list_first_entry(&session->s_cap_releases,
	msg = list_first_entry(&session->s_cap_releases,
			       struct ceph_msg, list_head);
			       struct ceph_msg, list_head);


		dout(" adding %p release to mds%d msg %p (%d left)\n",
	dout(" adding %llx release to mds%d msg %p (%d left)\n",
		     inode, session->s_mds, msg, session->s_num_cap_releases);
	     ino, session->s_mds, msg, session->s_num_cap_releases);


	BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
	BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
	head = msg->front.iov_base;
	head = msg->front.iov_base;
	head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
	head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
	item = msg->front.iov_base + msg->front.iov_len;
	item = msg->front.iov_base + msg->front.iov_len;
		item->ino = cpu_to_le64(ceph_ino(inode));
	item->ino = cpu_to_le64(ino);
		item->cap_id = cpu_to_le64(cap->cap_id);
	item->cap_id = cpu_to_le64(cap_id);
		item->migrate_seq = cpu_to_le32(cap->mseq);
	item->migrate_seq = cpu_to_le32(migrate_seq);
		item->seq = cpu_to_le32(cap->issue_seq);
	item->seq = cpu_to_le32(issue_seq);


	session->s_num_cap_releases--;
	session->s_num_cap_releases--;


	msg->front.iov_len += sizeof(*item);
	msg->front.iov_len += sizeof(*item);
	if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
	if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
		dout(" release msg %p full\n", msg);
		dout(" release msg %p full\n", msg);
			list_move_tail(&msg->list_head,
		list_move_tail(&msg->list_head, &session->s_cap_releases_done);
				       &session->s_cap_releases_done);
	} else {
	} else {
		dout(" release msg %p at %d/%d (%d)\n", msg,
		dout(" release msg %p at %d/%d (%d)\n", msg,
		     (int)le32_to_cpu(head->num),
		     (int)le32_to_cpu(head->num),
@@ -1029,6 +1019,24 @@ void ceph_queue_caps_release(struct inode *inode)
		     (int)msg->front.iov_len);
		     (int)msg->front.iov_len);
	}
	}
	spin_unlock(&session->s_cap_lock);
	spin_unlock(&session->s_cap_lock);
}

/*
 * Queue cap releases when an inode is dropped from our cache.  Since
 * inode is about to be destroyed, there is no need for i_lock.
 */
void ceph_queue_caps_release(struct inode *inode)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	struct rb_node *p;

	p = rb_first(&ci->i_caps);
	while (p) {
		struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
		struct ceph_mds_session *session = cap->session;

		__queue_cap_release(session, ceph_ino(inode), cap->cap_id,
				    cap->mseq, cap->issue_seq);
		p = rb_next(p);
		p = rb_next(p);
		__ceph_remove_cap(cap);
		__ceph_remove_cap(cap);
	}
	}
@@ -2655,7 +2663,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
	struct ceph_mds_caps *h;
	struct ceph_mds_caps *h;
	int mds = session->s_mds;
	int mds = session->s_mds;
	int op;
	int op;
	u32 seq;
	u32 seq, mseq;
	struct ceph_vino vino;
	struct ceph_vino vino;
	u64 cap_id;
	u64 cap_id;
	u64 size, max_size;
	u64 size, max_size;
@@ -2675,6 +2683,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
	vino.snap = CEPH_NOSNAP;
	vino.snap = CEPH_NOSNAP;
	cap_id = le64_to_cpu(h->cap_id);
	cap_id = le64_to_cpu(h->cap_id);
	seq = le32_to_cpu(h->seq);
	seq = le32_to_cpu(h->seq);
	mseq = le32_to_cpu(h->migrate_seq);
	size = le64_to_cpu(h->size);
	size = le64_to_cpu(h->size);
	max_size = le64_to_cpu(h->max_size);
	max_size = le64_to_cpu(h->max_size);


@@ -2689,6 +2698,18 @@ void ceph_handle_caps(struct ceph_mds_session *session,
	     vino.snap, inode);
	     vino.snap, inode);
	if (!inode) {
	if (!inode) {
		dout(" i don't have ino %llx\n", vino.ino);
		dout(" i don't have ino %llx\n", vino.ino);

		if (op == CEPH_CAP_OP_IMPORT)
			__queue_cap_release(session, vino.ino, cap_id,
					    mseq, seq);

		/*
		 * send any full release message to try to move things
		 * along for the mds (who clearly thinks we still have this
		 * cap).
		 */
		ceph_add_cap_releases(mdsc, session, -1);
		ceph_send_cap_releases(mdsc, session);
		goto done;
		goto done;
	}
	}


@@ -2714,7 +2735,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
	spin_lock(&inode->i_lock);
	spin_lock(&inode->i_lock);
	cap = __get_cap_for_mds(ceph_inode(inode), mds);
	cap = __get_cap_for_mds(ceph_inode(inode), mds);
	if (!cap) {
	if (!cap) {
		dout("no cap on %p ino %llx.%llx from mds%d, releasing\n",
		dout(" no cap on %p ino %llx.%llx from mds%d\n",
		     inode, ceph_ino(inode), ceph_snap(inode), mds);
		     inode, ceph_ino(inode), ceph_snap(inode), mds);
		spin_unlock(&inode->i_lock);
		spin_unlock(&inode->i_lock);
		goto done;
		goto done;
+1 −1
Original line number Original line Diff line number Diff line
@@ -827,7 +827,7 @@ static void ceph_set_dentry_offset(struct dentry *dn)


	spin_lock(&dcache_lock);
	spin_lock(&dcache_lock);
	spin_lock(&dn->d_lock);
	spin_lock(&dn->d_lock);
	list_move_tail(&dir->d_subdirs, &dn->d_u.d_child);
	list_move(&dn->d_u.d_child, &dir->d_subdirs);
	dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
	dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
	     dn->d_u.d_child.prev, dn->d_u.d_child.next);
	     dn->d_u.d_child.prev, dn->d_u.d_child.next);
	spin_unlock(&dn->d_lock);
	spin_unlock(&dn->d_lock);
+16 −12
Original line number Original line Diff line number Diff line
@@ -1066,7 +1066,7 @@ static int trim_caps(struct ceph_mds_client *mdsc,
 *
 *
 * Called under s_mutex.
 * Called under s_mutex.
 */
 */
static int add_cap_releases(struct ceph_mds_client *mdsc,
int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
			  struct ceph_mds_session *session,
			  struct ceph_mds_session *session,
			  int extra)
			  int extra)
{
{
@@ -1176,7 +1176,7 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
/*
/*
 * called under s_mutex
 * called under s_mutex
 */
 */
static void send_cap_releases(struct ceph_mds_client *mdsc,
void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
			    struct ceph_mds_session *session)
			    struct ceph_mds_session *session)
{
{
	struct ceph_msg *msg;
	struct ceph_msg *msg;
@@ -1980,7 +1980,7 @@ out_err:
	}
	}
	mutex_unlock(&mdsc->mutex);
	mutex_unlock(&mdsc->mutex);


	add_cap_releases(mdsc, req->r_session, -1);
	ceph_add_cap_releases(mdsc, req->r_session, -1);
	mutex_unlock(&session->s_mutex);
	mutex_unlock(&session->s_mutex);


	/* kick calling process */
	/* kick calling process */
@@ -2433,6 +2433,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
	struct ceph_dentry_info *di;
	struct ceph_dentry_info *di;
	int mds = session->s_mds;
	int mds = session->s_mds;
	struct ceph_mds_lease *h = msg->front.iov_base;
	struct ceph_mds_lease *h = msg->front.iov_base;
	u32 seq;
	struct ceph_vino vino;
	struct ceph_vino vino;
	int mask;
	int mask;
	struct qstr dname;
	struct qstr dname;
@@ -2446,6 +2447,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
	vino.ino = le64_to_cpu(h->ino);
	vino.ino = le64_to_cpu(h->ino);
	vino.snap = CEPH_NOSNAP;
	vino.snap = CEPH_NOSNAP;
	mask = le16_to_cpu(h->mask);
	mask = le16_to_cpu(h->mask);
	seq = le32_to_cpu(h->seq);
	dname.name = (void *)h + sizeof(*h) + sizeof(u32);
	dname.name = (void *)h + sizeof(*h) + sizeof(u32);
	dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
	dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
	if (dname.len != get_unaligned_le32(h+1))
	if (dname.len != get_unaligned_le32(h+1))
@@ -2456,8 +2458,9 @@ static void handle_lease(struct ceph_mds_client *mdsc,


	/* lookup inode */
	/* lookup inode */
	inode = ceph_find_inode(sb, vino);
	inode = ceph_find_inode(sb, vino);
	dout("handle_lease '%s', mask %d, ino %llx %p\n",
	dout("handle_lease %s, mask %d, ino %llx %p %.*s\n",
	     ceph_lease_op_name(h->action), mask, vino.ino, inode);
	     ceph_lease_op_name(h->action), mask, vino.ino, inode,
	     dname.len, dname.name);
	if (inode == NULL) {
	if (inode == NULL) {
		dout("handle_lease no inode %llx\n", vino.ino);
		dout("handle_lease no inode %llx\n", vino.ino);
		goto release;
		goto release;
@@ -2482,6 +2485,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
	switch (h->action) {
	switch (h->action) {
	case CEPH_MDS_LEASE_REVOKE:
	case CEPH_MDS_LEASE_REVOKE:
		if (di && di->lease_session == session) {
		if (di && di->lease_session == session) {
			if (ceph_seq_cmp(di->lease_seq, seq) > 0)
				h->seq = cpu_to_le32(di->lease_seq);
				h->seq = cpu_to_le32(di->lease_seq);
			__ceph_mdsc_drop_dentry_lease(dentry);
			__ceph_mdsc_drop_dentry_lease(dentry);
		}
		}
@@ -2496,7 +2500,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
			unsigned long duration =
			unsigned long duration =
				le32_to_cpu(h->duration_ms) * HZ / 1000;
				le32_to_cpu(h->duration_ms) * HZ / 1000;


			di->lease_seq = le32_to_cpu(h->seq);
			di->lease_seq = seq;
			dentry->d_time = di->lease_renew_from + duration;
			dentry->d_time = di->lease_renew_from + duration;
			di->lease_renew_after = di->lease_renew_from +
			di->lease_renew_after = di->lease_renew_from +
				(duration >> 1);
				(duration >> 1);
@@ -2686,10 +2690,10 @@ static void delayed_work(struct work_struct *work)
			send_renew_caps(mdsc, s);
			send_renew_caps(mdsc, s);
		else
		else
			ceph_con_keepalive(&s->s_con);
			ceph_con_keepalive(&s->s_con);
		add_cap_releases(mdsc, s, -1);
		ceph_add_cap_releases(mdsc, s, -1);
		if (s->s_state == CEPH_MDS_SESSION_OPEN ||
		if (s->s_state == CEPH_MDS_SESSION_OPEN ||
		    s->s_state == CEPH_MDS_SESSION_HUNG)
		    s->s_state == CEPH_MDS_SESSION_HUNG)
			send_cap_releases(mdsc, s);
			ceph_send_cap_releases(mdsc, s);
		mutex_unlock(&s->s_mutex);
		mutex_unlock(&s->s_mutex);
		ceph_put_mds_session(s);
		ceph_put_mds_session(s);


+6 −0
Original line number Original line Diff line number Diff line
@@ -322,6 +322,12 @@ static inline void ceph_mdsc_put_request(struct ceph_mds_request *req)
	kref_put(&req->r_kref, ceph_mdsc_release_request);
	kref_put(&req->r_kref, ceph_mdsc_release_request);
}
}


extern int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
				 struct ceph_mds_session *session,
				 int extra);
extern void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
				   struct ceph_mds_session *session);

extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc);
extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc);


extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
+2 −0
Original line number Original line Diff line number Diff line
@@ -400,6 +400,8 @@ static void release_generic_request(struct kref *kref)
		ceph_msg_put(req->reply);
		ceph_msg_put(req->reply);
	if (req->request)
	if (req->request)
		ceph_msg_put(req->request);
		ceph_msg_put(req->request);

	kfree(req);
}
}


static void put_generic_request(struct ceph_mon_generic_request *req)
static void put_generic_request(struct ceph_mon_generic_request *req)
Loading