]> git.ipfire.org Git - thirdparty/kernel/linux.git/commit
cifs: Label SMB2 statuses with errors
authorDavid Howells <dhowells@redhat.com>
Tue, 23 Dec 2025 00:04:01 +0000 (00:04 +0000)
committerSteve French <stfrench@microsoft.com>
Sun, 8 Feb 2026 23:07:46 +0000 (17:07 -0600)
commit10dfb0738a9d383575614b5d4389953cb97e1841
tree829a10829c3f0d98142914cc16189d028be571de
parentc9ce93ef27a1f4dd403d5222365f3cfe1c55c03a
cifs: Label SMB2 statuses with errors

Label the SMB2 status entries with error codes as a prelude to
autogenerating the mapping table.  This was done with the following script:

        #!/usr/bin/perl -w
        use strict;

        my @error_mapping_table = ();
        my %statuses = ();

        #
        # Read the status list
        #
        my $f = "fs/smb/common/smb2status.h";
        open FILE, "<$f" || die $f;
        my @contents = <FILE>;
        close FILE || die;

        my $l = 0;
        foreach (@contents) {
            $l++;
            if (m!^#define\s*([A-Za-z0-9_]+)\s+cpu_to_le32[(]([0-9a-fA-Fx]+)[)]!) {
                my $status = $1;
                my $code = $2;
                my $s;

                next if ($status =~ /^STATUS_SEVERITY/);

                if (exists($statuses{$status})) {
                    print("$f:$l: Duplicate declaration of ", $s->{status}, "\n");
                } else {
                    my %_s = (
                        status => $status,
                        code   => hex($code)
                        );
                    $statuses{$status} = \%_s;
                }
            }
        }

        #
        # Read the SMB2 status => error mapping table
        #
        $f = "fs/smb/client/smb2maperror.c";
        open(MFILE, "<$f") || die $f;
        my @maperror = <MFILE>;
        close MFILE || die;

        my $parse = 0;
        my $acc = "";
        $l = 0;
        foreach my $line (@maperror) {
            chomp $line;
            $l++;
            if ($parse == 0 &&
                $line =~ /^static const struct status_to_posix_error smb2_error_map_table/) {
                $parse = 1;
                next;
            }

            last if ($parse >= 1 && $line =~ /^[}];/);

            if ($parse == 1) {
                if ($line =~ /[\t][{].*[}],/) {
                    $acc = $line;
                    $parse = 3;
                } elsif ($line =~ /[\t][{].*/) {
                    $acc = $line;
                    $parse = 2;
                    next;
                } elsif ($line =~ m!^\s*/[*].*[*]/!) {
                    next;
                } else {
                    die "smb2maperror.c:$l: unparseable mapping element\n";
                }
            }
            if ($parse == 2) {
                if ($line =~ /.*[}],/) {
                    $acc .= $line;
                    $parse = 3;
                } else {
                    $acc .= $line;
                }
            }

            if ($parse == 3) {
                $acc =~ s/\s+//g;
                if ($acc =~ m/[{](.*)[}]/) {
                    $acc = $1;
                } else {
                    die "'$acc'";
                }
                my ($status, $error, $string) = split(/,/, $acc);

                if (exists($statuses{$status})) {
                    my $s = $statuses{$status};

                    if (exists($s->{error})) {
                        print("$f:$l: Dup mapping entry $status\n");
                    }

                    $s->{error} = $error;
                    #print $s->{code}, " => ", $error, "\n";
                } else {
                    print STDERR "$f:$l: Unknown status $status\n";
                }

                $acc = "";
                $parse = 1;
            }
        }

        #
        # Sort the error table by STATUS_* value
        #
        my @order = ();

        foreach my $status (keys(%statuses)) {
            my $s = $statuses{$status};
            push @order, $s;
            unless (exists($s->{code})) {
                print("Unknown code for ", $s->{status}, "\n")
            } else {
                #print("Code for ", $s->{status}, " is ", $s->{code}, "\n");
            }
        }

        @order = sort( { $a->{code} <=> $b->{code} } @order);

        foreach my $s (@order) {
            my $status = $s->{status};
            my $error  = $s->{error};
            my $code   = $s->{code};

            my $pad = " ";
            if (length($status) < 32) {
                my $n = 32 - length($status);
                $pad = "\t" x ((($n-1) / 8) + 1);
            }
            #printf("#define %s%scpu_to_le32(0x%08x) // -%s\n", $status, $pad, $code, $error);
            #printf("\t%s%s= 0x%08x, // -%s\n", $status, $pad, $code, $error);
        }

        #
        # Decorate the definitions
        #
        my @output = ();
        for (my $i = 0; $i <= $#contents; $i++) {
            my $line = $contents[$i];
            if ($line =~ m!^#define\s*([A-Za-z0-9_]+)\s+cpu_to_le32[(]([0-9a-fA-Fx]+)[)]!) {
                my $status = $1;
                my $code = $2;

                if ($status =~ /^STATUS_SEVERITY/) {
                    push @output, $line;
                    next;
                }

                my $pad = " ";
                if (length($status) < 40) {
                    my $n = 40 - length($status);
                    $pad = "\t" x ((($n-1) / 8) + 1);
                }

                my $s = $statuses{$1};
                my $error = "EIO";
                if (exists($s->{error})) {
                    $error = $s->{error};
                } else {
                    if (!$s->{code}) {
                        print "ZERO ", $status, "\n";
                        $error = "0";
                    } else {
                        $error = "-EIO";
                    }
                }

                #my $rev = "#define " . $status . $pad . "_S(" . $2 . ", " . $error . ")\n";
                my $rev = "#define " . $status . $pad . "cpu_to_le32(" . $2 . ") // " . $error . "\n";

                push @output, $rev;
            } else {
                push @output, $line;
            }
        }

        open FILE, ">fs/smb/common/smb2status.h" || die;
        print FILE @output;
        close FILE || die;

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <stfrench@microsoft.com>
cc: ChenXiaoSong <chenxiaosong@kylinos.cn>
cc: linux-cifs@vger.kernel.org
Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Reviewed-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/linux-cifs/20260106071507.1420900-2-chenxiaosong.chenxiaosong@linux.dev/
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/common/smb2status.h