kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
        }
        spin_lock(&kernfs_idr_lock);
-       idr_remove(&root->ino_idr, kernfs_ino(kn));
+       idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
        spin_unlock(&kernfs_idr_lock);
        kmem_cache_free(kernfs_node_cache, kn);
 
                                             unsigned flags)
 {
        struct kernfs_node *kn;
-       u32 gen;
+       u32 id_highbits;
        int ret;
 
        name = kstrdup_const(name, GFP_KERNEL);
        idr_preload(GFP_KERNEL);
        spin_lock(&kernfs_idr_lock);
        ret = idr_alloc_cyclic(&root->ino_idr, kn, 1, 0, GFP_ATOMIC);
-       if (ret >= 0 && ret < root->last_ino)
-               root->next_generation++;
-       gen = root->next_generation;
-       root->last_ino = ret;
+       if (ret >= 0 && ret < root->last_id_lowbits)
+               root->id_highbits++;
+       id_highbits = root->id_highbits;
+       root->last_id_lowbits = ret;
        spin_unlock(&kernfs_idr_lock);
        idr_preload_end();
        if (ret < 0)
                goto err_out2;
 
-       kn->id = (u64)gen << 32 | ret;
+       kn->id = (u64)id_highbits << 32 | ret;
 
        atomic_set(&kn->count, 1);
        atomic_set(&kn->active, KN_DEACTIVATED_BIAS);
        return kn;
 
  err_out3:
-       idr_remove(&root->ino_idr, kernfs_ino(kn));
+       idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
  err_out2:
        kmem_cache_free(kernfs_node_cache, kn);
  err_out1:
 
        spin_lock(&kernfs_idr_lock);
 
-       kn = idr_find(&root->ino_idr, ino);
+       kn = idr_find(&root->ino_idr, (u32)ino);
        if (!kn)
                goto err_unlock;
 
-       /* 0 matches all generations */
-       if (unlikely(gen && kernfs_gen(kn) != gen))
-               goto err_unlock;
+       if (sizeof(ino_t) >= sizeof(u64)) {
+               /* we looked up with the low 32bits, compare the whole */
+               if (kernfs_ino(kn) != ino)
+                       goto err_unlock;
+       } else {
+               /* 0 matches all generations */
+               if (unlikely(gen && kernfs_gen(kn) != gen))
+                       goto err_unlock;
+       }
 
        /*
         * ACTIVATED is protected with kernfs_mutex but it was clear when
 
        idr_init(&root->ino_idr);
        INIT_LIST_HEAD(&root->supers);
-       root->next_generation = 1;
+
+       /*
+        * On 64bit ino setups, id is ino.  On 32bit, low 32bits are ino.
+        * High bits generation.  The starting value for both ino and
+        * genenration is 1.  Initialize upper 32bit allocation
+        * accordingly.
+        */
+       if (sizeof(ino_t) >= sizeof(u64))
+               root->id_highbits = 0;
+       else
+               root->id_highbits = 1;
 
        kn = __kernfs_new_node(root, NULL, "", S_IFDIR | S_IRUGO | S_IXUGO,
                               GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
 
        case FILEID_INO32_GEN:
        case FILEID_INO32_GEN_PARENT:
                /*
-                * blk_log_action() exposes (ino,gen) pair without type and
-                * userland can call us with generic fid constructed from
-                * them.  Combine it back to ID.  See blk_log_action().
+                * blk_log_action() exposes "LOW32,HIGH32" pair without
+                * type and userland can call us with generic fid
+                * constructed from them.  Combine it back to ID.  See
+                * blk_log_action().
                 */
                id = ((u64)fid->i32.gen << 32) | fid->i32.ino;
                break;
 
        void                    *priv;
 
        /*
-        * 64bit unique ID.  Lower 32bits carry the inode number and lower
-        * generation.
+        * 64bit unique ID.  On 64bit ino setups, id is the ino.  On 32bit,
+        * the low 32bits are ino and upper generation.
         */
        u64                     id;
 
 
        /* private fields, do not use outside kernfs proper */
        struct idr              ino_idr;
-       u32                     last_ino;
-       u32                     next_generation;
+       u32                     last_id_lowbits;
+       u32                     id_highbits;
        struct kernfs_syscall_ops *syscall_ops;
 
        /* list of kernfs_super_info of this root, protected by kernfs_mutex */
 
 static inline ino_t kernfs_id_ino(u64 id)
 {
-       return (u32)id;
+       /* id is ino if ino_t is 64bit; otherwise, low 32bits */
+       if (sizeof(ino_t) >= sizeof(u64))
+               return id;
+       else
+               return (u32)id;
 }
 
 static inline u32 kernfs_id_gen(u64 id)
 {
-       return id >> 32;
+       /* gen is fixed at 1 if ino_t is 64bit; otherwise, high 32bits */
+       if (sizeof(ino_t) >= sizeof(u64))
+               return 1;
+       else
+               return id >> 32;
 }
 
 static inline ino_t kernfs_ino(struct kernfs_node *kn)
 
                        trace_seq_printf(&iter->seq, "%3d,%-3d %s %2s %3s ",
                                 MAJOR(t->device), MINOR(t->device),
                                 blkcg_name_buf, act, rwbs);
-               } else
+               } else {
+                       /*
+                        * The cgid portion used to be "INO,GEN".  Userland
+                        * builds a FILEID_INO32_GEN fid out of them and
+                        * opens the cgroup using open_by_handle_at(2).
+                        * While 32bit ino setups are still the same, 64bit
+                        * ones now use the 64bit ino as the whole ID and
+                        * no longer use generation.
+                        *
+                        * Regarldess of the content, always output
+                        * "LOW32,HIGH32" so that FILEID_INO32_GEN fid can
+                        * be mapped back to @id on both 64 and 32bit ino
+                        * setups.  See __kernfs_fh_to_dentry().
+                        */
                        trace_seq_printf(&iter->seq,
-                                "%3d,%-3d %lx,%-x %2s %3s ",
+                                "%3d,%-3d %llx,%-llx %2s %3s ",
                                 MAJOR(t->device), MINOR(t->device),
-                                kernfs_id_ino(id), kernfs_id_gen(id),
-                                act, rwbs);
+                                id & U32_MAX, id >> 32, act, rwbs);
+               }
        } else
                trace_seq_printf(&iter->seq, "%3d,%-3d %2s %3s ",
                                 MAJOR(t->device), MINOR(t->device), act, rwbs);