Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CIFS/SMB Filesystem Client

Overview

CIFS (Common Internet File System) / SMB (Server Message Block) is the standard file-sharing protocol used by Windows, Samba, and modern NAS devices. The Linux kernel client (cifs.ko) allows mounting remote SMB shares as local filesystems, providing transparent read/write access to files on Windows servers, Samba shares, and cloud storage (Azure Files, AWS FSx).

The kernel CIFS module implements SMB2/SMB3 protocol support (the older CIFS dialect is deprecated). It handles authentication, encryption, opportunistic locks (oplocks), and persistent file handles.

Source: fs/cifs/
Module: cifs
Mount helper: mount.cifs (from cifs-utils package)


Architecture

flowchart TD
    subgraph UserSpace["Userspace"]
        APP["Application"]
        VFS["VFS Layer"]
    end

    subgraph Kernel["Kernel (fs/cifs/)"]
        CIFS["cifs.ko module"]
        SMB2["SMB2/3 protocol engine"]
        TRANSPORT["TCP transport"]
        CACHE["CIFS cache (fscache)"]
    end

    subgraph Network["Network"]
        TCP["TCP connection"]
    end

    subgraph Server["SMB Server"]
        WIN["Windows Server"]
        SAMBA["Samba"]
        AZURE["Azure Files"]
        NAS["NAS / Synology"]
    end

    APP --> VFS
    VFS --> CIFS
    CIFS --> SMB2
    SMB2 --> TRANSPORT
    TRANSPORT --> TCP
    TCP --> Server
    CIFS --> CACHE

SMB Protocol Versions

VersionDialectYearFeatures
SMB1NT11996Legacy, insecure, deprecated
SMB22.0.22006Improved performance, large reads/writes
SMB 2.12.12010Leasing, large MTU
SMB33.02012Encryption, multichannel, persistent handles
SMB 3.0.23.0.22014Performance improvements
SMB 3.1.13.1.12015AES-128-CCM encryption, pre-auth integrity

Protocol Negotiation

# Check which dialect is negotiated
cat /proc/fs/cifs/DebugData | grep -i dialect
# or
mount | grep cifs

Mounting SMB Shares

Basic Mount

# Mount with mount.cifs helper
mount -t cifs //server/share /mnt/share \
    -o username=user,password=pass

# Mount with domain
mount -t cifs //server/share /mnt/share \
    -o domain=WORKGROUP,username=user,password=pass

# Mount with credentials file
mount -t cifs //server/share /mnt/share \
    -o credentials=/etc/samba/creds

# /etc/samba/creds format:
# username=user
# password=pass
# domain=WORKGROUP

Mount Options

# Common mount options
mount -t cifs //server/share /mnt/share -o \
    vers=3.0,           # SMB version (2.0, 2.1, 3.0, 3.1.1)
    username=user,      # Username
    password=pass,      # Password (or credentials=file)
    domain=WORKGROUP,   # Domain/workgroup
    uid=1000,           # Local UID for files
    gid=1000,           # Local GID for files
    file_mode=0644,     # Default file permissions
    dir_mode=0755,      # Default directory permissions
    iocharset=utf8,     # Character encoding
    noperm,             # Don't check local permissions
    serverino,          # Use server inode numbers
    cache=strict,       # Caching mode
    mfsymlinks,         # Minshall+French symlinks
    seal,               # SMB3 encryption
    multiuser,          # Multiuser mount (Kerberos)
    sec=ntlmsspi        # Security type

SMB Version Selection

# Force SMB3 (recommended)
mount -t cifs //server/share /mnt -o vers=3.0

# Force SMB3.1.1 (most secure)
mount -t cifs //server/share /mnt -o vers=3.1.1

# Auto-negotiate (default)
mount -t cifs //server/share /mnt -o vers=default

# Legacy SMB1 (avoid)
mount -t cifs //server/share /mnt -o vers=1.0

Multiuser Mounts

# Mount with Kerberos (multiuser)
mount -t cifs //server/share /mnt/share \
    -o sec=krb5,multiuser,cruid=$UID

