blob: 7c732cb4416411e597f2e1a4af96fd8bf7e49beb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/inode.c
3 *
Steve Frenchf19159d2010-04-21 04:12:10 +00004 * Copyright (C) International Business Machines Corp., 2002,2010
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/stat.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/pagemap.h>
Jeff Layton4f73c7d2014-04-30 09:31:47 -040025#include <linux/freezer.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010026#include <linux/sched/signal.h>
Ingo Molnar5dd43ce2017-06-20 12:19:09 +020027#include <linux/wait_bit.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <asm/div64.h>
30#include "cifsfs.h"
31#include "cifspdu.h"
32#include "cifsglob.h"
33#include "cifsproto.h"
34#include "cifs_debug.h"
35#include "cifs_fs_sb.h"
Steve French2baa2682014-09-27 02:19:01 -050036#include "cifs_unicode.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053037#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
Christoph Hellwig70eff552008-02-15 20:55:05 +000039
David Howells01c64fe2011-01-14 18:45:47 +000040static void cifs_set_ops(struct inode *inode)
Christoph Hellwig70eff552008-02-15 20:55:05 +000041{
42 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
43
44 switch (inode->i_mode & S_IFMT) {
45 case S_IFREG:
46 inode->i_op = &cifs_file_inode_ops;
47 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
48 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
49 inode->i_fop = &cifs_file_direct_nobrl_ops;
50 else
51 inode->i_fop = &cifs_file_direct_ops;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +030052 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
53 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
54 inode->i_fop = &cifs_file_strict_nobrl_ops;
55 else
56 inode->i_fop = &cifs_file_strict_ops;
Christoph Hellwig70eff552008-02-15 20:55:05 +000057 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
58 inode->i_fop = &cifs_file_nobrl_ops;
59 else { /* not direct, send byte range locks */
60 inode->i_fop = &cifs_file_ops;
61 }
62
Christoph Hellwig70eff552008-02-15 20:55:05 +000063 /* check if server can support readpages */
Jeff Layton0d424ad2010-09-20 16:01:35 -070064 if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +030065 PAGE_SIZE + MAX_CIFS_HDR_SIZE)
Christoph Hellwig70eff552008-02-15 20:55:05 +000066 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
67 else
68 inode->i_data.a_ops = &cifs_addr_ops;
69 break;
70 case S_IFDIR:
Steve Frenchbc5b6e22008-03-11 21:07:48 +000071#ifdef CONFIG_CIFS_DFS_UPCALL
David Howells01c64fe2011-01-14 18:45:47 +000072 if (IS_AUTOMOUNT(inode)) {
Igor Mammedov79626702008-03-09 03:44:18 +000073 inode->i_op = &cifs_dfs_referral_inode_operations;
74 } else {
Steve Frenchbc5b6e22008-03-11 21:07:48 +000075#else /* NO DFS support, treat as a directory */
76 {
77#endif
Igor Mammedov79626702008-03-09 03:44:18 +000078 inode->i_op = &cifs_dir_inode_ops;
79 inode->i_fop = &cifs_dir_ops;
80 }
Christoph Hellwig70eff552008-02-15 20:55:05 +000081 break;
82 case S_IFLNK:
83 inode->i_op = &cifs_symlink_inode_ops;
84 break;
85 default:
86 init_special_inode(inode, inode->i_mode, inode->i_rdev);
87 break;
88 }
89}
90
Jeff Laytondf2cf172010-02-12 07:44:16 -050091/* check inode attributes against fattr. If they don't match, tag the
92 * inode for cache invalidation
93 */
94static void
95cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
96{
97 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
98
Joe Perchesf96637b2013-05-04 22:12:25 -050099 cifs_dbg(FYI, "%s: revalidating inode %llu\n",
100 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500101
102 if (inode->i_state & I_NEW) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500103 cifs_dbg(FYI, "%s: inode %llu is new\n",
104 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500105 return;
106 }
107
108 /* don't bother with revalidation if we have an oplock */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400109 if (CIFS_CACHE_READ(cifs_i)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500110 cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
111 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500112 return;
113 }
114
115 /* revalidate if mtime or size have changed */
116 if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
117 cifs_i->server_eof == fattr->cf_eof) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500118 cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
119 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500120 return;
121 }
122
Joe Perchesf96637b2013-05-04 22:12:25 -0500123 cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
124 __func__, cifs_i->uniqueid);
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400125 set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500126}
127
Jim McDonough74d290d2013-09-21 10:36:10 -0500128/*
129 * copy nlink to the inode, unless it wasn't provided. Provide
130 * sane values if we don't have an existing one and none was provided
131 */
132static void
133cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
134{
135 /*
136 * if we're in a situation where we can't trust what we
137 * got from the server (readdir, some non-unix cases)
138 * fake reasonable values
139 */
140 if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
141 /* only provide fake values on a new inode */
142 if (inode->i_state & I_NEW) {
143 if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
144 set_nlink(inode, 2);
145 else
146 set_nlink(inode, 1);
147 }
148 return;
149 }
150
151 /* we trust the server, so update it */
152 set_nlink(inode, fattr->cf_nlink);
153}
154
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400155/* populate an inode with info from a cifs_fattr struct */
156void
157cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000158{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400159 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400160 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000161
Jeff Laytondf2cf172010-02-12 07:44:16 -0500162 cifs_revalidate_cache(inode, fattr);
163
Steve Frenchb7ca6922012-08-03 08:43:01 -0500164 spin_lock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400165 inode->i_atime = fattr->cf_atime;
166 inode->i_mtime = fattr->cf_mtime;
167 inode->i_ctime = fattr->cf_ctime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400168 inode->i_rdev = fattr->cf_rdev;
Jim McDonough74d290d2013-09-21 10:36:10 -0500169 cifs_nlink_fattr_to_inode(inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400170 inode->i_uid = fattr->cf_uid;
171 inode->i_gid = fattr->cf_gid;
172
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400173 /* if dynperm is set, don't clobber existing mode */
174 if (inode->i_state & I_NEW ||
175 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
176 inode->i_mode = fattr->cf_mode;
177
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400178 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400179
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400180 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
181 cifs_i->time = 0;
182 else
183 cifs_i->time = jiffies;
184
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400185 if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
186 set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
187 else
188 clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000189
Jeff Layton835a36c2010-02-10 16:21:33 -0500190 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000191 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400192 * Can't safely change the file size here if the client is writing to
193 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000194 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400195 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
196 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000197
198 /*
199 * i_blocks is not related to (i_size / i_blksize),
200 * but instead 512 byte (2**9) size is required for
201 * calculating num blocks.
202 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400203 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000204 }
205 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400206
David Howells01c64fe2011-01-14 18:45:47 +0000207 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
208 inode->i_flags |= S_AUTOMOUNT;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400209 if (inode->i_state & I_NEW)
210 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000211}
212
Jeff Layton4065c802010-05-17 07:18:58 -0400213void
214cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
215{
216 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
217
218 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
219 return;
220
221 fattr->cf_uniqueid = iunique(sb, ROOT_I);
222}
223
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400224/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
225void
226cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
227 struct cifs_sb_info *cifs_sb)
228{
229 memset(fattr, 0, sizeof(*fattr));
230 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
231 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
232 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
233
234 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
235 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
236 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
Steve French6e70e262017-09-21 21:32:29 -0500237 /* old POSIX extensions don't get create time */
238
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400239 fattr->cf_mode = le64_to_cpu(info->Permissions);
240
241 /*
242 * Since we set the inode type below we need to mask off
243 * to avoid strange results if bits set above.
244 */
245 fattr->cf_mode &= ~S_IFMT;
246 switch (le32_to_cpu(info->Type)) {
247 case UNIX_FILE:
248 fattr->cf_mode |= S_IFREG;
249 fattr->cf_dtype = DT_REG;
250 break;
251 case UNIX_SYMLINK:
252 fattr->cf_mode |= S_IFLNK;
253 fattr->cf_dtype = DT_LNK;
254 break;
255 case UNIX_DIR:
256 fattr->cf_mode |= S_IFDIR;
257 fattr->cf_dtype = DT_DIR;
258 break;
259 case UNIX_CHARDEV:
260 fattr->cf_mode |= S_IFCHR;
261 fattr->cf_dtype = DT_CHR;
262 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
263 le64_to_cpu(info->DevMinor) & MINORMASK);
264 break;
265 case UNIX_BLOCKDEV:
266 fattr->cf_mode |= S_IFBLK;
267 fattr->cf_dtype = DT_BLK;
268 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
269 le64_to_cpu(info->DevMinor) & MINORMASK);
270 break;
271 case UNIX_FIFO:
272 fattr->cf_mode |= S_IFIFO;
273 fattr->cf_dtype = DT_FIFO;
274 break;
275 case UNIX_SOCKET:
276 fattr->cf_mode |= S_IFSOCK;
277 fattr->cf_dtype = DT_SOCK;
278 break;
279 default:
280 /* safest to call it a file if we do not know */
281 fattr->cf_mode |= S_IFREG;
282 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500283 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400284 break;
285 }
286
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800287 fattr->cf_uid = cifs_sb->mnt_uid;
288 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
289 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800290 if (id < ((uid_t)-1)) {
291 kuid_t uid = make_kuid(&init_user_ns, id);
292 if (uid_valid(uid))
293 fattr->cf_uid = uid;
294 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800295 }
296
297 fattr->cf_gid = cifs_sb->mnt_gid;
298 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
299 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800300 if (id < ((gid_t)-1)) {
301 kgid_t gid = make_kgid(&init_user_ns, id);
302 if (gid_valid(gid))
303 fattr->cf_gid = gid;
304 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800305 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400306
307 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
308}
Steve Frenchb9a32602008-05-20 21:52:32 +0000309
310/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400311 * Fill a cifs_fattr struct with fake inode info.
312 *
313 * Needed to setup cifs_fattr data for the directory which is the
314 * junction to the new submount (ie to setup the fake directory
315 * which represents a DFS referral).
Steve Frenchb9a32602008-05-20 21:52:32 +0000316 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000317static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400318cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000319{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400320 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000321
Joe Perchesf96637b2013-05-04 22:12:25 -0500322 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000323
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400324 memset(fattr, 0, sizeof(*fattr));
325 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
326 fattr->cf_uid = cifs_sb->mnt_uid;
327 fattr->cf_gid = cifs_sb->mnt_gid;
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700328 ktime_get_real_ts(&fattr->cf_mtime);
329 fattr->cf_mtime = timespec_trunc(fattr->cf_mtime, sb->s_time_gran);
330 fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400331 fattr->cf_nlink = 2;
332 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000333}
334
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700335static int
336cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500337{
338 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400339 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500340 FILE_UNIX_BASIC_INFO find_data;
341 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500342 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500343 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700344 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000345 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500346
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400347 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700348 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500349 if (!rc) {
350 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
351 } else if (rc == -EREMOTE) {
352 cifs_create_dfs_fattr(&fattr, inode->i_sb);
353 rc = 0;
354 }
355
356 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400357 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500358 return rc;
359}
360
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400362 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400363 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400365 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000366 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400367 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000368 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400369 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Joe Perchesf96637b2013-05-04 22:12:25 -0500372 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000373
Jeff Layton7ffec372010-09-29 19:51:11 -0400374 tlink = cifs_sb_tlink(cifs_sb);
375 if (IS_ERR(tlink))
376 return PTR_ERR(tlink);
377 tcon = tlink_tcon(tlink);
378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400380 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +0900381 cifs_sb->local_nls, cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400382 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400383
384 if (!rc) {
385 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
386 } else if (rc == -EREMOTE) {
387 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700388 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400389 } else {
390 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000391 }
392
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200393 /* check for Minshall+French symlinks */
394 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000395 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
396 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200397 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000398 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200399 }
400
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400401 if (*pinode == NULL) {
402 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400403 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400404 *pinode = cifs_iget(sb, &fattr);
405 if (!*pinode)
406 rc = -ENOMEM;
407 } else {
408 /* we already have inode, update it */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900409
410 /* if uniqueid is different, return error */
411 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
412 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
413 rc = -ESTALE;
414 goto cgiiu_exit;
415 }
416
417 /* if filetype is different, return error */
418 if (unlikely(((*pinode)->i_mode & S_IFMT) !=
419 (fattr.cf_mode & S_IFMT))) {
420 rc = -ESTALE;
421 goto cgiiu_exit;
422 }
423
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400424 cifs_fattr_to_inode(*pinode, &fattr);
425 }
Steve French0e4bbde2008-05-20 19:50:46 +0000426
Nakajima Akira7196ac12015-04-22 15:24:44 +0900427cgiiu_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 return rc;
429}
430
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400431static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400432cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400433 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800434{
435 int rc;
Steve Frenchdb8b6312014-09-22 05:13:55 -0500436 __u32 oplock;
Jeff Layton7ffec372010-09-29 19:51:11 -0400437 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000438 struct cifs_tcon *tcon;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400439 struct cifs_fid fid;
440 struct cifs_open_parms oparms;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000441 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800442 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800443 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000444 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400445 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800446
447 pbuf = buf;
448
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400449 fattr->cf_mode &= ~S_IFMT;
450
451 if (fattr->cf_eof == 0) {
452 fattr->cf_mode |= S_IFIFO;
453 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800454 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400455 } else if (fattr->cf_eof < 8) {
456 fattr->cf_mode |= S_IFREG;
457 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800458 return -EINVAL; /* EOPNOTSUPP? */
459 }
Steve French50c2f752007-07-13 00:33:32 +0000460
Jeff Layton7ffec372010-09-29 19:51:11 -0400461 tlink = cifs_sb_tlink(cifs_sb);
462 if (IS_ERR(tlink))
463 return PTR_ERR(tlink);
464 tcon = tlink_tcon(tlink);
465
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400466 oparms.tcon = tcon;
467 oparms.cifs_sb = cifs_sb;
468 oparms.desired_access = GENERIC_READ;
469 oparms.create_options = CREATE_NOT_DIR;
470 oparms.disposition = FILE_OPEN;
471 oparms.path = path;
472 oparms.fid = &fid;
473 oparms.reconnect = false;
474
Steve Frenchdb8b6312014-09-22 05:13:55 -0500475 if (tcon->ses->server->oplocks)
476 oplock = REQ_OPLOCK;
477 else
478 oplock = 0;
479 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400480 if (rc) {
Steve Frenchdb8b6312014-09-22 05:13:55 -0500481 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400482 cifs_put_tlink(tlink);
483 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800484 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400485
486 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400487 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400488 io_parms.pid = current->tgid;
489 io_parms.tcon = tcon;
490 io_parms.offset = 0;
491 io_parms.length = 24;
492
Steve Frenchdb8b6312014-09-22 05:13:55 -0500493 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
494 &bytes_read, &pbuf, &buf_type);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400495 if ((rc == 0) && (bytes_read >= 8)) {
496 if (memcmp("IntxBLK", pbuf, 8) == 0) {
497 cifs_dbg(FYI, "Block device\n");
498 fattr->cf_mode |= S_IFBLK;
499 fattr->cf_dtype = DT_BLK;
500 if (bytes_read == 24) {
501 /* we have enough to decode dev num */
502 __u64 mjr; /* major */
503 __u64 mnr; /* minor */
504 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
505 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
506 fattr->cf_rdev = MKDEV(mjr, mnr);
507 }
508 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
509 cifs_dbg(FYI, "Char device\n");
510 fattr->cf_mode |= S_IFCHR;
511 fattr->cf_dtype = DT_CHR;
512 if (bytes_read == 24) {
513 /* we have enough to decode dev num */
514 __u64 mjr; /* major */
515 __u64 mnr; /* minor */
516 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
517 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
518 fattr->cf_rdev = MKDEV(mjr, mnr);
519 }
520 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
521 cifs_dbg(FYI, "Symlink\n");
522 fattr->cf_mode |= S_IFLNK;
523 fattr->cf_dtype = DT_LNK;
524 } else {
525 fattr->cf_mode |= S_IFREG; /* file? */
526 fattr->cf_dtype = DT_REG;
527 rc = -EOPNOTSUPP;
528 }
529 } else {
530 fattr->cf_mode |= S_IFREG; /* then it is a file */
531 fattr->cf_dtype = DT_REG;
532 rc = -EOPNOTSUPP; /* or some unknown SFU type */
533 }
Steve Frenchdb8b6312014-09-22 05:13:55 -0500534
535 tcon->ses->server->ops->close(xid, tcon, &fid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400536 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800537 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800538}
539
Steve French9e294f12005-11-17 16:59:21 -0800540#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
541
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400542/*
543 * Fetch mode bits as provided by SFU.
544 *
545 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
546 */
547static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400548 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800549{
Steve French3020a1f2005-11-18 11:31:10 -0800550#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800551 ssize_t rc;
552 char ea_value[4];
553 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400554 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000555 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800556
Jeff Layton7ffec372010-09-29 19:51:11 -0400557 tlink = cifs_sb_tlink(cifs_sb);
558 if (IS_ERR(tlink))
559 return PTR_ERR(tlink);
560 tcon = tlink_tcon(tlink);
561
Steve Frenchd979f3b2014-02-01 23:27:18 -0600562 if (tcon->ses->server->ops->query_all_EAs == NULL) {
563 cifs_put_tlink(tlink);
564 return -EOPNOTSUPP;
565 }
566
567 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
568 "SETFILEBITS", ea_value, 4 /* size of buf */,
Steve French67b4c882017-05-12 20:59:10 -0500569 cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400570 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000571 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800572 return (int)rc;
573 else if (rc > 3) {
574 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400575 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500576 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
577 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400578 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500579 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800580 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400581
582 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800583#else
584 return -EOPNOTSUPP;
585#endif
Steve French9e294f12005-11-17 16:59:21 -0800586}
587
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400588/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000589static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400590cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700591 struct super_block *sb, bool adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400592 bool symlink)
Steve Frenchb9a32602008-05-20 21:52:32 +0000593{
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700594 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French96daf2b2011-05-27 04:34:02 +0000595 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700596
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400597 memset(fattr, 0, sizeof(*fattr));
598 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
599 if (info->DeletePending)
600 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000601
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400602 if (info->LastAccessTime)
603 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700604 else {
605 ktime_get_real_ts(&fattr->cf_atime);
606 fattr->cf_atime = timespec_trunc(fattr->cf_atime, sb->s_time_gran);
607 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400608
609 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
610 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
611
612 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700613 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
614 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400615 }
616
617 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
618 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500619 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400620
Jim McDonough74d290d2013-09-21 10:36:10 -0500621 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400622
623 if (symlink) {
624 fattr->cf_mode = S_IFLNK;
625 fattr->cf_dtype = DT_LNK;
626 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400627 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
628 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300629 /*
630 * Server can return wrong NumberOfLinks value for directories
631 * when Unix extensions are disabled - fake it.
632 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500633 if (!tcon->unix_ext)
634 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400635 } else {
636 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
637 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400638
Jeff Laytond0c280d2009-07-09 01:46:44 -0400639 /* clear write bits if ATTR_READONLY is set */
640 if (fattr->cf_cifsattrs & ATTR_READONLY)
641 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400642
Jim McDonough74d290d2013-09-21 10:36:10 -0500643 /*
644 * Don't accept zero nlink from non-unix servers unless
645 * delete is pending. Instead mark it as unknown.
646 */
647 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
648 !info->DeletePending) {
649 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500650 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500651 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500652 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300653 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400654
655 fattr->cf_uid = cifs_sb->mnt_uid;
656 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000657}
658
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700659static int
660cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500661{
662 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400663 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500664 FILE_ALL_INFO find_data;
665 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500666 struct inode *inode = file_inode(filp);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700667 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000668 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700669 struct TCP_Server_Info *server = tcon->ses->server;
670
671 if (!server->ops->query_file_info)
672 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500673
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400674 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700675 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400676 switch (rc) {
677 case 0:
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700678 cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400679 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400680 break;
681 case -EREMOTE:
682 cifs_create_dfs_fattr(&fattr, inode->i_sb);
683 rc = 0;
684 break;
685 case -EOPNOTSUPP:
686 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500687 /*
688 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000689 * for now, just skip revalidating and mark inode for
690 * immediate reval.
691 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500692 rc = 0;
693 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400694 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500695 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400696 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500697
698 /*
699 * don't bother with SFU junk here -- just mark inode as needing
700 * revalidation.
701 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500702 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
703 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
704 cifs_fattr_to_inode(inode, &fattr);
705cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400706 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500707 return rc;
708}
709
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400710int
711cifs_get_inode_info(struct inode **inode, const char *full_path,
712 FILE_ALL_INFO *data, struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600713 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500715 bool validinum = false;
716 __u16 srchflgs;
717 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400718 struct cifs_tcon *tcon;
719 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400720 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400723 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400724 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500725 struct cifs_search_info *srchinf = NULL;
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400726 bool symlink = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727
Jeff Layton7ffec372010-09-29 19:51:11 -0400728 tlink = cifs_sb_tlink(cifs_sb);
729 if (IS_ERR(tlink))
730 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400731 tcon = tlink_tcon(tlink);
732 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400733
Joe Perchesf96637b2013-05-04 22:12:25 -0500734 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400736 if ((data == NULL) && (*inode != NULL)) {
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400737 if (CIFS_CACHE_READ(CIFS_I(*inode))) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500738 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400739 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 }
741 }
742
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400743 /* if inode info is not passed, get it from server */
744 if (data == NULL) {
745 if (!server->ops->query_path_info) {
746 rc = -ENOSYS;
747 goto cgii_exit;
748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400750 if (buf == NULL) {
751 rc = -ENOMEM;
752 goto cgii_exit;
753 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400754 data = (FILE_ALL_INFO *)buf;
755 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400756 data, &adjust_tz, &symlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400758
759 if (!rc) {
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700760 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400761 symlink);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400762 } else if (rc == -EREMOTE) {
763 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000764 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500765 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
766 srchinf = kzalloc(sizeof(struct cifs_search_info),
767 GFP_KERNEL);
768 if (srchinf == NULL) {
769 rc = -ENOMEM;
770 goto cgii_exit;
771 }
772
773 srchinf->endOfSearch = false;
774 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
775
776 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
777 CIFS_SEARCH_CLOSE_AT_END |
778 CIFS_SEARCH_BACKUP_SEARCH;
779
780 rc = CIFSFindFirst(xid, tcon, full_path,
781 cifs_sb, NULL, srchflgs, srchinf, false);
782 if (!rc) {
783 data =
784 (FILE_ALL_INFO *)srchinf->srch_entries_start;
785
786 cifs_dir_info_to_fattr(&fattr,
787 (FILE_DIRECTORY_INFO *)data, cifs_sb);
788 fattr.cf_uniqueid = le64_to_cpu(
789 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
790 validinum = true;
791
792 cifs_buf_release(srchinf->ntwrk_buf_start);
793 }
794 kfree(srchinf);
Steve French4c5930e2015-03-30 22:03:06 -0500795 if (rc)
796 goto cgii_exit;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500797 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000798 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400800 /*
801 * If an inode wasn't passed in, then get the inode number
802 *
803 * Is an i_ino of zero legal? Can we use that to check if the server
804 * supports returning inode numbers? Are there other sanity checks we
805 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400806 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400807 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000808 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500809 if (validinum == false) {
810 if (server->ops->get_srv_inum)
811 tmprc = server->ops->get_srv_inum(xid,
812 tcon, cifs_sb, full_path,
813 &fattr.cf_uniqueid, data);
814 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500815 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
816 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500817 fattr.cf_uniqueid = iunique(sb, ROOT_I);
818 cifs_autodisable_serverino(cifs_sb);
819 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500820 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500821 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400822 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000823 } else {
824 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
825 validinum == false && server->ops->get_srv_inum) {
826 /*
827 * Pass a NULL tcon to ensure we don't make a round
828 * trip to the server. This only works for SMB2+.
829 */
830 tmprc = server->ops->get_srv_inum(xid,
831 NULL, cifs_sb, full_path,
832 &fattr.cf_uniqueid, data);
833 if (tmprc)
834 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
835 } else
836 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
837 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000838
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400839 /* query for SFU type info if supported and needed */
840 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
841 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
842 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
843 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500844 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000845 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000846
Jeff Layton79df1ba2010-12-06 12:52:08 -0500847#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000848 /* fill in 0777 bits from ACL */
849 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400850 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600851 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500852 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
853 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600854 goto cgii_exit;
855 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000856 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500857#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400858
859 /* fill in remaining high mode bits e.g. SUID, VTX */
860 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
861 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
862
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200863 /* check for Minshall+French symlinks */
864 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000865 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
866 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200867 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000868 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200869 }
870
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400871 if (!*inode) {
872 *inode = cifs_iget(sb, &fattr);
873 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400874 rc = -ENOMEM;
875 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +0900876 /* we already have inode, update it */
877
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000878 /* if uniqueid is different, return error */
879 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
880 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
881 rc = -ESTALE;
882 goto cgii_exit;
883 }
884
Nakajima Akira7196ac12015-04-22 15:24:44 +0900885 /* if filetype is different, return error */
886 if (unlikely(((*inode)->i_mode & S_IFMT) !=
887 (fattr.cf_mode & S_IFMT))) {
888 rc = -ESTALE;
889 goto cgii_exit;
890 }
891
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400892 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000893 }
894
Igor Mammedov79626702008-03-09 03:44:18 +0000895cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400897 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 return rc;
899}
900
Steve French7f8ed422007-09-28 22:28:55 +0000901static const struct inode_operations cifs_ipc_inode_ops = {
902 .lookup = cifs_lookup,
903};
904
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400905static int
906cifs_find_inode(struct inode *inode, void *opaque)
907{
908 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
909
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400910 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400911 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
912 return 0;
913
Jeff Layton20054bd2011-01-07 11:30:27 -0500914 /* use createtime like an i_generation field */
915 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
916 return 0;
917
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400918 /* don't match inode of different type */
919 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
920 return 0;
921
Jeff Layton5acfec22010-08-02 17:43:54 -0400922 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400923 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400924 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400925
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400926 return 1;
927}
928
929static int
930cifs_init_inode(struct inode *inode, void *opaque)
931{
932 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
933
934 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500935 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400936 return 0;
937}
938
Jeff Layton5acfec22010-08-02 17:43:54 -0400939/*
940 * walk dentry list for an inode and report whether it has aliases that
941 * are hashed. We use this to determine if a directory inode can actually
942 * be used.
943 */
944static bool
945inode_has_hashed_dentries(struct inode *inode)
946{
947 struct dentry *dentry;
948
Nick Piggin873feea2011-01-07 17:50:06 +1100949 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -0400950 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400951 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100952 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400953 return true;
954 }
955 }
Nick Piggin873feea2011-01-07 17:50:06 +1100956 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400957 return false;
958}
959
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400960/* Given fattrs, get a corresponding inode */
961struct inode *
962cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
963{
964 unsigned long hash;
965 struct inode *inode;
966
Jeff Layton3d694382010-05-11 14:59:55 -0400967retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -0500968 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400969
970 /* hash down to 32-bits on 32-bit arch */
971 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
972
973 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400974 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400975 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400976 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400977 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400978
979 if (inode_has_hashed_dentries(inode)) {
980 cifs_autodisable_serverino(CIFS_SB(sb));
981 iput(inode);
982 fattr->cf_uniqueid = iunique(sb, ROOT_I);
983 goto retry_iget5_locked;
984 }
Jeff Layton3d694382010-05-11 14:59:55 -0400985 }
986
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400987 cifs_fattr_to_inode(inode, fattr);
988 if (sb->s_flags & MS_NOATIME)
989 inode->i_flags |= S_NOATIME | S_NOCMTIME;
990 if (inode->i_state & I_NEW) {
991 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +0000992#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530993 /* initialize per-inode cache cookie pointer */
994 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000995#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400996 unlock_new_inode(inode);
997 }
998 }
999
1000 return inode;
1001}
1002
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001004struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001006 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001007 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001008 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001009 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001010 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001011 char *path = NULL;
1012 int len;
1013
1014 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1015 && cifs_sb->prepath) {
1016 len = strlen(cifs_sb->prepath);
1017 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1018 if (path == NULL)
1019 return ERR_PTR(-ENOMEM);
1020 path[0] = '/';
1021 memcpy(path+1, cifs_sb->prepath, len);
1022 } else {
1023 path = kstrdup("", GFP_KERNEL);
1024 if (path == NULL)
1025 return ERR_PTR(-ENOMEM);
1026 }
David Howellsce634ab2008-02-07 00:15:33 -08001027
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001028 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001029 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001030 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001031 /* some servers mistakenly claim POSIX support */
1032 if (rc != -EOPNOTSUPP)
1033 goto iget_no_retry;
1034 cifs_dbg(VFS, "server does not support POSIX extensions");
1035 tcon->unix_ext = false;
1036 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001037
Aurelien Aptela6b50582016-05-25 19:59:09 +02001038 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1039 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001040
1041iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001042 if (!inode) {
1043 inode = ERR_PTR(rc);
1044 goto out;
1045 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001046
Steve French0ccd4802010-07-16 04:31:02 +00001047#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301048 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001049 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001050#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301051
Jeff Layton0d424ad2010-09-20 16:01:35 -07001052 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001053 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001054 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001055 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001056 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001057 inode->i_op = &cifs_ipc_inode_ops;
1058 inode->i_fop = &simple_dir_operations;
1059 inode->i_uid = cifs_sb->mnt_uid;
1060 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001061 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001062 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001063 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001064 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001065 }
1066
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001067out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001068 kfree(path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001069 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -08001070 * TODO: This is no longer true
1071 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001072 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001073 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074}
1075
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001076int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001077cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001078 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001079{
Steve French388e57b2008-09-16 23:50:58 +00001080 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001081 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001082 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001083 FILE_BASIC_INFO info_buf;
1084
Steve French1adcb712009-02-25 14:19:56 +00001085 if (attrs == NULL)
1086 return -EINVAL;
1087
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001088 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1089 if (!server->ops->set_file_info)
1090 return -ENOSYS;
1091
Steve French388e57b2008-09-16 23:50:58 +00001092 if (attrs->ia_valid & ATTR_ATIME) {
1093 set_time = true;
1094 info_buf.LastAccessTime =
1095 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1096 } else
1097 info_buf.LastAccessTime = 0;
1098
1099 if (attrs->ia_valid & ATTR_MTIME) {
1100 set_time = true;
1101 info_buf.LastWriteTime =
1102 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1103 } else
1104 info_buf.LastWriteTime = 0;
1105
1106 /*
1107 * Samba throws this field away, but windows may actually use it.
1108 * Do not set ctime unless other time stamps are changed explicitly
1109 * (i.e. by utimes()) since we would then have a mix of client and
1110 * server times.
1111 */
1112 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001113 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001114 info_buf.ChangeTime =
1115 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1116 } else
1117 info_buf.ChangeTime = 0;
1118
1119 info_buf.CreationTime = 0; /* don't change */
1120 info_buf.Attributes = cpu_to_le32(dosattr);
1121
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001122 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001123}
1124
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001125/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001126 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001127 * and rename it to a random name that hopefully won't conflict with
1128 * anything else.
1129 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001130int
1131cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1132 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001133{
1134 int oplock = 0;
1135 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001136 struct cifs_fid fid;
1137 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001138 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001139 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1140 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001141 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001142 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001143 __u32 dosattr, origattr;
1144 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001145
Jeff Layton7ffec372010-09-29 19:51:11 -04001146 tlink = cifs_sb_tlink(cifs_sb);
1147 if (IS_ERR(tlink))
1148 return PTR_ERR(tlink);
1149 tcon = tlink_tcon(tlink);
1150
Sachin Prabhuc483a982013-03-05 19:25:56 +00001151 /*
1152 * We cannot rename the file if the server doesn't support
1153 * CAP_INFOLEVEL_PASSTHRU
1154 */
1155 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1156 rc = -EBUSY;
1157 goto out;
1158 }
1159
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001160 oparms.tcon = tcon;
1161 oparms.cifs_sb = cifs_sb;
1162 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1163 oparms.create_options = CREATE_NOT_DIR;
1164 oparms.disposition = FILE_OPEN;
1165 oparms.path = full_path;
1166 oparms.fid = &fid;
1167 oparms.reconnect = false;
1168
1169 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001170 if (rc != 0)
1171 goto out;
1172
Steve French32709582008-10-20 00:44:19 +00001173 origattr = cifsInode->cifsAttrs;
1174 if (origattr == 0)
1175 origattr |= ATTR_NORMAL;
1176
1177 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001178 if (dosattr == 0)
1179 dosattr |= ATTR_NORMAL;
1180 dosattr |= ATTR_HIDDEN;
1181
Steve French32709582008-10-20 00:44:19 +00001182 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1183 if (dosattr != origattr) {
1184 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1185 if (info_buf == NULL) {
1186 rc = -ENOMEM;
1187 goto out_close;
1188 }
1189 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001190 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001191 current->tgid);
1192 /* although we would like to mark the file hidden
1193 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001194 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001195 cifsInode->cifsAttrs = dosattr;
1196 else
1197 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001198 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001199
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001200 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001201 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1202 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001203 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001204 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001205 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001206 goto undo_setattr;
1207 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001208
Steve French32709582008-10-20 00:44:19 +00001209 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001210 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001211 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001212 current->tgid);
1213 /*
1214 * some samba versions return -ENOENT when we try to set the
1215 * file disposition here. Likely a samba bug, but work around
1216 * it for now. This means that some cifsXXX files may hang
1217 * around after they shouldn't.
1218 *
1219 * BB: remove this hack after more servers have the fix
1220 */
1221 if (rc == -ENOENT)
1222 rc = 0;
1223 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001224 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001225 goto undo_rename;
1226 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001227 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001228 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001229
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001230out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001231 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001232out:
Steve French32709582008-10-20 00:44:19 +00001233 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001234 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001235 return rc;
Steve French32709582008-10-20 00:44:19 +00001236
1237 /*
1238 * reset everything back to the original state. Don't bother
1239 * dealing with errors here since we can't do anything about
1240 * them anyway.
1241 */
1242undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001243 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001244 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001245undo_setattr:
1246 if (dosattr != origattr) {
1247 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001248 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001249 current->tgid))
1250 cifsInode->cifsAttrs = origattr;
1251 }
1252
1253 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001254}
1255
Steve Frenchb7ca6922012-08-03 08:43:01 -05001256/* copied from fs/nfs/dir.c with small changes */
1257static void
1258cifs_drop_nlink(struct inode *inode)
1259{
1260 spin_lock(&inode->i_lock);
1261 if (inode->i_nlink > 0)
1262 drop_nlink(inode);
1263 spin_unlock(&inode->i_lock);
1264}
Steve Frenchff694522009-04-20 19:45:13 +00001265
1266/*
David Howells2b0143b2015-03-17 22:25:59 +00001267 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001268 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001269 * if that fails we can not attempt the fall back mechanisms on EACCESS
1270 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001271 * unlink on negative dentries currently.
1272 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001273int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274{
1275 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001276 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001278 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001279 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001280 struct super_block *sb = dir->i_sb;
1281 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001282 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001283 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001284 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001285 struct iattr *attrs = NULL;
1286 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
Joe Perchesf96637b2013-05-04 22:12:25 -05001288 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Jeff Layton7ffec372010-09-29 19:51:11 -04001290 tlink = cifs_sb_tlink(cifs_sb);
1291 if (IS_ERR(tlink))
1292 return PTR_ERR(tlink);
1293 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001294 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001295
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001296 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
Jeff Layton5f0319a2008-09-16 14:05:16 -04001298 /* Unlink can be called from rename so we can not take the
1299 * sb->s_vfs_rename_mutex here */
1300 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301302 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001303 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 }
Steve French2d785a52007-07-15 01:48:57 +00001305
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001306 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1307 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001308 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001309 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001310 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001311 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001312 if ((rc == 0) || (rc == -ENOENT))
1313 goto psx_del_no_retry;
1314 }
1315
Steve French60502472008-10-07 18:42:52 +00001316retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001317 if (!server->ops->unlink) {
1318 rc = -ENOSYS;
1319 goto psx_del_no_retry;
1320 }
1321
1322 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001323
Steve French2d785a52007-07-15 01:48:57 +00001324psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001326 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001327 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001329 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001330 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001331 if (server->ops->rename_pending_delete) {
1332 rc = server->ops->rename_pending_delete(full_path,
1333 dentry, xid);
1334 if (rc == 0)
1335 cifs_drop_nlink(inode);
1336 }
Steve Frenchff694522009-04-20 19:45:13 +00001337 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001338 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1339 if (attrs == NULL) {
1340 rc = -ENOMEM;
1341 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 }
Steve French388e57b2008-09-16 23:50:58 +00001343
1344 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001345 cifs_inode = CIFS_I(inode);
1346 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001347 if (origattr == 0)
1348 origattr |= ATTR_NORMAL;
1349 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001350 if (dosattr == 0)
1351 dosattr |= ATTR_NORMAL;
1352 dosattr |= ATTR_HIDDEN;
1353
1354 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001355 if (rc != 0)
1356 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001357
1358 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 }
Steve French60502472008-10-07 18:42:52 +00001360
1361 /* undo the setattr if we errored out and it's needed */
1362 if (rc != 0 && dosattr != 0)
1363 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1364
Steve French388e57b2008-09-16 23:50:58 +00001365out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001366 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001367 cifs_inode = CIFS_I(inode);
1368 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001369 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001370 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001371 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001372 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001373 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001374 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001375unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001377 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001378 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001379 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 return rc;
1381}
1382
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001383static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001384cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001385 const char *full_path, struct cifs_sb_info *cifs_sb,
1386 struct cifs_tcon *tcon, const unsigned int xid)
1387{
1388 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001389 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001390
1391 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001392 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001393 xid);
1394 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001395 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1396 xid, NULL);
1397
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001398 if (rc)
1399 return rc;
1400
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001401 /*
1402 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001403 * from the server or was set bogus. Also, since this is a brand new
1404 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001405 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001406 if (inode->i_nlink < 2)
1407 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001408 mode &= ~current_umask();
1409 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001410 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001411 mode |= S_ISGID;
1412
1413 if (tcon->unix_ext) {
1414 struct cifs_unix_set_info_args args = {
1415 .mode = mode,
1416 .ctime = NO_CHANGE_64,
1417 .atime = NO_CHANGE_64,
1418 .mtime = NO_CHANGE_64,
1419 .device = 0,
1420 };
1421 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001422 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001423 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001424 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001425 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001426 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001427 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001428 args.uid = INVALID_UID; /* no change */
1429 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001430 }
1431 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1432 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001433 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001434 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001435 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001436 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001437 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001438 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001439 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001440 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1441 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001442
Jeff Layton101b92d2012-09-19 06:22:45 -07001443 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1444 inode->i_uid = current_fsuid();
1445 if (inode->i_mode & S_ISGID)
1446 inode->i_gid = parent->i_gid;
1447 else
1448 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001449 }
1450 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001451 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001452 return rc;
1453}
1454
1455static int
1456cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1457 const char *full_path, struct cifs_sb_info *cifs_sb,
1458 struct cifs_tcon *tcon, const unsigned int xid)
1459{
1460 int rc = 0;
1461 u32 oplock = 0;
1462 FILE_UNIX_BASIC_INFO *info = NULL;
1463 struct inode *newinode = NULL;
1464 struct cifs_fattr fattr;
1465
1466 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1467 if (info == NULL) {
1468 rc = -ENOMEM;
1469 goto posix_mkdir_out;
1470 }
1471
1472 mode &= ~current_umask();
1473 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1474 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001475 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001476 if (rc == -EOPNOTSUPP)
1477 goto posix_mkdir_out;
1478 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001479 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001480 d_drop(dentry);
1481 goto posix_mkdir_out;
1482 }
1483
1484 if (info->Type == cpu_to_le32(-1))
1485 /* no return info, go query for it */
1486 goto posix_mkdir_get_info;
1487 /*
1488 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1489 * need to set uid/gid.
1490 */
1491
1492 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1493 cifs_fill_uniqueid(inode->i_sb, &fattr);
1494 newinode = cifs_iget(inode->i_sb, &fattr);
1495 if (!newinode)
1496 goto posix_mkdir_get_info;
1497
1498 d_instantiate(dentry, newinode);
1499
1500#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001501 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1502 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001503
1504 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001505 cifs_dbg(FYI, "unexpected number of links %d\n",
1506 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001507#endif
1508
1509posix_mkdir_out:
1510 kfree(info);
1511 return rc;
1512posix_mkdir_get_info:
1513 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1514 xid);
1515 goto posix_mkdir_out;
1516}
1517
Al Viro18bb1db2011-07-26 01:41:39 -04001518int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001520 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001521 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001523 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001524 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001525 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001526 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527
Joe Perchesf96637b2013-05-04 22:12:25 -05001528 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1529 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001532 tlink = cifs_sb_tlink(cifs_sb);
1533 if (IS_ERR(tlink))
1534 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001535 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001536
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001537 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Steve French7f573562005-08-30 11:32:14 -07001539 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301541 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001542 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 }
Steve French50c2f752007-07-13 00:33:32 +00001544
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001545 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1546 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001547 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1548 tcon, xid);
1549 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001550 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001551 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001552
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001553 server = tcon->ses->server;
1554
1555 if (!server->ops->mkdir) {
1556 rc = -ENOSYS;
1557 goto mkdir_out;
1558 }
1559
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001561 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001563 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001565 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001567
1568 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1569 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001570mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001571 /*
1572 * Force revalidate to get parent dir info when needed since cached
1573 * attributes are invalid now.
1574 */
1575 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001577 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001578 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 return rc;
1580}
1581
1582int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1583{
1584 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001585 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001587 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001588 struct cifs_tcon *tcon;
1589 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 char *full_path = NULL;
1591 struct cifsInodeInfo *cifsInode;
1592
Joe Perchesf96637b2013-05-04 22:12:25 -05001593 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001595 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
Steve French7f573562005-08-30 11:32:14 -07001597 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301599 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001600 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 }
1602
Jeff Layton7ffec372010-09-29 19:51:11 -04001603 cifs_sb = CIFS_SB(inode->i_sb);
1604 tlink = cifs_sb_tlink(cifs_sb);
1605 if (IS_ERR(tlink)) {
1606 rc = PTR_ERR(tlink);
1607 goto rmdir_exit;
1608 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001609 tcon = tlink_tcon(tlink);
1610 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001611
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001612 if (!server->ops->rmdir) {
1613 rc = -ENOSYS;
1614 cifs_put_tlink(tlink);
1615 goto rmdir_exit;
1616 }
1617
1618 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001619 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
1621 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001622 spin_lock(&d_inode(direntry)->i_lock);
1623 i_size_write(d_inode(direntry), 0);
1624 clear_nlink(d_inode(direntry));
1625 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 }
1627
David Howells2b0143b2015-03-17 22:25:59 +00001628 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001629 /* force revalidate to go get info when needed */
1630 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001631
1632 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001633 /*
1634 * Force revalidate to get parent dir info when needed since cached
1635 * attributes are invalid now.
1636 */
1637 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001638
David Howells2b0143b2015-03-17 22:25:59 +00001639 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001640 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Jeff Layton7ffec372010-09-29 19:51:11 -04001642rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001644 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 return rc;
1646}
1647
Steve Frenchee2fd962008-09-23 18:23:33 +00001648static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001649cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1650 const char *from_path, struct dentry *to_dentry,
1651 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001652{
1653 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001654 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001655 struct cifs_tcon *tcon;
1656 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001657 struct cifs_fid fid;
1658 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001659 int oplock, rc;
1660
Jeff Layton7ffec372010-09-29 19:51:11 -04001661 tlink = cifs_sb_tlink(cifs_sb);
1662 if (IS_ERR(tlink))
1663 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001664 tcon = tlink_tcon(tlink);
1665 server = tcon->ses->server;
1666
1667 if (!server->ops->rename)
1668 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001669
Steve Frenchee2fd962008-09-23 18:23:33 +00001670 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001671 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001672
1673 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001674 * Don't bother with rename by filehandle unless file is busy and
1675 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001676 * rename by filehandle to various Windows servers.
1677 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001678 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001679 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001680
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001681 /* open-file renames don't work across directories */
1682 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001683 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001684
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001685 oparms.tcon = tcon;
1686 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001687 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001688 oparms.desired_access = DELETE;
1689 oparms.create_options = CREATE_NOT_DIR;
1690 oparms.disposition = FILE_OPEN;
1691 oparms.path = from_path;
1692 oparms.fid = &fid;
1693 oparms.reconnect = false;
1694
1695 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001696 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001697 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001698 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001699 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001700 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001701 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001702do_rename_exit:
1703 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001704 return rc;
1705}
1706
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001707int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001708cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1709 struct inode *target_dir, struct dentry *target_dentry,
1710 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001712 char *from_name = NULL;
1713 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001714 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001715 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001716 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001717 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1718 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001719 unsigned int xid;
1720 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001722 if (flags & ~RENAME_NOREPLACE)
1723 return -EINVAL;
1724
Jeff Layton639e7a92010-09-03 11:50:09 -04001725 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001726 tlink = cifs_sb_tlink(cifs_sb);
1727 if (IS_ERR(tlink))
1728 return PTR_ERR(tlink);
1729 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001731 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001732
1733 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001734 * we already have the rename sem so we do not need to
1735 * grab it again here to protect the path integrity
1736 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001737 from_name = build_path_from_dentry(source_dentry);
1738 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 rc = -ENOMEM;
1740 goto cifs_rename_exit;
1741 }
1742
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001743 to_name = build_path_from_dentry(target_dentry);
1744 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001745 rc = -ENOMEM;
1746 goto cifs_rename_exit;
1747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001749 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1750 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001751
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001752 /*
1753 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
1754 */
1755 if (flags & RENAME_NOREPLACE)
1756 goto cifs_rename_exit;
1757
Jeff Layton14121bd2008-10-20 14:45:22 -04001758 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001759 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001760 * Are src and dst hardlinks of same inode? We can only tell
1761 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001762 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001763 info_buf_source =
1764 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1765 GFP_KERNEL);
1766 if (info_buf_source == NULL) {
1767 rc = -ENOMEM;
1768 goto cifs_rename_exit;
1769 }
1770
1771 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001772 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1773 info_buf_source,
1774 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001775 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04001776 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001777 goto unlink_target;
1778
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001779 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1780 info_buf_target,
1781 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001782 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04001783
Jeff Layton8d281ef2008-10-22 13:57:01 -04001784 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001785 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001786 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001787 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001788 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001789 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001790 }
1791 /*
1792 * else ... BB we could add the same check for Windows by
1793 * checking the UniqueId via FILE_INTERNAL_INFO
1794 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001795
Jeff Layton14121bd2008-10-20 14:45:22 -04001796unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001797 /* Try unlinking the target dentry if it's not negative */
David Howells2b0143b2015-03-17 22:25:59 +00001798 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04001799 if (d_is_dir(target_dentry))
1800 tmprc = cifs_rmdir(target_dir, target_dentry);
1801 else
1802 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001803 if (tmprc)
1804 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001805 rc = cifs_do_rename(xid, source_dentry, from_name,
1806 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 }
1808
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001809 /* force revalidate to go get info when needed */
1810 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1811
1812 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001813 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001814
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001816 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001817 kfree(from_name);
1818 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001819 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001820 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 return rc;
1822}
1823
Jeff Laytondf2cf172010-02-12 07:44:16 -05001824static bool
1825cifs_inode_needs_reval(struct inode *inode)
1826{
1827 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301828 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001829
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001830 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001831 return false;
1832
1833 if (!lookupCacheEnabled)
1834 return true;
1835
1836 if (cifs_i->time == 0)
1837 return true;
1838
Jeff Laytona87c9ad2014-03-26 07:24:23 -07001839 if (!cifs_sb->actimeo)
1840 return true;
1841
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301842 if (!time_in_range(jiffies, cifs_i->time,
1843 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001844 return true;
1845
Jeff Laytondb192722010-05-17 14:51:49 -04001846 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301847 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001848 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1849 return true;
1850
Jeff Laytondf2cf172010-02-12 07:44:16 -05001851 return false;
1852}
1853
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301854/*
1855 * Zap the cache. Called when invalid_mapping flag is set.
1856 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001857int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001858cifs_invalidate_mapping(struct inode *inode)
1859{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001860 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001861
Jeff Laytondf2cf172010-02-12 07:44:16 -05001862 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001863 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001864 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001865 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1866 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001867 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001868
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301869 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001870 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001871}
1872
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001873/**
1874 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
1875 * @word: long word containing the bit lock
1876 */
1877static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001878cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001879{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001880 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001881 if (signal_pending_state(mode, current))
1882 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001883 return 0;
1884}
1885
Jeff Laytone284e532014-04-30 09:31:46 -04001886int
1887cifs_revalidate_mapping(struct inode *inode)
1888{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001889 int rc;
1890 unsigned long *flags = &CIFS_I(inode)->flags;
1891
NeilBrown74316202014-07-07 15:16:04 +10001892 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
1893 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001894 if (rc)
1895 return rc;
1896
1897 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
1898 rc = cifs_invalidate_mapping(inode);
1899 if (rc)
1900 set_bit(CIFS_INO_INVALID_MAPPING, flags);
1901 }
1902
1903 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07001904 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001905 wake_up_bit(flags, CIFS_INO_LOCK);
1906
1907 return rc;
1908}
1909
1910int
1911cifs_zap_mapping(struct inode *inode)
1912{
1913 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
1914 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04001915}
1916
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001917int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001918{
1919 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001920 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001921 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001922
1923 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001924 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001925
Jeff Layton13cfb732010-09-29 19:51:11 -04001926 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001927 rc = cifs_get_file_info_unix(filp);
1928 else
1929 rc = cifs_get_file_info(filp);
1930
Jeff Laytonabab0952010-02-12 07:44:18 -05001931 return rc;
1932}
1933
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001934int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001936 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001937 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00001938 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001939 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001940 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
Jeff Laytondf2cf172010-02-12 07:44:16 -05001942 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 return -ENOENT;
1944
Jeff Laytondf2cf172010-02-12 07:44:16 -05001945 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001946 return rc;
1947
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001948 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949
1950 /* can not safely grab the rename sem here if rename calls revalidate
1951 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001952 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301954 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001955 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001957
Joe Perchesf96637b2013-05-04 22:12:25 -05001958 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1959 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02001960 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961
Jeff Layton0d424ad2010-09-20 16:01:35 -07001962 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001963 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1964 else
1965 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1966 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001968out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001970 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 return rc;
1972}
1973
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001974int cifs_revalidate_file(struct file *filp)
1975{
1976 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001977 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001978
1979 rc = cifs_revalidate_file_attr(filp);
1980 if (rc)
1981 return rc;
1982
Jeff Laytone284e532014-04-30 09:31:46 -04001983 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001984}
1985
1986/* revalidate a dentry's inode attributes */
1987int cifs_revalidate_dentry(struct dentry *dentry)
1988{
1989 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00001990 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001991
1992 rc = cifs_revalidate_dentry_attr(dentry);
1993 if (rc)
1994 return rc;
1995
Jeff Laytone284e532014-04-30 09:31:46 -04001996 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001997}
1998
David Howellsa528d352017-01-31 16:46:22 +00001999int cifs_getattr(const struct path *path, struct kstat *stat,
2000 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001{
David Howellsa528d352017-01-31 16:46:22 +00002002 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002003 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002004 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002005 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002006 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002007
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002008 /*
2009 * We need to be sure that all dirty pages are written and the server
2010 * has actual ctime, mtime and file length.
2011 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002012 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002013 inode->i_mapping->nrpages != 0) {
2014 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002015 if (rc) {
2016 mapping_set_error(inode->i_mapping, rc);
2017 return rc;
2018 }
Steve French5fe14c82006-11-07 19:26:33 +00002019 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002020
2021 rc = cifs_revalidate_dentry_attr(dentry);
2022 if (rc)
2023 return rc;
2024
2025 generic_fillattr(inode, stat);
2026 stat->blksize = CIFS_MAX_MSGSIZE;
2027 stat->ino = CIFS_I(inode)->uniqueid;
2028
Steve French6e70e262017-09-21 21:32:29 -05002029 /* old CIFS Unix Extensions doesn't return create time */
2030 if (CIFS_I(inode)->createtime) {
2031 stat->result_mask |= STATX_BTIME;
2032 stat->btime =
2033 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
2034 }
2035
2036 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2037 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2038 stat->attributes |= STATX_ATTR_COMPRESSED;
2039 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2040 stat->attributes |= STATX_ATTR_ENCRYPTED;
2041
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002042 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002043 * If on a multiuser mount without unix extensions or cifsacl being
2044 * enabled, and the admin hasn't overridden them, set the ownership
2045 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002046 */
2047 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002048 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002049 !tcon->unix_ext) {
2050 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2051 stat->uid = current_fsuid();
2052 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2053 stat->gid = current_fsgid();
2054 }
2055 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056}
2057
2058static int cifs_truncate_page(struct address_space *mapping, loff_t from)
2059{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002060 pgoff_t index = from >> PAGE_SHIFT;
2061 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 int rc = 0;
2064
2065 page = grab_cache_page(mapping, index);
2066 if (!page)
2067 return -ENOMEM;
2068
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002069 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002071 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 return rc;
2073}
2074
Christoph Hellwig1b947462010-07-18 17:51:21 -04002075static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002076{
Steve Frenchba6a46a2007-02-26 20:06:29 +00002077 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002078 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002079 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002080
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002081 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002082}
2083
Jeff Layton8efdbde2008-07-23 21:28:12 +00002084static int
2085cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002086 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002087{
2088 int rc;
2089 struct cifsFileInfo *open_file;
2090 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2091 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002092 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002093 struct cifs_tcon *tcon = NULL;
2094 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002095
2096 /*
2097 * To avoid spurious oplock breaks from server, in the case of
2098 * inodes that we already have open, avoid doing path based
2099 * setting of file size if we can do it by handle.
2100 * This keeps our caching token (oplock) and avoids timeouts
2101 * when the local oplock break takes longer to flush
2102 * writebehind data than the SMB timeout for the SetPathInfo
2103 * request would allow
2104 */
Jeff Layton6508d902010-09-29 19:51:11 -04002105 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002106 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002107 tcon = tlink_tcon(open_file->tlink);
2108 server = tcon->ses->server;
2109 if (server->ops->set_file_size)
2110 rc = server->ops->set_file_size(xid, tcon, open_file,
2111 attrs->ia_size, false);
2112 else
2113 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002114 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002115 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002116 } else
2117 rc = -EINVAL;
2118
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002119 if (!rc)
2120 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07002121
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002122 if (tcon == NULL) {
2123 tlink = cifs_sb_tlink(cifs_sb);
2124 if (IS_ERR(tlink))
2125 return PTR_ERR(tlink);
2126 tcon = tlink_tcon(tlink);
2127 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002128 }
2129
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002130 /*
2131 * Set file size by pathname rather than by handle either because no
2132 * valid, writeable file handle for it was found or because there was
2133 * an error setting it by handle.
2134 */
2135 if (server->ops->set_path_size)
2136 rc = server->ops->set_path_size(xid, tcon, full_path,
2137 attrs->ia_size, cifs_sb, false);
2138 else
2139 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002140 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002141
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002142 if (tlink)
2143 cifs_put_tlink(tlink);
2144
2145set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002146 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002147 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002148 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002149 cifs_truncate_page(inode->i_mapping, inode->i_size);
2150 }
2151
2152 return rc;
2153}
2154
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002155static int
2156cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2157{
2158 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002159 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002160 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002161 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002162 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2163 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002164 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002165 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002166 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002167 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002168
Al Viro35c265e2014-08-19 20:25:34 -04002169 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2170 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002171
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002172 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002173
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002174 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2175 attrs->ia_valid |= ATTR_FORCE;
2176
Jan Kara31051c82016-05-26 16:55:18 +02002177 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002178 if (rc < 0)
2179 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002180
2181 full_path = build_path_from_dentry(direntry);
2182 if (full_path == NULL) {
2183 rc = -ENOMEM;
2184 goto out;
2185 }
2186
Jeff Layton0f4d6342009-03-26 13:35:37 -04002187 /*
2188 * Attempt to flush data before changing attributes. We need to do
2189 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2190 * ownership or mode then we may also need to do this. Here, we take
2191 * the safe way out and just do the flush on all setattr requests. If
2192 * the flush returns error, store it to report later and continue.
2193 *
2194 * BB: This should be smarter. Why bother flushing pages that
2195 * will be truncated anyway? Also, should we error out here if
2196 * the flush returns error?
2197 */
2198 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002199 mapping_set_error(inode->i_mapping, rc);
2200 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002201
2202 if (attrs->ia_valid & ATTR_SIZE) {
2203 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2204 if (rc != 0)
2205 goto out;
2206 }
2207
2208 /* skip mode change if it's just for clearing setuid/setgid */
2209 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2210 attrs->ia_valid &= ~ATTR_MODE;
2211
2212 args = kmalloc(sizeof(*args), GFP_KERNEL);
2213 if (args == NULL) {
2214 rc = -ENOMEM;
2215 goto out;
2216 }
2217
2218 /* set up the struct */
2219 if (attrs->ia_valid & ATTR_MODE)
2220 args->mode = attrs->ia_mode;
2221 else
2222 args->mode = NO_CHANGE_64;
2223
2224 if (attrs->ia_valid & ATTR_UID)
2225 args->uid = attrs->ia_uid;
2226 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002227 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002228
2229 if (attrs->ia_valid & ATTR_GID)
2230 args->gid = attrs->ia_gid;
2231 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002232 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002233
2234 if (attrs->ia_valid & ATTR_ATIME)
2235 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2236 else
2237 args->atime = NO_CHANGE_64;
2238
2239 if (attrs->ia_valid & ATTR_MTIME)
2240 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2241 else
2242 args->mtime = NO_CHANGE_64;
2243
2244 if (attrs->ia_valid & ATTR_CTIME)
2245 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2246 else
2247 args->ctime = NO_CHANGE_64;
2248
2249 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002250 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002251 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002252 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002253 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002254 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002255 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002256 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002257 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002258 tlink = cifs_sb_tlink(cifs_sb);
2259 if (IS_ERR(tlink)) {
2260 rc = PTR_ERR(tlink);
2261 goto out;
2262 }
2263 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002264 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002265 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002266 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002267 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002268 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002269
Christoph Hellwig10257742010-06-04 11:30:02 +02002270 if (rc)
2271 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002272
Christoph Hellwig10257742010-06-04 11:30:02 +02002273 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002274 attrs->ia_size != i_size_read(inode))
2275 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002276
2277 setattr_copy(inode, attrs);
2278 mark_inode_dirty(inode);
2279
2280 /* force revalidate when any of these times are set since some
2281 of the fs types (eg ext3, fat) do not have fine enough
2282 time granularity to match protocol, and we do not have a
2283 a way (yet) to query the server fs's time granularity (and
2284 whether it rounds times down).
2285 */
2286 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2287 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002288out:
2289 kfree(args);
2290 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002291 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002292 return rc;
2293}
2294
Jeff Layton0510eeb2008-08-02 07:26:12 -04002295static int
2296cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002298 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002299 kuid_t uid = INVALID_UID;
2300 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002301 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002302 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002303 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 char *full_path = NULL;
2305 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002306 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002307 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002308
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002309 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
Al Viro35c265e2014-08-19 20:25:34 -04002311 cifs_dbg(FYI, "setattr on file %pd attrs->iavalid 0x%x\n",
2312 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002313
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002314 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2315 attrs->ia_valid |= ATTR_FORCE;
2316
Jan Kara31051c82016-05-26 16:55:18 +02002317 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002318 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002319 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002320 return rc;
Steve French6473a552005-11-29 20:20:10 -08002321 }
Steve French50c2f752007-07-13 00:33:32 +00002322
Steve French7f573562005-08-30 11:32:14 -07002323 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302325 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002326 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302327 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
Jeff Layton0f4d6342009-03-26 13:35:37 -04002330 /*
2331 * Attempt to flush data before changing attributes. We need to do
2332 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2333 * ownership or mode then we may also need to do this. Here, we take
2334 * the safe way out and just do the flush on all setattr requests. If
2335 * the flush returns error, store it to report later and continue.
2336 *
2337 * BB: This should be smarter. Why bother flushing pages that
2338 * will be truncated anyway? Also, should we error out here if
2339 * the flush returns error?
2340 */
2341 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002342 mapping_set_error(inode->i_mapping, rc);
2343 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002344
Steve French50531442008-03-14 19:21:31 +00002345 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002346 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2347 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002348 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002350
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002351 if (attrs->ia_valid & ATTR_UID)
2352 uid = attrs->ia_uid;
2353
2354 if (attrs->ia_valid & ATTR_GID)
2355 gid = attrs->ia_gid;
2356
2357#ifdef CONFIG_CIFS_ACL
2358 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002359 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002360 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2361 uid, gid);
2362 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002363 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2364 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002365 goto cifs_setattr_exit;
2366 }
2367 }
2368 } else
2369#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002370 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002371 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372
Jeff Laytond32c4f22007-10-18 03:05:22 -07002373 /* skip mode change if it's just for clearing setuid/setgid */
2374 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2375 attrs->ia_valid &= ~ATTR_MODE;
2376
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002379 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002380#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002381 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002382 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002383 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002384 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002385 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2386 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002387 goto cifs_setattr_exit;
2388 }
2389 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002390#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002391 if (((mode & S_IWUGO) == 0) &&
2392 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002393
2394 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2395
Jeff Layton51328612008-05-22 09:33:34 -04002396 /* fix up mode if we're not using dynperm */
2397 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2398 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2399 } else if ((mode & S_IWUGO) &&
2400 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002401
2402 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2403 /* Attributes of 0 are ignored */
2404 if (dosattr == 0)
2405 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002406
2407 /* reset local inode permissions to normal */
2408 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2409 attrs->ia_mode &= ~(S_IALLUGO);
2410 if (S_ISDIR(inode->i_mode))
2411 attrs->ia_mode |=
2412 cifs_sb->mnt_dir_mode;
2413 else
2414 attrs->ia_mode |=
2415 cifs_sb->mnt_file_mode;
2416 }
2417 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2418 /* ignore mode change - ATTR_READONLY hasn't changed */
2419 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 }
2422
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002423 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2424 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2425 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2426 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427
Steve Frenche30dcf32005-09-20 20:49:16 -07002428 /* Even if error on time set, no sense failing the call if
2429 the server would set the time to a reasonable value anyway,
2430 and this check ensures that we are not being called from
2431 sys_utimes in which case we ought to fail the call back to
2432 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002433 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002434 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002435 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 }
2437
2438 /* do not need local check to inode_check_ok since the server does
2439 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002440 if (rc)
2441 goto cifs_setattr_exit;
2442
2443 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002444 attrs->ia_size != i_size_read(inode))
2445 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002446
2447 setattr_copy(inode, attrs);
2448 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002449
Steve Frenche30dcf32005-09-20 20:49:16 -07002450cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002452 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 return rc;
2454}
2455
Jeff Layton0510eeb2008-08-02 07:26:12 -04002456int
2457cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2458{
Al Virofc640052016-04-10 01:33:30 -04002459 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002460 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002461
2462 if (pTcon->unix_ext)
2463 return cifs_setattr_unix(direntry, attrs);
2464
2465 return cifs_setattr_nounix(direntry, attrs);
2466
2467 /* BB: add cifs_setattr_legacy for really old servers */
2468}
2469
Steve French99ee4db2007-02-27 05:35:17 +00002470#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471void cifs_delete_inode(struct inode *inode)
2472{
Joe Perchesf96637b2013-05-04 22:12:25 -05002473 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 /* may have to add back in if and when safe distributed caching of
2475 directories added e.g. via FindNotify */
2476}
Steve French99ee4db2007-02-27 05:35:17 +00002477#endif