]) # LC_VM_FAULT_RETRY
#
+# LC_ALLOC_FILE_PSEUDO
+#
+# kernel 4.18-rc1 commit d93aa9d82aea80b80f225dbf9c7986df444d8106
+# new wrapper: alloc_file_pseudo()
+#
+AC_DEFUN([LC_ALLOC_FILE_PSEUDO], [
+LB_CHECK_COMPILE([if 'alloc_file_pseudo' is defined],
+alloc_file_pseudo, [
+ #include <linux/file.h>
+],[
+ struct file *file;
+ file = alloc_file_pseudo(NULL, NULL, "[test]",
+ 00000002, NULL);
+],[
+ AC_DEFINE(HAVE_ALLOC_FILE_PSEUDO, 1,
+ ['alloc_file_pseudo' exist])
+])
+]) # LC_ALLOC_FILE_PSEUDO
+
+#
# LC_INODE_TIMESPEC64
#
# kernel 4.17-rc7 commit 8efd6894ff089adeeac7cb9f32125b85d963d1bc
LC_I_PAGES
# 4.18
+ LC_ALLOC_FILE_PSEUDO
LC_INODE_TIMESPEC64
# 4.20
#define DEBUG_SUBSYSTEM S_OSD
#include <linux/fs_struct.h>
-#include <linux/kallsyms.h>
#include <linux/module.h>
#include <linux/user_namespace.h>
#include <linux/uidgid.h>
struct inode *inode)
{
struct lu_buf *buf = &oti->oti_big_buf;
- struct dentry *dentry = &oti->oti_obj_dentry;
struct file *filp;
struct lmv_mds_md_v1 *lmv1;
struct osd_check_lmv_buf oclb = {
int rc = 0;
ENTRY;
+ /* We should use the VFS layer to create a real dentry. */
+ oti->oti_obj_dentry.d_inode = inode;
+ oti->oti_obj_dentry.d_sb = inode->i_sb;
+
+ filp = alloc_file_pseudo(inode, dev->od_mnt, "/", O_NOATIME,
+ inode->i_fop);
+ if (IS_ERR(filp))
+ RETURN(-ENOMEM);
+ filp->f_mode |= FMODE_64BITHASH;
+ filp->f_pos = 0;
+ ihold(inode);
again:
- rc = __osd_xattr_get(inode, dentry, XATTR_NAME_LMV, buf->lb_buf,
- buf->lb_len);
+ rc = __osd_xattr_get(inode, filp->f_path.dentry, XATTR_NAME_LMV,
+ buf->lb_buf, buf->lb_len);
if (rc == -ERANGE) {
- rc = __osd_xattr_get(inode, dentry, XATTR_NAME_LMV, NULL, 0);
+ rc = __osd_xattr_get(inode, filp->f_path.dentry,
+ XATTR_NAME_LMV, NULL, 0);
if (rc > 0) {
lu_buf_realloc(buf, rc);
if (buf->lb_buf == NULL)
if (le32_to_cpu(lmv1->lmv_magic) != LMV_MAGIC_V1)
GOTO(out, rc = 0);
- filp = osd_quasi_file(oti->oti_env, inode);
- rc = osd_security_file_alloc(filp);
- if (rc)
- goto out;
-
do {
oclb.oclb_items = 0;
rc = iterate_dir(filp, &oclb.ctx);
} while (rc >= 0 && oclb.oclb_items > 0 && !oclb.oclb_found &&
filp->f_pos != LDISKFS_HTREE_EOF_64BIT);
- inode->i_fop->release(inode, filp);
-
out:
+ fput(filp);
if (rc < 0)
CDEBUG(D_LFSCK,
"%s: cannot check LMV, ino = %lu/%u: rc = %d\n",
if (!rc)
rc = rc2;
- osd_process_truncates(env, &truncates);
+ /* We preserve the origin behavior of ignoring any
+ * failures with the underlying punch / truncate
+ * operation. We do record for debugging if an error
+ * does occur in the lctl dk logs.
+ */
+ rc2 = osd_process_truncates(env, &truncates);
+ if (rc2 != 0)
+ CERROR("%s: failed truncate process: rc = %d\n",
+ osd_name(osd), rc2);
} else {
osd_trans_stop_cb(oh, th->th_result);
OBD_FREE_PTR(oh);
RETURN(rc);
}
-static int (*priv_security_file_alloc)(struct file *file);
-
-int osd_security_file_alloc(struct file *file)
-{
- if (priv_security_file_alloc)
- return priv_security_file_alloc(file);
- return 0;
-}
-
/*
* Concurrency: shouldn't matter.
*/
__u64 start, __u64 end)
{
struct osd_object *obj = osd_dt_obj(dt);
+ struct osd_device *dev = osd_obj2dev(obj);
struct inode *inode = obj->oo_inode;
- struct file *file = osd_quasi_file(env, inode);
+ struct file *file;
int rc;
ENTRY;
+ file = alloc_file_pseudo(inode, dev->od_mnt, "/", O_NOATIME,
+ inode->i_fop);
+ if (IS_ERR(file))
+ RETURN(PTR_ERR(file));
+ file->f_mode |= FMODE_64BITHASH;
rc = vfs_fsync_range(file, start, end, 0);
+ ihold(inode);
+ fput(file);
RETURN(rc);
}
};
struct osd_it_ea *osd_it_dir_init(const struct lu_env *env,
- struct inode *inode, __u32 attr)
+ struct osd_device *dev,
+ struct inode *inode, u32 attr)
{
struct osd_thread_info *info = osd_oti_get(env);
struct osd_it_ea *oie;
struct file *file;
- struct dentry *obj_dentry;
ENTRY;
+ file = alloc_file_pseudo(inode, dev->od_mnt, "/", O_NOATIME,
+ inode->i_fop);
+ if (IS_ERR(file))
+ RETURN(ERR_CAST(file));
- OBD_SLAB_ALLOC_PTR_GFP(oie, osd_itea_cachep, GFP_NOFS);
- if (oie == NULL)
- RETURN(ERR_PTR(-ENOMEM));
- obj_dentry = &oie->oie_dentry;
+ /* Only FMODE_64BITHASH or FMODE_32BITHASH should be set, NOT both. */
+ if (attr & LUDA_64BITHASH)
+ file->f_mode |= FMODE_64BITHASH;
+ else
+ file->f_mode |= FMODE_32BITHASH;
+ ihold(inode);
- obj_dentry->d_inode = inode;
- obj_dentry->d_sb = inode->i_sb;
- obj_dentry->d_name.hash = 0;
+ OBD_SLAB_ALLOC_PTR(oie, osd_itea_cachep);
+ if (!oie)
+ goto out_fput;
oie->oie_rd_dirent = 0;
oie->oie_it_dirent = 0;
info->oti_it_ea_buf_used = 1;
} else {
OBD_ALLOC(oie->oie_buf, OSD_IT_EA_BUFSIZE);
- if (oie->oie_buf == NULL)
- RETURN(ERR_PTR(-ENOMEM));
+ if (!oie->oie_buf)
+ goto out_free;
}
oie->oie_obj = NULL;
+ oie->oie_file = file;
- file = &oie->oie_file;
+ RETURN(oie);
- /* Only FMODE_64BITHASH or FMODE_32BITHASH should be set, NOT both. */
- if (attr & LUDA_64BITHASH)
- file->f_mode = FMODE_64BITHASH;
- else
- file->f_mode = FMODE_32BITHASH;
- file->f_path.dentry = obj_dentry;
- file->f_mapping = inode->i_mapping;
- file->f_op = inode->i_fop;
- file->f_inode = inode;
+out_free:
+ OBD_SLAB_FREE_PTR(oie, osd_itea_cachep);
+out_fput:
+ fput(file);
- RETURN(oie);
+ return ERR_PTR(-ENOMEM);
}
/**
__u32 attr)
{
struct osd_object *obj = osd_dt_obj(dt);
+ struct osd_device *dev = osd_obj2dev(obj);
struct lu_object *lo = &dt->do_lu;
struct osd_it_ea *oie;
if (!dt_object_exists(dt) || obj->oo_destroyed)
RETURN(ERR_PTR(-ENOENT));
- oie = osd_it_dir_init(env, obj->oo_inode, attr);
+ oie = osd_it_dir_init(env, dev, obj->oo_inode, attr);
if (IS_ERR(oie))
- RETURN((struct dt_it *)oie);
+ RETURN(ERR_CAST(oie));
oie->oie_obj = obj;
lu_object_get(lo);
struct osd_thread_info *info = osd_oti_get(env);
ENTRY;
- oie->oie_file.f_op->release(inode, &oie->oie_file);
+ fput(oie->oie_file);
if (unlikely(oie->oie_buf != info->oti_it_ea_buf))
OBD_FREE(oie->oie_buf, OSD_IT_EA_BUFSIZE);
else
ENTRY;
LASSERT(((const char *)key)[0] == '\0');
- it->oie_file.f_pos = 0;
+ it->oie_file->f_pos = 0;
it->oie_rd_dirent = 0;
it->oie_it_dirent = 0;
it->oie_dirent = NULL;
struct osd_it_ea *it = (struct osd_it_ea *)di;
struct osd_object *obj = it->oie_obj;
struct htree_lock *hlock = NULL;
- struct file *filp = &it->oie_file;
+ struct file *filp = it->oie_file;
int rc = 0;
struct osd_filldir_cbs buf = {
.ctx.actor = osd_ldiskfs_filldir,
}
}
- filp->f_cred = current_cred();
- rc = osd_security_file_alloc(filp);
- if (rc)
- GOTO(unlock, rc);
-
- filp->f_flags |= O_NOATIME;
- filp->f_mode |= FMODE_NONOTIFY;
rc = iterate_dir(filp, &buf.ctx);
if (rc)
GOTO(unlock, rc);
* If it does not get any dirent, it means it has been reached
* to the end of the dir
*/
- it->oie_file.f_pos = ldiskfs_get_htree_eof(&it->oie_file);
+ it->oie_file->f_pos = ldiskfs_get_htree_eof(it->oie_file);
if (rc == 0)
rc = 1;
} else {
it->oie_it_dirent++;
rc = 0;
} else {
- if (it->oie_file.f_pos == ldiskfs_get_htree_eof(&it->oie_file))
+ if (it->oie_file->f_pos == ldiskfs_get_htree_eof(it->oie_file))
rc = 1;
else
rc = osd_ldiskfs_it_fill(env, di);
int rc;
ENTRY;
- it->oie_file.f_pos = hash;
+ it->oie_file->f_pos = hash;
rc = osd_ldiskfs_it_fill(env, di);
if (rc > 0)
if (rc)
return rc;
-#ifdef CONFIG_KALLSYMS
- priv_security_file_alloc =
- (void *)cfs_kallsyms_lookup_name("security_file_alloc");
-#endif
-
rc = class_register_type(&osd_obd_device_ops, NULL, true,
LUSTRE_OSD_LDISKFS_NAME, &osd_device_type);
if (rc) {
rc = 0;
}
}
+
return rc;
}
struct osd_it_ea {
struct osd_object *oie_obj;
/** used in ldiskfs iterator, to stored file pointer */
- struct file oie_file;
+ struct file *oie_file;
/** how many entries have been read-cached from storage */
int oie_rd_dirent;
/** current entry is being iterated by caller */
struct osd_it_ea_dirent *oie_dirent;
/** buffer to hold entries, size == OSD_IT_EA_BUFSIZE */
void *oie_buf;
- struct dentry oie_dentry;
};
/**
unsigned int dr_init_at; /* the line iobuf was initialized */
};
-int osd_security_file_alloc(struct file *file);
-
#define osd_dirty_inode(inode, flag) (inode)->i_sb->s_op->dirty_inode((inode), flag)
+#ifndef HAVE_ALLOC_FILE_PSEUDO
+
+#define OPEN_FMODE(flag) ((__force fmode_t)(((flag + 1) & O_ACCMODE) | \
+ (flag & __FMODE_NONOTIFY)))
+static inline
+struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
+ const char *name, int flags,
+ const struct file_operations *fops)
+{
+ struct qstr this = QSTR_INIT(name, strlen(name));
+ struct path path;
+ struct file *file;
+
+ path.dentry = d_alloc_pseudo(mnt->mnt_sb, &this);
+ if (!path.dentry)
+ return ERR_PTR(-ENOMEM);
+ path.mnt = mntget(mnt);
+ d_instantiate(path.dentry, inode);
+ file = alloc_file(&path, OPEN_FMODE(flags), fops);
+ if (IS_ERR(file)) {
+ ihold(inode);
+ path_put(&path);
+ } else {
+ file->f_flags = flags;
+ }
+ return file;
+}
+#endif /* !HAVE_ALLOC_FILE_PSEUDO */
+
#ifdef HAVE_INODE_TIMESPEC64
# define osd_timespec timespec64
#else
/** dentry for Iterator context. */
struct dentry oti_it_dentry;
- union {
- /* fake struct file for osd_object_sync */
- struct file oti_file;
- /* osd_statfs() */
- struct kstatfs oti_ksfs;
- };
+ /* osd_statfs() */
+ struct kstatfs oti_ksfs;
struct htree_lock *oti_hlock;
struct osd_inode_id *id, const struct lu_fid *fid);
int osd_get_idif(struct osd_thread_info *info, struct inode *inode,
struct dentry *dentry, struct lu_fid *fid);
-struct osd_it_ea *osd_it_dir_init(const struct lu_env *env, struct inode *inode,
- __u32 attr);
+struct osd_it_ea *osd_it_dir_init(const struct lu_env *env,
+ struct osd_device *dev, struct inode *inode,
+ u32 attr);
void osd_it_dir_fini(const struct lu_env *env, struct osd_it_ea *oie,
struct inode *inode);
int osd_ldiskfs_it_fill(const struct lu_env *env, const struct dt_it *di);
return child_dentry;
}
-/* build quasi file structure when it is needed to call an inode i_fop */
-static inline struct file *osd_quasi_file_init(const struct lu_env *env,
- struct dentry *dentry,
- struct inode *inode)
-{
- struct osd_thread_info *info = osd_oti_get(env);
-
- info->oti_file.f_path.dentry = dentry;
- info->oti_file.f_mapping = inode->i_mapping;
- info->oti_file.f_op = inode->i_fop;
- info->oti_file.f_inode = inode;
- info->oti_file.f_pos = 0;
- info->oti_file.private_data = NULL;
- info->oti_file.f_cred = current_cred();
- info->oti_file.f_flags = O_NOATIME;
- info->oti_file.f_mode = FMODE_64BITHASH | FMODE_NONOTIFY;
-
- return &info->oti_file;
-}
-
-static inline struct file *osd_quasi_file(const struct lu_env *env,
- struct inode *inode)
-{
- struct osd_thread_info *info = osd_oti_get(env);
-
- info->oti_obj_dentry.d_inode = inode;
- info->oti_obj_dentry.d_sb = inode->i_sb;
-
- return osd_quasi_file_init(env, &info->oti_obj_dentry, inode);
-}
-
-static inline struct file *osd_quasi_file_by_dentry(const struct lu_env *env,
- struct dentry *dentry)
-{
- return osd_quasi_file_init(env, dentry, dentry->d_inode);
-}
-
extern int osd_trans_declare_op2rb[];
extern int ldiskfs_track_declares_assert;
void osd_trans_dump_creds(const struct lu_env *env, struct thandle *th);
int osd_trunc_lock(struct osd_object *obj, struct osd_thandle *oh,
bool shared);
void osd_trunc_unlock_all(const struct lu_env *env, struct list_head *list);
-void osd_process_truncates(const struct lu_env *env, struct list_head *list);
+int osd_process_truncates(const struct lu_env *env, struct list_head *list);
void osd_execute_truncate(struct osd_object *obj);
#ifdef HAVE_BIO_ENDIO_USES_ONE_ARG
loff_t offset, int whence)
{
struct osd_object *obj = osd_dt_obj(dt);
+ struct osd_device *dev = osd_obj2dev(obj);
struct inode *inode = obj->oo_inode;
struct file *file;
loff_t result;
ENTRY;
-
LASSERT(dt_object_exists(dt));
LASSERT(osd_invariant(obj));
LASSERT(inode);
LASSERT(offset >= 0);
- file = osd_quasi_file(env, inode);
- result = file->f_op->llseek(file, offset, whence);
+ file = alloc_file_pseudo(inode, dev->od_mnt, "/", O_NOATIME,
+ inode->i_fop);
+ if (IS_ERR(file))
+ RETURN(PTR_ERR(file));
+ file->f_mode |= FMODE_64BITHASH;
+ result = file->f_op->llseek(file, offset, whence);
+ ihold(inode);
+ fput(file);
/*
* If 'offset' is beyond end of object file then treat it as not error
* but valid case for SEEK_HOLE and return 'offset' as result.
osd_partial_page_flush(d, inode, size);
}
-void osd_execute_punch(const struct lu_env *env, struct osd_object *obj,
- loff_t start, loff_t end, int mode)
+static int osd_execute_punch(const struct lu_env *env, struct osd_object *obj,
+ loff_t start, loff_t end, int mode)
{
struct osd_device *d = osd_obj2dev(obj);
struct inode *inode = obj->oo_inode;
- struct file *file = osd_quasi_file(env, inode);
+ struct file *file;
+ int rc;
+
+ file = alloc_file_pseudo(inode, d->od_mnt, "/", O_NOATIME,
+ inode->i_fop);
+ if (IS_ERR(file))
+ RETURN(PTR_ERR(file));
- file->f_op->fallocate(file, mode, start, end - start);
- osd_partial_page_flush_punch(d, inode, start, end - 1);
+ file->f_mode |= FMODE_64BITHASH;
+ rc = file->f_op->fallocate(file, mode, start, end - start);
+ ihold(inode);
+ fput(file);
+ if (rc == 0)
+ osd_partial_page_flush_punch(d, inode, start, end - 1);
+ return rc;
}
-void osd_process_truncates(const struct lu_env *env, struct list_head *list)
+int osd_process_truncates(const struct lu_env *env, struct list_head *list)
{
struct osd_access_lock *al;
+ int rc = 0;
- LASSERT(journal_current_handle() == NULL);
+ LASSERT(!journal_current_handle());
list_for_each_entry(al, list, tl_list) {
if (al->tl_shared)
if (al->tl_truncate)
osd_execute_truncate(al->tl_obj);
else if (al->tl_punch)
- osd_execute_punch(env, al->tl_obj, al->tl_start,
- al->tl_end, al->tl_mode);
+ rc = osd_execute_punch(env, al->tl_obj, al->tl_start,
+ al->tl_end, al->tl_mode);
}
+
+ return rc;
}
.oifb_dentry = dentry
};
struct file *filp;
- struct inode *inode = dentry->d_inode;
+ struct path path;
int rc;
ENTRY;
+ LASSERT(filldir);
+ path.dentry = dget(dentry);
+ path.mnt = mntget(dev->od_mnt);
- LASSERT(filldir != NULL);
+ filp = dentry_open(&path, O_RDONLY, current_cred());
+ path_put(&path);
+ if (IS_ERR(filp))
+ RETURN(PTR_ERR(filp));
- filp = osd_quasi_file_by_dentry(info->oti_env, dentry);
- rc = osd_security_file_alloc(filp);
- if (rc)
- RETURN(rc);
+ filp->f_mode |= FMODE_64BITHASH | FMODE_NONOTIFY;
+ filp->f_flags |= O_NOATIME;
+ filp->f_pos = 0;
do {
buf.oifb_items = 0;
rc = iterate_dir(filp, &buf.ctx);
} while (rc >= 0 && buf.oifb_items > 0 &&
filp->f_pos != LDISKFS_HTREE_EOF_64BIT);
- inode->i_fop->release(inode, filp);
+ fput(filp);
RETURN(rc);
}
ENTRY;
- oie = osd_it_dir_init(env, inode, LUDA_TYPE);
+ oie = osd_it_dir_init(env, dev, inode, LUDA_TYPE);
if (IS_ERR(oie))
RETURN(PTR_ERR(oie));
- oie->oie_file.f_pos = 0;
+ oie->oie_file->f_pos = 0;
rc = osd_ldiskfs_it_fill(env, (struct dt_it *)oie);
if (rc > 0)
rc = -ENODATA;
if (oie->oie_it_dirent <= oie->oie_rd_dirent)
continue;
- if (oie->oie_file.f_pos ==
- ldiskfs_get_htree_eof(&oie->oie_file))
+ if (oie->oie_file->f_pos ==
+ ldiskfs_get_htree_eof(oie->oie_file))
break;
rc = osd_ldiskfs_it_fill(env, (struct dt_it *)oie);
{
handle_t *th;
struct lustre_scrub *scrub = &dev->od_scrub.os_scrub;
- struct dentry *dentry;
+ struct dentry dentry;
int rc;
ENTRY;
if (IS_ERR(th))
RETURN(PTR_ERR(th));
- dentry = &oie->oie_dentry;
- dentry->d_inode = dir;
- dentry->d_sb = dir->i_sb;
- rc = osd_obj_del_entry(info, dev, dentry, oie->oie_dirent->oied_name,
+ /* Should be created by the VFS layer */
+ dentry.d_inode = dir;
+ dentry.d_sb = dir->i_sb;
+ rc = osd_obj_del_entry(info, dev, &dentry, oie->oie_dirent->oied_name,
oie->oie_dirent->oied_namelen, th);
drop_nlink(inode);
mark_inode_dirty(inode);