# Users authenticate individually via cifscreds
cifscreds add server
# Enter password for user@server

Authentication

Security Modes

ModeDescriptionUse Case
sec=noneNo authenticationGuest shares
sec=ntlmNTLM v1Legacy (avoid)
sec=ntlmv2NTLM v2Windows domains
sec=ntlmsspNTLMSSPDefault for Windows
sec=ntlmsspiNTLMSSP with signingSecure default
sec=krb5Kerberos v5Enterprise SSO
sec=krb5iKerberos with signingMost secure

Kerberos Authentication

# Get Kerberos ticket
kinit user@REALM.COM

# Mount with Kerberos
mount -t cifs //server/share /mnt \
    -o sec=krb5,multiuser,cruid=$(id -u)

# Verify ticket
klist

Performance Tuning

Read/Write Sizes

# Increase read/write sizes for better throughput
mount -t cifs //server/share /mnt \
    -o rsize=1048576,wsize=1048576
    # Max: 1MB for SMB3, 128KB for SMB2

# Check current values
cat /proc/fs/cifs/DebugData | grep -i "rsize\|wsize"

Caching

# Cache modes
mount -t cifs //server/share /mnt -o cache=strict
# strict    — Default. Caches aggressively, oplock-based
# none      — No caching (always read from server)
# looserelaxed — Loose caching (less server validation)
# single    — Single client caching

# Fscache integration (cache to local disk)
# Requires CONFIG_CIFS_FSCACHE=y
mount -t cifs //server/share /mnt -o fsc

Multichannel (SMB3)

# Enable multichannel (multiple TCP connections)
mount -t cifs //server/share /mnt -o multichannel

# Check active channels
cat /proc/fs/cifs/DebugData | grep -i channel

Direct I/O

# Use direct I/O (bypass page cache)
mount -t cifs //server/share /mnt -o directio

# Force strict cache (default, recommended)
mount -t cifs //server/share /mnt -o cache=strict

Encryption

SMB3 Encryption

# Enable encryption (SMB3+)
mount -t cifs //server/share /mnt -o seal

# Check if encryption is active
cat /proc/fs/cifs/DebugData | grep -i encrypt

Encryption Algorithms

SMB VersionAlgorithmKey Size
SMB 3.0AES-128-CCM128-bit
SMB 3.0.2AES-128-CCM128-bit
SMB 3.1.1AES-128-GCM128-bit (preferred)

/proc and /sys Interfaces

/proc/fs/cifs/

# Debug data
cat /proc/fs/cifs/DebugData
# Shows: active connections, shares, SMB dialects, stats

# Statistics
cat /proc/fs/cifs/Stats
# Shows: operations count, bytes read/written, errors

# Security flags
cat /proc/fs/cifs/security_flags

# Lookup cache timeout
cat /proc/fs/cifs/lookupCacheEnabled
echo 1 > /proc/fs/cifs/lookupCacheEnabled  # Enable

Per-Mount Stats

# Mount-specific statistics
cat /proc/mounts | grep cifs
# Shows mount options and server info

# SMB session info
cat /proc/fs/cifs/DebugData | head -30

SMB3 Features

Persistent File Handles

SMB3 persistent handles survive server failover (clustered environments):

# Enable persistent handles
mount -t cifs //server/share /mnt -o persistenthandles

Leases (Oplocks)

SMB3 leases provide caching guarantees:

# Enable leases (default)
mount -t cifs //server/share /mnt -o nobrl
# Leases are enabled by default with cache=strict

Directory Leases

# Directory caching (SMB3.1.1+)
mount -t cifs //server/share /mnt -o nodfs

SMB doesn’t natively support Unix symlinks. The mfsymlinks option creates special files that appear as symlinks:

# Enable MF symlinks
mount -t cifs //server/share /mnt -o mfsymlinks

# MF symlinks are small files with special content:
# !<symlink>\xff\xfe + UTF-16LE target path

Troubleshooting

Connection Issues

# Test SMB connectivity
smbclient -L //server -U user

# Check SMB port (445)
nc -zv server 445

