diff options
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r-- | fs/ceph/inode.c | 133 |
1 files changed, 75 insertions, 58 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 261f3e6c0bcf..5d893d31e399 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -69,7 +69,7 @@ struct inode *ceph_get_snapdir(struct inode *parent) | |||
69 | 69 | ||
70 | BUG_ON(!S_ISDIR(parent->i_mode)); | 70 | BUG_ON(!S_ISDIR(parent->i_mode)); |
71 | if (IS_ERR(inode)) | 71 | if (IS_ERR(inode)) |
72 | return ERR_PTR(PTR_ERR(inode)); | 72 | return inode; |
73 | inode->i_mode = parent->i_mode; | 73 | inode->i_mode = parent->i_mode; |
74 | inode->i_uid = parent->i_uid; | 74 | inode->i_uid = parent->i_uid; |
75 | inode->i_gid = parent->i_gid; | 75 | inode->i_gid = parent->i_gid; |
@@ -384,7 +384,7 @@ void ceph_destroy_inode(struct inode *inode) | |||
384 | */ | 384 | */ |
385 | if (ci->i_snap_realm) { | 385 | if (ci->i_snap_realm) { |
386 | struct ceph_mds_client *mdsc = | 386 | struct ceph_mds_client *mdsc = |
387 | &ceph_client(ci->vfs_inode.i_sb)->mdsc; | 387 | &ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; |
388 | struct ceph_snap_realm *realm = ci->i_snap_realm; | 388 | struct ceph_snap_realm *realm = ci->i_snap_realm; |
389 | 389 | ||
390 | dout(" dropping residual ref to snap realm %p\n", realm); | 390 | dout(" dropping residual ref to snap realm %p\n", realm); |
@@ -442,8 +442,9 @@ int ceph_fill_file_size(struct inode *inode, int issued, | |||
442 | * the file is either opened or mmaped | 442 | * the file is either opened or mmaped |
443 | */ | 443 | */ |
444 | if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_RD| | 444 | if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_RD| |
445 | CEPH_CAP_FILE_WR|CEPH_CAP_FILE_BUFFER| | 445 | CEPH_CAP_FILE_WR|CEPH_CAP_FILE_BUFFER| |
446 | CEPH_CAP_FILE_EXCL)) || | 446 | CEPH_CAP_FILE_EXCL| |
447 | CEPH_CAP_FILE_LAZYIO)) || | ||
447 | mapping_mapped(inode->i_mapping) || | 448 | mapping_mapped(inode->i_mapping) || |
448 | __ceph_caps_file_wanted(ci)) { | 449 | __ceph_caps_file_wanted(ci)) { |
449 | ci->i_truncate_pending++; | 450 | ci->i_truncate_pending++; |
@@ -619,11 +620,12 @@ static int fill_inode(struct inode *inode, | |||
619 | memcpy(ci->i_xattrs.blob->vec.iov_base, | 620 | memcpy(ci->i_xattrs.blob->vec.iov_base, |
620 | iinfo->xattr_data, iinfo->xattr_len); | 621 | iinfo->xattr_data, iinfo->xattr_len); |
621 | ci->i_xattrs.version = le64_to_cpu(info->xattr_version); | 622 | ci->i_xattrs.version = le64_to_cpu(info->xattr_version); |
623 | xattr_blob = NULL; | ||
622 | } | 624 | } |
623 | 625 | ||
624 | inode->i_mapping->a_ops = &ceph_aops; | 626 | inode->i_mapping->a_ops = &ceph_aops; |
625 | inode->i_mapping->backing_dev_info = | 627 | inode->i_mapping->backing_dev_info = |
626 | &ceph_client(inode->i_sb)->backing_dev_info; | 628 | &ceph_sb_to_client(inode->i_sb)->backing_dev_info; |
627 | 629 | ||
628 | switch (inode->i_mode & S_IFMT) { | 630 | switch (inode->i_mode & S_IFMT) { |
629 | case S_IFIFO: | 631 | case S_IFIFO: |
@@ -674,14 +676,15 @@ static int fill_inode(struct inode *inode, | |||
674 | /* set dir completion flag? */ | 676 | /* set dir completion flag? */ |
675 | if (ci->i_files == 0 && ci->i_subdirs == 0 && | 677 | if (ci->i_files == 0 && ci->i_subdirs == 0 && |
676 | ceph_snap(inode) == CEPH_NOSNAP && | 678 | ceph_snap(inode) == CEPH_NOSNAP && |
677 | (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED)) { | 679 | (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) && |
680 | (ci->i_ceph_flags & CEPH_I_COMPLETE) == 0) { | ||
678 | dout(" marking %p complete (empty)\n", inode); | 681 | dout(" marking %p complete (empty)\n", inode); |
679 | ci->i_ceph_flags |= CEPH_I_COMPLETE; | 682 | ci->i_ceph_flags |= CEPH_I_COMPLETE; |
680 | ci->i_max_offset = 2; | 683 | ci->i_max_offset = 2; |
681 | } | 684 | } |
682 | 685 | ||
683 | /* it may be better to set st_size in getattr instead? */ | 686 | /* it may be better to set st_size in getattr instead? */ |
684 | if (ceph_test_opt(ceph_client(inode->i_sb), RBYTES)) | 687 | if (ceph_test_opt(ceph_sb_to_client(inode->i_sb), RBYTES)) |
685 | inode->i_size = ci->i_rbytes; | 688 | inode->i_size = ci->i_rbytes; |
686 | break; | 689 | break; |
687 | default: | 690 | default: |
@@ -733,6 +736,10 @@ no_change: | |||
733 | __ceph_get_fmode(ci, cap_fmode); | 736 | __ceph_get_fmode(ci, cap_fmode); |
734 | spin_unlock(&inode->i_lock); | 737 | spin_unlock(&inode->i_lock); |
735 | } | 738 | } |
739 | } else if (cap_fmode >= 0) { | ||
740 | pr_warning("mds issued no caps on %llx.%llx\n", | ||
741 | ceph_vinop(inode)); | ||
742 | __ceph_get_fmode(ci, cap_fmode); | ||
736 | } | 743 | } |
737 | 744 | ||
738 | /* update delegation info? */ | 745 | /* update delegation info? */ |
@@ -798,6 +805,37 @@ out_unlock: | |||
798 | } | 805 | } |
799 | 806 | ||
800 | /* | 807 | /* |
808 | * Set dentry's directory position based on the current dir's max, and | ||
809 | * order it in d_subdirs, so that dcache_readdir behaves. | ||
810 | */ | ||
811 | static void ceph_set_dentry_offset(struct dentry *dn) | ||
812 | { | ||
813 | struct dentry *dir = dn->d_parent; | ||
814 | struct inode *inode = dn->d_parent->d_inode; | ||
815 | struct ceph_dentry_info *di; | ||
816 | |||
817 | BUG_ON(!inode); | ||
818 | |||
819 | di = ceph_dentry(dn); | ||
820 | |||
821 | spin_lock(&inode->i_lock); | ||
822 | if ((ceph_inode(inode)->i_ceph_flags & CEPH_I_COMPLETE) == 0) { | ||
823 | spin_unlock(&inode->i_lock); | ||
824 | return; | ||
825 | } | ||
826 | di->offset = ceph_inode(inode)->i_max_offset++; | ||
827 | spin_unlock(&inode->i_lock); | ||
828 | |||
829 | spin_lock(&dcache_lock); | ||
830 | spin_lock(&dn->d_lock); | ||
831 | list_move(&dn->d_u.d_child, &dir->d_subdirs); | ||
832 | dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset, | ||
833 | dn->d_u.d_child.prev, dn->d_u.d_child.next); | ||
834 | spin_unlock(&dn->d_lock); | ||
835 | spin_unlock(&dcache_lock); | ||
836 | } | ||
837 | |||
838 | /* | ||
801 | * splice a dentry to an inode. | 839 | * splice a dentry to an inode. |
802 | * caller must hold directory i_mutex for this to be safe. | 840 | * caller must hold directory i_mutex for this to be safe. |
803 | * | 841 | * |
@@ -810,13 +848,15 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, | |||
810 | { | 848 | { |
811 | struct dentry *realdn; | 849 | struct dentry *realdn; |
812 | 850 | ||
851 | BUG_ON(dn->d_inode); | ||
852 | |||
813 | /* dn must be unhashed */ | 853 | /* dn must be unhashed */ |
814 | if (!d_unhashed(dn)) | 854 | if (!d_unhashed(dn)) |
815 | d_drop(dn); | 855 | d_drop(dn); |
816 | realdn = d_materialise_unique(dn, in); | 856 | realdn = d_materialise_unique(dn, in); |
817 | if (IS_ERR(realdn)) { | 857 | if (IS_ERR(realdn)) { |
818 | pr_err("splice_dentry error %p inode %p ino %llx.%llx\n", | 858 | pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n", |
819 | dn, in, ceph_vinop(in)); | 859 | PTR_ERR(realdn), dn, in, ceph_vinop(in)); |
820 | if (prehash) | 860 | if (prehash) |
821 | *prehash = false; /* don't rehash on error */ | 861 | *prehash = false; /* don't rehash on error */ |
822 | dn = realdn; /* note realdn contains the error */ | 862 | dn = realdn; /* note realdn contains the error */ |
@@ -831,44 +871,17 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, | |||
831 | dn = realdn; | 871 | dn = realdn; |
832 | } else { | 872 | } else { |
833 | BUG_ON(!ceph_dentry(dn)); | 873 | BUG_ON(!ceph_dentry(dn)); |
834 | |||
835 | dout("dn %p attached to %p ino %llx.%llx\n", | 874 | dout("dn %p attached to %p ino %llx.%llx\n", |
836 | dn, dn->d_inode, ceph_vinop(dn->d_inode)); | 875 | dn, dn->d_inode, ceph_vinop(dn->d_inode)); |
837 | } | 876 | } |
838 | if ((!prehash || *prehash) && d_unhashed(dn)) | 877 | if ((!prehash || *prehash) && d_unhashed(dn)) |
839 | d_rehash(dn); | 878 | d_rehash(dn); |
879 | ceph_set_dentry_offset(dn); | ||
840 | out: | 880 | out: |
841 | return dn; | 881 | return dn; |
842 | } | 882 | } |
843 | 883 | ||
844 | /* | 884 | /* |
845 | * Set dentry's directory position based on the current dir's max, and | ||
846 | * order it in d_subdirs, so that dcache_readdir behaves. | ||
847 | */ | ||
848 | static void ceph_set_dentry_offset(struct dentry *dn) | ||
849 | { | ||
850 | struct dentry *dir = dn->d_parent; | ||
851 | struct inode *inode = dn->d_parent->d_inode; | ||
852 | struct ceph_dentry_info *di; | ||
853 | |||
854 | BUG_ON(!inode); | ||
855 | |||
856 | di = ceph_dentry(dn); | ||
857 | |||
858 | spin_lock(&inode->i_lock); | ||
859 | di->offset = ceph_inode(inode)->i_max_offset++; | ||
860 | spin_unlock(&inode->i_lock); | ||
861 | |||
862 | spin_lock(&dcache_lock); | ||
863 | spin_lock(&dn->d_lock); | ||
864 | list_move_tail(&dir->d_subdirs, &dn->d_u.d_child); | ||
865 | dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset, | ||
866 | dn->d_u.d_child.prev, dn->d_u.d_child.next); | ||
867 | spin_unlock(&dn->d_lock); | ||
868 | spin_unlock(&dcache_lock); | ||
869 | } | ||
870 | |||
871 | /* | ||
872 | * Incorporate results into the local cache. This is either just | 885 | * Incorporate results into the local cache. This is either just |
873 | * one inode, or a directory, dentry, and possibly linked-to inode (e.g., | 886 | * one inode, or a directory, dentry, and possibly linked-to inode (e.g., |
874 | * after a lookup). | 887 | * after a lookup). |
@@ -929,14 +942,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
929 | 942 | ||
930 | if (!rinfo->head->is_target && !rinfo->head->is_dentry) { | 943 | if (!rinfo->head->is_target && !rinfo->head->is_dentry) { |
931 | dout("fill_trace reply is empty!\n"); | 944 | dout("fill_trace reply is empty!\n"); |
932 | if (rinfo->head->result == 0 && req->r_locked_dir) { | 945 | if (rinfo->head->result == 0 && req->r_locked_dir) |
933 | struct ceph_inode_info *ci = | 946 | ceph_invalidate_dir_request(req); |
934 | ceph_inode(req->r_locked_dir); | ||
935 | dout(" clearing %p complete (empty trace)\n", | ||
936 | req->r_locked_dir); | ||
937 | ci->i_ceph_flags &= ~CEPH_I_COMPLETE; | ||
938 | ci->i_release_count++; | ||
939 | } | ||
940 | return 0; | 947 | return 0; |
941 | } | 948 | } |
942 | 949 | ||
@@ -1007,13 +1014,18 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
1007 | req->r_old_dentry->d_name.len, | 1014 | req->r_old_dentry->d_name.len, |
1008 | req->r_old_dentry->d_name.name, | 1015 | req->r_old_dentry->d_name.name, |
1009 | dn, dn->d_name.len, dn->d_name.name); | 1016 | dn, dn->d_name.len, dn->d_name.name); |
1017 | |||
1010 | /* ensure target dentry is invalidated, despite | 1018 | /* ensure target dentry is invalidated, despite |
1011 | rehashing bug in vfs_rename_dir */ | 1019 | rehashing bug in vfs_rename_dir */ |
1012 | dn->d_time = jiffies; | 1020 | ceph_invalidate_dentry_lease(dn); |
1013 | ceph_dentry(dn)->lease_shared_gen = 0; | 1021 | |
1014 | /* take overwritten dentry's readdir offset */ | 1022 | /* take overwritten dentry's readdir offset */ |
1023 | dout("dn %p gets %p offset %lld (old offset %lld)\n", | ||
1024 | req->r_old_dentry, dn, ceph_dentry(dn)->offset, | ||
1025 | ceph_dentry(req->r_old_dentry)->offset); | ||
1015 | ceph_dentry(req->r_old_dentry)->offset = | 1026 | ceph_dentry(req->r_old_dentry)->offset = |
1016 | ceph_dentry(dn)->offset; | 1027 | ceph_dentry(dn)->offset; |
1028 | |||
1017 | dn = req->r_old_dentry; /* use old_dentry */ | 1029 | dn = req->r_old_dentry; /* use old_dentry */ |
1018 | in = dn->d_inode; | 1030 | in = dn->d_inode; |
1019 | } | 1031 | } |
@@ -1055,7 +1067,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
1055 | goto done; | 1067 | goto done; |
1056 | } | 1068 | } |
1057 | req->r_dentry = dn; /* may have spliced */ | 1069 | req->r_dentry = dn; /* may have spliced */ |
1058 | ceph_set_dentry_offset(dn); | ||
1059 | igrab(in); | 1070 | igrab(in); |
1060 | } else if (ceph_ino(in) == vino.ino && | 1071 | } else if (ceph_ino(in) == vino.ino && |
1061 | ceph_snap(in) == vino.snap) { | 1072 | ceph_snap(in) == vino.snap) { |
@@ -1098,7 +1109,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
1098 | err = PTR_ERR(dn); | 1109 | err = PTR_ERR(dn); |
1099 | goto done; | 1110 | goto done; |
1100 | } | 1111 | } |
1101 | ceph_set_dentry_offset(dn); | ||
1102 | req->r_dentry = dn; /* may have spliced */ | 1112 | req->r_dentry = dn; /* may have spliced */ |
1103 | igrab(in); | 1113 | igrab(in); |
1104 | rinfo->head->is_dentry = 1; /* fool notrace handlers */ | 1114 | rinfo->head->is_dentry = 1; /* fool notrace handlers */ |
@@ -1190,8 +1200,10 @@ retry_lookup: | |||
1190 | goto out; | 1200 | goto out; |
1191 | } | 1201 | } |
1192 | err = ceph_init_dentry(dn); | 1202 | err = ceph_init_dentry(dn); |
1193 | if (err < 0) | 1203 | if (err < 0) { |
1204 | dput(dn); | ||
1194 | goto out; | 1205 | goto out; |
1206 | } | ||
1195 | } else if (dn->d_inode && | 1207 | } else if (dn->d_inode && |
1196 | (ceph_ino(dn->d_inode) != vino.ino || | 1208 | (ceph_ino(dn->d_inode) != vino.ino || |
1197 | ceph_snap(dn->d_inode) != vino.snap)) { | 1209 | ceph_snap(dn->d_inode) != vino.snap)) { |
@@ -1225,18 +1237,23 @@ retry_lookup: | |||
1225 | goto out; | 1237 | goto out; |
1226 | } | 1238 | } |
1227 | dn = splice_dentry(dn, in, NULL); | 1239 | dn = splice_dentry(dn, in, NULL); |
1240 | if (IS_ERR(dn)) | ||
1241 | dn = NULL; | ||
1228 | } | 1242 | } |
1229 | 1243 | ||
1230 | if (fill_inode(in, &rinfo->dir_in[i], NULL, session, | 1244 | if (fill_inode(in, &rinfo->dir_in[i], NULL, session, |
1231 | req->r_request_started, -1, | 1245 | req->r_request_started, -1, |
1232 | &req->r_caps_reservation) < 0) { | 1246 | &req->r_caps_reservation) < 0) { |
1233 | pr_err("fill_inode badness on %p\n", in); | 1247 | pr_err("fill_inode badness on %p\n", in); |
1234 | dput(dn); | 1248 | goto next_item; |
1235 | continue; | ||
1236 | } | 1249 | } |
1237 | update_dentry_lease(dn, rinfo->dir_dlease[i], | 1250 | if (dn) |
1238 | req->r_session, req->r_request_started); | 1251 | update_dentry_lease(dn, rinfo->dir_dlease[i], |
1239 | dput(dn); | 1252 | req->r_session, |
1253 | req->r_request_started); | ||
1254 | next_item: | ||
1255 | if (dn) | ||
1256 | dput(dn); | ||
1240 | } | 1257 | } |
1241 | req->r_did_prepopulate = true; | 1258 | req->r_did_prepopulate = true; |
1242 | 1259 | ||
@@ -1425,7 +1442,7 @@ void ceph_queue_vmtruncate(struct inode *inode) | |||
1425 | { | 1442 | { |
1426 | struct ceph_inode_info *ci = ceph_inode(inode); | 1443 | struct ceph_inode_info *ci = ceph_inode(inode); |
1427 | 1444 | ||
1428 | if (queue_work(ceph_client(inode->i_sb)->trunc_wq, | 1445 | if (queue_work(ceph_sb_to_client(inode->i_sb)->trunc_wq, |
1429 | &ci->i_vmtruncate_work)) { | 1446 | &ci->i_vmtruncate_work)) { |
1430 | dout("ceph_queue_vmtruncate %p\n", inode); | 1447 | dout("ceph_queue_vmtruncate %p\n", inode); |
1431 | igrab(inode); | 1448 | igrab(inode); |
@@ -1485,7 +1502,7 @@ retry: | |||
1485 | if (wrbuffer_refs == 0) | 1502 | if (wrbuffer_refs == 0) |
1486 | ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); | 1503 | ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); |
1487 | if (wake) | 1504 | if (wake) |
1488 | wake_up(&ci->i_cap_wq); | 1505 | wake_up_all(&ci->i_cap_wq); |
1489 | } | 1506 | } |
1490 | 1507 | ||
1491 | 1508 | ||
@@ -1514,7 +1531,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) | |||
1514 | struct inode *parent_inode = dentry->d_parent->d_inode; | 1531 | struct inode *parent_inode = dentry->d_parent->d_inode; |
1515 | const unsigned int ia_valid = attr->ia_valid; | 1532 | const unsigned int ia_valid = attr->ia_valid; |
1516 | struct ceph_mds_request *req; | 1533 | struct ceph_mds_request *req; |
1517 | struct ceph_mds_client *mdsc = &ceph_client(dentry->d_sb)->mdsc; | 1534 | struct ceph_mds_client *mdsc = &ceph_sb_to_client(dentry->d_sb)->mdsc; |
1518 | int issued; | 1535 | int issued; |
1519 | int release = 0, dirtied = 0; | 1536 | int release = 0, dirtied = 0; |
1520 | int mask = 0; | 1537 | int mask = 0; |