hugetlb: wrap set_new_inode() with alloc_key()
PATCH 2/11 hugetlb: wrap set_new_inode() with alloc_key()
A first step toward removing inodes from key management:
Put set_new_inode() and the inode allocation loop into an alloc_key(), and introduce a new opaque type "struct hugetlb_key".
hugetlbpage.c | 122 ++++++++++++++++++++++++++++++---------------------------- 1 files changed, 64 insertions(+), 58 deletions(-)
arch/i386/mm/hugetlbpage.c +65 -59
@@ -13,6 +13,7 @@#include <linux/smp_lock.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/err.h> #include <asm/mman.h> #include <asm/pgalloc.h> #include <asm/tlb.h>
@@ -32,6 +33,8 @@ static struct htlbpagekey {int key; } htlbpagek[MAX_ID ]; +struct hugetlb_key ; +static struct inode *find_key_inode (int key) {int i;
@@ -43,6 +46,61 @@ static struct inode *find_key_inode(intreturn NULL ; } +static int check_size_prot (struct inode *inode,unsigned long len,int prot,int flag); +/* +* Call without htlbpage_lock, returns with htlbpage_lock held. +*/ +struct hugetlb_key *alloc_key (int key,unsigned long len,int prot,int flag,int *new) +{ +struct inode *inode; + +do { +spin_lock (&htlbpage_lock); + inode =find_key_inode (key); +if (!inode) { +if (!capable (CAP_SYS_ADMIN ) || !in_group_p (0 )) + inode =ERR_PTR (-EPERM ); +else if (!(flag &IPC_CREAT )) + inode =ERR_PTR (-ENOENT ); +else { + inode =kmalloc (sizeof (struct inode ),GFP_ATOMIC ); +if (!inode) + inode =ERR_PTR (-ENOMEM ); +else { +int i; +for (i =0 ; i <MAX_ID ; ++i) +if (!htlbpagek[i].key) +break ; +if (i ==MAX_ID ) { +kfree (inode); + inode =ERR_PTR (-ENOMEM ); + }else { +inode_init_once (inode); +atomic_inc (&inode->i_writecount); + inode->i_mapping = &inode->i_data; + inode->i_mapping->host = inode; + inode->i_ino = (unsigned long )key; + htlbpagek[i].key = key; + htlbpagek[i].in = inode; + inode->i_uid = current->fsuid; + inode->i_gid = current->fsgid; + inode->i_mode = prot; + inode->i_size = len; + *new =1 ; + } + } + } + }else if (atomic_read (&inode->i_writecount)) { + inode =ERR_PTR (-EAGAIN ); +spin_unlock (&htlbpage_lock); + }else if (check_size_prot (inode, len, prot, flag) <0 ) + inode =ERR_PTR (-EINVAL ); +else + *new =0 ; + }while (inode ==ERR_PTR (-EAGAIN )); +return (struct hugetlb_key *)inode; +} +static struct page *alloc_hugetlb_page (void ) {int i;
@@ -264,36 +322,6 @@ void zap_hugepage_range(struct vm_area_sspin_unlock (&mm->page_table_lock); } -static struct inode *set_new_inode (unsigned long len,int prot,int flag,int key) -{ -struct inode *inode; -int i; - -for (i =0 ; i <MAX_ID ; i++) { -if (htlbpagek[i].key ==0 ) -break ; - } -if (i ==MAX_ID ) -return NULL ; - inode =kmalloc (sizeof (struct inode ),GFP_ATOMIC ); -if (inode ==NULL ) -return NULL ; - -inode_init_once (inode); -atomic_inc (&inode->i_writecount); - inode->i_mapping = &inode->i_data; - inode->i_mapping->host = inode; - inode->i_ino = (unsigned long )key; - - htlbpagek[i].key = key; - htlbpagek[i].in = inode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; - inode->i_mode = prot; - inode->i_size = len; -return inode; -} -static int check_size_prot (struct inode *inode,unsigned long len,int prot,int flag) {if (inode->i_uid != current->fsuid)
@@ -315,36 +343,14 @@ static int alloc_shared_hugetlb_pages(inint retval = -ENOMEM ;int newalloc =0 ; -try_again: -spin_lock (&htlbpage_lock); + inode = (struct inode *)alloc_key (key, len, prot, flag, &newalloc); +if (IS_ERR (inode)) { + retval =PTR_ERR (inode); +spin_unlock (&htlbpage_lock); + goto out_err; + }else +spin_unlock (&htlbpage_lock); - inode =find_key_inode (key); -if (inode ==NULL ) { -if (!capable (CAP_SYS_ADMIN )) { -if (!in_group_p (0 )) { - retval = -EPERM ; - goto out_err; - } - } -if (!(flag &IPC_CREAT )) { - retval = -ENOENT ; - goto out_err; - } - inode =set_new_inode (len, prot, flag, key); -if (inode ==NULL ) - goto out_err; - newalloc =1 ; - }else { -if (check_size_prot (inode, len, prot, flag) <0 ) { - retval = -EINVAL ; - goto out_err; - } -else if (atomic_read (&inode->i_writecount)) { -spin_unlock (&htlbpage_lock); - goto try_again; - } - } -spin_unlock (&htlbpage_lock); mapping = inode->i_mapping; addr = do_mmap_pgoff(NULL, addr, len, (unsigned long) prot,