# Check DNS resolution
nslookup server

# Force specific SMB version
mount -t cifs //server/share /mnt -o vers=3.0

# Check dmesg for CIFS errors
dmesg | grep -i cifs

Authentication Failures

# Check credentials
smbclient //server/share -U user

# Try different security modes
mount -t cifs //server/share /mnt -o sec=ntlmssp,username=user

# Check Kerberos ticket
klist
kinit user@REALM

# Verify password
ntlm_auth --username=user --password=pass

Performance Issues

# Check current mount options
mount | grep cifs

# Test with larger read/write sizes
mount -t cifs //server/share /mnt -o rsize=1048576,wsize=1048576

# Benchmark throughput
dd if=/mnt/share/testfile of=/dev/null bs=1M count=1000

# Check network latency
ping server

Permission Issues

# Check server-side permissions
smbclient //server/share -U user -c "ls"

# Mount with specific UID/GID
mount -t cifs //server/share /mnt -o uid=1000,gid=1000

# Force file/directory modes
mount -t cifs //server/share /mnt -o file_mode=0666,dir_mode=0777

# Disable local permission checks
mount -t cifs //server/share /mnt -o noperm

KSMBD: In-Kernel SMB Server

ksmbd is an in-kernel SMB3 server (alternative to Samba):

# Load ksmbd module
modprobe ksmbd

# Configure /etc/ksmbd/ksmbd.conf
# [global]
#     workgroup = WORKGROUP
#
# [share]
#     path = /data
#     read only = no

# Start ksmbd
ksmbd.mountd

# From client:
# mount -t cifs //server/share /mnt -o username=user

ksmbd vs Samba

AspectksmbdSamba
ImplementationIn-kernelUserspace
PerformanceHigher (no context switches)Lower
FeaturesSMB3 focusedFull SMB/CIFS/AD
MaturityNewer (since 5.15)Decades old
ConfigurationMinimalFull-featured

On-Disk / Wire Protocol Structures

SMB2 Header

Every SMB2/SMB3 packet starts with a 64-byte header:

/* MS-SMB2 2.2.1 */
struct smb2_hdr {
    __le32 ProtocolId;       /* 0xFE534D42 ("\xfeSMB") */
    __le16 StructureSize;    /* Must be 64 */
    __le16 CreditCharge;     /* Credits consumed */
    __le32 Status;           /* NT status (response) */
    __le16 Command;          /* SMB2 command code */
    __le16 CreditRequest;    /* Credits requested (response) */
    __le32 Flags;            /* SMB2_FLAGS_* */
    __le32 NextCommand;      /* Offset to next in compound */
    __le64 MessageId;        /* Sequence number */
    __le32 Reserved;
    __le32 TreeId;           /* Tree connect ID */
    __le64 SessionId;        /* Session identifier */
    __u8   Signature[16];    /* HMAC-SHA256 signature */
};

Key SMB2 Commands

CommandCodePurpose
NEGOTIATE0x0000Protocol negotiation
SESSION_SETUP0x0001Authentication
LOGOFF0x0002Session teardown
TREE_CONNECT0x0003Share connection
TREE_DISCONNECT0x0004Share disconnect
CREATE0x0005Open/create files
CLOSE0x0006Close file handle
READ0x0008Read data
WRITE0x0009Write data
QUERY_DIRECTORY0x000EList directory
CHANGE_NOTIFY0x000FDirectory change monitoring
QUERY_INFO0x0010File/system info
SET_INFO0x0011Set file info
IOCTL0x0011FSCTL operations
OPLOCK_BREAK0x0024Lease/oplock break notification

NT Status Codes

The CIFS client maps NT status codes to Linux errno values:

