* Operations on dt device.
*/
struct dt_device_operations {
- /**
- * Return device-wide statistics.
+ /**
+ * Return device-wide statistics.
*
* Return device-wide stats including block size, total and
* free blocks, total and free objects, etc. See struct obd_statfs
*
* \retval 0 on success
* \retval negative negated errno on error
- */
- int (*dt_statfs)(const struct lu_env *env,
+ */
+ int (*dt_statfs)(const struct lu_env *env,
struct dt_device *dev,
struct obd_statfs *osfs,
struct obd_statfs_info *info);
- /**
+ /**
* Create transaction.
*
* Create in-memory structure representing the transaction for the
*
* \retval pointer to handle if creation succeeds
* \retval ERR_PTR(errno) if creation fails
- */
- struct thandle *(*dt_trans_create)(const struct lu_env *env,
- struct dt_device *dev);
+ */
+ struct thandle *(*dt_trans_create)(const struct lu_env *env,
+ struct dt_device *dev);
- /**
+ /**
* Start transaction.
*
* Start the transaction. The transaction described by \a th can be
*
* \retval 0 on success
* \retval negative negated errno on error
- */
- int (*dt_trans_start)(const struct lu_env *env,
+ */
+ int (*dt_trans_start)(const struct lu_env *env,
struct dt_device *dev,
struct thandle *th);
struct dt_device *dev,
struct thandle *th);
- /**
- * Add commit callback to the transaction.
+ /**
+ * Add commit callback to the transaction.
*
* Add a commit callback to the given transaction handle. The callback
* will be called when the associated transaction is stored. I.e. the
*
* \retval 0 on success
* \retval negative negated errno on error
- */
- int (*dt_trans_cb_add)(struct thandle *th,
- struct dt_txn_commit_cb *dcb);
+ */
+ int (*dt_trans_cb_add)(struct thandle *th,
+ struct dt_txn_commit_cb *dcb);
- /**
+ /**
* Return FID of root index object.
*
* Return the FID of the root object in the filesystem. This object
*
* \retval 0 on success
* \retval negative negated errno on error
- */
- int (*dt_root_get)(const struct lu_env *env,
+ */
+ int (*dt_root_get)(const struct lu_env *env,
struct dt_device *dev,
struct lu_fid *f);
- /**
- * Return device configuration data.
+ /**
+ * Return device configuration data.
*
* Return device (disk fs, actually) specific configuration.
* The configuration isn't subject to change at runtime.
* \param[in] env execution environment for this thread
* \param[in] dev dt device
* \param[out] param configuration parameters
- */
- void (*dt_conf_get)(const struct lu_env *env,
- const struct dt_device *dev,
- struct dt_device_param *param);
+ */
+ void (*dt_conf_get)(const struct lu_env *env,
+ const struct dt_device *dev,
+ struct dt_device_param *param);
/**
- * Return device's super block.
+ * Return device's vfsmount.
*
* \param[in] dev dt device
*/
- struct super_block *(*dt_mnt_sb_get)(const struct dt_device *dev);
+ struct vfsmount *(*dt_mnt_get)(const struct dt_device *dev);
/**
* Sync the device.
}
static inline void dt_conf_get(const struct lu_env *env,
- const struct dt_device *dev,
- struct dt_device_param *param)
+ const struct dt_device *dev,
+ struct dt_device_param *param)
{
- LASSERT(dev);
- LASSERT(dev->dd_ops);
- LASSERT(dev->dd_ops->dt_conf_get);
- return dev->dd_ops->dt_conf_get(env, dev, param);
+ LASSERT(dev);
+ LASSERT(dev->dd_ops);
+ LASSERT(dev->dd_ops->dt_conf_get);
+ return dev->dd_ops->dt_conf_get(env, dev, param);
}
-static inline struct super_block *dt_mnt_sb_get(const struct dt_device *dev)
+static inline struct vfsmount *dt_mnt_get(const struct dt_device *dev)
{
LASSERT(dev);
LASSERT(dev->dd_ops);
- if (dev->dd_ops->dt_mnt_sb_get)
- return dev->dd_ops->dt_mnt_sb_get(dev);
+ if (dev->dd_ops->dt_mnt_get)
+ return dev->dd_ops->dt_mnt_get(dev);
return ERR_PTR(-EOPNOTSUPP);
}
void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx);
void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx);
+#if !defined(HAVE_ALLOC_FILE_PSEUDO) && defined(HAVE_SERVER_SUPPORT)
+#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 */
+
#endif
* for the client inode i_flags. The LUSTRE_*_FL are the Lustre wire
* protocol equivalents of LDISKFS_*_FL values stored on disk, while
* the S_* flags are kernel-internal values that change between kernel
- * versions. These flags are set/cleared via FSFILT_IOC_{GET,SET}_FLAGS.
+ * versions. These are set/cleared via FS_IOC_GETFLAGS/FS_IOC_SETFLAGS.
* See b=16526 for a full history.
*/
static inline int ll_ext_to_inode_flags(int ext_flags)
/* for statfs() */
#define LL_SUPER_MAGIC 0x0BD00BD0
-#define FSFILT_IOC_GETVERSION _IOR('f', 3, long)
+#define LL_IOC_GETVERSION _IOR('f', 3, long)
+#define FSFILT_IOC_GETVERSION LL_IOC_GETVERSION /* backward compat */
+#define LL_IOC_RESIZE_FS _IOW('f', 16, __u64)
/* FIEMAP flags supported by Lustre */
#define LUSTRE_FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_DEVICE_ORDER)
switch (cmd) {
case BLKSSZGET:
RETURN(put_user(PAGE_SIZE, (int __user *)uarg));
- case FSFILT_IOC_GETVERSION:
+ case LL_IOC_GETVERSION:
case FS_IOC_GETVERSION:
RETURN(put_user(inode->i_generation, (int __user *)uarg));
case FS_IOC_GETFLAGS: {
param->ddp_has_lseek_data_hole = true;
}
-static struct super_block *osd_mnt_sb_get(const struct dt_device *d)
+static struct vfsmount *osd_mnt_get(const struct dt_device *d)
{
- return osd_sb(osd_dt_dev(d));
+ return osd_dt_dev(d)->od_mnt;
}
/*
.dt_trans_stop = osd_trans_stop,
.dt_trans_cb_add = osd_trans_cb_add,
.dt_conf_get = osd_conf_get,
- .dt_mnt_sb_get = osd_mnt_sb_get,
+ .dt_mnt_get = osd_mnt_get,
.dt_sync = osd_sync,
.dt_ro = osd_ro,
.dt_commit_async = osd_commit_async,
#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
.show_options = server_show_options,
};
+#if defined(HAVE_USER_NAMESPACE_ARG)
+# define USERNS_ARG mnt_userns,
+#else
+# define USERNS_ARG
+# ifdef HAVE_INODEOPS_ENHANCED_GETATTR
+# define server_getattr(ns, path, st, rq, fl) server_getattr(path, st, rq, fl)
+# endif
+#endif
+
/*
- * Xattr support for Lustre servers
+ * inode operations for Lustre server mountpoints
*/
+#if defined(HAVE_USER_NAMESPACE_ARG) || defined(HAVE_INODEOPS_ENHANCED_GETATTR)
+static int server_getattr(struct user_namespace *mnt_userns,
+ const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int flags)
+{
+ struct inode *inode = d_inode(path->dentry);
+#else
+static int server_getattr(struct vfsmount *mnt, struct dentry *de,
+ struct kstat *stat)
+{
+ struct inode *inode = de->d_inode;
+#endif
+ struct lustre_sb_info *lsi = s2lsi(inode->i_sb);
+ struct vfsmount *root_mnt;
+ struct inode *root_inode;
+
+ root_mnt = dt_mnt_get(lsi->lsi_dt_dev);
+ if (IS_ERR(root_mnt))
+ root_inode = igrab(inode);
+ else
+ root_inode = igrab(root_mnt->mnt_sb->s_root->d_inode);
+ if (!root_inode)
+ return -EACCES;
+
+ CDEBUG(D_SUPER, "%s: root_inode from %s ino=%lu, dev=%x\n",
+ lsi->lsi_svname, root_inode == inode ? "lsi" : "vfsmnt",
+ root_inode->i_ino, root_inode->i_rdev);
+ generic_fillattr(USERNS_ARG root_inode, stat);
+ iput(root_inode);
+
+ return 0;
+}
+
#ifdef HAVE_IOP_XATTR
-static ssize_t lustre_getxattr(struct dentry *dentry, const char *name,
+static ssize_t server_getxattr(struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (!selinux_is_enabled())
return -ENODATA;
}
-static int lustre_setxattr(struct dentry *dentry, const char *name,
+static int server_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
return -EOPNOTSUPP;
}
#endif
-static ssize_t lustre_listxattr(struct dentry *d_entry, char *name,
+static ssize_t server_listxattr(struct dentry *d_entry, char *name,
size_t size)
{
return -EOPNOTSUPP;
}
-static bool is_cmd_supported(unsigned int command)
+static bool is_cmd_supported(unsigned int cmd)
{
- switch (command) {
+ CDEBUG(D_SUPER, "ioctl cmd=%x\n", cmd);
+
+ switch (cmd) {
case FITRIM:
return true;
+ case LL_IOC_RESIZE_FS:
+ return true;
default:
return false;
}
return false;
}
-static long server_ioctl(struct file *filp, unsigned int command,
- unsigned long arg)
+static long server_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
- struct file active_filp;
- struct inode *inode = file_inode(filp);
- struct lustre_sb_info *lsi = s2lsi(inode->i_sb);
- struct super_block *dd_sb = dt_mnt_sb_get(lsi->lsi_dt_dev);
- struct inode *active_inode;
+ struct lustre_sb_info *lsi = s2lsi(file_inode(filp)->i_sb);
+ struct vfsmount *root_mnt;
+ struct file *root_filp;
+ struct inode *root_inode;
int err = -EOPNOTSUPP;
- if (IS_ERR(dd_sb) || !is_cmd_supported(command))
+ if (!is_cmd_supported(cmd))
+ return err;
+
+ root_mnt = dt_mnt_get(lsi->lsi_dt_dev);
+ if (IS_ERR(root_mnt))
return err;
- active_inode = igrab(dd_sb->s_root->d_inode);
- if (!active_inode)
+ root_inode = igrab(root_mnt->mnt_root->d_inode);
+ if (!root_inode)
return -EACCES;
- active_filp.f_inode = active_inode;
- if (active_inode->i_fop && active_inode->i_fop->unlocked_ioctl)
- err = active_inode->i_fop->unlocked_ioctl(&active_filp,
- command, arg);
- iput(active_inode);
+ root_filp = alloc_file_pseudo(root_inode, root_mnt, "/",
+ O_RDWR | O_NOATIME, root_inode->i_fop);
+ if (root_inode->i_fop && root_inode->i_fop->unlocked_ioctl)
+ err = root_inode->i_fop->unlocked_ioctl(root_filp, cmd, arg);
+ fput(root_filp);
+
return err;
}
static const struct inode_operations server_inode_operations = {
+ .getattr = server_getattr,
#ifdef HAVE_IOP_XATTR
- .setxattr = lustre_setxattr,
- .getxattr = lustre_getxattr,
+ .setxattr = server_setxattr,
+ .getxattr = server_getxattr,
#endif
- .listxattr = lustre_listxattr,
+ .listxattr = server_listxattr,
};
static const struct file_operations server_file_operations = {