diff options
Diffstat (limited to 'fs/ceph/dir.c')
| -rw-r--r-- | fs/ceph/dir.c | 97 |
1 files changed, 44 insertions, 53 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index a1986eb52045..e0a2dc6fcafc 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | #include "ceph_debug.h" | 1 | #include <linux/ceph/ceph_debug.h> |
| 2 | 2 | ||
| 3 | #include <linux/spinlock.h> | 3 | #include <linux/spinlock.h> |
| 4 | #include <linux/fs_struct.h> | 4 | #include <linux/fs_struct.h> |
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
| 8 | 8 | ||
| 9 | #include "super.h" | 9 | #include "super.h" |
| 10 | #include "mds_client.h" | ||
| 10 | 11 | ||
| 11 | /* | 12 | /* |
| 12 | * Directory operations: readdir, lookup, create, link, unlink, | 13 | * Directory operations: readdir, lookup, create, link, unlink, |
| @@ -94,10 +95,7 @@ static unsigned fpos_off(loff_t p) | |||
| 94 | */ | 95 | */ |
| 95 | static int __dcache_readdir(struct file *filp, | 96 | static int __dcache_readdir(struct file *filp, |
| 96 | void *dirent, filldir_t filldir) | 97 | void *dirent, filldir_t filldir) |
| 97 | __releases(inode->i_lock) | ||
| 98 | __acquires(inode->i_lock) | ||
| 99 | { | 98 | { |
| 100 | struct inode *inode = filp->f_dentry->d_inode; | ||
| 101 | struct ceph_file_info *fi = filp->private_data; | 99 | struct ceph_file_info *fi = filp->private_data; |
| 102 | struct dentry *parent = filp->f_dentry; | 100 | struct dentry *parent = filp->f_dentry; |
| 103 | struct inode *dir = parent->d_inode; | 101 | struct inode *dir = parent->d_inode; |
| @@ -153,7 +151,6 @@ more: | |||
| 153 | 151 | ||
| 154 | atomic_inc(&dentry->d_count); | 152 | atomic_inc(&dentry->d_count); |
| 155 | spin_unlock(&dcache_lock); | 153 | spin_unlock(&dcache_lock); |
| 156 | spin_unlock(&inode->i_lock); | ||
| 157 | 154 | ||
| 158 | dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos, | 155 | dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos, |
| 159 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); | 156 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); |
| @@ -171,35 +168,30 @@ more: | |||
| 171 | } else { | 168 | } else { |
| 172 | dput(last); | 169 | dput(last); |
| 173 | } | 170 | } |
| 174 | last = NULL; | ||
| 175 | } | 171 | } |
| 176 | |||
| 177 | spin_lock(&inode->i_lock); | ||
| 178 | spin_lock(&dcache_lock); | ||
| 179 | |||
| 180 | last = dentry; | 172 | last = dentry; |
| 181 | 173 | ||
| 182 | if (err < 0) | 174 | if (err < 0) |
| 183 | goto out_unlock; | 175 | goto out; |
| 184 | 176 | ||
| 185 | p = p->prev; | ||
| 186 | filp->f_pos++; | 177 | filp->f_pos++; |
| 187 | 178 | ||
| 188 | /* make sure a dentry wasn't dropped while we didn't have dcache_lock */ | 179 | /* make sure a dentry wasn't dropped while we didn't have dcache_lock */ |
| 189 | if ((ceph_inode(dir)->i_ceph_flags & CEPH_I_COMPLETE)) | 180 | if (!ceph_i_test(dir, CEPH_I_COMPLETE)) { |
| 190 | goto more; | 181 | dout(" lost I_COMPLETE on %p; falling back to mds\n", dir); |
| 191 | dout(" lost I_COMPLETE on %p; falling back to mds\n", dir); | 182 | err = -EAGAIN; |
| 192 | err = -EAGAIN; | 183 | goto out; |
| 184 | } | ||
| 185 | |||
| 186 | spin_lock(&dcache_lock); | ||
| 187 | p = p->prev; /* advance to next dentry */ | ||
| 188 | goto more; | ||
| 193 | 189 | ||
| 194 | out_unlock: | 190 | out_unlock: |
| 195 | spin_unlock(&dcache_lock); | 191 | spin_unlock(&dcache_lock); |
| 196 | 192 | out: | |
| 197 | if (last) { | 193 | if (last) |
| 198 | spin_unlock(&inode->i_lock); | ||
| 199 | dput(last); | 194 | dput(last); |
| 200 | spin_lock(&inode->i_lock); | ||
| 201 | } | ||
| 202 | |||
| 203 | return err; | 195 | return err; |
| 204 | } | 196 | } |
| 205 | 197 | ||
| @@ -227,15 +219,15 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 227 | struct ceph_file_info *fi = filp->private_data; | 219 | struct ceph_file_info *fi = filp->private_data; |
| 228 | struct inode *inode = filp->f_dentry->d_inode; | 220 | struct inode *inode = filp->f_dentry->d_inode; |
| 229 | struct ceph_inode_info *ci = ceph_inode(inode); | 221 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 230 | struct ceph_client *client = ceph_inode_to_client(inode); | 222 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
| 231 | struct ceph_mds_client *mdsc = &client->mdsc; | 223 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 232 | unsigned frag = fpos_frag(filp->f_pos); | 224 | unsigned frag = fpos_frag(filp->f_pos); |
| 233 | int off = fpos_off(filp->f_pos); | 225 | int off = fpos_off(filp->f_pos); |
| 234 | int err; | 226 | int err; |
| 235 | u32 ftype; | 227 | u32 ftype; |
| 236 | struct ceph_mds_reply_info_parsed *rinfo; | 228 | struct ceph_mds_reply_info_parsed *rinfo; |
| 237 | const int max_entries = client->mount_args->max_readdir; | 229 | const int max_entries = fsc->mount_options->max_readdir; |
| 238 | const int max_bytes = client->mount_args->max_readdir_bytes; | 230 | const int max_bytes = fsc->mount_options->max_readdir_bytes; |
| 239 | 231 | ||
| 240 | dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off); | 232 | dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off); |
| 241 | if (fi->at_end) | 233 | if (fi->at_end) |
| @@ -267,17 +259,17 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 267 | /* can we use the dcache? */ | 259 | /* can we use the dcache? */ |
| 268 | spin_lock(&inode->i_lock); | 260 | spin_lock(&inode->i_lock); |
| 269 | if ((filp->f_pos == 2 || fi->dentry) && | 261 | if ((filp->f_pos == 2 || fi->dentry) && |
| 270 | !ceph_test_opt(client, NOASYNCREADDIR) && | 262 | !ceph_test_mount_opt(fsc, NOASYNCREADDIR) && |
| 271 | ceph_snap(inode) != CEPH_SNAPDIR && | 263 | ceph_snap(inode) != CEPH_SNAPDIR && |
| 272 | (ci->i_ceph_flags & CEPH_I_COMPLETE) && | 264 | (ci->i_ceph_flags & CEPH_I_COMPLETE) && |
| 273 | __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { | 265 | __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { |
| 266 | spin_unlock(&inode->i_lock); | ||
| 274 | err = __dcache_readdir(filp, dirent, filldir); | 267 | err = __dcache_readdir(filp, dirent, filldir); |
| 275 | if (err != -EAGAIN) { | 268 | if (err != -EAGAIN) |
| 276 | spin_unlock(&inode->i_lock); | ||
| 277 | return err; | 269 | return err; |
| 278 | } | 270 | } else { |
| 271 | spin_unlock(&inode->i_lock); | ||
| 279 | } | 272 | } |
| 280 | spin_unlock(&inode->i_lock); | ||
| 281 | if (fi->dentry) { | 273 | if (fi->dentry) { |
| 282 | err = note_last_dentry(fi, fi->dentry->d_name.name, | 274 | err = note_last_dentry(fi, fi->dentry->d_name.name, |
| 283 | fi->dentry->d_name.len); | 275 | fi->dentry->d_name.len); |
| @@ -487,14 +479,13 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin) | |||
| 487 | struct dentry *ceph_finish_lookup(struct ceph_mds_request *req, | 479 | struct dentry *ceph_finish_lookup(struct ceph_mds_request *req, |
| 488 | struct dentry *dentry, int err) | 480 | struct dentry *dentry, int err) |
| 489 | { | 481 | { |
| 490 | struct ceph_client *client = ceph_sb_to_client(dentry->d_sb); | 482 | struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); |
| 491 | struct inode *parent = dentry->d_parent->d_inode; | 483 | struct inode *parent = dentry->d_parent->d_inode; |
| 492 | 484 | ||
| 493 | /* .snap dir? */ | 485 | /* .snap dir? */ |
| 494 | if (err == -ENOENT && | 486 | if (err == -ENOENT && |
| 495 | ceph_vino(parent).ino != CEPH_INO_ROOT && /* no .snap in root dir */ | ||
| 496 | strcmp(dentry->d_name.name, | 487 | strcmp(dentry->d_name.name, |
| 497 | client->mount_args->snapdir_name) == 0) { | 488 | fsc->mount_options->snapdir_name) == 0) { |
| 498 | struct inode *inode = ceph_get_snapdir(parent); | 489 | struct inode *inode = ceph_get_snapdir(parent); |
| 499 | dout("ENOENT on snapdir %p '%.*s', linking to snapdir %p\n", | 490 | dout("ENOENT on snapdir %p '%.*s', linking to snapdir %p\n", |
| 500 | dentry, dentry->d_name.len, dentry->d_name.name, inode); | 491 | dentry, dentry->d_name.len, dentry->d_name.name, inode); |
| @@ -539,8 +530,8 @@ static int is_root_ceph_dentry(struct inode *inode, struct dentry *dentry) | |||
| 539 | static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | 530 | static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, |
| 540 | struct nameidata *nd) | 531 | struct nameidata *nd) |
| 541 | { | 532 | { |
| 542 | struct ceph_client *client = ceph_sb_to_client(dir->i_sb); | 533 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
| 543 | struct ceph_mds_client *mdsc = &client->mdsc; | 534 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 544 | struct ceph_mds_request *req; | 535 | struct ceph_mds_request *req; |
| 545 | int op; | 536 | int op; |
| 546 | int err; | 537 | int err; |
| @@ -572,7 +563,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
| 572 | spin_lock(&dir->i_lock); | 563 | spin_lock(&dir->i_lock); |
| 573 | dout(" dir %p flags are %d\n", dir, ci->i_ceph_flags); | 564 | dout(" dir %p flags are %d\n", dir, ci->i_ceph_flags); |
| 574 | if (strncmp(dentry->d_name.name, | 565 | if (strncmp(dentry->d_name.name, |
| 575 | client->mount_args->snapdir_name, | 566 | fsc->mount_options->snapdir_name, |
| 576 | dentry->d_name.len) && | 567 | dentry->d_name.len) && |
| 577 | !is_root_ceph_dentry(dir, dentry) && | 568 | !is_root_ceph_dentry(dir, dentry) && |
| 578 | (ci->i_ceph_flags & CEPH_I_COMPLETE) && | 569 | (ci->i_ceph_flags & CEPH_I_COMPLETE) && |
| @@ -629,8 +620,8 @@ int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry) | |||
| 629 | static int ceph_mknod(struct inode *dir, struct dentry *dentry, | 620 | static int ceph_mknod(struct inode *dir, struct dentry *dentry, |
| 630 | int mode, dev_t rdev) | 621 | int mode, dev_t rdev) |
| 631 | { | 622 | { |
| 632 | struct ceph_client *client = ceph_sb_to_client(dir->i_sb); | 623 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
| 633 | struct ceph_mds_client *mdsc = &client->mdsc; | 624 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 634 | struct ceph_mds_request *req; | 625 | struct ceph_mds_request *req; |
| 635 | int err; | 626 | int err; |
| 636 | 627 | ||
| @@ -685,8 +676,8 @@ static int ceph_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 685 | static int ceph_symlink(struct inode *dir, struct dentry *dentry, | 676 | static int ceph_symlink(struct inode *dir, struct dentry *dentry, |
| 686 | const char *dest) | 677 | const char *dest) |
| 687 | { | 678 | { |
| 688 | struct ceph_client *client = ceph_sb_to_client(dir->i_sb); | 679 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
| 689 | struct ceph_mds_client *mdsc = &client->mdsc; | 680 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 690 | struct ceph_mds_request *req; | 681 | struct ceph_mds_request *req; |
| 691 | int err; | 682 | int err; |
| 692 | 683 | ||
| @@ -716,8 +707,8 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry, | |||
| 716 | 707 | ||
| 717 | static int ceph_mkdir(struct inode *dir, struct dentry *dentry, int mode) | 708 | static int ceph_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
| 718 | { | 709 | { |
| 719 | struct ceph_client *client = ceph_sb_to_client(dir->i_sb); | 710 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
| 720 | struct ceph_mds_client *mdsc = &client->mdsc; | 711 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 721 | struct ceph_mds_request *req; | 712 | struct ceph_mds_request *req; |
| 722 | int err = -EROFS; | 713 | int err = -EROFS; |
| 723 | int op; | 714 | int op; |
| @@ -758,8 +749,8 @@ out: | |||
| 758 | static int ceph_link(struct dentry *old_dentry, struct inode *dir, | 749 | static int ceph_link(struct dentry *old_dentry, struct inode *dir, |
| 759 | struct dentry *dentry) | 750 | struct dentry *dentry) |
| 760 | { | 751 | { |
| 761 | struct ceph_client *client = ceph_sb_to_client(dir->i_sb); | 752 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
| 762 | struct ceph_mds_client *mdsc = &client->mdsc; | 753 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 763 | struct ceph_mds_request *req; | 754 | struct ceph_mds_request *req; |
| 764 | int err; | 755 | int err; |
| 765 | 756 | ||
| @@ -813,8 +804,8 @@ static int drop_caps_for_unlink(struct inode *inode) | |||
| 813 | */ | 804 | */ |
| 814 | static int ceph_unlink(struct inode *dir, struct dentry *dentry) | 805 | static int ceph_unlink(struct inode *dir, struct dentry *dentry) |
| 815 | { | 806 | { |
| 816 | struct ceph_client *client = ceph_sb_to_client(dir->i_sb); | 807 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
| 817 | struct ceph_mds_client *mdsc = &client->mdsc; | 808 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 818 | struct inode *inode = dentry->d_inode; | 809 | struct inode *inode = dentry->d_inode; |
| 819 | struct ceph_mds_request *req; | 810 | struct ceph_mds_request *req; |
| 820 | int err = -EROFS; | 811 | int err = -EROFS; |
| @@ -854,8 +845,8 @@ out: | |||
| 854 | static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, | 845 | static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, |
| 855 | struct inode *new_dir, struct dentry *new_dentry) | 846 | struct inode *new_dir, struct dentry *new_dentry) |
| 856 | { | 847 | { |
| 857 | struct ceph_client *client = ceph_sb_to_client(old_dir->i_sb); | 848 | struct ceph_fs_client *fsc = ceph_sb_to_client(old_dir->i_sb); |
| 858 | struct ceph_mds_client *mdsc = &client->mdsc; | 849 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 859 | struct ceph_mds_request *req; | 850 | struct ceph_mds_request *req; |
| 860 | int err; | 851 | int err; |
| 861 | 852 | ||
| @@ -1076,7 +1067,7 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size, | |||
| 1076 | struct ceph_inode_info *ci = ceph_inode(inode); | 1067 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 1077 | int left; | 1068 | int left; |
| 1078 | 1069 | ||
| 1079 | if (!ceph_test_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT)) | 1070 | if (!ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT)) |
| 1080 | return -EISDIR; | 1071 | return -EISDIR; |
| 1081 | 1072 | ||
| 1082 | if (!cf->dir_info) { | 1073 | if (!cf->dir_info) { |
| @@ -1177,7 +1168,7 @@ void ceph_dentry_lru_add(struct dentry *dn) | |||
| 1177 | dout("dentry_lru_add %p %p '%.*s'\n", di, dn, | 1168 | dout("dentry_lru_add %p %p '%.*s'\n", di, dn, |
| 1178 | dn->d_name.len, dn->d_name.name); | 1169 | dn->d_name.len, dn->d_name.name); |
| 1179 | if (di) { | 1170 | if (di) { |
| 1180 | mdsc = &ceph_sb_to_client(dn->d_sb)->mdsc; | 1171 | mdsc = ceph_sb_to_client(dn->d_sb)->mdsc; |
| 1181 | spin_lock(&mdsc->dentry_lru_lock); | 1172 | spin_lock(&mdsc->dentry_lru_lock); |
| 1182 | list_add_tail(&di->lru, &mdsc->dentry_lru); | 1173 | list_add_tail(&di->lru, &mdsc->dentry_lru); |
| 1183 | mdsc->num_dentry++; | 1174 | mdsc->num_dentry++; |
| @@ -1193,7 +1184,7 @@ void ceph_dentry_lru_touch(struct dentry *dn) | |||
| 1193 | dout("dentry_lru_touch %p %p '%.*s' (offset %lld)\n", di, dn, | 1184 | dout("dentry_lru_touch %p %p '%.*s' (offset %lld)\n", di, dn, |
| 1194 | dn->d_name.len, dn->d_name.name, di->offset); | 1185 | dn->d_name.len, dn->d_name.name, di->offset); |
| 1195 | if (di) { | 1186 | if (di) { |
| 1196 | mdsc = &ceph_sb_to_client(dn->d_sb)->mdsc; | 1187 | mdsc = ceph_sb_to_client(dn->d_sb)->mdsc; |
| 1197 | spin_lock(&mdsc->dentry_lru_lock); | 1188 | spin_lock(&mdsc->dentry_lru_lock); |
| 1198 | list_move_tail(&di->lru, &mdsc->dentry_lru); | 1189 | list_move_tail(&di->lru, &mdsc->dentry_lru); |
| 1199 | spin_unlock(&mdsc->dentry_lru_lock); | 1190 | spin_unlock(&mdsc->dentry_lru_lock); |
| @@ -1208,7 +1199,7 @@ void ceph_dentry_lru_del(struct dentry *dn) | |||
| 1208 | dout("dentry_lru_del %p %p '%.*s'\n", di, dn, | 1199 | dout("dentry_lru_del %p %p '%.*s'\n", di, dn, |
| 1209 | dn->d_name.len, dn->d_name.name); | 1200 | dn->d_name.len, dn->d_name.name); |
| 1210 | if (di) { | 1201 | if (di) { |
| 1211 | mdsc = &ceph_sb_to_client(dn->d_sb)->mdsc; | 1202 | mdsc = ceph_sb_to_client(dn->d_sb)->mdsc; |
| 1212 | spin_lock(&mdsc->dentry_lru_lock); | 1203 | spin_lock(&mdsc->dentry_lru_lock); |
| 1213 | list_del_init(&di->lru); | 1204 | list_del_init(&di->lru); |
| 1214 | mdsc->num_dentry--; | 1205 | mdsc->num_dentry--; |
