OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [udf/] [file.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * file.c
3
 *
4
 * PURPOSE
5
 *  File handling routines for the OSTA-UDF(tm) filesystem.
6
 *
7
 * COPYRIGHT
8
 *  This file is distributed under the terms of the GNU General Public
9
 *  License (GPL). Copies of the GPL can be obtained from:
10
 *    ftp://prep.ai.mit.edu/pub/gnu/GPL
11
 *  Each contributing author retains all rights to their own work.
12
 *
13
 *  (C) 1998-1999 Dave Boynton
14
 *  (C) 1998-2004 Ben Fennema
15
 *  (C) 1999-2000 Stelias Computing Inc
16
 *
17
 * HISTORY
18
 *
19
 *  10/02/98 dgb  Attempt to integrate into udf.o
20
 *  10/07/98      Switched to using generic_readpage, etc., like isofs
21
 *                And it works!
22
 *  12/06/98 blf  Added udf_file_read. uses generic_file_read for all cases but
23
 *                ICBTAG_FLAG_AD_IN_ICB.
24
 *  04/06/99      64 bit file handling on 32 bit systems taken from ext2 file.c
25
 *  05/12/99      Preliminary file write support
26
 */
27
 
28
#include "udfdecl.h"
29
#include <linux/fs.h>
30
#include <linux/udf_fs.h>
31
#include <asm/uaccess.h>
32
#include <linux/kernel.h>
33
#include <linux/string.h> /* memset */
34
#include <linux/capability.h>
35
#include <linux/errno.h>
36
#include <linux/smp_lock.h>
37
#include <linux/pagemap.h>
38
#include <linux/buffer_head.h>
39
#include <linux/aio.h>
40
 
41
#include "udf_i.h"
42
#include "udf_sb.h"
43
 
44
static int udf_adinicb_readpage(struct file *file, struct page *page)
45
{
46
        struct inode *inode = page->mapping->host;
47
        char *kaddr;
48
 
49
        BUG_ON(!PageLocked(page));
50
 
51
        kaddr = kmap(page);
52
        memset(kaddr, 0, PAGE_CACHE_SIZE);
53
        memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), inode->i_size);
54
        flush_dcache_page(page);
55
        SetPageUptodate(page);
56
        kunmap(page);
57
        unlock_page(page);
58
 
59
        return 0;
60
}
61
 
62
static int udf_adinicb_writepage(struct page *page, struct writeback_control *wbc)
63
{
64
        struct inode *inode = page->mapping->host;
65
        char *kaddr;
66
 
67
        BUG_ON(!PageLocked(page));
68
 
69
        kaddr = kmap(page);
70
        memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size);
71
        mark_inode_dirty(inode);
72
        SetPageUptodate(page);
73
        kunmap(page);
74
        unlock_page(page);
75
 
76
        return 0;
77
}
78
 
79
static int udf_adinicb_write_end(struct file *file,
80
                        struct address_space *mapping,
81
                        loff_t pos, unsigned len, unsigned copied,
82
                        struct page *page, void *fsdata)
83
{
84
        struct inode *inode = mapping->host;
85
        unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
86
        char *kaddr;
87
 
88
        kaddr = kmap_atomic(page, KM_USER0);
89
        memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset,
90
                kaddr + offset, copied);
91
        kunmap_atomic(kaddr, KM_USER0);
92
 
93
        return simple_write_end(file, mapping, pos, len, copied, page, fsdata);
94
}
95
 
96
const struct address_space_operations udf_adinicb_aops = {
97
        .readpage       = udf_adinicb_readpage,
98
        .writepage      = udf_adinicb_writepage,
99
        .sync_page      = block_sync_page,
100
        .write_begin = simple_write_begin,
101
        .write_end = udf_adinicb_write_end,
102
};
103
 
104
static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
105
                                  unsigned long nr_segs, loff_t ppos)
106
{
107
        ssize_t retval;
108
        struct file *file = iocb->ki_filp;
109
        struct inode *inode = file->f_path.dentry->d_inode;
110
        int err, pos;
111
        size_t count = iocb->ki_left;
112
 
113
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) {
114
                if (file->f_flags & O_APPEND)
115
                        pos = inode->i_size;
116
                else
117
                        pos = ppos;
118
 
119
                if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
120
                                                pos + count)) {
121
                        udf_expand_file_adinicb(inode, pos + count, &err);
122
                        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) {
123
                                udf_debug("udf_expand_adinicb: err=%d\n", err);
124
                                return err;
125
                        }
