aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r--fs/ceph/inode.c183
1 files changed, 100 insertions, 83 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 8549a48115f7..278fd2891288 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -577,6 +577,8 @@ static int fill_inode(struct inode *inode,
577 int issued = 0, implemented; 577 int issued = 0, implemented;
578 struct timespec mtime, atime, ctime; 578 struct timespec mtime, atime, ctime;
579 u32 nsplits; 579 u32 nsplits;
580 struct ceph_inode_frag *frag;
581 struct rb_node *rb_node;
580 struct ceph_buffer *xattr_blob = NULL; 582 struct ceph_buffer *xattr_blob = NULL;
581 int err = 0; 583 int err = 0;
582 int queue_trunc = 0; 584 int queue_trunc = 0;
@@ -751,15 +753,38 @@ no_change:
751 /* FIXME: move me up, if/when version reflects fragtree changes */ 753 /* FIXME: move me up, if/when version reflects fragtree changes */
752 nsplits = le32_to_cpu(info->fragtree.nsplits); 754 nsplits = le32_to_cpu(info->fragtree.nsplits);
753 mutex_lock(&ci->i_fragtree_mutex); 755 mutex_lock(&ci->i_fragtree_mutex);
756 rb_node = rb_first(&ci->i_fragtree);
754 for (i = 0; i < nsplits; i++) { 757 for (i = 0; i < nsplits; i++) {
755 u32 id = le32_to_cpu(info->fragtree.splits[i].frag); 758 u32 id = le32_to_cpu(info->fragtree.splits[i].frag);
756 struct ceph_inode_frag *frag = __get_or_create_frag(ci, id); 759 frag = NULL;
757 760 while (rb_node) {
758 if (IS_ERR(frag)) 761 frag = rb_entry(rb_node, struct ceph_inode_frag, node);
759 continue; 762 if (ceph_frag_compare(frag->frag, id) >= 0) {
763 if (frag->frag != id)
764 frag = NULL;
765 else
766 rb_node = rb_next(rb_node);
767 break;
768 }
769 rb_node = rb_next(rb_node);
770 rb_erase(&frag->node, &ci->i_fragtree);
771 kfree(frag);
772 frag = NULL;
773 }
774 if (!frag) {
775 frag = __get_or_create_frag(ci, id);
776 if (IS_ERR(frag))
777 continue;
778 }
760 frag->split_by = le32_to_cpu(info->fragtree.splits[i].by); 779 frag->split_by = le32_to_cpu(info->fragtree.splits[i].by);
761 dout(" frag %x split by %d\n", frag->frag, frag->split_by); 780 dout(" frag %x split by %d\n", frag->frag, frag->split_by);
762 } 781 }
782 while (rb_node) {
783 frag = rb_entry(rb_node, struct ceph_inode_frag, node);
784 rb_node = rb_next(rb_node);
785 rb_erase(&frag->node, &ci->i_fragtree);
786 kfree(frag);
787 }
763 mutex_unlock(&ci->i_fragtree_mutex); 788 mutex_unlock(&ci->i_fragtree_mutex);
764 789
765 /* were we issued a capability? */ 790 /* were we issued a capability? */
@@ -953,7 +978,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
953 struct ceph_mds_reply_inode *ininfo; 978 struct ceph_mds_reply_inode *ininfo;
954 struct ceph_vino vino; 979 struct ceph_vino vino;
955 struct ceph_fs_client *fsc = ceph_sb_to_client(sb); 980 struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
956 int i = 0;
957 int err = 0; 981 int err = 0;
958 982
959 dout("fill_trace %p is_dentry %d is_target %d\n", req, 983 dout("fill_trace %p is_dentry %d is_target %d\n", req,
@@ -1014,6 +1038,29 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1014 } 1038 }
1015 } 1039 }
1016 1040
1041 if (rinfo->head->is_target) {
1042 vino.ino = le64_to_cpu(rinfo->targeti.in->ino);
1043 vino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
1044
1045 in = ceph_get_inode(sb, vino);
1046 if (IS_ERR(in)) {
1047 err = PTR_ERR(in);
1048 goto done;
1049 }
1050 req->r_target_inode = in;
1051
1052 err = fill_inode(in, &rinfo->targeti, NULL,
1053 session, req->r_request_started,
1054 (le32_to_cpu(rinfo->head->result) == 0) ?
1055 req->r_fmode : -1,
1056 &req->r_caps_reservation);
1057 if (err < 0) {
1058 pr_err("fill_inode badness %p %llx.%llx\n",
1059 in, ceph_vinop(in));
1060 goto done;
1061 }
1062 }
1063
1017 /* 1064 /*
1018 * ignore null lease/binding on snapdir ENOENT, or else we 1065 * ignore null lease/binding on snapdir ENOENT, or else we
1019 * will have trouble splicing in the virtual snapdir later 1066 * will have trouble splicing in the virtual snapdir later
@@ -1083,7 +1130,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1083 ceph_dentry(req->r_old_dentry)->offset); 1130 ceph_dentry(req->r_old_dentry)->offset);
1084 1131
1085 dn = req->r_old_dentry; /* use old_dentry */ 1132 dn = req->r_old_dentry; /* use old_dentry */
1086 in = dn->d_inode;
1087 } 1133 }
1088 1134
1089 /* null dentry? */ 1135 /* null dentry? */
@@ -1105,44 +1151,28 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1105 } 1151 }
1106 1152
1107 /* attach proper inode */ 1153 /* attach proper inode */
1108 ininfo = rinfo->targeti.in; 1154 if (!dn->d_inode) {
1109 vino.ino = le64_to_cpu(ininfo->ino); 1155 ihold(in);
1110 vino.snap = le64_to_cpu(ininfo->snapid);
1111 in = dn->d_inode;
1112 if (!in) {
1113 in = ceph_get_inode(sb, vino);
1114 if (IS_ERR(in)) {
1115 pr_err("fill_trace bad get_inode "
1116 "%llx.%llx\n", vino.ino, vino.snap);
1117 err = PTR_ERR(in);
1118 d_drop(dn);
1119 goto done;
1120 }
1121 dn = splice_dentry(dn, in, &have_lease, true); 1156 dn = splice_dentry(dn, in, &have_lease, true);
1122 if (IS_ERR(dn)) { 1157 if (IS_ERR(dn)) {
1123 err = PTR_ERR(dn); 1158 err = PTR_ERR(dn);
1124 goto done; 1159 goto done;
1125 } 1160 }
1126 req->r_dentry = dn; /* may have spliced */ 1161 req->r_dentry = dn; /* may have spliced */
1127 ihold(in); 1162 } else if (dn->d_inode && dn->d_inode != in) {
1128 } else if (ceph_ino(in) == vino.ino &&
1129 ceph_snap(in) == vino.snap) {
1130 ihold(in);
1131 } else {
1132 dout(" %p links to %p %llx.%llx, not %llx.%llx\n", 1163 dout(" %p links to %p %llx.%llx, not %llx.%llx\n",
1133 dn, in, ceph_ino(in), ceph_snap(in), 1164 dn, dn->d_inode, ceph_vinop(dn->d_inode),
1134 vino.ino, vino.snap); 1165 ceph_vinop(in));
1135 have_lease = false; 1166 have_lease = false;
1136 in = NULL;
1137 } 1167 }
1138 1168
1139 if (have_lease) 1169 if (have_lease)
1140 update_dentry_lease(dn, rinfo->dlease, session, 1170 update_dentry_lease(dn, rinfo->dlease, session,
1141 req->r_request_started); 1171 req->r_request_started);
1142 dout(" final dn %p\n", dn); 1172 dout(" final dn %p\n", dn);
1143 i++; 1173 } else if (!req->r_aborted &&
1144 } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP || 1174 (req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
1145 req->r_op == CEPH_MDS_OP_MKSNAP) && !req->r_aborted) { 1175 req->r_op == CEPH_MDS_OP_MKSNAP)) {
1146 struct dentry *dn = req->r_dentry; 1176 struct dentry *dn = req->r_dentry;
1147 1177
1148 /* fill out a snapdir LOOKUPSNAP dentry */ 1178 /* fill out a snapdir LOOKUPSNAP dentry */
@@ -1152,52 +1182,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1152 ininfo = rinfo->targeti.in; 1182 ininfo = rinfo->targeti.in;
1153 vino.ino = le64_to_cpu(ininfo->ino); 1183 vino.ino = le64_to_cpu(ininfo->ino);
1154 vino.snap = le64_to_cpu(ininfo->snapid); 1184 vino.snap = le64_to_cpu(ininfo->snapid);
1155 in = ceph_get_inode(sb, vino);
1156 if (IS_ERR(in)) {
1157 pr_err("fill_inode get_inode badness %llx.%llx\n",
1158 vino.ino, vino.snap);
1159 err = PTR_ERR(in);
1160 d_delete(dn);
1161 goto done;
1162 }
1163 dout(" linking snapped dir %p to dn %p\n", in, dn); 1185 dout(" linking snapped dir %p to dn %p\n", in, dn);
1186 ihold(in);
1164 dn = splice_dentry(dn, in, NULL, true); 1187 dn = splice_dentry(dn, in, NULL, true);
1165 if (IS_ERR(dn)) { 1188 if (IS_ERR(dn)) {
1166 err = PTR_ERR(dn); 1189 err = PTR_ERR(dn);
1167 goto done; 1190 goto done;
1168 } 1191 }
1169 req->r_dentry = dn; /* may have spliced */ 1192 req->r_dentry = dn; /* may have spliced */
1170 ihold(in);
1171 rinfo->head->is_dentry = 1; /* fool notrace handlers */
1172 }
1173
1174 if (rinfo->head->is_target) {
1175 vino.ino = le64_to_cpu(rinfo->targeti.in->ino);
1176 vino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
1177
1178 if (in == NULL || ceph_ino(in) != vino.ino ||
1179 ceph_snap(in) != vino.snap) {
1180 in = ceph_get_inode(sb, vino);
1181 if (IS_ERR(in)) {
1182 err = PTR_ERR(in);
1183 goto done;
1184 }
1185 }
1186 req->r_target_inode = in;
1187
1188 err = fill_inode(in,
1189 &rinfo->targeti, NULL,
1190 session, req->r_request_started,
1191 (le32_to_cpu(rinfo->head->result) == 0) ?
1192 req->r_fmode : -1,
1193 &req->r_caps_reservation);
1194 if (err < 0) {
1195 pr_err("fill_inode badness %p %llx.%llx\n",
1196 in, ceph_vinop(in));
1197 goto done;
1198 }
1199 } 1193 }
1200
1201done: 1194done:
1202 dout("fill_trace done err=%d\n", err); 1195 dout("fill_trace done err=%d\n", err);
1203 return err; 1196 return err;
@@ -1247,11 +1240,23 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
1247 struct qstr dname; 1240 struct qstr dname;
1248 struct dentry *dn; 1241 struct dentry *dn;
1249 struct inode *in; 1242 struct inode *in;
1250 int err = 0, i; 1243 int err = 0, ret, i;
1251 struct inode *snapdir = NULL; 1244 struct inode *snapdir = NULL;
1252 struct ceph_mds_request_head *rhead = req->r_request->front.iov_base; 1245 struct ceph_mds_request_head *rhead = req->r_request->front.iov_base;
1253 u64 frag = le32_to_cpu(rhead->args.readdir.frag);
1254 struct ceph_dentry_info *di; 1246 struct ceph_dentry_info *di;
1247 u64 r_readdir_offset = req->r_readdir_offset;
1248 u32 frag = le32_to_cpu(rhead->args.readdir.frag);
1249
1250 if (rinfo->dir_dir &&
1251 le32_to_cpu(rinfo->dir_dir->frag) != frag) {
1252 dout("readdir_prepopulate got new frag %x -> %x\n",
1253 frag, le32_to_cpu(rinfo->dir_dir->frag));
1254 frag = le32_to_cpu(rinfo->dir_dir->frag);
1255 if (ceph_frag_is_leftmost(frag))
1256 r_readdir_offset = 2;
1257 else
1258 r_readdir_offset = 0;
1259 }
1255 1260
1256 if (req->r_aborted) 1261 if (req->r_aborted)
1257 return readdir_prepopulate_inodes_only(req, session); 1262 return readdir_prepopulate_inodes_only(req, session);
@@ -1268,6 +1273,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
1268 ceph_fill_dirfrag(parent->d_inode, rinfo->dir_dir); 1273 ceph_fill_dirfrag(parent->d_inode, rinfo->dir_dir);
1269 } 1274 }
1270 1275
1276 /* FIXME: release caps/leases if error occurs */
1271 for (i = 0; i < rinfo->dir_nr; i++) { 1277 for (i = 0; i < rinfo->dir_nr; i++) {
1272 struct ceph_vino vino; 1278 struct ceph_vino vino;
1273 1279
@@ -1292,9 +1298,10 @@ retry_lookup:
1292 err = -ENOMEM; 1298 err = -ENOMEM;
1293 goto out; 1299 goto out;
1294 } 1300 }
1295 err = ceph_init_dentry(dn); 1301 ret = ceph_init_dentry(dn);
1296 if (err < 0) { 1302 if (ret < 0) {
1297 dput(dn); 1303 dput(dn);
1304 err = ret;
1298 goto out; 1305 goto out;
1299 } 1306 }
1300 } else if (dn->d_inode && 1307 } else if (dn->d_inode &&
@@ -1314,9 +1321,6 @@ retry_lookup:
1314 spin_unlock(&parent->d_lock); 1321 spin_unlock(&parent->d_lock);
1315 } 1322 }
1316 1323
1317 di = dn->d_fsdata;
1318 di->offset = ceph_make_fpos(frag, i + req->r_readdir_offset);
1319
1320 /* inode */ 1324 /* inode */
1321 if (dn->d_inode) { 1325 if (dn->d_inode) {
1322 in = dn->d_inode; 1326 in = dn->d_inode;
@@ -1329,26 +1333,39 @@ retry_lookup:
1329 err = PTR_ERR(in); 1333 err = PTR_ERR(in);
1330 goto out; 1334 goto out;
1331 } 1335 }
1332 dn = splice_dentry(dn, in, NULL, false);
1333 if (IS_ERR(dn))
1334 dn = NULL;
1335 } 1336 }
1336 1337
1337 if (fill_inode(in, &rinfo->dir_in[i], NULL, session, 1338 if (fill_inode(in, &rinfo->dir_in[i], NULL, session,
1338 req->r_request_started, -1, 1339 req->r_request_started, -1,
1339 &req->r_caps_reservation) < 0) { 1340 &req->r_caps_reservation) < 0) {
1340 pr_err("fill_inode badness on %p\n", in); 1341 pr_err("fill_inode badness on %p\n", in);
1342 if (!dn->d_inode)
1343 iput(in);
1344 d_drop(dn);
1341 goto next_item; 1345 goto next_item;
1342 } 1346 }
1343 if (dn) 1347
1344 update_dentry_lease(dn, rinfo->dir_dlease[i], 1348 if (!dn->d_inode) {
1345 req->r_session, 1349 dn = splice_dentry(dn, in, NULL, false);
1346 req->r_request_started); 1350 if (IS_ERR(dn)) {
1351 err = PTR_ERR(dn);
1352 dn = NULL;
1353 goto next_item;
1354 }
1355 }
1356
1357 di = dn->d_fsdata;
1358 di->offset = ceph_make_fpos(frag, i + r_readdir_offset);
1359
1360 update_dentry_lease(dn, rinfo->dir_dlease[i],
1361 req->r_session,
1362 req->r_request_started);
1347next_item: 1363next_item:
1348 if (dn) 1364 if (dn)
1349 dput(dn); 1365 dput(dn);
1350 } 1366 }
1351 req->r_did_prepopulate = true; 1367 if (err == 0)
1368 req->r_did_prepopulate = true;
1352 1369
1353out: 1370out:
1354 if (snapdir) { 1371 if (snapdir) {