read-only bind mount prep work
Subsystems (27)
cover read-only bind mount prep work
The following patches lay some of the groundwork for the read-only bind mounts. Christoph Hellwig suggested that I send them in separately. This was a good suggestion, as the bulk of the modifications of the entire set happen in here, and these should make no functional changes, and should be pretty easy to merge.
-- Dave
PATCH 2/6 r/o bind mount prepwork: move open_namei()'s vfs_create()
The code around vfs_create() in open_namei() is getting a bit too complex. Right now, there is at least the reference count on the dentry, and the i_mutex to worry about. Soon, we'll also have mnt_writecount.
So, break the vfs_create() call out of open_namei(), and into a helper function. This duplicates the call to may_open(), but that isn't such a bad thing since the arguments (acc_mode and flag) were being heavily massaged anyway.
---
lxc-dave/fs/namei.c | 30 ++++++++++++++++++++---------- 1 files changed, 20 insertions(+), 10 deletions(-)
fs/namei.c renamed from fs/namei.c~B2-prepwork-cleanup-open_namei +20 -10
@@ -1587,6 +1587,24 @@ int may_open(struct nameidata *nd, int areturn 0 ; } +static int open_namei_create (struct nameidata *nd,struct path *path, +int flag,int mode) +{ +int error; +struct dentry *dir = nd->dentry; + +if (!IS_POSIXACL (dir->d_inode)) + mode &= ~current->fs->umask; + error =vfs_create (dir->d_inode, path->dentry, mode, nd); +mutex_unlock (&dir->d_inode->i_mutex); +dput (nd->dentry); + nd->dentry = path->dentry; +if (error) +return error; +/* Don't check for write permission, don't truncate */ +return may_open (nd,0 , flag & ~O_TRUNC ); +} +/* * open_namei() *
@@ -1668,18 +1686,10 @@ do_last:/* Negative dentry, just create the file */ if (!path.dentry->d_inode) { -if (!IS_POSIXACL (dir->d_inode)) - mode &= ~current->fs->umask; - error =vfs_create (dir->d_inode, path.dentry, mode, nd); -mutex_unlock (&dir->d_inode->i_mutex); -dput (nd->dentry); - nd->dentry = path.dentry; + error =open_namei_create (nd, &path, flag, mode);if (error) goto exit; -/* Don't check for write permission, don't truncate */ - acc_mode =0 ; - flag &= ~O_TRUNC ; - goto ok; +return 0 ; }/*
_
PATCH 4/6 r/o bind mount prepwork: inc_nlink() helper
In reply to Dave HansenThis is mostly included for parity with dec_nlink(), where we will have some more hooks. This one should stay pretty darn straightforward for now.
---
lxc-dave/drivers/infiniband/hw/ipath/ipath_fs.c | 4 ++-- lxc-dave/drivers/usb/core/inode.c | 4 ++-- lxc-dave/fs/9p/vfs_inode.c | 2 +- lxc-dave/fs/autofs/root.c | 2 +- lxc-dave/fs/autofs4/root.c | 2 +- lxc-dave/fs/bfs/dir.c | 2 +- lxc-dave/fs/cifs/inode.c | 2 +- lxc-dave/fs/coda/dir.c | 2 +- lxc-dave/fs/configfs/dir.c | 4 ++-- lxc-dave/fs/configfs/mount.c | 2 +- lxc-dave/fs/debugfs/inode.c | 4 ++-- lxc-dave/fs/ext3/namei.c | 6 +++--- lxc-dave/fs/fuse/control.c | 2 +- lxc-dave/fs/hfsplus/dir.c | 2 +- lxc-dave/fs/hpfs/namei.c | 4 ++-- lxc-dave/fs/hugetlbfs/inode.c | 4 ++-- lxc-dave/fs/jffs2/dir.c | 6 +++--- lxc-dave/fs/jffs2/fs.c | 6 +++--- lxc-dave/fs/jfs/namei.c | 6 +++--- lxc-dave/fs/libfs.c | 4 ++-- lxc-dave/fs/msdos/namei.c | 4 ++-- lxc-dave/fs/ocfs2/dlm/dlmfs.c | 6 +++--- lxc-dave/fs/ocfs2/namei.c | 8 ++++---- lxc-dave/fs/ramfs/inode.c | 4 ++-- lxc-dave/fs/reiserfs/namei.c | 6 +++--- lxc-dave/fs/sysfs/dir.c | 4 ++-- lxc-dave/fs/sysfs/mount.c | 2 +- lxc-dave/fs/udf/inode.c | 2 +- lxc-dave/fs/udf/namei.c | 6 +++--- lxc-dave/fs/vfat/namei.c | 4 ++-- lxc-dave/include/linux/fs.h | 7 ++++++- lxc-dave/ipc/mqueue.c | 2 +- lxc-dave/kernel/cpuset.c | 8 ++++---- lxc-dave/mm/shmem.c | 8 ++++---- lxc-dave/net/sunrpc/rpc_pipe.c | 6 +++--- lxc-dave/security/inode.c | 4 ++-- lxc-dave/security/selinux/selinuxfs.c | 4 ++-- 37 files changed, 80 insertions(+), 75 deletions(-)
include/linux/fs.h renamed from include/linux/fs.h~B4-monitor_inc_nlink +6 -1
@@ -1256,9 +1256,14 @@ static inline void mark_inode_dirty_sync__mark_inode_dirty (inode,I_DIRTY_SYNC ); } -static inline void inode_inc_link_count (struct inode *inode) +static inline void inc_nlink (struct inode *inode) { inode->i_nlink++; +} + +static inline void inode_inc_link_count (struct inode *inode) +{ +inc_nlink (inode);mark_inode_dirty (inode); }
fs/libfs.c renamed from fs/libfs.c~B4-monitor_inc_nlink +2 -2
@@ -243,7 +243,7 @@ int simple_link(struct dentry *old_dentrstruct inode *inode = old_dentry->d_inode; inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME ; - inode->i_nlink++; +inc_nlink (inode);atomic_inc (&inode->i_count);dget (dentry);d_instantiate (dentry, inode);
@@ -306,7 +306,7 @@ int simple_rename(struct inode *old_dir,drop_nlink (old_dir); }else if (they_are_dirs) {drop_nlink (old_dir); - new_dir->i_nlink++; +inc_nlink (new_dir); } old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
mm/shmem.c renamed from mm/shmem.c~B4-monitor_inc_nlink +4 -4
@@ -1371,7 +1371,7 @@ shmem_get_inode(struct super_block *sb, &sbinfo->policy_nodes);break ;case S_IFDIR : - inode->i_nlink++; +inc_nlink (inode);/* Some things misbehave if size == 0 on a directory */ inode->i_size =2 *BOGO_DIRENT_SIZE ; inode->i_op = &shmem_dir_inode_operations;
@@ -1703,7 +1703,7 @@ static int shmem_mkdir(struct inode *dirif ((error =shmem_mknod (dir, dentry, mode |S_IFDIR ,0 )))return error; - dir->i_nlink++; +inc_nlink (dir);return 0 ; }
@@ -1738,7 +1738,7 @@ static int shmem_link(struct dentry *old dir->i_size +=BOGO_DIRENT_SIZE ; inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME ; - inode->i_nlink++; +inc_nlink (inode);atomic_inc (&inode->i_count);/* New dentry reference */ dget (dentry);/* Extra pinning count for the created dentry */ d_instantiate (dentry, inode);
@@ -1795,7 +1795,7 @@ static int shmem_rename(struct inode *oldrop_nlink (old_dir); }else if (they_are_dirs) {drop_nlink (old_dir); - new_dir->i_nlink++; +inc_nlink (new_dir); } old_dir->i_size -=BOGO_DIRENT_SIZE ;
drivers/infiniband/hw/ipath/ipath_fs.c renamed from drivers/infiniband/hw/ipath/ipath_fs.c~B4-monitor_inc_nlink +2 -2
@@ -66,8 +66,8 @@ static int ipathfs_mknod(struct inode *d inode->i_private = data;if ((mode &S_IFMT ) ==S_IFDIR ) { inode->i_op = &simple_dir_inode_operations; - inode->i_nlink++; - dir->i_nlink++; +inc_nlink (inode); +inc_nlink (dir); } inode->i_fop = fops;
drivers/usb/core/inode.c renamed from drivers/usb/core/inode.c~B4-monitor_inc_nlink +2 -2
@@ -263,7 +263,7 @@ static struct inode *usbfs_get_inode (st inode->i_fop = &simple_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode);break ; } }
@@ -295,7 +295,7 @@ static int usbfs_mkdir (struct inode *di mode = (mode & (S_IRWXUGO |S_ISVTX )) |S_IFDIR ; res =usbfs_mknod (dir, dentry, mode,0 );if (!res) - dir->i_nlink++; +inc_nlink (dir);return res; }
fs/9p/vfs_inode.c renamed from fs/9p/vfs_inode.c~B4-monitor_inc_nlink +1 -1
@@ -233,7 +233,7 @@ struct inode *v9fs_get_inode(struct supe inode->i_op = &v9fs_symlink_inode_operations;break ;case S_IFDIR : - inode->i_nlink++; +inc_nlink (inode);if (v9ses->extended) inode->i_op = &v9fs_dir_inode_operations_ext;else
fs/autofs/root.c renamed from fs/autofs/root.c~B4-monitor_inc_nlink +1 -1
@@ -466,7 +466,7 @@ static int autofs_root_mkdir(struct inod ent->dentry = dentry;autofs_hash_insert (dh,ent); - dir->i_nlink++; +inc_nlink (dir);d_instantiate (dentry,iget (dir->i_sb,ino));unlock_kernel ();
fs/autofs4/root.c renamed from fs/autofs4/root.c~B4-monitor_inc_nlink +1 -1
@@ -713,7 +713,7 @@ static int autofs4_dir_mkdir(struct inodif (p_ino && dentry->d_parent != dentry)atomic_inc (&p_ino->count); ino->inode = inode; - dir->i_nlink++; +inc_nlink (dir); dir->i_mtime =CURRENT_TIME ;return 0 ;
fs/bfs/dir.c renamed from fs/bfs/dir.c~B4-monitor_inc_nlink +1 -1
@@ -163,7 +163,7 @@ static int bfs_link(struct dentry * old,unlock_kernel ();return err; } - inode->i_nlink++; +inc_nlink (inode); inode->i_ctime =CURRENT_TIME_SEC ;mark_inode_dirty (inode);atomic_inc (&inode->i_count);
fs/cifs/inode.c renamed from fs/cifs/inode.c~B4-monitor_inc_nlink +1 -1
@@ -736,7 +736,7 @@ int cifs_mkdir(struct inode *inode, strucFYI (1 , ("cifs_mkdir returned 0x%x" , rc));d_drop (direntry); }else { - inode->i_nlink++; +inc_nlink (inode);if (pTcon->ses->capabilities &CAP_UNIX ) rc =cifs_get_inode_info_unix (&newinode, full_path, inode->i_sb,xid);
fs/coda/dir.c renamed from fs/coda/dir.c~B4-monitor_inc_nlink +1 -1
@@ -304,7 +304,7 @@ static int coda_link(struct dentry *sourcoda_dir_changed (dir_inode,0 );atomic_inc (&inode->i_count);d_instantiate (de, inode); - inode->i_nlink++; +inc_nlink (inode); out:unlock_kernel ();
fs/configfs/dir.c renamed from fs/configfs/dir.c~B4-monitor_inc_nlink +2 -2
@@ -113,7 +113,7 @@ static int init_dir(struct inode * inode inode->i_fop = &configfs_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode);return 0 ; }
@@ -141,7 +141,7 @@ static int create_dir(struct config_itemif (!error) { error =configfs_create (d, mode, init_dir);if (!error) { - p->d_inode->i_nlink++; +inc_nlink (p->d_inode); (d)->d_op = &configfs_dentry_ops; }else {struct configfs_dirent *sd = d->d_fsdata;
fs/configfs/mount.c renamed from fs/configfs/mount.c~B4-monitor_inc_nlink +1 -1
@@ -84,7 +84,7 @@ static int configfs_fill_super(struct su inode->i_op = &configfs_dir_inode_operations; inode->i_fop = &configfs_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode); }else {pr_debug ("configfs: could not get root inode\n" );return -ENOMEM ;
fs/debugfs/inode.c renamed from fs/debugfs/inode.c~B4-monitor_inc_nlink +2 -2
@@ -54,7 +54,7 @@ static struct inode *debugfs_get_inode(s inode->i_fop = &simple_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode);break ; } }
@@ -87,7 +87,7 @@ static int debugfs_mkdir(struct inode *d mode = (mode & (S_IRWXUGO |S_ISVTX )) |S_IFDIR ; res =debugfs_mknod (dir, dentry, mode,0 );if (!res) - dir->i_nlink++; +inc_nlink (dir);return res; }
fs/ext3/namei.c renamed from fs/ext3/namei.c~B4-monitor_inc_nlink +3 -3
@@ -1616,7 +1616,7 @@ static int ext3_delete_entry (handle_t **/ static inline void ext3_inc_count (handle_t *handle,struct inode *inode) { - inode->i_nlink++; +inc_nlink (inode); }static inline void ext3_dec_count (handle_t *handle,struct inode *inode)
@@ -1775,7 +1775,7 @@ retry:iput (inode); goto out_stop; } - dir->i_nlink++; +inc_nlink (dir);ext3_update_dx_flag (dir);ext3_mark_inode_dirty (handle, dir);d_instantiate (dentry, inode);
@@ -2341,7 +2341,7 @@ static int ext3_rename (struct inode * oif (new_inode) {drop_nlink (new_inode); }else { - new_dir->i_nlink++; +inc_nlink (new_dir);ext3_update_dx_flag (new_dir);ext3_mark_inode_dirty (handle, new_dir); }
fs/fuse/control.c renamed from fs/fuse/control.c~B4-monitor_inc_nlink +1 -1
@@ -116,7 +116,7 @@ int fuse_ctl_add_conn(struct fuse_conn *return 0 ; parent = fuse_control_sb->s_root; - parent->d_inode->i_nlink++; +inc_nlink (parent->d_inode);sprintf (name,"%llu" , (unsigned long long ) fc->id); parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2, &simple_dir_inode_operations,
fs/hfsplus/dir.c renamed from fs/hfsplus/dir.c~B4-monitor_inc_nlink +1 -1
@@ -298,7 +298,7 @@ static int hfsplus_link(struct dentry *sif (res)return res; - inode->i_nlink++; +inc_nlink (inode);hfsplus_instantiate (dst_dentry, inode, cnid);atomic_inc (&inode->i_count); inode->i_ctime =CURRENT_TIME_SEC ;
fs/hpfs/namei.c renamed from fs/hpfs/namei.c~B4-monitor_inc_nlink +2 -2
@@ -89,7 +89,7 @@ static int hpfs_mkdir(struct inode *dir,brelse (bh);hpfs_mark_4buffers_dirty (&qbh0);hpfs_brelse4 (&qbh0); - dir->i_nlink++; +inc_nlink (dir);insert_inode_hash (result); if (result->i_uid != current->fsuid ||
@@ -635,7 +635,7 @@ static int hpfs_rename(struct inode *old end:hpfs_i (i)->i_parent_dir = new_dir->i_ino;if (S_ISDIR (i->i_mode)) { - new_dir->i_nlink++; +inc_nlink (new_dir);drop_nlink (old_dir); }if ((fnode =hpfs_map_fnode (i->i_sb, i->i_ino, &bh))) {
fs/hugetlbfs/inode.c renamed from fs/hugetlbfs/inode.c~B4-monitor_inc_nlink +2 -2
@@ -377,7 +377,7 @@ static struct inode *hugetlbfs_get_inode inode->i_fop = &simple_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode);break ;case S_IFLNK : inode->i_op = &page_symlink_inode_operations;
@@ -418,7 +418,7 @@ static int hugetlbfs_mkdir(struct inode {int retval =hugetlbfs_mknod (dir, dentry, mode |S_IFDIR ,0 );if (!retval) - dir->i_nlink++; +inc_nlink (dir);return retval; }
fs/jffs2/dir.c renamed from fs/jffs2/dir.c~B4-monitor_inc_nlink +3 -3
@@ -588,7 +588,7 @@ static int jffs2_mkdir (struct inode *di } dir_i->i_mtime = dir_i->i_ctime =ITIME (je32_to_cpu (rd->mctime)); - dir_i->i_nlink++; +inc_nlink (dir_i);jffs2_free_raw_dirent (rd);
@@ -836,7 +836,7 @@ static int jffs2_rename (struct inode *o/* If it was a directory we moved, and there was no victim, increase i_nlink on its new parent */ if (S_ISDIR (old_dentry->d_inode->i_mode) && !victim_f) - new_dir_i->i_nlink++; +inc_nlink (new_dir_i);/* Unlink the original */ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
@@ -848,7 +848,7 @@ static int jffs2_rename (struct inode *o/* Oh shit. We really ought to make a single node which can do both atomically */ struct jffs2_inode_info *f =JFFS2_INODE_INFO (old_dentry->d_inode);down (&f->sem); - old_dentry->d_inode->i_nlink++; +inc_nlink (old_dentry->d_inode);if (f->inocache) f->inocache->nlink++;up (&f->sem);
fs/jffs2/fs.c renamed from fs/jffs2/fs.c~B4-monitor_inc_nlink +3 -3
@@ -277,13 +277,13 @@ void jffs2_read_inode (struct inode *inofor (fd=f->dents; fd; fd = fd->next) {if (fd->type ==DT_DIR && fd->ino) - inode->i_nlink++; +inc_nlink (inode); }/* and '..' */ - inode->i_nlink++; +inc_nlink (inode);/* Root dir gets i_nlink 3 for some reason */ if (inode->i_ino ==1 ) - inode->i_nlink++; +inc_nlink (inode); inode->i_op = &jffs2_dir_inode_operations; inode->i_fop = &jffs2_dir_operations;
fs/jfs/namei.c renamed from fs/jfs/namei.c~B4-monitor_inc_nlink +3 -3
@@ -292,7 +292,7 @@ static int jfs_mkdir(struct inode *dip,mark_inode_dirty (ip);/* update parent directory inode */ - dip->i_nlink++;/* for '..' from child directory */ +inc_nlink (dip);/* for '..' from child directory */ dip->i_ctime = dip->i_mtime =CURRENT_TIME ;mark_inode_dirty (dip);
@@ -822,7 +822,7 @@ static int jfs_link(struct dentry *old_d goto free_dname;/* update object inode */ - ip->i_nlink++;/* for new link */ +inc_nlink (ip);/* for new link */ ip->i_ctime =CURRENT_TIME ; dir->i_ctime = dir->i_mtime =CURRENT_TIME ;mark_inode_dirty (dir);
@@ -1206,7 +1206,7 @@ static int jfs_rename(struct inode *old_ goto out4; }if (S_ISDIR (old_ip->i_mode)) - new_dir->i_nlink++; +inc_nlink (new_dir); }/* * Remove old directory entry
fs/msdos/namei.c renamed from fs/msdos/namei.c~B4-monitor_inc_nlink +2 -2
@@ -385,7 +385,7 @@ static int msdos_mkdir(struct inode *dir err =msdos_add_entry (dir, msdos_name,1 , is_hid, cluster, &ts, &sinfo);if (err) goto out_free; - dir->i_nlink++; +inc_nlink (dir); inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos);brelse (sinfo.bh);
@@ -544,7 +544,7 @@ static int do_msdos_rename(struct inode }drop_nlink (old_dir);if (!new_inode) - new_dir->i_nlink++; +inc_nlink (new_dir); } err =fat_remove_entries (old_dir, &old_sinfo);/* and releases bh */
fs/ocfs2/dlm/dlmfs.c renamed from fs/ocfs2/dlm/dlmfs.c~B4-monitor_inc_nlink +3 -3
@@ -338,7 +338,7 @@ static struct inode *dlmfs_get_root_inod inode->i_blocks =0 ; inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ; - inode->i_nlink++; +inc_nlink (inode); inode->i_fop = &simple_dir_operations; inode->i_op = &dlmfs_root_inode_operations;
@@ -395,7 +395,7 @@ static struct inode *dlmfs_get_inode(str/* directory inodes start off with i_nlink == * 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode);break ; }
@@ -449,7 +449,7 @@ static int dlmfs_mkdir(struct inode * di } ip->ip_dlm = dlm; - dir->i_nlink++; +inc_nlink (dir);d_instantiate (dentry, inode);dget (dentry);/* Extra count - pin the dentry in core */
fs/ocfs2/namei.c renamed from fs/ocfs2/namei.c~B4-monitor_inc_nlink +4 -4
@@ -408,7 +408,7 @@ static int ocfs2_mknod(struct inode *dirmlog_errno (status); goto leave; } - dir->i_nlink++; +inc_nlink (dir); } status = ocfs2_add_entry(handle, dentry, inode,
@@ -702,7 +702,7 @@ static int ocfs2_link(struct dentry *old goto bail; } - inode->i_nlink++; +inc_nlink (inode); inode->i_ctime =CURRENT_TIME ; fe->i_links_count =cpu_to_le16 (inode->i_nlink); fe->i_ctime =cpu_to_le64 (inode->i_ctime.tv_sec);
@@ -902,7 +902,7 @@ static int ocfs2_unlink(struct inode *di parent_node_bh);if (status <0 ) {mlog_errno (status); - dir->i_nlink++; +inc_nlink (dir); } }
@@ -1344,7 +1344,7 @@ static int ocfs2_rename(struct inode *olif (new_inode) { new_inode->i_nlink--; }else { - new_dir->i_nlink++; +inc_nlink (new_dir);mark_inode_dirty (new_dir); } }
fs/ramfs/inode.c renamed from fs/ramfs/inode.c~B4-monitor_inc_nlink +2 -2
@@ -75,7 +75,7 @@ struct inode *ramfs_get_inode(struct sup inode->i_fop = &simple_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode);break ;case S_IFLNK : inode->i_op = &page_symlink_inode_operations;
@@ -113,7 +113,7 @@ static int ramfs_mkdir(struct inode * di {int retval =ramfs_mknod (dir, dentry, mode |S_IFDIR ,0 );if (!retval) - dir->i_nlink++; +inc_nlink (dir);return retval; }
fs/reiserfs/namei.c renamed from fs/reiserfs/namei.c~B4-monitor_inc_nlink +3 -3
@@ -19,7 +19,7 @@#include <linux/smp_lock.h> #include <linux/quotaops.h> -#define INC_DIR_INODE_NLINK (i) if (i->i_nlink != 1) { i->i_nlink++; if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; } +#define INC_DIR_INODE_NLINK (i) if (i->i_nlink != 1) { inc_nlink(i); if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; }#define DEC_DIR_INODE_NLINK (i) if (i->i_nlink != 1) drop_nlink(i);// directory item contains array of entry headers. This performs
@@ -1006,7 +1006,7 @@ static int reiserfs_unlink(struct inodereiserfs_cut_from_item (&th, &path, &(de.de_entry_key), dir,NULL ,0 );if (retval <0 ) { - inode->i_nlink++; +inc_nlink (inode); goto end_unlink; } inode->i_ctime =CURRENT_TIME_SEC ;
@@ -1143,7 +1143,7 @@ static int reiserfs_link(struct dentry * }/* inc before scheduling so reiserfs_unlink knows we are here */ - inode->i_nlink++; +inc_nlink (inode); retval =journal_begin (&th, dir->i_sb, jbegin_count);if (retval) {
fs/sysfs/dir.c renamed from fs/sysfs/dir.c~B4-monitor_inc_nlink +2 -2
@@ -103,7 +103,7 @@ static int init_dir(struct inode * inode inode->i_fop = &sysfs_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode);return 0 ; }
@@ -137,7 +137,7 @@ static int create_dir(struct kobject * kif (!error) { error =sysfs_create (*d, mode, init_dir);if (!error) { - p->d_inode->i_nlink++; +inc_nlink (p->d_inode); (*d)->d_op = &sysfs_dentry_ops;d_rehash (*d); }
fs/sysfs/mount.c renamed from fs/sysfs/mount.c~B4-monitor_inc_nlink +1 -1
@@ -49,7 +49,7 @@ static int sysfs_fill_super(struct super inode->i_op = &sysfs_dir_inode_operations; inode->i_fop = &sysfs_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode); }else {pr_debug ("sysfs: could not get root inode\n" );return -ENOMEM ;
fs/udf/inode.c renamed from fs/udf/inode.c~B4-monitor_inc_nlink +1 -1
@@ -1165,7 +1165,7 @@ static void udf_fill_inode(struct inode inode->i_op = &udf_dir_inode_operations; inode->i_fop = &udf_dir_operations; inode->i_mode |=S_IFDIR ; - inode->i_nlink ++; +inc_nlink (inode);break ; }case ICBTAG_FILE_TYPE_REALTIME :
fs/udf/namei.c renamed from fs/udf/namei.c~B4-monitor_inc_nlink +3 -3
@@ -762,7 +762,7 @@ static int udf_mkdir(struct inode * dir,cpu_to_le32 (UDF_I_UNIQUE (inode) &0x00000000FFFFFFFFUL ); cfi.fileCharacteristics |=FID_FILE_CHAR_DIRECTORY ;udf_write_fi (dir, &cfi, fi, &fibh,NULL ,NULL ); - dir->i_nlink++; +inc_nlink (dir);mark_inode_dirty (dir);d_instantiate (dentry, inode);if (fibh.sbh != fibh.ebh)
@@ -1147,7 +1147,7 @@ static int udf_link(struct dentry * old_if (fibh.sbh != fibh.ebh)udf_release_data (fibh.ebh);udf_release_data (fibh.sbh); - inode->i_nlink ++; +inc_nlink (inode); inode->i_ctime =current_fs_time (inode->i_sb);mark_inode_dirty (inode);atomic_inc (&inode->i_count);
@@ -1282,7 +1282,7 @@ static int udf_rename (struct inode * ol }else { - new_dir->i_nlink ++; +inc_nlink (new_dir);mark_inode_dirty (new_dir); } }
fs/vfat/namei.c renamed from fs/vfat/namei.c~B4-monitor_inc_nlink +2 -2
@@ -837,7 +837,7 @@ static int vfat_mkdir(struct inode *dir,if (err) goto out_free; dir->i_version++; - dir->i_nlink++; +inc_nlink (dir); inode =fat_build_inode (sb, sinfo.de, sinfo.i_pos);brelse (sinfo.bh);
@@ -932,7 +932,7 @@ static int vfat_rename(struct inode *old }drop_nlink (old_dir);if (!new_inode) - new_dir->i_nlink++; +inc_nlink (new_dir); } err =fat_remove_entries (old_dir, &old_sinfo);/* and releases bh */
ipc/mqueue.c renamed from ipc/mqueue.c~B4-monitor_inc_nlink +1 -1
@@ -168,7 +168,7 @@ static struct inode *mqueue_get_inode(st/* all is ok */ info->user =get_uid (u); }else if (S_ISDIR (mode)) { - inode->i_nlink++; +inc_nlink (inode);/* Some things misbehave if size == 0 on a directory */ inode->i_size =2 *DIRENT_SIZE ; inode->i_op = &mqueue_dir_inode_operations;
kernel/cpuset.c renamed from kernel/cpuset.c~B4-monitor_inc_nlink +4 -4
@@ -377,7 +377,7 @@ static int cpuset_fill_super(struct supe inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations;/* directories start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode); }else {return -ENOMEM ; }
@@ -1552,7 +1552,7 @@ static int cpuset_create_file(struct den inode->i_fop = &simple_dir_operations;/* start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode); }else if (S_ISREG (mode)) { inode->i_size =0 ; inode->i_fop = &cpuset_file_operations;
@@ -1585,7 +1585,7 @@ static int cpuset_create_dir(struct cpus error =cpuset_create_file (dentry,S_IFDIR | mode);if (!error) { dentry->d_fsdata = cs; - parent->d_inode->i_nlink++; +inc_nlink (parent->d_inode); cs->dentry = dentry; }dput (dentry);
@@ -2020,7 +2020,7 @@ int __init cpuset_init(void) } root = cpuset_mount->mnt_sb->s_root; root->d_fsdata = &top_cpuset; - root->d_inode->i_nlink++; +inc_nlink (root->d_inode); top_cpuset.dentry = root; root->d_inode->i_op = &cpuset_dir_inode_operations; number_of_cpusets =1 ;
net/sunrpc/rpc_pipe.c renamed from net/sunrpc/rpc_pipe.c~B4-monitor_inc_nlink +3 -3
@@ -496,7 +496,7 @@ rpc_get_inode(struct super_block *sb, incase S_IFDIR : inode->i_fop = &simple_dir_operations; inode->i_op = &simple_dir_inode_operations; - inode->i_nlink++; +inc_nlink (inode);default :break ; }
@@ -572,7 +572,7 @@ rpc_populate(struct dentry *parent,if (private)rpc_inode_setowner (inode, private);if (S_ISDIR (mode)) - dir->i_nlink++; +inc_nlink (dir);d_add (dentry, inode); }mutex_unlock (&dir->i_mutex);
@@ -594,7 +594,7 @@ __rpc_mkdir(struct inode *dir, struct de goto out_err; inode->i_ino =iunique (dir->i_sb,100 );d_instantiate (dentry, inode); - dir->i_nlink++; +inc_nlink (dir);inode_dir_notify (dir,DN_CREATE );return 0 ; out_err:
security/inode.c renamed from security/inode.c~B4-monitor_inc_nlink +2 -2
@@ -78,7 +78,7 @@ static struct inode *get_inode(struct su inode->i_fop = &simple_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode);break ; } }
@@ -111,7 +111,7 @@ static int mkdir(struct inode *dir, stru mode = (mode & (S_IRWXUGO |S_ISVTX )) |S_IFDIR ; res =mknod (dir, dentry, mode,0 );if (!res) - dir->i_nlink++; +inc_nlink (dir);return res; }
security/selinux/selinuxfs.c renamed from security/selinux/selinuxfs.c~B4-monitor_inc_nlink +2 -2
@@ -1253,10 +1253,10 @@ static int sel_make_dir(struct inode *di inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations;/* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; +inc_nlink (inode);d_add (dentry, inode);/* bump link count on parent directory, too */ - dir->i_nlink++; +inc_nlink (dir); out:return ret; }
_
PATCH 3/6 unlink: monitor i_nlink
In reply to Dave HansenWhen a filesystem decrements i_nlink to zero, it means that a write must be performed in order to drop the inode from the filesystem.
We're shortly going to have keep filesystems from being remounted r/o between the time that this i_nlink decrement and that write occurs.
So, add a little helper function to do the decrements. We'll tie into it in a bit to note when i_nlink hits zero.
---
lxc-dave/drivers/usb/core/inode.c | 7 ++++--- lxc-dave/fs/autofs/root.c | 2 +- lxc-dave/fs/autofs4/root.c | 2 +- lxc-dave/fs/bfs/dir.c | 9 +++------ lxc-dave/fs/cifs/inode.c | 10 +++++----- lxc-dave/fs/coda/dir.c | 4 ++-- lxc-dave/fs/ext2/namei.c | 2 +- lxc-dave/fs/ext3/namei.c | 14 +++++++------- lxc-dave/fs/hfs/dir.c | 2 +- lxc-dave/fs/hfsplus/dir.c | 2 +- lxc-dave/fs/hpfs/namei.c | 6 +++--- lxc-dave/fs/jffs/inode-v23.c | 3 +-- lxc-dave/fs/jffs2/dir.c | 6 +++--- lxc-dave/fs/jfs/namei.c | 14 ++++++-------- lxc-dave/fs/libfs.c | 10 +++++----- lxc-dave/fs/minix/namei.c | 2 +- lxc-dave/fs/msdos/namei.c | 9 ++++----- lxc-dave/fs/nfs/dir.c | 6 +++--- lxc-dave/fs/ocfs2/namei.c | 4 ++-- lxc-dave/fs/qnx4/namei.c | 6 ++---- lxc-dave/fs/reiserfs/namei.c | 6 +++--- lxc-dave/fs/sysv/namei.c | 2 +- lxc-dave/fs/udf/namei.c | 18 ++++++------------ lxc-dave/fs/ufs/namei.c | 2 +- lxc-dave/fs/vfat/namei.c | 9 ++++----- lxc-dave/include/linux/fs.h | 7 ++++++- lxc-dave/ipc/mqueue.c | 2 +- lxc-dave/mm/shmem.c | 10 +++++----- 28 files changed, 83 insertions(+), 93 deletions(-)
include/linux/fs.h renamed from include/linux/fs.h~B3-unlink-monitor-i_nlink-0 +6 -1
@@ -1262,9 +1262,14 @@ static inline void inode_inc_link_count(mark_inode_dirty (inode); } -static inline void inode_dec_link_count (struct inode *inode) +static inline void drop_nlink (struct inode *inode) { inode->i_nlink--; +} + +static inline void inode_dec_link_count (struct inode *inode) +{ +drop_nlink (inode);mark_inode_dirty (inode); }
drivers/usb/core/inode.c renamed from drivers/usb/core/inode.c~B3-unlink-monitor-i_nlink-0 +4 -3
@@ -332,7 +332,7 @@ static int usbfs_unlink (struct inode *d {struct inode *inode = dentry->d_inode;mutex_lock (&inode->i_mutex); - dentry->d_inode->i_nlink--; +drop_nlink (dentry->d_inode);dput (dentry);mutex_unlock (&inode->i_mutex);d_delete (dentry);
@@ -347,10 +347,11 @@ static int usbfs_rmdir(struct inode *dirmutex_lock (&inode->i_mutex);dentry_unhash (dentry);if (usbfs_empty (dentry)) { - dentry->d_inode->i_nlink -=2 ; +drop_nlink (dentry->d_inode); +drop_nlink (dentry->d_inode);dput (dentry); inode->i_flags |=S_DEAD ; - dir->i_nlink--; +drop_nlink (dir); error =0 ; }mutex_unlock (&inode->i_mutex);
fs/autofs/root.c renamed from fs/autofs/root.c~B3-unlink-monitor-i_nlink-0 +1 -1
@@ -414,7 +414,7 @@ static int autofs_root_rmdir(struct inod dentry->d_time = (unsigned long )(struct autofs_dir_ent *)NULL ;autofs_hash_delete (ent); - dir->i_nlink--; +drop_nlink (dir);d_drop (dentry);unlock_kernel ();
fs/autofs4/root.c renamed from fs/autofs4/root.c~B3-unlink-monitor-i_nlink-0 +1 -1
@@ -676,7 +676,7 @@ static int autofs4_dir_rmdir(struct inod dentry->d_inode->i_nlink =0 ;if (dir->i_nlink) - dir->i_nlink--; +drop_nlink (dir);return 0 ; }
fs/bfs/dir.c renamed from fs/bfs/dir.c~B3-unlink-monitor-i_nlink-0 +3 -6
@@ -117,8 +117,7 @@ static int bfs_create(struct inode * dir err =bfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino);if (err) { - inode->i_nlink--; -mark_inode_dirty (inode); +inode_dec_link_count (inode);iput (inode);unlock_kernel ();return err;
@@ -196,9 +195,8 @@ static int bfs_unlink(struct inode * dirmark_buffer_dirty (bh); dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ;mark_inode_dirty (dir); - inode->i_nlink--; inode->i_ctime = dir->i_ctime; -mark_inode_dirty (inode); +inode_dec_link_count (inode); error =0 ; out_brelse:
@@ -249,9 +247,8 @@ static int bfs_rename(struct inode * old old_dir->i_ctime = old_dir->i_mtime =CURRENT_TIME_SEC ;mark_inode_dirty (old_dir);if (new_inode) { - new_inode->i_nlink--; new_inode->i_ctime =CURRENT_TIME_SEC ; -mark_inode_dirty (new_inode); +inode_dec_link_count (new_inode); }mark_buffer_dirty (old_bh); error =0 ;
fs/cifs/inode.c renamed from fs/cifs/inode.c~B3-unlink-monitor-i_nlink-0 +5 -5
@@ -591,7 +591,7 @@ int cifs_unlink(struct inode *inode, strif (!rc) {if (direntry->d_inode) - direntry->d_inode->i_nlink--; +drop_nlink (direntry->d_inode); }else if (rc == -ENOENT ) {d_drop (direntry); }else if (rc == -ETXTBSY ) {
@@ -610,7 +610,7 @@ int cifs_unlink(struct inode *inode, str CIFS_MOUNT_MAP_SPECIAL_CHR);CIFSSMBClose (xid, pTcon, netfid);if (direntry->d_inode) - direntry->d_inode->i_nlink--; +drop_nlink (direntry->d_inode); } }else if (rc == -EACCES ) {/* try only if r/o attribute set in local lookup data? */
@@ -664,7 +664,7 @@ int cifs_unlink(struct inode *inode, str CIFS_MOUNT_MAP_SPECIAL_CHR);if (!rc) {if (direntry->d_inode) - direntry->d_inode->i_nlink--; +drop_nlink (direntry->d_inode); }else if (rc == -ETXTBSY ) {int oplock = FALSE;__u16 netfid;
@@ -685,7 +685,7 @@ int cifs_unlink(struct inode *inode, str CIFS_MOUNT_MAP_SPECIAL_CHR);CIFSSMBClose (xid, pTcon, netfid);if (direntry->d_inode) - direntry->d_inode->i_nlink--; +drop_nlink (direntry->d_inode); }/* BB if rc = -ETXTBUSY goto the rename logic BB */ }
@@ -817,7 +817,7 @@ int cifs_rmdir(struct inode *inode, stru cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);if (!rc) { - inode->i_nlink--; +drop_nlink (inode);i_size_write (direntry->d_inode,0 ); direntry->d_inode->i_nlink =0 ; }
fs/coda/dir.c renamed from fs/coda/dir.c~B3-unlink-monitor-i_nlink-0 +2 -2
@@ -367,7 +367,7 @@ int coda_unlink(struct inode *dir, struc }coda_dir_changed (dir,0 ); - de->d_inode->i_nlink--; +drop_nlink (de->d_inode);unlock_kernel ();return 0 ;
@@ -394,7 +394,7 @@ int coda_rmdir(struct inode *dir, struct }coda_dir_changed (dir,-1 ); - de->d_inode->i_nlink--; +drop_nlink (de->d_inode);d_delete (de);unlock_kernel ();
fs/ext2/namei.c renamed from fs/ext2/namei.c~B3-unlink-monitor-i_nlink-0 +1 -1
@@ -326,7 +326,7 @@ static int ext2_rename (struct inode * oext2_set_link (new_dir, new_de, new_page, old_inode); new_inode->i_ctime =CURRENT_TIME_SEC ;if (dir_de) - new_inode->i_nlink--; +drop_nlink (new_inode);inode_dec_link_count (new_inode); }else {if (dir_de) {
fs/ext3/namei.c renamed from fs/ext3/namei.c~B3-unlink-monitor-i_nlink-0 +7 -7
@@ -1621,7 +1621,7 @@ static inline void ext3_inc_count(handlestatic inline void ext3_dec_count (handle_t *handle,struct inode *inode) { - inode->i_nlink--; +drop_nlink (inode); } static int ext3_add_nondir(handle_t *handle,
@@ -1743,7 +1743,7 @@ retry: inode->i_size =EXT3_I (inode)->i_disksize = inode->i_sb->s_blocksize; dir_block =ext3_bread (handle, inode,0 ,1 , &err);if (!dir_block) { - inode->i_nlink--;/* is this nlink == 0? */ +drop_nlink (inode);/* is this nlink == 0? */ ext3_mark_inode_dirty (handle, inode);iput (inode); goto out_stop;
@@ -2053,7 +2053,7 @@ static int ext3_rmdir (struct inode * diext3_orphan_add (handle, inode); inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ;ext3_mark_inode_dirty (handle, inode); - dir->i_nlink--; +drop_nlink (dir);ext3_update_dx_flag (dir);ext3_mark_inode_dirty (handle, dir);
@@ -2104,7 +2104,7 @@ static int ext3_unlink(struct inode * di dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ;ext3_update_dx_flag (dir);ext3_mark_inode_dirty (handle, dir); - inode->i_nlink--; +drop_nlink (inode);if (!inode->i_nlink)ext3_orphan_add (handle, inode); inode->i_ctime = dir->i_ctime;
@@ -2326,7 +2326,7 @@ static int ext3_rename (struct inode * o }if (new_inode) { - new_inode->i_nlink--; +drop_nlink (new_inode); new_inode->i_ctime =CURRENT_TIME_SEC ; } old_dir->i_ctime = old_dir->i_mtime =CURRENT_TIME_SEC ;
@@ -2337,9 +2337,9 @@ static int ext3_rename (struct inode * oPARENT_INO (dir_bh->b_data) =cpu_to_le32 (new_dir->i_ino);BUFFER_TRACE (dir_bh,"call ext3_journal_dirty_metadata" );ext3_journal_dirty_metadata (handle, dir_bh); - old_dir->i_nlink--; +drop_nlink (old_dir);if (new_inode) { - new_inode->i_nlink--; +drop_nlink (new_inode); }else { new_dir->i_nlink++;ext3_update_dx_flag (new_dir);
fs/hfs/dir.c renamed from fs/hfs/dir.c~B3-unlink-monitor-i_nlink-0 +1 -1
@@ -246,7 +246,7 @@ static int hfs_unlink(struct inode *dir,if (res)return res; - inode->i_nlink--; +drop_nlink (inode);hfs_delete_inode (inode); inode->i_ctime =CURRENT_TIME_SEC ;mark_inode_dirty (inode);
fs/hfsplus/dir.c renamed from fs/hfsplus/dir.c~B3-unlink-monitor-i_nlink-0 +1 -1
@@ -338,7 +338,7 @@ static int hfsplus_unlink(struct inode *return res;if (inode->i_nlink >0 ) - inode->i_nlink--; +drop_nlink (inode);hfsplus_delete_inode (inode);if (inode->i_ino != cnid && !inode->i_nlink) {if (!atomic_read (&HFSPLUS_I (inode).opencnt)) {
fs/hpfs/namei.c renamed from fs/hpfs/namei.c~B3-unlink-monitor-i_nlink-0 +3 -3
@@ -434,7 +434,7 @@ again:unlock_kernel ();return -ENOSPC ;default : - inode->i_nlink--; +drop_nlink (inode); err =0 ; } goto out;
@@ -494,7 +494,7 @@ static int hpfs_rmdir(struct inode *dir, err = -ENOSPC ;break ;default : - dir->i_nlink--; +drop_nlink (dir); inode->i_nlink =0 ; err =0 ; }
@@ -636,7 +636,7 @@ static int hpfs_rename(struct inode *oldhpfs_i (i)->i_parent_dir = new_dir->i_ino;if (S_ISDIR (i->i_mode)) { new_dir->i_nlink++; - old_dir->i_nlink--; +drop_nlink (old_dir); }if ((fnode =hpfs_map_fnode (i->i_sb, i->i_ino, &bh))) { fnode->up = new_dir->i_ino;
fs/jffs2/dir.c renamed from fs/jffs2/dir.c~B3-unlink-monitor-i_nlink-0 +3 -3
@@ -615,7 +615,7 @@ static int jffs2_rmdir (struct inode *di } ret =jffs2_unlink (dir_i, dentry);if (!ret) - dir_i->i_nlink--; +drop_nlink (dir_i);return ret; }
@@ -823,7 +823,7 @@ static int jffs2_rename (struct inode *oif (victim_f) {/* There was a victim. Kill it off nicely */ - new_dentry->d_inode->i_nlink--; +drop_nlink (new_dentry->d_inode);/* Don't oops if the victim was a dirent pointing to an inode which didn't exist. */ if (victim_f->inocache) {
@@ -862,7 +862,7 @@ static int jffs2_rename (struct inode *o }if (S_ISDIR (old_dentry->d_inode->i_mode)) - old_dir_i->i_nlink--; +drop_nlink (old_dir_i); new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime =ITIME (now);
fs/jfs/namei.c renamed from fs/jfs/namei.c~B3-unlink-monitor-i_nlink-0 +6 -8
@@ -393,9 +393,8 @@ static int jfs_rmdir(struct inode *dip,/* update parent directory's link count corresponding * to ".." entry of the target directory deleted */ - dip->i_nlink--; dip->i_ctime = dip->i_mtime =CURRENT_TIME ; -mark_inode_dirty (dip); +inode_dec_link_count (dip);/* * OS/2 could have created EA and/or ACL
@@ -515,8 +514,7 @@ static int jfs_unlink(struct inode *dip,mark_inode_dirty (dip);/* update target's inode */ - ip->i_nlink--; -mark_inode_dirty (ip); +inode_dec_link_count (ip);/* * commit zero link count object
@@ -835,7 +833,7 @@ static int jfs_link(struct dentry *old_d rc =txCommit (tid,2 , &iplist[0 ],0 );if (rc) { - ip->i_nlink--; + ip->i_nlink--;/* never instantiated */ iput (ip); }else d_instantiate (dentry, ip);
@@ -1155,9 +1153,9 @@ static int jfs_rename(struct inode *old_ old_ip->i_ino, JFS_RENAME);if (rc) goto out4; - new_ip->i_nlink--; +drop_nlink (new_ip);if (S_ISDIR (new_ip->i_mode)) { - new_ip->i_nlink--; +drop_nlink (new_ip);if (new_ip->i_nlink) {mutex_unlock (&JFS_IP (new_ip)->commit_mutex);if (old_dir != new_dir)
@@ -1223,7 +1221,7 @@ static int jfs_rename(struct inode *old_ goto out4; }if (S_ISDIR (old_ip->i_mode)) { - old_dir->i_nlink--; +drop_nlink (old_dir);if (old_dir != new_dir) {/* * Change inode number of parent for moved directory
fs/libfs.c renamed from fs/libfs.c~B3-unlink-monitor-i_nlink-0 +5 -5
@@ -275,7 +275,7 @@ int simple_unlink(struct inode *dir, strstruct inode *inode = dentry->d_inode; inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME ; - inode->i_nlink--; +drop_nlink (inode);dput (dentry);return 0 ; }
@@ -285,9 +285,9 @@ int simple_rmdir(struct inode *dir, struif (!simple_empty (dentry))return -ENOTEMPTY ; - dentry->d_inode->i_nlink--; +drop_nlink (dentry->d_inode);simple_unlink (dir, dentry); - dir->i_nlink--; +drop_nlink (dir);return 0 ; }
@@ -303,9 +303,9 @@ int simple_rename(struct inode *old_dir,if (new_dentry->d_inode) {simple_unlink (new_dir, new_dentry);if (they_are_dirs) - old_dir->i_nlink--; +drop_nlink (old_dir); }else if (they_are_dirs) { - old_dir->i_nlink--; +drop_nlink (old_dir); new_dir->i_nlink++; }
fs/nfs/dir.c renamed from fs/nfs/dir.c~B3-unlink-monitor-i_nlink-0 +3 -3
@@ -842,7 +842,7 @@ static void nfs_dentry_iput(struct dentrnfs_inode_return_delegation (inode);if (dentry->d_flags &DCACHE_NFSFS_RENAMED ) {lock_kernel (); - inode->i_nlink--; +drop_nlink (inode);nfs_complete_unlink (dentry);unlock_kernel (); }
@@ -1395,7 +1395,7 @@ static int nfs_safe_remove(struct dentry error =NFS_PROTO (dir)->remove (dir, &dentry->d_name);/* The VFS may want to delete this inode */ if (error ==0 ) - inode->i_nlink--; +drop_nlink (inode);nfs_mark_for_revalidate (inode);nfs_end_data_update (inode); }else
@@ -1599,7 +1599,7 @@ static int nfs_rename(struct inode *old_ goto out; } }else - new_inode->i_nlink--; +drop_nlink (new_inode); go_ahead:/*
fs/ocfs2/namei.c renamed from fs/ocfs2/namei.c~B3-unlink-monitor-i_nlink-0 +2 -2
@@ -711,7 +711,7 @@ static int ocfs2_link(struct dentry *old err =ocfs2_journal_dirty (handle, fe_bh);if (err <0 ) {le16_add_cpu (&fe->i_links_count,-1 ); - inode->i_nlink--; +drop_nlink (inode);mlog_errno (err); goto bail; }
@@ -721,7 +721,7 @@ static int ocfs2_link(struct dentry *old parent_fe_bh, de_bh);if (err) {le16_add_cpu (&fe->i_links_count,-1 ); - inode->i_nlink--; +drop_nlink (inode);mlog_errno (err); goto bail; }
fs/qnx4/namei.c renamed from fs/qnx4/namei.c~B3-unlink-monitor-i_nlink-0 +2 -4
@@ -189,8 +189,7 @@ int qnx4_rmdir(struct inode *dir, struct inode->i_nlink =0 ;mark_inode_dirty (inode); inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ; - dir->i_nlink--; -mark_inode_dirty (dir); +inode_dec_link_count (dir); retval =0 ; end_rmdir:
@@ -234,9 +233,8 @@ int qnx4_unlink(struct inode *dir, strucmark_buffer_dirty (bh); dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ;mark_inode_dirty (dir); - inode->i_nlink--; inode->i_ctime = dir->i_ctime; -mark_inode_dirty (inode); +inode_dec_link_count (inode); retval =0 ; end_unlink:
fs/reiserfs/namei.c renamed from fs/reiserfs/namei.c~B3-unlink-monitor-i_nlink-0 +3 -3
@@ -20,7 +20,7 @@#include <linux/quotaops.h> #define INC_DIR_INODE_NLINK (i) if (i->i_nlink != 1) { i->i_nlink++; if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; } -#define DEC_DIR_INODE_NLINK (i) if (i->i_nlink != 1) i->i_nlink--; +#define DEC_DIR_INODE_NLINK (i) if (i->i_nlink != 1) drop_nlink(i);// directory item contains array of entry headers. This performs // binary search through that array
@@ -994,7 +994,7 @@ static int reiserfs_unlink(struct inode inode->i_nlink =1 ; } - inode->i_nlink--; +drop_nlink (inode);/* * we schedule before doing the add_save_link call, save the link
@@ -1475,7 +1475,7 @@ static int reiserfs_rename(struct inodeif (S_ISDIR (new_dentry_inode->i_mode)) { new_dentry_inode->i_nlink =0 ; }else { - new_dentry_inode->i_nlink--; +drop_nlink (new_dentry_inode); } new_dentry_inode->i_ctime = ctime; savelink = new_dentry_inode->i_nlink;
fs/sysv/namei.c renamed from fs/sysv/namei.c~B3-unlink-monitor-i_nlink-0 +1 -1
@@ -250,7 +250,7 @@ static int sysv_rename(struct inode * olsysv_set_link (new_de, new_page, old_inode); new_inode->i_ctime =CURRENT_TIME_SEC ;if (dir_de) - new_inode->i_nlink--; +drop_nlink (new_inode);inode_dec_link_count (new_inode); }else {if (dir_de) {
fs/udf/namei.c renamed from fs/udf/namei.c~B3-unlink-monitor-i_nlink-0 +6 -12
@@ -878,8 +878,7 @@ static int udf_rmdir(struct inode * dir, inode->i_nlink); inode->i_nlink =0 ; inode->i_size =0 ; -mark_inode_dirty (inode); - dir->i_nlink --; +inode_dec_link_count (inode); inode->i_ctime = dir->i_ctime = dir->i_mtime =current_fs_time (dir->i_sb);mark_inode_dirty (dir);
@@ -923,8 +922,7 @@ static int udf_unlink(struct inode * dir goto end_unlink; dir->i_ctime = dir->i_mtime =current_fs_time (dir->i_sb);mark_inode_dirty (dir); - inode->i_nlink--; -mark_inode_dirty (inode); +inode_dec_link_count (inode); inode->i_ctime = dir->i_ctime; retval =0 ;
@@ -1101,8 +1099,7 @@ out:return err; out_no_entry: - inode->i_nlink--; -mark_inode_dirty (inode); +inode_dec_link_count (inode);iput (inode); goto out; }
@@ -1261,9 +1258,8 @@ static int udf_rename (struct inode * olif (new_inode) { - new_inode->i_nlink--; new_inode->i_ctime =current_fs_time (new_inode->i_sb); -mark_inode_dirty (new_inode); +inode_dec_link_count (new_inode); } old_dir->i_ctime = old_dir->i_mtime =current_fs_time (old_dir->i_sb);mark_inode_dirty (old_dir);
@@ -1279,12 +1275,10 @@ static int udf_rename (struct inode * ol }else mark_buffer_dirty_inode (dir_bh, old_inode); - old_dir->i_nlink --; -mark_inode_dirty (old_dir); +inode_dec_link_count (old_dir);if (new_inode) { - new_inode->i_nlink --; -mark_inode_dirty (new_inode); +inode_dec_link_count (new_inode); }else {
fs/ufs/namei.c renamed from fs/ufs/namei.c~B3-unlink-monitor-i_nlink-0 +1 -1
@@ -308,7 +308,7 @@ static int ufs_rename(struct inode *old_ufs_set_link (new_dir, new_de, new_page, old_inode); new_inode->i_ctime =CURRENT_TIME_SEC ;if (dir_de) - new_inode->i_nlink--; +drop_nlink (new_inode);inode_dec_link_count (new_inode); }else {if (dir_de) {
fs/vfat/namei.c renamed from fs/vfat/namei.c~B3-unlink-monitor-i_nlink-0 +4 -5
@@ -782,7 +782,7 @@ static int vfat_rmdir(struct inode *dir, err =fat_remove_entries (dir, &sinfo);/* and releases bh */ if (err) goto out; - dir->i_nlink--; +drop_nlink (dir); inode->i_nlink =0 ; inode->i_mtime = inode->i_atime =CURRENT_TIME_SEC ;
@@ -930,7 +930,7 @@ static int vfat_rename(struct inode *oldif (err) goto error_dotdot; } - old_dir->i_nlink--; +drop_nlink (old_dir);if (!new_inode) new_dir->i_nlink++; }
@@ -947,10 +947,9 @@ static int vfat_rename(struct inode *oldmark_inode_dirty (old_dir);if (new_inode) { +drop_nlink (new_inode);if (is_dir) - new_inode->i_nlink -=2 ; -else - new_inode->i_nlink--; +drop_nlink (new_inode); new_inode->i_ctime = ts; } out:
ipc/mqueue.c renamed from ipc/mqueue.c~B3-unlink-monitor-i_nlink-0 +1 -1
@@ -307,7 +307,7 @@ static int mqueue_unlink(struct inode *d dir->i_ctime = dir->i_mtime = dir->i_atime =CURRENT_TIME ; dir->i_size -=DIRENT_SIZE ; - inode->i_nlink--; +drop_nlink (inode);dput (dentry);return 0 ; }
mm/shmem.c renamed from mm/shmem.c~B3-unlink-monitor-i_nlink-0 +5 -5
@@ -1760,7 +1760,7 @@ static int shmem_unlink(struct inode *di dir->i_size -=BOGO_DIRENT_SIZE ; inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME ; - inode->i_nlink--; +drop_nlink (inode);dput (dentry);/* Undo the count from "create" - this does all the work */ return 0 ; }
@@ -1770,8 +1770,8 @@ static int shmem_rmdir(struct inode *dirif (!simple_empty (dentry))return -ENOTEMPTY ; - dentry->d_inode->i_nlink--; - dir->i_nlink--; +drop_nlink (dentry->d_inode); +drop_nlink (dir);return shmem_unlink (dir, dentry); }
@@ -1792,9 +1792,9 @@ static int shmem_rename(struct inode *olif (new_dentry->d_inode) { (void )shmem_unlink (new_dir, new_dentry);if (they_are_dirs) - old_dir->i_nlink--; +drop_nlink (old_dir); }else if (they_are_dirs) { - old_dir->i_nlink--; +drop_nlink (old_dir); new_dir->i_nlink++; }
diff -puN fs/binfmt_misc.c~B3-unlink-monitor-i_nlink-0 fs/binfmt_misc.c
fs/jffs/inode-v23.c renamed from fs/jffs/inode-v23.c~B3-unlink-monitor-i_nlink-0 +1 -2
@@ -1052,9 +1052,8 @@ jffs_remove(struct inode *dir, struct de dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ;mark_inode_dirty (dir); - inode->i_nlink--; inode->i_ctime = dir->i_ctime; -mark_inode_dirty (inode); +inode_dec_link_count (inode);d_delete (dentry);/* This also frees the inode */
fs/minix/namei.c renamed from fs/minix/namei.c~B3-unlink-monitor-i_nlink-0 +1 -1
@@ -249,7 +249,7 @@ static int minix_rename(struct inode * ominix_set_link (new_de, new_page, old_inode); new_inode->i_ctime =CURRENT_TIME_SEC ;if (dir_de) - new_inode->i_nlink--; +drop_nlink (new_inode);inode_dec_link_count (new_inode); }else {if (dir_de) {
fs/msdos/namei.c renamed from fs/msdos/namei.c~B3-unlink-monitor-i_nlink-0 +4 -5
@@ -341,7 +341,7 @@ static int msdos_rmdir(struct inode *dir err =fat_remove_entries (dir, &sinfo);/* and releases bh */ if (err) goto out; - dir->i_nlink--; +drop_nlink (dir); inode->i_nlink =0 ; inode->i_ctime =CURRENT_TIME_SEC ;
@@ -542,7 +542,7 @@ static int do_msdos_rename(struct inodeif (err) goto error_dotdot; } - old_dir->i_nlink--; +drop_nlink (old_dir);if (!new_inode) new_dir->i_nlink++; }
@@ -559,10 +559,9 @@ static int do_msdos_rename(struct inodemark_inode_dirty (old_dir);if (new_inode) { +drop_nlink (new_inode);if (is_dir) - new_inode->i_nlink -=2 ; -else - new_inode->i_nlink--; +drop_nlink (new_inode); new_inode->i_ctime = ts; } out:
_
PATCH 1/6 prepare for write access checks: collapse if()
In reply to Dave HansenWe're shortly going to be adding a bunch more permission checks in these functions. That requires adding either a bunch of new if() conditions, or some gotos. This patch collapses existing if()s and uses gotos instead to prepare for the upcoming changes.
---
lxc-dave/fs/namei.c | 93 +++++++++++++++++++++++++++------------------------- lxc-dave/fs/open.c | 64 ++++++++++++++++++++--------------- 2 files changed, 87 insertions(+), 70 deletions(-)
fs/namei.c renamed from fs/namei.c~B1-prepwork-collapse-ifs +50 -43
@@ -1926,30 +1926,32 @@ asmlinkage long sys_mkdirat(int dfd, con {int error =0 ;char * tmp; +struct dentry *dentry; +struct nameidata nd; tmp =getname (pathname); error =PTR_ERR (tmp); -if (!IS_ERR (tmp)) { -struct dentry *dentry; -struct nameidata nd; +if (IS_ERR (tmp)) + goto out_err; - error =do_path_lookup (dfd, tmp,LOOKUP_PARENT , &nd); -if (error) - goto out; - dentry =lookup_create (&nd,1 ); - error =PTR_ERR (dentry); -if (!IS_ERR (dentry)) { -if (!IS_POSIXACL (nd.dentry->d_inode)) - mode &= ~current->fs->umask; - error =vfs_mkdir (nd.dentry->d_inode, dentry, mode); -dput (dentry); - } -mutex_unlock (&nd.dentry->d_inode->i_mutex); -path_release (&nd); -out: -putname (tmp); - } + error =do_path_lookup (dfd, tmp,LOOKUP_PARENT , &nd); +if (error) + goto out; + dentry =lookup_create (&nd,1 ); + error =PTR_ERR (dentry); +if (IS_ERR (dentry)) + goto out_unlock; +if (!IS_POSIXACL (nd.dentry->d_inode)) + mode &= ~current->fs->umask; + error =vfs_mkdir (nd.dentry->d_inode, dentry, mode); +dput (dentry); +out_unlock: +mutex_unlock (&nd.dentry->d_inode->i_mutex); +path_release (&nd); +out: +putname (tmp); +out_err:return error; }
@@ -2048,10 +2050,11 @@ static long do_rmdir(int dfd, const charmutex_lock_nested (&nd.dentry->d_inode->i_mutex,I_MUTEX_PARENT ); dentry =lookup_hash (&nd); error =PTR_ERR (dentry); -if (!IS_ERR (dentry)) { - error =vfs_rmdir (nd.dentry->d_inode, dentry); -dput (dentry); - } +if (IS_ERR (dentry)) + goto exit2; + error =vfs_rmdir (nd.dentry->d_inode, dentry); +dput (dentry); +exit2:mutex_unlock (&nd.dentry->d_inode->i_mutex); exit1:path_release (&nd);
@@ -2191,30 +2194,33 @@ asmlinkage long sys_symlinkat(const charint error =0 ;char * from;char * to; +struct dentry *dentry; +struct nameidata nd; from =getname (oldname);if (IS_ERR (from))return PTR_ERR (from); to =getname (newname); error =PTR_ERR (to); -if (!IS_ERR (to)) { -struct dentry *dentry; -struct nameidata nd; +if (IS_ERR (to)) + goto out_putname; - error =do_path_lookup (newdfd, to,LOOKUP_PARENT , &nd); -if (error) - goto out; - dentry =lookup_create (&nd,0 ); - error =PTR_ERR (dentry); -if (!IS_ERR (dentry)) { - error =vfs_symlink (nd.dentry->d_inode, dentry, from,S_IALLUGO ); -dput (dentry); - } -mutex_unlock (&nd.dentry->d_inode->i_mutex); -path_release (&nd); + error =do_path_lookup (newdfd, to,LOOKUP_PARENT , &nd); +if (error) + goto out; + dentry =lookup_create (&nd,0 ); + error =PTR_ERR (dentry); +if (IS_ERR (dentry)) + goto out_unlock; + + error =vfs_symlink (nd.dentry->d_inode, dentry, from,S_IALLUGO ); +dput (dentry); +out_unlock: +mutex_unlock (&nd.dentry->d_inode->i_mutex); +path_release (&nd); out: -putname (to); - } +putname (to); +out_putname:putname (from);return error; }
@@ -2300,10 +2306,11 @@ asmlinkage long sys_linkat(int olddfd, c goto out_release; new_dentry =lookup_create (&nd,0 ); error =PTR_ERR (new_dentry); -if (!IS_ERR (new_dentry)) { - error =vfs_link (old_nd.dentry, nd.dentry->d_inode, new_dentry); -dput (new_dentry); - } +if (IS_ERR (new_dentry)) + goto out_unlock; + error =vfs_link (old_nd.dentry, nd.dentry->d_inode, new_dentry); +dput (new_dentry); +out_unlock:mutex_unlock (&nd.dentry->d_inode->i_mutex); out_release:path_release (&nd);
fs/open.c renamed from fs/open.c~B1-prepwork-collapse-ifs +37 -27
97 lines not on this page · raw message
_
PATCH 6/6 monitor zeroing of i_nlink
In reply to Dave HansenSome filesystems, instead of simply decrementing i_nlink, simply zero it during an unlink operation. We need to catch these in addition to the decrement operations.
---
kernel/fork.c | 0 lxc-dave/fs/autofs4/root.c | 4 ++-- lxc-dave/fs/cifs/inode.c | 2 +- lxc-dave/fs/ext3/namei.c | 2 +- lxc-dave/fs/fuse/dir.c | 4 ++-- lxc-dave/fs/hfs/dir.c | 2 +- lxc-dave/fs/hfsplus/dir.c | 4 ++-- lxc-dave/fs/hpfs/namei.c | 4 ++-- lxc-dave/fs/jfs/namei.c | 2 +- lxc-dave/fs/msdos/namei.c | 4 ++-- lxc-dave/fs/nfs/dir.c | 2 +- lxc-dave/fs/qnx4/namei.c | 2 +- lxc-dave/fs/reiserfs/namei.c | 4 ++-- lxc-dave/fs/udf/namei.c | 2 +- lxc-dave/fs/vfat/namei.c | 4 ++-- lxc-dave/include/linux/fs.h | 5 +++++ 16 files changed, 26 insertions(+), 21 deletions(-)
diff -puN fs/libfs.c~B6-monitor-clear-i_nlink fs/libfs.c
fs/cifs/inode.c renamed from fs/cifs/inode.c~B6-monitor-clear-i_nlink +1 -1
@@ -819,7 +819,7 @@ int cifs_rmdir(struct inode *inode, struif (!rc) {drop_nlink (inode);i_size_write (direntry->d_inode,0 ); - direntry->d_inode->i_nlink =0 ; +clear_nlink (direntry->d_inode); } cifsInode =CIFS_I (direntry->d_inode);
fs/ext3/namei.c renamed from fs/ext3/namei.c~B6-monitor-clear-i_nlink +1 -1
@@ -2045,7 +2045,7 @@ static int ext3_rmdir (struct inode * di"empty directory has nlink!=2 (%d)" , inode->i_nlink); inode->i_version++; - inode->i_nlink =0 ; +clear_nlink (inode);/* There's no need to set i_disksize: the fact that i_nlink is * zero will ensure that the right thing happens during any * recovery. */
fs/autofs4/root.c renamed from fs/autofs4/root.c~B6-monitor-clear-i_nlink +2 -2
@@ -638,7 +638,7 @@ static int autofs4_dir_unlink(struct inodput (ino->dentry); dentry->d_inode->i_size =0 ; - dentry->d_inode->i_nlink =0 ; +clear_nlink (dentry->d_inode); dir->i_mtime =CURRENT_TIME ;
@@ -673,7 +673,7 @@ static int autofs4_dir_rmdir(struct inod }dput (ino->dentry); dentry->d_inode->i_size =0 ; - dentry->d_inode->i_nlink =0 ; +clear_nlink (dentry->d_inode);if (dir->i_nlink)drop_nlink (dir);
fs/fuse/dir.c renamed from fs/fuse/dir.c~B6-monitor-clear-i_nlink +2 -2
@@ -508,7 +508,7 @@ static int fuse_unlink(struct inode *dir/* Set nlink to zero so the inode can be cleared, if the inode does have more links this will be discovered at the next lookup/getattr */ - inode->i_nlink =0 ; +clear_nlink (inode);fuse_invalidate_attr (inode);fuse_invalidate_attr (dir);fuse_invalidate_entry_cache (entry);
@@ -534,7 +534,7 @@ static int fuse_rmdir(struct inode *dir, err = req->out.h.error;fuse_put_request (fc, req);if (!err) { - entry->d_inode->i_nlink =0 ; +clear_nlink (entry->d_inode);fuse_invalidate_attr (dir);fuse_invalidate_entry_cache (entry); }else if (err == -EINTR )
fs/hfs/dir.c renamed from fs/hfs/dir.c~B6-monitor-clear-i_nlink +1 -1
@@ -273,7 +273,7 @@ static int hfs_rmdir(struct inode *dir, res =hfs_cat_delete (inode->i_ino, dir, &dentry->d_name);if (res)return res; - inode->i_nlink =0 ; +clear_nlink (inode); inode->i_ctime =CURRENT_TIME_SEC ;hfs_delete_inode (inode);mark_inode_dirty (inode);
fs/hfsplus/dir.c renamed from fs/hfsplus/dir.c~B6-monitor-clear-i_nlink +2 -2
@@ -348,7 +348,7 @@ static int hfsplus_unlink(struct inode * }else inode->i_flags |=S_DEAD ; }else - inode->i_nlink =0 ; +clear_nlink (inode); inode->i_ctime =CURRENT_TIME_SEC ;mark_inode_dirty (inode);
@@ -387,7 +387,7 @@ static int hfsplus_rmdir(struct inode *d res =hfsplus_delete_cat (inode->i_ino, dir, &dentry->d_name);if (res)return res; - inode->i_nlink =0 ; +clear_nlink (inode); inode->i_ctime =CURRENT_TIME_SEC ;hfsplus_delete_inode (inode);mark_inode_dirty (inode);
fs/hpfs/namei.c renamed from fs/hpfs/namei.c~B6-monitor-clear-i_nlink +2 -2
@@ -495,7 +495,7 @@ static int hpfs_rmdir(struct inode *dir,break ;default :drop_nlink (dir); - inode->i_nlink =0 ; +clear_nlink (inode); err =0 ; } goto out;
@@ -590,7 +590,7 @@ static int hpfs_rename(struct inode *oldint r;if ((r =hpfs_remove_dirent (old_dir, dno, dep, &qbh,1 )) !=2 ) {if ((nde =map_dirent (new_dir,hpfs_i (new_dir)->i_dno, (char *)new_name, new_len,NULL , &qbh1))) { - new_inode->i_nlink =0 ; +clear_nlink (new_inode);copy_de (nde, &de);memcpy (nde->name, new_name, new_len);hpfs_mark_4buffers_dirty (&qbh1);
fs/jfs/namei.c renamed from fs/jfs/namei.c~B6-monitor-clear-i_nlink +1 -1
@@ -414,7 +414,7 @@ static int jfs_rmdir(struct inode *dip,JFS_IP (ip)->acl.flag =0 ;/* mark the target directory as deleted */ - ip->i_nlink =0 ; +clear_nlink (ip);mark_inode_dirty (ip); rc =txCommit (tid,2 , &iplist[0 ],0 );
fs/msdos/namei.c renamed from fs/msdos/namei.c~B6-monitor-clear-i_nlink +2 -2
@@ -343,7 +343,7 @@ static int msdos_rmdir(struct inode *dir goto out;drop_nlink (dir); - inode->i_nlink =0 ; +clear_nlink (inode); inode->i_ctime =CURRENT_TIME_SEC ;fat_detach (inode); out:
@@ -425,7 +425,7 @@ static int msdos_unlink(struct inode *di err =fat_remove_entries (dir, &sinfo);/* and releases bh */ if (err) goto out; - inode->i_nlink =0 ; +clear_nlink (inode); inode->i_ctime =CURRENT_TIME_SEC ;fat_detach (inode); out:
fs/nfs/dir.c renamed from fs/nfs/dir.c~B6-monitor-clear-i_nlink +1 -1
@@ -1280,7 +1280,7 @@ static int nfs_rmdir(struct inode *dir, error =NFS_PROTO (dir)->rmdir (dir, &dentry->d_name);/* Ensure the VFS deletes this inode */ if (error ==0 && dentry->d_inode !=NULL ) - dentry->d_inode->i_nlink =0 ; +clear_nlink (dentry->d_inode);nfs_end_data_update (dir);unlock_kernel ();
diff -puN fs/ocfs2/namei.c~B6-monitor-clear-i_nlink fs/ocfs2/namei.c
fs/qnx4/namei.c renamed from fs/qnx4/namei.c~B6-monitor-clear-i_nlink +1 -1
@@ -186,7 +186,7 @@ int qnx4_rmdir(struct inode *dir, structmemset (de->di_fname,0 ,sizeof de->di_fname); de->di_mode =0 ;mark_buffer_dirty (bh); - inode->i_nlink =0 ; +clear_nlink (inode);mark_inode_dirty (inode); inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ;inode_dec_link_count (dir);
fs/reiserfs/namei.c renamed from fs/reiserfs/namei.c~B6-monitor-clear-i_nlink +2 -2
@@ -913,7 +913,7 @@ static int reiserfs_rmdir(struct inode *reiserfs_warning (inode->i_sb,"%s: empty directory has nlink " "!= 2 (%d)" , __FUNCTION__, inode->i_nlink); - inode->i_nlink =0 ; +clear_nlink (inode); inode->i_ctime = dir->i_ctime = dir->i_mtime =CURRENT_TIME_SEC ;reiserfs_update_sd (&th, inode);
@@ -1473,7 +1473,7 @@ static int reiserfs_rename(struct inodeif (new_dentry_inode) {// adjust link number of the victim if (S_ISDIR (new_dentry_inode->i_mode)) { - new_dentry_inode->i_nlink =0 ; +clear_nlink (new_dentry_inode); }else {drop_nlink (new_dentry_inode); }
fs/udf/namei.c renamed from fs/udf/namei.c~B6-monitor-clear-i_nlink +1 -1
@@ -876,7 +876,7 @@ static int udf_rmdir(struct inode * dir,udf_warning (inode->i_sb,"udf_rmdir" ,"empty directory has nlink != 2 (%d)" , inode->i_nlink); - inode->i_nlink =0 ; +clear_nlink (inode); inode->i_size =0 ;inode_dec_link_count (inode); inode->i_ctime = dir->i_ctime = dir->i_mtime =current_fs_time (dir->i_sb);
fs/vfat/namei.c renamed from fs/vfat/namei.c~B6-monitor-clear-i_nlink +2 -2
@@ -784,7 +784,7 @@ static int vfat_rmdir(struct inode *dir, goto out;drop_nlink (dir); - inode->i_nlink =0 ; +clear_nlink (inode); inode->i_mtime = inode->i_atime =CURRENT_TIME_SEC ;fat_detach (inode); out:
@@ -808,7 +808,7 @@ static int vfat_unlink(struct inode *dir err =fat_remove_entries (dir, &sinfo);/* and releases bh */ if (err) goto out; - inode->i_nlink =0 ; +clear_nlink (inode); inode->i_mtime = inode->i_atime =CURRENT_TIME_SEC ;fat_detach (inode); out:
include/linux/fs.h renamed from include/linux/fs.h~B6-monitor-clear-i_nlink +5 -0
@@ -1272,6 +1272,11 @@ static inline void drop_nlink(struct ino inode->i_nlink--; } +static inline void clear_nlink (struct inode *inode) +{ + inode->i_nlink =0 ; +} +static inline void inode_dec_link_count (struct inode *inode) {drop_nlink (inode);
diff -puN kernel/fork.c~B6-monitor-clear-i_nlink kernel/fork.c _
PATCH 5/6 clean up OCFS2 nlink handling
In reply to Dave HansenOCFS2 does some operations on i_nlink, then reverts them if some of its operations fail to complete. This does not fit in well with the drop_nlink() logic where we expect i_nlink to stay at zero once it gets there.
So, delay all of the nlink operations until we're sure that the operations have completed. Also, introduce a small helper to check whether an inode has proper "unlinkable" i_nlink counts no matter whether it is a directory or regular inode.
This patch is broken out from the others because it does contain some logical changes.
---
arch/i386/kernel/setup.c | 0 lxc-dave/fs/ocfs2/namei.c | 45 ++++++++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 21 deletions(-)
fs/ocfs2/namei.c renamed from fs/ocfs2/namei.c~B5-clean_up_OCFS2_nlink_handling +24 -21
@@ -744,11 +744,23 @@ bail:return err; } +static inline int inode_is_unlinkable (struct inode *inode) +{ +if (S_ISDIR (inode->i_mode)) { +if (inode->i_nlink ==2 ) +return 1 ; +return 0 ; + } + +if (inode->i_nlink ==1 ) +return 1 ; +return 0 ; +} +static int ocfs2_unlink (struct inode *dir,struct dentry *dentry) {int status; -unsigned int saved_nlink =0 ;struct inode *inode = dentry->d_inode;struct ocfs2_super *osb =OCFS2_SB (dir->i_sb);u64 blkno;
@@ -760,6 +772,7 @@ static int ocfs2_unlink(struct inode *distruct buffer_head *dirent_bh =NULL ;char orphan_name[OCFS2_ORPHAN_NAMELEN +1 ];struct buffer_head *orphan_entry_bh =NULL ; +unsigned int future_nlink;mlog_entry ("(0x%p, 0x%p, '%.*s')\n" , dir, dentry, dentry->d_name.len, dentry->d_name.name);
@@ -823,18 +836,11 @@ static int ocfs2_unlink(struct inode *di } } -/* There are still a few steps left until we can consider the -* unlink to have succeeded. Save off nlink here before -* modification so we can set it back in case we hit an issue -* before commit. */ - saved_nlink = inode->i_nlink; -if (S_ISDIR (inode->i_mode)) - inode->i_nlink =0 ; +if (S_ISDIR (inode->i_mode) && (inode->i_nlink ==2 )) + future_nlink =0 ;else - inode->i_nlink--; - - status =ocfs2_request_unlink_vote (inode, dentry, - (unsigned int ) inode->i_nlink); + future_nlink = inode->i_nlink -1 ; + status =ocfs2_request_unlink_vote (inode, dentry, future_nlink);if (status <0 ) {/* This vote should succeed under all normal * circumstances. */
@@ -842,7 +848,7 @@ static int ocfs2_unlink(struct inode *di goto leave; } -if (!inode->i_nlink) { +if (inode_is_unlinkable (inode)) { status =ocfs2_prepare_orphan_dir (osb, handle, inode, orphan_name, &orphan_entry_bh);
@@ -869,7 +875,7 @@ static int ocfs2_unlink(struct inode *di fe = (struct ocfs2_dinode *) fe_bh->b_data; -if (!inode->i_nlink) { +if (inode_is_unlinkable (inode)) { status =ocfs2_orphan_add (osb, handle, inode, fe, orphan_name, orphan_entry_bh);if (status <0 ) {
@@ -885,10 +891,10 @@ static int ocfs2_unlink(struct inode *di goto leave; } -/* We can set nlink on the dinode now. clear the saved version -* so that it doesn't get set later. */ +if (S_ISDIR (inode->i_mode)) +drop_nlink (inode); +drop_nlink (inode); fe->i_links_count =cpu_to_le16 (inode->i_nlink); - saved_nlink =0 ; status =ocfs2_journal_dirty (handle, fe_bh);if (status <0 ) {
@@ -897,7 +903,7 @@ static int ocfs2_unlink(struct inode *di }if (S_ISDIR (inode->i_mode)) { - dir->i_nlink--; +drop_nlink (dir); status =ocfs2_mark_inode_dirty (handle, dir, parent_node_bh);if (status <0 ) {
@@ -907,9 +913,6 @@ static int ocfs2_unlink(struct inode *di } leave: -if (status <0 && saved_nlink) - inode->i_nlink = saved_nlink; -if (handle)ocfs2_commit_trans (handle);
diff -puN arch/i386/kernel/setup.c~B5-clean_up_OCFS2_nlink_handling arch/i386/kernel/setup.c _
Re: [PATCH 1/6] prepare for write access checks: collapse if()
In reply to Dave HansenQuoted 8 lines · Dave Hansen
We're shortly going to be adding a bunch more permission checks in these functions. That requires adding either a bunch of new
if()conditions, or some gotos. This patch collapses existing if()s and uses gotos instead to prepare for the upcoming changes.Signed-off-by Dave Hansen <[email protected]>
fs/open.c asmlinkage long sys_faccessat(int dfd, c · line 528
Quoted 3 lines
fs/open.c renamed from fs/open.c~B1-prepwork-collapse-ifs +3
-0+ res =vfs_permission (&nd, mode); +/* SuS v2 requires we report a read only fs too */ + if(res || !(mode & S_IWOTH) ||
except that there's a space missing after the if here :)
Re: [PATCH 2/6] r/o bind mount prepwork: move open_namei()'s vfs_create()
In reply to Dave HansenQuoted 6 lines · Dave Hansen
The code around
vfs_create()inopen_namei()is getting a bit too complex. Right now, there is at least the reference count on the dentry, and thei_mutexto worry about. Soon, we'll also havemnt_writecount.
Quoted 7 lines
So, break the
vfs_create()call out ofopen_namei(), and into a helper function. This duplicates the call tomay_open(), but that isn't such a bad thing since the arguments (acc_modeand flag) were being heavily massaged anyway.Signed-off-by Dave Hansen <[email protected]>
Re: [PATCH 3/6] unlink: monitor i_nlink
In reply to Dave HansenQuoted 5 lines · Dave Hansen
When a filesystem decrements
i_nlinkto zero, it means that a write must be performed in order to drop the inode from the filesystem.
Quoted 8 lines
We're shortly going to have keep filesystems from being remounted r/o between the time that this
i_nlinkdecrement and that write occurs.So, add a little helper function to do the decrements. We'll tie into it in a bit to note when
i_nlinkhits zero.Signed-off-by Dave Hansen <[email protected]>
Note that we all (and especially Andrew :)) need to be carefull not to introduce unguarded i_nlink decrements again. Dave, you'll probably need to do another audit when you introduce the real functionality.
Re: [PATCH 4/6] r/o bind mount prepwork: inc_nlink() helper
In reply to Dave HansenQuoted 4 lines · Dave Hansen
This is mostly included for parity with
dec_nlink(), where we will have some more hooks. This one should stay pretty darn straightforward for now.
Re: [PATCH 5/6] clean up OCFS2 nlink handling
In reply to Dave HansenQuoted 6 lines · Dave Hansen
OCFS2 does some operations on
i_nlink, then reverts them if some of its operations fail to complete. This does not fit in well with thedrop_nlink()logic where we expecti_nlinkto stay at zero once it gets there.
Quoted 7 lines
So, delay all of the nlink operations until we're sure that the operations have completed. Also, introduce a small helper to check whether an inode has proper "unlinkable"
i_nlinkcounts no matter whether it is a directory or regular inode.This patch is broken out from the others because it does contain some logical changes.
looks good to me, although I probably can't ACK ocfs2 patches. did you look whether gfs2 in -mm needs something similar?
Re: [PATCH 6/6] monitor zeroing of i_nlink
In reply to Dave HansenQuoted 6 lines · Dave Hansen
Some filesystems, instead of simply decrementing
i_nlink, simply zero it during an unlink operation. We need to catch these in addition to the decrement operations.Signed-off-by Dave Hansen <[email protected]>
btw, what about adding some nice kerneldoc for all the *_nlink helpers you added?
Quoted 3 lines
---
kernel/fork.c | 0
something is screwed up in your diffstats :)
Re: [PATCH 3/6] unlink: monitor i_nlink
In reply to Christoph HellwigQuoted 13 lines · Christoph Hellwig
Quoted 12 lines · Dave Hansen
When a filesystem decrements
i_nlinkto zero, it means that a write must be performed in order to drop the inode from the filesystem.We're shortly going to have keep filesystems from being remounted r/o between the time that this
i_nlinkdecrement and that write occurs.So, add a little helper function to do the decrements. We'll tie into it in a bit to note when
i_nlinkhits zero.
Quoted 7 lines
Quoted 1 line
Signed-off-by Dave Hansen <[email protected]>Note that we all (and especially Andrew :)) need to be carefull not to introduce unguarded
i_nlinkdecrements again. Dave, you'll probably need to do another audit when you introduce the real functionality.
Yup, I have my eyes on it. git and mm commits should help as well.
-- Dave
Re: [PATCH 1/6] prepare for write access checks: collapse if()
In reply to Christoph HellwigQuoted 11 lines · Christoph Hellwig
Quoted 8 lines · Dave Hansen
We're shortly going to be adding a bunch more permission checks in these functions. That requires adding either a bunch of new
if()conditions, or some gotos. This patch collapses existing if()s and uses gotos instead to prepare for the upcoming changes.Signed-off-by Dave Hansen <[email protected]>
Quoted 7 lines
Review
Quoted 3 lines
(quoted diff) +3
-0+ res = vfs_permission(&nd, mode); + /* SuS v2 requires we report a read only fs too */ + if(res || !(mode & S_IWOTH) ||except that there's a space missing after the if here :)
In my defense, the code I moved sucked, too. ;)
---
lxc-dave/fs/open.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff -puN fs/namei.c~B1-prepwork-collapse-ifs-spacefix fs/namei.c
fs/open.c renamed from fs/open.c~B1-prepwork-collapse-ifs-spacefix +2 -2
@@ -525,11 +525,11 @@ asmlinkage long sys_faccessat(int dfd, c res =vfs_permission (&nd, mode);/* SuS v2 requires we report a read only fs too */ -if (res || !(mode &S_IWOTH ) || +if (res || !(mode &S_IWOTH ) ||special_file (nd.dentry->d_inode->i_mode)) goto out_path_release; -if (IS_RDONLY (nd.dentry->d_inode)) +if (IS_RDONLY (nd.dentry->d_inode)) res = -EROFS ; out_path_release:
_
-- Dave
Re: [PATCH 3/6] unlink: monitor i_nlink
In reply to Dave HansenQuoted 16 lines · On Wed, 09 Aug 2006 10:17:19 -0700 Dave Hansen <[email protected]> wrote:
Quoted 15 lines · Christoph Hellwig
Quoted 13 lines · Dave Hansen
When a filesystem decrements
i_nlinkto zero, it means that a write must be performed in order to drop the inode from the filesystem.We're shortly going to have keep filesystems from being remounted r/o between the time that this
i_nlinkdecrement and that write occurs.So, add a little helper function to do the decrements. We'll tie into it in a bit to note when
i_nlinkhits zero.Signed-off-by Dave Hansen <[email protected]>
Quoted 8 lines
Quoted 5 lines
Note that we all (and especially Andrew :)) need to be carefull not to introduce unguarded
i_nlinkdecrements again. Dave, you'll probably need to do another audit when you introduce the real functionality.Yup, I have my eyes on it. git and mm commits should help as well.
A comprehensive way to do this sort of thing is to rename the field. We have >500 references, so one would do:
struct inode {
...
union {
unsigned int i_nlink;
unsigned int i_nlink_use_the_accessors_please;
}
...
};then, when everything in-tree is migrated, remove `i_nlink'.
It's a bit of a hassle, but it will give the most reliable result for both in-tree and out-of-tree filesystems.
Re: [PATCH 5/6] clean up OCFS2 nlink handling
In reply to Christoph HellwigQuoted 11 lines · Christoph Hellwig
Quoted 10 lines · Dave Hansen
OCFS2 does some operations on
i_nlink, then reverts them if some of its operations fail to complete. This does not fit in well with thedrop_nlink()logic where we expecti_nlinkto stay at zero once it gets there.So, delay all of the nlink operations until we're sure that the operations have completed. Also, introduce a small helper to check whether an inode has proper "unlinkable"
i_nlinkcounts no matter whether it is a directory or regular inode.
Quoted 4 lines
Quoted 2 lines
This patch is broken out from the others because it does contain some logical changes.
looks good to me, although I probably can't ACK ocfs2 patches.
That's probably OK. One of the Oracle guys was nice enough to help me beat it into shape and sign off on it.
Quoted 1 line
did you look whether gfs2 in -mm needs something similar?
It doesn't appear to. It doesn't manipulate i_nlink in the same, direct manner.
-- Dave
Re: [PATCH 5/6] clean up OCFS2 nlink handling
Hi,
Quoted 1 line · Dave Hansen
On Wed, 2006-08-09 at 18:12 +0100, Christoph Hellwig wrote:
[snip]
Quoted 6 lines
Quoted 1 line
did you look whether gfs2 in -mm needs something similar?
It doesn't appear to. It doesn't manipulate
i_nlinkin the same, direct manner.-- Dave
I think it will need something similar. I suspect the required changes will all be confined to routines in inode.c. If the link count is changed by (a) remote node(s), then gfs2_inode_attr_in() might change the link count. Also gfs2_change_nlink() is the other place to look. I think everywhere else is ok,
Steve.
Re: [PATCH 5/6] clean up OCFS2 nlink handling
Quoted 5 lines · Steven Whitehouse
Quoted 1 line · Dave Hansen
On Wed, 2006-08-09 at 18:12 +0100, Christoph Hellwig wrote:
[snip]
Quoted 2 lines
Quoted 1 line
did you look whether gfs2 in -mm needs something similar?
Quoted 8 lines
Quoted 2 lines
It doesn't appear to. It doesn't manipulate
i_nlinkin the same, direct manner.I think it will need something similar. I suspect the required changes will all be confined to routines in
inode.c. If the link count is changed by (a) remote node(s), thengfs2_inode_attr_in()might change the link count. Alsogfs2_change_nlink()is the other place to look. I think everywhere else is ok,
Well, I think this is all that it needs. I'm trying to decide if we need a set_nlink() function for users like this, but I'm not sure there are enough of them.
---
lxc-dave/fs/gfs2/inode.c | 3 +++ 2 files changed, 3 insertions(+)
fs/gfs2/inode.c renamed from fs/gfs2/inode.c~gfs +3 -0
@@ -332,6 +332,9 @@ int gfs2_change_nlink(struct gfs2_inode ip->i_di.di_ctime =get_seconds (); ip->i_inode.i_nlink = nlink; +if (!nlink) + ip->i_inode.i_state |=I_AWAITING_FINAL_IPUT ; +gfs2_trans_add_bh (ip->i_gl, dibh,1 );gfs2_dinode_out (&ip->i_di, dibh->b_data);brelse (dibh);
-- Dave
Re: [PATCH 5/6] clean up OCFS2 nlink handling
Hi,
Quoted 15 lines · Dave Hansen
Quoted 5 lines · Steven Whitehouse
Quoted 1 line · Dave Hansen
On Wed, 2006-08-09 at 18:12 +0100, Christoph Hellwig wrote:
[snip]
Quoted 2 lines
Quoted 1 line
did you look whether gfs2 in -mm needs something similar?
Quoted 8 lines
Quoted 2 lines
It doesn't appear to. It doesn't manipulate
i_nlinkin the same, direct manner.I think it will need something similar. I suspect the required changes will all be confined to routines in
inode.c. If the link count is changed by (a) remote node(s), thengfs2_inode_attr_in()might change the link count. Alsogfs2_change_nlink()is the other place to look. I think everywhere else is ok,
Quoted 4 lines
Well, I think this is all that it needs. I'm trying to decide if we need a
set_nlink()function for users like this, but I'm not sure there are enough of them.
I suspect that something is required for gfs2_inode_attr_in() as well. Here is the scenario... suppose there are two nodes A and B. On node A a file is opened, on node B the same file is then unlinked such that its link count hits zero. If node A then does something to the file (read or write, it doesn't matter) then it will reread the attributes off disk via gfs2_inode_attr_in() and discover that the link count is then zero.
We don't play any games in that once the link count has hit zero, thats it, it will never increment above zero again. The node which actually deals with the deallocation and clean up is the one that performs the final close (iput). This is dealt with using the iopen lock to ensure that we are certain of which node is the last to close the file. The iopen lock is held in a shared state by all nodes having the file open. On gfs2_delete_inode we attempt to upgrade the iopen lock to exclusive, if this succeeds we then presume that no other node has the file open and proceed with deallocation, as per a normal local filesystem.
So if I've understood what you are doing correctly, the adjustment you've made below needs to be copied into gfs2_inode_attr_in() as well,
Steve.
Quoted 22 lines
---
lxc-dave/fs/gfs2/inode.c | 3 +++ 2 files changed, 3 insertions(+)diff -puN
fs/gfs2/inode.c~gfsfs/gfs2/inode.cfs/gfs2/inode.c renamed from fs/gfs2/inode.c~gfs +3
-1@@ -332,6 +332,9 @@ int gfs2_change_nlink(struct gfs2_inode ip->i_di.di_ctime =get_seconds (); ip->i_inode.i_nlink = nlink; +if (!nlink) + ip->i_inode.i_state |=I_AWAITING_FINAL_IPUT ; +gfs2_trans_add_bh (ip->i_gl, dibh,1 );gfs2_dinode_out (&ip->i_di, dibh->b_data);brelse (dibh); -- Dave
Re: [PATCH 3/6] unlink: monitor i_nlink
In reply to Andrew MortonQuoted 10 lines · Andrew Morton
struct inode {
...
union {
unsigned inti_nlink;
unsigned inti_nlink_use_the_accessors_please; }
...
};then, when everything in-tree is migrated, remove `i_nlink'.
You can also mark a union member deprecated:
struct inode {
...
union {
unsigned int __deprecated i_nlink;
unsigned int i_nlink_use_the_accessors_please;
}
...
};So gcc will warn about any newly introduced users.
Arnd <><