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:
parent
9b7d357ca1
commit
9a664b4984
@ -2,7 +2,7 @@
|
|||||||
#ifndef _MFS_CLEAN_H
|
#ifndef _MFS_CLEAN_H
|
||||||
#define _MFS_CLEAN_H 1
|
#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 MARKCLEAN(b) ((b)->b_dirt = BP_CLEAN)
|
||||||
|
|
||||||
#define ISDIRTY(b) ((b)->b_dirt == BP_DIRTY)
|
#define ISDIRTY(b) ((b)->b_dirt == BP_DIRTY)
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
|
||||||
|
#include "super.h"
|
||||||
|
|
||||||
EXTERN struct inode {
|
EXTERN struct inode {
|
||||||
u16_t i_mode; /* file type, protection, etc. */
|
u16_t i_mode; /* file type, protection, etc. */
|
||||||
u16_t i_nlinks; /* how many links to this file */
|
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 ISEEK 1 /* i_seek = ISEEK if last op was SEEK */
|
||||||
|
|
||||||
#define IN_MARKCLEAN(i) i->i_dirt = IN_CLEAN
|
#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_ISCLEAN(i) i->i_dirt == IN_CLEAN
|
||||||
#define IN_ISDIRTY(i) i->i_dirt == IN_DIRTY
|
#define IN_ISDIRTY(i) i->i_dirt == IN_DIRTY
|
||||||
|
@ -148,8 +148,10 @@ PUBLIC int fs_unlink()
|
|||||||
return(r);
|
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(). */
|
/* 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
|
/* Only the su may unlink directories, but the su can unlink any
|
||||||
* dir.*/
|
* dir.*/
|
||||||
if( (rip->i_mode & I_TYPE) == I_DIRECTORY) r = EPERM;
|
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)
|
if( (rip = find_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL)
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
|
|
||||||
start = fs_m_in.REQ_TRC_START_LO;
|
if(rip->i_sp->s_rd_only) {
|
||||||
end = fs_m_in.REQ_TRC_END_LO;
|
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);
|
r = truncate_inode(rip, start);
|
||||||
else
|
else
|
||||||
r = freesp_inode(rip, start, end);
|
r = freesp_inode(rip, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,6 +494,9 @@ int check_permissions; /* check permissions when flag is !IS_EMPTY */
|
|||||||
if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY) {
|
if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY) {
|
||||||
return(ENOTDIR);
|
return(ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if((flag == DELETE || flag == ENTER) && ldir_ptr->i_sp->s_rd_only)
|
||||||
|
return EROFS;
|
||||||
|
|
||||||
r = OK;
|
r = OK;
|
||||||
|
|
||||||
|
@ -21,6 +21,11 @@ PUBLIC int fs_chmod()
|
|||||||
/* Temporarily open the file. */
|
/* Temporarily open the file. */
|
||||||
if( (rip = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL)
|
if( (rip = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL)
|
||||||
return(EINVAL);
|
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 */
|
/* 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);
|
rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES);
|
||||||
|
@ -62,7 +62,11 @@ PUBLIC int fs_readwrite(void)
|
|||||||
|
|
||||||
rdwt_err = OK; /* set to EIO if disk error occurs */
|
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 (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. */
|
/* Check in advance to see if file will grow too big. */
|
||||||
if (position > (off_t) (rip->i_sp->s_max_size - nrbytes))
|
if (position > (off_t) (rip->i_sp->s_max_size - nrbytes))
|
||||||
return(EFBIG);
|
return(EFBIG);
|
||||||
@ -73,6 +77,11 @@ PUBLIC int fs_readwrite(void)
|
|||||||
*/
|
*/
|
||||||
if(position > f_size) clear_zone(rip, f_size, 0);
|
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;
|
cum_io = 0;
|
||||||
/* Split the transfer into chunks that don't span two blocks. */
|
/* 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 != OK) r = rdwt_err; /* check for disk error */
|
||||||
if (rdwt_err == END_OF_FILE) r = OK;
|
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 == READING) rip->i_update |= ATIME;
|
||||||
if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
|
if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
|
||||||
IN_MARKDIRTY(rip); /* inode is thus now dirty */
|
IN_MARKDIRTY(rip); /* inode is thus now dirty */
|
||||||
@ -136,11 +148,14 @@ PUBLIC int fs_breadwrite(void)
|
|||||||
u64_t position;
|
u64_t position;
|
||||||
unsigned int off, cum_io, chunk, block_size;
|
unsigned int off, cum_io, chunk, block_size;
|
||||||
size_t nrbytes;
|
size_t nrbytes;
|
||||||
|
dev_t target_dev;
|
||||||
|
|
||||||
/* Pseudo inode for rw_chunk */
|
/* Pseudo inode for rw_chunk */
|
||||||
struct inode rip;
|
struct inode rip;
|
||||||
|
|
||||||
r = OK;
|
r = OK;
|
||||||
|
|
||||||
|
target_dev = (dev_t) fs_m_in.REQ_DEV2;
|
||||||
|
|
||||||
/* Get the values from the request message */
|
/* Get the values from the request message */
|
||||||
rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
|
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);
|
(unsigned long) fs_m_in.REQ_SEEK_POS_HI);
|
||||||
nrbytes = (size_t) fs_m_in.REQ_NBYTES;
|
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_mode = I_BLOCK_SPECIAL;
|
||||||
rip.i_size = 0;
|
rip.i_size = 0;
|
||||||
|
|
||||||
@ -642,8 +661,10 @@ PUBLIC int fs_getdents(void)
|
|||||||
else {
|
else {
|
||||||
fs_m_out.RES_NBYTES = userbuf_off;
|
fs_m_out.RES_NBYTES = userbuf_off;
|
||||||
fs_m_out.RES_SEEK_POS_LO = new_pos;
|
fs_m_out.RES_SEEK_POS_LO = new_pos;
|
||||||
rip->i_update |= ATIME;
|
if(!rip->i_sp->s_rd_only) {
|
||||||
IN_MARKDIRTY(rip);
|
rip->i_update |= ATIME;
|
||||||
|
IN_MARKDIRTY(rip);
|
||||||
|
}
|
||||||
r = OK;
|
r = OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user