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 + -
显示快捷键?