X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fllite_lib.c;h=3798225bd3c47db480b44b9ec8bfc4f8d7940181;hb=6c5e48383bc10dc0a798b56c898e5a90293246b6;hp=27bc96351aab8ac3aa168a4c290d9d63b109fa31;hpb=d5390bbde9b525b13ab91f5610abe1c4bb98eff9;p=fs%2Flustre-release.git diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 27bc963..3798225 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, Intel Corporation. + * Copyright (c) 2011, 2013, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -56,7 +56,7 @@ #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); @@ -93,19 +93,18 @@ static struct ll_sb_info *ll_init_sbi(void) si_meminfo(&si); pages = si.totalram - si.totalhigh; - if (pages >> (20 - CFS_PAGE_SHIFT) < 512) { - lru_page_max = pages / 2; - } else { - lru_page_max = (pages / 4) * 3; - } + lru_page_max = pages / 2; - /* initialize lru data */ + /* initialize ll_cache 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); + cfs_atomic_set(&sbi->ll_cache.ccc_unstable_nr, 0); + init_waitqueue_head(&sbi->ll_cache.ccc_unstable_waitq); + 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; @@ -162,11 +161,6 @@ void ll_free_sbi(struct super_block *sb) 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) { @@ -200,13 +194,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, RETURN(-ENOMEM); } - if (proc_lustre_fs_root) { - err = lprocfs_register_mountpoint(proc_lustre_fs_root, sb, - dt, md); - if (err < 0) - CERROR("could not register mount in /proc/fs/lustre\n"); - } - /* indicate the features supported by this client */ data->ocd_connect_flags = OBD_CONNECT_IBITS | OBD_CONNECT_NODEVOH | OBD_CONNECT_ATTRFID | @@ -218,7 +205,10 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH| OBD_CONNECT_EINPROGRESS | OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | - OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS; + OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS | + OBD_CONNECT_MAX_EASIZE | + OBD_CONNECT_FLOCK_DEAD | + OBD_CONNECT_DISP_STRIPE; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; @@ -280,6 +270,14 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_md_exp->exp_connect_data = *data; + 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); + } + /* 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 */ @@ -287,7 +285,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), OBD_STATFS_FOR_MDT0); if (err) - GOTO(out_md, 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. @@ -301,16 +299,16 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, valid != CLIENT_CONNECT_MDT_REQD) { char *buf; - OBD_ALLOC_WAIT(buf, CFS_PAGE_SIZE); - obd_connect_flags2str(buf, CFS_PAGE_SIZE, + 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, CFS_PAGE_SIZE); - GOTO(out_md, err = -EPROTO); + OBD_FREE(buf, PAGE_CACHE_SIZE); + GOTO(out_md_fid, err = -EPROTO); } size = sizeof(*data); @@ -319,7 +317,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (err) { CERROR("%s: Get connect data failed: rc = %d\n", sbi->ll_md_exp->exp_obd->obd_name, err); - GOTO(out_md, err); + GOTO(out_md_fid, err); } LASSERT(osfs->os_bsize); @@ -379,17 +377,25 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, 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; + sbi->ll_md_brw_size = PAGE_CACHE_SIZE; - if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) { - LCONSOLE_INFO("Layout lock feature supported.\n"); + if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; + + 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, err = -ENODEV); + GOTO(out_md_fid, err = -ENODEV); } data->ocd_connect_flags = OBD_CONNECT_GRANT | OBD_CONNECT_VERSION | @@ -451,6 +457,14 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_dt_exp->exp_connect_data = *data; + 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); + } + 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; @@ -461,13 +475,13 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, err = md_getstatus(sbi->ll_md_exp, &sbi->ll_root_fid, &oc); if (err) { CERROR("cannot mds_connect: rc = %d\n", err); - GOTO(out_dt, 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_dt, err = -EINVAL); + GOTO(out_lock_cn_cb, err = -EINVAL); } CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid)); @@ -478,7 +492,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, /* make root inode * XXX: move this to after cbd setup? */ - valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMDSCAPA; + valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMDSCAPA | + OBD_MD_FLMODEASIZE; if (sbi->ll_flags & LL_SBI_RMT_CLIENT) valid |= OBD_MD_FLRMTPERM; else if (sbi->ll_flags & LL_SBI_ACL) @@ -486,7 +501,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_ALLOC_PTR(op_data); if (op_data == NULL) - GOTO(out_dt, err = -ENOMEM); + GOTO(out_lock_cn_cb, err = -ENOMEM); op_data->op_fid1 = sbi->ll_root_fid; op_data->op_mode = 0; @@ -500,7 +515,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (err) { CERROR("%s: md_getattr failed for root: rc = %d\n", sbi->ll_md_exp->exp_obd->obd_name, err); - GOTO(out_dt, err); + GOTO(out_lock_cn_cb, err); } err = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp, @@ -508,11 +523,13 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (err) { CERROR("failed to understand root inode md: rc = %d\n", err); ptlrpc_req_finished(request); - GOTO(out_dt, err); + 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); @@ -560,13 +577,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, 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; @@ -577,23 +589,36 @@ 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)); + if (uuid != NULL) + sb->s_dev = get_uuid2int(uuid->uuid, strlen(uuid->uuid)); if (data != NULL) OBD_FREE_PTR(data); if (osfs != NULL) OBD_FREE_PTR(osfs); + if (proc_lustre_fs_root != NULL) { + err = lprocfs_register_mountpoint(proc_lustre_fs_root, sb, + dt, md); + if (err < 0) { + CERROR("%s: could not register mount in lprocfs: " + "rc = %d\n", ll_get_fsname(sb, NULL, 0), err); + err = 0; + } + } RETURN(err); out_root: if (root) iput(root); +out_lock_cn_cb: + obd_fid_fini(sbi->ll_dt_exp->exp_obd); out_dt: obd_disconnect(sbi->ll_dt_exp); sbi->ll_dt_exp = NULL; /* 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->exp_obd); out_md: obd_disconnect(sbi->ll_md_exp); sbi->ll_md_exp = NULL; @@ -602,7 +627,6 @@ out: OBD_FREE_PTR(data); if (osfs != NULL) OBD_FREE_PTR(osfs); - lprocfs_unregister_mountpoint(sbi); return err; } @@ -630,8 +654,10 @@ void ll_dump_inode(struct inode *inode) 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, + 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); } @@ -649,7 +675,7 @@ void lustre_dump_dentry(struct dentry *dentry, int recur) " 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, d_refcount(dentry), + dentry->d_parent, dentry->d_inode, d_count(dentry), dentry->d_flags, dentry->d_fsdata, subdirs); if (dentry->d_inode != NULL) ll_dump_inode(dentry->d_inode); @@ -681,6 +707,7 @@ void client_common_put_super(struct super_block *sb) cfs_list_del(&sbi->ll_conn_chain); + 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. @@ -689,6 +716,7 @@ void client_common_put_super(struct super_block *sb) lprocfs_unregister_mountpoint(sbi); + obd_fid_fini(sbi->ll_md_exp->exp_obd); obd_disconnect(sbi->ll_md_exp); sbi->ll_md_exp = NULL; @@ -709,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) @@ -790,22 +820,22 @@ static int ll_options(char *options, int *flags) *flags &= ~tmp; goto next; } -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 5, 50, 0) - tmp = ll_set_opt("acl", s1, LL_SBI_ACL); - if (tmp) { - /* Ignore deprecated mount option. The client will - * always try to mount with ACL support, whether this - * is used depends on whether server supports it. */ - LCONSOLE_ERROR_MSG(0x152, "Ignoring deprecated " - "mount option 'acl'.\n"); - goto next; - } - tmp = ll_set_opt("noacl", s1, LL_SBI_ACL); - if (tmp) { - LCONSOLE_ERROR_MSG(0x152, "Ignoring deprecated " - "mount option 'noacl'.\n"); - goto next; - } +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 6, 51, 0) + tmp = ll_set_opt("acl", s1, LL_SBI_ACL); + if (tmp) { + /* Ignore deprecated mount option. The client will + * always try to mount with ACL support, whether this + * is used depends on whether server supports it. */ + LCONSOLE_ERROR_MSG(0x152, "Ignoring deprecated " + "mount option 'acl'.\n"); + goto next; + } + tmp = ll_set_opt("noacl", s1, LL_SBI_ACL); + if (tmp) { + LCONSOLE_ERROR_MSG(0x152, "Ignoring deprecated " + "mount option 'noacl'.\n"); + goto next; + } #else #warning "{no}acl options have been deprecated since 1.8, please remove them" #endif @@ -919,6 +949,9 @@ void ll_lli_init(struct ll_inode_info *lli) 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); @@ -945,17 +978,11 @@ void ll_lli_init(struct ll_inode_info *lli) 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) @@ -977,15 +1004,15 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) if (cfg == NULL) RETURN(-ENOMEM); - cfs_module_get(); + try_module_get(THIS_MODULE); - /* client additional sb info */ - lsi->lsi_llsbi = sbi = ll_init_sbi(); - if (!sbi) { - cfs_module_put(THIS_MODULE); - OBD_FREE_PTR(cfg); - RETURN(-ENOMEM); - } + /* client additional sb info */ + lsi->lsi_llsbi = sbi = ll_init_sbi(); + if (!sbi) { + module_put(THIS_MODULE); + OBD_FREE_PTR(cfg); + RETURN(-ENOMEM); + } err = ll_options(lsi->lsi_lmd->lmd_opts, &sbi->ll_flags); if (err) @@ -1000,8 +1027,10 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) 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 @@ -1012,10 +1041,8 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) cfg->cfg_callback = class_config_llog_handler; /* set up client obds */ err = lustre_process_log(sb, profilenm, cfg); - if (err < 0) { - CERROR("Unable to process log: %d\n", err); - GOTO(out_free, err); - } + 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); @@ -1060,12 +1087,12 @@ 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); char *profilenm = get_profile_name(sb); - int force = 1, next; + int ccc_count, next, force = 1, rc = 0; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm); @@ -1075,12 +1102,28 @@ 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) force = obd->obd_force; } + /* Wait for unstable pages to be committed to stable storage */ + if (force == 0) { + struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); + rc = l_wait_event(sbi->ll_cache.ccc_unstable_waitq, + cfs_atomic_read(&sbi->ll_cache.ccc_unstable_nr) == 0, + &lwi); + } + + ccc_count = cfs_atomic_read(&sbi->ll_cache.ccc_unstable_nr); + if (force == 0 && rc != -EINTR) + LASSERTF(ccc_count == 0, "count: %i\n", ccc_count); + + /* We need to set force before the lov_disconnect in lustre_common_put_super, since l_d cleans up osc's as well. */ if (force) { @@ -1115,11 +1158,13 @@ void ll_put_super(struct super_block *sb) ll_free_sbi(sb); lsi->lsi_llsbi = NULL; - lustre_common_put_super(sb); + lustre_common_put_super(sb); - cfs_module_put(THIS_MODULE); + cl_env_cache_purge(~0); - EXIT; + module_put(THIS_MODULE); + + EXIT; } /* client_put_super */ struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock) @@ -1175,8 +1220,8 @@ void ll_clear_inode(struct inode *inode) struct ll_sb_info *sbi = ll_i2sbi(inode); ENTRY; - CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, - inode->i_generation, inode); + CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", + PFID(ll_inode2fid(inode)), inode); if (S_ISDIR(inode->i_mode)) { /* these should have been cleared in ll_file_release */ @@ -1185,7 +1230,9 @@ 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; + spin_unlock(&lli->lli_lock); md_null_inode(sbi->ll_md_exp, ll_inode2fid(inode)); LASSERT(!lli->lli_open_fd_write_count); @@ -1205,6 +1252,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) { @@ -1279,16 +1328,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; @@ -1326,8 +1371,9 @@ static int ll_setattr_done_writing(struct inode *inode, * from OSTs and send setattr to back to MDS. */ rc = ll_som_update(inode, op_data); } else if (rc) { - CERROR("inode %lu mdc truncate failed: rc = %d\n", - inode->i_ino, rc); + CERROR("%s: inode "DFID" mdc truncate failed: rc = %d\n", + ll_i2sbi(inode)->ll_md_exp->exp_obd->obd_name, + PFID(ll_inode2fid(inode)), rc); } RETURN(rc); } @@ -1352,50 +1398,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. @@ -1408,24 +1410,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; - int rc = 0, rc1 = 0; - ENTRY; + bool file_is_released = false; + int rc = 0, rc1 = 0; + ENTRY; - CDEBUG(D_VFSTRACE, "%s: setattr inode %p/fid:"DFID" from %llu to %llu, " - "valid %x\n", ll_get_fsname(inode->i_sb, NULL, 0), inode, - PFID(&lli->lli_fid), i_size_read(inode), attr->ia_size, - attr->ia_valid); + CDEBUG(D_VFSTRACE, "%s: setattr inode "DFID"(%p) from %llu to %llu, " + "valid %x, hsm_import %d\n", + ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), + inode, 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) @@ -1444,23 +1448,25 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; } - /* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */ - if (ia_valid & TIMES_SET_FLAGS) { - if (cfs_curproc_fsuid() != inode->i_uid && - !cfs_capable(CFS_CAP_FOWNER)) - RETURN(-EPERM); - } + /* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */ + if (attr->ia_valid & TIMES_SET_FLAGS) { + if (current_fsuid() != inode->i_uid && + !cfs_capable(CFS_CAP_FOWNER)) + RETURN(-EPERM); + } /* We mark all of the fields "set" so MDS/OST does not re-set them */ if (attr->ia_valid & ATTR_CTIME) { attr->ia_ctime = CFS_CURRENT_TIME; 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; } @@ -1470,13 +1476,6 @@ 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) { - 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 */ @@ -1485,33 +1484,56 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) RETURN(-ENOMEM); if (!S_ISDIR(inode->i_mode)) { - if (ia_valid & ATTR_SIZE) + if (attr->ia_valid & ATTR_SIZE) inode_dio_write_done(inode); mutex_unlock(&inode->i_mutex); down_write(&lli->lli_trunc_sem); } - /* We need a steady stripe configuration for setattr to avoid - * confusion. */ - lsm = ccc_inode_lsm_get(inode); + /* truncate on a released file must failed with -ENODATA, + * so size must not be set on MDS for released file + * but other attributes must be set + */ + if (S_ISREG(inode->i_mode)) { + struct lov_stripe_md *lsm; + __u32 gen; - /* 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; - /* can't call ll_setattr_ost() while holding a refcount of lsm */ - ccc_inode_lsm_put(inode, lsm); + 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); - memcpy(&op_data->op_attr, attr, sizeof(*attr)); + if (!hsm_import && attr->ia_valid & ATTR_SIZE) { + if (file_is_released) { + rc = ll_layout_restore(inode, 0, attr->ia_size); + if (rc < 0) + GOTO(out, rc); - /* Open epoch for truncate. */ - if (exp_connect_som(ll_i2mdexp(inode)) && - (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) - op_data->op_flags = MF_EPOCH_OPEN; + file_is_released = false; + ll_layout_refresh(inode, &gen); + } - rc = ll_md_setattr(dentry, op_data, &mod); - if (rc) - GOTO(out, rc); + /* If we are changing file size, file content is + * modified, flag it. */ + attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; + spin_lock(&lli->lli_lock); + lli->lli_flags |= LLIF_DATA_MODIFIED; + spin_unlock(&lli->lli_lock); + op_data->op_bias |= MDS_DATA_MODIFIED; + } + } + + memcpy(&op_data->op_attr, attr, sizeof(*attr)); + + /* Open epoch for truncate. */ + if (exp_connect_som(ll_i2mdexp(inode)) && !hsm_import && + (attr->ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) + op_data->op_flags = MF_EPOCH_OPEN; + + rc = ll_md_setattr(dentry, op_data, &mod); + if (rc) + GOTO(out, rc); /* RPC to MDT is sent, cancel data modification flag */ if (rc == 0 && (op_data->op_bias & MDS_DATA_MODIFIED)) { @@ -1520,40 +1542,39 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) spin_unlock(&lli->lli_lock); } - ll_ioepoch_open(lli, op_data->op_ioepoch); - 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)) - /* 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 = ll_setattr_ost(inode, attr); - EXIT; + ll_ioepoch_open(lli, op_data->op_ioepoch); + if (!S_ISREG(inode->i_mode) || file_is_released) + GOTO(out, rc = 0); + + 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 + * 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 = ll_setattr_ost(inode, attr); + } + EXIT; out: - if (op_data) { - if (op_data->op_ioepoch) { - rc1 = ll_setattr_done_writing(inode, op_data, mod); - if (!rc) - rc = rc1; - } - ll_finish_md_op_data(op_data); - } + if (op_data) { + if (op_data->op_ioepoch) { + rc1 = ll_setattr_done_writing(inode, op_data, mod); + if (!rc) + rc = rc1; + } + ll_finish_md_op_data(op_data); + } if (!S_ISDIR(inode->i_mode)) { up_write(&lli->lli_trunc_sem); mutex_lock(&inode->i_mutex); - if (ia_valid & ATTR_SIZE) + if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) inode_dio_wait(inode); } - ll_stats_ops_tally(ll_i2sbi(inode), (ia_valid & ATTR_SIZE) ? + ll_stats_ops_tally(ll_i2sbi(inode), (attr->ia_valid & ATTR_SIZE) ? LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1); return rc; @@ -1561,30 +1582,30 @@ out: 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, @@ -1640,6 +1661,7 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs) { struct super_block *sb = de->d_sb; struct obd_statfs osfs; + __u64 fsid = huge_encode_dev(sb->s_dev); int rc; CDEBUG(D_VFSTRACE, "VFS Op: at "LPU64" jiffies\n", get_jiffies_64()); @@ -1671,8 +1693,9 @@ 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.val[0] = (__u32)fsid; + sfs->f_fsid.val[1] = (__u32)(fsid >> 32); + return 0; } void ll_inode_size_lock(struct inode *inode) @@ -1729,7 +1752,8 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) 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) { @@ -1777,9 +1801,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) if (fid_is_sane(&lli->lli_fid)) { LASSERTF(lu_fid_eq(&lli->lli_fid, &body->fid1), "Trying to change FID "DFID - " to the "DFID", inode %lu/%u(%p)\n", - PFID(&lli->lli_fid), PFID(&body->fid1), - inode->i_ino, inode->i_generation, inode); + " to the "DFID", inode "DFID"(%p)\n", + PFID(&lli->lli_fid), PFID(&body->fid1), + PFID(ll_inode2fid(inode)), inode); } else lli->lli_fid = body->fid1; } @@ -1788,7 +1812,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; @@ -1797,20 +1821,26 @@ 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, LDLM_FL_CBPENDING); + &lockh, LDLM_FL_CBPENDING, + LCK_CR | LCK_CW | + LCK_PR | LCK_PW); if (mode) { if (lli->lli_flags & (LLIF_DONE_WRITING | LLIF_EPOCH_PENDING | LLIF_SOM_DIRTY)) { - CERROR("ino %lu flags %u still has " - "size authority! do not trust " - "the size got from MDS\n", - inode->i_ino, lli->lli_flags); + CERROR("%s: inode "DFID" flags %u still" + " has size authority! do not " + "trust the size from MDS\n", + sbi->ll_md_exp->exp_obd->obd_name, + PFID(ll_inode2fid(inode)), + lli->lli_flags); } else { /* 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); } @@ -1819,8 +1849,10 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) * deadlock bz14138 & bz14326 */ i_size_write(inode, body->size); - CDEBUG(D_VFSTRACE, "inode=%lu, updating i_size %llu\n", - inode->i_ino, (unsigned long long)body->size); + CDEBUG(D_VFSTRACE, + "inode="DFID", updating i_size %llu\n", + PFID(ll_inode2fid(inode)), + (unsigned long long)body->size); } if (body->valid & OBD_MD_FLBLOCKS) @@ -1835,6 +1867,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) @@ -1895,18 +1932,19 @@ void ll_delete_inode(struct inode *inode) 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); /* Workaround for LU-118 */ if (inode->i_data.nrpages) { - TREE_READ_LOCK_IRQ(&inode->i_data); - TREE_READ_UNLOCK_IRQ(&inode->i_data); + spin_lock_irq(&inode->i_data.tree_lock); + spin_unlock_irq(&inode->i_data.tree_lock); LASSERTF(inode->i_data.nrpages == 0, - "inode=%lu/%u(%p) nrpages=%lu, see " - "http://jira.whamcloud.com/browse/LU-118\n", - inode->i_ino, inode->i_generation, inode, + "inode="DFID"(%p) nrpages=%lu, see " + "http://jira.whamcloud.com/browse/LU-118\n", + PFID(ll_inode2fid(inode)), inode, inode->i_data.nrpages); } /* Workaround end */ @@ -1942,7 +1980,9 @@ int ll_iocontrol(struct inode *inode, struct file *file, rc = md_getattr(sbi->ll_md_exp, op_data, &req); ll_finish_md_op_data(op_data); if (rc) { - CERROR("failure %d inode %lu\n", rc, inode->i_ino); + CERROR("%s: failure inode "DFID": rc = %d\n", + sbi->ll_md_exp->exp_obd->obd_name, + PFID(ll_inode2fid(inode)), rc); RETURN(-abs(rc)); } @@ -1979,8 +2019,10 @@ int ll_iocontrol(struct inode *inode, struct file *file, inode->i_flags = ll_ext_to_inode_flags(flags); lsm = ccc_inode_lsm_get(inode); - if (lsm == NULL) + if (!lsm_has_objects(lsm)) { + ccc_inode_lsm_put(inode, lsm); RETURN(0); + } OBDO_ALLOC(oinfo.oi_oa); if (!oinfo.oi_oa) { @@ -1988,8 +2030,7 @@ int ll_iocontrol(struct inode *inode, struct file *file, 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; @@ -2014,40 +2055,27 @@ int ll_iocontrol(struct inode *inode, struct file *file, int ll_flush_ctx(struct inode *inode) { - struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ll_sb_info *sbi = ll_i2sbi(inode); - CDEBUG(D_SEC, "flush context for user %d\n", cfs_curproc_uid()); + CDEBUG(D_SEC, "flush context for user %d\n", current_uid()); - obd_set_info_async(NULL, sbi->ll_md_exp, - sizeof(KEY_FLUSH_CTX), KEY_FLUSH_CTX, - 0, NULL, NULL); - obd_set_info_async(NULL, sbi->ll_dt_exp, - sizeof(KEY_FLUSH_CTX), KEY_FLUSH_CTX, - 0, NULL, NULL); - return 0; + obd_set_info_async(NULL, sbi->ll_md_exp, + sizeof(KEY_FLUSH_CTX), KEY_FLUSH_CTX, + 0, NULL, NULL); + obd_set_info_async(NULL, sbi->ll_dt_exp, + sizeof(KEY_FLUSH_CTX), KEY_FLUSH_CTX, + 0, NULL, NULL); + return 0; } /* 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)); @@ -2070,34 +2098,22 @@ 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_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 + OBD_FREE_PTR(ioc_data); + } - EXIT; + /* 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. + */ + schedule(); + EXIT; } int ll_remount_fs(struct super_block *sb, int *flags, char *data) @@ -2158,7 +2174,9 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, */ 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)) { #ifdef CONFIG_FS_POSIX_ACL if (md.posix_acl) { @@ -2300,24 +2318,34 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data, if (op_data == NULL) return ERR_PTR(-ENOMEM); - ll_i2gids(op_data->op_suppgids, i1, i2); - op_data->op_fid1 = *ll_inode2fid(i1); - op_data->op_capa1 = ll_mdscapa_get(i1); + ll_i2gids(op_data->op_suppgids, i1, i2); + op_data->op_fid1 = *ll_inode2fid(i1); + op_data->op_capa1 = ll_mdscapa_get(i1); + if (S_ISDIR(i1->i_mode)) + op_data->op_mea1 = ll_i2info(i1)->lli_lmv_md; + + if (i2) { + op_data->op_fid2 = *ll_inode2fid(i2); + op_data->op_capa2 = ll_mdscapa_get(i2); + if (S_ISDIR(i2->i_mode)) + op_data->op_mea2 = ll_i2info(i2)->lli_lmv_md; + } else { + fid_zero(&op_data->op_fid2); + op_data->op_capa2 = NULL; + } - if (i2) { - op_data->op_fid2 = *ll_inode2fid(i2); - op_data->op_capa2 = ll_mdscapa_get(i2); - } else { - fid_zero(&op_data->op_fid2); - op_data->op_capa2 = NULL; - } + if (ll_i2sbi(i1)->ll_flags & LL_SBI_64BIT_HASH) + op_data->op_cli_flags |= CLI_HASH64; + + if (ll_need_32bit_api(ll_i2sbi(i1))) + op_data->op_cli_flags |= CLI_API32; op_data->op_name = name; op_data->op_namelen = namelen; 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_fsuid = current_fsuid(); + op_data->op_fsgid = current_fsgid(); op_data->op_cap = cfs_curproc_cap_pack(); op_data->op_bias = 0; op_data->op_cli_flags = 0; @@ -2412,11 +2440,11 @@ 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); } /** @@ -2456,7 +2484,6 @@ 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; @@ -2464,14 +2491,10 @@ static char* ll_d_path(struct dentry *dentry, char *buf, int bufsize) 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(cfs_page_t *page, int ioret) +void ll_dirty_page_discard_warn(struct page *page, int ioret) { char *buf, *path = NULL; struct dentry *dentry = NULL;