Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 316622 Details for
Bug 185585
Hangs when registering modules to handle ioctls in kernel compatibility mode
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
re-implement (un)registering 32-bit compat ioctls using refcounts x86_64
compat.patch (text/plain), 5.19 KB, created by
Jason Baron
on 2008-09-12 20:13:54 UTC
(
hide
)
Description:
re-implement (un)registering 32-bit compat ioctls using refcounts x86_64
Filename:
MIME Type:
Creator:
Jason Baron
Created:
2008-09-12 20:13:54 UTC
Size:
5.19 KB
patch
obsolete
>diff --git a/fs/compat.c b/fs/compat.c >index ac51f8f..1ef0d43 100644 >--- a/fs/compat.c >+++ b/fs/compat.c >@@ -252,6 +252,16 @@ out: > static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE]; > static DECLARE_RWSEM(ioctl32_sem); > >+/* create a parallel hash table that uses refcounts to allow multiple >+ parallel (un)register. Parallel table works around KABI issues */ >+ >+struct ioctl32_refcount { >+ int count; >+ wait_queue_head_t ref_wait; >+ struct ioctl32_refcount *next; >+}; >+static struct ioctl32_refcount *ioctl32_refcount_table[IOCTL_HASHSIZE]; >+ > extern struct ioctl_trans ioctl_start[]; > extern int ioctl_table_size; > >@@ -260,26 +270,40 @@ static inline unsigned long ioctl32_hash(unsigned long cmd) > return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE; > } > >-static void ioctl32_insert_translation(struct ioctl_trans *trans) >+static int ioctl32_insert_translation(struct ioctl_trans *trans) > { > unsigned long hash; > struct ioctl_trans *t; >+ struct ioctl32_refcount *new_ref, *r; >+ >+ new_ref = kmalloc(sizeof(*new_ref), GFP_KERNEL); >+ if (!new_ref) >+ return -ENOMEM; >+ new_ref->count = 0; >+ init_waitqueue_head(&new_ref->ref_wait); >+ new_ref->next = NULL; > > hash = ioctl32_hash (trans->cmd); >- if (!ioctl32_hash_table[hash]) >+ if (!ioctl32_hash_table[hash]) { > ioctl32_hash_table[hash] = trans; >- else { >+ ioctl32_refcount_table[hash] = new_ref; >+ } else { > t = ioctl32_hash_table[hash]; >+ r = ioctl32_refcount_table[hash]; > while (t->next) > t = t->next; >+ while (r->next) >+ r = r->next; > trans->next = NULL; > t->next = trans; >+ r->next = new_ref; > } >+ return 0; > } > > static int __init init_sys32_ioctl(void) > { >- int i; >+ int i, ret; > > for (i = 0; i < ioctl_table_size; i++) { > if (ioctl_start[i].next != 0) { >@@ -287,7 +311,9 @@ static int __init init_sys32_ioctl(void) > return -1; > } > >- ioctl32_insert_translation(&ioctl_start[i]); >+ ret = ioctl32_insert_translation(&ioctl_start[i]); >+ if (ret) >+ return -1; > } > return 0; > } >@@ -300,6 +326,7 @@ int register_ioctl32_conversion(unsigned int cmd, > struct ioctl_trans *t; > struct ioctl_trans *new_t; > unsigned long hash = ioctl32_hash(cmd); >+ int ret = 0; > > new_t = kmalloc(sizeof(*new_t), GFP_KERNEL); > if (!new_t) >@@ -318,10 +345,9 @@ int register_ioctl32_conversion(unsigned int cmd, > new_t->next = NULL; > new_t->cmd = cmd; > new_t->handler = handler; >- ioctl32_insert_translation(new_t); >- >+ ret = ioctl32_insert_translation(new_t); > up_write(&ioctl32_sem); >- return 0; >+ return ret; > } > EXPORT_SYMBOL(register_ioctl32_conversion); > >@@ -339,10 +365,14 @@ int unregister_ioctl32_conversion(unsigned int cmd) > { > unsigned long hash = ioctl32_hash(cmd); > struct ioctl_trans *t, *t1; >+ struct ioctl32_refcount *r, *r1; > >+restart: > down_write(&ioctl32_sem); > > t = ioctl32_hash_table[hash]; >+ r = ioctl32_refcount_table[hash]; >+ > if (!t) { > up_write(&ioctl32_sem); > return -EINVAL; >@@ -353,28 +383,46 @@ int unregister_ioctl32_conversion(unsigned int cmd) > printk("%p tried to unregister builtin ioctl %x\n", > __builtin_return_address(0), cmd); > } else { >+ if (r->count) { >+ up_write(&ioctl32_sem); >+ if(wait_event_interruptible(r->ref_wait, r->count == 0) < 0) >+ return -ERESTARTSYS; >+ goto restart; >+ } > ioctl32_hash_table[hash] = t->next; >+ ioctl32_refcount_table[hash] = r->next; > up_write(&ioctl32_sem); > kfree(t); >+ kfree(r); > return 0; > } > } > while (t->next) { > t1 = t->next; >+ r1 = r->next; > if (t1->cmd == cmd) { > if (builtin_ioctl(t1)) { > printk("%p tried to unregister builtin " > "ioctl %x\n", > __builtin_return_address(0), cmd); > goto out; >- } else { >+ } else { >+ if (r1->count) { >+ up_write(&ioctl32_sem); >+ if(wait_event_interruptible(r->ref_wait, r->count == 0) < 0) >+ return -ERESTARTSYS; >+ goto restart; >+ } > t->next = t1->next; >+ r->next = r1->next; > up_write(&ioctl32_sem); > kfree(t1); >+ kfree(r1); > return 0; > } > } > t = t1; >+ r = r1; > } > printk(KERN_ERR "Trying to free unknown 32bit ioctl handler %x\n", > cmd); >@@ -390,6 +438,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, > struct file * filp; > int error = -EBADF; > struct ioctl_trans *t; >+ struct ioctl32_refcount *r; > > filp = fget(fd); > if(!filp) >@@ -400,24 +449,33 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, > goto out; > } > >- down_read(&ioctl32_sem); >+ down_write(&ioctl32_sem); > > t = ioctl32_hash_table[ioctl32_hash (cmd)]; >+ r = ioctl32_refcount_table[ioctl32_hash(cmd)]; > >- while (t && t->cmd != cmd) >+ while (t && t->cmd != cmd) { > t = t->next; >+ r = r->next; >+ } > if (t) { > if (t->handler) { >+ r->count += 1; >+ up_write(&ioctl32_sem); > lock_kernel(); > error = t->handler(fd, cmd, arg, filp); > unlock_kernel(); >- up_read(&ioctl32_sem); >+ down_write(&ioctl32_sem); >+ r->count -= 1; >+ if (r->count == 0) >+ wake_up_all(&r->ref_wait); >+ up_write(&ioctl32_sem); > } else { >- up_read(&ioctl32_sem); >+ up_write(&ioctl32_sem); > error = sys_ioctl(fd, cmd, arg); > } > } else { >- up_read(&ioctl32_sem); >+ up_write(&ioctl32_sem); > if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { > error = siocdevprivate_ioctl(fd, cmd, arg); > } else {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 185585
: 316622