X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Fllite_lib.c;h=d65710dbb2c742ab40e16f8c580a30a194baec1f;hp=9980c2cdec9c64973f3ab37fc468f109cd102570;hb=5bd85b467a4b6ef57d7a3c119296c9a317afc73b;hpb=3e358040ae4b6fe8f28f20f8f1a07217d67d7e1a diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 9980c2c..d65710d 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -27,7 +27,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2012, Whamcloud, Inc. + * Copyright (c) 2011, 2013, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -56,27 +56,26 @@ #include #include "llite_internal.h" -cfs_mem_cache_t *ll_file_data_slab; +struct kmem_cache *ll_file_data_slab; CFS_LIST_HEAD(ll_super_blocks); DEFINE_SPINLOCK(ll_sb_lock); #ifndef MS_HAS_NEW_AOPS extern struct address_space_operations ll_aops; -extern struct address_space_operations ll_dir_aops; #else extern struct address_space_operations_ext ll_aops; -extern struct address_space_operations_ext ll_dir_aops; #endif #ifndef log2 -#define log2(n) cfs_ffz(~(n)) +#define log2(n) ffz(~(n)) #endif static struct ll_sb_info *ll_init_sbi(void) { - struct ll_sb_info *sbi = NULL; - unsigned long pages; + struct ll_sb_info *sbi = NULL; + unsigned long pages; + unsigned long lru_page_max; struct sysinfo si; class_uuid_t uuid; int i; @@ -86,23 +85,26 @@ static struct ll_sb_info *ll_init_sbi(void) if (!sbi) RETURN(NULL); - cfs_spin_lock_init(&sbi->ll_lock); - cfs_mutex_init(&sbi->ll_lco.lco_lock); - cfs_spin_lock_init(&sbi->ll_pp_extent_lock); - cfs_spin_lock_init(&sbi->ll_process_lock); + spin_lock_init(&sbi->ll_lock); + mutex_init(&sbi->ll_lco.lco_lock); + spin_lock_init(&sbi->ll_pp_extent_lock); + spin_lock_init(&sbi->ll_process_lock); sbi->ll_rw_stats_on = 0; si_meminfo(&si); pages = si.totalram - si.totalhigh; - if (pages >> (20 - CFS_PAGE_SHIFT) < 512) { -#ifdef HAVE_BGL_SUPPORT - sbi->ll_async_page_max = pages / 4; -#else - sbi->ll_async_page_max = pages / 2; -#endif - } else { - sbi->ll_async_page_max = (pages / 4) * 3; - } + if (pages >> (20 - PAGE_CACHE_SHIFT) < 512) { + lru_page_max = pages / 2; + } else { + lru_page_max = (pages / 4) * 3; + } + + /* initialize lru data */ + cfs_atomic_set(&sbi->ll_cache.ccc_users, 0); + sbi->ll_cache.ccc_lru_max = lru_page_max; + cfs_atomic_set(&sbi->ll_cache.ccc_lru_left, lru_page_max); + spin_lock_init(&sbi->ll_cache.ccc_lru_lock); + CFS_INIT_LIST_HEAD(&sbi->ll_cache.ccc_lru); sbi->ll_ra_info.ra_max_pages_per_file = min(pages / 32, SBI_DEFAULT_READAHEAD_MAX); @@ -116,9 +118,9 @@ static struct ll_sb_info *ll_init_sbi(void) class_uuid_unparse(uuid, &sbi->ll_sb_uuid); CDEBUG(D_CONFIG, "generated uuid: %s\n", sbi->ll_sb_uuid.uuid); - cfs_spin_lock(&ll_sb_lock); - cfs_list_add_tail(&sbi->ll_list, &ll_super_blocks); - cfs_spin_unlock(&ll_sb_lock); + spin_lock(&ll_sb_lock); + cfs_list_add_tail(&sbi->ll_list, &ll_super_blocks); + spin_unlock(&ll_sb_lock); sbi->ll_flags |= LL_SBI_VERBOSE; #ifdef ENABLE_CHECKSUM @@ -130,10 +132,10 @@ static struct ll_sb_info *ll_init_sbi(void) #endif for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) { - cfs_spin_lock_init(&sbi->ll_rw_extents_info.pp_extents[i]. \ - pp_r_hist.oh_lock); - cfs_spin_lock_init(&sbi->ll_rw_extents_info.pp_extents[i]. \ - pp_w_hist.oh_lock); + 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); } /* metadata statahead is enabled by default */ @@ -148,23 +150,18 @@ static struct ll_sb_info *ll_init_sbi(void) void ll_free_sbi(struct super_block *sb) { - struct ll_sb_info *sbi = ll_s2sbi(sb); - ENTRY; + struct ll_sb_info *sbi = ll_s2sbi(sb); + ENTRY; - if (sbi != NULL) { - cfs_spin_lock(&ll_sb_lock); - cfs_list_del(&sbi->ll_list); - cfs_spin_unlock(&ll_sb_lock); - OBD_FREE(sbi, sizeof(*sbi)); - } - EXIT; + if (sbi != NULL) { + spin_lock(&ll_sb_lock); + cfs_list_del(&sbi->ll_list); + spin_unlock(&ll_sb_lock); + OBD_FREE(sbi, sizeof(*sbi)); + } + EXIT; } -static struct dentry_operations ll_d_root_ops = { - .d_compare = ll_dcompare, - .d_revalidate = ll_revalidate_nd, -}; - static int client_common_fill_super(struct super_block *sb, char *md, char *dt, struct vfsmount *mnt) { @@ -215,7 +212,10 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_RMT_CLIENT | OBD_CONNECT_VBR | OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH| OBD_CONNECT_EINPROGRESS | - OBD_CONNECT_JOBSTATS; + OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | + OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS | + OBD_CONNECT_MAX_EASIZE | + OBD_CONNECT_FLOCK_DEAD; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; @@ -225,8 +225,14 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE; #endif #ifdef CONFIG_FS_POSIX_ACL - data->ocd_connect_flags |= OBD_CONNECT_ACL; + data->ocd_connect_flags |= OBD_CONNECT_ACL | OBD_CONNECT_UMASK; #endif + + if (OBD_FAIL_CHECK(OBD_FAIL_MDC_LIGHTWEIGHT)) + /* flag mdc connection as lightweight, only used for test + * purpose, use with care */ + data->ocd_connect_flags |= OBD_CONNECT_LIGHTWEIGHT; + data->ocd_ibits_known = MDS_INODELOCK_FULL; data->ocd_version = LUSTRE_VERSION_CODE; @@ -255,7 +261,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (sbi->ll_flags & LL_SBI_RMT_CLIENT) data->ocd_connect_flags |= OBD_CONNECT_RMT_CLIENT_FORCE; - data->ocd_brw_size = PTLRPC_MAX_BRW_SIZE; + data->ocd_brw_size = MD_MAX_BRW_SIZE; err = obd_connect(NULL, &sbi->ll_md_exp, obd, &sbi->ll_sb_uuid, data, NULL); if (err == -EBUSY) { @@ -269,51 +275,59 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, GOTO(out, err); } - err = obd_fid_init(sbi->ll_md_exp); - if (err) { - CERROR("Can't init metadata layer FID infrastructure, " - "rc %d\n", err); - GOTO(out_md, err); - } + sbi->ll_md_exp->exp_connect_data = *data; - err = obd_statfs(NULL, sbi->ll_md_exp, osfs, - cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), 0); - if (err) - GOTO(out_md_fid, err); - - /* This needs to be after statfs to ensure connect has finished. - * Note that "data" does NOT contain the valid connect reply. - * If connecting to a 1.8 server there will be no LMV device, so - * we can access the MDC export directly and exp_connect_flags will - * be non-zero, but if accessing an upgraded 2.1 server it will - * have the correct flags filled in. - * XXX: fill in the LMV exp_connect_flags from MDC(s). */ - valid = sbi->ll_md_exp->exp_connect_flags & CLIENT_CONNECT_MDT_REQD; - if (sbi->ll_md_exp->exp_connect_flags != 0 && - valid != CLIENT_CONNECT_MDT_REQD) { - char *buf; - - OBD_ALLOC_WAIT(buf, CFS_PAGE_SIZE); - obd_connect_flags2str(buf, CFS_PAGE_SIZE, - valid ^ CLIENT_CONNECT_MDT_REQD, ","); - 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, CFS_PAGE_SIZE); - GOTO(out_md, err = -EPROTO); - } + err = obd_fid_init(sbi->ll_md_exp->exp_obd, sbi->ll_md_exp, + LUSTRE_SEQ_METADATA); + if (err) { + CERROR("%s: Can't init metadata layer FID infrastructure, " + "rc = %d\n", sbi->ll_md_exp->exp_obd->obd_name, err); + GOTO(out_md, err); + } - size = sizeof(*data); - err = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_CONN_DATA), - KEY_CONN_DATA, &size, data, NULL); - if (err) { - CERROR("Get connect data failed: %d \n", err); - GOTO(out_md, err); - } + /* For mount, we only need fs info from MDT0, and also in DNE, it + * 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), + OBD_STATFS_FOR_MDT0); + if (err) + GOTO(out_md_fid, err); + + /* This needs to be after statfs to ensure connect has finished. + * Note that "data" does NOT contain the valid connect reply. + * If connecting to a 1.8 server there will be no LMV device, so + * we can access the MDC export directly and exp_connect_flags will + * be non-zero, but if accessing an upgraded 2.1 server it will + * have the correct flags filled in. + * XXX: fill in the LMV exp_connect_flags from MDC(s). */ + valid = exp_connect_flags(sbi->ll_md_exp) & CLIENT_CONNECT_MDT_REQD; + if (exp_connect_flags(sbi->ll_md_exp) != 0 && + 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, ","); + 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); + GOTO(out_md_fid, err = -EPROTO); + } - LASSERT(osfs->os_bsize); + size = sizeof(*data); + err = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_CONN_DATA), + KEY_CONN_DATA, &size, data, NULL); + if (err) { + CERROR("%s: Get connect data failed: rc = %d\n", + sbi->ll_md_exp->exp_obd->obd_name, err); + GOTO(out_md_fid, err); + } + + LASSERT(osfs->os_bsize); sb->s_blocksize = osfs->os_bsize; sb->s_blocksize_bits = log2(osfs->os_bsize); sb->s_magic = LL_SUPER_MAGIC; @@ -367,24 +381,34 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, 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_size = data->ocd_brw_size; - else - sbi->ll_md_brw_size = CFS_PAGE_SIZE; + if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) + sbi->ll_md_brw_size = data->ocd_brw_size; + else + sbi->ll_md_brw_size = PAGE_CACHE_SIZE; if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) { LCONSOLE_INFO("Layout lock feature supported.\n"); sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; } - obd = class_name2obd(dt); - if (!obd) { - CERROR("DT %s: not setup or attached\n", dt); - GOTO(out_md_fid, err = -ENODEV); - } + 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 { + sbi->ll_flags |= LL_SBI_XATTR_CACHE; + sbi->ll_xattr_cache_enabled = 1; + } + } + + obd = class_name2obd(dt); + if (!obd) { + CERROR("DT %s: not setup or attached\n", dt); + GOTO(out_md_fid, err = -ENODEV); + } data->ocd_connect_flags = OBD_CONNECT_GRANT | OBD_CONNECT_VERSION | - OBD_CONNECT_REQPORTAL | OBD_CONNECT_BRW_SIZE | + 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 | @@ -392,7 +416,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH | OBD_CONNECT_MAXBYTES | OBD_CONNECT_EINPROGRESS | - OBD_CONNECT_JOBSTATS; + OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | + OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; @@ -423,85 +448,96 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, obd->obd_upcall.onu_owner = &sbi->ll_lco; obd->obd_upcall.onu_upcall = cl_ocd_update; - data->ocd_brw_size = PTLRPC_MAX_BRW_SIZE; - - err = obd_connect(NULL, &sbi->ll_dt_exp, 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 " - "part. Please wait for recovery to " - "complete, abort, or time out.\n", dt); - GOTO(out_md_fid, err); - } else if (err) { - CERROR("Cannot connect to %s: rc = %d\n", dt, err); - GOTO(out_md_fid, err); - } + data->ocd_brw_size = DT_MAX_BRW_SIZE; + + err = obd_connect(NULL, &sbi->ll_dt_exp, 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 " + "part. Please wait for recovery to " + "complete, abort, or time out.\n", dt); + GOTO(out_md, err); + } else if (err) { + CERROR("%s: Cannot connect to %s: rc = %d\n", + sbi->ll_dt_exp->exp_obd->obd_name, dt, err); + GOTO(out_md, err); + } - err = obd_fid_init(sbi->ll_dt_exp); - if (err) { - CERROR("Can't init data layer FID infrastructure, " - "rc %d\n", err); - GOTO(out_dt, err); - } + sbi->ll_dt_exp->exp_connect_data = *data; - cfs_mutex_lock(&sbi->ll_lco.lco_lock); - sbi->ll_lco.lco_flags = data->ocd_connect_flags; - sbi->ll_lco.lco_md_exp = sbi->ll_md_exp; - sbi->ll_lco.lco_dt_exp = sbi->ll_dt_exp; - cfs_mutex_unlock(&sbi->ll_lco.lco_lock); + err = obd_fid_init(sbi->ll_dt_exp->exp_obd, sbi->ll_dt_exp, + LUSTRE_SEQ_METADATA); + if (err) { + CERROR("%s: Can't init data layer FID infrastructure, " + "rc = %d\n", sbi->ll_dt_exp->exp_obd->obd_name, err); + GOTO(out_dt, err); + } - fid_zero(&sbi->ll_root_fid); - err = md_getstatus(sbi->ll_md_exp, &sbi->ll_root_fid, &oc); - if (err) { - CERROR("cannot mds_connect: rc = %d\n", err); - GOTO(out_lock_cn_cb, err); - } - if (!fid_is_sane(&sbi->ll_root_fid)) { - CERROR("Invalid root fid during mount\n"); - GOTO(out_lock_cn_cb, err = -EINVAL); - } - CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid)); + mutex_lock(&sbi->ll_lco.lco_lock); + sbi->ll_lco.lco_flags = data->ocd_connect_flags; + sbi->ll_lco.lco_md_exp = sbi->ll_md_exp; + sbi->ll_lco.lco_dt_exp = sbi->ll_dt_exp; + mutex_unlock(&sbi->ll_lco.lco_lock); + + fid_zero(&sbi->ll_root_fid); + err = md_getstatus(sbi->ll_md_exp, &sbi->ll_root_fid, &oc); + if (err) { + CERROR("cannot mds_connect: rc = %d\n", err); + GOTO(out_lock_cn_cb, err); + } + if (!fid_is_sane(&sbi->ll_root_fid)) { + CERROR("%s: Invalid root fid "DFID" during mount\n", + sbi->ll_md_exp->exp_obd->obd_name, + PFID(&sbi->ll_root_fid)); + GOTO(out_lock_cn_cb, err = -EINVAL); + } + CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid)); - sb->s_op = &lustre_super_operations; -#if THREAD_SIZE >= 8192 /*b=17630*/ && !defined(HAVE_FSTYPE_MOUNT) /*LU-812*/ + sb->s_op = &lustre_super_operations; +#if THREAD_SIZE >= 8192 /*b=17630*/ 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_FLMDSCAPA; - if (sbi->ll_flags & LL_SBI_RMT_CLIENT) - valid |= OBD_MD_FLRMTPERM; - else if (sbi->ll_flags & LL_SBI_ACL) - valid |= OBD_MD_FLACL; - - OBD_ALLOC_PTR(op_data); - if (op_data == NULL) - GOTO(out_lock_cn_cb, err = -ENOMEM); - - op_data->op_fid1 = sbi->ll_root_fid; - op_data->op_mode = 0; - op_data->op_capa1 = oc; - op_data->op_valid = valid; + /* make root inode + * XXX: move this to after cbd setup? */ + valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMDSCAPA; + if (sbi->ll_flags & LL_SBI_RMT_CLIENT) + valid |= OBD_MD_FLRMTPERM; + else if (sbi->ll_flags & LL_SBI_ACL) + valid |= OBD_MD_FLACL; + + OBD_ALLOC_PTR(op_data); + if (op_data == NULL) + GOTO(out_lock_cn_cb, err = -ENOMEM); + + op_data->op_fid1 = sbi->ll_root_fid; + op_data->op_mode = 0; + op_data->op_capa1 = oc; + op_data->op_valid = valid; + + err = md_getattr(sbi->ll_md_exp, op_data, &request); + if (oc) + capa_put(oc); + OBD_FREE_PTR(op_data); + if (err) { + CERROR("%s: md_getattr failed for root: rc = %d\n", + sbi->ll_md_exp->exp_obd->obd_name, err); + GOTO(out_lock_cn_cb, err); + } - err = md_getattr(sbi->ll_md_exp, op_data, &request); - if (oc) - capa_put(oc); - OBD_FREE_PTR(op_data); - if (err) { - CERROR("md_getattr failed for root: rc = %d\n", err); - 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); - if (err) { - CERROR("failed to understand root inode md: rc = %d\n", err); - ptlrpc_req_finished (request); - 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); + if (err) { + CERROR("failed to understand root inode md: rc = %d\n", err); + ptlrpc_req_finished(request); + GOTO(out_lock_cn_cb, err); + } LASSERT(fid_is_sane(&sbi->ll_root_fid)); - root = ll_iget(sb, cl_fid_build_ino(&sbi->ll_root_fid, 0), &lmd); + 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); @@ -539,13 +575,18 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, NULL); cl_sb_init(sb); - sb->s_root = d_alloc_root(root); + 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); + + sb->s_root = d_make_root(root); + if (sb->s_root == NULL) { + CERROR("%s: can't make root dentry\n", + ll_get_fsname(sb, NULL, 0)); + GOTO(out_root, err = -ENOMEM); + } #ifdef HAVE_DCACHE_LOCK - sb->s_root->d_op = &ll_d_root_ops; -#else - /* kernel >= 2.6.38 store dentry operations in sb->s_d_op. */ - d_set_d_op(sb->s_root, &ll_d_root_ops); - sb->s_d_op = &ll_d_ops; + sb->s_root->d_op = &ll_d_ops; #endif sbi->ll_sdev_orig = sb->s_dev; @@ -556,9 +597,10 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, /* 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)); - sbi->ll_mnt = mnt; + if (uuid != NULL) { + sb->s_dev = get_uuid2int(uuid->uuid, strlen(uuid->uuid)); + get_uuid2fsid(uuid->uuid, strlen(uuid->uuid), &sbi->ll_fsid); + } if (data != NULL) OBD_FREE_PTR(data); @@ -570,12 +612,14 @@ out_root: if (root) iput(root); out_lock_cn_cb: - obd_fid_fini(sbi->ll_dt_exp); + obd_fid_fini(sbi->ll_dt_exp->exp_obd); out_dt: obd_disconnect(sbi->ll_dt_exp); sbi->ll_dt_exp = NULL; + /* Make sure all OScs are gone, since cl_cache is accessing sbi. */ + obd_zombie_barrier(); out_md_fid: - obd_fid_fini(sbi->ll_md_exp); + obd_fid_fini(sbi->ll_md_exp->exp_obd); out_md: obd_disconnect(sbi->ll_md_exp); sbi->ll_md_exp = NULL; @@ -604,17 +648,17 @@ int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize) void ll_dump_inode(struct inode *inode) { - struct list_head *tmp; - int dentry_count = 0; + struct ll_d_hlist_node *tmp; + int dentry_count = 0; - LASSERT(inode != NULL); + LASSERT(inode != NULL); - list_for_each(tmp, &inode->i_dentry) - dentry_count++; + ll_d_hlist_for_each(tmp, &inode->i_dentry) + dentry_count++; - CERROR("inode %p dump: dev=%s ino=%lu mode=%o count=%u, %d dentries\n", - inode, ll_i2mdexp(inode)->exp_obd->obd_name, inode->i_ino, - inode->i_mode, atomic_read(&inode->i_count), dentry_count); + CERROR("inode %p dump: dev=%s ino=%lu mode=%o count=%u, %d dentries\n", + inode, ll_i2mdexp(inode)->exp_obd->obd_name, inode->i_ino, + inode->i_mode, atomic_read(&inode->i_count), dentry_count); } void lustre_dump_dentry(struct dentry *dentry, int recur) @@ -657,21 +701,22 @@ void client_common_put_super(struct super_block *sb) } #endif - obd_cancel_unused(sbi->ll_dt_exp, NULL, 0, NULL); - ll_close_thread_shutdown(sbi->ll_lcq); cl_sb_fini(sb); cfs_list_del(&sbi->ll_conn_chain); - obd_fid_fini(sbi->ll_dt_exp); + obd_fid_fini(sbi->ll_dt_exp->exp_obd); obd_disconnect(sbi->ll_dt_exp); sbi->ll_dt_exp = NULL; + /* wait till all OSCs are gone, since cl_cache is accessing sbi. + * see LU-2543. */ + obd_zombie_barrier(); lprocfs_unregister_mountpoint(sbi); - obd_fid_fini(sbi->ll_md_exp); + obd_fid_fini(sbi->ll_md_exp->exp_obd); obd_disconnect(sbi->ll_md_exp); sbi->ll_md_exp = NULL; @@ -692,9 +737,11 @@ void ll_kill_super(struct super_block *sb) /* we need restore s_dev from changed for clustred NFS before put_super * because new kernels have cached s_dev and change sb->s_dev in * put_super not affected real removing devices */ - if (sbi) - sb->s_dev = sbi->ll_sdev_orig; - EXIT; + if (sbi) { + sb->s_dev = sbi->ll_sdev_orig; + sbi->ll_umounting = 1; + } + EXIT; } char *ll_read_opt(const char *opt, char *data) @@ -797,6 +844,16 @@ static int ll_options(char *options, int *flags) *flags |= 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) { @@ -864,14 +921,14 @@ next: void ll_lli_init(struct ll_inode_info *lli) { - lli->lli_inode_magic = LLI_INODE_MAGIC; - lli->lli_flags = 0; - lli->lli_ioepoch = 0; - lli->lli_maxbytes = MAX_LFS_FILESIZE; - cfs_spin_lock_init(&lli->lli_lock); - lli->lli_posix_acl = NULL; - lli->lli_remote_perms = NULL; - cfs_mutex_init(&lli->lli_rmtperm_mutex); + lli->lli_inode_magic = LLI_INODE_MAGIC; + lli->lli_flags = 0; + lli->lli_ioepoch = 0; + lli->lli_maxbytes = MAX_LFS_FILESIZE; + 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); CFS_INIT_LIST_HEAD(&lli->lli_close_list); @@ -886,48 +943,46 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_open_fd_read_count = 0; lli->lli_open_fd_write_count = 0; lli->lli_open_fd_exec_count = 0; - cfs_mutex_init(&lli->lli_och_mutex); - cfs_spin_lock_init(&lli->lli_agl_lock); + mutex_init(&lli->lli_och_mutex); + spin_lock_init(&lli->lli_agl_lock); lli->lli_has_smd = false; - lli->lli_clob = NULL; - - LASSERT(lli->lli_vfs_inode.i_mode != 0); - if (S_ISDIR(lli->lli_vfs_inode.i_mode)) { - cfs_mutex_init(&lli->lli_readdir_mutex); - lli->lli_opendir_key = NULL; - lli->lli_sai = NULL; - lli->lli_sa_pos = 0; - lli->lli_def_acl = NULL; - cfs_spin_lock_init(&lli->lli_sa_lock); - lli->lli_opendir_pid = 0; - } else { - cfs_sema_init(&lli->lli_size_sem, 1); - lli->lli_size_sem_owner = NULL; - lli->lli_symlink_name = NULL; - cfs_init_rwsem(&lli->lli_trunc_sem); - cfs_mutex_init(&lli->lli_write_mutex); - cfs_init_rwsem(&lli->lli_glimpse_sem); + lli->lli_layout_gen = LL_LAYOUT_GEN_NONE; + lli->lli_clob = NULL; + + init_rwsem(&lli->lli_xattrs_list_rwsem); + mutex_init(&lli->lli_xattrs_enq_lock); + + LASSERT(lli->lli_vfs_inode.i_mode != 0); + if (S_ISDIR(lli->lli_vfs_inode.i_mode)) { + mutex_init(&lli->lli_readdir_mutex); + lli->lli_opendir_key = NULL; + lli->lli_sai = NULL; + lli->lli_def_acl = NULL; + spin_lock_init(&lli->lli_sa_lock); + lli->lli_opendir_pid = 0; + } else { + sema_init(&lli->lli_size_sem, 1); + lli->lli_size_sem_owner = NULL; + lli->lli_symlink_name = NULL; + init_rwsem(&lli->lli_trunc_sem); + mutex_init(&lli->lli_write_mutex); + init_rwsem(&lli->lli_glimpse_sem); lli->lli_glimpse_time = 0; CFS_INIT_LIST_HEAD(&lli->lli_agl_list); lli->lli_agl_index = 0; lli->lli_async_rc = 0; + lli->lli_volatile = false; } - cfs_mutex_init(&lli->lli_layout_mutex); + mutex_init(&lli->lli_layout_mutex); } static inline int ll_bdi_register(struct backing_dev_info *bdi) { -#ifdef HAVE_BDI_REGISTER static atomic_t ll_bdi_num = ATOMIC_INIT(0); -#ifdef HAVE_BDI_NAME bdi->name = "lustre"; -#endif return bdi_register(bdi, NULL, "lustre-%d", atomic_inc_return(&ll_bdi_num)); -#else - return 0; -#endif } int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) @@ -963,17 +1018,19 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) if (err) GOTO(out_free, err); - err = ll_bdi_init(&lsi->lsi_bdi); - if (err) - GOTO(out_free, err); - lsi->lsi_flags |= LSI_BDI_INITIALIZED; - lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY; - err = ll_bdi_register(&lsi->lsi_bdi); - if (err) - GOTO(out_free, err); + err = bdi_init(&lsi->lsi_bdi); + if (err) + GOTO(out_free, err); + lsi->lsi_flags |= LSI_BDI_INITIALIZED; + lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY; + err = ll_bdi_register(&lsi->lsi_bdi); + if (err) + GOTO(out_free, err); -#ifdef HAVE_SB_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 @@ -981,7 +1038,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) 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); if (err < 0) { @@ -1032,7 +1089,7 @@ void lu_context_keys_dump(void); void ll_put_super(struct super_block *sb) { - struct config_llog_instance cfg; + struct config_llog_instance cfg, params_cfg; struct obd_device *obd; struct lustre_sb_info *lsi = s2lsi(sb); struct ll_sb_info *sbi = ll_s2sbi(sb); @@ -1047,6 +1104,9 @@ void ll_put_super(struct super_block *sb) cfg.cfg_instance = sb; lustre_end_log(sb, profilenm, &cfg); + params_cfg.cfg_instance = sb; + lustre_end_log(sb, PARAMS_FILENAME, ¶ms_cfg); + if (sbi->ll_md_exp) { obd = class_exp2obd(sbi->ll_md_exp); if (obd) @@ -1079,23 +1139,46 @@ void ll_put_super(struct super_block *sb) if (profilenm) class_del_profile(profilenm); - if (lsi->lsi_flags & LSI_BDI_INITIALIZED) { - ll_bdi_destroy(&lsi->lsi_bdi); - lsi->lsi_flags &= ~LSI_BDI_INITIALIZED; - } + if (lsi->lsi_flags & LSI_BDI_INITIALIZED) { + bdi_destroy(&lsi->lsi_bdi); + lsi->lsi_flags &= ~LSI_BDI_INITIALIZED; + } ll_free_sbi(sb); lsi->lsi_llsbi = NULL; lustre_common_put_super(sb); - cl_env_cache_purge(~0); - cfs_module_put(THIS_MODULE); EXIT; } /* client_put_super */ +struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock) +{ + struct inode *inode = NULL; + + /* NOTE: we depend on atomic igrab() -bzzz */ + lock_res_and_lock(lock); + if (lock->l_resource->lr_lvb_inode) { + struct ll_inode_info * lli; + lli = ll_i2info(lock->l_resource->lr_lvb_inode); + if (lli->lli_inode_magic == LLI_INODE_MAGIC) { + inode = igrab(lock->l_resource->lr_lvb_inode); + } else { + inode = lock->l_resource->lr_lvb_inode; + LDLM_DEBUG_LIMIT(inode->i_state & I_FREEING ? D_INFO : + D_WARNING, lock, "lr_lvb_inode %p is " + "bogus: magic %08x", + lock->l_resource->lr_lvb_inode, + lli->lli_inode_magic); + inode = NULL; + } + } + unlock_res_and_lock(lock); + return inode; +} + struct inode *ll_inode_from_lock(struct ldlm_lock *lock) { struct inode *inode = NULL; @@ -1118,18 +1201,6 @@ struct inode *ll_inode_from_lock(struct ldlm_lock *lock) return inode; } -static int null_if_equal(struct ldlm_lock *lock, void *data) -{ - if (data == lock->l_ast_data) { - lock->l_ast_data = NULL; - - if (lock->l_req_mode != lock->l_granted_mode) - LDLM_ERROR(lock,"clearing inode with ungranted lock"); - } - - return LDLM_ITER_CONTINUE; -} - void ll_clear_inode(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); @@ -1146,9 +1217,10 @@ void ll_clear_inode(struct inode *inode) LASSERT(lli->lli_opendir_pid == 0); } + spin_lock(&lli->lli_lock); ll_i2info(inode)->lli_flags &= ~LLIF_MDS_SIZE_LOCK; - md_change_cbdata(sbi->ll_md_exp, ll_inode2fid(inode), - null_if_equal, inode); + spin_unlock(&lli->lli_lock); + md_null_inode(sbi->ll_md_exp, ll_inode2fid(inode)); LASSERT(!lli->lli_open_fd_write_count); LASSERT(!lli->lli_open_fd_read_count); @@ -1167,6 +1239,8 @@ void ll_clear_inode(struct inode *inode) lli->lli_symlink_name = NULL; } + ll_xattr_cache_destroy(inode); + if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { LASSERT(lli->lli_posix_acl == NULL); if (lli->lli_remote_perms) { @@ -1215,24 +1289,24 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, NULL, 0, &request, mod); - if (rc) { - ptlrpc_req_finished(request); - if (rc == -ENOENT) { - inode->i_nlink = 0; - /* Unlinked special device node? Or just a race? - * Pretend we done everything. */ - if (!S_ISREG(inode->i_mode) && - !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); - op_data->op_attr.ia_valid = ia_valid; - } - } else if (rc != -EPERM && rc != -EACCES && rc != -ETXTBSY) { - CERROR("md_setattr fails: rc = %d\n", rc); - } - RETURN(rc); - } + if (rc) { + ptlrpc_req_finished(request); + if (rc == -ENOENT) { + clear_nlink(inode); + /* Unlinked special device node? Or just a race? + * Pretend we done everything. */ + if (!S_ISREG(inode->i_mode) && + !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); + op_data->op_attr.ia_valid = ia_valid; + } + } else if (rc != -EPERM && rc != -EACCES && rc != -ETXTBSY) { + CERROR("md_setattr fails: rc = %d\n", rc); + } + RETURN(rc); + } rc = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp, sbi->ll_md_exp, &md); @@ -1241,16 +1315,12 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, RETURN(rc); } - /* We want to adjust timestamps. - * If there is at least some data in file, we cleared ATTR_SIZE - * to avoid update size, otherwise it is important to do.(SOM case) - * (bug 6196) */ - ia_valid = op_data->op_attr.ia_valid; - /* Since we set ATTR_*_SET flags above, and already done permission - * check, So don't let inode_change_ok() check it again. */ - op_data->op_attr.ia_valid &= ~TIMES_SET_FLAGS; - rc = simple_setattr(dentry, &op_data->op_attr); - op_data->op_attr.ia_valid = ia_valid; + ia_valid = op_data->op_attr.ia_valid; + /* 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); + rc = simple_setattr(dentry, &op_data->op_attr); + op_data->op_attr.ia_valid = ia_valid; /* Extract epoch data if obtained. */ op_data->op_handle = md.body->handle; @@ -1314,50 +1384,6 @@ static int ll_setattr_ost(struct inode *inode, struct iattr *attr) return rc; } -#ifndef HAVE_VFS_INODE_NEWSIZE_OK -/** - * inode_newsize_ok - may this inode be truncated to a given size - * @inode: the inode to be truncated - * @offset: the new size to assign to the inode - * @Returns: 0 on success, -ve errno on failure - * - * inode_newsize_ok will check filesystem limits and ulimits to check that the - * new inode size is within limits. inode_newsize_ok will also send SIGXFSZ - * when necessary. Caller must not proceed with inode size change if failure is - * returned. @inode must be a file (not directory), with appropriate - * permissions to allow truncate (inode_newsize_ok does NOT check these - * conditions). - * - * inode_newsize_ok must be called with i_mutex held. - */ -int inode_newsize_ok(const struct inode *inode, loff_t offset) -{ - if (inode->i_size < offset) { - unsigned long limit; - - limit = rlimit(RLIMIT_FSIZE); - if (limit != RLIM_INFINITY && offset > limit) - goto out_sig; - if (offset > inode->i_sb->s_maxbytes) - goto out_big; - } else { - /* - * truncation of in-use swapfiles is disallowed - it would - * cause subsequent swapout to scribble on the now-freed - * blocks. - */ - if (IS_SWAPFILE(inode)) - return -ETXTBSY; - } - - return 0; -out_sig: - send_sig(SIGXFSZ, current, 0); -out_big: - return -EFBIG; -} -#endif - /* 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. @@ -1370,22 +1396,26 @@ out_big: * to the OST with the punch RPC, otherwise we do an explicit setattr RPC. * I don't believe it is possible to get e.g. ATTR_MTIME_SET and ATTR_SIZE * at the same time. + * + * In case of HSMimport, we only set attr on MDS. */ -int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) +int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) { - struct lov_stripe_md *lsm; struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); struct md_op_data *op_data = NULL; struct md_open_data *mod = NULL; - int ia_valid = attr->ia_valid; + bool file_is_released = false; int rc = 0, rc1 = 0; ENTRY; - CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu valid %x\n", inode->i_ino, - attr->ia_valid); + CDEBUG(D_VFSTRACE, "%s: setattr inode %p/fid:"DFID" from %llu to %llu, " + "valid %x, hsm_import %d\n", + ll_get_fsname(inode->i_sb, NULL, 0), inode, + PFID(&lli->lli_fid), i_size_read(inode), attr->ia_size, + attr->ia_valid, hsm_import); - if (ia_valid & ATTR_SIZE) { + if (attr->ia_valid & ATTR_SIZE) { /* Check new size against VFS/VM file size limit and rlimit */ rc = inode_newsize_ok(inode, attr->ia_size); if (rc) @@ -1405,7 +1435,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) } /* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */ - if (ia_valid & TIMES_SET_FLAGS) { + if (attr->ia_valid & TIMES_SET_FLAGS) { if (cfs_curproc_fsuid() != inode->i_uid && !cfs_capable(CFS_CAP_FOWNER)) RETURN(-EPERM); @@ -1416,11 +1446,13 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) attr->ia_ctime = CFS_CURRENT_TIME; attr->ia_valid |= ATTR_CTIME_SET; } - if (!(ia_valid & ATTR_ATIME_SET) && (attr->ia_valid & ATTR_ATIME)) { + if (!(attr->ia_valid & ATTR_ATIME_SET) && + (attr->ia_valid & ATTR_ATIME)) { attr->ia_atime = CFS_CURRENT_TIME; attr->ia_valid |= ATTR_ATIME_SET; } - if (!(ia_valid & ATTR_MTIME_SET) && (attr->ia_valid & ATTR_MTIME)) { + if (!(attr->ia_valid & ATTR_MTIME_SET) && + (attr->ia_valid & ATTR_MTIME)) { attr->ia_mtime = CFS_CURRENT_TIME; attr->ia_valid |= ATTR_MTIME_SET; } @@ -1430,6 +1462,14 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime), cfs_time_current_sec()); + /* If we are changing file size, file content is modified, flag it. */ + if (attr->ia_valid & ATTR_SIZE) { + attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; + spin_lock(&lli->lli_lock); + lli->lli_flags |= LLIF_DATA_MODIFIED; + spin_unlock(&lli->lli_lock); + } + /* We always do an MDS RPC, even if we're only changing the size; * only the MDS knows whether truncate() should fail with -ETXTBUSY */ @@ -1438,46 +1478,67 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) RETURN(-ENOMEM); if (!S_ISDIR(inode->i_mode)) { - if (ia_valid & ATTR_SIZE) - UP_WRITE_I_ALLOC_SEM(inode); + if (attr->ia_valid & ATTR_SIZE) + inode_dio_write_done(inode); mutex_unlock(&inode->i_mutex); - cfs_down_write(&lli->lli_trunc_sem); - mutex_lock(&inode->i_mutex); - if (ia_valid & ATTR_SIZE) - DOWN_WRITE_I_ALLOC_SEM(inode); + down_write(&lli->lli_trunc_sem); } - /* We need a steady stripe configuration for setattr to avoid - * confusion. */ - lsm = ccc_inode_lsm_get(inode); - - /* NB: ATTR_SIZE will only be set after this point if the size - * resides on the MDS, ie, this file has no objects. */ - if (lsm != NULL) - attr->ia_valid &= ~ATTR_SIZE; - memcpy(&op_data->op_attr, attr, sizeof(*attr)); /* Open epoch for truncate. */ if (exp_connect_som(ll_i2mdexp(inode)) && - (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) + (attr->ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) op_data->op_flags = MF_EPOCH_OPEN; + /* 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 lov_stripe_md *lsm; + __u32 gen; + + ll_layout_refresh(inode, &gen); + lsm = ccc_inode_lsm_get(inode); + if (lsm && lsm->lsm_pattern & LOV_PATTERN_F_RELEASED) + file_is_released = true; + ccc_inode_lsm_put(inode, lsm); + } + + /* if not in HSM import mode, clear size attr for released file + * we clear the attribute send to MDT in op_data, not the original + * received from caller in attr which is used later to + * decide return code */ + if (file_is_released && (attr->ia_valid & ATTR_SIZE) && !hsm_import) + op_data->op_attr.ia_valid &= ~ATTR_SIZE; + rc = ll_md_setattr(dentry, op_data, &mod); if (rc) GOTO(out, rc); + /* truncate failed (only when non HSM import), others succeed */ + if (file_is_released) { + if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) + GOTO(out, rc = -ENODATA); + else + GOTO(out, rc = 0); + } + + /* 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); + } + ll_ioepoch_open(lli, op_data->op_ioepoch); - if (lsm == NULL || !S_ISREG(inode->i_mode)) { - CDEBUG(D_INODE, "no lsm: not setting attrs on OST\n"); + if (!S_ISREG(inode->i_mode)) GOTO(out, rc = 0); - } - if (ia_valid & ATTR_SIZE) - attr->ia_valid |= ATTR_SIZE; - if (ia_valid & (ATTR_SIZE | - ATTR_ATIME | ATTR_ATIME_SET | - ATTR_MTIME | ATTR_MTIME_SET)) + if (attr->ia_valid & (ATTR_SIZE | + ATTR_ATIME | ATTR_ATIME_SET | + ATTR_MTIME | ATTR_MTIME_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 @@ -1485,9 +1546,9 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) * setting times to past, but it is necessary due to possible * time de-synchronization between MDT inode and OST objects */ rc = ll_setattr_ost(inode, attr); + } EXIT; out: - ccc_inode_lsm_put(inode, lsm); if (op_data) { if (op_data->op_ioepoch) { rc1 = ll_setattr_done_writing(inode, op_data, mod); @@ -1496,41 +1557,45 @@ out: } ll_finish_md_op_data(op_data); } - if (!S_ISDIR(inode->i_mode)) - cfs_up_write(&lli->lli_trunc_sem); + if (!S_ISDIR(inode->i_mode)) { + up_write(&lli->lli_trunc_sem); + mutex_lock(&inode->i_mutex); + if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) + inode_dio_wait(inode); + } - ll_stats_ops_tally(ll_i2sbi(inode), (ia_valid & ATTR_SIZE) ? - LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1); + ll_stats_ops_tally(ll_i2sbi(inode), (attr->ia_valid & ATTR_SIZE) ? + LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1); - return rc; + return rc; } int ll_setattr(struct dentry *de, struct iattr *attr) { - int mode = de->d_inode->i_mode; - - if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) == - (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) - attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; - - if (((attr->ia_valid & (ATTR_MODE|ATTR_FORCE|ATTR_SIZE)) == - (ATTR_SIZE|ATTR_MODE)) && - (((mode & S_ISUID) && !(attr->ia_mode & S_ISUID)) || - (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && - !(attr->ia_mode & S_ISGID)))) - attr->ia_valid |= ATTR_FORCE; - - if ((mode & S_ISUID) && - !(attr->ia_mode & S_ISUID) && - !(attr->ia_valid & ATTR_KILL_SUID)) - attr->ia_valid |= ATTR_KILL_SUID; - - if (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && - !(attr->ia_mode & S_ISGID) && - !(attr->ia_valid & ATTR_KILL_SGID)) - attr->ia_valid |= ATTR_KILL_SGID; - - return ll_setattr_raw(de, attr); + int mode = de->d_inode->i_mode; + + if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) == + (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) + attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; + + if (((attr->ia_valid & (ATTR_MODE|ATTR_FORCE|ATTR_SIZE)) == + (ATTR_SIZE|ATTR_MODE)) && + (((mode & S_ISUID) && !(attr->ia_mode & S_ISUID)) || + (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && + !(attr->ia_mode & S_ISGID)))) + attr->ia_valid |= ATTR_FORCE; + + if ((mode & S_ISUID) && + !(attr->ia_mode & S_ISUID) && + !(attr->ia_valid & ATTR_KILL_SUID)) + attr->ia_valid |= ATTR_KILL_SUID; + + if (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && + !(attr->ia_mode & S_ISGID) && + !(attr->ia_valid & ATTR_KILL_SGID)) + attr->ia_valid |= ATTR_KILL_SGID; + + return ll_setattr_raw(de, attr, false); } int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, @@ -1617,8 +1682,8 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs) sfs->f_blocks = osfs.os_blocks; sfs->f_bfree = osfs.os_bfree; sfs->f_bavail = osfs.os_bavail; - - return 0; + sfs->f_fsid = ll_s2sbi(sb)->ll_fsid; + return 0; } void ll_inode_size_lock(struct inode *inode) @@ -1629,7 +1694,7 @@ void ll_inode_size_lock(struct inode *inode) lli = ll_i2info(inode); LASSERT(lli->lli_size_sem_owner != current); - cfs_down(&lli->lli_size_sem); + down(&lli->lli_size_sem); LASSERT(lli->lli_size_sem_owner == NULL); lli->lli_size_sem_owner = current; } @@ -1641,7 +1706,7 @@ void ll_inode_size_unlock(struct inode *inode) lli = ll_i2info(inode); LASSERT(lli->lli_size_sem_owner == current); lli->lli_size_sem_owner = NULL; - cfs_up(&lli->lli_size_sem); + up(&lli->lli_size_sem); } void ll_update_inode(struct inode *inode, struct lustre_md *md) @@ -1653,23 +1718,13 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) LASSERT ((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0)); if (lsm != NULL) { - LASSERT(S_ISREG(inode->i_mode)); - cfs_mutex_lock(&lli->lli_och_mutex); - CDEBUG(D_INODE, "adding lsm %p to inode %lu/%u(%p)\n", - lsm, inode->i_ino, inode->i_generation, inode); - /* cl_file_inode_init must go before lli_has_smd or a race - * is possible where client thinks the file has stripes, - * but lov raid0 is not setup yet and parallel e.g. - * glimpse would try to use uninitialized lov */ - if (cl_file_inode_init(inode, md) == 0) - lli->lli_has_smd = true; - cfs_mutex_unlock(&lli->lli_och_mutex); + if (!lli->lli_has_smd && + !(sbi->ll_flags & LL_SBI_LAYOUT_LOCK)) + cl_file_inode_init(inode, md); lli->lli_maxbytes = lsm->lsm_maxbytes; if (lli->lli_maxbytes > MAX_LFS_FILESIZE) lli->lli_maxbytes = MAX_LFS_FILESIZE; - if (md->lsm != NULL) - obd_free_memmd(ll_i2dtexp(inode), &md->lsm); } if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { @@ -1677,15 +1732,16 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) ll_update_remote_perm(inode, md->remote_perm); } #ifdef CONFIG_FS_POSIX_ACL - else if (body->valid & OBD_MD_FLACL) { - cfs_spin_lock(&lli->lli_lock); - if (lli->lli_posix_acl) - posix_acl_release(lli->lli_posix_acl); - lli->lli_posix_acl = md->posix_acl; - cfs_spin_unlock(&lli->lli_lock); - } + else if (body->valid & OBD_MD_FLACL) { + spin_lock(&lli->lli_lock); + if (lli->lli_posix_acl) + posix_acl_release(lli->lli_posix_acl); + lli->lli_posix_acl = md->posix_acl; + spin_unlock(&lli->lli_lock); + } #endif - inode->i_ino = cl_fid_build_ino(&body->fid1, 0); + inode->i_ino = cl_fid_build_ino(&body->fid1, + sbi->ll_flags & LL_SBI_32BIT_API); inode->i_generation = cl_fid_build_gen(&body->fid1); if (body->valid & OBD_MD_FLATIME) { @@ -1717,16 +1773,16 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) } else { inode->i_blkbits = inode->i_sb->s_blocksize_bits; } - if (body->valid & OBD_MD_FLUID) - inode->i_uid = body->uid; - if (body->valid & OBD_MD_FLGID) - inode->i_gid = body->gid; - if (body->valid & OBD_MD_FLFLAGS) - inode->i_flags = ll_ext_to_inode_flags(body->flags); - if (body->valid & OBD_MD_FLNLINK) - inode->i_nlink = body->nlink; - if (body->valid & OBD_MD_FLRDEV) - inode->i_rdev = old_decode_dev(body->rdev); + if (body->valid & OBD_MD_FLUID) + inode->i_uid = body->uid; + if (body->valid & OBD_MD_FLGID) + inode->i_gid = body->gid; + if (body->valid & OBD_MD_FLFLAGS) + inode->i_flags = ll_ext_to_inode_flags(body->flags); + if (body->valid & OBD_MD_FLNLINK) + set_nlink(inode, body->nlink); + if (body->valid & OBD_MD_FLRDEV) + inode->i_rdev = old_decode_dev(body->rdev); if (body->valid & OBD_MD_FLID) { /* FID shouldn't be changed! */ @@ -1744,7 +1800,7 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) if (body->valid & OBD_MD_FLSIZE) { if (exp_connect_som(ll_i2mdexp(inode)) && - S_ISREG(inode->i_mode) && lli->lli_has_smd) { + S_ISREG(inode->i_mode)) { struct lustre_handle lockh; ldlm_mode_t mode; @@ -1753,7 +1809,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) * lock on the client and set LLIF_MDS_SIZE_LOCK holding * it. */ mode = ll_take_md_lock(inode, MDS_INODELOCK_UPDATE, - &lockh); + &lockh, LDLM_FL_CBPENDING, + LCK_CR | LCK_CW | + LCK_PR | LCK_PW); if (mode) { if (lli->lli_flags & (LLIF_DONE_WRITING | LLIF_EPOCH_PENDING | @@ -1766,7 +1824,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) /* Use old size assignment to avoid * deadlock bz14138 & bz14326 */ i_size_write(inode, body->size); + spin_lock(&lli->lli_lock); lli->lli_flags |= LLIF_MDS_SIZE_LOCK; + spin_unlock(&lli->lli_lock); } ldlm_lock_decref(&lockh, mode); } @@ -1791,6 +1851,11 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) LASSERT(md->oss_capa); ll_add_capa(inode, md->oss_capa); } + + if (body->valid & OBD_MD_TSTATE) { + if (body->t_state & MS_RESTORE) + lli->lli_flags |= LLIF_FILE_RESTORING; + } } void ll_read_inode2(struct inode *inode, void *opaque) @@ -1829,7 +1894,6 @@ void ll_read_inode2(struct inode *inode, void *opaque) } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ll_dir_inode_operations; inode->i_fop = &ll_dir_operations; - inode->i_mapping->a_ops = (struct address_space_operations *)&ll_dir_aops; EXIT; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &ll_fast_symlink_inode_operations; @@ -1837,8 +1901,8 @@ void ll_read_inode2(struct inode *inode, void *opaque) } else { inode->i_op = &ll_special_inode_operations; - init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + init_special_inode(inode, inode->i_mode, + inode->i_rdev); EXIT; } @@ -1847,18 +1911,13 @@ void ll_read_inode2(struct inode *inode, void *opaque) void ll_delete_inode(struct inode *inode) { struct cl_inode_info *lli = cl_i2info(inode); - struct ll_sb_info *sbi = ll_i2sbi(inode); - int rc; ENTRY; - rc = obd_fid_delete(sbi->ll_md_exp, ll_inode2fid(inode)); - if (rc) - CERROR("fid_delete() failed, rc %d\n", rc); - if (S_ISREG(inode->i_mode) && lli->lli_clob != NULL) /* discard all dirty pages before truncating them, required by * osc_extent implementation at LU-1030. */ - cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, CL_FSYNC_DISCARD); + cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, + CL_FSYNC_DISCARD, 1); truncate_inode_pages(&inode->i_data, 0); @@ -1875,11 +1934,9 @@ void ll_delete_inode(struct inode *inode) /* Workaround end */ #ifdef HAVE_SBOPS_EVICT_INODE - ll_clear_inode(inode); - end_writeback(inode); -#else - clear_inode(inode); + ll_clear_inode(inode); #endif + clear_inode(inode); EXIT; } @@ -1941,20 +1998,21 @@ int ll_iocontrol(struct inode *inode, struct file *file, if (rc) RETURN(rc); - OBDO_ALLOC(oinfo.oi_oa); - if (!oinfo.oi_oa) - RETURN(-ENOMEM); + inode->i_flags = ll_ext_to_inode_flags(flags); lsm = ccc_inode_lsm_get(inode); - if (lsm == NULL) { - inode->i_flags = ll_ext_to_inode_flags(flags); - OBDO_FREE(oinfo.oi_oa); + if (!lsm_has_objects(lsm)) { + ccc_inode_lsm_put(inode, lsm); RETURN(0); } + OBDO_ALLOC(oinfo.oi_oa); + if (!oinfo.oi_oa) { + ccc_inode_lsm_put(inode, lsm); + RETURN(-ENOMEM); + } oinfo.oi_md = lsm; - oinfo.oi_oa->o_id = lsm->lsm_object_id; - oinfo.oi_oa->o_seq = lsm->lsm_object_seq; + oinfo.oi_oa->o_oi = lsm->lsm_oi; oinfo.oi_oa->o_flags = flags; oinfo.oi_oa->o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS | OBD_MD_FLGROUP; @@ -1993,26 +2051,13 @@ int ll_flush_ctx(struct inode *inode) } /* umount -f client means force down, don't save state */ -#ifdef HAVE_UMOUNTBEGIN_VFSMOUNT -void ll_umount_begin(struct vfsmount *vfsmnt, int flags) -{ - struct super_block *sb = vfsmnt->mnt_sb; -#else void ll_umount_begin(struct super_block *sb) { -#endif struct ll_sb_info *sbi = ll_s2sbi(sb); struct obd_device *obd; struct obd_ioctl_data *ioc_data; ENTRY; -#ifdef HAVE_UMOUNTBEGIN_VFSMOUNT - if (!(flags & MNT_FORCE)) { - EXIT; - return; - } -#endif - CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb, sb->s_count, atomic_read(&sb->s_active)); @@ -2035,33 +2080,21 @@ void ll_umount_begin(struct super_block *sb) obd->obd_force = 1; OBD_ALLOC_PTR(ioc_data); - if (ioc_data) { - obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_md_exp, - sizeof ioc_data, ioc_data, NULL); + if (ioc_data) { + obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_md_exp, + sizeof *ioc_data, ioc_data, NULL); - obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_dt_exp, - sizeof ioc_data, ioc_data, NULL); - - OBD_FREE_PTR(ioc_data); - } + obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_dt_exp, + sizeof *ioc_data, ioc_data, NULL); + OBD_FREE_PTR(ioc_data); + } /* 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. */ cfs_schedule(); -#ifdef HAVE_UMOUNTBEGIN_VFSMOUNT - if (atomic_read(&vfsmnt->mnt_count) > 2) { - cfs_schedule_timeout_and_set_state(CFS_TASK_INTERRUPTIBLE, - cfs_time_seconds(1)); - if (atomic_read(&vfsmnt->mnt_count) > 2) - LCONSOLE_WARN("Mount still busy with %d refs! You " - "may try to umount it a bit later\n", - atomic_read(&vfsmnt->mnt_count)); - } -#endif - EXIT; } @@ -2097,13 +2130,11 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data) return 0; } -int ll_prep_inode(struct inode **inode, - struct ptlrpc_request *req, - struct super_block *sb) +int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, + struct super_block *sb, struct lookup_intent *it) { struct ll_sb_info *sbi = NULL; struct lustre_md md; - __u64 ibits; int rc; ENTRY; @@ -2125,10 +2156,10 @@ int ll_prep_inode(struct inode **inode, */ LASSERT(fid_is_sane(&md.body->fid1)); - *inode = ll_iget(sb, cl_fid_build_ino(&md.body->fid1, 0), &md); + *inode = ll_iget(sb, cl_fid_build_ino(&md.body->fid1, + sbi->ll_flags & LL_SBI_32BIT_API), + &md); if (*inode == NULL || IS_ERR(*inode)) { - if (md.lsm) - obd_free_memmd(sbi->ll_dt_exp, &md.lsm); #ifdef CONFIG_FS_POSIX_ACL if (md.posix_acl) { posix_acl_release(md.posix_acl); @@ -2142,16 +2173,37 @@ int ll_prep_inode(struct inode **inode, } } - /* sanity check for LAYOUT lock. */ - ibits = MDS_INODELOCK_LAYOUT; - if (S_ISREG(md.body->mode) && sbi->ll_flags & LL_SBI_LAYOUT_LOCK && - md.lsm != NULL && !ll_have_md_lock(*inode, &ibits, LCK_MINMODE)) { - CERROR("%s: inode "DFID" (%p) layout lock not granted.\n", - ll_get_fsname(*inode), PFID(ll_inode2fid(*inode)), - *inode); + /* Handling piggyback layout lock. + * Layout lock can be piggybacked by getattr and open request. + * The lsm can be applied to inode only if it comes with a layout lock + * otherwise correct layout may be overwritten, for example: + * 1. proc1: mdt returns a lsm but not granting layout + * 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) { + struct lustre_handle lockh; + struct ldlm_lock *lock; + + lockh.cookie = it->d.lustre.it_lock_handle; + lock = ldlm_handle2lock(&lockh); + LASSERT(lock != NULL); + if (ldlm_has_layout(lock)) { + struct cl_object_conf conf; + + memset(&conf, 0, sizeof(conf)); + conf.coc_opc = OBJECT_CONF_SET; + conf.coc_inode = *inode; + conf.coc_lock = lock; + conf.u.coc_md = &md; + (void)ll_layout_conf(*inode, &conf); + } + LDLM_LOCK_PUT(lock); } out: + if (md.lsm != NULL) + obd_free_memmd(sbi->ll_dt_exp, &md.lsm); md_free_lustre_md(sbi->ll_md_exp, &md); RETURN(rc); } @@ -2163,6 +2215,7 @@ int ll_obd_statfs(struct inode *inode, void *arg) char *buf = NULL; struct obd_ioctl_data *data = NULL; __u32 type; + __u32 flags; int len = 0, rc; if (!inode || !(sbi = ll_i2sbi(inode))) @@ -2184,14 +2237,15 @@ int ll_obd_statfs(struct inode *inode, void *arg) GOTO(out_statfs, rc = -EINVAL); memcpy(&type, data->ioc_inlbuf1, sizeof(__u32)); - if (type == LL_STATFS_LMV) + if (type & LL_STATFS_LMV) exp = sbi->ll_md_exp; - else if (type == LL_STATFS_LOV) + else if (type & LL_STATFS_LOV) exp = sbi->ll_dt_exp; else GOTO(out_statfs, rc = -ENODEV); - rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, NULL); + flags = (type & LL_STATFS_NODELAY) ? OBD_STATFS_NODELAY : 0; + rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, &flags); if (rc) GOTO(out_statfs, rc); out_statfs: @@ -2258,17 +2312,21 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data, op_data->op_capa2 = NULL; } - 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_fsuid = cfs_curproc_fsuid(); - op_data->op_fsgid = cfs_curproc_fsgid(); - op_data->op_cap = cfs_curproc_cap_pack(); - op_data->op_bias = MDS_CHECK_SPLIT; - op_data->op_opc = opc; - op_data->op_mds = 0; - op_data->op_data = data; + op_data->op_name = name; + op_data->op_namelen = namelen; + op_data->op_mode = mode; + op_data->op_mod_time = cfs_time_current_sec(); + op_data->op_fsuid = cfs_curproc_fsuid(); + op_data->op_fsgid = cfs_curproc_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, NULL)) + op_data->op_bias |= MDS_CREATE_VOLATILE; + op_data->op_opc = opc; + op_data->op_mds = 0; + op_data->op_data = data; /* If the file is being opened after mknod() (normally due to NFS) * try to use the default stripe data from parent directory for @@ -2277,14 +2335,18 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data, !ll_i2info(i2)->lli_has_smd) { struct ll_inode_info *lli = ll_i2info(i2); - cfs_spin_lock(&lli->lli_lock); + spin_lock(&lli->lli_lock); if (likely(!lli->lli_has_smd && !fid_is_zero(&lli->lli_pfid))) - op_data->op_fid1 = lli->lli_pfid; - cfs_spin_unlock(&lli->lli_lock); - /** We ignore parent's capability temporary. */ - } + op_data->op_fid1 = lli->lli_pfid; + spin_unlock(&lli->lli_lock); + /** We ignore parent's capability temporary. */ + } + + /* 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; + return op_data; } void ll_finish_md_op_data(struct md_op_data *op_data) @@ -2294,12 +2356,21 @@ void ll_finish_md_op_data(struct md_op_data *op_data) OBD_FREE_PTR(op_data); } +#ifdef HAVE_SUPEROPS_USE_DENTRY +int ll_show_options(struct seq_file *seq, struct dentry *dentry) +#else int ll_show_options(struct seq_file *seq, struct vfsmount *vfs) +#endif { struct ll_sb_info *sbi; - LASSERT((seq != NULL) && (vfs != NULL)); - sbi = ll_s2sbi(vfs->mnt_sb); +#ifdef HAVE_SUPEROPS_USE_DENTRY + LASSERT((seq != NULL) && (dentry != NULL)); + sbi = ll_s2sbi(dentry->d_sb); +#else + LASSERT((seq != NULL) && (vfs != NULL)); + sbi = ll_s2sbi(vfs->mnt_sb); +#endif if (sbi->ll_flags & LL_SBI_NOLCK) seq_puts(seq, ",nolock"); @@ -2316,6 +2387,9 @@ int ll_show_options(struct seq_file *seq, struct vfsmount *vfs) if (sbi->ll_flags & LL_SBI_LAZYSTATFS) seq_puts(seq, ",lazystatfs"); + if (sbi->ll_flags & LL_SBI_USER_FID2PATH) + seq_puts(seq, ",user_fid2path"); + RETURN(0); } @@ -2338,9 +2412,88 @@ int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg) if (!obd) RETURN(-ENOENT); - if (cfs_copy_to_user((void *)arg, obd->obd_name, - strlen(obd->obd_name) + 1)) - RETURN(-EFAULT); + if (copy_to_user((void *)arg, obd->obd_name, + strlen(obd->obd_name) + 1)) + RETURN(-EFAULT); - RETURN(0); + RETURN(0); +} + +/** + * Get lustre file system name by \a sbi. If \a buf is provided(non-NULL), the + * fsname will be returned in this buffer; otherwise, a static buffer will be + * used to store the fsname and returned to caller. + */ +char *ll_get_fsname(struct super_block *sb, char *buf, int buflen) +{ + static char fsname_static[MTI_NAME_MAXLEN]; + struct lustre_sb_info *lsi = s2lsi(sb); + char *ptr; + int len; + + if (buf == NULL) { + /* this means the caller wants to use static buffer + * and it doesn't care about race. Usually this is + * in error reporting path */ + buf = fsname_static; + buflen = sizeof(fsname_static); + } + + len = strlen(lsi->lsi_lmd->lmd_profile); + ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-'); + if (ptr && (strcmp(ptr, "-client") == 0)) + len -= 7; + + if (unlikely(len >= buflen)) + len = buflen - 1; + strncpy(buf, lsi->lsi_lmd->lmd_profile, len); + buf[len] = '\0'; + + return buf; +} + +static char* ll_d_path(struct dentry *dentry, char *buf, int bufsize) +{ + char *path = NULL; + +#ifdef HAVE_FS_STRUCT_USE_PATH + struct path p; + + p.dentry = dentry; + p.mnt = current->fs->root.mnt; + path_get(&p); + path = d_path(&p, buf, bufsize); + path_put(&p); +#else + path = d_path(dentry, current->fs->rootmnt, buf, bufsize); +#endif + + return path; +} + +void ll_dirty_page_discard_warn(struct page *page, int ioret) +{ + char *buf, *path = NULL; + struct dentry *dentry = NULL; + struct ccc_object *obj = cl_inode2ccc(page->mapping->host); + + /* this can be called inside spin lock so use GFP_ATOMIC. */ + buf = (char *)__get_free_page(GFP_ATOMIC); + if (buf != NULL) { + dentry = d_find_alias(page->mapping->host); + if (dentry != NULL) + path = ll_d_path(dentry, buf, PAGE_SIZE); + } + + CWARN("%s: dirty page discard: %s/fid: "DFID"/%s may get corrupted " + "(rc %d)\n", ll_get_fsname(page->mapping->host->i_sb, NULL, 0), + s2lsi(page->mapping->host->i_sb)->lsi_lmd->lmd_dev, + PFID(&obj->cob_header.coh_lu.loh_fid), + (path && !IS_ERR(path)) ? path : "", ioret); + + if (dentry != NULL) + dput(dentry); + + if (buf != NULL) + free_page((unsigned long)buf); }