diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-02-16 03:44:47 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2010-03-04 18:20:21 -0500 |
commit | c411e5f66a5dd36827a5f9d1392a1afdf69ff075 (patch) | |
tree | ec15fda09302f281785675f4b9878e5360a49788 /fs/quota/quota.c | |
parent | 0a5a9c725512461d19397490f3adf29931dca1f2 (diff) |
quota: split do_quotactl
Split out a helper for each non-trivial command from do_quotactl.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota/quota.c')
-rw-r--r-- | fs/quota/quota.c | 250 |
1 files changed, 146 insertions, 104 deletions
diff --git a/fs/quota/quota.c b/fs/quota/quota.c index ee91e2756950..4d7fdc4443b9 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c | |||
@@ -234,122 +234,164 @@ restart: | |||
234 | spin_unlock(&sb_lock); | 234 | spin_unlock(&sb_lock); |
235 | } | 235 | } |
236 | 236 | ||
237 | /* Copy parameters and call proper function */ | 237 | static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id, |
238 | static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, | 238 | void __user *addr) |
239 | void __user *addr) | ||
240 | { | 239 | { |
240 | char *pathname; | ||
241 | int ret; | 241 | int ret; |
242 | 242 | ||
243 | switch (cmd) { | 243 | pathname = getname(addr); |
244 | case Q_QUOTAON: { | 244 | if (IS_ERR(pathname)) |
245 | char *pathname; | 245 | return PTR_ERR(pathname); |
246 | 246 | ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0); | |
247 | pathname = getname(addr); | 247 | putname(pathname); |
248 | if (IS_ERR(pathname)) | 248 | return ret; |
249 | return PTR_ERR(pathname); | 249 | } |
250 | ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0); | ||
251 | putname(pathname); | ||
252 | return ret; | ||
253 | } | ||
254 | case Q_QUOTAOFF: | ||
255 | return sb->s_qcop->quota_off(sb, type, 0); | ||
256 | 250 | ||
257 | case Q_GETFMT: { | 251 | static int quota_getfmt(struct super_block *sb, int type, void __user *addr) |
258 | __u32 fmt; | 252 | { |
253 | __u32 fmt; | ||
259 | 254 | ||
260 | down_read(&sb_dqopt(sb)->dqptr_sem); | 255 | down_read(&sb_dqopt(sb)->dqptr_sem); |
261 | if (!sb_has_quota_active(sb, type)) { | 256 | if (!sb_has_quota_active(sb, type)) { |
262 | up_read(&sb_dqopt(sb)->dqptr_sem); | 257 | up_read(&sb_dqopt(sb)->dqptr_sem); |
263 | return -ESRCH; | 258 | return -ESRCH; |
264 | } | 259 | } |
265 | fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id; | 260 | fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id; |
266 | up_read(&sb_dqopt(sb)->dqptr_sem); | 261 | up_read(&sb_dqopt(sb)->dqptr_sem); |
267 | if (copy_to_user(addr, &fmt, sizeof(fmt))) | 262 | if (copy_to_user(addr, &fmt, sizeof(fmt))) |
268 | return -EFAULT; | 263 | return -EFAULT; |
269 | return 0; | 264 | return 0; |
270 | } | 265 | } |
271 | case Q_GETINFO: { | ||
272 | struct if_dqinfo info; | ||
273 | |||
274 | ret = sb->s_qcop->get_info(sb, type, &info); | ||
275 | if (ret) | ||
276 | return ret; | ||
277 | if (copy_to_user(addr, &info, sizeof(info))) | ||
278 | return -EFAULT; | ||
279 | return 0; | ||
280 | } | ||
281 | case Q_SETINFO: { | ||
282 | struct if_dqinfo info; | ||
283 | 266 | ||
284 | if (copy_from_user(&info, addr, sizeof(info))) | 267 | static int quota_getinfo(struct super_block *sb, int type, void __user *addr) |
285 | return -EFAULT; | 268 | { |
286 | return sb->s_qcop->set_info(sb, type, &info); | 269 | struct if_dqinfo info; |
287 | } | 270 | int ret; |
288 | case Q_GETQUOTA: { | ||
289 | struct if_dqblk idq; | ||
290 | |||
291 | ret = sb->s_qcop->get_dqblk(sb, type, id, &idq); | ||
292 | if (ret) | ||
293 | return ret; | ||
294 | if (copy_to_user(addr, &idq, sizeof(idq))) | ||
295 | return -EFAULT; | ||
296 | return 0; | ||
297 | } | ||
298 | case Q_SETQUOTA: { | ||
299 | struct if_dqblk idq; | ||
300 | 271 | ||
301 | if (copy_from_user(&idq, addr, sizeof(idq))) | 272 | ret = sb->s_qcop->get_info(sb, type, &info); |
302 | return -EFAULT; | 273 | if (!ret && copy_to_user(addr, &info, sizeof(info))) |
303 | return sb->s_qcop->set_dqblk(sb, type, id, &idq); | 274 | return -EFAULT; |
304 | } | 275 | return ret; |
305 | case Q_SYNC: | 276 | } |
306 | if (sb) | ||
307 | sync_quota_sb(sb, type); | ||
308 | else | ||
309 | sync_dquots(type); | ||
310 | return 0; | ||
311 | 277 | ||
312 | case Q_XQUOTAON: | 278 | static int quota_setinfo(struct super_block *sb, int type, void __user *addr) |
313 | case Q_XQUOTAOFF: | 279 | { |
314 | case Q_XQUOTARM: { | 280 | struct if_dqinfo info; |
315 | __u32 flags; | ||
316 | 281 | ||
317 | if (copy_from_user(&flags, addr, sizeof(flags))) | 282 | if (copy_from_user(&info, addr, sizeof(info))) |
318 | return -EFAULT; | 283 | return -EFAULT; |
319 | return sb->s_qcop->set_xstate(sb, flags, cmd); | 284 | return sb->s_qcop->set_info(sb, type, &info); |
320 | } | 285 | } |
321 | case Q_XGETQSTAT: { | 286 | |
322 | struct fs_quota_stat fqs; | 287 | static int quota_getquota(struct super_block *sb, int type, qid_t id, |
288 | void __user *addr) | ||
289 | { | ||
290 | struct if_dqblk idq; | ||
291 | int ret; | ||
292 | |||
293 | ret = sb->s_qcop->get_dqblk(sb, type, id, &idq); | ||
294 | if (ret) | ||
295 | return ret; | ||
296 | if (copy_to_user(addr, &idq, sizeof(idq))) | ||
297 | return -EFAULT; | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int quota_setquota(struct super_block *sb, int type, qid_t id, | ||
302 | void __user *addr) | ||
303 | { | ||
304 | struct if_dqblk idq; | ||
305 | |||
306 | if (copy_from_user(&idq, addr, sizeof(idq))) | ||
307 | return -EFAULT; | ||
308 | return sb->s_qcop->set_dqblk(sb, type, id, &idq); | ||
309 | } | ||
310 | |||
311 | static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr) | ||
312 | { | ||
313 | __u32 flags; | ||
314 | |||
315 | if (copy_from_user(&flags, addr, sizeof(flags))) | ||
316 | return -EFAULT; | ||
317 | return sb->s_qcop->set_xstate(sb, flags, cmd); | ||
318 | } | ||
319 | |||
320 | static int quota_getxstate(struct super_block *sb, void __user *addr) | ||
321 | { | ||
322 | struct fs_quota_stat fqs; | ||
323 | int ret; | ||
323 | 324 | ||
324 | if ((ret = sb->s_qcop->get_xstate(sb, &fqs))) | 325 | ret = sb->s_qcop->get_xstate(sb, &fqs); |
325 | return ret; | 326 | if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) |
326 | if (copy_to_user(addr, &fqs, sizeof(fqs))) | 327 | return -EFAULT; |
327 | return -EFAULT; | 328 | return ret; |
328 | return 0; | 329 | } |
329 | } | ||
330 | case Q_XSETQLIM: { | ||
331 | struct fs_disk_quota fdq; | ||
332 | 330 | ||
333 | if (copy_from_user(&fdq, addr, sizeof(fdq))) | 331 | static int quota_setxquota(struct super_block *sb, int type, qid_t id, |
334 | return -EFAULT; | 332 | void __user *addr) |
335 | return sb->s_qcop->set_xquota(sb, type, id, &fdq); | 333 | { |
336 | } | 334 | struct fs_disk_quota fdq; |
337 | case Q_XGETQUOTA: { | 335 | |
338 | struct fs_disk_quota fdq; | 336 | if (copy_from_user(&fdq, addr, sizeof(fdq))) |
339 | 337 | return -EFAULT; | |
340 | ret = sb->s_qcop->get_xquota(sb, type, id, &fdq); | 338 | return sb->s_qcop->set_xquota(sb, type, id, &fdq); |
341 | if (ret) | 339 | } |
342 | return ret; | 340 | |
343 | if (copy_to_user(addr, &fdq, sizeof(fdq))) | 341 | static int quota_getxquota(struct super_block *sb, int type, qid_t id, |
344 | return -EFAULT; | 342 | void __user *addr) |
345 | return 0; | 343 | { |
346 | } | 344 | struct fs_disk_quota fdq; |
347 | case Q_XQUOTASYNC: | 345 | int ret; |
348 | return sb->s_qcop->quota_sync(sb, type); | 346 | |
349 | /* We never reach here unless validity check is broken */ | 347 | ret = sb->s_qcop->get_xquota(sb, type, id, &fdq); |
350 | default: | 348 | if (!ret && copy_to_user(addr, &fdq, sizeof(fdq))) |
351 | BUG(); | 349 | return -EFAULT; |
350 | return ret; | ||
351 | } | ||
352 | |||
353 | /* Copy parameters and call proper function */ | ||
354 | static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, | ||
355 | void __user *addr) | ||
356 | { | ||
357 | switch (cmd) { | ||
358 | case Q_QUOTAON: | ||
359 | return quota_quotaon(sb, type, cmd, id, addr); | ||
360 | case Q_QUOTAOFF: | ||
361 | return sb->s_qcop->quota_off(sb, type, 0); | ||
362 | case Q_GETFMT: | ||
363 | return quota_getfmt(sb, type, addr); | ||
364 | case Q_GETINFO: | ||
365 | return quota_getinfo(sb, type, addr); | ||
366 | case Q_SETINFO: | ||
367 | return quota_setinfo(sb, type, addr); | ||
368 | case Q_GETQUOTA: | ||
369 | return quota_getquota(sb, type, id, addr); | ||
370 | case Q_SETQUOTA: | ||
371 | return quota_setquota(sb, type, id, addr); | ||
372 | case Q_SYNC: | ||
373 | if (sb) | ||
374 | sync_quota_sb(sb, type); | ||
375 | else | ||
376 | sync_dquots(type); | ||
377 | return 0; | ||
378 | case Q_XQUOTAON: | ||
379 | case Q_XQUOTAOFF: | ||
380 | case Q_XQUOTARM: | ||
381 | return quota_setxstate(sb, cmd, addr); | ||
382 | case Q_XGETQSTAT: | ||
383 | return quota_getxstate(sb, addr); | ||
384 | case Q_XSETQLIM: | ||
385 | return quota_setxquota(sb, type, id, addr); | ||
386 | case Q_XGETQUOTA: | ||
387 | return quota_getxquota(sb, type, id, addr); | ||
388 | case Q_XQUOTASYNC: | ||
389 | return sb->s_qcop->quota_sync(sb, type); | ||
390 | /* We never reach here unless validity check is broken */ | ||
391 | default: | ||
392 | BUG(); | ||
352 | } | 393 | } |
394 | |||
353 | return 0; | 395 | return 0; |
354 | } | 396 | } |
355 | 397 | ||