X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=fs%2Fjfs%2Fnamei.c;h=25161c4121e4ba4f677bd1ed73abc8dcbc003d3d;hb=f720e3ba558680cc7dd3995d005bdc8ee2ef46af;hp=b8d16a6aa88f0c7c11f4bb741f671bba40ac51c6;hpb=f0b364a13d7fba001c0571d954f165dfaf5f434a;p=firefly-linux-kernel-4.4.55.git diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index b8d16a6aa88f..25161c4121e4 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -4,16 +4,16 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -41,7 +41,7 @@ static s64 commitZeroLink(tid_t, struct inode *); /* * NAME: free_ea_wmap(inode) * - * FUNCTION: free uncommitted extended attributes from working map + * FUNCTION: free uncommitted extended attributes from working map * */ static inline void free_ea_wmap(struct inode *inode) @@ -62,7 +62,7 @@ static inline void free_ea_wmap(struct inode *inode) * FUNCTION: create a regular file in the parent directory * with name = and mode = * - * PARAMETER: dip - parent directory vnode + * PARAMETER: dip - parent directory vnode * dentry - dentry of new file * mode - create mode (rwxrwxrwx). * nd- nd struct @@ -97,15 +97,15 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, * begin the transaction before we search the directory. */ ip = ialloc(dip, mode); - if (ip == NULL) { - rc = -ENOSPC; + if (IS_ERR(ip)) { + rc = PTR_ERR(ip); goto out2; } tid = txBegin(dip->i_sb, 0); - mutex_lock(&JFS_IP(dip)->commit_mutex); - mutex_lock(&JFS_IP(ip)->commit_mutex); + mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); + mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); rc = jfs_init_acl(tid, ip, dip); if (rc) @@ -190,7 +190,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, * FUNCTION: create a child directory in the parent directory * with name = and mode = * - * PARAMETER: dip - parent directory vnode + * PARAMETER: dip - parent directory vnode * dentry - dentry of child directory * mode - create mode (rwxrwxrwx). * @@ -231,15 +231,15 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) * begin the transaction before we search the directory. */ ip = ialloc(dip, S_IFDIR | mode); - if (ip == NULL) { - rc = -ENOSPC; + if (IS_ERR(ip)) { + rc = PTR_ERR(ip); goto out2; } tid = txBegin(dip->i_sb, 0); - mutex_lock(&JFS_IP(dip)->commit_mutex); - mutex_lock(&JFS_IP(ip)->commit_mutex); + mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); + mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); rc = jfs_init_acl(tid, ip, dip); if (rc) @@ -324,18 +324,18 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) * * FUNCTION: remove a link to child directory * - * PARAMETER: dip - parent inode + * PARAMETER: dip - parent inode * dentry - child directory dentry * * RETURN: -EINVAL - if name is . or .. - * -EINVAL - if . or .. exist but are invalid. + * -EINVAL - if . or .. exist but are invalid. * errors from subroutines * * note: - * if other threads have the directory open when the last link - * is removed, the "." and ".." entries, if present, are removed before - * rmdir() returns and no new entries may be created in the directory, - * but the directory is not removed until the last reference to + * if other threads have the directory open when the last link + * is removed, the "." and ".." entries, if present, are removed before + * rmdir() returns and no new entries may be created in the directory, + * but the directory is not removed until the last reference to * the directory is released (cf.unlink() of regular file). */ static int jfs_rmdir(struct inode *dip, struct dentry *dentry) @@ -365,8 +365,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry) tid = txBegin(dip->i_sb, 0); - mutex_lock(&JFS_IP(dip)->commit_mutex); - mutex_lock(&JFS_IP(ip)->commit_mutex); + mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); + mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); iplist[0] = dip; iplist[1] = ip; @@ -446,11 +446,11 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry) /* * NAME: jfs_unlink(dip, dentry) * - * FUNCTION: remove a link to object named by + * FUNCTION: remove a link to object named by * from parent directory * - * PARAMETER: dip - inode of parent directory - * dentry - dentry of object to be removed + * PARAMETER: dip - inode of parent directory + * dentry - dentry of object to be removed * * RETURN: errors from subroutines * @@ -483,12 +483,12 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry) if ((rc = get_UCSname(&dname, dentry))) goto out; - IWRITE_LOCK(ip); + IWRITE_LOCK(ip, RDWRLOCK_NORMAL); tid = txBegin(dip->i_sb, 0); - mutex_lock(&JFS_IP(dip)->commit_mutex); - mutex_lock(&JFS_IP(ip)->commit_mutex); + mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); + mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); iplist[0] = dip; iplist[1] = ip; @@ -517,7 +517,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry) inode_dec_link_count(ip); /* - * commit zero link count object + * commit zero link count object */ if (ip->i_nlink == 0) { assert(!test_cflag(COMMIT_Nolink, ip)); @@ -596,9 +596,9 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry) /* * NAME: commitZeroLink() * - * FUNCTION: for non-directory, called by jfs_remove(), + * FUNCTION: for non-directory, called by jfs_remove(), * truncate a regular file, directory or symbolic - * link to zero length. return 0 if type is not + * link to zero length. return 0 if type is not * one of these. * * if the file is currently associated with a VM segment @@ -608,7 +608,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry) * map by ctrunc1. * if there is no VM segment on entry, the resources are * freed in both work and permanent map. - * (? for temporary file - memory object is cached even + * (? for temporary file - memory object is cached even * after no reference: * reference count > 0 - ) * @@ -662,7 +662,7 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip) /* * free xtree/data (truncate to zero length): - * free xtree/data pages from cache if COMMIT_PWMAP, + * free xtree/data pages from cache if COMMIT_PWMAP, * free xtree/data blocks from persistent block map, and * free xtree/data blocks from working block map if COMMIT_PWMAP; */ @@ -676,8 +676,8 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip) /* * NAME: jfs_free_zero_link() * - * FUNCTION: for non-directory, called by iClose(), - * free resources of a file from cache and WORKING map + * FUNCTION: for non-directory, called by iClose(), + * free resources of a file from cache and WORKING map * for a file previously committed with zero link count * while associated with a pager object, * @@ -762,7 +762,7 @@ void jfs_free_zero_link(struct inode *ip) * FUNCTION: create a link to by the name = * in the parent directory * - * PARAMETER: vp - target object + * PARAMETER: vp - target object * dvp - parent directory of new link * name - name of new link to target object * crp - credential @@ -802,8 +802,8 @@ static int jfs_link(struct dentry *old_dentry, tid = txBegin(ip->i_sb, 0); - mutex_lock(&JFS_IP(dir)->commit_mutex); - mutex_lock(&JFS_IP(ip)->commit_mutex); + mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT); + mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); /* * scan parent directory for entry/freespace @@ -855,12 +855,12 @@ static int jfs_link(struct dentry *old_dentry, * NAME: jfs_symlink(dip, dentry, name) * * FUNCTION: creates a symbolic link to by name - * in directory + * in directory * - * PARAMETER: dip - parent directory vnode - * dentry - dentry of symbolic link - * name - the path name of the existing object - * that will be the source of the link + * PARAMETER: dip - parent directory vnode + * dentry - dentry of symbolic link + * name - the path name of the existing object + * that will be the source of the link * * RETURN: errors from subroutines * @@ -906,15 +906,15 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, * (iAlloc() returns new, locked inode) */ ip = ialloc(dip, S_IFLNK | 0777); - if (ip == NULL) { - rc = -ENOSPC; + if (IS_ERR(ip)) { + rc = PTR_ERR(ip); goto out2; } tid = txBegin(dip->i_sb, 0); - mutex_lock(&JFS_IP(dip)->commit_mutex); - mutex_lock(&JFS_IP(ip)->commit_mutex); + mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); + mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); rc = jfs_init_security(tid, ip, dip); if (rc) @@ -926,7 +926,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, tblk->u.ixpxd = JFS_IP(ip)->ixpxd; /* fix symlink access permission - * (dir_create() ANDs in the u.u_cmask, + * (dir_create() ANDs in the u.u_cmask, * but symlinks really need to be 777 access) */ ip->i_mode |= 0777; @@ -967,7 +967,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, ip->i_mapping->a_ops = &jfs_aops; /* - * even though the data of symlink object (source + * even though the data of symlink object (source * path name) is treated as non-journaled user data, * it is read/written thru buffer cache for performance. */ @@ -978,7 +978,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, xlen = xsize >> JFS_SBI(sb)->l2bsize; if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) { txAbort(tid, 0); - rc = -ENOSPC; goto out3; } extent = xaddr; @@ -1053,9 +1052,9 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, /* - * NAME: jfs_rename + * NAME: jfs_rename * - * FUNCTION: rename a file or directory + * FUNCTION: rename a file or directory */ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) @@ -1128,7 +1127,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, goto out3; } } else if (new_ip) { - IWRITE_LOCK(new_ip); + IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL); /* Init inode for quota operations. */ DQUOT_INIT(new_ip); } @@ -1138,13 +1137,21 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, */ tid = txBegin(new_dir->i_sb, 0); - mutex_lock(&JFS_IP(new_dir)->commit_mutex); - mutex_lock(&JFS_IP(old_ip)->commit_mutex); + /* + * How do we know the locking is safe from deadlocks? + * The vfs does the hard part for us. Any time we are taking nested + * commit_mutexes, the vfs already has i_mutex held on the parent. + * Here, the vfs has already taken i_mutex on both old_dir and new_dir. + */ + mutex_lock_nested(&JFS_IP(new_dir)->commit_mutex, COMMIT_MUTEX_PARENT); + mutex_lock_nested(&JFS_IP(old_ip)->commit_mutex, COMMIT_MUTEX_CHILD); if (old_dir != new_dir) - mutex_lock(&JFS_IP(old_dir)->commit_mutex); + mutex_lock_nested(&JFS_IP(old_dir)->commit_mutex, + COMMIT_MUTEX_SECOND_PARENT); if (new_ip) { - mutex_lock(&JFS_IP(new_ip)->commit_mutex); + mutex_lock_nested(&JFS_IP(new_ip)->commit_mutex, + COMMIT_MUTEX_VICTIM); /* * Change existing directory entry to new inode number */ @@ -1176,7 +1183,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, /* free block resources */ if ((new_size = commitZeroLink(tid, new_ip)) < 0) { txAbort(tid, 1); /* Marks FS Dirty */ - rc = new_size; + rc = new_size; goto out4; } tblk = tid_to_tblock(tid); @@ -1292,7 +1299,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, new_size = xtTruncate_pmap(tid, new_ip, new_size); if (new_size < 0) { txAbort(tid, 1); - rc = new_size; + rc = new_size; } else rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC); txEnd(tid); @@ -1324,9 +1331,9 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, /* - * NAME: jfs_mknod + * NAME: jfs_mknod * - * FUNCTION: Create a special file (device) + * FUNCTION: Create a special file (device) */ static int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) @@ -1350,16 +1357,16 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, goto out; ip = ialloc(dir, mode); - if (ip == NULL) { - rc = -ENOSPC; + if (IS_ERR(ip)) { + rc = PTR_ERR(ip); goto out1; } jfs_ip = JFS_IP(ip); tid = txBegin(dir->i_sb, 0); - mutex_lock(&JFS_IP(dir)->commit_mutex); - mutex_lock(&JFS_IP(ip)->commit_mutex); + mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT); + mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); rc = jfs_init_acl(tid, ip, dir); if (rc) @@ -1496,7 +1503,7 @@ struct dentry *jfs_get_parent(struct dentry *dentry) return parent; } -struct inode_operations jfs_dir_inode_operations = { +const struct inode_operations jfs_dir_inode_operations = { .create = jfs_create, .lookup = jfs_lookup, .link = jfs_link,