@@ -71,6 +71,12 @@ void bch2_mark_io_failure(struct bch_io_failures *failed,
71
71
}
72
72
}
73
73
74
+ static inline u64 dev_latency (struct bch_fs * c , unsigned dev )
75
+ {
76
+ struct bch_dev * ca = bch2_dev_rcu (c , dev );
77
+ return ca ? atomic64_read (& ca -> cur_latency [READ ]) : S64_MAX ;
78
+ }
79
+
74
80
/*
75
81
* returns true if p1 is better than p2:
76
82
*/
@@ -79,11 +85,8 @@ static inline bool ptr_better(struct bch_fs *c,
79
85
const struct extent_ptr_decoded p2 )
80
86
{
81
87
if (likely (!p1 .idx && !p2 .idx )) {
82
- struct bch_dev * dev1 = bch2_dev_bkey_exists (c , p1 .ptr .dev );
83
- struct bch_dev * dev2 = bch2_dev_bkey_exists (c , p2 .ptr .dev );
84
-
85
- u64 l1 = atomic64_read (& dev1 -> cur_latency [READ ]);
86
- u64 l2 = atomic64_read (& dev2 -> cur_latency [READ ]);
88
+ u64 l1 = dev_latency (c , p1 .ptr .dev );
89
+ u64 l2 = dev_latency (c , p2 .ptr .dev );
87
90
88
91
/* Pick at random, biased in favor of the faster device: */
89
92
@@ -109,21 +112,21 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
109
112
const union bch_extent_entry * entry ;
110
113
struct extent_ptr_decoded p ;
111
114
struct bch_dev_io_failures * f ;
112
- struct bch_dev * ca ;
113
115
int ret = 0 ;
114
116
115
117
if (k .k -> type == KEY_TYPE_error )
116
118
return - EIO ;
117
119
120
+ rcu_read_lock ();
118
121
bkey_for_each_ptr_decode (k .k , ptrs , p , entry ) {
119
122
/*
120
123
* Unwritten extent: no need to actually read, treat it as a
121
124
* hole and return 0s:
122
125
*/
123
- if (p .ptr .unwritten )
124
- return 0 ;
125
-
126
- ca = bch2_dev_bkey_exists ( c , p . ptr . dev );
126
+ if (p .ptr .unwritten ) {
127
+ ret = 0 ;
128
+ break ;
129
+ }
127
130
128
131
/*
129
132
* If there are any dirty pointers it's an error if we can't
@@ -132,7 +135,9 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
132
135
if (!ret && !p .ptr .cached )
133
136
ret = - EIO ;
134
137
135
- if (p .ptr .cached && dev_ptr_stale (ca , & p .ptr ))
138
+ struct bch_dev * ca = bch2_dev_rcu (c , p .ptr .dev );
139
+
140
+ if (p .ptr .cached && (!ca || dev_ptr_stale (ca , & p .ptr )))
136
141
continue ;
137
142
138
143
f = failed ? dev_io_failures (failed , p .ptr .dev ) : NULL ;
@@ -141,12 +146,13 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
141
146
? f -> idx
142
147
: f -> idx + 1 ;
143
148
144
- if (!p .idx &&
145
- !bch2_dev_is_readable (ca ))
149
+ if (!p .idx && !ca )
146
150
p .idx ++ ;
147
151
148
- if (bch2_force_reconstruct_read &&
149
- !p .idx && p .has_ec )
152
+ if (!p .idx && p .has_ec && bch2_force_reconstruct_read )
153
+ p .idx ++ ;
154
+
155
+ if (!p .idx && !bch2_dev_is_readable (ca ))
150
156
p .idx ++ ;
151
157
152
158
if (p .idx >= (unsigned ) p .has_ec + 1 )
@@ -158,6 +164,7 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
158
164
* pick = p ;
159
165
ret = 1 ;
160
166
}
167
+ rcu_read_unlock ();
161
168
162
169
return ret ;
163
170
}
0 commit comments