Ext3文件读写流程概述

Ext3文件读写流程概述
 
Ext3文件系统在进行读写操作的时候,首先需要open相应的文件,然后再进行读写操作。在open操作时,Linux kernel会创建一个file对象描述这个文件。File对象和文件的dentry和inode对象建立联系,并且将ext3的文件操作方法、映射处理方法(address space)注册到file对象中。
 
Ext3文件读写过程会涉及到VFS层的page cache,并且通常的读写操作都会使用到这层page cache,目的是提高磁盘的IO性能。在Linux中后台会运行writeback线程定时同步pagecache和设备之间的数据。Page cache的方式虽然能够提高IO性能,但是也对数据的安全性带来了潜在影响。
 
本文的目的是分析ext3文件系统读写流程中的关键函数,对于page cache原理以及writeback机制将在后继文章中做深入分析。
 
关键数据结构
 
File数据结构是Linux用来描述文件的关键数据结构,该对象在一个文件被进程打开的时候被创建。当一个文件被关闭的时候,file对象也会被立即销毁。file数据结构不会被作为元数据信息持久化保存至设备。该数据结构定义如下:
 
  
  
  1. struct file {  
  2.     /*  
  3.      * fu_list becomes invalid after file_free is called and queued via  
  4.      * fu_rcuhead for RCU freeing  
  5.      */  
  6.     union {  
  7.         struct list_head    fu_list;  
  8.         struct rcu_head     fu_rcuhead;  
  9.     } f_u;  
  10.     struct path     f_path;     /* 文件路径,包含文件dentry目录项和vfsmount信息 */  
  11. #define f_dentry    f_path.dentry  
  12. #define f_vfsmnt    f_path.mnt  
  13.     const struct file_operations    *f_op;  /* 文件操作函数集 */  
  14.  
  15.     /*  
  16.      * Protects f_ep_links, f_flags, f_pos vs i_size in lseek SEEK_CUR.  
  17.      * Must not be taken from IRQ context.  
  18.      */  
  19.     spinlock_t      f_lock;  
  20. #ifdef CONFIG_SMP  
  21.     int         f_sb_list_cpu;  
  22. #endif  
  23.     atomic_long_t       f_count;  
  24.     unsigned int        f_flags;  
  25.     fmode_t         f_mode; /* 文件操作模式 */  
  26.     loff_t          f_pos;  
  27.     struct fown_struct  f_owner;  
  28.     const struct cred   *f_cred;  
  29.     struct file_ra_state    f_ra;  
  30.  
  31.     u64         f_version;  
  32. #ifdef CONFIG_SECURITY  
  33.     void            *f_security;  
  34. #endif  
  35.     /* needed for tty driver, and maybe others */  
  36.     void            *private_data;  
  37.  
  38. #ifdef CONFIG_EPOLL  
  39.     /* Used by fs/eventpoll.c to link all the hooks to this file */  
  40.     struct list_head    f_ep_links;  
  41.     struct list_head    f_tfile_llink;  
  42. #endif /* #ifdef CONFIG_EPOLL */  
  43.     struct address_space    *f_mapping; /* address space映射信息,指向inode中的i_mapping */  
  44. #ifdef CONFIG_DEBUG_WRITECOUNT  
  45.     unsigned long f_mnt_write_state;  
  46. #endif  
  47. }; 

