Merge branch 'stable-3.2' into pandora-3.2
authorGrazvydas Ignotas <notasas@gmail.com>
Sat, 8 Nov 2014 22:48:49 +0000 (00:48 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Sat, 8 Nov 2014 22:48:49 +0000 (00:48 +0200)
1  2 
arch/arm/mm/alignment.c
fs/namei.c
mm/shmem.c

diff --combined arch/arm/mm/alignment.c
@@@ -38,6 -38,7 +38,7 @@@
   * This code is not portable to processors with late data abort handling.
   */
  #define CODING_BITS(i)        (i & 0x0e000000)
+ #define COND_BITS(i)  (i & 0xf0000000)
  
  #define LDST_I_BIT(i) (i & (1 << 26))         /* Immediate constant   */
  #define LDST_P_BIT(i) (i & (1 << 24))         /* Preindex             */
@@@ -812,6 -813,8 +813,8 @@@ do_alignment(unsigned long addr, unsign
                break;
  
        case 0x04000000:        /* ldr or str immediate */
+               if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */
+                       goto bad;
                offset.un = OFFSET_BITS(instr);
                handler = do_alignment_ldrstr;
                break;
@@@ -965,7 -968,7 +968,7 @@@ static int __init alignment_init(void
                ai_usermode = safe_usermode(ai_usermode, false);
        }
  
 -      hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
 +      hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
                        "alignment exception");
  
        /*
diff --combined fs/namei.c
@@@ -554,24 -554,22 +554,22 @@@ static int complete_walk(struct nameida
  
  static __always_inline void set_root(struct nameidata *nd)
  {
-       if (!nd->root.mnt)
-               get_fs_root(current->fs, &nd->root);
+       get_fs_root(current->fs, &nd->root);
  }
  
  static int link_path_walk(const char *, struct nameidata *);
  
- static __always_inline void set_root_rcu(struct nameidata *nd)
+ static __always_inline unsigned set_root_rcu(struct nameidata *nd)
  {
-       if (!nd->root.mnt) {
-               struct fs_struct *fs = current->fs;
-               unsigned seq;
+       struct fs_struct *fs = current->fs;
+       unsigned seq, res;
  
-               do {
-                       seq = read_seqcount_begin(&fs->seq);
-                       nd->root = fs->root;
-                       nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq);
-               } while (read_seqcount_retry(&fs->seq, seq));
-       }
+       do {
+               seq = read_seqcount_begin(&fs->seq);
+               nd->root = fs->root;
+               res = __read_seqcount_begin(&nd->root.dentry->d_seq);
+       } while (read_seqcount_retry(&fs->seq, seq));
+       return res;
  }
  
  static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
                goto fail;
  
        if (*link == '/') {
-               set_root(nd);
+               if (!nd->root.mnt)
+                       set_root(nd);
                path_put(&nd->path);
                nd->path = nd->root;
                path_get(&nd->root);
@@@ -912,22 -911,11 +911,11 @@@ static bool __follow_mount_rcu(struct n
        return true;
  }
  
- static void follow_mount_rcu(struct nameidata *nd)
- {
-       while (d_mountpoint(nd->path.dentry)) {
-               struct vfsmount *mounted;
-               mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry, 1);
-               if (!mounted)
-                       break;
-               nd->path.mnt = mounted;
-               nd->path.dentry = mounted->mnt_root;
-               nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
-       }
- }
  static int follow_dotdot_rcu(struct nameidata *nd)
  {
-       set_root_rcu(nd);
+       struct inode *inode = nd->inode;
+       if (!nd->root.mnt)
+               set_root_rcu(nd);
  
        while (1) {
                if (nd->path.dentry == nd->root.dentry &&
                        struct dentry *parent = old->d_parent;
                        unsigned seq;
  
+                       inode = parent->d_inode;
                        seq = read_seqcount_begin(&parent->d_seq);
                        if (read_seqcount_retry(&old->d_seq, nd->seq))
                                goto failed;
                }
                if (!follow_up_rcu(&nd->path))
                        break;
+               inode = nd->path.dentry->d_inode;
                nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
        }
-       follow_mount_rcu(nd);
-       nd->inode = nd->path.dentry->d_inode;
+       while (d_mountpoint(nd->path.dentry)) {
+               struct vfsmount *mounted;
+               mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry, 1);
+               if (!mounted)
+                       break;
+               nd->path.mnt = mounted;
+               nd->path.dentry = mounted->mnt_root;
+               inode = nd->path.dentry->d_inode;
+               nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
+       }
+       nd->inode = inode;
        return 0;
  
  failed:
@@@ -1030,7 -1029,8 +1029,8 @@@ static void follow_mount(struct path *p
  
  static void follow_dotdot(struct nameidata *nd)
  {
-       set_root(nd);
+       if (!nd->root.mnt)
+               set_root(nd);
  
        while(1) {
                struct dentry *old = nd->path.dentry;
@@@ -1504,7 -1504,7 +1504,7 @@@ static int path_init(int dfd, const cha
                if (flags & LOOKUP_RCU) {
                        br_read_lock(vfsmount_lock);
                        rcu_read_lock();
-                       set_root_rcu(nd);
+                       nd->seq = set_root_rcu(nd);
                } else {
                        set_root(nd);
                        path_get(&nd->root);
        }
  
        nd->inode = nd->path.dentry->d_inode;
-       return 0;
+       if (!(flags & LOOKUP_RCU))
+               return 0;
+       if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
+               return 0;
+       if (!(nd->flags & LOOKUP_ROOT))
+               nd->root.mnt = NULL;
+       rcu_read_unlock();
+       return -ECHILD;
  
  fput_fail:
        fput_light(file, fput_needed);
@@@ -1755,11 -1762,10 +1762,11 @@@ static struct dentry *__lookup_hash(str
   * needs parent already locked. Doesn't follow mounts.
   * SMP-safe.
   */
 -static struct dentry *lookup_hash(struct nameidata *nd)
 +struct dentry *lookup_hash(struct nameidata *nd)
  {
        return __lookup_hash(&nd->last, nd->path.dentry, nd);
  }
 +EXPORT_SYMBOL(lookup_hash);
  
  /**
   * lookup_one_len - filesystem helper to lookup single pathname component
diff --combined mm/shmem.c
@@@ -1185,7 -1185,6 +1185,7 @@@ int vmtruncate_range(struct inode *inod
        mutex_unlock(&inode->i_mutex);
        return 0;
  }
 +EXPORT_SYMBOL_GPL(vmtruncate_range);
  
  #ifdef CONFIG_NUMA
  static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *mpol)
@@@ -1720,8 -1719,10 +1720,10 @@@ static int shmem_rename(struct inode *o
  
        if (new_dentry->d_inode) {
                (void) shmem_unlink(new_dir, new_dentry);
-               if (they_are_dirs)
+               if (they_are_dirs) {
+                       drop_nlink(new_dentry->d_inode);
                        drop_nlink(old_dir);
+               }
        } else if (they_are_dirs) {
                drop_nlink(old_dir);
                inc_nlink(new_dir);
@@@ -2712,7 -2713,6 +2714,7 @@@ int shmem_zero_setup(struct vm_area_str
        vma->vm_flags |= VM_CAN_NONLINEAR;
        return 0;
  }
 +EXPORT_SYMBOL_GPL(shmem_zero_setup);
  
  /**
   * shmem_read_mapping_page_gfp - read into page cache, using specified page allocation flags.