View | Details | Raw Unified | Return to bug 13329
Collapse All | Expand All

(-)a/fs/cifs/cifsglob.h (-1 / +1 lines)
Lines 350-356 struct cifsFileInfo { Link Here
350
	bool invalidHandle:1;	/* file closed via session abend */
350
	bool invalidHandle:1;	/* file closed via session abend */
351
	bool messageMode:1;	/* for pipes: message vs byte mode */
351
	bool messageMode:1;	/* for pipes: message vs byte mode */
352
	atomic_t wrtPending;   /* handle in use - defer close */
352
	atomic_t wrtPending;   /* handle in use - defer close */
353
	struct mutex fh_mutex; /* prevents reopen race after dead ses*/
353
	struct semaphore fh_sem; /* prevents reopen race after dead ses*/
354
	struct cifs_search_info srch_inf;
354
	struct cifs_search_info srch_inf;
355
};
355
};
356
356
(-)a/fs/cifs/dir.c (-102 / +52 lines)
Lines 129-190 cifs_bp_rename_retry: Link Here
129
	return full_path;
129
	return full_path;
130
}
130
}
131
131
132
static void
133
cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
134
			struct cifsTconInfo *tcon, bool write_only)
135
{
136
	int oplock = 0;
137
	struct cifsFileInfo *pCifsFile;
138
	struct cifsInodeInfo *pCifsInode;
139
140
	pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
141
142
	if (pCifsFile == NULL)
143
		return;
144
145
	if (oplockEnabled)
146
		oplock = REQ_OPLOCK;
147
148
	pCifsFile->netfid = fileHandle;
149
	pCifsFile->pid = current->tgid;
150
	pCifsFile->pInode = newinode;
151
	pCifsFile->invalidHandle = false;
152
	pCifsFile->closePend = false;
153
	mutex_init(&pCifsFile->fh_mutex);
154
	mutex_init(&pCifsFile->lock_mutex);
155
	INIT_LIST_HEAD(&pCifsFile->llist);
156
	atomic_set(&pCifsFile->wrtPending, 0);
157
158
	/* set the following in open now
159
			pCifsFile->pfile = file; */
160
	write_lock(&GlobalSMBSeslock);
161
	list_add(&pCifsFile->tlist, &tcon->openFileList);
162
	pCifsInode = CIFS_I(newinode);
163
	if (pCifsInode) {
164
		/* if readable file instance put first in list*/
165
		if (write_only)
166
			list_add_tail(&pCifsFile->flist,
167
				      &pCifsInode->openFileList);
168
		else
169
			list_add(&pCifsFile->flist, &pCifsInode->openFileList);
170
171
		if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
172
			pCifsInode->clientCanCacheAll = true;
173
			pCifsInode->clientCanCacheRead = true;
174
			cFYI(1, ("Exclusive Oplock inode %p", newinode));
175
		} else if ((oplock & 0xF) == OPLOCK_READ)
176
				pCifsInode->clientCanCacheRead = true;
177
	}
178
	write_unlock(&GlobalSMBSeslock);
179
}
180
181
int cifs_posix_open(char *full_path, struct inode **pinode,
132
int cifs_posix_open(char *full_path, struct inode **pinode,
182
		    struct super_block *sb, int mode, int oflags,
133
		    struct super_block *sb, int mode, int oflags,
183
		    int *poplock, __u16 *pnetfid, int xid)
134
		    int *poplock, __u16 *pnetfid, int xid)
184
{
135
{
185
	int rc;
136
	int rc;
186
	__u32 oplock;
137
	__u32 oplock;
187
	bool write_only = false;
188
	FILE_UNIX_BASIC_INFO *presp_data;
138
	FILE_UNIX_BASIC_INFO *presp_data;
189
	__u32 posix_flags = 0;
139
	__u32 posix_flags = 0;
190
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
140
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Lines 222-229 int cifs_posix_open(char *full_path, struct inode **pinode, Link Here
222
	if (oflags & O_DIRECT)
172
	if (oflags & O_DIRECT)
223
		posix_flags |= SMB_O_DIRECT;
173
		posix_flags |= SMB_O_DIRECT;
224
174
225
	if (!(oflags & FMODE_READ))
226
		write_only = true;
227
175
228
	rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
176
	rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
229
			pnetfid, presp_data, &oplock, full_path,
177
			pnetfid, presp_data, &oplock, full_path,
Lines 252-259 int cifs_posix_open(char *full_path, struct inode **pinode, Link Here
252
200
253
	posix_fill_in_inode(*pinode, presp_data, 1);
201
	posix_fill_in_inode(*pinode, presp_data, 1);
254
202
255
	cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only);
256
257
posix_open_ret:
203
posix_open_ret:
258
	kfree(presp_data);
204
	kfree(presp_data);
259
	return rc;
205
	return rc;
Lines 281-287 cifs_create(struct inode *inode, struct dentry *direntry, int mode, Link Here
281
	int create_options = CREATE_NOT_DIR;
227
	int create_options = CREATE_NOT_DIR;
282
	int oplock = 0;
228
	int oplock = 0;
283
	int oflags;
229
	int oflags;
284
	bool posix_create = false;
285
	/*
230
	/*
286
	 * BB below access is probably too much for mknod to request
231
	 * BB below access is probably too much for mknod to request
287
	 *    but we have to do query and setpathinfo so requesting
232
	 *    but we have to do query and setpathinfo so requesting
Lines 296-301 cifs_create(struct inode *inode, struct dentry *direntry, int mode, Link Here
296
	char *full_path = NULL;
241
	char *full_path = NULL;
297
	FILE_ALL_INFO *buf = NULL;
242
	FILE_ALL_INFO *buf = NULL;
298
	struct inode *newinode = NULL;
243
	struct inode *newinode = NULL;
244
	struct cifsInodeInfo *pCifsInode;
299
	int disposition = FILE_OVERWRITE_IF;
245
	int disposition = FILE_OVERWRITE_IF;
300
	bool write_only = false;
246
	bool write_only = false;
301
247
Lines 329-341 cifs_create(struct inode *inode, struct dentry *direntry, int mode, Link Here
329
		   negotation.  EREMOTE indicates DFS junction, which is not
275
		   negotation.  EREMOTE indicates DFS junction, which is not
330
		   handled in posix open */
276
		   handled in posix open */
331
277
332
		if (rc == 0) {
278
		if ((rc == 0) && (newinode == NULL))
333
			posix_create = true;
279
			goto cifs_create_get_file_info; /* query inode info */
334
			if (newinode == NULL) /* query inode info */
280
		else if (rc == 0) /* success, no need to query */
335
				goto cifs_create_get_file_info;
281
			goto cifs_create_set_dentry;
336
			else /* success, no need to query */
282
		else if ((rc != -EIO) && (rc != -EREMOTE) &&
337
				goto cifs_create_set_dentry;
338
		} else if ((rc != -EIO) && (rc != -EREMOTE) &&
339
			 (rc != -EOPNOTSUPP)) /* path not found or net err */
283
			 (rc != -EOPNOTSUPP)) /* path not found or net err */
340
			goto cifs_create_out;
284
			goto cifs_create_out;
341
		/* else fallthrough to retry, using older open call, this is
285
		/* else fallthrough to retry, using older open call, this is
Lines 467-475 cifs_create_set_dentry: Link Here
467
	if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
411
	if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
468
		/* mknod case - do not leave file open */
412
		/* mknod case - do not leave file open */
469
		CIFSSMBClose(xid, tcon, fileHandle);
413
		CIFSSMBClose(xid, tcon, fileHandle);
470
	} else if (!(posix_create) && (newinode)) {
414
	} else if (newinode) {
471
			cifs_fill_fileinfo(newinode, fileHandle,
415
		struct cifsFileInfo *pCifsFile =
472
					cifs_sb->tcon, write_only);
416
			kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
417
418
		if (pCifsFile == NULL)
419
			goto cifs_create_out;
420
		pCifsFile->netfid = fileHandle;
421
		pCifsFile->pid = current->tgid;
422
		pCifsFile->pInode = newinode;
423
		pCifsFile->invalidHandle = false;
424
		pCifsFile->closePend     = false;
425
		init_MUTEX(&pCifsFile->fh_sem);
426
		mutex_init(&pCifsFile->lock_mutex);
427
		INIT_LIST_HEAD(&pCifsFile->llist);
428
		atomic_set(&pCifsFile->wrtPending, 0);
429
430
		/* set the following in open now
431
				pCifsFile->pfile = file; */
432
		write_lock(&GlobalSMBSeslock);
433
		list_add(&pCifsFile->tlist, &tcon->openFileList);
434
		pCifsInode = CIFS_I(newinode);
435
		if (pCifsInode) {
436
			/* if readable file instance put first in list*/
437
			if (write_only) {
438
				list_add_tail(&pCifsFile->flist,
439
					      &pCifsInode->openFileList);
440
			} else {
441
				list_add(&pCifsFile->flist,
442
					 &pCifsInode->openFileList);
443
			}
444
			if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
445
				pCifsInode->clientCanCacheAll = true;
446
				pCifsInode->clientCanCacheRead = true;
447
				cFYI(1, ("Exclusive Oplock inode %p",
448
					newinode));
449
			} else if ((oplock & 0xF) == OPLOCK_READ)
450
				pCifsInode->clientCanCacheRead = true;
451
		}
452
		write_unlock(&GlobalSMBSeslock);
473
	}
453
	}
474
cifs_create_out:
454
cifs_create_out:
475
	kfree(buf);
455
	kfree(buf);
Lines 602-622 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, Link Here
602
	return rc;
582
	return rc;
603
}
583
}
604
584
585
605
struct dentry *
586
struct dentry *
606
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
587
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
607
	    struct nameidata *nd)
588
	    struct nameidata *nd)
608
{
589
{
609
	int xid;
590
	int xid;
610
	int rc = 0; /* to get around spurious gcc warning, set to zero here */
591
	int rc = 0; /* to get around spurious gcc warning, set to zero here */
611
	int oplock = 0;
612
	int mode;
613
	__u16 fileHandle = 0;
614
	bool posix_open = false;
615
	struct cifs_sb_info *cifs_sb;
592
	struct cifs_sb_info *cifs_sb;
616
	struct cifsTconInfo *pTcon;
593
	struct cifsTconInfo *pTcon;
617
	struct inode *newInode = NULL;
594
	struct inode *newInode = NULL;
618
	char *full_path = NULL;
595
	char *full_path = NULL;
619
	struct file *filp;
620
596
621
	xid = GetXid();
597
	xid = GetXid();
622
598
Lines 658-694 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, Link Here
658
	}
634
	}
659
	cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
635
	cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
660
636
661
	if (pTcon->unix_ext) {
637
	if (pTcon->unix_ext)
662
		if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
638
		rc = cifs_get_inode_info_unix(&newInode, full_path,
663
				(nd->flags & LOOKUP_OPEN)) {
639
					      parent_dir_inode->i_sb, xid);
664
			if (!((nd->intent.open.flags & O_CREAT) &&
640
	else
665
					(nd->intent.open.flags & O_EXCL))) {
666
				mode = nd->intent.open.create_mode &
667
						~current_umask();
668
				rc = cifs_posix_open(full_path, &newInode,
669
					parent_dir_inode->i_sb, mode,
670
					nd->intent.open.flags, &oplock,
671
					&fileHandle, xid);
672
				/*
673
				 * This code works around a bug in
674
				 * samba posix open in samba versions 3.3.1
675
				 * and earlier where create works
676
				 * but open fails with invalid parameter.
677
				 * If either of these error codes are
678
				 * returned, follow the normal lookup.
679
				 * Otherwise, the error during posix open
680
				 * is handled.
681
				 */
682
				if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
683
					posix_open = true;
684
			}
685
		}
686
		if (!posix_open)
687
			rc = cifs_get_inode_info_unix(&newInode, full_path,
688
						parent_dir_inode->i_sb, xid);
689
	} else
690
		rc = cifs_get_inode_info(&newInode, full_path, NULL,
641
		rc = cifs_get_inode_info(&newInode, full_path, NULL,
691
				parent_dir_inode->i_sb, xid, NULL);
642
					 parent_dir_inode->i_sb, xid, NULL);
