From: Stoyan Gaydarov <stoyboyker@gmail.com>
To: Jonathan Corbet <corbet@lwn.net>
Cc: linux-kernel@vger.kernel.org, gregkh@suse.de
Subject: Re: [PATCH 01/13] [staging] changed ioctls to unlocked
Date: Tue, 24 Mar 2009 19:12:36 -0500 [thread overview]
Message-ID: <6d291e080903241712y6d688bbfp753aae641617a5a7@mail.gmail.com> (raw)
In-Reply-To: <20090324174057.47f7da3d@bike.lwn.net>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 19704 bytes --]
On Tue, Mar 24, 2009 at 6:40 PM, Jonathan Corbet <corbet@lwn.net> wrote:> OK, looking at the patch now...>>>  drivers/staging/epl/EplApiLinuxKernel.c |  10 ++->>  drivers/staging/meilhaus/memain.c    |  124 +++++++++++++++++++++---------->>  drivers/staging/poch/poch.c       |  25 +++++-->>  3 files changed, 107 insertions(+), 52 deletions(-)>>>> diff --git a/drivers/staging/epl/EplApiLinuxKernel.c b/drivers/staging/epl/EplApiLinuxKernel.c>> index 05ca062..9517da2 100644>> --- a/drivers/staging/epl/EplApiLinuxKernel.c>> +++ b/drivers/staging/epl/EplApiLinuxKernel.c>> @@ -219,7 +219,7 @@ static ssize_t EplLinRead(struct file *pInstance_p, char *pDstBuff_p,>>             size_t BuffSize_p, loff_t * pFileOffs_p);>>  static ssize_t EplLinWrite(struct file *pInstance_p, const char *pSrcBuff_p,>>              size_t BuffSize_p, loff_t * pFileOffs_p);>> -static int EplLinIoctl(struct inode *pDeviceFile_p, struct file *pInstance_p,>> +static long EplLinIoctl(struct file *pInstance_p,>>            unsigned int uiIoctlCmd_p, unsigned long ulArg_p);>>>>  //--------------------------------------------------------------------------->> @@ -237,7 +237,7 @@ static struct file_operations EplLinFileOps_g = {>>    .release = EplLinRelease,>>    .read = EplLinRead,>>    .write = EplLinWrite,>> -   .ioctl = EplLinIoctl,>> +   .unlocked_ioctl = EplLinIoctl,>>>>  };>>>> @@ -551,12 +551,13 @@ static ssize_t EplLinWrite(struct file *pInstance_p,   // information about driver>>  //  -> ioctl(...)>>  //--------------------------------------------------------------------------->>>> -static int EplLinIoctl(struct inode *pDeviceFile_p,  // information about the device to open>> -           struct file *pInstance_p,     // information about driver instance>> +static long EplLinIoctl(struct file *pInstance_p,   // information about driver instance>>            unsigned int uiIoctlCmd_p,    // Ioctl command to execute>>            unsigned long ulArg_p)  // Ioctl command specific argument/parameter>>  {>>>> +   lock_kernel();>> +>>    tEplKernel EplRet;>>    int iErr;>>    int iRet;>> @@ -1148,6 +1149,7 @@ static int EplLinIoctl(struct inode *pDeviceFile_p,   // information about the dev>>     Exit:>>>>  //   TRACE1("EPL: - EplLinIoctl (iRet=%d)\n", iRet);>> +   unlock_kernel();>>    return (iRet);>>>>  }>> Gee what ugly code you're working on here.  It's like...crap or> something...:)>> You should avoid making it worse by putting lock_kernel() above the> variable declarations, though.  That will set off alarms for sure, even in> -staging code.>>> diff --git a/drivers/staging/meilhaus/memain.c b/drivers/staging/meilhaus/memain.c>> index b09d1a6..9a1706b 100644>> --- a/drivers/staging/meilhaus/memain.c>> +++ b/drivers/staging/meilhaus/memain.c>> @@ -95,7 +95,7 @@ static int replace_with_dummy(int vendor_id, int device_id, int serial_no);>>  static void clear_device_list(void);>>  static int me_open(struct inode *inode_ptr, struct file *filep);>>  static int me_release(struct inode *, struct file *);>> -static int me_ioctl(struct inode *, struct file *, unsigned int, unsigned long);>> +static long me_ioctl(struct file *, unsigned int, unsigned long);>>  //static int me_probe_usb(struct usb_interface *interface, const struct usb_device_id *id);>>  //static void me_disconnect_usb(struct usb_interface *interface);>>>> @@ -109,7 +109,7 @@ static struct cdev *cdevp;>>>>  static struct file_operations me_file_operations = {>>    .owner = THIS_MODULE,>> -   .ioctl = me_ioctl,>> +   .unlocked_ioctl = me_ioctl,>>    .open = me_open,>>    .release = me_release,>>  };>> @@ -1751,14 +1751,17 @@ static void me_disconnect_usb(struct usb_interface *interface)>>  }>>  */>>>> -static int me_ioctl(struct inode *inodep,>> -         struct file *filep, unsigned int service, unsigned long arg)>> +static long me_ioctl(struct file *filep, unsigned int service,>> +         unsigned long arg)>>  {>> +   lock_kernel();>> +   long ret;>> Please declare the variable first.>>>    PDEBUG("executed.\n");>>>>    if (_IOC_TYPE(service) != MEMAIN_MAGIC) {>>        PERROR("Invalid magic number.\n");>> +       unlock_kernel();>>        return -ENOTTY;>>    }>> You also clearly do not need to do lock_kernel() before this test, so you> could move it down here and avoid one unlock/return sequence.>>> @@ -1766,147 +1769,186 @@ static int me_ioctl(struct inode *inodep,>>>>    switch (service) {>>    case ME_IO_IRQ_ENABLE:>> -       return me_io_irq_start(filep, (me_io_irq_start_t *) arg);>> +       ret = me_io_irq_start(filep, (me_io_irq_start_t *) arg);>> +       break;>>>>    case ME_IO_IRQ_WAIT:>> -       return me_io_irq_wait(filep, (me_io_irq_wait_t *) arg);>> +       ret = me_io_irq_wait(filep, (me_io_irq_wait_t *) arg);>> +       break;>>>>    case ME_IO_IRQ_DISABLE:>> -       return me_io_irq_stop(filep, (me_io_irq_stop_t *) arg);>> +       ret = me_io_irq_stop(filep, (me_io_irq_stop_t *) arg);>> +       break;>>>>    case ME_IO_RESET_DEVICE:>> -       return me_io_reset_device(filep, (me_io_reset_device_t *) arg);>> +       ret =  me_io_reset_device(filep, (me_io_reset_device_t *) arg);>> +       break;>>>>    case ME_IO_RESET_SUBDEVICE:>> -       return me_io_reset_subdevice(filep,>> +       ret =  me_io_reset_subdevice(filep,>>                       (me_io_reset_subdevice_t *) arg);>> +       break;>>>>    case ME_IO_SINGLE_CONFIG:>> -       return me_io_single_config(filep,>> +       ret = me_io_single_config(filep,>>                      (me_io_single_config_t *) arg);>> +       break;>>>>    case ME_IO_SINGLE:>> -       return me_io_single(filep, (me_io_single_t *) arg);>> +       ret =  me_io_single(filep, (me_io_single_t *) arg);>> +       break;>>>>    case ME_IO_STREAM_CONFIG:>> -       return me_io_stream_config(filep,>> +       ret = me_io_stream_config(filep,>>                      (me_io_stream_config_t *) arg);>> +       break;>>>>    case ME_IO_STREAM_NEW_VALUES:>> -       return me_io_stream_new_values(filep,>> +       ret =  me_io_stream_new_values(filep,>>                        (me_io_stream_new_values_t *)>>                        arg);>> +       break;>>>>    case ME_IO_STREAM_READ:>> -       return me_io_stream_read(filep, (me_io_stream_read_t *) arg);>> +       ret = me_io_stream_read(filep, (me_io_stream_read_t *) arg);>> +       break;>>>>    case ME_IO_STREAM_START:>> -       return me_io_stream_start(filep, (me_io_stream_start_t *) arg);>> +       ret = me_io_stream_start(filep, (me_io_stream_start_t *) arg);>> +       break;>>>>    case ME_IO_STREAM_STATUS:>> -       return me_io_stream_status(filep,>> +       ret =  me_io_stream_status(filep,>>                      (me_io_stream_status_t *) arg);>> +       break;>>>>    case ME_IO_STREAM_STOP:>> -       return me_io_stream_stop(filep, (me_io_stream_stop_t *) arg);>> +       ret = me_io_stream_stop(filep, (me_io_stream_stop_t *) arg);>> +       break;>>>>    case ME_IO_STREAM_WRITE:>> -       return me_io_stream_write(filep, (me_io_stream_write_t *) arg);>> +       ret = me_io_stream_write(filep, (me_io_stream_write_t *) arg);>> +       break;>>>>    case ME_LOCK_DRIVER:>> -       return me_lock_driver(filep, (me_lock_driver_t *) arg);>> +       ret = me_lock_driver(filep, (me_lock_driver_t *) arg);>> +       break;>>>>    case ME_LOCK_DEVICE:>> -       return me_lock_device(filep, (me_lock_device_t *) arg);>> +       ret = me_lock_device(filep, (me_lock_device_t *) arg);>> +       break;>>>>    case ME_LOCK_SUBDEVICE:>> -       return me_lock_subdevice(filep, (me_lock_subdevice_t *) arg);>> +       ret = me_lock_subdevice(filep, (me_lock_subdevice_t *) arg);>> +       break;>>>>    case ME_QUERY_INFO_DEVICE:>> -       return me_query_info_device(filep,>> +       ret = me_query_info_device(filep,>>                      (me_query_info_device_t *) arg);>> +       break;>>>>    case ME_QUERY_DESCRIPTION_DEVICE:>> -       return me_query_description_device(filep,>> +       ret = me_query_description_device(filep,>>                          (me_query_description_device_t>>                          *) arg);>> +       break;>>>>    case ME_QUERY_NAME_DEVICE:>> -       return me_query_name_device(filep,>> +       ret = me_query_name_device(filep,>>                      (me_query_name_device_t *) arg);>> +       break;>>>>    case ME_QUERY_NAME_DEVICE_DRIVER:>> -       return me_query_name_device_driver(filep,>> +       ret = me_query_name_device_driver(filep,>>                          (me_query_name_device_driver_t>>                          *) arg);>> +       break;>>>>    case ME_QUERY_NUMBER_DEVICES:>> -       return me_query_number_devices(filep,>> +       ret = me_query_number_devices(filep,>>                        (me_query_number_devices_t *)>>                        arg);>> +       break;>>>>    case ME_QUERY_NUMBER_SUBDEVICES:>> -       return me_query_number_subdevices(filep,>> +       ret =  me_query_number_subdevices(filep,>>                         (me_query_number_subdevices_t>>                          *) arg);>> +       break;>>>>    case ME_QUERY_NUMBER_CHANNELS:>> -       return me_query_number_channels(filep,>> +       ret = me_query_number_channels(filep,>>                        (me_query_number_channels_t *)>>                        arg);>> +       break;>>>>    case ME_QUERY_NUMBER_RANGES:>> -       return me_query_number_ranges(filep,>> +       ret = me_query_number_ranges(filep,>>                       (me_query_number_ranges_t *) arg);>> +       break;>>>>    case ME_QUERY_RANGE_BY_MIN_MAX:>> -       return me_query_range_by_min_max(filep,>> +       ret = me_query_range_by_min_max(filep,>>                         (me_query_range_by_min_max_t *)>>                         arg);>> +       break;>>>>    case ME_QUERY_RANGE_INFO:>> -       return me_query_range_info(filep,>> +       ret = me_query_range_info(filep,>>                      (me_query_range_info_t *) arg);>> +       break;>>>>    case ME_QUERY_SUBDEVICE_BY_TYPE:>> -       return me_query_subdevice_by_type(filep,>> +       ret = me_query_subdevice_by_type(filep,>>                         (me_query_subdevice_by_type_t>>                          *) arg);>> +       break;>>>>    case ME_QUERY_SUBDEVICE_TYPE:>> -       return me_query_subdevice_type(filep,>> +       ret = me_query_subdevice_type(filep,>>                        (me_query_subdevice_type_t *)>>                        arg);>> +       break;>>>>    case ME_QUERY_SUBDEVICE_CAPS:>> -       return me_query_subdevice_caps(filep,>> +       ret = me_query_subdevice_caps(filep,>>                        (me_query_subdevice_caps_t *)>>                        arg);>> +       break;>>>>    case ME_QUERY_SUBDEVICE_CAPS_ARGS:>> -       return me_query_subdevice_caps_args(filep,>> +       ret = me_query_subdevice_caps_args(filep,>>                          (me_query_subdevice_caps_args_t>>                           *) arg);>> +       break;>>>>    case ME_QUERY_TIMER:>> -       return me_query_timer(filep, (me_query_timer_t *) arg);>> +       ret = me_query_timer(filep, (me_query_timer_t *) arg);>> +       break;>>>>    case ME_QUERY_VERSION_MAIN_DRIVER:>> -       return me_query_version_main_driver(filep,>> +       ret = me_query_version_main_driver(filep,>>                          (me_query_version_main_driver_t>>                           *) arg);>> +       break;>>>>    case ME_QUERY_VERSION_DEVICE_DRIVER:>> -       return me_query_version_device_driver(filep,>> +       ret = me_query_version_device_driver(filep,>>                           (me_query_version_device_driver_t>>                            *) arg);>> +       break;>>>>    case ME_CONFIG_LOAD:>> -       return me_config_load(filep, (me_config_load_t *) arg);>> +       ret = me_config_load(filep, (me_config_load_t *) arg);>> +       break;>> +   }>> +   if(!ret) {>> +     PERROR("Invalid ioctl number.\n");>> +     ret = -ENOTTY;>>    }>> Actually, you've changed the control flow a bit, and probably broken the> function too.  If it's truly an invalid ioctl number, you'll just drop out> of the switch - there's no default branch.  But ret will be a random value> in that case.>> In every other case, you take a return code of zero (which means success)> and map it onto -ENOTTY.  Probably not the right thing to do.
I have changed this to add a default so if its invalid it will do whatits supposed to
>>> - Â Â PERROR("Invalid ioctl number.\n");>> - Â Â return -ENOTTY;>> + Â Â unlock_kernel();>> + Â Â return ret;>> Â }>>>> Â // Init and exit of module.>> diff --git a/drivers/staging/poch/poch.c b/drivers/staging/poch/poch.c>> index 0d111dd..03cc5b7 100644>> --- a/drivers/staging/poch/poch.c>> +++ b/drivers/staging/poch/poch.c>> @@ -979,9 +979,10 @@ static unsigned int poch_poll(struct file *filp, poll_table *pt)>> Â Â Â return ret;>> Â }>>>> -static int poch_ioctl(struct inode *inode, struct file *filp,>> - Â Â Â Â Â Â Â Â Â unsigned int cmd, unsigned long arg)>> +static long poch_ioctl(struct file *filp, unsigned int cmd,>> + Â Â Â Â Â Â Â Â Â unsigned long arg)>> Â {>> + Â Â lock_kernel();>> Â Â Â struct channel_info *channel = filp->private_data;>> Â Â Â void __iomem *fpga = channel->fpga_iomem;>> Â Â Â void __iomem *bridge = channel->bridge_iomem;>> After declarations, please. Â If you're not sure about accesses to channel,> you need to separate the declarations and the initializations of the> variables.>>> @@ -1026,8 +1027,10 @@ static int poch_ioctl(struct inode *inode, struct file *filp,>> Â Â Â Â Â Â Â }>> Â Â Â Â Â Â Â break;>> Â Â Â case POCH_IOC_GET_COUNTERS:>> - Â Â Â Â Â Â if (!access_ok(VERIFY_WRITE, argp, sizeof(struct poch_counters)))>> + Â Â Â Â Â Â if (!access_ok(VERIFY_WRITE, argp, sizeof(struct poch_counters))) {>> + Â Â Â Â Â Â Â Â Â Â unlock_kernel();>> Â Â Â Â Â Â Â Â Â Â Â return -EFAULT;>> + Â Â Â Â Â Â }>> In general, you want to have a single unlock/return at the end, and use> goto to get there from inside the function. Â Lots of returns from the> middle of a function which takes locks can lead to grief sooner or later.> If there's only one path out, things are harder to break.
I understand that but since this patch was just to move the BKL intoview, i wanted to change as little about the functions as possible,thats why the flow is not changed as much
>>> Â Â Â Â Â Â Â spin_lock_irq(&channel->counters_lock);>> Â Â Â Â Â Â Â counters = channel->counters;>> @@ -1036,23 +1039,31 @@ static int poch_ioctl(struct inode *inode, struct file *filp,>>>> Â Â Â Â Â Â Â ret = copy_to_user(argp, &counters,>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sizeof(struct poch_counters));>> - Â Â Â Â Â Â if (ret)>> + Â Â Â Â Â Â if (ret) {>> + Â Â Â Â Â Â Â Â Â Â unlock_kernel();>> Â Â Â Â Â Â Â Â Â Â Â return ret;>> + Â Â Â Â Â Â }>>>> Â Â Â Â Â Â Â break;>> Â Â Â case POCH_IOC_SYNC_GROUP_FOR_USER:>> Â Â Â case POCH_IOC_SYNC_GROUP_FOR_DEVICE:>> Â Â Â Â Â Â Â vms = find_vma(current->mm, arg);>> - Â Â Â Â Â Â if (!vms)>> + Â Â Â Â Â Â if (!vms) {>> + Â Â Â Â Â Â Â Â Â Â unlock_kernel();>> Â Â Â Â Â Â Â Â Â Â Â /* Address not mapped. */>> Â Â Â Â Â Â Â Â Â Â Â return -EINVAL;>> - Â Â Â Â Â Â if (vms->vm_file != filp)>> + Â Â Â Â Â Â }>> + Â Â Â Â Â Â if (vms->vm_file != filp) {>> + Â Â Â Â Â Â Â Â Â Â unlock_kernel();>> Â Â Â Â Â Â Â Â Â Â Â /* Address mapped from different device/file. */>> Â Â Â Â Â Â Â Â Â Â Â return -EINVAL;>> + Â Â Â Â Â Â }>>>> Â Â Â Â Â Â Â flush_cache_range(vms, arg, arg + channel->group_size);>> Â Â Â Â Â Â Â break;>> Â Â Â }>> +>> + Â Â unlock_kernel();>> Â Â Â return 0;>> Â }>> This driver looks like it has other locking problems, incidentally; it has> a spinlock for its counters, but there's nothing serializing access to the> device registers.>> jon>
I have made some modifications and will resubmit this patch.
--
-Stoyanÿôèº{.nÇ+·®+%Ëÿ±éݶ\x17¥wÿº{.nÇ+·¥{±þG«éÿ{ayº\x1dÊÚë,j\a¢f£¢·hïêÿêçz_è®\x03(éÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?¨èÚ&£ø§~á¶iOæ¬z·vØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?I¥
prev parent reply other threads:[~2009-03-25 0:12 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-03-24 21:12 stoyboyker
2009-03-24 22:01 ` Greg KH
2009-03-24 23:19 ` Jonathan Corbet
2009-03-24 23:40 ` Jonathan Corbet
2009-03-25 0:12 ` Stoyan Gaydarov [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6d291e080903241712y6d688bbfp753aae641617a5a7@mail.gmail.com \
--to=stoyboyker@gmail.com \
--cc=corbet@lwn.net \
--cc=gregkh@suse.de \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®