• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * fs/sharefs/file.c
4  *
5  * Copyright (c) 1998-2022 Erez Zadok
6  * Copyright (c) 2009	   Shrikar Archak
7  * Copyright (c) 2003-2022 Stony Brook University
8  * Copyright (c) 2003-2022 The Research Foundation of SUNY
9  * Copyright (c) 2023 Huawei Device Co., Ltd.
10  */
11 
12 #include "sharefs.h"
13 
sharefs_readdir(struct file * file,struct dir_context * ctx)14 static int sharefs_readdir(struct file *file, struct dir_context *ctx)
15 {
16 	int err;
17 	struct file *lower_file = NULL;
18 	struct dentry *dentry = file->f_path.dentry;
19 
20 	lower_file = sharefs_lower_file(file);
21 	err = iterate_dir(lower_file, ctx);
22 	file->f_pos = lower_file->f_pos;
23 	if (err >= 0)		/* copy the atime */
24 		fsstack_copy_attr_atime(d_inode(dentry),
25 					file_inode(lower_file));
26 	return err;
27 }
28 
sharefs_open(struct inode * inode,struct file * file)29 static int sharefs_open(struct inode *inode, struct file *file)
30 {
31 	int err = 0;
32 	struct file *lower_file = NULL;
33 	struct path lower_path;
34 
35 	/* don't open unhashed/deleted files */
36 	if (d_unhashed(file->f_path.dentry)) {
37 		err = -ENOENT;
38 		goto out_err;
39 	}
40 
41 	file->private_data =
42 		kzalloc(sizeof(struct sharefs_file_info), GFP_KERNEL);
43 	if (!SHAREFS_F(file)) {
44 		err = -ENOMEM;
45 		goto out_err;
46 	}
47 
48 	/* open lower object and link sharefs's file struct to lower's */
49 	sharefs_get_lower_path(file->f_path.dentry, &lower_path);
50 	lower_file = dentry_open(&lower_path, file->f_flags, current_cred());
51 	path_put(&lower_path);
52 	if (IS_ERR(lower_file)) {
53 		err = PTR_ERR(lower_file);
54 		lower_file = sharefs_lower_file(file);
55 		if (lower_file) {
56 			sharefs_set_lower_file(file, NULL);
57 			fput(lower_file); /* fput calls dput for lower_dentry */
58 		}
59 	} else {
60 		sharefs_set_lower_file(file, lower_file);
61 	}
62 
63 	if (err) {
64 		kfree(SHAREFS_F(file));
65 	} else {
66 		kuid_t uid = inode->i_uid;
67 		kgid_t gid = inode->i_gid;
68 		mode_t mode = inode->i_mode;
69 		fsstack_copy_attr_all(inode, sharefs_lower_inode(inode));
70 		inode->i_uid = uid;
71 		inode->i_gid = gid;
72 		inode->i_mode = mode;
73 	}
74 out_err:
75 	return err;
76 }
77 
sharefs_flush(struct file * file,fl_owner_t id)78 static int sharefs_flush(struct file *file, fl_owner_t id)
79 {
80 	int err = 0;
81 	struct file *lower_file = NULL;
82 
83 	lower_file = sharefs_lower_file(file);
84 	if (lower_file && lower_file->f_op && lower_file->f_op->flush) {
85 		filemap_write_and_wait(file->f_mapping);
86 		err = lower_file->f_op->flush(lower_file, id);
87 	}
88 
89 	return err;
90 }
91 
92 /* release all lower object references & free the file info structure */
sharefs_file_release(struct inode * inode,struct file * file)93 static int sharefs_file_release(struct inode *inode, struct file *file)
94 {
95 	struct file *lower_file;
96 
97 	lower_file = sharefs_lower_file(file);
98 	if (lower_file) {
99 		sharefs_set_lower_file(file, NULL);
100 		fput(lower_file);
101 	}
102 
103 	kfree(SHAREFS_F(file));
104 	return 0;
105 }
106 
sharefs_fsync(struct file * file,loff_t start,loff_t end,int datasync)107 static int sharefs_fsync(struct file *file, loff_t start, loff_t end,
108 			int datasync)
109 {
110 	int err;
111 	struct file *lower_file;
112 	struct path lower_path;
113 	struct dentry *dentry = file->f_path.dentry;
114 
115 	err = __generic_file_fsync(file, start, end, datasync);
116 	if (err)
117 		goto out;
118 	lower_file = sharefs_lower_file(file);
119 	sharefs_get_lower_path(dentry, &lower_path);
120 	err = vfs_fsync_range(lower_file, start, end, datasync);
121 	sharefs_put_lower_path(dentry, &lower_path);
122 out:
123 	return err;
124 }
125 
sharefs_fasync(int fd,struct file * file,int flag)126 static int sharefs_fasync(int fd, struct file *file, int flag)
127 {
128 	int err = 0;
129 	struct file *lower_file = NULL;
130 
131 	lower_file = sharefs_lower_file(file);
132 	if (lower_file->f_op && lower_file->f_op->fasync)
133 		err = lower_file->f_op->fasync(fd, lower_file, flag);
134 
135 	return err;
136 }
137 
138 /*
139  * Sharefs cannot use generic_file_llseek as ->llseek, because it would
140  * only set the offset of the upper file.  So we have to implement our
141  * own method to set both the upper and lower file offsets
142  * consistently.
143  */
sharefs_file_llseek(struct file * file,loff_t offset,int whence)144 static loff_t sharefs_file_llseek(struct file *file, loff_t offset, int whence)
145 {
146 	loff_t err;
147 	struct file *lower_file;
148 
149 	lower_file = sharefs_lower_file(file);
150 	lower_file->f_pos = file->f_pos;
151 	err = generic_file_llseek(lower_file, offset, whence);
152 	file->f_pos = lower_file->f_pos;
153 
154 	return err;
155 }
156 
157 /*
158  * Sharefs read_iter, redirect modified iocb to lower read_iter
159  */
160 ssize_t
sharefs_read_iter(struct kiocb * iocb,struct iov_iter * iter)161 sharefs_read_iter(struct kiocb *iocb, struct iov_iter *iter)
162 {
163 	int err;
164 	struct file *file = iocb->ki_filp;
165 	struct file *lower_file;
166 
167 	lower_file = sharefs_lower_file(file);
168 	if (!lower_file->f_op->read_iter) {
169 		err = -EINVAL;
170 		goto out;
171 	}
172 
173 	/* prevent lower_file from being released */
174 	get_file(lower_file);
175 	iocb->ki_filp = lower_file;
176 	err = lower_file->f_op->read_iter(iocb, iter);
177 	iocb->ki_filp = file;
178 	fput(lower_file);
179 
180 	/* update upper inode atime as needed */
181 	if (err >= 0 || err == -EIOCBQUEUED)
182 		fsstack_copy_attr_atime(d_inode(file->f_path.dentry),
183 					file_inode(lower_file));
184 out:
185 	return err;
186 }
187 
188 /*
189  * Sharefs write_iter, redirect modified iocb to lower write_iter
190  */
191 ssize_t
sharefs_write_iter(struct kiocb * iocb,struct iov_iter * iter)192 sharefs_write_iter(struct kiocb *iocb, struct iov_iter *iter)
193 {
194 	int err;
195 	struct file *file = iocb->ki_filp;
196 	struct file *lower_file;
197 
198 	lower_file = sharefs_lower_file(file);
199 	if (!lower_file->f_op->write_iter) {
200 		err = -EINVAL;
201 		goto out;
202 	}
203 
204 	get_file(lower_file); /* prevent lower_file from being released */
205 	iocb->ki_filp = lower_file;
206 	err = lower_file->f_op->write_iter(iocb, iter);
207 	iocb->ki_filp = file;
208 	fput(lower_file);
209 	/* update upper inode times/sizes as needed */
210 	if (err >= 0 || err == -EIOCBQUEUED) {
211 		fsstack_copy_inode_size(d_inode(file->f_path.dentry),
212 					file_inode(lower_file));
213 		fsstack_copy_attr_times(d_inode(file->f_path.dentry),
214 					file_inode(lower_file));
215 	}
216 out:
217 	return err;
218 }
219 
sharefs_file_mmap(struct file * file,struct vm_area_struct * vma)220 int sharefs_file_mmap(struct file *file, struct vm_area_struct *vma)
221 {
222 	int err = 0;
223 	struct file *lower_file;
224 
225 	lower_file = sharefs_lower_file(file);
226 	if (!lower_file)
227 		return -EINVAL;
228 
229 	if (!lower_file->f_op->mmap)
230 		return -ENODEV;
231 
232 	if (WARN_ON(file != vma->vm_file))
233 		return -EIO;
234 
235 	vma->vm_file = get_file(lower_file);
236 	err = call_mmap(vma->vm_file, vma);
237 	if (err)
238 		fput(lower_file);
239 	else
240 		fput(file);
241 
242 	file_accessed(file);
243 
244 	return err;
245 }
246 
247 const struct file_operations sharefs_main_fops = {
248 	.llseek		= sharefs_file_llseek,
249 	.open		= sharefs_open,
250 	.flush		= sharefs_flush,
251 	.release	= sharefs_file_release,
252 	.fsync		= sharefs_fsync,
253 	.fasync		= sharefs_fasync,
254 	.read_iter	= sharefs_read_iter,
255 	.write_iter	= sharefs_write_iter,
256 	.mmap		= sharefs_file_mmap,
257 	.splice_read = generic_file_splice_read,
258 	.splice_write = iter_file_splice_write,
259 };
260 
261 /* trimmed directory options */
262 const struct file_operations sharefs_dir_fops = {
263 	.llseek		= sharefs_file_llseek,
264 	.read		= generic_read_dir,
265 	.iterate	= sharefs_readdir,
266 	.open		= sharefs_open,
267 	.release	= sharefs_file_release,
268 	.flush		= sharefs_flush,
269 	.fsync		= sharefs_fsync,
270 	.fasync		= sharefs_fasync,
271 };
272