Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 834170c8 authored by Steve French's avatar Steve French
Browse files

Enable previous version support



Add ioctl to query previous versions of file

Allows listing snapshots on files on SMB3 mounts.

Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 18dd8e1a
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -36,7 +36,15 @@ struct smb_mnt_fs_info {
	__u64   cifs_posix_caps;
	__u64   cifs_posix_caps;
} __packed;
} __packed;


struct smb_snapshot_array {
	__u32	number_of_snapshots;
	__u32	number_of_snapshots_returned;
	__u32	snapshot_array_size;
	/*	snapshots[]; */
} __packed;

#define CIFS_IOCTL_MAGIC	0xCF
#define CIFS_IOCTL_MAGIC	0xCF
#define CIFS_IOC_COPYCHUNK_FILE	_IOW(CIFS_IOCTL_MAGIC, 3, int)
#define CIFS_IOC_COPYCHUNK_FILE	_IOW(CIFS_IOCTL_MAGIC, 3, int)
#define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
#define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
#define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
#define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
#define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
+2 −0
Original line number Original line Diff line number Diff line
@@ -388,6 +388,8 @@ struct smb_version_operations {
	int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
	int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
	int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon,
	int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon,
			     struct cifsFileInfo *src_file);
			     struct cifsFileInfo *src_file);
	int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon,
			     struct cifsFileInfo *src_file, void __user *);
	int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
	int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
				struct cifs_sb_info *, const unsigned char *,
				struct cifs_sb_info *, const unsigned char *,
				char *, unsigned int *);
				char *, unsigned int *);
+14 −2
Original line number Original line Diff line number Diff line
@@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
	xid = get_xid();
	xid = get_xid();


	cifs_sb = CIFS_SB(inode->i_sb);
	cifs_sb = CIFS_SB(inode->i_sb);

	cifs_dbg(VFS, "cifs ioctl 0x%x\n", command);
	switch (command) {
	switch (command) {
		case FS_IOC_GETFLAGS:
		case FS_IOC_GETFLAGS:
			if (pSMBFile == NULL)
			if (pSMBFile == NULL)
@@ -267,11 +267,23 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
			tcon = tlink_tcon(pSMBFile->tlink);
			tcon = tlink_tcon(pSMBFile->tlink);
			rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
			rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
			break;
			break;
		case CIFS_ENUMERATE_SNAPSHOTS:
			if (arg == 0) {
				rc = -EINVAL;
				goto cifs_ioc_exit;
			}
			tcon = tlink_tcon(pSMBFile->tlink);
			if (tcon->ses->server->ops->enum_snapshots)
				rc = tcon->ses->server->ops->enum_snapshots(xid, tcon,
						pSMBFile, (void __user *)arg);
			else
				rc = -EOPNOTSUPP;
			break;
		default:
		default:
			cifs_dbg(FYI, "unsupported ioctl\n");
			cifs_dbg(FYI, "unsupported ioctl\n");
			break;
			break;
	}
	}

cifs_ioc_exit:
	free_xid(xid);
	free_xid(xid);
	return rc;
	return rc;
}
}
+48 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@
#include "cifs_unicode.h"
#include "cifs_unicode.h"
#include "smb2status.h"
#include "smb2status.h"
#include "smb2glob.h"
#include "smb2glob.h"
#include "cifs_ioctl.h"


static int
static int
change_conf(struct TCP_Server_Info *server)
change_conf(struct TCP_Server_Info *server)
@@ -894,6 +895,50 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,


}
}


static int
smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
		   struct cifsFileInfo *cfile, void __user *ioc_buf)
{
	char *retbuf = NULL;
	unsigned int ret_data_len = 0;
	int rc;
	struct smb_snapshot_array snapshot_in;

	rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
			cfile->fid.volatile_fid,
			FSCTL_SRV_ENUMERATE_SNAPSHOTS,
			true /* is_fsctl */, NULL, 0 /* no input data */,
			(char **)&retbuf,
			&ret_data_len);
	cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
			rc, ret_data_len);
	if (rc)
		return rc;

	if (ret_data_len && (ioc_buf != NULL) && (retbuf != NULL)) {
		/* Fixup buffer */
		if (copy_from_user(&snapshot_in, ioc_buf,
		    sizeof(struct smb_snapshot_array))) {
			rc = -EFAULT;
			kfree(retbuf);
			return rc;
		}
		if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) {
			rc = -ERANGE;
			return rc;
		}

		if (ret_data_len > snapshot_in.snapshot_array_size)
			ret_data_len = snapshot_in.snapshot_array_size;

		if (copy_to_user(ioc_buf, retbuf, ret_data_len))
			rc = -EFAULT;
	}

	kfree(retbuf);
	return rc;
}

static int
static int
smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
		     const char *path, struct cifs_sb_info *cifs_sb,
		     const char *path, struct cifs_sb_info *cifs_sb,
@@ -1659,6 +1704,7 @@ struct smb_version_operations smb21_operations = {
	.clone_range = smb2_clone_range,
	.clone_range = smb2_clone_range,
	.wp_retry_size = smb2_wp_retry_size,
	.wp_retry_size = smb2_wp_retry_size,
	.dir_needs_close = smb2_dir_needs_close,
	.dir_needs_close = smb2_dir_needs_close,
	.enum_snapshots = smb3_enum_snapshots,
};
};


struct smb_version_operations smb30_operations = {
struct smb_version_operations smb30_operations = {
@@ -1745,6 +1791,7 @@ struct smb_version_operations smb30_operations = {
	.wp_retry_size = smb2_wp_retry_size,
	.wp_retry_size = smb2_wp_retry_size,
	.dir_needs_close = smb2_dir_needs_close,
	.dir_needs_close = smb2_dir_needs_close,
	.fallocate = smb3_fallocate,
	.fallocate = smb3_fallocate,
	.enum_snapshots = smb3_enum_snapshots,
};
};


#ifdef CONFIG_CIFS_SMB311
#ifdef CONFIG_CIFS_SMB311
@@ -1832,6 +1879,7 @@ struct smb_version_operations smb311_operations = {
	.wp_retry_size = smb2_wp_retry_size,
	.wp_retry_size = smb2_wp_retry_size,
	.dir_needs_close = smb2_dir_needs_close,
	.dir_needs_close = smb2_dir_needs_close,
	.fallocate = smb3_fallocate,
	.fallocate = smb3_fallocate,
	.enum_snapshots = smb3_enum_snapshots,
};
};
#endif /* CIFS_SMB311 */
#endif /* CIFS_SMB311 */