X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Fllite_lib.c;h=ad377fe378ca7016594a81d9a89327db88d1e7e8;hp=10fef55c7dcf65921a46aa954295dc7b7d357d5c;hb=04c172b686763be0d42eb4c36532d5795166eb7c;hpb=ca41d88d9228e469a8728c20c21c7e919b77dc12 diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 10fef55..ad377fe 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -23,7 +23,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2016, Intel Corporation. + * Copyright (c) 2011, 2017, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -48,12 +48,12 @@ #endif #include -#include +#include #include #include #include #include -#include +#include #include #include #include @@ -99,8 +99,7 @@ static struct ll_sb_info *ll_init_sbi(void) sbi->ll_ra_info.ra_max_pages_per_file = min(pages / 32, SBI_DEFAULT_READAHEAD_MAX); sbi->ll_ra_info.ra_max_pages = sbi->ll_ra_info.ra_max_pages_per_file; - sbi->ll_ra_info.ra_max_read_ahead_whole_pages = - SBI_DEFAULT_READAHEAD_WHOLE_MAX; + sbi->ll_ra_info.ra_max_read_ahead_whole_pages = -1; ll_generate_random_uuid(uuid); class_uuid_unparse(uuid, &sbi->ll_sb_uuid); @@ -124,6 +123,7 @@ static struct ll_sb_info *ll_init_sbi(void) } /* metadata statahead is enabled by default */ + sbi->ll_sa_running_max = LL_SA_RUNNING_DEF; sbi->ll_sa_max = LL_SA_RPC_DEF; atomic_set(&sbi->ll_sa_total, 0); atomic_set(&sbi->ll_sa_wrong, 0); @@ -131,6 +131,7 @@ static struct ll_sb_info *ll_init_sbi(void) atomic_set(&sbi->ll_agl_total, 0); sbi->ll_flags |= LL_SBI_AGL_ENABLED; sbi->ll_flags |= LL_SBI_FAST_READ; + sbi->ll_flags |= LL_SBI_TINY_WRITE; /* root squash */ sbi->ll_squash.rsi_uid = 0; @@ -158,30 +159,23 @@ static void ll_free_sbi(struct super_block *sb) EXIT; } -static inline int obd_connect_has_secctx(struct obd_connect_data *data) -{ - return data->ocd_connect_flags & OBD_CONNECT_FLAGS2 && - data->ocd_connect_flags2 & OBD_CONNECT2_FILE_SECCTX; -} - static int client_common_fill_super(struct super_block *sb, char *md, char *dt, struct vfsmount *mnt) { struct inode *root = NULL; - struct ll_sb_info *sbi = ll_s2sbi(sb); - struct obd_device *obd; - struct obd_statfs *osfs = NULL; - struct ptlrpc_request *request = NULL; - struct obd_connect_data *data = NULL; - struct obd_uuid *uuid; - struct md_op_data *op_data; - struct lustre_md lmd; + struct ll_sb_info *sbi = ll_s2sbi(sb); + struct obd_statfs *osfs = NULL; + struct ptlrpc_request *request = NULL; + struct obd_connect_data *data = NULL; + struct obd_uuid *uuid; + struct md_op_data *op_data; + struct lustre_md lmd; u64 valid; - int size, err, checksum; - ENTRY; + int size, err, checksum; - obd = class_name2obd(md); - if (!obd) { + ENTRY; + sbi->ll_md_obd = class_name2obd(md); + if (!sbi->ll_md_obd) { CERROR("MD %s: not setup or attached\n", md); RETURN(-EINVAL); } @@ -196,13 +190,18 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, RETURN(-ENOMEM); } - /* indicate the features supported by this client */ - data->ocd_connect_flags = OBD_CONNECT_IBITS | OBD_CONNECT_NODEVOH | - OBD_CONNECT_ATTRFID | - OBD_CONNECT_VERSION | OBD_CONNECT_BRW_SIZE | - OBD_CONNECT_MDS_CAPA | OBD_CONNECT_OSS_CAPA | - OBD_CONNECT_CANCELSET | OBD_CONNECT_FID | - OBD_CONNECT_AT | OBD_CONNECT_LOV_V3 | + /* pass client page size via ocd_grant_blkbits, the server should report + * back its backend blocksize for grant calculation purpose */ + data->ocd_grant_blkbits = PAGE_SHIFT; + + /* indicate MDT features supported by this client */ + data->ocd_connect_flags = OBD_CONNECT_IBITS | OBD_CONNECT_NODEVOH | + OBD_CONNECT_ATTRFID | OBD_CONNECT_GRANT | + OBD_CONNECT_VERSION | OBD_CONNECT_BRW_SIZE | + OBD_CONNECT_SRVLOCK | OBD_CONNECT_TRUNCLOCK| + OBD_CONNECT_MDS_CAPA | OBD_CONNECT_OSS_CAPA | + OBD_CONNECT_CANCELSET | OBD_CONNECT_FID | + OBD_CONNECT_AT | OBD_CONNECT_LOV_V3 | OBD_CONNECT_VBR | OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH | OBD_CONNECT_EINPROGRESS | @@ -213,11 +212,16 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK | OBD_CONNECT_OPEN_BY_FID | OBD_CONNECT_DIR_STRIPE | - OBD_CONNECT_BULK_MBITS | + OBD_CONNECT_BULK_MBITS | OBD_CONNECT_CKSUM | OBD_CONNECT_SUBTREE | - OBD_CONNECT_FLAGS2 | OBD_CONNECT_MULTIMODRPCS; + OBD_CONNECT_MULTIMODRPCS | + OBD_CONNECT_GRANT_PARAM | + OBD_CONNECT_SHORTIO | OBD_CONNECT_FLAGS2; - data->ocd_connect_flags2 = 0; + data->ocd_connect_flags2 = OBD_CONNECT2_FLR | + OBD_CONNECT2_LOCK_CONVERT | + OBD_CONNECT2_DIR_MIGRATE | + OBD_CONNECT2_SUM_STATFS; #ifdef HAVE_LRU_RESIZE_SUPPORT if (sbi->ll_flags & LL_SBI_LRU_RESIZE) @@ -228,6 +232,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_LARGE_ACL; #endif + data->ocd_cksum_types = obd_cksum_types_supported_client(); + if (OBD_FAIL_CHECK(OBD_FAIL_MDC_LIGHTWEIGHT)) /* flag mdc connection as lightweight, only used for test * purpose, use with care */ @@ -259,13 +265,12 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (sbi->ll_flags & LL_SBI_ALWAYS_PING) data->ocd_connect_flags &= ~OBD_CONNECT_PINGLESS; -#ifdef HAVE_SECURITY_DENTRY_INIT_SECURITY - data->ocd_connect_flags2 |= OBD_CONNECT2_FILE_SECCTX; -#endif /* HAVE_SECURITY_DENTRY_INIT_SECURITY */ + obd_connect_set_secctx(data); data->ocd_brw_size = MD_MAX_BRW_SIZE; - err = obd_connect(NULL, &sbi->ll_md_exp, obd, &sbi->ll_sb_uuid, data, NULL); + err = obd_connect(NULL, &sbi->ll_md_exp, sbi->ll_md_obd, + &sbi->ll_sb_uuid, data, NULL); if (err == -EBUSY) { LCONSOLE_ERROR_MSG(0x14f, "An MDT (md %s) is performing " "recovery, of which this client is not a " @@ -291,7 +296,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, * can make sure the client can be mounted as long as MDT0 is * avaible */ err = obd_statfs(NULL, sbi->ll_md_exp, osfs, - cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), + ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS, OBD_STATFS_FOR_MDT0); if (err) GOTO(out_md_fid, err); @@ -378,8 +383,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, } } - obd = class_name2obd(dt); - if (!obd) { + sbi->ll_dt_obd = class_name2obd(dt); + if (!sbi->ll_dt_obd) { CERROR("DT %s: not setup or attached\n", dt); GOTO(out_md_fid, err = -ENODEV); } @@ -388,6 +393,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, * back its backend blocksize for grant calculation purpose */ data->ocd_grant_blkbits = PAGE_SHIFT; + /* indicate OST features supported by this client */ data->ocd_connect_flags = OBD_CONNECT_GRANT | OBD_CONNECT_VERSION | OBD_CONNECT_REQPORTAL | OBD_CONNECT_BRW_SIZE | OBD_CONNECT_CANCELSET | OBD_CONNECT_FID | @@ -399,23 +405,41 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS | OBD_CONNECT_LFSCK | - OBD_CONNECT_BULK_MBITS; + OBD_CONNECT_BULK_MBITS | OBD_CONNECT_SHORTIO | + OBD_CONNECT_FLAGS2 | OBD_CONNECT_GRANT_SHRINK; + +/* The client currently advertises support for OBD_CONNECT_LOCKAHEAD_OLD so it + * can interoperate with an older version of lockahead which was released prior + * to landing in master. This support will be dropped when 2.13 development + * starts. At the point, we should not just drop the connect flag (below), we + * should also remove the support in the code. + * + * Removing it means a few things: + * 1. Remove this section here + * 2. Remove CEF_NONBLOCK in ll_file_lockahead() + * 3. Remove function exp_connect_lockahead_old + * 4. Remove LDLM_FL_LOCKAHEAD_OLD_RESERVED in lustre_dlm_flags.h + * */ +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 12, 50, 0) + data->ocd_connect_flags |= OBD_CONNECT_LOCKAHEAD_OLD; +#endif - data->ocd_connect_flags2 = 0; + data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD; if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_GRANT_PARAM)) data->ocd_connect_flags |= OBD_CONNECT_GRANT_PARAM; /* OBD_CONNECT_CKSUM should always be set, even if checksums are * disabled by default, because it can still be enabled on the - * fly via /proc. As a consequence, we still need to come to an - * agreement on the supported algorithms at connect time */ + * fly via /sys. As a consequence, we still need to come to an + * agreement on the supported algorithms at connect time + */ data->ocd_connect_flags |= OBD_CONNECT_CKSUM; if (OBD_FAIL_CHECK(OBD_FAIL_OSC_CKSUM_ADLER_ONLY)) data->ocd_cksum_types = OBD_CKSUM_ADLER; else - data->ocd_cksum_types = cksum_types_supported_client(); + data->ocd_cksum_types = obd_cksum_types_supported_client(); #ifdef HAVE_LRU_RESIZE_SUPPORT data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE; @@ -428,13 +452,13 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, "ocd_grant: %d\n", data->ocd_connect_flags, data->ocd_version, data->ocd_grant); - obd->obd_upcall.onu_owner = &sbi->ll_lco; - obd->obd_upcall.onu_upcall = cl_ocd_update; + sbi->ll_dt_obd->obd_upcall.onu_owner = &sbi->ll_lco; + sbi->ll_dt_obd->obd_upcall.onu_upcall = cl_ocd_update; data->ocd_brw_size = DT_MAX_BRW_SIZE; - err = obd_connect(NULL, &sbi->ll_dt_exp, obd, &sbi->ll_sb_uuid, data, - NULL); + err = obd_connect(NULL, &sbi->ll_dt_exp, sbi->ll_dt_obd, + &sbi->ll_sb_uuid, data, NULL); if (err == -EBUSY) { LCONSOLE_ERROR_MSG(0x150, "An OST (dt %s) is performing " "recovery, of which this client is not a " @@ -449,6 +473,12 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_dt_exp->exp_connect_data = *data; + /* Don't change value if it was specified in the config log */ + if (sbi->ll_ra_info.ra_max_read_ahead_whole_pages == -1) + sbi->ll_ra_info.ra_max_read_ahead_whole_pages = + max_t(unsigned long, SBI_DEFAULT_READAHEAD_WHOLE_MAX, + (data->ocd_brw_size >> PAGE_SHIFT)); + err = obd_fid_init(sbi->ll_dt_exp->exp_obd, sbi->ll_dt_exp, LUSTRE_SEQ_METADATA); if (err) { @@ -479,6 +509,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid)); sb->s_op = &lustre_super_operations; +#ifdef HAVE_XATTR_HANDLER_FLAGS + sb->s_xattr = ll_xattr_handlers; +#endif #if THREAD_SIZE >= 8192 /*b=17630*/ sb->s_export_op = &lustre_export_operations; #endif @@ -535,13 +568,15 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, } checksum = sbi->ll_flags & LL_SBI_CHECKSUM; - err = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM), - KEY_CHECKSUM, sizeof(checksum), &checksum, - NULL); - if (err) { - CERROR("%s: Set checksum failed: rc = %d\n", - sbi->ll_dt_exp->exp_obd->obd_name, err); - GOTO(out_root, err); + if (sbi->ll_checksum_set) { + err = obd_set_info_async(NULL, sbi->ll_dt_exp, + sizeof(KEY_CHECKSUM), KEY_CHECKSUM, + sizeof(checksum), &checksum, NULL); + if (err) { + CERROR("%s: Set checksum failed: rc = %d\n", + sbi->ll_dt_exp->exp_obd->obd_name, err); + GOTO(out_root, err); + } } cl_sb_init(sb); @@ -580,14 +615,21 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (osfs != NULL) OBD_FREE_PTR(osfs); - if (sbi->ll_proc_root != NULL) { - err = lprocfs_ll_register_obd(sb, dt); + if (sbi->ll_dt_obd) { + err = sysfs_create_link(&sbi->ll_kset.kobj, + &sbi->ll_dt_obd->obd_kset.kobj, + sbi->ll_dt_obd->obd_type->typ_name); if (err < 0) { CERROR("%s: could not register %s in llite: rc = %d\n", dt, ll_get_fsname(sb, NULL, 0), err); err = 0; } - err = lprocfs_ll_register_obd(sb, md); + } + + if (sbi->ll_md_obd) { + err = sysfs_create_link(&sbi->ll_kset.kobj, + &sbi->ll_md_obd->obd_kset.kobj, + sbi->ll_md_obd->obd_type->typ_name); if (err < 0) { CERROR("%s: could not register %s in llite: rc = %d\n", md, ll_get_fsname(sb, NULL, 0), err); @@ -604,11 +646,13 @@ out_lock_cn_cb: out_dt: obd_disconnect(sbi->ll_dt_exp); sbi->ll_dt_exp = NULL; + sbi->ll_dt_obd = NULL; out_md_fid: obd_fid_fini(sbi->ll_md_exp->exp_obd); out_md: obd_disconnect(sbi->ll_md_exp); sbi->ll_md_exp = NULL; + sbi->ll_md_obd = NULL; out: if (data != NULL) OBD_FREE_PTR(data); @@ -700,7 +744,7 @@ static void client_common_put_super(struct super_block *sb) obd_disconnect(sbi->ll_dt_exp); sbi->ll_dt_exp = NULL; - lprocfs_ll_unregister_mountpoint(sbi); + ll_debugfs_unregister_super(sb); obd_fid_fini(sbi->ll_md_exp->exp_obd); obd_disconnect(sbi->ll_md_exp); @@ -738,23 +782,24 @@ void ll_kill_super(struct super_block *sb) static inline int ll_set_opt(const char *opt, char *data, int fl) { - if (strncmp(opt, data, strlen(opt)) != 0) - return(0); - else - return(fl); + if (strncmp(opt, data, strlen(opt)) != 0) + return 0; + else + return fl; } /* non-client-specific mount options are parsed in lmd_parse */ -static int ll_options(char *options, int *flags) +static int ll_options(char *options, struct ll_sb_info *sbi) { - int tmp; - char *s1 = options, *s2; - ENTRY; + int tmp; + char *s1 = options, *s2; + int *flags = &sbi->ll_flags; + ENTRY; - if (!options) - RETURN(0); + if (!options) + RETURN(0); - CDEBUG(D_CONFIG, "Parsing opts %s\n", options); + CDEBUG(D_CONFIG, "Parsing opts %s\n", options); while (*s1) { CDEBUG(D_SUPER, "next opt=%s\n", s1); @@ -811,16 +856,18 @@ static int ll_options(char *options, int *flags) goto next; } - tmp = ll_set_opt("checksum", s1, LL_SBI_CHECKSUM); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("nochecksum", s1, LL_SBI_CHECKSUM); - if (tmp) { - *flags &= ~tmp; - goto next; - } + tmp = ll_set_opt("checksum", s1, LL_SBI_CHECKSUM); + if (tmp) { + *flags |= tmp; + sbi->ll_checksum_set = 1; + goto next; + } + tmp = ll_set_opt("nochecksum", s1, LL_SBI_CHECKSUM); + if (tmp) { + *flags &= ~tmp; + sbi->ll_checksum_set = 1; + goto next; + } tmp = ll_set_opt("lruresize", s1, LL_SBI_LRU_RESIZE); if (tmp) { *flags |= tmp; @@ -907,98 +954,125 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_opendir_pid = 0; lli->lli_sa_enabled = 0; lli->lli_def_stripe_offset = -1; + init_rwsem(&lli->lli_lsm_sem); } else { mutex_init(&lli->lli_size_mutex); lli->lli_symlink_name = NULL; init_rwsem(&lli->lli_trunc_sem); range_lock_tree_init(&lli->lli_write_tree); init_rwsem(&lli->lli_glimpse_sem); - lli->lli_glimpse_time = 0; + lli->lli_glimpse_time = ktime_set(0, 0); INIT_LIST_HEAD(&lli->lli_agl_list); lli->lli_agl_index = 0; lli->lli_async_rc = 0; } mutex_init(&lli->lli_layout_mutex); - memset(lli->lli_jobid, 0, LUSTRE_JOBID_SIZE); + memset(lli->lli_jobid, 0, sizeof(lli->lli_jobid)); } -static inline int ll_bdi_register(struct backing_dev_info *bdi) +#define MAX_STRING_SIZE 128 + +#ifndef HAVE_SUPER_SETUP_BDI_NAME + +#define LSI_BDI_INITIALIZED 0x00400000 + +#ifndef HAVE_BDI_CAP_MAP_COPY +# define BDI_CAP_MAP_COPY 0 +#endif + +static int super_setup_bdi_name(struct super_block *sb, char *fmt, ...) { - static atomic_t ll_bdi_num = ATOMIC_INIT(0); + struct lustre_sb_info *lsi = s2lsi(sb); + char buf[MAX_STRING_SIZE]; + va_list args; + int err; + + err = bdi_init(&lsi->lsi_bdi); + if (err) + return err; - bdi->name = "lustre"; - return bdi_register(bdi, NULL, "lustre-%d", - atomic_inc_return(&ll_bdi_num)); + lsi->lsi_flags |= LSI_BDI_INITIALIZED; + lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY; + lsi->lsi_bdi.name = "lustre"; + va_start(args, fmt); + vsnprintf(buf, MAX_STRING_SIZE, fmt, args); + va_end(args); + err = bdi_register(&lsi->lsi_bdi, NULL, "%s", buf); + va_end(args); + if (!err) + sb->s_bdi = &lsi->lsi_bdi; + + return err; } +#endif /* !HAVE_SUPER_SETUP_BDI_NAME */ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) { struct lustre_profile *lprof = NULL; struct lustre_sb_info *lsi = s2lsi(sb); - struct ll_sb_info *sbi; + struct ll_sb_info *sbi = NULL; char *dt = NULL, *md = NULL; char *profilenm = get_profile_name(sb); struct config_llog_instance *cfg; /* %p for void* in printf needs 16+2 characters: 0xffffffffffffffff */ const int instlen = sizeof(cfg->cfg_instance) * 2 + 2; - int md_len = 0; - int dt_len = 0; - int err; - ENTRY; + char name[MAX_STRING_SIZE]; + int md_len = 0; + int dt_len = 0; + char *ptr; + int len; + int err; + ENTRY; CDEBUG(D_VFSTRACE, "VFS Op: sb %p\n", sb); + try_module_get(THIS_MODULE); + OBD_ALLOC_PTR(cfg); if (cfg == NULL) - RETURN(-ENOMEM); - - try_module_get(THIS_MODULE); + GOTO(out_free_cfg, err = -ENOMEM); /* client additional sb info */ lsi->lsi_llsbi = sbi = ll_init_sbi(); - if (!sbi) { - module_put(THIS_MODULE); - OBD_FREE_PTR(cfg); - RETURN(-ENOMEM); - } + if (!sbi) + GOTO(out_free_cfg, err = -ENOMEM); - err = ll_options(lsi->lsi_lmd->lmd_opts, &sbi->ll_flags); + err = ll_options(lsi->lsi_lmd->lmd_opts, sbi); if (err) - GOTO(out_free, err); + GOTO(out_free_cfg, err); - err = bdi_init(&lsi->lsi_bdi); + err = super_setup_bdi_name(sb, "lustre-%p", sb); if (err) - GOTO(out_free, err); - lsi->lsi_flags |= LSI_BDI_INITIALIZED; -#ifdef HAVE_BDI_CAP_MAP_COPY - lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY; -#else - lsi->lsi_bdi.capabilities = 0; -#endif - err = ll_bdi_register(&lsi->lsi_bdi); - if (err) - GOTO(out_free, err); + GOTO(out_free_cfg, err); - sb->s_bdi = &lsi->lsi_bdi; #ifndef HAVE_DCACHE_LOCK /* kernel >= 2.6.38 store dentry operations in sb->s_d_op. */ sb->s_d_op = &ll_d_ops; #endif + /* Get fsname */ + len = strlen(lsi->lsi_lmd->lmd_profile); + ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-'); + if (ptr && (strcmp(ptr, "-client") == 0)) + len -= 7; - /* Call lprocfs_ll_register_mountpoint() before lustre_process_log() - * so that "llite.*.*" params can be processed correctly. */ - if (proc_lustre_fs_root != NULL) { - err = lprocfs_ll_register_mountpoint(proc_lustre_fs_root, sb); - if (err < 0) { - CERROR("%s: could not register mountpoint in llite: " - "rc = %d\n", ll_get_fsname(sb, NULL, 0), err); - err = 0; - } + /* Mount info */ + snprintf(name, MAX_STRING_SIZE, "%.*s-%p", len, + lsi->lsi_lmd->lmd_profile, sb); + + /* Call ll_debugfs_register_super() before lustre_process_log() + * so that "llite.*.*" params can be processed correctly. + */ + err = ll_debugfs_register_super(sb, name); + if (err < 0) { + CERROR("%s: could not register mountpoint in llite: rc = %d\n", + ll_get_fsname(sb, NULL, 0), err); + err = 0; } /* Generate a string unique to this super, in case some joker tries - to mount the same fs at two mount points. - Use the address of the super itself.*/ + * to mount the same fs at two mount points. + * Use the address of the super itself. + */ cfg->cfg_instance = sb; cfg->cfg_uuid = lsi->lsi_llsbi->ll_sb_uuid; cfg->cfg_callback = class_config_llog_handler; @@ -1006,7 +1080,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) /* set up client obds */ err = lustre_process_log(sb, profilenm, cfg); if (err < 0) - GOTO(out_proc, err); + GOTO(out_debugfs, err); /* Profile set with LCFG_MOUNTOPT so we can find our mdc and osc obds */ lprof = class_get_profile(profilenm); @@ -1014,7 +1088,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) LCONSOLE_ERROR_MSG(0x156, "The client profile '%s' could not be" " read from the MGS. Does that filesystem " "exist?\n", profilenm); - GOTO(out_proc, err = -EINVAL); + GOTO(out_debugfs, err = -EINVAL); } CDEBUG(D_CONFIG, "Found profile %s: mdc=%s osc=%s\n", profilenm, lprof->lp_md, lprof->lp_dt); @@ -1022,38 +1096,42 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) dt_len = strlen(lprof->lp_dt) + instlen + 2; OBD_ALLOC(dt, dt_len); if (!dt) - GOTO(out_proc, err = -ENOMEM); + GOTO(out_profile, err = -ENOMEM); snprintf(dt, dt_len - 1, "%s-%p", lprof->lp_dt, cfg->cfg_instance); md_len = strlen(lprof->lp_md) + instlen + 2; OBD_ALLOC(md, md_len); if (!md) - GOTO(out_proc, err = -ENOMEM); + GOTO(out_free_dt, err = -ENOMEM); snprintf(md, md_len - 1, "%s-%p", lprof->lp_md, cfg->cfg_instance); /* connections, registrations, sb setup */ err = client_common_fill_super(sb, md, dt, mnt); if (err < 0) - GOTO(out_proc, err); + GOTO(out_free_md, err); sbi->ll_client_common_fill_super_succeeded = 1; -out_proc: - if (err < 0) - lprocfs_ll_unregister_mountpoint(sbi); -out_free: +out_free_md: if (md) OBD_FREE(md, md_len); +out_free_dt: if (dt) OBD_FREE(dt, dt_len); - if (lprof != NULL) +out_profile: + if (lprof) class_put_profile(lprof); +out_debugfs: + if (err < 0) + ll_debugfs_unregister_super(sb); +out_free_cfg: + if (cfg) + OBD_FREE_PTR(cfg); + if (err) ll_put_super(sb); else if (sbi->ll_flags & LL_SBI_VERBOSE) LCONSOLE_WARN("Mounted %s\n", profilenm); - - OBD_FREE_PTR(cfg); RETURN(err); } /* ll_fill_super */ @@ -1068,6 +1146,9 @@ void ll_put_super(struct super_block *sb) int next, force = 1, rc = 0; ENTRY; + if (!sbi) + GOTO(out_no_sbi, 0); + CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm); cfg.cfg_instance = sb; @@ -1121,14 +1202,16 @@ void ll_put_super(struct super_block *sb) if (profilenm) class_del_profile(profilenm); +#ifndef HAVE_SUPER_SETUP_BDI_NAME if (lsi->lsi_flags & LSI_BDI_INITIALIZED) { bdi_destroy(&lsi->lsi_bdi); lsi->lsi_flags &= ~LSI_BDI_INITIALIZED; } +#endif ll_free_sbi(sb); lsi->lsi_llsbi = NULL; - +out_no_sbi: lustre_common_put_super(sb); cl_env_cache_purge(~0); @@ -1232,9 +1315,16 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) { struct lu_fid *fid; struct lmv_stripe_md *lsm = md->lmv; + struct ll_inode_info *lli = ll_i2info(inode); int i; LASSERT(lsm != NULL); + + CDEBUG(D_INODE, "%s: "DFID" set dir layout:\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(&lli->lli_fid)); + lsm_md_dump(D_INODE, lsm); + /* XXX sigh, this lsm_root initialization should be in * LMV layer, but it needs ll_iget right now, so we * put this here right now. */ @@ -1245,93 +1335,103 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) * where the initialization of slave inode is slightly * different, so it reset lsm_md to NULL to avoid * initializing lsm for slave inode. */ - /* For migrating inode, master stripe and master object will - * be same, so we only need assign this inode */ - if (lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION && i == 0) - lsm->lsm_md_oinfo[i].lmo_root = inode; - else - lsm->lsm_md_oinfo[i].lmo_root = + lsm->lsm_md_oinfo[i].lmo_root = ll_iget_anon_dir(inode->i_sb, fid, md); - if (IS_ERR(lsm->lsm_md_oinfo[i].lmo_root)) { int rc = PTR_ERR(lsm->lsm_md_oinfo[i].lmo_root); lsm->lsm_md_oinfo[i].lmo_root = NULL; + while (i-- > 0) { + iput(lsm->lsm_md_oinfo[i].lmo_root); + lsm->lsm_md_oinfo[i].lmo_root = NULL; + } return rc; } } - return 0; -} + lli->lli_lsm_md = lsm; -static inline int lli_lsm_md_eq(const struct lmv_stripe_md *lsm_md1, - const struct lmv_stripe_md *lsm_md2) -{ - return lsm_md1->lsm_md_magic == lsm_md2->lsm_md_magic && - lsm_md1->lsm_md_stripe_count == lsm_md2->lsm_md_stripe_count && - lsm_md1->lsm_md_master_mdt_index == - lsm_md2->lsm_md_master_mdt_index && - lsm_md1->lsm_md_hash_type == lsm_md2->lsm_md_hash_type && - lsm_md1->lsm_md_layout_version == - lsm_md2->lsm_md_layout_version && - strcmp(lsm_md1->lsm_md_pool_name, - lsm_md2->lsm_md_pool_name) == 0; + return 0; } static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); struct lmv_stripe_md *lsm = md->lmv; - int rc; + int rc = 0; + ENTRY; LASSERT(S_ISDIR(inode->i_mode)); CDEBUG(D_INODE, "update lsm %p of "DFID"\n", lli->lli_lsm_md, PFID(ll_inode2fid(inode))); - /* no striped information from request. */ - if (lsm == NULL) { - if (lli->lli_lsm_md == NULL) { - RETURN(0); - } else if (lli->lli_lsm_md->lsm_md_hash_type & - LMV_HASH_FLAG_MIGRATION) { - /* migration is done, the temporay MIGRATE layout has - * been removed */ - CDEBUG(D_INODE, DFID" finish migration.\n", - PFID(ll_inode2fid(inode))); - lmv_free_memmd(lli->lli_lsm_md); - lli->lli_lsm_md = NULL; - RETURN(0); - } else { - /* The lustre_md from req does not include stripeEA, - * see ll_md_setattr */ - RETURN(0); + /* + * no striped information from request, lustre_md from req does not + * include stripeEA, see ll_md_setattr() + */ + if (!lsm) + RETURN(0); + + /* + * normally dir layout doesn't change, only take read lock to check + * that to avoid blocking other MD operations. + */ + if (lli->lli_lsm_md) + down_read(&lli->lli_lsm_sem); + else + down_write(&lli->lli_lsm_sem); + + /* + * if dir layout mismatch, check whether version is increased, which + * means layout is changed, this happens in dir migration and lfsck. + */ + if (lli->lli_lsm_md && !lsm_md_eq(lli->lli_lsm_md, lsm)) { + if (lsm->lsm_md_layout_version <= + lli->lli_lsm_md->lsm_md_layout_version) { + CERROR("%s: "DFID" dir layout mismatch:\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(&lli->lli_fid)); + lsm_md_dump(D_ERROR, lli->lli_lsm_md); + lsm_md_dump(D_ERROR, lsm); + GOTO(unlock, rc = -EINVAL); } + + /* layout changed, switch to write lock */ + up_read(&lli->lli_lsm_sem); + down_write(&lli->lli_lsm_sem); + ll_dir_clear_lsm_md(inode); } - /* set the directory layout */ - if (lli->lli_lsm_md == NULL) { + /* set directory layout */ + if (!lli->lli_lsm_md) { struct cl_attr *attr; rc = ll_init_lsm_md(inode, md); + up_write(&lli->lli_lsm_sem); if (rc != 0) RETURN(rc); /* set md->lmv to NULL, so the following free lustre_md * will not free this lsm */ md->lmv = NULL; - lli->lli_lsm_md = lsm; + + /* + * md_merge_attr() may take long, since lsm is already set, + * switch to read lock. + */ + down_read(&lli->lli_lsm_sem); OBD_ALLOC_PTR(attr); if (attr == NULL) - RETURN(-ENOMEM); + GOTO(unlock, rc = -ENOMEM); /* validate the lsm */ rc = md_merge_attr(ll_i2mdexp(inode), lsm, attr, ll_md_blocking_ast); if (rc != 0) { OBD_FREE_PTR(attr); - RETURN(rc); + GOTO(unlock, rc); } if (md->body->mbo_valid & OBD_MD_FLNLINK) @@ -1346,49 +1446,11 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) md->body->mbo_mtime = attr->cat_mtime; OBD_FREE_PTR(attr); - - CDEBUG(D_INODE, "Set lsm %p magic %x to "DFID"\n", lsm, - lsm->lsm_md_magic, PFID(ll_inode2fid(inode))); - RETURN(0); } +unlock: + up_read(&lli->lli_lsm_sem); - /* Compare the old and new stripe information */ - if (!lsm_md_eq(lli->lli_lsm_md, lsm)) { - struct lmv_stripe_md *old_lsm = lli->lli_lsm_md; - int idx; - - CERROR("%s: inode "DFID"(%p)'s lmv layout mismatch (%p)/(%p)" - "magic:0x%x/0x%x stripe count: %d/%d master_mdt: %d/%d" - "hash_type:0x%x/0x%x layout: 0x%x/0x%x pool:%s/%s\n", - ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), - inode, lsm, old_lsm, - lsm->lsm_md_magic, old_lsm->lsm_md_magic, - lsm->lsm_md_stripe_count, - old_lsm->lsm_md_stripe_count, - lsm->lsm_md_master_mdt_index, - old_lsm->lsm_md_master_mdt_index, - lsm->lsm_md_hash_type, old_lsm->lsm_md_hash_type, - lsm->lsm_md_layout_version, - old_lsm->lsm_md_layout_version, - lsm->lsm_md_pool_name, - old_lsm->lsm_md_pool_name); - - for (idx = 0; idx < old_lsm->lsm_md_stripe_count; idx++) { - CERROR("%s: sub FIDs in old lsm idx %d, old: "DFID"\n", - ll_get_fsname(inode->i_sb, NULL, 0), idx, - PFID(&old_lsm->lsm_md_oinfo[idx].lmo_fid)); - } - - for (idx = 0; idx < lsm->lsm_md_stripe_count; idx++) { - CERROR("%s: sub FIDs in new lsm idx %d, new: "DFID"\n", - ll_get_fsname(inode->i_sb, NULL, 0), idx, - PFID(&lsm->lsm_md_oinfo[idx].lmo_fid)); - } - - RETURN(-EIO); - } - - RETURN(0); + RETURN(rc); } void ll_clear_inode(struct inode *inode) @@ -1429,6 +1491,7 @@ void ll_clear_inode(struct inode *inode) ll_xattr_cache_destroy(inode); #ifdef CONFIG_FS_POSIX_ACL + forget_all_cached_acls(inode); if (lli->lli_posix_acl) { LASSERT(atomic_read(&lli->lli_posix_acl->a_refcount) == 1); posix_acl_release(lli->lli_posix_acl); @@ -1524,7 +1587,8 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data) * * In case of HSMimport, we only set attr on MDS. */ -int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) +int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, + enum op_xvalid xvalid, bool hsm_import) { struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); @@ -1564,20 +1628,20 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) RETURN(-EPERM); } - /* We mark all of the fields "set" so MDS/OST does not re-set them */ - if (!(attr->ia_valid & ATTR_CTIME_SET) && - (attr->ia_valid & ATTR_CTIME)) { - attr->ia_ctime = CURRENT_TIME; - attr->ia_valid |= ATTR_CTIME_SET; - } + /* We mark all of the fields "set" so MDS/OST does not re-set them */ + if (!(xvalid & OP_XVALID_CTIME_SET) && + (attr->ia_valid & ATTR_CTIME)) { + attr->ia_ctime = current_time(inode); + xvalid |= OP_XVALID_CTIME_SET; + } if (!(attr->ia_valid & ATTR_ATIME_SET) && (attr->ia_valid & ATTR_ATIME)) { - attr->ia_atime = CURRENT_TIME; + attr->ia_atime = current_time(inode); attr->ia_valid |= ATTR_ATIME_SET; } if (!(attr->ia_valid & ATTR_MTIME_SET) && (attr->ia_valid & ATTR_MTIME)) { - attr->ia_mtime = CURRENT_TIME; + attr->ia_mtime = current_time(inode); attr->ia_valid |= ATTR_MTIME_SET; } @@ -1601,13 +1665,22 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) if (!hsm_import && attr->ia_valid & ATTR_SIZE) { /* If we are changing file size, file content is - * modified, flag it. */ - attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; + * modified, flag it. + */ + xvalid |= OP_XVALID_OWNEROVERRIDE; op_data->op_bias |= MDS_DATA_MODIFIED; ll_file_clear_flag(lli, LLIF_DATA_MODIFIED); } + if (attr->ia_valid & ATTR_FILE) { + struct ll_file_data *fd = LUSTRE_FPRIVATE(attr->ia_file); + + if (fd->fd_lease_och) + op_data->op_bias |= MDS_TRUNC_KEEP_LEASE; + } + op_data->op_attr = *attr; + op_data->op_xvalid = xvalid; rc = ll_md_setattr(dentry, op_data); if (rc) @@ -1616,17 +1689,17 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) if (!S_ISREG(inode->i_mode) || hsm_import) GOTO(out, rc = 0); - if (attr->ia_valid & (ATTR_SIZE | - ATTR_ATIME | ATTR_ATIME_SET | - ATTR_MTIME | ATTR_MTIME_SET | - ATTR_CTIME | ATTR_CTIME_SET)) { + if (attr->ia_valid & (ATTR_SIZE | ATTR_ATIME | ATTR_ATIME_SET | + ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME) || + xvalid & OP_XVALID_CTIME_SET) { /* For truncate and utimes sending attributes to OSTs, setting * mtime/atime to the past will be performed under PW [0:EOF] * extent lock (new_size:EOF for truncate). It may seem * excessive to send mtime/atime updates to OSTs when not * setting times to past, but it is necessary due to possible - * time de-synchronization between MDT inode and OST objects */ - rc = cl_setattr_ost(lli->lli_clob, attr, 0); + * time de-synchronization between MDT inode and OST objects + */ + rc = cl_setattr_ost(lli->lli_clob, attr, xvalid, 0); } /* If the file was restored, it needs to set dirty flag. @@ -1686,10 +1759,11 @@ out: int ll_setattr(struct dentry *de, struct iattr *attr) { int mode = de->d_inode->i_mode; + enum op_xvalid xvalid = 0; if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) == (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) - attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; + xvalid |= OP_XVALID_OWNEROVERRIDE; if (((attr->ia_valid & (ATTR_MODE|ATTR_FORCE|ATTR_SIZE)) == (ATTR_SIZE|ATTR_MODE)) && @@ -1710,20 +1784,18 @@ int ll_setattr(struct dentry *de, struct iattr *attr) !(attr->ia_valid & ATTR_KILL_SGID)) attr->ia_valid |= ATTR_KILL_SGID; - /* avoid polluted from ATTR_TIMES_SET, - * projid is not expected to be set here */ - attr->ia_valid &= ~MDS_ATTR_PROJID; - - return ll_setattr_raw(de, attr, false); + return ll_setattr_raw(de, attr, xvalid, false); } -int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, - __u64 max_age, __u32 flags) +int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs, + u32 flags) { - struct ll_sb_info *sbi = ll_s2sbi(sb); - struct obd_statfs obd_osfs; - int rc; - ENTRY; + struct obd_statfs obd_osfs; + time64_t max_age; + int rc; + + ENTRY; + max_age = ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS; rc = obd_statfs(NULL, sbi->ll_md_exp, osfs, max_age, flags); if (rc) { @@ -1731,15 +1803,18 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, RETURN(rc); } - osfs->os_type = sb->s_magic; + osfs->os_type = LL_SUPER_MAGIC; CDEBUG(D_SUPER, "MDC blocks %llu/%llu objects %llu/%llu\n", osfs->os_bavail, osfs->os_blocks, osfs->os_ffree,osfs->os_files); + if (osfs->os_state & OS_STATE_SUM) + GOTO(out, rc); + if (sbi->ll_flags & LL_SBI_LAZYSTATFS) flags |= OBD_STATFS_NODELAY; - rc = obd_statfs_rqset(sbi->ll_dt_exp, &obd_osfs, max_age, flags); + rc = obd_statfs(NULL, sbi->ll_dt_exp, &obd_osfs, max_age, flags); if (rc) { CERROR("obd_statfs fails: rc = %d\n", rc); RETURN(rc); @@ -1764,6 +1839,7 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, osfs->os_ffree = obd_osfs.os_ffree; } +out: RETURN(rc); } int ll_statfs(struct dentry *de, struct kstatfs *sfs) @@ -1776,12 +1852,10 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs) CDEBUG(D_VFSTRACE, "VFS Op: at %llu jiffies\n", get_jiffies_64()); ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_STAFS, 1); - /* Some amount of caching on the client is allowed */ - rc = ll_statfs_internal(sb, &osfs, - cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), - 0); - if (rc) - return rc; + /* Some amount of caching on the client is allowed */ + rc = ll_statfs_internal(ll_s2sbi(sb), &osfs, OBD_STATFS_SUM); + if (rc) + return rc; statfs_unpack(sfs, &osfs); @@ -1825,6 +1899,15 @@ void ll_inode_size_unlock(struct inode *inode) mutex_unlock(&lli->lli_size_mutex); } +void ll_update_inode_flags(struct inode *inode, int ext_flags) +{ + inode->i_flags = ll_ext_to_inode_flags(ext_flags); + if (ext_flags & LUSTRE_PROJINHERIT_FL) + ll_file_set_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT); + else + ll_file_clear_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT); +} + int ll_update_inode(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); @@ -1881,7 +1964,7 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) /* Clear i_flags to remove S_NOSEC before permissions are updated */ if (body->mbo_valid & OBD_MD_FLFLAGS) - inode->i_flags = ll_ext_to_inode_flags(body->mbo_flags); + ll_update_inode_flags(inode, body->mbo_flags); if (body->mbo_valid & OBD_MD_FLMODE) inode->i_mode = (inode->i_mode & S_IFMT) | (body->mbo_mode & ~S_IFMT); @@ -2004,6 +2087,8 @@ int ll_read_inode2(struct inode *inode, void *opaque) void ll_delete_inode(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); + struct address_space *mapping = &inode->i_data; + unsigned long nrpages; ENTRY; if (S_ISREG(inode->i_mode) && lli->lli_clob != NULL) @@ -2011,11 +2096,26 @@ void ll_delete_inode(struct inode *inode) * otherwise we may lose data while umount */ cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, CL_FSYNC_LOCAL, 1); - truncate_inode_pages_final(&inode->i_data); + truncate_inode_pages_final(mapping); - LASSERTF(inode->i_data.nrpages == 0, "inode="DFID"(%p) nrpages=%lu, " - "see https://jira.hpdd.intel.com/browse/LU-118\n", - PFID(ll_inode2fid(inode)), inode, inode->i_data.nrpages); + /* Workaround for LU-118: Note nrpages may not be totally updated when + * truncate_inode_pages() returns, as there can be a page in the process + * of deletion (inside __delete_from_page_cache()) in the specified + * range. Thus mapping->nrpages can be non-zero when this function + * returns even after truncation of the whole mapping. Only do this if + * npages isn't already zero. + */ + nrpages = mapping->nrpages; + if (nrpages) { + spin_lock_irq(&mapping->tree_lock); + nrpages = mapping->nrpages; + spin_unlock_irq(&mapping->tree_lock); + } /* Workaround end */ + + LASSERTF(nrpages == 0, "%s: inode="DFID"(%p) nrpages=%lu, " + "see https://jira.whamcloud.com/browse/LU-118\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(ll_inode2fid(inode)), inode, nrpages); #ifdef HAVE_SBOPS_EVICT_INODE ll_clear_inode(inode); @@ -2028,13 +2128,13 @@ void ll_delete_inode(struct inode *inode) int ll_iocontrol(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ptlrpc_request *req = NULL; - int rc, flags = 0; - ENTRY; + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ptlrpc_request *req = NULL; + int rc, flags = 0; + ENTRY; - switch(cmd) { - case FSFILT_IOC_GETFLAGS: { + switch (cmd) { + case FS_IOC_GETFLAGS: { struct mdt_body *body; struct md_op_data *op_data; @@ -2058,32 +2158,41 @@ int ll_iocontrol(struct inode *inode, struct file *file, flags = body->mbo_flags; - ptlrpc_req_finished(req); + ptlrpc_req_finished(req); RETURN(put_user(flags, (int __user *)arg)); - } - case FSFILT_IOC_SETFLAGS: { + } + case FS_IOC_SETFLAGS: { struct iattr *attr; struct md_op_data *op_data; struct cl_object *obj; + struct fsxattr fa = { 0 }; if (get_user(flags, (int __user *)arg)) RETURN(-EFAULT); - op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - RETURN(PTR_ERR(op_data)); + fa.fsx_projid = ll_i2info(inode)->lli_projid; + if (flags & LUSTRE_PROJINHERIT_FL) + fa.fsx_xflags = FS_XFLAG_PROJINHERIT; + + rc = ll_ioctl_check_project(inode, &fa); + if (rc) + RETURN(rc); + + op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, + LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + RETURN(PTR_ERR(op_data)); op_data->op_attr_flags = flags; - op_data->op_attr.ia_valid |= ATTR_ATTR_FLAG; + op_data->op_xvalid |= OP_XVALID_FLAGS; rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, &req); ll_finish_md_op_data(op_data); ptlrpc_req_finished(req); if (rc) RETURN(rc); - inode->i_flags = ll_ext_to_inode_flags(flags); + ll_update_inode_flags(inode, flags); obj = ll_i2info(inode)->lli_clob; if (obj == NULL) @@ -2093,8 +2202,7 @@ int ll_iocontrol(struct inode *inode, struct file *file, if (attr == NULL) RETURN(-ENOMEM); - attr->ia_valid = ATTR_ATTR_FLAG; - rc = cl_setattr_ost(obj, attr, flags); + rc = cl_setattr_ost(obj, attr, OP_XVALID_FLAGS, flags); OBD_FREE_PTR(attr); RETURN(rc); @@ -2242,7 +2350,7 @@ void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req) } op_data->op_fid1 = body->mbo_fid1; - op_data->op_handle = body->mbo_handle; + op_data->op_open_handle = body->mbo_open_handle; op_data->op_mod_time = ktime_get_real_seconds(); md_close(exp, op_data, NULL, &close_req); ptlrpc_req_finished(close_req); @@ -2384,30 +2492,21 @@ out_statfs: return rc; } -int ll_process_config(struct lustre_cfg *lcfg) +/* + * this is normally called in ll_fini_md_op_data(), but sometimes it needs to + * be called early to avoid deadlock. + */ +void ll_unlock_md_op_lsm(struct md_op_data *op_data) { - struct super_block *sb; - unsigned long x; - int rc = 0; - char *ptr; + if (op_data->op_mea2_sem) { + up_read(op_data->op_mea2_sem); + op_data->op_mea2_sem = NULL; + } - /* The instance name contains the sb: lustre-client-aacfe000 */ - ptr = strrchr(lustre_cfg_string(lcfg, 0), '-'); - if (!ptr || !*(++ptr)) - return -EINVAL; - if (sscanf(ptr, "%lx", &x) != 1) - return -EINVAL; - sb = (struct super_block *)x; - /* This better be a real Lustre superblock! */ - LASSERT(s2lsi(sb)->lsi_lmd->lmd_magic == LMD_MAGIC); - - /* Note we have not called client_common_fill_super yet, so - proc fns must be able to handle that! */ - rc = class_process_proc_param(PARAM_LLITE, lprocfs_llite_obd_vars, - lcfg, sb); - if (rc > 0) - rc = 0; - return rc; + if (op_data->op_mea1_sem) { + up_read(op_data->op_mea1_sem); + op_data->op_mea1_sem = NULL; + } } /* this function prepares md_op_data hint for passing it down to MD stack. */ @@ -2439,7 +2538,10 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, ll_i2gids(op_data->op_suppgids, i1, i2); op_data->op_fid1 = *ll_inode2fid(i1); op_data->op_default_stripe_offset = -1; + if (S_ISDIR(i1->i_mode)) { + down_read(&ll_i2info(i1)->lli_lsm_sem); + op_data->op_mea1_sem = &ll_i2info(i1)->lli_lsm_sem; op_data->op_mea1 = ll_i2info(i1)->lli_lsm_md; if (opc == LUSTRE_OPC_MKDIR) op_data->op_default_stripe_offset = @@ -2448,8 +2550,14 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, if (i2) { op_data->op_fid2 = *ll_inode2fid(i2); - if (S_ISDIR(i2->i_mode)) + if (S_ISDIR(i2->i_mode)) { + if (i2 != i1) { + down_read(&ll_i2info(i2)->lli_lsm_sem); + op_data->op_mea2_sem = + &ll_i2info(i2)->lli_lsm_sem; + } op_data->op_mea2 = ll_i2info(i2)->lli_lsm_md; + } } else { fid_zero(&op_data->op_fid2); } @@ -2463,15 +2571,14 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, op_data->op_name = name; op_data->op_namelen = namelen; op_data->op_mode = mode; - op_data->op_mod_time = cfs_time_current_sec(); + op_data->op_mod_time = ktime_get_real_seconds(); op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); + op_data->op_mds = 0; if ((opc == LUSTRE_OPC_CREATE) && (name != NULL) && filename_is_volatile(name, namelen, &op_data->op_mds)) { op_data->op_bias |= MDS_CREATE_VOLATILE; - } else { - op_data->op_mds = 0; } op_data->op_data = data; @@ -2480,6 +2587,7 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, void ll_finish_md_op_data(struct md_op_data *op_data) { + ll_unlock_md_op_lsm(op_data); security_release_secctx(op_data->op_file_secctx, op_data->op_file_secctx_size); OBD_FREE_PTR(op_data); @@ -2745,7 +2853,6 @@ static int ll_linkea_decode(struct linkea_data *ldata, unsigned int linkno, */ int ll_getparent(struct file *file, struct getparent __user *arg) { - struct dentry *dentry = file_dentry(file); struct inode *inode = file_inode(file); struct linkea_data *ldata; struct lu_buf buf = LU_BUF_NULL; @@ -2778,7 +2885,13 @@ int ll_getparent(struct file *file, struct getparent __user *arg) if (rc < 0) GOTO(ldata_free, rc); - rc = ll_getxattr(dentry, XATTR_NAME_LINK, buf.lb_buf, buf.lb_len); +#ifdef HAVE_XATTR_HANDLER_FLAGS + rc = ll_xattr_list(inode, XATTR_NAME_LINK, XATTR_TRUSTED_T, buf.lb_buf, + buf.lb_len, OBD_MD_FLXATTR); +#else + rc = ll_getxattr(file_dentry(file), XATTR_NAME_LINK, buf.lb_buf, + buf.lb_len); +#endif /* HAVE_XATTR_HANDLER_FLAGS */ if (rc < 0) GOTO(lb_free, rc);