return rc;
}
+static int cifs_set_compression_by_path(unsigned int xid, struct file *filep,
+ struct cifs_tcon *tcon)
+{
+ struct inode *inode = file_inode(filep);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifs_open_parms oparms;
+ struct cifs_open_info_data data = {};
+ struct cifsFileInfo *tmp_cfile = NULL;
+ struct cifs_fid fid = {};
+ const char *full_path;
+ __u32 oplock = 0;
+ u64 uniqueid;
+ void *page;
+ int rc;
+
+ if (!server->ops->open || !server->ops->close ||
+ !server->ops->query_file_info)
+ return -EOPNOTSUPP;
+
+ if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM) ||
+ cifs_sb->mnt_cifs_serverino_autodisabled)
+ return -EOPNOTSUPP;
+
+ if (d_unhashed(filep->f_path.dentry))
+ return -ESTALE;
+
+ page = alloc_dentry_path();
+ full_path = build_path_from_dentry(filep->f_path.dentry, page);
+ if (IS_ERR(full_path)) {
+ free_dentry_path(page);
+ return PTR_ERR(full_path);
+ }
+
+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA |
+ FILE_READ_ATTRIBUTES,
+ FILE_OPEN, 0, ACL_NO_MODE);
+ oparms.fid = &fid;
+
+ rc = server->ops->open(xid, &oparms, &oplock, NULL);
+ if (rc)
+ goto out;
+
+ tmp_cfile = kzalloc_obj(*tmp_cfile);
+ if (!tmp_cfile) {
+ rc = -ENOMEM;
+ goto close;
+ }
+
+ tmp_cfile->fid = fid;
+ rc = server->ops->query_file_info(xid, tcon, tmp_cfile, &data);
+ if (rc)
+ goto close;
+
+ uniqueid = le64_to_cpu(data.fi.IndexNumber);
+ if (uniqueid != CIFS_I(inode)->uniqueid) {
+ rc = -ESTALE;
+ goto close;
+ }
+
+ rc = server->ops->set_compression(xid, tcon, tmp_cfile);
+
+close:
+ server->ops->close(xid, tcon, &fid);
+ if (tmp_cfile)
+ kfree(tmp_cfile);
+ cifs_free_open_info(&data);
+out:
+ free_dentry_path(page);
+ return rc;
+}
+
+static int cifs_ioctl_set_compression(unsigned int xid, struct file *filep,
+ struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile)
+{
+ struct cifsFileInfo *wfile;
+ struct cifs_tcon *wtcon;
+ struct inode *inode = file_inode(filep);
+ int rc;
+
+ if (!tcon->ses->server->ops->set_compression)
+ return -EOPNOTSUPP;
+
+ if (cfile && (cfile->fid.access & FILE_WRITE_DATA)) {
+ rc = tcon->ses->server->ops->set_compression(xid, tcon, cfile);
+ if (rc != -EACCES)
+ return rc;
+ }
+
+ rc = cifs_get_writable_file(CIFS_I(inode), FIND_FSUID_ONLY, &wfile);
+ if (!rc) {
+ wtcon = tlink_tcon(wfile->tlink);
+ rc = wtcon->ses->server->ops->set_compression(xid, wtcon, wfile);
+ cifsFileInfo_put(wfile);
+ if (rc != -EACCES)
+ return rc;
+ } else if (rc != -EBADF) {
+ return rc;
+ }
+
+ return cifs_set_compression_by_path(xid, filep, tcon);
+}
+
static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
unsigned long srcfd)
{
break;
/* Try to set compress flag */
- if (tcon->ses->server->ops->set_compression) {
- rc = tcon->ses->server->ops->set_compression(
- xid, tcon, pSMBFile);
- cifs_dbg(FYI, "set compress flag rc %d\n", rc);
+ rc = cifs_ioctl_set_compression(xid, filep, tcon,
+ pSMBFile);
+ if (rc == 0) {
+ spin_lock(&inode->i_lock);
+ CIFS_I(inode)->cifsAttrs |=
+ FILE_ATTRIBUTE_COMPRESSED;
+ spin_unlock(&inode->i_lock);
}
+ cifs_dbg(FYI, "set compress flag rc %d\n", rc);
break;
case CIFS_IOC_COPYCHUNK_FILE:
rc = cifs_ioctl_copychunk(xid, filep, arg);