X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Ffile.c;h=85c3944d3061c94bc4ef57da4b2f5f2acf1002eb;hb=d821adb626e050206f1b4605f1159cf65ad22af5;hp=14e38cf7050c35306ea957d2579feb1ce9498d90;hpb=a7811634d45319dc3812fa652c727367fa290a24;p=fs%2Flustre-release.git diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 14e38cf..85c3944 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -27,7 +27,7 @@ * Copyright (c) 2002, 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/ @@ -55,7 +55,11 @@ struct ll_file_data *ll_file_data_get(void) struct ll_file_data *fd; OBD_SLAB_ALLOC_PTR_GFP(fd, ll_file_data_slab, CFS_ALLOC_IO); + if (fd == NULL) + return NULL; + fd->fd_write_failed = false; + return fd; } @@ -95,8 +99,9 @@ static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data, { ENTRY; - op_data->op_attr.ia_valid = ATTR_MODE | ATTR_ATIME_SET | - ATTR_MTIME_SET | ATTR_CTIME_SET; + op_data->op_attr.ia_valid = ATTR_MODE | ATTR_ATIME | ATTR_ATIME_SET | + ATTR_MTIME | ATTR_MTIME_SET | + ATTR_CTIME | ATTR_CTIME_SET; if (!(och->och_flags & FMODE_WRITE)) goto out; @@ -521,12 +526,12 @@ int ll_file_open(struct inode *inode, struct file *file) it = file->private_data; /* XXX: compat macro */ file->private_data = NULL; /* prevent ll_local_open assertion */ - fd = ll_file_data_get(); - if (fd == NULL) - GOTO(out_och_free, rc = -ENOMEM); + fd = ll_file_data_get(); + if (fd == NULL) + GOTO(out_openerr, rc = -ENOMEM); - fd->fd_file = file; - if (S_ISDIR(inode->i_mode)) { + fd->fd_file = file; + if (S_ISDIR(inode->i_mode)) { spin_lock(&lli->lli_sa_lock); if (lli->lli_opendir_key == NULL && lli->lli_sai == NULL && lli->lli_opendir_pid == 0) { @@ -535,7 +540,7 @@ int ll_file_open(struct inode *inode, struct file *file) opendir_set = 1; } spin_unlock(&lli->lli_sa_lock); - } + } if (inode->i_sb->s_root == file->f_dentry) { LUSTRE_FPRIVATE(file) = fd; @@ -926,8 +931,7 @@ out: CDEBUG(D_VFSTRACE, "Restart %s on %s from %lld, count:%zd\n", iot == CIT_READ ? "read" : "write", file->f_dentry->d_name.name, *ppos, count); - LASSERTF(io->u.ci_rw.crw_count == count, "%zd != %zd\n", - io->u.ci_rw.crw_count, count); + LASSERTF(io->ci_nob == 0, "%zd", io->ci_nob); goto restart; } @@ -1258,7 +1262,7 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos, } #endif -static int ll_lov_recreate(struct inode *inode, obd_id id, obd_seq seq, +static int ll_lov_recreate(struct inode *inode, struct ost_id *oi, obd_count ost_idx) { struct obd_export *exp = ll_i2dtexp(inode); @@ -1284,8 +1288,7 @@ static int ll_lov_recreate(struct inode *inode, obd_id id, obd_seq seq, if (lsm2 == NULL) GOTO(out, rc = -ENOMEM); - oa->o_id = id; - oa->o_seq = seq; + oa->o_oi = *oi; oa->o_nlink = ost_idx; oa->o_flags |= OBD_FL_RECREATE_OBJS; oa->o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS | OBD_MD_FLGROUP; @@ -1308,6 +1311,7 @@ out: static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg) { struct ll_recreate_obj ucreat; + struct ost_id oi; ENTRY; if (!cfs_capable(CFS_CAP_SYS_ADMIN)) @@ -1317,14 +1321,15 @@ static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg) sizeof(ucreat))) RETURN(-EFAULT); - RETURN(ll_lov_recreate(inode, ucreat.lrc_id, 0, - ucreat.lrc_ost_idx)); + ostid_set_seq_mdt0(&oi); + ostid_set_id(&oi, ucreat.lrc_id); + RETURN(ll_lov_recreate(inode, &oi, ucreat.lrc_ost_idx)); } static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg) { struct lu_fid fid; - obd_id id; + struct ost_id oi; obd_count ost_idx; ENTRY; @@ -1334,9 +1339,9 @@ static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg) if (copy_from_user(&fid, (struct lu_fid *)arg, sizeof(fid))) RETURN(-EFAULT); - id = fid_oid(&fid) | ((fid_seq(&fid) & 0xffff) << 32); + fid_to_ostid(&fid, &oi); ost_idx = (fid_seq(&fid) >> 16) & 0xffff; - RETURN(ll_lov_recreate(inode, id, 0, ost_idx)); + RETURN(ll_lov_recreate(inode, &oi, ost_idx)); } int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file, @@ -1869,7 +1874,7 @@ static int ll_swap_layouts(struct file *file1, struct file *file2, __u32 gid; __u64 dv; struct ll_swap_stack *llss = NULL; - int rc, rc1; + int rc; OBD_ALLOC_PTR(llss); if (llss == NULL) @@ -1991,12 +1996,22 @@ putgl: } /* update time if requested */ - rc = rc1 = 0; - if (llss->ia2.ia_valid != 0) + rc = 0; + if (llss->ia2.ia_valid != 0) { + mutex_lock(&llss->inode1->i_mutex); rc = ll_setattr(file1->f_dentry, &llss->ia2); + mutex_unlock(&llss->inode1->i_mutex); + } + + if (llss->ia1.ia_valid != 0) { + int rc1; - if (llss->ia1.ia_valid != 0) + mutex_lock(&llss->inode2->i_mutex); rc1 = ll_setattr(file2->f_dentry, &llss->ia1); + mutex_unlock(&llss->inode2->i_mutex); + if (rc == 0) + rc = rc1; + } free: if (llss != NULL) @@ -2364,7 +2379,7 @@ int ll_flush(struct file *file, fl_owner_t id) * Return how many pages have been written. */ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, - enum cl_fsync_mode mode) + enum cl_fsync_mode mode, int ignore_layout) { struct cl_env_nest nest; struct lu_env *env; @@ -2386,7 +2401,7 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, io = ccc_env_thread_io(env); io->ci_obj = cl_i2info(inode)->lli_clob; - io->ci_ignore_layout = 1; + io->ci_ignore_layout = ignore_layout; /* initialize parameters for sync */ fio = &io->u.ci_fsync; @@ -2418,15 +2433,15 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, */ #ifdef HAVE_FILE_FSYNC_4ARGS -int ll_fsync(struct file *file, loff_t start, loff_t end, int data) +int ll_fsync(struct file *file, loff_t start, loff_t end, int datasync) { struct dentry *dentry = file->f_dentry; #elif defined(HAVE_FILE_FSYNC_2ARGS) -int ll_fsync(struct file *file, int data) +int ll_fsync(struct file *file, int datasync) { struct dentry *dentry = file->f_dentry; #else -int ll_fsync(struct file *file, struct dentry *dentry, int data) +int ll_fsync(struct file *file, struct dentry *dentry, int datasync) { #endif struct inode *inode = dentry->d_inode; @@ -2470,11 +2485,11 @@ int ll_fsync(struct file *file, struct dentry *dentry, int data) if (!err) ptlrpc_req_finished(req); - if (data) { + if (datasync && S_ISREG(inode->i_mode)) { struct ll_file_data *fd = LUSTRE_FPRIVATE(file); err = cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, - CL_FSYNC_ALL); + CL_FSYNC_ALL, 0); if (rc == 0 && err < 0) rc = err; if (rc < 0) @@ -2652,11 +2667,11 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits, ldlm_mode_t l_req_mode) CDEBUG(D_INFO, "trying to match res "DFID" mode %s\n", PFID(fid), ldlm_lockname[mode]); - flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK; - for (i = 0; i < MDS_INODELOCK_MAXSHIFT && *bits != 0; i++) { - policy.l_inodebits.bits = *bits & (1 << i); - if (policy.l_inodebits.bits == 0) - continue; + flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK; + for (i = 0; i <= MDS_INODELOCK_MAXSHIFT && *bits != 0; i++) { + policy.l_inodebits.bits = *bits & (1 << i); + if (policy.l_inodebits.bits == 0) + continue; if (md_lock_match(ll_i2mdexp(inode), flags, fid, LDLM_IBITS, &policy, mode, &lockh)) { @@ -2768,7 +2783,7 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it, here to preserve get_cwd functionality on 2.6. Bug 10503 */ if (!dentry->d_inode->i_nlink) - d_lustre_invalidate(dentry); + d_lustre_invalidate(dentry, 0); ll_lookup_finish_locks(&oit, dentry); } else if (!ll_have_md_lock(dentry->d_inode, &ibits, LCK_MINMODE)) { @@ -3226,6 +3241,72 @@ int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf) RETURN(result); } +/* Fetch layout from MDT with getxattr request, if it's not ready yet */ +static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock) + +{ + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct obd_capa *oc; + struct ptlrpc_request *req; + struct mdt_body *body; + void *lvbdata; + void *lmm; + int lmmsize; + int rc; + ENTRY; + + if (lock->l_lvb_data != NULL) + RETURN(0); + + /* if layout lock was granted right away, the layout is returned + * within DLM_LVB of dlm reply; otherwise if the lock was ever + * blocked and then granted via completion ast, we have to fetch + * layout here. Please note that we can't use the LVB buffer in + * completion AST because it doesn't have a large enough buffer */ + oc = ll_mdscapa_get(inode); + rc = ll_get_max_mdsize(sbi, &lmmsize); + if (rc == 0) + rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, + OBD_MD_FLXATTR, XATTR_NAME_LOV, NULL, 0, + lmmsize, 0, &req); + capa_put(oc); + if (rc < 0) + RETURN(rc); + + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + if (body == NULL || body->eadatasize > lmmsize) + GOTO(out, rc = -EPROTO); + + lmmsize = body->eadatasize; + if (lmmsize == 0) /* empty layout */ + GOTO(out, rc = 0); + + lmm = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, lmmsize); + if (lmm == NULL) + GOTO(out, rc = -EFAULT); + + OBD_ALLOC_LARGE(lvbdata, lmmsize); + if (lvbdata == NULL) + GOTO(out, rc = -ENOMEM); + + memcpy(lvbdata, lmm, lmmsize); + lock_res_and_lock(lock); + if (lock->l_lvb_data == NULL) { + lock->l_lvb_data = lvbdata; + lock->l_lvb_len = lmmsize; + lvbdata = NULL; + } + unlock_res_and_lock(lock); + + if (lvbdata != NULL) + OBD_FREE_LARGE(lvbdata, lmmsize); + EXIT; + +out: + ptlrpc_req_finished(req); + return rc; +} + /** * Apply the layout to the inode. Layout lock is held and will be released * in this function. @@ -3240,6 +3321,7 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, struct cl_object_conf conf; int rc = 0; bool lvb_ready; + bool wait_layout = false; ENTRY; LASSERT(lustre_handle_is_used(lockh)); @@ -3251,14 +3333,15 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, LDLM_DEBUG(lock, "File %p/"DFID" being reconfigured: %d.\n", inode, PFID(&lli->lli_fid), reconf); + /* in case this is a caching lock and reinstate with new inode */ + md_set_lock_data(sbi->ll_md_exp, &lockh->cookie, inode, NULL); + lock_res_and_lock(lock); lvb_ready = !!(lock->l_flags & LDLM_FL_LVB_READY); unlock_res_and_lock(lock); /* checking lvb_ready is racy but this is okay. The worst case is * that multi processes may configure the file on the same time. */ if (lvb_ready || !reconf) { - LDLM_LOCK_PUT(lock); - rc = -ENODATA; if (lvb_ready) { /* layout_gen must be valid if layout lock is not @@ -3266,10 +3349,13 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, *gen = lli->lli_layout_gen; rc = 0; } - ldlm_lock_decref(lockh, mode); - RETURN(rc); + GOTO(out, rc); } + rc = ll_layout_fetch(inode, lock); + if (rc < 0) + GOTO(out, rc); + /* for layout lock, lmm is returned in lock's lvb. * lvb_data is immutable if the lock is held so it's safe to access it * without res lock. See the description in ldlm_lock_decref_internal() @@ -3288,11 +3374,8 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, PFID(&lli->lli_fid), rc); } } - if (rc < 0) { - LDLM_LOCK_PUT(lock); - ldlm_lock_decref(lockh, mode); - RETURN(rc); - } + if (rc < 0) + GOTO(out, rc); /* set layout to file. Unlikely this will fail as old layout was * surely eliminated */ @@ -3302,15 +3385,20 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, conf.coc_lock = lock; conf.u.coc_md = &md; rc = ll_layout_conf(inode, &conf); - LDLM_LOCK_PUT(lock); - - ldlm_lock_decref(lockh, mode); if (md.lsm != NULL) obd_free_memmd(sbi->ll_dt_exp, &md.lsm); + /* refresh layout failed, need to wait */ + wait_layout = rc == -EBUSY; + EXIT; + +out: + LDLM_LOCK_PUT(lock); + ldlm_lock_decref(lockh, mode); + /* wait for IO to complete if it's still being used. */ - if (rc == -EBUSY) { + if (wait_layout) { CDEBUG(D_INODE, "%s: %p/"DFID" wait for layout reconf.\n", ll_get_fsname(inode->i_sb, NULL, 0), inode, PFID(&lli->lli_fid)); @@ -3325,7 +3413,6 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, CDEBUG(D_INODE, "file: "DFID" waiting layout return: %d.\n", PFID(&lli->lli_fid), rc); } - RETURN(rc); } @@ -3358,7 +3445,7 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) int rc; ENTRY; - *gen = LL_LAYOUT_GEN_NONE; + *gen = lli->lli_layout_gen; if (!(sbi->ll_flags & LL_SBI_LAYOUT_LOCK)) RETURN(0); @@ -3417,8 +3504,6 @@ again: ll_finish_md_op_data(op_data); - md_set_lock_data(sbi->ll_md_exp, &it.d.lustre.it_lock_handle, inode, NULL); - mode = it.d.lustre.it_lock_mode; it.d.lustre.it_lock_mode = 0; ll_intent_drop_lock(&it);