From: Sage Weil Date: Mon, 16 Mar 2009 22:29:29 +0000 (-0700) Subject: kclient: rename listener -> unsafe; fix fsync; simplify dir_fsync X-Git-Tag: v0.7.2~160 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3ea98116ba2bf1d35e727f7d40f2afb58852391c;p=ceph.git kclient: rename listener -> unsafe; fix fsync; simplify dir_fsync --- diff --git a/src/kernel/dir.c b/src/kernel/dir.c index 7540f5a80c73..e31e3a756a21 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -800,52 +800,50 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size, return size - left; } -static int ceph_dir_fsync(struct file *file, struct dentry *dentry, int datasync) +static int ceph_dir_fsync(struct file *file, struct dentry *dentry, + int datasync) { struct inode *inode = dentry->d_inode; struct ceph_inode_info *ci = ceph_inode(inode); - int ret, err; - struct list_head *p, *n, *head; + struct list_head *head = &ci->i_unsafe_dirops; struct ceph_mds_request *req; u64 last_tid; + int ret = 0; - ret = 0; - dout(10, "sync on directory\n"); - - head = &ci->i_listener_list; - - spin_lock(&ci->i_listener_lock); - + dout(10, "dir_fsync %p\n", inode); + spin_lock(&ci->i_unsafe_lock); if (list_empty(head)) goto out; req = list_entry(head->prev, - struct ceph_mds_request, r_listener_item); + struct ceph_mds_request, r_unsafe_dir_item); last_tid = req->r_tid; - list_for_each_safe(p, n, head) { - req = list_entry(p, struct ceph_mds_request, r_listener_item); - - /* avoid starvation */ - if (req->r_tid > last_tid) - goto out; - + do { ceph_mdsc_get_request(req); - spin_unlock(&ci->i_listener_lock); + spin_unlock(&ci->i_unsafe_lock); + dout(10, "dir_fsync %p wait on tid %llu (until %llu)\n", + inode, req->r_tid, last_tid); if (req->r_timeout) { - err = wait_for_completion_timeout(&req->r_safe_completion, - req->r_timeout); - if (err == 0) + ret = wait_for_completion_timeout(&req->r_safe_completion, + req->r_timeout); + if (ret > 0) + ret = 0; + else if (ret == 0) ret = -EIO; /* timed out */ } else { wait_for_completion(&req->r_safe_completion); } - spin_lock(&ci->i_listener_lock); - + spin_lock(&ci->i_unsafe_lock); ceph_mdsc_put_request(req); - } + + if (ret || list_empty(head)) + break; + req = list_entry(head->next, + struct ceph_mds_request, r_unsafe_dir_item); + } while (req->r_tid < last_tid); out: - spin_unlock(&ci->i_listener_lock); + spin_unlock(&ci->i_unsafe_lock); return ret; } diff --git a/src/kernel/file.c b/src/kernel/file.c index d027d71fa9d9..0c379bd18871 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -412,9 +412,9 @@ static void sync_write_commit(struct ceph_osd_request *req) struct ceph_inode_info *ci = ceph_inode(req->r_inode); dout(10, "sync_write_commit %p tid %llu\n", req, req->r_tid); - spin_lock(&ci->i_listener_lock); + spin_lock(&ci->i_unsafe_lock); list_del_init(&req->r_unsafe_item); - spin_unlock(&ci->i_listener_lock); + spin_unlock(&ci->i_unsafe_lock); ceph_put_cap_refs(ci, CEPH_CAP_FILE_WR); } @@ -431,7 +431,7 @@ static void sync_write_wait(struct inode *inode) struct ceph_osd_request *req; u64 last_tid; - spin_lock(&ci->i_listener_lock); + spin_lock(&ci->i_unsafe_lock); if (list_empty(head)) goto out; @@ -442,22 +442,24 @@ static void sync_write_wait(struct inode *inode) do { ceph_osdc_get_request(req); - spin_unlock(&ci->i_listener_lock); + spin_unlock(&ci->i_unsafe_lock); dout(10, "sync_write_wait on tid %llu (until %llu)\n", req->r_tid, last_tid); wait_for_completion(&req->r_safe_completion); - spin_lock(&ci->i_listener_lock); + spin_lock(&ci->i_unsafe_lock); ceph_osdc_put_request(req); /* * from here on look at first entry in chain, since we * only want to wait for anything older than last_tid */ + if (list_empty(head)) + break; req = list_entry(head->next, struct ceph_osd_request, r_unsafe_item); - } while (req->r_tid <= last_tid); + } while (req->r_tid < last_tid); out: - spin_unlock(&ci->i_listener_lock); + spin_unlock(&ci->i_unsafe_lock); } /* @@ -560,9 +562,9 @@ more: * Add to inode unsafe list only after we * start_request so that a tid has been assigned. */ - spin_lock(&ci->i_listener_lock); + spin_lock(&ci->i_unsafe_lock); list_add(&ci->i_unsafe_writes, &req->r_unsafe_item); - spin_unlock(&ci->i_listener_lock); + spin_unlock(&ci->i_unsafe_lock); ceph_get_more_cap_refs(ci, CEPH_CAP_FILE_WR); } ret = ceph_osdc_wait_request(&client->osdc, req); @@ -733,7 +735,7 @@ static int ceph_fsync(struct file *file, struct dentry *dentry, int datasync) struct inode *inode = dentry->d_inode; int ret; - dout(10, "fsync on inode %p\n", inode); + dout(10, "fsync %p\n", inode); sync_write_wait(inode); ret = filemap_write_and_wait(inode->i_mapping); diff --git a/src/kernel/inode.c b/src/kernel/inode.c index bedf122a0d21..0754f274e87f 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -288,7 +288,10 @@ struct inode *ceph_alloc_inode(struct super_block *sb) ci->i_wrbuffer_ref_head = 0; ci->i_rdcache_gen = 0; ci->i_rdcache_revoking = 0; + INIT_LIST_HEAD(&ci->i_unsafe_writes); + INIT_LIST_HEAD(&ci->i_unsafe_dirops); + spin_lock_init(&ci->i_unsafe_lock); ci->i_snap_realm = NULL; INIT_LIST_HEAD(&ci->i_snap_realm_item); @@ -299,9 +302,6 @@ struct inode *ceph_alloc_inode(struct super_block *sb) INIT_WORK(&ci->i_vmtruncate_work, ceph_vmtruncate_work); - INIT_LIST_HEAD(&ci->i_listener_list); - spin_lock_init(&ci->i_listener_lock); - return &ci->vfs_inode; } diff --git a/src/kernel/mds_client.c b/src/kernel/mds_client.c index 1eb0210b2f13..6959d461bab7 100644 --- a/src/kernel/mds_client.c +++ b/src/kernel/mds_client.c @@ -441,10 +441,10 @@ static void __register_request(struct ceph_mds_client *mdsc, if (listener) { struct ceph_inode_info *ci = ceph_inode(listener); - spin_lock(&ci->i_listener_lock); - req->r_listener = listener; - list_add_tail(&req->r_listener_item, &ci->i_listener_list); - spin_unlock(&ci->i_listener_lock); + spin_lock(&ci->i_unsafe_lock); + req->r_unsafe_dir = listener; + list_add_tail(&req->r_unsafe_dir_item, &ci->i_unsafe_dirops); + spin_unlock(&ci->i_unsafe_lock); } ceph_sysfs_mds_req_init(mdsc, req); @@ -457,12 +457,12 @@ static void __unregister_request(struct ceph_mds_client *mdsc, radix_tree_delete(&mdsc->request_tree, req->r_tid); ceph_mdsc_put_request(req); - if (req->r_listener) { - struct ceph_inode_info *ci = ceph_inode(req->r_listener); + if (req->r_unsafe_dir) { + struct ceph_inode_info *ci = ceph_inode(req->r_unsafe_dir); - spin_lock(&ci->i_listener_lock); - list_del_init(&req->r_listener_item); - spin_unlock(&ci->i_listener_lock); + spin_lock(&ci->i_unsafe_lock); + list_del_init(&req->r_unsafe_dir_item); + spin_unlock(&ci->i_unsafe_lock); } ceph_sysfs_mds_req_cleanup(req); @@ -836,7 +836,7 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, return ERR_PTR(-ENOMEM); req->r_started = jiffies; req->r_resend_mds = -1; - INIT_LIST_HEAD(&req->r_listener_item); + INIT_LIST_HEAD(&req->r_unsafe_dir_item); req->r_fmode = -1; atomic_set(&req->r_ref, 1); /* one for request_tree, one for caller */ INIT_LIST_HEAD(&req->r_wait); diff --git a/src/kernel/mds_client.h b/src/kernel/mds_client.h index 9d25a9d004de..0af5851231f0 100644 --- a/src/kernel/mds_client.h +++ b/src/kernel/mds_client.h @@ -179,8 +179,8 @@ struct ceph_mds_request { u32 r_direct_hash; /* choose dir frag based on this dentry hash */ bool r_direct_is_hash; /* true if r_direct_hash is valid */ - struct inode *r_listener; - struct list_head r_listener_item; + struct inode *r_unsafe_dir; + struct list_head r_unsafe_dir_item; /* references to the trailing dentry and inode from parsing the * mds response. also used to feed a VFS-provided dentry into diff --git a/src/kernel/super.h b/src/kernel/super.h index 5caeae807d93..403f83a65545 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -281,7 +281,10 @@ struct ceph_inode_info { If it's non-zero, we _may_ have cached pages. */ u32 i_rdcache_revoking; /* RDCACHE gen to async invalidate, if any */ + struct list_head i_unsafe_writes; /* uncommitted sync writes */ + struct list_head i_unsafe_dirops; /* uncommitted mds dir ops */ + spinlock_t i_unsafe_lock; struct ceph_snap_realm *i_snap_realm; /* snap realm (if caps) */ struct list_head i_snap_realm_item; @@ -292,9 +295,6 @@ struct ceph_inode_info { struct work_struct i_vmtruncate_work; - struct list_head i_listener_list; /* requests we pend on */ - spinlock_t i_listener_lock; - struct inode vfs_inode; /* at end */ };