每个文件在内存中都会对应一个inode对象。在设备上也会保存每个文件的inode元数据信息,通过inode元数据信息可以找到该文件所占用的所有文件数据块(block)。VFS定义了一个通用的inode数据结构,同时ext3定义了ext3_inode元数据结构。在创建内存inode对象时,需要采用ext3_inode元数据信息初始化inode对象。Inode数据结构定义如下:

  
  
  1. struct inode {  
  2.     umode_t         i_mode;  
  3.     unsigned short      i_opflags;  
  4.     uid_t           i_uid;  
  5.     gid_t           i_gid;  
  6.     unsigned int        i_flags;  
  7.  
  8. #ifdef CONFIG_FS_POSIX_ACL  
  9.     struct posix_acl    *i_acl;  
  10.     struct posix_acl    *i_default_acl;  
  11. #endif  
  12.  
  13.     const struct inode_operations   *i_op;  /* inode操作函数集 */  
  14.     struct super_block  *i_sb;      /* 指向superblock */  
  15.     struct address_space    *i_mapping; /* 指向当前使用的页缓存的映射信息 */  
  16.  
  17. #ifdef CONFIG_SECURITY  
  18.     void            *i_security;  
  19. #endif  
  20.  
  21.     /* Stat data, not accessed from path walking */  
  22.     unsigned long       i_ino;  
  23.     /*  
  24.      * Filesystems may only read i_nlink directly.  They shall use the  
  25.      * following functions for modification:  
  26.      *  
  27.      *    (set|clear|inc|drop)_nlink  
  28.      *    inode_(inc|dec)_link_count  
  29.      */  
  30.     union {  
  31.         const unsigned int i_nlink;  
  32.         unsigned int __i_nlink;  
  33.     };  
  34.     dev_t           i_rdev;     /* 设备号,major&minor */  
  35.     struct timespec     i_atime;  
  36.     struct timespec     i_mtime;  
  37.     struct timespec     i_ctime;  
  38.     spinlock_t      i_lock; /* i_blocks, i_bytes, maybe i_size */  
  39.     unsigned short          i_bytes;  
  40.     blkcnt_t        i_blocks;   /* 文件块数量 */  
  41.     loff_t          i_size;  
  42.  
  43. #ifdef __NEED_I_SIZE_ORDERED  
  44.     seqcount_t      i_size_seqcount;  
  45. #endif  
  46.  
  47.     /* Misc */  
  48.     unsigned long       i_state;  
  49.     struct mutex        i_mutex;  
  50.  
  51.     unsigned long       dirtied_when;   /* jiffies of first dirtying */  
  52.  
  53.     struct hlist_node   i_hash; /* 连接到inode Hash Table中 */  
  54.     struct list_head    i_wb_list;  /* backing dev IO list */  
  55.     struct list_head    i_lru;      /* inode LRU list */  
  56.     struct list_head    i_sb_list;  
  57.     union {  
  58.         struct list_head    i_dentry;  
  59.         struct rcu_head     i_rcu;  
  60.     };  
  61.     atomic_t        i_count;  
  62.     unsigned int        i_blkbits;  /* 块大小,通常磁盘块大小为512字节,因此i_blkbits为9 */  
  63.     u64         i_version;  
  64.     atomic_t        i_dio_count;  
  65.     atomic_t        i_writecount;  
  66.     const struct file_operations    *i_fop; /* former ->i_op->default_file_ops,文件操作函数集 */  
  67.     struct file_lock    *i_flock;  
  68.     struct address_space    i_data; /* 页高速缓存映射信息 */  
  69. #ifdef CONFIG_QUOTA  
  70.     struct dquot        *i_dquot[MAXQUOTAS];  
  71. #endif  
  72.     struct list_head    i_devices;  
  73.     union {  
  74.         struct pipe_inode_info  *i_pipe;        /* 管道设备 */  
  75.         struct block_device *i_bdev;    /* block device块设备 */  
  76.         struct cdev     *i_cdev;    /* 字符设备 */  
  77.     };  
  78.  
  79.     __u32           i_generation;  
  80.  
  81. #ifdef CONFIG_FSNOTIFY  
  82.     __u32           i_fsnotify_mask; /* all events this inode cares about */  
  83.     struct hlist_head   i_fsnotify_marks;  
  84. #endif  
  85.  
  86. #ifdef CONFIG_IMA  
  87.     atomic_t        i_readcount; /* struct files open RO */  
  88. #endif  
  89.     void            *i_private; /* fs or device private pointer */  
  90. }; 

 

 

读过程源码分析
 
Ext3文件系统读过程相对比较简单,函数调用关系如下图所示:

 

 
读过程可以分为两大类:Direct_io方式和page_cache方式。对于Direct_io方式,首先通过filemap_write_and_wait_range函数将page cache中的数据与设备同步并且无效掉page cache中的内容,然后再通过ext3提供的direct_io方法从设备读取数据。
另一种是直接从page cache中获取数据,通过do_generic_file_read函数实现该方式。该函数的主要流程说明如下:
1,通过读地址从page cache的radix树中获取相应的page页。
2,如果对应的page页不存在,那么需要创建一个page,然后再从设备读取相应的数据更新至page页。
3,当page页准备完毕之后,从页中拷贝数据至用户空间,page_cache方式的读操作完成。
 
写过程源码分析
 
