Blame view
fs/udf/file.c
6.17 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 |
/* * file.c * * PURPOSE * File handling routines for the OSTA-UDF(tm) filesystem. * |
1da177e4c Linux-2.6.12-rc2 |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
* COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. * * (C) 1998-1999 Dave Boynton * (C) 1998-2004 Ben Fennema * (C) 1999-2000 Stelias Computing Inc * * HISTORY * * 10/02/98 dgb Attempt to integrate into udf.o * 10/07/98 Switched to using generic_readpage, etc., like isofs * And it works! * 12/06/98 blf Added udf_file_read. uses generic_file_read for all cases but * ICBTAG_FLAG_AD_IN_ICB. * 04/06/99 64 bit file handling on 32 bit systems taken from ext2 file.c * 05/12/99 Preliminary file write support */ #include "udfdecl.h" #include <linux/fs.h> |
1da177e4c Linux-2.6.12-rc2 |
30 31 |
#include <asm/uaccess.h> #include <linux/kernel.h> |
28de7948a UDF: coding style... |
32 |
#include <linux/string.h> /* memset */ |
16f7e0fe2 [PATCH] capable/c... |
33 |
#include <linux/capability.h> |
1da177e4c Linux-2.6.12-rc2 |
34 |
#include <linux/errno.h> |
1da177e4c Linux-2.6.12-rc2 |
35 36 |
#include <linux/pagemap.h> #include <linux/buffer_head.h> |
e8edc6e03 Detach sched.h fr... |
37 |
#include <linux/aio.h> |
1da177e4c Linux-2.6.12-rc2 |
38 39 40 |
#include "udf_i.h" #include "udf_sb.h" |
cb00ea352 UDF: coding style... |
41 |
static int udf_adinicb_readpage(struct file *file, struct page *page) |
1da177e4c Linux-2.6.12-rc2 |
42 43 44 |
{ struct inode *inode = page->mapping->host; char *kaddr; |
48d6d8ff7 udf: cache struct... |
45 |
struct udf_inode_info *iinfo = UDF_I(inode); |
1da177e4c Linux-2.6.12-rc2 |
46 |
|
cd7619d6b [PATCH] Extermina... |
47 |
BUG_ON(!PageLocked(page)); |
1da177e4c Linux-2.6.12-rc2 |
48 49 50 |
kaddr = kmap(page); memset(kaddr, 0, PAGE_CACHE_SIZE); |
48d6d8ff7 udf: cache struct... |
51 |
memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size); |
1da177e4c Linux-2.6.12-rc2 |
52 53 54 55 |
flush_dcache_page(page); SetPageUptodate(page); kunmap(page); unlock_page(page); |
28de7948a UDF: coding style... |
56 |
|
1da177e4c Linux-2.6.12-rc2 |
57 58 |
return 0; } |
4b11111ab udf: fix coding s... |
59 60 |
static int udf_adinicb_writepage(struct page *page, struct writeback_control *wbc) |
1da177e4c Linux-2.6.12-rc2 |
61 62 63 |
{ struct inode *inode = page->mapping->host; char *kaddr; |
48d6d8ff7 udf: cache struct... |
64 |
struct udf_inode_info *iinfo = UDF_I(inode); |
1da177e4c Linux-2.6.12-rc2 |
65 |
|
cd7619d6b [PATCH] Extermina... |
66 |
BUG_ON(!PageLocked(page)); |
1da177e4c Linux-2.6.12-rc2 |
67 68 |
kaddr = kmap(page); |
48d6d8ff7 udf: cache struct... |
69 |
memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, inode->i_size); |
1da177e4c Linux-2.6.12-rc2 |
70 71 72 73 |
mark_inode_dirty(inode); SetPageUptodate(page); kunmap(page); unlock_page(page); |
28de7948a UDF: coding style... |
74 |
|
1da177e4c Linux-2.6.12-rc2 |
75 76 |
return 0; } |
be021ee41 udf: convert to n... |
77 78 79 80 |
static int udf_adinicb_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) |
1da177e4c Linux-2.6.12-rc2 |
81 |
{ |
be021ee41 udf: convert to n... |
82 83 84 |
struct inode *inode = mapping->host; unsigned offset = pos & (PAGE_CACHE_SIZE - 1); char *kaddr; |
48d6d8ff7 udf: cache struct... |
85 |
struct udf_inode_info *iinfo = UDF_I(inode); |
1da177e4c Linux-2.6.12-rc2 |
86 |
|
be021ee41 udf: convert to n... |
87 |
kaddr = kmap_atomic(page, KM_USER0); |
48d6d8ff7 udf: cache struct... |
88 |
memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr + offset, |
be021ee41 udf: convert to n... |
89 90 91 92 |
kaddr + offset, copied); kunmap_atomic(kaddr, KM_USER0); return simple_write_end(file, mapping, pos, len, copied, page, fsdata); |
1da177e4c Linux-2.6.12-rc2 |
93 |
} |
f5e54d6e5 [PATCH] mark addr... |
94 |
const struct address_space_operations udf_adinicb_aops = { |
28de7948a UDF: coding style... |
95 96 |
.readpage = udf_adinicb_readpage, .writepage = udf_adinicb_writepage, |
be021ee41 udf: convert to n... |
97 98 |
.write_begin = simple_write_begin, .write_end = udf_adinicb_write_end, |
1da177e4c Linux-2.6.12-rc2 |
99 |
}; |
543ade1fc [PATCH] Streamlin... |
100 |
static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, |
cb00ea352 UDF: coding style... |
101 |
unsigned long nr_segs, loff_t ppos) |
1da177e4c Linux-2.6.12-rc2 |
102 103 |
{ ssize_t retval; |
543ade1fc [PATCH] Streamlin... |
104 |
struct file *file = iocb->ki_filp; |
5096e933a [PATCH] struct pa... |
105 |
struct inode *inode = file->f_path.dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
106 |
int err, pos; |
543ade1fc [PATCH] Streamlin... |
107 |
size_t count = iocb->ki_left; |
48d6d8ff7 udf: cache struct... |
108 |
struct udf_inode_info *iinfo = UDF_I(inode); |
1da177e4c Linux-2.6.12-rc2 |
109 |
|
8754a3f71 udf: Protect udf_... |
110 |
down_write(&iinfo->i_data_sem); |
48d6d8ff7 udf: cache struct... |
111 |
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { |
1da177e4c Linux-2.6.12-rc2 |
112 113 114 |
if (file->f_flags & O_APPEND) pos = inode->i_size; else |
543ade1fc [PATCH] Streamlin... |
115 |
pos = ppos; |
1da177e4c Linux-2.6.12-rc2 |
116 |
|
4b11111ab udf: fix coding s... |
117 118 |
if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) + |
28de7948a UDF: coding style... |
119 |
pos + count)) { |
7e49b6f24 udf: Convert UDF ... |
120 121 |
err = udf_expand_file_adinicb(inode); if (err) { |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 |
udf_debug("udf_expand_adinicb: err=%d ", err); return err; } |
cb00ea352 UDF: coding style... |
126 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
127 |
if (pos + count > inode->i_size) |
48d6d8ff7 udf: cache struct... |
128 |
iinfo->i_lenAlloc = pos + count; |
1da177e4c Linux-2.6.12-rc2 |
129 |
else |
48d6d8ff7 udf: cache struct... |
130 |
iinfo->i_lenAlloc = inode->i_size; |
d2eb8c359 udf: Fix deadlock... |
131 |
up_write(&iinfo->i_data_sem); |
1da177e4c Linux-2.6.12-rc2 |
132 |
} |
d2eb8c359 udf: Fix deadlock... |
133 134 |
} else up_write(&iinfo->i_data_sem); |
1da177e4c Linux-2.6.12-rc2 |
135 |
|
543ade1fc [PATCH] Streamlin... |
136 |
retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); |
1da177e4c Linux-2.6.12-rc2 |
137 138 |
if (retval > 0) mark_inode_dirty(inode); |
28de7948a UDF: coding style... |
139 |
|
1da177e4c Linux-2.6.12-rc2 |
140 141 |
return retval; } |
2f07a88b3 udf: BKL ioctl pu... |
142 |
long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
143 |
{ |
2f07a88b3 udf: BKL ioctl pu... |
144 |
struct inode *inode = filp->f_dentry->d_inode; |
28de7948a UDF: coding style... |
145 |
long old_block, new_block; |
1da177e4c Linux-2.6.12-rc2 |
146 |
int result = -EINVAL; |
6f2861097 switch udf_ioctl(... |
147 |
if (inode_permission(inode, MAY_READ) != 0) { |
2f07a88b3 udf: BKL ioctl pu... |
148 149 150 151 |
udf_debug("no permission to access inode %lu ", inode->i_ino); result = -EPERM; goto out; |
1da177e4c Linux-2.6.12-rc2 |
152 |
} |
cb00ea352 UDF: coding style... |
153 |
if (!arg) { |
1da177e4c Linux-2.6.12-rc2 |
154 155 |
udf_debug("invalid argument to udf_ioctl "); |
2f07a88b3 udf: BKL ioctl pu... |
156 157 |
result = -EINVAL; goto out; |
1da177e4c Linux-2.6.12-rc2 |
158 |
} |
cb00ea352 UDF: coding style... |
159 160 |
switch (cmd) { case UDF_GETVOLIDENT: |
4b11111ab udf: fix coding s... |
161 162 |
if (copy_to_user((char __user *)arg, UDF_SB(inode->i_sb)->s_volume_ident, 32)) |
2f07a88b3 udf: BKL ioctl pu... |
163 |
result = -EFAULT; |
4b11111ab udf: fix coding s... |
164 |
else |
2f07a88b3 udf: BKL ioctl pu... |
165 166 |
result = 0; goto out; |
cb00ea352 UDF: coding style... |
167 |
case UDF_RELOCATE_BLOCKS: |
2f07a88b3 udf: BKL ioctl pu... |
168 169 170 171 172 173 174 175 |
if (!capable(CAP_SYS_ADMIN)) { result = -EACCES; goto out; } if (get_user(old_block, (long __user *)arg)) { result = -EFAULT; goto out; } |
4b11111ab udf: fix coding s... |
176 177 178 |
result = udf_relocate_blocks(inode->i_sb, old_block, &new_block); if (result == 0) |
28de7948a UDF: coding style... |
179 |
result = put_user(new_block, (long __user *)arg); |
2f07a88b3 udf: BKL ioctl pu... |
180 |
goto out; |
cb00ea352 UDF: coding style... |
181 |
case UDF_GETEASIZE: |
c0b344385 udf: remove UDF_I... |
182 |
result = put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg); |
2f07a88b3 udf: BKL ioctl pu... |
183 |
goto out; |
cb00ea352 UDF: coding style... |
184 |
case UDF_GETEABLOCK: |
c0b344385 udf: remove UDF_I... |
185 186 187 |
result = copy_to_user((char __user *)arg, UDF_I(inode)->i_ext.i_data, UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0; |
2f07a88b3 udf: BKL ioctl pu... |
188 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
189 |
} |
2f07a88b3 udf: BKL ioctl pu... |
190 |
out: |
1da177e4c Linux-2.6.12-rc2 |
191 192 |
return result; } |
cb00ea352 UDF: coding style... |
193 |
static int udf_release_file(struct inode *inode, struct file *filp) |
1da177e4c Linux-2.6.12-rc2 |
194 |
{ |
cb00ea352 UDF: coding style... |
195 |
if (filp->f_mode & FMODE_WRITE) { |
cbc8cc335 udf: Fix possible... |
196 |
mutex_lock(&inode->i_mutex); |
4d0fb621d udf: Replace bkl ... |
197 |
down_write(&UDF_I(inode)->i_data_sem); |
1da177e4c Linux-2.6.12-rc2 |
198 |
udf_discard_prealloc(inode); |
2c948b3f8 udf: Avoid IO in ... |
199 |
udf_truncate_tail_extent(inode); |
4d0fb621d udf: Replace bkl ... |
200 |
up_write(&UDF_I(inode)->i_data_sem); |
cbc8cc335 udf: Fix possible... |
201 |
mutex_unlock(&inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
202 203 204 |
} return 0; } |
4b6f5d20b [PATCH] Make most... |
205 |
const struct file_operations udf_file_operations = { |
28de7948a UDF: coding style... |
206 207 |
.read = do_sync_read, .aio_read = generic_file_aio_read, |
2f07a88b3 udf: BKL ioctl pu... |
208 |
.unlocked_ioctl = udf_ioctl, |
363504628 udf: Remove dead ... |
209 |
.open = generic_file_open, |
28de7948a UDF: coding style... |
210 211 212 213 |
.mmap = generic_file_mmap, .write = do_sync_write, .aio_write = udf_file_aio_write, .release = udf_release_file, |
1b061d924 rename the generi... |
214 |
.fsync = generic_file_fsync, |
28de7948a UDF: coding style... |
215 |
.splice_read = generic_file_splice_read, |
5c89468c1 udf: add llseek m... |
216 |
.llseek = generic_file_llseek, |
1da177e4c Linux-2.6.12-rc2 |
217 |
}; |
d39aae9ec add missing setat... |
218 219 220 221 222 223 224 225 |
static int udf_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; int error; error = inode_change_ok(inode, attr); if (error) return error; |
1025774ce remove inode_setattr |
226 227 228 |
if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size != i_size_read(inode)) { |
7e49b6f24 udf: Convert UDF ... |
229 |
error = udf_setsize(inode, attr->ia_size); |
1025774ce remove inode_setattr |
230 231 232 233 234 235 236 |
if (error) return error; } setattr_copy(inode, attr); mark_inode_dirty(inode); return 0; |
d39aae9ec add missing setat... |
237 |
} |
c5ef1c42c [PATCH] mark stru... |
238 |
const struct inode_operations udf_file_inode_operations = { |
d39aae9ec add missing setat... |
239 |
.setattr = udf_setattr, |
1da177e4c Linux-2.6.12-rc2 |
240 |
}; |