青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

小默

【轉】proc文件系統分析(四)

(六) 對proc文件默認操作的分析 
現在,我們已經基本清楚了proc文件系統對自己proc_dir_entry結構的管理了。下面我們回過頭來,再看一下在文件注冊函數中的一段代碼: 
if (S_ISDIR(dp->mode)) { 
if (dp->proc_iops == NULL) { 
dp->proc_fops = &proc_dir_operations; 
dp->proc_iops = &proc_dir_inode_operations; 
} 
dir->nlink++; 
} else if (S_ISLNK(dp->mode)) { 
if (dp->proc_iops == NULL) 
dp->proc_iops = &proc_link_inode_operations; 
} else if (S_ISREG(dp->mode)) { 
if (dp->proc_fops == NULL) 
dp->proc_fops = &proc_file_operations; 
} 
我在前面已經提過,這段代碼根據注冊的proc文件類型的不同,為proc_dir_entry結構設置了不同的操作函數集。也就是說,我們使用封裝的create_proc_entry函數在proc文件系統中注冊文件時,可以不用去管這些操作函數集,因為該結構總是自動地設置了相應的proc_iops和proc_fops操作函數。下面我們就對這些默認的操作進行一個分析,因為這對我們了解proc文件系統和VFS的結構非常重要。 
1 對普通文件的操作 
我們首先看一下普通proc文件的函數集,根據代碼段: 
if (S_ISREG(dp->mode)) { 
if (dp->proc_fops == NULL) 
dp->proc_fops = &proc_file_operations; 
} 
我們可以看到,對于普通的proc文件,只設置了文件操作,即proc_file_operations,從這一點上可以看出,對于普通的proc文件,只缺省提供了文件操作,因此,在必要的時候,我們必須手工設置需要的索引節點操作函數集,比如inode_operations中的權限檢查函數permission等等。 
對于proc_file_operations,我們可以看到,只實現了三個函數: 
static struct file_operations proc_file_operations = { 
llseek: proc_file_lseek, 
read: proc_file_read, 
write: proc_file_write, 
}; 
下面我們簡單的看一下它們實現的功能: 
(1)llseek: proc_file_lseek 
這個函數,用來實現lseek系統調用,其功能是設置file結構的->f_pos域,因此,根據第三個參數orig的不同,將f_pos設置為相應的值,該函數非常簡單,因此不作過多的介紹。 
(2)read: proc_file_read 
這個函數是file_operations結構中的成員,在后面我們將看到,在proc_dir_entry結構中實現的file_operations和inode_operations將鏈接至VFS的inode中,因此,該函數將用來實現read系統調用。在這個函數中,首先根據file結構,得到相應的inode,然后由 
struct proc_dir_entry * dp; 
dp = (struct proc_dir_entry *) inode->u.generic_ip; 
而得到proc_dir_entry結構,然后,開始調用該proc_dir_entry結構中的函數,向用戶空間返回指定大小的數據,我們看一下下面的代碼片斷: 
if (dp->get_info) { 
/* 
* Handle backwards compatibility with the old net 
* routines. 
*/ 
n = dp->get_info(page, &start, *ppos, count); 
if (n read_proc) { 
n = dp->read_proc(page, &start, *ppos, 
count, &eof, dp->data); 
} else 
break; 
由此我們看出,該函數的實現依賴于proc_dir_entry結構中的get_info和read_proc函數,因此,如果我們要注冊自己的proc文件,在不設置自己的proc_fops操作函數集的時候,必須實現上面兩個函數中的一個,否則,這個缺省的proc_file_read函數將做不了任何工作。示意圖如下: 
在這個函數中,實現了從內核空間向用戶空間傳遞數據的功能,其中使用了許多技巧,在這里就不作討論了,具體實現可以參考源碼。 
(3)write: proc_file_write 
與上面的函數類似,我們可以看到proc_file_write函數同樣依賴于proc_dir_entry中的write_proc(file, buffer, count, dp->data)函數,它的實現非常簡單: 
static ssize_t 
proc_file_write(struct file * file, const char * buffer, 
size_t count, loff_t *ppos) 
{ 
struct inode *inode = file->f_dentry->d_inode; 
struct proc_dir_entry * dp; 
dp = (struct proc_dir_entry *) inode->u.generic_ip; 
if (!dp->write_proc) 
return -EIO; 
/* FIXME: does this routine need ppos? probably... */ 
return dp->write_proc(file, buffer, count, dp->data); 
} 
我們看到,它只是簡單地檢測了->write_proc函數是否存在,如果我們在proc_dir_entry結構中實現了這個函數,那么就調用它,否則,就退出。 
根據上面的討論,我們看到,對于普通文件的操作函數,proc文件系統為我們提供了一個簡單的封裝,因此,我們只要在proc_dir_entry中實現相關的讀寫操作即可。 
但是,如果我們想提供讀寫操作之外的函數,那么我們就可以定義自己的file_operations函數集,并且在proc文件注冊后,將它鏈接到proc_dir_entry的proc_fops上,這樣,就可以使用自己的函數集了。 
2 對鏈接文件的操作 
根據代碼段: 
else if (S_ISLNK(dp->mode)) { 
if (dp->proc_iops == NULL) 
dp->proc_iops = &proc_link_inode_operations; 
我們可以看出,對于鏈接文件,proc文件系統為它設置了索引節點操作proc_iops。因為我們知道,一個符號鏈接,只擁有inode結構,而沒有文件結構,所以,為它提供proc_link_inode_operations函數集就可以了。 
下面我們看一下,這個函數集的內容: 
static struct inode_operations proc_link_inode_operations = { 
readlink: proc_readlink, 
follow_link: proc_follow_link, 
}; 
這個函數集實現了和鏈接相關的兩個函數,我們分別來看一下: 
(1)readlink: proc_readlink 
該函數用來實現readlink系統調用,它的功能是獲得目標文件的文件名,我們在前面看到,對于一個鏈接文件,在注冊時已經將鏈接目標的文件放在了proc_dir_entry結構的->data域中(參考前面介紹的函數proc_symlink),因此,我們只要將->data中的數據返回就可以了,它的代碼如下: 
static int proc_readlink(struct dentry *dentry, char *buffer, int buflen) 
{ 
char *s= 
((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data; 
return vfs_readlink(dentry, buffer, buflen, s); 
} 
我們看到,這個函數使用一個指針指向->data,然后,使用VFS函數vfs_readlink將數據返回到用戶空間,非常的簡單。 
(2)follow_link: proc_follow_link 
這個函數代碼如下: 
static int proc_follow_link(struct dentry *dentry, struct nameidata *nd) 
{ 
char *s= 
((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data; 
return vfs_follow_link(nd, s); 
} 
和上面介紹的函數類似,它同樣利用VFS的函數實現其功能,對于vfs_follow_link,可以參考fs/namei.c文件。其結構如下圖所示: 
3 對目錄文件的操作 
最后我們看一下proc文件系統對目錄文件的操作函數集,在文件注冊的時候,有如下代碼: 
if (S_ISDIR(dp->mode)) { 
if (dp->proc_iops == NULL) { 
dp->proc_fops = &proc_dir_operations; 
dp->proc_iops = &proc_dir_inode_operations; 
} 
dir->nlink++; 
} 
從中我們可以看到,在proc文件系統中注冊目錄文件的時候,它會檢查是否該proc_dir_entry結構已經注冊了proc_iops函數集,如果沒有,那么就為proc_fops和proc_iops設置相應的缺省函數集。下面我們對它們分別進行討論: 
1.對目錄的文件操作proc_dir_operations: 
static struct file_operations proc_dir_operations = { 
read: generic_read_dir, 
readdir: proc_readdir, 
}; 
這個函數集的主要功能,是在由proc_dir_entry結構構成的proc文件樹中解析目錄。下面我們對這兩個函數進行一個簡單的分析: 
(1)read: generic_read_dir 
我們知道,對于read系統調用,當其參數文件句柄指向目錄的時候,將返回EISDIR錯誤。因此,目錄文件的read函數將完成這個工作。generic_read_dir函數是VFS提供的通用函數,可以參考fs/read_write.c文件: 
ssize_t generic_read_dir(struct file *filp, char *buf, size_t siz, loff_t *ppos){ 
return –EISDIR; 
} 
這個函數很簡單,只要返回錯誤碼就可以了。 
(2)readdir: proc_readdir 
這個函數用來實現readdir系統調用,它從目錄文件中讀出dirent結構到內存中。我們可以參考fs/readdir.c中的filldir()函數。 
2.對目錄文件索引節點的操作函數:proc_dir_inode_operations 
首先,我們看一下proc_dir_inode_operations的定義: 
/* 
* proc directories can do almost nothing.. 
*/ 
static struct inode_operations proc_dir_inode_operations = { 
lookup: proc_lookup, 
}; 
我們看到,對于目錄文件的索引節點,只定義了一個函數lookup。因為我們在前面對VFS進行分析的時候知道,以下操作,是只在目錄節點中定義的: 
int (*create) (struct inode *,struct dentry *,int); 
struct dentry * (*lookup) (struct inode *,struct dentry *); 
int (*link) (struct dentry *,struct inode *,struct dentry *); 
int (*unlink) (struct inode *,struct dentry *); 
int (*symlink) (struct inode *,struct dentry *,const char *); 
int (*mkdir) (struct inode *,struct dentry *,int); 
int (*rmdir) (struct inode *,struct dentry *); 
int (*mknod) (struct inode *,struct dentry *,int,int); 
int (*rename) (struct inode *, struct dentry *, 
struct inode *, struct dentry *); 
但是經過我們對proc文件系統的分析,我們知道,proc文件系統中的文件都是在內核代碼中通過proc_dir_entry實現的,因此,它不提供目錄索引節點的create,link,unlink,symlink,mkdir,rmdir,mknod,rename方法,也就是說,用戶是不能通過shell命令在/proc目錄中對proc文件進行改名,刪除,建子目錄等操作的。這也算是proc文件系統的一種保護策略。 
而在內核中,則使用proc_mkdir,proc_mknod等函數,在核心內通過代碼來維護proc文件樹。由此可以看出虛擬文件系統的一些特性。對目錄文件的默認操作,可以參見下面的示意圖: 
下面我們就來看一下唯一定義的函數lookup: proc_lookup,到底實現了什么功能。 
在進行具體分析之前,我們先考慮一個問題,我們知道,proc文件系統維護了自己的proc_dir_entry結構,因此提供了create_proc_entry,remove_proc_entry等等函數,并且為了方便實現對proc文件的讀寫功能,特意在proc_dir_entry結構中設置了get_info,read_proc和write_proc函數指針(我們在前面介紹過,這三個函數被封裝在proc_file_operations中),并且,提供了自己的inode_operations和file_operations,分別是proc_iops 和proc_fops。也就是說,我們在建立proc文件以及為proc文件建立操作函數的時候,似乎可以不用考慮VFS的實現,只要建立并注冊該proc_dir_entry結構,然后實現其proc_iops 和proc_fops(或者get_info,read_proc和write_proc)就可以了。 
但是我們知道,在linux系統中,所有的子系統都是與VFS層交互,而VFS是通過inode結構進行管理的,并且在其上的操作(文件和索引節點的操作)也是通過該inode結構的inode_operations和file_operations實現的。因此,proc文件系統必須將自己的文件與VFS的inode鏈接起來。 
那么proc文件系統是在何時,通過何種方法將自己的proc_dir_entry結構和VFS的inode聯系在一起的,并且將對inode的inode_operations和file_operations操作定位到自己結構中的proc_iops 和proc_fops上呢?通過我們對lookup: proc_lookup的分析,就會明白這一過程。 
我們先看一下它的代碼: 
struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry) 
{ 
struct inode *inode; 
struct proc_dir_entry * de; 
int error; 
error = -ENOENT; 
inode = NULL; 
de = (struct proc_dir_entry *) dir->u.generic_ip; 
if (de) { 
for (de = de->subdir; de ; de = de->next) { 
if (!de || !de->low_ino) 
continue; 
if (de->namelen != dentry->d_name.len) 
continue; 
if (!memcmp(dentry->d_name.name, 
de->name, de->namelen)) { 
int ino = de->low_ino; 
error = -EINVAL; 
inode = proc_get_inode(dir->i_sb, ino, de); 
break; 
} 
} 
} 
if (inode) { 
dentry->d_op = &proc_dentry_operations; 
d_add(dentry, inode); 
return NULL; 
} 
return ERR_PTR(error); 
} 
這個函數的參數是struct inode * dir和struct dentry *dentry,它的功能是查找由dentry指定的文件,是否在由dir指定的目錄中。 
我們知道,proc文件系統通過proc_dir_entry結構維護文件信息,并且該結構與相應的inode->u.generic_ip聯系,因此,這個函數首先通過struct inode * dir得到了相應目錄文件的proc_dir_entry結構,并使用指針de指向它,然后,開始在該結構的孩子中查找指定的dentry。 
判斷是否找到的條件很簡單,就是de->namelen等于 dentry->d_name.len,并且dentry->d_name.name等于de->name,根據程序流程,如果沒有找到,那么將返回-ENOENT錯誤(使用inode指針作為判斷條件),如果找到該文件,那么就根據ino = de->low_ino(要注意的是,這時候的de已經指向由dentry確定的proc_dir_entry結構了。)調用函數: 
inode = proc_get_inode(dir->i_sb, ino, de); 
這個proc_get_inode的功能很容易猜到,就是從由超級塊i_sb確定的文件系統中,得到索引節點號為ino的inode。因此考慮兩種情況,第一種情況,這個索引節點已經被讀入緩存了,那么直接返回該inode即可。第二種情況是,指定ino的索引節點不在緩存中,那么就需要調用相應的函數,將該索引節點從邏輯文件系統中讀入inode中。 
下面我們就來分析一下proc_get_inode函數,尤其注意上面所說的第二種情況,因為這正是inode和proc_dir_entry建立聯系并重定位操作函數集的時機。先看一下源碼: 
struct inode * proc_get_inode(struct super_block * sb, int ino, 
struct proc_dir_entry * de) 
{ 
struct inode * inode; 
/* 
* Increment the use count so the dir entry can't disappear. 
*/ 
de_get(de); 
#if 1 
/* shouldn't ever happen */ 
if (de && de->deleted) 
printk("proc_iget: using deleted entry %s, count=%d\n", de->name, atomic_read(&de->count)); 
#endif 
inode = iget(sb, ino); 
if (!inode) 
goto out_fail; 
inode->u.generic_ip = (void *) de; /* link the proc_dir_entry to inode */ 
/* 
* set up other fields in the inode 
*/ 
if (de) { 
if (de->mode) { 
inode->i_mode = de->mode; 
inode->i_uid = de->uid; 
inode->i_gid = de->gid; 
} 
if (de->size) 
inode->i_size = de->size; 
if (de->nlink) 
inode->i_nlink = de->nlink; 
if (de->owner) 
__MOD_INC_USE_COUNT(de->owner); 
if (S_ISBLK(de->mode)||S_ISCHR(de->mode)||S_ISFIFO(de->mode)) 
init_special_inode(inode,de->mode,kdev_t_to_nr(de->rdev)); 
else { 
if (de->proc_iops) 
inode->i_op = de->proc_iops; 
if (de->proc_fops) 
inode->i_fop = de->proc_fops; 
} 
} 
out: 
return inode; 
out_fail: 
de_put(de); 
goto out; 
} 
我們根據程序流程,分析它的功能: 
1.使用de_get(de)增加proc_dir_entry結構de的引用計數。 
2.使用VFS的iget(sb, ino)函數,從sb指定的文件系統中得到節點號為ino的索引節點,并使用指針inode指向它。如果沒有得到,則直接跳到標號out_fail,減少de的引用計數后退出。 
因此我們要了解一下iget,這個函數由VFS提供,可以參考源文件fs/inode.c和頭文件include/linux/fs.h,在fs.h頭文件中,有如下定義: 
static inline struct inode *iget(struct super_block *sb, unsigned long ino) 
{ 
return iget4(sb, ino, NULL, NULL); 
} 
因此該函數是由fs/inode.c中的iget4實現的。主要步驟是,首先根據sb和ino得到要查找的索引節點的哈希鏈表,然后調用find_inode函數在該鏈表中查找該索引節點。如果找到了,那么就增加該索引節點的引用計數,并將其返回;否則,調用get_new_inode函數,以便從邏輯文件系統中讀出該索引節點。 
而get_new_inode函數也很簡單,它分配一個inode結構,并試圖重新查找指定的索引節點,如果還是沒有找到,那么就給新分配的索引節點加入到哈希鏈表和使用鏈表中,并設置一些基本信息,如i_ino,i_sb,i_dev等,并且,將其引用計數i_count初始化為1。然后,調用超級塊sb的read_inode函數,來作邏輯文件系統自己特定的工作,但對于proc文件系統來說,read_inode函數基本沒有實質性的功能,可參考前文對該函數的分析。最后,返回這個新建的索引節點。 
3.這時,我們已經得到了指定的inode(或者是從緩存中返回,或者是利用get_new_inode函數剛剛創建),那么就使用語句 
inode->u.generic_ip = (void *) de; 
將proc_dir_entry結構de與相應的索引節點鏈接起來。因此,我們就可以在其他時刻,利用proc文件索引節點的->u.generic_ip得到相應的proc_dir_entry結構了。 
對于新創建的inode來說,將其->u.generic_ip域指向(void *) de沒什么問題,因為該域還沒有被賦值,但是如果這個inode是從緩存中得到的,那么,說明該域已經指向了一個proc_dir_entry結構,這樣直接賦值,會不會引起問題呢? 
這有兩種情況,第一種情況,它指向的proc_dir_entry結構沒有發生過變化,那么,由于索引節點是由ino確定的,而且在一個文件系統中,確保了索引節點號ino的唯一性,因此,使用inode->u.generic_ip = (void *) de語句對其重新進行賦值,不會發生任何問題。 
另一種情況是在這之前,程序曾調用remove_proc_entry要將該proc_dir_entry結構刪除,那么由于它的引用計數count不等于零,因此,該結構不會被釋放,而只是打上了刪除標記。所以這種情況下,該賦值語句也不會引起問題。 
我們知道,當inode的i_count變為0的時候,會調用sb的proc_delete_inode函數,這個函數將inode的i_state設置為I_CLEAR,這可以理解為將該inode刪除了,并調用de_put,減少并檢查proc_dir_entry的引用計數,如果到零,也將其釋放。因此我們看到,引用計數的機制使得VFS的inode結構和proc的proc_dir_entry結構能夠保持同步,也就是說,對于一個存在于緩存中的的inode,必有一個proc_dir_entry結構存在。 
4.這時,我們已經得到了inode結構,并且將相應的proc_dir_entry結構de與inode鏈接在了一起。因此,就可以根據de的信息,對inode的一些域進行填充了。其中最重要的是使用語句: 
if (de->proc_iops) 
inode->i_op = de->proc_iops; 
if (de->proc_fops) 
inode->i_fop = de->proc_fops; 
將inode的操作函數集重定向到proc_dir_entry結構提供的函數集上。這是因為我們可以通過proc_dir_entry結構進行方便的設置和調整,但最終要將文件提交至VFS進行管理。正是在這種思想下,proc文件系統提供提供了一套封裝函數,使得我們可以只對proc_dir_entry結構進行操作,而忽略與VFS的inode的聯系。 
5.最后,成功地返回所要的inode結構。 
(七) 小結 
至此,已經對proc文件系統進行了一個粗略的分析,從文件系統的注冊,到proc_dir_entry結構的管理,以及與VFS的聯系等等。下面我們對proc文件系統的整體結構作一個總結。 
proc文件系統使用VFS接口,注冊自己的文件類型,并且通過注冊時提供的proc_read_super函數,創建自己的超級塊,然后裝載vfsmount結構。在proc文件系統內部,則使用proc_dir_entry結構來維護自己的文件樹,并且通過目錄文件的lookup函數,將proc_dir_entry結構與VFS的inode結構建立聯系。 


本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u2/74524/showart_1129842.html

posted on 2010-06-23 06:10 小默 閱讀(596) 評論(0)  編輯 收藏 引用 所屬分類: Linux

導航

統計

留言簿(13)

隨筆分類(287)

隨筆檔案(289)

漏洞

搜索

積分與排名

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产日韩欧美在线99 | 亚洲香蕉成视频在线观看| 狠狠色丁香婷综合久久| 国产农村妇女精品| 国产日韩欧美麻豆| 国产一区二区三区直播精品电影| 国产亚洲精品成人av久久ww| 国内成人精品2018免费看| 在线观看91久久久久久| 亚洲欧洲中文日韩久久av乱码| 99一区二区| 久久激情一区| 亚洲国产一区二区三区在线播 | 欧美一区二区三区四区夜夜大片| 久久国产精品亚洲77777| 久久人人爽爽爽人久久久| 男女激情久久| 日韩一区二区精品视频| 亚洲女人av| 欧美大片91| 国产伦精品一区二区三区高清| 伊人久久综合| 亚洲欧美日韩成人| 亚洲国产精品久久久久婷婷老年 | 亚洲动漫精品| 欧美中文在线观看国产| 久久久久久久久久久久久9999| 欧美视频日韩视频| 在线视频日本亚洲性| 亚洲激情一区二区三区| 欧美中在线观看| 国产区二精品视| 久久精品亚洲一区二区| 亚洲免费小视频| 国产精品美女久久久久久2018| 亚洲精品乱码久久久久| 亚洲国产欧美在线人成| 国产精品亚发布| 欧美欧美午夜aⅴ在线观看| 久久亚洲风情| 亚洲精品视频一区二区三区| 欧美在线视频一区二区三区| 欧美激情视频在线播放| 黑人巨大精品欧美一区二区 | 国产精品99久久久久久久久久久久| 久久大综合网| 国产毛片精品国产一区二区三区| 一区二区三区精品国产| 亚洲国产精品传媒在线观看 | 亚洲一区二区三区在线| 亚洲国产裸拍裸体视频在线观看乱了| 欧美在线影院| 国产午夜精品麻豆| 校园春色综合网| 亚洲午夜在线| 国产精品久久久久久模特| 一区二区三区日韩精品| 亚洲美女av电影| 欧美日韩视频在线第一区| 亚洲最黄网站| 一道本一区二区| 国产精品女主播在线观看| 亚洲欧美激情四射在线日 | 亚洲综合色网站| 国产精品久久久一区麻豆最新章节 | 午夜精品久久久久久久男人的天堂| 欧美国产视频在线观看| 免费在线观看日韩欧美| 亚洲日本理论电影| 亚洲国产欧美另类丝袜| 欧美日韩国产不卡| 在线综合视频| 亚洲欧美国产精品桃花| 国产一区久久久| 欧美国产日韩一区二区在线观看| 久久综合久久综合九色| 亚洲狠狠婷婷| 亚洲午夜一区二区| 一区二区三区在线免费播放| 亚洲黄一区二区| 国产精品网站在线播放| 免费亚洲网站| 欧美色图一区二区三区| 久久国产欧美精品| 欧美成人精品影院| 欧美中文在线免费| 久久综合999| 亚洲国产日韩欧美在线图片| 国产精品久久久爽爽爽麻豆色哟哟| 亚洲电影天堂av| 欧美激情一区二区三区全黄| 亚洲欧美日韩久久精品| 久久精品人人做人人爽电影蜜月| 国产伦精品一区二区三区| 久久综合给合| 欧美日韩精品| 久久久久久自在自线| 欧美精品videossex性护士| 亚洲欧美经典视频| 蜜桃av噜噜一区二区三区| 亚洲专区国产精品| 免费观看在线综合色| 欧美一区在线视频| 欧美喷水视频| 免费在线成人av| 国产欧美日韩视频一区二区三区 | 久久精品亚洲乱码伦伦中文| 中文av一区二区| 在线播放日韩专区| 亚洲第一福利社区| av成人黄色| 欧美va天堂在线| 国产欧美日本| 亚洲精品之草原avav久久| 一色屋精品亚洲香蕉网站| 亚洲少妇诱惑| 一区二区三区欧美| 麻豆成人在线播放| 欧美精品自拍| 狠狠色综合网| 亚洲免费视频观看| 亚洲视频在线二区| 一区精品在线播放| 亚洲精品久久久久久久久| 久久精品72免费观看| 国产精品久久久久久久久久尿 | 国产午夜亚洲精品不卡| 欧美aⅴ一区二区三区视频| 国产精品你懂的在线| 亚洲国产99精品国自产| 在线观看欧美激情| 久久av在线| 欧美亚洲系列| 欧美日韩一区在线| 91久久在线| 亚洲美女区一区| 欧美日韩精品一区二区在线播放 | 亚洲在线中文字幕| 欧美日本高清视频| 欧美国产在线观看| 永久免费毛片在线播放不卡| 欧美一区二区精品久久911| 欧美在线高清视频| 国产日韩欧美电影在线观看| 亚洲免费视频观看| 欧美一级久久久| 国产视频精品免费播放| 欧美中文在线视频| 免费国产一区二区| 亚洲另类自拍| 国产精品扒开腿做爽爽爽视频| 亚洲无线视频| 久久午夜视频| 国产日韩欧美在线| 久久亚洲精品视频| 欧美日韩另类综合| 亚洲男人第一网站| 亚洲欧洲av一区二区三区久久| 欧美在线亚洲| 精东粉嫩av免费一区二区三区| 久久久久国产精品一区| 亚洲国产日韩一区| 亚洲另类在线视频| 欧美激情1区2区3区| 亚洲午夜视频在线| 媚黑女一区二区| 亚洲色图自拍| 国产一区二区三区在线观看精品 | 欧美aⅴ一区二区三区视频| 亚洲电影免费观看高清| 中文一区字幕| 国产一区三区三区| 欧美日本韩国一区| 欧美一区三区二区在线观看| 欧美.com| 欧美一区观看| 99精品视频网| 伊人色综合久久天天五月婷| 欧美日韩一级片在线观看| 久久av一区二区三区漫画| 亚洲精品字幕| 米奇777超碰欧美日韩亚洲| 亚洲欧美成人网| 日韩一本二本av| 影音国产精品| 国产美女诱惑一区二区| 欧美国产视频日韩| 久久久夜精品| 欧美在线观看网站| 中文av一区特黄| 日韩一区二区精品葵司在线| 欧美91视频| 久久精品国产亚洲一区二区| 亚洲午夜一区二区三区| 亚洲精品美女在线观看播放| 国外成人在线视频| 国产精品自拍网站| 国产精品vip| 欧美日韩久久| 欧美极品一区|