mirror of
https://github.com/psankar/simplefs.git
synced 2025-07-23 22:15:03 +02:00
basic write support
This commit is contained in:
parent
22f33bcd32
commit
a68d101c93
120
simple.c
120
simple.c
@ -38,6 +38,7 @@ void simplefs_sb_sync(struct super_block *vsb)
|
|||||||
bh->b_data = (char *)sb;
|
bh->b_data = (char *)sb;
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
sync_dirty_buffer(bh);
|
sync_dirty_buffer(bh);
|
||||||
|
brelse(bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplefs_inode_add(struct super_block *vsb, struct simplefs_inode *inode)
|
void simplefs_inode_add(struct super_block *vsb, struct simplefs_inode *inode)
|
||||||
@ -71,6 +72,7 @@ void simplefs_inode_add(struct super_block *vsb, struct simplefs_inode *inode)
|
|||||||
|
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
simplefs_sb_sync(vsb);
|
simplefs_sb_sync(vsb);
|
||||||
|
brelse(bh);
|
||||||
|
|
||||||
mutex_unlock(&simplefs_sb_lock);
|
mutex_unlock(&simplefs_sb_lock);
|
||||||
mutex_unlock(&simplefs_inodes_mgmt_lock);
|
mutex_unlock(&simplefs_inodes_mgmt_lock);
|
||||||
@ -180,6 +182,7 @@ static int simplefs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||||||
pos += sizeof(struct simplefs_dir_record);
|
pos += sizeof(struct simplefs_dir_record);
|
||||||
record++;
|
record++;
|
||||||
}
|
}
|
||||||
|
brelse(bh);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -243,6 +246,8 @@ ssize_t simplefs_read(struct file * filp, char __user * buf, size_t len,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk(KERN_INFO "Read request for file of size: [%llu]\n",
|
||||||
|
inode->file_size);
|
||||||
if (*ppos >= inode->file_size) {
|
if (*ppos >= inode->file_size) {
|
||||||
/* Read request with offset beyond the filesize */
|
/* Read request with offset beyond the filesize */
|
||||||
return 0;
|
return 0;
|
||||||
@ -258,7 +263,7 @@ ssize_t simplefs_read(struct file * filp, char __user * buf, size_t len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer = (char *)bh->b_data;
|
buffer = (char *)bh->b_data;
|
||||||
nbytes = min(strlen(buffer), len);
|
nbytes = min((size_t) inode->file_size, len);
|
||||||
|
|
||||||
if (copy_to_user(buf, buffer, nbytes)) {
|
if (copy_to_user(buf, buffer, nbytes)) {
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
@ -275,8 +280,117 @@ ssize_t simplefs_read(struct file * filp, char __user * buf, size_t len,
|
|||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: The write support is rudimentary. I have not figured out a way to do writes
|
||||||
|
* from particular offsets (even though I have written some untested code for this below) efficiently. */
|
||||||
|
ssize_t simplefs_write(struct file * filp, const char __user * buf, size_t len,
|
||||||
|
loff_t * ppos)
|
||||||
|
{
|
||||||
|
/* After the commit dd37978c5 in the upstream linux kernel,
|
||||||
|
* we can use just filp->f_inode instead of the
|
||||||
|
* f->f_path.dentry->d_inode redirection */
|
||||||
|
struct inode *inode;
|
||||||
|
struct simplefs_inode *sfs_inode;
|
||||||
|
struct simplefs_inode *inode_iterator;
|
||||||
|
struct buffer_head *bh;
|
||||||
|
struct super_block *sb;
|
||||||
|
|
||||||
|
char *buffer;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
printk(KERN_INFO "file size write begins\n");
|
||||||
|
|
||||||
|
inode = filp->f_path.dentry->d_inode;
|
||||||
|
sfs_inode = SIMPLEFS_INODE(inode);
|
||||||
|
sb = inode->i_sb;
|
||||||
|
|
||||||
|
if (*ppos + len >= SIMPLEFS_DEFAULT_BLOCK_SIZE) {
|
||||||
|
printk(KERN_ERR "File size write will exceed a block");
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
bh = (struct buffer_head *)sb_bread(filp->f_path.dentry->d_inode->i_sb,
|
||||||
|
sfs_inode->data_block_number);
|
||||||
|
|
||||||
|
if (!bh) {
|
||||||
|
printk(KERN_ERR "Reading the block number [%llu] failed.",
|
||||||
|
sfs_inode->data_block_number);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
buffer = (char *)bh->b_data;
|
||||||
|
|
||||||
|
/* Move the pointer until the required byte offset */
|
||||||
|
buffer += *ppos;
|
||||||
|
|
||||||
|
if (copy_from_user(buffer, buf, len)) {
|
||||||
|
brelse(bh);
|
||||||
|
printk(KERN_ERR
|
||||||
|
"Error copying file contents from the userspace buffer to the kernel space\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
*ppos += len;
|
||||||
|
|
||||||
|
mark_buffer_dirty(bh);
|
||||||
|
sync_dirty_buffer(bh);
|
||||||
|
brelse(bh);
|
||||||
|
|
||||||
|
/* Set new size
|
||||||
|
* sfs_inode->file_size = max(sfs_inode->file_size, *ppos);
|
||||||
|
*
|
||||||
|
* FIXME: What to do if someone writes only some parts in between ?
|
||||||
|
* The above code will also fail in case a file is overwritten with
|
||||||
|
* a shorter buffer */
|
||||||
|
|
||||||
|
if (mutex_lock_interruptible(&simplefs_inodes_mgmt_lock)) {
|
||||||
|
printk(KERN_ERR "Failed to acquire mutex lock %s +%d\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
return -EINTR;
|
||||||
|
}
|
||||||
|
/* Save the modified inode */
|
||||||
|
bh = (struct buffer_head *)sb_bread(sb,
|
||||||
|
SIMPLEFS_INODESTORE_BLOCK_NUMBER);
|
||||||
|
|
||||||
|
sfs_inode->file_size = *ppos;
|
||||||
|
|
||||||
|
inode_iterator = (struct simplefs_inode *)bh->b_data;
|
||||||
|
|
||||||
|
if (mutex_lock_interruptible(&simplefs_sb_lock)) {
|
||||||
|
printk(KERN_ERR "Failed to acquire mutex lock %s +%d\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
return -EINTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
while (inode_iterator->inode_no != sfs_inode->inode_no
|
||||||
|
&& count < SIMPLEFS_SB(sb)->inodes_count) {
|
||||||
|
count++;
|
||||||
|
inode_iterator++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (likely(count < SIMPLEFS_SB(sb)->inodes_count)) {
|
||||||
|
inode_iterator->file_size = sfs_inode->file_size;
|
||||||
|
printk(KERN_INFO
|
||||||
|
"The new filesize that is written is: [%llu] and len was: [%lu]\n",
|
||||||
|
sfs_inode->file_size, len);
|
||||||
|
|
||||||
|
mark_buffer_dirty(bh);
|
||||||
|
sync_dirty_buffer(bh);
|
||||||
|
} else {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"The new filesize could not be stored to the inode.");
|
||||||
|
len = -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
brelse(bh);
|
||||||
|
|
||||||
|
mutex_unlock(&simplefs_sb_lock);
|
||||||
|
mutex_unlock(&simplefs_inodes_mgmt_lock);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
const struct file_operations simplefs_file_operations = {
|
const struct file_operations simplefs_file_operations = {
|
||||||
.read = simplefs_read
|
.read = simplefs_read,
|
||||||
|
.write = simplefs_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct file_operations simplefs_dir_operations = {
|
const struct file_operations simplefs_dir_operations = {
|
||||||
@ -408,6 +522,7 @@ static int simplefs_create_fs_object(struct inode *dir, struct dentry *dentry,
|
|||||||
|
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
sync_dirty_buffer(bh);
|
sync_dirty_buffer(bh);
|
||||||
|
brelse(bh);
|
||||||
|
|
||||||
parent_dir_inode->dir_children_count++;
|
parent_dir_inode->dir_children_count++;
|
||||||
|
|
||||||
@ -423,6 +538,7 @@ static int simplefs_create_fs_object(struct inode *dir, struct dentry *dentry,
|
|||||||
|
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
sync_dirty_buffer(bh);
|
sync_dirty_buffer(bh);
|
||||||
|
brelse(bh);
|
||||||
|
|
||||||
mutex_unlock(&simplefs_inodes_mgmt_lock);
|
mutex_unlock(&simplefs_inodes_mgmt_lock);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user