@@ -134,42 +134,38 @@ static long bch2_ioctl_incremental(struct bch_ioctl_incremental __user *user_arg
134134struct fsck_thread {
135135 struct thread_with_stdio thr ;
136136 struct bch_fs * c ;
137- char * * devs ;
138- size_t nr_devs ;
139137 struct bch_opts opts ;
140138};
141139
142140static void bch2_fsck_thread_exit (struct thread_with_stdio * _thr )
143141{
144142 struct fsck_thread * thr = container_of (_thr , struct fsck_thread , thr );
145- if (thr -> devs )
146- for (size_t i = 0 ; i < thr -> nr_devs ; i ++ )
147- kfree (thr -> devs [i ]);
148- kfree (thr -> devs );
149143 kfree (thr );
150144}
151145
152146static int bch2_fsck_offline_thread_fn (struct thread_with_stdio * stdio )
153147{
154148 struct fsck_thread * thr = container_of (stdio , struct fsck_thread , thr );
155- struct bch_fs * c = bch2_fs_open (thr -> devs , thr -> nr_devs , thr -> opts );
156-
157- if (IS_ERR (c ))
158- return PTR_ERR (c );
149+ struct bch_fs * c = thr -> c ;
159150
160- int ret = 0 ;
161- if (test_bit (BCH_FS_errors_fixed , & c -> flags ))
162- ret |= 1 ;
163- if (test_bit (BCH_FS_error , & c -> flags ))
164- ret |= 4 ;
151+ int ret = PTR_ERR_OR_ZERO (c );
152+ if (ret )
153+ return ret ;
165154
166- bch2_fs_stop (c );
155+ ret = bch2_fs_start (thr -> c );
156+ if (ret )
157+ goto err ;
167158
168- if (ret & 1 )
159+ if (test_bit ( BCH_FS_errors_fixed , & c -> flags )) {
169160 bch2_stdio_redirect_printf (& stdio -> stdio , false, "%s: errors fixed\n" , c -> name );
170- if (ret & 4 )
161+ ret |= 1 ;
162+ }
163+ if (test_bit (BCH_FS_error , & c -> flags )) {
171164 bch2_stdio_redirect_printf (& stdio -> stdio , false, "%s: still has errors\n" , c -> name );
172-
165+ ret |= 4 ;
166+ }
167+ err :
168+ bch2_fs_stop (c );
173169 return ret ;
174170}
175171
@@ -182,7 +178,7 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a
182178{
183179 struct bch_ioctl_fsck_offline arg ;
184180 struct fsck_thread * thr = NULL ;
185- u64 * devs = NULL ;
181+ darray_str ( devs ) = {} ;
186182 long ret = 0 ;
187183
188184 if (copy_from_user (& arg , user_arg , sizeof (arg )))
@@ -194,29 +190,32 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a
194190 if (!capable (CAP_SYS_ADMIN ))
195191 return - EPERM ;
196192
197- if (!(devs = kcalloc (arg .nr_devs , sizeof (* devs ), GFP_KERNEL )) ||
198- !(thr = kzalloc (sizeof (* thr ), GFP_KERNEL )) ||
199- !(thr -> devs = kcalloc (arg .nr_devs , sizeof (* thr -> devs ), GFP_KERNEL ))) {
200- ret = - ENOMEM ;
201- goto err ;
202- }
193+ for (size_t i = 0 ; i < arg .nr_devs ; i ++ ) {
194+ u64 dev_u64 ;
195+ ret = copy_from_user_errcode (& dev_u64 , & user_arg -> devs [i ], sizeof (u64 ));
196+ if (ret )
197+ goto err ;
203198
204- thr -> opts = bch2_opts_empty ();
205- thr -> nr_devs = arg .nr_devs ;
199+ char * dev_str = strndup_user ((char __user * )(unsigned long ) dev_u64 , PATH_MAX );
200+ ret = PTR_ERR_OR_ZERO (dev_str );
201+ if (ret )
202+ goto err ;
206203
207- if (copy_from_user (devs , & user_arg -> devs [0 ],
208- array_size (sizeof (user_arg -> devs [0 ]), arg .nr_devs ))) {
209- ret = - EINVAL ;
210- goto err ;
204+ ret = darray_push (& devs , dev_str );
205+ if (ret ) {
206+ kfree (dev_str );
207+ goto err ;
208+ }
211209 }
212210
213- for (size_t i = 0 ; i < arg .nr_devs ; i ++ ) {
214- thr -> devs [i ] = strndup_user ((char __user * )(unsigned long ) devs [i ], PATH_MAX );
215- ret = PTR_ERR_OR_ZERO (thr -> devs [i ]);
216- if (ret )
217- goto err ;
211+ thr = kzalloc (sizeof (* thr ), GFP_KERNEL );
212+ if (!thr ) {
213+ ret = - ENOMEM ;
214+ goto err ;
218215 }
219216
217+ thr -> opts = bch2_opts_empty ();
218+
220219 if (arg .opts ) {
221220 char * optstr = strndup_user ((char __user * )(unsigned long ) arg .opts , 1 << 16 );
222221
@@ -230,15 +229,22 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a
230229
231230 opt_set (thr -> opts , stdio , (u64 )(unsigned long )& thr -> thr .stdio );
232231
232+ /* We need request_key() to be called before we punt to kthread: */
233+ opt_set (thr -> opts , nostart , true);
234+
235+ thr -> c = bch2_fs_open (devs .data , arg .nr_devs , thr -> opts );
236+
233237 ret = bch2_run_thread_with_stdio (& thr -> thr , & bch2_offline_fsck_ops );
234- err :
235- if (ret < 0 ) {
236- if (thr )
237- bch2_fsck_thread_exit (& thr -> thr );
238- pr_err ("ret %s" , bch2_err_str (ret ));
239- }
240- kfree (devs );
238+ out :
239+ darray_for_each (devs , i )
240+ kfree (* i );
241+ darray_exit (& devs );
241242 return ret ;
243+ err :
244+ if (thr )
245+ bch2_fsck_thread_exit (& thr -> thr );
246+ pr_err ("ret %s" , bch2_err_str (ret ));
247+ goto out ;
242248}
243249
244250static long bch2_global_ioctl (unsigned cmd , void __user * arg )
0 commit comments