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