1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* |
3 | * Copyright (C) 2019 Samsung Electronics Co., Ltd. |
4 | */ |
5 | |
6 | #ifndef __VFS_CACHE_H__ |
7 | #define __VFS_CACHE_H__ |
8 | |
9 | #include <linux/file.h> |
10 | #include <linux/fs.h> |
11 | #include <linux/rwsem.h> |
12 | #include <linux/spinlock.h> |
13 | #include <linux/idr.h> |
14 | #include <linux/workqueue.h> |
15 | |
16 | #include "vfs.h" |
17 | #include "mgmt/share_config.h" |
18 | |
19 | /* Windows style file permissions for extended response */ |
20 | #define FILE_GENERIC_ALL 0x1F01FF |
21 | #define FILE_GENERIC_READ 0x120089 |
22 | #define FILE_GENERIC_WRITE 0x120116 |
23 | #define FILE_GENERIC_EXECUTE 0X1200a0 |
24 | |
25 | #define KSMBD_START_FID 0 |
26 | #define KSMBD_NO_FID (INT_MAX) |
27 | #define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL) |
28 | |
29 | struct ksmbd_conn; |
30 | struct ksmbd_session; |
31 | |
32 | struct ksmbd_lock { |
33 | struct file_lock *fl; |
34 | struct list_head clist; |
35 | struct list_head flist; |
36 | struct list_head llist; |
37 | unsigned int flags; |
38 | int cmd; |
39 | int zero_len; |
40 | unsigned long long start; |
41 | unsigned long long end; |
42 | }; |
43 | |
44 | struct stream { |
45 | char *name; |
46 | ssize_t size; |
47 | }; |
48 | |
49 | struct ksmbd_inode { |
50 | rwlock_t m_lock; |
51 | atomic_t m_count; |
52 | atomic_t op_count; |
53 | /* opinfo count for streams */ |
54 | atomic_t sop_count; |
55 | struct dentry *m_de; |
56 | unsigned int m_flags; |
57 | struct hlist_node m_hash; |
58 | struct list_head m_fp_list; |
59 | struct list_head m_op_list; |
60 | struct oplock_info *m_opinfo; |
61 | __le32 m_fattr; |
62 | }; |
63 | |
64 | enum { |
65 | FP_NEW = 0, |
66 | FP_INITED, |
67 | FP_CLOSED |
68 | }; |
69 | |
70 | struct ksmbd_file { |
71 | struct file *filp; |
72 | u64 persistent_id; |
73 | u64 volatile_id; |
74 | |
75 | spinlock_t f_lock; |
76 | |
77 | struct ksmbd_inode *f_ci; |
78 | struct ksmbd_inode *f_parent_ci; |
79 | struct oplock_info __rcu *f_opinfo; |
80 | struct ksmbd_conn *conn; |
81 | struct ksmbd_tree_connect *tcon; |
82 | |
83 | atomic_t refcount; |
84 | __le32 daccess; |
85 | __le32 saccess; |
86 | __le32 coption; |
87 | __le32 cdoption; |
88 | __u64 create_time; |
89 | __u64 itime; |
90 | |
91 | bool is_nt_open; |
92 | bool attrib_only; |
93 | |
94 | char client_guid[16]; |
95 | char create_guid[16]; |
96 | char app_instance_id[16]; |
97 | |
98 | struct stream stream; |
99 | struct list_head node; |
100 | struct list_head blocked_works; |
101 | struct list_head lock_list; |
102 | |
103 | int durable_timeout; |
104 | |
105 | /* if ls is happening on directory, below is valid*/ |
106 | struct ksmbd_readdir_data readdir_data; |
107 | int dot_dotdot[2]; |
108 | unsigned int f_state; |
109 | bool reserve_lease_break; |
110 | bool is_durable; |
111 | bool is_persistent; |
112 | bool is_resilient; |
113 | }; |
114 | |
115 | static inline void set_ctx_actor(struct dir_context *ctx, |
116 | filldir_t actor) |
117 | { |
118 | ctx->actor = actor; |
119 | } |
120 | |
121 | #define KSMBD_NR_OPEN_DEFAULT BITS_PER_LONG |
122 | |
123 | struct ksmbd_file_table { |
124 | rwlock_t lock; |
125 | struct idr *idr; |
126 | }; |
127 | |
128 | static inline bool has_file_id(u64 id) |
129 | { |
130 | return id < KSMBD_NO_FID; |
131 | } |
132 | |
133 | static inline bool ksmbd_stream_fd(struct ksmbd_file *fp) |
134 | { |
135 | return fp->stream.name != NULL; |
136 | } |
137 | |
138 | int ksmbd_init_file_table(struct ksmbd_file_table *ft); |
139 | void ksmbd_destroy_file_table(struct ksmbd_file_table *ft); |
140 | int ksmbd_close_fd(struct ksmbd_work *work, u64 id); |
141 | struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, u64 id); |
142 | struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id); |
143 | struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id, |
144 | u64 pid); |
145 | void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp); |
146 | struct ksmbd_inode *ksmbd_inode_lookup_lock(struct dentry *d); |
147 | void ksmbd_inode_put(struct ksmbd_inode *ci); |
148 | struct ksmbd_file *ksmbd_lookup_global_fd(unsigned long long id); |
149 | struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id); |
150 | void ksmbd_put_durable_fd(struct ksmbd_file *fp); |
151 | struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid); |
152 | struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry); |
153 | unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp); |
154 | struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp); |
155 | void ksmbd_close_tree_conn_fds(struct ksmbd_work *work); |
156 | void ksmbd_close_session_fds(struct ksmbd_work *work); |
157 | int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode); |
158 | int ksmbd_init_global_file_table(void); |
159 | void ksmbd_free_global_file_table(void); |
160 | void ksmbd_set_fd_limit(unsigned long limit); |
161 | void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp, |
162 | unsigned int state); |
163 | |
164 | /* |
165 | * INODE hash |
166 | */ |
167 | int __init ksmbd_inode_hash_init(void); |
168 | void ksmbd_release_inode_hash(void); |
169 | |
170 | enum KSMBD_INODE_STATUS { |
171 | KSMBD_INODE_STATUS_OK, |
172 | KSMBD_INODE_STATUS_UNKNOWN, |
173 | KSMBD_INODE_STATUS_PENDING_DELETE, |
174 | }; |
175 | |
176 | int ksmbd_query_inode_status(struct dentry *dentry); |
177 | bool ksmbd_inode_pending_delete(struct ksmbd_file *fp); |
178 | void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp); |
179 | void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp); |
180 | void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp, |
181 | int file_info); |
182 | int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp); |
183 | int ksmbd_validate_name_reconnect(struct ksmbd_share_config *share, |
184 | struct ksmbd_file *fp, char *name); |
185 | int ksmbd_init_file_cache(void); |
186 | void ksmbd_exit_file_cache(void); |
187 | #endif /* __VFS_CACHE_H__ */ |
188 | |