aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2012-08-03 09:43:01 -0400
committerSteve French <smfrench@gmail.com>2012-08-19 23:30:00 -0400
commitb7ca69289680cf631fb20b7d436467c4ec1153cd (patch)
tree94c52c03ebf4efa68cb52df5aa60b554cf6cf999 /fs
parent6dab7ede9390d4d937cb89feca932e4fd575d2da (diff)
CIFS: Protect i_nlink from being negative
that can cause warning messages. Pavel had initially suggested a smaller patch around drop_nlink, after a similar problem was discovered NFS. Protecting additional places where nlink is touched was suggested by Jeff Layton and is included in this. Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/inode.c24
-rw-r--r--fs/cifs/link.c2
2 files changed, 18 insertions, 8 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 7354877fa3bd..cb79c7edecb0 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -124,10 +124,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
124{ 124{
125 struct cifsInodeInfo *cifs_i = CIFS_I(inode); 125 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
126 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 126 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
127 unsigned long oldtime = cifs_i->time;
128 127
129 cifs_revalidate_cache(inode, fattr); 128 cifs_revalidate_cache(inode, fattr);
130 129
130 spin_lock(&inode->i_lock);
131 inode->i_atime = fattr->cf_atime; 131 inode->i_atime = fattr->cf_atime;
132 inode->i_mtime = fattr->cf_mtime; 132 inode->i_mtime = fattr->cf_mtime;
133 inode->i_ctime = fattr->cf_ctime; 133 inode->i_ctime = fattr->cf_ctime;
@@ -148,9 +148,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
148 else 148 else
149 cifs_i->time = jiffies; 149 cifs_i->time = jiffies;
150 150
151 cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode,
152 oldtime, cifs_i->time);
153
154 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; 151 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
155 152
156 cifs_i->server_eof = fattr->cf_eof; 153 cifs_i->server_eof = fattr->cf_eof;
@@ -158,7 +155,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
158 * Can't safely change the file size here if the client is writing to 155 * Can't safely change the file size here if the client is writing to
159 * it due to potential races. 156 * it due to potential races.
160 */ 157 */
161 spin_lock(&inode->i_lock);
162 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { 158 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
163 i_size_write(inode, fattr->cf_eof); 159 i_size_write(inode, fattr->cf_eof);
164 160
@@ -859,12 +855,14 @@ struct inode *cifs_root_iget(struct super_block *sb)
859 855
860 if (rc && tcon->ipc) { 856 if (rc && tcon->ipc) {
861 cFYI(1, "ipc connection - fake read inode"); 857 cFYI(1, "ipc connection - fake read inode");
858 spin_lock(&inode->i_lock);
862 inode->i_mode |= S_IFDIR; 859 inode->i_mode |= S_IFDIR;
863 set_nlink(inode, 2); 860 set_nlink(inode, 2);
864 inode->i_op = &cifs_ipc_inode_ops; 861 inode->i_op = &cifs_ipc_inode_ops;
865 inode->i_fop = &simple_dir_operations; 862 inode->i_fop = &simple_dir_operations;
866 inode->i_uid = cifs_sb->mnt_uid; 863 inode->i_uid = cifs_sb->mnt_uid;
867 inode->i_gid = cifs_sb->mnt_gid; 864 inode->i_gid = cifs_sb->mnt_gid;
865 spin_unlock(&inode->i_lock);
868 } else if (rc) { 866 } else if (rc) {
869 iget_failed(inode); 867 iget_failed(inode);
870 inode = ERR_PTR(rc); 868 inode = ERR_PTR(rc);
@@ -1110,6 +1108,15 @@ undo_setattr:
1110 goto out_close; 1108 goto out_close;
1111} 1109}
1112 1110
1111/* copied from fs/nfs/dir.c with small changes */
1112static void
1113cifs_drop_nlink(struct inode *inode)
1114{
1115 spin_lock(&inode->i_lock);
1116 if (inode->i_nlink > 0)
1117 drop_nlink(inode);
1118 spin_unlock(&inode->i_lock);
1119}
1113 1120
1114/* 1121/*
1115 * If dentry->d_inode is null (usually meaning the cached dentry 1122 * If dentry->d_inode is null (usually meaning the cached dentry
@@ -1166,13 +1173,13 @@ retry_std_delete:
1166psx_del_no_retry: 1173psx_del_no_retry:
1167 if (!rc) { 1174 if (!rc) {
1168 if (inode) 1175 if (inode)
1169 drop_nlink(inode); 1176 cifs_drop_nlink(inode);
1170 } else if (rc == -ENOENT) { 1177 } else if (rc == -ENOENT) {
1171 d_drop(dentry); 1178 d_drop(dentry);
1172 } else if (rc == -ETXTBSY) { 1179 } else if (rc == -ETXTBSY) {
1173 rc = cifs_rename_pending_delete(full_path, dentry, xid); 1180 rc = cifs_rename_pending_delete(full_path, dentry, xid);
1174 if (rc == 0) 1181 if (rc == 0)
1175 drop_nlink(inode); 1182 cifs_drop_nlink(inode);
1176 } else if ((rc == -EACCES) && (dosattr == 0) && inode) { 1183 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
1177 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); 1184 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1178 if (attrs == NULL) { 1185 if (attrs == NULL) {
@@ -1241,9 +1248,10 @@ cifs_mkdir_qinfo(struct inode *inode, struct dentry *dentry, umode_t mode,
1241 * setting nlink not necessary except in cases where we failed to get it 1248 * setting nlink not necessary except in cases where we failed to get it
1242 * from the server or was set bogus 1249 * from the server or was set bogus
1243 */ 1250 */
1251 spin_lock(&dentry->d_inode->i_lock);
1244 if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2)) 1252 if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2))
1245 set_nlink(dentry->d_inode, 2); 1253 set_nlink(dentry->d_inode, 2);
1246 1254 spin_unlock(&dentry->d_inode->i_lock);
1247 mode &= ~current_umask(); 1255 mode &= ~current_umask();
1248 /* must turn on setgid bit if parent dir has it */ 1256 /* must turn on setgid bit if parent dir has it */
1249 if (inode->i_mode & S_ISGID) 1257 if (inode->i_mode & S_ISGID)
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 09e4b3ae4564..e6ce3b112875 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -433,7 +433,9 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
433 if (old_file->d_inode) { 433 if (old_file->d_inode) {
434 cifsInode = CIFS_I(old_file->d_inode); 434 cifsInode = CIFS_I(old_file->d_inode);
435 if (rc == 0) { 435 if (rc == 0) {
436 spin_lock(&old_file->d_inode->i_lock);
436 inc_nlink(old_file->d_inode); 437 inc_nlink(old_file->d_inode);
438 spin_unlock(&old_file->d_inode->i_lock);
437/* BB should we make this contingent on superblock flag NOATIME? */ 439/* BB should we make this contingent on superblock flag NOATIME? */
438/* old_file->d_inode->i_ctime = CURRENT_TIME;*/ 440/* old_file->d_inode->i_ctime = CURRENT_TIME;*/
439 /* parent dir timestamps will update from srv 441 /* parent dir timestamps will update from srv