diff options
Diffstat (limited to 'fs/udf')
-rw-r--r-- | fs/udf/Kconfig | 1 | ||||
-rw-r--r-- | fs/udf/file.c | 23 | ||||
-rw-r--r-- | fs/udf/ialloc.c | 2 | ||||
-rw-r--r-- | fs/udf/inode.c | 61 | ||||
-rw-r--r-- | fs/udf/namei.c | 2 | ||||
-rw-r--r-- | fs/udf/super.c | 13 | ||||
-rw-r--r-- | fs/udf/udfdecl.h | 3 |
7 files changed, 62 insertions, 43 deletions
diff --git a/fs/udf/Kconfig b/fs/udf/Kconfig index 0e0e99bd6bce..f8def3c8ea4c 100644 --- a/fs/udf/Kconfig +++ b/fs/udf/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | config UDF_FS | 1 | config UDF_FS |
2 | tristate "UDF file system support" | 2 | tristate "UDF file system support" |
3 | depends on BKL # needs serious work to remove | ||
3 | select CRC_ITU_T | 4 | select CRC_ITU_T |
4 | help | 5 | help |
5 | This is the new file system used on some CD-ROMs and DVDs. Say Y if | 6 | This is the new file system used on some CD-ROMs and DVDs. Say Y if |
diff --git a/fs/udf/file.c b/fs/udf/file.c index 94e06d6bddbd..66b9e7e7e4c5 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/pagemap.h> | 36 | #include <linux/pagemap.h> |
37 | #include <linux/buffer_head.h> | 37 | #include <linux/buffer_head.h> |
38 | #include <linux/aio.h> | 38 | #include <linux/aio.h> |
39 | #include <linux/smp_lock.h> | ||
40 | 39 | ||
41 | #include "udf_i.h" | 40 | #include "udf_i.h" |
42 | #include "udf_sb.h" | 41 | #include "udf_sb.h" |
@@ -228,6 +227,28 @@ const struct file_operations udf_file_operations = { | |||
228 | .llseek = generic_file_llseek, | 227 | .llseek = generic_file_llseek, |
229 | }; | 228 | }; |
230 | 229 | ||
230 | static int udf_setattr(struct dentry *dentry, struct iattr *attr) | ||
231 | { | ||
232 | struct inode *inode = dentry->d_inode; | ||
233 | int error; | ||
234 | |||
235 | error = inode_change_ok(inode, attr); | ||
236 | if (error) | ||
237 | return error; | ||
238 | |||
239 | if ((attr->ia_valid & ATTR_SIZE) && | ||
240 | attr->ia_size != i_size_read(inode)) { | ||
241 | error = vmtruncate(inode, attr->ia_size); | ||
242 | if (error) | ||
243 | return error; | ||
244 | } | ||
245 | |||
246 | setattr_copy(inode, attr); | ||
247 | mark_inode_dirty(inode); | ||
248 | return 0; | ||
249 | } | ||
250 | |||
231 | const struct inode_operations udf_file_inode_operations = { | 251 | const struct inode_operations udf_file_inode_operations = { |
252 | .setattr = udf_setattr, | ||
232 | .truncate = udf_truncate, | 253 | .truncate = udf_truncate, |
233 | }; | 254 | }; |
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 18cd7111185d..75d9304d0dc3 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c | |||
@@ -31,8 +31,6 @@ void udf_free_inode(struct inode *inode) | |||
31 | struct super_block *sb = inode->i_sb; | 31 | struct super_block *sb = inode->i_sb; |
32 | struct udf_sb_info *sbi = UDF_SB(sb); | 32 | struct udf_sb_info *sbi = UDF_SB(sb); |
33 | 33 | ||
34 | clear_inode(inode); | ||
35 | |||
36 | mutex_lock(&sbi->s_alloc_mutex); | 34 | mutex_lock(&sbi->s_alloc_mutex); |
37 | if (sbi->s_lvid_bh) { | 35 | if (sbi->s_lvid_bh) { |
38 | struct logicalVolIntegrityDescImpUse *lvidiu = | 36 | struct logicalVolIntegrityDescImpUse *lvidiu = |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 124852bcf6fe..fc48f37aa2dd 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -68,37 +68,23 @@ static void udf_update_extents(struct inode *, | |||
68 | static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); | 68 | static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); |
69 | 69 | ||
70 | 70 | ||
71 | void udf_delete_inode(struct inode *inode) | 71 | void udf_evict_inode(struct inode *inode) |
72 | { | ||
73 | truncate_inode_pages(&inode->i_data, 0); | ||
74 | |||
75 | if (is_bad_inode(inode)) | ||
76 | goto no_delete; | ||
77 | |||
78 | inode->i_size = 0; | ||
79 | udf_truncate(inode); | ||
80 | lock_kernel(); | ||
81 | |||
82 | udf_update_inode(inode, IS_SYNC(inode)); | ||
83 | udf_free_inode(inode); | ||
84 | |||
85 | unlock_kernel(); | ||
86 | return; | ||
87 | |||
88 | no_delete: | ||
89 | clear_inode(inode); | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * If we are going to release inode from memory, we truncate last inode extent | ||
94 | * to proper length. We could use drop_inode() but it's called under inode_lock | ||
95 | * and thus we cannot mark inode dirty there. We use clear_inode() but we have | ||
96 | * to make sure to write inode as it's not written automatically. | ||
97 | */ | ||
98 | void udf_clear_inode(struct inode *inode) | ||
99 | { | 72 | { |
100 | struct udf_inode_info *iinfo = UDF_I(inode); | 73 | struct udf_inode_info *iinfo = UDF_I(inode); |
74 | int want_delete = 0; | ||
75 | |||
76 | truncate_inode_pages(&inode->i_data, 0); | ||
101 | 77 | ||
78 | if (!inode->i_nlink && !is_bad_inode(inode)) { | ||
79 | want_delete = 1; | ||
80 | inode->i_size = 0; | ||
81 | udf_truncate(inode); | ||
82 | lock_kernel(); | ||
83 | udf_update_inode(inode, IS_SYNC(inode)); | ||
84 | unlock_kernel(); | ||
85 | } | ||
86 | invalidate_inode_buffers(inode); | ||
87 | end_writeback(inode); | ||
102 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && | 88 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && |
103 | inode->i_size != iinfo->i_lenExtents) { | 89 | inode->i_size != iinfo->i_lenExtents) { |
104 | printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has " | 90 | printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has " |
@@ -108,9 +94,13 @@ void udf_clear_inode(struct inode *inode) | |||
108 | (unsigned long long)inode->i_size, | 94 | (unsigned long long)inode->i_size, |
109 | (unsigned long long)iinfo->i_lenExtents); | 95 | (unsigned long long)iinfo->i_lenExtents); |
110 | } | 96 | } |
111 | |||
112 | kfree(iinfo->i_ext.i_data); | 97 | kfree(iinfo->i_ext.i_data); |
113 | iinfo->i_ext.i_data = NULL; | 98 | iinfo->i_ext.i_data = NULL; |
99 | if (want_delete) { | ||
100 | lock_kernel(); | ||
101 | udf_free_inode(inode); | ||
102 | unlock_kernel(); | ||
103 | } | ||
114 | } | 104 | } |
115 | 105 | ||
116 | static int udf_writepage(struct page *page, struct writeback_control *wbc) | 106 | static int udf_writepage(struct page *page, struct writeback_control *wbc) |
@@ -127,9 +117,16 @@ static int udf_write_begin(struct file *file, struct address_space *mapping, | |||
127 | loff_t pos, unsigned len, unsigned flags, | 117 | loff_t pos, unsigned len, unsigned flags, |
128 | struct page **pagep, void **fsdata) | 118 | struct page **pagep, void **fsdata) |
129 | { | 119 | { |
130 | *pagep = NULL; | 120 | int ret; |
131 | return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 121 | |
132 | udf_get_block); | 122 | ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block); |
123 | if (unlikely(ret)) { | ||
124 | loff_t isize = mapping->host->i_size; | ||
125 | if (pos + len > isize) | ||
126 | vmtruncate(mapping->host, isize); | ||
127 | } | ||
128 | |||
129 | return ret; | ||
133 | } | 130 | } |
134 | 131 | ||
135 | static sector_t udf_bmap(struct address_space *mapping, sector_t block) | 132 | static sector_t udf_bmap(struct address_space *mapping, sector_t block) |
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index bf5fc674193c..6d8dc02baebb 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -1101,7 +1101,7 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir, | |||
1101 | inc_nlink(inode); | 1101 | inc_nlink(inode); |
1102 | inode->i_ctime = current_fs_time(inode->i_sb); | 1102 | inode->i_ctime = current_fs_time(inode->i_sb); |
1103 | mark_inode_dirty(inode); | 1103 | mark_inode_dirty(inode); |
1104 | atomic_inc(&inode->i_count); | 1104 | ihold(inode); |
1105 | d_instantiate(dentry, inode); | 1105 | d_instantiate(dentry, inode); |
1106 | unlock_kernel(); | 1106 | unlock_kernel(); |
1107 | 1107 | ||
diff --git a/fs/udf/super.c b/fs/udf/super.c index 612d1e2e285a..76f3d6d97b40 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -175,8 +175,7 @@ static const struct super_operations udf_sb_ops = { | |||
175 | .alloc_inode = udf_alloc_inode, | 175 | .alloc_inode = udf_alloc_inode, |
176 | .destroy_inode = udf_destroy_inode, | 176 | .destroy_inode = udf_destroy_inode, |
177 | .write_inode = udf_write_inode, | 177 | .write_inode = udf_write_inode, |
178 | .delete_inode = udf_delete_inode, | 178 | .evict_inode = udf_evict_inode, |
179 | .clear_inode = udf_clear_inode, | ||
180 | .put_super = udf_put_super, | 179 | .put_super = udf_put_super, |
181 | .sync_fs = udf_sync_fs, | 180 | .sync_fs = udf_sync_fs, |
182 | .statfs = udf_statfs, | 181 | .statfs = udf_statfs, |
@@ -1579,9 +1578,7 @@ static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh, | |||
1579 | { | 1578 | { |
1580 | struct anchorVolDescPtr *anchor; | 1579 | struct anchorVolDescPtr *anchor; |
1581 | long main_s, main_e, reserve_s, reserve_e; | 1580 | long main_s, main_e, reserve_s, reserve_e; |
1582 | struct udf_sb_info *sbi; | ||
1583 | 1581 | ||
1584 | sbi = UDF_SB(sb); | ||
1585 | anchor = (struct anchorVolDescPtr *)bh->b_data; | 1582 | anchor = (struct anchorVolDescPtr *)bh->b_data; |
1586 | 1583 | ||
1587 | /* Locate the main sequence */ | 1584 | /* Locate the main sequence */ |
@@ -1883,6 +1880,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1883 | struct kernel_lb_addr rootdir, fileset; | 1880 | struct kernel_lb_addr rootdir, fileset; |
1884 | struct udf_sb_info *sbi; | 1881 | struct udf_sb_info *sbi; |
1885 | 1882 | ||
1883 | lock_kernel(); | ||
1884 | |||
1886 | uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); | 1885 | uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); |
1887 | uopt.uid = -1; | 1886 | uopt.uid = -1; |
1888 | uopt.gid = -1; | 1887 | uopt.gid = -1; |
@@ -1891,8 +1890,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1891 | uopt.dmode = UDF_INVALID_MODE; | 1890 | uopt.dmode = UDF_INVALID_MODE; |
1892 | 1891 | ||
1893 | sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL); | 1892 | sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL); |
1894 | if (!sbi) | 1893 | if (!sbi) { |
1894 | unlock_kernel(); | ||
1895 | return -ENOMEM; | 1895 | return -ENOMEM; |
1896 | } | ||
1896 | 1897 | ||
1897 | sb->s_fs_info = sbi; | 1898 | sb->s_fs_info = sbi; |
1898 | 1899 | ||
@@ -2038,6 +2039,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
2038 | goto error_out; | 2039 | goto error_out; |
2039 | } | 2040 | } |
2040 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 2041 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
2042 | unlock_kernel(); | ||
2041 | return 0; | 2043 | return 0; |
2042 | 2044 | ||
2043 | error_out: | 2045 | error_out: |
@@ -2058,6 +2060,7 @@ error_out: | |||
2058 | kfree(sbi); | 2060 | kfree(sbi); |
2059 | sb->s_fs_info = NULL; | 2061 | sb->s_fs_info = NULL; |
2060 | 2062 | ||
2063 | unlock_kernel(); | ||
2061 | return -EINVAL; | 2064 | return -EINVAL; |
2062 | } | 2065 | } |
2063 | 2066 | ||
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 2bac0354891f..6995ab1f4305 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
@@ -139,8 +139,7 @@ extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); | |||
139 | extern struct buffer_head *udf_bread(struct inode *, int, int, int *); | 139 | extern struct buffer_head *udf_bread(struct inode *, int, int, int *); |
140 | extern void udf_truncate(struct inode *); | 140 | extern void udf_truncate(struct inode *); |
141 | extern void udf_read_inode(struct inode *); | 141 | extern void udf_read_inode(struct inode *); |
142 | extern void udf_delete_inode(struct inode *); | 142 | extern void udf_evict_inode(struct inode *); |
143 | extern void udf_clear_inode(struct inode *); | ||
144 | extern int udf_write_inode(struct inode *, struct writeback_control *wbc); | 143 | extern int udf_write_inode(struct inode *, struct writeback_control *wbc); |
145 | extern long udf_block_map(struct inode *, sector_t); | 144 | extern long udf_block_map(struct inode *, sector_t); |
146 | extern int udf_extend_file(struct inode *, struct extent_position *, | 145 | extern int udf_extend_file(struct inode *, struct extent_position *, |