Commit 63c70a0d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client

* '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
...@@ -981,6 +981,46 @@ static int send_cap_msg(struct ceph_mds_session *session, ...@@ -981,6 +981,46 @@ static int send_cap_msg(struct ceph_mds_session *session,
return 0; return 0;
} }
static void __queue_cap_release(struct ceph_mds_session *session,
u64 ino, u64 cap_id, u32 migrate_seq,
u32 issue_seq)
{
struct ceph_msg *msg;
struct ceph_mds_cap_release *head;
struct ceph_mds_cap_item *item;
spin_lock(&session->s_cap_lock);
BUG_ON(!session->s_num_cap_releases);
msg = list_first_entry(&session->s_cap_releases,
struct ceph_msg, list_head);
dout(" adding %llx release to mds%d msg %p (%d left)\n",
ino, session->s_mds, msg, session->s_num_cap_releases);
BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
head = msg->front.iov_base;
head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
item = msg->front.iov_base + msg->front.iov_len;
item->ino = cpu_to_le64(ino);
item->cap_id = cpu_to_le64(cap_id);
item->migrate_seq = cpu_to_le32(migrate_seq);
item->seq = cpu_to_le32(issue_seq);
session->s_num_cap_releases--;
msg->front.iov_len += sizeof(*item);
if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
dout(" release msg %p full\n", msg);
list_move_tail(&msg->list_head, &session->s_cap_releases_done);
} else {
dout(" release msg %p at %d/%d (%d)\n", msg,
(int)le32_to_cpu(head->num),
(int)CEPH_CAPS_PER_RELEASE,
(int)msg->front.iov_len);
}
spin_unlock(&session->s_cap_lock);
}
/* /*
* Queue cap releases when an inode is dropped from our cache. Since * 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. * inode is about to be destroyed, there is no need for i_lock.
...@@ -994,41 +1034,9 @@ void ceph_queue_caps_release(struct inode *inode) ...@@ -994,41 +1034,9 @@ void ceph_queue_caps_release(struct inode *inode)
while (p) { while (p) {
struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node); struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
struct ceph_mds_session *session = cap->session; struct ceph_mds_session *session = cap->session;
struct ceph_msg *msg;
struct ceph_mds_cap_release *head;
struct ceph_mds_cap_item *item;
spin_lock(&session->s_cap_lock); __queue_cap_release(session, ceph_ino(inode), cap->cap_id,
BUG_ON(!session->s_num_cap_releases); cap->mseq, cap->issue_seq);
msg = list_first_entry(&session->s_cap_releases,
struct ceph_msg, list_head);
dout(" adding %p release to mds%d msg %p (%d left)\n",
inode, session->s_mds, msg, session->s_num_cap_releases);
BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
head = msg->front.iov_base;
head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
item = msg->front.iov_base + msg->front.iov_len;
item->ino = cpu_to_le64(ceph_ino(inode));
item->cap_id = cpu_to_le64(cap->cap_id);
item->migrate_seq = cpu_to_le32(cap->mseq);
item->seq = cpu_to_le32(cap->issue_seq);
session->s_num_cap_releases--;
msg->front.iov_len += sizeof(*item);
if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
dout(" release msg %p full\n", msg);
list_move_tail(&msg->list_head,
&session->s_cap_releases_done);
} else {
dout(" release msg %p at %d/%d (%d)\n", msg,
(int)le32_to_cpu(head->num),
(int)CEPH_CAPS_PER_RELEASE,
(int)msg->front.iov_len);
}
spin_unlock(&session->s_cap_lock);
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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
......
...@@ -827,7 +827,7 @@ static void ceph_set_dentry_offset(struct dentry *dn) ...@@ -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);
......
...@@ -1066,9 +1066,9 @@ static int trim_caps(struct ceph_mds_client *mdsc, ...@@ -1066,9 +1066,9 @@ 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)
{ {
struct ceph_msg *msg; struct ceph_msg *msg;
struct ceph_mds_cap_release *head; struct ceph_mds_cap_release *head;
...@@ -1176,8 +1176,8 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) ...@@ -1176,8 +1176,8 @@ 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 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) ...@@ -1980,7 +1980,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
} }
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, ...@@ -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, ...@@ -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, ...@@ -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,7 +2485,8 @@ static void handle_lease(struct ceph_mds_client *mdsc, ...@@ -2482,7 +2485,8 @@ 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) {
h->seq = cpu_to_le32(di->lease_seq); if (ceph_seq_cmp(di->lease_seq, seq) > 0)
h->seq = cpu_to_le32(di->lease_seq);
__ceph_mdsc_drop_dentry_lease(dentry); __ceph_mdsc_drop_dentry_lease(dentry);
} }
release = 1; release = 1;
...@@ -2496,7 +2500,7 @@ static void handle_lease(struct ceph_mds_client *mdsc, ...@@ -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) ...@@ -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);
......
...@@ -322,6 +322,12 @@ static inline void ceph_mdsc_put_request(struct ceph_mds_request *req) ...@@ -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,
......
...@@ -400,6 +400,8 @@ static void release_generic_request(struct kref *kref) ...@@ -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)
......
...@@ -89,7 +89,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -89,7 +89,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_files = le64_to_cpu(st.num_objects); buf->f_files = le64_to_cpu(st.num_objects);
buf->f_ffree = -1; buf->f_ffree = -1;
buf->f_namelen = PATH_MAX; buf->f_namelen = NAME_MAX;
buf->f_frsize = PAGE_CACHE_SIZE; buf->f_frsize = PAGE_CACHE_SIZE;
/* leave fsid little-endian, regardless of host endianness */ /* leave fsid little-endian, regardless of host endianness */
...@@ -926,7 +926,7 @@ static int ceph_compare_super(struct super_block *sb, void *data) ...@@ -926,7 +926,7 @@ static int ceph_compare_super(struct super_block *sb, void *data)
/* /*
* construct our own bdi so we can control readahead, etc. * construct our own bdi so we can control readahead, etc.
*/ */
static atomic_long_t bdi_seq = ATOMIC_INIT(0); static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client) static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment