⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cifsfs.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* some applications poll for the file length in this strange		   way so we must seek to end on non-oplocked files by		   setting the revalidate time to zero */		CIFS_I(file->f_path.dentry->d_inode)->time = 0;		retval = cifs_revalidate(file->f_path.dentry);		if (retval < 0)			return (loff_t)retval;	}	return remote_llseek(file, offset, origin);}static struct file_system_type cifs_fs_type = {	.owner = THIS_MODULE,	.name = "cifs",	.get_sb = cifs_get_sb,	.kill_sb = kill_anon_super,	/*  .fs_flags */};const struct inode_operations cifs_dir_inode_ops = {	.create = cifs_create,	.lookup = cifs_lookup,	.getattr = cifs_getattr,	.unlink = cifs_unlink,	.link = cifs_hardlink,	.mkdir = cifs_mkdir,	.rmdir = cifs_rmdir,	.rename = cifs_rename,	.permission = cifs_permission,/*	revalidate:cifs_revalidate,   */	.setattr = cifs_setattr,	.symlink = cifs_symlink,	.mknod   = cifs_mknod,#ifdef CONFIG_CIFS_XATTR	.setxattr = cifs_setxattr,	.getxattr = cifs_getxattr,	.listxattr = cifs_listxattr,	.removexattr = cifs_removexattr,#endif};const struct inode_operations cifs_file_inode_ops = {/*	revalidate:cifs_revalidate, */	.setattr = cifs_setattr,	.getattr = cifs_getattr, /* do we need this anymore? */	.rename = cifs_rename,	.permission = cifs_permission,#ifdef CONFIG_CIFS_XATTR	.setxattr = cifs_setxattr,	.getxattr = cifs_getxattr,	.listxattr = cifs_listxattr,	.removexattr = cifs_removexattr,#endif};const struct inode_operations cifs_symlink_inode_ops = {	.readlink = generic_readlink,	.follow_link = cifs_follow_link,	.put_link = cifs_put_link,	.permission = cifs_permission,	/* BB add the following two eventually */	/* revalidate: cifs_revalidate,	   setattr:    cifs_notify_change, *//* BB do we need notify change */#ifdef CONFIG_CIFS_XATTR	.setxattr = cifs_setxattr,	.getxattr = cifs_getxattr,	.listxattr = cifs_listxattr,	.removexattr = cifs_removexattr,#endif};const struct file_operations cifs_file_ops = {	.read = do_sync_read,	.write = do_sync_write,	.aio_read = generic_file_aio_read,	.aio_write = cifs_file_aio_write,	.open = cifs_open,	.release = cifs_close,	.lock = cifs_lock,	.fsync = cifs_fsync,	.flush = cifs_flush,	.mmap  = cifs_file_mmap,	.splice_read = generic_file_splice_read,	.llseek = cifs_llseek,#ifdef CONFIG_CIFS_POSIX	.ioctl	= cifs_ioctl,#endif /* CONFIG_CIFS_POSIX */#ifdef CONFIG_CIFS_EXPERIMENTAL	.dir_notify = cifs_dir_notify,#endif /* CONFIG_CIFS_EXPERIMENTAL */};const struct file_operations cifs_file_direct_ops = {	/* no mmap, no aio, no readv -	   BB reevaluate whether they can be done with directio, no cache */	.read = cifs_user_read,	.write = cifs_user_write,	.open = cifs_open,	.release = cifs_close,	.lock = cifs_lock,	.fsync = cifs_fsync,	.flush = cifs_flush,	.splice_read = generic_file_splice_read,#ifdef CONFIG_CIFS_POSIX	.ioctl  = cifs_ioctl,#endif /* CONFIG_CIFS_POSIX */	.llseek = cifs_llseek,#ifdef CONFIG_CIFS_EXPERIMENTAL	.dir_notify = cifs_dir_notify,#endif /* CONFIG_CIFS_EXPERIMENTAL */};const struct file_operations cifs_file_nobrl_ops = {	.read = do_sync_read,	.write = do_sync_write,	.aio_read = generic_file_aio_read,	.aio_write = cifs_file_aio_write,	.open = cifs_open,	.release = cifs_close,	.fsync = cifs_fsync,	.flush = cifs_flush,	.mmap  = cifs_file_mmap,	.splice_read = generic_file_splice_read,	.llseek = cifs_llseek,#ifdef CONFIG_CIFS_POSIX	.ioctl	= cifs_ioctl,#endif /* CONFIG_CIFS_POSIX */#ifdef CONFIG_CIFS_EXPERIMENTAL	.dir_notify = cifs_dir_notify,#endif /* CONFIG_CIFS_EXPERIMENTAL */};const struct file_operations cifs_file_direct_nobrl_ops = {	/* no mmap, no aio, no readv -	   BB reevaluate whether they can be done with directio, no cache */	.read = cifs_user_read,	.write = cifs_user_write,	.open = cifs_open,	.release = cifs_close,	.fsync = cifs_fsync,	.flush = cifs_flush,	.splice_read = generic_file_splice_read,#ifdef CONFIG_CIFS_POSIX	.ioctl  = cifs_ioctl,#endif /* CONFIG_CIFS_POSIX */	.llseek = cifs_llseek,#ifdef CONFIG_CIFS_EXPERIMENTAL	.dir_notify = cifs_dir_notify,#endif /* CONFIG_CIFS_EXPERIMENTAL */};const struct file_operations cifs_dir_ops = {	.readdir = cifs_readdir,	.release = cifs_closedir,	.read    = generic_read_dir,#ifdef CONFIG_CIFS_EXPERIMENTAL	.dir_notify = cifs_dir_notify,#endif /* CONFIG_CIFS_EXPERIMENTAL */	.ioctl  = cifs_ioctl,};static voidcifs_init_once(struct kmem_cache *cachep, void *inode){	struct cifsInodeInfo *cifsi = inode;	inode_init_once(&cifsi->vfs_inode);	INIT_LIST_HEAD(&cifsi->lockList);}static intcifs_init_inodecache(void){	cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",					      sizeof(struct cifsInodeInfo),					      0, (SLAB_RECLAIM_ACCOUNT|						SLAB_MEM_SPREAD),					      cifs_init_once);	if (cifs_inode_cachep == NULL)		return -ENOMEM;	return 0;}static voidcifs_destroy_inodecache(void){	kmem_cache_destroy(cifs_inode_cachep);}static intcifs_init_request_bufs(void){	if (CIFSMaxBufSize < 8192) {	/* Buffer size can not be smaller than 2 * PATH_MAX since maximum	Unicode path name has to fit in any SMB/CIFS path based frames */		CIFSMaxBufSize = 8192;	} else if (CIFSMaxBufSize > 1024*127) {		CIFSMaxBufSize = 1024 * 127;	} else {		CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/	}/*	cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */	cifs_req_cachep = kmem_cache_create("cifs_request",					    CIFSMaxBufSize +					    MAX_CIFS_HDR_SIZE, 0,					    SLAB_HWCACHE_ALIGN, NULL);	if (cifs_req_cachep == NULL)		return -ENOMEM;	if (cifs_min_rcv < 1)		cifs_min_rcv = 1;	else if (cifs_min_rcv > 64) {		cifs_min_rcv = 64;		cERROR(1, ("cifs_min_rcv set to maximum (64)"));	}	cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,						  cifs_req_cachep);	if (cifs_req_poolp == NULL) {		kmem_cache_destroy(cifs_req_cachep);		return -ENOMEM;	}	/* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and	almost all handle based requests (but not write response, nor is it	sufficient for path based requests).  A smaller size would have	been more efficient (compacting multiple slab items on one 4k page)	for the case in which debug was on, but this larger size allows	more SMBs to use small buffer alloc and is still much more	efficient to alloc 1 per page off the slab compared to 17K (5page)	alloc of large cifs buffers even when page debugging is on */	cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",			MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,			NULL);	if (cifs_sm_req_cachep == NULL) {		mempool_destroy(cifs_req_poolp);		kmem_cache_destroy(cifs_req_cachep);		return -ENOMEM;	}	if (cifs_min_small < 2)		cifs_min_small = 2;	else if (cifs_min_small > 256) {		cifs_min_small = 256;		cFYI(1, ("cifs_min_small set to maximum (256)"));	}	cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,						     cifs_sm_req_cachep);	if (cifs_sm_req_poolp == NULL) {		mempool_destroy(cifs_req_poolp);		kmem_cache_destroy(cifs_req_cachep);		kmem_cache_destroy(cifs_sm_req_cachep);		return -ENOMEM;	}	return 0;}static voidcifs_destroy_request_bufs(void){	mempool_destroy(cifs_req_poolp);	kmem_cache_destroy(cifs_req_cachep);	mempool_destroy(cifs_sm_req_poolp);	kmem_cache_destroy(cifs_sm_req_cachep);}static intcifs_init_mids(void){	cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",					    sizeof(struct mid_q_entry), 0,					    SLAB_HWCACHE_ALIGN, NULL);	if (cifs_mid_cachep == NULL)		return -ENOMEM;	/* 3 is a reasonable minimum number of simultaneous operations */	cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);	if (cifs_mid_poolp == NULL) {		kmem_cache_destroy(cifs_mid_cachep);		return -ENOMEM;	}	cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",					sizeof(struct oplock_q_entry), 0,					SLAB_HWCACHE_ALIGN, NULL);	if (cifs_oplock_cachep == NULL) {		mempool_destroy(cifs_mid_poolp);		kmem_cache_destroy(cifs_mid_cachep);		return -ENOMEM;	}	return 0;}static voidcifs_destroy_mids(void){	mempool_destroy(cifs_mid_poolp);	kmem_cache_destroy(cifs_mid_cachep);	kmem_cache_destroy(cifs_oplock_cachep);}static int cifs_oplock_thread(void *dummyarg){	struct oplock_q_entry *oplock_item;	struct cifsTconInfo *pTcon;	struct inode *inode;	__u16  netfid;	int rc, waitrc = 0;	set_freezable();	do {		if (try_to_freeze())			continue;		spin_lock(&GlobalMid_Lock);		if (list_empty(&GlobalOplock_Q)) {			spin_unlock(&GlobalMid_Lock);			set_current_state(TASK_INTERRUPTIBLE);			schedule_timeout(39*HZ);		} else {			oplock_item = list_entry(GlobalOplock_Q.next,				struct oplock_q_entry, qhead);			if (oplock_item) {				cFYI(1, ("found oplock item to write out"));				pTcon = oplock_item->tcon;				inode = oplock_item->pinode;				netfid = oplock_item->netfid;				spin_unlock(&GlobalMid_Lock);				DeleteOplockQEntry(oplock_item);				/* can not grab inode sem here since it would				deadlock when oplock received on delete				since vfs_unlink holds the i_mutex across				the call */				/* mutex_lock(&inode->i_mutex);*/				if (S_ISREG(inode->i_mode)) {					rc =					   filemap_fdatawrite(inode->i_mapping);					if (CIFS_I(inode)->clientCanCacheRead									 == 0) {						waitrc = filemap_fdatawait(inode->i_mapping);						invalidate_remote_inode(inode);					}					if (rc == 0)						rc = waitrc;				} else					rc = 0;				/* mutex_unlock(&inode->i_mutex);*/				if (rc)					CIFS_I(inode)->write_behind_rc = rc;				cFYI(1, ("Oplock flush inode %p rc %d",					inode, rc));				/* releasing stale oplock after recent reconnect				of smb session using a now incorrect file				handle is not a data integrity issue but do				not bother sending an oplock release if session				to server still is disconnected since oplock				already released by the server in that case */				if (pTcon->tidStatus != CifsNeedReconnect) {				    rc = CIFSSMBLock(0, pTcon, netfid,					    0 /* len */ , 0 /* offset */, 0,					    0, LOCKING_ANDX_OPLOCK_RELEASE,					    0 /* wait flag */);					cFYI(1, ("Oplock release rc = %d", rc));				}			} else				spin_unlock(&GlobalMid_Lock);			set_current_state(TASK_INTERRUPTIBLE);			schedule_timeout(1);  /* yield in case q were corrupt */		}	} while (!kthread_should_stop());	return 0;}static int cifs_dnotify_thread(void *dummyarg){	struct list_head *tmp;	struct cifsSesInfo *ses;	do {		if (try_to_freeze())			continue;		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(15*HZ);		read_lock(&GlobalSMBSeslock);		/* check if any stuck requests that need		   to be woken up and wakeq so the		   thread can wake up and error out */		list_for_each(tmp, &GlobalSMBSessionList) {			ses = list_entry(tmp, struct cifsSesInfo,				cifsSessionList);			if (ses && ses->server &&			     atomic_read(&ses->server->inFlight))				wake_up_all(&ses->server->response_q);		}		read_unlock(&GlobalSMBSeslock);	} while (!kthread_should_stop());	return 0;}static int __initinit_cifs(void){	int rc = 0;#ifdef CONFIG_PROC_FS	cifs_proc_init();#endif/*	INIT_LIST_HEAD(&GlobalServerList);*/	/* BB not implemented yet */	INIT_LIST_HEAD(&GlobalSMBSessionList);	INIT_LIST_HEAD(&GlobalTreeConnectionList);	INIT_LIST_HEAD(&GlobalOplock_Q);#ifdef CONFIG_CIFS_EXPERIMENTAL	INIT_LIST_HEAD(&GlobalDnotifyReqList);	INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);#endif/* *  Initialize Global counters */	atomic_set(&sesInfoAllocCount, 0);	atomic_set(&tconInfoAllocCount, 0);	atomic_set(&tcpSesAllocCount, 0);	atomic_set(&tcpSesReconnectCount, 0);	atomic_set(&tconInfoReconnectCount, 0);	atomic_set(&bufAllocCount, 0);	atomic_set(&smBufAllocCount, 0);#ifdef CONFIG_CIFS_STATS2	atomic_set(&totBufAllocCount, 0);	atomic_set(&totSmBufAllocCount, 0);#endif /* CONFIG_CIFS_STATS2 */	atomic_set(&midCount, 0);	GlobalCurrentXid = 0;	GlobalTotalActiveXid = 0;	GlobalMaxActiveXid = 0;	memset(Local_System_Name, 0, 15);	rwlock_init(&GlobalSMBSeslock);	spin_lock_init(&GlobalMid_Lock);	if (cifs_max_pending < 2) {		cifs_max_pending = 2;		cFYI(1, ("cifs_max_pending set to min of 2"));	} else if (cifs_max_pending > 256) {		cifs_max_pending = 256;		cFYI(1, ("cifs_max_pending set to max of 256"));	}	rc = cifs_init_inodecache();	if (rc)		goto out_clean_proc;	rc = cifs_init_mids();	if (rc)		goto out_destroy_inodecache;	rc = cifs_init_request_bufs();	if (rc)		goto out_destroy_mids;	rc = register_filesystem(&cifs_fs_type);	if (rc)		goto out_destroy_request_bufs;#ifdef CONFIG_CIFS_UPCALL	rc = register_key_type(&cifs_spnego_key_type);	if (rc)		goto out_unregister_filesystem;#endif	oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");	if (IS_ERR(oplockThread)) {		rc = PTR_ERR(oplockThread);		cERROR(1, ("error %d create oplock thread", rc));		goto out_unregister_key_type;	}	dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");	if (IS_ERR(dnotifyThread)) {		rc = PTR_ERR(dnotifyThread);		cERROR(1, ("error %d create dnotify thread", rc));		goto out_stop_oplock_thread;	}	return 0; out_stop_oplock_thread:	kthread_stop(oplockThread); out_unregister_key_type:#ifdef CONFIG_CIFS_UPCALL	unregister_key_type(&cifs_spnego_key_type); out_unregister_filesystem:#endif	unregister_filesystem(&cifs_fs_type); out_destroy_request_bufs:	cifs_destroy_request_bufs(); out_destroy_mids:	cifs_destroy_mids(); out_destroy_inodecache:	cifs_destroy_inodecache(); out_clean_proc:#ifdef CONFIG_PROC_FS	cifs_proc_clean();#endif	return rc;}static void __exitexit_cifs(void){	cFYI(0, ("exit_cifs"));#ifdef CONFIG_PROC_FS	cifs_proc_clean();#endif#ifdef CONFIG_CIFS_UPCALL	unregister_key_type(&cifs_spnego_key_type);#endif	unregister_filesystem(&cifs_fs_type);	cifs_destroy_inodecache();	cifs_destroy_mids();	cifs_destroy_request_bufs();	kthread_stop(oplockThread);	kthread_stop(dnotifyThread);}MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");MODULE_LICENSE("GPL");	/* combination of LGPL + GPL source behaves as GPL */MODULE_DESCRIPTION    ("VFS to access servers complying with the SNIA CIFS Specification "     "e.g. Samba and Windows");MODULE_VERSION(CIFS_VERSION);module_init(init_cifs)module_exit(exit_cifs)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -