]> Zhao Yanbai Git Server - minix.git/commitdiff
mfs: restore readonly mounting
authorBen Gras <ben@minix3.org>
Thu, 22 Dec 2011 00:29:27 +0000 (01:29 +0100)
committerBen Gras <ben@minix3.org>
Thu, 22 Dec 2011 00:29:27 +0000 (01:29 +0100)
. use dirty marking hooks to check and warn
  when inodes/bufs are marked dirty on a readonly
  mounted fs
. add readonly mount checks to restore readonly
  mounting

Signed-off-by: Ben Gras <ben@minix3.org>
servers/mfs/clean.h
servers/mfs/inode.h
servers/mfs/link.c
servers/mfs/path.c
servers/mfs/protect.c
servers/mfs/read.c

index 6f740a198fea1e3289cc452d87c45d9f3bd87bda..626c7aceca61dba8ce8083c3931eb4fb3abc0653 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _MFS_CLEAN_H
 #define _MFS_CLEAN_H 1
 
-#define MARKDIRTY(b) ((b)->b_dirt = BP_DIRTY)
+#define MARKDIRTY(b) do { if(superblock.s_dev == (b)->b_dev && superblock.s_rd_only) { printf("%s:%d: dirty block on rofs! ", __FILE__, __LINE__); util_stacktrace(); } else { (b)->b_dirt = BP_DIRTY; } } while(0)
 #define MARKCLEAN(b) ((b)->b_dirt = BP_CLEAN)
 
 #define ISDIRTY(b)     ((b)->b_dirt == BP_DIRTY)
index ea2038eee9d87c3c3817c31d847e392b466625d9..112defb61edd26123cea939ae96878c3fb01b77a 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <sys/queue.h>
 
+#include "super.h"
+
 EXTERN struct inode {
   u16_t i_mode;                /* file type, protection, etc. */
   u16_t i_nlinks;              /* how many links to this file */
@@ -63,7 +65,7 @@ EXTERN unsigned int inode_cache_miss;
 #define ISEEK              1   /* i_seek = ISEEK if last op was SEEK */
 
 #define IN_MARKCLEAN(i) i->i_dirt = IN_CLEAN
-#define IN_MARKDIRTY(i) i->i_dirt = IN_DIRTY
+#define IN_MARKDIRTY(i) do { if(i->i_sp->s_rd_only) { printf("%s:%d: dirty inode on rofs ", __FILE__, __LINE__); util_stacktrace(); } else { i->i_dirt = IN_DIRTY; } } while(0)
 
 #define IN_ISCLEAN(i) i->i_dirt == IN_CLEAN
 #define IN_ISDIRTY(i) i->i_dirt == IN_DIRTY
index a872b865b18fc066867987de97a0127fe5ff726b..49854634e2a1d2ad11e579497a65c3a05f1d1c03 100644 (file)
@@ -148,8 +148,10 @@ PUBLIC int fs_unlink()
        return(r);
   }
   
