diff options
Diffstat (limited to 'fs/hugetlbfs')
-rw-r--r-- | fs/hugetlbfs/inode.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 6e5bd42f3860..7aafeb8fa300 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/statfs.h> | 31 | #include <linux/statfs.h> |
32 | #include <linux/security.h> | 32 | #include <linux/security.h> |
33 | #include <linux/magic.h> | 33 | #include <linux/magic.h> |
34 | #include <linux/migrate.h> | ||
34 | 35 | ||
35 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
36 | 37 | ||
@@ -331,8 +332,7 @@ static void truncate_huge_page(struct page *page) | |||
331 | { | 332 | { |
332 | cancel_dirty_page(page, /* No IO accounting for huge pages? */0); | 333 | cancel_dirty_page(page, /* No IO accounting for huge pages? */0); |
333 | ClearPageUptodate(page); | 334 | ClearPageUptodate(page); |
334 | remove_from_page_cache(page); | 335 | delete_from_page_cache(page); |
335 | put_page(page); | ||
336 | } | 336 | } |
337 | 337 | ||
338 | static void truncate_hugepages(struct inode *inode, loff_t lstart) | 338 | static void truncate_hugepages(struct inode *inode, loff_t lstart) |
@@ -412,10 +412,10 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset) | |||
412 | pgoff = offset >> PAGE_SHIFT; | 412 | pgoff = offset >> PAGE_SHIFT; |
413 | 413 | ||
414 | i_size_write(inode, offset); | 414 | i_size_write(inode, offset); |
415 | spin_lock(&mapping->i_mmap_lock); | 415 | mutex_lock(&mapping->i_mmap_mutex); |
416 | if (!prio_tree_empty(&mapping->i_mmap)) | 416 | if (!prio_tree_empty(&mapping->i_mmap)) |
417 | hugetlb_vmtruncate_list(&mapping->i_mmap, pgoff); | 417 | hugetlb_vmtruncate_list(&mapping->i_mmap, pgoff); |
418 | spin_unlock(&mapping->i_mmap_lock); | 418 | mutex_unlock(&mapping->i_mmap_mutex); |
419 | truncate_hugepages(inode, offset); | 419 | truncate_hugepages(inode, offset); |
420 | return 0; | 420 | return 0; |
421 | } | 421 | } |
@@ -455,6 +455,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, | |||
455 | inode = new_inode(sb); | 455 | inode = new_inode(sb); |
456 | if (inode) { | 456 | if (inode) { |
457 | struct hugetlbfs_inode_info *info; | 457 | struct hugetlbfs_inode_info *info; |
458 | inode->i_ino = get_next_ino(); | ||
458 | inode->i_mode = mode; | 459 | inode->i_mode = mode; |
459 | inode->i_uid = uid; | 460 | inode->i_uid = uid; |
460 | inode->i_gid = gid; | 461 | inode->i_gid = gid; |
@@ -573,6 +574,19 @@ static int hugetlbfs_set_page_dirty(struct page *page) | |||
573 | return 0; | 574 | return 0; |
574 | } | 575 | } |
575 | 576 | ||
577 | static int hugetlbfs_migrate_page(struct address_space *mapping, | ||
578 | struct page *newpage, struct page *page) | ||
579 | { | ||
580 | int rc; | ||
581 | |||
582 | rc = migrate_huge_page_move_mapping(mapping, newpage, page); | ||
583 | if (rc) | ||
584 | return rc; | ||
585 | migrate_page_copy(newpage, page); | ||
586 | |||
587 | return 0; | ||
588 | } | ||
589 | |||
576 | static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 590 | static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
577 | { | 591 | { |
578 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb); | 592 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb); |
@@ -648,17 +662,25 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) | |||
648 | return &p->vfs_inode; | 662 | return &p->vfs_inode; |
649 | } | 663 | } |
650 | 664 | ||
665 | static void hugetlbfs_i_callback(struct rcu_head *head) | ||
666 | { | ||
667 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
668 | INIT_LIST_HEAD(&inode->i_dentry); | ||
669 | kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode)); | ||
670 | } | ||
671 | |||
651 | static void hugetlbfs_destroy_inode(struct inode *inode) | 672 | static void hugetlbfs_destroy_inode(struct inode *inode) |
652 | { | 673 | { |
653 | hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb)); | 674 | hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb)); |
654 | mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy); | 675 | mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy); |
655 | kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode)); | 676 | call_rcu(&inode->i_rcu, hugetlbfs_i_callback); |
656 | } | 677 | } |
657 | 678 | ||
658 | static const struct address_space_operations hugetlbfs_aops = { | 679 | static const struct address_space_operations hugetlbfs_aops = { |
659 | .write_begin = hugetlbfs_write_begin, | 680 | .write_begin = hugetlbfs_write_begin, |
660 | .write_end = hugetlbfs_write_end, | 681 | .write_end = hugetlbfs_write_end, |
661 | .set_page_dirty = hugetlbfs_set_page_dirty, | 682 | .set_page_dirty = hugetlbfs_set_page_dirty, |
683 | .migratepage = hugetlbfs_migrate_page, | ||
662 | }; | 684 | }; |
663 | 685 | ||
664 | 686 | ||
@@ -674,6 +696,7 @@ const struct file_operations hugetlbfs_file_operations = { | |||
674 | .mmap = hugetlbfs_file_mmap, | 696 | .mmap = hugetlbfs_file_mmap, |
675 | .fsync = noop_fsync, | 697 | .fsync = noop_fsync, |
676 | .get_unmapped_area = hugetlb_get_unmapped_area, | 698 | .get_unmapped_area = hugetlb_get_unmapped_area, |
699 | .llseek = default_llseek, | ||
677 | }; | 700 | }; |
678 | 701 | ||
679 | static const struct inode_operations hugetlbfs_dir_inode_operations = { | 702 | static const struct inode_operations hugetlbfs_dir_inode_operations = { |
@@ -879,15 +902,15 @@ void hugetlb_put_quota(struct address_space *mapping, long delta) | |||
879 | } | 902 | } |
880 | } | 903 | } |
881 | 904 | ||
882 | static int hugetlbfs_get_sb(struct file_system_type *fs_type, | 905 | static struct dentry *hugetlbfs_mount(struct file_system_type *fs_type, |
883 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 906 | int flags, const char *dev_name, void *data) |
884 | { | 907 | { |
885 | return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super, mnt); | 908 | return mount_nodev(fs_type, flags, data, hugetlbfs_fill_super); |
886 | } | 909 | } |
887 | 910 | ||
888 | static struct file_system_type hugetlbfs_fs_type = { | 911 | static struct file_system_type hugetlbfs_fs_type = { |
889 | .name = "hugetlbfs", | 912 | .name = "hugetlbfs", |
890 | .get_sb = hugetlbfs_get_sb, | 913 | .mount = hugetlbfs_mount, |
891 | .kill_sb = kill_litter_super, | 914 | .kill_sb = kill_litter_super, |
892 | }; | 915 | }; |
893 | 916 | ||
@@ -898,7 +921,8 @@ static int can_do_hugetlb_shm(void) | |||
898 | return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group); | 921 | return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group); |
899 | } | 922 | } |
900 | 923 | ||
901 | struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | 924 | struct file *hugetlb_file_setup(const char *name, size_t size, |
925 | vm_flags_t acctflag, | ||
902 | struct user_struct **user, int creat_flags) | 926 | struct user_struct **user, int creat_flags) |
903 | { | 927 | { |
904 | int error = -ENOMEM; | 928 | int error = -ENOMEM; |
@@ -915,8 +939,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, | |||
915 | if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) { | 939 | if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) { |
916 | *user = current_user(); | 940 | *user = current_user(); |
917 | if (user_shm_lock(size, *user)) { | 941 | if (user_shm_lock(size, *user)) { |
918 | WARN_ONCE(1, | 942 | printk_once(KERN_WARNING "Using mlock ulimits for SHM_HUGETLB is deprecated\n"); |
919 | "Using mlock ulimits for SHM_HUGETLB deprecated\n"); | ||
920 | } else { | 943 | } else { |
921 | *user = NULL; | 944 | *user = NULL; |
922 | return ERR_PTR(-EPERM); | 945 | return ERR_PTR(-EPERM); |