#define FSCTL_UNLOCK_VOLUME 0x0009001C
#define FSCTL_IS_PATHNAME_VALID 0x0009002C /* BB add struct */
#define FSCTL_GET_COMPRESSION 0x0009003C
-#define FSCTL_SET_COMPRESSION 0x0009C040 /* BB add struct */
+#define FSCTL_SET_COMPRESSION 0x0009C040
#define FSCTL_QUERY_FAT_BPB 0x00090058 /* BB add struct */
/* Verify the next FSCTL number, we had it as 0x00090090 before */
#define FSCTL_FILESYSTEM_GET_STATS 0x00090060 /* BB add struct */
rsp->VolatileFileId = req->VolatileFileId;
break;
}
+ case FSCTL_SET_COMPRESSION: {
+ struct compress_ioctl *cmpr_req;
+ struct ksmbd_file *fp;
+
+ if (in_buf_len < sizeof(struct compress_ioctl)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+ ksmbd_debug(SMB, "User does not have write permission\n");
+ ret = -EACCES;
+ goto out;
+ }
+
+ cmpr_req = (struct compress_ioctl *)buffer;
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ ret = ksmbd_vfs_set_compression(work, fp, le16_to_cpu(cmpr_req->CompressionState));
+ ksmbd_fd_put(work, fp);
+ if (ret)
+ goto out;
+ break;
+ }
case FSCTL_CREATE_OR_GET_OBJECT_ID:
{
struct file_object_buf_type1_ioctl_rsp *obj_buf;
out:
return rc;
}
+
+int ksmbd_vfs_set_compression(struct ksmbd_work *work, struct ksmbd_file *fp, u16 fmt)
+{
+ struct file_kattr fa;
+ struct dentry *dentry = fp->filp->f_path.dentry;
+ struct mnt_idmap *idmap = file_mnt_idmap(fp->filp);
+ u32 flags;
+ __le32 old_fattr;
+ int rc;
+
+ if (!(fp->daccess & FILE_WRITE_DATA_LE)) {
+ rc = -EACCES;
+ goto out;
+ }
+
+ rc = vfs_fileattr_get(dentry, &fa);
+ if (rc)
+ goto out;
+
+ flags = fa.flags;
+ if (fmt == COMPRESSION_FORMAT_NONE) {
+ flags &= ~FS_COMPR_FL;
+ } else if (fmt == COMPRESSION_FORMAT_DEFAULT ||
+ fmt == COMPRESSION_FORMAT_LZNT1) {
+ flags |= FS_COMPR_FL;
+ } else {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (flags != fa.flags) {
+ fileattr_fill_flags(&fa, flags);
+ rc = mnt_want_write_file(fp->filp);
+ if (rc)
+ goto out;
+
+ rc = vfs_fileattr_set(idmap, dentry, &fa);
+ mnt_drop_write_file(fp->filp);
+ if (rc)
+ goto out;
+ }
+
+ old_fattr = fp->f_ci->m_fattr;
+ if (fmt == COMPRESSION_FORMAT_NONE)
+ fp->f_ci->m_fattr &= ~FILE_ATTRIBUTE_COMPRESSED_LE;
+ else
+ fp->f_ci->m_fattr |= FILE_ATTRIBUTE_COMPRESSED_LE;
+
+ if (fp->f_ci->m_fattr != old_fattr &&
+ test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
+ struct xattr_dos_attrib da;
+
+ rc = ksmbd_vfs_get_dos_attrib_xattr(idmap, dentry, &da);
+ if (rc <= 0) {
+ rc = 0;
+ goto out;
+ }
+
+ da.attr = le32_to_cpu(fp->f_ci->m_fattr);
+ rc = ksmbd_vfs_set_dos_attrib_xattr(idmap,
+ &fp->filp->f_path,
+ &da, true);
+ if (rc)
+ rc = 0;
+ }
+
+out:
+ return rc;
+}
struct inode *parent_inode);
void ksmbd_vfs_update_compressed_fattr(struct dentry *dentry, __le32 *fattr);
int ksmbd_vfs_get_compression(struct ksmbd_file *fp, u16 *fmt);
+int ksmbd_vfs_set_compression(struct ksmbd_work *work, struct ksmbd_file *fp, u16 fmt);
#endif /* __KSMBD_VFS_H__ */