X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Fllite_lib.c;h=ccdcc8c5ad1d55488c3e046525219e0814020cb3;hp=b5447d49e732b358afc33aed34a9fc1b0601eb5b;hb=0feec5a3c7d4518d5c563739124b202a6a0a99f7;hpb=0f38a0b9db4f7c6c101ee55fe7b94d49a32eabe9 diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index b5447d4..ccdcc8c 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -27,7 +27,6 @@ */ /* * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. * * lustre/llite/llite_lib.c * @@ -41,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -48,12 +48,12 @@ #include #include #include -#include #include #ifndef HAVE_CPUS_READ_LOCK #include #endif +#include #include #ifdef HAVE_UAPI_LINUX_MOUNT_H #include @@ -93,7 +93,6 @@ static struct ll_sb_info *ll_init_sbi(void) unsigned long lru_page_max; struct sysinfo si; int rc; - int i; ENTRY; @@ -159,25 +158,18 @@ static struct ll_sb_info *ll_init_sbi(void) sbi->ll_ra_info.ra_max_read_ahead_whole_pages = -1; atomic_set(&sbi->ll_ra_info.ra_async_inflight, 0); - sbi->ll_flags |= LL_SBI_VERBOSE; + set_bit(LL_SBI_VERBOSE, sbi->ll_flags); #ifdef ENABLE_CHECKSUM - sbi->ll_flags |= LL_SBI_CHECKSUM; + set_bit(LL_SBI_CHECKSUM, sbi->ll_flags); #endif #ifdef ENABLE_FLOCK - sbi->ll_flags |= LL_SBI_FLOCK; + set_bit(LL_SBI_FLOCK, sbi->ll_flags); #endif #ifdef HAVE_LRU_RESIZE_SUPPORT - sbi->ll_flags |= LL_SBI_LRU_RESIZE; + set_bit(LL_SBI_LRU_RESIZE, sbi->ll_flags); #endif - sbi->ll_flags |= LL_SBI_LAZYSTATFS; - - for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) { - spin_lock_init(&sbi->ll_rw_extents_info.pp_extents[i]. - pp_r_hist.oh_lock); - spin_lock_init(&sbi->ll_rw_extents_info.pp_extents[i]. - pp_w_hist.oh_lock); - } + set_bit(LL_SBI_LAZYSTATFS, sbi->ll_flags); /* metadata statahead is enabled by default */ sbi->ll_sa_running_max = LL_SA_RUNNING_DEF; @@ -186,9 +178,10 @@ static struct ll_sb_info *ll_init_sbi(void) atomic_set(&sbi->ll_sa_wrong, 0); atomic_set(&sbi->ll_sa_running, 0); 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; + set_bit(LL_SBI_AGL_ENABLED, sbi->ll_flags); + set_bit(LL_SBI_FAST_READ, sbi->ll_flags); + set_bit(LL_SBI_TINY_WRITE, sbi->ll_flags); + set_bit(LL_SBI_PARALLEL_DIO, sbi->ll_flags); ll_sbi_set_encrypt(sbi, true); /* root squash */ @@ -200,6 +193,11 @@ static struct ll_sb_info *ll_init_sbi(void) /* Per-filesystem file heat */ sbi->ll_heat_decay_weight = SBI_DEFAULT_HEAT_DECAY_WEIGHT; sbi->ll_heat_period_second = SBI_DEFAULT_HEAT_PERIOD_SECOND; + + /* Per-fs open heat level before requesting open lock */ + sbi->ll_oc_thrsh_count = SBI_DEFAULT_OPENCACHE_THRESHOLD_COUNT; + sbi->ll_oc_max_ms = SBI_DEFAULT_OPENCACHE_THRESHOLD_MAX_MS; + sbi->ll_oc_thrsh_ms = SBI_DEFAULT_OPENCACHE_THRESHOLD_MS; RETURN(sbi); out_destroy_ra: if (sbi->ll_foreign_symlink_prefix) @@ -256,6 +254,7 @@ static void ll_free_sbi(struct super_block *sb) sizeof(struct ll_foreign_symlink_upcall_item)); sbi->ll_foreign_symlink_upcall_items = NULL; } + ll_free_rw_stats_info(sbi); pcc_super_fini(&sbi->ll_pcc_super); OBD_FREE(sbi, sizeof(*sbi)); } @@ -274,6 +273,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) struct lustre_md lmd; u64 valid; int size, err, checksum; + bool api32; + void *encctx; + int encctxlen; ENTRY; sbi->ll_md_obd = class_name2obd(md); @@ -300,7 +302,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) 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_SRVLOCK | OBD_CONNECT_MDS_CAPA | OBD_CONNECT_OSS_CAPA | OBD_CONNECT_CANCELSET | OBD_CONNECT_FID | OBD_CONNECT_AT | OBD_CONNECT_LOV_V3 | @@ -318,6 +320,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) OBD_CONNECT_SUBTREE | OBD_CONNECT_MULTIMODRPCS | OBD_CONNECT_GRANT_PARAM | + OBD_CONNECT_GRANT_SHRINK | OBD_CONNECT_SHORTIO | OBD_CONNECT_FLAGS2; data->ocd_connect_flags2 = OBD_CONNECT2_DIR_MIGRATE | @@ -332,10 +335,12 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) OBD_CONNECT2_PCC | OBD_CONNECT2_CRUSH | OBD_CONNECT2_LSEEK | OBD_CONNECT2_GETATTR_PFID | - OBD_CONNECT2_DOM_LVB; + OBD_CONNECT2_DOM_LVB | + OBD_CONNECT2_REP_MBITS | + OBD_CONNECT2_ATOMIC_OPEN_LOCK; #ifdef HAVE_LRU_RESIZE_SUPPORT - if (sbi->ll_flags & LL_SBI_LRU_RESIZE) + if (test_bit(LL_SBI_LRU_RESIZE, sbi->ll_flags)) data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE; #endif data->ocd_connect_flags |= OBD_CONNECT_ACL_FLAGS; @@ -352,7 +357,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) if (sb->s_flags & SB_RDONLY) data->ocd_connect_flags |= OBD_CONNECT_RDONLY; - if (sbi->ll_flags & LL_SBI_USER_XATTR) + if (test_bit(LL_SBI_USER_XATTR, sbi->ll_flags)) data->ocd_connect_flags |= OBD_CONNECT_XATTR; #ifdef SB_NOSEC @@ -364,7 +369,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) sbi->ll_fop = ll_select_file_operations(sbi); /* always ping even if server suppress_pings */ - if (sbi->ll_flags & LL_SBI_ALWAYS_PING) + if (test_bit(LL_SBI_ALWAYS_PING, sbi->ll_flags)) data->ocd_connect_flags &= ~OBD_CONNECT_PINGLESS; obd_connect_set_secctx(data); @@ -449,35 +454,36 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) sb->s_maxbytes = MAX_LFS_FILESIZE; sbi->ll_namelen = osfs->os_namelen; sbi->ll_mnt.mnt = current->fs->root.mnt; + sbi->ll_mnt_ns = current->nsproxy->mnt_ns; - if ((sbi->ll_flags & LL_SBI_USER_XATTR) && + if (test_bit(LL_SBI_USER_XATTR, sbi->ll_flags) && !(data->ocd_connect_flags & OBD_CONNECT_XATTR)) { LCONSOLE_INFO("Disabling user_xattr feature because " "it is not supported on the server\n"); - sbi->ll_flags &= ~LL_SBI_USER_XATTR; + clear_bit(LL_SBI_USER_XATTR, sbi->ll_flags); } if (data->ocd_connect_flags & OBD_CONNECT_ACL) { #ifdef SB_POSIXACL sb->s_flags |= SB_POSIXACL; #endif - sbi->ll_flags |= LL_SBI_ACL; + set_bit(LL_SBI_ACL, sbi->ll_flags); } else { LCONSOLE_INFO("client wants to enable acl, but mdt not!\n"); #ifdef SB_POSIXACL sb->s_flags &= ~SB_POSIXACL; #endif - sbi->ll_flags &= ~LL_SBI_ACL; + clear_bit(LL_SBI_ACL, sbi->ll_flags); } if (data->ocd_connect_flags & OBD_CONNECT_64BITHASH) - sbi->ll_flags |= LL_SBI_64BIT_HASH; + set_bit(LL_SBI_64BIT_HASH, sbi->ll_flags); if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) - sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; + set_bit(LL_SBI_LAYOUT_LOCK, sbi->ll_flags); if (obd_connect_has_secctx(data)) - sbi->ll_flags |= LL_SBI_FILE_SECCTX; + set_bit(LL_SBI_FILE_SECCTX, sbi->ll_flags); if (ll_sbi_has_encrypt(sbi) && !obd_connect_has_enc(data)) { if (ll_sbi_has_test_dummy_encryption(sbi)) @@ -494,7 +500,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) } else if (!sbi->ll_xattr_cache_set) { /* If xattr_cache is already set (no matter 0 or 1) * during processing llog, it won't be enabled here. */ - sbi->ll_flags |= LL_SBI_XATTR_CACHE; + set_bit(LL_SBI_XATTR_CACHE, sbi->ll_flags); sbi->ll_xattr_cache_enabled = 1; } } @@ -513,7 +519,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) data->ocd_connect_flags = OBD_CONNECT_GRANT | OBD_CONNECT_VERSION | OBD_CONNECT_REQPORTAL | OBD_CONNECT_BRW_SIZE | OBD_CONNECT_CANCELSET | OBD_CONNECT_FID | - OBD_CONNECT_SRVLOCK | OBD_CONNECT_TRUNCLOCK| + OBD_CONNECT_SRVLOCK | OBD_CONNECT_AT | OBD_CONNECT_OSS_CAPA | OBD_CONNECT_VBR | OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH | OBD_CONNECT_MAXBYTES | @@ -524,7 +530,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) OBD_CONNECT_BULK_MBITS | OBD_CONNECT_SHORTIO | OBD_CONNECT_FLAGS2 | OBD_CONNECT_GRANT_SHRINK; data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD | - OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK; + OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK | + OBD_CONNECT2_REP_MBITS; if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_GRANT_PARAM)) data->ocd_connect_flags |= OBD_CONNECT_GRANT_PARAM; @@ -545,7 +552,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE; #endif /* always ping even if server suppress_pings */ - if (sbi->ll_flags & LL_SBI_ALWAYS_PING) + if (test_bit(LL_SBI_ALWAYS_PING, sbi->ll_flags)) data->ocd_connect_flags &= ~OBD_CONNECT_PINGLESS; if (ll_sbi_has_encrypt(sbi)) @@ -637,8 +644,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) /* make root inode * XXX: move this to after cbd setup? */ - valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMODEASIZE; - if (sbi->ll_flags & LL_SBI_ACL) + valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMODEASIZE | + OBD_MD_ENCCTX; + if (test_bit(LL_SBI_ACL, sbi->ll_flags)) valid |= OBD_MD_FLACL; OBD_ALLOC_PTR(op_data); @@ -651,6 +659,13 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) err = md_getattr(sbi->ll_md_exp, op_data, &request); + /* We need enc ctx info, so reset it in op_data to + * prevent it from being freed. + */ + encctx = op_data->op_file_encctx; + encctxlen = op_data->op_file_encctx_size; + op_data->op_file_encctx = NULL; + op_data->op_file_encctx_size = 0; OBD_FREE_PTR(op_data); if (err) { CERROR("%s: md_getattr failed for root: rc = %d\n", @@ -658,8 +673,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) GOTO(out_lock_cn_cb, err); } - err = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp, - sbi->ll_md_exp, &lmd); + err = md_get_lustre_md(sbi->ll_md_exp, &request->rq_pill, + sbi->ll_dt_exp, sbi->ll_md_exp, &lmd); if (err) { CERROR("failed to understand root inode md: rc = %d\n", err); ptlrpc_req_finished(request); @@ -667,11 +682,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) } LASSERT(fid_is_sane(&sbi->ll_root_fid)); - root = ll_iget(sb, cl_fid_build_ino(&sbi->ll_root_fid, - sbi->ll_flags & LL_SBI_32BIT_API), - &lmd); + api32 = test_bit(LL_SBI_32BIT_API, sbi->ll_flags); + root = ll_iget(sb, cl_fid_build_ino(&sbi->ll_root_fid, api32), &lmd); md_free_lustre_md(sbi->ll_md_exp, &lmd); - ptlrpc_req_finished(request); if (IS_ERR(root)) { lmd_clear_acl(&lmd); @@ -679,10 +692,23 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt) root = NULL; CERROR("%s: bad ll_iget() for root: rc = %d\n", sbi->ll_fsname, err); + ptlrpc_req_finished(request); GOTO(out_root, err); } - checksum = sbi->ll_flags & LL_SBI_CHECKSUM; + if (encctxlen) { + CDEBUG(D_SEC, + "server returned encryption ctx for root inode "DFID"\n", + PFID(&sbi->ll_root_fid)); + err = ll_set_encflags(root, encctx, encctxlen, true); + if (err) + CWARN("%s: cannot set enc ctx for "DFID": rc = %d\n", + sbi->ll_fsname, + PFID(&sbi->ll_root_fid), err); + } + ptlrpc_req_finished(request); + + checksum = test_bit(LL_SBI_CHECKSUM, sbi->ll_flags); if (sbi->ll_checksum_set) { err = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM), KEY_CHECKSUM, @@ -885,183 +911,196 @@ void ll_kill_super(struct super_block *sb) EXIT; } -static inline int ll_set_opt(const char *opt, char *data, int fl) +/* Since we use this table for ll_sbi_flags_seq_show make + * sure what you want displayed for a specific token that + * is listed more than once below be listed first. For + * example we want "checksum" displayed, not "nochecksum" + * for the sbi_flags. + */ +static const match_table_t ll_sbi_flags_name = { + {LL_SBI_NOLCK, "nolock"}, + {LL_SBI_CHECKSUM, "checksum"}, + {LL_SBI_CHECKSUM, "nochecksum"}, + {LL_SBI_LOCALFLOCK, "localflock"}, + {LL_SBI_FLOCK, "flock"}, + {LL_SBI_FLOCK, "noflock"}, + {LL_SBI_USER_XATTR, "user_xattr"}, + {LL_SBI_USER_XATTR, "nouser_xattr"}, + {LL_SBI_LRU_RESIZE, "lruresize"}, + {LL_SBI_LRU_RESIZE, "nolruresize"}, + {LL_SBI_LAZYSTATFS, "lazystatfs"}, + {LL_SBI_LAZYSTATFS, "nolazystatfs"}, + {LL_SBI_32BIT_API, "32bitapi"}, + {LL_SBI_USER_FID2PATH, "user_fid2path"}, + {LL_SBI_USER_FID2PATH, "nouser_fid2path"}, + {LL_SBI_VERBOSE, "verbose"}, + {LL_SBI_VERBOSE, "noverbose"}, + {LL_SBI_ALWAYS_PING, "always_ping"}, + {LL_SBI_TEST_DUMMY_ENCRYPTION, "test_dummy_encryption"}, + {LL_SBI_ENCRYPT, "encrypt"}, + {LL_SBI_ENCRYPT, "noencrypt"}, + {LL_SBI_FOREIGN_SYMLINK, "foreign_symlink=%s"}, + {LL_SBI_NUM_MOUNT_OPT, NULL}, + + {LL_SBI_ACL, "acl"}, + {LL_SBI_AGL_ENABLED, "agl"}, + {LL_SBI_64BIT_HASH, "64bit_hash"}, + {LL_SBI_LAYOUT_LOCK, "layout"}, + {LL_SBI_XATTR_CACHE, "xattr_cache"}, + {LL_SBI_NOROOTSQUASH, "norootsquash"}, + {LL_SBI_FAST_READ, "fast_read"}, + {LL_SBI_FILE_SECCTX, "file_secctx"}, + {LL_SBI_TINY_WRITE, "tiny_write"}, + {LL_SBI_FILE_HEAT, "file_heat"}, + {LL_SBI_PARALLEL_DIO, "parallel_dio"}, +}; + +int ll_sbi_flags_seq_show(struct seq_file *m, void *v) { - if (strncmp(opt, data, strlen(opt)) != 0) - return 0; - else - return fl; + struct super_block *sb = m->private; + int i; + + for (i = 0; i < LL_SBI_NUM_FLAGS; i++) { + int j; + + if (!test_bit(i, ll_s2sbi(sb)->ll_flags)) + continue; + + for (j = 0; j < ARRAY_SIZE(ll_sbi_flags_name); j++) { + if (ll_sbi_flags_name[j].token == i && + ll_sbi_flags_name[j].pattern) { + seq_printf(m, "%s ", + ll_sbi_flags_name[j].pattern); + break; + } + } + } + seq_puts(m, "\b\n"); + return 0; } /* non-client-specific mount options are parsed in lmd_parse */ -static int ll_options(char *options, struct ll_sb_info *sbi) +static int ll_options(char *options, struct super_block *sb) { - int tmp; - char *s1 = options, *s2; - int *flags = &sbi->ll_flags; - ENTRY; + struct ll_sb_info *sbi = ll_s2sbi(sb); + char *s2, *s1, *opts; + ENTRY; if (!options) RETURN(0); + /* Don't stomp on lmd_opts */ + opts = kstrdup(options, GFP_KERNEL); + if (!opts) + RETURN(-ENOMEM); + s1 = opts; + s2 = opts; + CDEBUG(D_CONFIG, "Parsing opts %s\n", options); - while (*s1) { + while ((s1 = strsep(&opts, ",")) != NULL) { + substring_t args[MAX_OPT_ARGS]; + bool turn_off = false; + int token; + + if (!*s1) + continue; + CDEBUG(D_SUPER, "next opt=%s\n", s1); - tmp = ll_set_opt("nolock", s1, LL_SBI_NOLCK); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("flock", s1, LL_SBI_FLOCK); - if (tmp) { - *flags = (*flags & ~LL_SBI_LOCALFLOCK) | tmp; - goto next; - } - tmp = ll_set_opt("localflock", s1, LL_SBI_LOCALFLOCK); - if (tmp) { - *flags = (*flags & ~LL_SBI_FLOCK) | tmp; - goto next; - } - tmp = ll_set_opt("noflock", s1, LL_SBI_FLOCK|LL_SBI_LOCALFLOCK); - if (tmp) { - *flags &= ~tmp; - goto next; - } - tmp = ll_set_opt("user_xattr", s1, LL_SBI_USER_XATTR); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("nouser_xattr", s1, LL_SBI_USER_XATTR); - if (tmp) { - *flags &= ~tmp; - goto next; - } - tmp = ll_set_opt("context", s1, 1); - if (tmp) - goto next; - tmp = ll_set_opt("fscontext", s1, 1); - if (tmp) - goto next; - tmp = ll_set_opt("defcontext", s1, 1); - if (tmp) - goto next; - tmp = ll_set_opt("rootcontext", s1, 1); - if (tmp) - goto next; - tmp = ll_set_opt("user_fid2path", s1, LL_SBI_USER_FID2PATH); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("nouser_fid2path", s1, LL_SBI_USER_FID2PATH); - 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; + if (strncmp(s1, "no", 2) == 0) + turn_off = true; + + /* + * Initialize args struct so we know whether arg was + * found; some options take optional arguments. + */ + args[0].to = NULL; + args[0].from = NULL; + token = match_token(s1, ll_sbi_flags_name, args); + if (token == LL_SBI_NUM_MOUNT_OPT) { + if (match_wildcard("context", s1) || + match_wildcard("fscontext", s1) || + match_wildcard("defcontext", s1) || + match_wildcard("rootcontext",s1)) + continue; + + LCONSOLE_ERROR_MSG(0x152, + "Unknown option '%s', won't mount.\n", + s1); + RETURN(-EINVAL); } - tmp = ll_set_opt("nochecksum", s1, LL_SBI_CHECKSUM); - if (tmp) { - *flags &= ~tmp; + + switch (token) { + case LL_SBI_NOLCK: + case LL_SBI_32BIT_API: + case LL_SBI_64BIT_HASH: + case LL_SBI_ALWAYS_PING: + set_bit(token, sbi->ll_flags); + break; + + case LL_SBI_FLOCK: + clear_bit(LL_SBI_LOCALFLOCK, sbi->ll_flags); + if (turn_off) + clear_bit(LL_SBI_FLOCK, sbi->ll_flags); + else + set_bit(token, sbi->ll_flags); + break; + + case LL_SBI_LOCALFLOCK: + clear_bit(LL_SBI_FLOCK, sbi->ll_flags); + set_bit(token, sbi->ll_flags); + break; + + case LL_SBI_CHECKSUM: sbi->ll_checksum_set = 1; - goto next; - } - tmp = ll_set_opt("lruresize", s1, LL_SBI_LRU_RESIZE); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("nolruresize", s1, LL_SBI_LRU_RESIZE); - if (tmp) { - *flags &= ~tmp; - goto next; - } - tmp = ll_set_opt("lazystatfs", s1, LL_SBI_LAZYSTATFS); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("nolazystatfs", s1, LL_SBI_LAZYSTATFS); - if (tmp) { - *flags &= ~tmp; - goto next; - } - tmp = ll_set_opt("32bitapi", s1, LL_SBI_32BIT_API); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("verbose", s1, LL_SBI_VERBOSE); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("noverbose", s1, LL_SBI_VERBOSE); - if (tmp) { - *flags &= ~tmp; - goto next; - } - tmp = ll_set_opt("always_ping", s1, LL_SBI_ALWAYS_PING); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("test_dummy_encryption", s1, - LL_SBI_TEST_DUMMY_ENCRYPTION); - if (tmp) { + /* fall through */ + case LL_SBI_USER_XATTR: + case LL_SBI_USER_FID2PATH: + case LL_SBI_LRU_RESIZE: + case LL_SBI_LAZYSTATFS: + case LL_SBI_VERBOSE: + if (turn_off) + clear_bit(token, sbi->ll_flags); + else + set_bit(token, sbi->ll_flags); + break; + case LL_SBI_TEST_DUMMY_ENCRYPTION: { #ifdef HAVE_LUSTRE_CRYPTO - *flags |= tmp; + set_bit(token, sbi->ll_flags); #else LCONSOLE_WARN("Test dummy encryption mount option ignored: encryption not supported\n"); #endif - goto next; + break; } - tmp = ll_set_opt("noencrypt", s1, LL_SBI_ENCRYPT); - if (tmp) { + case LL_SBI_ENCRYPT: #ifdef HAVE_LUSTRE_CRYPTO - *flags &= ~tmp; + if (turn_off) + clear_bit(token, sbi->ll_flags); + else + set_bit(token, sbi->ll_flags); #else - LCONSOLE_WARN("noencrypt mount option ignored: encryption not supported\n"); + LCONSOLE_WARN("noencrypt or encrypt mount option ignored: encryption not supported\n"); #endif - goto next; - } - tmp = ll_set_opt("foreign_symlink", s1, LL_SBI_FOREIGN_SYMLINK); - if (tmp) { - int prefix_pos = sizeof("foreign_symlink=") - 1; - int equal_pos = sizeof("foreign_symlink=") - 2; - + break; + case LL_SBI_FOREIGN_SYMLINK: /* non-default prefix provided ? */ - if (strlen(s1) >= sizeof("foreign_symlink=") && - *(s1 + equal_pos) == '=') { - char *old = sbi->ll_foreign_symlink_prefix; - size_t old_len = - sbi->ll_foreign_symlink_prefix_size; + if (args->from) { + size_t old_len; + char *old; /* path must be absolute */ - if (*(s1 + sizeof("foreign_symlink=") - - 1) != '/') { + if (args->from[0] != '/') { LCONSOLE_ERROR_MSG(0x152, - "foreign prefix '%s' must be an absolute path\n", - s1 + prefix_pos); + "foreign prefix '%s' must be an absolute path\n", + args->from); RETURN(-EINVAL); } - /* last option ? */ - s2 = strchrnul(s1 + prefix_pos, ','); - if (sbi->ll_foreign_symlink_prefix) { - sbi->ll_foreign_symlink_prefix = NULL; - sbi->ll_foreign_symlink_prefix_size = 0; - } + old_len = sbi->ll_foreign_symlink_prefix_size; + old = sbi->ll_foreign_symlink_prefix; /* alloc for path length and '\0' */ - OBD_ALLOC(sbi->ll_foreign_symlink_prefix, - s2 - (s1 + prefix_pos) + 1); + sbi->ll_foreign_symlink_prefix = match_strdup(args); if (!sbi->ll_foreign_symlink_prefix) { /* restore previous */ sbi->ll_foreign_symlink_prefix = old; @@ -1069,32 +1108,26 @@ static int ll_options(char *options, struct ll_sb_info *sbi) old_len; RETURN(-ENOMEM); } + sbi->ll_foreign_symlink_prefix_size = + args->to - args->from + 1; + OBD_ALLOC_POST(sbi->ll_foreign_symlink_prefix, + sbi->ll_foreign_symlink_prefix_size, + "kmalloced"); if (old) OBD_FREE(old, old_len); - strncpy(sbi->ll_foreign_symlink_prefix, - s1 + prefix_pos, - s2 - (s1 + prefix_pos)); - sbi->ll_foreign_symlink_prefix_size = - s2 - (s1 + prefix_pos) + 1; + + /* enable foreign symlink support */ + set_bit(token, sbi->ll_flags); } else { LCONSOLE_ERROR_MSG(0x152, "invalid %s option\n", s1); } - /* enable foreign symlink support */ - *flags |= tmp; - goto next; + /* fall through */ + default: + break; } - LCONSOLE_ERROR_MSG(0x152, "Unknown option '%s', won't mount.\n", - s1); - RETURN(-EINVAL); - -next: - /* Find next opt */ - s2 = strchr(s1, ','); - if (s2 == NULL) - break; - s1 = s2 + 1; } + kfree(opts); RETURN(0); } @@ -1102,7 +1135,7 @@ void ll_lli_init(struct ll_inode_info *lli) { lli->lli_inode_magic = LLI_INODE_MAGIC; lli->lli_flags = 0; - spin_lock_init(&lli->lli_lock); + rwlock_init(&lli->lli_lock); lli->lli_posix_acl = NULL; /* Do not set lli_fid, it has been initialized already. */ fid_zero(&lli->lli_pfid); @@ -1154,6 +1187,8 @@ void ll_lli_init(struct ll_inode_info *lli) } mutex_init(&lli->lli_layout_mutex); memset(lli->lli_jobid, 0, sizeof(lli->lli_jobid)); + /* ll_cl_context initialize */ + INIT_LIST_HEAD(&lli->lli_lccs); } #define MAX_STRING_SIZE 128 @@ -1227,7 +1262,7 @@ int ll_fill_super(struct super_block *sb) if (IS_ERR(sbi)) GOTO(out_free_cfg, err = PTR_ERR(sbi)); - err = ll_options(lsi->lsi_lmd->lmd_opts, sbi); + err = ll_options(lsi->lsi_lmd->lmd_opts, sb); if (err) GOTO(out_free_cfg, err); @@ -1267,6 +1302,9 @@ int ll_fill_super(struct super_block *sb) if (err) GOTO(out_free_cfg, err); + /* disable kernel readahead */ + sb->s_bdi->ra_pages = 0; + /* Call ll_debugfs_register_super() before lustre_process_log() * so that "llite.*.*" params can be processed correctly. */ @@ -1337,7 +1375,7 @@ out_free_cfg: if (err) ll_put_super(sb); - else if (sbi->ll_flags & LL_SBI_VERBOSE) + else if (test_bit(LL_SBI_VERBOSE, sbi->ll_flags)) LCONSOLE_WARN("Mounted %s\n", profilenm); RETURN(err); } /* ll_fill_super */ @@ -1404,7 +1442,7 @@ void ll_put_super(struct super_block *sb) while ((obd = class_devices_in_group(&sbi->ll_sb_uuid, &next))) class_manual_cleanup(obd); - if (sbi->ll_flags & LL_SBI_VERBOSE) + if (test_bit(LL_SBI_VERBOSE, sbi->ll_flags)) LCONSOLE_WARN("Unmounted %s\n", profilenm ? profilenm : ""); if (profilenm) @@ -1473,13 +1511,16 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb, const struct lu_fid *fid, struct lustre_md *md) { - struct ll_sb_info *sbi = ll_s2sbi(sb); - struct mdt_body *body = md->body; - struct inode *inode; - ino_t ino; + struct ll_sb_info *sbi = ll_s2sbi(sb); + struct ll_inode_info *lli; + struct mdt_body *body = md->body; + struct inode *inode; + ino_t ino; + ENTRY; - ino = cl_fid_build_ino(fid, sbi->ll_flags & LL_SBI_32BIT_API); + LASSERT(md->lmv); + ino = cl_fid_build_ino(fid, test_bit(LL_SBI_32BIT_API, sbi->ll_flags)); inode = iget_locked(sb, ino); if (inode == NULL) { CERROR("%s: failed get simple inode "DFID": rc = -ENOENT\n", @@ -1487,10 +1528,8 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb, RETURN(ERR_PTR(-ENOENT)); } + lli = ll_i2info(inode); if (inode->i_state & I_NEW) { - struct ll_inode_info *lli = ll_i2info(inode); - struct lmv_stripe_md *lsm = md->lmv; - inode->i_mode = (inode->i_mode & ~S_IFMT) | (body->mbo_mode & S_IFMT); LASSERTF(S_ISDIR(inode->i_mode), "Not slave inode "DFID"\n", @@ -1511,12 +1550,17 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb, lli->lli_fid = *fid; ll_lli_init(lli); - LASSERT(lsm != NULL); /* master object FID */ lli->lli_pfid = body->mbo_fid1; CDEBUG(D_INODE, "lli %p slave "DFID" master "DFID"\n", lli, PFID(fid), PFID(&lli->lli_pfid)); unlock_new_inode(inode); + } else { + /* in directory restripe/auto-split, a directory will be + * transformed to a stripe if it's plain, set its pfid here, + * otherwise ll_lock_cancel_bits() can't find the master inode. + */ + lli->lli_pfid = body->mbo_fid1; } RETURN(inode); @@ -1575,6 +1619,8 @@ static void ll_update_default_lsm_md(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); + ENTRY; + if (!md->default_lmv) { /* clear default lsm */ if (lli->lli_default_lsm_md) { @@ -1585,30 +1631,28 @@ static void ll_update_default_lsm_md(struct inode *inode, struct lustre_md *md) } up_write(&lli->lli_lsm_sem); } - } else if (lli->lli_default_lsm_md) { - /* update default lsm if it changes */ + RETURN_EXIT; + } + + if (lli->lli_default_lsm_md) { + /* do nonthing if default lsm isn't changed */ down_read(&lli->lli_lsm_sem); if (lli->lli_default_lsm_md && - !lsm_md_eq(lli->lli_default_lsm_md, md->default_lmv)) { - up_read(&lli->lli_lsm_sem); - down_write(&lli->lli_lsm_sem); - if (lli->lli_default_lsm_md) - lmv_free_memmd(lli->lli_default_lsm_md); - lli->lli_default_lsm_md = md->default_lmv; - lsm_md_dump(D_INODE, md->default_lmv); - md->default_lmv = NULL; - up_write(&lli->lli_lsm_sem); - } else { + lsm_md_eq(lli->lli_default_lsm_md, md->default_lmv)) { up_read(&lli->lli_lsm_sem); + RETURN_EXIT; } - } else { - /* init default lsm */ - down_write(&lli->lli_lsm_sem); - lli->lli_default_lsm_md = md->default_lmv; - lsm_md_dump(D_INODE, md->default_lmv); - md->default_lmv = NULL; - up_write(&lli->lli_lsm_sem); + up_read(&lli->lli_lsm_sem); } + + down_write(&lli->lli_lsm_sem); + if (lli->lli_default_lsm_md) + lmv_free_memmd(lli->lli_default_lsm_md); + lli->lli_default_lsm_md = md->default_lmv; + lsm_md_dump(D_INODE, md->default_lmv); + md->default_lmv = NULL; + up_write(&lli->lli_lsm_sem); + RETURN_EXIT; } static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) @@ -1628,6 +1672,12 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) if (md->default_lmv) ll_update_default_lsm_md(inode, md); + /* after dir migration/restripe, a stripe may be turned into a + * directory, in this case, zero out its lli_pfid. + */ + if (unlikely(fid_is_norm(&lli->lli_pfid))) + fid_zero(&lli->lli_pfid); + /* * no striped information from request, lustre_md from req does not * include stripeEA, see ll_md_setattr() @@ -1778,17 +1828,29 @@ void ll_clear_inode(struct inode *inode) static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data) { - struct lustre_md md; - struct inode *inode = dentry->d_inode; - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ptlrpc_request *request = NULL; - int rc, ia_valid; - ENTRY; + struct lustre_md md; + struct inode *inode = dentry->d_inode; + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ptlrpc_request *request = NULL; + int rc, ia_valid; + + ENTRY; + + op_data = ll_prep_md_op_data(op_data, inode, NULL, NULL, 0, 0, + LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + RETURN(PTR_ERR(op_data)); + + /* If this is a chgrp of a regular file, we want to reserve enough + * quota to cover the entire file size. + */ + if (S_ISREG(inode->i_mode) && op_data->op_attr.ia_valid & ATTR_GID && + from_kgid(&init_user_ns, op_data->op_attr.ia_gid) != + from_kgid(&init_user_ns, inode->i_gid)) { + op_data->op_xvalid |= OP_XVALID_BLOCKS; + op_data->op_attr_blocks = inode->i_blocks; + } - op_data = ll_prep_md_op_data(op_data, inode, NULL, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - RETURN(PTR_ERR(op_data)); rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, &request); if (rc) { @@ -1801,7 +1863,8 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data) !S_ISDIR(inode->i_mode)) { ia_valid = op_data->op_attr.ia_valid; op_data->op_attr.ia_valid &= ~TIMES_SET_FLAGS; - rc = simple_setattr(dentry, &op_data->op_attr); + rc = simple_setattr(&init_user_ns, dentry, + &op_data->op_attr); op_data->op_attr.ia_valid = ia_valid; } } else if (rc != -EPERM && rc != -EACCES && rc != -ETXTBSY) { @@ -1810,8 +1873,8 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data) RETURN(rc); } - rc = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp, - sbi->ll_md_exp, &md); + rc = md_get_lustre_md(sbi->ll_md_exp, &request->rq_pill, sbi->ll_dt_exp, + sbi->ll_md_exp, &md); if (rc) { ptlrpc_req_finished(request); RETURN(rc); @@ -1823,7 +1886,7 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data) op_data->op_attr.ia_valid &= ~(TIMES_SET_FLAGS | ATTR_SIZE); if (S_ISREG(inode->i_mode)) inode_lock(inode); - rc = simple_setattr(dentry, &op_data->op_attr); + rc = simple_setattr(&init_user_ns, dentry, &op_data->op_attr); if (S_ISREG(inode->i_mode)) inode_unlock(inode); op_data->op_attr.ia_valid = ia_valid; @@ -1954,7 +2017,7 @@ int ll_io_zero_page(struct inode *inode, pgoff_t index, pgoff_t offset, anchor = &vvp_env_info(env)->vti_anchor; cl_sync_io_init(anchor, 1); clpage->cp_sync_io = anchor; - cl_2queue_add(queue, clpage); + cl_2queue_add(queue, clpage, true); rc = cl_io_submit_rw(env, io, CRT_WRITE, queue); if (rc) GOTO(queuefini1, rc); @@ -1990,6 +2053,44 @@ putenv: RETURN(rc); } +/** + * Get reference file from volatile file name. + * Volatile file name may look like: + * /LUSTRE_VOLATILE_HDR:::fd= + * where fd is opened descriptor of reference file. + * + * \param[in] volatile_name volatile file name + * \param[in] volatile_len volatile file name length + * \param[out] ref_file pointer to struct file of reference file + * + * \retval 0 on success + * \retval negative errno on failure + */ +int volatile_ref_file(const char *volatile_name, int volatile_len, + struct file **ref_file) +{ + char *p, *q, *fd_str; + int fd, rc; + + p = strnstr(volatile_name, ":fd=", volatile_len); + if (!p || strlen(p + 4) == 0) + return -EINVAL; + + q = strchrnul(p + 4, ':'); + fd_str = kstrndup(p + 4, q - p - 4, GFP_NOFS); + if (!fd_str) + return -ENOMEM; + rc = kstrtouint(fd_str, 10, &fd); + kfree(fd_str); + if (rc) + return -EINVAL; + + *ref_file = fget(fd); + if (!(*ref_file)) + return -EINVAL; + return 0; +} + /* If this inode has objects allocated to it (lsm != NULL), then the OST * object(s) determine the file size and mtime. Otherwise, the MDS will * keep these values until such a time that objects are allocated for it. @@ -2131,8 +2232,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, * it is necessary due to possible time * de-synchronization between MDT inode and OST objects */ - if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode) && - attr->ia_valid & ATTR_SIZE) { + if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) { xvalid |= OP_XVALID_FLAGS; flags = LUSTRE_ENCRYPT_FL; /* Call to ll_io_zero_page is not necessary if @@ -2141,7 +2241,8 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, * In case of Direct IO, all we need is to set * new size. */ - if (attr->ia_size & ~PAGE_MASK && + if (attr->ia_valid & ATTR_SIZE && + attr->ia_size & ~PAGE_MASK && !(attr->ia_valid & ATTR_FILE && attr->ia_file->f_flags & O_DIRECT)) { pgoff_t offset = @@ -2153,6 +2254,55 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, if (rc) GOTO(out, rc); } + /* If encrypted volatile file without the key, + * we need to fetch size from reference file, + * and set it on OST objects. This happens when + * migrating or extending an encrypted file + * without the key. + */ + if (filename_is_volatile(dentry->d_name.name, + dentry->d_name.len, + NULL) && + llcrypt_require_key(inode) == -ENOKEY) { + struct file *ref_file; + struct inode *ref_inode; + struct ll_inode_info *ref_lli; + struct cl_object *ref_obj; + struct cl_attr ref_attr = { 0 }; + struct lu_env *env; + __u16 refcheck; + + rc = volatile_ref_file( + dentry->d_name.name, + dentry->d_name.len, + &ref_file); + if (rc) + GOTO(out, rc); + + ref_inode = file_inode(ref_file); + if (!ref_inode) { + fput(ref_file); + GOTO(out, rc = -EINVAL); + } + + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + GOTO(out, rc = PTR_ERR(env)); + + ref_lli = ll_i2info(ref_inode); + ref_obj = ref_lli->lli_clob; + cl_object_attr_lock(ref_obj); + rc = cl_object_attr_get(env, ref_obj, + &ref_attr); + cl_object_attr_unlock(ref_obj); + cl_env_put(env, &refcheck); + fput(ref_file); + if (rc) + GOTO(out, rc); + + attr->ia_valid |= ATTR_SIZE; + attr->ia_size = ref_attr.cat_size; + } } rc = cl_setattr_ost(lli->lli_clob, attr, xvalid, flags); } @@ -2211,10 +2361,11 @@ out: LPROC_LL_TRUNC : LPROC_LL_SETATTR, ktime_us_delta(ktime_get(), kstart)); - return rc; + RETURN(rc); } -int ll_setattr(struct dentry *de, struct iattr *attr) +int ll_setattr(struct user_namespace *mnt_userns, struct dentry *de, + struct iattr *attr) { int mode = de->d_inode->i_mode; enum op_xvalid xvalid = 0; @@ -2260,7 +2411,7 @@ int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs, ENTRY; max_age = ktime_get_seconds() - sbi->ll_statfs_max_age; - if (sbi->ll_flags & LL_SBI_LAZYSTATFS) + if (test_bit(LL_SBI_LAZYSTATFS, sbi->ll_flags)) flags |= OBD_STATFS_NODELAY; rc = obd_statfs(NULL, sbi->ll_md_exp, osfs, max_age, flags); @@ -2314,7 +2465,7 @@ static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs) int ret; qctl.qc_id = ll_i2info(inode)->lli_projid; - ret = quotactl_ioctl(ll_i2sbi(inode), &qctl); + ret = quotactl_ioctl(inode->i_sb, &qctl); if (ret) { /* ignore errors if project ID does not have * a quota limit or feature unsupported. @@ -2428,6 +2579,7 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) struct ll_inode_info *lli = ll_i2info(inode); struct mdt_body *body = md->body; struct ll_sb_info *sbi = ll_i2sbi(inode); + bool api32; int rc = 0; if (body->mbo_valid & OBD_MD_FLEASIZE) { @@ -2445,8 +2597,8 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) if (body->mbo_valid & OBD_MD_FLACL) lli_replace_acl(lli, md); - inode->i_ino = cl_fid_build_ino(&body->mbo_fid1, - sbi->ll_flags & LL_SBI_32BIT_API); + api32 = test_bit(LL_SBI_32BIT_API, sbi->ll_flags); + inode->i_ino = cl_fid_build_ino(&body->mbo_fid1, api32); inode->i_generation = cl_fid_build_gen(&body->mbo_fid1); if (body->mbo_valid & OBD_MD_FLATIME) { @@ -2493,8 +2645,11 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) inode->i_gid = make_kgid(&init_user_ns, body->mbo_gid); if (body->mbo_valid & OBD_MD_FLPROJID) lli->lli_projid = body->mbo_projid; - if (body->mbo_valid & OBD_MD_FLNLINK) + if (body->mbo_valid & OBD_MD_FLNLINK) { + spin_lock(&inode->i_lock); set_nlink(inode, body->mbo_nlink); + spin_unlock(&inode->i_lock); + } if (body->mbo_valid & OBD_MD_FLRDEV) inode->i_rdev = old_decode_dev(body->mbo_rdev); @@ -2513,7 +2668,15 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) LASSERT(fid_seq(&lli->lli_fid) != 0); - lli->lli_attr_valid = body->mbo_valid; + /* In case of encrypted file without the key, please do not lose + * clear text size stored into lli_lazysize in ll_merge_attr(), + * we will need it in ll_prepare_close(). + */ + if (lli->lli_attr_valid & OBD_MD_FLLAZYSIZE && lli->lli_lazysize && + llcrypt_require_key(inode) == -ENOKEY) + lli->lli_attr_valid = body->mbo_valid | OBD_MD_FLLAZYSIZE; + else + lli->lli_attr_valid = body->mbo_valid; if (body->mbo_valid & OBD_MD_FLSIZE) { i_size_write(inode, body->mbo_size); @@ -2544,6 +2707,51 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) return 0; } +/* update directory depth to ROOT, called after LOOKUP lock is fetched. */ +void ll_update_dir_depth(struct inode *dir, struct inode *inode) +{ + struct ll_inode_info *lli; + + if (!S_ISDIR(inode->i_mode)) + return; + + if (inode == dir) + return; + + lli = ll_i2info(inode); + lli->lli_dir_depth = ll_i2info(dir)->lli_dir_depth + 1; + CDEBUG(D_INODE, DFID" depth %hu\n", + PFID(&lli->lli_fid), lli->lli_dir_depth); +} + +void ll_truncate_inode_pages_final(struct inode *inode) +{ + struct address_space *mapping = &inode->i_data; + unsigned long nrpages; + unsigned long flags; + + truncate_inode_pages_final(mapping); + + /* 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) { + ll_xa_lock_irqsave(&mapping->i_pages, flags); + nrpages = mapping->nrpages; + ll_xa_unlock_irqrestore(&mapping->i_pages, flags); + } /* Workaround end */ + + LASSERTF(nrpages == 0, "%s: inode="DFID"(%p) nrpages=%lu, " + "see https://jira.whamcloud.com/browse/LU-118\n", + ll_i2sbi(inode)->ll_fsname, + PFID(ll_inode2fid(inode)), inode, nrpages); +} + int ll_read_inode2(struct inode *inode, void *opaque) { struct lustre_md *md = opaque; @@ -2601,10 +2809,6 @@ 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; - unsigned long flags; - ENTRY; if (S_ISREG(inode->i_mode) && lli->lli_clob != NULL) { @@ -2618,27 +2822,8 @@ void ll_delete_inode(struct inode *inode) cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, inode->i_nlink ? CL_FSYNC_LOCAL : CL_FSYNC_DISCARD, 1); } - truncate_inode_pages_final(mapping); - - /* 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) { - ll_xa_lock_irqsave(&mapping->i_pages, flags); - nrpages = mapping->nrpages; - ll_xa_unlock_irqrestore(&mapping->i_pages, flags); - } /* Workaround end */ - - LASSERTF(nrpages == 0, "%s: inode="DFID"(%p) nrpages=%lu, " - "see https://jira.whamcloud.com/browse/LU-118\n", - ll_i2sbi(inode)->ll_fsname, - PFID(ll_inode2fid(inode)), inode, nrpages); + ll_truncate_inode_pages_final(inode); ll_clear_inode(inode); clear_inode(inode); @@ -2695,7 +2880,8 @@ int ll_iocontrol(struct inode *inode, struct file *file, if (flags & LUSTRE_PROJINHERIT_FL) fa.fsx_xflags = FS_XFLAG_PROJINHERIT; - rc = ll_ioctl_check_project(inode, &fa); + rc = ll_ioctl_check_project(inode, fa.fsx_xflags, + fa.fsx_projid); if (rc) RETURN(rc); @@ -2830,7 +3016,7 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data) else sb->s_flags &= ~SB_RDONLY; - if (sbi->ll_flags & LL_SBI_VERBOSE) + if (test_bit(LL_SBI_VERBOSE, sbi->ll_flags)) LCONSOLE_WARN("Remounted %s %s\n", profilenm, read_only ? "read-only" : "read-write"); } @@ -2852,7 +3038,7 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data) * \param[in] sb super block for this file-system * \param[in] open_req pointer to the original open request */ -void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req) +void ll_open_cleanup(struct super_block *sb, struct req_capsule *pill) { struct mdt_body *body; struct md_op_data *op_data; @@ -2860,7 +3046,7 @@ void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req) struct obd_export *exp = ll_s2sbi(sb)->ll_md_exp; ENTRY; - body = req_capsule_server_get(&open_req->rq_pill, &RMF_MDT_BODY); + body = req_capsule_server_get(pill, &RMF_MDT_BODY); OBD_ALLOC_PTR(op_data); if (op_data == NULL) { CWARN("%s: cannot allocate op_data to release open handle for " @@ -2879,7 +3065,7 @@ void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req) EXIT; } -int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, +int ll_prep_inode(struct inode **inode, struct req_capsule *pill, struct super_block *sb, struct lookup_intent *it) { struct ll_sb_info *sbi = NULL; @@ -2891,7 +3077,7 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, LASSERT(*inode || sb); sbi = sb ? ll_s2sbi(sb) : ll_i2sbi(*inode); - rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp, + rc = md_get_lustre_md(sbi->ll_md_exp, pill, sbi->ll_dt_exp, sbi->ll_md_exp, &md); if (rc != 0) GOTO(out, rc); @@ -2910,22 +3096,22 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, if (rc != 0) GOTO(out, rc); } else { + bool api32 = test_bit(LL_SBI_32BIT_API, sbi->ll_flags); + struct lu_fid *fid1 = &md.body->mbo_fid1; + LASSERT(sb != NULL); /* * At this point server returns to client's same fid as client * generated for creating. So using ->fid1 is okay here. */ - if (!fid_is_sane(&md.body->mbo_fid1)) { + if (!fid_is_sane(fid1)) { CERROR("%s: Fid is insane "DFID"\n", - sbi->ll_fsname, - PFID(&md.body->mbo_fid1)); + sbi->ll_fsname, PFID(fid1)); GOTO(out, rc = -EINVAL); } - *inode = ll_iget(sb, cl_fid_build_ino(&md.body->mbo_fid1, - sbi->ll_flags & LL_SBI_32BIT_API), - &md); + *inode = ll_iget(sb, cl_fid_build_ino(fid1, api32), &md); if (IS_ERR(*inode)) { lmd_clear_acl(&md); rc = IS_ERR(*inode) ? PTR_ERR(*inode) : -ENOMEM; @@ -2981,7 +3167,7 @@ out: if (rc != 0 && it != NULL && it->it_op & IT_OPEN) { ll_intent_drop_lock(it); - ll_open_cleanup(sb != NULL ? sb : (*inode)->i_sb, req); + ll_open_cleanup(sb != NULL ? sb : (*inode)->i_sb, pill); } return rc; @@ -3054,6 +3240,9 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, __u32 mode, enum md_op_code opc, void *data) { + struct llcrypt_name fname = { 0 }; + int rc; + LASSERT(i1 != NULL); if (name == NULL) { @@ -3061,7 +3250,9 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, if (namelen != 0) return ERR_PTR(-EINVAL); } else { - if (namelen > ll_i2sbi(i1)->ll_namelen) + if ((!IS_ENCRYPTED(i1) || + (opc != LUSTRE_OPC_LOOKUP && opc != LUSTRE_OPC_CREATE)) && + namelen > ll_i2sbi(i1)->ll_namelen) return ERR_PTR(-ENAMETOOLONG); /* "/" is not valid name, but it's allowed */ @@ -3078,7 +3269,6 @@ 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_code = opc; if (S_ISDIR(i1->i_mode)) { down_read_non_owner(&ll_i2info(i1)->lli_lsm_sem); @@ -3104,19 +3294,67 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, fid_zero(&op_data->op_fid2); } - if (ll_i2sbi(i1)->ll_flags & LL_SBI_64BIT_HASH) + if (test_bit(LL_SBI_64BIT_HASH, ll_i2sbi(i1)->ll_flags)) op_data->op_cli_flags |= CLI_HASH64; if (ll_need_32bit_api(ll_i2sbi(i1))) op_data->op_cli_flags |= CLI_API32; - op_data->op_name = name; - op_data->op_namelen = namelen; + if ((i2 && is_root_inode(i2)) || + opc == LUSTRE_OPC_LOOKUP || opc == LUSTRE_OPC_CREATE) { + /* In case of lookup, ll_setup_filename() has already been + * called in ll_lookup_it(), so just take provided name. + * Also take provided name if we are dealing with root inode. + */ + fname.disk_name.name = (unsigned char *)name; + fname.disk_name.len = namelen; + } else if (name && namelen) { + struct qstr dname = QSTR_INIT(name, namelen); + struct inode *dir; + struct lu_fid *pfid = NULL; + struct lu_fid fid; + int lookup; + + if (!S_ISDIR(i1->i_mode) && i2 && S_ISDIR(i2->i_mode)) { + /* special case when called from ll_link() */ + dir = i2; + lookup = 0; + } else { + dir = i1; + lookup = (int)(opc == LUSTRE_OPC_ANY); + } + if (opc == LUSTRE_OPC_ANY && lookup) + pfid = &fid; + rc = ll_setup_filename(dir, &dname, lookup, &fname, pfid); + if (rc) { + ll_finish_md_op_data(op_data); + return ERR_PTR(rc); + } + if (pfid && !fid_is_zero(pfid)) { + if (i2 == NULL) + op_data->op_fid2 = fid; + op_data->op_bias = MDS_FID_OP; + } + if (fname.disk_name.name && + fname.disk_name.name != (unsigned char *)name) + /* op_data->op_name must be freed after use */ + op_data->op_flags |= MF_OPNAME_KMALLOCED; + } + + /* In fact LUSTRE_OPC_LOOKUP, LUSTRE_OPC_OPEN + * are LUSTRE_OPC_ANY + */ + if (opc == LUSTRE_OPC_LOOKUP || opc == LUSTRE_OPC_OPEN) + op_data->op_code = LUSTRE_OPC_ANY; + else + op_data->op_code = opc; + op_data->op_name = fname.disk_name.name; + op_data->op_namelen = fname.disk_name.len; op_data->op_mode = mode; 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_cap = current_cap(); op_data->op_mds = 0; if ((opc == LUSTRE_OPC_CREATE) && (name != NULL) && filename_is_volatile(name, namelen, &op_data->op_mds)) { @@ -3130,8 +3368,13 @@ 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); + ll_security_release_secctx(op_data->op_file_secctx, + op_data->op_file_secctx_size); + if (op_data->op_flags & MF_OPNAME_KMALLOCED) + /* allocated via ll_setup_filename called + * from ll_prep_md_op_data + */ + kfree(op_data->op_name); llcrypt_free_ctx(op_data->op_file_encctx, op_data->op_file_encctx_size); OBD_FREE_PTR(op_data); } @@ -3139,47 +3382,40 @@ void ll_finish_md_op_data(struct md_op_data *op_data) int ll_show_options(struct seq_file *seq, struct dentry *dentry) { struct ll_sb_info *sbi; + int i; LASSERT(seq && dentry); sbi = ll_s2sbi(dentry->d_sb); - if (sbi->ll_flags & LL_SBI_NOLCK) - seq_puts(seq, ",nolock"); + if (test_bit(LL_SBI_NOLCK, sbi->ll_flags)) + seq_puts(seq, "nolock"); - /* "flock" is the default since 2.13, but it wasn't for many years, - * so it is still useful to print this to show it is enabled. - * Start to print "noflock" so it is now clear when flock is disabled. - */ - if (sbi->ll_flags & LL_SBI_FLOCK) - seq_puts(seq, ",flock"); - else if (sbi->ll_flags & LL_SBI_LOCALFLOCK) - seq_puts(seq, ",localflock"); - else - seq_puts(seq, ",noflock"); - - if (sbi->ll_flags & LL_SBI_USER_XATTR) - seq_puts(seq, ",user_xattr"); - - if (sbi->ll_flags & LL_SBI_LAZYSTATFS) - seq_puts(seq, ",lazystatfs"); - - if (sbi->ll_flags & LL_SBI_USER_FID2PATH) - seq_puts(seq, ",user_fid2path"); - - if (sbi->ll_flags & LL_SBI_ALWAYS_PING) - seq_puts(seq, ",always_ping"); - - if (ll_sbi_has_test_dummy_encryption(sbi)) - seq_puts(seq, ",test_dummy_encryption"); - - if (ll_sbi_has_encrypt(sbi)) - seq_puts(seq, ",encrypt"); - else - seq_puts(seq, ",noencrypt"); + for (i = 1; ll_sbi_flags_name[i].token != LL_SBI_NUM_MOUNT_OPT; i++) { + /* match_table in some cases has patterns for both enabled and + * disabled cases. Ignore 'no'xxx versions if bit is set. + */ + if (test_bit(ll_sbi_flags_name[i].token, sbi->ll_flags) && + strncmp(ll_sbi_flags_name[i].pattern, "no", 2)) { + if (ll_sbi_flags_name[i].token == + LL_SBI_FOREIGN_SYMLINK) { + seq_show_option(seq, "foreign_symlink", + sbi->ll_foreign_symlink_prefix); + } else { + seq_printf(seq, ",%s", + ll_sbi_flags_name[i].pattern); + } - if (sbi->ll_flags & LL_SBI_FOREIGN_SYMLINK) { - seq_puts(seq, ",foreign_symlink="); - seq_puts(seq, sbi->ll_foreign_symlink_prefix); + /* You can have either localflock or flock but not + * both. If localflock is set don't print flock or + * noflock. + */ + if (ll_sbi_flags_name[i].token == LL_SBI_LOCALFLOCK) + i += 2; + } else if (!test_bit(ll_sbi_flags_name[i].token, sbi->ll_flags) && + !strncmp(ll_sbi_flags_name[i].pattern, "no", 2)) { + seq_printf(seq, ",%s", + ll_sbi_flags_name[i].pattern); + } } RETURN(0); @@ -3294,7 +3530,7 @@ void ll_compute_rootsquash_state(struct ll_sb_info *sbi) /* Update norootsquash flag */ spin_lock(&squash->rsi_lock); if (list_empty(&squash->rsi_nosquash_nids)) - sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH; + clear_bit(LL_SBI_NOROOTSQUASH, sbi->ll_flags); else { /* Do not apply root squash as soon as one of our NIDs is * in the nosquash_nids list */ @@ -3309,9 +3545,9 @@ void ll_compute_rootsquash_state(struct ll_sb_info *sbi) } } if (matched) - sbi->ll_flags |= LL_SBI_NOROOTSQUASH; + set_bit(LL_SBI_NOROOTSQUASH, sbi->ll_flags); else - sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH; + clear_bit(LL_SBI_NOROOTSQUASH, sbi->ll_flags); } spin_unlock(&squash->rsi_lock); } @@ -3385,7 +3621,7 @@ int ll_getparent(struct file *file, struct getparent __user *arg) ENTRY; if (!capable(CAP_DAC_READ_SEARCH) && - !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH)) + !test_bit(LL_SBI_USER_FID2PATH, ll_i2sbi(inode)->ll_flags)) RETURN(-EPERM); if (get_user(name_size, &arg->gp_name_size))