mirror of
https://github.com/psankar/simplefs.git
synced 2025-07-23 05:54:39 +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;
|
||||
mark_buffer_dirty(bh);
|
||||
sync_dirty_buffer(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
|
||||
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);
|
||||
simplefs_sb_sync(vsb);
|
||||
brelse(bh);
|
||||
|
||||
mutex_unlock(&simplefs_sb_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);
|
||||
record++;
|
||||
}
|
||||
brelse(bh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -243,6 +246,8 @@ ssize_t simplefs_read(struct file * filp, char __user * buf, size_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Read request for file of size: [%llu]\n",
|
||||
inode->file_size);
|
||||
if (*ppos >= inode->file_size) {
|
||||
/* Read request with offset beyond the filesize */
|
||||
return 0;
|
||||
@ -258,7 +263,7 @@ ssize_t simplefs_read(struct file * filp, char __user * buf, size_t len,
|
||||
}
|
||||
|
||||
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)) {
|
||||
brelse(bh);
|
||||
@ -275,8 +280,117 @@ ssize_t simplefs_read(struct file * filp, char __user * buf, size_t len,
|
||||
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 = {
|
||||
.read = simplefs_read
|
||||
.read = simplefs_read,
|
||||
.write = simplefs_write,
|
||||
};
|
||||
|
||||
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);
|
||||
sync_dirty_buffer(bh);
|
||||
brelse(bh);
|
||||
|
||||
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);
|
||||
sync_dirty_buffer(bh);
|
||||
brelse(bh);
|
||||
|
||||
mutex_unlock(&simplefs_inodes_mgmt_lock);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user