diff options
Diffstat (limited to 'fs/sync.c')
| -rw-r--r-- | fs/sync.c | 48 |
1 files changed, 37 insertions, 11 deletions
| @@ -75,14 +75,39 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync) | |||
| 75 | return ret; | 75 | return ret; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | long do_fsync(struct file *file, int datasync) | 78 | /** |
| 79 | * vfs_fsync - perform a fsync or fdatasync on a file | ||
| 80 | * @file: file to sync | ||
| 81 | * @dentry: dentry of @file | ||
| 82 | * @data: only perform a fdatasync operation | ||
| 83 | * | ||
| 84 | * Write back data and metadata for @file to disk. If @datasync is | ||
| 85 | * set only metadata needed to access modified file data is written. | ||
| 86 | * | ||
| 87 | * In case this function is called from nfsd @file may be %NULL and | ||
| 88 | * only @dentry is set. This can only happen when the filesystem | ||
| 89 | * implements the export_operations API. | ||
| 90 | */ | ||
| 91 | int vfs_fsync(struct file *file, struct dentry *dentry, int datasync) | ||
| 79 | { | 92 | { |
| 80 | int ret; | 93 | const struct file_operations *fop; |
| 81 | int err; | 94 | struct address_space *mapping; |
| 82 | struct address_space *mapping = file->f_mapping; | 95 | int err, ret; |
| 96 | |||
| 97 | /* | ||
| 98 | * Get mapping and operations from the file in case we have | ||
| 99 | * as file, or get the default values for them in case we | ||
| 100 | * don't have a struct file available. Damn nfsd.. | ||
| 101 | */ | ||
| 102 | if (file) { | ||
| 103 | mapping = file->f_mapping; | ||
| 104 | fop = file->f_op; | ||
| 105 | } else { | ||
| 106 | mapping = dentry->d_inode->i_mapping; | ||
| 107 | fop = dentry->d_inode->i_fop; | ||
| 108 | } | ||
| 83 | 109 | ||
| 84 | if (!file->f_op || !file->f_op->fsync) { | 110 | if (!fop || !fop->fsync) { |
| 85 | /* Why? We can still call filemap_fdatawrite */ | ||
| 86 | ret = -EINVAL; | 111 | ret = -EINVAL; |
| 87 | goto out; | 112 | goto out; |
| 88 | } | 113 | } |
| @@ -94,7 +119,7 @@ long do_fsync(struct file *file, int datasync) | |||
| 94 | * livelocks in fsync_buffers_list(). | 119 | * livelocks in fsync_buffers_list(). |
| 95 | */ | 120 | */ |
| 96 | mutex_lock(&mapping->host->i_mutex); | 121 | mutex_lock(&mapping->host->i_mutex); |
| 97 | err = file->f_op->fsync(file, file->f_path.dentry, datasync); | 122 | err = fop->fsync(file, dentry, datasync); |
| 98 | if (!ret) | 123 | if (!ret) |
| 99 | ret = err; | 124 | ret = err; |
| 100 | mutex_unlock(&mapping->host->i_mutex); | 125 | mutex_unlock(&mapping->host->i_mutex); |
| @@ -104,15 +129,16 @@ long do_fsync(struct file *file, int datasync) | |||
| 104 | out: | 129 | out: |
| 105 | return ret; | 130 | return ret; |
| 106 | } | 131 | } |
| 132 | EXPORT_SYMBOL(vfs_fsync); | ||
| 107 | 133 | ||
| 108 | static long __do_fsync(unsigned int fd, int datasync) | 134 | static int do_fsync(unsigned int fd, int datasync) |
| 109 | { | 135 | { |
| 110 | struct file *file; | 136 | struct file *file; |
| 111 | int ret = -EBADF; | 137 | int ret = -EBADF; |
| 112 | 138 | ||
| 113 | file = fget(fd); | 139 | file = fget(fd); |
| 114 | if (file) { | 140 | if (file) { |
| 115 | ret = do_fsync(file, datasync); | 141 | ret = vfs_fsync(file, file->f_path.dentry, datasync); |
| 116 | fput(file); | 142 | fput(file); |
| 117 | } | 143 | } |
| 118 | return ret; | 144 | return ret; |
| @@ -120,12 +146,12 @@ static long __do_fsync(unsigned int fd, int datasync) | |||
| 120 | 146 | ||
| 121 | asmlinkage long sys_fsync(unsigned int fd) | 147 | asmlinkage long sys_fsync(unsigned int fd) |
| 122 | { | 148 | { |
| 123 | return __do_fsync(fd, 0); | 149 | return do_fsync(fd, 0); |
| 124 | } | 150 | } |
| 125 | 151 | ||
| 126 | asmlinkage long sys_fdatasync(unsigned int fd) | 152 | asmlinkage long sys_fdatasync(unsigned int fd) |
| 127 | { | 153 | { |
| 128 | return __do_fsync(fd, 1); | 154 | return do_fsync(fd, 1); |
| 129 | } | 155 | } |
| 130 | 156 | ||
| 131 | /* | 157 | /* |