/* fs/cifs/netmisc.c - simplified */
static const struct { int ntstatus; int errno_val; } nt_to_unix[] = {
    { 0x00000000, 0 },           /* STATUS_SUCCESS */
    { 0xC000000D, -EINVAL },     /* STATUS_INVALID_PARAMETER */
    { 0xC000000F, -ENOENT },     /* STATUS_NO_SUCH_FILE */
    { 0xC0000022, -EACCES },     /* STATUS_ACCESS_DENIED */
    { 0xC0000034, -ENOENT },     /* STATUS_OBJECT_NAME_NOT_FOUND */
    { 0xC0000043, -EACCES },     /* STATUS_LOCK_NOT_GRANTED */
    { 0x80000005, -EIO },        /* STATUS_BUFFER_OVERFLOW */
    { 0xC000006D, -ECONNABORTED },/* STATUS_CONNECTION_ABORTED */
    { 0xC0000120, -ECANCELED },  /* STATUS_CANCELLED */
};

Credit-Based Flow Control

SMB2/SMB3 uses a credit-based flow control mechanism to prevent clients from overwhelming the server:

sequenceDiagram
    participant Client
    participant Server

    Client->>Server: NEGOTIATE (CreditRequest=31)
    Server-->>Client: NEGOTIATE Response (CreditResponse=31)
    Note over Client,Server: Client has 31 credits

    Client->>Server: CREATE (CreditCharge=1, MessageId=1)
    Server-->>Client: CREATE Response (CreditResponse=1)
    Note over Client: Credits: 31-1+1=31

    Client->>Server: READ (CreditCharge=1, MessageId=2)
    Client->>Server: WRITE (CreditCharge=1, MessageId=3)
    Note over Client: Two requests in flight (multi-credit)
    Server-->>Client: READ Response (CreditResponse=0)
    Server-->>Client: WRITE Response (CreditResponse=0)
    Note over Client: Credits: 31-2=29
  • CreditCharge: Number of credits consumed per request (large I/O uses more)
  • CreditRequest/CreditResponse: Grants additional credits
  • Maximum credits: Typically 512-8192 depending on server
  • Multi-credit operations: Large reads/writes consume multiple credits
/* fs/cifs/smb2pdu.c - credit tracking */
struct cifs_credits {
    unsigned int total_credits;     /* Total available */
    unsigned int in_flight;         /* Currently in-flight */
    spinlock_t lock;
};

SMB3 Compounding

SMB3 allows compounding multiple operations into a single network request, reducing round trips:

sequenceDiagram
    participant Client
    participant Server

    Note over Client: Traditional: 3 round trips
    Client->>Server: CREATE file
    Server-->>Client: File handle
    Client->>Server: WRITE data
    Server-->>Client: Write result
    Client->>Server: CLOSE file
    Server-->>Client: Close result

    Note over Client: Compounded: 1 round trip
    Client->>Server: CREATE + WRITE + CLOSE (compounded)
    Server-->>Client: All results in single response
# The kernel CIFS client uses compounding for:
# - Query directory + file info lookups
# - Open + read sequences
# - Write + close sequences

# Compounding is automatic; no mount option needed
# Internally uses NextCommand field in SMB2 header

Compound Request Structure

/* Compounded requests chain via NextCommand offset */
struct smb2_compound_hdr {
    struct smb2_hdr hdr1;        /* First request */
    /* hdr1.NextCommand = offset to hdr2 */
    struct smb2_hdr hdr2;        /* Second request */
    /* hdr2.NextCommand = 0 (last in chain) */
    /* Per-request data follows each header */
};

DFS (Distributed File System) Referrals

The CIFS client supports DFS (Distributed File System), which allows shares to span multiple servers:

flowchart TD
    A["Client requests \\\\domain\\share\\path"] --> B["DFS server returns referral"]
    B --> C["Referral: \\\\server1\\share1\\subpath"]
    B --> D["Referral: \\\\server2\\share2\\backup"]
    C --> E["Client connects to server1"]
    D --> F["Client connects to server2"]
# DFS is automatic when connecting to domain-based shares
# mount -t cifs //domain.com/share /mnt \
#     -o username=user,domain=EXAMPLE

# The client sends FSCTL_DFS_GET_REFERRALS to the server
# and follows referrals transparently

# Check DFS referral info
cat /proc/fs/cifs/DebugData | grep -i dfs

DFS Referral Types

