diff options
| -rw-r--r-- | fs/ceph/addr.c | 8 | ||||
| -rw-r--r-- | fs/ceph/inode.c | 136 |
2 files changed, 64 insertions, 80 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 1e561c059539..ec3ba43b9faa 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
| @@ -210,9 +210,13 @@ static int readpage_nounlock(struct file *filp, struct page *page) | |||
| 210 | if (err < 0) { | 210 | if (err < 0) { |
| 211 | SetPageError(page); | 211 | SetPageError(page); |
| 212 | goto out; | 212 | goto out; |
| 213 | } else if (err < PAGE_CACHE_SIZE) { | 213 | } else { |
| 214 | if (err < PAGE_CACHE_SIZE) { | ||
| 214 | /* zero fill remainder of page */ | 215 | /* zero fill remainder of page */ |
| 215 | zero_user_segment(page, err, PAGE_CACHE_SIZE); | 216 | zero_user_segment(page, err, PAGE_CACHE_SIZE); |
| 217 | } else { | ||
| 218 | flush_dcache_page(page); | ||
| 219 | } | ||
| 216 | } | 220 | } |
| 217 | SetPageUptodate(page); | 221 | SetPageUptodate(page); |
| 218 | 222 | ||
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 9a8e396aed89..278fd2891288 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
| @@ -978,7 +978,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
| 978 | struct ceph_mds_reply_inode *ininfo; | 978 | struct ceph_mds_reply_inode *ininfo; |
| 979 | struct ceph_vino vino; | 979 | struct ceph_vino vino; |
| 980 | struct ceph_fs_client *fsc = ceph_sb_to_client(sb); | 980 | struct ceph_fs_client *fsc = ceph_sb_to_client(sb); |
| 981 | int i = 0; | ||
| 982 | int err = 0; | 981 | int err = 0; |
| 983 | 982 | ||
| 984 | 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, |
| @@ -1039,6 +1038,29 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
| 1039 | } | 1038 | } |
| 1040 | } | 1039 | } |
| 1041 | 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 | |||
| 1042 | /* | 1064 | /* |
| 1043 | * ignore null lease/binding on snapdir ENOENT, or else we | 1065 | * ignore null lease/binding on snapdir ENOENT, or else we |
| 1044 | * will have trouble splicing in the virtual snapdir later | 1066 | * will have trouble splicing in the virtual snapdir later |
| @@ -1108,7 +1130,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
| 1108 | ceph_dentry(req->r_old_dentry)->offset); | 1130 | ceph_dentry(req->r_old_dentry)->offset); |
| 1109 | 1131 | ||
| 1110 | dn = req->r_old_dentry; /* use old_dentry */ | 1132 | dn = req->r_old_dentry; /* use old_dentry */ |
| 1111 | in = dn->d_inode; | ||
| 1112 | } | 1133 | } |
| 1113 | 1134 | ||
| 1114 | /* null dentry? */ | 1135 | /* null dentry? */ |
| @@ -1130,44 +1151,28 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
| 1130 | } | 1151 | } |
| 1131 | 1152 | ||
| 1132 | /* attach proper inode */ | 1153 | /* attach proper inode */ |
| 1133 | ininfo = rinfo->targeti.in; | 1154 | if (!dn->d_inode) { |
| 1134 | vino.ino = le64_to_cpu(ininfo->ino); | 1155 | ihold(in); |
| 1135 | vino.snap = le64_to_cpu(ininfo->snapid); | ||
| 1136 | in = dn->d_inode; | ||
| 1137 | if (!in) { | ||
| 1138 | in = ceph_get_inode(sb, vino); | ||
| 1139 | if (IS_ERR(in)) { | ||
| 1140 | pr_err("fill_trace bad get_inode " | ||
| 1141 | "%llx.%llx\n", vino.ino, vino.snap); | ||
| 1142 | err = PTR_ERR(in); | ||
| 1143 | d_drop(dn); | ||
| 1144 | goto done; | ||
| 1145 | } | ||
| 1146 | dn = splice_dentry(dn, in, &have_lease, true); | 1156 | dn = splice_dentry(dn, in, &have_lease, true); |
| 1147 | if (IS_ERR(dn)) { | 1157 | if (IS_ERR(dn)) { |
| 1148 | err = PTR_ERR(dn); | 1158 | err = PTR_ERR(dn); |
| 1149 | goto done; | 1159 | goto done; |
| 1150 | } | 1160 | } |
| 1151 | req->r_dentry = dn; /* may have spliced */ | 1161 | req->r_dentry = dn; /* may have spliced */ |
| 1152 | ihold(in); | 1162 | } else if (dn->d_inode && dn->d_inode != in) { |
| 1153 | } else if (ceph_ino(in) == vino.ino && | ||
| 1154 | ceph_snap(in) == vino.snap) { | ||
| 1155 | ihold(in); | ||
| 1156 | } else { | ||
| 1157 | dout(" %p links to %p %llx.%llx, not %llx.%llx\n", | 1163 | dout(" %p links to %p %llx.%llx, not %llx.%llx\n", |
| 1158 | dn, in, ceph_ino(in), ceph_snap(in), | 1164 | dn, dn->d_inode, ceph_vinop(dn->d_inode), |
| 1159 | vino.ino, vino.snap); | 1165 | ceph_vinop(in)); |
| 1160 | have_lease = false; | 1166 | have_lease = false; |
| 1161 | in = NULL; | ||
| 1162 | } | 1167 | } |
| 1163 | 1168 | ||
| 1164 | if (have_lease) | 1169 | if (have_lease) |
| 1165 | update_dentry_lease(dn, rinfo->dlease, session, | 1170 | update_dentry_lease(dn, rinfo->dlease, session, |
| 1166 | req->r_request_started); | 1171 | req->r_request_started); |
| 1167 | dout(" final dn %p\n", dn); | 1172 | dout(" final dn %p\n", dn); |
| 1168 | i++; | 1173 | } else if (!req->r_aborted && |
| 1169 | } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP || | 1174 | (req->r_op == CEPH_MDS_OP_LOOKUPSNAP || |
| 1170 | req->r_op == CEPH_MDS_OP_MKSNAP) && !req->r_aborted) { | 1175 | req->r_op == CEPH_MDS_OP_MKSNAP)) { |
| 1171 | struct dentry *dn = req->r_dentry; | 1176 | struct dentry *dn = req->r_dentry; |
| 1172 | 1177 | ||
| 1173 | /* fill out a snapdir LOOKUPSNAP dentry */ | 1178 | /* fill out a snapdir LOOKUPSNAP dentry */ |
| @@ -1177,52 +1182,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
| 1177 | ininfo = rinfo->targeti.in; | 1182 | ininfo = rinfo->targeti.in; |
| 1178 | vino.ino = le64_to_cpu(ininfo->ino); | 1183 | vino.ino = le64_to_cpu(ininfo->ino); |
| 1179 | vino.snap = le64_to_cpu(ininfo->snapid); | 1184 | vino.snap = le64_to_cpu(ininfo->snapid); |
| 1180 | in = ceph_get_inode(sb, vino); | ||
| 1181 | if (IS_ERR(in)) { | ||
| 1182 | pr_err("fill_inode get_inode badness %llx.%llx\n", | ||
| 1183 | vino.ino, vino.snap); | ||
| 1184 | err = PTR_ERR(in); | ||
| 1185 | d_delete(dn); | ||
| 1186 | goto done; | ||
| 1187 | } | ||
| 1188 | 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); | ||
| 1189 | dn = splice_dentry(dn, in, NULL, true); | 1187 | dn = splice_dentry(dn, in, NULL, true); |
| 1190 | if (IS_ERR(dn)) { | 1188 | if (IS_ERR(dn)) { |
| 1191 | err = PTR_ERR(dn); | 1189 | err = PTR_ERR(dn); |
| 1192 | goto done; | 1190 | goto done; |
| 1193 | } | 1191 | } |
| 1194 | req->r_dentry = dn; /* may have spliced */ | 1192 | req->r_dentry = dn; /* may have spliced */ |
| 1195 | ihold(in); | ||
| 1196 | rinfo->head->is_dentry = 1; /* fool notrace handlers */ | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | if (rinfo->head->is_target) { | ||
| 1200 | vino.ino = le64_to_cpu(rinfo->targeti.in->ino); | ||
| 1201 | vino.snap = le64_to_cpu(rinfo->targeti.in->snapid); | ||
| 1202 | |||
| 1203 | if (in == NULL || ceph_ino(in) != vino.ino || | ||
| 1204 | ceph_snap(in) != vino.snap) { | ||
| 1205 | in = ceph_get_inode(sb, vino); | ||
| 1206 | if (IS_ERR(in)) { | ||
| 1207 | err = PTR_ERR(in); | ||
| 1208 | goto done; | ||
| 1209 | } | ||
| 1210 | } | ||
| 1211 | req->r_target_inode = in; | ||
| 1212 | |||
| 1213 | err = fill_inode(in, | ||
| 1214 | &rinfo->targeti, NULL, | ||
| 1215 | session, req->r_request_started, | ||
| 1216 | (le32_to_cpu(rinfo->head->result) == 0) ? | ||
| 1217 | req->r_fmode : -1, | ||
| 1218 | &req->r_caps_reservation); | ||
| 1219 | if (err < 0) { | ||
| 1220 | pr_err("fill_inode badness %p %llx.%llx\n", | ||
| 1221 | in, ceph_vinop(in)); | ||
| 1222 | goto done; | ||
| 1223 | } | ||
| 1224 | } | 1193 | } |
| 1225 | |||
| 1226 | done: | 1194 | done: |
| 1227 | dout("fill_trace done err=%d\n", err); | 1195 | dout("fill_trace done err=%d\n", err); |
| 1228 | return err; | 1196 | return err; |
| @@ -1272,7 +1240,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, | |||
| 1272 | struct qstr dname; | 1240 | struct qstr dname; |
| 1273 | struct dentry *dn; | 1241 | struct dentry *dn; |
| 1274 | struct inode *in; | 1242 | struct inode *in; |
| 1275 | int err = 0, i; | 1243 | int err = 0, ret, i; |
| 1276 | struct inode *snapdir = NULL; | 1244 | struct inode *snapdir = NULL; |
| 1277 | 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; |
| 1278 | struct ceph_dentry_info *di; | 1246 | struct ceph_dentry_info *di; |
| @@ -1305,6 +1273,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, | |||
| 1305 | ceph_fill_dirfrag(parent->d_inode, rinfo->dir_dir); | 1273 | ceph_fill_dirfrag(parent->d_inode, rinfo->dir_dir); |
| 1306 | } | 1274 | } |
| 1307 | 1275 | ||
| 1276 | /* FIXME: release caps/leases if error occurs */ | ||
| 1308 | for (i = 0; i < rinfo->dir_nr; i++) { | 1277 | for (i = 0; i < rinfo->dir_nr; i++) { |
| 1309 | struct ceph_vino vino; | 1278 | struct ceph_vino vino; |
| 1310 | 1279 | ||
| @@ -1329,9 +1298,10 @@ retry_lookup: | |||
| 1329 | err = -ENOMEM; | 1298 | err = -ENOMEM; |
| 1330 | goto out; | 1299 | goto out; |
| 1331 | } | 1300 | } |
| 1332 | err = ceph_init_dentry(dn); | 1301 | ret = ceph_init_dentry(dn); |
| 1333 | if (err < 0) { | 1302 | if (ret < 0) { |
| 1334 | dput(dn); | 1303 | dput(dn); |
| 1304 | err = ret; | ||
| 1335 | goto out; | 1305 | goto out; |
| 1336 | } | 1306 | } |
| 1337 | } else if (dn->d_inode && | 1307 | } else if (dn->d_inode && |
| @@ -1351,9 +1321,6 @@ retry_lookup: | |||
| 1351 | spin_unlock(&parent->d_lock); | 1321 | spin_unlock(&parent->d_lock); |
| 1352 | } | 1322 | } |
| 1353 | 1323 | ||
| 1354 | di = dn->d_fsdata; | ||
| 1355 | di->offset = ceph_make_fpos(frag, i + r_readdir_offset); | ||
| 1356 | |||
| 1357 | /* inode */ | 1324 | /* inode */ |
| 1358 | if (dn->d_inode) { | 1325 | if (dn->d_inode) { |
| 1359 | in = dn->d_inode; | 1326 | in = dn->d_inode; |
| @@ -1366,26 +1333,39 @@ retry_lookup: | |||
| 1366 | err = PTR_ERR(in); | 1333 | err = PTR_ERR(in); |
| 1367 | goto out; | 1334 | goto out; |
| 1368 | } | 1335 | } |
| 1369 | dn = splice_dentry(dn, in, NULL, false); | ||
| 1370 | if (IS_ERR(dn)) | ||
| 1371 | dn = NULL; | ||
| 1372 | } | 1336 | } |
| 1373 | 1337 | ||
| 1374 | if (fill_inode(in, &rinfo->dir_in[i], NULL, session, | 1338 | if (fill_inode(in, &rinfo->dir_in[i], NULL, session, |
| 1375 | req->r_request_started, -1, | 1339 | req->r_request_started, -1, |
| 1376 | &req->r_caps_reservation) < 0) { | 1340 | &req->r_caps_reservation) < 0) { |
| 1377 | 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); | ||
| 1378 | goto next_item; | 1345 | goto next_item; |
| 1379 | } | 1346 | } |
| 1380 | if (dn) | 1347 | |
| 1381 | update_dentry_lease(dn, rinfo->dir_dlease[i], | 1348 | if (!dn->d_inode) { |
| 1382 | req->r_session, | 1349 | dn = splice_dentry(dn, in, NULL, false); |
| 1383 | 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); | ||
| 1384 | next_item: | 1363 | next_item: |
| 1385 | if (dn) | 1364 | if (dn) |
| 1386 | dput(dn); | 1365 | dput(dn); |
| 1387 | } | 1366 | } |
| 1388 | req->r_did_prepopulate = true; | 1367 | if (err == 0) |
| 1368 | req->r_did_prepopulate = true; | ||
| 1389 | 1369 | ||
| 1390 | out: | 1370 | out: |
| 1391 | if (snapdir) { | 1371 | if (snapdir) { |