+  if(rip->i_sp->s_rd_only) {
+       r = EROFS;
+  }  else if(fs_m_in.m_type == REQ_UNLINK) {
   /* Now test if the call is allowed, separately for unlink() and rmdir(). */
-  if(fs_m_in.m_type == REQ_UNLINK) {
          /* Only the su may unlink directories, but the su can unlink any
           * dir.*/
          if( (rip->i_mode & I_TYPE) == I_DIRECTORY) r = EPERM;
@@ -496,14 +498,18 @@ PUBLIC int fs_ftrunc(void)
   if( (rip = find_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL)
          return(EINVAL);
 
-  start = fs_m_in.REQ_TRC_START_LO;
-  end = fs_m_in.REQ_TRC_END_LO;
+  if(rip->i_sp->s_rd_only) {
+       r = EROFS;
+  } else {
+    start = fs_m_in.REQ_TRC_START_LO;
+    end = fs_m_in.REQ_TRC_END_LO;
 
-  if (end == 0)
+    if (end == 0)
          r = truncate_inode(rip, start);
-  else 
+    else 
          r = freesp_inode(rip, start, end);
-  
+  }
+
   return(r);
 }
     
index 804cde6a6534e16c6baa191d46431261a1b2bfaf..efab7a3334c9d2c6454f69f96eaca42c46e38f12 100644 (file)
@@ -494,6 +494,9 @@ int check_permissions;               /* check permissions when flag is !IS_EMPTY */
   if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY)  {
        return(ENOTDIR);
    }
+
+  if((flag == DELETE || flag == ENTER) && ldir_ptr->i_sp->s_rd_only)
+       return EROFS;
   
   r = OK;
 
index b2d92c078f4084de96cad0339c3a60996c2addd0..7e46ae3185ca87415207a4c8bbccbf5679a97534 100644 (file)
@@ -21,6 +21,11 @@ PUBLIC int fs_chmod()
   /* Temporarily open the file. */
   if( (rip = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL)
          return(EINVAL);
+  if(rip->i_sp->s_rd_only) {
+       put_inode(rip);
+       return EROFS;
+  }
 
   /* Now make the change. Clear setgid bit if file is not in caller's grp */
   rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES);
index b89ae25a95215672f5d4528333c391ba2484b515..6ec47b272800861ec704f4c9fbda07f676e6dfb1 100644 (file)
@@ -62,7 +62,11 @@ PUBLIC int fs_readwrite(void)
   
   rdwt_err = OK;               /* set to EIO if disk error occurs */
 
+  /* If this is file i/o, check we can write */
   if (rw_flag == WRITING && !block_spec) {
+         if(rip->i_sp->s_rd_only) 
+                 return EROFS;
+
          /* Check in advance to see if file will grow too big. */
          if (position > (off_t) (rip->i_sp->s_max_size - nrbytes))
                  return(EFBIG);
@@ -73,6 +77,11 @@ PUBLIC int fs_readwrite(void)
           */
          if(position > f_size) clear_zone(rip, f_size, 0);
   }
+
+  /* If this is block i/o, check we can write */
+  if(block_spec && rw_flag == WRITING &&
+       (dev_t) rip->i_zone[0] == superblock.s_dev && superblock.s_rd_only)
+               return EROFS;
              
   cum_io = 0;
   /* Split the transfer into chunks that don't span two blocks. */
@@ -114,7 +123,10 @@ PUBLIC int fs_readwrite(void)
   if (rdwt_err != OK) r = rdwt_err;    /* check for disk error */
   if (rdwt_err == END_OF_FILE) r = OK;
 
-  if (r == OK) {
+  /* even on a ROFS, writing to a device node on it is fine, 
+   * just don't update the inode stats for it. And dito for reading.
+   */
+  if (r == OK && !rip->i_sp->s_rd_only) {
          if (rw_flag == READING) rip->i_update |= ATIME;
          if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
          IN_MARKDIRTY(rip);            /* inode is thus now dirty */
@@ -136,11 +148,14 @@ PUBLIC int fs_breadwrite(void)
   u64_t position;
   unsigned int off, cum_io, chunk, block_size;
   size_t nrbytes;
+  dev_t target_dev;
 
   /* Pseudo inode for rw_chunk */
   struct inode rip;
   
   r = OK;
+
+  target_dev = (dev_t) fs_m_in.REQ_DEV2;
   
   /* Get the values from the request message */ 
   rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
@@ -149,9 +164,13 @@ PUBLIC int fs_breadwrite(void)
                    (unsigned long) fs_m_in.REQ_SEEK_POS_HI);
   nrbytes = (size_t) fs_m_in.REQ_NBYTES;
   
-  block_size = get_block_size( (dev_t) fs_m_in.REQ_DEV2);
+  block_size = get_block_size(target_dev);
+
+  /* Don't block-write to a RO-mounted filesystem. */
+  if(superblock.s_dev == target_dev && superblock.s_rd_only)
+       return EROFS;
 
-  rip.i_zone[0] = (zone_t) fs_m_in.REQ_DEV2;
+  rip.i_zone[0] = (zone_t) target_dev;
   rip.i_mode = I_BLOCK_SPECIAL;
   rip.i_size = 0;
 
@@ -642,8 +661,10 @@ PUBLIC int fs_getdents(void)
   else {
          fs_m_out.RES_NBYTES = userbuf_off;
          fs_m_out.RES_SEEK_POS_LO = new_pos;
-         rip->i_update |= ATIME;
-         IN_MARKDIRTY(rip);
+         if(!rip->i_sp->s_rd_only) {
+                 rip->i_update |= ATIME;
+                 IN_MARKDIRTY(rip);
+         }
          r = OK;
   }