[PATCH v2 52/53] CIFS: Add statfs support for SMB2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
---
 fs/cifs/cifsfs.c    |   52 +++++++++++++++++++++++++++++++-------------------
 fs/cifs/smb2glob.h  |    2 +
 fs/cifs/smb2pdu.c   |   18 +++++++++++++++++
 fs/cifs/smb2proto.h |    2 +
 4 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 3683384..844ea94 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -169,31 +169,14 @@ static void cifs_kill_sb(struct super_block *sb)
 	cifs_umount(cifs_sb);
 }
 
-static int
-cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
+static void
+cifs_queryfs(int xid, struct cifs_tcon *tcon, struct kstatfs *buf)
 {
-	struct super_block *sb = dentry->d_sb;
-	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
 	int rc = -EOPNOTSUPP;
-	int xid;
-
-	xid = GetXid();
 
 	buf->f_type = CIFS_MAGIC_NUMBER;
 
 	/*
-	 * PATH_MAX may be too long - it would presumably be total path,
-	 * but note that some servers (includinng Samba 3) have a shorter
-	 * maximum path.
-	 *
-	 * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO.
-	 */
-	buf->f_namelen = PATH_MAX;
-	buf->f_files = 0;	/* undefined */
-	buf->f_ffree = 0;	/* unlimited */
-
-	/*
 	 * We could add a second check for a QFS Unix capability bit
 	 */
 	if ((tcon->ses->capabilities & CAP_UNIX) &&
@@ -214,8 +197,37 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	 */
 	if (rc)
 		rc = SMBOldQFSInfo(xid, tcon, buf);
+}
+
+static int
+cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+	struct super_block *sb = dentry->d_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+	int xid;
+
+	xid = GetXid();
+
+	/*
+	 * PATH_MAX may be too long - it would presumably be total path,
+	 * but note that some servers (includinng Samba 3) have a shorter
+	 * maximum path.
+	 *
+	 * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO.
+	 */
+	buf->f_namelen = PATH_MAX;
+	buf->f_files = 0;	/* undefined */
+	buf->f_ffree = 0;	/* unlimited */
+
+#ifdef CONFIG_CIFS_SMB2
+	if (tcon->ses->server->is_smb2)
+		smb2_open_queryfs_close(xid, tcon, buf);
+	else
+#endif
+		cifs_queryfs(xid, tcon, buf);
 
-	FreeXid(xid);
+	_FreeXid(xid);
 	return 0;
 }
 
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
index 9e42f71..49634d4 100644
--- a/fs/cifs/smb2glob.h
+++ b/fs/cifs/smb2glob.h
@@ -25,6 +25,8 @@
 #include <linux/workqueue.h>
 #include "smb2pdu.h"
 
+#define SMB2_MAGIC_NUMBER 0xFE534D42
+
 /*
  * The sizes of various internal tables and strings
  */
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 4ce496a..dc73968 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1921,6 +1921,24 @@ qfsdev_exit:
 	return rc;
 }
 
+void
+smb2_open_queryfs_close(int xid, struct cifs_tcon *tcon, struct kstatfs *buf)
+{
+	int rc;
+	u64 persist_fid, volatile_fid;
+	__le16 srch_path = 0; /* Null - open root of share */
+	u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+
+	rc = SMB2_open(xid, tcon, &srch_path, &persist_fid, &volatile_fid,
+			FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock);
+	if (!rc) {
+		buf->f_type = SMB2_MAGIC_NUMBER;
+		SMB2_QFS_info(xid, tcon, persist_fid, volatile_fid,
+					  buf);
+		SMB2_close(xid, tcon, persist_fid, volatile_fid);
+	}
+}
+
 int SMB2_query_info(const int xid, struct cifs_tcon *tcon,
 		    u64 persistent_fid, u64 volatile_fid,
 		    FILE_ALL_INFO_SMB2 *pdata)
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 0425700..aa894cc 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -111,6 +111,8 @@ extern int smb2_open_op_close(int xid, struct cifs_tcon *tcon, __le16 *path,
 			      __u32 desired_access, __u32 create_disposition,
 			      __u32 file_attributes, __u32 create_options,
 			      void *data, int command);
+extern void smb2_open_queryfs_close(int xid, struct cifs_tcon *tcon,
+				    struct kstatfs *buf);
 extern void smb2_set_ops(struct inode *inode);
 extern bool smb2_is_size_safe_to_change(struct smb2_inode *smb2_ind,
 					__u64 end_of_file);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux