Skip to content

Commit f80ac7e

Browse files
dhowellssmfrench
authored andcommitted
cifs: Add a tracepoint to log EIO errors
Add a tracepoint to log EIO errors and give it the capacity to convey up to two integers of information. This is then wrapped with three functions: int smb_EIO(enum smb_eio_trace trace) int smb_EIO1(enum smb_eio_trace trace, unsigned long info) int smb_EIO2(enum smb_eio_trace trace, unsigned long info, unsigned long info2) depending on how many bits of info are desired to be logged with any particular trace. The functions all return -EIO and can be used in place of -EIO. The trace argument is an enum value that gets translated to a string when the trace is printed. This makes is easier to log EIO instances when the client is under high load than turning on a printk wrapper such as cifs_dbg(). Granted, EIO could have its own separate EIO printing since EIO shouldn't happen. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> cc: linux-cifs@vger.kernel.org cc: linux-fsdevel@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 3a7b6d0 commit f80ac7e

27 files changed

Lines changed: 609 additions & 312 deletions

fs/smb/client/cached_dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
176176
server = cifs_pick_channel(ses);
177177

178178
if (!server->ops->new_lease_key)
179-
return -EIO;
179+
return smb_EIO(smb_eio_trace_no_lease_key);
180180

181181
utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
182182
if (!utf16_path)

fs/smb/client/cifsacl.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid)
300300
__func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
301301
goto out_revert_creds;
302302
} else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
303-
rc = -EIO;
303+
rc = smb_EIO1(smb_eio_trace_malformed_sid_key, sidkey->datalen);
304304
cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
305305
__func__, sidkey->datalen);
306306
goto invalidate_key;
@@ -317,7 +317,8 @@ id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid)
317317

318318
ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
319319
if (ksid_size > sidkey->datalen) {
320-
rc = -EIO;
320+
rc = smb_EIO2(smb_eio_trace_malformed_ksid_key,
321+
ksid_size, sidkey->datalen);
321322
cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
322323
__func__, sidkey->datalen, ksid_size);
323324
goto invalidate_key;
@@ -352,7 +353,8 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid,
352353
if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
353354
cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
354355
__func__, psid->num_subauth);
355-
return -EIO;
356+
return smb_EIO2(smb_eio_trace_sid_too_many_auth,
357+
psid->num_subauth, SID_MAX_SUB_AUTHORITIES);
356358
}
357359

358360
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) ||
@@ -1227,7 +1229,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
12271229
__u32 dacloffset;
12281230

12291231
if (pntsd == NULL)
1230-
return -EIO;
1232+
return smb_EIO(smb_eio_trace_null_pointers);
12311233

12321234
owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
12331235
le32_to_cpu(pntsd->osidoffset));

fs/smb/client/cifsencrypt.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@ static int cifs_sig_iter(const struct iov_iter *iter, size_t maxsize,
7575
struct cifs_calc_sig_ctx *ctx)
7676
{
7777
struct iov_iter tmp_iter = *iter;
78-
int err = -EIO;
78+
size_t did;
79+
int err;
7980

80-
if (iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, &err,
81-
cifs_sig_step) != maxsize)
82-
return err;
81+
did = iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, &err,
82+
cifs_sig_step);
83+
if (did != maxsize)
84+
return smb_EIO2(smb_eio_trace_sig_iter, did, maxsize);
8385
return 0;
8486
}
8587

@@ -96,7 +98,8 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
9698
iov_iter_kvec(&iter, ITER_SOURCE, rqst->rq_iov, rqst->rq_nvec, size);
9799

98100
if (iov_iter_count(&iter) <= 4)
99-
return -EIO;
101+
return smb_EIO2(smb_eio_trace_sig_data_too_small,
102+
iov_iter_count(&iter), 4);
100103

101104
rc = cifs_sig_iter(&iter, iov_iter_count(&iter), ctx);
102105
if (rc < 0)

fs/smb/client/cifsglob.h

Lines changed: 0 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,94 +2206,6 @@ static inline void move_cifs_info_to_smb2(struct smb2_file_all_info *dst, const
22062206
dst->FileNameLength = src->FileNameLength;
22072207
}
22082208

