X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Fllite_lib.c;h=87159a0774c3dc5734386bebf47011784e5ba187;hp=ac626309004776e2b784010cee02885cf98aa917;hb=a8dcf372f430c308d3e96fb506563068d0a80c2d;hpb=353ef58b1d2394c4721a340e2463b07d4069d99c;ds=sidebyside diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index ac62630..87159a0 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -15,11 +15,7 @@ * * You should have received a copy of the GNU General Public License * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ @@ -27,7 +23,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2014, Intel Corporation. + * Copyright (c) 2011, 2016, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -42,6 +38,7 @@ #include #include +#include #include #include #include @@ -49,13 +46,14 @@ #ifdef HAVE_UIDGID_HEADER # include #endif +#include -#include +#include #include #include #include #include -#include +#include #include #include #include @@ -63,9 +61,6 @@ struct kmem_cache *ll_file_data_slab; -static struct list_head ll_super_blocks = LIST_HEAD_INIT(ll_super_blocks); -static DEFINE_SPINLOCK(ll_sb_lock); - #ifndef log2 #define log2(n) ffz(~(n)) #endif @@ -106,17 +101,11 @@ static struct ll_sb_info *ll_init_sbi(void) 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; - INIT_LIST_HEAD(&sbi->ll_conn_chain); - INIT_LIST_HEAD(&sbi->ll_orphan_dentry_list); ll_generate_random_uuid(uuid); class_uuid_unparse(uuid, &sbi->ll_sb_uuid); CDEBUG(D_CONFIG, "generated uuid: %s\n", sbi->ll_sb_uuid.uuid); - spin_lock(&ll_sb_lock); - list_add_tail(&sbi->ll_list, &ll_super_blocks); - spin_unlock(&ll_sb_lock); - sbi->ll_flags |= LL_SBI_VERBOSE; #ifdef ENABLE_CHECKSUM sbi->ll_flags |= LL_SBI_CHECKSUM; @@ -125,6 +114,7 @@ static struct ll_sb_info *ll_init_sbi(void) #ifdef HAVE_LRU_RESIZE_SUPPORT sbi->ll_flags |= LL_SBI_LRU_RESIZE; #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]. @@ -140,6 +130,7 @@ static struct ll_sb_info *ll_init_sbi(void) 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; /* root squash */ sbi->ll_squash.rsi_uid = 0; @@ -156,9 +147,6 @@ static void ll_free_sbi(struct super_block *sb) ENTRY; if (sbi != NULL) { - spin_lock(&ll_sb_lock); - list_del(&sbi->ll_list); - spin_unlock(&ll_sb_lock); if (!list_empty(&sbi->ll_squash.rsi_nosquash_nids)) cfs_free_nidlist(&sbi->ll_squash.rsi_nosquash_nids); if (sbi->ll_cache != NULL) { @@ -170,6 +158,12 @@ 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) { @@ -202,30 +196,36 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, RETURN(-ENOMEM); } - /* indicate the features supported by this client */ + /* indicate MDT 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 | - OBD_CONNECT_RMT_CLIENT | OBD_CONNECT_VBR | - OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH| + OBD_CONNECT_VBR | OBD_CONNECT_FULL20 | + OBD_CONNECT_64BITHASH | OBD_CONNECT_EINPROGRESS | OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | - OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS | + OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS| OBD_CONNECT_MAX_EASIZE | OBD_CONNECT_FLOCK_DEAD | OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK | OBD_CONNECT_OPEN_BY_FID | - OBD_CONNECT_DIR_STRIPE; + OBD_CONNECT_DIR_STRIPE | + OBD_CONNECT_BULK_MBITS | + OBD_CONNECT_SUBTREE | + OBD_CONNECT_FLAGS2 | OBD_CONNECT_MULTIMODRPCS; + + data->ocd_connect_flags2 = 0; #ifdef HAVE_LRU_RESIZE_SUPPORT if (sbi->ll_flags & LL_SBI_LRU_RESIZE) data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE; #endif #ifdef CONFIG_FS_POSIX_ACL - data->ocd_connect_flags |= OBD_CONNECT_ACL | OBD_CONNECT_UMASK; + data->ocd_connect_flags |= OBD_CONNECT_ACL | OBD_CONNECT_UMASK | + OBD_CONNECT_LARGE_ACL; #endif if (OBD_FAIL_CHECK(OBD_FAIL_MDC_LIGHTWEIGHT)) @@ -241,12 +241,11 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (sbi->ll_flags & LL_SBI_USER_XATTR) data->ocd_connect_flags |= OBD_CONNECT_XATTR; -#ifdef HAVE_MS_FLOCK_LOCK - /* force vfs to use lustre handler for flock() calls - bug 10743 */ - sb->s_flags |= MS_FLOCK_LOCK; -#endif -#ifdef MS_HAS_NEW_AOPS - sb->s_flags |= MS_HAS_NEW_AOPS; +#ifdef MS_NOSEC + /* Setting this indicates we correctly support S_NOSEC (See kernel + * commit 9e1f1de02c2275d7172e18dc4e7c2065777611bf) + */ + sb->s_flags |= MS_NOSEC; #endif if (sbi->ll_flags & LL_SBI_FLOCK) @@ -256,10 +255,13 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, else sbi->ll_fop = &ll_file_operations_noflock; - /* real client */ - data->ocd_connect_flags |= OBD_CONNECT_REAL; - if (sbi->ll_flags & LL_SBI_RMT_CLIENT) - data->ocd_connect_flags |= OBD_CONNECT_RMT_CLIENT_FORCE; + /* always ping even if server suppress_pings */ + 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 */ data->ocd_brw_size = MD_MAX_BRW_SIZE; @@ -306,15 +308,15 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, valid != CLIENT_CONNECT_MDT_REQD) { char *buf; - OBD_ALLOC_WAIT(buf, PAGE_CACHE_SIZE); - obd_connect_flags2str(buf, PAGE_CACHE_SIZE, - valid ^ CLIENT_CONNECT_MDT_REQD, ","); + OBD_ALLOC_WAIT(buf, PAGE_SIZE); + obd_connect_flags2str(buf, PAGE_SIZE, + valid ^ CLIENT_CONNECT_MDT_REQD, 0, ","); LCONSOLE_ERROR_MSG(0x170, "Server %s does not support " "feature(s) needed for correct operation " "of this client (%s). Please upgrade " "server or downgrade client.\n", sbi->ll_md_exp->exp_obd->obd_name, buf); - OBD_FREE(buf, PAGE_CACHE_SIZE); + OBD_FREE(buf, PAGE_SIZE); GOTO(out_md_fid, err = -EPROTO); } @@ -328,11 +330,12 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, } LASSERT(osfs->os_bsize); - sb->s_blocksize = osfs->os_bsize; - sb->s_blocksize_bits = log2(osfs->os_bsize); - sb->s_magic = LL_SUPER_MAGIC; - sb->s_maxbytes = MAX_LFS_FILESIZE; - sbi->ll_namelen = osfs->os_namelen; + sb->s_blocksize = osfs->os_bsize; + sb->s_blocksize_bits = log2(osfs->os_bsize); + sb->s_magic = LL_SUPER_MAGIC; + sb->s_maxbytes = MAX_LFS_FILESIZE; + sbi->ll_namelen = osfs->os_namelen; + sbi->ll_mnt.mnt = current->fs->root.mnt; if ((sbi->ll_flags & LL_SBI_USER_XATTR) && !(data->ocd_connect_flags & OBD_CONNECT_XATTR)) { @@ -354,35 +357,22 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_flags &= ~LL_SBI_ACL; } - if (data->ocd_connect_flags & OBD_CONNECT_RMT_CLIENT) { - if (!(sbi->ll_flags & LL_SBI_RMT_CLIENT)) { - sbi->ll_flags |= LL_SBI_RMT_CLIENT; - LCONSOLE_INFO("client is set as remote by default.\n"); - } - } else { - if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { - sbi->ll_flags &= ~LL_SBI_RMT_CLIENT; - LCONSOLE_INFO("client claims to be remote, but server " - "rejected, forced to be local.\n"); - } - } - if (data->ocd_connect_flags & OBD_CONNECT_64BITHASH) sbi->ll_flags |= LL_SBI_64BIT_HASH; - if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) - sbi->ll_md_brw_pages = data->ocd_brw_size >> PAGE_CACHE_SHIFT; - else - sbi->ll_md_brw_pages = 1; - if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; + if (obd_connect_has_secctx(data)) + sbi->ll_flags |= LL_SBI_FILE_SECCTX; + if (data->ocd_ibits_known & MDS_INODELOCK_XATTR) { if (!(data->ocd_connect_flags & OBD_CONNECT_MAX_EASIZE)) { LCONSOLE_INFO("%s: disabling xattr cache due to " "unknown maximum xattr size.\n", dt); - } else { + } 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; sbi->ll_xattr_cache_enabled = 1; } @@ -394,44 +384,70 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, GOTO(out_md_fid, err = -ENODEV); } - data->ocd_connect_flags = OBD_CONNECT_GRANT | OBD_CONNECT_VERSION | + /* 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 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 | - OBD_CONNECT_SRVLOCK | OBD_CONNECT_TRUNCLOCK| - OBD_CONNECT_AT | OBD_CONNECT_RMT_CLIENT | - OBD_CONNECT_OSS_CAPA | OBD_CONNECT_VBR| - OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH | - OBD_CONNECT_MAXBYTES | + OBD_CONNECT_CANCELSET | OBD_CONNECT_FID | + OBD_CONNECT_SRVLOCK | OBD_CONNECT_TRUNCLOCK| + OBD_CONNECT_AT | OBD_CONNECT_OSS_CAPA | + OBD_CONNECT_VBR | OBD_CONNECT_FULL20 | + OBD_CONNECT_64BITHASH | OBD_CONNECT_MAXBYTES | OBD_CONNECT_EINPROGRESS | OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK | - OBD_CONNECT_PINGLESS | OBD_CONNECT_LFSCK; + OBD_CONNECT_PINGLESS | OBD_CONNECT_LFSCK | + OBD_CONNECT_BULK_MBITS | + OBD_CONNECT_FLAGS2; + +/* 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 - if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_CKSUM)) { - /* 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 */ - data->ocd_connect_flags |= OBD_CONNECT_CKSUM; + data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD; - 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(); - } + 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 */ + 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(); #ifdef HAVE_LRU_RESIZE_SUPPORT - data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE; + data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE; #endif - if (sbi->ll_flags & LL_SBI_RMT_CLIENT) - data->ocd_connect_flags |= OBD_CONNECT_RMT_CLIENT_FORCE; + /* always ping even if server suppress_pings */ + if (sbi->ll_flags & LL_SBI_ALWAYS_PING) + data->ocd_connect_flags &= ~OBD_CONNECT_PINGLESS; - CDEBUG(D_RPCTRACE, "ocd_connect_flags: "LPX64" ocd_version: %d " - "ocd_grant: %d\n", data->ocd_connect_flags, - data->ocd_version, data->ocd_grant); + CDEBUG(D_RPCTRACE, "ocd_connect_flags: %#llx ocd_version: %d " + "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; + obd->obd_upcall.onu_owner = &sbi->ll_lco; + obd->obd_upcall.onu_upcall = cl_ocd_update; data->ocd_brw_size = DT_MAX_BRW_SIZE; @@ -466,7 +482,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, mutex_unlock(&sbi->ll_lco.lco_lock); fid_zero(&sbi->ll_root_fid); - err = md_getstatus(sbi->ll_md_exp, &sbi->ll_root_fid); + err = md_get_root(sbi->ll_md_exp, get_mount_fileset(sb), + &sbi->ll_root_fid); if (err) { CERROR("cannot mds_connect: rc = %d\n", err); GOTO(out_lock_cn_cb, err); @@ -480,16 +497,17 @@ 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; + sb->s_export_op = &lustre_export_operations; #endif /* 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_RMT_CLIENT) - valid |= OBD_MD_FLRMTPERM; - else if (sbi->ll_flags & LL_SBI_ACL) + if (sbi->ll_flags & LL_SBI_ACL) valid |= OBD_MD_FLACL; OBD_ALLOC_PTR(op_data); @@ -517,42 +535,45 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, GOTO(out_lock_cn_cb, err); } - LASSERT(fid_is_sane(&sbi->ll_root_fid)); + 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); - md_free_lustre_md(sbi->ll_md_exp, &lmd); - ptlrpc_req_finished(request); + md_free_lustre_md(sbi->ll_md_exp, &lmd); + ptlrpc_req_finished(request); if (IS_ERR(root)) { #ifdef CONFIG_FS_POSIX_ACL - if (lmd.posix_acl) { - posix_acl_release(lmd.posix_acl); - lmd.posix_acl = NULL; - } -#endif - err = IS_ERR(root) ? PTR_ERR(root) : -EBADF; - root = NULL; - CERROR("lustre_lite: bad iget4 for root\n"); - GOTO(out_root, err); - } - -#ifdef CONFIG_FS_POSIX_ACL - if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { - rct_init(&sbi->ll_rct); - et_init(&sbi->ll_et); - } + if (lmd.posix_acl) { + posix_acl_release(lmd.posix_acl); + lmd.posix_acl = NULL; + } #endif + err = IS_ERR(root) ? PTR_ERR(root) : -EBADF; + root = NULL; + CERROR("lustre_lite: bad iget4 for root\n"); + GOTO(out_root, err); + } - 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); - cl_sb_init(sb); + 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); + } + cl_sb_init(sb); err = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CACHE_SET), KEY_CACHE_SET, sizeof(*sbi->ll_cache), sbi->ll_cache, NULL); + if (err) { + CERROR("%s: Set cache_set failed: rc = %d\n", + sbi->ll_dt_exp->exp_obd->obd_name, err); + GOTO(out_root, err); + } sb->s_root = d_make_root(root); if (sb->s_root == NULL) { @@ -564,51 +585,57 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sb->s_root->d_op = &ll_d_ops; #endif - sbi->ll_sdev_orig = sb->s_dev; + sbi->ll_sdev_orig = sb->s_dev; - /* We set sb->s_dev equal on all lustre clients in order to support - * NFS export clustering. NFSD requires that the FSID be the same - * on all clients. */ - /* s_dev is also used in lt_compare() to compare two fs, but that is - * only a node-local comparison. */ - uuid = obd_get_uuid(sbi->ll_md_exp); + /* We set sb->s_dev equal on all lustre clients in order to support + * NFS export clustering. NFSD requires that the FSID be the same + * on all clients. */ + /* s_dev is also used in lt_compare() to compare two fs, but that is + * only a node-local comparison. */ + uuid = obd_get_uuid(sbi->ll_md_exp); if (uuid != NULL) sb->s_dev = get_uuid2int(uuid->uuid, strlen(uuid->uuid)); - if (data != NULL) - OBD_FREE_PTR(data); - if (osfs != NULL) - OBD_FREE_PTR(osfs); - if (proc_lustre_fs_root != NULL) { - err = lprocfs_register_mountpoint(proc_lustre_fs_root, sb, - dt, md); + if (data != NULL) + OBD_FREE_PTR(data); + if (osfs != NULL) + OBD_FREE_PTR(osfs); + + if (sbi->ll_proc_root != NULL) { + err = lprocfs_ll_register_obd(sb, dt); if (err < 0) { - CERROR("%s: could not register mount in lprocfs: " - "rc = %d\n", ll_get_fsname(sb, NULL, 0), err); + 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 (err < 0) { + CERROR("%s: could not register %s in llite: rc = %d\n", + md, ll_get_fsname(sb, NULL, 0), err); err = 0; } } - RETURN(err); + RETURN(err); out_root: - if (root) - iput(root); + if (root) + iput(root); out_lock_cn_cb: obd_fid_fini(sbi->ll_dt_exp->exp_obd); out_dt: - obd_disconnect(sbi->ll_dt_exp); - sbi->ll_dt_exp = NULL; + obd_disconnect(sbi->ll_dt_exp); + sbi->ll_dt_exp = 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; + obd_disconnect(sbi->ll_md_exp); + sbi->ll_md_exp = NULL; out: - if (data != NULL) - OBD_FREE_PTR(data); - if (osfs != NULL) - OBD_FREE_PTR(osfs); - return err; + if (data != NULL) + OBD_FREE_PTR(data); + if (osfs != NULL) + OBD_FREE_PTR(osfs); + return err; } int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize) @@ -683,78 +710,24 @@ int ll_set_default_mdsize(struct ll_sb_info *sbi, int lmmsize) RETURN(rc); } -static void ll_dump_inode(struct inode *inode) -{ - struct ll_d_hlist_node *tmp; - int dentry_count = 0; - - LASSERT(inode != NULL); - - ll_d_hlist_for_each(tmp, &inode->i_dentry) - dentry_count++; - - CERROR("%s: inode %p dump: dev=%s fid="DFID - " mode=%o count=%u, %d dentries\n", - ll_get_fsname(inode->i_sb, NULL, 0), inode, - ll_i2mdexp(inode)->exp_obd->obd_name, PFID(ll_inode2fid(inode)), - inode->i_mode, atomic_read(&inode->i_count), dentry_count); -} - -void lustre_dump_dentry(struct dentry *dentry, int recur) -{ - struct list_head *tmp; - int subdirs = 0; - - LASSERT(dentry != NULL); - - list_for_each(tmp, &dentry->d_subdirs) - subdirs++; - - CERROR("dentry %p dump: name=%.*s parent=%.*s (%p), inode=%p, count=%u," - " flags=0x%x, fsdata=%p, %d subdirs\n", dentry, - dentry->d_name.len, dentry->d_name.name, - dentry->d_parent->d_name.len, dentry->d_parent->d_name.name, - dentry->d_parent, dentry->d_inode, ll_d_count(dentry), - dentry->d_flags, dentry->d_fsdata, subdirs); - if (dentry->d_inode != NULL) - ll_dump_inode(dentry->d_inode); - - if (recur == 0) - return; - - list_for_each(tmp, &dentry->d_subdirs) { - struct dentry *d = list_entry(tmp, struct dentry, d_child); - lustre_dump_dentry(d, recur - 1); - } -} - static void client_common_put_super(struct super_block *sb) { - struct ll_sb_info *sbi = ll_s2sbi(sb); - ENTRY; - -#ifdef CONFIG_FS_POSIX_ACL - if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { - et_fini(&sbi->ll_et); - rct_fini(&sbi->ll_rct); - } -#endif - - cl_sb_fini(sb); + struct ll_sb_info *sbi = ll_s2sbi(sb); + ENTRY; - list_del(&sbi->ll_conn_chain); + cl_sb_fini(sb); obd_fid_fini(sbi->ll_dt_exp->exp_obd); - obd_disconnect(sbi->ll_dt_exp); - sbi->ll_dt_exp = NULL; + obd_disconnect(sbi->ll_dt_exp); + sbi->ll_dt_exp = NULL; - lprocfs_unregister_mountpoint(sbi); + lprocfs_ll_unregister_mountpoint(sbi); obd_fid_fini(sbi->ll_md_exp->exp_obd); - obd_disconnect(sbi->ll_md_exp); - sbi->ll_md_exp = NULL; + obd_disconnect(sbi->ll_md_exp); + sbi->ll_md_exp = NULL; - EXIT; + EXIT; } void ll_kill_super(struct super_block *sb) @@ -836,11 +809,18 @@ static int ll_options(char *options, int *flags) *flags &= ~tmp; goto next; } - tmp = ll_set_opt("remote_client", s1, LL_SBI_RMT_CLIENT); - if (tmp) { - *flags |= tmp; + 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; @@ -897,6 +877,11 @@ static int ll_options(char *options, int *flags) *flags &= ~tmp; goto next; } + tmp = ll_set_opt("always_ping", s1, LL_SBI_ALWAYS_PING); + if (tmp) { + *flags |= tmp; + goto next; + } LCONSOLE_ERROR_MSG(0x152, "Unknown option '%s', won't mount.\n", s1); RETURN(-EINVAL); @@ -917,12 +902,8 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_flags = 0; spin_lock_init(&lli->lli_lock); lli->lli_posix_acl = NULL; - lli->lli_remote_perms = NULL; - mutex_init(&lli->lli_rmtperm_mutex); /* Do not set lli_fid, it has been initialized already. */ fid_zero(&lli->lli_pfid); - atomic_set(&lli->lli_open_count, 0); - lli->lli_rmtperm_time = 0; lli->lli_mds_read_och = NULL; lli->lli_mds_write_och = NULL; lli->lli_mds_exec_och = NULL; @@ -959,6 +940,7 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_async_rc = 0; } mutex_init(&lli->lli_layout_mutex); + memset(lli->lli_jobid, 0, LUSTRE_JOBID_SIZE); } static inline int ll_bdi_register(struct backing_dev_info *bdi) @@ -972,22 +954,24 @@ static inline int ll_bdi_register(struct backing_dev_info *bdi) 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; - 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 err; - ENTRY; + struct lustre_profile *lprof = NULL; + struct lustre_sb_info *lsi = s2lsi(sb); + struct ll_sb_info *sbi; + 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; - CDEBUG(D_VFSTRACE, "VFS Op: sb %p\n", sb); + CDEBUG(D_VFSTRACE, "VFS Op: sb %p\n", sb); - OBD_ALLOC_PTR(cfg); - if (cfg == NULL) - RETURN(-ENOMEM); + OBD_ALLOC_PTR(cfg); + if (cfg == NULL) + RETURN(-ENOMEM); try_module_get(THIS_MODULE); @@ -999,76 +983,99 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) RETURN(-ENOMEM); } - err = ll_options(lsi->lsi_lmd->lmd_opts, &sbi->ll_flags); - if (err) - GOTO(out_free, err); + err = ll_options(lsi->lsi_lmd->lmd_opts, &sbi->ll_flags); + if (err) + GOTO(out_free, err); err = bdi_init(&lsi->lsi_bdi); 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); - sb->s_bdi = &lsi->lsi_bdi; + 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 - /* 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.*/ - cfg->cfg_instance = sb; - cfg->cfg_uuid = lsi->lsi_llsbi->ll_sb_uuid; + /* 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; + } + } + + /* 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.*/ + cfg->cfg_instance = sb; + cfg->cfg_uuid = lsi->lsi_llsbi->ll_sb_uuid; cfg->cfg_callback = class_config_llog_handler; - /* set up client obds */ - err = lustre_process_log(sb, profilenm, cfg); + cfg->cfg_sub_clds = CONFIG_SUB_CLIENT; + /* set up client obds */ + err = lustre_process_log(sb, profilenm, cfg); if (err < 0) - GOTO(out_free, err); - - /* Profile set with LCFG_MOUNTOPT so we can find our mdc and osc obds */ - lprof = class_get_profile(profilenm); - if (lprof == NULL) { - LCONSOLE_ERROR_MSG(0x156, "The client profile '%s' could not be" - " read from the MGS. Does that filesystem " - "exist?\n", profilenm); - GOTO(out_free, err = -EINVAL); - } - CDEBUG(D_CONFIG, "Found profile %s: mdc=%s osc=%s\n", profilenm, - lprof->lp_md, lprof->lp_dt); - - OBD_ALLOC(dt, strlen(lprof->lp_dt) + instlen + 2); - if (!dt) - GOTO(out_free, err = -ENOMEM); - sprintf(dt, "%s-%p", lprof->lp_dt, cfg->cfg_instance); - - OBD_ALLOC(md, strlen(lprof->lp_md) + instlen + 2); - if (!md) - GOTO(out_free, err = -ENOMEM); - sprintf(md, "%s-%p", lprof->lp_md, cfg->cfg_instance); - - /* connections, registrations, sb setup */ - err = client_common_fill_super(sb, md, dt, mnt); + GOTO(out_proc, err); + + /* Profile set with LCFG_MOUNTOPT so we can find our mdc and osc obds */ + lprof = class_get_profile(profilenm); + if (lprof == NULL) { + 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); + } + CDEBUG(D_CONFIG, "Found profile %s: mdc=%s osc=%s\n", profilenm, + lprof->lp_md, lprof->lp_dt); + + dt_len = strlen(lprof->lp_dt) + instlen + 2; + OBD_ALLOC(dt, dt_len); + if (!dt) + GOTO(out_proc, 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); + 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_free, err); + GOTO(out_proc, err); sbi->ll_client_common_fill_super_succeeded = 1; +out_proc: + if (err < 0) + lprocfs_ll_unregister_mountpoint(sbi); out_free: - if (md) - OBD_FREE(md, strlen(lprof->lp_md) + instlen + 2); - if (dt) - OBD_FREE(dt, strlen(lprof->lp_dt) + instlen + 2); - 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); + if (md) + OBD_FREE(md, md_len); + if (dt) + OBD_FREE(dt, dt_len); + if (lprof != NULL) + class_put_profile(lprof); + 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 */ void ll_put_super(struct super_block *sb) @@ -1177,7 +1184,7 @@ struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock) return inode; } -static void ll_dir_clear_lsm_md(struct inode *inode) +void ll_dir_clear_lsm_md(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); @@ -1221,9 +1228,11 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb, LTIME_S(inode->i_ctime) = 0; inode->i_rdev = 0; +#ifdef HAVE_BACKING_DEV_INFO /* initializing backing dev info. */ inode->i_mapping->backing_dev_info = &s2lsi(inode->i_sb)->lsi_bdi; +#endif inode->i_op = &ll_dir_inode_operations; inode->i_fop = &ll_dir_operations; lli->lli_fid = *fid; @@ -1323,15 +1332,42 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) /* set the directory layout */ if (lli->lli_lsm_md == NULL) { + struct cl_attr *attr; rc = ll_init_lsm_md(inode, md); if (rc != 0) RETURN(rc); - lli->lli_lsm_md = lsm; - /* set lsm_md to NULL, so the following free lustre_md + /* set md->lmv to NULL, so the following free lustre_md * will not free this lsm */ md->lmv = NULL; + lli->lli_lsm_md = lsm; + + OBD_ALLOC_PTR(attr); + if (attr == NULL) + RETURN(-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); + } + + if (md->body->mbo_valid & OBD_MD_FLNLINK) + md->body->mbo_nlink = attr->cat_nlink; + if (md->body->mbo_valid & OBD_MD_FLSIZE) + md->body->mbo_size = attr->cat_size; + if (md->body->mbo_valid & OBD_MD_FLATIME) + md->body->mbo_atime = attr->cat_atime; + if (md->body->mbo_valid & OBD_MD_FLCTIME) + md->body->mbo_ctime = attr->cat_ctime; + if (md->body->mbo_valid & OBD_MD_FLMTIME) + 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); @@ -1413,17 +1449,10 @@ void ll_clear_inode(struct inode *inode) ll_xattr_cache_destroy(inode); - if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { - LASSERT(lli->lli_posix_acl == NULL); - if (lli->lli_remote_perms) { - free_rmtperm_hash(lli->lli_remote_perms); - lli->lli_remote_perms = NULL; - } - } #ifdef CONFIG_FS_POSIX_ACL - else if (lli->lli_posix_acl) { + forget_all_cached_acls(inode); + if (lli->lli_posix_acl) { LASSERT(atomic_read(&lli->lli_posix_acl->a_refcount) == 1); - LASSERT(lli->lli_remote_perms == NULL); posix_acl_release(lli->lli_posix_acl); lli->lli_posix_acl = NULL; } @@ -1489,7 +1518,11 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data) /* inode size will be in ll_setattr_ost, can't do it now since dirty * cache is not cleared yet. */ 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); + if (S_ISREG(inode->i_mode)) + inode_unlock(inode); op_data->op_attr.ia_valid = ia_valid; rc = ll_update_inode(inode, &md); @@ -1518,7 +1551,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); struct md_op_data *op_data = NULL; - bool file_is_released = false; int rc = 0; ENTRY; @@ -1538,7 +1570,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) * OST maximum object size and number of stripes. This * needs another check in addition to the VFS check above. */ if (attr->ia_size > ll_file_maxbytes(inode)) { - CDEBUG(D_INODE,"file "DFID" too large %llu > "LPU64"\n", + CDEBUG(D_INODE,"file "DFID" too large %llu > %llu\n", PFID(&lli->lli_fid), attr->ia_size, ll_file_maxbytes(inode)); RETURN(-EFBIG); @@ -1555,107 +1587,61 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) } /* We mark all of the fields "set" so MDS/OST does not re-set them */ - if (attr->ia_valid & ATTR_CTIME) { - attr->ia_ctime = CFS_CURRENT_TIME; + if (!(attr->ia_valid & ATTR_CTIME_SET) && + (attr->ia_valid & ATTR_CTIME)) { + attr->ia_ctime = current_time(inode); attr->ia_valid |= ATTR_CTIME_SET; } if (!(attr->ia_valid & ATTR_ATIME_SET) && (attr->ia_valid & ATTR_ATIME)) { - attr->ia_atime = CFS_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 = CFS_CURRENT_TIME; + attr->ia_mtime = current_time(inode); attr->ia_valid |= ATTR_MTIME_SET; } if (attr->ia_valid & (ATTR_MTIME | ATTR_CTIME)) - CDEBUG(D_INODE, "setting mtime %lu, ctime %lu, now = %lu\n", + CDEBUG(D_INODE, "setting mtime %lu, ctime %lu, now = %llu\n", LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime), - cfs_time_current_sec()); - - /* We always do an MDS RPC, even if we're only changing the size; - * only the MDS knows whether truncate() should fail with -ETXTBUSY */ + (s64)ktime_get_real_seconds()); - OBD_ALLOC_PTR(op_data); - if (op_data == NULL) - RETURN(-ENOMEM); - - if (!S_ISDIR(inode->i_mode)) { + if (S_ISREG(inode->i_mode)) { if (attr->ia_valid & ATTR_SIZE) inode_dio_write_done(inode); - mutex_unlock(&inode->i_mutex); + inode_unlock(inode); } - /* truncate on a released file must failed with -ENODATA, - * so size must not be set on MDS for released file - * but other attributes must be set - */ - if (S_ISREG(inode->i_mode)) { - struct cl_layout cl = { - .cl_is_released = false, - }; - struct lu_env *env; - int refcheck; - __u32 gen; - - rc = ll_layout_refresh(inode, &gen); - if (rc < 0) - GOTO(out, rc); - - /* XXX: the only place we need to know the layout type, - * this will be removed by a later patch. -Jinshan */ - env = cl_env_get(&refcheck); - if (IS_ERR(env)) - GOTO(out, rc = PTR_ERR(env)); - - rc = cl_object_layout_get(env, lli->lli_clob, &cl); - cl_env_put(env, &refcheck); - if (rc < 0) - GOTO(out, rc); - - file_is_released = cl.cl_is_released; - - if (!hsm_import && attr->ia_valid & ATTR_SIZE) { - if (file_is_released) { - rc = ll_layout_restore(inode, 0, attr->ia_size); - if (rc < 0) - GOTO(out, rc); + /* We always do an MDS RPC, even if we're only changing the size; + * only the MDS knows whether truncate() should fail with -ETXTBUSY */ - file_is_released = false; - ll_layout_refresh(inode, &gen); - } + OBD_ALLOC_PTR(op_data); + if (op_data == NULL) + GOTO(out, rc = -ENOMEM); - /* If we are changing file size, file content is - * modified, flag it. */ - attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; - spin_lock(&lli->lli_lock); - lli->lli_flags |= LLIF_DATA_MODIFIED; - spin_unlock(&lli->lli_lock); - op_data->op_bias |= MDS_DATA_MODIFIED; - } + 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; + op_data->op_bias |= MDS_DATA_MODIFIED; + ll_file_clear_flag(lli, LLIF_DATA_MODIFIED); } - memcpy(&op_data->op_attr, attr, sizeof(*attr)); + op_data->op_attr = *attr; rc = ll_md_setattr(dentry, op_data); if (rc) GOTO(out, rc); - /* RPC to MDT is sent, cancel data modification flag */ - if (rc == 0 && (op_data->op_bias & MDS_DATA_MODIFIED)) { - spin_lock(&lli->lli_lock); - lli->lli_flags &= ~LLIF_DATA_MODIFIED; - spin_unlock(&lli->lli_lock); - } - - if (!S_ISREG(inode->i_mode) || file_is_released) + 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_MTIME | ATTR_MTIME_SET | + ATTR_CTIME | ATTR_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 @@ -1664,15 +1650,53 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) * time de-synchronization between MDT inode and OST objects */ rc = cl_setattr_ost(lli->lli_clob, attr, 0); } + + /* If the file was restored, it needs to set dirty flag. + * + * We've already sent MDS_DATA_MODIFIED flag in + * ll_md_setattr() for truncate. However, the MDT refuses to + * set the HS_DIRTY flag on released files, so we have to set + * it again if the file has been restored. Please check how + * LLIF_DATA_MODIFIED is set in vvp_io_setattr_fini(). + * + * Please notice that if the file is not released, the previous + * MDS_DATA_MODIFIED has taken effect and usually + * LLIF_DATA_MODIFIED is not set(see vvp_io_setattr_fini()). + * This way we can save an RPC for common open + trunc + * operation. */ + if (ll_file_test_and_clear_flag(lli, LLIF_DATA_MODIFIED)) { + struct hsm_state_set hss = { + .hss_valid = HSS_SETMASK, + .hss_setmask = HS_DIRTY, + }; + int rc2; + + rc2 = ll_hsm_state_set(inode, &hss); + /* truncate and write can happen at the same time, so that + * the file can be set modified even though the file is not + * restored from released state, and ll_hsm_state_set() is + * not applicable for the file, and rc2 < 0 is normal in this + * case. */ + if (rc2 < 0) + CDEBUG(D_INFO, DFID "HSM set dirty failed: rc2 = %d\n", + PFID(ll_inode2fid(inode)), rc2); + } + EXIT; out: if (op_data != NULL) ll_finish_md_op_data(op_data); - if (!S_ISDIR(inode->i_mode)) { - mutex_lock(&inode->i_mutex); + if (S_ISREG(inode->i_mode)) { + inode_lock(inode); if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) inode_dio_wait(inode); + /* Once we've got the i_mutex, it's safe to set the S_NOSEC + * flag. ll_update_inode (called from ll_md_setattr), clears + * inode flags, so there is a gap where S_NOSEC is not set. + * This can cause a writer to take the i_mutex unnecessarily, + * but this is safe to do and should be rare. */ + inode_has_no_xattr(inode); } ll_stats_ops_tally(ll_i2sbi(inode), (attr->ia_valid & ATTR_SIZE) ? @@ -1708,6 +1732,10 @@ 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); } @@ -1727,7 +1755,7 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, osfs->os_type = sb->s_magic; - CDEBUG(D_SUPER, "MDC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n", + CDEBUG(D_SUPER, "MDC blocks %llu/%llu objects %llu/%llu\n", osfs->os_bavail, osfs->os_blocks, osfs->os_ffree,osfs->os_files); if (sbi->ll_flags & LL_SBI_LAZYSTATFS) @@ -1739,7 +1767,7 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, RETURN(rc); } - CDEBUG(D_SUPER, "OSC blocks "LPU64"/"LPU64" objects "LPU64"/"LPU64"\n", + CDEBUG(D_SUPER, "OSC blocks %llu/%llu objects %llu/%llu\n", obd_osfs.os_bavail, obd_osfs.os_blocks, obd_osfs.os_ffree, obd_osfs.os_files); @@ -1767,7 +1795,7 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs) __u64 fsid = huge_encode_dev(sb->s_dev); int rc; - CDEBUG(D_VFSTRACE, "VFS Op: at "LPU64" jiffies\n", get_jiffies_64()); + 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 */ @@ -1824,24 +1852,22 @@ 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); + int rc = 0; - if (body->mbo_valid & OBD_MD_FLEASIZE) - cl_file_inode_init(inode, md); + if (body->mbo_valid & OBD_MD_FLEASIZE) { + rc = cl_file_inode_init(inode, md); + if (rc) + return rc; + } if (S_ISDIR(inode->i_mode)) { - int rc; - rc = ll_update_lsm_md(inode, md); if (rc != 0) return rc; } - if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { - if (body->mbo_valid & OBD_MD_FLRMTPERM) - ll_update_remote_perm(inode, md->remote_perm); - } #ifdef CONFIG_FS_POSIX_ACL - else if (body->mbo_valid & OBD_MD_FLACL) { + if (body->mbo_valid & OBD_MD_FLACL) { spin_lock(&lli->lli_lock); if (lli->lli_posix_acl) posix_acl_release(lli->lli_posix_acl); @@ -1862,7 +1888,7 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) if (body->mbo_valid & OBD_MD_FLMTIME) { if (body->mbo_mtime > LTIME_S(inode->i_mtime)) { CDEBUG(D_INODE, "setting ino %lu mtime from %lu " - "to "LPU64"\n", inode->i_ino, + "to %llu\n", inode->i_ino, LTIME_S(inode->i_mtime), body->mbo_mtime); LTIME_S(inode->i_mtime) = body->mbo_mtime; } @@ -1875,6 +1901,9 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) lli->lli_ctime = body->mbo_ctime; } + /* 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); if (body->mbo_valid & OBD_MD_FLMODE) inode->i_mode = (inode->i_mode & S_IFMT) | (body->mbo_mode & ~S_IFMT); @@ -1894,8 +1923,8 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) inode->i_uid = make_kuid(&init_user_ns, body->mbo_uid); if (body->mbo_valid & OBD_MD_FLGID) inode->i_gid = make_kgid(&init_user_ns, body->mbo_gid); - if (body->mbo_valid & OBD_MD_FLFLAGS) - inode->i_flags = ll_ext_to_inode_flags(body->mbo_flags); + if (body->mbo_valid & OBD_MD_FLPROJID) + lli->lli_projid = body->mbo_projid; if (body->mbo_valid & OBD_MD_FLNLINK) set_nlink(inode, body->mbo_nlink); if (body->mbo_valid & OBD_MD_FLRDEV) @@ -1928,8 +1957,14 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) } if (body->mbo_valid & OBD_MD_TSTATE) { + /* Set LLIF_FILE_RESTORING if restore ongoing and + * clear it when done to ensure to start again + * glimpsing updated attrs + */ if (body->mbo_t_state & MS_RESTORE) - lli->lli_flags |= LLIF_FILE_RESTORING; + ll_file_set_flag(lli, LLIF_FILE_RESTORING); + else + ll_file_clear_flag(lli, LLIF_FILE_RESTORING); } return 0; @@ -1959,10 +1994,10 @@ int ll_read_inode2(struct inode *inode, void *opaque) /* OIDEBUG(inode); */ - /* initializing backing dev info. */ - inode->i_mapping->backing_dev_info = &s2lsi(inode->i_sb)->lsi_bdi; - - +#ifdef HAVE_BACKING_DEV_INFO + /* initializing backing dev info. */ + inode->i_mapping->backing_dev_info = &s2lsi(inode->i_sb)->lsi_bdi; +#endif if (S_ISREG(inode->i_mode)) { struct ll_sb_info *sbi = ll_i2sbi(inode); inode->i_op = &ll_file_inode_operations; @@ -2115,6 +2150,8 @@ void ll_umount_begin(struct super_block *sb) struct ll_sb_info *sbi = ll_s2sbi(sb); struct obd_device *obd; struct obd_ioctl_data *ioc_data; + struct l_wait_info lwi; + wait_queue_head_t waitq; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb, @@ -2122,7 +2159,7 @@ void ll_umount_begin(struct super_block *sb) obd = class_exp2obd(sbi->ll_md_exp); if (obd == NULL) { - CERROR("Invalid MDC connection handle "LPX64"\n", + CERROR("Invalid MDC connection handle %#llx\n", sbi->ll_md_exp->exp_handle.h_cookie); EXIT; return; @@ -2131,7 +2168,7 @@ void ll_umount_begin(struct super_block *sb) obd = class_exp2obd(sbi->ll_dt_exp); if (obd == NULL) { - CERROR("Invalid LOV connection handle "LPX64"\n", + CERROR("Invalid LOV connection handle %#llx\n", sbi->ll_dt_exp->exp_handle.h_cookie); EXIT; return; @@ -2150,10 +2187,14 @@ void ll_umount_begin(struct super_block *sb) } /* Really, we'd like to wait until there are no requests outstanding, - * and then continue. For now, we just invalidate the requests, - * schedule() and sleep one second if needed, and hope. + * and then continue. For now, we just periodically checking for vfs + * to decrement mnt_cnt and hope to finish it within 10sec. */ - schedule(); + init_waitqueue_head(&waitq); + lwi = LWI_TIMEOUT_INTERVAL(cfs_time_seconds(10), + cfs_time_seconds(1), NULL, NULL); + l_wait_event(waitq, may_umount(sbi->ll_mnt.mnt), &lwi); + EXIT; } @@ -2224,7 +2265,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_mod_time = cfs_time_current_sec(); + op_data->op_mod_time = ktime_get_real_seconds(); md_close(exp, op_data, NULL, &close_req); ptlrpc_req_finished(close_req); ll_finish_md_op_data(op_data); @@ -2254,11 +2295,16 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, } else { LASSERT(sb != NULL); - /* - * At this point server returns to client's same fid as client - * generated for creating. So using ->fid1 is okay here. - */ - LASSERT(fid_is_sane(&md.body->mbo_fid1)); + /* + * 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)) { + CERROR("%s: Fid is insane "DFID"\n", + ll_get_fsname(sb, NULL, 0), + PFID(&md.body->mbo_fid1)); + GOTO(out, rc = -EINVAL); + } *inode = ll_iget(sb, cl_fid_build_ino(&md.body->mbo_fid1, sbi->ll_flags & LL_SBI_32BIT_API), @@ -2285,11 +2331,11 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, * 2. layout was changed by another client * 3. proc2: refresh layout and layout lock granted * 4. proc1: to apply a stale layout */ - if (it != NULL && it->d.lustre.it_lock_mode != 0) { + if (it != NULL && it->it_lock_mode != 0) { struct lustre_handle lockh; struct ldlm_lock *lock; - lockh.cookie = it->d.lustre.it_lock_handle; + lockh.cookie = it->it_lock_handle; lock = ldlm_handle2lock(&lockh); LASSERT(lock != NULL); if (ldlm_has_layout(lock)) { @@ -2324,7 +2370,6 @@ int ll_obd_statfs(struct inode *inode, void __user *arg) char *buf = NULL; struct obd_ioctl_data *data = NULL; __u32 type; - __u32 __user flags; /* not user, but obd_iocontrol is abused */ int len = 0, rc; if (!inode || !(sbi = ll_i2sbi(inode))) @@ -2353,14 +2398,12 @@ int ll_obd_statfs(struct inode *inode, void __user *arg) else GOTO(out_statfs, rc = -ENODEV); - flags = (type & LL_STATFS_NODELAY) ? OBD_STATFS_NODELAY : 0; - rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, &flags); + rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, NULL); if (rc) GOTO(out_statfs, rc); out_statfs: - if (buf) - obd_ioctl_freedata(buf, len); - return rc; + OBD_FREE_LARGE(buf, len); + return rc; } int ll_process_config(struct lustre_cfg *lcfg) @@ -2446,8 +2489,6 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, 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_bias = 0; - op_data->op_cli_flags = 0; if ((opc == LUSTRE_OPC_CREATE) && (name != NULL) && filename_is_volatile(name, namelen, &op_data->op_mds)) { op_data->op_bias |= MDS_CREATE_VOLATILE; @@ -2456,15 +2497,13 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, } op_data->op_data = data; - /* When called by ll_setattr_raw, file is i1. */ - if (LLIF_DATA_MODIFIED & ll_i2info(i1)->lli_flags) - op_data->op_bias |= MDS_DATA_MODIFIED; - return op_data; } void ll_finish_md_op_data(struct md_op_data *op_data) { + security_release_secctx(op_data->op_file_secctx, + op_data->op_file_secctx_size); OBD_FREE_PTR(op_data); } @@ -2502,6 +2541,9 @@ int ll_show_options(struct seq_file *seq, struct vfsmount *vfs) 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"); + RETURN(0); } @@ -2641,7 +2683,7 @@ void ll_compute_rootsquash_state(struct ll_sb_info *sbi) struct root_squash_info *squash = &sbi->ll_squash; int i; bool matched; - lnet_process_id_t id; + struct lnet_process_id id; /* Update norootsquash flag */ down_write(&squash->rsi_sem); @@ -2686,7 +2728,7 @@ static int ll_linkea_decode(struct linkea_data *ldata, unsigned int linkno, int rc; ENTRY; - rc = linkea_init(ldata); + rc = linkea_init_with_rec(ldata); if (rc < 0) RETURN(rc); @@ -2725,8 +2767,7 @@ 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->f_path.dentry; - struct inode *inode = dentry->d_inode; + struct inode *inode = file_inode(file); struct linkea_data *ldata; struct lu_buf buf = LU_BUF_NULL; struct lu_name ln; @@ -2758,7 +2799,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);