-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
* GPL HEADER START
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* GPL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2011, 2012, Whamcloud, Inc.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
int result;
result = lu_kmem_init(ccc_caches);
- if (result == 0) {
- result = lu_device_type_init(device_type);
- ccc_inode_fini_env = cl_env_alloc(&dummy_refcheck,
- LCT_REMEMBER|LCT_NOREF);
- if (IS_ERR(ccc_inode_fini_env))
- result = PTR_ERR(ccc_inode_fini_env);
- else
- ccc_inode_fini_env->le_ctx.lc_cookie = 0x4;
+ if (result)
+ return result;
+
+ result = lu_device_type_init(device_type);
+ if (result)
+ goto out_kmem;
+
+ ccc_inode_fini_env = cl_env_alloc(&dummy_refcheck,
+ LCT_REMEMBER|LCT_NOREF);
+ if (IS_ERR(ccc_inode_fini_env)) {
+ result = PTR_ERR(ccc_inode_fini_env);
+ goto out_device;
}
+
+ ccc_inode_fini_env->le_ctx.lc_cookie = 0x4;
+ return 0;
+out_device:
+ lu_device_type_fini(device_type);
+out_kmem:
+ lu_kmem_fini(ccc_caches);
return result;
}
lvb->lvb_mtime = cl_inode_mtime(inode);
lvb->lvb_atime = cl_inode_atime(inode);
lvb->lvb_ctime = cl_inode_ctime(inode);
+ /*
+ * LU-417: Add dirty pages block count lest i_blocks reports 0, some
+ * "cp" or "tar" on remote node may think it's a completely sparse file
+ * and skip it.
+ */
+ if (lvb->lvb_size > 0 && lvb->lvb_blocks == 0)
+ lvb->lvb_blocks = dirty_cnt(inode);
RETURN(0);
}
if (lock->cll_descr.cld_start == 0 &&
lock->cll_descr.cld_end == CL_PAGE_EOF) {
cl_isize_write_nolock(inode, attr->cat_kms);
- CDEBUG(D_INODE, DFID" updating i_size "LPU64"\n",
+ CDEBUG(D_INODE|D_VFSTRACE,
+ DFID" updating i_size "LPU64"\n",
PFID(lu_object_fid(&obj->co_lu)),
(__u64)cl_isize_read(inode));
}
cl_inode_atime(inode) = attr->cat_atime;
cl_inode_ctime(inode) = attr->cat_ctime;
} else {
- CL_LOCK_DEBUG(D_INFO, env, lock, "attr_get: %i\n", rc);
+ CL_LOCK_DEBUG(D_INFO, env, lock, "attr_get: %d\n", rc);
}
cl_object_attr_unlock(obj);
cl_isize_unlock(inode, 0);
CLOBINVRNT(env, obj, ccc_object_invariant(obj));
ENTRY;
- CDEBUG(D_VFSTRACE, "lock: %i [%lu, %lu]\n", mode, start, end);
+ CDEBUG(D_VFSTRACE, "lock: %d [%lu, %lu]\n", mode, start, end);
memset(&cio->cui_link, 0, sizeof cio->cui_link);
}
}
-static void ccc_object_size_lock(struct cl_object *obj, int vfslock)
+static void ccc_object_size_lock(struct cl_object *obj)
{
struct inode *inode = ccc_object_inode(obj);
- if (vfslock)
- cl_isize_lock(inode, 0);
+ cl_isize_lock(inode, 0);
cl_object_attr_lock(obj);
}
-static void ccc_object_size_unlock(struct cl_object *obj, int vfslock)
+static void ccc_object_size_unlock(struct cl_object *obj)
{
struct inode *inode = ccc_object_inode(obj);
cl_object_attr_unlock(obj);
- if (vfslock)
- cl_isize_unlock(inode, 0);
+ cl_isize_unlock(inode, 0);
}
/**
* protect consistency between inode size and cl_object
* attributes. cl_object_size_lock() protects consistency between cl_attr's of
* top-object and sub-objects.
- *
- * In page fault path cl_isize_lock cannot be taken, client has to live with
- * the resulting races.
*/
int ccc_prep_size(const struct lu_env *env, struct cl_object *obj,
- struct cl_io *io, loff_t start, size_t count, int vfslock,
- int *exceed)
+ struct cl_io *io, loff_t start, size_t count, int *exceed)
{
struct cl_attr *attr = ccc_env_thread_attr(env);
struct inode *inode = ccc_object_inode(obj);
* ll_inode_size_lock(). This guarantees that short reads are handled
* correctly in the face of concurrent writes and truncates.
*/
- ccc_object_size_lock(obj, vfslock);
+ ccc_object_size_lock(obj);
result = cl_object_attr_get(env, obj, attr);
if (result == 0) {
kms = attr->cat_kms;
* return a short read (B) or some zeroes at the end
* of the buffer (C)
*/
- ccc_object_size_unlock(obj, vfslock);
- result = cl_glimpse_lock(env, io, inode, obj);
+ ccc_object_size_unlock(obj);
+ result = cl_glimpse_lock(env, io, inode, obj, 0);
if (result == 0 && exceed != NULL) {
/* If objective page index exceed end-of-file
* page index, return directly. Do not expect
* which will always be >= the kms value here.
* b=11081
*/
- /*
- * XXX in a page fault path, change inode size without
- * ll_inode_size_lock() held! there is a race
- * condition with truncate path. (see ll_extent_lock)
- */
- /*
- * XXX i_size_write() is not used because it is not
- * safe to take the ll_inode_size_lock() due to a
- * potential lock inversion (bug 6077). And since
- * it's not safe to use i_size_write() without a
- * covering mutex we do the assignment directly. It
- * is not critical that the size be correct.
- */
if (cl_isize_read(inode) < kms) {
- if (vfslock)
- cl_isize_write_nolock(inode, kms);
- else
- cl_isize_write(inode, kms);
+ cl_isize_write_nolock(inode, kms);
+ CDEBUG(D_VFSTRACE,
+ DFID" updating i_size "LPU64"\n",
+ PFID(lu_object_fid(&obj->co_lu)),
+ (__u64)cl_isize_read(inode));
+
}
}
}
- ccc_object_size_unlock(obj, vfslock);
+ ccc_object_size_unlock(obj);
return result;
}
{
struct ccc_req *vrq;
+ if (ioret > 0)
+ cl_stats_tally(slice->crs_dev, slice->crs_req->crq_type, ioret);
+
vrq = cl2ccc_req(slice);
OBD_SLAB_FREE_PTR(vrq, ccc_req_kmem);
}
OBD_MD_FLUID|OBD_MD_FLGID;
}
}
- obdo_from_inode(oa, inode, &cl_i2info(inode)->lli_fid,
- valid_flags & flags);
+ obdo_from_inode(oa, inode, valid_flags & flags);
+ obdo_set_parent_fid(oa, &cl_i2info(inode)->lli_fid);
+#ifdef __KERNEL__
+ memcpy(attr->cra_jobid, cl_i2info(inode)->lli_jobid,
+ JOBSTATS_JOBID_SIZE);
+#endif
}
const struct cl_req_operations ccc_req_ops = {
if (IS_ERR(env))
RETURN(PTR_ERR(env));
- io = &ccc_env_info(env)->cti_io;
+ io = ccc_env_thread_io(env);
io->ci_obj = cl_i2info(inode)->lli_clob;
io->u.ci_setattr.sa_attr.lvb_atime = LTIME_S(attr->ia_atime);
io->u.ci_setattr.sa_valid = attr->ia_valid;
io->u.ci_setattr.sa_capa = capa;
- if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0)
+ if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) {
+ struct ccc_io *cio = ccc_env_io(env);
+
+ if (attr->ia_valid & ATTR_FILE)
+ /* populate the file descriptor for ftruncate to honor
+ * group lock - see LU-787 */
+ cio->cui_fd = cl_iattr2fd(inode, attr);
+
result = cl_io_loop(env, io);
- else
+ } else {
result = io->ci_result;
+ }
cl_io_fini(env, io);
cl_env_put(env, &refcheck);
RETURN(result);
}
/**
- * Initializes or updates CLIO part when new meta-data arrives from the
- * server.
+ * Initialize or update CLIO structures for regular files when new
+ * meta-data arrives from the server.
*
- * - allocates cl_object if necessary,
- * - updated layout, if object was already here.
+ * \param inode regular file inode
+ * \param md new file metadata from MDS
+ * - allocates cl_object if necessary,
+ * - updated layout, if object was already here.
*/
-int cl_inode_init(struct inode *inode, struct lustre_md *md)
+int cl_file_inode_init(struct inode *inode, struct lustre_md *md)
{
struct lu_env *env;
struct cl_inode_info *lli;
struct cl_object *clob;
struct lu_site *site;
struct lu_fid *fid;
- const struct cl_object_conf conf = {
+ struct cl_object_conf conf = {
.coc_inode = inode,
.u = {
.coc_md = md
int result = 0;
int refcheck;
- /* LASSERT(inode->i_state & I_NEW); */
LASSERT(md->body->valid & OBD_MD_FLID);
-
- if (!S_ISREG(cl_inode_mode(inode)))
- return 0;
+ LASSERT(S_ISREG(cl_inode_mode(inode)));
env = cl_env_get(&refcheck);
if (IS_ERR(env))
LASSERT(fid_is_sane(fid));
if (lli->lli_clob == NULL) {
+ /* clob is slave of inode, empty lli_clob means for new inode,
+ * there is no clob in cache with the given fid, so it is
+ * unnecessary to perform lookup-alloc-lookup-insert, just
+ * alloc and insert directly. */
+#ifdef __KERNEL__
+ LASSERT(inode->i_state & I_NEW);
+#endif
+ conf.coc_lu.loc_flags = LOC_F_NEW;
clob = cl_object_find(env, lu2cl_dev(site->ls_top_dev),
fid, &conf);
if (!IS_ERR(clob)) {
static void cl_object_put_last(struct lu_env *env, struct cl_object *obj)
{
struct lu_object_header *header = obj->co_lu.lo_header;
- struct lu_site *site;
cfs_waitlink_t waiter;
if (unlikely(cfs_atomic_read(&header->loh_ref) != 1)) {
- site = obj->co_lu.lo_dev->ld_site;
+ struct lu_site *site = obj->co_lu.lo_dev->ld_site;
+ struct lu_site_bkt_data *bkt;
+
+ bkt = lu_site_bkt_from_fid(site, &header->loh_fid);
cfs_waitlink_init(&waiter);
- cfs_waitq_add(&site->ls_marche_funebre, &waiter);
+ cfs_waitq_add(&bkt->lsb_marche_funebre, &waiter);
while (1) {
cfs_set_current_state(CFS_TASK_UNINT);
}
cfs_set_current_state(CFS_TASK_RUNNING);
- cfs_waitq_del(&site->ls_marche_funebre, &waiter);
+ cfs_waitq_del(&bkt->lsb_marche_funebre, &waiter);
}
cl_object_put(env, obj);
}
/**
- * for 32 bit inode numbers directly map seq+oid to 32bit number.
- */
-__u32 cl_fid_build_ino32(const struct lu_fid *fid)
-{
- RETURN(fid_flatten32(fid));
-}
-
-/**
* build inode number from passed @fid */
-__u64 cl_fid_build_ino(const struct lu_fid *fid)
+__u64 cl_fid_build_ino(const struct lu_fid *fid, int api32)
{
-#if BITS_PER_LONG == 32
- RETURN(fid_flatten32(fid));
-#else
- RETURN(fid_flatten(fid));
-#endif
+ if (BITS_PER_LONG == 32 || api32)
+ RETURN(fid_flatten32(fid));
+ else
+ RETURN(fid_flatten(fid));
}
/**