Mẹo chạy Zed remote server trên FreeBSD và bản vá nhân
Một lập trình viên đã đánh lừa Zed bằng một wrapper uname giả để chạy Linux server của trình soạn thảo này trên FreeBSD qua lớp tương thích Linuxulator. Quá trình đó dẫn tới phát hiện một lỗi hồi quy trong nhân FreeBSD khiến danh sách tệp bị mất, và bản vá đã được đưa vào nhánh releng/15.2.

Một lập trình viên đã chia sẻ cách chạy remote server của trình soạn thảo Zed trên FreeBSD bằng một mẹo nhỏ, và trong quá trình đó phát hiện ra một lỗi hồi quy trong nhân FreeBSD khiến toàn bộ danh sách tệp của dự án biến mất. Bản vá cho lỗi này đã được đưa vào nhánh releng/15.2, nên bản 15.2-RELEASE sẽ có sẵn.
Từ VS Code sang Zed
Tác giả cho biết đã dùng VS Code gần mười năm, nhưng thời gian gần đây trình soạn thảo này trở nên chậm và ngày càng nặng nề vì các tính năng AI. Tùy chọn chat.disableAIFeatures có tắt được phần lớn tính năng AI tích hợp, nhưng VS Code vẫn cảm giác vụng về. Zed thì nhanh hơn, và có công tắc tắt toàn bộ tính năng AI từ khá sớm — một toggle trong Settings hoặc "disable_ai": true trong tệp cấu hình.
Lý do không phải vì tác giả tránh LLM. Anh vẫn tự viết phần lớn mã FOSS, và chỉ giao lại những việc mệt mỏi như kiểm thử hồi quy, xử lý các trường hợp biên và khám phá ý tưởng, thường qua các harness như OpenCode. Với tác giả, các harness kiểu claude code tích hợp trong trình soạn thảo khá cồng kềnh.
Bước 1: Bật tương thích Linux
Zed hiện chưa cung cấp remote server cho FreeBSD, nhưng FreeBSD chạy được các binary Linux thông qua lớp tương thích (Linuxulator). Vì vậy có thể dùng server bản Linux của Zed. Điều kiện là một máy chủ FreeBSD truy cập được qua SSH.
sudo sysrc linux_enable=YES
sudo service linux start
sudo pkg install linux_base-rl9
kldstat -m linux64 # phải in ra một module
Bước 2: Đánh lừa Zed về nền tảng
Zed hỏi máy chủ đang chạy nền tảng gì. FreeBSD trả lời "FreeBSD amd64", không có server tương ứng, và Zed bỏ cuộc. Giải pháp là một wrapper trả lời "Linux x86_64" cho riêng câu hỏi đó và chuyển mọi thứ khác cho uname thật.
Lưu đoạn script sau thành ~/.local/bin/uname và cấp quyền thực thi:
#!/bin/sh
case "$#:$*" in
1:-sm|1:-ms) printf 'Linux x86_64\n' ;;
*) exec /usr/bin/uname "$@" ;;
esac
Sau đó thêm ~/.local/bin vào PATH cho các phiên SSH không tương tác. Với zsh, thêm export PATH="$HOME/.local/bin:$PATH" vào ~/.zshenv (hoặc tệp tương đương của shell đang dùng).
Bước 3: Kết nối
Kết nối qua SSH từ Zed và mở một thư mục. Lần kết nối đầu tiên sẽ tải server Linux lên ~/.zed_server/. Có thể theo dõi quá trình bằng lệnh tail -f ~/.local/share/zed/logs/server-workspace-*.log.
Bước 4: Cần nhân có bản vá
Nếu chưa có bản vá, kết nối vẫn thành công nhưng cây dự án trống trơn, kèm dòng lỗi trong log server:
error processing entry failed to read directory entry
Caused by:
Invalid argument (os error 22)
Bản vá ec6629628cb nằm trên main, stable/15 và releng/15.2, nên 15.2-RELEASE sẽ bao gồm nó. Nếu lỗi vẫn còn, cần kiểm tra xem đã khởi động đúng nhân mới chưa bằng uname -v.
Lỗi nhìn từ góc độ đơn giản
Để hiển thị dự án, Zed hỏi server tên các tệp trong từng thư mục, mỗi lần một nhóm nhỏ. Zed dành sẵn một vùng đệm nhỏ cho mỗi lần.
Hãy hình dung một giáo viên đọc danh sách lớp cho học sinh ghi vào một tờ giấy nhớ. Giáo viên gạch tên từng người sau khi đọc, và không bao giờ đọc lại tên đã gạch. Tờ giấy chỉ chứa được 6 tên, nhưng giáo viên đọc theo nhóm 4 — thói quen hợp lý và gần như luôn hiệu quả. Vì 6 không chia hết cho 4, giáo viên đọc 8 tên và gạch hết 8, nhưng chỉ 6 tên vừa giấy.
Không thể đưa 6 tên và giữ 2 tên còn lại cho lần sau, vì chúng đã bị gạch. Kết quả là báo lỗi — ồn ào nhưng minh bạch. Khi tác giả thử cách "im lặng", 112 trong số 1.002 tệp biến mất khỏi danh sách mà không có cảnh báo. Zed nhận lỗi và quyết định không đọc được thư mục, hiển thị nó trống.
Bản vá rất nhỏ: chỉ đọc số tên vừa với vùng đệm, gạch đúng số đó, rồi quay lại lấy nhóm tiếp theo cho đến hết danh sách. Trong lỗi thực tế, "giáo viên" là lớp dịch Linux của FreeBSD (Linuxulator), "tờ giấy" là vùng đệm 768 byte, và "nhóm 4 tên" là khối 512 byte.
Chi tiết cho dân nhân
Đây là lỗi hồi quy. Một bản vá tháng 2 năm 2026 xử lý việc thư mục NFS trả về mục rác (110f2567cb51, PR 292282) đã thay đổi cách sys/compat/linux/linux_file.c tính kích thước lệnh đọc native, trong cả linux_getdents() và linux_getdents64():
/* trước tháng 2/2026 */
buflen = min(args->count, MAXBSIZE);
/* sau đó: mọi yêu cầu được làm tròn lên bội số của khối 512 byte */
buflen = min(roundup2(args->count, DEV_BSIZE), MAXBSIZE);
Nếu vùng đệm của bên gọi không phải bội số của 512 byte, lô native có thể lớn hơn vùng đệm. Lớp giả lập chuyển đổi các bản ghi cho đến khi một bản ghi không vừa và trả về EINVAL, nhưng kern_getdirentries() đã tiến offset của thư mục qua toàn bộ lô. Đó là lý do trả về lô một phần không đủ.
Bản vá ec6629628cb (được review trong D60760):
if (args->count >= DEV_BSIZE)
buflen = min(args->count, MAXBSIZE);
else
buflen = roundup2(args->count, DEV_BSIZE);
Cách này an toàn vì bản ghi thư mục của Linux không bao giờ lớn hơn của FreeBSD: với dirent64, phần header là 19 byte so với 24 byte, và cả hai đều làm tròn mỗi bản ghi lên bội số của 8. Một lô native vừa vùng đệm của bên gọi thì sau chuyển đổi cũng vừa.
getdents cũ cũng mắc cùng lỗi với bên gọi 32-bit và 64-bit. Bản vá đầu tiên chỉ sửa getdents64; khi sửa cả hai, ma trận kiểm thử giảm từ 86 lỗi xuống 0.
Tác giả cảm ơn Kyle Evans (kevans@) và Mark Johnston (markj@) đã review bản vá và góp ý. Bản vá vào releng/15.2 khá nhanh, không nằm lâu ở nhánh stable.
Góc nhìn
Câu chuyện cho thấy một mẹo nhỏ ở tầng người dùng — giả lập uname — có thể nhanh chóng trở thành một bản vá nhân thật khi nó chạm vào một lỗi hồi quy. Với các kỹ sư dùng hệ điều hành ít phổ biến, việc hiểu lớp tương thích Linux của FreeBSD giúp tận dụng được hệ sinh thái công cụ Linux mà không cần chờ hỗ trợ chính thức.
Bài học kỹ thuật đáng chú ý là lỗi "im lặng" nguy hiểm hơn lỗi "ồn ào": báo EINVAL khiến danh sách tệp trống, nhưng nếu bỏ qua thì một phần tệp biến mất mà không ai biết. Khi tích hợp các công cụ đọc hệ thống tệp, nên kiểm tra kỹ việc xử lý offset và vùng đệm không chia hết kích thước khối.
Cuối cùng, việc bản vá được làm tròn kích thước lô theo 512 byte cho thấy các thay đổi nhỏ nhằm sửa một trường hợp cụ thể có thể gây hồi quy ở các trường hợp khác. Một bộ kiểm thử bao phủ nhiều kích thước vùng đệm và nhiều kiến trúc là cách phòng ngừa hợp lý.
Nguồn: hayzam.com · Quy trình biên tập


