diff options
author | ae <ae@FreeBSD.org> | 2014-04-15 09:10:01 +0000 |
---|---|---|
committer | ae <ae@FreeBSD.org> | 2014-04-15 09:10:01 +0000 |
commit | b95b3ecef4cb3f615612c9cd3dd758cdb532391b (patch) | |
tree | ada0964cc24f63d420ec93ef2dbf4690c3fe4a91 /sys/fs/smbfs/smbfs_smb.c | |
parent | d8b63f3ba114f723e55129a2d5ce79fea9e568a6 (diff) | |
download | FreeBSD-src-b95b3ecef4cb3f615612c9cd3dd758cdb532391b.zip FreeBSD-src-b95b3ecef4cb3f615612c9cd3dd758cdb532391b.tar.gz |
Use SMB_QUERY_FS_SIZE_INFO request to populate statfs structure.
When server doesn't support this request, try to use SMB_INFO_ALLOCATION.
And use SMB_COM_QUERY_INFORMATION_DISK request as fallback.
MFC after: 2 weeks
Diffstat (limited to 'sys/fs/smbfs/smbfs_smb.c')
-rw-r--r-- | sys/fs/smbfs/smbfs_smb.c | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/sys/fs/smbfs/smbfs_smb.c b/sys/fs/smbfs/smbfs_smb.c index 0e10e5e..ada84c2 100644 --- a/sys/fs/smbfs/smbfs_smb.c +++ b/sys/fs/smbfs/smbfs_smb.c @@ -135,8 +135,49 @@ smbfs_smb_lock(struct smbnode *np, int op, caddr_t id, return smbfs_smb_lockandx(np, op, (uintptr_t)id, start, end, scred); } -int -smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp, +static int +smbfs_query_info_fs(struct smb_share *ssp, struct statfs *sbp, + struct smb_cred *scred) +{ + struct smb_t2rq *t2p; + struct mbchain *mbp; + struct mdchain *mdp; + uint32_t bsize, bpu; + int64_t units, funits; + int error; + + error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, + scred, &t2p); + if (error) + return (error); + mbp = &t2p->t2_tparam; + mb_init(mbp); + mb_put_uint16le(mbp, SMB_QUERY_FS_SIZE_INFO); + t2p->t2_maxpcount = 2; + t2p->t2_maxdcount = sizeof(int64_t) * 2 + sizeof(uint32_t) * 2; + error = smb_t2_request(t2p); + if (error) { + smb_t2_done(t2p); + return (error); + } + mdp = &t2p->t2_rdata; + md_get_int64le(mdp, &units); + md_get_int64le(mdp, &funits); + md_get_uint32le(mdp, &bpu); + md_get_uint32le(mdp, &bsize); + sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ + sbp->f_blocks= (uint64_t)units; /* total data blocks in filesystem */ + sbp->f_bfree = (uint64_t)funits;/* free blocks in fs */ + sbp->f_bavail= (uint64_t)funits;/* free blocks avail to non-superuser */ + sbp->f_files = 0xffff; /* total file nodes in filesystem */ + sbp->f_ffree = 0xffff; /* free file nodes in fs */ + smb_t2_done(t2p); + return (0); +} + + +static int +smbfs_query_info_alloc(struct smb_share *ssp, struct statfs *sbp, struct smb_cred *scred) { struct smb_t2rq *t2p; @@ -176,8 +217,8 @@ smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp, return 0; } -int -smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp, +static int +smbfs_query_info_disk(struct smb_share *ssp, struct statfs *sbp, struct smb_cred *scred) { struct smb_rq *rqp; @@ -213,6 +254,20 @@ smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp, return 0; } +int +smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp, + struct smb_cred *scred) +{ + + if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) { + if (smbfs_query_info_fs(ssp, sbp, scred) == 0) + return (0); + if (smbfs_query_info_alloc(ssp, sbp, scred) == 0) + return (0); + } + return (smbfs_query_info_disk(ssp, sbp, scred)); +} + static int smbfs_smb_seteof(struct smbnode *np, int64_t newsize, struct smb_cred *scred) { |