提交 834170c8 编写于 作者: S Steve French

Enable previous version support

Add ioctl to query previous versions of file

Allows listing snapshots on files on SMB3 mounts.
Signed-off-by: NSteve French <smfrench@gmail.com>
上级 18dd8e1a
...@@ -36,7 +36,15 @@ struct smb_mnt_fs_info { ...@@ -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)
...@@ -388,6 +388,8 @@ struct smb_version_operations { ...@@ -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 *);
......
...@@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) ...@@ -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) ...@@ -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;
} }
...@@ -28,6 +28,7 @@ ...@@ -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, ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册