In order to get the unique id for the volume (the 8 byte VolumeSerialNumber) we need to issue a QUERY_INFO level 59 (FILE_ID_INFORMATION). Today we only query the older 4 byte (not guaranteed to be unique serial number). See section 2.4.21 of MS-FSCC. Looks like Samba and ksmbd do not support this info level though - although Windows does support it. Any thoughts on ksmbd or Samba support for FILE_ID_INFORMATION query? See attached work in progress patch -- Thanks, Steve
From a5f90b46b17d20af4cdbfae6ac43dabc1e58e87e Mon Sep 17 00:00:00 2001 From: Steve French <stfrench@xxxxxxxxxxxxx> Date: Fri, 29 Mar 2024 00:30:49 -0500 Subject: [PATCH] smb3: update sb uuid when full id information available Some servers like Windows and Azure report the larger (16 byte) unique volume serial number. For those that return full_id_information populate the sb->s_uuid This will also allow the new ioctl FS_IOC_GETFSUUID to work Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- fs/smb/client/cifsfs.c | 2 ++ fs/smb/client/cifsglob.h | 1 + fs/smb/client/smb2ops.c | 2 ++ fs/smb/client/smb2pdu.c | 18 ++++++++++++++++++ fs/smb/client/smb2proto.h | 2 ++ 5 files changed, 25 insertions(+) diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index aa6f1ecb7c0e..c6445f93d954 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -269,6 +269,8 @@ cifs_read_super(struct super_block *sb) goto out_no_root; } + if (tcon->vol_uuid != 0) + super_set_uuid(sb, (void *)&tcon->vol_uuid, sizeof(tcon->vol_uuid)); #ifdef CONFIG_CIFS_NFSD_EXPORT if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { cifs_dbg(FYI, "export ops supported\n"); diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 7ed9d05f6890..dae11166eb6f 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1264,6 +1264,7 @@ struct cifs_tcon { __u32 share_flags; __u32 maximal_access; __u32 vol_serial_number; + __u64 vol_uuid; /* full (64 bit, unique) serial number */ __le64 vol_create_time; __u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */ __u32 handle_timeout; /* persistent and durable handle timeout in ms */ diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 2ed456948f34..84d2f3f1c89a 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -831,6 +831,8 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon, if (rc) return; + SMB2_get_vol_serial_num(xid, tcon, fid.persistent_fid, fid.volatile_fid); + SMB3_request_interfaces(xid, tcon, true /* called during mount */); SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 3ea688558e6c..f262b8251b2e 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -3908,6 +3908,24 @@ SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon, SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen); } +int +SMB2_get_vol_serial_num(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid) +{ + int rc; + struct smb2_file_id_information vol_info; + + rc = query_info(xid, tcon, persistent_fid, volatile_fid, + FILE_ID_INFORMATION, SMB2_O_INFO_FILE, 0, + sizeof(struct smb2_file_id_information), + sizeof(struct smb2_file_id_information), + (void **)&vol_info, NULL); + if (!rc) + tcon->vol_uuid = le64_to_cpu(vol_info.VolumeSerialNumber); + + return rc; +} + int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, __le64 *uniqueid) diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h index 732169d8a67a..b518f1fdedcf 100644 --- a/fs/smb/client/smb2proto.h +++ b/fs/smb/client/smb2proto.h @@ -207,6 +207,8 @@ extern void SMB2_query_info_free(struct smb_rqst *rqst); extern int SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id, void **data, unsigned int *plen, u32 info); +extern int SMB2_get_vol_serial_num(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid); extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, __le64 *uniqueid); -- 2.40.1