X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Ffile.c;h=612312c804a9936f10cb5ae24451731caf40fc70;hp=adf68ef0d3d573ca7458c3eeac28d77714a86905;hb=a1307d41a3a6682f60c91df4b581f21fb2980265;hpb=d01834323af7a14d2d4959d9bea58073e3bb16ea diff --git a/lustre/llite/file.c b/lustre/llite/file.c index adf68ef..612312c 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -42,7 +42,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include -#include #include #include #include @@ -91,8 +90,7 @@ void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, op_data->op_attr.ia_ctime = inode->i_ctime; op_data->op_attr.ia_size = i_size_read(inode); op_data->op_attr_blocks = inode->i_blocks; - ((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags = - ll_inode_to_ext_flags(inode->i_flags); + op_data->op_attr_flags = ll_inode_to_ext_flags(inode->i_flags); op_data->op_ioepoch = ll_i2info(inode)->lli_ioepoch; if (fh) op_data->op_handle = *fh; @@ -383,12 +381,10 @@ int ll_file_release(struct inode *inode, struct file *file) fd = LUSTRE_FPRIVATE(file); LASSERT(fd != NULL); - /* The last ref on @file, maybe not the the owner pid of statahead. - * Different processes can open the same dir, "ll_opendir_key" means: - * it is me that should stop the statahead thread. */ - if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd && - lli->lli_opendir_pid != 0) - ll_stop_statahead(inode, lli->lli_opendir_key); + /* The last ref on @file, maybe not the the owner pid of statahead, + * because parent and child process can share the same file handle. */ + if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd) + ll_deauthorize_statahead(inode, fd); if (inode->i_sb->s_root == file->f_dentry) { LUSTRE_FPRIVATE(file) = NULL; @@ -555,36 +551,28 @@ static int ll_local_open(struct file *file, struct lookup_intent *it, */ int ll_file_open(struct inode *inode, struct file *file) { - struct ll_inode_info *lli = ll_i2info(inode); - struct lookup_intent *it, oit = { .it_op = IT_OPEN, - .it_flags = file->f_flags }; - struct obd_client_handle **och_p = NULL; - __u64 *och_usecount = NULL; - struct ll_file_data *fd; - int rc = 0, opendir_set = 0; - ENTRY; + struct ll_inode_info *lli = ll_i2info(inode); + struct lookup_intent *it, oit = { .it_op = IT_OPEN, + .it_flags = file->f_flags }; + struct obd_client_handle **och_p = NULL; + __u64 *och_usecount = NULL; + struct ll_file_data *fd; + int rc = 0; + ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), flags %o\n", PFID(ll_inode2fid(inode)), inode, file->f_flags); - it = file->private_data; /* XXX: compat macro */ - file->private_data = NULL; /* prevent ll_local_open assertion */ + 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_openerr, rc = -ENOMEM); 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) { - lli->lli_opendir_key = fd; - lli->lli_opendir_pid = current_pid(); - opendir_set = 1; - } - spin_unlock(&lli->lli_sa_lock); - } + if (S_ISDIR(inode->i_mode)) + ll_authorize_statahead(inode, fd); if (inode->i_sb->s_root == file->f_dentry) { LUSTRE_FPRIVATE(file) = fd; @@ -735,10 +723,10 @@ out_och_free: mutex_unlock(&lli->lli_och_mutex); out_openerr: - if (opendir_set != 0) - ll_stop_statahead(inode, lli->lli_opendir_key); - if (fd != NULL) - ll_file_data_put(fd); + if (lli->lli_opendir_key == fd) + ll_deauthorize_statahead(inode, fd); + if (fd != NULL) + ll_file_data_put(fd); } else { ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, 1); } @@ -1024,7 +1012,7 @@ int ll_inode_getattr(struct inode *inode, struct obdo *obdo, CDEBUG(D_INODE, "objid "DOSTID" size %llu, blocks %llu," " blksize %lu\n", POSTID(oi), i_size_read(inode), (unsigned long long)inode->i_blocks, - (unsigned long)ll_inode_blksize(inode)); + 1UL << inode->i_blkbits); } ccc_inode_lsm_put(inode, lsm); RETURN(rc); @@ -1046,7 +1034,12 @@ int ll_merge_lvb(const struct lu_env *env, struct inode *inode) LTIME_S(inode->i_atime) = lli->lli_lvb.lvb_atime; LTIME_S(inode->i_mtime) = lli->lli_lvb.lvb_mtime; LTIME_S(inode->i_ctime) = lli->lli_lvb.lvb_ctime; - inode_init_lvb(inode, &lvb); + + lvb.lvb_size = i_size_read(inode); + lvb.lvb_blocks = inode->i_blocks; + lvb.lvb_mtime = LTIME_S(inode->i_mtime); + lvb.lvb_atime = LTIME_S(inode->i_atime); + lvb.lvb_ctime = LTIME_S(inode->i_ctime); cl_object_attr_lock(obj); rc = cl_object_attr_get(env, obj, attr); @@ -1151,9 +1144,10 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, struct ll_file_data *fd = LUSTRE_FPRIVATE(file); struct cl_io *io; ssize_t result; + struct range_lock range; ENTRY; - CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: "LPU64", count: %zd\n", + CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: "LPU64", count: %zu\n", file->f_dentry->d_name.name, iot, *ppos, count); restart: @@ -1161,10 +1155,14 @@ restart: ll_io_init(io, file, iot == CIT_WRITE); if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) { - struct vvp_io *vio = vvp_env_io(env); - struct ccc_io *cio = ccc_env_io(env); - int write_mutex_locked = 0; + struct vvp_io *vio = vvp_env_io(env); + struct ccc_io *cio = ccc_env_io(env); + bool range_locked = false; + if (file->f_flags & O_APPEND) + range_lock_init(&range, 0, LUSTRE_EOF); + else + range_lock_init(&range, *ppos, *ppos + count - 1); cio->cui_fd = LUSTRE_FPRIVATE(file); vio->cui_io_subtype = args->via_io_subtype; @@ -1176,10 +1174,14 @@ restart: cio->cui_iocb = args->u.normal.via_iocb; if ((iot == CIT_WRITE) && !(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { - if (mutex_lock_interruptible(&lli-> - lli_write_mutex)) - GOTO(out, result = -ERESTARTSYS); - write_mutex_locked = 1; + CDEBUG(D_VFSTRACE, "Range lock "RL_FMT"\n", + RL_PARA(&range)); + result = range_lock(&lli->lli_write_tree, + &range); + if (result < 0) + GOTO(out, result); + + range_locked = true; } down_read(&lli->lli_trunc_sem); break; @@ -1198,8 +1200,11 @@ restart: if (args->via_io_subtype == IO_NORMAL) up_read(&lli->lli_trunc_sem); - if (write_mutex_locked) - mutex_unlock(&lli->lli_write_mutex); + if (range_locked) { + CDEBUG(D_VFSTRACE, "Range unlock "RL_FMT"\n", + RL_PARA(&range)); + range_unlock(&lli->lli_write_tree, &range); + } } else { /* cl_io_rw_init() handled IO */ result = io->ci_result; @@ -1215,7 +1220,7 @@ out: /* If any bit been read/written (result != 0), we just return * short read/write instead of restart io. */ if ((result == 0 || result == -ENODATA) && io->ci_need_restart) { - CDEBUG(D_VFSTRACE, "Restart %s on %s from %lld, count:%zd\n", + CDEBUG(D_VFSTRACE, "Restart %s on %s from %lld, count:%zu\n", iot == CIT_READ ? "read" : "write", file->f_dentry->d_name.name, *ppos, count); LASSERTF(io->ci_nob == 0, "%zd\n", io->ci_nob); @@ -1301,7 +1306,7 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov, RETURN(result); } -static ssize_t ll_file_read(struct file *file, char *buf, size_t count, +static ssize_t ll_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct lu_env *env; @@ -1367,8 +1372,8 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov, RETURN(result); } -static ssize_t ll_file_write(struct file *file, const char *buf, size_t count, - loff_t *ppos) +static ssize_t ll_file_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { struct lu_env *env; struct iovec *local_iov; @@ -1426,88 +1431,6 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos, RETURN(result); } -static int ll_lov_recreate(struct inode *inode, struct ost_id *oi, - obd_count ost_idx) -{ - struct obd_export *exp = ll_i2dtexp(inode); - struct obd_trans_info oti = { 0 }; - struct obdo *oa = NULL; - int lsm_size; - int rc = 0; - struct lov_stripe_md *lsm = NULL, *lsm2; - ENTRY; - - OBDO_ALLOC(oa); - if (oa == NULL) - RETURN(-ENOMEM); - - lsm = ccc_inode_lsm_get(inode); - if (!lsm_has_objects(lsm)) - GOTO(out, rc = -ENOENT); - - lsm_size = sizeof(*lsm) + (sizeof(struct lov_oinfo) * - (lsm->lsm_stripe_count)); - - OBD_ALLOC_LARGE(lsm2, lsm_size); - if (lsm2 == NULL) - GOTO(out, rc = -ENOMEM); - - 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; - obdo_from_inode(oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME | - OBD_MD_FLMTIME | OBD_MD_FLCTIME); - obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid); - memcpy(lsm2, lsm, lsm_size); - ll_inode_size_lock(inode); - rc = obd_create(NULL, exp, oa, &lsm2, &oti); - ll_inode_size_unlock(inode); - - OBD_FREE_LARGE(lsm2, lsm_size); - GOTO(out, rc); -out: - ccc_inode_lsm_put(inode, lsm); - OBDO_FREE(oa); - return rc; -} - -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)) - RETURN(-EPERM); - - if (copy_from_user(&ucreat, (struct ll_recreate_obj *)arg, - sizeof(ucreat))) - RETURN(-EFAULT); - - 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; - struct ost_id oi; - obd_count ost_idx; - ENTRY; - - if (!cfs_capable(CFS_CAP_SYS_ADMIN)) - RETURN(-EPERM); - - if (copy_from_user(&fid, (struct lu_fid *)arg, sizeof(fid))) - RETURN(-EFAULT); - - fid_to_ostid(&fid, &oi); - ost_idx = (fid_seq(&fid) >> 16) & 0xffff; - RETURN(ll_lov_recreate(inode, &oi, ost_idx)); -} - int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file, __u64 flags, struct lov_user_md *lum, int lum_size) @@ -1650,7 +1573,7 @@ static int ll_lov_setea(struct inode *inode, struct file *file, if (lump == NULL) RETURN(-ENOMEM); - if (copy_from_user(lump, (struct lov_user_md *)arg, lum_size)) { + if (copy_from_user(lump, (struct lov_user_md __user *)arg, lum_size)) { OBD_FREE_LARGE(lump, lum_size); RETURN(-EFAULT); } @@ -1664,38 +1587,32 @@ static int ll_lov_setea(struct inode *inode, struct file *file, static int ll_lov_setstripe(struct inode *inode, struct file *file, unsigned long arg) { - struct lov_user_md_v3 lumv3; - struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; - struct lov_user_md_v1 *lumv1p = (struct lov_user_md_v1 *)arg; - struct lov_user_md_v3 *lumv3p = (struct lov_user_md_v3 *)arg; - int lum_size, rc; - __u64 flags = FMODE_WRITE; + struct lov_user_md __user *lum = (struct lov_user_md __user *)arg; + struct lov_user_md *klum; + int lum_size, rc; + __u64 flags = FMODE_WRITE; ENTRY; - /* first try with v1 which is smaller than v3 */ - lum_size = sizeof(struct lov_user_md_v1); - if (copy_from_user(lumv1, lumv1p, lum_size)) - RETURN(-EFAULT); - - if (lumv1->lmm_magic == LOV_USER_MAGIC_V3) { - lum_size = sizeof(struct lov_user_md_v3); - if (copy_from_user(&lumv3, lumv3p, lum_size)) - RETURN(-EFAULT); - } + rc = ll_copy_user_md(lum, &klum); + if (rc < 0) + RETURN(rc); - rc = ll_lov_setstripe_ea_info(inode, file, flags, lumv1, lum_size); + lum_size = rc; + rc = ll_lov_setstripe_ea_info(inode, file, flags, klum, lum_size); if (rc == 0) { struct lov_stripe_md *lsm; __u32 gen; - put_user(0, &lumv1p->lmm_stripe_count); + put_user(0, &lum->lmm_stripe_count); ll_layout_refresh(inode, &gen); lsm = ccc_inode_lsm_get(inode); rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), - 0, lsm, (void *)arg); + 0, lsm, lum); ccc_inode_lsm_put(inode, lsm); } + + OBD_FREE(klum, lum_size); RETURN(rc); } @@ -1708,7 +1625,7 @@ static int ll_lov_getstripe(struct inode *inode, unsigned long arg) lsm = ccc_inode_lsm_get(inode); if (lsm != NULL) rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), 0, - lsm, (void *)arg); + lsm, (void __user *)arg); ccc_inode_lsm_put(inode, lsm); RETURN(rc); } @@ -1722,6 +1639,11 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) int rc; ENTRY; + if (arg == 0) { + CWARN("group id for group lock must not be 0\n"); + RETURN(-EINVAL); + } + if (ll_file_nolock(file)) RETURN(-EOPNOTSUPP); @@ -1949,6 +1871,10 @@ static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg) if (get_user(extent_count, &((struct ll_user_fiemap __user *)arg)->fm_extent_count)) RETURN(-EFAULT); + + if (extent_count >= + (SIZE_MAX - sizeof(*fiemap_s)) / sizeof(struct ll_fiemap_extent)) + RETURN(-EINVAL); num_bytes = sizeof(*fiemap_s) + (extent_count * sizeof(struct ll_fiemap_extent)); @@ -1981,7 +1907,7 @@ static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg) ret_bytes += (fiemap_s->fm_mapped_extents * sizeof(struct ll_fiemap_extent)); - if (copy_to_user((void *)arg, fiemap_s, ret_bytes)) + if (copy_to_user((void __user *)arg, fiemap_s, ret_bytes)) rc = -EFAULT; error: @@ -2352,14 +2278,14 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch(cmd) { case LL_IOC_GETFLAGS: /* Get the current value of the file flags */ - return put_user(fd->fd_flags, (int *)arg); + return put_user(fd->fd_flags, (int __user *)arg); case LL_IOC_SETFLAGS: case LL_IOC_CLRFLAGS: /* Set or clear specific file flags */ /* XXX This probably needs checks to ensure the flags are * not abused, and to handle any flag side effects. */ - if (get_user(flags, (int *) arg)) + if (get_user(flags, (int __user *) arg)) RETURN(-EFAULT); if (cmd == LL_IOC_SETFLAGS) { @@ -2383,7 +2309,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct file *file2; struct lustre_swap_layouts lsl; - if (copy_from_user(&lsl, (char *)arg, + if (copy_from_user(&lsl, (char __user *)arg, sizeof(struct lustre_swap_layouts))) RETURN(-EFAULT); @@ -2402,10 +2328,6 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } case LL_IOC_LOV_GETSTRIPE: RETURN(ll_lov_getstripe(inode, arg)); - case LL_IOC_RECREATE_OBJ: - RETURN(ll_lov_recreate_obj(inode, arg)); - case LL_IOC_RECREATE_FID: - RETURN(ll_lov_recreate_fid(inode, arg)); case FSFILT_IOC_FIEMAP: RETURN(ll_ioctl_fiemap(inode, arg)); case FSFILT_IOC_GETFLAGS: @@ -2413,13 +2335,13 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) RETURN(ll_iocontrol(inode, file, cmd, arg)); case FSFILT_IOC_GETVERSION_OLD: case FSFILT_IOC_GETVERSION: - RETURN(put_user(inode->i_generation, (int *)arg)); + RETURN(put_user(inode->i_generation, (int __user *)arg)); case LL_IOC_GROUP_LOCK: RETURN(ll_get_grouplock(inode, file, arg)); case LL_IOC_GROUP_UNLOCK: RETURN(ll_put_grouplock(inode, file, arg)); case IOC_OBD_STATFS: - RETURN(ll_obd_statfs(inode, (void *)arg)); + RETURN(ll_obd_statfs(inode, (void __user *)arg)); /* We need to special case any other ioctls we want to handle, * to send them to the MDS/OST as appropriate and to properly @@ -2430,25 +2352,29 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_FLUSHCTX: RETURN(ll_flush_ctx(inode)); case LL_IOC_PATH2FID: { - if (copy_to_user((void *)arg, ll_inode2fid(inode), + if (copy_to_user((void __user *)arg, ll_inode2fid(inode), sizeof(struct lu_fid))) RETURN(-EFAULT); RETURN(0); } + case LL_IOC_GETPARENT: + RETURN(ll_getparent(file, (void __user *)arg)); + case OBD_IOC_FID2PATH: - RETURN(ll_fid2path(inode, (void *)arg)); + RETURN(ll_fid2path(inode, (void __user *)arg)); case LL_IOC_DATA_VERSION: { struct ioc_data_version idv; int rc; - if (copy_from_user(&idv, (char *)arg, sizeof(idv))) + if (copy_from_user(&idv, (char __user *)arg, sizeof(idv))) RETURN(-EFAULT); idv.idv_flags &= LL_DV_RD_FLUSH | LL_DV_WR_FLUSH; rc = ll_data_version(inode, &idv.idv_version, idv.idv_flags); - if (rc == 0 && copy_to_user((char *) arg, &idv, sizeof(idv))) + if (rc == 0 && + copy_to_user((char __user *)arg, &idv, sizeof(idv))) RETURN(-EFAULT); RETURN(rc); @@ -2461,7 +2387,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (mdtidx < 0) RETURN(mdtidx); - if (put_user((int)mdtidx, (int*)arg)) + if (put_user((int)mdtidx, (int __user *)arg)) RETURN(-EFAULT); RETURN(0); @@ -2488,7 +2414,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), op_data, NULL); - if (copy_to_user((void *)arg, hus, sizeof(*hus))) + if (copy_to_user((void __user *)arg, hus, sizeof(*hus))) rc = -EFAULT; ll_finish_md_op_data(op_data); @@ -2503,7 +2429,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (hss == NULL) RETURN(-ENOMEM); - if (copy_from_user(hss, (char *)arg, sizeof(*hss))) { + if (copy_from_user(hss, (char __user *)arg, sizeof(*hss))) { OBD_FREE_PTR(hss); RETURN(-EFAULT); } @@ -2532,7 +2458,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), op_data, NULL); - if (copy_to_user((char *)arg, hca, sizeof(*hca))) + if (copy_to_user((char __user *)arg, hca, sizeof(*hca))) rc = -EFAULT; ll_finish_md_op_data(op_data); @@ -2631,7 +2557,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (hui == NULL) RETURN(-ENOMEM); - if (copy_from_user(hui, (void *)arg, sizeof(*hui))) { + if (copy_from_user(hui, (void __user *)arg, sizeof(*hui))) { OBD_FREE_PTR(hui); RETURN(-EFAULT); } @@ -2650,7 +2576,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) RETURN(err); RETURN(obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL, - (void *)arg)); + (void __user *)arg)); } } }