diff options
| -rw-r--r-- | fs/ceph/dir.c | 2 | ||||
| -rw-r--r-- | fs/ceph/mds_client.c | 13 |
2 files changed, 11 insertions, 4 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 7263f825d426..852ff8600ac9 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
| @@ -506,7 +506,7 @@ int ceph_handle_snapdir(struct ceph_mds_request *req, | |||
| 506 | struct dentry *dentry, int err) | 506 | struct dentry *dentry, int err) |
| 507 | { | 507 | { |
| 508 | struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); | 508 | struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); |
| 509 | struct inode *parent = dentry->d_parent->d_inode; | 509 | struct inode *parent = dentry->d_parent->d_inode; /* we hold i_mutex */ |
| 510 | 510 | ||
| 511 | /* .snap dir? */ | 511 | /* .snap dir? */ |
| 512 | if (err == -ENOENT && | 512 | if (err == -ENOENT && |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 66a8939cc518..fee028b5332e 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
| @@ -621,6 +621,12 @@ static void __unregister_request(struct ceph_mds_client *mdsc, | |||
| 621 | */ | 621 | */ |
| 622 | struct dentry *get_nonsnap_parent(struct dentry *dentry) | 622 | struct dentry *get_nonsnap_parent(struct dentry *dentry) |
| 623 | { | 623 | { |
| 624 | /* | ||
| 625 | * we don't need to worry about protecting the d_parent access | ||
| 626 | * here because we never renaming inside the snapped namespace | ||
| 627 | * except to resplice to another snapdir, and either the old or new | ||
| 628 | * result is a valid result. | ||
| 629 | */ | ||
| 624 | while (!IS_ROOT(dentry) && ceph_snap(dentry->d_inode) != CEPH_NOSNAP) | 630 | while (!IS_ROOT(dentry) && ceph_snap(dentry->d_inode) != CEPH_NOSNAP) |
| 625 | dentry = dentry->d_parent; | 631 | dentry = dentry->d_parent; |
| 626 | return dentry; | 632 | return dentry; |
| @@ -656,7 +662,9 @@ static int __choose_mds(struct ceph_mds_client *mdsc, | |||
| 656 | if (req->r_inode) { | 662 | if (req->r_inode) { |
| 657 | inode = req->r_inode; | 663 | inode = req->r_inode; |
| 658 | } else if (req->r_dentry) { | 664 | } else if (req->r_dentry) { |
| 659 | struct inode *dir = req->r_dentry->d_parent->d_inode; | 665 | /* ignore race with rename; old or new d_parent is okay */ |
| 666 | struct dentry *parent = req->r_dentry->d_parent; | ||
| 667 | struct inode *dir = parent->d_inode; | ||
| 660 | 668 | ||
| 661 | if (dir->i_sb != mdsc->fsc->sb) { | 669 | if (dir->i_sb != mdsc->fsc->sb) { |
| 662 | /* not this fs! */ | 670 | /* not this fs! */ |
| @@ -664,8 +672,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc, | |||
| 664 | } else if (ceph_snap(dir) != CEPH_NOSNAP) { | 672 | } else if (ceph_snap(dir) != CEPH_NOSNAP) { |
| 665 | /* direct snapped/virtual snapdir requests | 673 | /* direct snapped/virtual snapdir requests |
| 666 | * based on parent dir inode */ | 674 | * based on parent dir inode */ |
| 667 | struct dentry *dn = | 675 | struct dentry *dn = get_nonsnap_parent(parent); |
| 668 | get_nonsnap_parent(req->r_dentry->d_parent); | ||
| 669 | inode = dn->d_inode; | 676 | inode = dn->d_inode; |
| 670 | dout("__choose_mds using nonsnap parent %p\n", inode); | 677 | dout("__choose_mds using nonsnap parent %p\n", inode); |
| 671 | } else if (req->r_dentry->d_inode) { | 678 | } else if (req->r_dentry->d_inode) { |
