diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/binfmt_elf.c | 2 | ||||
-rw-r--r-- | fs/binfmt_flat.c | 6 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 3 | ||||
-rw-r--r-- | fs/cifs/README | 4 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 56 | ||||
-rw-r--r-- | fs/cifs/dir.c | 3 | ||||
-rw-r--r-- | fs/cifs/file.c | 2 | ||||
-rw-r--r-- | fs/cifs/inode.c | 48 | ||||
-rw-r--r-- | fs/cifs/misc.c | 1 | ||||
-rw-r--r-- | fs/coda/psdev.c | 18 | ||||
-rw-r--r-- | fs/debugfs/file.c | 67 | ||||
-rw-r--r-- | fs/exec.c | 16 | ||||
-rw-r--r-- | fs/hostfs/hostfs_kern.c | 1 | ||||
-rw-r--r-- | fs/jbd/checkpoint.c | 5 | ||||
-rw-r--r-- | fs/libfs.c | 100 | ||||
-rw-r--r-- | fs/mpage.c | 5 | ||||
-rw-r--r-- | fs/namei.c | 153 | ||||
-rw-r--r-- | fs/nfs/dir.c | 49 | ||||
-rw-r--r-- | fs/nfs/file.c | 42 | ||||
-rw-r--r-- | fs/proc/proc_devtree.c | 105 | ||||
-rw-r--r-- | fs/sysfs/bin.c | 4 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 26 | ||||
-rw-r--r-- | fs/sysfs/file.c | 6 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 102 | ||||
-rw-r--r-- | fs/sysfs/mount.c | 4 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 8 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 4 | ||||
-rw-r--r-- | fs/udf/udftime.c | 2 |
30 files changed, 549 insertions, 297 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index c374be51b041..f8f6b6b76179 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1125,7 +1125,7 @@ static int dump_write(struct file *file, const void *addr, int nr) | |||
1125 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; | 1125 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; |
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | static int dump_seek(struct file *file, off_t off) | 1128 | static int dump_seek(struct file *file, loff_t off) |
1129 | { | 1129 | { |
1130 | if (file->f_op->llseek) { | 1130 | if (file->f_op->llseek) { |
1131 | if (file->f_op->llseek(file, off, 0) != off) | 1131 | if (file->f_op->llseek(file, off, 0) != off) |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index f0cd67d9d31b..c8998dc66882 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
520 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); | 520 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); |
521 | 521 | ||
522 | down_write(¤t->mm->mmap_sem); | 522 | down_write(¤t->mm->mmap_sem); |
523 | textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, 0, 0); | 523 | textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0); |
524 | up_write(¤t->mm->mmap_sem); | 524 | up_write(¤t->mm->mmap_sem); |
525 | if (!textpos || textpos >= (unsigned long) -4096) { | 525 | if (!textpos || textpos >= (unsigned long) -4096) { |
526 | if (!textpos) | 526 | if (!textpos) |
@@ -532,7 +532,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
532 | down_write(¤t->mm->mmap_sem); | 532 | down_write(¤t->mm->mmap_sem); |
533 | realdatastart = do_mmap(0, 0, data_len + extra + | 533 | realdatastart = do_mmap(0, 0, data_len + extra + |
534 | MAX_SHARED_LIBS * sizeof(unsigned long), | 534 | MAX_SHARED_LIBS * sizeof(unsigned long), |
535 | PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0); | 535 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); |
536 | up_write(¤t->mm->mmap_sem); | 536 | up_write(¤t->mm->mmap_sem); |
537 | 537 | ||
538 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { | 538 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { |
@@ -574,7 +574,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
574 | down_write(¤t->mm->mmap_sem); | 574 | down_write(¤t->mm->mmap_sem); |
575 | textpos = do_mmap(0, 0, text_len + data_len + extra + | 575 | textpos = do_mmap(0, 0, text_len + data_len + extra + |
576 | MAX_SHARED_LIBS * sizeof(unsigned long), | 576 | MAX_SHARED_LIBS * sizeof(unsigned long), |
577 | PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0); | 577 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); |
578 | up_write(¤t->mm->mmap_sem); | 578 | up_write(¤t->mm->mmap_sem); |
579 | if (!textpos || textpos >= (unsigned long) -4096) { | 579 | if (!textpos || textpos >= (unsigned long) -4096) { |
580 | if (!textpos) | 580 | if (!textpos) |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 95483baab706..dab4774ee7bb 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -6,7 +6,8 @@ kills the cifsd thread (NB: killing the cifs kernel threads is not | |||
6 | recommended, unmount and rmmod cifs will kill them when they are | 6 | recommended, unmount and rmmod cifs will kill them when they are |
7 | no longer needed). Fix readdir to ASCII servers (ie older servers | 7 | no longer needed). Fix readdir to ASCII servers (ie older servers |
8 | which do not support Unicode) and also require asterik. | 8 | which do not support Unicode) and also require asterik. |
9 | 9 | Fix out of memory case in which data could be written one page | |
10 | off in the page cache. | ||
10 | 11 | ||
11 | Version 1.33 | 12 | Version 1.33 |
12 | ------------ | 13 | ------------ |
diff --git a/fs/cifs/README b/fs/cifs/README index e74df0c73256..34b0cf7111f3 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -371,7 +371,7 @@ A partial list of the supported mount options follows: | |||
371 | on newly created files, directories, and devices (create, | 371 | on newly created files, directories, and devices (create, |
372 | mkdir, mknod) which will result in the server setting the | 372 | mkdir, mknod) which will result in the server setting the |
373 | uid and gid to the default (usually the server uid of the | 373 | uid and gid to the default (usually the server uid of the |
374 | usern who mounted the share). Letting the server (rather than | 374 | user who mounted the share). Letting the server (rather than |
375 | the client) set the uid and gid is the default. This | 375 | the client) set the uid and gid is the default. This |
376 | parameter has no effect if the CIFS Unix Extensions are not | 376 | parameter has no effect if the CIFS Unix Extensions are not |
377 | negotiated. | 377 | negotiated. |
@@ -384,7 +384,7 @@ A partial list of the supported mount options follows: | |||
384 | client (e.g. when the application is doing large sequential | 384 | client (e.g. when the application is doing large sequential |
385 | reads bigger than page size without rereading the same data) | 385 | reads bigger than page size without rereading the same data) |
386 | this can provide better performance than the default | 386 | this can provide better performance than the default |
387 | behavior which caches reads (reaadahead) and writes | 387 | behavior which caches reads (readahead) and writes |
388 | (writebehind) through the local Linux client pagecache | 388 | (writebehind) through the local Linux client pagecache |
389 | if oplock (caching token) is granted and held. Note that | 389 | if oplock (caching token) is granted and held. Note that |
390 | direct allows write operations larger than page size | 390 | direct allows write operations larger than page size |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index d00b3bfe1a52..78af5850c558 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -96,5 +96,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | |||
96 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 96 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
97 | extern int cifs_ioctl (struct inode * inode, struct file * filep, | 97 | extern int cifs_ioctl (struct inode * inode, struct file * filep, |
98 | unsigned int command, unsigned long arg); | 98 | unsigned int command, unsigned long arg); |
99 | #define CIFS_VERSION "1.34" | 99 | #define CIFS_VERSION "1.35" |
100 | #endif /* _CIFSFS_H */ | 100 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0010511083fc..ea239dea571e 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -228,7 +228,7 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | |||
228 | const struct nls_table *nls_codepage, | 228 | const struct nls_table *nls_codepage, |
229 | int remap_special_chars); | 229 | int remap_special_chars); |
230 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 230 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
231 | extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen, | 231 | extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, |
232 | const struct nls_table * codepage); | 232 | const struct nls_table * codepage); |
233 | extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, | 233 | extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, |
234 | const struct nls_table * cp, int mapChars); | 234 | const struct nls_table * cp, int mapChars); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 741ff0c69f37..3c628bf667a5 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -567,7 +567,7 @@ DelFileRetry: | |||
567 | 567 | ||
568 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 568 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
569 | name_len = | 569 | name_len = |
570 | cifsConvertToUCS((__u16 *) pSMB->fileName, fileName, | 570 | cifsConvertToUCS((__le16 *) pSMB->fileName, fileName, |
571 | PATH_MAX, nls_codepage, remap); | 571 | PATH_MAX, nls_codepage, remap); |
572 | name_len++; /* trailing null */ | 572 | name_len++; /* trailing null */ |
573 | name_len *= 2; | 573 | name_len *= 2; |
@@ -665,7 +665,7 @@ MkDirRetry: | |||
665 | return rc; | 665 | return rc; |
666 | 666 | ||
667 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 667 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
668 | name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name, | 668 | name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name, |
669 | PATH_MAX, nls_codepage, remap); | 669 | PATH_MAX, nls_codepage, remap); |
670 | name_len++; /* trailing null */ | 670 | name_len++; /* trailing null */ |
671 | name_len *= 2; | 671 | name_len *= 2; |
@@ -719,7 +719,7 @@ openRetry: | |||
719 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 719 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
720 | count = 1; /* account for one byte pad to word boundary */ | 720 | count = 1; /* account for one byte pad to word boundary */ |
721 | name_len = | 721 | name_len = |
722 | cifsConvertToUCS((__u16 *) (pSMB->fileName + 1), | 722 | cifsConvertToUCS((__le16 *) (pSMB->fileName + 1), |
723 | fileName, PATH_MAX, nls_codepage, remap); | 723 | fileName, PATH_MAX, nls_codepage, remap); |
724 | name_len++; /* trailing null */ | 724 | name_len++; /* trailing null */ |
725 | name_len *= 2; | 725 | name_len *= 2; |
@@ -1141,7 +1141,7 @@ renameRetry: | |||
1141 | 1141 | ||
1142 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1142 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1143 | name_len = | 1143 | name_len = |
1144 | cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName, | 1144 | cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, |
1145 | PATH_MAX, nls_codepage, remap); | 1145 | PATH_MAX, nls_codepage, remap); |
1146 | name_len++; /* trailing null */ | 1146 | name_len++; /* trailing null */ |
1147 | name_len *= 2; | 1147 | name_len *= 2; |
@@ -1149,7 +1149,7 @@ renameRetry: | |||
1149 | /* protocol requires ASCII signature byte on Unicode string */ | 1149 | /* protocol requires ASCII signature byte on Unicode string */ |
1150 | pSMB->OldFileName[name_len + 1] = 0x00; | 1150 | pSMB->OldFileName[name_len + 1] = 0x00; |
1151 | name_len2 = | 1151 | name_len2 = |
1152 | cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2], | 1152 | cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2], |
1153 | toName, PATH_MAX, nls_codepage, remap); | 1153 | toName, PATH_MAX, nls_codepage, remap); |
1154 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; | 1154 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; |
1155 | name_len2 *= 2; /* convert to bytes */ | 1155 | name_len2 *= 2; /* convert to bytes */ |
@@ -1236,10 +1236,10 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, | |||
1236 | /* unicode only call */ | 1236 | /* unicode only call */ |
1237 | if(target_name == NULL) { | 1237 | if(target_name == NULL) { |
1238 | sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid); | 1238 | sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid); |
1239 | len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name, | 1239 | len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name, |
1240 | dummy_string, 24, nls_codepage, remap); | 1240 | dummy_string, 24, nls_codepage, remap); |
1241 | } else { | 1241 | } else { |
1242 | len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name, | 1242 | len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name, |
1243 | target_name, PATH_MAX, nls_codepage, remap); | 1243 | target_name, PATH_MAX, nls_codepage, remap); |
1244 | } | 1244 | } |
1245 | rename_info->target_name_len = cpu_to_le32(2 * len_of_str); | 1245 | rename_info->target_name_len = cpu_to_le32(2 * len_of_str); |
@@ -1296,7 +1296,7 @@ copyRetry: | |||
1296 | pSMB->Flags = cpu_to_le16(flags & COPY_TREE); | 1296 | pSMB->Flags = cpu_to_le16(flags & COPY_TREE); |
1297 | 1297 | ||
1298 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1298 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1299 | name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName, | 1299 | name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName, |
1300 | fromName, PATH_MAX, nls_codepage, | 1300 | fromName, PATH_MAX, nls_codepage, |
1301 | remap); | 1301 | remap); |
1302 | name_len++; /* trailing null */ | 1302 | name_len++; /* trailing null */ |
@@ -1304,7 +1304,7 @@ copyRetry: | |||
1304 | pSMB->OldFileName[name_len] = 0x04; /* pad */ | 1304 | pSMB->OldFileName[name_len] = 0x04; /* pad */ |
1305 | /* protocol requires ASCII signature byte on Unicode string */ | 1305 | /* protocol requires ASCII signature byte on Unicode string */ |
1306 | pSMB->OldFileName[name_len + 1] = 0x00; | 1306 | pSMB->OldFileName[name_len + 1] = 0x00; |
1307 | name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], | 1307 | name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], |
1308 | toName, PATH_MAX, nls_codepage, remap); | 1308 | toName, PATH_MAX, nls_codepage, remap); |
1309 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; | 1309 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; |
1310 | name_len2 *= 2; /* convert to bytes */ | 1310 | name_len2 *= 2; /* convert to bytes */ |
@@ -1453,7 +1453,7 @@ createHardLinkRetry: | |||
1453 | return rc; | 1453 | return rc; |
1454 | 1454 | ||
1455 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1455 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1456 | name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName, | 1456 | name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName, |
1457 | PATH_MAX, nls_codepage, remap); | 1457 | PATH_MAX, nls_codepage, remap); |
1458 | name_len++; /* trailing null */ | 1458 | name_len++; /* trailing null */ |
1459 | name_len *= 2; | 1459 | name_len *= 2; |
@@ -1476,7 +1476,7 @@ createHardLinkRetry: | |||
1476 | data_offset = (char *) (&pSMB->hdr.Protocol) + offset; | 1476 | data_offset = (char *) (&pSMB->hdr.Protocol) + offset; |
1477 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1477 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1478 | name_len_target = | 1478 | name_len_target = |
1479 | cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX, | 1479 | cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX, |
1480 | nls_codepage, remap); | 1480 | nls_codepage, remap); |
1481 | name_len_target++; /* trailing null */ | 1481 | name_len_target++; /* trailing null */ |
1482 | name_len_target *= 2; | 1482 | name_len_target *= 2; |
@@ -1546,14 +1546,14 @@ winCreateHardLinkRetry: | |||
1546 | 1546 | ||
1547 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1547 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1548 | name_len = | 1548 | name_len = |
1549 | cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName, | 1549 | cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, |
1550 | PATH_MAX, nls_codepage, remap); | 1550 | PATH_MAX, nls_codepage, remap); |
1551 | name_len++; /* trailing null */ | 1551 | name_len++; /* trailing null */ |
1552 | name_len *= 2; | 1552 | name_len *= 2; |
1553 | pSMB->OldFileName[name_len] = 0; /* pad */ | 1553 | pSMB->OldFileName[name_len] = 0; /* pad */ |
1554 | pSMB->OldFileName[name_len + 1] = 0x04; | 1554 | pSMB->OldFileName[name_len + 1] = 0x04; |
1555 | name_len2 = | 1555 | name_len2 = |
1556 | cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], | 1556 | cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], |
1557 | toName, PATH_MAX, nls_codepage, remap); | 1557 | toName, PATH_MAX, nls_codepage, remap); |
1558 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; | 1558 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; |
1559 | name_len2 *= 2; /* convert to bytes */ | 1559 | name_len2 *= 2; /* convert to bytes */ |
@@ -1939,7 +1939,7 @@ queryAclRetry: | |||
1939 | 1939 | ||
1940 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1940 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1941 | name_len = | 1941 | name_len = |
1942 | cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, | 1942 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, |
1943 | PATH_MAX, nls_codepage, remap); | 1943 | PATH_MAX, nls_codepage, remap); |
1944 | name_len++; /* trailing null */ | 1944 | name_len++; /* trailing null */ |
1945 | name_len *= 2; | 1945 | name_len *= 2; |
@@ -2024,7 +2024,7 @@ setAclRetry: | |||
2024 | return rc; | 2024 | return rc; |
2025 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 2025 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
2026 | name_len = | 2026 | name_len = |
2027 | cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, | 2027 | cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, |
2028 | PATH_MAX, nls_codepage, remap); | 2028 | PATH_MAX, nls_codepage, remap); |
2029 | name_len++; /* trailing null */ | 2029 | name_len++; /* trailing null */ |
2030 | name_len *= 2; | 2030 | name_len *= 2; |
@@ -2188,7 +2188,7 @@ QPathInfoRetry: | |||
2188 | 2188 | ||
2189 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 2189 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
2190 | name_len = | 2190 | name_len = |
2191 | cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, | 2191 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, |
2192 | PATH_MAX, nls_codepage, remap); | 2192 | PATH_MAX, nls_codepage, remap); |
2193 | name_len++; /* trailing null */ | 2193 | name_len++; /* trailing null */ |
2194 | name_len *= 2; | 2194 | name_len *= 2; |
@@ -2269,7 +2269,7 @@ UnixQPathInfoRetry: | |||
2269 | 2269 | ||
2270 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 2270 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
2271 | name_len = | 2271 | name_len = |
2272 | cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, | 2272 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, |
2273 | PATH_MAX, nls_codepage, remap); | 2273 | PATH_MAX, nls_codepage, remap); |
2274 | name_len++; /* trailing null */ | 2274 | name_len++; /* trailing null */ |
2275 | name_len *= 2; | 2275 | name_len *= 2; |
@@ -2350,7 +2350,7 @@ findUniqueRetry: | |||
2350 | 2350 | ||
2351 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 2351 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
2352 | name_len = | 2352 | name_len = |
2353 | cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX | 2353 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX |
2354 | /* find define for this maxpathcomponent */ | 2354 | /* find define for this maxpathcomponent */ |
2355 | , nls_codepage); | 2355 | , nls_codepage); |
2356 | name_len++; /* trailing null */ | 2356 | name_len++; /* trailing null */ |
@@ -2435,7 +2435,7 @@ findFirstRetry: | |||
2435 | 2435 | ||
2436 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 2436 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
2437 | name_len = | 2437 | name_len = |
2438 | cifsConvertToUCS((__u16 *) pSMB->FileName,searchName, | 2438 | cifsConvertToUCS((__le16 *) pSMB->FileName,searchName, |
2439 | PATH_MAX, nls_codepage, remap); | 2439 | PATH_MAX, nls_codepage, remap); |
2440 | /* We can not add the asterik earlier in case | 2440 | /* We can not add the asterik earlier in case |
2441 | it got remapped to 0xF03A as if it were part of the | 2441 | it got remapped to 0xF03A as if it were part of the |
@@ -2726,7 +2726,7 @@ GetInodeNumberRetry: | |||
2726 | 2726 | ||
2727 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 2727 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
2728 | name_len = | 2728 | name_len = |
2729 | cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, | 2729 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, |
2730 | PATH_MAX,nls_codepage, remap); | 2730 | PATH_MAX,nls_codepage, remap); |
2731 | name_len++; /* trailing null */ | 2731 | name_len++; /* trailing null */ |
2732 | name_len *= 2; | 2732 | name_len *= 2; |
@@ -2837,7 +2837,7 @@ getDFSRetry: | |||
2837 | if (ses->capabilities & CAP_UNICODE) { | 2837 | if (ses->capabilities & CAP_UNICODE) { |
2838 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; | 2838 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; |
2839 | name_len = | 2839 | name_len = |
2840 | cifsConvertToUCS((__u16 *) pSMB->RequestFileName, | 2840 | cifsConvertToUCS((__le16 *) pSMB->RequestFileName, |
2841 | searchName, PATH_MAX, nls_codepage, remap); | 2841 | searchName, PATH_MAX, nls_codepage, remap); |
2842 | name_len++; /* trailing null */ | 2842 | name_len++; /* trailing null */ |
2843 | name_len *= 2; | 2843 | name_len *= 2; |
@@ -3369,7 +3369,7 @@ SetEOFRetry: | |||
3369 | 3369 | ||
3370 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 3370 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
3371 | name_len = | 3371 | name_len = |
3372 | cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, | 3372 | cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, |
3373 | PATH_MAX, nls_codepage, remap); | 3373 | PATH_MAX, nls_codepage, remap); |
3374 | name_len++; /* trailing null */ | 3374 | name_len++; /* trailing null */ |
3375 | name_len *= 2; | 3375 | name_len *= 2; |
@@ -3627,7 +3627,7 @@ SetTimesRetry: | |||
3627 | 3627 | ||
3628 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 3628 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
3629 | name_len = | 3629 | name_len = |
3630 | cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, | 3630 | cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, |
3631 | PATH_MAX, nls_codepage, remap); | 3631 | PATH_MAX, nls_codepage, remap); |
3632 | name_len++; /* trailing null */ | 3632 | name_len++; /* trailing null */ |
3633 | name_len *= 2; | 3633 | name_len *= 2; |
@@ -3708,7 +3708,7 @@ SetAttrLgcyRetry: | |||
3708 | 3708 | ||
3709 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 3709 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
3710 | name_len = | 3710 | name_len = |
3711 | ConvertToUCS((wchar_t *) pSMB->fileName, fileName, | 3711 | ConvertToUCS((__le16 *) pSMB->fileName, fileName, |
3712 | PATH_MAX, nls_codepage); | 3712 | PATH_MAX, nls_codepage); |
3713 | name_len++; /* trailing null */ | 3713 | name_len++; /* trailing null */ |
3714 | name_len *= 2; | 3714 | name_len *= 2; |
@@ -3759,7 +3759,7 @@ setPermsRetry: | |||
3759 | 3759 | ||
3760 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 3760 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
3761 | name_len = | 3761 | name_len = |
3762 | cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, | 3762 | cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, |
3763 | PATH_MAX, nls_codepage, remap); | 3763 | PATH_MAX, nls_codepage, remap); |
3764 | name_len++; /* trailing null */ | 3764 | name_len++; /* trailing null */ |
3765 | name_len *= 2; | 3765 | name_len *= 2; |
@@ -3904,7 +3904,7 @@ QAllEAsRetry: | |||
3904 | 3904 | ||
3905 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 3905 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
3906 | name_len = | 3906 | name_len = |
3907 | cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, | 3907 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, |
3908 | PATH_MAX, nls_codepage, remap); | 3908 | PATH_MAX, nls_codepage, remap); |
3909 | name_len++; /* trailing null */ | 3909 | name_len++; /* trailing null */ |
3910 | name_len *= 2; | 3910 | name_len *= 2; |
@@ -4047,7 +4047,7 @@ QEARetry: | |||
4047 | 4047 | ||
4048 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 4048 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
4049 | name_len = | 4049 | name_len = |
4050 | cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, | 4050 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, |
4051 | PATH_MAX, nls_codepage, remap); | 4051 | PATH_MAX, nls_codepage, remap); |
4052 | name_len++; /* trailing null */ | 4052 | name_len++; /* trailing null */ |
4053 | name_len *= 2; | 4053 | name_len *= 2; |
@@ -4194,7 +4194,7 @@ SetEARetry: | |||
4194 | 4194 | ||
4195 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 4195 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
4196 | name_len = | 4196 | name_len = |
4197 | cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, | 4197 | cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, |
4198 | PATH_MAX, nls_codepage, remap); | 4198 | PATH_MAX, nls_codepage, remap); |
4199 | name_len++; /* trailing null */ | 4199 | name_len++; /* trailing null */ |
4200 | name_len *= 2; | 4200 | name_len *= 2; |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e3137aa48cdd..3f3538d4a1fa 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -392,7 +392,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
392 | rc = 0; | 392 | rc = 0; |
393 | d_add(direntry, NULL); | 393 | d_add(direntry, NULL); |
394 | } else { | 394 | } else { |
395 | cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc)); | 395 | cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", |
396 | rc,full_path)); | ||
396 | /* BB special case check for Access Denied - watch security | 397 | /* BB special case check for Access Denied - watch security |
397 | exposure of returning dir info implicitly via different rc | 398 | exposure of returning dir info implicitly via different rc |
398 | if file exists or not but no access BB */ | 399 | if file exists or not but no access BB */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index dde2d251fc3d..30ab70ce5547 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1352,6 +1352,8 @@ static void cifs_copy_cache_pages(struct address_space *mapping, | |||
1352 | GFP_KERNEL)) { | 1352 | GFP_KERNEL)) { |
1353 | page_cache_release(page); | 1353 | page_cache_release(page); |
1354 | cFYI(1, ("Add page cache failed")); | 1354 | cFYI(1, ("Add page cache failed")); |
1355 | data += PAGE_CACHE_SIZE; | ||
1356 | bytes_read -= PAGE_CACHE_SIZE; | ||
1355 | continue; | 1357 | continue; |
1356 | } | 1358 | } |
1357 | 1359 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 670947288262..8d336a900255 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -82,12 +82,12 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
82 | /* get new inode */ | 82 | /* get new inode */ |
83 | if (*pinode == NULL) { | 83 | if (*pinode == NULL) { |
84 | *pinode = new_inode(sb); | 84 | *pinode = new_inode(sb); |
85 | if(*pinode == NULL) | 85 | if (*pinode == NULL) |
86 | return -ENOMEM; | 86 | return -ENOMEM; |
87 | /* Is an i_ino of zero legal? */ | 87 | /* Is an i_ino of zero legal? */ |
88 | /* Are there sanity checks we can use to ensure that | 88 | /* Are there sanity checks we can use to ensure that |
89 | the server is really filling in that field? */ | 89 | the server is really filling in that field? */ |
90 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 90 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
91 | (*pinode)->i_ino = | 91 | (*pinode)->i_ino = |
92 | (unsigned long)findData.UniqueId; | 92 | (unsigned long)findData.UniqueId; |
93 | } /* note ino incremented to unique num in new_inode */ | 93 | } /* note ino incremented to unique num in new_inode */ |
@@ -134,7 +134,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
134 | inode->i_gid = le64_to_cpu(findData.Gid); | 134 | inode->i_gid = le64_to_cpu(findData.Gid); |
135 | inode->i_nlink = le64_to_cpu(findData.Nlinks); | 135 | inode->i_nlink = le64_to_cpu(findData.Nlinks); |
136 | 136 | ||
137 | if(is_size_safe_to_change(cifsInfo)) { | 137 | if (is_size_safe_to_change(cifsInfo)) { |
138 | /* can not safely change the file size here if the | 138 | /* can not safely change the file size here if the |
139 | client is writing to it due to potential races */ | 139 | client is writing to it due to potential races */ |
140 | 140 | ||
@@ -162,7 +162,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
162 | if (S_ISREG(inode->i_mode)) { | 162 | if (S_ISREG(inode->i_mode)) { |
163 | cFYI(1, (" File inode ")); | 163 | cFYI(1, (" File inode ")); |
164 | inode->i_op = &cifs_file_inode_ops; | 164 | inode->i_op = &cifs_file_inode_ops; |
165 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | 165 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) |
166 | inode->i_fop = &cifs_file_direct_ops; | 166 | inode->i_fop = &cifs_file_direct_ops; |
167 | else | 167 | else |
168 | inode->i_fop = &cifs_file_ops; | 168 | inode->i_fop = &cifs_file_ops; |
@@ -198,17 +198,17 @@ int cifs_get_inode_info(struct inode **pinode, | |||
198 | pTcon = cifs_sb->tcon; | 198 | pTcon = cifs_sb->tcon; |
199 | cFYI(1,("Getting info on %s ", search_path)); | 199 | cFYI(1,("Getting info on %s ", search_path)); |
200 | 200 | ||
201 | if((pfindData == NULL) && (*pinode != NULL)) { | 201 | if ((pfindData == NULL) && (*pinode != NULL)) { |
202 | if(CIFS_I(*pinode)->clientCanCacheRead) { | 202 | if (CIFS_I(*pinode)->clientCanCacheRead) { |
203 | cFYI(1,("No need to revalidate cached inode sizes")); | 203 | cFYI(1,("No need to revalidate cached inode sizes")); |
204 | return rc; | 204 | return rc; |
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | /* if file info not passed in then get it from server */ | 208 | /* if file info not passed in then get it from server */ |
209 | if(pfindData == NULL) { | 209 | if (pfindData == NULL) { |
210 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 210 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
211 | if(buf == NULL) | 211 | if (buf == NULL) |
212 | return -ENOMEM; | 212 | return -ENOMEM; |
213 | pfindData = (FILE_ALL_INFO *)buf; | 213 | pfindData = (FILE_ALL_INFO *)buf; |
214 | /* could do find first instead but this returns more info */ | 214 | /* could do find first instead but this returns more info */ |
@@ -268,7 +268,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
268 | IndexNumber field is not guaranteed unique? */ | 268 | IndexNumber field is not guaranteed unique? */ |
269 | 269 | ||
270 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 270 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
271 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){ | 271 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){ |
272 | int rc1 = 0; | 272 | int rc1 = 0; |
273 | __u64 inode_num; | 273 | __u64 inode_num; |
274 | 274 | ||
@@ -277,7 +277,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
277 | cifs_sb->local_nls, | 277 | cifs_sb->local_nls, |
278 | cifs_sb->mnt_cifs_flags & | 278 | cifs_sb->mnt_cifs_flags & |
279 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 279 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
280 | if(rc1) { | 280 | if (rc1) { |
281 | cFYI(1,("GetSrvInodeNum rc %d", rc1)); | 281 | cFYI(1,("GetSrvInodeNum rc %d", rc1)); |
282 | /* BB EOPNOSUPP disable SERVER_INUM? */ | 282 | /* BB EOPNOSUPP disable SERVER_INUM? */ |
283 | } else /* do we need cast or hash to ino? */ | 283 | } else /* do we need cast or hash to ino? */ |
@@ -355,7 +355,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
355 | if (S_ISREG(inode->i_mode)) { | 355 | if (S_ISREG(inode->i_mode)) { |
356 | cFYI(1, (" File inode ")); | 356 | cFYI(1, (" File inode ")); |
357 | inode->i_op = &cifs_file_inode_ops; | 357 | inode->i_op = &cifs_file_inode_ops; |
358 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | 358 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) |
359 | inode->i_fop = &cifs_file_direct_ops; | 359 | inode->i_fop = &cifs_file_direct_ops; |
360 | else | 360 | else |
361 | inode->i_fop = &cifs_file_ops; | 361 | inode->i_fop = &cifs_file_ops; |
@@ -422,7 +422,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
422 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 422 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
423 | 423 | ||
424 | if (!rc) { | 424 | if (!rc) { |
425 | direntry->d_inode->i_nlink--; | 425 | if (direntry->d_inode) |
426 | direntry->d_inode->i_nlink--; | ||
426 | } else if (rc == -ENOENT) { | 427 | } else if (rc == -ENOENT) { |
427 | d_drop(direntry); | 428 | d_drop(direntry); |
428 | } else if (rc == -ETXTBSY) { | 429 | } else if (rc == -ETXTBSY) { |
@@ -440,7 +441,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
440 | cifs_sb->mnt_cifs_flags & | 441 | cifs_sb->mnt_cifs_flags & |
441 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 442 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
442 | CIFSSMBClose(xid, pTcon, netfid); | 443 | CIFSSMBClose(xid, pTcon, netfid); |
443 | direntry->d_inode->i_nlink--; | 444 | if (direntry->d_inode) |
445 | direntry->d_inode->i_nlink--; | ||
444 | } | 446 | } |
445 | } else if (rc == -EACCES) { | 447 | } else if (rc == -EACCES) { |
446 | /* try only if r/o attribute set in local lookup data? */ | 448 | /* try only if r/o attribute set in local lookup data? */ |
@@ -494,7 +496,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
494 | cifs_sb->mnt_cifs_flags & | 496 | cifs_sb->mnt_cifs_flags & |
495 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 497 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
496 | if (!rc) { | 498 | if (!rc) { |
497 | direntry->d_inode->i_nlink--; | 499 | if (direntry->d_inode) |
500 | direntry->d_inode->i_nlink--; | ||
498 | } else if (rc == -ETXTBSY) { | 501 | } else if (rc == -ETXTBSY) { |
499 | int oplock = FALSE; | 502 | int oplock = FALSE; |
500 | __u16 netfid; | 503 | __u16 netfid; |
@@ -514,17 +517,20 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
514 | cifs_sb->mnt_cifs_flags & | 517 | cifs_sb->mnt_cifs_flags & |
515 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 518 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
516 | CIFSSMBClose(xid, pTcon, netfid); | 519 | CIFSSMBClose(xid, pTcon, netfid); |
517 | direntry->d_inode->i_nlink--; | 520 | if (direntry->d_inode) |
521 | direntry->d_inode->i_nlink--; | ||
518 | } | 522 | } |
519 | /* BB if rc = -ETXTBUSY goto the rename logic BB */ | 523 | /* BB if rc = -ETXTBUSY goto the rename logic BB */ |
520 | } | 524 | } |
521 | } | 525 | } |
522 | } | 526 | } |
523 | cifsInode = CIFS_I(direntry->d_inode); | 527 | if (direntry->d_inode) { |
524 | cifsInode->time = 0; /* will force revalidate to get info when | 528 | cifsInode = CIFS_I(direntry->d_inode); |
525 | needed */ | 529 | cifsInode->time = 0; /* will force revalidate to get info |
526 | direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = | 530 | when needed */ |
527 | current_fs_time(inode->i_sb); | 531 | direntry->d_inode->i_ctime = current_fs_time(inode->i_sb); |
532 | } | ||
533 | inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); | ||
528 | cifsInode = CIFS_I(inode); | 534 | cifsInode = CIFS_I(inode); |
529 | cifsInode->time = 0; /* force revalidate of dir as well */ | 535 | cifsInode->time = 0; /* force revalidate of dir as well */ |
530 | 536 | ||
@@ -576,7 +582,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
576 | if (direntry->d_inode) | 582 | if (direntry->d_inode) |
577 | direntry->d_inode->i_nlink = 2; | 583 | direntry->d_inode->i_nlink = 2; |
578 | if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) | 584 | if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) |
579 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 585 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
580 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 586 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, |
581 | mode, | 587 | mode, |
582 | (__u64)current->euid, | 588 | (__u64)current->euid, |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index db14b503d89e..072b4ee8c53e 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -571,6 +571,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, | |||
571 | break; | 571 | break; |
572 | case UNI_LESSTHAN: | 572 | case UNI_LESSTHAN: |
573 | target[j] = '<'; | 573 | target[j] = '<'; |
574 | break; | ||
574 | default: | 575 | default: |
575 | len = cp->uni2char(src_char, &target[j], | 576 | len = cp->uni2char(src_char, &target[j], |
576 | NLS_MAX_CHARSET_SIZE); | 577 | NLS_MAX_CHARSET_SIZE); |
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index ef001a9313e6..3d1cce3653b8 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c | |||
@@ -61,7 +61,7 @@ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */ | |||
61 | 61 | ||
62 | 62 | ||
63 | struct venus_comm coda_comms[MAX_CODADEVS]; | 63 | struct venus_comm coda_comms[MAX_CODADEVS]; |
64 | static struct class_simple *coda_psdev_class; | 64 | static struct class *coda_psdev_class; |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * Device operations | 67 | * Device operations |
@@ -363,14 +363,14 @@ static int init_coda_psdev(void) | |||
363 | CODA_PSDEV_MAJOR); | 363 | CODA_PSDEV_MAJOR); |
364 | return -EIO; | 364 | return -EIO; |
365 | } | 365 | } |
366 | coda_psdev_class = class_simple_create(THIS_MODULE, "coda"); | 366 | coda_psdev_class = class_create(THIS_MODULE, "coda"); |
367 | if (IS_ERR(coda_psdev_class)) { | 367 | if (IS_ERR(coda_psdev_class)) { |
368 | err = PTR_ERR(coda_psdev_class); | 368 | err = PTR_ERR(coda_psdev_class); |
369 | goto out_chrdev; | 369 | goto out_chrdev; |
370 | } | 370 | } |
371 | devfs_mk_dir ("coda"); | 371 | devfs_mk_dir ("coda"); |
372 | for (i = 0; i < MAX_CODADEVS; i++) { | 372 | for (i = 0; i < MAX_CODADEVS; i++) { |
373 | class_simple_device_add(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i), | 373 | class_device_create(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i), |
374 | NULL, "cfs%d", i); | 374 | NULL, "cfs%d", i); |
375 | err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i), | 375 | err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i), |
376 | S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i); | 376 | S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i); |
@@ -382,8 +382,8 @@ static int init_coda_psdev(void) | |||
382 | 382 | ||
383 | out_class: | 383 | out_class: |
384 | for (i = 0; i < MAX_CODADEVS; i++) | 384 | for (i = 0; i < MAX_CODADEVS; i++) |
385 | class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i)); | 385 | class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i)); |
386 | class_simple_destroy(coda_psdev_class); | 386 | class_destroy(coda_psdev_class); |
387 | out_chrdev: | 387 | out_chrdev: |
388 | unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); | 388 | unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); |
389 | out: | 389 | out: |
@@ -425,10 +425,10 @@ static int __init init_coda(void) | |||
425 | return 0; | 425 | return 0; |
426 | out: | 426 | out: |
427 | for (i = 0; i < MAX_CODADEVS; i++) { | 427 | for (i = 0; i < MAX_CODADEVS; i++) { |
428 | class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i)); | 428 | class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i)); |
429 | devfs_remove("coda/%d", i); | 429 | devfs_remove("coda/%d", i); |
430 | } | 430 | } |
431 | class_simple_destroy(coda_psdev_class); | 431 | class_destroy(coda_psdev_class); |
432 | devfs_remove("coda"); | 432 | devfs_remove("coda"); |
433 | unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); | 433 | unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); |
434 | coda_sysctl_clean(); | 434 | coda_sysctl_clean(); |
@@ -447,10 +447,10 @@ static void __exit exit_coda(void) | |||
447 | printk("coda: failed to unregister filesystem\n"); | 447 | printk("coda: failed to unregister filesystem\n"); |
448 | } | 448 | } |
449 | for (i = 0; i < MAX_CODADEVS; i++) { | 449 | for (i = 0; i < MAX_CODADEVS; i++) { |
450 | class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i)); | 450 | class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i)); |
451 | devfs_remove("coda/%d", i); | 451 | devfs_remove("coda/%d", i); |
452 | } | 452 | } |
453 | class_simple_destroy(coda_psdev_class); | 453 | class_destroy(coda_psdev_class); |
454 | devfs_remove("coda"); | 454 | devfs_remove("coda"); |
455 | unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); | 455 | unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); |
456 | coda_sysctl_clean(); | 456 | coda_sysctl_clean(); |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 548556ff2506..efc97d9b7860 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
@@ -45,44 +45,15 @@ struct file_operations debugfs_file_operations = { | |||
45 | .open = default_open, | 45 | .open = default_open, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | #define simple_type(type, format, temptype, strtolfn) \ | 48 | static void debugfs_u8_set(void *data, u64 val) |
49 | static ssize_t read_file_##type(struct file *file, char __user *user_buf, \ | 49 | { |
50 | size_t count, loff_t *ppos) \ | 50 | *(u8 *)data = val; |
51 | { \ | 51 | } |
52 | char buf[32]; \ | 52 | static u64 debugfs_u8_get(void *data) |
53 | type *val = file->private_data; \ | 53 | { |
54 | \ | 54 | return *(u8 *)data; |
55 | snprintf(buf, sizeof(buf), format "\n", *val); \ | 55 | } |
56 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\ | 56 | DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); |
57 | } \ | ||
58 | static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\ | ||
59 | size_t count, loff_t *ppos) \ | ||
60 | { \ | ||
61 | char *endp; \ | ||
62 | char buf[32]; \ | ||
63 | int buf_size; \ | ||
64 | type *val = file->private_data; \ | ||
65 | temptype tmp; \ | ||
66 | \ | ||
67 | memset(buf, 0x00, sizeof(buf)); \ | ||
68 | buf_size = min(count, (sizeof(buf)-1)); \ | ||
69 | if (copy_from_user(buf, user_buf, buf_size)) \ | ||
70 | return -EFAULT; \ | ||
71 | \ | ||
72 | tmp = strtolfn(buf, &endp, 0); \ | ||
73 | if ((endp == buf) || ((type)tmp != tmp)) \ | ||
74 | return -EINVAL; \ | ||
75 | *val = tmp; \ | ||
76 | return count; \ | ||
77 | } \ | ||
78 | static struct file_operations fops_##type = { \ | ||
79 | .read = read_file_##type, \ | ||
80 | .write = write_file_##type, \ | ||
81 | .open = default_open, \ | ||
82 | }; | ||
83 | simple_type(u8, "%c", unsigned long, simple_strtoul); | ||
84 | simple_type(u16, "%hi", unsigned long, simple_strtoul); | ||
85 | simple_type(u32, "%i", unsigned long, simple_strtoul); | ||
86 | 57 | ||
87 | /** | 58 | /** |
88 | * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. | 59 | * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. |
@@ -116,6 +87,16 @@ struct dentry *debugfs_create_u8(const char *name, mode_t mode, | |||
116 | } | 87 | } |
117 | EXPORT_SYMBOL_GPL(debugfs_create_u8); | 88 | EXPORT_SYMBOL_GPL(debugfs_create_u8); |
118 | 89 | ||
90 | static void debugfs_u16_set(void *data, u64 val) | ||
91 | { | ||
92 | *(u16 *)data = val; | ||
93 | } | ||
94 | static u64 debugfs_u16_get(void *data) | ||
95 | { | ||
96 | return *(u16 *)data; | ||
97 | } | ||
98 | DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); | ||
99 | |||
119 | /** | 100 | /** |
120 | * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. | 101 | * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. |
121 | * | 102 | * |
@@ -148,6 +129,16 @@ struct dentry *debugfs_create_u16(const char *name, mode_t mode, | |||
148 | } | 129 | } |
149 | EXPORT_SYMBOL_GPL(debugfs_create_u16); | 130 | EXPORT_SYMBOL_GPL(debugfs_create_u16); |
150 | 131 | ||
132 | static void debugfs_u32_set(void *data, u64 val) | ||
133 | { | ||
134 | *(u32 *)data = val; | ||
135 | } | ||
136 | static u64 debugfs_u32_get(void *data) | ||
137 | { | ||
138 | return *(u32 *)data; | ||
139 | } | ||
140 | DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); | ||
141 | |||
151 | /** | 142 | /** |
152 | * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. | 143 | * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. |
153 | * | 144 | * |
@@ -649,6 +649,7 @@ static inline int de_thread(struct task_struct *tsk) | |||
649 | } | 649 | } |
650 | sig->group_exit_task = NULL; | 650 | sig->group_exit_task = NULL; |
651 | sig->notify_count = 0; | 651 | sig->notify_count = 0; |
652 | sig->real_timer.data = (unsigned long)current; | ||
652 | spin_unlock_irq(lock); | 653 | spin_unlock_irq(lock); |
653 | 654 | ||
654 | /* | 655 | /* |
@@ -675,10 +676,8 @@ static inline int de_thread(struct task_struct *tsk) | |||
675 | proc_dentry2 = proc_pid_unhash(leader); | 676 | proc_dentry2 = proc_pid_unhash(leader); |
676 | write_lock_irq(&tasklist_lock); | 677 | write_lock_irq(&tasklist_lock); |
677 | 678 | ||
678 | if (leader->tgid != current->tgid) | 679 | BUG_ON(leader->tgid != current->tgid); |
679 | BUG(); | 680 | BUG_ON(current->pid == current->tgid); |
680 | if (current->pid == current->tgid) | ||
681 | BUG(); | ||
682 | /* | 681 | /* |
683 | * An exec() starts a new thread group with the | 682 | * An exec() starts a new thread group with the |
684 | * TGID of the previous thread group. Rehash the | 683 | * TGID of the previous thread group. Rehash the |
@@ -726,8 +725,7 @@ static inline int de_thread(struct task_struct *tsk) | |||
726 | proc_pid_flush(proc_dentry1); | 725 | proc_pid_flush(proc_dentry1); |
727 | proc_pid_flush(proc_dentry2); | 726 | proc_pid_flush(proc_dentry2); |
728 | 727 | ||
729 | if (exit_state != EXIT_ZOMBIE) | 728 | BUG_ON(exit_state != EXIT_ZOMBIE); |
730 | BUG(); | ||
731 | release_task(leader); | 729 | release_task(leader); |
732 | } | 730 | } |
733 | 731 | ||
@@ -772,10 +770,8 @@ no_thread_group: | |||
772 | kmem_cache_free(sighand_cachep, oldsighand); | 770 | kmem_cache_free(sighand_cachep, oldsighand); |
773 | } | 771 | } |
774 | 772 | ||
775 | if (!thread_group_empty(current)) | 773 | BUG_ON(!thread_group_empty(current)); |
776 | BUG(); | 774 | BUG_ON(!thread_group_leader(current)); |
777 | if (!thread_group_leader(current)) | ||
778 | BUG(); | ||
779 | return 0; | 775 | return 0; |
780 | } | 776 | } |
781 | 777 | ||
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 14a0d339d036..4bf43ea87c46 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "kern_util.h" | 23 | #include "kern_util.h" |
24 | #include "kern.h" | 24 | #include "kern.h" |
25 | #include "user_util.h" | 25 | #include "user_util.h" |
26 | #include "2_5compat.h" | ||
27 | #include "init.h" | 26 | #include "init.h" |
28 | 27 | ||
29 | struct hostfs_inode_info { | 28 | struct hostfs_inode_info { |
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 98d830401c56..5a97e346bd95 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c | |||
@@ -188,7 +188,6 @@ static int __cleanup_transaction(journal_t *journal, transaction_t *transaction) | |||
188 | } else { | 188 | } else { |
189 | jbd_unlock_bh_state(bh); | 189 | jbd_unlock_bh_state(bh); |
190 | } | 190 | } |
191 | jh = next_jh; | ||
192 | } while (jh != last_jh); | 191 | } while (jh != last_jh); |
193 | 192 | ||
194 | return ret; | 193 | return ret; |
@@ -339,8 +338,10 @@ int log_do_checkpoint(journal_t *journal) | |||
339 | } | 338 | } |
340 | } while (jh != last_jh && !retry); | 339 | } while (jh != last_jh && !retry); |
341 | 340 | ||
342 | if (batch_count) | 341 | if (batch_count) { |
343 | __flush_batch(journal, bhs, &batch_count); | 342 | __flush_batch(journal, bhs, &batch_count); |
343 | retry = 1; | ||
344 | } | ||
344 | 345 | ||
345 | /* | 346 | /* |
346 | * If someone cleaned up this transaction while we slept, we're | 347 | * If someone cleaned up this transaction while we slept, we're |
diff --git a/fs/libfs.c b/fs/libfs.c index f90b29595927..5025563e7379 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -519,6 +519,102 @@ int simple_transaction_release(struct inode *inode, struct file *file) | |||
519 | return 0; | 519 | return 0; |
520 | } | 520 | } |
521 | 521 | ||
522 | /* Simple attribute files */ | ||
523 | |||
524 | struct simple_attr { | ||
525 | u64 (*get)(void *); | ||
526 | void (*set)(void *, u64); | ||
527 | char get_buf[24]; /* enough to store a u64 and "\n\0" */ | ||
528 | char set_buf[24]; | ||
529 | void *data; | ||
530 | const char *fmt; /* format for read operation */ | ||
531 | struct semaphore sem; /* protects access to these buffers */ | ||
532 | }; | ||
533 | |||
534 | /* simple_attr_open is called by an actual attribute open file operation | ||
535 | * to set the attribute specific access operations. */ | ||
536 | int simple_attr_open(struct inode *inode, struct file *file, | ||
537 | u64 (*get)(void *), void (*set)(void *, u64), | ||
538 | const char *fmt) | ||
539 | { | ||
540 | struct simple_attr *attr; | ||
541 | |||
542 | attr = kmalloc(sizeof(*attr), GFP_KERNEL); | ||
543 | if (!attr) | ||
544 | return -ENOMEM; | ||
545 | |||
546 | attr->get = get; | ||
547 | attr->set = set; | ||
548 | attr->data = inode->u.generic_ip; | ||
549 | attr->fmt = fmt; | ||
550 | init_MUTEX(&attr->sem); | ||
551 | |||
552 | file->private_data = attr; | ||
553 | |||
554 | return nonseekable_open(inode, file); | ||
555 | } | ||
556 | |||
557 | int simple_attr_close(struct inode *inode, struct file *file) | ||
558 | { | ||
559 | kfree(file->private_data); | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | /* read from the buffer that is filled with the get function */ | ||
564 | ssize_t simple_attr_read(struct file *file, char __user *buf, | ||
565 | size_t len, loff_t *ppos) | ||
566 | { | ||
567 | struct simple_attr *attr; | ||
568 | size_t size; | ||
569 | ssize_t ret; | ||
570 | |||
571 | attr = file->private_data; | ||
572 | |||
573 | if (!attr->get) | ||
574 | return -EACCES; | ||
575 | |||
576 | down(&attr->sem); | ||
577 | if (*ppos) /* continued read */ | ||
578 | size = strlen(attr->get_buf); | ||
579 | else /* first read */ | ||
580 | size = scnprintf(attr->get_buf, sizeof(attr->get_buf), | ||
581 | attr->fmt, | ||
582 | (unsigned long long)attr->get(attr->data)); | ||
583 | |||
584 | ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size); | ||
585 | up(&attr->sem); | ||
586 | return ret; | ||
587 | } | ||
588 | |||
589 | /* interpret the buffer as a number to call the set function with */ | ||
590 | ssize_t simple_attr_write(struct file *file, const char __user *buf, | ||
591 | size_t len, loff_t *ppos) | ||
592 | { | ||
593 | struct simple_attr *attr; | ||
594 | u64 val; | ||
595 | size_t size; | ||
596 | ssize_t ret; | ||
597 | |||
598 | attr = file->private_data; | ||
599 | |||
600 | if (!attr->set) | ||
601 | return -EACCES; | ||
602 | |||
603 | down(&attr->sem); | ||
604 | ret = -EFAULT; | ||
605 | size = min(sizeof(attr->set_buf) - 1, len); | ||
606 | if (copy_from_user(attr->set_buf, buf, size)) | ||
607 | goto out; | ||
608 | |||
609 | ret = len; /* claim we got the whole input */ | ||
610 | attr->set_buf[size] = '\0'; | ||
611 | val = simple_strtol(attr->set_buf, NULL, 0); | ||
612 | attr->set(attr->data, val); | ||
613 | out: | ||
614 | up(&attr->sem); | ||
615 | return ret; | ||
616 | } | ||
617 | |||
522 | EXPORT_SYMBOL(dcache_dir_close); | 618 | EXPORT_SYMBOL(dcache_dir_close); |
523 | EXPORT_SYMBOL(dcache_dir_lseek); | 619 | EXPORT_SYMBOL(dcache_dir_lseek); |
524 | EXPORT_SYMBOL(dcache_dir_open); | 620 | EXPORT_SYMBOL(dcache_dir_open); |
@@ -547,3 +643,7 @@ EXPORT_SYMBOL(simple_read_from_buffer); | |||
547 | EXPORT_SYMBOL(simple_transaction_get); | 643 | EXPORT_SYMBOL(simple_transaction_get); |
548 | EXPORT_SYMBOL(simple_transaction_read); | 644 | EXPORT_SYMBOL(simple_transaction_read); |
549 | EXPORT_SYMBOL(simple_transaction_release); | 645 | EXPORT_SYMBOL(simple_transaction_release); |
646 | EXPORT_SYMBOL_GPL(simple_attr_open); | ||
647 | EXPORT_SYMBOL_GPL(simple_attr_close); | ||
648 | EXPORT_SYMBOL_GPL(simple_attr_read); | ||
649 | EXPORT_SYMBOL_GPL(simple_attr_write); | ||
diff --git a/fs/mpage.c b/fs/mpage.c index b92c0e64aefa..bb9aebe93862 100644 --- a/fs/mpage.c +++ b/fs/mpage.c | |||
@@ -79,8 +79,11 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err) | |||
79 | if (--bvec >= bio->bi_io_vec) | 79 | if (--bvec >= bio->bi_io_vec) |
80 | prefetchw(&bvec->bv_page->flags); | 80 | prefetchw(&bvec->bv_page->flags); |
81 | 81 | ||
82 | if (!uptodate) | 82 | if (!uptodate){ |
83 | SetPageError(page); | 83 | SetPageError(page); |
84 | if (page->mapping) | ||
85 | set_bit(AS_EIO, &page->mapping->flags); | ||
86 | } | ||
84 | end_page_writeback(page); | 87 | end_page_writeback(page); |
85 | } while (bvec >= bio->bi_io_vec); | 88 | } while (bvec >= bio->bi_io_vec); |
86 | bio_put(bio); | 89 | bio_put(bio); |
diff --git a/fs/namei.c b/fs/namei.c index dd78f01b6de8..a7f7f44119b3 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -493,12 +493,21 @@ fail: | |||
493 | return PTR_ERR(link); | 493 | return PTR_ERR(link); |
494 | } | 494 | } |
495 | 495 | ||
496 | static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) | 496 | struct path { |
497 | struct vfsmount *mnt; | ||
498 | struct dentry *dentry; | ||
499 | }; | ||
500 | |||
501 | static inline int __do_follow_link(struct path *path, struct nameidata *nd) | ||
497 | { | 502 | { |
498 | int error; | 503 | int error; |
504 | struct dentry *dentry = path->dentry; | ||
499 | 505 | ||
500 | touch_atime(nd->mnt, dentry); | 506 | touch_atime(path->mnt, dentry); |
501 | nd_set_link(nd, NULL); | 507 | nd_set_link(nd, NULL); |
508 | |||
509 | if (path->mnt == nd->mnt) | ||
510 | mntget(path->mnt); | ||
502 | error = dentry->d_inode->i_op->follow_link(dentry, nd); | 511 | error = dentry->d_inode->i_op->follow_link(dentry, nd); |
503 | if (!error) { | 512 | if (!error) { |
504 | char *s = nd_get_link(nd); | 513 | char *s = nd_get_link(nd); |
@@ -507,6 +516,8 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
507 | if (dentry->d_inode->i_op->put_link) | 516 | if (dentry->d_inode->i_op->put_link) |
508 | dentry->d_inode->i_op->put_link(dentry, nd); | 517 | dentry->d_inode->i_op->put_link(dentry, nd); |
509 | } | 518 | } |
519 | dput(dentry); | ||
520 | mntput(path->mnt); | ||
510 | 521 | ||
511 | return error; | 522 | return error; |
512 | } | 523 | } |
@@ -518,7 +529,7 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
518 | * Without that kind of total limit, nasty chains of consecutive | 529 | * Without that kind of total limit, nasty chains of consecutive |
519 | * symlinks can cause almost arbitrarily long lookups. | 530 | * symlinks can cause almost arbitrarily long lookups. |
520 | */ | 531 | */ |
521 | static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) | 532 | static inline int do_follow_link(struct path *path, struct nameidata *nd) |
522 | { | 533 | { |
523 | int err = -ELOOP; | 534 | int err = -ELOOP; |
524 | if (current->link_count >= MAX_NESTED_LINKS) | 535 | if (current->link_count >= MAX_NESTED_LINKS) |
@@ -527,17 +538,20 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
527 | goto loop; | 538 | goto loop; |
528 | BUG_ON(nd->depth >= MAX_NESTED_LINKS); | 539 | BUG_ON(nd->depth >= MAX_NESTED_LINKS); |
529 | cond_resched(); | 540 | cond_resched(); |
530 | err = security_inode_follow_link(dentry, nd); | 541 | err = security_inode_follow_link(path->dentry, nd); |
531 | if (err) | 542 | if (err) |
532 | goto loop; | 543 | goto loop; |
533 | current->link_count++; | 544 | current->link_count++; |
534 | current->total_link_count++; | 545 | current->total_link_count++; |
535 | nd->depth++; | 546 | nd->depth++; |
536 | err = __do_follow_link(dentry, nd); | 547 | err = __do_follow_link(path, nd); |
537 | current->link_count--; | 548 | current->link_count--; |
538 | nd->depth--; | 549 | nd->depth--; |
539 | return err; | 550 | return err; |
540 | loop: | 551 | loop: |
552 | dput(path->dentry); | ||
553 | if (path->mnt != nd->mnt) | ||
554 | mntput(path->mnt); | ||
541 | path_release(nd); | 555 | path_release(nd); |
542 | return err; | 556 | return err; |
543 | } | 557 | } |
@@ -565,87 +579,91 @@ int follow_up(struct vfsmount **mnt, struct dentry **dentry) | |||
565 | /* no need for dcache_lock, as serialization is taken care in | 579 | /* no need for dcache_lock, as serialization is taken care in |
566 | * namespace.c | 580 | * namespace.c |
567 | */ | 581 | */ |
568 | static int follow_mount(struct vfsmount **mnt, struct dentry **dentry) | 582 | static int __follow_mount(struct path *path) |
569 | { | 583 | { |
570 | int res = 0; | 584 | int res = 0; |
585 | while (d_mountpoint(path->dentry)) { | ||
586 | struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry); | ||
587 | if (!mounted) | ||
588 | break; | ||
589 | dput(path->dentry); | ||
590 | if (res) | ||
591 | mntput(path->mnt); | ||
592 | path->mnt = mounted; | ||
593 | path->dentry = dget(mounted->mnt_root); | ||
594 | res = 1; | ||
595 | } | ||
596 | return res; | ||
597 | } | ||
598 | |||
599 | static void follow_mount(struct vfsmount **mnt, struct dentry **dentry) | ||
600 | { | ||
571 | while (d_mountpoint(*dentry)) { | 601 | while (d_mountpoint(*dentry)) { |
572 | struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); | 602 | struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); |
573 | if (!mounted) | 603 | if (!mounted) |
574 | break; | 604 | break; |
605 | dput(*dentry); | ||
575 | mntput(*mnt); | 606 | mntput(*mnt); |
576 | *mnt = mounted; | 607 | *mnt = mounted; |
577 | dput(*dentry); | ||
578 | *dentry = dget(mounted->mnt_root); | 608 | *dentry = dget(mounted->mnt_root); |
579 | res = 1; | ||
580 | } | 609 | } |
581 | return res; | ||
582 | } | 610 | } |
583 | 611 | ||
584 | /* no need for dcache_lock, as serialization is taken care in | 612 | /* no need for dcache_lock, as serialization is taken care in |
585 | * namespace.c | 613 | * namespace.c |
586 | */ | 614 | */ |
587 | static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) | 615 | int follow_down(struct vfsmount **mnt, struct dentry **dentry) |
588 | { | 616 | { |
589 | struct vfsmount *mounted; | 617 | struct vfsmount *mounted; |
590 | 618 | ||
591 | mounted = lookup_mnt(*mnt, *dentry); | 619 | mounted = lookup_mnt(*mnt, *dentry); |
592 | if (mounted) { | 620 | if (mounted) { |
621 | dput(*dentry); | ||
593 | mntput(*mnt); | 622 | mntput(*mnt); |
594 | *mnt = mounted; | 623 | *mnt = mounted; |
595 | dput(*dentry); | ||
596 | *dentry = dget(mounted->mnt_root); | 624 | *dentry = dget(mounted->mnt_root); |
597 | return 1; | 625 | return 1; |
598 | } | 626 | } |
599 | return 0; | 627 | return 0; |
600 | } | 628 | } |
601 | 629 | ||
602 | int follow_down(struct vfsmount **mnt, struct dentry **dentry) | 630 | static inline void follow_dotdot(struct nameidata *nd) |
603 | { | ||
604 | return __follow_down(mnt,dentry); | ||
605 | } | ||
606 | |||
607 | static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry) | ||
608 | { | 631 | { |
609 | while(1) { | 632 | while(1) { |
610 | struct vfsmount *parent; | 633 | struct vfsmount *parent; |
611 | struct dentry *old = *dentry; | 634 | struct dentry *old = nd->dentry; |
612 | 635 | ||
613 | read_lock(¤t->fs->lock); | 636 | read_lock(¤t->fs->lock); |
614 | if (*dentry == current->fs->root && | 637 | if (nd->dentry == current->fs->root && |
615 | *mnt == current->fs->rootmnt) { | 638 | nd->mnt == current->fs->rootmnt) { |
616 | read_unlock(¤t->fs->lock); | 639 | read_unlock(¤t->fs->lock); |
617 | break; | 640 | break; |
618 | } | 641 | } |
619 | read_unlock(¤t->fs->lock); | 642 | read_unlock(¤t->fs->lock); |
620 | spin_lock(&dcache_lock); | 643 | spin_lock(&dcache_lock); |
621 | if (*dentry != (*mnt)->mnt_root) { | 644 | if (nd->dentry != nd->mnt->mnt_root) { |
622 | *dentry = dget((*dentry)->d_parent); | 645 | nd->dentry = dget(nd->dentry->d_parent); |
623 | spin_unlock(&dcache_lock); | 646 | spin_unlock(&dcache_lock); |
624 | dput(old); | 647 | dput(old); |
625 | break; | 648 | break; |
626 | } | 649 | } |
627 | spin_unlock(&dcache_lock); | 650 | spin_unlock(&dcache_lock); |
628 | spin_lock(&vfsmount_lock); | 651 | spin_lock(&vfsmount_lock); |
629 | parent = (*mnt)->mnt_parent; | 652 | parent = nd->mnt->mnt_parent; |
630 | if (parent == *mnt) { | 653 | if (parent == nd->mnt) { |
631 | spin_unlock(&vfsmount_lock); | 654 | spin_unlock(&vfsmount_lock); |
632 | break; | 655 | break; |
633 | } | 656 | } |
634 | mntget(parent); | 657 | mntget(parent); |
635 | *dentry = dget((*mnt)->mnt_mountpoint); | 658 | nd->dentry = dget(nd->mnt->mnt_mountpoint); |
636 | spin_unlock(&vfsmount_lock); | 659 | spin_unlock(&vfsmount_lock); |
637 | dput(old); | 660 | dput(old); |
638 | mntput(*mnt); | 661 | mntput(nd->mnt); |
639 | *mnt = parent; | 662 | nd->mnt = parent; |
640 | } | 663 | } |
641 | follow_mount(mnt, dentry); | 664 | follow_mount(&nd->mnt, &nd->dentry); |
642 | } | 665 | } |
643 | 666 | ||
644 | struct path { | ||
645 | struct vfsmount *mnt; | ||
646 | struct dentry *dentry; | ||
647 | }; | ||
648 | |||
649 | /* | 667 | /* |
650 | * It's more convoluted than I'd like it to be, but... it's still fairly | 668 | * It's more convoluted than I'd like it to be, but... it's still fairly |
651 | * small and for now I'd prefer to have fast path as straight as possible. | 669 | * small and for now I'd prefer to have fast path as straight as possible. |
@@ -664,6 +682,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, | |||
664 | done: | 682 | done: |
665 | path->mnt = mnt; | 683 | path->mnt = mnt; |
666 | path->dentry = dentry; | 684 | path->dentry = dentry; |
685 | __follow_mount(path); | ||
667 | return 0; | 686 | return 0; |
668 | 687 | ||
669 | need_lookup: | 688 | need_lookup: |
@@ -751,7 +770,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
751 | case 2: | 770 | case 2: |
752 | if (this.name[1] != '.') | 771 | if (this.name[1] != '.') |
753 | break; | 772 | break; |
754 | follow_dotdot(&nd->mnt, &nd->dentry); | 773 | follow_dotdot(nd); |
755 | inode = nd->dentry->d_inode; | 774 | inode = nd->dentry->d_inode; |
756 | /* fallthrough */ | 775 | /* fallthrough */ |
757 | case 1: | 776 | case 1: |
@@ -771,8 +790,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
771 | err = do_lookup(nd, &this, &next); | 790 | err = do_lookup(nd, &this, &next); |
772 | if (err) | 791 | if (err) |
773 | break; | 792 | break; |
774 | /* Check mountpoints.. */ | ||
775 | follow_mount(&next.mnt, &next.dentry); | ||
776 | 793 | ||
777 | err = -ENOENT; | 794 | err = -ENOENT; |
778 | inode = next.dentry->d_inode; | 795 | inode = next.dentry->d_inode; |
@@ -783,10 +800,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
783 | goto out_dput; | 800 | goto out_dput; |
784 | 801 | ||
785 | if (inode->i_op->follow_link) { | 802 | if (inode->i_op->follow_link) { |
786 | mntget(next.mnt); | 803 | err = do_follow_link(&next, nd); |
787 | err = do_follow_link(next.dentry, nd); | ||
788 | dput(next.dentry); | ||
789 | mntput(next.mnt); | ||
790 | if (err) | 804 | if (err) |
791 | goto return_err; | 805 | goto return_err; |
792 | err = -ENOENT; | 806 | err = -ENOENT; |
@@ -798,6 +812,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
798 | break; | 812 | break; |
799 | } else { | 813 | } else { |
800 | dput(nd->dentry); | 814 | dput(nd->dentry); |
815 | if (nd->mnt != next.mnt) | ||
816 | mntput(nd->mnt); | ||
801 | nd->mnt = next.mnt; | 817 | nd->mnt = next.mnt; |
802 | nd->dentry = next.dentry; | 818 | nd->dentry = next.dentry; |
803 | } | 819 | } |
@@ -819,7 +835,7 @@ last_component: | |||
819 | case 2: | 835 | case 2: |
820 | if (this.name[1] != '.') | 836 | if (this.name[1] != '.') |
821 | break; | 837 | break; |
822 | follow_dotdot(&nd->mnt, &nd->dentry); | 838 | follow_dotdot(nd); |
823 | inode = nd->dentry->d_inode; | 839 | inode = nd->dentry->d_inode; |
824 | /* fallthrough */ | 840 | /* fallthrough */ |
825 | case 1: | 841 | case 1: |
@@ -833,19 +849,17 @@ last_component: | |||
833 | err = do_lookup(nd, &this, &next); | 849 | err = do_lookup(nd, &this, &next); |
834 | if (err) | 850 | if (err) |
835 | break; | 851 | break; |
836 | follow_mount(&next.mnt, &next.dentry); | ||
837 | inode = next.dentry->d_inode; | 852 | inode = next.dentry->d_inode; |
838 | if ((lookup_flags & LOOKUP_FOLLOW) | 853 | if ((lookup_flags & LOOKUP_FOLLOW) |
839 | && inode && inode->i_op && inode->i_op->follow_link) { | 854 | && inode && inode->i_op && inode->i_op->follow_link) { |
840 | mntget(next.mnt); | 855 | err = do_follow_link(&next, nd); |
841 | err = do_follow_link(next.dentry, nd); | ||
842 | dput(next.dentry); | ||
843 | mntput(next.mnt); | ||
844 | if (err) | 856 | if (err) |
845 | goto return_err; | 857 | goto return_err; |
846 | inode = nd->dentry->d_inode; | 858 | inode = nd->dentry->d_inode; |
847 | } else { | 859 | } else { |
848 | dput(nd->dentry); | 860 | dput(nd->dentry); |
861 | if (nd->mnt != next.mnt) | ||
862 | mntput(nd->mnt); | ||
849 | nd->mnt = next.mnt; | 863 | nd->mnt = next.mnt; |
850 | nd->dentry = next.dentry; | 864 | nd->dentry = next.dentry; |
851 | } | 865 | } |
@@ -885,6 +899,8 @@ return_base: | |||
885 | return 0; | 899 | return 0; |
886 | out_dput: | 900 | out_dput: |
887 | dput(next.dentry); | 901 | dput(next.dentry); |
902 | if (nd->mnt != next.mnt) | ||
903 | mntput(next.mnt); | ||
888 | break; | 904 | break; |
889 | } | 905 | } |
890 | path_release(nd); | 906 | path_release(nd); |
@@ -1398,7 +1414,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1398 | int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | 1414 | int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) |
1399 | { | 1415 | { |
1400 | int acc_mode, error = 0; | 1416 | int acc_mode, error = 0; |
1401 | struct dentry *dentry; | 1417 | struct path path; |
1402 | struct dentry *dir; | 1418 | struct dentry *dir; |
1403 | int count = 0; | 1419 | int count = 0; |
1404 | 1420 | ||
@@ -1442,23 +1458,24 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | |||
1442 | dir = nd->dentry; | 1458 | dir = nd->dentry; |
1443 | nd->flags &= ~LOOKUP_PARENT; | 1459 | nd->flags &= ~LOOKUP_PARENT; |
1444 | down(&dir->d_inode->i_sem); | 1460 | down(&dir->d_inode->i_sem); |
1445 | dentry = __lookup_hash(&nd->last, nd->dentry, nd); | 1461 | path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); |
1462 | path.mnt = nd->mnt; | ||
1446 | 1463 | ||
1447 | do_last: | 1464 | do_last: |
1448 | error = PTR_ERR(dentry); | 1465 | error = PTR_ERR(path.dentry); |
1449 | if (IS_ERR(dentry)) { | 1466 | if (IS_ERR(path.dentry)) { |
1450 | up(&dir->d_inode->i_sem); | 1467 | up(&dir->d_inode->i_sem); |
1451 | goto exit; | 1468 | goto exit; |
1452 | } | 1469 | } |
1453 | 1470 | ||
1454 | /* Negative dentry, just create the file */ | 1471 | /* Negative dentry, just create the file */ |
1455 | if (!dentry->d_inode) { | 1472 | if (!path.dentry->d_inode) { |
1456 | if (!IS_POSIXACL(dir->d_inode)) | 1473 | if (!IS_POSIXACL(dir->d_inode)) |
1457 | mode &= ~current->fs->umask; | 1474 | mode &= ~current->fs->umask; |
1458 | error = vfs_create(dir->d_inode, dentry, mode, nd); | 1475 | error = vfs_create(dir->d_inode, path.dentry, mode, nd); |
1459 | up(&dir->d_inode->i_sem); | 1476 | up(&dir->d_inode->i_sem); |
1460 | dput(nd->dentry); | 1477 | dput(nd->dentry); |
1461 | nd->dentry = dentry; | 1478 | nd->dentry = path.dentry; |
1462 | if (error) | 1479 | if (error) |
1463 | goto exit; | 1480 | goto exit; |
1464 | /* Don't check for write permission, don't truncate */ | 1481 | /* Don't check for write permission, don't truncate */ |
@@ -1476,22 +1493,24 @@ do_last: | |||
1476 | if (flag & O_EXCL) | 1493 | if (flag & O_EXCL) |
1477 | goto exit_dput; | 1494 | goto exit_dput; |
1478 | 1495 | ||
1479 | if (d_mountpoint(dentry)) { | 1496 | if (__follow_mount(&path)) { |
1480 | error = -ELOOP; | 1497 | error = -ELOOP; |
1481 | if (flag & O_NOFOLLOW) | 1498 | if (flag & O_NOFOLLOW) |
1482 | goto exit_dput; | 1499 | goto exit_dput; |
1483 | while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry)); | ||
1484 | } | 1500 | } |
1485 | error = -ENOENT; | 1501 | error = -ENOENT; |
1486 | if (!dentry->d_inode) | 1502 | if (!path.dentry->d_inode) |
1487 | goto exit_dput; | 1503 | goto exit_dput; |
1488 | if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) | 1504 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) |
1489 | goto do_link; | 1505 | goto do_link; |
1490 | 1506 | ||
1491 | dput(nd->dentry); | 1507 | dput(nd->dentry); |
1492 | nd->dentry = dentry; | 1508 | nd->dentry = path.dentry; |
1509 | if (nd->mnt != path.mnt) | ||
1510 | mntput(nd->mnt); | ||
1511 | nd->mnt = path.mnt; | ||
1493 | error = -EISDIR; | 1512 | error = -EISDIR; |
1494 | if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) | 1513 | if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) |
1495 | goto exit; | 1514 | goto exit; |
1496 | ok: | 1515 | ok: |
1497 | error = may_open(nd, acc_mode, flag); | 1516 | error = may_open(nd, acc_mode, flag); |
@@ -1500,7 +1519,9 @@ ok: | |||
1500 | return 0; | 1519 | return 0; |
1501 | 1520 | ||
1502 | exit_dput: | 1521 | exit_dput: |
1503 | dput(dentry); | 1522 | dput(path.dentry); |
1523 | if (nd->mnt != path.mnt) | ||
1524 | mntput(path.mnt); | ||
1504 | exit: | 1525 | exit: |
1505 | path_release(nd); | 1526 | path_release(nd); |
1506 | return error; | 1527 | return error; |
@@ -1520,18 +1541,15 @@ do_link: | |||
1520 | * are done. Procfs-like symlinks just set LAST_BIND. | 1541 | * are done. Procfs-like symlinks just set LAST_BIND. |
1521 | */ | 1542 | */ |
1522 | nd->flags |= LOOKUP_PARENT; | 1543 | nd->flags |= LOOKUP_PARENT; |
1523 | error = security_inode_follow_link(dentry, nd); | 1544 | error = security_inode_follow_link(path.dentry, nd); |
1524 | if (error) | 1545 | if (error) |
1525 | goto exit_dput; | 1546 | goto exit_dput; |
1526 | error = __do_follow_link(dentry, nd); | 1547 | error = __do_follow_link(&path, nd); |
1527 | dput(dentry); | ||
1528 | if (error) | 1548 | if (error) |
1529 | return error; | 1549 | return error; |
1530 | nd->flags &= ~LOOKUP_PARENT; | 1550 | nd->flags &= ~LOOKUP_PARENT; |
1531 | if (nd->last_type == LAST_BIND) { | 1551 | if (nd->last_type == LAST_BIND) |
1532 | dentry = nd->dentry; | ||
1533 | goto ok; | 1552 | goto ok; |
1534 | } | ||
1535 | error = -EISDIR; | 1553 | error = -EISDIR; |
1536 | if (nd->last_type != LAST_NORM) | 1554 | if (nd->last_type != LAST_NORM) |
1537 | goto exit; | 1555 | goto exit; |
@@ -1546,7 +1564,8 @@ do_link: | |||
1546 | } | 1564 | } |
1547 | dir = nd->dentry; | 1565 | dir = nd->dentry; |
1548 | down(&dir->d_inode->i_sem); | 1566 | down(&dir->d_inode->i_sem); |
1549 | dentry = __lookup_hash(&nd->last, nd->dentry, nd); | 1567 | path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); |
1568 | path.mnt = nd->mnt; | ||
1550 | putname(nd->last.name); | 1569 | putname(nd->last.name); |
1551 | goto do_last; | 1570 | goto do_last; |
1552 | } | 1571 | } |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 73f96acd5d37..ff6155f5e8d9 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -528,19 +528,39 @@ static inline void nfs_renew_times(struct dentry * dentry) | |||
528 | dentry->d_time = jiffies; | 528 | dentry->d_time = jiffies; |
529 | } | 529 | } |
530 | 530 | ||
531 | /* | ||
532 | * Return the intent data that applies to this particular path component | ||
533 | * | ||
534 | * Note that the current set of intents only apply to the very last | ||
535 | * component of the path. | ||
536 | * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT. | ||
537 | */ | ||
538 | static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask) | ||
539 | { | ||
540 | if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT)) | ||
541 | return 0; | ||
542 | return nd->flags & mask; | ||
543 | } | ||
544 | |||
545 | /* | ||
546 | * Inode and filehandle revalidation for lookups. | ||
547 | * | ||
548 | * We force revalidation in the cases where the VFS sets LOOKUP_REVAL, | ||
549 | * or if the intent information indicates that we're about to open this | ||
550 | * particular file and the "nocto" mount flag is not set. | ||
551 | * | ||
552 | */ | ||
531 | static inline | 553 | static inline |
532 | int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | 554 | int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) |
533 | { | 555 | { |
534 | struct nfs_server *server = NFS_SERVER(inode); | 556 | struct nfs_server *server = NFS_SERVER(inode); |
535 | 557 | ||
536 | if (nd != NULL) { | 558 | if (nd != NULL) { |
537 | int ndflags = nd->flags; | ||
538 | /* VFS wants an on-the-wire revalidation */ | 559 | /* VFS wants an on-the-wire revalidation */ |
539 | if (ndflags & LOOKUP_REVAL) | 560 | if (nd->flags & LOOKUP_REVAL) |
540 | goto out_force; | 561 | goto out_force; |
541 | /* This is an open(2) */ | 562 | /* This is an open(2) */ |
542 | if ((ndflags & LOOKUP_OPEN) && | 563 | if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 && |
543 | !(ndflags & LOOKUP_CONTINUE) && | ||
544 | !(server->flags & NFS_MOUNT_NOCTO)) | 564 | !(server->flags & NFS_MOUNT_NOCTO)) |
545 | goto out_force; | 565 | goto out_force; |
546 | } | 566 | } |
@@ -560,12 +580,8 @@ static inline | |||
560 | int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, | 580 | int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, |
561 | struct nameidata *nd) | 581 | struct nameidata *nd) |
562 | { | 582 | { |
563 | int ndflags = 0; | ||
564 | |||
565 | if (nd) | ||
566 | ndflags = nd->flags; | ||
567 | /* Don't revalidate a negative dentry if we're creating a new file */ | 583 | /* Don't revalidate a negative dentry if we're creating a new file */ |
568 | if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE)) | 584 | if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0) |
569 | return 0; | 585 | return 0; |
570 | return !nfs_check_verifier(dir, dentry); | 586 | return !nfs_check_verifier(dir, dentry); |
571 | } | 587 | } |
@@ -700,12 +716,16 @@ struct dentry_operations nfs_dentry_operations = { | |||
700 | .d_iput = nfs_dentry_iput, | 716 | .d_iput = nfs_dentry_iput, |
701 | }; | 717 | }; |
702 | 718 | ||
719 | /* | ||
720 | * Use intent information to check whether or not we're going to do | ||
721 | * an O_EXCL create using this path component. | ||
722 | */ | ||
703 | static inline | 723 | static inline |
704 | int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | 724 | int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) |
705 | { | 725 | { |
706 | if (NFS_PROTO(dir)->version == 2) | 726 | if (NFS_PROTO(dir)->version == 2) |
707 | return 0; | 727 | return 0; |
708 | if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE)) | 728 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0) |
709 | return 0; | 729 | return 0; |
710 | return (nd->intent.open.flags & O_EXCL) != 0; | 730 | return (nd->intent.open.flags & O_EXCL) != 0; |
711 | } | 731 | } |
@@ -772,12 +792,13 @@ struct dentry_operations nfs4_dentry_operations = { | |||
772 | .d_iput = nfs_dentry_iput, | 792 | .d_iput = nfs_dentry_iput, |
773 | }; | 793 | }; |
774 | 794 | ||
795 | /* | ||
796 | * Use intent information to determine whether we need to substitute | ||
797 | * the NFSv4-style stateful OPEN for the LOOKUP call | ||
798 | */ | ||
775 | static int is_atomic_open(struct inode *dir, struct nameidata *nd) | 799 | static int is_atomic_open(struct inode *dir, struct nameidata *nd) |
776 | { | 800 | { |
777 | if (!nd) | 801 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0) |
778 | return 0; | ||
779 | /* Check that we are indeed trying to open this file */ | ||
780 | if ((nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_OPEN)) | ||
781 | return 0; | 802 | return 0; |
782 | /* NFS does not (yet) have a stateful open for directories */ | 803 | /* NFS does not (yet) have a stateful open for directories */ |
783 | if (nd->flags & LOOKUP_DIRECTORY) | 804 | if (nd->flags & LOOKUP_DIRECTORY) |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f06eee6dcff5..55c907592490 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | static int nfs_file_open(struct inode *, struct file *); | 38 | static int nfs_file_open(struct inode *, struct file *); |
39 | static int nfs_file_release(struct inode *, struct file *); | 39 | static int nfs_file_release(struct inode *, struct file *); |
40 | static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin); | ||
40 | static int nfs_file_mmap(struct file *, struct vm_area_struct *); | 41 | static int nfs_file_mmap(struct file *, struct vm_area_struct *); |
41 | static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); | 42 | static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); |
42 | static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); | 43 | static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); |
@@ -48,7 +49,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); | |||
48 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); | 49 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); |
49 | 50 | ||
50 | struct file_operations nfs_file_operations = { | 51 | struct file_operations nfs_file_operations = { |
51 | .llseek = remote_llseek, | 52 | .llseek = nfs_file_llseek, |
52 | .read = do_sync_read, | 53 | .read = do_sync_read, |
53 | .write = do_sync_write, | 54 | .write = do_sync_write, |
54 | .aio_read = nfs_file_read, | 55 | .aio_read = nfs_file_read, |
@@ -114,6 +115,45 @@ nfs_file_release(struct inode *inode, struct file *filp) | |||
114 | return NFS_PROTO(inode)->file_release(inode, filp); | 115 | return NFS_PROTO(inode)->file_release(inode, filp); |
115 | } | 116 | } |
116 | 117 | ||
118 | /** | ||
119 | * nfs_revalidate_size - Revalidate the file size | ||
120 | * @inode - pointer to inode struct | ||
121 | * @file - pointer to struct file | ||
122 | * | ||
123 | * Revalidates the file length. This is basically a wrapper around | ||
124 | * nfs_revalidate_inode() that takes into account the fact that we may | ||
125 | * have cached writes (in which case we don't care about the server's | ||
126 | * idea of what the file length is), or O_DIRECT (in which case we | ||
127 | * shouldn't trust the cache). | ||
128 | */ | ||
129 | static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) | ||
130 | { | ||
131 | struct nfs_server *server = NFS_SERVER(inode); | ||
132 | struct nfs_inode *nfsi = NFS_I(inode); | ||
133 | |||
134 | if (server->flags & NFS_MOUNT_NOAC) | ||
135 | goto force_reval; | ||
136 | if (filp->f_flags & O_DIRECT) | ||
137 | goto force_reval; | ||
138 | if (nfsi->npages != 0) | ||
139 | return 0; | ||
140 | return nfs_revalidate_inode(server, inode); | ||
141 | force_reval: | ||
142 | return __nfs_revalidate_inode(server, inode); | ||
143 | } | ||
144 | |||
145 | static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | ||
146 | { | ||
147 | /* origin == SEEK_END => we must revalidate the cached file length */ | ||
148 | if (origin == 2) { | ||
149 | struct inode *inode = filp->f_mapping->host; | ||
150 | int retval = nfs_revalidate_file_size(inode, filp); | ||
151 | if (retval < 0) | ||
152 | return (loff_t)retval; | ||
153 | } | ||
154 | return remote_llseek(filp, offset, origin); | ||
155 | } | ||
156 | |||
117 | /* | 157 | /* |
118 | * Flush all dirty pages, and check for write errors. | 158 | * Flush all dirty pages, and check for write errors. |
119 | * | 159 | * |
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index 67423c696c0a..6fd57f154197 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c | |||
@@ -12,15 +12,8 @@ | |||
12 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
13 | 13 | ||
14 | #ifndef HAVE_ARCH_DEVTREE_FIXUPS | 14 | #ifndef HAVE_ARCH_DEVTREE_FIXUPS |
15 | static inline void set_node_proc_entry(struct device_node *np, struct proc_dir_entry *de) | 15 | static inline void set_node_proc_entry(struct device_node *np, |
16 | { | 16 | struct proc_dir_entry *de) |
17 | } | ||
18 | |||
19 | static void inline set_node_name_link(struct device_node *np, struct proc_dir_entry *de) | ||
20 | { | ||
21 | } | ||
22 | |||
23 | static void inline set_node_addr_link(struct device_node *np, struct proc_dir_entry *de) | ||
24 | { | 17 | { |
25 | } | 18 | } |
26 | #endif | 19 | #endif |
@@ -58,89 +51,67 @@ static int property_read_proc(char *page, char **start, off_t off, | |||
58 | /* | 51 | /* |
59 | * Process a node, adding entries for its children and its properties. | 52 | * Process a node, adding entries for its children and its properties. |
60 | */ | 53 | */ |
61 | void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *de) | 54 | void proc_device_tree_add_node(struct device_node *np, |
55 | struct proc_dir_entry *de) | ||
62 | { | 56 | { |
63 | struct property *pp; | 57 | struct property *pp; |
64 | struct proc_dir_entry *ent; | 58 | struct proc_dir_entry *ent; |
65 | struct device_node *child, *sib; | 59 | struct device_node *child; |
66 | const char *p, *at; | 60 | struct proc_dir_entry *list = NULL, **lastp; |
67 | int l; | 61 | const char *p; |
68 | struct proc_dir_entry *list, **lastp, *al; | ||
69 | 62 | ||
70 | set_node_proc_entry(np, de); | 63 | set_node_proc_entry(np, de); |
71 | lastp = &list; | 64 | lastp = &list; |
72 | for (pp = np->properties; pp != 0; pp = pp->next) { | 65 | for (child = NULL; (child = of_get_next_child(np, child));) { |
73 | /* | ||
74 | * Unfortunately proc_register puts each new entry | ||
75 | * at the beginning of the list. So we rearrange them. | ||
76 | */ | ||
77 | ent = create_proc_read_entry(pp->name, strncmp(pp->name, "security-", 9) ? | ||
78 | S_IRUGO : S_IRUSR, de, property_read_proc, pp); | ||
79 | if (ent == 0) | ||
80 | break; | ||
81 | if (!strncmp(pp->name, "security-", 9)) | ||
82 | ent->size = 0; /* don't leak number of password chars */ | ||
83 | else | ||
84 | ent->size = pp->length; | ||
85 | *lastp = ent; | ||
86 | lastp = &ent->next; | ||
87 | } | ||
88 | child = NULL; | ||
89 | while ((child = of_get_next_child(np, child))) { | ||
90 | p = strrchr(child->full_name, '/'); | 66 | p = strrchr(child->full_name, '/'); |
91 | if (!p) | 67 | if (!p) |
92 | p = child->full_name; | 68 | p = child->full_name; |
93 | else | 69 | else |
94 | ++p; | 70 | ++p; |
95 | /* chop off '@0' if the name ends with that */ | ||
96 | l = strlen(p); | ||
97 | if (l > 2 && p[l-2] == '@' && p[l-1] == '0') | ||
98 | l -= 2; | ||
99 | ent = proc_mkdir(p, de); | 71 | ent = proc_mkdir(p, de); |
100 | if (ent == 0) | 72 | if (ent == 0) |
101 | break; | 73 | break; |
102 | *lastp = ent; | 74 | *lastp = ent; |
75 | ent->next = NULL; | ||
103 | lastp = &ent->next; | 76 | lastp = &ent->next; |
104 | proc_device_tree_add_node(child, ent); | 77 | proc_device_tree_add_node(child, ent); |
105 | 78 | } | |
106 | /* | 79 | of_node_put(child); |
107 | * If we left the address part on the name, consider | 80 | for (pp = np->properties; pp != 0; pp = pp->next) { |
108 | * adding symlinks from the name and address parts. | ||
109 | */ | ||
110 | if (p[l] != 0 || (at = strchr(p, '@')) == 0) | ||
111 | continue; | ||
112 | |||
113 | /* | 81 | /* |
114 | * If this is the first node with a given name property, | 82 | * Yet another Apple device-tree bogosity: on some machines, |
115 | * add a symlink with the name property as its name. | 83 | * they have properties & nodes with the same name. Those |
84 | * properties are quite unimportant for us though, thus we | ||
85 | * simply "skip" them here, but we do have to check. | ||
116 | */ | 86 | */ |
117 | sib = NULL; | 87 | for (ent = list; ent != NULL; ent = ent->next) |
118 | while ((sib = of_get_next_child(np, sib)) && sib != child) | 88 | if (!strcmp(ent->name, pp->name)) |
119 | if (sib->name && strcmp(sib->name, child->name) == 0) | ||
120 | break; | ||
121 | if (sib == child && strncmp(p, child->name, l) != 0) { | ||
122 | al = proc_symlink(child->name, de, ent->name); | ||
123 | if (al == 0) { | ||
124 | of_node_put(sib); | ||
125 | break; | 89 | break; |
126 | } | 90 | if (ent != NULL) { |
127 | set_node_name_link(child, al); | 91 | printk(KERN_WARNING "device-tree: property \"%s\" name" |
128 | *lastp = al; | 92 | " conflicts with node in %s\n", pp->name, |
129 | lastp = &al->next; | 93 | np->full_name); |
94 | continue; | ||
130 | } | 95 | } |
131 | of_node_put(sib); | 96 | |
132 | /* | 97 | /* |
133 | * Add another directory with the @address part as its name. | 98 | * Unfortunately proc_register puts each new entry |
99 | * at the beginning of the list. So we rearrange them. | ||
134 | */ | 100 | */ |
135 | al = proc_symlink(at, de, ent->name); | 101 | ent = create_proc_read_entry(pp->name, |
136 | if (al == 0) | 102 | strncmp(pp->name, "security-", 9) |
103 | ? S_IRUGO : S_IRUSR, de, | ||
104 | property_read_proc, pp); | ||
105 | if (ent == 0) | ||
137 | break; | 106 | break; |
138 | set_node_addr_link(child, al); | 107 | if (!strncmp(pp->name, "security-", 9)) |
139 | *lastp = al; | 108 | ent->size = 0; /* don't leak number of password chars */ |
140 | lastp = &al->next; | 109 | else |
110 | ent->size = pp->length; | ||
111 | ent->next = NULL; | ||
112 | *lastp = ent; | ||
113 | lastp = &ent->next; | ||
141 | } | 114 | } |
142 | of_node_put(child); | ||
143 | *lastp = NULL; | ||
144 | de->subdir = list; | 115 | de->subdir = list; |
145 | } | 116 | } |
146 | 117 | ||
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index d4aaa88d0214..78899eeab974 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
@@ -25,7 +25,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) | |||
25 | struct kobject * kobj = to_kobj(dentry->d_parent); | 25 | struct kobject * kobj = to_kobj(dentry->d_parent); |
26 | 26 | ||
27 | if (!attr->read) | 27 | if (!attr->read) |
28 | return -EINVAL; | 28 | return -EIO; |
29 | 29 | ||
30 | return attr->read(kobj, buffer, off, count); | 30 | return attr->read(kobj, buffer, off, count); |
31 | } | 31 | } |
@@ -71,7 +71,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) | |||
71 | struct kobject *kobj = to_kobj(dentry->d_parent); | 71 | struct kobject *kobj = to_kobj(dentry->d_parent); |
72 | 72 | ||
73 | if (!attr->write) | 73 | if (!attr->write) |
74 | return -EINVAL; | 74 | return -EIO; |
75 | 75 | ||
76 | return attr->write(kobj, buffer, offset, count); | 76 | return attr->write(kobj, buffer, offset, count); |
77 | } | 77 | } |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index fe198210bc2d..37d7a6875d86 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -101,18 +101,19 @@ static int create_dir(struct kobject * k, struct dentry * p, | |||
101 | down(&p->d_inode->i_sem); | 101 | down(&p->d_inode->i_sem); |
102 | *d = sysfs_get_dentry(p,n); | 102 | *d = sysfs_get_dentry(p,n); |
103 | if (!IS_ERR(*d)) { | 103 | if (!IS_ERR(*d)) { |
104 | error = sysfs_create(*d, mode, init_dir); | 104 | error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR); |
105 | if (!error) { | 105 | if (!error) { |
106 | error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, | 106 | error = sysfs_create(*d, mode, init_dir); |
107 | SYSFS_DIR); | ||
108 | if (!error) { | 107 | if (!error) { |
109 | p->d_inode->i_nlink++; | 108 | p->d_inode->i_nlink++; |
110 | (*d)->d_op = &sysfs_dentry_ops; | 109 | (*d)->d_op = &sysfs_dentry_ops; |
111 | d_rehash(*d); | 110 | d_rehash(*d); |
112 | } | 111 | } |
113 | } | 112 | } |
114 | if (error && (error != -EEXIST)) | 113 | if (error && (error != -EEXIST)) { |
114 | sysfs_put((*d)->d_fsdata); | ||
115 | d_drop(*d); | 115 | d_drop(*d); |
116 | } | ||
116 | dput(*d); | 117 | dput(*d); |
117 | } else | 118 | } else |
118 | error = PTR_ERR(*d); | 119 | error = PTR_ERR(*d); |
@@ -171,17 +172,19 @@ static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry) | |||
171 | init = init_file; | 172 | init = init_file; |
172 | } | 173 | } |
173 | 174 | ||
175 | dentry->d_fsdata = sysfs_get(sd); | ||
176 | sd->s_dentry = dentry; | ||
174 | error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); | 177 | error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); |
175 | if (error) | 178 | if (error) { |
179 | sysfs_put(sd); | ||
176 | return error; | 180 | return error; |
181 | } | ||
177 | 182 | ||
178 | if (bin_attr) { | 183 | if (bin_attr) { |
179 | dentry->d_inode->i_size = bin_attr->size; | 184 | dentry->d_inode->i_size = bin_attr->size; |
180 | dentry->d_inode->i_fop = &bin_fops; | 185 | dentry->d_inode->i_fop = &bin_fops; |
181 | } | 186 | } |
182 | dentry->d_op = &sysfs_dentry_ops; | 187 | dentry->d_op = &sysfs_dentry_ops; |
183 | dentry->d_fsdata = sysfs_get(sd); | ||
184 | sd->s_dentry = dentry; | ||
185 | d_rehash(dentry); | 188 | d_rehash(dentry); |
186 | 189 | ||
187 | return 0; | 190 | return 0; |
@@ -191,13 +194,15 @@ static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry) | |||
191 | { | 194 | { |
192 | int err = 0; | 195 | int err = 0; |
193 | 196 | ||
197 | dentry->d_fsdata = sysfs_get(sd); | ||
198 | sd->s_dentry = dentry; | ||
194 | err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); | 199 | err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); |
195 | if (!err) { | 200 | if (!err) { |
196 | dentry->d_op = &sysfs_dentry_ops; | 201 | dentry->d_op = &sysfs_dentry_ops; |
197 | dentry->d_fsdata = sysfs_get(sd); | ||
198 | sd->s_dentry = dentry; | ||
199 | d_rehash(dentry); | 202 | d_rehash(dentry); |
200 | } | 203 | } else |
204 | sysfs_put(sd); | ||
205 | |||
201 | return err; | 206 | return err; |
202 | } | 207 | } |
203 | 208 | ||
@@ -228,6 +233,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
228 | 233 | ||
229 | struct inode_operations sysfs_dir_inode_operations = { | 234 | struct inode_operations sysfs_dir_inode_operations = { |
230 | .lookup = sysfs_lookup, | 235 | .lookup = sysfs_lookup, |
236 | .setattr = sysfs_setattr, | ||
231 | }; | 237 | }; |
232 | 238 | ||
233 | static void remove_dir(struct dentry * d) | 239 | static void remove_dir(struct dentry * d) |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 364208071e17..849aac115460 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -23,7 +23,7 @@ subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page) | |||
23 | { | 23 | { |
24 | struct subsystem * s = to_subsys(kobj); | 24 | struct subsystem * s = to_subsys(kobj); |
25 | struct subsys_attribute * sattr = to_sattr(attr); | 25 | struct subsys_attribute * sattr = to_sattr(attr); |
26 | ssize_t ret = 0; | 26 | ssize_t ret = -EIO; |
27 | 27 | ||
28 | if (sattr->show) | 28 | if (sattr->show) |
29 | ret = sattr->show(s,page); | 29 | ret = sattr->show(s,page); |
@@ -36,7 +36,7 @@ subsys_attr_store(struct kobject * kobj, struct attribute * attr, | |||
36 | { | 36 | { |
37 | struct subsystem * s = to_subsys(kobj); | 37 | struct subsystem * s = to_subsys(kobj); |
38 | struct subsys_attribute * sattr = to_sattr(attr); | 38 | struct subsys_attribute * sattr = to_sattr(attr); |
39 | ssize_t ret = 0; | 39 | ssize_t ret = -EIO; |
40 | 40 | ||
41 | if (sattr->store) | 41 | if (sattr->store) |
42 | ret = sattr->store(s,page,count); | 42 | ret = sattr->store(s,page,count); |
@@ -182,7 +182,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t | |||
182 | return -ENOMEM; | 182 | return -ENOMEM; |
183 | 183 | ||
184 | if (count >= PAGE_SIZE) | 184 | if (count >= PAGE_SIZE) |
185 | count = PAGE_SIZE - 1; | 185 | count = PAGE_SIZE; |
186 | error = copy_from_user(buffer->page,buf,count); | 186 | error = copy_from_user(buffer->page,buf,count); |
187 | buffer->needs_read_fill = 1; | 187 | buffer->needs_read_fill = 1; |
188 | return error ? -EFAULT : count; | 188 | return error ? -EFAULT : count; |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index aff7b2dfa8ee..565cac1d4200 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -26,18 +26,107 @@ static struct backing_dev_info sysfs_backing_dev_info = { | |||
26 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, | 26 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | struct inode * sysfs_new_inode(mode_t mode) | 29 | static struct inode_operations sysfs_inode_operations ={ |
30 | .setattr = sysfs_setattr, | ||
31 | }; | ||
32 | |||
33 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | ||
34 | { | ||
35 | struct inode * inode = dentry->d_inode; | ||
36 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
37 | struct iattr * sd_iattr; | ||
38 | unsigned int ia_valid = iattr->ia_valid; | ||
39 | int error; | ||
40 | |||
41 | if (!sd) | ||
42 | return -EINVAL; | ||
43 | |||
44 | sd_iattr = sd->s_iattr; | ||
45 | |||
46 | error = inode_change_ok(inode, iattr); | ||
47 | if (error) | ||
48 | return error; | ||
49 | |||
50 | error = inode_setattr(inode, iattr); | ||
51 | if (error) | ||
52 | return error; | ||
53 | |||
54 | if (!sd_iattr) { | ||
55 | /* setting attributes for the first time, allocate now */ | ||
56 | sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL); | ||
57 | if (!sd_iattr) | ||
58 | return -ENOMEM; | ||
59 | /* assign default attributes */ | ||
60 | memset(sd_iattr, 0, sizeof(struct iattr)); | ||
61 | sd_iattr->ia_mode = sd->s_mode; | ||
62 | sd_iattr->ia_uid = 0; | ||
63 | sd_iattr->ia_gid = 0; | ||
64 | sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME; | ||
65 | sd->s_iattr = sd_iattr; | ||
66 | } | ||
67 | |||
68 | /* attributes were changed atleast once in past */ | ||
69 | |||
70 | if (ia_valid & ATTR_UID) | ||
71 | sd_iattr->ia_uid = iattr->ia_uid; | ||
72 | if (ia_valid & ATTR_GID) | ||
73 | sd_iattr->ia_gid = iattr->ia_gid; | ||
74 | if (ia_valid & ATTR_ATIME) | ||
75 | sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime, | ||
76 | inode->i_sb->s_time_gran); | ||
77 | if (ia_valid & ATTR_MTIME) | ||
78 | sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime, | ||
79 | inode->i_sb->s_time_gran); | ||
80 | if (ia_valid & ATTR_CTIME) | ||
81 | sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime, | ||
82 | inode->i_sb->s_time_gran); | ||
83 | if (ia_valid & ATTR_MODE) { | ||
84 | umode_t mode = iattr->ia_mode; | ||
85 | |||
86 | if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) | ||
87 | mode &= ~S_ISGID; | ||
88 | sd_iattr->ia_mode = mode; | ||
89 | } | ||
90 | |||
91 | return error; | ||
92 | } | ||
93 | |||
94 | static inline void set_default_inode_attr(struct inode * inode, mode_t mode) | ||
95 | { | ||
96 | inode->i_mode = mode; | ||
97 | inode->i_uid = 0; | ||
98 | inode->i_gid = 0; | ||
99 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
100 | } | ||
101 | |||
102 | static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) | ||
103 | { | ||
104 | inode->i_mode = iattr->ia_mode; | ||
105 | inode->i_uid = iattr->ia_uid; | ||
106 | inode->i_gid = iattr->ia_gid; | ||
107 | inode->i_atime = iattr->ia_atime; | ||
108 | inode->i_mtime = iattr->ia_mtime; | ||
109 | inode->i_ctime = iattr->ia_ctime; | ||
110 | } | ||
111 | |||
112 | struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd) | ||
30 | { | 113 | { |
31 | struct inode * inode = new_inode(sysfs_sb); | 114 | struct inode * inode = new_inode(sysfs_sb); |
32 | if (inode) { | 115 | if (inode) { |
33 | inode->i_mode = mode; | ||
34 | inode->i_uid = 0; | ||
35 | inode->i_gid = 0; | ||
36 | inode->i_blksize = PAGE_CACHE_SIZE; | 116 | inode->i_blksize = PAGE_CACHE_SIZE; |
37 | inode->i_blocks = 0; | 117 | inode->i_blocks = 0; |
38 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
39 | inode->i_mapping->a_ops = &sysfs_aops; | 118 | inode->i_mapping->a_ops = &sysfs_aops; |
40 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; | 119 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; |
120 | inode->i_op = &sysfs_inode_operations; | ||
121 | |||
122 | if (sd->s_iattr) { | ||
123 | /* sysfs_dirent has non-default attributes | ||
124 | * get them for the new inode from persistent copy | ||
125 | * in sysfs_dirent | ||
126 | */ | ||
127 | set_inode_attr(inode, sd->s_iattr); | ||
128 | } else | ||
129 | set_default_inode_attr(inode, mode); | ||
41 | } | 130 | } |
42 | return inode; | 131 | return inode; |
43 | } | 132 | } |
@@ -48,7 +137,8 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) | |||
48 | struct inode * inode = NULL; | 137 | struct inode * inode = NULL; |
49 | if (dentry) { | 138 | if (dentry) { |
50 | if (!dentry->d_inode) { | 139 | if (!dentry->d_inode) { |
51 | if ((inode = sysfs_new_inode(mode))) { | 140 | struct sysfs_dirent * sd = dentry->d_fsdata; |
141 | if ((inode = sysfs_new_inode(mode, sd))) { | ||
52 | if (dentry->d_parent && dentry->d_parent->d_inode) { | 142 | if (dentry->d_parent && dentry->d_parent->d_inode) { |
53 | struct inode *p_inode = dentry->d_parent->d_inode; | 143 | struct inode *p_inode = dentry->d_parent->d_inode; |
54 | p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; | 144 | p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 5c805bb1a4b7..f1117e885bd6 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -28,6 +28,7 @@ static struct sysfs_dirent sysfs_root = { | |||
28 | .s_children = LIST_HEAD_INIT(sysfs_root.s_children), | 28 | .s_children = LIST_HEAD_INIT(sysfs_root.s_children), |
29 | .s_element = NULL, | 29 | .s_element = NULL, |
30 | .s_type = SYSFS_ROOT, | 30 | .s_type = SYSFS_ROOT, |
31 | .s_iattr = NULL, | ||
31 | }; | 32 | }; |
32 | 33 | ||
33 | static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | 34 | static int sysfs_fill_super(struct super_block *sb, void *data, int silent) |
@@ -42,7 +43,8 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | |||
42 | sb->s_time_gran = 1; | 43 | sb->s_time_gran = 1; |
43 | sysfs_sb = sb; | 44 | sysfs_sb = sb; |
44 | 45 | ||
45 | inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); | 46 | inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, |
47 | &sysfs_root); | ||
46 | if (inode) { | 48 | if (inode) { |
47 | inode->i_op = &sysfs_dir_inode_operations; | 49 | inode->i_op = &sysfs_dir_inode_operations; |
48 | inode->i_fop = &sysfs_dir_operations; | 50 | inode->i_fop = &sysfs_dir_operations; |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index dfdf70174354..fae57c83a722 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -43,7 +43,7 @@ static void fill_object_path(struct kobject * kobj, char * buffer, int length) | |||
43 | } | 43 | } |
44 | } | 44 | } |
45 | 45 | ||
46 | static int sysfs_add_link(struct dentry * parent, char * name, struct kobject * target) | 46 | static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target) |
47 | { | 47 | { |
48 | struct sysfs_dirent * parent_sd = parent->d_fsdata; | 48 | struct sysfs_dirent * parent_sd = parent->d_fsdata; |
49 | struct sysfs_symlink * sl; | 49 | struct sysfs_symlink * sl; |
@@ -79,7 +79,7 @@ exit1: | |||
79 | * @target: object we're pointing to. | 79 | * @target: object we're pointing to. |
80 | * @name: name of the symlink. | 80 | * @name: name of the symlink. |
81 | */ | 81 | */ |
82 | int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name) | 82 | int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) |
83 | { | 83 | { |
84 | struct dentry * dentry = kobj->dentry; | 84 | struct dentry * dentry = kobj->dentry; |
85 | int error = 0; | 85 | int error = 0; |
@@ -99,13 +99,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * nam | |||
99 | * @name: name of the symlink to remove. | 99 | * @name: name of the symlink to remove. |
100 | */ | 100 | */ |
101 | 101 | ||
102 | void sysfs_remove_link(struct kobject * kobj, char * name) | 102 | void sysfs_remove_link(struct kobject * kobj, const char * name) |
103 | { | 103 | { |
104 | sysfs_hash_and_remove(kobj->dentry,name); | 104 | sysfs_hash_and_remove(kobj->dentry,name); |
105 | } | 105 | } |
106 | 106 | ||
107 | static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target, | 107 | static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target, |
108 | char *path) | 108 | char *path) |
109 | { | 109 | { |
110 | char * s; | 110 | char * s; |
111 | int depth, size; | 111 | int depth, size; |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index a8a24a0c0b3b..29da6f5f07c8 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -2,7 +2,7 @@ | |||
2 | extern struct vfsmount * sysfs_mount; | 2 | extern struct vfsmount * sysfs_mount; |
3 | extern kmem_cache_t *sysfs_dir_cachep; | 3 | extern kmem_cache_t *sysfs_dir_cachep; |
4 | 4 | ||
5 | extern struct inode * sysfs_new_inode(mode_t mode); | 5 | extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); |
6 | extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); | 6 | extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); |
7 | 7 | ||
8 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, | 8 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, |
@@ -17,6 +17,7 @@ extern void sysfs_remove_subdir(struct dentry *); | |||
17 | 17 | ||
18 | extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); | 18 | extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); |
19 | extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); | 19 | extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); |
20 | extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | ||
20 | 21 | ||
21 | extern struct rw_semaphore sysfs_rename_sem; | 22 | extern struct rw_semaphore sysfs_rename_sem; |
22 | extern struct super_block * sysfs_sb; | 23 | extern struct super_block * sysfs_sb; |
@@ -75,6 +76,7 @@ static inline void release_sysfs_dirent(struct sysfs_dirent * sd) | |||
75 | kobject_put(sl->target_kobj); | 76 | kobject_put(sl->target_kobj); |
76 | kfree(sl); | 77 | kfree(sl); |
77 | } | 78 | } |
79 | kfree(sd->s_iattr); | ||
78 | kmem_cache_free(sysfs_dir_cachep, sd); | 80 | kmem_cache_free(sysfs_dir_cachep, sd); |
79 | } | 81 | } |
80 | 82 | ||
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c index 457a8fe28575..85d8dbe843f1 100644 --- a/fs/udf/udftime.c +++ b/fs/udf/udftime.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | /* How many days come before each month (0-12). */ | 48 | /* How many days come before each month (0-12). */ |
49 | const unsigned short int __mon_yday[2][13] = | 49 | static const unsigned short int __mon_yday[2][13] = |
50 | { | 50 | { |
51 | /* Normal years. */ | 51 | /* Normal years. */ |
52 | { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | 52 | { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, |