tmpfs-idr.patch 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. SPDX-License-Identifier: GPL-2.0
  2. diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
  3. index 20d815a33145..64354e89a701 100644
  4. --- a/include/linux/shmem_fs.h
  5. +++ b/include/linux/shmem_fs.h
  6. @@ -26,10 +26,13 @@ struct shmem_inode_info {
  7. };
  8. struct shmem_sb_info {
  9. + struct mutex idr_lock;
  10. + bool idr_nouse;
  11. + struct idr idr; /* manages inode-number */
  12. unsigned long max_blocks; /* How many blocks are allowed */
  13. struct percpu_counter used_blocks; /* How many are allocated */
  14. - unsigned long max_inodes; /* How many inodes are allowed */
  15. - unsigned long free_inodes; /* How many are left for allocation */
  16. + int max_inodes; /* How many inodes are allowed */
  17. + int free_inodes; /* How many are left for allocation */
  18. spinlock_t stat_lock; /* Serialize shmem_sb_info changes */
  19. umode_t mode; /* Mount mode for root directory */
  20. unsigned char huge; /* Whether to try for hugepages */
  21. diff --git a/mm/shmem.c b/mm/shmem.c
  22. index 2275a0ff7c30..0d0105d2d208 100644
  23. --- a/mm/shmem.c
  24. +++ b/mm/shmem.c
  25. @@ -113,11 +113,14 @@ static unsigned long shmem_default_max_blocks(void)
  26. return totalram_pages() / 2;
  27. }
  28. -static unsigned long shmem_default_max_inodes(void)
  29. +static int shmem_default_max_inodes(void)
  30. {
  31. unsigned long nr_pages = totalram_pages();
  32. + unsigned long ul;
  33. - return min(nr_pages - totalhigh_pages(), nr_pages / 2);
  34. + ul = INT_MAX;
  35. + ul = min3(ul, nr_pages - totalhigh_pages(), nr_pages / 2);
  36. + return ul;
  37. }
  38. #endif
  39. @@ -1095,6 +1098,11 @@ static void shmem_evict_inode(struct inode *inode)
  40. simple_xattrs_free(&info->xattrs);
  41. WARN_ON(inode->i_blocks);
  42. + if (!sbinfo->idr_nouse && inode->i_ino) {
  43. + mutex_lock(&sbinfo->idr_lock);
  44. + idr_remove(&sbinfo->idr, inode->i_ino);
  45. + mutex_unlock(&sbinfo->idr_lock);
  46. + }
  47. shmem_free_inode(inode->i_sb);
  48. clear_inode(inode);
  49. }
  50. @@ -2219,13 +2227,13 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
  51. struct inode *inode;
  52. struct shmem_inode_info *info;
  53. struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
  54. + int ino;
  55. if (shmem_reserve_inode(sb))
  56. return NULL;
  57. inode = new_inode(sb);
  58. if (inode) {
  59. - inode->i_ino = get_next_ino();
  60. inode_init_owner(inode, dir, mode);
  61. inode->i_blocks = 0;
  62. inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
  63. @@ -2269,6 +2277,25 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
  64. break;
  65. }
  66. + if (!sbinfo->idr_nouse) {
  67. + /* inum 0 and 1 are unused */
  68. + mutex_lock(&sbinfo->idr_lock);
  69. + ino = idr_alloc(&sbinfo->idr, inode, 2, INT_MAX,
  70. + GFP_NOFS);
  71. + if (ino > 0) {
  72. + inode->i_ino = ino;
  73. + mutex_unlock(&sbinfo->idr_lock);
  74. + __insert_inode_hash(inode, inode->i_ino);
  75. + } else {
  76. + inode->i_ino = 0;
  77. + mutex_unlock(&sbinfo->idr_lock);
  78. + iput(inode);
  79. + /* shmem_free_inode() will be called */
  80. + inode = NULL;
  81. + }
  82. + } else
  83. + inode->i_ino = get_next_ino();
  84. +
  85. lockdep_annotate_inode_mutex_key(inode);
  86. } else
  87. shmem_free_inode(sb);
  88. @@ -3274,8 +3301,7 @@ static struct dentry *shmem_get_parent(struct dentry *child)
  89. static int shmem_match(struct inode *ino, void *vfh)
  90. {
  91. __u32 *fh = vfh;
  92. - __u64 inum = fh[2];
  93. - inum = (inum << 32) | fh[1];
  94. + __u64 inum = fh[1];
  95. return ino->i_ino == inum && fh[0] == ino->i_generation;
  96. }
  97. @@ -3295,14 +3321,11 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb,
  98. struct dentry *dentry = NULL;
  99. u64 inum;
  100. - if (fh_len < 3)
  101. + if (fh_len < 2)
  102. return NULL;
  103. - inum = fid->raw[2];
  104. - inum = (inum << 32) | fid->raw[1];
  105. -
  106. - inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),
  107. - shmem_match, fid->raw);
  108. + inum = fid->raw[1];
  109. + inode = ilookup5(sb, inum, shmem_match, fid->raw);
  110. if (inode) {
  111. dentry = shmem_find_alias(inode);
  112. iput(inode);
  113. @@ -3314,30 +3337,15 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb,
  114. static int shmem_encode_fh(struct inode *inode, __u32 *fh, int *len,
  115. struct inode *parent)
  116. {
  117. - if (*len < 3) {
  118. - *len = 3;
  119. + if (*len < 2) {
  120. + *len = 2;
  121. return FILEID_INVALID;
  122. }
  123. - if (inode_unhashed(inode)) {
  124. - /* Unfortunately insert_inode_hash is not idempotent,
  125. - * so as we hash inodes here rather than at creation
  126. - * time, we need a lock to ensure we only try
  127. - * to do it once
  128. - */
  129. - static DEFINE_SPINLOCK(lock);
  130. - spin_lock(&lock);
  131. - if (inode_unhashed(inode))
  132. - __insert_inode_hash(inode,
  133. - inode->i_ino + inode->i_generation);
  134. - spin_unlock(&lock);
  135. - }
  136. -
  137. fh[0] = inode->i_generation;
  138. fh[1] = inode->i_ino;
  139. - fh[2] = ((__u64)inode->i_ino) >> 32;
  140. - *len = 3;
  141. + *len = 2;
  142. return 1;
  143. }
  144. @@ -3401,7 +3409,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
  145. goto bad_val;
  146. } else if (!strcmp(this_char,"nr_inodes")) {
  147. sbinfo->max_inodes = memparse(value, &rest);
  148. - if (*rest)
  149. + if (*rest || sbinfo->max_inodes < 2)
  150. goto bad_val;
  151. } else if (!strcmp(this_char,"mode")) {
  152. if (remount)
  153. @@ -3466,7 +3474,7 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
  154. {
  155. struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
  156. struct shmem_sb_info config = *sbinfo;
  157. - unsigned long inodes;
  158. + int inodes;
  159. int error = -EINVAL;
  160. config.mpol = NULL;
  161. @@ -3515,7 +3523,7 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root)
  162. seq_printf(seq, ",size=%luk",
  163. sbinfo->max_blocks << (PAGE_SHIFT - 10));
  164. if (sbinfo->max_inodes != shmem_default_max_inodes())
  165. - seq_printf(seq, ",nr_inodes=%lu", sbinfo->max_inodes);
  166. + seq_printf(seq, ",nr_inodes=%d", sbinfo->max_inodes);
  167. if (sbinfo->mode != (0777 | S_ISVTX))
  168. seq_printf(seq, ",mode=%03ho", sbinfo->mode);
  169. if (!uid_eq(sbinfo->uid, GLOBAL_ROOT_UID))
  170. @@ -3539,6 +3547,8 @@ static void shmem_put_super(struct super_block *sb)
  171. {
  172. struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
  173. + if (!sbinfo->idr_nouse)
  174. + idr_destroy(&sbinfo->idr);
  175. percpu_counter_destroy(&sbinfo->used_blocks);
  176. mpol_put(sbinfo->mpol);
  177. kfree(sbinfo);
  178. @@ -3557,6 +3567,8 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
  179. if (!sbinfo)
  180. return -ENOMEM;
  181. + mutex_init(&sbinfo->idr_lock);
  182. + idr_init(&sbinfo->idr);
  183. sbinfo->mode = 0777 | S_ISVTX;
  184. sbinfo->uid = current_fsuid();
  185. sbinfo->gid = current_fsgid();
  186. @@ -3664,6 +3676,15 @@ static void shmem_destroy_inodecache(void)
  187. kmem_cache_destroy(shmem_inode_cachep);
  188. }
  189. +static __init void shmem_no_idr(struct super_block *sb)
  190. +{
  191. + struct shmem_sb_info *sbinfo;
  192. +
  193. + sbinfo = SHMEM_SB(sb);
  194. + sbinfo->idr_nouse = true;
  195. + idr_destroy(&sbinfo->idr);
  196. +}
  197. +
  198. static const struct address_space_operations shmem_aops = {
  199. .writepage = shmem_writepage,
  200. .set_page_dirty = __set_page_dirty_no_writeback,
  201. @@ -3794,6 +3815,7 @@ int __init shmem_init(void)
  202. pr_err("Could not kern_mount tmpfs\n");
  203. goto out1;
  204. }
  205. + shmem_no_idr(shm_mnt->mnt_sb);
  206. #ifdef CONFIG_TRANSPARENT_HUGE_PAGECACHE
  207. if (has_transparent_hugepage() && shmem_huge > SHMEM_HUGE_DENY)