From 7f0fdc5d3f99a3e4fa6d486bd89243456bcb3e3d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sat, 10 Jul 2004 19:28:28 -0700 Subject: [PATCH] quota: inode->i_flags locking fixes The patch fixes locking of i_flags. It removes S_QUOTA flag from i_flags because it was almost unused and updating it on some places correctly (under i_sem) would be tricky. Note that accessing of S_NOQUOTA flag is serialized by dqptr_sem and so we can reliably tested without i_sem. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fs.h | 16 +++++++--------- include/linux/quotaops.h | 19 ++++++++++++++++--- 2 files changed, 23 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/include/linux/fs.h b/include/linux/fs.h index 92e525264998..de1cd53ca7d3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -133,14 +133,13 @@ extern int leases_enable, dir_notify_enable, lease_break_time; #define S_SYNC 1 /* Writes are synced at once */ #define S_NOATIME 2 /* Do not update access times */ -#define S_QUOTA 4 /* Quota initialized for file */ -#define S_APPEND 8 /* Append-only file */ -#define S_IMMUTABLE 16 /* Immutable file */ -#define S_DEAD 32 /* removed, but still open directory */ -#define S_NOQUOTA 64 /* Inode is not counted to quota */ -#define S_DIRSYNC 128 /* Directory modifications are synchronous */ -#define S_NOCMTIME 256 /* Do not update file c/mtime */ -#define S_SWAPFILE 512 /* Do not truncate: swapon got its bmaps */ +#define S_APPEND 4 /* Append-only file */ +#define S_IMMUTABLE 8 /* Immutable file */ +#define S_DEAD 16 /* removed, but still open directory */ +#define S_NOQUOTA 32 /* Inode is not counted to quota */ +#define S_DIRSYNC 64 /* Directory modifications are synchronous */ +#define S_NOCMTIME 128 /* Do not update file c/mtime */ +#define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */ /* * Note that nosuid etc flags are inode-specific: setting some file-system @@ -164,7 +163,6 @@ extern int leases_enable, dir_notify_enable, lease_break_time; ((inode)->i_flags & (S_SYNC|S_DIRSYNC))) #define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK) -#define IS_QUOTAINIT(inode) ((inode)->i_flags & S_QUOTA) #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 9db474dcafd5..acc926c64e78 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -69,9 +69,22 @@ static __inline__ void DQUOT_INIT(struct inode *inode) /* The same as with DQUOT_INIT */ static __inline__ void DQUOT_DROP(struct inode *inode) { - if (IS_QUOTAINIT(inode)) { - BUG_ON(!inode->i_sb); - inode->i_sb->dq_op->drop(inode); /* Ops must be set when there's any quota... */ + /* Here we can get arbitrary inode from clear_inode() so we have + * to be careful. OTOH we don't need locking as quota operations + * are allowed to change only at mount time */ + if (!IS_NOQUOTA(inode) && inode->i_sb && inode->i_sb->dq_op + && inode->i_sb->dq_op->drop) { + int cnt; + /* Test before calling to rule out calls from proc and such + * where we are not allowed to block. Note that this is + * actually reliable test even without the lock - the caller + * must assure that nobody can come after the DQUOT_DROP and + * add quota pointers back anyway */ + for (cnt = 0; cnt < MAXQUOTAS; cnt++) + if (inode->i_dquot[cnt] != NODQUOT) + break; + if (cnt < MAXQUOTAS) + inode->i_sb->dq_op->drop(inode); } } -- cgit v1.2.3 From c8a6ba011918486195870aab9a8e3d61c76c1b02 Mon Sep 17 00:00:00 2001 From: David Howells Date: Sat, 10 Jul 2004 19:30:11 -0700 Subject: [PATCH] intrinsic automount and mountpoint degradation support Here's a patch that I worked out with Al Viro that adds support for a filesystem (such as kAFS) to perform automounting intrinsically without the need for a userspace daemon. It also adds support for such mountpoints to be degraded at the filesystem's behest until they've been untouched long enough that they'll be removed. I've a patch (to follow) that removes some #ifdef's from fs/afs/* thus allowing it to make use of this facility. There are five pieces to this: (1) Any interested filesystem needs to have at least one list to which expirable mountpoints can be added. Access to this list is governed by the vfsmount_lock. (2) When a filesystem wants to create an expirable mount, it calls do_kern_mount() to get a handle on the filesystem it wants mounting, and then calls do_add_mount() to mount that filesystem on the designated mountpoint, supplying the list mentioned in (1) to which the vfsmount will be added. In kAFS's case, the mountpoint is a directory with a follow_link() method defined (fs/afs/mntpt.c). This uses the struct nameidata supplied as an argument as a determination of where the new filesystem should be mounted. (3) When something using a vfsmount finishes dealing with it, it calls mntput(). This unmarks the vfsmount for immediate expiry. There are two criteria for determining if a vfsmount may be expired - it mustn't be marked as in use for anything other than being a child of another vfsmount, and it must have an expiry mark against it already. (4) The filesystem then determines the policy on expiring the mounts created in (2). When it feels the need to, it passes the list mentioned in (1) to mark_mounts_for_expiry() to request everything on the list be expired. This function examines each mount listed. If the vfsmount meets the criteria mentioned in (3), then the vfsmount is deleted from the namespace and disposed of as for unmounting; otherwise the vfsmount is left untouched apart from now bearing an expiration mark if it didn't before. kAFS's expiration policy is simply to invoke this process at regular intervals for all the mounts on its list. (5) An expiration facility is also provided to userspace: by calling umount() with a MNT_EXPIRE flag, it can make a request to unmount only if the mountpoint hasn't been used since the last request and isn't in use now. This allows expiration to be driven by userspace instead of by the kernel if that is desirable. This also means that do_umount() has to use a different version of path_release() to everyone else... it can't call mntput() as that clears the expiration flag, thus rendering this unachievable; so it's version of path_release() calls _mntput(), which doesn't do the clear. My original idea was to give the kernel more knowledge of automounted things. This avoids a certain problem with stat() on a mountpoint causing it to mount (for example, do "ls -l /afs" on a machine with kAFS), but Al wanted it done this way. > Why is autofs unsuitable? Because: (1) Autofs is flat; AFS requires a tree - mounts on mounts on mounts on mounts... (2) AFS holds the data as to what the mountpoints are and where they go, and these may be cross-links to subtrees beyond your control. It's also not trivial to extract a list of mountpoints as is required for autofs. (3) Autofs is not namespace safe. (4) Ducking back to userspace to get that to do the mount is pretty tricky if namespaces are involved. In fact, autofs may well want to make use of this facility. Signed-Off-By: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/automount-support.txt | 118 +++++++++++++ fs/namei.c | 10 ++ fs/namespace.c | 215 +++++++++++++++++++++--- fs/super.c | 3 + include/linux/fs.h | 1 + include/linux/mount.h | 21 ++- include/linux/namei.h | 1 + include/linux/namespace.h | 2 +- 8 files changed, 350 insertions(+), 21 deletions(-) create mode 100644 Documentation/filesystems/automount-support.txt (limited to 'include/linux') diff --git a/Documentation/filesystems/automount-support.txt b/Documentation/filesystems/automount-support.txt new file mode 100644 index 000000000000..58c65a1713e5 --- /dev/null +++ b/Documentation/filesystems/automount-support.txt @@ -0,0 +1,118 @@ +Support is available for filesystems that wish to do automounting support (such +as kAFS which can be found in fs/afs/). This facility includes allowing +in-kernel mounts to be performed and mountpoint degradation to be +requested. The latter can also be requested by userspace. + + +====================== +IN-KERNEL AUTOMOUNTING +====================== + +A filesystem can now mount another filesystem on one of its directories by the +following procedure: + + (1) Give the directory a follow_link() operation. + + When the directory is accessed, the follow_link op will be called, and + it will be provided with the location of the mountpoint in the nameidata + structure (vfsmount and dentry). + + (2) Have the follow_link() op do the following steps: + + (a) Call do_kern_mount() to call the appropriate filesystem to set up a + superblock and gain a vfsmount structure representing it. + + (b) Copy the nameidata provided as an argument and substitute the dentry + argument into it the copy. + + (c) Call do_add_mount() to install the new vfsmount into the namespace's + mountpoint tree, thus making it accessible to userspace. Use the + nameidata set up in (b) as the destination. + + If the mountpoint will be automatically expired, then do_add_mount() + should also be given the location of an expiration list (see further + down). + + (d) Release the path in the nameidata argument and substitute in the new + vfsmount and its root dentry. The ref counts on these will need + incrementing. + +Then from userspace, you can just do something like: + + [root@andromeda root]# mount -t afs \#root.afs. /afs + [root@andromeda root]# ls /afs + asd cambridge cambridge.redhat.com grand.central.org + [root@andromeda root]# ls /afs/cambridge + afsdoc + [root@andromeda root]# ls /afs/cambridge/afsdoc/ + ChangeLog html LICENSE pdf RELNOTES-1.2.2 + +And then if you look in the mountpoint catalogue, you'll see something like: + + [root@andromeda root]# cat /proc/mounts + ... + #root.afs. /afs afs rw 0 0 + #root.cell. /afs/cambridge.redhat.com afs rw 0 0 + #afsdoc. /afs/cambridge.redhat.com/afsdoc afs rw 0 0 + + +=========================== +AUTOMATIC MOUNTPOINT EXPIRY +=========================== + +Automatic expiration of mountpoints is easy, provided you've mounted the +mountpoint to be expired in the automounting procedure outlined above. + +To do expiration, you need to follow these steps: + + (3) Create at least one list off which the vfsmounts to be expired can be + hung. Access to this list will be governed by the vfsmount_lock. + + (4) In step (2c) above, the call to do_add_mount() should be provided with a + pointer to this list. It will hang the vfsmount off of it if it succeeds. + + (5) When you want mountpoints to be expired, call mark_mounts_for_expiry() + with a pointer to this list. This will process the list, marking every + vfsmount thereon for potential expiry on the next call. + + If a vfsmount was already flagged for expiry, and if its usage count is 1 + (it's only referenced by its parent vfsmount), then it will be deleted + from the namespace and thrown away (effectively unmounted). + + It may prove simplest to simply call this at regular intervals, using + some sort of timed event to drive it. + +The expiration flag is cleared by calls to mntput. This means that expiration +will only happen on the second expiration request after the last time the +mountpoint was accessed. + +If a mountpoint is moved, it gets removed from the expiration list. If a bind +mount is made on an expirable mount, the new vfsmount will not be on the +expiration list and will not expire. + +If a namespace is copied, all mountpoints contained therein will be copied, +and the copies of those that are on an expiration list will be added to the +same expiration list. + + +======================= +USERSPACE DRIVEN EXPIRY +======================= + +As an alternative, it is possible for userspace to request expiry of any +mountpoint (though some will be rejected - the current process's idea of the +rootfs for example). It does this by passing the MNT_EXPIRE flag to +umount(). This flag is considered incompatible with MNT_FORCE and MNT_DETACH. + +If the mountpoint in question is in referenced by something other than +umount() or its parent mountpoint, an EBUSY error will be returned and the +mountpoint will not be marked for expiration or unmounted. + +If the mountpoint was not already marked for expiry at that time, an EAGAIN +error will be given and it won't be unmounted. + +Otherwise if it was already marked and it wasn't referenced, unmounting will +take place as usual. + +Again, the expiration flag is cleared every time anything other than umount() +looks at a mountpoint. diff --git a/fs/namei.c b/fs/namei.c index 3db4da5a2116..bbadcf782e92 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -278,6 +278,16 @@ void path_release(struct nameidata *nd) mntput(nd->mnt); } +/* + * umount() mustn't call path_release()/mntput() as that would clear + * mnt_expiry_mark + */ +void path_release_on_umount(struct nameidata *nd) +{ + dput(nd->dentry); + _mntput(nd->mnt); +} + /* * Internal lookup() using the new generic dcache. * SMP-safe diff --git a/fs/namespace.c b/fs/namespace.c index f3ab6910fdf1..759527b1efe2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -60,6 +60,7 @@ struct vfsmount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); + INIT_LIST_HEAD(&mnt->mnt_fslink); if (name) { int size = strlen(name)+1; char *newname = kmalloc(size, GFP_KERNEL); @@ -106,13 +107,9 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) EXPORT_SYMBOL(lookup_mnt); -static int check_mnt(struct vfsmount *mnt) +static inline int check_mnt(struct vfsmount *mnt) { - spin_lock(&vfsmount_lock); - while (mnt->mnt_parent != mnt) - mnt = mnt->mnt_parent; - spin_unlock(&vfsmount_lock); - return mnt == current->namespace->root; + return mnt->mnt_namespace == current->namespace; } static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) @@ -164,6 +161,14 @@ clone_mnt(struct vfsmount *old, struct dentry *root) mnt->mnt_root = dget(root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; + mnt->mnt_namespace = old->mnt_namespace; + + /* stick the duplicate mount on the same expiry list + * as the original if that was on one */ + spin_lock(&vfsmount_lock); + if (!list_empty(&old->mnt_fslink)) + list_add(&mnt->mnt_fslink, &old->mnt_fslink); + spin_unlock(&vfsmount_lock); } return mnt; } @@ -346,6 +351,7 @@ void umount_tree(struct vfsmount *mnt) while (!list_empty(&kill)) { mnt = list_entry(kill.next, struct vfsmount, mnt_list); list_del_init(&mnt->mnt_list); + list_del_init(&mnt->mnt_fslink); if (mnt->mnt_parent == mnt) { spin_unlock(&vfsmount_lock); } else { @@ -368,6 +374,24 @@ static int do_umount(struct vfsmount *mnt, int flags) if (retval) return retval; + /* + * Allow userspace to request a mountpoint be expired rather than + * unmounting unconditionally. Unmount only happens if: + * (1) the mark is already set (the mark is cleared by mntput()) + * (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount] + */ + if (flags & MNT_EXPIRE) { + if (mnt == current->fs->rootmnt || + flags & (MNT_FORCE | MNT_DETACH)) + return -EINVAL; + + if (atomic_read(&mnt->mnt_count) != 2) + return -EBUSY; + + if (!xchg(&mnt->mnt_expiry_mark, 1)) + return -EAGAIN; + } + /* * If we may have to abort operations to get out of this * mount, and they will themselves hold resources we must @@ -461,7 +485,7 @@ asmlinkage long sys_umount(char __user * name, int flags) retval = do_umount(nd.mnt, flags); dput_and_out: - path_release(&nd); + path_release_on_umount(&nd); out: return retval; } @@ -618,6 +642,11 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) } if (mnt) { + /* stop bind mounts from expiring */ + spin_lock(&vfsmount_lock); + list_del_init(&mnt->mnt_fslink); + spin_unlock(&vfsmount_lock); + err = graft_tree(mnt, nd); if (err) { spin_lock(&vfsmount_lock); @@ -638,7 +667,8 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) * on it - tough luck. */ -static int do_remount(struct nameidata *nd,int flags,int mnt_flags,void *data) +static int do_remount(struct nameidata *nd, int flags, int mnt_flags, + void *data) { int err; struct super_block * sb = nd->mnt->mnt_sb; @@ -710,6 +740,10 @@ static int do_move_mount(struct nameidata *nd, char *old_name) detach_mnt(old_nd.mnt, &parent_nd); attach_mnt(old_nd.mnt, nd); + + /* if the mount is moved, it should no longer be expire + * automatically */ + list_del_init(&old_nd.mnt->mnt_fslink); out2: spin_unlock(&vfsmount_lock); out1: @@ -722,11 +756,14 @@ out: return err; } -static int do_add_mount(struct nameidata *nd, char *type, int flags, +/* + * create a new mount for userspace and request it to be added into the + * namespace's tree + */ +static int do_new_mount(struct nameidata *nd, char *type, int flags, int mnt_flags, char *name, void *data) { struct vfsmount *mnt; - int err; if (!type || !memchr(type, 0, PAGE_SIZE)) return -EINVAL; @@ -736,9 +773,20 @@ static int do_add_mount(struct nameidata *nd, char *type, int flags, return -EPERM; mnt = do_kern_mount(type, flags, name, data); - err = PTR_ERR(mnt); if (IS_ERR(mnt)) - goto out; + return PTR_ERR(mnt); + + return do_add_mount(mnt, nd, mnt_flags, NULL); +} + +/* + * add a mount into a namespace's mount tree + * - provide the option of adding the new mount to an expiration list + */ +int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, + int mnt_flags, struct list_head *fslist) +{ + int err; down_write(¤t->namespace->sem); /* Something was mounted here while we slept */ @@ -750,22 +798,143 @@ static int do_add_mount(struct nameidata *nd, char *type, int flags, /* Refuse the same filesystem on the same mount point */ err = -EBUSY; - if (nd->mnt->mnt_sb == mnt->mnt_sb && nd->mnt->mnt_root == nd->dentry) + if (nd->mnt->mnt_sb == newmnt->mnt_sb && + nd->mnt->mnt_root == nd->dentry) goto unlock; err = -EINVAL; - if (S_ISLNK(mnt->mnt_root->d_inode->i_mode)) + if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode)) goto unlock; - mnt->mnt_flags = mnt_flags; - err = graft_tree(mnt, nd); + newmnt->mnt_flags = mnt_flags; + err = graft_tree(newmnt, nd); + + if (err == 0 && fslist) { + /* add to the specified expiration list */ + spin_lock(&vfsmount_lock); + list_add_tail(&newmnt->mnt_fslink, fslist); + spin_unlock(&vfsmount_lock); + } + unlock: up_write(¤t->namespace->sem); - mntput(mnt); -out: + mntput(newmnt); return err; } +EXPORT_SYMBOL_GPL(do_add_mount); + +/* + * process a list of expirable mountpoints with the intent of discarding any + * mountpoints that aren't in use and haven't been touched since last we came + * here + */ +void mark_mounts_for_expiry(struct list_head *mounts) +{ + struct namespace *namespace; + struct list_head graveyard, *_p, *_n; + struct vfsmount *mnt; + + if (list_empty(mounts)) + return; + + INIT_LIST_HEAD(&graveyard); + + spin_lock(&vfsmount_lock); + + /* extract from the expiration list every vfsmount that matches the + * following criteria: + * - only referenced by its parent vfsmount + * - still marked for expiry (marked on the last call here; marks are + * cleared by mntput()) + */ + list_for_each_safe(_p, _n, mounts) { + mnt = list_entry(_p, struct vfsmount, mnt_fslink); + + if (!xchg(&mnt->mnt_expiry_mark, 1) || + atomic_read(&mnt->mnt_count) != 1) + continue; + + mntget(mnt); + list_move(&mnt->mnt_fslink, &graveyard); + } + + /* + * go through the vfsmounts we've just consigned to the graveyard to + * - check that they're still dead + * - delete the vfsmount from the appropriate namespace under lock + * - dispose of the corpse + */ + while (!list_empty(&graveyard)) { + mnt = list_entry(graveyard.next, struct vfsmount, mnt_fslink); + list_del_init(&mnt->mnt_fslink); + + /* don't do anything if the namespace is dead - all the + * vfsmounts from it are going away anyway */ + namespace = mnt->mnt_namespace; + if (!namespace || atomic_read(&namespace->count) <= 0) + continue; + get_namespace(namespace); + + spin_unlock(&vfsmount_lock); + down_write(&namespace->sem); + spin_lock(&vfsmount_lock); + + /* check that it is still dead: the count should now be 2 - as + * contributed by the vfsmount parent and the mntget above */ + if (atomic_read(&mnt->mnt_count) == 2) { + struct vfsmount *xdmnt; + struct dentry *xdentry; + + /* delete from the namespace */ + list_del_init(&mnt->mnt_list); + list_del_init(&mnt->mnt_child); + list_del_init(&mnt->mnt_hash); + mnt->mnt_mountpoint->d_mounted--; + + xdentry = mnt->mnt_mountpoint; + mnt->mnt_mountpoint = mnt->mnt_root; + xdmnt = mnt->mnt_parent; + mnt->mnt_parent = mnt; + + spin_unlock(&vfsmount_lock); + + mntput(xdmnt); + dput(xdentry); + + /* now lay it to rest if this was the last ref on the + * superblock */ + if (atomic_read(&mnt->mnt_sb->s_active) == 1) { + /* last instance - try to be smart */ + lock_kernel(); + DQUOT_OFF(mnt->mnt_sb); + acct_auto_close(mnt->mnt_sb); + unlock_kernel(); + } + + mntput(mnt); + } + else { + /* someone brought it back to life whilst we didn't + * have any locks held so return it to the expiration + * list */ + list_add_tail(&mnt->mnt_fslink, mounts); + spin_unlock(&vfsmount_lock); + } + + up_write(&namespace->sem); + + mntput(mnt); + put_namespace(namespace); + + spin_lock(&vfsmount_lock); + } + + spin_unlock(&vfsmount_lock); +} + +EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); + int copy_mount_options (const void __user *data, unsigned long *where) { int i; @@ -860,7 +1029,7 @@ long do_mount(char * dev_name, char * dir_name, char *type_page, else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); else - retval = do_add_mount(&nd, type_page, flags, mnt_flags, + retval = do_new_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page); dput_out: path_release(&nd); @@ -1185,6 +1354,7 @@ static void __init init_mount_tree(void) init_rwsem(&namespace->sem); list_add(&mnt->mnt_list, &namespace->list); namespace->root = mnt; + mnt->mnt_namespace = namespace; init_task.namespace = namespace; read_lock(&tasklist_lock); @@ -1252,8 +1422,15 @@ void __init mnt_init(unsigned long mempages) void __put_namespace(struct namespace *namespace) { + struct vfsmount *mnt; + down_write(&namespace->sem); spin_lock(&vfsmount_lock); + + list_for_each_entry(mnt, &namespace->list, mnt_list) { + mnt->mnt_namespace = NULL; + } + umount_tree(namespace->root); spin_unlock(&vfsmount_lock); up_write(&namespace->sem); diff --git a/fs/super.c b/fs/super.c index ca60ada578b5..38c23bf558d4 100644 --- a/fs/super.c +++ b/fs/super.c @@ -793,6 +793,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) mnt->mnt_root = dget(sb->s_root); mnt->mnt_mountpoint = sb->s_root; mnt->mnt_parent = mnt; + mnt->mnt_namespace = current->namespace; up_write(&sb->s_umount); put_filesystem(type); return mnt; @@ -809,6 +810,8 @@ out: return (struct vfsmount *)sb; } +EXPORT_SYMBOL_GPL(do_kern_mount); + struct vfsmount *kern_mount(struct file_system_type *type) { return do_kern_mount(type->name, 0, type->name, NULL); diff --git a/include/linux/fs.h b/include/linux/fs.h index de1cd53ca7d3..e847ef6d20fb 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -716,6 +716,7 @@ extern int send_sigurg(struct fown_struct *fown); #define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */ #define MNT_DETACH 0x00000002 /* Just detach from the tree */ +#define MNT_EXPIRE 0x00000004 /* Mark for expiry */ extern struct list_head super_blocks; extern spinlock_t sb_lock; diff --git a/include/linux/mount.h b/include/linux/mount.h index 61554dda78a8..42e2c9460088 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -29,8 +29,11 @@ struct vfsmount struct list_head mnt_child; /* and going through their mnt_child */ atomic_t mnt_count; int mnt_flags; + int mnt_expiry_mark; /* true if marked for expiry */ char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; + struct list_head mnt_fslink; /* link in fs-specific expiry list */ + struct namespace *mnt_namespace; /* containing namespace */ }; static inline struct vfsmount *mntget(struct vfsmount *mnt) @@ -42,7 +45,7 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt) extern void __mntput(struct vfsmount *mnt); -static inline void mntput(struct vfsmount *mnt) +static inline void _mntput(struct vfsmount *mnt) { if (mnt) { if (atomic_dec_and_test(&mnt->mnt_count)) @@ -50,10 +53,26 @@ static inline void mntput(struct vfsmount *mnt) } } +static inline void mntput(struct vfsmount *mnt) +{ + if (mnt) { + mnt->mnt_expiry_mark = 0; + _mntput(mnt); + } +} + extern void free_vfsmnt(struct vfsmount *mnt); extern struct vfsmount *alloc_vfsmnt(const char *name); extern struct vfsmount *do_kern_mount(const char *fstype, int flags, const char *name, void *data); + +struct nameidata; + +extern int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, + int mnt_flags, struct list_head *fslist); + +extern void mark_mounts_for_expiry(struct list_head *mounts); + extern spinlock_t vfsmount_lock; #endif diff --git a/include/linux/namei.h b/include/linux/namei.h index adcafdec8ee7..1bbfa296e11f 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -61,6 +61,7 @@ extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); extern int FASTCALL(path_walk(const char *, struct nameidata *)); extern int FASTCALL(link_path_walk(const char *, struct nameidata *)); extern void path_release(struct nameidata *); +extern void path_release_on_umount(struct nameidata *); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); extern struct dentry * lookup_hash(struct qstr *, struct dentry *); diff --git a/include/linux/namespace.h b/include/linux/namespace.h index fdd8abb07386..9eca1558d72f 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -14,7 +14,7 @@ struct namespace { extern void umount_tree(struct vfsmount *); extern int copy_namespace(int, struct task_struct *); -void __put_namespace(struct namespace *namespace); +extern void __put_namespace(struct namespace *namespace); static inline void put_namespace(struct namespace *namespace) { -- cgit v1.2.3 From 49a83003403debd48b1ebd3cae29a1f417ee469f Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Sat, 10 Jul 2004 19:30:45 -0700 Subject: [PATCH] Use llseek instead of f_pos= for directory seeking nfsd currently just sets f_pos when seeking in a directory. This bypasses any checking and other handling that a filesystem might want to do. So instead, we define "vfs_llseek" to be an exported "llseek", and use that, both to seek at the start, and the find the new position at the end. Thanks to "Derrick Schommer" "Trond Myklebust" Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/vfs.c | 10 ++++++---- fs/read_write.c | 10 ++++------ include/linux/fs.h | 2 ++ 3 files changed, 12 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 3c57bc31f521..f7ac90d15961 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1477,10 +1477,12 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file); if (err) goto out; - if (offset > ~(u32) 0) - goto out_close; - file.f_pos = offset; + offset = vfs_llseek(&file, offset, 0); + if (offset < 0) { + err = nfserrno((int)offset); + goto out_close; + } /* * Read the directory entries. This silly loop is necessary because @@ -1496,7 +1498,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, err = nfserrno(err); else err = cdp->err; - *offsetp = file.f_pos; + *offsetp = vfs_llseek(&file, 0, 1); if (err == nfserr_eof || err == nfserr_toosmall) err = nfs_ok; /* can still be found in ->err */ diff --git a/fs/read_write.c b/fs/read_write.c index f765a22b49cb..481332642515 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -76,14 +76,12 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin) unlock_kernel(); return retval; } - EXPORT_SYMBOL(remote_llseek); loff_t no_llseek(struct file *file, loff_t offset, int origin) { return -ESPIPE; } - EXPORT_SYMBOL(no_llseek); loff_t default_llseek(struct file *file, loff_t offset, int origin) @@ -109,10 +107,9 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin) unlock_kernel(); return retval; } - EXPORT_SYMBOL(default_llseek); -static inline loff_t llseek(struct file *file, loff_t offset, int origin) +loff_t vfs_llseek(struct file *file, loff_t offset, int origin) { loff_t (*fn)(struct file *, loff_t, int); @@ -121,6 +118,7 @@ static inline loff_t llseek(struct file *file, loff_t offset, int origin) fn = file->f_op->llseek; return fn(file, offset, origin); } +EXPORT_SYMBOL(vfs_llseek); asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) { @@ -135,7 +133,7 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) retval = -EINVAL; if (origin <= 2) { - loff_t res = llseek(file, offset, origin); + loff_t res = vfs_llseek(file, offset, origin); retval = res; if (res != (loff_t)retval) retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ @@ -165,7 +163,7 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, if (origin > 2) goto out_putf; - offset = llseek(file, ((loff_t) offset_high << 32) | offset_low, + offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low, origin); retval = (int)offset; diff --git a/include/linux/fs.h b/include/linux/fs.h index e847ef6d20fb..3d24beb4ac36 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1341,6 +1341,8 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *); /* needed for stackable file system support */ extern loff_t default_llseek(struct file *file, loff_t offset, int origin); +extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin); + extern void inode_init_once(struct inode *); extern void iput(struct inode *); extern struct inode * igrab(struct inode *); -- cgit v1.2.3 From c0f0c1663a475e933fc90a4a563be135bbfd7015 Mon Sep 17 00:00:00 2001 From: Mika Kukkonen Date: Sat, 10 Jul 2004 19:34:19 -0700 Subject: [PATCH] Fix misplaced 'inline' in include/linux/iso_fs.h CC [M] fs/isofs/namei.o In file included from fs/isofs/namei.c:10: include/linux/iso_fs.h:280: warning: `inline' is not at beginning of declaration Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/iso_fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h index 23cdbf83cb16..dd53b6cd2173 100644 --- a/include/linux/iso_fs.h +++ b/include/linux/iso_fs.h @@ -277,7 +277,7 @@ static inline unsigned long isofs_get_ino(unsigned long block, * and "offset" will hold normalized values. Only directories are * affected making it safe to call even for non-directory file * types. */ -static void inline +static inline void isofs_normalize_block_and_offset(struct iso_directory_record* de, unsigned long *block, unsigned long *offset) -- cgit v1.2.3 From 3664d16904b5928d282074ac9b70b16fab534a14 Mon Sep 17 00:00:00 2001 From: Andrey Panin Date: Sat, 10 Jul 2004 19:35:39 -0700 Subject: [PATCH] fix CRC16 misnaming As pointed by Thomas Sailer, crc16.c module contains CRC16-CCITT (x^16 + x^12 + x^5 + 1) implementation, not IBM CRC16 (x^16 + x^15 + x^2 + 1) one. Looks like we need to rename it accordingly and this patchset does exactly this. Signed-off-by: Andrey Panin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/crc-ccitt.h | 15 +++++++++++ include/linux/crc16.h | 15 ----------- lib/Kconfig | 10 +++---- lib/Makefile | 2 +- lib/crc-ccitt.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ lib/crc16.c | 69 ----------------------------------------------- 6 files changed, 90 insertions(+), 90 deletions(-) create mode 100644 include/linux/crc-ccitt.h delete mode 100644 include/linux/crc16.h create mode 100644 lib/crc-ccitt.c delete mode 100644 lib/crc16.c (limited to 'include/linux') diff --git a/include/linux/crc-ccitt.h b/include/linux/crc-ccitt.h new file mode 100644 index 000000000000..f52696a1ff0d --- /dev/null +++ b/include/linux/crc-ccitt.h @@ -0,0 +1,15 @@ +#ifndef _LINUX_CRC_CCITT_H +#define _LINUX_CRC_CCITT_H + +#include + +extern u16 const crc_ccitt_table[256]; + +extern u16 crc_ccitt(u16 crc, const u8 *buffer, size_t len); + +static inline u16 crc_ccitt_byte(u16 crc, const u8 c) +{ + return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff]; +} + +#endif /* _LINUX_CRC_CCITT_H */ diff --git a/include/linux/crc16.h b/include/linux/crc16.h deleted file mode 100644 index a077021e1c38..000000000000 --- a/include/linux/crc16.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _LINUX_CRC16_H -#define _LINUX_CRC16_H - -#include - -extern u16 const crc16_table[256]; - -extern u16 crc16(u16 crc, const u8 *buffer, size_t len); - -static inline u16 crc16_byte(u16 crc, const u8 c) -{ - return (crc >> 8) ^ crc16_table[(crc ^ c) & 0xff]; -} - -#endif /* _LINUX_CRC16_H */ diff --git a/lib/Kconfig b/lib/Kconfig index e7ab540544f2..2f25b0cfa9ae 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -4,13 +4,13 @@ menu "Library routines" -config CRC16 - tristate "CRC16 functions" +config CRC_CCITT + tristate "CRC-CCITT functions" help This option is provided for the case where no in-kernel-tree - modules require CRC16 functions, but a module built outside the - kernel tree does. Such modules that use library CRC16 functions - require M here. + modules require CRC-CCITT functions, but a module built outside + the kernel tree does. Such modules that use library CRC-CCITT + functions require M here. config CRC32 tristate "CRC32 functions" diff --git a/lib/Makefile b/lib/Makefile index 2c776e38e4fc..295e70bcd223 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -18,7 +18,7 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y) lib-y += dec_and_lock.o endif -obj-$(CONFIG_CRC16) += crc16.o +obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o obj-$(CONFIG_CRC32) += crc32.o obj-$(CONFIG_LIBCRC32C) += libcrc32c.o diff --git a/lib/crc-ccitt.c b/lib/crc-ccitt.c new file mode 100644 index 000000000000..115d149af407 --- /dev/null +++ b/lib/crc-ccitt.c @@ -0,0 +1,69 @@ +/* + * linux/lib/crc-ccitt.c + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include + +/* + * This mysterious table is just the CRC of each possible byte. It can be + * computed using the standard bit-at-a-time methods. The polynomial can + * be seen in entry 128, 0x8408. This corresponds to x^0 + x^5 + x^12. + * Add the implicit x^16, and you have the standard CRC-CCITT. + */ +u16 const crc_ccitt_table[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; +EXPORT_SYMBOL(crc_ccitt_table); + +/** + * crc_ccitt - recompute the CRC for the data buffer + * @crc - previous CRC value + * @buffer - data pointer + * @len - number of bytes in the buffer + */ +u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len) +{ + while (len--) + crc = crc_ccitt_byte(crc, *buffer++); + return crc; +} +EXPORT_SYMBOL(crc_ccitt); + +MODULE_DESCRIPTION("CRC-CCITT calculations"); +MODULE_LICENSE("GPL"); diff --git a/lib/crc16.c b/lib/crc16.c deleted file mode 100644 index b3dfc9db2250..000000000000 --- a/lib/crc16.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * linux/lib/crc16.c - * - * This source code is licensed under the GNU General Public License, - * Version 2. See the file COPYING for more details. - */ - -#include -#include -#include - -/* - * This mysterious table is just the CRC of each possible byte. It can be - * computed using the standard bit-at-a-time methods. The polynomial can - * be seen in entry 128, 0x8408. This corresponds to x^0 + x^5 + x^12. - * Add the implicit x^16, and you have the standard CRC-CCITT. - */ -u16 const crc16_table[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; -EXPORT_SYMBOL(crc16_table); - -/** - * crc16 - recompute the CRC for the data buffer - * @crc - previous CRC value - * @buffer - data pointer - * @len - number of bytes in the buffer - */ -u16 crc16(u16 crc, u8 const *buffer, size_t len) -{ - while (len--) - crc = crc16_byte(crc, *buffer++); - return crc; -} -EXPORT_SYMBOL(crc16); - -MODULE_DESCRIPTION("CRC16 calculations"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From edd57a7600f9cc7b2f2b45bee76ec7c806f89ff3 Mon Sep 17 00:00:00 2001 From: Andrey Panin Date: Sat, 10 Jul 2004 19:36:35 -0700 Subject: [PATCH] CRC16 renaming in PPP driver Signed-off-by: Andrey Panin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/ppp_async.c | 2 +- include/linux/ppp_defs.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 1ddefbd2ee6c..8e139278de0e 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/ppp_defs.h b/include/linux/ppp_defs.h index 58c71466a726..402056cd049d 100644 --- a/include/linux/ppp_defs.h +++ b/include/linux/ppp_defs.h @@ -42,7 +42,7 @@ #ifndef _PPP_DEFS_H_ #define _PPP_DEFS_H_ -#include +#include /* * The basic PPP frame. @@ -97,7 +97,7 @@ #define PPP_INITFCS 0xffff /* Initial FCS value */ #define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ -#define PPP_FCS(fcs, c) crc16_byte(fcs, c) +#define PPP_FCS(fcs, c) crc_ccitt_byte(fcs, c) /* * Extended asyncmap - allows any character to be escaped. -- cgit v1.2.3 From b706f5fa59601f27026ddf88c02dad675551ac87 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Sat, 10 Jul 2004 20:08:26 -0700 Subject: [PATCH] sparse: removal of iovec use in mtd mtd, jffs and jffs2 switched from iovec to kvec --- drivers/mtd/chips/cfi_cmdset_0020.c | 4 ++-- drivers/mtd/mtdcore.c | 4 ++-- drivers/mtd/mtdpart.c | 8 ++++---- drivers/mtd/nand/nand.c | 14 +++++++------- fs/jffs/intrep.c | 4 ++-- fs/jffs2/os-linux.h | 5 +++-- fs/jffs2/wbuf.c | 8 ++++---- fs/jffs2/write.c | 4 ++-- fs/jffs2/writev.c | 4 ++-- include/linux/mtd/mtd.h | 19 ++++++++++++------- 10 files changed, 40 insertions(+), 34 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 074f6905991d..f1fd12188162 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -38,7 +38,7 @@ static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_staa_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -static int cfi_staa_writev(struct mtd_info *mtd, const struct iovec *vecs, +static int cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); static int cfi_staa_erase_varsize(struct mtd_info *, struct erase_info *); static void cfi_staa_sync (struct mtd_info *); @@ -700,7 +700,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to, #define ECCBUF_DIV(x) ((x) & ~(ECCBUF_SIZE - 1)) #define ECCBUF_MOD(x) ((x) & (ECCBUF_SIZE - 1)) static int -cfi_staa_writev(struct mtd_info *mtd, const struct iovec *vecs, +cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { unsigned long i; diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 054648e3bacc..910246f41ad4 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -232,7 +232,7 @@ void put_mtd_device(struct mtd_info *mtd) * dont implement their own */ -int default_mtd_writev(struct mtd_info *mtd, const struct iovec *vecs, +int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { unsigned long i; @@ -262,7 +262,7 @@ int default_mtd_writev(struct mtd_info *mtd, const struct iovec *vecs, * implement their own */ -int default_mtd_readv(struct mtd_info *mtd, struct iovec *vecs, +int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen) { unsigned long i; diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 460d56f70bec..e90064e85928 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -182,7 +182,7 @@ static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t l len, retlen, buf); } -static int part_writev (struct mtd_info *mtd, const struct iovec *vecs, +static int part_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { struct mtd_part *part = PART(mtd); @@ -197,7 +197,7 @@ static int part_writev (struct mtd_info *mtd, const struct iovec *vecs, NULL, &mtd->oobinfo); } -static int part_readv (struct mtd_info *mtd, struct iovec *vecs, +static int part_readv (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen) { struct mtd_part *part = PART(mtd); @@ -210,7 +210,7 @@ static int part_readv (struct mtd_info *mtd, struct iovec *vecs, NULL, &mtd->oobinfo); } -static int part_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, +static int part_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) { @@ -224,7 +224,7 @@ static int part_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, eccbuf, oobsel); } -static int part_readv_ecc (struct mtd_info *mtd, struct iovec *vecs, +static int part_readv_ecc (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) { diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c index e9919425b322..6e3570a24ab0 100644 --- a/drivers/mtd/nand/nand.c +++ b/drivers/mtd/nand/nand.c @@ -168,9 +168,9 @@ static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * ret static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf); -static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs, +static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t * retlen); -static int nand_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, +static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); static int nand_erase (struct mtd_info *mtd, struct erase_info *instr); static void nand_sync (struct mtd_info *mtd); @@ -961,15 +961,15 @@ out: /* - * NAND write with iovec + * NAND write with kvec */ -static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, +static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t * retlen) { return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, 0)); } -static int nand_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, +static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) { int i, page, len, total_len, ret = 0, written = 0; @@ -1016,7 +1016,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, unsi goto out; } - /* Loop until all iovecs' data has been written */ + /* Loop until all kvec' data has been written */ len = 0; while (count) { /* @@ -1025,7 +1025,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct iovec *vecs, unsi * else we have to copy into data_buf. */ if ((vecs->iov_len - len) >= mtd->oobblock) { - this->data_poi = (u_char *) vecs->iov_base; + this->data_poi = vecs->iov_base; this->data_poi += len; len += mtd->oobblock; /* Check, if we have to switch to the next tuple */ diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index 816f07676539..24558ea6fbd7 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c @@ -209,7 +209,7 @@ flash_safe_write(struct mtd_info *mtd, loff_t to, static int -flash_safe_writev(struct mtd_info *mtd, const struct iovec *vecs, +flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long iovec_cnt, loff_t to) { size_t retlen, retlen_a; @@ -1740,7 +1740,7 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node, { struct jffs_fmcontrol *fmc = c->fmc; struct jffs_fm *fm; - struct iovec node_iovec[4]; + struct kvec node_iovec[4]; unsigned long iovec_cnt; __u32 pos; diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 91401c1c9dca..11f3a5a35dfe 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -132,8 +132,9 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_wbuf_dirty(c) (!!(c)->wbuf_len) struct kstatfs; +struct kvec; /* wbuf.c */ -int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino); +int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino); int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf); int jffs2_check_oob_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,int mode); @@ -185,7 +186,7 @@ int jffs2_remount_fs (struct super_block *, int *, char *); int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); /* writev.c */ -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, +int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); /* super.c */ diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index ecfb155cb82b..956f98d8dd35 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -544,9 +544,9 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) #define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) #define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) -int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) +int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) { - struct iovec outvecs[3]; + struct kvec outvecs[3]; uint32_t totlen = 0; uint32_t split_ofs = 0; uint32_t old_totlen; @@ -751,11 +751,11 @@ alldone: /* * This is the entry for flash write. - * Check, if we work on NAND FLASH, if so build an iovec and write it via vritev + * Check, if we work on NAND FLASH, if so build an kvec and write it via vritev */ int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf) { - struct iovec vecs[1]; + struct kvec vecs[1]; if (jffs2_can_mark_obsolete(c)) return c->mtd->write(c->mtd, ofs, len, retlen, buf); diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index f28d9d5bcd36..11c761045215 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -92,7 +92,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 struct jffs2_raw_node_ref *raw; struct jffs2_full_dnode *fn; size_t retlen; - struct iovec vecs[2]; + struct kvec vecs[2]; int ret; int retried = 0; unsigned long cnt = 2; @@ -233,7 +233,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; size_t retlen; - struct iovec vecs[2]; + struct kvec vecs[2]; int retried = 0; int ret; diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index 80cd3820373f..c88bf7336e50 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -18,7 +18,7 @@ /* This ought to be in core MTD code. All registered MTD devices without writev should have this put in place. Bug the MTD maintainer */ -static inline int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs, +static inline int mtd_fake_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { unsigned long i; @@ -39,7 +39,7 @@ static inline int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs return ret; } -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, +int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { if (c->mtd->writev) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index d186585b73a4..7718658e8e1b 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -12,6 +12,11 @@ #include #include +struct kvec { + void *iov_base; /* and that should *never* hold a userland pointer */ + size_t iov_len; +}; + #endif /* __KERNEL__ */ struct erase_info_user { @@ -200,16 +205,16 @@ struct mtd_info { /* This function is not yet implemented */ int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - /* iovec-based read/write methods. We need these especially for NAND flash, + /* kvec-based read/write methods. We need these especially for NAND flash, with its limited number of write cycles per erase. NB: The 'count' parameter is the number of _vectors_, each of which contains an (ofs, len) tuple. */ - int (*readv) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, size_t *retlen); - int (*readv_ecc) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, + int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen); + int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); - int (*writev) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen); - int (*writev_ecc) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, + int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); + int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); /* Sync */ @@ -250,10 +255,10 @@ struct mtd_notifier { extern void register_mtd_user (struct mtd_notifier *new); extern int unregister_mtd_user (struct mtd_notifier *old); -int default_mtd_writev(struct mtd_info *mtd, const struct iovec *vecs, +int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); -int default_mtd_readv(struct mtd_info *mtd, struct iovec *vecs, +int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen); #define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args) -- cgit v1.2.3