Skip to content

Commit 84e9a2d

Browse files
committed
Merge tag 'v6.8-rc-part1-smb-client' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client fixes from Steve French: "Various smb client fixes, most related to better handling special file types: - Improve handling of special file types: - performance improvement (better compounding and better caching of readdir entries that are reparse points) - extend support for creating special files (sockets, fifos, block/char devices) - fix renaming and hardlinking of reparse points - extend support for creating symlinks with IO_REPARSE_TAG_SYMLINK - Multichannel logging improvement - Exception handling fix - Minor cleanups" * tag 'v6.8-rc-part1-smb-client' of git://git.samba.org/sfrench/cifs-2.6: cifs: update internal module version number for cifs.ko cifs: remove unneeded return statement cifs: make cifs_chan_update_iface() a void function cifs: delete unnecessary NULL checks in cifs_chan_update_iface() cifs: get rid of dup length check in parse_reparse_point() smb: client: stop revalidating reparse points unnecessarily cifs: Pass unbyteswapped eof value into SMB2_set_eof() smb3: Improve exception handling in allocate_mr_list() cifs: fix in logging in cifs_chan_update_iface smb: client: handle special files and symlinks in SMB3 POSIX smb: client: cleanup smb2_query_reparse_point() smb: client: allow creating symlinks via reparse points smb: client: fix hardlinking of reparse points smb: client: fix renaming of reparse points smb: client: optimise reparse point querying smb: client: allow creating special files via reparse points smb: client: extend smb2_compound_op() to accept more commands smb: client: Fix minor whitespace errors and warnings
2 parents 587217f + 26ba1bf commit 84e9a2d

File tree

18 files changed

+1131
-829
lines changed

18 files changed

+1131
-829
lines changed

fs/smb/client/cifsfs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,6 @@ extern const struct export_operations cifs_export_ops;
152152
#endif /* CONFIG_CIFS_NFSD_EXPORT */
153153

154154
/* when changing internal version - update following two lines at same time */
155-
#define SMB3_PRODUCT_BUILD 46
156-
#define CIFS_VERSION "2.46"
155+
#define SMB3_PRODUCT_BUILD 47
156+
#define CIFS_VERSION "2.47"
157157
#endif /* _CIFSFS_H */

