📄 inode.c
字号:
/* * inode.c * * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * Copyright (C) 1997 by Volker Lendecke * * Please add a note about your changes to smbfs in the ChangeLog file. */#include <linux/config.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/errno.h>#include <linux/locks.h>#include <linux/malloc.h>#include <linux/init.h>#include <linux/file.h>#include <linux/dcache.h>#include <linux/smp_lock.h>#include <linux/nls.h>#include <linux/smb_fs.h>#include <linux/smbno.h>#include <linux/smb_mount.h>#include <asm/system.h>#include <asm/uaccess.h>#include "smb_debug.h"#include "getopt.h"/* Always pick a default string */#ifdef CONFIG_SMB_NLS_REMOTE#define SMB_NLS_REMOTE CONFIG_SMB_NLS_REMOTE#else#define SMB_NLS_REMOTE ""#endifstatic void smb_delete_inode(struct inode *);static void smb_put_super(struct super_block *);static int smb_statfs(struct super_block *, struct statfs *);static void smb_set_inode_attr(struct inode *, struct smb_fattr *);static struct super_operations smb_sops ={ put_inode: force_delete, delete_inode: smb_delete_inode, put_super: smb_put_super, statfs: smb_statfs,};/* We are always generating a new inode here */struct inode *smb_iget(struct super_block *sb, struct smb_fattr *fattr){ struct inode *result; DEBUG1("smb_iget: %p\n", fattr); result = new_inode(sb); if (!result) return result; result->i_ino = fattr->f_ino; memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i)); smb_set_inode_attr(result, fattr); if (S_ISREG(result->i_mode)) { result->i_op = &smb_file_inode_operations; result->i_fop = &smb_file_operations; result->i_data.a_ops = &smb_file_aops; } else if (S_ISDIR(result->i_mode)) { result->i_op = &smb_dir_inode_operations; result->i_fop = &smb_dir_operations; } insert_inode_hash(result); return result;}/* * Copy the inode data to a smb_fattr structure. */voidsmb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr){ memset(fattr, 0, sizeof(struct smb_fattr)); fattr->f_mode = inode->i_mode; fattr->f_nlink = inode->i_nlink; fattr->f_ino = inode->i_ino; fattr->f_uid = inode->i_uid; fattr->f_gid = inode->i_gid; fattr->f_rdev = inode->i_rdev; fattr->f_size = inode->i_size; fattr->f_mtime = inode->i_mtime; fattr->f_ctime = inode->i_ctime; fattr->f_atime = inode->i_atime; fattr->f_blksize= inode->i_blksize; fattr->f_blocks = inode->i_blocks; fattr->attr = inode->u.smbfs_i.attr; /* * Keep the attributes in sync with the inode permissions. */ if (fattr->f_mode & S_IWUSR) fattr->attr &= ~aRONLY; else fattr->attr |= aRONLY;}static voidsmb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr){ inode->i_mode = fattr->f_mode; inode->i_nlink = fattr->f_nlink; inode->i_uid = fattr->f_uid; inode->i_gid = fattr->f_gid; inode->i_rdev = fattr->f_rdev; inode->i_ctime = fattr->f_ctime; inode->i_blksize= fattr->f_blksize; inode->i_blocks = fattr->f_blocks; /* * Don't change the size and mtime/atime fields * if we're writing to the file. */ if (!(inode->u.smbfs_i.cache_valid & SMB_F_LOCALWRITE)) { inode->i_size = fattr->f_size; inode->i_mtime = fattr->f_mtime; inode->i_atime = fattr->f_atime; } inode->u.smbfs_i.attr = fattr->attr; /* * Update the "last time refreshed" field for revalidation. */ inode->u.smbfs_i.oldmtime = jiffies;}/* * This is called if the connection has gone bad ... * try to kill off all the current inodes. */voidsmb_invalidate_inodes(struct smb_sb_info *server){ VERBOSE("\n"); shrink_dcache_sb(SB_of(server)); invalidate_inodes(SB_of(server));}/* * This is called to update the inode attributes after * we've made changes to a file or directory. */static intsmb_refresh_inode(struct dentry *dentry){ struct inode *inode = dentry->d_inode; int error; struct smb_fattr fattr; error = smb_proc_getattr(dentry, &fattr); if (!error) { smb_renew_times(dentry); /* * Check whether the type part of the mode changed, * and don't update the attributes if it did. */ if ((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT)) smb_set_inode_attr(inode, &fattr); else { /* * Big trouble! The inode has become a new object, * so any operations attempted on it are invalid. * * To limit damage, mark the inode as bad so that * subsequent lookup validations will fail. */ PARANOIA("%s/%s changed mode, %07o to %07o\n", DENTRY_PATH(dentry), inode->i_mode, fattr.f_mode); fattr.f_mode = inode->i_mode; /* save mode */ make_bad_inode(inode); inode->i_mode = fattr.f_mode; /* restore mode */ /* * No need to worry about unhashing the dentry: the * lookup validation will see that the inode is bad. * But we do want to invalidate the caches ... */ if (!S_ISDIR(inode->i_mode)) invalidate_inode_pages(inode); else smb_invalid_dir_cache(inode); error = -EIO; } } return error;}/* * This is called when we want to check whether the inode * has changed on the server. If it has changed, we must * invalidate our local caches. */intsmb_revalidate_inode(struct dentry *dentry){ struct inode *inode = dentry->d_inode; time_t last_time; int error = 0; DEBUG1("smb_revalidate_inode\n"); /* * If this is a file opened with write permissions, * the inode will be up-to-date. */ lock_kernel(); if (S_ISREG(inode->i_mode) && smb_is_open(inode)) { if (inode->u.smbfs_i.access != SMB_O_RDONLY) goto out; } /* * Check whether we've recently refreshed the inode. */ if (time_before(jiffies, inode->u.smbfs_i.oldmtime + HZ/10)) { VERBOSE("up-to-date, jiffies=%lu, oldtime=%lu\n", jiffies, inode->u.smbfs_i.oldmtime); goto out; } /* * Save the last modified time, then refresh the inode. * (Note: a size change should have a different mtime.) */ last_time = inode->i_mtime; error = smb_refresh_inode(dentry); if (error || inode->i_mtime != last_time) { VERBOSE("%s/%s changed, old=%ld, new=%ld\n", DENTRY_PATH(dentry), (long) last_time, (long) inode->i_mtime); if (!S_ISDIR(inode->i_mode)) invalidate_inode_pages(inode); else smb_invalid_dir_cache(inode); }out: unlock_kernel(); return error;}/* * This routine is called when i_nlink == 0 and i_count goes to 0. * All blocking cleanup operations need to go here to avoid races. */static voidsmb_delete_inode(struct inode *ino){ DEBUG1("ino=%ld\n", ino->i_ino); lock_kernel(); if (smb_close(ino)) PARANOIA("could not close inode %ld\n", ino->i_ino); unlock_kernel(); clear_inode(ino);}/* FIXME: flags and has_arg could probably be merged. */struct option opts[] = { { "version", 1, 0, 'v' }, { "win95", 0, SMB_MOUNT_WIN95, 1 }, { "oldattr", 0, SMB_MOUNT_OLDATTR, 1 }, { "dirattr", 0, SMB_MOUNT_DIRATTR, 1 }, { "case", 0, SMB_MOUNT_CASE, 1 }, { "uid", 1, 0, 'u' }, { "gid", 1, 0, 'g' }, { "file_mode", 1, 0, 'f' }, { "dir_mode", 1, 0, 'd' }, { "iocharset", 1, 0, 'i' }, { "codepage", 1, 0, 'c' }, { NULL, 0, 0, 0}};static intparse_options(struct smb_mount_data_kernel *mnt, char *options){ int c; unsigned long flags; unsigned long value; char *optarg; char *optopt; flags = 0; while ( (c = smb_getopt("smbfs", &options, opts, &optopt, &optarg, &flags, &value)) > 0) { VERBOSE("'%s' -> '%s'\n", optopt, optarg ? optarg : "<none>"); switch (c) { case 1: /* got a "flag" option */ break; case 'v': if (value != SMB_MOUNT_VERSION) { printk ("smbfs: Bad mount version %ld, expected %d\n", value, SMB_MOUNT_VERSION); return 0; } mnt->version = value; break; case 'u': mnt->uid = value; break; case 'g': mnt->gid = value; break; case 'f': mnt->file_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO); mnt->file_mode |= S_IFREG; break; case 'd': mnt->dir_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO); mnt->dir_mode |= S_IFDIR; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -