From: Yehuda Sadeh Date: Mon, 12 Jan 2009 22:41:14 +0000 (-0800) Subject: kclient: avoid starvation when fsync on dir X-Git-Tag: v0.6~1^2~89 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7c7d228921c9efa7ba1bafba21b0dfa2d284348e;p=ceph.git kclient: avoid starvation when fsync on dir --- diff --git a/src/kernel/dir.c b/src/kernel/dir.c index c4c80235c421..8a1fa803ca46 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -862,14 +862,31 @@ 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; + struct list_head *p, *n, *head; + struct ceph_mds_request *req; + u64 last_tid; ret = 0; - dout(0, "sync on directory\n"); + dout(10, "sync on directory\n"); + + head = &ci->i_listener_list; + spin_lock(&ci->i_listener_lock); - list_for_each_safe(p, n, &ci->i_listener_list) { - struct ceph_mds_request *req = - list_entry(p, struct ceph_mds_request, r_listener_item); + + if (list_empty(head)) + goto out; + + req = list_entry(head->prev, + struct ceph_mds_request, r_listener_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; + ceph_mdsc_get_request(req); spin_unlock(&ci->i_listener_lock); if (req->r_timeout) { @@ -884,8 +901,8 @@ static int ceph_dir_fsync(struct file *file, struct dentry *dentry, int datasync ceph_mdsc_put_request(req); } +out: spin_unlock(&ci->i_listener_lock); - return ret; }