Ext3的写过程主要分为direct_io写过程和page cache写过程两大类,整个写过程的函数调用关系如下图所示:

 

 
写操作的核心函数是__generic_file_aio_write,该函数实现如下:
  
  
  1. ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,  
  2.                  unsigned long nr_segs, loff_t *ppos)  
  3. {  
  4.     struct file *file = iocb->ki_filp;  
  5.     /* 获取address space映射信息 */  
  6.     struct address_space * mapping = file->f_mapping;  
  7.     size_t ocount;      /* original count */  
  8.     size_t count;       /* after file limit checks */  
  9.     struct inode    *inode = mapping->host; /* 获取文件inode索引节点 */  
  10.     loff_t      pos;  
  11.     ssize_t     written;  
  12.     ssize_t     err;  
  13.  
  14.     ocount = 0;  
  15.     /* 检验数据区域是否存在问题,数据由iov数据结构管理 */  
  16.     err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);  
  17.     if (err)  
  18.         return err;  
  19.     /* ocount为可以写入的数据长度 */  
  20.     count = ocount;  
  21.     pos = *ppos;  
  22.  
  23.     vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);  
  24.  
  25.     /* We can write back this queue in page reclaim */  
  26.     current->backing_dev_info = mapping->backing_dev_info;  
  27.     written = 0;  
  28.     /* 边界检查,需要判断写入数据是否超界、小文件边界检查以及设备是否是read-only。如果超界,那么降低写入数据长度 */  
  29.     err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));  
  30.     if (err)  
  31.         goto out;  
  32.     /* count为实际可以写入的数据长度,如果写入数据长度为0,直接结束 */  
  33.     if (count == 0)  
  34.         goto out;  
  35.  
  36.     err = file_remove_suid(file);  
  37.     if (err)  
  38.         goto out;  
  39.  
  40.     file_update_time(file);  
  41.  
  42.     /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */  
  43.     if (unlikely(file->f_flags & O_DIRECT)) {  
  44.         /* Direct IO操作模式,该模式会bypass Page Cache,直接将数据写入磁盘设备 */  
  45.         loff_t endbyte;  
  46.         ssize_t written_buffered;  
  47.         /* 将对应page cache无效掉,然后将数据直接写入磁盘 */  
  48.         written = generic_file_direct_write(iocb, iov, &nr_segs, pos,  
  49.                             ppos, count, ocount);  
  50.         if (written < 0 || written == count)  
  51.             /* 所有数据已经写入磁盘,正确返回 */  
  52.             goto out;  
  53.         /*  
  54.          * direct-io write to a hole: fall through to buffered I/O  
  55.          * for completing the rest of the request.  
  56.          */  
  57.         pos += written;  
  58.         count -written;  
  59.         /* 有些请求由于没有和块大小(通常为512字节)对齐,那么将无法正确完成direct-io操作。在__blockdev_direct_IO 函数中会检查逻辑地址是否和块大小对齐,__blockdev_direct_IO无法处理不对齐的请求。另外,在ext3逻辑地址和物理块地址映射操作函数ext3_get_block返回失败时,无法完成buffer_head的映射,那么request请求也将无法得到正确处理。所有没有得到处理的请求通过 buffer写的方式得到处理。从这点来看,direct_io并没有完全bypass page cache,在有些情况下是一种写无效模式。generic_file_buffered_write函数完成buffer写,将数据直接写入page cache */  
  60.         written_buffered = generic_file_buffered_write(iocb, iov,  
  61.                         nr_segs, pos, ppos, count,  
  62.                         written);  
  63.         /*  
  64.          * If generic_file_buffered_write() retuned a synchronous error  
  65.          * then we want to return the number of bytes which were  
  66.          * direct-written, or the error code if that was zero.  Note  
  67.          * that this differs from normal direct-io semantics, which  
  68.          * will return -EFOO even if some bytes were written.  
  69.          */  
  70.         if (written_buffered < 0) {  
  71.             /* 如果page cache写失败,那么返回写成功的数据长度 */  
  72.             err = written_buffered;  
  73.             goto out;  
  74.         }  
  75.  
  76.         /*  
  77.          * We need to ensure that the page cache pages are written to  
  78.          * disk and invalidated to preserve the expected O_DIRECT  
  79.          * semantics.  
  80.          */  
  81.         endbyte = pos + written_buffered - written - 1;  
  82.         /* 将page cache中的数据同步到磁盘 */  
  83.         err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);  
  84.         if (err == 0) {  
  85.             written = written_buffered;  
  86.             /* 将page cache无效掉,保证下次读操作从磁盘获取数据 */  
  87.             invalidate_mapping_pages(mapping,  
  88.                          pos >> PAGE_CACHE_SHIFT,  
  89.                          endbyte >> PAGE_CACHE_SHIFT);  
  90.         } else {  
  91.             /*  
  92.              * We don't know how much we wrote, so just return  
  93.              * the number of bytes which were direct-written  
  94.              */  
  95.         }  
  96.     } else {  
  97.         /* 将数据写入page cache。绝大多数的ext3写操作都会采用page cache写方式,通过后台writeback线程将page cache同步到硬盘 */  
  98.         written = generic_file_buffered_write(iocb, iov, nr_segs,  
  99.                 pos, ppos, count, written);  
  100.     }  
  101. out:  
  102.     current->backing_dev_info = NULL;  
  103.     return written ? written : err;  

 

