bug 名稱
truncate操作失敗
bug 描述
使用fstest工具,先執行create再執行truncate後,伺服器會返回eio,而不是期望的0,過一段時間之後,重複執行truncate則成功。
這是導致truncate測試用例所有失敗的唯一原因。具體測試指令碼在fstest/tests/truncate目錄下。
bug 重現過程
1. 在客戶端掛載目錄下,使用fstest建立乙個檔案
命令:./fstest create aaa 0644
2. 執行truncate操作
命令:./fstest truncate aaa 1234567
3. 會顯示eio
出現bug的系統日誌
客戶端日誌:
伺服器端日誌:
bug 分析
現象分析
根據操作不成功的返回值eio,很難分析出具體原因,因為eio是經過err_map操作之後的對映值,具體錯誤的返回值需要在log中定位。
log分析
1. 根據客戶端和伺服器的錯誤返回值10038,得出對應的巨集定義是err_openmode;
2. 通過在伺服器端日誌的3903行(見上圖)分析,定位出錯的具體**函式。
經過判斷,當前stateid是存在 對應的delegation的,然後進入check_delemode()函式,該函式**如下:
在2295行,經過打printk,斷定dp->dl_type的值為nfs4_open_deleagate_read。
4. 經過閱讀pnfs協議,發現在setattr()操作之前進行的open()操作,伺服器會嘗試授予delegation.
5. 閱讀伺服器端open()操作**,發現呼叫nfs4_open_delegation(current_fh, open, stp)後,入口引數open,中含有op_share_access變數,經過列印輸入,其值為nfs4_share_access_read。在隨後進行的分配delegation操作中,會把分配給它的delegation設定為nfs4_share_access_read。當客戶端下次持有這個delegation來執行setattr操作時,由於設定了修改size的標誌位,導致delegation的型別判斷失敗,操作失敗。
6. 若在shell中執行touch命令建立檔案,然後在執行truncate系統呼叫,則不會出現同樣錯誤,是因為touch觸發的系統呼叫是:open("cc", o_wronly|o_creat|o_noctty|o_nonblock, 0666);而測試指令碼中的建立命令是open(str(0), o_creat | o_excl, num(1));兩者相比,建立時候的標誌位設定不同,導致伺服器接收到的open操作,入口引數的op_share_access不同,從而測試指令碼的命令可以獲得讀許可權的delegation,而touch命令則無法獲取delegation。
7. 對於使用測試指令碼建立檔案,過一段時間後在執行truncate操作可以成功。
是由於客戶端會每60秒執行nfs4_renew_state(struct work_struct *work)操作,此操作會檢查是否存在「unreferenced」的delegation,若有則將其釋放。
而truncate操作之後,會執行檔案的close操作,刪除對應dentry,使得open操作得到的delegation變成「unreferenced」,在nfs4_renew_state()操作中被刪除。也就是說,檔案被建立之後,只要客戶端執行了nfs4_renew_state操作,再執行truncate操作,就可以成功。
8.由於nfs4_renew_state()操作是定期執行的,而truncate操作是隨機發生的,導致之前的第一次操作失敗後,間隔「不確定的時間」,再次成功。
bug定位
執行修改檔案大小的操作時候,客戶端持有的delegation型別為nfs4_share_access_read。
解決方案
在客戶端傳送setattr()請求之前,檢查修改size的標誌位是否設定,若設定,則釋放delegation。
在函式nfs_setattr()中,新增如下**:
驗證驗證通過。
**以及文件的提交路徑
PHP 執行多條 truncate
相同點 1.truncate和不帶where子句的delete 以及drop都會刪除表內的資料。2.drop truncate都是ddl語句 資料定義語言 執行後會自動提交。不同點 1.truncate 和 delete 只刪除資料不刪除表的結構 定義 drop 語句將刪除表的結構被依賴的約束 co...
誤操作經歷,truncate導致閃回查詢失敗
開發人員向我反映由於誤操作刪除了表裡的一些資料,要求我恢復。諮詢了誤操作的時間點後,我用閃回查詢試了一下,被誤刪的資料還在回滾段,可以挽救回來。我先備份了現在表裡的資料。create table a as select from 業務表。然後我做了一件愚蠢的事 truncate table 業務表 ...
解決erl sname gandalf 執行失敗
輸入erl sname gandalf後如圖 通過很多周折 包括使用crashdump viewer start 檢視崩潰記錄,網上查閱資料等等,都是竹籃打水一場空 總歸在反覆看報錯資訊之後,終於將目光注意到了這串英文,原來系統早就非常明確的告訴我,問題出在 cookie!接著我在 erlang程式...