fs/smb/client/cifsglob.h

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ struct cifs_open_info_data {
192192
bool symlink;
193193
};
194194
struct {
195+
/* ioctl response buffer */
196+
struct {
197+
int buftype;
198+
struct kvec iov;
199+
} io;
195200
__u32 tag;
196201
union {
197202
struct reparse_data_buffer *buf;
@@ -205,13 +210,17 @@ struct cifs_open_info_data {
205210
};
206211
};
207212

208-
#define cifs_open_data_reparse(d) \
209-
((d)->reparse_point || \
210-
(le32_to_cpu((d)->fi.Attributes) & ATTR_REPARSE))
211-
212-
static inline void cifs_free_open_info(struct cifs_open_info_data *data)
213+
static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
213214
{
214-
kfree(data->symlink_target);
215+
struct smb2_file_all_info *fi = &data->fi;
216+
u32 attrs = le32_to_cpu(fi->Attributes);
217+
bool ret;
218+
219+
ret = data->reparse_point || (attrs & ATTR_REPARSE);
220+
if (ret)
221+
attrs |= ATTR_REPARSE;
222+
fi->Attributes = cpu_to_le32(attrs);
223+
return ret;
215224
}
216225

217226
/*
@@ -390,12 +399,17 @@ struct smb_version_operations {
390399
int (*rename_pending_delete)(const char *, struct dentry *,
391400
const unsigned int);
392401
/* send rename request */
393-
int (*rename)(const unsigned int, struct cifs_tcon *, const char *,
394-
const char *, struct cifs_sb_info *);
402+
int (*rename)(const unsigned int xid,
403+
struct cifs_tcon *tcon,
404+
struct dentry *source_dentry,
405+
const char *from_name, const char *to_name,
406+
struct cifs_sb_info *cifs_sb);
395407
/* send create hardlink request */
396-
int (*create_hardlink)(const unsigned int, struct cifs_tcon *,
397-
const char *, const char *,
398-
struct cifs_sb_info *);
408+
int (*create_hardlink)(const unsigned int xid,
409+
struct cifs_tcon *tcon,
410+
struct dentry *source_dentry,
411+
const char *from_name, const char *to_name,
412+
struct cifs_sb_info *cifs_sb);
399413
/* query symlink target */
400414
int (*query_symlink)(const unsigned int xid,
401415
struct cifs_tcon *tcon,
@@ -560,6 +574,12 @@ struct smb_version_operations {
560574
int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb,
561575
struct kvec *rsp_iov,
562576
struct cifs_open_info_data *data);
577+
int (*create_reparse_symlink)(const unsigned int xid,
578+
struct inode *inode,
579+
struct dentry *dentry,
580+
struct cifs_tcon *tcon,
581+
const char *full_path,
582+
const char *symname);
563583
};
564584

565585
struct smb_version_values {
@@ -1545,6 +1565,7 @@ struct cifsInodeInfo {
15451565
spinlock_t deferred_lock; /* protection on deferred list */
15461566
bool lease_granted; /* Flag to indicate whether lease or oplock is granted. */
15471567
char *symlink_target;
1568+
__u32 reparse_tag;
15481569
};
15491570

15501571
static inline struct cifsInodeInfo *
@@ -2238,8 +2259,8 @@ static inline void cifs_sg_set_buf(struct sg_table *sgtable,
22382259

22392260
struct smb2_compound_vars {
22402261
struct cifs_open_parms oparms;
2241-
struct kvec rsp_iov[3];
2242-
struct smb_rqst rqst[3];
2262+
struct kvec rsp_iov[MAX_COMPOUND];
2263+
struct smb_rqst rqst[MAX_COMPOUND];
22432264
struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
22442265
struct kvec qi_iov;
22452266
struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];

fs/smb/client/cifsproto.h

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,12 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path,
211211
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
212212
struct cifs_fattr *fattr,
213213
struct cifs_open_info_data *data);
214-
extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
215-
struct super_block *sb, unsigned int xid);
214+
215+
extern int smb311_posix_get_inode_info(struct inode **inode,
216+
const char *full_path,
217+
struct cifs_open_info_data *data,
218+
struct super_block *sb,
219+
const unsigned int xid);
216220
extern int cifs_get_inode_info_unix(struct inode **pinode,
217221
const unsigned char *search_path,
218222
struct super_block *sb, unsigned int xid);
@@ -435,16 +439,19 @@ extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
435439
int remap_special_chars);
436440
extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
437441
const char *name, struct cifs_sb_info *cifs_sb);
438-
extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
439-
const char *from_name, const char *to_name,
440-
struct cifs_sb_info *cifs_sb);
442+
int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
443+
struct dentry *source_dentry,
444+
const char *from_name, const char *to_name,
445+
struct cifs_sb_info *cifs_sb);
441446
extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
442447
int netfid, const char *target_name,
443448
const struct nls_table *nls_codepage,
444449
int remap_special_chars);
445-
extern int CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
446-
const char *from_name, const char *to_name,
447-
struct cifs_sb_info *cifs_sb);
450+
int CIFSCreateHardLink(const unsigned int xid,
451+
struct cifs_tcon *tcon,
452+
struct dentry *source_dentry,
453+
const char *from_name, const char *to_name,
454+
struct cifs_sb_info *cifs_sb);
448455
extern int CIFSUnixCreateHardLink(const unsigned int xid,
449456
struct cifs_tcon *tcon,
450457
const char *fromName, const char *toName,
@@ -649,7 +656,7 @@ cifs_chan_is_iface_active(struct cifs_ses *ses,
649656
struct TCP_Server_Info *server);
650657
void
651658
cifs_disable_secondary_channels(struct cifs_ses *ses);
652-
int
659+
void
653660
cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server);
654661
int
655662
SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount);
@@ -760,4 +767,11 @@ static inline void release_mid(struct mid_q_entry *mid)
760767
kref_put(&mid->refcount, __release_mid);
761768
}
762769

770+
static inline void cifs_free_open_info(struct cifs_open_info_data *data)
771+
{
772+
kfree(data->symlink_target);
773+
free_rsp_buf(data->reparse.io.buftype, data->reparse.io.iov.iov_base);
774+
memset(data, 0, sizeof(*data));
775+
}
776+
763777
#endif /* _CIFSPROTO_H */

fs/smb/client/cifssmb.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,10 +2149,10 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
21492149
return rc;
21502150
}
21512151

