Commit | Line | Data |
---|---|---|
ee184c81 DC |
1 | /* |
2 | * fs/sdcardfs/sdcardfs.h | |
3 | * | |
4 | * The sdcardfs v2.0 | |
5 | * This file system replaces the sdcard daemon on Android | |
6 | * On version 2.0, some of the daemon functions have been ported | |
7 | * to support the multi-user concepts of Android 4.4 | |
8 | * | |
9 | * Copyright (c) 2013 Samsung Electronics Co. Ltd | |
10 | * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, | |
11 | * Sunghwan Yun, Sungjong Seo | |
12 | * | |
13 | * This program has been developed as a stackable file system based on | |
14 | * the WrapFS which written by | |
15 | * | |
16 | * Copyright (c) 1998-2011 Erez Zadok | |
17 | * Copyright (c) 2009 Shrikar Archak | |
18 | * Copyright (c) 2003-2011 Stony Brook University | |
19 | * Copyright (c) 2003-2011 The Research Foundation of SUNY | |
20 | * | |
21 | * This file is dual licensed. It may be redistributed and/or modified | |
22 | * under the terms of the Apache 2.0 License OR version 2 of the GNU | |
23 | * General Public License. | |
24 | */ | |
25 | ||
26 | #ifndef _SDCARDFS_H_ | |
27 | #define _SDCARDFS_H_ | |
28 | ||
29 | #include <linux/dcache.h> | |
30 | #include <linux/file.h> | |
31 | #include <linux/fs.h> | |
0962b962 | 32 | #include <linux/aio.h> |
ee184c81 DC |
33 | #include <linux/mm.h> |
34 | #include <linux/mount.h> | |
35 | #include <linux/namei.h> | |
36 | #include <linux/seq_file.h> | |
37 | #include <linux/statfs.h> | |
38 | #include <linux/fs_stack.h> | |
39 | #include <linux/magic.h> | |
40 | #include <linux/uaccess.h> | |
41 | #include <linux/slab.h> | |
42 | #include <linux/sched.h> | |
43 | #include <linux/types.h> | |
44 | #include <linux/security.h> | |
45 | #include <linux/string.h> | |
3ebb8b99 | 46 | #include <linux/list.h> |
ee184c81 DC |
47 | #include "multiuser.h" |
48 | ||
49 | /* the file system name */ | |
50 | #define SDCARDFS_NAME "sdcardfs" | |
51 | ||
52 | /* sdcardfs root inode number */ | |
53 | #define SDCARDFS_ROOT_INO 1 | |
54 | ||
55 | /* useful for tracking code reachability */ | |
56 | #define UDBG printk(KERN_DEFAULT "DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__) | |
57 | ||
58 | #define SDCARDFS_DIRENT_SIZE 256 | |
59 | ||
60 | /* temporary static uid settings for development */ | |
61 | #define AID_ROOT 0 /* uid for accessing /mnt/sdcard & extSdcard */ | |
62 | #define AID_MEDIA_RW 1023 /* internal media storage write access */ | |
63 | ||
64 | #define AID_SDCARD_RW 1015 /* external storage write access */ | |
65 | #define AID_SDCARD_R 1028 /* external storage read access */ | |
66 | #define AID_SDCARD_PICS 1033 /* external storage photos access */ | |
67 | #define AID_SDCARD_AV 1034 /* external storage audio/video access */ | |
68 | #define AID_SDCARD_ALL 1035 /* access all users external storage */ | |
69 | ||
70 | #define AID_PACKAGE_INFO 1027 | |
71 | ||
a50d4516 DR |
72 | |
73 | /* | |
74 | * Permissions are handled by our permission function. | |
75 | * We don't want anyone who happens to look at our inode value to prematurely | |
76 | * block access, so store more permissive values. These are probably never | |
77 | * used. | |
78 | */ | |
79 | #define fixup_tmp_permissions(x) \ | |
ee184c81 DC |
80 | do { \ |
81 | (x)->i_uid = SDCARDFS_I(x)->d_uid; \ | |
a50d4516 DR |
82 | (x)->i_gid = AID_SDCARD_RW; \ |
83 | (x)->i_mode = ((x)->i_mode & S_IFMT) | 0775;\ | |
ee184c81 DC |
84 | } while (0) |
85 | ||
86 | /* OVERRIDE_CRED() and REVERT_CRED() | |
87 | * OVERRID_CRED() | |
88 | * backup original task->cred | |
89 | * and modifies task->cred->fsuid/fsgid to specified value. | |
90 | * REVERT_CRED() | |
91 | * restore original task->cred->fsuid/fsgid. | |
92 | * These two macro should be used in pair, and OVERRIDE_CRED() should be | |
93 | * placed at the beginning of a function, right after variable declaration. | |
94 | */ | |
95 | #define OVERRIDE_CRED(sdcardfs_sbi, saved_cred) \ | |
96 | saved_cred = override_fsids(sdcardfs_sbi); \ | |
97 | if (!saved_cred) { return -ENOMEM; } | |
98 | ||
99 | #define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred) \ | |
100 | saved_cred = override_fsids(sdcardfs_sbi); \ | |
101 | if (!saved_cred) { return ERR_PTR(-ENOMEM); } | |
102 | ||
103 | #define REVERT_CRED(saved_cred) revert_fsids(saved_cred) | |
104 | ||
105 | #define DEBUG_CRED() \ | |
106 | printk("KAKJAGI: %s:%d fsuid %d fsgid %d\n", \ | |
107 | __FUNCTION__, __LINE__, \ | |
108 | (int)current->cred->fsuid, \ | |
109 | (int)current->cred->fsgid); | |
110 | ||
3ebb8b99 | 111 | /* Android 5.0 support */ |
ee184c81 DC |
112 | |
113 | /* Permission mode for a specific node. Controls how file permissions | |
114 | * are derived for children nodes. */ | |
115 | typedef enum { | |
3ebb8b99 DR |
116 | /* Nothing special; this node should just inherit from its parent. */ |
117 | PERM_INHERIT, | |
118 | /* This node is one level above a normal root; used for legacy layouts | |
119 | * which use the first level to represent user_id. */ | |
120 | PERM_PRE_ROOT, | |
121 | /* This node is "/" */ | |
122 | PERM_ROOT, | |
123 | /* This node is "/Android" */ | |
124 | PERM_ANDROID, | |
125 | /* This node is "/Android/data" */ | |
126 | PERM_ANDROID_DATA, | |
127 | /* This node is "/Android/obb" */ | |
128 | PERM_ANDROID_OBB, | |
129 | /* This node is "/Android/media" */ | |
130 | PERM_ANDROID_MEDIA, | |
ee184c81 DC |
131 | } perm_t; |
132 | ||
ee184c81 DC |
133 | struct sdcardfs_sb_info; |
134 | struct sdcardfs_mount_options; | |
135 | ||
136 | /* Do not directly use this function. Use OVERRIDE_CRED() instead. */ | |
137 | const struct cred * override_fsids(struct sdcardfs_sb_info* sbi); | |
138 | /* Do not directly use this function, use REVERT_CRED() instead. */ | |
139 | void revert_fsids(const struct cred * old_cred); | |
140 | ||
141 | /* operations vectors defined in specific files */ | |
142 | extern const struct file_operations sdcardfs_main_fops; | |
143 | extern const struct file_operations sdcardfs_dir_fops; | |
144 | extern const struct inode_operations sdcardfs_main_iops; | |
145 | extern const struct inode_operations sdcardfs_dir_iops; | |
146 | extern const struct inode_operations sdcardfs_symlink_iops; | |
147 | extern const struct super_operations sdcardfs_sops; | |
148 | extern const struct dentry_operations sdcardfs_ci_dops; | |
149 | extern const struct address_space_operations sdcardfs_aops, sdcardfs_dummy_aops; | |
150 | extern const struct vm_operations_struct sdcardfs_vm_ops; | |
151 | ||
152 | extern int sdcardfs_init_inode_cache(void); | |
153 | extern void sdcardfs_destroy_inode_cache(void); | |
154 | extern int sdcardfs_init_dentry_cache(void); | |
155 | extern void sdcardfs_destroy_dentry_cache(void); | |
156 | extern int new_dentry_private_data(struct dentry *dentry); | |
157 | extern void free_dentry_private_data(struct dentry *dentry); | |
158 | extern struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, | |
542a676e DC |
159 | unsigned int flags); |
160 | extern struct inode *sdcardfs_iget(struct super_block *sb, | |
3ebb8b99 | 161 | struct inode *lower_inode, userid_t id); |
ee184c81 | 162 | extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, |
3ebb8b99 | 163 | struct path *lower_path, userid_t id); |
ee184c81 DC |
164 | |
165 | /* file private data */ | |
166 | struct sdcardfs_file_info { | |
167 | struct file *lower_file; | |
168 | const struct vm_operations_struct *lower_vm_ops; | |
169 | }; | |
170 | ||
171 | /* sdcardfs inode data in memory */ | |
172 | struct sdcardfs_inode_info { | |
173 | struct inode *lower_inode; | |
3ebb8b99 | 174 | /* state derived based on current position in hierachy */ |
ee184c81 DC |
175 | perm_t perm; |
176 | userid_t userid; | |
177 | uid_t d_uid; | |
3ebb8b99 | 178 | bool under_android; |
486a7476 DR |
179 | /* top folder for ownership */ |
180 | struct inode *top; | |
ee184c81 DC |
181 | |
182 | struct inode vfs_inode; | |
183 | }; | |
184 | ||
3ebb8b99 | 185 | |
ee184c81 DC |
186 | /* sdcardfs dentry data in memory */ |
187 | struct sdcardfs_dentry_info { | |
188 | spinlock_t lock; /* protects lower_path */ | |
189 | struct path lower_path; | |
190 | struct path orig_path; | |
191 | }; | |
192 | ||
193 | struct sdcardfs_mount_options { | |
194 | uid_t fs_low_uid; | |
195 | gid_t fs_low_gid; | |
3ebb8b99 | 196 | userid_t fs_user_id; |
3ebb8b99 | 197 | bool multiuser; |
ee184c81 DC |
198 | unsigned int reserved_mb; |
199 | }; | |
200 | ||
04e6ac52 DR |
201 | struct sdcardfs_vfsmount_options { |
202 | gid_t gid; | |
203 | mode_t mask; | |
204 | }; | |
205 | ||
206 | extern int parse_options_remount(struct super_block *sb, char *options, int silent, | |
207 | struct sdcardfs_vfsmount_options *vfsopts); | |
208 | ||
ee184c81 DC |
209 | /* sdcardfs super-block data in memory */ |
210 | struct sdcardfs_sb_info { | |
3ebb8b99 | 211 | struct super_block *sb; |
ee184c81 DC |
212 | struct super_block *lower_sb; |
213 | /* derived perm policy : some of options have been added | |
214 | * to sdcardfs_mount_options (Android 4.4 support) */ | |
215 | struct sdcardfs_mount_options options; | |
216 | spinlock_t lock; /* protects obbpath */ | |
217 | char *obbpath_s; | |
218 | struct path obbpath; | |
219 | void *pkgl_id; | |
3ebb8b99 | 220 | struct list_head list; |
ee184c81 DC |
221 | }; |
222 | ||
223 | /* | |
224 | * inode to private data | |
225 | * | |
226 | * Since we use containers and the struct inode is _inside_ the | |
227 | * sdcardfs_inode_info structure, SDCARDFS_I will always (given a non-NULL | |
228 | * inode pointer), return a valid non-NULL pointer. | |
229 | */ | |
230 | static inline struct sdcardfs_inode_info *SDCARDFS_I(const struct inode *inode) | |
231 | { | |
232 | return container_of(inode, struct sdcardfs_inode_info, vfs_inode); | |
233 | } | |
234 | ||
235 | /* dentry to private data */ | |
236 | #define SDCARDFS_D(dent) ((struct sdcardfs_dentry_info *)(dent)->d_fsdata) | |
237 | ||
238 | /* superblock to private data */ | |
239 | #define SDCARDFS_SB(super) ((struct sdcardfs_sb_info *)(super)->s_fs_info) | |
240 | ||
241 | /* file to private Data */ | |
242 | #define SDCARDFS_F(file) ((struct sdcardfs_file_info *)((file)->private_data)) | |
243 | ||
244 | /* file to lower file */ | |
245 | static inline struct file *sdcardfs_lower_file(const struct file *f) | |
246 | { | |
247 | return SDCARDFS_F(f)->lower_file; | |
248 | } | |
249 | ||
250 | static inline void sdcardfs_set_lower_file(struct file *f, struct file *val) | |
251 | { | |
252 | SDCARDFS_F(f)->lower_file = val; | |
253 | } | |
254 | ||
255 | /* inode to lower inode. */ | |
256 | static inline struct inode *sdcardfs_lower_inode(const struct inode *i) | |
257 | { | |
258 | return SDCARDFS_I(i)->lower_inode; | |
259 | } | |
260 | ||
261 | static inline void sdcardfs_set_lower_inode(struct inode *i, struct inode *val) | |
262 | { | |
263 | SDCARDFS_I(i)->lower_inode = val; | |
264 | } | |
265 | ||
266 | /* superblock to lower superblock */ | |
267 | static inline struct super_block *sdcardfs_lower_super( | |
268 | const struct super_block *sb) | |
269 | { | |
270 | return SDCARDFS_SB(sb)->lower_sb; | |
271 | } | |
272 | ||
273 | static inline void sdcardfs_set_lower_super(struct super_block *sb, | |
274 | struct super_block *val) | |
275 | { | |
276 | SDCARDFS_SB(sb)->lower_sb = val; | |
277 | } | |
278 | ||
279 | /* path based (dentry/mnt) macros */ | |
280 | static inline void pathcpy(struct path *dst, const struct path *src) | |
281 | { | |
282 | dst->dentry = src->dentry; | |
283 | dst->mnt = src->mnt; | |
284 | } | |
285 | ||
286 | /* sdcardfs_get_pname functions calls path_get() | |
287 | * therefore, the caller must call "proper" path_put functions | |
288 | */ | |
289 | #define SDCARDFS_DENT_FUNC(pname) \ | |
290 | static inline void sdcardfs_get_##pname(const struct dentry *dent, \ | |
291 | struct path *pname) \ | |
292 | { \ | |
293 | spin_lock(&SDCARDFS_D(dent)->lock); \ | |
294 | pathcpy(pname, &SDCARDFS_D(dent)->pname); \ | |
295 | path_get(pname); \ | |
296 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | |
297 | return; \ | |
298 | } \ | |
299 | static inline void sdcardfs_put_##pname(const struct dentry *dent, \ | |
300 | struct path *pname) \ | |
301 | { \ | |
302 | path_put(pname); \ | |
303 | return; \ | |
304 | } \ | |
305 | static inline void sdcardfs_set_##pname(const struct dentry *dent, \ | |
306 | struct path *pname) \ | |
307 | { \ | |
308 | spin_lock(&SDCARDFS_D(dent)->lock); \ | |
309 | pathcpy(&SDCARDFS_D(dent)->pname, pname); \ | |
310 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | |
311 | return; \ | |
312 | } \ | |
313 | static inline void sdcardfs_reset_##pname(const struct dentry *dent) \ | |
314 | { \ | |
315 | spin_lock(&SDCARDFS_D(dent)->lock); \ | |
316 | SDCARDFS_D(dent)->pname.dentry = NULL; \ | |
317 | SDCARDFS_D(dent)->pname.mnt = NULL; \ | |
318 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | |
319 | return; \ | |
320 | } \ | |
321 | static inline void sdcardfs_put_reset_##pname(const struct dentry *dent) \ | |
322 | { \ | |
323 | struct path pname; \ | |
324 | spin_lock(&SDCARDFS_D(dent)->lock); \ | |
325 | if(SDCARDFS_D(dent)->pname.dentry) { \ | |
326 | pathcpy(&pname, &SDCARDFS_D(dent)->pname); \ | |
327 | SDCARDFS_D(dent)->pname.dentry = NULL; \ | |
328 | SDCARDFS_D(dent)->pname.mnt = NULL; \ | |
329 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | |
330 | path_put(&pname); \ | |
331 | } else \ | |
332 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | |
333 | return; \ | |
334 | } | |
335 | ||
336 | SDCARDFS_DENT_FUNC(lower_path) | |
337 | SDCARDFS_DENT_FUNC(orig_path) | |
338 | ||
486a7476 DR |
339 | /* grab a refererence if we aren't linking to ourself */ |
340 | static inline void set_top(struct sdcardfs_inode_info *info, struct inode *top) | |
341 | { | |
342 | struct inode *old_top = NULL; | |
343 | BUG_ON(IS_ERR_OR_NULL(top)); | |
344 | if (info->top && info->top != &info->vfs_inode) { | |
345 | old_top = info->top; | |
346 | } | |
347 | if (top != &info->vfs_inode) | |
348 | igrab(top); | |
349 | info->top = top; | |
350 | iput(old_top); | |
351 | } | |
352 | ||
353 | static inline struct inode *grab_top(struct sdcardfs_inode_info *info) | |
354 | { | |
355 | struct inode *top = info->top; | |
356 | if (top) { | |
357 | return igrab(top); | |
358 | } else { | |
359 | return NULL; | |
360 | } | |
361 | } | |
362 | ||
363 | static inline void release_top(struct sdcardfs_inode_info *info) | |
364 | { | |
365 | iput(info->top); | |
366 | } | |
367 | ||
a50d4516 DR |
368 | static inline int get_gid(struct vfsmount *mnt, struct sdcardfs_inode_info *info) { |
369 | struct sdcardfs_vfsmount_options *opts = mnt->data; | |
370 | ||
371 | if (opts->gid == AID_SDCARD_RW) { | |
3ebb8b99 DR |
372 | /* As an optimization, certain trusted system components only run |
373 | * as owner but operate across all users. Since we're now handing | |
374 | * out the sdcard_rw GID only to trusted apps, we're okay relaxing | |
375 | * the user boundary enforcement for the default view. The UIDs | |
376 | * assigned to app directories are still multiuser aware. */ | |
377 | return AID_SDCARD_RW; | |
378 | } else { | |
a50d4516 | 379 | return multiuser_get_uid(info->userid, opts->gid); |
3ebb8b99 DR |
380 | } |
381 | } | |
a50d4516 | 382 | static inline int get_mode(struct vfsmount *mnt, struct sdcardfs_inode_info *info) { |
3ebb8b99 DR |
383 | int owner_mode; |
384 | int filtered_mode; | |
a50d4516 DR |
385 | struct sdcardfs_vfsmount_options *opts = mnt->data; |
386 | int visible_mode = 0775 & ~opts->mask; | |
387 | ||
3ebb8b99 DR |
388 | |
389 | if (info->perm == PERM_PRE_ROOT) { | |
390 | /* Top of multi-user view should always be visible to ensure | |
391 | * secondary users can traverse inside. */ | |
392 | visible_mode = 0711; | |
393 | } else if (info->under_android) { | |
394 | /* Block "other" access to Android directories, since only apps | |
395 | * belonging to a specific user should be in there; we still | |
396 | * leave +x open for the default view. */ | |
a50d4516 | 397 | if (opts->gid == AID_SDCARD_RW) { |
3ebb8b99 DR |
398 | visible_mode = visible_mode & ~0006; |
399 | } else { | |
400 | visible_mode = visible_mode & ~0007; | |
401 | } | |
402 | } | |
403 | owner_mode = info->lower_inode->i_mode & 0700; | |
404 | filtered_mode = visible_mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6)); | |
405 | return filtered_mode; | |
406 | } | |
407 | ||
ee184c81 DC |
408 | static inline int has_graft_path(const struct dentry *dent) |
409 | { | |
410 | int ret = 0; | |
411 | ||
412 | spin_lock(&SDCARDFS_D(dent)->lock); | |
413 | if (SDCARDFS_D(dent)->orig_path.dentry != NULL) | |
414 | ret = 1; | |
415 | spin_unlock(&SDCARDFS_D(dent)->lock); | |
416 | ||
417 | return ret; | |
418 | } | |
419 | ||
420 | static inline void sdcardfs_get_real_lower(const struct dentry *dent, | |
421 | struct path *real_lower) | |
422 | { | |
423 | /* in case of a local obb dentry | |
424 | * the orig_path should be returned | |
425 | */ | |
426 | if(has_graft_path(dent)) | |
427 | sdcardfs_get_orig_path(dent, real_lower); | |
428 | else | |
429 | sdcardfs_get_lower_path(dent, real_lower); | |
430 | } | |
431 | ||
432 | static inline void sdcardfs_put_real_lower(const struct dentry *dent, | |
433 | struct path *real_lower) | |
434 | { | |
435 | if(has_graft_path(dent)) | |
436 | sdcardfs_put_orig_path(dent, real_lower); | |
437 | else | |
438 | sdcardfs_put_lower_path(dent, real_lower); | |
439 | } | |
440 | ||
3ebb8b99 DR |
441 | extern struct mutex sdcardfs_super_list_lock; |
442 | extern struct list_head sdcardfs_super_list; | |
443 | ||
ee184c81 | 444 | /* for packagelist.c */ |
f4249539 | 445 | extern appid_t get_appid(const char *app_name); |
3ebb8b99 | 446 | extern int check_caller_access_to_name(struct inode *parent_node, const char* name); |
ee184c81 | 447 | extern int open_flags_to_access_mode(int open_flags); |
ee184c81 DC |
448 | extern int packagelist_init(void); |
449 | extern void packagelist_exit(void); | |
450 | ||
451 | /* for derived_perm.c */ | |
486a7476 DR |
452 | extern void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid, |
453 | uid_t uid, bool under_android, struct inode *top); | |
ee184c81 | 454 | extern void get_derived_permission(struct dentry *parent, struct dentry *dentry); |
3ebb8b99 | 455 | extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, struct dentry *newdentry); |
486a7476 DR |
456 | extern void fixup_top_recursive(struct dentry *parent); |
457 | extern void fixup_perms_recursive(struct dentry *dentry, const char *name, size_t len); | |
3ebb8b99 DR |
458 | |
459 | extern void update_derived_permission_lock(struct dentry *dentry); | |
ee184c81 DC |
460 | extern int need_graft_path(struct dentry *dentry); |
461 | extern int is_base_obbpath(struct dentry *dentry); | |
462 | extern int is_obbpath_invalid(struct dentry *dentry); | |
463 | extern int setup_obb_dentry(struct dentry *dentry, struct path *lower_path); | |
464 | ||
465 | /* locking helpers */ | |
466 | static inline struct dentry *lock_parent(struct dentry *dentry) | |
467 | { | |
468 | struct dentry *dir = dget_parent(dentry); | |
469 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); | |
470 | return dir; | |
471 | } | |
472 | ||
473 | static inline void unlock_dir(struct dentry *dir) | |
474 | { | |
475 | mutex_unlock(&dir->d_inode->i_mutex); | |
476 | dput(dir); | |
477 | } | |
478 | ||
479 | static inline int prepare_dir(const char *path_s, uid_t uid, gid_t gid, mode_t mode) | |
480 | { | |
481 | int err; | |
482 | struct dentry *dent; | |
483 | struct iattr attrs; | |
542a676e | 484 | struct path parent; |
ee184c81 | 485 | |
542a676e | 486 | dent = kern_path_locked(path_s, &parent); |
ee184c81 DC |
487 | if (IS_ERR(dent)) { |
488 | err = PTR_ERR(dent); | |
489 | if (err == -EEXIST) | |
490 | err = 0; | |
491 | goto out_unlock; | |
492 | } | |
493 | ||
403275a8 | 494 | err = vfs_mkdir2(parent.mnt, parent.dentry->d_inode, dent, mode); |
ee184c81 DC |
495 | if (err) { |
496 | if (err == -EEXIST) | |
497 | err = 0; | |
498 | goto out_dput; | |
499 | } | |
500 | ||
501 | attrs.ia_uid = uid; | |
502 | attrs.ia_gid = gid; | |
503 | attrs.ia_valid = ATTR_UID | ATTR_GID; | |
504 | mutex_lock(&dent->d_inode->i_mutex); | |
403275a8 | 505 | notify_change2(parent.mnt, dent, &attrs); |
ee184c81 DC |
506 | mutex_unlock(&dent->d_inode->i_mutex); |
507 | ||
508 | out_dput: | |
509 | dput(dent); | |
510 | ||
511 | out_unlock: | |
512 | /* parent dentry locked by lookup_create */ | |
542a676e DC |
513 | mutex_unlock(&parent.dentry->d_inode->i_mutex); |
514 | path_put(&parent); | |
ee184c81 DC |
515 | return err; |
516 | } | |
517 | ||
518 | /* | |
519 | * Return 1, if a disk has enough free space, otherwise 0. | |
520 | * We assume that any files can not be overwritten. | |
521 | */ | |
522 | static inline int check_min_free_space(struct dentry *dentry, size_t size, int dir) | |
523 | { | |
524 | int err; | |
525 | struct path lower_path; | |
526 | struct kstatfs statfs; | |
527 | u64 avail; | |
528 | struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); | |
529 | ||
530 | if (sbi->options.reserved_mb) { | |
531 | /* Get fs stat of lower filesystem. */ | |
532 | sdcardfs_get_lower_path(dentry, &lower_path); | |
533 | err = vfs_statfs(&lower_path, &statfs); | |
534 | sdcardfs_put_lower_path(dentry, &lower_path); | |
535 | ||
536 | if (unlikely(err)) | |
537 | return 0; | |
538 | ||
539 | /* Invalid statfs informations. */ | |
540 | if (unlikely(statfs.f_bsize == 0)) | |
541 | return 0; | |
542 | ||
543 | /* if you are checking directory, set size to f_bsize. */ | |
544 | if (unlikely(dir)) | |
545 | size = statfs.f_bsize; | |
546 | ||
547 | /* available size */ | |
548 | avail = statfs.f_bavail * statfs.f_bsize; | |
549 | ||
550 | /* not enough space */ | |
551 | if ((u64)size > avail) | |
552 | return 0; | |
553 | ||
554 | /* enough space */ | |
555 | if ((avail - size) > (sbi->options.reserved_mb * 1024 * 1024)) | |
556 | return 1; | |
557 | ||
558 | return 0; | |
559 | } else | |
560 | return 1; | |
561 | } | |
562 | ||
a50d4516 DR |
563 | /* |
564 | * Copies attrs and maintains sdcardfs managed attrs | |
565 | * Since our permission check handles all special permissions, set those to be open | |
566 | */ | |
3ebb8b99 DR |
567 | static inline void sdcardfs_copy_and_fix_attrs(struct inode *dest, const struct inode *src) |
568 | { | |
a50d4516 DR |
569 | |
570 | dest->i_mode = (src->i_mode & S_IFMT) | S_IRWXU | S_IRWXG | | |
571 | S_IROTH | S_IXOTH; /* 0775 */ | |
3ebb8b99 | 572 | dest->i_uid = SDCARDFS_I(dest)->d_uid; |
a50d4516 | 573 | dest->i_gid = AID_SDCARD_RW; |
3ebb8b99 DR |
574 | dest->i_rdev = src->i_rdev; |
575 | dest->i_atime = src->i_atime; | |
576 | dest->i_mtime = src->i_mtime; | |
577 | dest->i_ctime = src->i_ctime; | |
578 | dest->i_blkbits = src->i_blkbits; | |
579 | dest->i_flags = src->i_flags; | |
580 | set_nlink(dest, src->i_nlink); | |
581 | } | |
ee184c81 | 582 | #endif /* not _SDCARDFS_H_ */ |