diff options
| -rw-r--r-- | fs/ceph/mds_client.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 397a47b696ce..8d1f11c7a5a2 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
| @@ -560,6 +560,13 @@ static void __unregister_request(struct ceph_mds_client *mdsc, | |||
| 560 | * | 560 | * |
| 561 | * Called under mdsc->mutex. | 561 | * Called under mdsc->mutex. |
| 562 | */ | 562 | */ |
| 563 | struct dentry *get_nonsnap_parent(struct dentry *dentry) | ||
| 564 | { | ||
| 565 | while (!IS_ROOT(dentry) && ceph_snap(dentry->d_inode) != CEPH_NOSNAP) | ||
| 566 | dentry = dentry->d_parent; | ||
| 567 | return dentry; | ||
| 568 | } | ||
| 569 | |||
| 563 | static int __choose_mds(struct ceph_mds_client *mdsc, | 570 | static int __choose_mds(struct ceph_mds_client *mdsc, |
| 564 | struct ceph_mds_request *req) | 571 | struct ceph_mds_request *req) |
| 565 | { | 572 | { |
| @@ -590,14 +597,29 @@ static int __choose_mds(struct ceph_mds_client *mdsc, | |||
| 590 | if (req->r_inode) { | 597 | if (req->r_inode) { |
| 591 | inode = req->r_inode; | 598 | inode = req->r_inode; |
| 592 | } else if (req->r_dentry) { | 599 | } else if (req->r_dentry) { |
| 593 | if (req->r_dentry->d_inode) { | 600 | struct inode *dir = req->r_dentry->d_parent->d_inode; |
| 601 | |||
| 602 | if (dir->i_sb != mdsc->client->sb) { | ||
| 603 | /* not this fs! */ | ||
| 604 | inode = req->r_dentry->d_inode; | ||
| 605 | } else if (ceph_snap(dir) != CEPH_NOSNAP) { | ||
| 606 | /* direct snapped/virtual snapdir requests | ||
| 607 | * based on parent dir inode */ | ||
| 608 | struct dentry *dn = | ||
| 609 | get_nonsnap_parent(req->r_dentry->d_parent); | ||
| 610 | inode = dn->d_inode; | ||
| 611 | dout("__choose_mds using nonsnap parent %p\n", inode); | ||
| 612 | } else if (req->r_dentry->d_inode) { | ||
| 613 | /* dentry target */ | ||
| 594 | inode = req->r_dentry->d_inode; | 614 | inode = req->r_dentry->d_inode; |
| 595 | } else { | 615 | } else { |
| 596 | inode = req->r_dentry->d_parent->d_inode; | 616 | /* dir + name */ |
| 617 | inode = dir; | ||
| 597 | hash = req->r_dentry->d_name.hash; | 618 | hash = req->r_dentry->d_name.hash; |
| 598 | is_hash = true; | 619 | is_hash = true; |
| 599 | } | 620 | } |
| 600 | } | 621 | } |
| 622 | |||
| 601 | dout("__choose_mds %p is_hash=%d (%d) mode %d\n", inode, (int)is_hash, | 623 | dout("__choose_mds %p is_hash=%d (%d) mode %d\n", inode, (int)is_hash, |
| 602 | (int)hash, mode); | 624 | (int)hash, mode); |
| 603 | if (!inode) | 625 | if (!inode) |