2152-
int
2153-
CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2154-
const char *from_name, const char *to_name,
2155-
struct cifs_sb_info *cifs_sb)
2152+
int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2153+
struct dentry *source_dentry,
2154+
const char *from_name, const char *to_name,
2155+
struct cifs_sb_info *cifs_sb)
21562156
{
21572157
int rc = 0;
21582158
RENAME_REQ *pSMB = NULL;
@@ -2530,10 +2530,11 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
25302530
return rc;
25312531
}
25322532

2533-
int
2534-
CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2535-
const char *from_name, const char *to_name,
2536-
struct cifs_sb_info *cifs_sb)
2533+
int CIFSCreateHardLink(const unsigned int xid,
2534+
struct cifs_tcon *tcon,
2535+
struct dentry *source_dentry,
2536+
const char *from_name, const char *to_name,
2537+
struct cifs_sb_info *cifs_sb)
25372538
{
25382539
int rc = 0;
25392540
NT_RENAME_REQ *pSMB = NULL;
@@ -2699,11 +2700,12 @@ int cifs_query_reparse_point(const unsigned int xid,
26992700
u32 *tag, struct kvec *rsp,
27002701
int *rsp_buftype)
27012702
{
2703+
struct reparse_data_buffer *buf;
27022704
struct cifs_open_parms oparms;
27032705
TRANSACT_IOCTL_REQ *io_req = NULL;
27042706
TRANSACT_IOCTL_RSP *io_rsp = NULL;
27052707
struct cifs_fid fid;
2706-
__u32 data_offset, data_count;
2708+
__u32 data_offset, data_count, len;
27072709
__u8 *start, *end;
27082710
int io_rsp_len;
27092711
int oplock = 0;
@@ -2773,7 +2775,16 @@ int cifs_query_reparse_point(const unsigned int xid,
27732775
goto error;
27742776
}
27752777

2776-
*tag = le32_to_cpu(((struct reparse_data_buffer *)start)->ReparseTag);
2778+
data_count = le16_to_cpu(io_rsp->ByteCount);
2779+
buf = (struct reparse_data_buffer *)start;
2780+
len = sizeof(*buf);
2781+
if (data_count < len ||
2782+
data_count < le16_to_cpu(buf->ReparseDataLength) + len) {
2783+
rc = -EIO;
2784+
goto error;
2785+
}
2786+
2787+
*tag = le32_to_cpu(buf->ReparseTag);
27772788
rsp->iov_base = io_rsp;
27782789
rsp->iov_len = io_rsp_len;
27792790
*rsp_buftype = CIFS_LARGE_BUFFER;

fs/smb/client/connect.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ static int reconnect_target_unlocked(struct TCP_Server_Info *server, struct dfs_
483483
static int reconnect_dfs_server(struct TCP_Server_Info *server)
484484
{
485485
struct dfs_cache_tgt_iterator *target_hint = NULL;
486+
486487
DFS_CACHE_TGT_LIST(tl);
487488
int num_targets = 0;
488489
int rc = 0;
@@ -745,6 +746,7 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
745746
{
746747
struct msghdr smb_msg = {};
747748
struct kvec iov = {.iov_base = buf, .iov_len = to_read};
749+
748750
iov_iter_kvec(&smb_msg.msg_iter, ITER_DEST, &iov, 1, to_read);
749751

750752
return cifs_readv_from_socket(server, &smb_msg);
@@ -1400,11 +1402,13 @@ cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
14001402
case AF_INET: {
14011403
struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
14021404
struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1405+
14031406
return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
14041407
}
14051408
case AF_INET6: {
14061409
struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
14071410
struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
1411+
14081412
return (ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr)
14091413
&& saddr6->sin6_scope_id == vaddr6->sin6_scope_id);
14101414
}
@@ -2599,8 +2603,8 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
25992603
rc = -EOPNOTSUPP;
26002604
goto out_fail;
26012605
} else {
2602-
cifs_dbg(VFS, "Check vers= mount option. SMB3.11 "
2603-
"disabled but required for POSIX extensions\n");
2606+
cifs_dbg(VFS,
2607+
"Check vers= mount option. SMB3.11 disabled but required for POSIX extensions\n");
26042608
rc = -EOPNOTSUPP;
26052609
goto out_fail;
26062610
}
@@ -2743,7 +2747,6 @@ cifs_put_tlink(struct tcon_link *tlink)
27432747
if (!IS_ERR(tlink_tcon(tlink)))
27442748
cifs_put_tcon(tlink_tcon(tlink));
27452749
kfree(tlink);
2746-
return;
27472750
}
27482751

27492752
static int
@@ -2884,6 +2887,7 @@ static inline void
28842887
cifs_reclassify_socket4(struct socket *sock)
28852888
{
28862889
struct sock *sk = sock->sk;
2890+
28872891
BUG_ON(!sock_allow_reclassification(sk));
28882892
sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
28892893
&cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
@@ -2893,6 +2897,7 @@ static inline void
28932897
cifs_reclassify_socket6(struct socket *sock)
28942898
{
28952899
struct sock *sk = sock->sk;
2900+
28962901
BUG_ON(!sock_allow_reclassification(sk));
28972902
sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
28982903
&cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
@@ -2927,15 +2932,18 @@ static int
29272932
bind_socket(struct TCP_Server_Info *server)
29282933
{
29292934
int rc = 0;
2935+
29302936
if (server->srcaddr.ss_family != AF_UNSPEC) {
29312937
/* Bind to the specified local IP address */
29322938
struct socket *socket = server->ssocket;
2939+
29332940
rc = kernel_bind(socket,
29342941
(struct sockaddr *) &server->srcaddr,
29352942
sizeof(server->srcaddr));
29362943
if (rc < 0) {
29372944
struct sockaddr_in *saddr4;
29382945
struct sockaddr_in6 *saddr6;
2946+
29392947
saddr4 = (struct sockaddr_in *)&server->srcaddr;
29402948
saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
29412949
if (saddr6->sin6_family == AF_INET6)
@@ -3165,6 +3173,7 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
31653173

31663174
if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
31673175
__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3176+
31683177
cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
31693178
/*
31703179
* check for reconnect case in which we do not
@@ -3668,7 +3677,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
36683677
smb_buffer_response = smb_buffer;
36693678

36703679
header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3671-
NULL /*no tid */ , 4 /*wct */ );
3680+
NULL /*no tid */, 4 /*wct */);
36723681

36733682
smb_buffer->Mid = get_next_mid(ses->server);
36743683
smb_buffer->Uid = ses->Suid;
@@ -3687,12 +3696,12 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
36873696
if (ses->server->sign)
36883697
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
36893698

3690-
if (ses->capabilities & CAP_STATUS32) {
3699+
if (ses->capabilities & CAP_STATUS32)
36913700
smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3692-
}
3693-
if (ses->capabilities & CAP_DFS) {
3701+
3702+
if (ses->capabilities & CAP_DFS)
36943703
smb_buffer->Flags2 |= SMBFLG2_DFS;
3695-
}
3704+
36963705
if (ses->capabilities & CAP_UNICODE) {
36973706
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
36983707
length =

fs/smb/client/dir.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -680,9 +680,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
680680
full_path, d_inode(direntry));
681681

682682
again:
683-
if (pTcon->posix_extensions)
684-
rc = smb311_posix_get_inode_info(&newInode, full_path, parent_dir_inode->i_sb, xid);
685-
else if (pTcon->unix_ext) {
683+
if (pTcon->posix_extensions) {
684+
rc = smb311_posix_get_inode_info(&newInode, full_path, NULL,
685+
parent_dir_inode->i_sb, xid);
686+
} else if (pTcon->unix_ext) {
686687
rc = cifs_get_inode_info_unix(&newInode, full_path,
687688
parent_dir_inode->i_sb, xid);
688689
} else {

fs/smb/client/file.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,14 +1020,16 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
10201020
if (!is_interrupt_error(rc))
10211021
mapping_set_error(inode->i_mapping, rc);
10221022

1023-
if (tcon->posix_extensions)
1024-
rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid);
1025-
else if (tcon->unix_ext)
1023+
if (tcon->posix_extensions) {
1024+
rc = smb311_posix_get_inode_info(&inode, full_path,
1025+
NULL, inode->i_sb, xid);
1026+
} else if (tcon->unix_ext) {
10261027
rc = cifs_get_inode_info_unix(&inode, full_path,
10271028
inode->i_sb, xid);
1028-
else
1029+
} else {
10291030
rc = cifs_get_inode_info(&inode, full_path, NULL,
10301031
inode->i_sb, xid, NULL);
1032+
}
10311033
}
10321034
/*
10331035
* Else we are writing out data to server already and could deadlock if

0 commit comments

Comments
 (0)