TypeDescription
Type 1Single target (simple redirection)
Type 2Multiple targets with priority
Type 3DFS root with subfolder targets
Type 4DFS root with multiple root targets

Directory Leasing (SMB 3.1.1)

Directory leases allow clients to cache directory listings without re-querying the server:

# Directory leases are enabled by default with SMB 3.1.1
# The client caches directory entries for the lease duration

# Disable directory caching
mount -t cifs //server/share /mnt -o nodfs

# Lease break: server notifies client when directory changes
# Client invalidates cached listing and re-reads
/* fs/cifs/smb2ops.c - lease handling */
struct cifs_lease {
    u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* 16 bytes */
    unsigned int epoch;
    unsigned int state;
    /* Lease states: SMB2_LEASE_NONE, READ, HANDLE, WRITE */
};

Lease State Transitions

stateDiagram-v2
    [*] --> NoLease: Initial open
    NoLease --> ReadLease: Server grants R lease
    ReadLease --> NoLease: Server breaks lease
    ReadLease --> ReadHandle: Server upgrades
    ReadHandle --> NoLease: Server breaks lease
    ReadHandle --> ReadWrite: Server upgrades
    ReadWrite --> NoLease: Server breaks lease

Change Notify

SMB2/3 supports directory change notifications, allowing clients to be alerted when files change:

# The kernel CIFS client supports inotify/dnotify
# through SMB2 CHANGE_NOTIFY requests

# Watch a directory (uses inotify under the hood)
inotifywait -m /mnt/smbshare/

# The kernel sends SMB2_CHANGE_NOTIFY to the server
# Server responds when directory contents change
/* fs/cifs/smb2ops.c - change notify */
int smb2_notify(const unsigned int xid, struct cifs_tcon *tcon,
                struct cifs_fid *fid, u32 completion_filter, bool watch_tree)
{
    /* Sends SMB2 CHANGE_NOTIFY request */
    /* completion_filter: FILE_NOTIFY_CHANGE_* flags */
    /* Server responds asynchronously when changes occur */
}

Key Kernel Data Structures

struct cifs_ses (SMB Session)

/* fs/cifs/cifsglob.h */
struct cifs_ses {
    struct list_head list;           /* Global session list */
    struct cifs_tcon *tcon_ipc;      /* IPC$ connection */
    char *server_name;               /* Server hostname */
    char *user_name;                 /* Username */
    char *domainName;                /* Domain name */
    __u16 Suid;                      /* Session ID */
    unsigned int status;             /* Session state */
    unsigned capabilities;           /* Server capabilities */
    struct session_key auth_key;     /* Authentication key */
    __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* Signing key */
    __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; /* Encryption key */
    struct nls_table *local_nls;     /* Character encoding */
};

struct cifs_tcon (Tree Connect / Share)

/* fs/cifs/cifsglob.h */
struct cifs_tcon {
    struct list_head list;           /* Session share list */
    struct cifs_ses *ses;            /* Parent session */
    char treeName[MAX_TREE_SIZE + 1];/* Share name */
    char *nativeFileSystem;          /* Server FS type */
    __u32 tid;                       /* Tree ID */
    unsigned share_flags;            /* Share flags */
    unsigned share_capabilities;     /* Share capabilities */
    unsigned maximal_access;         /* Max granted access */
    struct cifs_fid crfid;           /* Cached root fid */
    bool print:1;                    /* Printer share */
    bool pipe:1;                     /* Named pipe */
    bool ipc:1;                      /* IPC$ share */
    bool seal:1;                     /* Encryption enabled */
    bool unix_ext:1;                 /* POSIX extensions */
};

struct cifsFileInfo (Open File)

/* fs/cifs/cifsglob.h */
struct cifsFileInfo {
    struct list_head list;           /* Open file list */
    struct cifs_tcon *tcon;          /* Share */
    __u32 pid;                       /* Process ID */
    __u16 fid;                       /* File ID (v1) */
    struct cifs_fid cfid;            /* Cached fid (SMB2+) */
    unsigned int f_flags;            /* Open flags */
    struct dentry *dentry;           /* Directory entry */
    struct cifs_search_info srch_inf; /* Search state */
    bool invalidHandle:1;            /* Handle needs reconnect */
    bool oplock_break_cancelled:1;   /* Oplock break pending */
};

