Merge branch 'bkl/ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 24 May 2010 15:01:10 +0000 (08:01 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 24 May 2010 15:01:10 +0000 (08:01 -0700)
* 'bkl/ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing:
  uml: Pushdown the bkl from harddog_kern ioctl
  sunrpc: Pushdown the bkl from sunrpc cache ioctl
  sunrpc: Pushdown the bkl from ioctl
  autofs4: Pushdown the bkl from ioctl
  uml: Convert to unlocked_ioctls to remove implicit BKL
  ncpfs: BKL ioctl pushdown
  coda: Clean-up whitespace problems in pioctl.c
  coda: BKL ioctl pushdown
  drivers: Push down BKL into various drivers
  isdn: Push down BKL into ioctl functions
  scsi: Push down BKL into ioctl functions
  dvb: Push down BKL into ioctl functions
  smbfs: Push down BKL into ioctl function
  coda/psdev: Remove BKL from ioctl function
  um/mmapper: Remove BKL usage
  sn_hwperf: Kill BKL usage
  hfsplus: Push down BKL into ioctl function

1  2 
arch/ia64/sn/kernel/sn2/sn_hwperf.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/mtd/mtdchar.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-sas.c
drivers/scsi/3w-xxxx.c
drivers/scsi/gdth.c
drivers/usb/mon/mon_bin.c
net/sunrpc/cache.c

@@@ -30,7 -30,6 +30,6 @@@
  #include <linux/miscdevice.h>
  #include <linux/utsname.h>
  #include <linux/cpumask.h>
- #include <linux/smp_lock.h>
  #include <linux/nodemask.h>
  #include <linux/smp.h>
  #include <linux/mutex.h>
@@@ -629,9 -628,9 +628,9 @@@ static int sn_hwperf_op_cpu(struct sn_h
                else {
                        /* migrate the task before calling SAL */ 
                        save_allowed = current->cpus_allowed;
 -                      set_cpus_allowed(current, cpumask_of_cpu(cpu));
 +                      set_cpus_allowed_ptr(current, cpumask_of(cpu));
                        sn_hwperf_call_sal(op_info);
 -                      set_cpus_allowed(current, save_allowed);
 +                      set_cpus_allowed_ptr(current, &save_allowed);
                }
        }
        r = op_info->ret;
@@@ -682,8 -681,7 +681,7 @@@ static int sn_hwperf_map_err(int hwperf
  /*
   * ioctl for "sn_hwperf" misc device
   */
- static int
- sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, unsigned long arg)
+ static long sn_hwperf_ioctl(struct file *fp, u32 op, unsigned long arg)
  {
        struct sn_hwperf_ioctl_args a;
        struct cpuinfo_ia64 *cdata;
        int i;
        int j;
  
-       unlock_kernel();
        /* only user requests are allowed here */
        if ((op & SN_HWPERF_OP_MASK) < 10) {
                r = -EINVAL;
  error:
        vfree(p);
  
-       lock_kernel();
        return r;
  }
  
  static const struct file_operations sn_hwperf_fops = {
-       .ioctl = sn_hwperf_ioctl,
+       .unlocked_ioctl = sn_hwperf_ioctl,
  };
  
  static struct miscdevice sn_hwperf_dev = {
@@@ -36,6 -36,7 +36,7 @@@
  #include <linux/list.h>
  #include <linux/freezer.h>
  #include <linux/jiffies.h>
+ #include <linux/smp_lock.h>
  #include <linux/kthread.h>
  #include <asm/processor.h>
  
@@@ -95,10 -96,6 +96,10 @@@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wa
   * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
   */
  
 +#define DVB_FE_NO_EXIT        0
 +#define DVB_FE_NORMAL_EXIT    1
 +#define DVB_FE_DEVICE_REMOVED 2
 +
  static DEFINE_MUTEX(frontend_mutex);
  
  struct dvb_frontend_private {
@@@ -501,7 -498,7 +502,7 @@@ static int dvb_frontend_is_exiting(stru
  {
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
  
 -      if (fepriv->exit)
 +      if (fepriv->exit != DVB_FE_NO_EXIT)
                return 1;
  
        if (fepriv->dvbdev->writers == 1)
@@@ -563,7 -560,7 +564,7 @@@ restart
  
                if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
                        /* got signal or quitting */
 -                      fepriv->exit = 1;
 +                      fepriv->exit = DVB_FE_NORMAL_EXIT;
                        break;
                }
  
        }
  
        fepriv->thread = NULL;
 -      fepriv->exit = 0;
 +      if (kthread_should_stop())
 +              fepriv->exit = DVB_FE_DEVICE_REMOVED;
 +      else
 +              fepriv->exit = DVB_FE_NO_EXIT;
        mb();
  
        dvb_frontend_wakeup(fe);
@@@ -693,7 -687,7 +694,7 @@@ static void dvb_frontend_stop(struct dv
  
        dprintk ("%s\n", __func__);
  
 -      fepriv->exit = 1;
 +      fepriv->exit = DVB_FE_NORMAL_EXIT;
        mb();
  
        if (!fepriv->thread)
@@@ -762,7 -756,7 +763,7 @@@ static int dvb_frontend_start(struct dv
        dprintk ("%s\n", __func__);
  
        if (fepriv->thread) {
 -              if (!fepriv->exit)
 +              if (fepriv->exit == DVB_FE_NO_EXIT)
                        return 0;
                else
                        dvb_frontend_stop (fe);
                return -EINTR;
  
        fepriv->state = FESTATE_IDLE;
 -      fepriv->exit = 0;
 +      fepriv->exit = DVB_FE_NO_EXIT;
        fepriv->thread = NULL;
        mb();
  
@@@ -1195,14 -1189,14 +1196,14 @@@ static void dtv_property_cache_submit(s
        }
  }
  
- static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
+ static int dvb_frontend_ioctl_legacy(struct file *file,
                        unsigned int cmd, void *parg);
- static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
+ static int dvb_frontend_ioctl_properties(struct file *file,
                        unsigned int cmd, void *parg);
  
  static int dtv_property_process_get(struct dvb_frontend *fe,
                                    struct dtv_property *tvp,
-                                   struct inode *inode, struct file *file)
+                                   struct file *file)
  {
        int r = 0;
  
  
  static int dtv_property_process_set(struct dvb_frontend *fe,
                                    struct dtv_property *tvp,
-                                   struct inode *inode,
                                    struct file *file)
  {
        int r = 0;
                dprintk("%s() Finalised property cache\n", __func__);
                dtv_property_cache_submit(fe);
  
-               r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND,
+               r |= dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND,
                        &fepriv->parameters);
                break;
        case DTV_FREQUENCY:
                break;
        case DTV_VOLTAGE:
                fe->dtv_property_cache.voltage = tvp->u.data;
-               r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_VOLTAGE,
+               r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE,
                        (void *)fe->dtv_property_cache.voltage);
                break;
        case DTV_TONE:
                fe->dtv_property_cache.sectone = tvp->u.data;
-               r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_TONE,
+               r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE,
                        (void *)fe->dtv_property_cache.sectone);
                break;
        case DTV_CODE_RATE_HP:
        return r;
  }
  
- static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
+ static int dvb_frontend_ioctl(struct file *file,
                        unsigned int cmd, void *parg)
  {
        struct dvb_device *dvbdev = file->private_data;
  
        dprintk("%s (%d)\n", __func__, _IOC_NR(cmd));
  
 -      if (fepriv->exit)
 +      if (fepriv->exit != DVB_FE_NO_EXIT)
                return -ENODEV;
  
        if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
                return -ERESTARTSYS;
  
        if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
-               err = dvb_frontend_ioctl_properties(inode, file, cmd, parg);
+               err = dvb_frontend_ioctl_properties(file, cmd, parg);
        else {
                fe->dtv_property_cache.state = DTV_UNDEFINED;
-               err = dvb_frontend_ioctl_legacy(inode, file, cmd, parg);
+               err = dvb_frontend_ioctl_legacy(file, cmd, parg);
        }
  
        up(&fepriv->sem);
        return err;
  }
  
- static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
+ static int dvb_frontend_ioctl_properties(struct file *file,
                        unsigned int cmd, void *parg)
  {
        struct dvb_device *dvbdev = file->private_data;
                }
  
                for (i = 0; i < tvps->num; i++) {
-                       (tvp + i)->result = dtv_property_process_set(fe, tvp + i, inode, file);
+                       (tvp + i)->result = dtv_property_process_set(fe, tvp + i, file);
                        err |= (tvp + i)->result;
                }
  
                }
  
                for (i = 0; i < tvps->num; i++) {
-                       (tvp + i)->result = dtv_property_process_get(fe, tvp + i, inode, file);
+                       (tvp + i)->result = dtv_property_process_get(fe, tvp + i, file);
                        err |= (tvp + i)->result;
                }
  
@@@ -1604,7 -1597,7 +1604,7 @@@ out
        return err;
  }
  
