summaryrefslogtreecommitdiffstats
path: root/fs/udf/file.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
commit529c593ece216e4aaffd36bd940cb94f1fa63129 (patch)
tree78f1c0b805f5656aa7b0417a043c5346f700a2cf /fs/udf/file.c
parent0bd079751d25808d1972baee5c4eaa1db2227257 (diff)
Merge with 2.3.43. I did ignore all modifications to the qlogicisp.c
driver due to the Origin A64 hacks.
Diffstat (limited to 'fs/udf/file.c')
-rw-r--r--fs/udf/file.c229
1 files changed, 87 insertions, 142 deletions
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 8ea44d2a8..5cf51cd0e 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -72,110 +72,119 @@ static loff_t udf_file_llseek(struct file * file, loff_t offset, int origin)
return offset;
}
-static inline void remove_suid(struct inode * inode)
+static int udf_adinicb_readpage(struct dentry *dentry, struct page * page)
{
- unsigned int mode;
+ struct inode *inode = dentry->d_inode;
- /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
- mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
-
- /* was any of the uid bits set? */
- mode &= inode->i_mode;
- if (mode && !capable(CAP_FSETID))
- {
- inode->i_mode &= ~mode;
- mark_inode_dirty(inode);
- }
-}
-
-static ssize_t udf_file_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
- ssize_t retval;
- struct inode *inode = file->f_dentry->d_inode;
+ struct buffer_head *bh;
+ unsigned long kaddr = 0;
- retval = generic_file_write(file, buf, count, ppos, block_write_partial_page);
+ if (!PageLocked(page))
+ PAGE_BUG(page);
- if (retval > 0)
- {
- remove_suid(inode);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
- mark_inode_dirty(inode);
- }
- return retval;
+ kaddr = kmap(page);
+ memset((char *)kaddr, 0, PAGE_CACHE_SIZE);
+ bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
+ ll_rw_block (READ, 1, &bh);
+ wait_on_buffer(bh);
+ memcpy((char *)kaddr, bh->b_data + udf_ext0_offset(inode),
+ inode->i_size);
+ brelse(bh);
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
}
-int udf_write_partial_page_adinicb(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+static int udf_adinicb_writepage(struct dentry *dentry, struct page *page)
{
- struct inode *inode = file->f_dentry->d_inode;
- int err = 0, block;
+ struct inode *inode = dentry->d_inode;
+
struct buffer_head *bh;
unsigned long kaddr = 0;
if (!PageLocked(page))
BUG();
- if (offset < 0 || offset >= (inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode)))
- BUG();
- if (bytes+offset < 0 || bytes+offset > (inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode)))
- BUG();
kaddr = kmap(page);
- block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
- bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
+ bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
if (!buffer_uptodate(bh))
{
ll_rw_block (READ, 1, &bh);
wait_on_buffer(bh);
}
- err = copy_from_user((char *)kaddr + offset, buf, bytes);
+ memcpy(bh->b_data + udf_ext0_offset(inode), (char *)kaddr,
+ inode->i_size);
+ ll_rw_block (WRITE, 1, &bh);
+ wait_on_buffer(bh);
+ brelse(bh);
+ SetPageUptodate(page);
+ kunmap(page);
+ return 0;
+}
+
+static int udf_adinicb_prepare_write(struct page *page, unsigned offset, unsigned to)
+{
+ kmap(page);
+ return 0;
+}
+
+static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct buffer_head *bh;
+ char *kaddr = (char*)page_address(page);
+ bh = bread (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
+ if (!buffer_uptodate(bh)) {
+ ll_rw_block (READ, 1, &bh);
+ wait_on_buffer(bh);
+ }
memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
- (char *)kaddr + offset, bytes);
+ kaddr + offset, to-offset);
mark_buffer_dirty(bh, 0);
brelse(bh);
kunmap(page);
SetPageUptodate(page);
- return bytes;
+ return 0;
}
-static ssize_t udf_file_write_adinicb(struct file * file, const char * buf,
+struct address_space_operations udf_adinicb_aops = {
+ readpage: udf_adinicb_readpage,
+ writepage: udf_adinicb_writepage,
+ prepare_write: udf_adinicb_prepare_write,
+ commit_write: udf_adinicb_commit_write
+};
+
+static ssize_t udf_file_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
ssize_t retval;
struct inode *inode = file->f_dentry->d_inode;
int err, pos;
- if (file->f_flags & O_APPEND)
- pos = inode->i_size;
- else
- pos = *ppos;
-
- if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
- pos + count))
- {
- udf_expand_file_adinicb(file, pos + count, &err);
- if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
- {
- udf_debug("udf_expand_adinicb: err=%d\n", err);
- return err;
- }
- else
- return udf_file_write(file, buf, count, ppos);
- }
- else
- {
- if (pos + count > inode->i_size)
- UDF_I_LENALLOC(inode) = pos + count;
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+ if (file->f_flags & O_APPEND)
+ pos = inode->i_size;
else
- UDF_I_LENALLOC(inode) = inode->i_size;
+ pos = *ppos;
+
+ if (inode->i_sb->s_blocksize <
+ (udf_file_entry_alloc_offset(inode) + pos + count)) {
+ udf_expand_file_adinicb(file, pos + count, &err);
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+ udf_debug("udf_expand_adinicb: err=%d\n", err);
+ return err;
+ }
+ } else {
+ if (pos + count > inode->i_size)
+ UDF_I_LENALLOC(inode) = pos + count;
+ else
+ UDF_I_LENALLOC(inode) = inode->i_size;
+ }
}
- retval = generic_file_write(file, buf, count, ppos, udf_write_partial_page_adinicb);
-
- if (retval > 0)
- {
- remove_suid(inode);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ retval = generic_file_write(file, buf, count, ppos);
+ if (retval > 0) {
UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
mark_inode_dirty(inode);
}
@@ -338,83 +347,19 @@ static int udf_open_file(struct inode * inode, struct file * filp)
}
static struct file_operations udf_file_operations = {
- udf_file_llseek, /* llseek */
- generic_file_read, /* read */
- udf_file_write, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- udf_ioctl, /* ioctl */
- generic_file_mmap, /* mmap */
- udf_open_file, /* open */
- NULL, /* flush */
- udf_release_file, /* release */
- udf_sync_file, /* fsync */
- NULL, /* fasync */
- NULL /* lock */
+ llseek: udf_file_llseek,
+ read: generic_file_read,
+ write: udf_file_write,
+ ioctl: udf_ioctl,
+ mmap: generic_file_mmap,
+ open: udf_open_file,
+ release: udf_release_file,
+ fsync: udf_sync_file,
};
struct inode_operations udf_file_inode_operations = {
&udf_file_operations,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- udf_get_block, /* get_block */
- block_read_full_page, /* readpage */
- block_write_full_page, /* writepage */
-#if CONFIG_UDF_RW == 1
- udf_truncate, /* truncate */
-#else
- NULL, /* truncate */
-#endif
- NULL, /* permission */
- NULL /* revalidate */
-};
-
-static struct file_operations udf_file_operations_adinicb = {
- udf_file_llseek, /* llseek */
- generic_file_read, /* read */
- udf_file_write_adinicb, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- udf_ioctl, /* ioctl */
- NULL, /* mmap */
- NULL, /* open */
- NULL, /* flush */
- udf_release_file, /* release */
- udf_sync_file_adinicb, /* fsync */
- NULL, /* fasync */
- NULL /* lock */
-};
-
-struct inode_operations udf_file_inode_operations_adinicb = {
- &udf_file_operations_adinicb,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- udf_get_block, /* get_block */
- udf_readpage_adinicb, /* readpage */
- udf_writepage_adinicb, /* writepage */
#if CONFIG_UDF_RW == 1
- udf_truncate_adinicb, /* truncate */
-#else
- NULL, /* truncate */
+ truncate: udf_truncate,
#endif
- NULL, /* permission */
- NULL /* revalidate */
};