+static int ll_file_futimes_3(struct file *file, const struct ll_futimes_3 *lfu)
+{
+ struct inode *inode = file_inode(file);
+ struct iattr ia = {
+ .ia_valid = ATTR_ATIME | ATTR_ATIME_SET |
+ ATTR_MTIME | ATTR_MTIME_SET |
+ ATTR_CTIME | ATTR_CTIME_SET,
+ .ia_atime = {
+ .tv_sec = lfu->lfu_atime_sec,
+ .tv_nsec = lfu->lfu_atime_nsec,
+ },
+ .ia_mtime = {
+ .tv_sec = lfu->lfu_mtime_sec,
+ .tv_nsec = lfu->lfu_mtime_nsec,
+ },
+ .ia_ctime = {
+ .tv_sec = lfu->lfu_ctime_sec,
+ .tv_nsec = lfu->lfu_ctime_nsec,
+ },
+ };
+ int rc;
+ ENTRY;
+
+ if (!capable(CAP_SYS_ADMIN))
+ RETURN(-EPERM);
+
+ if (!S_ISREG(inode->i_mode))
+ RETURN(-EINVAL);
+
+ inode_lock(inode);
+ rc = ll_setattr_raw(file_dentry(file), &ia, false);
+ inode_unlock(inode);
+
+ RETURN(rc);
+}
+
+/*
+ * Give file access advices
+ *
+ * The ladvise interface is similar to Linux fadvise() system call, except it
+ * forwards the advices directly from Lustre client to server. The server side
+ * codes will apply appropriate read-ahead and caching techniques for the
+ * corresponding files.
+ *
+ * A typical workload for ladvise is e.g. a bunch of different clients are
+ * doing small random reads of a file, so prefetching pages into OSS cache
+ * with big linear reads before the random IO is a net benefit. Fetching
+ * all that data into each client cache with fadvise() may not be, due to
+ * much more data being sent to the client.
+ */
+static int ll_ladvise(struct inode *inode, struct file *file, __u64 flags,
+ struct llapi_lu_ladvise *ladvise)
+{
+ struct lu_env *env;
+ struct cl_io *io;
+ struct cl_ladvise_io *lio;
+ int rc;
+ __u16 refcheck;
+ ENTRY;
+
+ env = cl_env_get(&refcheck);
+ if (IS_ERR(env))
+ RETURN(PTR_ERR(env));
+
+ io = vvp_env_thread_io(env);
+ io->ci_obj = ll_i2info(inode)->lli_clob;
+
+ /* initialize parameters for ladvise */
+ lio = &io->u.ci_ladvise;
+ lio->li_start = ladvise->lla_start;
+ lio->li_end = ladvise->lla_end;
+ lio->li_fid = ll_inode2fid(inode);
+ lio->li_advice = ladvise->lla_advice;
+ lio->li_flags = flags;
+
+ if (cl_io_init(env, io, CIT_LADVISE, io->ci_obj) == 0)
+ rc = cl_io_loop(env, io);
+ else
+ rc = io->ci_result;
+
+ cl_io_fini(env, io);
+ cl_env_put(env, &refcheck);
+ RETURN(rc);
+}
+
+int ll_ioctl_fsgetxattr(struct inode *inode, unsigned int cmd,
+ unsigned long arg)
+{
+ struct fsxattr fsxattr;
+
+ if (copy_from_user(&fsxattr,
+ (const struct fsxattr __user *)arg,
+ sizeof(fsxattr)))
+ RETURN(-EFAULT);
+
+ fsxattr.fsx_projid = ll_i2info(inode)->lli_projid;
+ if (copy_to_user((struct fsxattr __user *)arg,
+ &fsxattr, sizeof(fsxattr)))
+ RETURN(-EFAULT);
+
+ RETURN(0);
+}
+
+int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
+ unsigned long arg)
+{
+
+ struct md_op_data *op_data;
+ struct ptlrpc_request *req = NULL;
+ int rc = 0;
+ struct fsxattr fsxattr;
+
+ /* only root could change project ID */
+ if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+ RETURN(-EPERM);
+
+ op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
+ LUSTRE_OPC_ANY, NULL);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
+
+ if (copy_from_user(&fsxattr,
+ (const struct fsxattr __user *)arg,
+ sizeof(fsxattr)))
+ GOTO(out_fsxattr1, rc = -EFAULT);
+
+ op_data->op_projid = fsxattr.fsx_projid;
+ op_data->op_attr.ia_valid |= MDS_ATTR_PROJID;
+ rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL,
+ 0, &req);
+ ptlrpc_req_finished(req);
+
+out_fsxattr1:
+ ll_finish_md_op_data(op_data);
+ RETURN(rc);
+
+
+}
+