18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <linux/ceph/ceph_debug.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/backing-dev.h> 68c2ecf20Sopenharmony_ci#include <linux/ctype.h> 78c2ecf20Sopenharmony_ci#include <linux/fs.h> 88c2ecf20Sopenharmony_ci#include <linux/inet.h> 98c2ecf20Sopenharmony_ci#include <linux/in6.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/mount.h> 128c2ecf20Sopenharmony_ci#include <linux/fs_context.h> 138c2ecf20Sopenharmony_ci#include <linux/fs_parser.h> 148c2ecf20Sopenharmony_ci#include <linux/sched.h> 158c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 168c2ecf20Sopenharmony_ci#include <linux/slab.h> 178c2ecf20Sopenharmony_ci#include <linux/statfs.h> 188c2ecf20Sopenharmony_ci#include <linux/string.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "super.h" 218c2ecf20Sopenharmony_ci#include "mds_client.h" 228c2ecf20Sopenharmony_ci#include "cache.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <linux/ceph/ceph_features.h> 258c2ecf20Sopenharmony_ci#include <linux/ceph/decode.h> 268c2ecf20Sopenharmony_ci#include <linux/ceph/mon_client.h> 278c2ecf20Sopenharmony_ci#include <linux/ceph/auth.h> 288c2ecf20Sopenharmony_ci#include <linux/ceph/debugfs.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(ceph_fsc_lock); 318c2ecf20Sopenharmony_cistatic LIST_HEAD(ceph_fsc_list); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* 348c2ecf20Sopenharmony_ci * Ceph superblock operations 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * Handle the basics of mounting, unmounting. 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* 408c2ecf20Sopenharmony_ci * super ops 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_cistatic void ceph_put_super(struct super_block *s) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = ceph_sb_to_client(s); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci dout("put_super\n"); 478c2ecf20Sopenharmony_ci ceph_mdsc_close_sessions(fsc->mdsc); 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry)); 538c2ecf20Sopenharmony_ci struct ceph_mon_client *monc = &fsc->client->monc; 548c2ecf20Sopenharmony_ci struct ceph_statfs st; 558c2ecf20Sopenharmony_ci int i, err; 568c2ecf20Sopenharmony_ci u64 data_pool; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (fsc->mdsc->mdsmap->m_num_data_pg_pools == 1) { 598c2ecf20Sopenharmony_ci data_pool = fsc->mdsc->mdsmap->m_data_pg_pools[0]; 608c2ecf20Sopenharmony_ci } else { 618c2ecf20Sopenharmony_ci data_pool = CEPH_NOPOOL; 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci dout("statfs\n"); 658c2ecf20Sopenharmony_ci err = ceph_monc_do_statfs(monc, data_pool, &st); 668c2ecf20Sopenharmony_ci if (err < 0) 678c2ecf20Sopenharmony_ci return err; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci /* fill in kstatfs */ 708c2ecf20Sopenharmony_ci buf->f_type = CEPH_SUPER_MAGIC; /* ?? */ 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* 738c2ecf20Sopenharmony_ci * express utilization in terms of large blocks to avoid 748c2ecf20Sopenharmony_ci * overflow on 32-bit machines. 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci * NOTE: for the time being, we make bsize == frsize to humor 778c2ecf20Sopenharmony_ci * not-yet-ancient versions of glibc that are broken. 788c2ecf20Sopenharmony_ci * Someday, we will probably want to report a real block 798c2ecf20Sopenharmony_ci * size... whatever that may mean for a network file system! 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci buf->f_bsize = 1 << CEPH_BLOCK_SHIFT; 828c2ecf20Sopenharmony_ci buf->f_frsize = 1 << CEPH_BLOCK_SHIFT; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci /* 858c2ecf20Sopenharmony_ci * By default use root quota for stats; fallback to overall filesystem 868c2ecf20Sopenharmony_ci * usage if using 'noquotadf' mount option or if the root dir doesn't 878c2ecf20Sopenharmony_ci * have max_bytes quota set. 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_ci if (ceph_test_mount_opt(fsc, NOQUOTADF) || 908c2ecf20Sopenharmony_ci !ceph_quota_update_statfs(fsc, buf)) { 918c2ecf20Sopenharmony_ci buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10); 928c2ecf20Sopenharmony_ci buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10); 938c2ecf20Sopenharmony_ci buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10); 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci buf->f_files = le64_to_cpu(st.num_objects); 978c2ecf20Sopenharmony_ci buf->f_ffree = -1; 988c2ecf20Sopenharmony_ci buf->f_namelen = NAME_MAX; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* Must convert the fsid, for consistent values across arches */ 1018c2ecf20Sopenharmony_ci buf->f_fsid.val[0] = 0; 1028c2ecf20Sopenharmony_ci mutex_lock(&monc->mutex); 1038c2ecf20Sopenharmony_ci for (i = 0 ; i < sizeof(monc->monmap->fsid) / sizeof(__le32) ; ++i) 1048c2ecf20Sopenharmony_ci buf->f_fsid.val[0] ^= le32_to_cpu(((__le32 *)&monc->monmap->fsid)[i]); 1058c2ecf20Sopenharmony_ci mutex_unlock(&monc->mutex); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* fold the fs_cluster_id into the upper bits */ 1088c2ecf20Sopenharmony_ci buf->f_fsid.val[1] = monc->fs_cluster_id; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci return 0; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic int ceph_sync_fs(struct super_block *sb, int wait) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = ceph_sb_to_client(sb); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci if (!wait) { 1188c2ecf20Sopenharmony_ci dout("sync_fs (non-blocking)\n"); 1198c2ecf20Sopenharmony_ci ceph_flush_dirty_caps(fsc->mdsc); 1208c2ecf20Sopenharmony_ci dout("sync_fs (non-blocking) done\n"); 1218c2ecf20Sopenharmony_ci return 0; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci dout("sync_fs (blocking)\n"); 1258c2ecf20Sopenharmony_ci ceph_osdc_sync(&fsc->client->osdc); 1268c2ecf20Sopenharmony_ci ceph_mdsc_sync(fsc->mdsc); 1278c2ecf20Sopenharmony_ci dout("sync_fs (blocking) done\n"); 1288c2ecf20Sopenharmony_ci return 0; 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/* 1328c2ecf20Sopenharmony_ci * mount options 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_cienum { 1358c2ecf20Sopenharmony_ci Opt_wsize, 1368c2ecf20Sopenharmony_ci Opt_rsize, 1378c2ecf20Sopenharmony_ci Opt_rasize, 1388c2ecf20Sopenharmony_ci Opt_caps_wanted_delay_min, 1398c2ecf20Sopenharmony_ci Opt_caps_wanted_delay_max, 1408c2ecf20Sopenharmony_ci Opt_caps_max, 1418c2ecf20Sopenharmony_ci Opt_readdir_max_entries, 1428c2ecf20Sopenharmony_ci Opt_readdir_max_bytes, 1438c2ecf20Sopenharmony_ci Opt_congestion_kb, 1448c2ecf20Sopenharmony_ci /* int args above */ 1458c2ecf20Sopenharmony_ci Opt_snapdirname, 1468c2ecf20Sopenharmony_ci Opt_mds_namespace, 1478c2ecf20Sopenharmony_ci Opt_recover_session, 1488c2ecf20Sopenharmony_ci Opt_source, 1498c2ecf20Sopenharmony_ci /* string args above */ 1508c2ecf20Sopenharmony_ci Opt_dirstat, 1518c2ecf20Sopenharmony_ci Opt_rbytes, 1528c2ecf20Sopenharmony_ci Opt_asyncreaddir, 1538c2ecf20Sopenharmony_ci Opt_dcache, 1548c2ecf20Sopenharmony_ci Opt_ino32, 1558c2ecf20Sopenharmony_ci Opt_fscache, 1568c2ecf20Sopenharmony_ci Opt_poolperm, 1578c2ecf20Sopenharmony_ci Opt_require_active_mds, 1588c2ecf20Sopenharmony_ci Opt_acl, 1598c2ecf20Sopenharmony_ci Opt_quotadf, 1608c2ecf20Sopenharmony_ci Opt_copyfrom, 1618c2ecf20Sopenharmony_ci Opt_wsync, 1628c2ecf20Sopenharmony_ci}; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cienum ceph_recover_session_mode { 1658c2ecf20Sopenharmony_ci ceph_recover_session_no, 1668c2ecf20Sopenharmony_ci ceph_recover_session_clean 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic const struct constant_table ceph_param_recover[] = { 1708c2ecf20Sopenharmony_ci { "no", ceph_recover_session_no }, 1718c2ecf20Sopenharmony_ci { "clean", ceph_recover_session_clean }, 1728c2ecf20Sopenharmony_ci {} 1738c2ecf20Sopenharmony_ci}; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic const struct fs_parameter_spec ceph_mount_parameters[] = { 1768c2ecf20Sopenharmony_ci fsparam_flag_no ("acl", Opt_acl), 1778c2ecf20Sopenharmony_ci fsparam_flag_no ("asyncreaddir", Opt_asyncreaddir), 1788c2ecf20Sopenharmony_ci fsparam_s32 ("caps_max", Opt_caps_max), 1798c2ecf20Sopenharmony_ci fsparam_u32 ("caps_wanted_delay_max", Opt_caps_wanted_delay_max), 1808c2ecf20Sopenharmony_ci fsparam_u32 ("caps_wanted_delay_min", Opt_caps_wanted_delay_min), 1818c2ecf20Sopenharmony_ci fsparam_u32 ("write_congestion_kb", Opt_congestion_kb), 1828c2ecf20Sopenharmony_ci fsparam_flag_no ("copyfrom", Opt_copyfrom), 1838c2ecf20Sopenharmony_ci fsparam_flag_no ("dcache", Opt_dcache), 1848c2ecf20Sopenharmony_ci fsparam_flag_no ("dirstat", Opt_dirstat), 1858c2ecf20Sopenharmony_ci fsparam_flag_no ("fsc", Opt_fscache), // fsc|nofsc 1868c2ecf20Sopenharmony_ci fsparam_string ("fsc", Opt_fscache), // fsc=... 1878c2ecf20Sopenharmony_ci fsparam_flag_no ("ino32", Opt_ino32), 1888c2ecf20Sopenharmony_ci fsparam_string ("mds_namespace", Opt_mds_namespace), 1898c2ecf20Sopenharmony_ci fsparam_flag_no ("poolperm", Opt_poolperm), 1908c2ecf20Sopenharmony_ci fsparam_flag_no ("quotadf", Opt_quotadf), 1918c2ecf20Sopenharmony_ci fsparam_u32 ("rasize", Opt_rasize), 1928c2ecf20Sopenharmony_ci fsparam_flag_no ("rbytes", Opt_rbytes), 1938c2ecf20Sopenharmony_ci fsparam_u32 ("readdir_max_bytes", Opt_readdir_max_bytes), 1948c2ecf20Sopenharmony_ci fsparam_u32 ("readdir_max_entries", Opt_readdir_max_entries), 1958c2ecf20Sopenharmony_ci fsparam_enum ("recover_session", Opt_recover_session, ceph_param_recover), 1968c2ecf20Sopenharmony_ci fsparam_flag_no ("require_active_mds", Opt_require_active_mds), 1978c2ecf20Sopenharmony_ci fsparam_u32 ("rsize", Opt_rsize), 1988c2ecf20Sopenharmony_ci fsparam_string ("snapdirname", Opt_snapdirname), 1998c2ecf20Sopenharmony_ci fsparam_string ("source", Opt_source), 2008c2ecf20Sopenharmony_ci fsparam_u32 ("wsize", Opt_wsize), 2018c2ecf20Sopenharmony_ci fsparam_flag_no ("wsync", Opt_wsync), 2028c2ecf20Sopenharmony_ci {} 2038c2ecf20Sopenharmony_ci}; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistruct ceph_parse_opts_ctx { 2068c2ecf20Sopenharmony_ci struct ceph_options *copts; 2078c2ecf20Sopenharmony_ci struct ceph_mount_options *opts; 2088c2ecf20Sopenharmony_ci}; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci/* 2118c2ecf20Sopenharmony_ci * Remove adjacent slashes and then the trailing slash, unless it is 2128c2ecf20Sopenharmony_ci * the only remaining character. 2138c2ecf20Sopenharmony_ci * 2148c2ecf20Sopenharmony_ci * E.g. "//dir1////dir2///" --> "/dir1/dir2", "///" --> "/". 2158c2ecf20Sopenharmony_ci */ 2168c2ecf20Sopenharmony_cistatic void canonicalize_path(char *path) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci int i, j = 0; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci for (i = 0; path[i] != '\0'; i++) { 2218c2ecf20Sopenharmony_ci if (path[i] != '/' || j < 1 || path[j - 1] != '/') 2228c2ecf20Sopenharmony_ci path[j++] = path[i]; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (j > 1 && path[j - 1] == '/') 2268c2ecf20Sopenharmony_ci j--; 2278c2ecf20Sopenharmony_ci path[j] = '\0'; 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci/* 2318c2ecf20Sopenharmony_ci * Parse the source parameter. Distinguish the server list from the path. 2328c2ecf20Sopenharmony_ci * 2338c2ecf20Sopenharmony_ci * The source will look like: 2348c2ecf20Sopenharmony_ci * <server_spec>[,<server_spec>...]:[<path>] 2358c2ecf20Sopenharmony_ci * where 2368c2ecf20Sopenharmony_ci * <server_spec> is <ip>[:<port>] 2378c2ecf20Sopenharmony_ci * <path> is optional, but if present must begin with '/' 2388c2ecf20Sopenharmony_ci */ 2398c2ecf20Sopenharmony_cistatic int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci struct ceph_parse_opts_ctx *pctx = fc->fs_private; 2428c2ecf20Sopenharmony_ci struct ceph_mount_options *fsopt = pctx->opts; 2438c2ecf20Sopenharmony_ci char *dev_name = param->string, *dev_name_end; 2448c2ecf20Sopenharmony_ci int ret; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci dout("%s '%s'\n", __func__, dev_name); 2478c2ecf20Sopenharmony_ci if (!dev_name || !*dev_name) 2488c2ecf20Sopenharmony_ci return invalfc(fc, "Empty source"); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci dev_name_end = strchr(dev_name, '/'); 2518c2ecf20Sopenharmony_ci if (dev_name_end) { 2528c2ecf20Sopenharmony_ci /* 2538c2ecf20Sopenharmony_ci * The server_path will include the whole chars from userland 2548c2ecf20Sopenharmony_ci * including the leading '/'. 2558c2ecf20Sopenharmony_ci */ 2568c2ecf20Sopenharmony_ci kfree(fsopt->server_path); 2578c2ecf20Sopenharmony_ci fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL); 2588c2ecf20Sopenharmony_ci if (!fsopt->server_path) 2598c2ecf20Sopenharmony_ci return -ENOMEM; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci canonicalize_path(fsopt->server_path); 2628c2ecf20Sopenharmony_ci } else { 2638c2ecf20Sopenharmony_ci dev_name_end = dev_name + strlen(dev_name); 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci dev_name_end--; /* back up to ':' separator */ 2678c2ecf20Sopenharmony_ci if (dev_name_end < dev_name || *dev_name_end != ':') 2688c2ecf20Sopenharmony_ci return invalfc(fc, "No path or : separator in source"); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci dout("device name '%.*s'\n", (int)(dev_name_end - dev_name), dev_name); 2718c2ecf20Sopenharmony_ci if (fsopt->server_path) 2728c2ecf20Sopenharmony_ci dout("server path '%s'\n", fsopt->server_path); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci ret = ceph_parse_mon_ips(param->string, dev_name_end - dev_name, 2758c2ecf20Sopenharmony_ci pctx->copts, fc->log.log); 2768c2ecf20Sopenharmony_ci if (ret) 2778c2ecf20Sopenharmony_ci return ret; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci fc->source = param->string; 2808c2ecf20Sopenharmony_ci param->string = NULL; 2818c2ecf20Sopenharmony_ci return 0; 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic int ceph_parse_mount_param(struct fs_context *fc, 2858c2ecf20Sopenharmony_ci struct fs_parameter *param) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci struct ceph_parse_opts_ctx *pctx = fc->fs_private; 2888c2ecf20Sopenharmony_ci struct ceph_mount_options *fsopt = pctx->opts; 2898c2ecf20Sopenharmony_ci struct fs_parse_result result; 2908c2ecf20Sopenharmony_ci unsigned int mode; 2918c2ecf20Sopenharmony_ci int token, ret; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci ret = ceph_parse_param(param, pctx->copts, fc->log.log); 2948c2ecf20Sopenharmony_ci if (ret != -ENOPARAM) 2958c2ecf20Sopenharmony_ci return ret; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci token = fs_parse(fc, ceph_mount_parameters, param, &result); 2988c2ecf20Sopenharmony_ci dout("%s fs_parse '%s' token %d\n", __func__, param->key, token); 2998c2ecf20Sopenharmony_ci if (token < 0) 3008c2ecf20Sopenharmony_ci return token; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci switch (token) { 3038c2ecf20Sopenharmony_ci case Opt_snapdirname: 3048c2ecf20Sopenharmony_ci kfree(fsopt->snapdir_name); 3058c2ecf20Sopenharmony_ci fsopt->snapdir_name = param->string; 3068c2ecf20Sopenharmony_ci param->string = NULL; 3078c2ecf20Sopenharmony_ci break; 3088c2ecf20Sopenharmony_ci case Opt_mds_namespace: 3098c2ecf20Sopenharmony_ci kfree(fsopt->mds_namespace); 3108c2ecf20Sopenharmony_ci fsopt->mds_namespace = param->string; 3118c2ecf20Sopenharmony_ci param->string = NULL; 3128c2ecf20Sopenharmony_ci break; 3138c2ecf20Sopenharmony_ci case Opt_recover_session: 3148c2ecf20Sopenharmony_ci mode = result.uint_32; 3158c2ecf20Sopenharmony_ci if (mode == ceph_recover_session_no) 3168c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_CLEANRECOVER; 3178c2ecf20Sopenharmony_ci else if (mode == ceph_recover_session_clean) 3188c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_CLEANRECOVER; 3198c2ecf20Sopenharmony_ci else 3208c2ecf20Sopenharmony_ci BUG(); 3218c2ecf20Sopenharmony_ci break; 3228c2ecf20Sopenharmony_ci case Opt_source: 3238c2ecf20Sopenharmony_ci if (fc->source) 3248c2ecf20Sopenharmony_ci return invalfc(fc, "Multiple sources specified"); 3258c2ecf20Sopenharmony_ci return ceph_parse_source(param, fc); 3268c2ecf20Sopenharmony_ci case Opt_wsize: 3278c2ecf20Sopenharmony_ci if (result.uint_32 < PAGE_SIZE || 3288c2ecf20Sopenharmony_ci result.uint_32 > CEPH_MAX_WRITE_SIZE) 3298c2ecf20Sopenharmony_ci goto out_of_range; 3308c2ecf20Sopenharmony_ci fsopt->wsize = ALIGN(result.uint_32, PAGE_SIZE); 3318c2ecf20Sopenharmony_ci break; 3328c2ecf20Sopenharmony_ci case Opt_rsize: 3338c2ecf20Sopenharmony_ci if (result.uint_32 < PAGE_SIZE || 3348c2ecf20Sopenharmony_ci result.uint_32 > CEPH_MAX_READ_SIZE) 3358c2ecf20Sopenharmony_ci goto out_of_range; 3368c2ecf20Sopenharmony_ci fsopt->rsize = ALIGN(result.uint_32, PAGE_SIZE); 3378c2ecf20Sopenharmony_ci break; 3388c2ecf20Sopenharmony_ci case Opt_rasize: 3398c2ecf20Sopenharmony_ci fsopt->rasize = ALIGN(result.uint_32, PAGE_SIZE); 3408c2ecf20Sopenharmony_ci break; 3418c2ecf20Sopenharmony_ci case Opt_caps_wanted_delay_min: 3428c2ecf20Sopenharmony_ci if (result.uint_32 < 1) 3438c2ecf20Sopenharmony_ci goto out_of_range; 3448c2ecf20Sopenharmony_ci fsopt->caps_wanted_delay_min = result.uint_32; 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci case Opt_caps_wanted_delay_max: 3478c2ecf20Sopenharmony_ci if (result.uint_32 < 1) 3488c2ecf20Sopenharmony_ci goto out_of_range; 3498c2ecf20Sopenharmony_ci fsopt->caps_wanted_delay_max = result.uint_32; 3508c2ecf20Sopenharmony_ci break; 3518c2ecf20Sopenharmony_ci case Opt_caps_max: 3528c2ecf20Sopenharmony_ci if (result.int_32 < 0) 3538c2ecf20Sopenharmony_ci goto out_of_range; 3548c2ecf20Sopenharmony_ci fsopt->caps_max = result.int_32; 3558c2ecf20Sopenharmony_ci break; 3568c2ecf20Sopenharmony_ci case Opt_readdir_max_entries: 3578c2ecf20Sopenharmony_ci if (result.uint_32 < 1) 3588c2ecf20Sopenharmony_ci goto out_of_range; 3598c2ecf20Sopenharmony_ci fsopt->max_readdir = result.uint_32; 3608c2ecf20Sopenharmony_ci break; 3618c2ecf20Sopenharmony_ci case Opt_readdir_max_bytes: 3628c2ecf20Sopenharmony_ci if (result.uint_32 < PAGE_SIZE && result.uint_32 != 0) 3638c2ecf20Sopenharmony_ci goto out_of_range; 3648c2ecf20Sopenharmony_ci fsopt->max_readdir_bytes = result.uint_32; 3658c2ecf20Sopenharmony_ci break; 3668c2ecf20Sopenharmony_ci case Opt_congestion_kb: 3678c2ecf20Sopenharmony_ci if (result.uint_32 < 1024) /* at least 1M */ 3688c2ecf20Sopenharmony_ci goto out_of_range; 3698c2ecf20Sopenharmony_ci fsopt->congestion_kb = result.uint_32; 3708c2ecf20Sopenharmony_ci break; 3718c2ecf20Sopenharmony_ci case Opt_dirstat: 3728c2ecf20Sopenharmony_ci if (!result.negated) 3738c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_DIRSTAT; 3748c2ecf20Sopenharmony_ci else 3758c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_DIRSTAT; 3768c2ecf20Sopenharmony_ci break; 3778c2ecf20Sopenharmony_ci case Opt_rbytes: 3788c2ecf20Sopenharmony_ci if (!result.negated) 3798c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_RBYTES; 3808c2ecf20Sopenharmony_ci else 3818c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_RBYTES; 3828c2ecf20Sopenharmony_ci break; 3838c2ecf20Sopenharmony_ci case Opt_asyncreaddir: 3848c2ecf20Sopenharmony_ci if (!result.negated) 3858c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_NOASYNCREADDIR; 3868c2ecf20Sopenharmony_ci else 3878c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR; 3888c2ecf20Sopenharmony_ci break; 3898c2ecf20Sopenharmony_ci case Opt_dcache: 3908c2ecf20Sopenharmony_ci if (!result.negated) 3918c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_DCACHE; 3928c2ecf20Sopenharmony_ci else 3938c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_DCACHE; 3948c2ecf20Sopenharmony_ci break; 3958c2ecf20Sopenharmony_ci case Opt_ino32: 3968c2ecf20Sopenharmony_ci if (!result.negated) 3978c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_INO32; 3988c2ecf20Sopenharmony_ci else 3998c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_INO32; 4008c2ecf20Sopenharmony_ci break; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci case Opt_fscache: 4038c2ecf20Sopenharmony_ci#ifdef CONFIG_CEPH_FSCACHE 4048c2ecf20Sopenharmony_ci kfree(fsopt->fscache_uniq); 4058c2ecf20Sopenharmony_ci fsopt->fscache_uniq = NULL; 4068c2ecf20Sopenharmony_ci if (result.negated) { 4078c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE; 4088c2ecf20Sopenharmony_ci } else { 4098c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_FSCACHE; 4108c2ecf20Sopenharmony_ci fsopt->fscache_uniq = param->string; 4118c2ecf20Sopenharmony_ci param->string = NULL; 4128c2ecf20Sopenharmony_ci } 4138c2ecf20Sopenharmony_ci break; 4148c2ecf20Sopenharmony_ci#else 4158c2ecf20Sopenharmony_ci return invalfc(fc, "fscache support is disabled"); 4168c2ecf20Sopenharmony_ci#endif 4178c2ecf20Sopenharmony_ci case Opt_poolperm: 4188c2ecf20Sopenharmony_ci if (!result.negated) 4198c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_NOPOOLPERM; 4208c2ecf20Sopenharmony_ci else 4218c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_NOPOOLPERM; 4228c2ecf20Sopenharmony_ci break; 4238c2ecf20Sopenharmony_ci case Opt_require_active_mds: 4248c2ecf20Sopenharmony_ci if (!result.negated) 4258c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_MOUNTWAIT; 4268c2ecf20Sopenharmony_ci else 4278c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_MOUNTWAIT; 4288c2ecf20Sopenharmony_ci break; 4298c2ecf20Sopenharmony_ci case Opt_quotadf: 4308c2ecf20Sopenharmony_ci if (!result.negated) 4318c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_NOQUOTADF; 4328c2ecf20Sopenharmony_ci else 4338c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_NOQUOTADF; 4348c2ecf20Sopenharmony_ci break; 4358c2ecf20Sopenharmony_ci case Opt_copyfrom: 4368c2ecf20Sopenharmony_ci if (!result.negated) 4378c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_NOCOPYFROM; 4388c2ecf20Sopenharmony_ci else 4398c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_NOCOPYFROM; 4408c2ecf20Sopenharmony_ci break; 4418c2ecf20Sopenharmony_ci case Opt_acl: 4428c2ecf20Sopenharmony_ci if (!result.negated) { 4438c2ecf20Sopenharmony_ci#ifdef CONFIG_CEPH_FS_POSIX_ACL 4448c2ecf20Sopenharmony_ci fc->sb_flags |= SB_POSIXACL; 4458c2ecf20Sopenharmony_ci#else 4468c2ecf20Sopenharmony_ci return invalfc(fc, "POSIX ACL support is disabled"); 4478c2ecf20Sopenharmony_ci#endif 4488c2ecf20Sopenharmony_ci } else { 4498c2ecf20Sopenharmony_ci fc->sb_flags &= ~SB_POSIXACL; 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci break; 4528c2ecf20Sopenharmony_ci case Opt_wsync: 4538c2ecf20Sopenharmony_ci if (!result.negated) 4548c2ecf20Sopenharmony_ci fsopt->flags &= ~CEPH_MOUNT_OPT_ASYNC_DIROPS; 4558c2ecf20Sopenharmony_ci else 4568c2ecf20Sopenharmony_ci fsopt->flags |= CEPH_MOUNT_OPT_ASYNC_DIROPS; 4578c2ecf20Sopenharmony_ci break; 4588c2ecf20Sopenharmony_ci default: 4598c2ecf20Sopenharmony_ci BUG(); 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci return 0; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ciout_of_range: 4648c2ecf20Sopenharmony_ci return invalfc(fc, "%s out of range", param->key); 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistatic void destroy_mount_options(struct ceph_mount_options *args) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci dout("destroy_mount_options %p\n", args); 4708c2ecf20Sopenharmony_ci if (!args) 4718c2ecf20Sopenharmony_ci return; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci kfree(args->snapdir_name); 4748c2ecf20Sopenharmony_ci kfree(args->mds_namespace); 4758c2ecf20Sopenharmony_ci kfree(args->server_path); 4768c2ecf20Sopenharmony_ci kfree(args->fscache_uniq); 4778c2ecf20Sopenharmony_ci kfree(args); 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistatic int strcmp_null(const char *s1, const char *s2) 4818c2ecf20Sopenharmony_ci{ 4828c2ecf20Sopenharmony_ci if (!s1 && !s2) 4838c2ecf20Sopenharmony_ci return 0; 4848c2ecf20Sopenharmony_ci if (s1 && !s2) 4858c2ecf20Sopenharmony_ci return -1; 4868c2ecf20Sopenharmony_ci if (!s1 && s2) 4878c2ecf20Sopenharmony_ci return 1; 4888c2ecf20Sopenharmony_ci return strcmp(s1, s2); 4898c2ecf20Sopenharmony_ci} 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_cistatic int compare_mount_options(struct ceph_mount_options *new_fsopt, 4928c2ecf20Sopenharmony_ci struct ceph_options *new_opt, 4938c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci struct ceph_mount_options *fsopt1 = new_fsopt; 4968c2ecf20Sopenharmony_ci struct ceph_mount_options *fsopt2 = fsc->mount_options; 4978c2ecf20Sopenharmony_ci int ofs = offsetof(struct ceph_mount_options, snapdir_name); 4988c2ecf20Sopenharmony_ci int ret; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci ret = memcmp(fsopt1, fsopt2, ofs); 5018c2ecf20Sopenharmony_ci if (ret) 5028c2ecf20Sopenharmony_ci return ret; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name); 5058c2ecf20Sopenharmony_ci if (ret) 5068c2ecf20Sopenharmony_ci return ret; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci ret = strcmp_null(fsopt1->mds_namespace, fsopt2->mds_namespace); 5098c2ecf20Sopenharmony_ci if (ret) 5108c2ecf20Sopenharmony_ci return ret; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci ret = strcmp_null(fsopt1->server_path, fsopt2->server_path); 5138c2ecf20Sopenharmony_ci if (ret) 5148c2ecf20Sopenharmony_ci return ret; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci ret = strcmp_null(fsopt1->fscache_uniq, fsopt2->fscache_uniq); 5178c2ecf20Sopenharmony_ci if (ret) 5188c2ecf20Sopenharmony_ci return ret; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci return ceph_compare_options(new_opt, fsc->client); 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci/** 5248c2ecf20Sopenharmony_ci * ceph_show_options - Show mount options in /proc/mounts 5258c2ecf20Sopenharmony_ci * @m: seq_file to write to 5268c2ecf20Sopenharmony_ci * @root: root of that (sub)tree 5278c2ecf20Sopenharmony_ci */ 5288c2ecf20Sopenharmony_cistatic int ceph_show_options(struct seq_file *m, struct dentry *root) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = ceph_sb_to_client(root->d_sb); 5318c2ecf20Sopenharmony_ci struct ceph_mount_options *fsopt = fsc->mount_options; 5328c2ecf20Sopenharmony_ci size_t pos; 5338c2ecf20Sopenharmony_ci int ret; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci /* a comma between MNT/MS and client options */ 5368c2ecf20Sopenharmony_ci seq_putc(m, ','); 5378c2ecf20Sopenharmony_ci pos = m->count; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci ret = ceph_print_client_options(m, fsc->client, false); 5408c2ecf20Sopenharmony_ci if (ret) 5418c2ecf20Sopenharmony_ci return ret; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* retract our comma if no client options */ 5448c2ecf20Sopenharmony_ci if (m->count == pos) 5458c2ecf20Sopenharmony_ci m->count--; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci if (fsopt->flags & CEPH_MOUNT_OPT_DIRSTAT) 5488c2ecf20Sopenharmony_ci seq_puts(m, ",dirstat"); 5498c2ecf20Sopenharmony_ci if ((fsopt->flags & CEPH_MOUNT_OPT_RBYTES)) 5508c2ecf20Sopenharmony_ci seq_puts(m, ",rbytes"); 5518c2ecf20Sopenharmony_ci if (fsopt->flags & CEPH_MOUNT_OPT_NOASYNCREADDIR) 5528c2ecf20Sopenharmony_ci seq_puts(m, ",noasyncreaddir"); 5538c2ecf20Sopenharmony_ci if ((fsopt->flags & CEPH_MOUNT_OPT_DCACHE) == 0) 5548c2ecf20Sopenharmony_ci seq_puts(m, ",nodcache"); 5558c2ecf20Sopenharmony_ci if (fsopt->flags & CEPH_MOUNT_OPT_INO32) 5568c2ecf20Sopenharmony_ci seq_puts(m, ",ino32"); 5578c2ecf20Sopenharmony_ci if (fsopt->flags & CEPH_MOUNT_OPT_FSCACHE) { 5588c2ecf20Sopenharmony_ci seq_show_option(m, "fsc", fsopt->fscache_uniq); 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci if (fsopt->flags & CEPH_MOUNT_OPT_NOPOOLPERM) 5618c2ecf20Sopenharmony_ci seq_puts(m, ",nopoolperm"); 5628c2ecf20Sopenharmony_ci if (fsopt->flags & CEPH_MOUNT_OPT_NOQUOTADF) 5638c2ecf20Sopenharmony_ci seq_puts(m, ",noquotadf"); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci#ifdef CONFIG_CEPH_FS_POSIX_ACL 5668c2ecf20Sopenharmony_ci if (root->d_sb->s_flags & SB_POSIXACL) 5678c2ecf20Sopenharmony_ci seq_puts(m, ",acl"); 5688c2ecf20Sopenharmony_ci else 5698c2ecf20Sopenharmony_ci seq_puts(m, ",noacl"); 5708c2ecf20Sopenharmony_ci#endif 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci if ((fsopt->flags & CEPH_MOUNT_OPT_NOCOPYFROM) == 0) 5738c2ecf20Sopenharmony_ci seq_puts(m, ",copyfrom"); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci if (fsopt->mds_namespace) 5768c2ecf20Sopenharmony_ci seq_show_option(m, "mds_namespace", fsopt->mds_namespace); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci if (fsopt->flags & CEPH_MOUNT_OPT_CLEANRECOVER) 5798c2ecf20Sopenharmony_ci seq_show_option(m, "recover_session", "clean"); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci if (fsopt->flags & CEPH_MOUNT_OPT_ASYNC_DIROPS) 5828c2ecf20Sopenharmony_ci seq_puts(m, ",nowsync"); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci if (fsopt->wsize != CEPH_MAX_WRITE_SIZE) 5858c2ecf20Sopenharmony_ci seq_printf(m, ",wsize=%u", fsopt->wsize); 5868c2ecf20Sopenharmony_ci if (fsopt->rsize != CEPH_MAX_READ_SIZE) 5878c2ecf20Sopenharmony_ci seq_printf(m, ",rsize=%u", fsopt->rsize); 5888c2ecf20Sopenharmony_ci if (fsopt->rasize != CEPH_RASIZE_DEFAULT) 5898c2ecf20Sopenharmony_ci seq_printf(m, ",rasize=%u", fsopt->rasize); 5908c2ecf20Sopenharmony_ci if (fsopt->congestion_kb != default_congestion_kb()) 5918c2ecf20Sopenharmony_ci seq_printf(m, ",write_congestion_kb=%u", fsopt->congestion_kb); 5928c2ecf20Sopenharmony_ci if (fsopt->caps_max) 5938c2ecf20Sopenharmony_ci seq_printf(m, ",caps_max=%d", fsopt->caps_max); 5948c2ecf20Sopenharmony_ci if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT) 5958c2ecf20Sopenharmony_ci seq_printf(m, ",caps_wanted_delay_min=%u", 5968c2ecf20Sopenharmony_ci fsopt->caps_wanted_delay_min); 5978c2ecf20Sopenharmony_ci if (fsopt->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT) 5988c2ecf20Sopenharmony_ci seq_printf(m, ",caps_wanted_delay_max=%u", 5998c2ecf20Sopenharmony_ci fsopt->caps_wanted_delay_max); 6008c2ecf20Sopenharmony_ci if (fsopt->max_readdir != CEPH_MAX_READDIR_DEFAULT) 6018c2ecf20Sopenharmony_ci seq_printf(m, ",readdir_max_entries=%u", fsopt->max_readdir); 6028c2ecf20Sopenharmony_ci if (fsopt->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT) 6038c2ecf20Sopenharmony_ci seq_printf(m, ",readdir_max_bytes=%u", fsopt->max_readdir_bytes); 6048c2ecf20Sopenharmony_ci if (strcmp(fsopt->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT)) 6058c2ecf20Sopenharmony_ci seq_show_option(m, "snapdirname", fsopt->snapdir_name); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci return 0; 6088c2ecf20Sopenharmony_ci} 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci/* 6118c2ecf20Sopenharmony_ci * handle any mon messages the standard library doesn't understand. 6128c2ecf20Sopenharmony_ci * return error if we don't either. 6138c2ecf20Sopenharmony_ci */ 6148c2ecf20Sopenharmony_cistatic int extra_mon_dispatch(struct ceph_client *client, struct ceph_msg *msg) 6158c2ecf20Sopenharmony_ci{ 6168c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = client->private; 6178c2ecf20Sopenharmony_ci int type = le16_to_cpu(msg->hdr.type); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci switch (type) { 6208c2ecf20Sopenharmony_ci case CEPH_MSG_MDS_MAP: 6218c2ecf20Sopenharmony_ci ceph_mdsc_handle_mdsmap(fsc->mdsc, msg); 6228c2ecf20Sopenharmony_ci return 0; 6238c2ecf20Sopenharmony_ci case CEPH_MSG_FS_MAP_USER: 6248c2ecf20Sopenharmony_ci ceph_mdsc_handle_fsmap(fsc->mdsc, msg); 6258c2ecf20Sopenharmony_ci return 0; 6268c2ecf20Sopenharmony_ci default: 6278c2ecf20Sopenharmony_ci return -1; 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci/* 6328c2ecf20Sopenharmony_ci * create a new fs client 6338c2ecf20Sopenharmony_ci * 6348c2ecf20Sopenharmony_ci * Success or not, this function consumes @fsopt and @opt. 6358c2ecf20Sopenharmony_ci */ 6368c2ecf20Sopenharmony_cistatic struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt, 6378c2ecf20Sopenharmony_ci struct ceph_options *opt) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc; 6408c2ecf20Sopenharmony_ci int err; 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci fsc = kzalloc(sizeof(*fsc), GFP_KERNEL); 6438c2ecf20Sopenharmony_ci if (!fsc) { 6448c2ecf20Sopenharmony_ci err = -ENOMEM; 6458c2ecf20Sopenharmony_ci goto fail; 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci fsc->client = ceph_create_client(opt, fsc); 6498c2ecf20Sopenharmony_ci if (IS_ERR(fsc->client)) { 6508c2ecf20Sopenharmony_ci err = PTR_ERR(fsc->client); 6518c2ecf20Sopenharmony_ci goto fail; 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci opt = NULL; /* fsc->client now owns this */ 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci fsc->client->extra_mon_dispatch = extra_mon_dispatch; 6568c2ecf20Sopenharmony_ci ceph_set_opt(fsc->client, ABORT_ON_FULL); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci if (!fsopt->mds_namespace) { 6598c2ecf20Sopenharmony_ci ceph_monc_want_map(&fsc->client->monc, CEPH_SUB_MDSMAP, 6608c2ecf20Sopenharmony_ci 0, true); 6618c2ecf20Sopenharmony_ci } else { 6628c2ecf20Sopenharmony_ci ceph_monc_want_map(&fsc->client->monc, CEPH_SUB_FSMAP, 6638c2ecf20Sopenharmony_ci 0, false); 6648c2ecf20Sopenharmony_ci } 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci fsc->mount_options = fsopt; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci fsc->sb = NULL; 6698c2ecf20Sopenharmony_ci fsc->mount_state = CEPH_MOUNT_MOUNTING; 6708c2ecf20Sopenharmony_ci fsc->filp_gen = 1; 6718c2ecf20Sopenharmony_ci fsc->have_copy_from2 = true; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci atomic_long_set(&fsc->writeback_count, 0); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci err = -ENOMEM; 6768c2ecf20Sopenharmony_ci /* 6778c2ecf20Sopenharmony_ci * The number of concurrent works can be high but they don't need 6788c2ecf20Sopenharmony_ci * to be processed in parallel, limit concurrency. 6798c2ecf20Sopenharmony_ci */ 6808c2ecf20Sopenharmony_ci fsc->inode_wq = alloc_workqueue("ceph-inode", WQ_UNBOUND, 0); 6818c2ecf20Sopenharmony_ci if (!fsc->inode_wq) 6828c2ecf20Sopenharmony_ci goto fail_client; 6838c2ecf20Sopenharmony_ci fsc->cap_wq = alloc_workqueue("ceph-cap", 0, 1); 6848c2ecf20Sopenharmony_ci if (!fsc->cap_wq) 6858c2ecf20Sopenharmony_ci goto fail_inode_wq; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci spin_lock(&ceph_fsc_lock); 6888c2ecf20Sopenharmony_ci list_add_tail(&fsc->metric_wakeup, &ceph_fsc_list); 6898c2ecf20Sopenharmony_ci spin_unlock(&ceph_fsc_lock); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci return fsc; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cifail_inode_wq: 6948c2ecf20Sopenharmony_ci destroy_workqueue(fsc->inode_wq); 6958c2ecf20Sopenharmony_cifail_client: 6968c2ecf20Sopenharmony_ci ceph_destroy_client(fsc->client); 6978c2ecf20Sopenharmony_cifail: 6988c2ecf20Sopenharmony_ci kfree(fsc); 6998c2ecf20Sopenharmony_ci if (opt) 7008c2ecf20Sopenharmony_ci ceph_destroy_options(opt); 7018c2ecf20Sopenharmony_ci destroy_mount_options(fsopt); 7028c2ecf20Sopenharmony_ci return ERR_PTR(err); 7038c2ecf20Sopenharmony_ci} 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_cistatic void flush_fs_workqueues(struct ceph_fs_client *fsc) 7068c2ecf20Sopenharmony_ci{ 7078c2ecf20Sopenharmony_ci flush_workqueue(fsc->inode_wq); 7088c2ecf20Sopenharmony_ci flush_workqueue(fsc->cap_wq); 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_cistatic void destroy_fs_client(struct ceph_fs_client *fsc) 7128c2ecf20Sopenharmony_ci{ 7138c2ecf20Sopenharmony_ci dout("destroy_fs_client %p\n", fsc); 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci spin_lock(&ceph_fsc_lock); 7168c2ecf20Sopenharmony_ci list_del(&fsc->metric_wakeup); 7178c2ecf20Sopenharmony_ci spin_unlock(&ceph_fsc_lock); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci ceph_mdsc_destroy(fsc); 7208c2ecf20Sopenharmony_ci destroy_workqueue(fsc->inode_wq); 7218c2ecf20Sopenharmony_ci destroy_workqueue(fsc->cap_wq); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci destroy_mount_options(fsc->mount_options); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci ceph_destroy_client(fsc->client); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci kfree(fsc); 7288c2ecf20Sopenharmony_ci dout("destroy_fs_client %p done\n", fsc); 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci/* 7328c2ecf20Sopenharmony_ci * caches 7338c2ecf20Sopenharmony_ci */ 7348c2ecf20Sopenharmony_cistruct kmem_cache *ceph_inode_cachep; 7358c2ecf20Sopenharmony_cistruct kmem_cache *ceph_cap_cachep; 7368c2ecf20Sopenharmony_cistruct kmem_cache *ceph_cap_flush_cachep; 7378c2ecf20Sopenharmony_cistruct kmem_cache *ceph_dentry_cachep; 7388c2ecf20Sopenharmony_cistruct kmem_cache *ceph_file_cachep; 7398c2ecf20Sopenharmony_cistruct kmem_cache *ceph_dir_file_cachep; 7408c2ecf20Sopenharmony_cistruct kmem_cache *ceph_mds_request_cachep; 7418c2ecf20Sopenharmony_cimempool_t *ceph_wb_pagevec_pool; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_cistatic void ceph_inode_init_once(void *foo) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci struct ceph_inode_info *ci = foo; 7468c2ecf20Sopenharmony_ci inode_init_once(&ci->vfs_inode); 7478c2ecf20Sopenharmony_ci} 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_cistatic int __init init_caches(void) 7508c2ecf20Sopenharmony_ci{ 7518c2ecf20Sopenharmony_ci int error = -ENOMEM; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci ceph_inode_cachep = kmem_cache_create("ceph_inode_info", 7548c2ecf20Sopenharmony_ci sizeof(struct ceph_inode_info), 7558c2ecf20Sopenharmony_ci __alignof__(struct ceph_inode_info), 7568c2ecf20Sopenharmony_ci SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD| 7578c2ecf20Sopenharmony_ci SLAB_ACCOUNT, ceph_inode_init_once); 7588c2ecf20Sopenharmony_ci if (!ceph_inode_cachep) 7598c2ecf20Sopenharmony_ci return -ENOMEM; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci ceph_cap_cachep = KMEM_CACHE(ceph_cap, SLAB_MEM_SPREAD); 7628c2ecf20Sopenharmony_ci if (!ceph_cap_cachep) 7638c2ecf20Sopenharmony_ci goto bad_cap; 7648c2ecf20Sopenharmony_ci ceph_cap_flush_cachep = KMEM_CACHE(ceph_cap_flush, 7658c2ecf20Sopenharmony_ci SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD); 7668c2ecf20Sopenharmony_ci if (!ceph_cap_flush_cachep) 7678c2ecf20Sopenharmony_ci goto bad_cap_flush; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci ceph_dentry_cachep = KMEM_CACHE(ceph_dentry_info, 7708c2ecf20Sopenharmony_ci SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD); 7718c2ecf20Sopenharmony_ci if (!ceph_dentry_cachep) 7728c2ecf20Sopenharmony_ci goto bad_dentry; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci ceph_file_cachep = KMEM_CACHE(ceph_file_info, SLAB_MEM_SPREAD); 7758c2ecf20Sopenharmony_ci if (!ceph_file_cachep) 7768c2ecf20Sopenharmony_ci goto bad_file; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci ceph_dir_file_cachep = KMEM_CACHE(ceph_dir_file_info, SLAB_MEM_SPREAD); 7798c2ecf20Sopenharmony_ci if (!ceph_dir_file_cachep) 7808c2ecf20Sopenharmony_ci goto bad_dir_file; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci ceph_mds_request_cachep = KMEM_CACHE(ceph_mds_request, SLAB_MEM_SPREAD); 7838c2ecf20Sopenharmony_ci if (!ceph_mds_request_cachep) 7848c2ecf20Sopenharmony_ci goto bad_mds_req; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci ceph_wb_pagevec_pool = mempool_create_kmalloc_pool(10, CEPH_MAX_WRITE_SIZE >> PAGE_SHIFT); 7878c2ecf20Sopenharmony_ci if (!ceph_wb_pagevec_pool) 7888c2ecf20Sopenharmony_ci goto bad_pagevec_pool; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci error = ceph_fscache_register(); 7918c2ecf20Sopenharmony_ci if (error) 7928c2ecf20Sopenharmony_ci goto bad_fscache; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci return 0; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_cibad_fscache: 7978c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_mds_request_cachep); 7988c2ecf20Sopenharmony_cibad_pagevec_pool: 7998c2ecf20Sopenharmony_ci mempool_destroy(ceph_wb_pagevec_pool); 8008c2ecf20Sopenharmony_cibad_mds_req: 8018c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_dir_file_cachep); 8028c2ecf20Sopenharmony_cibad_dir_file: 8038c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_file_cachep); 8048c2ecf20Sopenharmony_cibad_file: 8058c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_dentry_cachep); 8068c2ecf20Sopenharmony_cibad_dentry: 8078c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_cap_flush_cachep); 8088c2ecf20Sopenharmony_cibad_cap_flush: 8098c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_cap_cachep); 8108c2ecf20Sopenharmony_cibad_cap: 8118c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_inode_cachep); 8128c2ecf20Sopenharmony_ci return error; 8138c2ecf20Sopenharmony_ci} 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_cistatic void destroy_caches(void) 8168c2ecf20Sopenharmony_ci{ 8178c2ecf20Sopenharmony_ci /* 8188c2ecf20Sopenharmony_ci * Make sure all delayed rcu free inodes are flushed before we 8198c2ecf20Sopenharmony_ci * destroy cache. 8208c2ecf20Sopenharmony_ci */ 8218c2ecf20Sopenharmony_ci rcu_barrier(); 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_inode_cachep); 8248c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_cap_cachep); 8258c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_cap_flush_cachep); 8268c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_dentry_cachep); 8278c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_file_cachep); 8288c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_dir_file_cachep); 8298c2ecf20Sopenharmony_ci kmem_cache_destroy(ceph_mds_request_cachep); 8308c2ecf20Sopenharmony_ci mempool_destroy(ceph_wb_pagevec_pool); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci ceph_fscache_unregister(); 8338c2ecf20Sopenharmony_ci} 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci/* 8368c2ecf20Sopenharmony_ci * ceph_umount_begin - initiate forced umount. Tear down the 8378c2ecf20Sopenharmony_ci * mount, skipping steps that may hang while waiting for server(s). 8388c2ecf20Sopenharmony_ci */ 8398c2ecf20Sopenharmony_cistatic void ceph_umount_begin(struct super_block *sb) 8408c2ecf20Sopenharmony_ci{ 8418c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = ceph_sb_to_client(sb); 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci dout("ceph_umount_begin - starting forced umount\n"); 8448c2ecf20Sopenharmony_ci if (!fsc) 8458c2ecf20Sopenharmony_ci return; 8468c2ecf20Sopenharmony_ci fsc->mount_state = CEPH_MOUNT_SHUTDOWN; 8478c2ecf20Sopenharmony_ci ceph_osdc_abort_requests(&fsc->client->osdc, -EIO); 8488c2ecf20Sopenharmony_ci ceph_mdsc_force_umount(fsc->mdsc); 8498c2ecf20Sopenharmony_ci fsc->filp_gen++; // invalidate open files 8508c2ecf20Sopenharmony_ci} 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_cistatic const struct super_operations ceph_super_ops = { 8538c2ecf20Sopenharmony_ci .alloc_inode = ceph_alloc_inode, 8548c2ecf20Sopenharmony_ci .free_inode = ceph_free_inode, 8558c2ecf20Sopenharmony_ci .write_inode = ceph_write_inode, 8568c2ecf20Sopenharmony_ci .drop_inode = generic_delete_inode, 8578c2ecf20Sopenharmony_ci .evict_inode = ceph_evict_inode, 8588c2ecf20Sopenharmony_ci .sync_fs = ceph_sync_fs, 8598c2ecf20Sopenharmony_ci .put_super = ceph_put_super, 8608c2ecf20Sopenharmony_ci .show_options = ceph_show_options, 8618c2ecf20Sopenharmony_ci .statfs = ceph_statfs, 8628c2ecf20Sopenharmony_ci .umount_begin = ceph_umount_begin, 8638c2ecf20Sopenharmony_ci}; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci/* 8668c2ecf20Sopenharmony_ci * Bootstrap mount by opening the root directory. Note the mount 8678c2ecf20Sopenharmony_ci * @started time from caller, and time out if this takes too long. 8688c2ecf20Sopenharmony_ci */ 8698c2ecf20Sopenharmony_cistatic struct dentry *open_root_dentry(struct ceph_fs_client *fsc, 8708c2ecf20Sopenharmony_ci const char *path, 8718c2ecf20Sopenharmony_ci unsigned long started) 8728c2ecf20Sopenharmony_ci{ 8738c2ecf20Sopenharmony_ci struct ceph_mds_client *mdsc = fsc->mdsc; 8748c2ecf20Sopenharmony_ci struct ceph_mds_request *req = NULL; 8758c2ecf20Sopenharmony_ci int err; 8768c2ecf20Sopenharmony_ci struct dentry *root; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci /* open dir */ 8798c2ecf20Sopenharmony_ci dout("open_root_inode opening '%s'\n", path); 8808c2ecf20Sopenharmony_ci req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS); 8818c2ecf20Sopenharmony_ci if (IS_ERR(req)) 8828c2ecf20Sopenharmony_ci return ERR_CAST(req); 8838c2ecf20Sopenharmony_ci req->r_path1 = kstrdup(path, GFP_NOFS); 8848c2ecf20Sopenharmony_ci if (!req->r_path1) { 8858c2ecf20Sopenharmony_ci root = ERR_PTR(-ENOMEM); 8868c2ecf20Sopenharmony_ci goto out; 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci req->r_ino1.ino = CEPH_INO_ROOT; 8908c2ecf20Sopenharmony_ci req->r_ino1.snap = CEPH_NOSNAP; 8918c2ecf20Sopenharmony_ci req->r_started = started; 8928c2ecf20Sopenharmony_ci req->r_timeout = fsc->client->options->mount_timeout; 8938c2ecf20Sopenharmony_ci req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE); 8948c2ecf20Sopenharmony_ci req->r_num_caps = 2; 8958c2ecf20Sopenharmony_ci err = ceph_mdsc_do_request(mdsc, NULL, req); 8968c2ecf20Sopenharmony_ci if (err == 0) { 8978c2ecf20Sopenharmony_ci struct inode *inode = req->r_target_inode; 8988c2ecf20Sopenharmony_ci req->r_target_inode = NULL; 8998c2ecf20Sopenharmony_ci dout("open_root_inode success\n"); 9008c2ecf20Sopenharmony_ci root = d_make_root(inode); 9018c2ecf20Sopenharmony_ci if (!root) { 9028c2ecf20Sopenharmony_ci root = ERR_PTR(-ENOMEM); 9038c2ecf20Sopenharmony_ci goto out; 9048c2ecf20Sopenharmony_ci } 9058c2ecf20Sopenharmony_ci dout("open_root_inode success, root dentry is %p\n", root); 9068c2ecf20Sopenharmony_ci } else { 9078c2ecf20Sopenharmony_ci root = ERR_PTR(err); 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ciout: 9108c2ecf20Sopenharmony_ci ceph_mdsc_put_request(req); 9118c2ecf20Sopenharmony_ci return root; 9128c2ecf20Sopenharmony_ci} 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci/* 9158c2ecf20Sopenharmony_ci * mount: join the ceph cluster, and open root directory. 9168c2ecf20Sopenharmony_ci */ 9178c2ecf20Sopenharmony_cistatic struct dentry *ceph_real_mount(struct ceph_fs_client *fsc, 9188c2ecf20Sopenharmony_ci struct fs_context *fc) 9198c2ecf20Sopenharmony_ci{ 9208c2ecf20Sopenharmony_ci int err; 9218c2ecf20Sopenharmony_ci unsigned long started = jiffies; /* note the start time */ 9228c2ecf20Sopenharmony_ci struct dentry *root; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci dout("mount start %p\n", fsc); 9258c2ecf20Sopenharmony_ci mutex_lock(&fsc->client->mount_mutex); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci if (!fsc->sb->s_root) { 9288c2ecf20Sopenharmony_ci const char *path = fsc->mount_options->server_path ? 9298c2ecf20Sopenharmony_ci fsc->mount_options->server_path + 1 : ""; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci err = __ceph_open_session(fsc->client, started); 9328c2ecf20Sopenharmony_ci if (err < 0) 9338c2ecf20Sopenharmony_ci goto out; 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci /* setup fscache */ 9368c2ecf20Sopenharmony_ci if (fsc->mount_options->flags & CEPH_MOUNT_OPT_FSCACHE) { 9378c2ecf20Sopenharmony_ci err = ceph_fscache_register_fs(fsc, fc); 9388c2ecf20Sopenharmony_ci if (err < 0) 9398c2ecf20Sopenharmony_ci goto out; 9408c2ecf20Sopenharmony_ci } 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci dout("mount opening path '%s'\n", path); 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci ceph_fs_debugfs_init(fsc); 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci root = open_root_dentry(fsc, path, started); 9478c2ecf20Sopenharmony_ci if (IS_ERR(root)) { 9488c2ecf20Sopenharmony_ci err = PTR_ERR(root); 9498c2ecf20Sopenharmony_ci goto out; 9508c2ecf20Sopenharmony_ci } 9518c2ecf20Sopenharmony_ci fsc->sb->s_root = dget(root); 9528c2ecf20Sopenharmony_ci } else { 9538c2ecf20Sopenharmony_ci root = dget(fsc->sb->s_root); 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci fsc->mount_state = CEPH_MOUNT_MOUNTED; 9578c2ecf20Sopenharmony_ci dout("mount success\n"); 9588c2ecf20Sopenharmony_ci mutex_unlock(&fsc->client->mount_mutex); 9598c2ecf20Sopenharmony_ci return root; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ciout: 9628c2ecf20Sopenharmony_ci mutex_unlock(&fsc->client->mount_mutex); 9638c2ecf20Sopenharmony_ci return ERR_PTR(err); 9648c2ecf20Sopenharmony_ci} 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_cistatic int ceph_set_super(struct super_block *s, struct fs_context *fc) 9678c2ecf20Sopenharmony_ci{ 9688c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = s->s_fs_info; 9698c2ecf20Sopenharmony_ci int ret; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci dout("set_super %p\n", s); 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci s->s_maxbytes = MAX_LFS_FILESIZE; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci s->s_xattr = ceph_xattr_handlers; 9768c2ecf20Sopenharmony_ci fsc->sb = s; 9778c2ecf20Sopenharmony_ci fsc->max_file_size = 1ULL << 40; /* temp value until we get mdsmap */ 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci s->s_op = &ceph_super_ops; 9808c2ecf20Sopenharmony_ci s->s_d_op = &ceph_dentry_ops; 9818c2ecf20Sopenharmony_ci s->s_export_op = &ceph_export_ops; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci s->s_time_gran = 1; 9848c2ecf20Sopenharmony_ci s->s_time_min = 0; 9858c2ecf20Sopenharmony_ci s->s_time_max = U32_MAX; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci ret = set_anon_super_fc(s, fc); 9888c2ecf20Sopenharmony_ci if (ret != 0) 9898c2ecf20Sopenharmony_ci fsc->sb = NULL; 9908c2ecf20Sopenharmony_ci return ret; 9918c2ecf20Sopenharmony_ci} 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci/* 9948c2ecf20Sopenharmony_ci * share superblock if same fs AND options 9958c2ecf20Sopenharmony_ci */ 9968c2ecf20Sopenharmony_cistatic int ceph_compare_super(struct super_block *sb, struct fs_context *fc) 9978c2ecf20Sopenharmony_ci{ 9988c2ecf20Sopenharmony_ci struct ceph_fs_client *new = fc->s_fs_info; 9998c2ecf20Sopenharmony_ci struct ceph_mount_options *fsopt = new->mount_options; 10008c2ecf20Sopenharmony_ci struct ceph_options *opt = new->client->options; 10018c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = ceph_sb_to_client(sb); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci dout("ceph_compare_super %p\n", sb); 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci if (compare_mount_options(fsopt, opt, fsc)) { 10068c2ecf20Sopenharmony_ci dout("monitor(s)/mount options don't match\n"); 10078c2ecf20Sopenharmony_ci return 0; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci if ((opt->flags & CEPH_OPT_FSID) && 10108c2ecf20Sopenharmony_ci ceph_fsid_compare(&opt->fsid, &fsc->client->fsid)) { 10118c2ecf20Sopenharmony_ci dout("fsid doesn't match\n"); 10128c2ecf20Sopenharmony_ci return 0; 10138c2ecf20Sopenharmony_ci } 10148c2ecf20Sopenharmony_ci if (fc->sb_flags != (sb->s_flags & ~SB_BORN)) { 10158c2ecf20Sopenharmony_ci dout("flags differ\n"); 10168c2ecf20Sopenharmony_ci return 0; 10178c2ecf20Sopenharmony_ci } 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci if (fsc->blocklisted && !ceph_test_mount_opt(fsc, CLEANRECOVER)) { 10208c2ecf20Sopenharmony_ci dout("client is blocklisted (and CLEANRECOVER is not set)\n"); 10218c2ecf20Sopenharmony_ci return 0; 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) { 10258c2ecf20Sopenharmony_ci dout("client has been forcibly unmounted\n"); 10268c2ecf20Sopenharmony_ci return 0; 10278c2ecf20Sopenharmony_ci } 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci return 1; 10308c2ecf20Sopenharmony_ci} 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci/* 10338c2ecf20Sopenharmony_ci * construct our own bdi so we can control readahead, etc. 10348c2ecf20Sopenharmony_ci */ 10358c2ecf20Sopenharmony_cistatic atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_cistatic int ceph_setup_bdi(struct super_block *sb, struct ceph_fs_client *fsc) 10388c2ecf20Sopenharmony_ci{ 10398c2ecf20Sopenharmony_ci int err; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci err = super_setup_bdi_name(sb, "ceph-%ld", 10428c2ecf20Sopenharmony_ci atomic_long_inc_return(&bdi_seq)); 10438c2ecf20Sopenharmony_ci if (err) 10448c2ecf20Sopenharmony_ci return err; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci /* set ra_pages based on rasize mount option? */ 10478c2ecf20Sopenharmony_ci sb->s_bdi->ra_pages = fsc->mount_options->rasize >> PAGE_SHIFT; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci /* set io_pages based on max osd read size */ 10508c2ecf20Sopenharmony_ci sb->s_bdi->io_pages = fsc->mount_options->rsize >> PAGE_SHIFT; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci return 0; 10538c2ecf20Sopenharmony_ci} 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_cistatic int ceph_get_tree(struct fs_context *fc) 10568c2ecf20Sopenharmony_ci{ 10578c2ecf20Sopenharmony_ci struct ceph_parse_opts_ctx *pctx = fc->fs_private; 10588c2ecf20Sopenharmony_ci struct super_block *sb; 10598c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc; 10608c2ecf20Sopenharmony_ci struct dentry *res; 10618c2ecf20Sopenharmony_ci int (*compare_super)(struct super_block *, struct fs_context *) = 10628c2ecf20Sopenharmony_ci ceph_compare_super; 10638c2ecf20Sopenharmony_ci int err; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci dout("ceph_get_tree\n"); 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci if (!fc->source) 10688c2ecf20Sopenharmony_ci return invalfc(fc, "No source"); 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci /* create client (which we may/may not use) */ 10718c2ecf20Sopenharmony_ci fsc = create_fs_client(pctx->opts, pctx->copts); 10728c2ecf20Sopenharmony_ci pctx->opts = NULL; 10738c2ecf20Sopenharmony_ci pctx->copts = NULL; 10748c2ecf20Sopenharmony_ci if (IS_ERR(fsc)) { 10758c2ecf20Sopenharmony_ci err = PTR_ERR(fsc); 10768c2ecf20Sopenharmony_ci goto out_final; 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci err = ceph_mdsc_init(fsc); 10808c2ecf20Sopenharmony_ci if (err < 0) 10818c2ecf20Sopenharmony_ci goto out; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (ceph_test_opt(fsc->client, NOSHARE)) 10848c2ecf20Sopenharmony_ci compare_super = NULL; 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci fc->s_fs_info = fsc; 10878c2ecf20Sopenharmony_ci sb = sget_fc(fc, compare_super, ceph_set_super); 10888c2ecf20Sopenharmony_ci fc->s_fs_info = NULL; 10898c2ecf20Sopenharmony_ci if (IS_ERR(sb)) { 10908c2ecf20Sopenharmony_ci err = PTR_ERR(sb); 10918c2ecf20Sopenharmony_ci goto out; 10928c2ecf20Sopenharmony_ci } 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci if (ceph_sb_to_client(sb) != fsc) { 10958c2ecf20Sopenharmony_ci destroy_fs_client(fsc); 10968c2ecf20Sopenharmony_ci fsc = ceph_sb_to_client(sb); 10978c2ecf20Sopenharmony_ci dout("get_sb got existing client %p\n", fsc); 10988c2ecf20Sopenharmony_ci } else { 10998c2ecf20Sopenharmony_ci dout("get_sb using new client %p\n", fsc); 11008c2ecf20Sopenharmony_ci err = ceph_setup_bdi(sb, fsc); 11018c2ecf20Sopenharmony_ci if (err < 0) 11028c2ecf20Sopenharmony_ci goto out_splat; 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci res = ceph_real_mount(fsc, fc); 11068c2ecf20Sopenharmony_ci if (IS_ERR(res)) { 11078c2ecf20Sopenharmony_ci err = PTR_ERR(res); 11088c2ecf20Sopenharmony_ci goto out_splat; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci dout("root %p inode %p ino %llx.%llx\n", res, 11118c2ecf20Sopenharmony_ci d_inode(res), ceph_vinop(d_inode(res))); 11128c2ecf20Sopenharmony_ci fc->root = fsc->sb->s_root; 11138c2ecf20Sopenharmony_ci return 0; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ciout_splat: 11168c2ecf20Sopenharmony_ci if (!ceph_mdsmap_is_cluster_available(fsc->mdsc->mdsmap)) { 11178c2ecf20Sopenharmony_ci pr_info("No mds server is up or the cluster is laggy\n"); 11188c2ecf20Sopenharmony_ci err = -EHOSTUNREACH; 11198c2ecf20Sopenharmony_ci } 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci ceph_mdsc_close_sessions(fsc->mdsc); 11228c2ecf20Sopenharmony_ci deactivate_locked_super(sb); 11238c2ecf20Sopenharmony_ci goto out_final; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ciout: 11268c2ecf20Sopenharmony_ci destroy_fs_client(fsc); 11278c2ecf20Sopenharmony_ciout_final: 11288c2ecf20Sopenharmony_ci dout("ceph_get_tree fail %d\n", err); 11298c2ecf20Sopenharmony_ci return err; 11308c2ecf20Sopenharmony_ci} 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_cistatic void ceph_free_fc(struct fs_context *fc) 11338c2ecf20Sopenharmony_ci{ 11348c2ecf20Sopenharmony_ci struct ceph_parse_opts_ctx *pctx = fc->fs_private; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (pctx) { 11378c2ecf20Sopenharmony_ci destroy_mount_options(pctx->opts); 11388c2ecf20Sopenharmony_ci ceph_destroy_options(pctx->copts); 11398c2ecf20Sopenharmony_ci kfree(pctx); 11408c2ecf20Sopenharmony_ci } 11418c2ecf20Sopenharmony_ci} 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_cistatic int ceph_reconfigure_fc(struct fs_context *fc) 11448c2ecf20Sopenharmony_ci{ 11458c2ecf20Sopenharmony_ci struct ceph_parse_opts_ctx *pctx = fc->fs_private; 11468c2ecf20Sopenharmony_ci struct ceph_mount_options *fsopt = pctx->opts; 11478c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = ceph_sb_to_client(fc->root->d_sb); 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci if (fsopt->flags & CEPH_MOUNT_OPT_ASYNC_DIROPS) 11508c2ecf20Sopenharmony_ci ceph_set_mount_opt(fsc, ASYNC_DIROPS); 11518c2ecf20Sopenharmony_ci else 11528c2ecf20Sopenharmony_ci ceph_clear_mount_opt(fsc, ASYNC_DIROPS); 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci sync_filesystem(fc->root->d_sb); 11558c2ecf20Sopenharmony_ci return 0; 11568c2ecf20Sopenharmony_ci} 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_cistatic const struct fs_context_operations ceph_context_ops = { 11598c2ecf20Sopenharmony_ci .free = ceph_free_fc, 11608c2ecf20Sopenharmony_ci .parse_param = ceph_parse_mount_param, 11618c2ecf20Sopenharmony_ci .get_tree = ceph_get_tree, 11628c2ecf20Sopenharmony_ci .reconfigure = ceph_reconfigure_fc, 11638c2ecf20Sopenharmony_ci}; 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci/* 11668c2ecf20Sopenharmony_ci * Set up the filesystem mount context. 11678c2ecf20Sopenharmony_ci */ 11688c2ecf20Sopenharmony_cistatic int ceph_init_fs_context(struct fs_context *fc) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci struct ceph_parse_opts_ctx *pctx; 11718c2ecf20Sopenharmony_ci struct ceph_mount_options *fsopt; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci pctx = kzalloc(sizeof(*pctx), GFP_KERNEL); 11748c2ecf20Sopenharmony_ci if (!pctx) 11758c2ecf20Sopenharmony_ci return -ENOMEM; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci pctx->copts = ceph_alloc_options(); 11788c2ecf20Sopenharmony_ci if (!pctx->copts) 11798c2ecf20Sopenharmony_ci goto nomem; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci pctx->opts = kzalloc(sizeof(*pctx->opts), GFP_KERNEL); 11828c2ecf20Sopenharmony_ci if (!pctx->opts) 11838c2ecf20Sopenharmony_ci goto nomem; 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci fsopt = pctx->opts; 11868c2ecf20Sopenharmony_ci fsopt->flags = CEPH_MOUNT_OPT_DEFAULT; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci fsopt->wsize = CEPH_MAX_WRITE_SIZE; 11898c2ecf20Sopenharmony_ci fsopt->rsize = CEPH_MAX_READ_SIZE; 11908c2ecf20Sopenharmony_ci fsopt->rasize = CEPH_RASIZE_DEFAULT; 11918c2ecf20Sopenharmony_ci fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL); 11928c2ecf20Sopenharmony_ci if (!fsopt->snapdir_name) 11938c2ecf20Sopenharmony_ci goto nomem; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci fsopt->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT; 11968c2ecf20Sopenharmony_ci fsopt->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT; 11978c2ecf20Sopenharmony_ci fsopt->max_readdir = CEPH_MAX_READDIR_DEFAULT; 11988c2ecf20Sopenharmony_ci fsopt->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT; 11998c2ecf20Sopenharmony_ci fsopt->congestion_kb = default_congestion_kb(); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci#ifdef CONFIG_CEPH_FS_POSIX_ACL 12028c2ecf20Sopenharmony_ci fc->sb_flags |= SB_POSIXACL; 12038c2ecf20Sopenharmony_ci#endif 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci fc->fs_private = pctx; 12068c2ecf20Sopenharmony_ci fc->ops = &ceph_context_ops; 12078c2ecf20Sopenharmony_ci return 0; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_cinomem: 12108c2ecf20Sopenharmony_ci destroy_mount_options(pctx->opts); 12118c2ecf20Sopenharmony_ci ceph_destroy_options(pctx->copts); 12128c2ecf20Sopenharmony_ci kfree(pctx); 12138c2ecf20Sopenharmony_ci return -ENOMEM; 12148c2ecf20Sopenharmony_ci} 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_cistatic void ceph_kill_sb(struct super_block *s) 12178c2ecf20Sopenharmony_ci{ 12188c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = ceph_sb_to_client(s); 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci dout("kill_sb %p\n", s); 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci ceph_mdsc_pre_umount(fsc->mdsc); 12238c2ecf20Sopenharmony_ci flush_fs_workqueues(fsc); 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci /* 12268c2ecf20Sopenharmony_ci * Though the kill_anon_super() will finally trigger the 12278c2ecf20Sopenharmony_ci * sync_filesystem() anyway, we still need to do it here 12288c2ecf20Sopenharmony_ci * and then bump the stage of shutdown to stop the work 12298c2ecf20Sopenharmony_ci * queue as earlier as possible. 12308c2ecf20Sopenharmony_ci */ 12318c2ecf20Sopenharmony_ci sync_filesystem(s); 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci fsc->mdsc->stopping = CEPH_MDSC_STOPPING_FLUSHED; 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci kill_anon_super(s); 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci fsc->client->extra_mon_dispatch = NULL; 12388c2ecf20Sopenharmony_ci ceph_fs_debugfs_cleanup(fsc); 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci ceph_fscache_unregister_fs(fsc); 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci destroy_fs_client(fsc); 12438c2ecf20Sopenharmony_ci} 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_cistatic struct file_system_type ceph_fs_type = { 12468c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 12478c2ecf20Sopenharmony_ci .name = "ceph", 12488c2ecf20Sopenharmony_ci .init_fs_context = ceph_init_fs_context, 12498c2ecf20Sopenharmony_ci .kill_sb = ceph_kill_sb, 12508c2ecf20Sopenharmony_ci .fs_flags = FS_RENAME_DOES_D_MOVE, 12518c2ecf20Sopenharmony_ci}; 12528c2ecf20Sopenharmony_ciMODULE_ALIAS_FS("ceph"); 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ciint ceph_force_reconnect(struct super_block *sb) 12558c2ecf20Sopenharmony_ci{ 12568c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc = ceph_sb_to_client(sb); 12578c2ecf20Sopenharmony_ci int err = 0; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci ceph_umount_begin(sb); 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci /* Make sure all page caches get invalidated. 12628c2ecf20Sopenharmony_ci * see remove_session_caps_cb() */ 12638c2ecf20Sopenharmony_ci flush_workqueue(fsc->inode_wq); 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci /* In case that we were blocklisted. This also reset 12668c2ecf20Sopenharmony_ci * all mon/osd connections */ 12678c2ecf20Sopenharmony_ci ceph_reset_client_addr(fsc->client); 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci ceph_osdc_clear_abort_err(&fsc->client->osdc); 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci fsc->blocklisted = false; 12728c2ecf20Sopenharmony_ci fsc->mount_state = CEPH_MOUNT_MOUNTED; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci if (sb->s_root) { 12758c2ecf20Sopenharmony_ci err = __ceph_do_getattr(d_inode(sb->s_root), NULL, 12768c2ecf20Sopenharmony_ci CEPH_STAT_CAP_INODE, true); 12778c2ecf20Sopenharmony_ci } 12788c2ecf20Sopenharmony_ci return err; 12798c2ecf20Sopenharmony_ci} 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_cistatic int __init init_ceph(void) 12828c2ecf20Sopenharmony_ci{ 12838c2ecf20Sopenharmony_ci int ret = init_caches(); 12848c2ecf20Sopenharmony_ci if (ret) 12858c2ecf20Sopenharmony_ci goto out; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci ceph_flock_init(); 12888c2ecf20Sopenharmony_ci ret = register_filesystem(&ceph_fs_type); 12898c2ecf20Sopenharmony_ci if (ret) 12908c2ecf20Sopenharmony_ci goto out_caches; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci pr_info("loaded (mds proto %d)\n", CEPH_MDSC_PROTOCOL); 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci return 0; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ciout_caches: 12978c2ecf20Sopenharmony_ci destroy_caches(); 12988c2ecf20Sopenharmony_ciout: 12998c2ecf20Sopenharmony_ci return ret; 13008c2ecf20Sopenharmony_ci} 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_cistatic void __exit exit_ceph(void) 13038c2ecf20Sopenharmony_ci{ 13048c2ecf20Sopenharmony_ci dout("exit_ceph\n"); 13058c2ecf20Sopenharmony_ci unregister_filesystem(&ceph_fs_type); 13068c2ecf20Sopenharmony_ci destroy_caches(); 13078c2ecf20Sopenharmony_ci} 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_cistatic int param_set_metrics(const char *val, const struct kernel_param *kp) 13108c2ecf20Sopenharmony_ci{ 13118c2ecf20Sopenharmony_ci struct ceph_fs_client *fsc; 13128c2ecf20Sopenharmony_ci int ret; 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci ret = param_set_bool(val, kp); 13158c2ecf20Sopenharmony_ci if (ret) { 13168c2ecf20Sopenharmony_ci pr_err("Failed to parse sending metrics switch value '%s'\n", 13178c2ecf20Sopenharmony_ci val); 13188c2ecf20Sopenharmony_ci return ret; 13198c2ecf20Sopenharmony_ci } else if (!disable_send_metrics) { 13208c2ecf20Sopenharmony_ci // wake up all the mds clients 13218c2ecf20Sopenharmony_ci spin_lock(&ceph_fsc_lock); 13228c2ecf20Sopenharmony_ci list_for_each_entry(fsc, &ceph_fsc_list, metric_wakeup) { 13238c2ecf20Sopenharmony_ci metric_schedule_delayed(&fsc->mdsc->metric); 13248c2ecf20Sopenharmony_ci } 13258c2ecf20Sopenharmony_ci spin_unlock(&ceph_fsc_lock); 13268c2ecf20Sopenharmony_ci } 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci return 0; 13298c2ecf20Sopenharmony_ci} 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_cistatic const struct kernel_param_ops param_ops_metrics = { 13328c2ecf20Sopenharmony_ci .set = param_set_metrics, 13338c2ecf20Sopenharmony_ci .get = param_get_bool, 13348c2ecf20Sopenharmony_ci}; 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_cibool disable_send_metrics = false; 13378c2ecf20Sopenharmony_cimodule_param_cb(disable_send_metrics, ¶m_ops_metrics, &disable_send_metrics, 0644); 13388c2ecf20Sopenharmony_ciMODULE_PARM_DESC(disable_send_metrics, "Enable sending perf metrics to ceph cluster (default: on)"); 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_cimodule_init(init_ceph); 13418c2ecf20Sopenharmony_cimodule_exit(exit_ceph); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ciMODULE_AUTHOR("Sage Weil <sage@newdream.net>"); 13448c2ecf20Sopenharmony_ciMODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>"); 13458c2ecf20Sopenharmony_ciMODULE_AUTHOR("Patience Warnick <patience@newdream.net>"); 13468c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Ceph filesystem for Linux"); 13478c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1348