Commit 42d163d0 authored by Nick Piggin's avatar Nick Piggin Committed by James Toy

Signed-off-by: Nick Piggin <npiggin@suse.de>

Acked-by: default avatarJan Kara <jack@suse.cz>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Cc: Chris Mason <chris.mason@oracle.com>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: Steven French <sfrench@us.ibm.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent cfd8a4d6
...@@ -217,5 +217,6 @@ const struct file_operations udf_file_operations = { ...@@ -217,5 +217,6 @@ const struct file_operations udf_file_operations = {
}; };
const struct inode_operations udf_file_inode_operations = { const struct inode_operations udf_file_inode_operations = {
.truncate = udf_truncate, .new_truncate = 1,
.setattr = udf_setattr,
}; };
...@@ -67,6 +67,7 @@ static void udf_update_extents(struct inode *, ...@@ -67,6 +67,7 @@ static void udf_update_extents(struct inode *,
struct extent_position *); struct extent_position *);
static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
static void udf_truncate_blocks(struct inode *inode);
void udf_delete_inode(struct inode *inode) void udf_delete_inode(struct inode *inode)
{ {
...@@ -76,7 +77,7 @@ void udf_delete_inode(struct inode *inode) ...@@ -76,7 +77,7 @@ void udf_delete_inode(struct inode *inode)
goto no_delete; goto no_delete;
inode->i_size = 0; inode->i_size = 0;
udf_truncate(inode); udf_truncate_blocks(inode);
lock_kernel(); lock_kernel();
udf_update_inode(inode, IS_SYNC(inode)); udf_update_inode(inode, IS_SYNC(inode));
...@@ -124,9 +125,34 @@ static int udf_write_begin(struct file *file, struct address_space *mapping, ...@@ -124,9 +125,34 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags, loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata) struct page **pagep, void **fsdata)
{ {
int ret;
*pagep = NULL; *pagep = NULL;
return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
udf_get_block); udf_get_block);
if (ret < 0) {
struct inode *inode = mapping->host;
loff_t isize = inode->i_size;
if (pos + len > isize)
udf_truncate_blocks(inode);
}
return ret;
}
static int udf_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata)
{
int ret;
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
if (ret < len) {
struct inode *inode = mapping->host;
loff_t isize = inode->i_size;
if (pos + len > isize)
udf_truncate_blocks(inode);
}
return ret;
} }
static sector_t udf_bmap(struct address_space *mapping, sector_t block) static sector_t udf_bmap(struct address_space *mapping, sector_t block)
...@@ -139,7 +165,7 @@ const struct address_space_operations udf_aops = { ...@@ -139,7 +165,7 @@ const struct address_space_operations udf_aops = {
.writepage = udf_writepage, .writepage = udf_writepage,
.sync_page = block_sync_page, .sync_page = block_sync_page,
.write_begin = udf_write_begin, .write_begin = udf_write_begin,
.write_end = generic_write_end, .write_end = udf_write_end,
.bmap = udf_bmap, .bmap = udf_bmap,
}; };
...@@ -1012,7 +1038,7 @@ struct buffer_head *udf_bread(struct inode *inode, int block, ...@@ -1012,7 +1038,7 @@ struct buffer_head *udf_bread(struct inode *inode, int block,
return NULL; return NULL;
} }
void udf_truncate(struct inode *inode) static void udf_truncate_blocks(struct inode *inode)
{ {
int offset; int offset;
int err; int err;
...@@ -1058,6 +1084,43 @@ void udf_truncate(struct inode *inode) ...@@ -1058,6 +1084,43 @@ void udf_truncate(struct inode *inode)
unlock_kernel(); unlock_kernel();
} }
static int udf_setsize(struct inode *inode, loff_t newsize)
{
loff_t oldsize;
int error;
error = inode_newsize_ok(inode, newsize);
if (error)
return error;
oldsize = inode->i_size;
i_size_write(inode, newsize);
truncate_pagecache(inode, oldsize, newsize);
udf_truncate_blocks(inode);
return error;
}
int udf_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int error;
if (attr->ia_valid & ATTR_SIZE) {
error = udf_setsize(inode, attr->ia_size);
if (error)
return error;
}
error = simple_setattr(dentry, attr);
if (error)
return error;
mark_inode_dirty(inode);
return error;
}
static void __udf_read_inode(struct inode *inode) static void __udf_read_inode(struct inode *inode)
{ {
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
......
...@@ -138,7 +138,7 @@ extern int udf_sync_inode(struct inode *); ...@@ -138,7 +138,7 @@ extern int udf_sync_inode(struct inode *);
extern void udf_expand_file_adinicb(struct inode *, int, int *); extern void udf_expand_file_adinicb(struct inode *, int, int *);
extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
extern struct buffer_head *udf_bread(struct inode *, int, int, int *); extern struct buffer_head *udf_bread(struct inode *, int, int, int *);
extern void udf_truncate(struct inode *); extern int udf_setattr(struct dentry *, struct iattr *);
extern void udf_read_inode(struct inode *); extern void udf_read_inode(struct inode *);
extern void udf_delete_inode(struct inode *); extern void udf_delete_inode(struct inode *);
extern void udf_clear_inode(struct inode *); extern void udf_clear_inode(struct inode *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment