super.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /*
  2. * fs/scfs/super.c
  3. *
  4. * Copyright (C) 2014 Samsung Electronics Co., Ltd.
  5. * Authors: Sunghwan Yun <sunghwan.yun@samsung.com>
  6. * Jongmin Kim <jm45.kim@samsung.com>
  7. * Sangwoo Lee <sangwoo2.lee@samsung.com>
  8. * Inbae Lee <inbae.lee@samsung.com>
  9. *
  10. * This program has been developed as a stackable file system based on
  11. * the WrapFS, which was written by:
  12. *
  13. * Copyright (C) 1997-2003 Erez Zadok
  14. * Copyright (C) 2001-2003 Stony Brook University
  15. * Copyright (C) 2004-2006 International Business Machines Corp.
  16. * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  17. * Michael C. Thompson <mcthomps@us.ibm.com>
  18. *
  19. * This program is free software: you can redistribute it and/or modify
  20. * it under the terms of the GNU General Public License as published by
  21. * the Free Software Foundation, either version 2 of the License, or
  22. * (at your option) any later version.
  23. *
  24. * This program is distributed in the hope that it will be useful, but
  25. * WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  27. * General Public License for more details.
  28. *
  29. * You should have received a copy of the GNU General Public License
  30. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  31. */
  32. #include <linux/export.h>
  33. #include <linux/statfs.h>
  34. #include <linux/seq_file.h>
  35. #include <linux/genhd.h>
  36. #include <linux/module.h>
  37. #include "scfs.h"
  38. #include "../mount.h"
  39. #include <linux/lzo.h>
  40. #define SCFS_VERSION "1.2.19"
  41. #if MAX_BUFFER_CACHE
  42. //extern struct read_buffer_cache buffer_cache[];
  43. //extern spinlock_t buffer_cache_lock;
  44. #endif
  45. #ifdef CONFIG_DEBUG_FS
  46. int scfs_mounted = 1;
  47. #endif
  48. static struct kobject *scfs_kobj;
  49. static const char * scfs_version = SCFS_VERSION;
  50. extern const char *tfm_names[SCFS_COMP_TOTAL_TYPES];
  51. static ssize_t version_show(struct kobject *kobj,
  52. struct kobj_attribute *attr, char *buf)
  53. {
  54. return snprintf(buf, PAGE_SIZE, scfs_version);
  55. }
  56. static struct kobj_attribute version_attr = __ATTR_RO(version);
  57. #ifdef CONFIG_SYSTEM_COMPRESSED
  58. static const char * system_type = "scfs\n";
  59. #else
  60. static const char * system_type = "ext4\n";
  61. #endif
  62. static ssize_t system_type_show(struct kobject *kobj,
  63. struct kobj_attribute *attr, char *buf)
  64. {
  65. return snprintf(buf, PAGE_SIZE, system_type);
  66. }
  67. static struct kobj_attribute system_type_attr = __ATTR_RO(system_type);
  68. static const char * supported_comp_types = "lzo"
  69. #if 0 //#ifdef CONFIG_CRYPTO_DEFLATE
  70. ",bzip2"
  71. #endif
  72. #ifdef CONFIG_CRYPTO_ZLIB
  73. ",zlib"
  74. #endif
  75. #ifdef CONFIG_CRYPTO_FASTLZO
  76. ",fastlzo"
  77. #endif
  78. "\n";
  79. static ssize_t supported_comp_types_show(struct kobject *kobj,
  80. struct kobj_attribute *attr, char *buf)
  81. {
  82. return snprintf(buf, PAGE_SIZE, supported_comp_types);
  83. }
  84. static struct kobj_attribute supported_comp_types_attr = __ATTR_RO(supported_comp_types);
  85. static struct attribute *attributes[] = {
  86. &system_type_attr.attr,
  87. &version_attr.attr,
  88. &supported_comp_types_attr.attr,
  89. NULL,
  90. };
  91. static struct attribute_group attr_group = {
  92. .attrs = attributes,
  93. };
  94. static struct inode *scfs_alloc_inode(struct super_block *sb)
  95. {
  96. struct scfs_inode_info *sii;
  97. sii = kmem_cache_alloc(scfs_inode_info_cache, GFP_KERNEL);
  98. if (!sii)
  99. return NULL;
  100. profile_add_kmcached(sizeof(struct scfs_inode_info), SCFS_S(sb));
  101. memset(sii, 0, offsetof(struct scfs_inode_info, vfs_inode));
  102. sii->vfs_inode.i_version = 1;
  103. if (SCFS_S(sb)->options.flags & SCFS_DATA_COMPRESSABLE)
  104. sii->flags |= SCFS_DATA_COMPRESSABLE;
  105. mutex_init(&sii->lower_file_mutex);
  106. mutex_init(&sii->cinfo_mutex);
  107. INIT_LIST_HEAD(&sii->cinfo_list);
  108. #ifdef SCFS_MULTI_THREAD_COMPRESSION
  109. INIT_LIST_HEAD(&sii->cbm_list);
  110. sii->cbm_list_comp_count = 0;
  111. sii->cbm_list_write_count = 0;
  112. sii->is_inserted_to_sii_list = 0;
  113. sii->cbm_list_comp = NULL;
  114. #endif
  115. return &sii->vfs_inode;
  116. }
  117. static void scfs_destroy_inode(struct inode *inode)
  118. {
  119. struct scfs_sb_info *sbi = SCFS_S(inode->i_sb);
  120. struct scfs_inode_info *sii = SCFS_I(inode);
  121. if (sii->cinfo_array)
  122. scfs_cinfo_free(sii, sii->cinfo_array);
  123. if (!list_empty(&sii->cinfo_list)) {
  124. SCFS_PRINT_ERROR("cinfo list is not empty!\n");
  125. ASSERT(0);
  126. }
  127. if (sii->cluster_buffer.c_page) {
  128. __free_pages(sii->cluster_buffer.c_page, SCFS_MEMPOOL_ORDER + 1);
  129. sii->cluster_buffer.c_buffer = NULL;
  130. sii->cluster_buffer.c_page = NULL;
  131. }
  132. if (sii->cluster_buffer.u_page) {
  133. __free_pages(sii->cluster_buffer.u_page, SCFS_MEMPOOL_ORDER + 1);
  134. sii->cluster_buffer.u_buffer = NULL;
  135. sii->cluster_buffer.u_page = NULL;
  136. atomic_sub(1, &sbi->current_file_count);
  137. }
  138. kmem_cache_free(scfs_inode_info_cache, sii);
  139. profile_sub_kmcached(sizeof(struct scfs_inode_info), SCFS_S(inode->i_sb));
  140. }
  141. static void scfs_evict_inode(struct inode *inode)
  142. {
  143. struct inode *lower_inode;
  144. struct scfs_inode_info *sii = SCFS_I(inode);
  145. truncate_inode_pages(&inode->i_data, 0);
  146. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
  147. clear_inode(inode);
  148. #else
  149. end_writeback(inode);
  150. #endif
  151. /* to conserve memory, evicted inode will throw out the cluster info */
  152. if (sii->cinfo_array) {
  153. scfs_cinfo_free(sii, sii->cinfo_array);
  154. sii->cinfo_array = NULL;
  155. }
  156. if (!list_empty(&sii->cinfo_list))
  157. SCFS_PRINT_ERROR("cinfo list is not empty!\n");
  158. lower_inode = scfs_lower_inode(inode);
  159. scfs_set_lower_inode(inode, NULL);
  160. iput(lower_inode);
  161. }
  162. static int scfs_statfs(struct dentry *dentry, struct kstatfs *buf)
  163. {
  164. int ret;
  165. struct dentry *lower_dentry = scfs_lower_dentry(dentry);
  166. ret = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
  167. if (ret)
  168. return ret;
  169. buf->f_type = SCFS_SUPER_MAGIC;
  170. return ret;
  171. }
  172. static int scfs_show_options(struct seq_file *m, struct dentry *root)
  173. {
  174. struct scfs_sb_info *sbi = SCFS_S(root->d_sb);
  175. struct scfs_mount_options *opts = &sbi->options;
  176. if (!(opts->flags & SCFS_DATA_COMPRESSABLE))
  177. seq_printf(m, ",nocomp");
  178. if (opts->cluster_size)
  179. seq_printf(m, ",cluster_size=%u", opts->cluster_size);
  180. if (opts->comp_threshold >= 0)
  181. seq_printf(m, ",comp_threshold=%u", opts->comp_threshold);
  182. switch (opts->comp_type) {
  183. case SCFS_COMP_LZO:
  184. seq_printf(m, ",comp_type=lzo");
  185. break;
  186. case SCFS_COMP_BZIP2:
  187. seq_printf(m, ",comp_type=bzip2");
  188. break;
  189. case SCFS_COMP_ZLIB:
  190. seq_printf(m, ",comp_type=zlib");
  191. break;
  192. case SCFS_COMP_FASTLZO:
  193. seq_printf(m, ",comp_type=fastlzo");
  194. break;
  195. default:
  196. break;
  197. }
  198. return 0;
  199. }
  200. #ifdef CONFIG_DEBUG_FS
  201. static int lower_path_show(struct seq_file *s, void *unused)
  202. {
  203. seq_printf(s, "%s\n", (char *)(s->private));
  204. return 0;
  205. }
  206. static int lower_path_open(struct inode *inode, struct file *file)
  207. {
  208. return single_open(file, lower_path_show, inode->i_private);
  209. }
  210. static const struct file_operations lower_path_ops = {
  211. .open = lower_path_open,
  212. .read = seq_read,
  213. .llseek = seq_lseek,
  214. .release = single_release,
  215. };
  216. /*
  217. * XXX : An error handling in this function is necessary?
  218. *
  219. */
  220. static int scfs_debugfs_init(struct super_block *sb)
  221. {
  222. struct scfs_sb_info *sbi = SCFS_S(sb);
  223. struct dentry *debugfs_root;
  224. struct scfs_dentry_info *d_info = (struct scfs_dentry_info *)(sb->s_root->d_fsdata);
  225. char root_name[100];
  226. if (!debugfs_initialized())
  227. return -ENODEV;
  228. memset(root_name, 0, 100);
  229. sprintf(root_name, "scfs_%d", scfs_mounted);
  230. debugfs_root = debugfs_create_dir(root_name, NULL);
  231. if (!debugfs_root)
  232. return PTR_ERR(debugfs_root);
  233. sbi->scfs_debugfs_root = debugfs_root;
  234. if (!debugfs_create_file("lower_path", S_IRUGO, debugfs_root,
  235. (void *)(&d_info->lower_path.dentry->d_name.name), &lower_path_ops))
  236. goto fail;
  237. #ifdef SCFS_PROFILE_MEM
  238. debugfs_create_atomic_t("scfs_kmalloced", S_IRUGO,
  239. debugfs_root, &sbi->kmalloced_size);
  240. debugfs_create_atomic_t("scfs_vmalloced", S_IRUGO,
  241. debugfs_root, &sbi->vmalloced_size);
  242. debugfs_create_atomic_t("scfs_mempooled_size", S_IRUGO,
  243. debugfs_root, &sbi->mempooled_size);
  244. debugfs_create_atomic_t("scfs_kmcached_size", S_IRUGO,
  245. debugfs_root, &sbi->kmcached_size);
  246. #endif
  247. #ifdef SCFS_ASYNC_READ_PAGES
  248. debugfs_create_u64("scfs_readpage_total_count", S_IRUGO,
  249. debugfs_root, &sbi->scfs_readpage_total_count);
  250. debugfs_create_u64("scfs_readpage_io_count", S_IRUGO,
  251. debugfs_root, &sbi->scfs_readpage_io_count);
  252. debugfs_create_u64("scfs_lowerpage_total_count", S_IRUGO,
  253. debugfs_root, &sbi->scfs_lowerpage_total_count);
  254. debugfs_create_u64("scfs_lowerpage_reclaim_count", S_IRUGO,
  255. debugfs_root, &sbi->scfs_lowerpage_reclaim_count);
  256. debugfs_create_u64("scfs_lowerpage_alloc_count", S_IRUGO,
  257. debugfs_root, &sbi->scfs_lowerpage_alloc_count);
  258. debugfs_create_u64("scfs_op_mode", S_IRUGO,
  259. debugfs_root, &sbi->scfs_op_mode);
  260. debugfs_create_u64("scfs_sequential_page_number", S_IRUGO | S_IWUGO,
  261. debugfs_root, &sbi->scfs_sequential_page_number);
  262. debugfs_create_u64("buffer_cache_overflow_count_smb", S_IRUGO,
  263. debugfs_root, &sbi->buffer_cache_overflow_count_smb);
  264. debugfs_create_u64("buffer_cache_reclaimed_before_used_count", S_IRUGO,
  265. debugfs_root, &sbi->buffer_cache_reclaimed_before_used_count);
  266. debugfs_create_atomic_t("scfs_standby_readpage_count", S_IRUGO,
  267. debugfs_root, &sbi->scfs_standby_readpage_count);
  268. debugfs_create_u32("page_buffer_next_filling_index_smb", S_IRUGO,
  269. debugfs_root, &sbi->page_buffer_next_filling_index_smb);
  270. debugfs_create_u32("page_buffer_next_io_index_smb", S_IRUGO,
  271. debugfs_root, &sbi->page_buffer_next_io_index_smb);
  272. debugfs_create_u32("max_page_buffer_size_smb", S_IRUGO,
  273. debugfs_root, &sbi->max_page_buffer_size_smb);
  274. #ifdef CONFIG_SCFS_LOWER_PAGECACHE_INVALIDATION
  275. sbi->scfs_op_mode |= (1 << SM_LowInval);
  276. #endif
  277. #endif
  278. return 0;
  279. fail:
  280. debugfs_remove_recursive(debugfs_root);
  281. return -ENOMEM;
  282. }
  283. static void scfs_debugfs_exit(struct scfs_sb_info *sbi)
  284. {
  285. if (!sbi)
  286. return;
  287. debugfs_remove_recursive(sbi->scfs_debugfs_root);
  288. }
  289. #else
  290. static inline int scfs_debugfs_init(struct super_block *sb)
  291. {
  292. return 0;
  293. }
  294. static inline void scfs_debugfs_exit(struct scfs_sb_info *sbi) { }
  295. #endif
  296. static struct dentry *scfs_mount(struct file_system_type *fs_type, int flags,
  297. const char *dev_name, void *raw_data)
  298. {
  299. struct super_block *sb;
  300. struct scfs_sb_info *sbi;
  301. struct scfs_dentry_info *root_info;
  302. struct inode *inode;
  303. struct path path;
  304. int ret, i;
  305. sbi = kzalloc(sizeof(struct scfs_sb_info), GFP_KERNEL);
  306. if (!sbi) {
  307. ret = -ENOMEM;
  308. return ERR_PTR(ret);
  309. }
  310. profile_add_kmalloced(sizeof(struct scfs_sb_info), sbi);
  311. /* set default values */
  312. sbi->options.flags |= SCFS_DATA_COMPRESSABLE;
  313. sbi->options.comp_threshold = 75;
  314. ret = scfs_parse_options(sbi, raw_data);
  315. if (ret) {
  316. goto out_free;
  317. }
  318. if (!sbi->options.cluster_size)
  319. sbi->options.cluster_size = SCFS_CLUSTER_SIZE_DEF;
  320. if (!sbi->options.comp_type)
  321. sbi->options.comp_type = SCFS_COMP_LZO;
  322. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
  323. sb = sget(fs_type, NULL, set_anon_super, flags, NULL);
  324. #else
  325. sb = sget(fs_type, NULL, set_anon_super, NULL);
  326. #endif
  327. if (IS_ERR(sb)) {
  328. goto out_free;
  329. }
  330. ret = bdi_setup_and_register(&sbi->bdi, "scfs", BDI_CAP_MAP_COPY);
  331. if (ret)
  332. goto out_free;
  333. sb->s_bdi = &sbi->bdi;
  334. sb->s_bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE;
  335. sb->s_fs_info = sbi;
  336. sb->s_op = &scfs_sops;
  337. sb->s_d_op = &scfs_dops;
  338. ret= kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
  339. if (ret) {
  340. goto out_deactivate;
  341. }
  342. scfs_set_lower_super(sb, path.dentry->d_sb);
  343. sb->s_maxbytes = path.dentry->d_sb->s_maxbytes;
  344. sb->s_blocksize = path.dentry->d_sb->s_blocksize;
  345. sb->s_magic = SCFS_SUPER_MAGIC;
  346. inode = scfs_get_inode(path.dentry->d_inode, sb);
  347. if (IS_ERR(inode)) {
  348. goto out_pathput;
  349. }
  350. sb->s_root = d_make_root(inode);
  351. if (!sb->s_root) {
  352. ret = -ENOMEM;
  353. goto out_pathput;
  354. }
  355. root_info = kmem_cache_zalloc(scfs_dentry_info_cache, GFP_KERNEL);
  356. if (!root_info)
  357. goto out_pathput;
  358. profile_add_kmcached(sizeof(struct scfs_dentry_info), sbi);
  359. /* After these setting, when dput() is called with upper dentry
  360. * that with lower dentry is also called in deactivate_super().
  361. * So path_put() shouldn't be called from here */
  362. sb->s_root->d_fsdata = root_info;
  363. scfs_set_lower_dentry(sb->s_root, path.dentry);
  364. scfs_set_dentry_lower_mnt(sb->s_root, path.mnt);
  365. /* shared mempool for read/write cluster buffers. */
  366. sbi->mempool = mempool_create_page_pool(SCFS_MEMPOOL_COUNT,
  367. SCFS_MEMPOOL_ORDER);
  368. if (!sbi->mempool) {
  369. SCFS_PRINT_ERROR("mempool create failed!\n");
  370. ret = -ENOMEM;
  371. goto out_deactivate;
  372. }
  373. #if MAX_BUFFER_CACHE
  374. /* initialize read buffers */
  375. for (i = 0; i < MAX_BUFFER_CACHE; i++) {
  376. sbi->buffer_cache[i].u_page = scfs_alloc_mempool_buffer(sbi);
  377. sbi->buffer_cache[i].c_page = scfs_alloc_mempool_buffer(sbi);
  378. if (sbi->buffer_cache[i].u_page == NULL ||
  379. sbi->buffer_cache[i].c_page == NULL) {
  380. SCFS_PRINT_ERROR("mempool alloc failed!\n");
  381. ret = -ENOMEM;
  382. goto out_deactivate;
  383. }
  384. sbi->buffer_cache[i].ino = -1;
  385. sbi->buffer_cache[i].clust_num = -1;
  386. sbi->buffer_cache[i].is_compressed = -1;
  387. atomic_set(&sbi->buffer_cache[i].is_used, -1);
  388. }
  389. spin_lock_init(&sbi->buffer_cache_lock);
  390. #endif
  391. #ifndef CONFIG_SCFS_USE_CRYPTO
  392. switch (sbi->options.comp_type) {
  393. case SCFS_COMP_LZO:
  394. sbi->scfs_workdata = vmalloc(LZO1X_MEM_COMPRESS);
  395. if (!sbi->scfs_workdata) {
  396. SCFS_PRINT_ERROR("vmalloc for lzo workmem failed, "
  397. "len %d\n", LZO1X_MEM_COMPRESS);
  398. ret = -ENOMEM;
  399. goto out_deactivate;
  400. }
  401. break;
  402. default:
  403. break;
  404. }
  405. spin_lock_init(&sbi->workdata_lock);
  406. #endif
  407. #ifdef SCFS_ASYNC_READ_PAGES
  408. spin_lock_init(&sbi->spinlock_smb);
  409. ret = smb_init(sbi);
  410. if (ret) {
  411. SCFS_PRINT_ERROR("failed to init scfs memory buffering\n");
  412. goto out_workdata;
  413. }
  414. sbi->max_page_buffer_size_smb = MAX_PAGE_BUFFER_SIZE_SMB;
  415. #endif
  416. #ifdef SCFS_MULTI_THREAD_COMPRESSION
  417. INIT_LIST_HEAD(&sbi->sii_list);
  418. spin_lock_init(&sbi->sii_list_lock);
  419. sbi->cbm_list_total_count = 0;
  420. ret = smtc_init(sbi);
  421. if (ret) {
  422. SCFS_PRINT_ERROR("failed to init scfs multi-thread compression\n");
  423. goto out_workdata;
  424. }
  425. #endif
  426. ret = scfs_debugfs_init(sb);
  427. if (ret) {
  428. SCFS_PRINT_ERROR("failed to scfs_debugfs_init\n");
  429. goto out_workdata;
  430. }
  431. SCFS_PRINT_ALWAYS("v.%s\n (mempool:%dKBx%d,dev:%s,comp:%s)\n",
  432. scfs_version,
  433. SCFS_MEMPOOL_SIZE / 1024, SCFS_MEMPOOL_COUNT,
  434. dev_name, tfm_names[sbi->options.comp_type]);
  435. scfs_mounted++;
  436. sb->s_flags |= MS_ACTIVE;
  437. return dget(sb->s_root);
  438. out_pathput:
  439. path_put(&path);
  440. out_workdata:
  441. vfree(sbi->scfs_workdata);
  442. out_deactivate:
  443. deactivate_locked_super(sb);
  444. out_free:
  445. kfree(sbi);
  446. return ERR_PTR(ret);
  447. }
  448. static void scfs_kill_block_super(struct super_block *sb)
  449. {
  450. struct scfs_sb_info *sbi = SCFS_S(sb);
  451. kill_anon_super(sb);
  452. if (!sbi)
  453. return;
  454. #ifdef SCFS_MULTI_THREAD_COMPRESSION
  455. smtc_destroy(sbi);
  456. #endif
  457. #ifdef SCFS_ASYNC_READ_PAGES
  458. smb_destroy(sbi);
  459. #endif
  460. #ifdef CONFIG_SCFS_USE_CRYPTO
  461. if (sbi->scfs_workdata)
  462. vfree(sbi->scfs_workdata);
  463. #endif
  464. if (sbi->mempool)
  465. mempool_destroy(sbi->mempool);
  466. scfs_debugfs_exit(sbi);
  467. bdi_destroy(&sbi->bdi);
  468. kmem_cache_free(scfs_sb_info_cache, sbi);
  469. }
  470. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
  471. static int scfs_d_revalidate(struct dentry *dentry, unsigned int flags)
  472. {
  473. struct dentry *lower_dentry;
  474. struct vfsmount *lower_mnt;
  475. int ret = 1;
  476. if (flags & LOOKUP_RCU)
  477. return -ECHILD;
  478. lower_dentry = scfs_lower_dentry(dentry);
  479. lower_mnt = scfs_dentry_to_lower_mnt(dentry);
  480. if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
  481. goto out;
  482. ret = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
  483. if (dentry->d_inode) {
  484. struct inode *lower_inode =
  485. scfs_lower_inode(dentry->d_inode);
  486. fsstack_copy_attr_all(dentry->d_inode, lower_inode);
  487. }
  488. out:
  489. return ret;
  490. }
  491. #else
  492. static int scfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
  493. {
  494. struct dentry *lower_dentry;
  495. struct vfsmount *lower_mnt;
  496. struct dentry *dentry_save = NULL;
  497. struct vfsmount *vfsmount_save = NULL;
  498. int ret = 1;
  499. if (nd && nd->flags & LOOKUP_RCU)
  500. return -ECHILD;
  501. lower_dentry = scfs_lower_dentry(dentry);
  502. lower_mnt = scfs_dentry_to_lower_mnt(dentry);
  503. if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
  504. goto out;
  505. if (nd) {
  506. dentry_save = nd->path.dentry;
  507. vfsmount_save = nd->path.mnt;
  508. nd->path.dentry = lower_dentry;
  509. nd->path.mnt = lower_mnt;
  510. }
  511. ret = lower_dentry->d_op->d_revalidate(lower_dentry, nd);
  512. if (nd) {
  513. nd->path.dentry = dentry_save;
  514. nd->path.mnt = vfsmount_save;
  515. }
  516. if (dentry->d_inode) {
  517. struct inode *lower_inode =
  518. scfs_lower_inode(dentry->d_inode);
  519. fsstack_copy_attr_all(dentry->d_inode, lower_inode);
  520. }
  521. out:
  522. return ret;
  523. }
  524. #endif
  525. static void scfs_d_release(struct dentry *dentry)
  526. {
  527. if (SCFS_D(dentry)) {
  528. if (scfs_lower_dentry(dentry)) {
  529. dput(scfs_lower_dentry(dentry));
  530. mntput(scfs_dentry_to_lower_mnt(dentry));
  531. }
  532. kmem_cache_free(scfs_dentry_info_cache,
  533. SCFS_D(dentry));
  534. profile_sub_kmcached(sizeof(struct scfs_dentry_info),
  535. SCFS_S(dentry->d_sb));
  536. }
  537. return;
  538. }
  539. static int scfs_remount_fs(struct super_block *sb, int *flags, char *options)
  540. {
  541. struct super_block *lower_sb = SCFS_S(sb)->lower_sb;
  542. struct mount *mnt;
  543. struct dentry *dentry;
  544. char *dev_name = NULL, *dir_name;
  545. int start = PATH_MAX - 1;
  546. int ret = -EINVAL;
  547. dir_name = kmalloc(PATH_MAX, GFP_KERNEL);
  548. if (!dir_name)
  549. return -ENOMEM;
  550. if (!(*flags & MS_RDONLY))
  551. set_device_ro(lower_sb->s_bdev, 0);
  552. dir_name[start] = '\0';
  553. mnt = list_first_entry(&lower_sb->s_mounts, struct mount, mnt_instance);
  554. if (mnt) {
  555. dev_name = kstrdup(mnt->mnt_devname, GFP_KERNEL);
  556. dentry = mnt->mnt_mountpoint;
  557. while (dentry->d_parent != dentry) {
  558. start -= dentry->d_name.len;
  559. if (start < 0) {
  560. kfree(dir_name);
  561. return -EINVAL;
  562. }
  563. memcpy(dir_name + start, dentry->d_name.name, dentry->d_name.len);
  564. dir_name[--start] = '/';
  565. dentry = dentry->d_parent;
  566. if (dentry->d_parent == dentry && mnt->mnt_parent &&
  567. mnt->mnt_parent != mnt) {
  568. dentry = mnt->mnt_parent->mnt_mountpoint;
  569. mnt = mnt->mnt_parent;
  570. }
  571. }
  572. ret = do_mount(dev_name, dir_name + start, lower_sb->s_id,
  573. *flags | MS_REMOUNT, options);
  574. } else
  575. SCFS_PRINT_ERROR("remount fail, missing mnt\n");
  576. if (dev_name)
  577. kfree(dev_name);
  578. kfree(dir_name);
  579. return ret;
  580. }
  581. static struct file_system_type scfs_fs_type = {
  582. .owner = THIS_MODULE,
  583. .name = "scfs",
  584. .mount = scfs_mount,
  585. .kill_sb = scfs_kill_block_super, /* TODO */
  586. .fs_flags = 0 /* TODO */
  587. };
  588. const struct super_operations scfs_sops = {
  589. .alloc_inode = scfs_alloc_inode,
  590. .destroy_inode = scfs_destroy_inode,
  591. .evict_inode = scfs_evict_inode,
  592. .statfs = scfs_statfs,
  593. .remount_fs = scfs_remount_fs,
  594. .show_options = scfs_show_options,
  595. };
  596. const struct dentry_operations scfs_dops = {
  597. .d_revalidate = scfs_d_revalidate,
  598. .d_release = scfs_d_release,
  599. };
  600. /*************************/
  601. /* sysfs & init routines */
  602. /*************************/
  603. static int do_sysfs_registration(void)
  604. {
  605. int ret;
  606. scfs_kobj = kobject_create_and_add("scfs", fs_kobj);
  607. if (!scfs_kobj) {
  608. SCFS_PRINT_ERROR("unable to create scfs kset\n");
  609. ret = -ENOMEM;
  610. goto out;
  611. }
  612. ret = sysfs_create_group(scfs_kobj, &attr_group);
  613. if (ret) {
  614. SCFS_PRINT_ERROR("unable to create scfs version attributes\n");
  615. kobject_put(scfs_kobj);
  616. }
  617. out:
  618. return ret;
  619. }
  620. static void do_sysfs_unregistration(void)
  621. {
  622. sysfs_remove_group(scfs_kobj, &attr_group);
  623. kobject_put(scfs_kobj);
  624. }
  625. static int __init scfs_init(void)
  626. {
  627. int ret = 0;
  628. ret = scfs_init_kmem_caches();
  629. if (ret) {
  630. SCFS_PRINT_ERROR("kmem_cache init failed\n");
  631. goto out;
  632. }
  633. ret = scfs_compressors_init();
  634. if (ret) {
  635. SCFS_PRINT_ERROR("compressor initialization was failed.\n");
  636. goto out_free_kmem_caches;
  637. }
  638. ret = do_sysfs_registration();
  639. if (ret) {
  640. SCFS_PRINT_ERROR("sysfs registration failed\n");
  641. goto out_do_scfs_compressor_exit;
  642. }
  643. /*
  644. ret = scfs_init_kthread();
  645. if (ret) {
  646. SCFS_PRINT_ERROR("kthread initialization failed; "
  647. "ret = [%d]\n", ret);
  648. goto out_do_sysfs_unregistration;
  649. }
  650. */
  651. ret = register_filesystem(&scfs_fs_type);
  652. if (ret) {
  653. SCFS_PRINT_ERROR("failed to register filesystem\n");
  654. //goto out_free_kmem_caches;
  655. goto out_do_sysfs_unregistration;
  656. }
  657. goto out;
  658. /*
  659. out_destroy_kthread:
  660. scfs_destroy_kthread();
  661. */
  662. out_do_sysfs_unregistration:
  663. do_sysfs_unregistration();
  664. out_do_scfs_compressor_exit:
  665. scfs_compressors_exit();
  666. out_free_kmem_caches:
  667. scfs_free_kmem_caches();
  668. out:
  669. return ret;
  670. }
  671. static void __exit scfs_exit(void)
  672. {
  673. //scfs_destroy_kthread();
  674. do_sysfs_unregistration();
  675. unregister_filesystem(&scfs_fs_type);
  676. scfs_compressors_exit();
  677. scfs_free_kmem_caches();
  678. }
  679. /* late_initcall to let compressors initialize first */
  680. late_initcall(scfs_init);
  681. module_exit(scfs_exit);
  682. MODULE_LICENSE("GPL");
  683. MODULE_AUTHOR("System Memory Lab");
  684. MODULE_DESCRIPTION("SCFS Module");
  685. MODULE_VERSION(SCFS_VERSION);