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--; |