126
                } else {
127
                        if (pos + count > inode->i_size)
128
                                UDF_I_LENALLOC(inode) = pos + count;
129
                        else
130
                                UDF_I_LENALLOC(inode) = inode->i_size;
131
                }
132
        }
133
 
134
        retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
135
        if (retval > 0)
136
                mark_inode_dirty(inode);
137
 
138
        return retval;
139
}
140
 
141
/*
142
 * udf_ioctl
143
 *
144
 * PURPOSE
145
 *      Issue an ioctl.
146
 *
147
 * DESCRIPTION
148
 *      Optional - sys_ioctl() will return -ENOTTY if this routine is not
149
 *      available, and the ioctl cannot be handled without filesystem help.
150
 *
151
 *      sys_ioctl() handles these ioctls that apply only to regular files:
152
 *              FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD
153
 *      These ioctls are also handled by sys_ioctl():
154
 *              FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC
155
 *      All other ioctls are passed to the filesystem.
156
 *
157
 *      Refer to sys_ioctl() in fs/ioctl.c
158
 *      sys_ioctl() -> .
159
 *
160
 * PRE-CONDITIONS
161
 *      inode                   Pointer to inode that ioctl was issued on.
162
 *      filp                    Pointer to file that ioctl was issued on.
163
 *      cmd                     The ioctl command.
164
 *      arg                     The ioctl argument [can be interpreted as a
165
 *                              user-space pointer if desired].
166
 *
167
 * POST-CONDITIONS
168
 *      <return>                Success (>=0) or an error code (<=0) that
169
 *                              sys_ioctl() will return.
170
 *
171
 * HISTORY
172
 *      July 1, 1997 - Andrew E. Mileski
173
 *      Written, tested, and released.
174
 */
175
int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
176
              unsigned long arg)
177
{
178
        long old_block, new_block;
179
        int result = -EINVAL;
180
 
181
        if (file_permission(filp, MAY_READ) != 0) {
182
                udf_debug("no permission to access inode %lu\n",
183
                          inode->i_ino);
184
                return -EPERM;
185
        }
186
 
187
        if (!arg) {
188
                udf_debug("invalid argument to udf_ioctl\n");
189
                return -EINVAL;
190
        }
191
 
192
        switch (cmd) {
193
        case UDF_GETVOLIDENT:
194
                return copy_to_user((char __user *)arg,
195
                                    UDF_SB_VOLIDENT(inode->i_sb), 32) ? -EFAULT : 0;
196
        case UDF_RELOCATE_BLOCKS:
197
                if (!capable(CAP_SYS_ADMIN))
198
                        return -EACCES;
199
                if (get_user(old_block, (long __user *)arg))
200
                        return -EFAULT;
201
                if ((result = udf_relocate_blocks(inode->i_sb,
202
                                                  old_block, &new_block)) == 0)
203
                        result = put_user(new_block, (long __user *)arg);
204
                return result;
205
        case UDF_GETEASIZE:
206
                result = put_user(UDF_I_LENEATTR(inode), (int __user *)arg);
207
                break;
208
        case UDF_GETEABLOCK:
209
                result = copy_to_user((char __user *)arg, UDF_I_DATA(inode),
210
                                      UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
211
                break;
212
        }
213
 
214
        return result;
215
}
216
 
217
/*
218
 * udf_release_file
219
 *
220
 * PURPOSE
221
 *  Called when all references to the file are closed
222
 *
223
 * DESCRIPTION
224
 *  Discard prealloced blocks
225
 *
226
 * HISTORY
227
 *
228
 */
229
static int udf_release_file(struct inode *inode, struct file *filp)
230
{
231
        if (filp->f_mode & FMODE_WRITE) {
232
                lock_kernel();
233
                udf_discard_prealloc(inode);
234
                unlock_kernel();
235
        }
236
        return 0;
237
}
238
 
239
const struct file_operations udf_file_operations = {
240
        .read                   = do_sync_read,
241
        .aio_read               = generic_file_aio_read,
242
        .ioctl                  = udf_ioctl,
243
        .open                   = generic_file_open,
244
        .mmap                   = generic_file_mmap,
245
        .write                  = do_sync_write,
246
        .aio_write              = udf_file_aio_write,
247
        .release                = udf_release_file,
248
        .fsync                  = udf_fsync_file,
249
        .splice_read            = generic_file_splice_read,
250
};
251
 
252
const struct inode_operations udf_file_inode_operations = {
253
        .truncate = udf_truncate,
254
};

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.