- static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
+ static int dvb_frontend_ioctl_legacy(struct file *file,
                        unsigned int cmd, void *parg)
  {
        struct dvb_device *dvbdev = file->private_data;
@@@ -1923,8 -1916,6 +1923,8 @@@ static int dvb_frontend_open(struct ino
        int ret;
  
        dprintk ("%s\n", __func__);
 +      if (fepriv->exit == DVB_FE_DEVICE_REMOVED)
 +              return -ENODEV;
  
        if (adapter->mfe_shared) {
                mutex_lock (&adapter->mfe_lock);
@@@ -2017,7 -2008,7 +2017,7 @@@ static int dvb_frontend_release(struct 
        ret = dvb_generic_release (inode, file);
  
        if (dvbdev->users == -1) {
 -              if (fepriv->exit == 1) {
 +              if (fepriv->exit != DVB_FE_NO_EXIT) {
                        fops_put(file->f_op);
                        file->f_op = NULL;
                        wake_up(&dvbdev->wait_queue);
  
  static const struct file_operations dvb_frontend_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = dvb_generic_ioctl,
+       .unlocked_ioctl = dvb_generic_ioctl,
        .poll           = dvb_frontend_poll,
        .open           = dvb_frontend_open,
        .release        = dvb_frontend_release
@@@ -59,6 -59,7 +59,7 @@@
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/dvb/net.h>
+ #include <linux/smp_lock.h>
  #include <linux/uio.h>
  #include <asm/uaccess.h>
  #include <linux/crc32.h>
@@@ -1109,14 -1110,14 +1110,14 @@@ static int dvb_net_feed_stop(struct net
  }
  
  
 -static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc)
 +static int dvb_set_mc_filter(struct net_device *dev, unsigned char *addr)
  {
        struct dvb_net_priv *priv = netdev_priv(dev);
  
        if (priv->multi_num == DVB_NET_MULTICAST_MAX)
                return -ENOMEM;
  
 -      memcpy(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6);
 +      memcpy(priv->multi_macs[priv->multi_num], addr, ETH_ALEN);
  
        priv->multi_num++;
        return 0;
@@@ -1140,7 -1141,8 +1141,7 @@@ static void wq_set_multicast_list (stru
                dprintk("%s: allmulti mode\n", dev->name);
                priv->rx_mode = RX_MODE_ALL_MULTI;
        } else if (!netdev_mc_empty(dev)) {
 -              int mci;
 -              struct dev_mc_list *mc;
 +              struct netdev_hw_addr *ha;
  
                dprintk("%s: set_mc_list, %d entries\n",
                        dev->name, netdev_mc_count(dev));
                priv->rx_mode = RX_MODE_MULTI;
                priv->multi_num = 0;
  
 -              for (mci = 0, mc=dev->mc_list;
 -                   mci < netdev_mc_count(dev);
 -                   mc = mc->next, mci++) {
 -                      dvb_set_mc_filter(dev, mc);
 -              }
 +              netdev_for_each_mc_addr(ha, dev)
 +                      dvb_set_mc_filter(dev, ha->addr);
        }
  
        netif_addr_unlock_bh(dev);
@@@ -1329,7 -1334,7 +1330,7 @@@ static int dvb_net_remove_if(struct dvb
        return 0;
  }
  
- static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
+ static int dvb_net_do_ioctl(struct file *file,
                  unsigned int cmd, void *parg)
  {
        struct dvb_device *dvbdev = file->private_data;
        return 0;
  }
  
- static int dvb_net_ioctl(struct inode *inode, struct file *file,
+ static long dvb_net_ioctl(struct file *file,
              unsigned int cmd, unsigned long arg)
  {
-       return dvb_usercopy(inode, file, cmd, arg, dvb_net_do_ioctl);
+       int ret;
+       lock_kernel();
+       ret = dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
+       unlock_kernel();
+       return ret;
  }
  
  static int dvb_net_close(struct inode *inode, struct file *file)
  
  static const struct file_operations dvb_net_fops = {
        .owner = THIS_MODULE,
-       .ioctl = dvb_net_ioctl,
+       .unlocked_ioctl = dvb_net_ioctl,
        .open = dvb_generic_open,
        .release = dvb_net_close,
  };
diff --combined drivers/mtd/mtdchar.c
  #include <linux/smp_lock.h>
  #include <linux/backing-dev.h>
  #include <linux/compat.h>
 +#include <linux/mount.h>
  
  #include <linux/mtd/mtd.h>
  #include <linux/mtd/compatmac.h>
  
  #include <asm/uaccess.h>
  
 +#define MTD_INODE_FS_MAGIC 0x11307854
 +static struct vfsmount *mtd_inode_mnt __read_mostly;
  
  /*
   * Data structure to hold the pointer to the mtd device as well
@@@ -31,7 -28,6 +31,7 @@@
   */
  struct mtd_file_info {
        struct mtd_info *mtd;
 +      struct inode *ino;
        enum mtd_file_modes mode;
  };
  
@@@ -68,10 -64,12 +68,10 @@@ static int mtd_open(struct inode *inode
        int ret = 0;
        struct mtd_info *mtd;
        struct mtd_file_info *mfi;
 +      struct inode *mtd_ino;
  
        DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
  
 -      if (devnum >= MAX_MTD_DEVICES)
 -              return -ENODEV;
 -
        /* You can't open the RO devices RW */
        if ((file->f_mode & FMODE_WRITE) && (minor & 1))
                return -EACCES;
                goto out;
        }
  
 -      if (mtd->backing_dev_info)
 -              file->f_mapping->backing_dev_info = mtd->backing_dev_info;
 +      mtd_ino = iget_locked(mtd_inode_mnt->mnt_sb, devnum);
 +      if (!mtd_ino) {
 +              put_mtd_device(mtd);
 +              ret = -ENOMEM;
 +              goto out;
 +      }
 +      if (mtd_ino->i_state & I_NEW) {
 +              mtd_ino->i_private = mtd;
 +              mtd_ino->i_mode = S_IFCHR;
 +              mtd_ino->i_data.backing_dev_info = mtd->backing_dev_info;
 +              unlock_new_inode(mtd_ino);
 +      }
 +      file->f_mapping = mtd_ino->i_mapping;
  
        /* You can't open it RW if it's not a writeable device */
        if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
 +              iput(mtd_ino);
                put_mtd_device(mtd);
                ret = -EACCES;
                goto out;
  
        mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
        if (!mfi) {
 +              iput(mtd_ino);
                put_mtd_device(mtd);
                ret = -ENOMEM;
                goto out;
        }
 +      mfi->ino = mtd_ino;
        mfi->mtd = mtd;
        file->private_data = mfi;
  
@@@ -141,8 -125,6 +141,8 @@@ static int mtd_close(struct inode *inod
        if ((file->f_mode & FMODE_WRITE) && mtd->sync)
                mtd->sync(mtd);
  
 +      iput(mfi->ino);
 +
        put_mtd_device(mtd);
        file->private_data = NULL;
        kfree(mfi);
@@@ -391,7 -373,7 +391,7 @@@ static int mtd_do_writeoob(struct file 
        if (!mtd->write_oob)
                ret = -EOPNOTSUPP;
        else
 -              ret = access_ok(VERIFY_READ, ptr, length) ? 0 : EFAULT;
 +              ret = access_ok(VERIFY_READ, ptr, length) ? 0 : -EFAULT;
  
        if (ret)
                return ret;
@@@ -468,8 -450,7 +468,7 @@@ static int mtd_do_readoob(struct mtd_in
        return ret;
  }
  
- static int mtd_ioctl(struct inode *inode, struct file *file,
-                    u_int cmd, u_long arg)
+ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
  {
        struct mtd_file_info *mfi = file->private_data;
        struct mtd_info *mtd = mfi->mtd;
        {
                uint32_t ur_idx;
                struct mtd_erase_region_info *kr;
 -              struct region_info_user *ur = (struct region_info_user *) argp;
 +              struct region_info_user __user *ur = argp;
  
                if (get_user(ur_idx, &(ur->regionindex)))
                        return -EFAULT;
        return ret;
  } /* memory_ioctl */
  
+ static long mtd_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
+ {
+       int ret;
+       lock_kernel();
+       ret = mtd_ioctl(file, cmd, arg);
+       unlock_kernel();
+       return ret;
+ }
  #ifdef CONFIG_COMPAT
  
  struct mtd_oob_buf32 {
  static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
        unsigned long arg)
  {
-       struct inode *inode = file->f_path.dentry->d_inode;
        struct mtd_file_info *mfi = file->private_data;
        struct mtd_info *mtd = mfi->mtd;
        void __user *argp = compat_ptr(arg);
                break;
        }
        default:
-               ret = mtd_ioctl(inode, file, cmd, (unsigned long)argp);
+               ret = mtd_ioctl(file, cmd, (unsigned long)argp);
        }
  
        unlock_kernel();
@@@ -960,7 -951,7 +969,7 @@@ static const struct file_operations mtd
        .llseek         = mtd_lseek,
        .read           = mtd_read,
        .write          = mtd_write,
-       .ioctl          = mtd_ioctl,
+       .unlocked_ioctl = mtd_unlocked_ioctl,
  #ifdef CONFIG_COMPAT
        .compat_ioctl   = mtd_compat_ioctl,
  #endif
  #endif
  };
  
 +static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags,
 +                               const char *dev_name, void *data,
 +                               struct vfsmount *mnt)
 +{
 +        return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC,
 +                             mnt);
 +}
 +
 +static struct file_system_type mtd_inodefs_type = {
 +       .name = "mtd_inodefs",
 +       .get_sb = mtd_inodefs_get_sb,
 +       .kill_sb = kill_anon_super,
 +};
 +
 +static void mtdchar_notify_add(struct mtd_info *mtd)
 +{
 +}
 +
 +static void mtdchar_notify_remove(struct mtd_info *mtd)
 +{
 +      struct inode *mtd_ino = ilookup(mtd_inode_mnt->mnt_sb, mtd->index);
 +
 +      if (mtd_ino) {
 +              /* Destroy the inode if it exists */
 +              mtd_ino->i_nlink = 0;
 +              iput(mtd_ino);
 +      }
 +}
 +
 +static struct mtd_notifier mtdchar_notifier = {
 +      .add = mtdchar_notify_add,
 +      .remove = mtdchar_notify_remove,
 +};
 +
  static int __init init_mtdchar(void)
  {
 -      int status;
 +      int ret;
  
 -      status = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops);
 -      if (status < 0) {
 -              printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
 -                     MTD_CHAR_MAJOR);
 +      ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS,
 +                                 "mtd", &mtd_fops);
 +      if (ret < 0) {
 +              pr_notice("Can't allocate major number %d for "
 +                              "Memory Technology Devices.\n", MTD_CHAR_MAJOR);
 +              return ret;
        }
  
 -      return status;
 +      ret = register_filesystem(&mtd_inodefs_type);
 +      if (ret) {
 +              pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret);
 +              goto err_unregister_chdev;
 +      }
 +
 +      mtd_inode_mnt = kern_mount(&mtd_inodefs_type);
 +      if (IS_ERR(mtd_inode_mnt)) {
 +              ret = PTR_ERR(mtd_inode_mnt);
 +              pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret);
 +              goto err_unregister_filesystem;
 +      }
 +      register_mtd_user(&mtdchar_notifier);
 +
 +      return ret;
 +
 +err_unregister_filesystem:
 +      unregister_filesystem(&mtd_inodefs_type);
 +err_unregister_chdev:
 +      __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
 +      return ret;
  }
  
  static void __exit cleanup_mtdchar(void)
  {
 -      unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
 +      unregister_mtd_user(&mtdchar_notifier);
 +      mntput(mtd_inode_mnt);
 +      unregister_filesystem(&mtd_inodefs_type);
 +      __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
  }
  
  module_init(init_mtdchar);
@@@ -301,9 -301,7 +301,9 @@@ static int pccard_get_status(struct pcm
            (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
                u_char reg;
                if (c->CardValues & PRESENT_PIN_REPLACE) {
 +                      mutex_lock(&s->ops_mutex);
                        pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
 +                      mutex_unlock(&s->ops_mutex);
                        status->CardState |=
                                (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
                        status->CardState |=
                        status->CardState |= CS_EVENT_READY_CHANGE;
                }
                if (c->CardValues & PRESENT_EXT_STATUS) {
 +                      mutex_lock(&s->ops_mutex);
                        pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
 +                      mutex_unlock(&s->ops_mutex);
                        status->CardState |=
                                (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
                }
@@@ -355,7 -351,7 +355,7 @@@ static int pccard_get_configuration_inf
                if (s->state & SOCKET_CARDBUS_CONFIG) {
                        config->Attributes = CONF_VALID_CLIENT;
                        config->IntType = INT_CARDBUS;
 -                      config->AssignedIRQ = s->irq.AssignedIRQ;
 +                      config->AssignedIRQ = s->pcmcia_irq;
                        if (config->AssignedIRQ)
                                config->Attributes |= CONF_ENABLE_IRQ;
                        if (s->io[0].res) {
        config->ExtStatus = c->ExtStatus;
        config->Present = config->CardValues = c->CardValues;
        config->IRQAttributes = c->irq.Attributes;
 -      config->AssignedIRQ = s->irq.AssignedIRQ;
 +      config->AssignedIRQ = s->pcmcia_irq;
        config->BasePort1 = c->io.BasePort1;
        config->NumPorts1 = c->io.NumPorts1;
        config->Attributes1 = c->io.Attributes1;
@@@ -575,6 -571,7 +575,6 @@@ static struct pci_bus *pcmcia_lookup_bu
  
  static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int first)
  {
 -      dev_node_t *node;
        struct pcmcia_device *p_dev;
        struct pcmcia_driver *p_drv;
        int ret = 0;
                goto err_put;
        }
  
 -      if (first)
 -              node = p_dev->dev_node;
 -      else
 -              for (node = p_dev->dev_node; node; node = node->next)
 -                      if (node == bind_info->next)
 -                              break;
 -      if (!node) {
 +      if (!first) {
                ret = -ENODEV;
                goto err_put;
        }
  
 -      strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
 -      bind_info->major = node->major;
 -      bind_info->minor = node->minor;
 -      bind_info->next = node->next;
 +      strlcpy(bind_info->name, dev_name(&p_dev->dev), DEV_NAME_LEN);
 +      bind_info->next = NULL;
  
   err_put:
        pcmcia_put_dev(p_dev);
@@@ -813,8 -818,7 +813,7 @@@ static u_int ds_poll(struct file *file
  
  /*====================================================================*/
  
- static int ds_ioctl(struct inode *inode, struct file *file,
-                   u_int cmd, u_long arg)
+ static int ds_ioctl(struct file *file, u_int cmd, u_long arg)
  {
      struct pcmcia_socket *s;
      void __user *uarg = (char __user *)arg;
@@@ -1021,13 -1025,25 +1020,25 @@@ free_out
      return err;
  } /* ds_ioctl */
  
+ static long ds_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+       int ret;
+       lock_kernel();
+       ret = ds_ioctl(file, cmd, arg);
+       unlock_kernel();
+       return ret;
+ }
  /*====================================================================*/
  
  static const struct file_operations ds_fops = {
        .owner          = THIS_MODULE,
        .open           = ds_open,
        .release        = ds_release,
-       .ioctl          = ds_ioctl,
+       .unlocked_ioctl = ds_unlocked_ioctl,
        .read           = ds_read,
        .write          = ds_write,
        .poll           = ds_poll,
diff --combined drivers/scsi/3w-9xxx.c
@@@ -1,11 -1,10 +1,11 @@@
  /*
     3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux.
  
 -   Written By: Adam Radford <linuxraid@amcc.com>
 -   Modifications By: Tom Couch <linuxraid@amcc.com>
 +   Written By: Adam Radford <linuxraid@lsi.com>
 +   Modifications By: Tom Couch <linuxraid@lsi.com>
  
     Copyright (C) 2004-2009 Applied Micro Circuits Corporation.
 +   Copyright (C) 2010 LSI Corporation.
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
     Bugs/Comments/Suggestions should be mailed to:
 -   linuxraid@amcc.com
 +   linuxraid@lsi.com
  
     For more information, goto:
 -   http://www.amcc.com
 +   http://www.lsi.com
  
     Note: This version of the driver does not contain a bundled firmware
           image.
@@@ -78,7 -77,6 +78,7 @@@
                   Use pci_resource_len() for ioremap().
     2.26.02.012 - Add power management support.
     2.26.02.013 - Fix bug in twa_load_sgl().
 +   2.26.02.014 - Force 60 second timeout default.
  */
  
  #include <linux/module.h>
  #include "3w-9xxx.h"
  
  /* Globals */
 -#define TW_DRIVER_VERSION "2.26.02.013"
 +#define TW_DRIVER_VERSION "2.26.02.014"
  static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
  static unsigned int twa_device_extension_count;
  static int twa_major = -1;
  extern struct timezone sys_tz;
  
  /* Module parameters */
 -MODULE_AUTHOR ("AMCC");
 +MODULE_AUTHOR ("LSI");
  MODULE_DESCRIPTION ("3ware 9000 Storage Controller Linux Driver");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(TW_DRIVER_VERSION);
@@@ -125,7 -123,7 +125,7 @@@ static void twa_aen_queue_event(TW_Devi
  static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id);
  static char *twa_aen_severity_lookup(unsigned char severity_code);
  static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id);
- static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+ static long twa_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
  static int twa_chrdev_open(struct inode *inode, struct file *file);
  static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host);
  static void twa_free_request_id(TW_Device_Extension *tw_dev,int request_id);
@@@ -220,7 -218,7 +220,7 @@@ static struct device_attribute *twa_hos
  /* File operations struct for character device */
  static const struct file_operations twa_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = twa_chrdev_ioctl,
+       .unlocked_ioctl = twa_chrdev_ioctl,
        .open           = twa_chrdev_open,
        .release        = NULL
  };
@@@ -637,8 -635,9 +637,9 @@@ out
  } /* End twa_check_srl() */
  
  /* This function handles ioctl for the character device */
- static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ static long twa_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
+       struct inode *inode = file->f_path.dentry->d_inode;
        long timeout;
        unsigned long *cpu_addr, data_buffer_length_adjusted = 0, flags = 0;
        dma_addr_t dma_handle;
        int retval = TW_IOCTL_ERROR_OS_EFAULT;
        void __user *argp = (void __user *)arg;
  
+       lock_kernel();
        /* Only let one of these through at a time */
        if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
                retval = TW_IOCTL_ERROR_OS_EINTR;
@@@ -876,6 -877,7 +879,7 @@@ out3
  out2:
        mutex_unlock(&tw_dev->ioctl_lock);
  out:
+       unlock_kernel();
        return retval;
  } /* End twa_chrdev_ioctl() */
  
@@@ -1992,15 -1994,6 +1996,15 @@@ static void twa_unmap_scsi_data(TW_Devi
                scsi_dma_unmap(cmd);
  } /* End twa_unmap_scsi_data() */
  
 +/* This function gets called when a disk is coming on-line */
 +static int twa_slave_configure(struct scsi_device *sdev)
 +{
 +      /* Force 60 second timeout */
 +      blk_queue_rq_timeout(sdev->request_queue, 60 * HZ);
 +
 +      return 0;
 +} /* End twa_slave_configure() */
 +
  /* scsi_host_template initializer */
  static struct scsi_host_template driver_template = {
        .module                 = THIS_MODULE,
        .bios_param             = twa_scsi_biosparam,
        .change_queue_depth     = twa_change_queue_depth,
        .can_queue              = TW_Q_LENGTH-2,
 +      .slave_configure        = twa_slave_configure,
        .this_id                = -1,
        .sg_tablesize           = TW_APACHE_MAX_SGL_LENGTH,
        .max_sectors            = TW_MAX_SECTORS,
diff --combined drivers/scsi/3w-sas.c
@@@ -98,7 -98,7 +98,7 @@@ static int twl_reset_device_extension(T
  /* Functions */
  
  /* This function returns AENs through sysfs */
 -static ssize_t twl_sysfs_aen_read(struct kobject *kobj,
 +static ssize_t twl_sysfs_aen_read(struct file *filp, struct kobject *kobj,
                                  struct bin_attribute *bin_attr,
                                  char *outbuf, loff_t offset, size_t count)
  {
@@@ -129,7 -129,7 +129,7 @@@ static struct bin_attribute twl_sysfs_a
  };
  
  /* This function returns driver compatibility info through sysfs */
 -static ssize_t twl_sysfs_compat_info(struct kobject *kobj,
 +static ssize_t twl_sysfs_compat_info(struct file *filp, struct kobject *kobj,
                                     struct bin_attribute *bin_attr,
                                     char *outbuf, loff_t offset, size_t count)
  {
@@@ -750,19 -750,22 +750,22 @@@ static void twl_load_sgl(TW_Device_Exte
  
  /* This function handles ioctl for the character device
     This interface is used by smartmontools open source software */
- static int twl_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ static long twl_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
        long timeout;
        unsigned long *cpu_addr, data_buffer_length_adjusted = 0, flags = 0;
        dma_addr_t dma_handle;
        int request_id = 0;
        TW_Ioctl_Driver_Command driver_command;
+       struct inode *inode = file->f_dentry->d_inode;
        TW_Ioctl_Buf_Apache *tw_ioctl;
        TW_Command_Full *full_command_packet;
        TW_Device_Extension *tw_dev = twl_device_extension_list[iminor(inode)];
        int retval = -EFAULT;
        void __user *argp = (void __user *)arg;
  
+       lock_kernel();
        /* Only let one of these through at a time */
        if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
                retval = -EINTR;
@@@ -858,6 -861,7 +861,7 @@@ out3
  out2:
        mutex_unlock(&tw_dev->ioctl_lock);
  out:
+       unlock_kernel();
        return retval;
  } /* End twl_chrdev_ioctl() */
  
@@@ -884,7 -888,7 +888,7 @@@ out
  /* File operations struct for character device */
  static const struct file_operations twl_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = twl_chrdev_ioctl,
+       .unlocked_ioctl = twl_chrdev_ioctl,
        .open           = twl_chrdev_open,
        .release        = NULL
  };
diff --combined drivers/scsi/3w-xxxx.c
@@@ -1,12 -1,12 +1,12 @@@
  /* 
     3w-xxxx.c -- 3ware Storage Controller device driver for Linux.
  
 -   Written By: Adam Radford <linuxraid@amcc.com>
 +   Written By: Adam Radford <linuxraid@lsi.com>
     Modifications By: Joel Jacobson <linux@3ware.com>
                     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
                       Brad Strand <linux@3ware.com>
  
 -   Copyright (C) 1999-2009 3ware Inc.
 +   Copyright (C) 1999-2010 3ware Inc.
  
     Kernel compatibility By:   Andre Hedrick <andre@suse.com>
     Non-Copyright (C) 2000     Andre Hedrick <andre@suse.com>
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  
     Bugs/Comments/Suggestions should be mailed to:                            
 -   linuxraid@amcc.com
 +   linuxraid@lsi.com
  
     For more information, goto:
 -   http://www.amcc.com
 +   http://www.lsi.com
  
     History
     -------
     1.26.02.002 - Free irq handler in __tw_shutdown().
                   Turn on RCD bit for caching mode page.
                   Serialize reset code.
 +   1.26.02.003 - Force 60 second timeout default.
  */
  
  #include <linux/module.h>
  #include "3w-xxxx.h"
  
  /* Globals */
 -#define TW_DRIVER_VERSION "1.26.02.002"
 +#define TW_DRIVER_VERSION "1.26.02.003"
  static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
  static int tw_device_extension_count = 0;
  static int twe_major = -1;
  
  /* Module parameters */
 -MODULE_AUTHOR("AMCC");
 +MODULE_AUTHOR("LSI");
  MODULE_DESCRIPTION("3ware Storage Controller Linux Driver");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(TW_DRIVER_VERSION);
@@@ -881,7 -880,7 +881,7 @@@ static int tw_allocate_memory(TW_Device
  } /* End tw_allocate_memory() */
  
  /* This function handles ioctl for the character device */
- static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ static long tw_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
        int request_id;
        dma_addr_t dma_handle;
        unsigned long flags;
        unsigned int data_buffer_length = 0;
        unsigned long data_buffer_length_adjusted = 0;
+       struct inode *inode = file->f_dentry->d_inode;
        unsigned long *cpu_addr;
        long timeout;
        TW_New_Ioctl *tw_ioctl;
  
        dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
  
+       lock_kernel();
        /* Only let one of these through at a time */
-       if (mutex_lock_interruptible(&tw_dev->ioctl_lock))
+       if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
+               unlock_kernel();
                return -EINTR;
+       }
  
        /* First copy down the buffer length */
        if (copy_from_user(&data_buffer_length, argp, sizeof(unsigned int)))
@@@ -1030,6 -1033,7 +1034,7 @@@ out2
        dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
  out:
        mutex_unlock(&tw_dev->ioctl_lock);
+       unlock_kernel();
        return retval;
  } /* End tw_chrdev_ioctl() */
  
@@@ -1052,7 -1056,7 +1057,7 @@@ static int tw_chrdev_open(struct inode 
  /* File operations struct for character device */
  static const struct file_operations tw_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = tw_chrdev_ioctl,
+       .unlocked_ioctl = tw_chrdev_ioctl,
        .open           = tw_chrdev_open,
        .release        = NULL
  };
@@@ -2246,15 -2250,6 +2251,15 @@@ static void tw_shutdown(struct pci_dev 
        __tw_shutdown(tw_dev);
  } /* End tw_shutdown() */
  
 +/* This function gets called when a disk is coming online */
 +static int tw_slave_configure(struct scsi_device *sdev)
 +{
 +      /* Force 60 second timeout */
 +      blk_queue_rq_timeout(sdev->request_queue, 60 * HZ);
 +
 +      return 0;
 +} /* End tw_slave_configure() */
 +
  static struct scsi_host_template driver_template = {
        .module                 = THIS_MODULE,
        .name                   = "3ware Storage Controller",
        .bios_param             = tw_scsi_biosparam,
        .change_queue_depth     = tw_change_queue_depth,
        .can_queue              = TW_Q_LENGTH-2,
 +      .slave_configure        = tw_slave_configure,
        .this_id                = -1,
        .sg_tablesize           = TW_MAX_SGL_LENGTH,
        .max_sectors            = TW_MAX_SECTORS,
diff --combined drivers/scsi/gdth.c
@@@ -180,8 -180,8 +180,8 @@@ static const char *gdth_ctr_name(gdth_h
  
  static int gdth_open(struct inode *inode, struct file *filep);
  static int gdth_close(struct inode *inode, struct file *filep);
- static int gdth_ioctl(struct inode *inode, struct file *filep,
-                       unsigned int cmd, unsigned long arg);
+ static long gdth_unlocked_ioctl(struct file *filep, unsigned int cmd,
+                               unsigned long arg);
  
  static void gdth_flush(gdth_ha_str *ha);
  static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
@@@ -369,7 -369,7 +369,7 @@@ MODULE_LICENSE("GPL")
  
  /* ioctl interface */
  static const struct file_operations gdth_fops = {
-     .ioctl   = gdth_ioctl,
+     .unlocked_ioctl   = gdth_unlocked_ioctl,
      .open    = gdth_open,
      .release = gdth_close,
  };
@@@ -3842,7 -3842,7 +3842,7 @@@ int __init option_setup(char *str
  
      TRACE2(("option_setup() str %s\n", str ? str:"NULL")); 
  
 -    while (cur && isdigit(*cur) && i <= MAXHA) {
 +    while (cur && isdigit(*cur) && i < MAXHA) {
          ints[i++] = simple_strtoul(cur, NULL, 0);
          if ((cur = strchr(cur, ',')) != NULL) cur++;
      }
@@@ -4462,8 -4462,7 +4462,7 @@@ free_fail
      return rc;
  }
    
- static int gdth_ioctl(struct inode *inode, struct file *filep,
-                       unsigned int cmd, unsigned long arg)
+ static int gdth_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  {
      gdth_ha_str *ha; 
      Scsi_Cmnd *scp;
      return 0;
  }
  
+ static long gdth_unlocked_ioctl(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+ {
+       int ret;
+       lock_kernel();
+       ret = gdth_ioctl(file, cmd, arg);
+       unlock_kernel();
+       return ret;
+ }
  
  /* flush routine */
  static void gdth_flush(gdth_ha_str *ha)
@@@ -416,13 -416,13 +416,13 @@@ static unsigned int mon_bin_get_data(co
  
        } else {
                /* If IOMMU coalescing occurred, we cannot trust sg_page */
 -              if (urb->sg->nents != urb->num_sgs) {
 +              if (urb->transfer_flags & URB_DMA_SG_COMBINED) {
                        *flag = 'D';
                        return length;
                }
  
                /* Copy up to the first non-addressable segment */
 -              for_each_sg(urb->sg->sg, sg, urb->num_sgs, i) {
 +              for_each_sg(urb->sg, sg, urb->num_sgs, i) {
                        if (length == 0 || PageHighMem(sg_page(sg)))
                                break;
                        this_len = min_t(unsigned int, sg->length, length);
@@@ -954,8 -954,7 +954,7 @@@ static int mon_bin_queued(struct mon_re
  
  /*
   */
- static int mon_bin_ioctl(struct inode *inode, struct file *file,
-     unsigned int cmd, unsigned long arg)
+ static int mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
        struct mon_reader_bin *rp = file->private_data;
        // struct mon_bus* mbus = rp->r.m_bus;
        return ret;
  }
  
+ static long mon_bin_unlocked_ioctl(struct file *file, unsigned int cmd,
+                                  unsigned long arg)
+ {
+       int ret;
+       lock_kernel();
+       ret = mon_bin_ioctl(file, cmd, arg);
+       unlock_kernel();
+       return ret;
+ }
  #ifdef CONFIG_COMPAT
  static long mon_bin_compat_ioctl(struct file *file,
      unsigned int cmd, unsigned long arg)
                return 0;
  
        case MON_IOCG_STATS:
-               return mon_bin_ioctl(NULL, file, cmd,
-                                           (unsigned long) compat_ptr(arg));
+               return mon_bin_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
  
        case MON_IOCQ_URB_LEN:
        case MON_IOCQ_RING_SIZE:
        case MON_IOCT_RING_SIZE:
        case MON_IOCH_MFLUSH:
-               return mon_bin_ioctl(NULL, file, cmd, arg);
+               return mon_bin_ioctl(file, cmd, arg);
  
        default:
                ;
@@@ -1239,7 -1250,7 +1250,7 @@@ static const struct file_operations mon
        .read =         mon_bin_read,
        /* .write =     mon_text_write, */
        .poll =         mon_bin_poll,
-       .ioctl =        mon_bin_ioctl,
+       .unlocked_ioctl = mon_bin_unlocked_ioctl,
  #ifdef CONFIG_COMPAT
        .compat_ioctl = mon_bin_compat_ioctl,
  #endif
diff --combined net/sunrpc/cache.c
  #include <linux/workqueue.h>
  #include <linux/mutex.h>
  #include <linux/pagemap.h>
 +#include <linux/smp_lock.h>
  #include <asm/ioctls.h>
  #include <linux/sunrpc/types.h>
  #include <linux/sunrpc/cache.h>
  #include <linux/sunrpc/stats.h>
  #include <linux/sunrpc/rpc_pipe_fs.h>
+ #include <linux/smp_lock.h>
  
  #define        RPCDBG_FACILITY RPCDBG_CACHE
  
@@@ -50,17 -50,11 +51,17 @@@ static void cache_init(struct cache_hea
        h->last_refresh = now;
  }
  
 +static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h)
 +{
 +      return  (h->expiry_time < get_seconds()) ||
 +              (detail->flush_time > h->last_refresh);
 +}
 +
  struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
                                       struct cache_head *key, int hash)
  {
        struct cache_head **head,  **hp;
 -      struct cache_head *new = NULL;
 +      struct cache_head *new = NULL, *freeme = NULL;
  
        head = &detail->hash_table[hash];
  
@@@ -69,9 -63,6 +70,9 @@@
        for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
                struct cache_head *tmp = *hp;
                if (detail->match(tmp, key)) {
 +                      if (cache_is_expired(detail, tmp))
 +                              /* This entry is expired, we will discard it. */
 +                              break;
                        cache_get(tmp);
                        read_unlock(&detail->hash_lock);
                        return tmp;
        for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
                struct cache_head *tmp = *hp;
                if (detail->match(tmp, key)) {
 +                      if (cache_is_expired(detail, tmp)) {
 +                              *hp = tmp->next;
 +                              tmp->next = NULL;
 +                              detail->entries --;
 +                              freeme = tmp;
 +                              break;
 +                      }
                        cache_get(tmp);
                        write_unlock(&detail->hash_lock);
                        cache_put(new, detail);
        cache_get(new);
        write_unlock(&detail->hash_lock);
  
 +      if (freeme)
 +              cache_put(freeme, detail);
        return new;
  }
  EXPORT_SYMBOL_GPL(sunrpc_cache_lookup);
@@@ -202,7 -184,10 +203,7 @@@ static int cache_make_upcall(struct cac
  
  static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h)
  {
 -      if (!test_bit(CACHE_VALID, &h->flags) ||
 -          h->expiry_time < get_seconds())
 -              return -EAGAIN;
 -      else if (detail->flush_time > h->last_refresh)
 +      if (!test_bit(CACHE_VALID, &h->flags))
                return -EAGAIN;
        else {
                /* entry is valid */
@@@ -413,27 -398,31 +414,27 @@@ static int cache_clean(void
                /* Ok, now to clean this strand */
  
                cp = & current_detail->hash_table[current_index];
 -              ch = *cp;
 -              for (; ch; cp= & ch->next, ch= *cp) {
 +              for (ch = *cp ; ch ; cp = & ch->next, ch = *cp) {
                        if (current_detail->nextcheck > ch->expiry_time)
                                current_detail->nextcheck = ch->expiry_time+1;
 -                      if (ch->expiry_time >= get_seconds() &&
 -                          ch->last_refresh >= current_detail->flush_time)
 +                      if (!cache_is_expired(current_detail, ch))
                                continue;
 -                      if (test_and_clear_bit(CACHE_PENDING, &ch->flags))
 -                              cache_dequeue(current_detail, ch);
  
 -                      if (atomic_read(&ch->ref.refcount) == 1)
 -                              break;
 -              }
 -              if (ch) {
                        *cp = ch->next;
                        ch->next = NULL;
                        current_detail->entries--;
                        rv = 1;
 +                      break;
                }
 +
                write_unlock(&current_detail->hash_lock);
                d = current_detail;
                if (!ch)
                        current_index ++;
                spin_unlock(&cache_list_lock);
                if (ch) {
 +                      if (test_and_clear_bit(CACHE_PENDING, &ch->flags))
 +                              cache_dequeue(current_detail, ch);
                        cache_revisit_request(ch);
                        cache_put(ch, d);
                }
@@@ -1245,10 -1234,8 +1246,10 @@@ static int content_open(struct inode *i
        if (!cd || !try_module_get(cd->owner))
                return -EACCES;
        han = __seq_open_private(file, &cache_content_op, sizeof(*han));
 -      if (han == NULL)
 +      if (han == NULL) {
 +              module_put(cd->owner);
                return -ENOMEM;
 +      }
  
        han->cd = cd;
        return 0;
@@@ -1345,18 -1332,12 +1346,18 @@@ static unsigned int cache_poll_procfs(s
        return cache_poll(filp, wait, cd);
  }
  
 -static int cache_ioctl_procfs(struct inode *inode, struct file *filp,
 -                            unsigned int cmd, unsigned long arg)
 +static long cache_ioctl_procfs(struct file *filp,
 +                             unsigned int cmd, unsigned long arg)
  {
 +      long ret;
 +      struct inode *inode = filp->f_path.dentry->d_inode;
        struct cache_detail *cd = PDE(inode)->data;
  
 -      return cache_ioctl(inode, filp, cmd, arg, cd);
 +      lock_kernel();
 +      ret = cache_ioctl(inode, filp, cmd, arg, cd);
 +      unlock_kernel();
 +
 +      return ret;
  }
  
  static int cache_open_procfs(struct inode *inode, struct file *filp)
@@@ -1379,7 -1360,7 +1380,7 @@@ static const struct file_operations cac
        .read           = cache_read_procfs,
        .write          = cache_write_procfs,
        .poll           = cache_poll_procfs,
 -      .ioctl          = cache_ioctl_procfs, /* for FIONREAD */
 +      .unlocked_ioctl = cache_ioctl_procfs, /* for FIONREAD */
        .open           = cache_open_procfs,
        .release        = cache_release_procfs,
  };
@@@ -1545,12 -1526,18 +1546,18 @@@ static unsigned int cache_poll_pipefs(s
        return cache_poll(filp, wait, cd);
  }
  
- static int cache_ioctl_pipefs(struct inode *inode, struct file *filp,
+ static long cache_ioctl_pipefs(struct file *filp,
                              unsigned int cmd, unsigned long arg)
  {
+       struct inode *inode = filp->f_dentry->d_inode;
        struct cache_detail *cd = RPC_I(inode)->private;
+       long ret;
  
-       return cache_ioctl(inode, filp, cmd, arg, cd);
+       lock_kernel();
+       ret = cache_ioctl(inode, filp, cmd, arg, cd);
+       unlock_kernel();
+       return ret;
  }
  
  static int cache_open_pipefs(struct inode *inode, struct file *filp)
@@@ -1573,7 -1560,7 +1580,7 @@@ const struct file_operations cache_file
        .read           = cache_read_pipefs,
        .write          = cache_write_pipefs,
        .poll           = cache_poll_pipefs,
-       .ioctl          = cache_ioctl_pipefs, /* for FIONREAD */
+       .unlocked_ioctl = cache_ioctl_pipefs, /* for FIONREAD */
        .open           = cache_open_pipefs,
        .release        = cache_release_pipefs,
  };