Persistent File Handles (SMB3)

Persistent handles survive server restarts and cluster failover:

sequenceDiagram
    participant Client
    participant NodeA as Server Node A
    participant NodeB as Server Node B

    Client->>NodeA: CREATE (persistent handle)
    NodeA-->>Client: Handle granted (persistent)
    Client->>NodeA: READ/WRITE (normal I/O)
    Note over NodeA: Node A fails
    NodeA--xClient: Connection lost
    Client->>NodeB: Reconnect + reclaim handle
    NodeB-->>Client: Handle restored
    Client->>NodeB: READ/WRITE (continues)
# Enable persistent handles (SMB3+ only)
mount -t cifs //server/share /mnt -o persistenthandles

# Requires server support (Windows Scale-Out File Server)
# On failure: client reconnects and reclaims handles
# No data loss or application-visible errors

Connection Multiplexing

The kernel CIFS client supports multiple TCP connections per session for higher throughput:

# SMB3 multichannel
mount -t cifs //server/share /mnt -o multichannel

# The client creates multiple TCP connections
# across different network paths (NICs)
# File I/O is striped across channels

# Check channels
cat /proc/fs/cifs/DebugData | grep -i channel

Multichannel Architecture

flowchart LR
    subgraph Client["CIFS Client"]
        C1["Channel 1<br>NIC1 -> Server NIC1"]
        C2["Channel 2<br>NIC2 -> Server NIC2"]
    end
    subgraph Server["SMB Server"]
        S1["NIC1"]
        S2["NIC2"]
    end
    C1 --> S1
    C2 --> S2

POSIX Extensions

The CIFS client supports Samba’s POSIX extensions for Unix-specific features:

# Enable POSIX extensions
mount -t cifs //server/share /mnt -o posix

# With POSIX extensions:
# - Hard links work
# - Symlinks work natively (not MF symlinks)
# - Unix permissions are preserved
# - Special files (FIFOs, sockets) work

# Requires Samba server with 'unix extensions = yes'

POSIX vs Windows Behavior

FeatureWithout POSIXWith POSIX
SymlinksMF symlinks (files)Native symlinks
Hard linksNot supportedSupported
PermissionsMapped to ACLsUnix mode bits
Special filesNot supportedFIFOs, sockets
File lockingWindows locksPOSIX locks

Connection Recovery

The CIFS client handles server disconnections and automatically reconnects:

/* fs/cifs/connect.c - reconnect logic */
int cifs_reconnect(struct cifs_tcon *tcon)
{
    /* 1. Mark all open files as invalid */
    /* 2. Drop existing TCP connection */
    /* 3. Re-establish TCP */
    /* 4. Re-authenticate (SESSION_SETUP) */
    /* 5. Reconnect tree connects */
    /* 6. Re-open files on next access */
}
# Reconnect timeout and retry configuration
mount -t cifs //server/share /mnt \
    -o echo_interval=30,  # Echo keepalive interval (seconds)
    max_credits=512        # Maximum credits

# Monitor connection status
cat /proc/fs/cifs/DebugData | head -20

Source Files

FileContents
fs/cifs/cifsfs.cCIFS VFS integration, mount
fs/cifs/smb2ops.cSMB2/3 protocol operations
fs/cifs/smb2pdu.cSMB2/3 protocol data units
fs/cifs/connect.cConnection management
fs/cifs/transport.cTCP transport layer
fs/cifs/cifssmb.cSMB1 protocol (legacy)
fs/cifs/cache.cFscache integration
fs/cifs/inode.cInode operations
fs/cifs/file.cFile operations
fs/ksmbd/In-kernel SMB server

Further Reading


See Also

  • Filesystems Overview — Linux filesystem landscape
  • Network Namespaces — network namespace SMB mounts
  • NFS — another network filesystem
  • VFS — virtual filesystem layer