从__generic_file_aio_write函数可以看出,ext3写操作主要分为两大类:一类为direct_io;另一类为buffer_io (page cache write)。Direct IO可以bypass page cache,直接将数据写入设备。下面首先分析一下direct_io的处理流程。

如果操作地址对应的page页存在于page cache中,那么首先需要将这些page页中的数据同磁盘进行同步,然后将这些page缓存页无效掉,从而保证后继读操作能够从磁盘获取最新数据。在代码实现过程中,还需要考虑预读机制引入的page缓存页,所以在数据写入磁盘之后,需要再次查找page cache的radix树,保证写入的地址范围没有数据被缓存。
 
Generic_file_direct_write是处理direct_io的主要函数,该函数的实现如下:
  
  
  1. ssize_t  
  2. generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,  
  3.         unsigned long *nr_segs, loff_t pos, loff_t *ppos,  
  4.         size_t count, size_t ocount)  
  5. {  
  6.     struct file *file = iocb->ki_filp;  
  7.     struct address_space *mapping = file->f_mapping;  
  8.     struct inode    *inode = mapping->host;  
  9.     ssize_t     written;  
  10.     size_t      write_len;  
  11.     pgoff_t     end;  
  12.  
  13.     if (count != ocount)  
  14.         *nr_segs = iov_shorten((struct iovec *)iov, *nr_segs, count);  
  15.  
  16.     write_len = iov_length(iov, *nr_segs);  
  17.     end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT;  
  18.     /* 将对应区域page cache中的新数据页刷新到设备,这个操作是同步的 */  
  19.     written = filemap_write_and_wait_range(mapping, pos, pos + write_len - 1);  
  20.     if (written)  
  21.         goto out;  
  22.  
  23.     /*  
  24.      * After a write we want buffered reads to be sure to go to disk to get  
  25.      * the new data.  We invalidate clean cached page from the region we're  
  26.      * about to write.  We do this *before* the write so that we can return  
  27.      * without clobbering -EIOCBQUEUED from ->direct_IO().  
  28.      */  
  29.     /* 将page cache对应page 缓存无效掉,这样可以保证后继的读操作能从磁盘获取最新数据 */  
  30.     if (mapping->nrpages) {  
  31.         /* 无效对应的page缓存 */  
  32.         written = invalidate_inode_pages2_range(mapping,  
  33.                     pos >> PAGE_CACHE_SHIFT, end);  
  34.         /*  
  35.          * If a page can not be invalidated, return 0 to fall back  
  36.          * to buffered write.  
  37.          */  
  38.         if (written) {  
  39.             if (written == -EBUSY)  
  40.                 return 0;  
  41.             goto out;  
  42.         }  
  43.     }  
  44.     /* 调用ext3文件系统的direct io方法,将数据写入磁盘 */  
  45.     written = mapping->a_ops->direct_IO(WRITE, iocb, iov, pos, *nr_segs);  
  46.  
  47.     /*  
  48.      * Finally, try again to invalidate clean pages which might have been  
  49.      * cached by non-direct readahead, or faulted in by get_user_pages()  
  50.      * if the source of the write was an mmap'ed region of the file  
  51.      * we're writing.  Either one is a pretty crazy thing to do,  
  52.      * so we don't support it 100%.  If this invalidation  
  53.      * fails, tough, the write still worked...  
  54.      */  
  55.     /* 再次无效掉由于预读操作导致的对应地址的page cache缓存页 */  
  56.     if (mapping->nrpages) {  
  57.         invalidate_inode_pages2_range(mapping,  
  58.                           pos >> PAGE_CACHE_SHIFT, end);  
  59.     }  
  60.  
  61.     if (written > 0) {  
  62.         pos += written;  
  63.         if (pos > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {  
  64.             i_size_write(inode, pos);  
  65.             mark_inode_dirty(inode);  
  66.         }  
  67.         *ppos = pos;  
  68.     }  
  69. out:  
  70.     return written;  

 

generic_file_direct_write函数中刷新page cache的函数调用关系描述如下:

filemap_write_and_wait_range à__filemap_fdatawrite_range à do_writepages
do_writepages函数的作用是将page页中的数据同步到设备,该函数实现如下:
 
  
  
  1. int do_writepages(struct address_space *mapping, struct writeback_control *wbc)  
  2. {  
  3.     int ret;  
  4.  
  5.     if (wbc->nr_to_write <= 0)  
  6.         return 0;  
  7.     if (mapping->a_ops->writepages)  
  8.         /* 如果文件系统定义了writepages方法,调用该方法刷新page cache页 */  
  9.         ret = mapping->a_ops->writepages(mapping, wbc);  
  10.     else  
  11.         /* ext3没有定义writepages方法,因此调用generic_writepages()函数将page cache中的脏页刷新到磁盘 */  
  12.         ret = generic_writepages(mapping, wbc);  
  13.     return ret;  

从上述分析可以看出,direct_io需要块大小对齐,否则还会调用page cache的路径。为了提高I/O性能,通常情况下ext3都会采用page cache异步写的方式。这也就是ext3的第二种写操作方式,该方式实现的关键函数是generic_file_buffered_write,其实现如下:

  
  
  1. ssize_t  
  2. generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,  
  3.         unsigned long nr_segs, loff_t pos, loff_t *ppos,  
  4.         size_t count, ssize_t written)  
  5. {  
  6.     struct file *file = iocb->ki_filp;  
  7.     ssize_t status;  
  8.     struct iov_iter i;  
  9.  
  10.     iov_iter_init(&i, iov, nr_segs, count, written);  
  11.     /* 执行page cache写操作 */  
  12.     status = generic_perform_write(file, &i, pos);  
  13.  
  14.     if (likely(status >= 0)) {  
  15.         written += status;  
  16.         *ppos = pos + status;  
  17.     }  
  18.       
  19.     return written ? written : status;  

generic_file_buffered_write其实是对generic_perform_write函数的封装,generic_perform_write实现了page cache写的所有流程,该函数实现如下:

  
  
  1. static ssize_t generic_perform_write(struct file *file,  
  2.                 struct iov_iter *i, loff_t pos)  
  3. {  
  4.     struct address_space *mapping = file->f_mapping;  
  5.     const struct address_space_operations *a_ops = mapping->a_ops;  /* 映射处理函数集 */  
  6.     long status = 0;  
  7.     ssize_t written = 0;  
  8.     unsigned int flags = 0;  
  9.  
  10.     /*  
  11.      * Copies from kernel address space cannot fail (NFSD is a big user).  
  12.      */  
  13.     if (segment_eq(get_fs(), KERNEL_DS))  
  14.         flags |= AOP_FLAG_UNINTERRUPTIBLE;  
  15.  
  16.     do {  
  17.         struct page *page;  
  18.         unsigned long offset;   /* Offset into pagecache page */  
  19.         unsigned long bytes;    /* Bytes to write to page */  
  20.         size_t copied;      /* Bytes copied from user */  
  21.         void *fsdata;  
  22.  
  23.         offset = (pos & (PAGE_CACHE_SIZE - 1));  
  24.         bytes = min_t(unsigned long, PAGE_CACHE_SIZE - offset,  
  25.                         iov_iter_count(i));  
  26.  
  27. again:  
  28.         /*  
  29.          * Bring in the user page that we will copy from _first_.  
  30.          * Otherwise there's a nasty deadlock on copying from the  
  31.          * same page as we're writing to, without it being marked  
  32.          * up-to-date.  
  33.          *  
  34.          * Not only is this an optimisation, but it is also required  
  35.          * to check that the address is actually valid, when atomic  
  36.          * usercopies are used, below.  
  37.          */  
  38.         if (unlikely(iov_iter_fault_in_readable(i, bytes))) {  
  39.             status = -EFAULT;  
  40.             break;  
  41.         }  
  42.         /* 调用ext3中的write_begin函数(inode.c中)ext3_write_begin, 如果写入的page页不存在,那么ext3_write_begin会创建一个Page页,然后从硬盘中读入相应的数据 */  
  43.         status = a_ops->write_begin(file, mapping, pos, bytes, flags,  
  44.                         &page, &fsdata);  
  45.         if (unlikely(status))  
  46.             break;  
  47.  
  48.         if (mapping_writably_mapped(mapping))  
  49.             flush_dcache_page(page);  
  50.  
  51.         pagefault_disable();  
  52.         /* 将数据拷贝到page cache中 */  
  53.         copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes);  
  54.         pagefault_enable();  
  55.         flush_dcache_page(page);  
  56.  
  57.         mark_page_accessed(page);  
  58.         /* 调用ext3的write_end函数(inode.c中),写完数据之后会将page页标识为dirty,后台writeback线程会将dirty page刷新到设备 */  
  59.         status = a_ops->write_end(file, mapping, pos, bytes, copied,  
  60.                         page, fsdata);  
  61.         if (unlikely(status < 0))  
  62.             break;  
  63.         copied = status;  
  64.  
  65.         cond_resched();  
  66.  
  67.         iov_iter_advance(i, copied);  
  68.         if (unlikely(copied == 0)) {  
  69.             /*  
  70.              * If we were unable to copy any data at all, we must  
  71.              * fall back to a single segment length write.  
  72.              *  
  73.              * If we didn't fallback here, we could livelock  
  74.              * because not all segments in the iov can be copied at  
  75.              * once without a pagefault.  
  76.              */  
  77.             bytes = min_t(unsigned long, PAGE_CACHE_SIZE - offset,  
  78.                         iov_iter_single_seg_count(i));  
  79.             goto again;  
  80.         }  
  81.         pos += copied;  
  82.         written += copied;  
  83.  
  84.         balance_dirty_pages_ratelimited(mapping);  
  85.         if (fatal_signal_pending(current)) {  
  86.             status = -EINTR;  
  87.             break;  
  88.         }  
  89.     } while (iov_iter_count(i));  
  90.  
  91.     return written ? written : status;  

 

本文出自 “存储之道” 博客,请务必保留此出处http://alanwu.blog.51cto.com/3652632/1106506

可以读写Ext2,以Ext2方式挂载Ext3文件系统(不支持Ext3日志),不支持中文! It provides Windows NT4.0/2000/XP/2003/Vista/2008 with full access to Linux Ext2 volumes (read access andwrite access). This may be useful if you have installed both Windows and Linux as a dual boot environment on your computer. What features are supported? Complete reading and writing access to files and directories of volumes with theExt2 orExt3 file system. Supports features which are specific to the I/O-system of Windows: Byte Range Locks, Directory Notfication (so the Explorer updates the view of a directory on changes within that directory), Oplocks (so SMB clients are able to cache the content of files). Allows Windows to run with paging files on Ext2 volumes. UTF-8 encoded file names are supported. The driver treats files with file names that start with a dot "." character ashidden. Supports GPT disks if the Windows version used also does. Supports use of the Windows mountvol utility to create or delete drive letters for Ext2 volumes (except on Windows NT 4.0). See also section"Can drive letters also be configured from scripts?". What features are *not* supported? Inodes that are larger than 128 bytes are not supported. Access rights are not maintained. All users can access all the directories and files of an Ext2 volume. If a new file or directory is created, it inherits all the permissions, the GID and the UID from the directory where it has been created. There is one exception to this rule: a file (but not a directory) the driver has created always has cleared "x" permissions, it inherits the "r" and the "w" permissions only. See also section"What limitations arise from not maintaining access rights?". The driver does not allow accessing special files at Ext2 volumes, the access will be always denied. (Special files are sockets, soft links, block devices, character devices and pipes.) Alternate 8.3-DOS names are not supported (just because there is no place to store them in an Ext2 file system). This can prevent legacy DOS applications, executed by the NTVDM of Windows, from accessing some files or directories. Currently the driver does not implement defragging support. So defragmentation applications will neither show fragmentation information nor defragment any Ext2 volume. This software does not achieve booting a Windows operating system from an Ext2 volume. LVM volumes are not supported, so it is not possible to access them.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值