2209-
static inline int cifs_get_num_sgs(const struct smb_rqst *rqst,
2210-
int num_rqst,
2211-
const u8 *sig)
2212-
{
2213-
unsigned int len, skip;
2214-
unsigned int nents = 0;
2215-
unsigned long addr;
2216-
size_t data_size;
2217-
int i, j;
2218-
2219-
/*
2220-
* The first rqst has a transform header where the first 20 bytes are
2221-
* not part of the encrypted blob.
2222-
*/
2223-
skip = 20;
2224-
2225-
/* Assumes the first rqst has a transform header as the first iov.
2226-
* I.e.
2227-
* rqst[0].rq_iov[0] is transform header
2228-
* rqst[0].rq_iov[1+] data to be encrypted/decrypted
2229-
* rqst[1+].rq_iov[0+] data to be encrypted/decrypted
2230-
*/
2231-
for (i = 0; i < num_rqst; i++) {
2232-
data_size = iov_iter_count(&rqst[i].rq_iter);
2233-
2234-
/* We really don't want a mixture of pinned and unpinned pages
2235-
* in the sglist. It's hard to keep track of which is what.
2236-
* Instead, we convert to a BVEC-type iterator higher up.
2237-
*/
2238-
if (data_size &&
2239-
WARN_ON_ONCE(user_backed_iter(&rqst[i].rq_iter)))
2240-
return -EIO;
2241-
2242-
/* We also don't want to have any extra refs or pins to clean
2243-
* up in the sglist.
2244-
*/
2245-
if (data_size &&
2246-
WARN_ON_ONCE(iov_iter_extract_will_pin(&rqst[i].rq_iter)))
2247-
return -EIO;
2248-
2249-
for (j = 0; j < rqst[i].rq_nvec; j++) {
2250-
struct kvec *iov = &rqst[i].rq_iov[j];
2251-
2252-
addr = (unsigned long)iov->iov_base + skip;
2253-
if (is_vmalloc_or_module_addr((void *)addr)) {
2254-
len = iov->iov_len - skip;
2255-
nents += DIV_ROUND_UP(offset_in_page(addr) + len,
2256-
PAGE_SIZE);
2257-
} else {
2258-
nents++;
2259-
}
2260-
skip = 0;
2261-
}
2262-
if (data_size)
2263-
nents += iov_iter_npages(&rqst[i].rq_iter, INT_MAX);
2264-
}
2265-
nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE);
2266-
return nents;
2267-
}
2268-
2269-
/* We can not use the normal sg_set_buf() as we will sometimes pass a
2270-
* stack object as buf.
2271-
*/
2272-
static inline void cifs_sg_set_buf(struct sg_table *sgtable,
2273-
const void *buf,
2274-
unsigned int buflen)
2275-
{
2276-
unsigned long addr = (unsigned long)buf;
2277-
unsigned int off = offset_in_page(addr);
2278-
2279-
addr &= PAGE_MASK;
2280-
if (is_vmalloc_or_module_addr((void *)addr)) {
2281-
do {
2282-
unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off);
2283-
2284-
sg_set_page(&sgtable->sgl[sgtable->nents++],
2285-
vmalloc_to_page((void *)addr), len, off);
2286-
2287-
off = 0;
2288-
addr += PAGE_SIZE;
2289-
buflen -= len;
2290-
} while (buflen);
2291-
} else {
2292-
sg_set_page(&sgtable->sgl[sgtable->nents++],
2293-
virt_to_page((void *)addr), buflen, off);
2294-
}
2295-
}
2296-
22972209
#define CIFS_OPARMS(_cifs_sb, _tcon, _path, _da, _cd, _co, _mode) \
22982210
((struct cifs_open_parms) { \
22992211
.tcon = _tcon, \

fs/smb/client/cifsproto.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,4 +786,110 @@ static inline void cifs_free_open_info(struct cifs_open_info_data *data)
786786
memset(data, 0, sizeof(*data));
787787
}
788788

789+
static inline int smb_EIO(enum smb_eio_trace trace)
790+
{
791+
trace_smb3_eio(trace, 0, 0);
792+
return -EIO;
793+
}
794+
795+
static inline int smb_EIO1(enum smb_eio_trace trace, unsigned long info)
796+
{
797+
trace_smb3_eio(trace, info, 0);
798+
return -EIO;
799+
}
800+
801+
static inline int smb_EIO2(enum smb_eio_trace trace, unsigned long info, unsigned long info2)
802+
{
803+
trace_smb3_eio(trace, info, info2);
804+
return -EIO;
805+
}
806+
807+
static inline int cifs_get_num_sgs(const struct smb_rqst *rqst,
808+
int num_rqst,
809+
const u8 *sig)
810+
{
811+
unsigned int len, skip;
812+
unsigned int nents = 0;
813+
unsigned long addr;
814+
size_t data_size;
815+
int i, j;
816+
817+
/*
818+
* The first rqst has a transform header where the first 20 bytes are
819+
* not part of the encrypted blob.
820+
*/
821+
skip = 20;
822+
823+
/* Assumes the first rqst has a transform header as the first iov.
824+
* I.e.
825+
* rqst[0].rq_iov[0] is transform header
826+
* rqst[0].rq_iov[1+] data to be encrypted/decrypted
827+
* rqst[1+].rq_iov[0+] data to be encrypted/decrypted
828+
*/
829+
for (i = 0; i < num_rqst; i++) {
830+
data_size = iov_iter_count(&rqst[i].rq_iter);
831+
832+
/* We really don't want a mixture of pinned and unpinned pages
833+
* in the sglist. It's hard to keep track of which is what.
834+
* Instead, we convert to a BVEC-type iterator higher up.
835+
*/
836+
if (data_size &&
837+
WARN_ON_ONCE(user_backed_iter(&rqst[i].rq_iter)))
838+
return smb_EIO(smb_eio_trace_user_iter);
839+
840+
/* We also don't want to have any extra refs or pins to clean
841+
* up in the sglist.
842+
*/
843+
if (data_size &&
844+
WARN_ON_ONCE(iov_iter_extract_will_pin(&rqst[i].rq_iter)))
845+
return smb_EIO(smb_eio_trace_extract_will_pin);
846+
847+
for (j = 0; j < rqst[i].rq_nvec; j++) {
848+
struct kvec *iov = &rqst[i].rq_iov[j];
849+
850+
addr = (unsigned long)iov->iov_base + skip;
851+
if (is_vmalloc_or_module_addr((void *)addr)) {
852+
len = iov->iov_len - skip;
853+
nents += DIV_ROUND_UP(offset_in_page(addr) + len,
854+
PAGE_SIZE);
855+
} else {
856+
nents++;
857+
}
858+
skip = 0;
859+
}
860+
if (data_size)
861+
nents += iov_iter_npages(&rqst[i].rq_iter, INT_MAX);
862+
}
863+
nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE);
864+
return nents;
865+
}
866+
867+
/* We can not use the normal sg_set_buf() as we will sometimes pass a
868+
* stack object as buf.
869+
*/
870+
static inline void cifs_sg_set_buf(struct sg_table *sgtable,
871+
const void *buf,
872+
unsigned int buflen)
873+
{
874+
unsigned long addr = (unsigned long)buf;
875+
unsigned int off = offset_in_page(addr);
876+
877+
addr &= PAGE_MASK;
878+
if (is_vmalloc_or_module_addr((void *)addr)) {
879+
do {
880+
unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off);
881+
882+
sg_set_page(&sgtable->sgl[sgtable->nents++],
883+
vmalloc_to_page((void *)addr), len, off);
884+
885+
off = 0;
886+
addr += PAGE_SIZE;
887+
buflen -= len;
888+
} while (buflen);
889+
} else {
890+
sg_set_page(&sgtable->sgl[sgtable->nents++],
891+
virt_to_page((void *)addr), buflen, off);
892+
}
893+
}
894+
789895
#endif /* _CIFSPROTO_H */

0 commit comments

Comments
 (0)