X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Ffile.c;h=9ddbf22c0cd61eb575619649a138f787e964def5;hb=6bce536725efd166d2772f13fe954f271f9c53b8;hp=d9627af7ad58d0552a3c6bd32108be852f2f012f;hpb=e9a543b0d3039027423cb469525015f97caa3a3f;p=fs%2Flustre-release.git diff --git a/lustre/llite/file.c b/lustre/llite/file.c index d9627af..9ddbf22 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -42,9 +42,7 @@ #include #include #include -#ifdef HAVE_UIDGID_HEADER -# include -#endif +#include #include #include @@ -163,6 +161,7 @@ static int ll_close_inode_openhandle(struct inode *inode, op_data->op_attr_blocks += ((struct inode *)data)->i_blocks; op_data->op_attr.ia_valid |= ATTR_SIZE; op_data->op_xvalid |= OP_XVALID_BLOCKS; + /* fallthrough */ case MDS_CLOSE_LAYOUT_SPLIT: case MDS_CLOSE_LAYOUT_SWAP: { struct split_param *sp = data; @@ -353,7 +352,9 @@ static int ll_md_close(struct inode *inode, struct file *file) } mutex_unlock(&lli->lli_och_mutex); - if (!md_lock_match(ll_i2mdexp(inode), flags, ll_inode2fid(inode), + /* LU-4398: do not cache write open lock if the file has exec bit */ + if ((lockmode == LCK_CW && inode->i_mode & S_IXUGO) || + !md_lock_match(ll_i2mdexp(inode), flags, ll_inode2fid(inode), LDLM_IBITS, &policy, lockmode, &lockh)) rc = ll_md_real_close(inode, fd->fd_omode); @@ -371,19 +372,19 @@ out: */ int ll_file_release(struct inode *inode, struct file *file) { - struct ll_file_data *fd; - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ll_inode_info *lli = ll_i2info(inode); - int rc; - ENTRY; + struct ll_file_data *fd; + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ll_inode_info *lli = ll_i2info(inode); + ktime_t kstart = ktime_get(); + int rc; + + ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", PFID(ll_inode2fid(inode)), inode); - if (inode->i_sb->s_root != file_dentry(file)) - ll_stats_ops_tally(sbi, LPROC_LL_RELEASE, 1); - fd = LUSTRE_FPRIVATE(file); - LASSERT(fd != NULL); + fd = LUSTRE_FPRIVATE(file); + LASSERT(fd != NULL); /* The last ref on @file, maybe not the the owner pid of statahead, * because parent and child process can share the same file handle. */ @@ -393,7 +394,7 @@ int ll_file_release(struct inode *inode, struct file *file) if (inode->i_sb->s_root == file_dentry(file)) { LUSTRE_FPRIVATE(file) = NULL; ll_file_data_put(fd); - RETURN(0); + GOTO(out, rc = 0); } pcc_file_release(inode, file); @@ -409,6 +410,10 @@ int ll_file_release(struct inode *inode, struct file *file) if (CFS_FAIL_TIMEOUT_MS(OBD_FAIL_PTLRPC_DUMP_LOG, cfs_fail_val)) libcfs_debug_dumplog(); +out: + if (!rc && inode->i_sb->s_root != file_dentry(file)) + ll_stats_ops_tally(sbi, LPROC_LL_RELEASE, + ktime_us_delta(ktime_get(), kstart)); RETURN(rc); } @@ -448,8 +453,8 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req, if (obj == NULL) RETURN_EXIT; - if (!req_capsule_has_field(&req->rq_pill, &RMF_NIOBUF_INLINE, - RCL_SERVER)) + if (!req_capsule_field_present(&req->rq_pill, &RMF_NIOBUF_INLINE, + RCL_SERVER)) RETURN_EXIT; rnb = req_capsule_server_get(&req->rq_pill, &RMF_NIOBUF_INLINE); @@ -461,7 +466,7 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req, * client PAGE_SIZE to be used on that client, if server's PAGE_SIZE is * smaller then offset may be not aligned and that data is just ignored. */ - if (rnb->rnb_offset % PAGE_SIZE) + if (rnb->rnb_offset & ~PAGE_MASK) RETURN_EXIT; /* Server returns whole file or just file tail if it fills in reply @@ -481,9 +486,9 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req, data = (char *)rnb + sizeof(*rnb); lnb.lnb_file_offset = rnb->rnb_offset; - start = lnb.lnb_file_offset / PAGE_SIZE; + start = lnb.lnb_file_offset >> PAGE_SHIFT; index = 0; - LASSERT(lnb.lnb_file_offset % PAGE_SIZE == 0); + LASSERT((lnb.lnb_file_offset & ~PAGE_MASK) == 0); lnb.lnb_page_offset = 0; do { lnb.lnb_data = data + (index << PAGE_SHIFT); @@ -690,6 +695,7 @@ int ll_file_open(struct inode *inode, struct file *file) struct obd_client_handle **och_p = NULL; __u64 *och_usecount = NULL; struct ll_file_data *fd; + ktime_t kstart = ktime_get(); int rc = 0; ENTRY; @@ -779,7 +785,9 @@ restart: } else { LASSERT(*och_usecount == 0); if (!it->it_disposition) { - struct ll_dentry_data *ldd = ll_d2d(file->f_path.dentry); + struct dentry *dentry = file_dentry(file); + struct ll_dentry_data *ldd; + /* We cannot just request lock handle now, new ELC code means that one of other OPEN locks for this file could be cancelled, and since blocking ast handler @@ -801,18 +809,21 @@ restart: * lookup path only, since ll_iget_for_nfs always calls * ll_d_init(). */ + ldd = ll_d2d(dentry); if (ldd && ldd->lld_nfs_dentry) { ldd->lld_nfs_dentry = 0; - it->it_flags |= MDS_OPEN_LOCK; + if (!filename_is_volatile(dentry->d_name.name, + dentry->d_name.len, + NULL)) + it->it_flags |= MDS_OPEN_LOCK; } - /* + /* * Always specify MDS_OPEN_BY_FID because we don't want * to get file with different fid. */ it->it_flags |= MDS_OPEN_BY_FID; - rc = ll_intent_file_open(file_dentry(file), NULL, 0, - it); + rc = ll_intent_file_open(dentry, NULL, 0, it); if (rc) GOTO(out_openerr, rc); @@ -847,14 +858,17 @@ restart: GOTO(out_och_free, rc); mutex_unlock(&lli->lli_och_mutex); - fd = NULL; - /* Must do this outside lli_och_mutex lock to prevent deadlock where - different kind of OPEN lock for this same inode gets cancelled - by ldlm_cancel_lru */ - if (!S_ISREG(inode->i_mode)) - GOTO(out_och_free, rc); + /* lockless for direct IO so that it can do IO in parallel */ + if (file->f_flags & O_DIRECT) + fd->fd_flags |= LL_FILE_LOCKLESS_IO; + fd = NULL; + /* Must do this outside lli_och_mutex lock to prevent deadlock where + different kind of OPEN lock for this same inode gets cancelled + by ldlm_cancel_lru */ + if (!S_ISREG(inode->i_mode)) + GOTO(out_och_free, rc); cl_lov_delay_create_clear(&file->f_flags); GOTO(out_och_free, rc); @@ -873,9 +887,10 @@ out_openerr: if (fd != NULL) ll_file_data_put(fd); - } else { - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, 1); - } + } else { + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, + ktime_us_delta(ktime_get(), kstart)); + } out_nofiledata: if (it && it_disposition(it, DISP_ENQ_OPEN_REF)) { @@ -883,7 +898,7 @@ out_nofiledata: it_clear_disposition(it, DISP_ENQ_OPEN_REF); } - return rc; + return rc; } static int ll_md_blocking_lease_ast(struct ldlm_lock *lock, @@ -1063,7 +1078,9 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode, GOTO(out_release_it, rc); LASSERT(it_disposition(&it, DISP_ENQ_OPEN_REF)); - ll_och_fill(sbi->ll_md_exp, &it, och); + rc = ll_och_fill(sbi->ll_md_exp, &it, och); + if (rc) + GOTO(out_release_it, rc); if (!it_disposition(&it, DISP_OPEN_LEASE)) /* old server? */ GOTO(out_close, rc = -EOPNOTSUPP); @@ -1278,11 +1295,10 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode) * POSIX. Solving this problem needs to send an RPC to MDT for each * read, this will hurt performance. */ - if (inode->i_atime.tv_sec < lli->lli_atime || - lli->lli_update_atime) { + if (ll_file_test_and_clear_flag(lli, LLIF_UPDATE_ATIME) || + inode->i_atime.tv_sec < lli->lli_atime) inode->i_atime.tv_sec = lli->lli_atime; - lli->lli_update_atime = 0; - } + inode->i_mtime.tv_sec = lli->lli_mtime; inode->i_ctime.tv_sec = lli->lli_ctime; @@ -1372,13 +1388,14 @@ static bool file_is_noatime(const struct file *file) if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) return true; - if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)) + if ((inode->i_sb->s_flags & SB_NODIRATIME) && S_ISDIR(inode->i_mode)) return true; return false; } -void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot) +void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot, + struct vvp_io_args *args) { struct inode *inode = file_inode(file); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); @@ -1391,7 +1408,13 @@ void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot) io->u.ci_wr.wr_sync = !!(file->f_flags & O_SYNC || file->f_flags & O_DIRECT || IS_SYNC(inode)); +#ifdef HAVE_GENERIC_WRITE_SYNC_2ARGS + io->u.ci_wr.wr_sync |= !!(args && + args->via_io_subtype == IO_NORMAL && + args->u.normal.via_iocb->ki_flags & IOCB_DSYNC); +#endif } + io->ci_obj = ll_i2info(inode)->lli_clob; io->ci_lockreq = CILR_MAYBE; if (ll_file_nolock(file)) { @@ -1456,6 +1479,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, int rc = 0; unsigned retried = 0; bool restarted = false; + unsigned ignore_lockless = 0; ENTRY; @@ -1465,7 +1489,8 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, restart: io = vvp_env_thread_io(env); - ll_io_init(io, file, iot); + ll_io_init(io, file, iot, args); + io->ci_ignore_lockless = ignore_lockless; io->ci_ndelay_tried = retried; if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) { @@ -1538,7 +1563,8 @@ out: file->f_path.dentry->d_name.name, iot, rc, result, io->ci_need_restart); - if ((rc == 0 || rc == -ENODATA) && count > 0 && io->ci_need_restart) { + if ((rc == 0 || rc == -ENODATA || rc == -ENOLCK) && + count > 0 && io->ci_need_restart) { CDEBUG(D_VFSTRACE, "%s: restart %s from %lld, count: %zu, ret: %zd, rc: %d\n", file_dentry(file)->d_name.name, @@ -1546,6 +1572,7 @@ out: *ppos, count, result, rc); /* preserve the tried count for FLR */ retried = io->ci_ndelay_tried; + ignore_lockless = io->ci_ignore_lockless; restarted = true; goto restart; } @@ -1636,7 +1663,7 @@ ll_do_fast_read(struct kiocb *iocb, struct iov_iter *iter) if (result > 0) { ll_heat_add(file_inode(iocb->ki_filp), CIT_READ, result); ll_stats_ops_tally(ll_i2sbi(file_inode(iocb->ki_filp)), - LPROC_LL_READ_BYTES, result); + LPROC_LL_READ_BYTES, result); } return result; @@ -1649,9 +1676,11 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct lu_env *env; struct vvp_io_args *args; + struct file *file = iocb->ki_filp; ssize_t result; ssize_t rc2; __u16 refcheck; + ktime_t kstart = ktime_get(); bool cached; if (!iov_iter_count(to)) @@ -1670,9 +1699,9 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to) */ result = pcc_file_read_iter(iocb, to, &cached); if (cached) - return result; + GOTO(out, result); - ll_ras_enter(iocb->ki_filp); + ll_ras_enter(file, iocb->ki_pos, iov_iter_count(to)); result = ll_do_fast_read(iocb, to); if (result < 0 || iov_iter_count(to) == 0) @@ -1686,7 +1715,7 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to) args->u.normal.via_iter = to; args->u.normal.via_iocb = iocb; - rc2 = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ, + rc2 = ll_file_io_generic(env, args, file, CIT_READ, &iocb->ki_pos, iov_iter_count(to)); if (rc2 > 0) result += rc2; @@ -1695,6 +1724,14 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to) cl_env_put(env, &refcheck); out: + if (result > 0) { + ll_rw_stats_tally(ll_i2sbi(file_inode(file)), current->pid, + LUSTRE_FPRIVATE(file), iocb->ki_pos, result, + READ); + ll_stats_ops_tally(ll_i2sbi(file_inode(file)), LPROC_LL_READ, + ktime_us_delta(ktime_get(), kstart)); + } + return result; } @@ -1765,8 +1802,10 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from) struct vvp_io_args *args; struct lu_env *env; ssize_t rc_tiny = 0, rc_normal; + struct file *file = iocb->ki_filp; __u16 refcheck; bool cached; + ktime_t kstart = ktime_get(); int result; ENTRY; @@ -1786,15 +1825,15 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from) */ result = pcc_file_write_iter(iocb, from, &cached); if (cached && result != -ENOSPC && result != -EDQUOT) - return result; + GOTO(out, rc_normal = result); /* NB: we can't do direct IO for tiny writes because they use the page * cache, we can't do sync writes because tiny writes can't flush * pages, and we can't do append writes because we can't guarantee the * required DLM locks are held to protect file size. */ - if (ll_sbi_has_tiny_write(ll_i2sbi(file_inode(iocb->ki_filp))) && - !(iocb->ki_filp->f_flags & (O_DIRECT | O_SYNC | O_APPEND))) + if (ll_sbi_has_tiny_write(ll_i2sbi(file_inode(file))) && + !(file->f_flags & (O_DIRECT | O_SYNC | O_APPEND))) rc_tiny = ll_do_tiny_write(iocb, from); /* In case of error, go on and try normal write - Only stop if tiny @@ -1811,8 +1850,8 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from) args->u.normal.via_iter = from; args->u.normal.via_iocb = iocb; - rc_normal = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE, - &iocb->ki_pos, iov_iter_count(from)); + rc_normal = ll_file_io_generic(env, args, file, CIT_WRITE, + &iocb->ki_pos, iov_iter_count(from)); /* On success, combine bytes written. */ if (rc_tiny >= 0 && rc_normal > 0) @@ -1825,6 +1864,14 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from) cl_env_put(env, &refcheck); out: + if (rc_normal > 0) { + ll_rw_stats_tally(ll_i2sbi(file_inode(file)), current->pid, + LUSTRE_FPRIVATE(file), iocb->ki_pos, + rc_normal, WRITE); + ll_stats_ops_tally(ll_i2sbi(file_inode(file)), LPROC_LL_WRITE, + ktime_us_delta(ktime_get(), kstart)); + } + RETURN(rc_normal); } @@ -1990,7 +2037,7 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos, if (cached) RETURN(result); - ll_ras_enter(in_file); + ll_ras_enter(in_file, *ppos, count); env = cl_env_get(&refcheck); if (IS_ERR(env)) @@ -2002,6 +2049,11 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos, result = ll_file_io_generic(env, args, in_file, CIT_READ, ppos, count); cl_env_put(env, &refcheck); + + if (result > 0) + ll_rw_stats_tally(ll_i2sbi(file_inode(in_file)), current->pid, + LUSTRE_FPRIVATE(in_file), *ppos, result, + READ); RETURN(result); } @@ -2015,6 +2067,12 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, int rc; ENTRY; + if ((__swab32(lum->lmm_magic) & le32_to_cpu(LOV_MAGIC_MASK)) == + le32_to_cpu(LOV_MAGIC_MAGIC)) { + /* this code will only exist for big-endian systems */ + lustre_swab_lov_user_md(lum, 0); + } + ll_inode_size_lock(inode); rc = ll_intent_file_open(dentry, lum, lum_size, &oit); if (rc < 0) @@ -2078,13 +2136,14 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, lmm->lmm_magic != cpu_to_le32(LOV_MAGIC_FOREIGN)) GOTO(out, rc = -EPROTO); - /* - * This is coming from the MDS, so is probably in - * little endian. We convert it to host endian before - * passing it to userspace. - */ - if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) { - int stripe_count; + /* + * This is coming from the MDS, so is probably in + * little endian. We convert it to host endian before + * passing it to userspace. + */ + if ((lmm->lmm_magic & __swab32(LOV_MAGIC_MAGIC)) == + __swab32(LOV_MAGIC_MAGIC)) { + int stripe_count = 0; if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1) || lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) { @@ -2094,36 +2153,19 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, stripe_count = 0; } - /* if function called for directory - we should - * avoid swab not existent lsm objects */ - if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) { - lustre_swab_lov_user_md_v1( - (struct lov_user_md_v1 *)lmm); - if (S_ISREG(body->mbo_mode)) - lustre_swab_lov_user_md_objects( - ((struct lov_user_md_v1 *)lmm)->lmm_objects, - stripe_count); - } else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) { - lustre_swab_lov_user_md_v3( - (struct lov_user_md_v3 *)lmm); - if (S_ISREG(body->mbo_mode)) - lustre_swab_lov_user_md_objects( - ((struct lov_user_md_v3 *)lmm)->lmm_objects, - stripe_count); - } else if (lmm->lmm_magic == - cpu_to_le32(LOV_MAGIC_COMP_V1)) { - lustre_swab_lov_comp_md_v1( - (struct lov_comp_md_v1 *)lmm); - } else if (lmm->lmm_magic == - cpu_to_le32(LOV_MAGIC_FOREIGN)) { - struct lov_foreign_md *lfm; - - lfm = (struct lov_foreign_md *)lmm; - __swab32s(&lfm->lfm_magic); - __swab32s(&lfm->lfm_length); - __swab32s(&lfm->lfm_type); - __swab32s(&lfm->lfm_flags); - } + lustre_swab_lov_user_md((struct lov_user_md *)lmm, 0); + + /* if function called for directory - we should + * avoid swab not existent lsm objects */ + if (lmm->lmm_magic == LOV_MAGIC_V1 && S_ISREG(body->mbo_mode)) + lustre_swab_lov_user_md_objects( + ((struct lov_user_md_v1 *)lmm)->lmm_objects, + stripe_count); + else if (lmm->lmm_magic == LOV_MAGIC_V3 && + S_ISREG(body->mbo_mode)) + lustre_swab_lov_user_md_objects( + ((struct lov_user_md_v3 *)lmm)->lmm_objects, + stripe_count); } out: @@ -2210,10 +2252,11 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file, cl_lov_delay_create_clear(&file->f_flags); out: - OBD_FREE(klum, lum_size); + OBD_FREE_LARGE(klum, lum_size); RETURN(rc); } + static int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) { @@ -2229,18 +2272,28 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) RETURN(-EINVAL); } - if (ll_file_nolock(file)) - RETURN(-EOPNOTSUPP); + if (ll_file_nolock(file)) + RETURN(-EOPNOTSUPP); +retry: + if (file->f_flags & O_NONBLOCK) { + if (!mutex_trylock(&lli->lli_group_mutex)) + RETURN(-EAGAIN); + } else + mutex_lock(&lli->lli_group_mutex); - spin_lock(&lli->lli_lock); if (fd->fd_flags & LL_FILE_GROUP_LOCKED) { CWARN("group lock already existed with gid %lu\n", fd->fd_grouplock.lg_gid); - spin_unlock(&lli->lli_lock); - RETURN(-EINVAL); + GOTO(out, rc = -EINVAL); + } + if (arg != lli->lli_group_gid && lli->lli_group_users != 0) { + if (file->f_flags & O_NONBLOCK) + GOTO(out, rc = -EAGAIN); + mutex_unlock(&lli->lli_group_mutex); + wait_var_event(&lli->lli_group_users, !lli->lli_group_users); + GOTO(retry, rc = 0); } LASSERT(fd->fd_grouplock.lg_lock == NULL); - spin_unlock(&lli->lli_lock); /** * XXX: group lock needs to protect all OST objects while PFL @@ -2260,7 +2313,7 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) env = cl_env_get(&refcheck); if (IS_ERR(env)) - RETURN(PTR_ERR(env)); + GOTO(out, rc = PTR_ERR(env)); rc = cl_object_layout_get(env, obj, &cl); if (!rc && cl.cl_is_composite) @@ -2269,28 +2322,26 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) cl_env_put(env, &refcheck); if (rc) - RETURN(rc); + GOTO(out, rc); } rc = cl_get_grouplock(ll_i2info(inode)->lli_clob, arg, (file->f_flags & O_NONBLOCK), &grouplock); - if (rc) - RETURN(rc); - spin_lock(&lli->lli_lock); - if (fd->fd_flags & LL_FILE_GROUP_LOCKED) { - spin_unlock(&lli->lli_lock); - CERROR("another thread just won the race\n"); - cl_put_grouplock(&grouplock); - RETURN(-EINVAL); - } + if (rc) + GOTO(out, rc); fd->fd_flags |= LL_FILE_GROUP_LOCKED; fd->fd_grouplock = grouplock; - spin_unlock(&lli->lli_lock); + if (lli->lli_group_users == 0) + lli->lli_group_gid = grouplock.lg_gid; + lli->lli_group_users++; CDEBUG(D_INFO, "group lock %lu obtained\n", arg); - RETURN(0); +out: + mutex_unlock(&lli->lli_group_mutex); + + RETURN(rc); } static int ll_put_grouplock(struct inode *inode, struct file *file, @@ -2299,32 +2350,40 @@ static int ll_put_grouplock(struct inode *inode, struct file *file, struct ll_inode_info *lli = ll_i2info(inode); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); struct ll_grouplock grouplock; + int rc; ENTRY; - spin_lock(&lli->lli_lock); + mutex_lock(&lli->lli_group_mutex); if (!(fd->fd_flags & LL_FILE_GROUP_LOCKED)) { - spin_unlock(&lli->lli_lock); - CWARN("no group lock held\n"); - RETURN(-EINVAL); - } + CWARN("no group lock held\n"); + GOTO(out, rc = -EINVAL); + } LASSERT(fd->fd_grouplock.lg_lock != NULL); if (fd->fd_grouplock.lg_gid != arg) { CWARN("group lock %lu doesn't match current id %lu\n", arg, fd->fd_grouplock.lg_gid); - spin_unlock(&lli->lli_lock); - RETURN(-EINVAL); + GOTO(out, rc = -EINVAL); } grouplock = fd->fd_grouplock; memset(&fd->fd_grouplock, 0, sizeof(fd->fd_grouplock)); fd->fd_flags &= ~LL_FILE_GROUP_LOCKED; - spin_unlock(&lli->lli_lock); cl_put_grouplock(&grouplock); + + lli->lli_group_users--; + if (lli->lli_group_users == 0) { + lli->lli_group_gid = 0; + wake_up_var(&lli->lli_group_users); + } CDEBUG(D_INFO, "group lock %lu released\n", arg); - RETURN(0); + GOTO(out, rc = 0); +out: + mutex_unlock(&lli->lli_group_mutex); + + RETURN(rc); } /** @@ -2359,7 +2418,9 @@ int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it) if (!och) GOTO(out, rc = -ENOMEM); - ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och); + rc = ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och); + if (rc) + GOTO(out, rc); rc = ll_close_inode_openhandle(inode, och, 0, NULL); out: @@ -3005,6 +3066,7 @@ static int ll_ladvise_sanity(struct inode *inode, ladvise_names[advice], rc); GOTO(out, rc); } + /* fallthrough */ case LU_LADVISE_WILLREAD: case LU_LADVISE_DONTNEED: default: @@ -3991,6 +4053,7 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin) { struct inode *inode = file_inode(file); loff_t retval, eof = 0; + ktime_t kstart = ktime_get(); ENTRY; retval = offset + ((origin == SEEK_END) ? i_size_read(inode) : @@ -3998,7 +4061,6 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin) CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), to=%llu=%#llx(%d)\n", PFID(ll_inode2fid(inode)), inode, retval, retval, origin); - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LLSEEK, 1); if (origin == SEEK_END || origin == SEEK_HOLE || origin == SEEK_DATA) { retval = ll_glimpse_size(inode); @@ -4008,7 +4070,10 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin) } retval = ll_generic_file_llseek_size(file, offset, origin, - ll_file_maxbytes(inode), eof); + ll_file_maxbytes(inode), eof); + if (retval >= 0) + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LLSEEK, + ktime_us_delta(ktime_get(), kstart)); RETURN(retval); } @@ -4092,41 +4157,25 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, * file_dentry() as is done otherwise. */ -#ifdef HAVE_FILE_FSYNC_4ARGS int ll_fsync(struct file *file, loff_t start, loff_t end, int datasync) { struct dentry *dentry = file_dentry(file); -#elif defined(HAVE_FILE_FSYNC_2ARGS) -int ll_fsync(struct file *file, int datasync) -{ - struct dentry *dentry = file_dentry(file); - loff_t start = 0; - loff_t end = LLONG_MAX; -#else -int ll_fsync(struct file *file, struct dentry *dentry, int datasync) -{ - loff_t start = 0; - loff_t end = LLONG_MAX; -#endif struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); struct ptlrpc_request *req; + ktime_t kstart = ktime_get(); int rc, err; ENTRY; - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", - PFID(ll_inode2fid(inode)), inode); - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FSYNC, 1); + CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), start %lld, end %lld," + "datasync %d\n", + PFID(ll_inode2fid(inode)), inode, start, end, datasync); -#ifdef HAVE_FILE_FSYNC_4ARGS - rc = filemap_write_and_wait_range(inode->i_mapping, start, end); - inode_lock(inode); -#else /* fsync's caller has already called _fdata{sync,write}, we want * that IO to finish before calling the osc and mdc sync methods */ - rc = filemap_fdatawait(inode->i_mapping); -#endif + rc = filemap_write_and_wait_range(inode->i_mapping, start, end); + inode_lock(inode); /* catch async errors that were recorded back when async writeback * failed for pages in this mapping. */ @@ -4167,9 +4216,11 @@ int ll_fsync(struct file *file, struct dentry *dentry, int datasync) fd->fd_write_failed = false; } -#ifdef HAVE_FILE_FSYNC_4ARGS inode_unlock(inode); -#endif + + if (!rc) + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FSYNC, + ktime_us_delta(ktime_get(), kstart)); RETURN(rc); } @@ -4187,6 +4238,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) struct lustre_handle lockh = { 0 }; union ldlm_policy_data flock = { { 0 } }; int fl_type = file_lock->fl_type; + ktime_t kstart = ktime_get(); __u64 flags = 0; int rc; int rc2 = 0; @@ -4195,23 +4247,22 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID" file_lock=%p\n", PFID(ll_inode2fid(inode)), file_lock); - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FLOCK, 1); - - if (file_lock->fl_flags & FL_FLOCK) { - LASSERT((cmd == F_SETLKW) || (cmd == F_SETLK)); - /* flocks are whole-file locks */ - flock.l_flock.end = OFFSET_MAX; - /* For flocks owner is determined by the local file desctiptor*/ - flock.l_flock.owner = (unsigned long)file_lock->fl_file; - } else if (file_lock->fl_flags & FL_POSIX) { - flock.l_flock.owner = (unsigned long)file_lock->fl_owner; - flock.l_flock.start = file_lock->fl_start; - flock.l_flock.end = file_lock->fl_end; - } else { - RETURN(-EINVAL); - } - flock.l_flock.pid = file_lock->fl_pid; + if (file_lock->fl_flags & FL_FLOCK) { + LASSERT((cmd == F_SETLKW) || (cmd == F_SETLK)); + /* flocks are whole-file locks */ + flock.l_flock.end = OFFSET_MAX; + /* For flocks owner is determined by the local file desctiptor*/ + flock.l_flock.owner = (unsigned long)file_lock->fl_file; + } else if (file_lock->fl_flags & FL_POSIX) { + flock.l_flock.owner = (unsigned long)file_lock->fl_owner; + flock.l_flock.start = file_lock->fl_start; + flock.l_flock.end = file_lock->fl_end; + } else { + RETURN(-EINVAL); + } + flock.l_flock.pid = file_lock->fl_pid; +#if defined(HAVE_LM_COMPARE_OWNER) || defined(lm_compare_owner) /* Somewhat ugly workaround for svc lockd. * lockd installs custom fl_lmops->lm_compare_owner that checks * for the fl_owner to be the same (which it always is on local node @@ -4221,6 +4272,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) * pointer space for current->files are not intersecting */ if (file_lock->fl_lmops && file_lock->fl_lmops->lm_compare_owner) flock.l_flock.owner = (unsigned long)file_lock->fl_pid; +#endif switch (fl_type) { case F_RDLCK: @@ -4313,7 +4365,10 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) ll_finish_md_op_data(op_data); - RETURN(rc); + if (!rc) + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FLOCK, + ktime_us_delta(ktime_get(), kstart)); + RETURN(rc); } int ll_get_fid_by_name(struct inode *parent, const char *name, @@ -4503,9 +4558,20 @@ out_iput: static int ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock) { - ENTRY; + struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + ENTRY; - RETURN(-ENOSYS); + /* + * In order to avoid flood of warning messages, only print one message + * for one file. And the entire message rate on the client is limited + * by CDEBUG_LIMIT too. + */ + if (!(fd->fd_flags & LL_FILE_FLOCK_WARNING)) { + fd->fd_flags |= LL_FILE_FLOCK_WARNING; + CDEBUG_LIMIT(D_TTY | D_CONSOLE, + "flock disabled, mount with '-o [local]flock' to enable\r\n"); + } + RETURN(-ENOSYS); } /** @@ -4537,7 +4603,7 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits, enum ldlm_mode l_req_mode) 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++) { + for (i = 0; i < MDS_INODELOCK_NUMBITS && *bits != 0; i++) { policy.l_inodebits.bits = *bits & (1 << i); if (policy.l_inodebits.bits == 0) continue; @@ -4642,9 +4708,9 @@ static int ll_inode_revalidate(struct dentry *dentry, enum ldlm_intent_flags op) * here to preserve get_cwd functionality on 2.6. * Bug 10503 */ if (!dentry->d_inode->i_nlink) { - ll_lock_dcache(inode); + spin_lock(&inode->i_lock); d_lustre_invalidate(dentry, 0); - ll_unlock_dcache(inode); + spin_unlock(&inode->i_lock); } ll_lookup_finish_locks(&oit, dentry); @@ -4688,10 +4754,9 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat) struct inode *inode = de->d_inode; struct ll_sb_info *sbi = ll_i2sbi(inode); struct ll_inode_info *lli = ll_i2info(inode); + ktime_t kstart = ktime_get(); int rc; - ll_stats_ops_tally(sbi, LPROC_LL_GETATTR, 1); - rc = ll_inode_revalidate(de, IT_GETATTR); if (rc < 0) RETURN(rc); @@ -4752,7 +4817,10 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat) stat->size = i_size_read(inode); stat->blocks = inode->i_blocks; - return 0; + ll_stats_ops_tally(sbi, LPROC_LL_GETATTR, + ktime_us_delta(ktime_get(), kstart)); + + return 0; } #ifdef HAVE_INODEOPS_ENHANCED_GETATTR @@ -4820,7 +4888,7 @@ struct posix_acl *ll_get_acl(struct inode *inode, int type) } #ifdef HAVE_IOP_SET_ACL -#ifdef CONFIG_FS_POSIX_ACL +#ifdef CONFIG_LUSTRE_FS_POSIX_ACL int ll_set_acl(struct inode *inode, struct posix_acl *acl, int type) { struct ll_sb_info *sbi = ll_i2sbi(inode); @@ -4876,50 +4944,10 @@ out: set_cached_acl(inode, type, acl); RETURN(rc); } -#endif /* CONFIG_FS_POSIX_ACL */ +#endif /* CONFIG_LUSTRE_FS_POSIX_ACL */ #endif /* HAVE_IOP_SET_ACL */ -#ifndef HAVE_GENERIC_PERMISSION_2ARGS -static int -# ifdef HAVE_GENERIC_PERMISSION_4ARGS -ll_check_acl(struct inode *inode, int mask, unsigned int flags) -# else -ll_check_acl(struct inode *inode, int mask) -# endif -{ -# ifdef CONFIG_FS_POSIX_ACL - struct posix_acl *acl; - int rc; - ENTRY; - -# ifdef HAVE_GENERIC_PERMISSION_4ARGS - if (flags & IPERM_FLAG_RCU) - return -ECHILD; -# endif - acl = ll_get_acl(inode, ACL_TYPE_ACCESS); - - if (!acl) - RETURN(-EAGAIN); - - rc = posix_acl_permission(inode, acl, mask); - posix_acl_release(acl); - - RETURN(rc); -# else /* !CONFIG_FS_POSIX_ACL */ - return -EAGAIN; -# endif /* CONFIG_FS_POSIX_ACL */ -} -#endif /* HAVE_GENERIC_PERMISSION_2ARGS */ - -#ifdef HAVE_GENERIC_PERMISSION_4ARGS -int ll_inode_permission(struct inode *inode, int mask, unsigned int flags) -#else -# ifdef HAVE_INODE_PERMISION_2ARGS int ll_inode_permission(struct inode *inode, int mask) -# else -int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd) -# endif -#endif { int rc = 0; struct ll_sb_info *sbi; @@ -4928,15 +4956,11 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd) const struct cred *old_cred = NULL; cfs_cap_t cap; bool squash_id = false; + ktime_t kstart = ktime_get(); ENTRY; -#ifdef MAY_NOT_BLOCK if (mask & MAY_NOT_BLOCK) return -ECHILD; -#elif defined(HAVE_GENERIC_PERMISSION_4ARGS) - if (flags & IPERM_FLAG_RCU) - return -ECHILD; -#endif /* as root inode are NOT getting validated in lookup operation, * need to do it before permission check. */ @@ -4978,14 +5002,17 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd) old_cred = override_creds(cred); } - ll_stats_ops_tally(sbi, LPROC_LL_INODE_PERM, 1); - rc = ll_generic_permission(inode, mask, flags, ll_check_acl); + rc = generic_permission(inode, mask); /* restore current process's credentials and FS capability */ if (squash_id) { revert_creds(old_cred); put_cred(cred); } + if (!rc) + ll_stats_ops_tally(sbi, LPROC_LL_INODE_PERM, + ktime_us_delta(ktime_get(), kstart)); + RETURN(rc); }