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 | /* |