Loading fs/cifs/cifs_ioctl.h +8 −0 Original line number Diff line number Diff line Loading @@ -36,7 +36,15 @@ struct smb_mnt_fs_info { __u64 cifs_posix_caps; } __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_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int) #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_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array) fs/cifs/cifsglob.h +2 −0 Original line number Diff line number Diff line Loading @@ -388,6 +388,8 @@ struct smb_version_operations { int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon, 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 *, struct cifs_sb_info *, const unsigned char *, char *, unsigned int *); Loading fs/cifs/ioctl.c +14 −2 Original line number Diff line number Diff line Loading @@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) xid = get_xid(); cifs_sb = CIFS_SB(inode->i_sb); cifs_dbg(VFS, "cifs ioctl 0x%x\n", command); switch (command) { case FS_IOC_GETFLAGS: if (pSMBFile == NULL) Loading Loading @@ -267,11 +267,23 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) tcon = tlink_tcon(pSMBFile->tlink); rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg); 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: cifs_dbg(FYI, "unsupported ioctl\n"); break; } cifs_ioc_exit: free_xid(xid); return rc; } fs/cifs/smb2ops.c +48 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "cifs_unicode.h" #include "smb2status.h" #include "smb2glob.h" #include "cifs_ioctl.h" static int change_conf(struct TCP_Server_Info *server) Loading Loading @@ -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 smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, const char *path, struct cifs_sb_info *cifs_sb, Loading Loading @@ -1659,6 +1704,7 @@ struct smb_version_operations smb21_operations = { .clone_range = smb2_clone_range, .wp_retry_size = smb2_wp_retry_size, .dir_needs_close = smb2_dir_needs_close, .enum_snapshots = smb3_enum_snapshots, }; struct smb_version_operations smb30_operations = { Loading Loading @@ -1745,6 +1791,7 @@ struct smb_version_operations smb30_operations = { .wp_retry_size = smb2_wp_retry_size, .dir_needs_close = smb2_dir_needs_close, .fallocate = smb3_fallocate, .enum_snapshots = smb3_enum_snapshots, }; #ifdef CONFIG_CIFS_SMB311 Loading Loading @@ -1832,6 +1879,7 @@ struct smb_version_operations smb311_operations = { .wp_retry_size = smb2_wp_retry_size, .dir_needs_close = smb2_dir_needs_close, .fallocate = smb3_fallocate, .enum_snapshots = smb3_enum_snapshots, }; #endif /* CIFS_SMB311 */ Loading Loading
fs/cifs/cifs_ioctl.h +8 −0 Original line number Diff line number Diff line Loading @@ -36,7 +36,15 @@ struct smb_mnt_fs_info { __u64 cifs_posix_caps; } __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_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int) #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_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
fs/cifs/cifsglob.h +2 −0 Original line number Diff line number Diff line Loading @@ -388,6 +388,8 @@ struct smb_version_operations { int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon, 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 *, struct cifs_sb_info *, const unsigned char *, char *, unsigned int *); Loading
fs/cifs/ioctl.c +14 −2 Original line number Diff line number Diff line Loading @@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) xid = get_xid(); cifs_sb = CIFS_SB(inode->i_sb); cifs_dbg(VFS, "cifs ioctl 0x%x\n", command); switch (command) { case FS_IOC_GETFLAGS: if (pSMBFile == NULL) Loading Loading @@ -267,11 +267,23 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) tcon = tlink_tcon(pSMBFile->tlink); rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg); 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: cifs_dbg(FYI, "unsupported ioctl\n"); break; } cifs_ioc_exit: free_xid(xid); return rc; }
fs/cifs/smb2ops.c +48 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "cifs_unicode.h" #include "smb2status.h" #include "smb2glob.h" #include "cifs_ioctl.h" static int change_conf(struct TCP_Server_Info *server) Loading Loading @@ -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 smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, const char *path, struct cifs_sb_info *cifs_sb, Loading Loading @@ -1659,6 +1704,7 @@ struct smb_version_operations smb21_operations = { .clone_range = smb2_clone_range, .wp_retry_size = smb2_wp_retry_size, .dir_needs_close = smb2_dir_needs_close, .enum_snapshots = smb3_enum_snapshots, }; struct smb_version_operations smb30_operations = { Loading Loading @@ -1745,6 +1791,7 @@ struct smb_version_operations smb30_operations = { .wp_retry_size = smb2_wp_retry_size, .dir_needs_close = smb2_dir_needs_close, .fallocate = smb3_fallocate, .enum_snapshots = smb3_enum_snapshots, }; #ifdef CONFIG_CIFS_SMB311 Loading Loading @@ -1832,6 +1879,7 @@ struct smb_version_operations smb311_operations = { .wp_retry_size = smb2_wp_retry_size, .dir_needs_close = smb2_dir_needs_close, .fallocate = smb3_fallocate, .enum_snapshots = smb3_enum_snapshots, }; #endif /* CIFS_SMB311 */ Loading