diff options
Diffstat (limited to 'fs/file_table.c')
-rw-r--r-- | fs/file_table.c | 42 |
1 files changed, 18 insertions, 24 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index edecd36fed9b..6f0e62ecfddd 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -32,8 +32,7 @@ struct files_stat_struct files_stat = { | |||
32 | .max_files = NR_FILE | 32 | .max_files = NR_FILE |
33 | }; | 33 | }; |
34 | 34 | ||
35 | /* public. Not pretty! */ | 35 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); |
36 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); | ||
37 | 36 | ||
38 | /* SLAB cache for file structures */ | 37 | /* SLAB cache for file structures */ |
39 | static struct kmem_cache *filp_cachep __read_mostly; | 38 | static struct kmem_cache *filp_cachep __read_mostly; |
@@ -249,7 +248,7 @@ static void __fput(struct file *file) | |||
249 | cdev_put(inode->i_cdev); | 248 | cdev_put(inode->i_cdev); |
250 | fops_put(file->f_op); | 249 | fops_put(file->f_op); |
251 | put_pid(file->f_owner.pid); | 250 | put_pid(file->f_owner.pid); |
252 | file_kill(file); | 251 | file_sb_list_del(file); |
253 | if (file->f_mode & FMODE_WRITE) | 252 | if (file->f_mode & FMODE_WRITE) |
254 | drop_file_write_access(file); | 253 | drop_file_write_access(file); |
255 | file->f_path.dentry = NULL; | 254 | file->f_path.dentry = NULL; |
@@ -328,31 +327,29 @@ struct file *fget_light(unsigned int fd, int *fput_needed) | |||
328 | return file; | 327 | return file; |
329 | } | 328 | } |
330 | 329 | ||
331 | |||
332 | void put_filp(struct file *file) | 330 | void put_filp(struct file *file) |
333 | { | 331 | { |
334 | if (atomic_long_dec_and_test(&file->f_count)) { | 332 | if (atomic_long_dec_and_test(&file->f_count)) { |
335 | security_file_free(file); | 333 | security_file_free(file); |
336 | file_kill(file); | 334 | file_sb_list_del(file); |
337 | file_free(file); | 335 | file_free(file); |
338 | } | 336 | } |
339 | } | 337 | } |
340 | 338 | ||
341 | void file_move(struct file *file, struct list_head *list) | 339 | void file_sb_list_add(struct file *file, struct super_block *sb) |
342 | { | 340 | { |
343 | if (!list) | 341 | spin_lock(&files_lock); |
344 | return; | 342 | BUG_ON(!list_empty(&file->f_u.fu_list)); |
345 | file_list_lock(); | 343 | list_add(&file->f_u.fu_list, &sb->s_files); |
346 | list_move(&file->f_u.fu_list, list); | 344 | spin_unlock(&files_lock); |
347 | file_list_unlock(); | ||
348 | } | 345 | } |
349 | 346 | ||
350 | void file_kill(struct file *file) | 347 | void file_sb_list_del(struct file *file) |
351 | { | 348 | { |
352 | if (!list_empty(&file->f_u.fu_list)) { | 349 | if (!list_empty(&file->f_u.fu_list)) { |
353 | file_list_lock(); | 350 | spin_lock(&files_lock); |
354 | list_del_init(&file->f_u.fu_list); | 351 | list_del_init(&file->f_u.fu_list); |
355 | file_list_unlock(); | 352 | spin_unlock(&files_lock); |
356 | } | 353 | } |
357 | } | 354 | } |
358 | 355 | ||
@@ -361,7 +358,7 @@ int fs_may_remount_ro(struct super_block *sb) | |||
361 | struct file *file; | 358 | struct file *file; |
362 | 359 | ||
363 | /* Check that no files are currently opened for writing. */ | 360 | /* Check that no files are currently opened for writing. */ |
364 | file_list_lock(); | 361 | spin_lock(&files_lock); |
365 | list_for_each_entry(file, &sb->s_files, f_u.fu_list) { | 362 | list_for_each_entry(file, &sb->s_files, f_u.fu_list) { |
366 | struct inode *inode = file->f_path.dentry->d_inode; | 363 | struct inode *inode = file->f_path.dentry->d_inode; |
367 | 364 | ||
@@ -373,10 +370,10 @@ int fs_may_remount_ro(struct super_block *sb) | |||
373 | if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) | 370 | if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) |
374 | goto too_bad; | 371 | goto too_bad; |
375 | } | 372 | } |
376 | file_list_unlock(); | 373 | spin_unlock(&files_lock); |
377 | return 1; /* Tis' cool bro. */ | 374 | return 1; /* Tis' cool bro. */ |
378 | too_bad: | 375 | too_bad: |
379 | file_list_unlock(); | 376 | spin_unlock(&files_lock); |
380 | return 0; | 377 | return 0; |
381 | } | 378 | } |
382 | 379 | ||
@@ -392,7 +389,7 @@ void mark_files_ro(struct super_block *sb) | |||
392 | struct file *f; | 389 | struct file *f; |
393 | 390 | ||
394 | retry: | 391 | retry: |
395 | file_list_lock(); | 392 | spin_lock(&files_lock); |
396 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { | 393 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { |
397 | struct vfsmount *mnt; | 394 | struct vfsmount *mnt; |
398 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) | 395 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) |
@@ -408,16 +405,13 @@ retry: | |||
408 | continue; | 405 | continue; |
409 | file_release_write(f); | 406 | file_release_write(f); |
410 | mnt = mntget(f->f_path.mnt); | 407 | mnt = mntget(f->f_path.mnt); |
411 | file_list_unlock(); | 408 | /* This can sleep, so we can't hold the spinlock. */ |
412 | /* | 409 | spin_unlock(&files_lock); |
413 | * This can sleep, so we can't hold | ||
414 | * the file_list_lock() spinlock. | ||
415 | */ | ||
416 | mnt_drop_write(mnt); | 410 | mnt_drop_write(mnt); |
417 | mntput(mnt); | 411 | mntput(mnt); |
418 | goto retry; | 412 | goto retry; |
419 | } | 413 | } |
420 | file_list_unlock(); | 414 | spin_unlock(&files_lock); |
421 | } | 415 | } |
422 | 416 | ||
423 | void __init files_init(unsigned long mempages) | 417 | void __init files_init(unsigned long mempages) |