@@ -71,6 +71,12 @@ void bch2_mark_io_failure(struct bch_io_failures *failed,
7171 }
7272}
7373
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+
7480/*
7581 * returns true if p1 is better than p2:
7682 */
@@ -79,11 +85,8 @@ static inline bool ptr_better(struct bch_fs *c,
7985 const struct extent_ptr_decoded p2 )
8086{
8187 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 );
8790
8891 /* Pick at random, biased in favor of the faster device: */
8992
@@ -109,21 +112,21 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
109112 const union bch_extent_entry * entry ;
110113 struct extent_ptr_decoded p ;
111114 struct bch_dev_io_failures * f ;
112- struct bch_dev * ca ;
113115 int ret = 0 ;
114116
115117 if (k .k -> type == KEY_TYPE_error )
116118 return - EIO ;
117119
120+ rcu_read_lock ();
118121 bkey_for_each_ptr_decode (k .k , ptrs , p , entry ) {
119122 /*
120123 * Unwritten extent: no need to actually read, treat it as a
121124 * hole and return 0s:
122125 */
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+ }
127130
128131 /*
129132 * 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,
132135 if (!ret && !p .ptr .cached )
133136 ret = - EIO ;
134137
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 )))
136141 continue ;
137142
138143 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,
141146 ? f -> idx
142147 : f -> idx + 1 ;
143148
144- if (!p .idx &&
145- !bch2_dev_is_readable (ca ))
149+ if (!p .idx && !ca )
146150 p .idx ++ ;
147151
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 ))
150156 p .idx ++ ;
151157
152158 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,
158164 * pick = p ;
159165 ret = 1 ;
160166 }
167+ rcu_read_unlock ();
161168
162169 return ret ;
163170}
0 commit comments