summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsfs.c11
-rw-r--r--fs/cifs/cifspdu.h16
-rw-r--r--fs/cifs/cifssmb.c14
3 files changed, 33 insertions, 8 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 850738ed1eaf..dec4d9149d35 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -170,7 +170,7 @@ cifs_put_super(struct super_block *sb)
static int
cifs_statfs(struct super_block *sb, struct kstatfs *buf)
{
- int xid, rc;
+ int xid, rc = 0;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
@@ -189,6 +189,15 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf)
buf->f_files = 0; /* undefined */
buf->f_ffree = 0; /* unlimited */
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+/* BB we could add a second check for a QFS Unix capability bit */
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf, cifs_sb->local_nls);
+
+ /* Only need to call the old QFSInfo if failed
+ on newer one */
+ if(rc)
+#endif /* CIFS_EXPERIMENTAL */
rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
/*
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index d176d966047c..c5b7a560902e 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1509,12 +1509,20 @@ typedef struct {
#define CIFS_UNIX_XATTR_CAP 0x00000004 /*support for new namespace*/
typedef struct {
- /* For undefined values return -1 in that field */
+ /* For undefined recommended transfer size return -1 in that field */
__le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
__le32 BlockSize;
- __le64 TotalBlocks; /* redundant but easy to return */
- __le64 BlocksAvail; /* redundant but easy to return */
- __le64 UserBlocksAvail; /* bavail */
+ /* The next three fields are in terms of the block size.
+ (above). If block size is unknown, 4096 would be a
+ reasonable block size for a server to report.
+ Note that returning the blocks/blocksavail removes need
+ to make a second call (to QFSInfo level 0x103 to get this info.
+ UserBlockAvail is typically less than or equal to BlocksAvail,
+ if no distinction is made return the same value in each */
+ __le64 TotalBlocks;
+ __le64 BlocksAvail; /* bfree */
+ __le64 UserBlocksAvail; /* bavail */
+ /* For undefined Node fields or FSID return -1 */
__le64 TotalFileNodes;
__le64 FreeFileNodes;
__le64 FileSysIdentifier; /* fsid */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c47ad1a96587..8a06dba05abb 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -3159,15 +3159,23 @@ QFSPosixRetry:
(FILE_SYSTEM_POSIX_INFO
*) (((char *) &pSMBr->hdr.Protocol) +
data_offset);
+ FSData->f_bsize =
+ le32_to_cpu(response_data->BlockSize);
FSData->f_blocks =
le64_to_cpu(response_data->TotalBlocks);
FSData->f_bfree =
le64_to_cpu(response_data->BlocksAvail);
- FSData->f_bavail =
+ if(response_data->UserBlocksAvail == -1) {
+ FSData->f_bavail = FSData->f_bfree;
+ } else {
+ FSData->f_bavail =
le64_to_cpu(response_data->UserBlocksAvail);
- FSData->f_files =
+ }
+ if(response_data->TotalFileNodes != -1)
+ FSData->f_files =
le64_to_cpu(response_data->TotalFileNodes);
- FSData->f_ffree =
+ if(response_data->FreeFileNodes != -1)
+ FSData->f_ffree =
le64_to_cpu(response_data->FreeFileNodes);
}
}