X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Ffile.c;h=b29a9c63502a3f0df7ffa4a4e6c9c79aa1bb3cbf;hp=8f7321deed56321e5332c13796437ab69e332874;hb=43620480d7b4ac578f5f9fd8465183b23e0d0dd1;hpb=003df3c38fe74a092f75569793edd6ec5a387d5c diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 8f7321d..b29a9c6 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -334,10 +334,11 @@ static int ll_md_close(struct obd_export *md_exp, struct inode *inode, rc = ll_md_real_close(file->f_dentry->d_inode, fd->fd_omode); } - } else { - CERROR("Releasing a file %p with negative dentry %p. Name %s", - file, file->f_dentry, file->f_dentry->d_name.name); - } + } else { + CERROR("released file has negative dentry: file = %p, " + "dentry = %p, name = %s\n", + file, file->f_dentry, file->f_dentry->d_name.name); + } out: LUSTRE_FPRIVATE(file) = NULL; @@ -409,80 +410,69 @@ int ll_file_release(struct inode *inode, struct file *file) RETURN(rc); } -static int ll_intent_file_open(struct file *file, void *lmm, - int lmmsize, struct lookup_intent *itp) +static int ll_intent_file_open(struct file *file, void *lmm, int lmmsize, + struct lookup_intent *itp) { - struct ll_sb_info *sbi = ll_i2sbi(file->f_dentry->d_inode); - struct dentry *parent = file->f_dentry->d_parent; - const char *name = file->f_dentry->d_name.name; - const int len = file->f_dentry->d_name.len; - struct md_op_data *op_data; + struct dentry *de = file->f_dentry; + struct ll_sb_info *sbi = ll_i2sbi(de->d_inode); + struct dentry *parent = de->d_parent; + const char *name = NULL; + int len = 0; + struct md_op_data *op_data; struct ptlrpc_request *req = NULL; - __u32 opc = LUSTRE_OPC_ANY; - int rc; - ENTRY; + int rc; + ENTRY; - if (!parent) - RETURN(-ENOENT); - - /* Usually we come here only for NFSD, and we want open lock. - But we can also get here with pre 2.6.15 patchless kernels, and in - that case that lock is also ok */ - /* We can also get here if there was cached open handle in revalidate_it - * but it disappeared while we were getting from there to ll_file_open. - * But this means this file was closed and immediatelly opened which - * makes a good candidate for using OPEN lock */ - /* If lmmsize & lmm are not 0, we are just setting stripe info - * parameters. No need for the open lock */ - if (lmm == NULL && lmmsize == 0) { - itp->it_flags |= MDS_OPEN_LOCK; - if (itp->it_flags & FMODE_WRITE) - opc = LUSTRE_OPC_CREATE; - } + LASSERT(parent != NULL); + LASSERT(itp->it_flags & MDS_OPEN_BY_FID); - op_data = ll_prep_md_op_data(NULL, parent->d_inode, - file->f_dentry->d_inode, name, len, - O_RDWR, opc, NULL); - if (IS_ERR(op_data)) - RETURN(PTR_ERR(op_data)); + /* if server supports open-by-fid, or file name is invalid, don't pack + * name in open request */ + if (!(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_OPEN_BY_FID) && + lu_name_is_valid_2(de->d_name.name, de->d_name.len)) { + name = de->d_name.name; + len = de->d_name.len; + } + op_data = ll_prep_md_op_data(NULL, parent->d_inode, de->d_inode, + name, len, 0, LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + RETURN(PTR_ERR(op_data)); op_data->op_data = lmm; op_data->op_data_size = lmmsize; - itp->it_flags |= MDS_OPEN_BY_FID; rc = md_intent_lock(sbi->ll_md_exp, op_data, itp, &req, &ll_md_blocking_ast, 0); - ll_finish_md_op_data(op_data); - if (rc == -ESTALE) { - /* reason for keep own exit path - don`t flood log - * with messages with -ESTALE errors. - */ - if (!it_disposition(itp, DISP_OPEN_OPEN) || - it_open_error(DISP_OPEN_OPEN, itp)) - GOTO(out, rc); - ll_release_openhandle(file->f_dentry, itp); - GOTO(out, rc); - } + ll_finish_md_op_data(op_data); + if (rc == -ESTALE) { + /* reason for keep own exit path - don`t flood log + * with messages with -ESTALE errors. + */ + if (!it_disposition(itp, DISP_OPEN_OPEN) || + it_open_error(DISP_OPEN_OPEN, itp)) + GOTO(out, rc); + ll_release_openhandle(de, itp); + GOTO(out, rc); + } - if (it_disposition(itp, DISP_LOOKUP_NEG)) - GOTO(out, rc = -ENOENT); + if (it_disposition(itp, DISP_LOOKUP_NEG)) + GOTO(out, rc = -ENOENT); - if (rc != 0 || it_open_error(DISP_OPEN_OPEN, itp)) { - rc = rc ? rc : it_open_error(DISP_OPEN_OPEN, itp); - CDEBUG(D_VFSTRACE, "lock enqueue: err: %d\n", rc); - GOTO(out, rc); - } + if (rc != 0 || it_open_error(DISP_OPEN_OPEN, itp)) { + rc = rc ? rc : it_open_error(DISP_OPEN_OPEN, itp); + CDEBUG(D_VFSTRACE, "lock enqueue: err: %d\n", rc); + GOTO(out, rc); + } - rc = ll_prep_inode(&file->f_dentry->d_inode, req, NULL, itp); - if (!rc && itp->d.lustre.it_lock_mode) - ll_set_lock_data(sbi->ll_md_exp, file->f_dentry->d_inode, - itp, NULL); + rc = ll_prep_inode(&de->d_inode, req, NULL, itp); + if (!rc && itp->d.lustre.it_lock_mode) + ll_set_lock_data(sbi->ll_md_exp, de->d_inode, itp, NULL); out: ptlrpc_req_finished(req); - ll_intent_drop_lock(itp); + ll_intent_drop_lock(itp); - RETURN(rc); + RETURN(rc); } /** @@ -543,6 +533,10 @@ static int ll_local_open(struct file *file, struct lookup_intent *it, ll_readahead_init(inode, &fd->fd_ras); fd->fd_omode = it->it_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); + /* ll_cl_context initialize */ + rwlock_init(&fd->fd_lock); + INIT_LIST_HEAD(&fd->fd_lccs); + RETURN(0); } @@ -669,9 +663,20 @@ restart: would attempt to grab och_mutex as well, that would result in a deadlock */ mutex_unlock(&lli->lli_och_mutex); - it->it_create_mode |= M_CHECK_STALE; + /* + * Normally called under two situations: + * 1. NFS export. + * 2. A race/condition on MDS resulting in no open + * handle to be returned from LOOKUP|OPEN request, + * for example if the target entry was a symlink. + * + * Always fetch MDS_OPEN_LOCK if this is not setstripe. + * + * Always specify MDS_OPEN_BY_FID because we don't want + * to get file with different fid. + */ + it->it_flags |= MDS_OPEN_LOCK | MDS_OPEN_BY_FID; rc = ll_intent_file_open(file, NULL, 0, it); - it->it_create_mode &= ~M_CHECK_STALE; if (rc) GOTO(out_openerr, rc); @@ -973,11 +978,11 @@ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, oinfo.oi_oa->o_flags |= OBD_FL_FLUSH; } - set = ptlrpc_prep_set(); - if (set == NULL) { - CERROR("can't allocate ptlrpc set\n"); - rc = -ENOMEM; - } else { + set = ptlrpc_prep_set(); + if (set == NULL) { + CERROR("cannot allocate ptlrpc set: rc = %d\n", -ENOMEM); + rc = -ENOMEM; + } else { rc = obd_getattr_async(exp, &oinfo, set); if (rc == 0) rc = ptlrpc_set_wait(set); @@ -1160,8 +1165,8 @@ restart: struct ccc_io *cio = ccc_env_io(env); int write_mutex_locked = 0; - cio->cui_fd = LUSTRE_FPRIVATE(file); - vio->cui_io_subtype = args->via_io_subtype; + cio->cui_fd = LUSTRE_FPRIVATE(file); + vio->cui_io_subtype = args->via_io_subtype; switch (vio->cui_io_subtype) { case IO_NORMAL: @@ -1186,7 +1191,11 @@ restart: CERROR("Unknow IO type - %u\n", vio->cui_io_subtype); LBUG(); } + + ll_cl_add(file, env, io); result = cl_io_loop(env, io); + ll_cl_remove(file, env); + if (args->via_io_subtype == IO_NORMAL) up_read(&lli->lli_trunc_sem); if (write_mutex_locked) @@ -1209,7 +1218,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->ci_nob == 0, "%zd", io->ci_nob); + LASSERTF(io->ci_nob == 0, "%zd\n", io->ci_nob); goto restart; } @@ -1517,6 +1526,7 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file, } ll_inode_size_lock(inode); + oit.it_flags |= MDS_OPEN_BY_FID; rc = ll_intent_file_open(file, lum, lum_size, &oit); if (rc) GOTO(out_unlock, rc); @@ -1884,38 +1894,39 @@ out: RETURN(rc); } -int ll_fid2path(struct inode *inode, void *arg) +int ll_fid2path(struct inode *inode, void __user *arg) { struct obd_export *exp = ll_i2mdexp(inode); - struct getinfo_fid2path *gfout, *gfin; - int outsize, rc; + const struct getinfo_fid2path __user *gfin = arg; + __u32 pathlen; + struct getinfo_fid2path *gfout; + size_t outsize; + int rc; + ENTRY; if (!cfs_capable(CFS_CAP_DAC_READ_SEARCH) && !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH)) RETURN(-EPERM); - /* Need to get the buflen */ - OBD_ALLOC_PTR(gfin); - if (gfin == NULL) - RETURN(-ENOMEM); - if (copy_from_user(gfin, arg, sizeof(*gfin))) { - OBD_FREE_PTR(gfin); + /* Only need to get the buflen */ + if (get_user(pathlen, &gfin->gf_pathlen)) RETURN(-EFAULT); - } - outsize = sizeof(*gfout) + gfin->gf_pathlen; + if (pathlen > PATH_MAX) + RETURN(-EINVAL); + + outsize = sizeof(*gfout) + pathlen; OBD_ALLOC(gfout, outsize); - if (gfout == NULL) { - OBD_FREE_PTR(gfin); + if (gfout == NULL) RETURN(-ENOMEM); - } - memcpy(gfout, gfin, sizeof(*gfout)); - OBD_FREE_PTR(gfin); + + if (copy_from_user(gfout, arg, sizeof(*gfout))) + GOTO(gf_free, rc = -EFAULT); /* Call mdc_iocontrol */ rc = obd_iocontrol(OBD_IOC_FID2PATH, exp, outsize, gfout, NULL); - if (rc) + if (rc != 0) GOTO(gf_free, rc); if (copy_to_user(arg, gfout, outsize)) @@ -1938,6 +1949,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)); @@ -2298,10 +2313,14 @@ static int ll_hsm_import(struct inode *inode, struct file *file, ATTR_MTIME | ATTR_MTIME_SET | ATTR_ATIME | ATTR_ATIME_SET; + mutex_lock(&inode->i_mutex); + rc = ll_setattr_raw(file->f_dentry, attr, true); if (rc == -ENODATA) rc = 0; + mutex_unlock(&inode->i_mutex); + out: if (hss != NULL) OBD_FREE_PTR(hss); @@ -2312,6 +2331,12 @@ out: RETURN(rc); } +static inline long ll_lease_type_from_fmode(fmode_t fmode) +{ + return ((fmode & FMODE_READ) ? LL_LEASE_RDLCK : 0) | + ((fmode & FMODE_WRITE) ? LL_LEASE_WRLCK : 0); +} + static long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -2522,20 +2547,20 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct ll_inode_info *lli = ll_i2info(inode); struct obd_client_handle *och = NULL; bool lease_broken; - fmode_t mode = 0; + fmode_t fmode; switch (arg) { - case F_WRLCK: + case LL_LEASE_WRLCK: if (!(file->f_mode & FMODE_WRITE)) RETURN(-EPERM); - mode = FMODE_WRITE; + fmode = FMODE_WRITE; break; - case F_RDLCK: + case LL_LEASE_RDLCK: if (!(file->f_mode & FMODE_READ)) RETURN(-EPERM); - mode = FMODE_READ; + fmode = FMODE_READ; break; - case F_UNLCK: + case LL_LEASE_UNLCK: mutex_lock(&lli->lli_och_mutex); if (fd->fd_lease_och != NULL) { och = fd->fd_lease_och; @@ -2543,25 +2568,26 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } mutex_unlock(&lli->lli_och_mutex); - if (och != NULL) { - mode = och->och_flags &(FMODE_READ|FMODE_WRITE); - rc = ll_lease_close(och, inode, &lease_broken); - if (rc == 0 && lease_broken) - mode = 0; - } else { - rc = -ENOLCK; - } + if (och == NULL) + RETURN(-ENOLCK); + + fmode = och->och_flags; + rc = ll_lease_close(och, inode, &lease_broken); + if (rc < 0) + RETURN(rc); + + if (lease_broken) + fmode = 0; - /* return the type of lease or error */ - RETURN(rc < 0 ? rc : (int)mode); + RETURN(ll_lease_type_from_fmode(fmode)); default: RETURN(-EINVAL); } - CDEBUG(D_INODE, "Set lease with mode %d\n", mode); + CDEBUG(D_INODE, "Set lease with mode %u\n", fmode); /* apply for lease */ - och = ll_lease_open(inode, file, mode, 0); + och = ll_lease_open(inode, file, fmode, 0); if (IS_ERR(och)) RETURN(PTR_ERR(och)); @@ -2582,8 +2608,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_GET_LEASE: { struct ll_inode_info *lli = ll_i2info(inode); struct ldlm_lock *lock = NULL; + fmode_t fmode = 0; - rc = 0; mutex_lock(&lli->lli_och_mutex); if (fd->fd_lease_och != NULL) { struct obd_client_handle *och = fd->fd_lease_och; @@ -2592,14 +2618,15 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (lock != NULL) { lock_res_and_lock(lock); if (!ldlm_is_cancel(lock)) - rc = och->och_flags & - (FMODE_READ | FMODE_WRITE); + fmode = och->och_flags; + unlock_res_and_lock(lock); LDLM_LOCK_PUT(lock); } } mutex_unlock(&lli->lli_och_mutex); - RETURN(rc); + + RETURN(ll_lease_type_from_fmode(fmode)); } case LL_IOC_HSM_IMPORT: { struct hsm_user_import *hui; @@ -3257,11 +3284,9 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits) if (IS_ERR(op_data)) RETURN(PTR_ERR(op_data)); - oit.it_create_mode |= M_CHECK_STALE; rc = md_intent_lock(exp, op_data, &oit, &req, &ll_md_blocking_ast, 0); ll_finish_md_op_data(op_data); - oit.it_create_mode &= ~M_CHECK_STALE; if (rc < 0) { rc = ll_inode_revalidate_fini(inode, rc); GOTO (out, rc); @@ -3887,7 +3912,7 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, LASSERT(lock != NULL); LASSERT(ldlm_has_layout(lock)); - LDLM_DEBUG(lock, "file "DFID"(%p) being reconfigured: %d\n", + LDLM_DEBUG(lock, "file "DFID"(%p) being reconfigured: %d", PFID(&lli->lli_fid), inode, reconf); /* in case this is a caching lock and reinstate with new inode */ @@ -4042,7 +4067,7 @@ again: it.it_op = IT_LAYOUT; lockh.cookie = 0ULL; - LDLM_DEBUG_NOLOCK("%s: requeue layout lock for file "DFID"(%p)\n", + LDLM_DEBUG_NOLOCK("%s: requeue layout lock for file "DFID"(%p)", ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), inode);