mfs: restore readonly mounting

. 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>
This commit is contained in:
Ben Gras 2011-12-22 01:29:27 +01:00
parent 9b7d357ca1
commit 9a664b4984
6 changed files with 50 additions and 13 deletions

View 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)

View 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

View 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);
}

View 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;

View 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);

View 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);
rip.i_zone[0] = (zone_t) fs_m_in.REQ_DEV2;
/* 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) 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;
}