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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [sync.c] - Blame information for rev 81

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * High-level sync()-related operations
3
 */
4
 
5
#include <linux/kernel.h>
6
#include <linux/file.h>
7
#include <linux/fs.h>
8
#include <linux/module.h>
9
#include <linux/sched.h>
10
#include <linux/writeback.h>
11
#include <linux/syscalls.h>
12
#include <linux/linkage.h>
13
#include <linux/pagemap.h>
14
#include <linux/quotaops.h>
15
#include <linux/buffer_head.h>
16
 
17
#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
18
                        SYNC_FILE_RANGE_WAIT_AFTER)
19
 
20
/*
21
 * sync everything.  Start out by waking pdflush, because that writes back
22
 * all queues in parallel.
23
 */
24
static void do_sync(unsigned long wait)
25
{
26
        wakeup_pdflush(0);
27
        sync_inodes(0);          /* All mappings, inodes and their blockdevs */
28
        DQUOT_SYNC(NULL);
29
        sync_supers();          /* Write the superblocks */
30
        sync_filesystems(0);     /* Start syncing the filesystems */
31
        sync_filesystems(wait); /* Waitingly sync the filesystems */
32
        sync_inodes(wait);      /* Mappings, inodes and blockdevs, again. */
33
        if (!wait)
34
                printk("Emergency Sync complete\n");
35
        if (unlikely(laptop_mode))
36
                laptop_sync_completion();
37
}
38
 
39
asmlinkage long sys_sync(void)
40
{
41
        do_sync(1);
42
        return 0;
43
}
44
 
45
void emergency_sync(void)
46
{
47
        pdflush_operation(do_sync, 0);
48
}
49
 
50
/*
51
 * Generic function to fsync a file.
52
 *
53
 * filp may be NULL if called via the msync of a vma.
54
 */
55
int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
56
{
57
        struct inode * inode = dentry->d_inode;
58
        struct super_block * sb;
59
        int ret, err;
60
 
61
        /* sync the inode to buffers */
62
        ret = write_inode_now(inode, 0);
63
 
64
        /* sync the superblock to buffers */
65
        sb = inode->i_sb;
66
        lock_super(sb);
67
        if (sb->s_op->write_super)
68
                sb->s_op->write_super(sb);
69
        unlock_super(sb);
70
 
71
        /* .. finally sync the buffers to disk */
72
        err = sync_blockdev(sb->s_bdev);
73
        if (!ret)
74
                ret = err;
75
        return ret;
76
}
77
 
78
long do_fsync(struct file *file, int datasync)
79
{
80
        int ret;
81
        int err;
82
        struct address_space *mapping = file->f_mapping;
83
 
84
        if (!file->f_op || !file->f_op->fsync) {
85
                /* Why?  We can still call filemap_fdatawrite */
86
                ret = -EINVAL;
87
                goto out;
88
        }
89
 
90
        ret = filemap_fdatawrite(mapping);
91
 
92
        /*
93
         * We need to protect against concurrent writers, which could cause
94
         * livelocks in fsync_buffers_list().
95
         */
96
        mutex_lock(&mapping->host->i_mutex);
97
        err = file->f_op->fsync(file, file->f_path.dentry, datasync);
98
        if (!ret)
99
                ret = err;
100
        mutex_unlock(&mapping->host->i_mutex);
101
        err = filemap_fdatawait(mapping);
102
        if (!ret)
103
                ret = err;
104
out:
105
        return ret;
106
}
107
 
108
static long __do_fsync(unsigned int fd, int datasync)
109
{
110
        struct file *file;
111
        int ret = -EBADF;
112
 
113
        file = fget(fd);
114
        if (file) {
115
                ret = do_fsync(file, datasync);
116
                fput(file);
117
        }
118
        return ret;
119
}
120
 
121
asmlinkage long sys_fsync(unsigned int fd)
122
{
123
        return __do_fsync(fd, 0);
124
}
125
 
126
asmlinkage long sys_fdatasync(unsigned int fd)
127
{
128
        return __do_fsync(fd, 1);
129
}
130
 
131
/*
132
 * sys_sync_file_range() permits finely controlled syncing over a segment of
133
 * a file in the range offset .. (offset+nbytes-1) inclusive.  If nbytes is
134
 * zero then sys_sync_file_range() will operate from offset out to EOF.
135
 *
136
 * The flag bits are:
137
 *
138
 * SYNC_FILE_RANGE_WAIT_BEFORE: wait upon writeout of all pages in the range
139
 * before performing the write.
140
 *
141
 * SYNC_FILE_RANGE_WRITE: initiate writeout of all those dirty pages in the
142
 * range which are not presently under writeback.
143
 *
144
 * SYNC_FILE_RANGE_WAIT_AFTER: wait upon writeout of all pages in the range
145
 * after performing the write.
146
 *
147
 * Useful combinations of the flag bits are:
148
 *
149
 * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE: ensures that all pages
150
 * in the range which were dirty on entry to sys_sync_file_range() are placed
151
 * under writeout.  This is a start-write-for-data-integrity operation.
152
 *
153
 * SYNC_FILE_RANGE_WRITE: start writeout of all dirty pages in the range which
154
 * are not presently under writeout.  This is an asynchronous flush-to-disk
155
 * operation.  Not suitable for data integrity operations.
156
 *
157
 * SYNC_FILE_RANGE_WAIT_BEFORE (or SYNC_FILE_RANGE_WAIT_AFTER): wait for
158
 * completion of writeout of all pages in the range.  This will be used after an
159
 * earlier SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE operation to wait
160
 * for that operation to complete and to return the result.
161
 *
162
 * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER:
163
 * a traditional sync() operation.  This is a write-for-data-integrity operation
164
 * which will ensure that all pages in the range which were dirty on entry to
165
 * sys_sync_file_range() are committed to disk.
166
 *
167
 *
168
 * SYNC_FILE_RANGE_WAIT_BEFORE and SYNC_FILE_RANGE_WAIT_AFTER will detect any
169
 * I/O errors or ENOSPC conditions and will return those to the caller, after
170
 * clearing the EIO and ENOSPC flags in the address_space.
171
 *
172
 * It should be noted that none of these operations write out the file's
173
 * metadata.  So unless the application is strictly performing overwrites of
174
 * already-instantiated disk blocks, there are no guarantees here that the data
175
 * will be available after a crash.
176
 */
177
asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
178
                                        unsigned int flags)
179
{
180
        int ret;
181
        struct file *file;
182
        loff_t endbyte;                 /* inclusive */
183
        int fput_needed;
184
        umode_t i_mode;
185
 
186
        ret = -EINVAL;
187
        if (flags & ~VALID_FLAGS)
188
                goto out;
189
 
190
        endbyte = offset + nbytes;
191
 
192
        if ((s64)offset < 0)
193
                goto out;
194
        if ((s64)endbyte < 0)
195
                goto out;
196
        if (endbyte < offset)
197
                goto out;
198
 
199
        if (sizeof(pgoff_t) == 4) {
200
                if (offset >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
201
                        /*
202
                         * The range starts outside a 32 bit machine's
203
                         * pagecache addressing capabilities.  Let it "succeed"
204
                         */
205
                        ret = 0;
206
                        goto out;
207
                }
208
                if (endbyte >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
209
                        /*
210
                         * Out to EOF
211
                         */
212
                        nbytes = 0;
213
                }
214
        }
215
 
216
        if (nbytes == 0)
217
                endbyte = LLONG_MAX;
218
        else
219
                endbyte--;              /* inclusive */
220
 
221
        ret = -EBADF;
222
        file = fget_light(fd, &fput_needed);
223
        if (!file)
224
                goto out;
225
 
226
        i_mode = file->f_path.dentry->d_inode->i_mode;
227
        ret = -ESPIPE;
228
        if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
229
                        !S_ISLNK(i_mode))
230
                goto out_put;
231
 
232
        ret = do_sync_mapping_range(file->f_mapping, offset, endbyte, flags);
233
out_put:
234
        fput_light(file, fput_needed);
235
out:
236
        return ret;
237
}
238
 
239
/* It would be nice if people remember that not all the world's an i386
240
   when they introduce new system calls */
241
asmlinkage long sys_sync_file_range2(int fd, unsigned int flags,
242
                                     loff_t offset, loff_t nbytes)
243
{
244
        return sys_sync_file_range(fd, offset, nbytes, flags);
245
}
246
 
247
/*
248
 * `endbyte' is inclusive
249
 */
250
int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
251
                          loff_t endbyte, unsigned int flags)
252
{
253
        int ret;
254
 
255
        if (!mapping) {
256
                ret = -EINVAL;
257
                goto out;
258
        }
259
 
260
        ret = 0;
261
        if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
262
                ret = wait_on_page_writeback_range(mapping,
263
                                        offset >> PAGE_CACHE_SHIFT,
264
                                        endbyte >> PAGE_CACHE_SHIFT);
265
                if (ret < 0)
266
                        goto out;
267
        }
268
 
269
        if (flags & SYNC_FILE_RANGE_WRITE) {
270
                ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
271
                                                WB_SYNC_NONE);
272
                if (ret < 0)
273
                        goto out;
274
        }
275
 
276
        if (flags & SYNC_FILE_RANGE_WAIT_AFTER) {
277
                ret = wait_on_page_writeback_range(mapping,
278
                                        offset >> PAGE_CACHE_SHIFT,
279
                                        endbyte >> PAGE_CACHE_SHIFT);
280
        }
281
out:
282
        return ret;
283
}
284
EXPORT_SYMBOL_GPL(do_sync_mapping_range);

powered by: WebSVN 2.1.0

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