2016-12-02 48 views
3

我的服務器上安裝了紅帽企業Linux服務器版本6.6(2.6.32-504.el6.x86_64),並具有低於分區的層次結構。statvfs系統調用失敗,錯誤值對於定義的數據類型太大

Filesystem  Size Used Avail Use% Mounted on 
/dev/sda2  7.9G 1.7G 5.9G 22%/
tmpfs   5.4G 8.0K 5.4G 1% /dev/shm 
/dev/sda8  53G 1.4G 49G 3% /mysql/data 
/dev/sda6  7.9G 4.5G 3.1G 60% /usr/BWhttpd 
/dev/sda4  32G 989M 29G 4% /var 
/dev/sdb1  25T 37M 25T 1% /media1 
/dev/sdc1  25T 37M 25T 1% /media2 
/dev/sdd1  25T 37M 25T 1% /media3 
/dev/sde1  22T 21T 1.1T 95% /media4 

我發出的每個

/mediax

分區,但系統調用的statvfs調用失敗,錯誤Value too large for defined data type

我能夠找到系統調用返回的錯誤EOVERFLOW,但不知道struct statvfs的哪個成員導致了這一點。

是否必須對/ mediax分區的大小做任何事情。

注意:分區是xfs文件系統類型。

+0

您發佈的輸出看起來來自'df',[它在內部使用'statvfs()'](https://www.gnu.org/software/coreutils/coreutils.html),所以它似乎'statvfs()'適用於你的系統。你如何編譯你的代碼?你編譯爲32位還是64位? –

+0

@AndrewHenle是輸出是'df'命令的輸出。我不確定32/64位編譯是否會在這裏產生影響。可以詳細說明這一點。 –

+0

@AndrewHenle我也嘗試在http://lingrok.org/xref/coreutils/src/df.c這裏檢查'df'的源代碼,但無法找到對'statvfs'的引用我猜它直接使用內核調用'stat'。 –

回答

3

如在所提到的man 2 statfs手冊頁:

原始版本的Linux的statfs()和fstatfs()系統調用在設計時沒有考慮到非常大的文件大小。隨後,Linux 2.6添加了使用新結構statfs64的新statfs64()和fstatfs64()系統調用。新結構包含與原始statfs結構相同的字段,但各個字段的大小都會增加,以適應大文件大小。 glibc statfs()和fstatfs()包裝函數透明地處理內核差異。

就你而言,由於某種原因,你使用的是非64位版本的系統調用。

Linux內核實現使用四種不同的系統調用(加上任選其兼容性版本)中的fstat*fs*()stat*fs*()庫調用:fstatfs()fstatfs64()statfs()statfs64()。在內核源代碼中,所有四個都在fs/statfs.c中定義,並使用內核內部函數vfs_statfs()將必要的信息收集到一個struct kstatfs結構中。

statfs()兩者並fstatfs()使用內核內部功能do_statfs_native()(在fs/statfs.c)到田裏從內核struct kstatfs複製到用戶空間struct statfs緩衝器。問題是,許多內核結構字段比用戶空間緩衝區中的字段大。 do_statfs_native()驗證值是否合適,如果不符合,則返回-EOVERFLOW

這是我能找到的唯一情況,可能導致四個系統調用中的任何一個返回-EOVERFLOW

對於statfs64()fstatfs64(),核函數do_statfs64()用於將字段從內核內部struct kstatfs到用戶空間struct statfs64緩衝區拷貝。用戶空間緩衝區字段至少與內核結構字段一樣大,因此不存在溢出風險。 (函數永不返回-EOVERFLOW。)

此修復程序旨在確保您使用64位版本的struct statfs和相應的系統調用。


爲了確保glibc的使用結構的正確版本(那些能夠正確描述非常大的文件系統),確保你有

#define _FILE_OFFSET_BITS 64 
之前的任何 #include小號

;或者,將-D_FILE_OFFSET_BITS=64添加到您的編譯器標誌。

所有這些都確保glibc知道您正在Linux 2.6或更高版本的內核(3.x,4.x等)上運行,並且它肯定應該嘗試使用具有適當大小的字段的結構。

或者,您也可以定義_LARGEFILE64_SOURCE,揭露struct statfs64struct statvfs64類型和相應的圍繞系統調用statfs64()statvfs64()包裝。這樣可以避免讓glibc做任何猜測,並確保使用可以正確描述所有Linux文件系統大小的系統調用版本。

這兩個選項都適用於所有Linux體系結構,32位和64位。

+0

以任何方式做到這一點意味着我們可以裝入任何大尺寸的分區,或者分區的閾值還有一些。 –

+1

@Krishna_Oza:不,這並不意味着;只有在分區可以掛載的情況下,我們可以像內核看到它一樣準確獲取它的統計信息。至於分區大小限制:磁盤上使用的分區表格式可能會限制分區的大小(這可能會讓某些人感到意外,並且是轉移到大型存儲驅動器的GPT格式分區表的原因)。而且,每個文件系統的確有多大的限制;對於ext4,我認爲它是2^60字節(1.15e18字節)。理論上,通用文件系統代碼應該可以達到2^60字節。當然沒有測試過! –

1

不是一個完整的答案,但對於內核代碼(V4.9,我目前還沒有內核的代碼,但我懷疑這部分已經改變了很多),你應該尋找一個值>0xffffffff以下參數中的一個:f_blocksf_bfreef_bavailf_bsizef_frsizef_filesf_files,即除任何f_fsid參數,f_flag,和f_namemax

if (sizeof buf->f_blocks == 4) { 
    if ((st.f_blocks | st.f_bfree | st.f_bavail | 
     st.f_bsize | st.f_frsize) & 
     0xffffffff00000000ULL) 
     return -EOVERFLOW; 
    /* 
    * f_files and f_ffree may be -1; it's okay to stuff 
    * that into 32 bits 
    */ 
    if (st.f_files != -1 && 
     (st.f_files & 0xffffffff00000000ULL)) 
     return -EOVERFLOW; 
    if (st.f_ffree != -1 && 
     (st.f_ffree & 0xffffffff00000000ULL)) 
     return -EOVERFLOW; 
} 
+0

你在這裏指的是哪個內核文件,我可以看看與我的內核版本相同的文件。但是對於18T驅動器而言,再次正常工作並且22T驅動器無法正常工作。 –

+0

@Krishna_Oza:fs/statfs.c。 – Matthias

相關問題