692
643
693
	if ((rc == 0) && (newInode != NULL)) {
644
	if ((rc == 0) && (newInode != NULL)) {
694
		if (pTcon->nocase)
645
		if (pTcon->nocase)
Lines 696-703 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, Link Here
696
		else
647
		else
697
			direntry->d_op = &cifs_dentry_ops;
648
			direntry->d_op = &cifs_dentry_ops;
698
		d_add(direntry, newInode);
649
		d_add(direntry, newInode);
699
		if (posix_open)
650
700
			filp = lookup_instantiate_filp(nd, direntry, NULL);
701
		/* since paths are not looked up by component - the parent
651
		/* since paths are not looked up by component - the parent
702
		   directories are presumed to be good here */
652
		   directories are presumed to be good here */
703
		renew_parental_timestamps(direntry);
653
		renew_parental_timestamps(direntry);
(-)a/fs/cifs/file.c (-31 / +47 lines)
Lines 46-52 static inline struct cifsFileInfo *cifs_init_private( Link Here
46
	memset(private_data, 0, sizeof(struct cifsFileInfo));
46
	memset(private_data, 0, sizeof(struct cifsFileInfo));
47
	private_data->netfid = netfid;
47
	private_data->netfid = netfid;
48
	private_data->pid = current->tgid;
48
	private_data->pid = current->tgid;
49
	mutex_init(&private_data->fh_mutex);
49
	init_MUTEX(&private_data->fh_sem);
50
	mutex_init(&private_data->lock_mutex);
50
	mutex_init(&private_data->lock_mutex);
51
	INIT_LIST_HEAD(&private_data->llist);
51
	INIT_LIST_HEAD(&private_data->llist);
52
	private_data->pfile = file; /* needed for writepage */
52
	private_data->pfile = file; /* needed for writepage */
Lines 129-140 static inline int cifs_posix_open_inode_helper(struct inode *inode, Link Here
129
			struct file *file, struct cifsInodeInfo *pCifsInode,
129
			struct file *file, struct cifsInodeInfo *pCifsInode,
130
			struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
130
			struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
131
{
131
{
132
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
133
/*	struct timespec temp; */   /* BB REMOVEME BB */
132
134
133
	file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
135
	file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
134
	if (file->private_data == NULL)
136
	if (file->private_data == NULL)
135
		return -ENOMEM;
137
		return -ENOMEM;
136
	pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
138
	pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
137
	write_lock(&GlobalSMBSeslock);
139
	write_lock(&GlobalSMBSeslock);
140
	list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
138
141
139
	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
142
	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
140
	if (pCifsInode == NULL) {
143
	if (pCifsInode == NULL) {
Lines 142-147 static inline int cifs_posix_open_inode_helper(struct inode *inode, Link Here
142
		return -EINVAL;
145
		return -EINVAL;
143
	}
146
	}
144
147
148
	/* want handles we can use to read with first
149
	   in the list so we do not have to walk the
150
	   list to search for one in write_begin */
151
	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
152
		list_add_tail(&pCifsFile->flist,
153
			      &pCifsInode->openFileList);
154
	} else {
155
		list_add(&pCifsFile->flist,
156
			 &pCifsInode->openFileList);
157
	}
158
145
	if (pCifsInode->clientCanCacheRead) {
159
	if (pCifsInode->clientCanCacheRead) {
146
		/* we have the inode open somewhere else
160
		/* we have the inode open somewhere else
147
		   no need to discard cache data */
161
		   no need to discard cache data */
Lines 270-301 int cifs_open(struct inode *inode, struct file *file) Link Here
270
	cifs_sb = CIFS_SB(inode->i_sb);
284
	cifs_sb = CIFS_SB(inode->i_sb);
271
	tcon = cifs_sb->tcon;
285
	tcon = cifs_sb->tcon;
272
286
273
	/* search inode for this file and fill in file->private_data */
287
	if (file->f_flags & O_CREAT) {
274
	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
288
		/* search inode for this file and fill in file->private_data */
275
	read_lock(&GlobalSMBSeslock);
289
		pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
276
	list_for_each(tmp, &pCifsInode->openFileList) {
290
		read_lock(&GlobalSMBSeslock);
277
		pCifsFile = list_entry(tmp, struct cifsFileInfo,
291
		list_for_each(tmp, &pCifsInode->openFileList) {
278
				       flist);
292
			pCifsFile = list_entry(tmp, struct cifsFileInfo,
279
		if ((pCifsFile->pfile == NULL) &&
293
					       flist);
280
		    (pCifsFile->pid == current->tgid)) {
294
			if ((pCifsFile->pfile == NULL) &&
281
			/* mode set in cifs_create */
295
			    (pCifsFile->pid == current->tgid)) {
282
296
				/* mode set in cifs_create */
283
			/* needed for writepage */
297
284
			pCifsFile->pfile = file;
298
				/* needed for writepage */
285
299
				pCifsFile->pfile = file;
286
			file->private_data = pCifsFile;
300
287
			break;
301
				file->private_data = pCifsFile;
302
				break;
303
			}
304
		}
305
		read_unlock(&GlobalSMBSeslock);
306
		if (file->private_data != NULL) {
307
			rc = 0;
308
			FreeXid(xid);
309
			return rc;
310
		} else {
311
			if (file->f_flags & O_EXCL)
312
				cERROR(1, ("could not find file instance for "
313
					   "new file %p", file));
288
		}
314
		}
289
	}
315
	}
290
	read_unlock(&GlobalSMBSeslock);
291
292
	if (file->private_data != NULL) {
293
		rc = 0;
294
		FreeXid(xid);
295
		return rc;
296
	} else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
297
			cERROR(1, ("could not find file instance for "
298
				   "new file %p", file));
299
316
300
	full_path = build_path_from_dentry(file->f_path.dentry);
317
	full_path = build_path_from_dentry(file->f_path.dentry);
301
	if (full_path == NULL) {
318
	if (full_path == NULL) {
Lines 483-491 static int cifs_reopen_file(struct file *file, bool can_flush) Link Here
483
		return -EBADF;
500
		return -EBADF;
484
501
485
	xid = GetXid();
502
	xid = GetXid();
486
	mutex_unlock(&pCifsFile->fh_mutex);
503
	down(&pCifsFile->fh_sem);
487
	if (!pCifsFile->invalidHandle) {
504
	if (!pCifsFile->invalidHandle) {
488
		mutex_lock(&pCifsFile->fh_mutex);
505
		up(&pCifsFile->fh_sem);
489
		FreeXid(xid);
506
		FreeXid(xid);
490
		return 0;
507
		return 0;
491
	}
508
	}
Lines 516-522 static int cifs_reopen_file(struct file *file, bool can_flush) Link Here
516
	if (full_path == NULL) {
533
	if (full_path == NULL) {
517
		rc = -ENOMEM;
534
		rc = -ENOMEM;
518
reopen_error_exit:
535
reopen_error_exit:
519
		mutex_lock(&pCifsFile->fh_mutex);
536
		up(&pCifsFile->fh_sem);
520
		FreeXid(xid);
537
		FreeXid(xid);
521
		return rc;
538
		return rc;
522
	}
539
	}
Lines 558-571 reopen_error_exit: Link Here
558
			 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
575
			 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
559
				CIFS_MOUNT_MAP_SPECIAL_CHR);
576
				CIFS_MOUNT_MAP_SPECIAL_CHR);
560
	if (rc) {
577
	if (rc) {
561
		mutex_lock(&pCifsFile->fh_mutex);
578
		up(&pCifsFile->fh_sem);
562
		cFYI(1, ("cifs_open returned 0x%x", rc));
579
		cFYI(1, ("cifs_open returned 0x%x", rc));
563
		cFYI(1, ("oplock: %d", oplock));
580
		cFYI(1, ("oplock: %d", oplock));
564
	} else {
581
	} else {
565
reopen_success:
582
reopen_success:
566
		pCifsFile->netfid = netfid;
583
		pCifsFile->netfid = netfid;
567
		pCifsFile->invalidHandle = false;
584
		pCifsFile->invalidHandle = false;
568
		mutex_lock(&pCifsFile->fh_mutex);
585
		up(&pCifsFile->fh_sem);
569
		pCifsInode = CIFS_I(inode);
586
		pCifsInode = CIFS_I(inode);
570
		if (pCifsInode) {
587
		if (pCifsInode) {
571
			if (can_flush) {
588
			if (can_flush) {
572
- 

Return to bug 13329