xfs_vfsops.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,927 行 · 第 1/4 页

C
1,927
字号
	int		flags,	int             xflags,	int             *bypassed){	int		error = 0;	int		last_error = 0;	uint		log_flags = XFS_LOG_FORCE;	xfs_buf_t	*bp;	xfs_buf_log_item_t	*bip;	/*	 * Sync out the log.  This ensures that the log is periodically	 * flushed even if there is not enough activity to fill it up.	 */	if (flags & SYNC_WAIT)		log_flags |= XFS_LOG_SYNC;	xfs_log_force(mp, (xfs_lsn_t)0, log_flags);	if (flags & (SYNC_ATTR|SYNC_DELWRI)) {		if (flags & SYNC_BDFLUSH)			xfs_finish_reclaim_all(mp, 1);		else			error = xfs_sync_inodes(mp, flags, xflags, bypassed);	}	/*	 * Flushing out dirty data above probably generated more	 * log activity, so if this isn't vfs_sync() then flush	 * the log again.	 */	if (flags & SYNC_DELWRI) {		xfs_log_force(mp, (xfs_lsn_t)0, log_flags);	}	if (flags & SYNC_FSDATA) {		/*		 * If this is vfs_sync() then only sync the superblock		 * if we can lock it without sleeping and it is not pinned.		 */		if (flags & SYNC_BDFLUSH) {			bp = xfs_getsb(mp, XFS_BUF_TRYLOCK);			if (bp != NULL) {				bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*);				if ((bip != NULL) &&				    xfs_buf_item_dirty(bip)) {					if (!(XFS_BUF_ISPINNED(bp))) {						XFS_BUF_ASYNC(bp);						error = xfs_bwrite(mp, bp);					} else {						xfs_buf_relse(bp);					}				} else {					xfs_buf_relse(bp);				}			}		} else {			bp = xfs_getsb(mp, 0);			/*			 * If the buffer is pinned then push on the log so			 * we won't get stuck waiting in the write for			 * someone, maybe ourselves, to flush the log.			 * Even though we just pushed the log above, we			 * did not have the superblock buffer locked at			 * that point so it can become pinned in between			 * there and here.			 */			if (XFS_BUF_ISPINNED(bp))				xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);			if (flags & SYNC_WAIT)				XFS_BUF_UNASYNC(bp);			else				XFS_BUF_ASYNC(bp);			error = xfs_bwrite(mp, bp);		}		if (error) {			last_error = error;		}	}	/*	 * If this is the periodic sync, then kick some entries out of	 * the reference cache.  This ensures that idle entries are	 * eventually kicked out of the cache.	 */	if (flags & SYNC_REFCACHE) {		xfs_refcache_purge_some(mp);	}	/*	 * Now check to see if the log needs a "dummy" transaction.	 */	if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {		xfs_trans_t *tp;		xfs_inode_t *ip;		/*		 * Put a dummy transaction in the log to tell		 * recovery that all others are OK.		 */		tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);		if ((error = xfs_trans_reserve(tp, 0,				XFS_ICHANGE_LOG_RES(mp),				0, 0, 0)))  {			xfs_trans_cancel(tp, 0);			return error;		}		ip = mp->m_rootip;		xfs_ilock(ip, XFS_ILOCK_EXCL);		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);		xfs_trans_ihold(tp, ip);		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);		error = xfs_trans_commit(tp, 0, NULL);		xfs_iunlock(ip, XFS_ILOCK_EXCL);		xfs_log_force(mp, (xfs_lsn_t)0, log_flags);	}	/*	 * When shutting down, we need to insure that the AIL is pushed	 * to disk or the filesystem can appear corrupt from the PROM.	 */	if ((flags & (SYNC_CLOSE|SYNC_WAIT)) == (SYNC_CLOSE|SYNC_WAIT)) {		XFS_bflush(mp->m_ddev_targp);		if (mp->m_rtdev_targp) {			XFS_bflush(mp->m_rtdev_targp);		}	}	return XFS_ERROR(last_error);}/* * xfs_vget - called by DMAPI to get vnode from file handle */STATIC intxfs_vget(	bhv_desc_t	*bdp,	vnode_t		**vpp,	fid_t		*fidp){	xfs_mount_t	*mp = XFS_BHVTOM(bdp);	xfs_fid_t	*xfid = (struct xfs_fid *)fidp;	xfs_inode_t	*ip;	int		error;	xfs_ino_t	ino;	unsigned int	igen;	/*	 * Invalid.  Since handles can be created in user space and passed in	 * via gethandle(), this is not cause for a panic.	 */	if (xfid->xfs_fid_len != sizeof(*xfid) - sizeof(xfid->xfs_fid_len))		return XFS_ERROR(EINVAL);	ino  = xfid->xfs_fid_ino;	igen = xfid->xfs_fid_gen;	/*	 * NFS can sometimes send requests for ino 0.  Fail them gracefully.	 */	if (ino == 0)		return XFS_ERROR(ESTALE);	error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0);	if (error) {		*vpp = NULL;		return error;	}	if (ip == NULL) {		*vpp = NULL;		return XFS_ERROR(EIO);	}	if (ip->i_d.di_mode == 0 || (igen && (ip->i_d.di_gen != igen))) {		xfs_iput_new(ip, XFS_ILOCK_SHARED);		*vpp = NULL;		return XFS_ERROR(ENOENT);	}	*vpp = XFS_ITOV(ip);	xfs_iunlock(ip, XFS_ILOCK_SHARED);	return 0;}#define MNTOPT_LOGBUFS	"logbufs"	/* number of XFS log buffers */#define MNTOPT_LOGBSIZE	"logbsize"	/* size of XFS log buffers */#define MNTOPT_LOGDEV	"logdev"	/* log device */#define MNTOPT_RTDEV	"rtdev"		/* realtime I/O device */#define MNTOPT_BIOSIZE	"biosize"	/* log2 of preferred buffered io size */#define MNTOPT_WSYNC	"wsync"		/* safe-mode nfs compatible mount */#define MNTOPT_INO64	"ino64"		/* force inodes into 64-bit range */#define MNTOPT_NOALIGN	"noalign"	/* turn off stripe alignment */#define MNTOPT_SWALLOC	"swalloc"	/* turn on stripe width allocation */#define MNTOPT_SUNIT	"sunit"		/* data volume stripe unit */#define MNTOPT_SWIDTH	"swidth"	/* data volume stripe width */#define MNTOPT_NOUUID	"nouuid"	/* ignore filesystem UUID */#define MNTOPT_MTPT	"mtpt"		/* filesystem mount point */#define MNTOPT_NORECOVERY   "norecovery"   /* don't run XFS recovery */#define MNTOPT_NOLOGFLUSH   "nologflush"   /* don't hard flush on log writes */#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */#define MNTOPT_64BITINODE   "inode64"	/* inodes can be allocated anywhere */#define MNTOPT_IKEEP	"ikeep"		/* do not free empty inode clusters */#define MNTOPT_NOIKEEP	"noikeep"	/* free empty inode clusters */intxfs_parseargs(	struct bhv_desc		*bhv,	char			*options,	struct xfs_mount_args	*args,	int			update){	struct vfs		*vfsp = bhvtovfs(bhv);	char			*this_char, *value, *eov;	int			dsunit, dswidth, vol_dsunit, vol_dswidth;	int			iosize;#if 0	/* XXX: off by default, until some remaining issues ironed out */	args->flags |= XFSMNT_IDELETE; /* default to on */#endif	if (!options)		return 0;	iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;	while ((this_char = strsep(&options, ",")) != NULL) {		if (!*this_char)			continue;		if ((value = strchr(this_char, '=')) != NULL)			*value++ = 0;		if (!strcmp(this_char, MNTOPT_LOGBUFS)) {			if (!value || !*value) {				printk("XFS: %s option requires an argument\n",					MNTOPT_LOGBUFS);				return EINVAL;			}			args->logbufs = simple_strtoul(value, &eov, 10);		} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {			int	last, in_kilobytes = 0;			if (!value || !*value) {				printk("XFS: %s option requires an argument\n",					MNTOPT_LOGBSIZE);				return EINVAL;			}			last = strlen(value) - 1;			if (value[last] == 'K' || value[last] == 'k') {				in_kilobytes = 1;				value[last] = '\0';			}			args->logbufsize = simple_strtoul(value, &eov, 10);			if (in_kilobytes)				args->logbufsize <<= 10;		} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {			if (!value || !*value) {				printk("XFS: %s option requires an argument\n",					MNTOPT_LOGDEV);				return EINVAL;			}			strncpy(args->logname, value, MAXNAMELEN);		} else if (!strcmp(this_char, MNTOPT_MTPT)) {			if (!value || !*value) {				printk("XFS: %s option requires an argument\n",					MNTOPT_MTPT);				return EINVAL;			}			strncpy(args->mtpt, value, MAXNAMELEN);		} else if (!strcmp(this_char, MNTOPT_RTDEV)) {			if (!value || !*value) {				printk("XFS: %s option requires an argument\n",					MNTOPT_RTDEV);				return EINVAL;			}			strncpy(args->rtname, value, MAXNAMELEN);		} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {			if (!value || !*value) {				printk("XFS: %s option requires an argument\n",					MNTOPT_BIOSIZE); 				return EINVAL;			}			iosize = simple_strtoul(value, &eov, 10);			args->flags |= XFSMNT_IOSIZE;			args->iosizelog = (uint8_t) iosize;		} else if (!strcmp(this_char, MNTOPT_WSYNC)) {			args->flags |= XFSMNT_WSYNC;		} else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {			args->flags |= XFSMNT_OSYNCISOSYNC;		} else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {			args->flags |= XFSMNT_NORECOVERY;		} else if (!strcmp(this_char, MNTOPT_INO64)) {			args->flags |= XFSMNT_INO64;#if !XFS_BIG_INUMS			printk("XFS: %s option not allowed on this system\n",				MNTOPT_INO64);			return EINVAL;#endif		} else if (!strcmp(this_char, MNTOPT_NOALIGN)) {			args->flags |= XFSMNT_NOALIGN;		} else if (!strcmp(this_char, MNTOPT_SWALLOC)) {			args->flags |= XFSMNT_SWALLOC;		} else if (!strcmp(this_char, MNTOPT_SUNIT)) {			if (!value || !*value) {				printk("XFS: %s option requires an argument\n",					MNTOPT_SUNIT);				return EINVAL;			}			dsunit = simple_strtoul(value, &eov, 10);		} else if (!strcmp(this_char, MNTOPT_SWIDTH)) {			if (!value || !*value) {				printk("XFS: %s option requires an argument\n",					MNTOPT_SWIDTH);				return EINVAL;			}			dswidth = simple_strtoul(value, &eov, 10);		} else if (!strcmp(this_char, MNTOPT_64BITINODE)) {			args->flags &= ~XFSMNT_32BITINODES;#if !XFS_BIG_INUMS			printk("XFS: %s option not allowed on this system\n",				MNTOPT_64BITINODE);			return EINVAL;#endif		} else if (!strcmp(this_char, MNTOPT_NOUUID)) {			args->flags |= XFSMNT_NOUUID;		} else if (!strcmp(this_char, MNTOPT_NOLOGFLUSH)) {			args->flags |= XFSMNT_NOLOGFLUSH;		} else if (!strcmp(this_char, MNTOPT_IKEEP)) {			args->flags &= ~XFSMNT_IDELETE;		} else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {			args->flags |= XFSMNT_IDELETE;		} else if (!strcmp(this_char, "osyncisdsync")) {			/* no-op, this is now the default */printk("XFS: osyncisdsync is now the default, option is deprecated.\n");		} else if (!strcmp(this_char, "irixsgid")) {printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");		} else {			printk("XFS: unknown mount option [%s].\n", this_char);			return EINVAL;		}	}	if (args->flags & XFSMNT_NORECOVERY) {		if ((vfsp->vfs_flag & VFS_RDONLY) == 0) {			printk("XFS: no-recovery mounts must be read-only.\n");			return EINVAL;		}	}	if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {		printk(	"XFS: sunit and swidth options incompatible with the noalign option\n");		return EINVAL;	}	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {		printk("XFS: sunit and swidth must be specified together\n");		return EINVAL;	}	if (dsunit && (dswidth % dsunit != 0)) {		printk(	"XFS: stripe width (%d) must be a multiple of the stripe unit (%d)\n",			dswidth, dsunit);		return EINVAL;	}	if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {		if (dsunit) {			args->sunit = dsunit;			args->flags |= XFSMNT_RETERR;		} else {			args->sunit = vol_dsunit;		}		dswidth ? (args->swidth = dswidth) :			  (args->swidth = vol_dswidth);	} else {		args->sunit = args->swidth = 0;	}	return 0;}intxfs_showargs(	struct bhv_desc		*bhv,	struct seq_file		*m){	static struct proc_xfs_info {		int	flag;		char	*str;	} xfs_info[] = {		/* the few simple ones we can get from the mount struct */		{ XFS_MOUNT_WSYNC,		"," MNTOPT_WSYNC },		{ XFS_MOUNT_INO64,		"," MNTOPT_INO64 },		{ XFS_MOUNT_NOALIGN,		"," MNTOPT_NOALIGN },		{ XFS_MOUNT_SWALLOC,		"," MNTOPT_SWALLOC },		{ XFS_MOUNT_NOUUID,		"," MNTOPT_NOUUID },		{ XFS_MOUNT_NORECOVERY,		"," MNTOPT_NORECOVERY },		{ XFS_MOUNT_OSYNCISOSYNC,	"," MNTOPT_OSYNCISOSYNC },		{ XFS_MOUNT_NOLOGFLUSH,		"," MNTOPT_NOLOGFLUSH },		{ XFS_MOUNT_IDELETE,		"," MNTOPT_NOIKEEP },		{ 0, NULL }	};	struct proc_xfs_info	*xfs_infop;	struct xfs_mount	*mp = XFS_BHVTOM(bhv);	for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {		if (mp->m_flags & xfs_infop->flag)			seq_puts(m, xfs_infop->str);	}	if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)		seq_printf(m, "," MNTOPT_BIOSIZE "=%d", mp->m_writeio_log);	if (mp->m_logbufs > 0)		seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);	if (mp->m_logbsize > 0)		seq_printf(m, "," MNTOPT_LOGBSIZE "=%d", mp->m_logbsize);	if (mp->m_ddev_targp != mp->m_logdev_targp)		seq_printf(m, "," MNTOPT_LOGDEV "=%s",				XFS_BUFTARG_NAME(mp->m_logdev_targp));	if (mp->m_rtdev_targp && mp->m_ddev_targp != mp->m_rtdev_targp)		seq_printf(m, "," MNTOPT_RTDEV "=%s",				XFS_BUFTARG_NAME(mp->m_rtdev_targp));	if (mp->m_dalign > 0)		seq_printf(m, "," MNTOPT_SUNIT "=%d",				(int)XFS_FSB_TO_BB(mp, mp->m_dalign));	if (mp->m_swidth > 0)		seq_printf(m, "," MNTOPT_SWIDTH "=%d",				(int)XFS_FSB_TO_BB(mp, mp->m_swidth));	if (!(mp->m_flags & XFS_MOUNT_32BITINOOPT))		seq_printf(m, "," MNTOPT_64BITINODE);		return 0;}STATIC voidxfs_freeze(	bhv_desc_t	*bdp){	xfs_mount_t	*mp = XFS_BHVTOM(bdp);	while (atomic_read(&mp->m_active_trans) > 0)		delay(100);	/* Push the superblock and write an unmount record */	xfs_log_unmount_write(mp);	xfs_unmountfs_writesb(mp);}vfsops_t xfs_vfsops = {	BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),	.vfs_parseargs		= xfs_parseargs,	.vfs_showargs		= xfs_showargs,	.vfs_mount		= xfs_mount,	.vfs_unmount		= xfs_unmount,	.vfs_mntupdate		= xfs_mntupdate,	.vfs_root		= xfs_root,	.vfs_statvfs		= xfs_statvfs,	.vfs_sync		= xfs_sync,	.vfs_vget		= xfs_vget,	.vfs_dmapiops		= (vfs_dmapiops_t)fs_nosys,	.vfs_quotactl		= (vfs_quotactl_t)fs_nosys,	.vfs_init_vnode		= xfs_initialize_vnode,	.vfs_force_shutdown	= xfs_do_force_shutdown,	.vfs_freeze		= xfs_freeze,};

⌨️ 快捷键说明

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