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 | |
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
-rw-r--r-- | sys/fs/smbfs/smbfs_smb.c | 63 | ||||
-rw-r--r-- | sys/fs/smbfs/smbfs_subr.h | 2 | ||||
-rw-r--r-- | sys/fs/smbfs/smbfs_vfsops.c | 17 |
3 files changed, 64 insertions, 18 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) { diff --git a/sys/fs/smbfs/smbfs_subr.h b/sys/fs/smbfs/smbfs_subr.h index 0900f09..d22df08 100644 --- a/sys/fs/smbfs/smbfs_subr.h +++ b/sys/fs/smbfs/smbfs_subr.h @@ -126,8 +126,6 @@ struct smbfs_fctx { */ int smbfs_smb_lock(struct smbnode *np, int op, caddr_t id, off_t start, off_t end, struct smb_cred *scred); -int smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp, - struct smb_cred *scred); int smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp, struct smb_cred *scred); int smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred); diff --git a/sys/fs/smbfs/smbfs_vfsops.c b/sys/fs/smbfs/smbfs_vfsops.c index 2d33df3..8277982 100644 --- a/sys/fs/smbfs/smbfs_vfsops.c +++ b/sys/fs/smbfs/smbfs_vfsops.c @@ -390,7 +390,7 @@ smbfs_statfs(struct mount *mp, struct statfs *sbp) struct smbnode *np = smp->sm_root; struct smb_share *ssp = smp->sm_share; struct smb_cred *scred; - int error = 0; + int error; if (np == NULL) { vfs_mount_error(mp, "np == NULL"); @@ -400,16 +400,9 @@ smbfs_statfs(struct mount *mp, struct statfs *sbp) sbp->f_iosize = SSTOVC(ssp)->vc_txmax; /* optimal transfer block size */ scred = smbfs_malloc_scred(); smb_makescred(scred, td, td->td_ucred); - - if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) - error = smbfs_smb_statfs2(ssp, sbp, scred); - else - error = smbfs_smb_statfs(ssp, sbp, scred); - if (error) { - smbfs_free_scred(scred); - return error; - } - sbp->f_flags = 0; /* copy of mount exported flags */ + error = smbfs_smb_statfs(ssp, sbp, scred); + if (error == 0) + sbp->f_flags = 0; /* copy of mount exported flags */ smbfs_free_scred(scred); - return 0; + return (error); } |