aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-01-29 02:55:31 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2013-02-26 02:46:08 -0500
commit79f9f99ad1e3e19d4ac300573b51289e3ee8ba86 (patch)
tree455ace78657477d949e856575f39a23d4abf9ed3 /fs/ceph
parent4f522a247bc26d4ab5c8fc406ffffa8b3a77abe3 (diff)
ceph: prepopulate inodes only when request is aborted
If r_aborted is true, we do not hold the dir i_mutex, and cannot touch the dcache. However, we still need to update the inodes with the state returned by the MDS. Reported-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Sage Weil <sage@inktank.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/inode.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 2971eaa65cdc..4bc086a72475 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1130,8 +1130,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1130 req->r_request_started); 1130 req->r_request_started);
1131 dout(" final dn %p\n", dn); 1131 dout(" final dn %p\n", dn);
1132 i++; 1132 i++;
1133 } else if (req->r_op == CEPH_MDS_OP_LOOKUPSNAP || 1133 } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
1134 req->r_op == CEPH_MDS_OP_MKSNAP) { 1134 req->r_op == CEPH_MDS_OP_MKSNAP) && !req->r_aborted) {
1135 struct dentry *dn = req->r_dentry; 1135 struct dentry *dn = req->r_dentry;
1136 1136
1137 /* fill out a snapdir LOOKUPSNAP dentry */ 1137 /* fill out a snapdir LOOKUPSNAP dentry */
@@ -1195,6 +1195,39 @@ done:
1195/* 1195/*
1196 * Prepopulate our cache with readdir results, leases, etc. 1196 * Prepopulate our cache with readdir results, leases, etc.
1197 */ 1197 */
1198static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req,
1199 struct ceph_mds_session *session)
1200{
1201 struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
1202 int i, err = 0;
1203
1204 for (i = 0; i < rinfo->dir_nr; i++) {
1205 struct ceph_vino vino;
1206 struct inode *in;
1207 int rc;
1208
1209 vino.ino = le64_to_cpu(rinfo->dir_in[i].in->ino);
1210 vino.snap = le64_to_cpu(rinfo->dir_in[i].in->snapid);
1211
1212 in = ceph_get_inode(req->r_dentry->d_sb, vino);
1213 if (IS_ERR(in)) {
1214 err = PTR_ERR(in);
1215 dout("new_inode badness got %d\n", err);
1216 continue;
1217 }
1218 rc = fill_inode(in, &rinfo->dir_in[i], NULL, session,
1219 req->r_request_started, -1,
1220 &req->r_caps_reservation);
1221 if (rc < 0) {
1222 pr_err("fill_inode badness on %p got %d\n", in, rc);
1223 err = rc;
1224 continue;
1225 }
1226 }
1227
1228 return err;
1229}
1230
1198int ceph_readdir_prepopulate(struct ceph_mds_request *req, 1231int ceph_readdir_prepopulate(struct ceph_mds_request *req,
1199 struct ceph_mds_session *session) 1232 struct ceph_mds_session *session)
1200{ 1233{
@@ -1209,6 +1242,9 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
1209 u64 frag = le32_to_cpu(rhead->args.readdir.frag); 1242 u64 frag = le32_to_cpu(rhead->args.readdir.frag);
1210 struct ceph_dentry_info *di; 1243 struct ceph_dentry_info *di;
1211 1244
1245 if (req->r_aborted)
1246 return readdir_prepopulate_inodes_only(req, session);
1247
1212 if (le32_to_cpu(rinfo->head->op) == CEPH_MDS_OP_LSSNAP) { 1248 if (le32_to_cpu(rinfo->head->op) == CEPH_MDS_OP_LSSNAP) {
1213 snapdir = ceph_get_snapdir(parent->d_inode); 1249 snapdir = ceph_get_snapdir(parent->d_inode);
1214 parent = d_find_alias(snapdir); 1250 parent = d_find_alias(snapdir);